diff --git a/APRDesign b/APRDesign
deleted file mode 100644
index 905f94568bb..00000000000
--- a/APRDesign
+++ /dev/null
@@ -1,340 +0,0 @@
-Design of APR
-
-The Apache Portable Run-time libraries have been designed to provide a common
-interface to low level routines across any platform.  The original goal of APR
-was to combine all code in Apache to one common code base.  This is not the
-correct approach however, so the goal of APR has changed.  
-
-There are places where common code is not a good thing.  For example, how to
-map requests to either threads or processes should be platform specific. 
-APR's place is now to combine any code that can be safely combined without
-sacrificing performance.
-
-To this end we have created a set of operations that are required for cross
-platfrom development.  There may be other types that are desired and those
-will be implemented in the future.  The first version of APR will focus on
-what Apache 2.0 needs.  Of course, anything that is submitted will be
-considered for inclusion.
-
-This document will discuss the structure of APR, and how best to contribute
-code to the effort.
-
-APR On Windows
-
-APR on Windows is different from APR on all other systems, because it
-doesn't use autoconf. On Unix, apr_private.h (private to APR) and apr.h 
-(public, used by applications that use APR) are generated by autoconf 
-from acconfig.h and apr.h.in respectively. On Windows, apr_private.h 
-and apr.h are created from apr_private.hw and apr.hw respectively.
-
-!!!***  If you add code to acconfig.h or tests to configure.in or aclocal.m4,
-        please give some thought to whether or not Windows needs this addition
-        as well.  A general rule of thumb, is that if it is a feature macro,
-        such as APR_HAS_THREADS, Windows needs it.  If the definition is going
-        to be used in a public APR header file, such as apr_general.h, Windows
-        needs it.
-        
-        The only time it is safe to add a macro or test without also adding 
-        the macro to apr*.hw, is if the macro tells APR how to build.  For
-        example, a test for a header file does not need to be added to Windows.
-***!!!
-
-APR Features
-
-One of the goals of APR is to provide a common set of features across all 
-platforms.  This is an admirable goal, it is also not realisitic.  We cannot
-expect to be able to implement ALL features on ALL platforms.  So we are
-going to do the next best thing.  Provide a common interface to ALL APR 
-features on MOST platforms.
-
-APR developers should create FEATURE MACROS for any feature that is not
-available on ALL platforms.  This should be a simple definition which has
-the form:
-
-APR_HAS_FEATURE
-
-This macro should evaluate to true if APR has this feature on this platform.
-For example, Linux and Windows have mmap'ed files, and APR is providing an
-interface for mmapp'ing a file.  On both Linux and Windows, APR_HAS_MMAP
-should evaluate to one, and the ap_mmap_* functions should map files into
-memory and return the appropriate status codes.
-
-If your OS of choice does not have mmap'ed files, APR_HAS_MMAP should evaluate 
-to zero, and all ap_mmap_* functions should not be defined.  The second step 
-is a precaution that will allow us to break at compile time if a programmer 
-tries to use unsupported functions. 
-
-APR types
-
-The base types in APR
-file_io     File I/O, including pipes
-lib         A portable library originally used in Apache.  This contains
-            memory management, tables, and arrays.
-locks       Mutex and reader/writer locks
-misc        Any APR type which doesn't have any other place to belong
-network_io  Network I/O
-shmem       Shared Memory (Not currently implemented)   
-signal      Asynchronous Signals
-threadproc  Threads and Processes
-time        Time 
-
-Directory Structure
-
-Each type has a base directory.  Inside this base directory, are
-subdirectories, which contain the actual code.  These subdirectories are named
-after the platforms the are compiled on.  Unix is also used as a common
-directory.  If the code you are writing is POSIX based, you should look at the
-code in the unix directory.  A good rule of thumb, is that if more than half
-your code needs to be ifdef'ed out, and the structures required for your code
-are substantively different from the POSIX code, you should create a new
-directory.
-
-Currently, the APR code is written for Unix, BeOS, Windows, and OS/2.  An
-example of the directory structure is the file I/O directory:
-
-apr
-  |
-   ->  file_io
-          |
-           -> unix            The Unix and common base code
-          |
-           -> win32           The Windows code
-          | 
-           -> os2             The OS/2 code
-
-Obviously, BeOS does not have a directory.  This is because BeOS is currently
-using the Unix directory for it's file_io.  In the near future, it will be
-possible to use indiviual files from the Unix directory.
-
-There are a few special top level directories.  These are test, inc, include,
-and libs.  Test is a directory which stores all test programs.  It is expected
-that if a new type is developed, there will also be a new test program, to
-help people port this new type to different platforms.  Inc is a directory for
-internal header files.  This directory is likely to go away soon.  Include is
-a directory which stores all required APR header files for external use.  The
-distinction between internal and external header files will be made soon. 
-Finally, libs is a generated directory.  When APR finishes building, it will
-store it's library files in the libs directory.
-
-Creating an APR Type
-
-The current design of APR requires that APR types be incomplete.  It is not
-possible to write flexible portable code if programs can access the internals
-of APR types.  This is because different platforms are likely to define
-different native types.
-
-For this reason, each platform defines a structure in their own directories. 
-Those structures are then typedef'ed in an external header file.  For example
-in file_io/unix/fileio.h:
-
-    struct ap_file_t {
-        ap_context_t *cntxt;
-        int filedes;
-        FILE *filehand;
-        ...
-    }
-
-In include/apr_file_io.h:
-    typedef struct ap_file_t    ap_file_t;
-
-This will cause a compiler error if somebody tries to access the filedes field
-in this strcture.  Windows does not have a filedes field, so obviously, it is
-important that programs not be able to access these.
-
-The only exception to the incomplete type rule can be found in apr_portable.h.
-This file defines the native types for each platform.  Using these types, it
-is possible to extract native types for any APR type.
-
-You may notice the ap_context_t field.  All APR types have this field.  This
-type is used to allocate memory within APR.
-
-New Function
-
-When creating a new function, please try to adhere to these rules.
-
-1)  Result arguments should be the first arguments.
-2)  If a function needs a context, it should be the last argument.
-3)  These rules are flexible, especially if it makes the code easier
-    to understand because it mimics a standard function.
-
-Documentation
-
-Whenever a new function is added to APR, it MUST be documented.  New 
-functions will not be committed unless there are docs to go along with them.
-The documentation should be a comment block above the function in the unix
-.c file.  This does not mean you must implement the function for Unix.  But,
-it would be nice if you submitted a file with the prototypes and the comments
-above the prototypes to be checked into the unix tree.
-
-The format for the comment block is:
-
-/*
-
-=head1 function prototype
-
-B<Brief description of function>
-
-    arg 1)  explanation of arg 1
-    arg 2)  explanation of arg 2
-    arg N)  explanation of arg N
-
-B<NOTE>:  Any extra information the programmer needs.
-
-=cut
- */                                                                             
-
-The spacing for the documentation is VERY important, because the docs are
-processed with perldoc, and this spacing is required for the perldoc scripts
-to work properly.
-
-For an actual example, look at any function in the fileio/unix directory.
-
-APR Error reporting
-
-Most APR functions should return an ap_status_t type.  The only time an
-APR function does not return an ap_status_t is if it absolutly CAN NOT
-fail.  Examples of this would be filling out an array when you know you are
-not beyond the array's range.  If it cannot fail on your platform, but it
-could conceivably fail on another platform, it should return an ap_status_t.
-Unless you are sure, return an ap_status_t.  :-)
-
-All platform return errno values unchanged.  Each platform can also have
-one system error type, which can be returned after an offset is added.  
-There are five types of error values in APR, each with it's own offset.
-
-    Name			Purpose
-0) 			This is 0 for all platforms and isn't really defined
- 			anywhere, but it is the offset for errno values.
-			(This has no name because it isn't actually defined, 
-                        but completeness we are discussing it here).
-1) APR_OS_START_ERROR	This is platform dependant, and is the offset at which
-			APR errors start to be defined.  (Canonical error
-			values are also defined in this section.  [Canonical
-			error values are discussed later]).
-2) APR_OS_START_STATUS	This is platform dependant, and is the offset at which
-			APR status values start.
-4) APR_OS_START_USEERR	This is platform dependant, and is the offset at which
-			APR apps can begin to add their own error codes.
-3) APR_OS_START_SYSERR	This is platform dependant, and is the offset at which
-			system error values begin.
-
-All of these definitions can be found in apr_errno.h for all platforms.  When
-an error occurs in an APR function, the function must return an error code.
-If the error occurred in a system call and that system call uses errno to
-report an error, then the code is returned unchanged.  For example: 
-
-    if (open(fname, oflags, 0777) < 0)
-        return errno;
-
-
-The next place an error can occur is a system call that uses some error value
-other than the primary error value on a platform.  This can also be handled
-by APR applications.  For example:
-
-    if (CreateFile(fname, oflags, sharemod, NULL, 
-                   createflags, attributes,0) == INVALID_HANDLE_VALUE
-        return (GetLAstError() + APR_OS_START_SYSERR);
-
-These two examples implement the same function for two different platforms.
-Obviously even if the underlying problem is the same on both platforms, this
-will result in two different error codes being returned.  This is OKAY, and
-is correct for APR.  APR relies on the fact that most of the time an error
-occurs, the program logs the error and continues, it does not try to
-programatically solve the problem.  This does not mean we have not provided
-support for programmatically solving the problem, it just isn't the default
-case.  We'll get to how this problem is solved in a little while.
-
-If the error occurs in an APR function but it is not due to a system call,
-but it is actually an APR error or just a status code from APR, then the
-appropriate code should be returned.  These codes are defined in apr_errno.h
-and are self explanatory.
-
-No APR code should ever return a code between APR_OS_START_USEERR and 
-APR_OS_START_SYSERR, those codes are reserved for APR applications.
-
-To programmatically correct an error in a running application, the error codes
-need to be consistent across platforms.  This should make sense.  To get
-consistent error codes, APR provides a function ap_canonicalize_error().
-This function will take as input any ap_status_t value, and return a small
-subset of canonical APR error codes.  These codes will be equivalent to
-Unix errno's.  Why is it a small subset?  Because we don't want to try to
-convert everything in the first pass.  As more programs require that more
-error codes are converted, they will be added to this function.  
-
-Why did APR take this approach?  There are two ways to deal with error 
-codes portably.
-
-1)  return the same error code across all platforms.  2)  return platform
-specific error codes and convert them when necessary.  
-
-The problem with option number one is that it takes time to convert error 
-codes to a common code, and most of the time programs want to just output 
-an error string.  If we convert all errors to a common subset, we have four 
-steps to output an error string:
-
-    make syscall that fails
-        convert to common error code                 step 1
-        return common error code
-            check for success
-            call error output function               step 2
-                convert back to system error         step 3
-                output error string                  step 4
-
-By keeping the errors platform specific, we can output error strings in two
-steps.
-
-    make syscall that fails
-        return error code
-            check for success
-            call error output function               step 1
-                output error string                  step 2
-
-Less often, programs change their execution based on what error was returned.
-This is no more expensive using option 2 and it is using option 1, but we
-put the onus of converting the error code on the programmer themselves.
-For example, using option 1:
-
-    make syscall that fails
-        convert to common error code
-        return common error code
-            decide execution basd on common error code
-
-Using option 2:
-    
-    make syscall that fails
-        return error code
-            convert to common error code (using ap_canonicalize_error)
-            decide execution based on common error code
-
-Finally, there is one more operation on error codes.  You can get a string
-that explains in human readable form what has happened.  To do this using 
-APR, call ap_strerror().
-
-On all platforms ap_strerror takes the form:
-
-char *ap_strerror(ap_status_t err)
-{
-    if (err < APR_OS_START_ERRNO2)
-        return (platform dependant error string generator)
-    if (err < APR_OS_START_ERROR)
-        return (platform dependant error string generator for
-                supplemental error values)
-    if (err < APR_OS_SYSERR)
-        return (APR generated error or status string)
-    if (err == 0)
-        return "No error was found"
-    else
-        return "APR doesn't understand this error value"
-}
-
-Notice, this does not handle canonicalized error values well.  Those will 
-return "APR doesn't understand this error value" on some platforms and
-an actual error string on others.  To deal with this, just get the
-string before canonicalizing your error code.
-
-The other problem with option 1, is that it is a lossy conversion.  For
-example, Windows and OS/2 have a couple hundred error codes, but POSIX errno
-only defines about 50 errno values.  This means that if we convert to a
-canonical error value immediately, there is no way for the programmer to
-get the actual system error.
-
diff --git a/CHANGES b/CHANGES
new file mode 100644
index 00000000000..2f92d163a9d
--- /dev/null
+++ b/CHANGES
@@ -0,0 +1,194 @@
+                                                     -*- coding: utf-8 -*-
+Changes for APR 2.0.0
+
+  *) Add apr_pool_tag_get to retrieve the pool tag name.  [Joe Orton]
+
+  *) Add apr_sockaddr_zone_set, apr_sockaddr_zone_set to set and retrieve
+     the zone for link-local IPv6 addresses.  [Joe Orton]
+
+  *) apr_sockaddr_equal: Compare link-local IPv6 addresses with different
+     zones as not equal.  [Joe Orton]
+
+  *) apr_sockaddr_ip_getbuf, apr_sockaddr_ip_get: Append "%zone" for
+     IPv6 link-local addresses.  [Joe Orton]
+
+  *) Don't seek to the end when opening files with APR_FOPEN_APPEND on Windows.
+     [Evgeny Kotkov <evgeny.kotkov visualsvn.com>]
+
+  *) Fix a deadlock when writing to locked files opened with APR_FOPEN_APPEND
+     on Windows. PR 50058.
+     [Evgeny Kotkov <evgeny.kotkov visualsvn.com>]
+
+  *) apr_file_write: Optimize large writes to buffered files on Windows.
+     [Evgeny Kotkov <evgeny.kotkov visualsvn.com>]
+
+  *) apr_file_trunc: Truncating a buffered file could add unexpected
+     data after the truncate position. PR 51017.
+     [Evgeny Kotkov <evgeny.kotkov visualsvn.com>]
+
+  *) apr_file_trunc: Fix an issue where reading from a buffered file
+     after truncate could return stale data from the buffer.
+     [Evgeny Kotkov <evgeny.kotkov visualsvn.com>]
+
+  *) apr_allocator, apr_pools: Add apr_allocator_page_size() and
+     apr_allocator_min_order_set() to respectively get the (system's) page size
+     in use and set the minimum allocation size for an allocator (expressed in
+     2^order pages).  [Yann Ylavic]
+
+  *) apr_file_gets: Optimize for buffered files on Windows.
+     [Evgeny Kotkov <evgeny.kotkov visualsvn.com>]
+
+  *) apr_crypto: avoid excessive iteration in bcrypt hash.
+     [Hanno Böck <hanno hboeck.de>]
+
+  *) apr_siphash: Implement keyed hash function SipHash.  [Yann Ylavic]
+
+  *) apr_atomic: change the API of apr_atomic_casptr() apr_atomic_xchgptr()
+     functions to take a volatile pointer to void instead of pointer to
+     volatile void.  [Yann Ylavic]
+
+  *) apr_crypto: Add apr_crypto_key() function which supports keys
+     generated from a passphrase or a raw secret provided by the caller.
+     Deprecate apr_crypto_passphrase(). [Graham Leggett]
+
+  *) apr_crypto_nss: Ensure the SECItem returned by PK11_ParamFromIV
+     is properly freed. [Graham Leggett]
+
+  *) apr_crypto: Don't cache the driver if initialisation fails. This
+     stops the second and subsequent attempt to use the API from failing
+     claiming the library is not initialised. [Graham Leggett]
+
+  *) apr_xml_to_text: Add style APR_XML_X2T_PARSED to maintain a
+     consistent namespace prefix. [Jari Urpalainen
+     <jari.urpalainen nokia.com>]
+
+  *) apr_os_proc_mutex-unix: For consistency with other OS native to APR
+     types constructors/_put()ers and non-unix mutex mechanisms, always
+     destroy the underlying native mutex when apr_proc_mutex_destroy() is
+     called explicitly.  [Yann Ylavic]
+
+  *) apr_os_proc_mutex_put_ex: Allow to specify whether the OS native
+     mutex should or not be cleaned up (destroyed) with the constructed
+     APR mutex (given pool), and default to not for the simple _put()
+     function.  [Yann Ylavic]
+
+  *) apr_file_io: Add apr_file_pipe_create_pools() allowing a pair of
+     pipes to be created, each in a different pool. [Graham Leggett]
+
+  *) apr_table_overlap: Add APR_OVERLAP_TABLES_ADD to merge and set when
+     overlapping tables. [Graham Leggett]
+
+  *) apr_filepath_merge: Fix truename length calculation on Windows
+     in cases where the "short" name variant is actually longer than
+     the "long" or "true" name. See: testnames.c:merge_shortname().
+     [Bert Huijben <rhuijben a.o>]
+
+  *) apr_file_mktemp: Use mkostemp() where available to save on system
+     calls.  [Joe Orton]
+
+  *) apr_pools: Fix pool debugging output so that creation events are
+     always emitted before allocation events and subpool destruction
+     events are emitted on pool clear/destroy for proper accounting.
+     [Brane Čibej]
+
+  *) apr_atomic: Fix errors when building on Visual Studio 2013 while
+     maintaining the ability to build on Visual Studio 6 with Windows
+     Server 2003 R2 SDK. PR 57191. [Gregg Smith]
+
+  *) build: Correctly use AC_(PATH|CHECK)_TOOL to support cross compilation.
+     PR: 56866.  [Timothy Gu <timothygu99 gmail.com>]
+
+  *) apr_queue: Add apr_queue_timedpush() and apr_queue_timedpop() to
+     support timedout operations. PR 56951. [Anthony Minessale <anthm
+     freeswitch org>, Travis Cross <tc+asf travislists com>, Yann Ylavic].
+
+  *) apr_allocator: Be less wasteful and don't return a memnode that is
+     much larger than what was requested. [Stefan Fuhrmann
+     <stefan fuhrmann wandisco com>]
+
+  *) Windows platform: Remove support for Windows 9x.
+
+  *) Added signed apr_intptr_t.  Changed ODBC dbd driver to use this.
+     [Tom Donovan]
+
+  *) Changes to apr_pollset_method_e enum value of APR_POLLSET_POLL and
+     APR_POLLSET_AIO_MSGQ.  Restore APR_POLLSET_POLL to its pre-r1308910 
+     (April 2012) value, and move APR_POLLSET_AIO_MSGQ ahead. This restores
+     ABI compat with released branches.  [Eric Covener]
+
+  *) Add apr_pbase64_encode() and apr_pbase64_decode() to encode to/from
+     the pool. [Graham Leggett]
+
+  *) Mark apr_dbd_freetds as unsupported, and remove it from all builds
+     [Nick Kew]
+
+  *) Fix pool integrity checks with threads. Add new apr_pool_owner_set()
+     function. PR 43375, 52785. [Stefan Fritsch]
+
+  *) Add support code to teach valgrind about APR pools, allocators, and
+     bucket allocators. [Stefan Fritsch]
+
+  *) apr_socket_accept_filter(): The 2nd and 3rd arguments are now 
+     const char * instead of char *.  [Jeff Trawick]
+
+  *) apr_brigades: add a check to prevent infinite while loop in case
+     of a corrupted brigade.  Problem evidenced in PR 51062.  Analysis by
+     Krzysztof Kostałkowicz <KKostalkowicz ivmx.pl>, patch [Nick Kew].
+
+  *) Support libxml2 as an alternative XML parser to expat [Nick Kew]
+
+  *) Hide apr_wait_for_io_or_timeout() from public view and add instead
+     apr_socket_wait() and apr_file_pipe_wait(). [Brian Havard]
+
+  *) Support connecttimeout, readtimeout and writetimeout MySQL options
+     PR 48251 [Marko Kevac <marko kevac.org>]
+
+  *) Transfer the apr-util spec file contents to apr.spec. [Graham
+     Leggett]
+
+  *) Added Unix domain socket support.  [Mladen Turk]
+
+  *) Merge APR-util into APR.  [various]
+
+  *) apr_socket_listen: Allow larger listen backlog values on Windows 8+.
+     [Evgeny Kotkov <evgeny.kotkov visualsvn.com>]
+
+Changes for APR and APR-util 1.6.x and later:
+
+  *) http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/CHANGES?view=markup
+  *) http://svn.apache.org/viewvc/apr/apr-util/branches/1.6.x/CHANGES?view=markup
+
+Changes for APR and APR-util 1.5.x and later:
+
+  *) http://svn.apache.org/viewvc/apr/apr/branches/1.5.x/CHANGES?view=markup
+  *) http://svn.apache.org/viewvc/apr/apr-util/branches/1.5.x/CHANGES?view=markup
+
+Changes for APR and APR-util 1.4.x and later:
+
+  *) http://svn.apache.org/viewvc/apr/apr/branches/1.4.x/CHANGES?view=markup
+  *) http://svn.apache.org/viewvc/apr/apr-util/branches/1.4.x/CHANGES?view=markup
+
+Changes for APR and APR-util 1.3.x and later:
+
+  *) http://svn.apache.org/viewvc/apr/apr/branches/1.3.x/CHANGES?view=markup
+  *) http://svn.apache.org/viewvc/apr/apr-util/branches/1.3.x/CHANGES?view=markup
+
+Changes for APR and APR-util 1.2.x and later:
+
+  *) http://svn.apache.org/viewvc/apr/apr/branches/1.2.x/CHANGES?view=markup
+  *) http://svn.apache.org/viewvc/apr/apr-util/branches/1.2.x/CHANGES?view=markup
+
+Changes for APR and APR-util 1.1.x and later:
+
+  *) http://svn.apache.org/viewvc/apr/apr/branches/1.1.x/CHANGES?view=markup
+  *) http://svn.apache.org/viewvc/apr/apr-util/branches/1.1.x/CHANGES?view=markup
+
+Changes for APR and APR-util 1.0.x and later:
+
+  *) http://svn.apache.org/viewvc/apr/apr/branches/1.0.x/CHANGES?view=markup
+  *) http://svn.apache.org/viewvc/apr/apr-util/branches/1.0.x/CHANGES?view=markup
+
+Changes for APR and APR-util 0.9.x and later/earlier:
+
+  *) http://svn.apache.org/viewvc/apr/apr/branches/0.9.x/CHANGES?view=markup
+  *) http://svn.apache.org/viewvc/apr/apr-util/branches/0.9.x/CHANGES?view=markup
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 00000000000..9a36de9c26e
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,631 @@
+# 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.
+#
+# Read README.cmake before using this.
+
+PROJECT(APR C)
+
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+# Either Expat or LibXml2 is required; the others are optional
+FIND_PACKAGE(Expat)
+FIND_PACKAGE(LibXml2)
+FIND_PACKAGE(OpenSSL)
+
+IF(NOT EXPAT_FOUND AND NOT LIBXML2_FOUND)
+  MESSAGE(FATAL_ERROR "Either Expat or LibXml2 is required, but neither was found")
+ENDIF()
+
+IF(EXPAT_FOUND)
+  OPTION(APU_USE_EXPAT      "Use Expat"                    ON)
+  IF(LIBXML2_FOUND)
+    OPTION(APU_USE_LIBXML2  "Use LibXml2"                  OFF)
+  ENDIF()
+ELSE()
+  OPTION(APU_USE_LIBXML2    "Use LibXml2"                  ON)
+ENDIF()
+
+OPTION(APR_INSTALL_PRIVATE_H  "Install selected private .h files (for httpd)"  OFF)
+OPTION(APU_HAVE_CRYPTO      "Crypto support"               OFF)
+OPTION(APU_HAVE_ODBC        "Build ODBC DBD driver"        ON)
+OPTION(APR_HAVE_IPV6        "IPv6 support"                 ON)
+OPTION(INSTALL_PDB          "Install .pdb files (if generated)"  ON)
+OPTION(APR_BUILD_TESTAPR    "Build the test suite"         OFF)
+OPTION(TEST_STATIC_LIBS     "Test programs use APR static libraries instead of shared libraries?" OFF)
+SET(MIN_WINDOWS_VER             "Vista" 
+    CACHE STRING "Minimum Windows version")
+SET(LIBXML2_ICONV_INCLUDE_DIR   ""
+    CACHE STRING "Directory with iconv include files for libxml2")
+SET(LIBXML2_ICONV_LIBRARIES     ""
+    CACHE STRING "iconv libraries to link with for libxml2")
+
+IF(NOT APU_USE_EXPAT AND NOT APU_USE_LIBXML2)
+  MESSAGE(FATAL_ERROR "Either Expat or LibXml2 must be selected")
+ENDIF()
+IF(APU_USE_EXPAT AND APU_USE_LIBXML2)
+  MESSAGE(FATAL_ERROR "Only one of Expat and LibXml2 can be selected")
+ENDIF()
+
+IF(APU_HAVE_CRYPTO)
+IF(NOT OPENSSL_FOUND)
+  MESSAGE(FATAL_ERROR "OpenSSL is the only supported crypto implementation, and it wasn't found!")
+ENDIF()
+ENDIF()
+
+# create 1-or-0 representation of feature tests for apr.h
+
+SET(apr_have_ipv6_10 0)
+SET(apu_have_crypto_10 0)
+SET(apu_use_libxml2_10 0)
+SET(apu_use_expat_10 0)
+
+IF(APR_HAVE_IPV6)
+  SET(apr_have_ipv6_10 1)
+ENDIF()
+
+IF(APU_HAVE_CRYPTO)
+  SET(apu_have_crypto_10 1)
+ENDIF()
+
+IF(APU_USE_EXPAT)
+  SET(apu_use_expat_10 1)
+ELSE()
+  SET(apu_use_libxml2_10 1)
+ENDIF()
+
+IF("${MIN_WINDOWS_VER}" STREQUAL "")
+  SET(win32_winnt_str "0x0600")
+ELSEIF(${MIN_WINDOWS_VER} STREQUAL "Vista")
+  SET(win32_winnt_str "0x0600")
+ELSEIF(${MIN_WINDOWS_VER} STREQUAL "Windows7")
+  SET(win32_winnt_str "0x0601")
+ELSE()
+  SET(win32_winnt_str ${MIN_WINDOWS_VER})
+ENDIF()
+
+CONFIGURE_FILE(include/apr.hwc
+               ${PROJECT_BINARY_DIR}/apr.h)
+# "COPYONLY" just because anything else isn't implemented ;)
+CONFIGURE_FILE(include/private/apu_select_dbm.hw
+               ${PROJECT_BINARY_DIR}/apu_select_dbm.h
+               COPYONLY)
+CONFIGURE_FILE(include/apu_want.hw
+               ${PROJECT_BINARY_DIR}/apu_want.h
+               COPYONLY)
+
+ADD_EXECUTABLE(gen_test_char tools/gen_test_char.c)
+GET_TARGET_PROPERTY(GEN_TEST_CHAR_EXE gen_test_char LOCATION)
+ADD_CUSTOM_COMMAND(
+  COMMENT "Generating character tables, apr_escape_test_char.h, for current locale"
+  DEPENDS gen_test_char
+  COMMAND ${GEN_TEST_CHAR_EXE} > ${PROJECT_BINARY_DIR}/apr_escape_test_char.h
+  OUTPUT ${PROJECT_BINARY_DIR}/apr_escape_test_char.h
+)
+ADD_CUSTOM_TARGET(
+  test_char_header ALL
+  DEPENDS ${PROJECT_BINARY_DIR}/apr_escape_test_char.h
+)
+
+IF(APU_USE_EXPAT)
+  SET(XMLLIB_INCLUDE_DIR ${EXPAT_INCLUDE_DIRS})
+  SET(XMLLIB_LIBRARIES   ${EXPAT_LIBRARIES})
+ELSE()
+  SET(XMLLIB_INCLUDE_DIR "${LIBXML2_INCLUDE_DIR};${LIBXML2_ICONV_INCLUDE_DIR}")
+  SET(XMLLIB_LIBRARIES   "${LIBXML2_LIBRARIES};${LIBXML2_ICONV_LIBRARIES}")
+ENDIF()
+
+# Generated .h files are stored in PROJECT_BINARY_DIR, not the
+# source tree.
+#
+# BROKEN: not searching PROJECT_BINARY_DIR first, so you have to
+#         manually delete apr.h in PROJECT_SOURCE_DIR/include if
+#         you've generated apr.h before using a different build
+
+SET(APR_INCLUDE_DIRECTORIES
+  ${PROJECT_BINARY_DIR}
+  ${CMAKE_CURRENT_SOURCE_DIR}/include
+  ${CMAKE_CURRENT_SOURCE_DIR}/include/arch/win32
+  ${CMAKE_CURRENT_SOURCE_DIR}/include/arch/unix
+  ${CMAKE_CURRENT_SOURCE_DIR}/include/private
+)
+
+SET(APR_SYSTEM_LIBS
+  ws2_32
+  mswsock
+  rpcrt4
+)
+
+INCLUDE_DIRECTORIES(${APR_INCLUDE_DIRECTORIES} ${XMLLIB_INCLUDE_DIR})
+
+SET(APR_PUBLIC_HEADERS_STATIC
+  include/apr_allocator.h
+  include/apr_anylock.h
+  include/apr_atomic.h
+  include/apr_base64.h
+  include/apr_buckets.h
+  include/apr_crypto.h
+  include/apr_cstr.h
+  include/apr_date.h
+  include/apr_dbd.h
+  include/apr_dbm.h
+  include/apr_dso.h
+  include/apr_env.h
+  include/apr_errno.h
+  include/apr_escape.h
+  include/apr_file_info.h
+  include/apr_file_io.h
+  include/apr_fnmatch.h
+  include/apr_general.h
+  include/apr_getopt.h
+  include/apr_global_mutex.h
+  include/apr_hash.h
+  include/apr_hooks.h
+  include/apr_inherit.h
+  include/apr_lib.h
+  include/apr_md4.h
+  include/apr_md5.h
+  include/apr_memcache.h
+  include/apr_mmap.h
+  include/apr_network_io.h
+  include/apr_optional.h
+  include/apr_optional_hooks.h
+  include/apr_perms_set.h
+  include/apr_poll.h
+  include/apr_pools.h
+  include/apr_portable.h
+  include/apr_proc_mutex.h
+  include/apr_queue.h
+  include/apr_random.h
+  include/apr_redis.h
+  include/apr_reslist.h
+  include/apr_ring.h
+  include/apr_rmm.h
+  include/apr_sdbm.h
+  include/apr_sha1.h
+  include/apr_shm.h
+  include/apr_signal.h
+  include/apr_siphash.h
+  include/apr_skiplist.h
+  include/apr_strings.h
+  include/apr_strmatch.h
+  include/apr_tables.h
+  include/apr_thread_cond.h
+  include/apr_thread_mutex.h
+  include/apr_thread_pool.h
+  include/apr_thread_proc.h
+  include/apr_thread_rwlock.h
+  include/apr_time.h
+  include/apr_uri.h
+  include/apr_user.h
+  include/apr_uuid.h
+  include/apr_version.h
+  include/apr_want.h
+  include/apr_xlate.h
+  include/apr_xml.h
+  include/apu.h
+  include/apu_errno.h
+  include/apu_version.h
+)
+SET(APR_PUBLIC_HEADERS_GENERATED
+  ${PROJECT_BINARY_DIR}/apr.h
+  ${PROJECT_BINARY_DIR}/apu_want.h
+)
+
+SET(APR_SOURCES
+  atomic/win32/apr_atomic.c
+  buckets/apr_brigade.c
+  buckets/apr_buckets.c
+  buckets/apr_buckets_alloc.c
+  buckets/apr_buckets_eos.c
+  buckets/apr_buckets_file.c
+  buckets/apr_buckets_flush.c
+  buckets/apr_buckets_heap.c
+  buckets/apr_buckets_mmap.c
+  buckets/apr_buckets_pipe.c
+  buckets/apr_buckets_pool.c
+  buckets/apr_buckets_refcount.c
+  buckets/apr_buckets_simple.c
+  buckets/apr_buckets_socket.c
+  crypto/apr_crypto.c
+  crypto/apr_md4.c
+  crypto/apr_md5.c
+  crypto/apr_passwd.c
+  crypto/apr_sha1.c
+  crypto/apr_siphash.c
+  crypto/crypt_blowfish.c
+  crypto/getuuid.c
+  crypto/uuid.c
+  dbd/apr_dbd.c
+  dbm/apr_dbm.c
+  dbm/apr_dbm_sdbm.c
+  dbm/sdbm/sdbm.c
+  dbm/sdbm/sdbm_hash.c
+  dbm/sdbm/sdbm_lock.c
+  dbm/sdbm/sdbm_pair.c
+  dso/win32/dso.c
+  encoding/apr_base64.c
+  encoding/apr_escape.c
+  file_io/unix/copy.c
+  file_io/unix/fileacc.c
+  file_io/unix/filepath_util.c
+  file_io/unix/fullrw.c
+  file_io/unix/mktemp.c
+  file_io/unix/tempdir.c
+  file_io/win32/buffer.c
+  file_io/win32/dir.c
+  file_io/win32/filedup.c
+  file_io/win32/filepath.c
+  file_io/win32/filestat.c
+  file_io/win32/filesys.c
+  file_io/win32/flock.c
+  file_io/win32/open.c
+  file_io/win32/pipe.c
+  file_io/win32/readwrite.c
+  file_io/win32/seek.c
+  hooks/apr_hooks.c
+  locks/win32/proc_mutex.c
+  locks/win32/thread_cond.c
+  locks/win32/thread_mutex.c
+  locks/win32/thread_rwlock.c
+  memcache/apr_memcache.c
+  memory/unix/apr_pools.c
+  misc/unix/errorcodes.c
+  misc/unix/getopt.c
+  misc/unix/otherchild.c
+  misc/unix/version.c
+  misc/win32/charset.c
+  misc/win32/env.c
+  misc/win32/internal.c
+  misc/win32/misc.c
+  misc/win32/rand.c
+  misc/win32/start.c
+  misc/win32/utf8.c
+  mmap/unix/common.c
+  mmap/win32/mmap.c
+  network_io/unix/inet_ntop.c
+  network_io/unix/inet_pton.c
+  network_io/unix/multicast.c
+  network_io/unix/sockaddr.c
+  network_io/unix/socket_util.c
+  network_io/win32/sendrecv.c
+  network_io/win32/sockets.c
+  network_io/win32/sockopt.c
+  passwd/apr_getpass.c
+  poll/unix/poll.c
+  poll/unix/pollcb.c
+  poll/unix/pollset.c
+  poll/unix/select.c
+  poll/unix/wakeup.c
+  random/unix/apr_random.c
+  random/unix/sha2.c
+  random/unix/sha2_glue.c
+  redis/apr_redis.c
+  shmem/win32/shm.c
+  strings/apr_cpystrn.c
+  strings/apr_cstr.c
+  strings/apr_fnmatch.c
+  strings/apr_snprintf.c
+  strings/apr_strings.c
+  strings/apr_strnatcmp.c
+  strings/apr_strtok.c
+  strmatch/apr_strmatch.c
+  tables/apr_hash.c
+  tables/apr_skiplist.c
+  tables/apr_tables.c
+  threadproc/win32/proc.c
+  threadproc/win32/signals.c
+  threadproc/win32/thread.c
+  threadproc/win32/threadpriv.c
+  time/win32/time.c
+  time/win32/timestr.c
+  uri/apr_uri.c
+  user/win32/groupinfo.c
+  user/win32/userinfo.c
+  util-misc/apr_date.c
+  util-misc/apr_queue.c
+  util-misc/apr_reslist.c
+  util-misc/apr_rmm.c
+  util-misc/apr_thread_pool.c
+  util-misc/apu_dso.c
+  xlate/xlate.c
+  xml/apr_xml.c
+  xml/apr_xml_expat.c
+  xml/apr_xml_libxml2.c
+)
+
+SET(APR_TEST_SOURCES
+  test/abts.c
+  test/testargs.c
+  test/testatomic.c
+  test/testbase64.c
+  test/testbuckets.c
+  test/testcond.c
+  test/testcrypto.c
+  test/testdate.c
+  test/testdbd.c
+  test/testdbm.c
+  test/testdir.c
+  test/testdso.c
+  test/testdup.c
+  test/testenv.c
+  test/testescape.c
+  test/testfile.c
+  test/testfilecopy.c
+  test/testfileinfo.c
+  test/testflock.c
+  test/testfmt.c
+  test/testfnmatch.c
+  test/testglobalmutex.c
+  test/testhash.c
+  test/testhooks.c
+  test/testipsub.c
+  test/testlfs.c
+  test/testlfsabi.c
+  test/testlfsabi32.c
+  test/testlfsabi64.c
+  test/testlfsabi_include.c
+  test/testlock.c
+  test/testmd4.c
+  test/testmd5.c
+  test/testmemcache.c
+  test/testmmap.c
+  test/testnames.c
+  test/testoc.c
+  test/testpass.c
+  test/testpath.c
+  test/testpipe.c
+  test/testpoll.c
+  test/testpools.c
+  test/testproc.c
+  test/testprocmutex.c
+  test/testqueue.c
+  test/testrand.c
+  test/testredis.c
+  test/testreslist.c
+  test/testrmm.c
+  test/testshm.c
+  test/testsiphash.c
+  test/testskiplist.c
+  test/testsleep.c
+  test/testsock.c
+  test/testsockets.c
+  test/testsockopt.c
+  test/teststr.c
+  test/teststrmatch.c
+  test/teststrnatcmp.c
+  test/testtable.c
+  test/testtemp.c
+  test/testthread.c
+  test/testtime.c
+  test/testud.c
+  test/testuri.c
+  test/testuser.c
+  test/testutil.c
+  test/testuuid.c
+  test/testvsn.c
+  test/testxlate.c
+  test/testxml.c
+)
+
+SET(install_targets)
+SET(install_bin_pdb)
+SET(dbd_drivers)
+
+# libapr-2 is shared, apr-2 is static
+ADD_LIBRARY(libapr-2 SHARED ${APR_SOURCES} ${APR_PUBLIC_HEADERS_GENERATED} libapr.rc)
+SET(install_targets ${install_targets} libapr-2)
+SET(install_bin_pdb ${install_bin_pdb} ${PROJECT_BINARY_DIR}/libapr-2.pdb)
+TARGET_LINK_LIBRARIES(libapr-2 ${XMLLIB_LIBRARIES} ${APR_SYSTEM_LIBS})
+SET_TARGET_PROPERTIES(libapr-2 PROPERTIES COMPILE_DEFINITIONS "APR_DECLARE_EXPORT;APR_HAVE_MODULAR_DSO")
+ADD_DEPENDENCIES(libapr-2 test_char_header)
+
+ADD_LIBRARY(apr-2 STATIC ${APR_SOURCES} ${APR_PUBLIC_HEADERS_GENERATED})
+SET(install_targets ${install_targets} apr-2)
+# no .pdb file generated for static libraries
+TARGET_LINK_LIBRARIES(apr-2 ${XMLLIB_LIBRARIES} ${APR_SYSTEM_LIBS})
+SET_TARGET_PROPERTIES(apr-2 PROPERTIES COMPILE_DEFINITIONS "APR_DECLARE_STATIC;APR_HAVE_MODULAR_DSO")
+ADD_DEPENDENCIES(apr-2 test_char_header)
+
+# libaprapp-2 and aprapp-2 are static
+ADD_LIBRARY(libaprapp-2 STATIC misc/win32/apr_app.c misc/win32/internal.c ${APR_PUBLIC_HEADERS_GENERATED})
+SET(install_targets ${install_targets} libaprapp-2)
+SET_TARGET_PROPERTIES(libaprapp-2 PROPERTIES COMPILE_DEFINITIONS APR_APP)
+
+ADD_LIBRARY(aprapp-2 STATIC misc/win32/apr_app.c misc/win32/internal.c ${APR_PUBLIC_HEADERS_GENERATED})
+SET(install_targets ${install_targets} aprapp-2)
+SET_TARGET_PROPERTIES(aprapp-2 PROPERTIES COMPILE_DEFINITIONS "APR_DECLARE_STATIC;APR_APP")
+
+IF(APU_HAVE_CRYPTO)
+  IF(NOT OPENSSL_FOUND)
+    MESSAGE(FATAL_ERROR "Only OpenSSL-based crypto is currently implemented in the cmake build")
+  ENDIF()
+  ADD_LIBRARY(apr_crypto_openssl-2 SHARED crypto/apr_crypto_openssl.c libapr.rc)
+  SET(install_targets ${install_targets} apr_crypto_openssl-2)
+  SET(install_bin_pdb ${install_bin_pdb} ${PROJECT_BINARY_DIR}/apr_crypto_openssl-2.pdb)
+  SET_TARGET_PROPERTIES(apr_crypto_openssl-2 PROPERTIES INCLUDE_DIRECTORIES "${APR_INCLUDE_DIRECTORIES};${OPENSSL_INCLUDE_DIR}")
+  SET_TARGET_PROPERTIES(apr_crypto_openssl-2 PROPERTIES COMPILE_FLAGS "-DDLL_NAME=apr_crypto_openssl")
+  TARGET_LINK_LIBRARIES(apr_crypto_openssl-2 libapr-2 ${APR_SYSTEM_LIBS} ${OPENSSL_LIBRARIES})
+ENDIF()
+
+IF(APU_HAVE_ODBC)
+  ADD_LIBRARY(apr_dbd_odbc-2 SHARED dbd/apr_dbd_odbc.c libapr.rc)
+  SET(install_targets ${install_targets} apr_dbd_odbc-2)
+  SET(install_bin_pdb ${install_bin_pdb} ${PROJECT_BINARY_DIR}/apr_dbd_odbc-2.pdb)
+  SET(dbd_drivers ${dbd_drivers} odbc)
+  TARGET_LINK_LIBRARIES(apr_dbd_odbc-2 libapr-2 ${APR_SYSTEM_LIBS} odbc32 odbccp32)
+  SET_PROPERTY(TARGET apr_dbd_odbc-2 APPEND PROPERTY LINK_FLAGS /export:apr_dbd_odbc_driver)
+  SET_TARGET_PROPERTIES(apr_dbd_odbc-2 PROPERTIES COMPILE_DEFINITIONS "APU_HAVE_ODBC;HAVE_SQL_H;APR_DECLARE_EXPORT;APU_DSO_MODULE_BUILD")
+  SET_TARGET_PROPERTIES(apr_dbd_odbc-2 PROPERTIES COMPILE_FLAGS "-DDLL_NAME=apr_dbd_odbc")
+ENDIF()
+
+IF(APR_BUILD_TESTAPR)
+  ENABLE_TESTING()
+  # Create a "check" target that displays test program output to the console.
+  ADD_CUSTOM_TARGET(check COMMAND ${CMAKE_CTEST_COMMAND} --verbose)
+
+  # copy data files to build directory so that we can run programs from there
+  EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E make_directory 
+                  ${PROJECT_BINARY_DIR}/data)
+  EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E copy_if_different 
+                  ${PROJECT_SOURCE_DIR}/test/data/billion-laughs.xml
+                  ${PROJECT_BINARY_DIR}/data/billion-laughs.xml)
+  EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E copy_if_different 
+                  ${PROJECT_SOURCE_DIR}/test/data/file_datafile.txt
+                  ${PROJECT_BINARY_DIR}/data/file_datafile.txt)
+  EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E copy_if_different
+                  ${PROJECT_SOURCE_DIR}/test/data/mmap_datafile.txt
+                  ${PROJECT_BINARY_DIR}/data/mmap_datafile.txt)
+
+  IF(TEST_STATIC_LIBS)
+    SET(whichapr    apr-2)
+    SET(whichaprapp aprapp-2)
+    SET(apiflag     -DAPR_DECLARE_STATIC)
+  ELSE()
+    SET(whichapr    libapr-2)
+    SET(whichaprapp libaprapp-2)
+    SET(apiflag)
+  ENDIF()
+
+  ADD_EXECUTABLE(testapp test/testapp.c)
+  TARGET_LINK_LIBRARIES(testapp ${whichapr} ${whichaprapp} ${XMLLIB_LIBRARIES} ${APR_SYSTEM_LIBS})
+  SET_TARGET_PROPERTIES(testapp PROPERTIES LINK_FLAGS /entry:wmainCRTStartup)
+  IF(apiflag)
+    SET_TARGET_PROPERTIES(testapp PROPERTIES COMPILE_FLAGS ${apiflag})
+  ENDIF()
+  ADD_TEST(NAME testapp COMMAND testapp)
+
+  ADD_EXECUTABLE(testall ${APR_TEST_SOURCES})
+  TARGET_LINK_LIBRARIES(testall ${whichapr} ${XMLLIB_LIBRARIES} ${APR_SYSTEM_LIBS})
+  IF(apiflag)
+    SET_TARGET_PROPERTIES(testall PROPERTIES COMPILE_FLAGS ${apiflag})
+  ENDIF()
+  ADD_TEST(NAME testall COMMAND testall)
+
+  ADD_LIBRARY(mod_test MODULE test/mod_test.c)
+  TARGET_LINK_LIBRARIES(mod_test ${whichapr} ${APR_SYSTEM_LIBS})
+  SET_PROPERTY(TARGET mod_test APPEND PROPERTY LINK_FLAGS /export:print_hello)
+  # nasty work-around for difficulties adding more than one additional flag
+  # (they get joined in a bad way behind the scenes)
+  GET_PROPERTY(link_flags TARGET mod_test PROPERTY LINK_FLAGS)
+  SET(link_flags "${link_flags} /export:count_reps")
+  SET_TARGET_PROPERTIES(mod_test PROPERTIES LINK_FLAGS ${link_flags})
+  IF(apiflag)
+    SET_TARGET_PROPERTIES(mod_test PROPERTIES COMPILE_FLAGS ${apiflag})
+  ENDIF()
+
+  # Build all the single-source executable files with no special build
+  # requirements.
+  SET(single_source_programs
+    test/dbd.c
+    test/echod.c
+    test/sendfile.c
+    test/sockperf.c
+    test/testlockperf.c
+    test/testmutexscope.c
+    test/globalmutexchild.c
+    test/occhild.c
+    test/proc_child.c
+    test/readchild.c
+    test/sockchild.c
+    test/testshmproducer.c
+    test/testshmconsumer.c
+    test/tryread.c
+    test/internal/testucs.c
+  )
+
+  FOREACH(sourcefile ${single_source_programs})
+    STRING(REGEX REPLACE ".*/([^\\]+)\\.c" "\\1" proggie ${sourcefile})
+    ADD_EXECUTABLE(${proggie} ${sourcefile})
+    TARGET_LINK_LIBRARIES(${proggie} ${whichapr} ${XMLLIB_LIBRARIES} ${APR_SYSTEM_LIBS})
+    IF(apiflag)
+      SET_TARGET_PROPERTIES(${proggie} PROPERTIES COMPILE_FLAGS ${apiflag})
+    ENDIF()
+  ENDFOREACH()
+
+  # Add tests for programs that run by themselves with no arguments.
+  SET(simple_tests
+    testmutexscope
+    testucs
+  )
+
+  FOREACH(simple ${simple_tests})
+    ADD_TEST(NAME ${simple} COMMAND ${simple})
+  ENDFOREACH()
+
+  # testlockperf takes forever on Windows with default counter limit
+  ADD_TEST(NAME testlockperf COMMAND testlockperf -c 50000)
+
+  # dbd and sendfile are run multiple times with different parameters.
+  FOREACH(somedbd ${dbd_drivers})
+    ADD_TEST(NAME dbd-${somedbd} COMMAND dbd ${somedbd})
+  ENDFOREACH()
+
+  FOREACH(sendfile_mode blocking nonblocking timeout)
+    ADD_TEST(NAME sendfile-${sendfile_mode} COMMAND sendfile client ${sendfile_mode} startserver)
+  ENDFOREACH()
+
+  # No test is added for echod+sockperf.  Those will have to be run manually.
+
+ENDIF (APR_BUILD_TESTAPR)
+
+# Installation
+
+INSTALL(TARGETS ${install_targets}
+        RUNTIME DESTINATION bin
+        LIBRARY DESTINATION lib
+        ARCHIVE DESTINATION lib
+       )
+
+IF(INSTALL_PDB)
+  INSTALL(FILES ${install_bin_pdb}
+          DESTINATION bin
+          CONFIGURATIONS RelWithDebInfo Debug)
+ENDIF()
+
+INSTALL(FILES ${APR_PUBLIC_HEADERS_STATIC} ${APR_PUBLIC_HEADERS_GENERATED} DESTINATION include)
+IF(APR_INSTALL_PRIVATE_H)
+  # Kludges for unexpected dependencies of httpd 2.x, not installed by default
+  SET(APR_PRIVATE_H_FOR_HTTPD
+    include/arch/win32/apr_arch_file_io.h
+    include/arch/win32/apr_arch_misc.h
+    include/arch/win32/apr_arch_utf8.h
+    include/arch/win32/apr_private.h
+    )
+  INSTALL(FILES ${APR_PRIVATE_H_FOR_HTTPD} DESTINATION include/arch/win32)
+ENDIF()
+
+STRING(TOUPPER "${CMAKE_BUILD_TYPE}" buildtype)
+MESSAGE(STATUS "")
+MESSAGE(STATUS "")
+MESSAGE(STATUS "APR configuration summary:")
+MESSAGE(STATUS "")
+
+MESSAGE(STATUS "  Build type ...................... : ${CMAKE_BUILD_TYPE}")
+MESSAGE(STATUS "  Install .pdb (if available)...... : ${INSTALL_PDB}")
+MESSAGE(STATUS "  Install prefix .................. : ${CMAKE_INSTALL_PREFIX}")
+MESSAGE(STATUS "  C compiler ...................... : ${CMAKE_C_COMPILER}")
+MESSAGE(STATUS "  IPv6 ............................ : ${APR_HAVE_IPV6}")
+MESSAGE(STATUS "  DBD ODBC driver ................. : ${APU_HAVE_ODBC}")
+MESSAGE(STATUS "  Use Expat ....................... : ${APU_USE_EXPAT}")
+MESSAGE(STATUS "  Use LibXml2 ..................... : ${APU_USE_LIBXML2}")
+MESSAGE(STATUS "  Minimum Windows version ......... : ${MIN_WINDOWS_VER}")
+MESSAGE(STATUS "  Library files for XML ........... : ${XMLLIB_LIBRARIES}")
+MESSAGE(STATUS "  Build test suite ................ : ${APR_BUILD_TESTAPR}")
+IF(TEST_STATIC_LIBS)
+MESSAGE(STATUS "    (testing static libraries)")
+ELSE()
+MESSAGE(STATUS "    (testing dynamic libraries)")
+ENDIF()
+MESSAGE(STATUS "  Install private .h for httpd .... : ${APR_INSTALL_PRIVATE_H}")
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 00000000000..f517ea3dc8d
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,488 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
+
+
+
+APACHE PORTABLE RUNTIME SUBCOMPONENTS: 
+
+The Apache Portable Runtime includes a number of subcomponents with
+separate copyright notices and license terms. Your use of the source
+code for these subcomponents is subject to the terms and conditions
+of the following licenses. 
+
+From strings/apr_fnmatch.c, include/apr_fnmatch.h, misc/unix/getopt.c,
+file_io/unix/mktemp.c, strings/apr_strings.c:
+
+/* 
+ * Copyright (c) 1987, 1993, 1994
+ *      The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by the University of
+ *      California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+
+From network_io/unix/inet_ntop.c, network_io/unix/inet_pton.c:
+
+/* Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+
+From dso/aix/dso.c:
+
+ *  Based on libdl (dlfcn.c/dlfcn.h) which is
+ *  Copyright (c) 1992,1993,1995,1996,1997,1988
+ *  Jens-Uwe Mager, Helios Software GmbH, Hannover, Germany.
+ *
+ *  Not derived from licensed software.
+ *
+ *  Permission is granted to freely use, copy, modify, and redistribute
+ *  this software, provided that the author is not construed to be liable
+ *  for any results of using the software, alterations are clearly marked
+ *  as such, and this notice is not modified.
+
+From strings/apr_strnatcmp.c, include/apr_strings.h:
+
+  strnatcmp.c -- Perform 'natural order' comparisons of strings in C.
+  Copyright (C) 2000 by Martin Pool <mbp@humbug.org.au>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+From strings/apr_snprintf.c:
+
+  *
+  * cvt - IEEE floating point formatting routines.
+  *       Derived from UNIX V7, Copyright(C) Caldera International Inc.
+  *
+
+  Copyright(C) Caldera International Inc.  2001-2002.  All rights reserved.
+  
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions are
+  met:
+
+  Redistributions of source code and documentation must retain the above
+  copyright notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  All advertising materials mentioning features or use of this software
+  must display the following acknowledgement:
+
+     This product includes software developed or owned by  Caldera
+     International, Inc.
+
+  Neither the name of Caldera International, Inc. nor the names of other
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
+  INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+  NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE FOR ANY DIRECT,
+  INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.
+
+For the include\apr_md5.h component: 
+
+ * This is work is derived from material Copyright RSA Data Security, Inc.
+ *
+ * The RSA copyright statement and Licence for that original material is
+ * included below. This is followed by the Apache copyright statement and
+ * licence for the modifications made to that material.
+
+   Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+   rights reserved.
+
+   License to copy and use this software is granted provided that it
+   is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+   Algorithm" in all material mentioning or referencing this software
+   or this function.
+
+   License is also granted to make and use derivative works provided
+   that such works are identified as "derived from the RSA Data
+   Security, Inc. MD5 Message-Digest Algorithm" in all material
+   mentioning or referencing the derived work.
+
+   RSA Data Security, Inc. makes no representations concerning either
+   the merchantability of this software or the suitability of this
+   software for any particular purpose. It is provided "as is"
+   without express or implied warranty of any kind.
+
+   These notices must be retained in any copies of any part of this
+   documentation and/or software.
+
+For the passwd\apr_md5.c component:
+
+ * This is work is derived from material Copyright RSA Data Security, Inc.
+ *
+ * The RSA copyright statement and Licence for that original material is
+ * included below. This is followed by the Apache copyright statement and
+ * licence for the modifications made to that material.
+
+   Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+   rights reserved.
+
+   License to copy and use this software is granted provided that it
+   is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+   Algorithm" in all material mentioning or referencing this software
+   or this function.
+
+   License is also granted to make and use derivative works provided
+   that such works are identified as "derived from the RSA Data
+   Security, Inc. MD5 Message-Digest Algorithm" in all material
+   mentioning or referencing the derived work.
+
+   RSA Data Security, Inc. makes no representations concerning either
+   the merchantability of this software or the suitability of this
+   software for any particular purpose. It is provided "as is"
+   without express or implied warranty of any kind.
+
+   These notices must be retained in any copies of any part of this
+   documentation and/or software.
+
+ * The apr_md5_encode() routine uses much code obtained from the FreeBSD 3.0
+ * MD5 crypt() function, which is licenced as follows:
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <phk@login.dknet.dk> wrote this file.  As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return.  Poul-Henning Kamp
+ * ----------------------------------------------------------------------------
+
+For the crypto\apr_md4.c component:
+
+ * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+ * rights reserved.
+ *
+ * License to copy and use this software is granted provided that it
+ * is identified as the "RSA Data Security, Inc. MD4 Message-Digest
+ * Algorithm" in all material mentioning or referencing this software
+ * or this function.
+ *
+ * License is also granted to make and use derivative works provided
+ * that such works are identified as "derived from the RSA Data
+ * Security, Inc. MD4 Message-Digest Algorithm" in all material
+ * mentioning or referencing the derived work.
+ *
+ * RSA Data Security, Inc. makes no representations concerning either
+ * the merchantability of this software or the suitability of this
+ * software for any particular purpose. It is provided "as is"
+ * without express or implied warranty of any kind.
+ *
+ * These notices must be retained in any copies of any part of this
+ * documentation and/or software.
+
+For the crypto\crypt_blowfish.c(.h) component:
+
+ * Written by Solar Designer <solar at openwall.com> in 1998-2011.
+ * No copyright is claimed, and the software is hereby placed in the public
+ * domain.  In case this attempt to disclaim copyright and place the software
+ * in the public domain is deemed null and void, then the software is
+ * Copyright (c) 1998-2011 Solar Designer and it is hereby released to the
+ * general public under the following terms:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted.
+ *
+ * There's ABSOLUTELY NO WARRANTY, express or implied.
+
+ See crypto/crypt_blowfish.c for more information.
+
+For the include\apr_md4.h component:
+
+ * This is derived from material copyright RSA Data Security, Inc.
+ * Their notice is reproduced below in its entirety.
+ *
+ * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+ * rights reserved.
+ *
+ * License to copy and use this software is granted provided that it
+ * is identified as the "RSA Data Security, Inc. MD4 Message-Digest
+ * Algorithm" in all material mentioning or referencing this software
+ * or this function.
+ *
+ * License is also granted to make and use derivative works provided
+ * that such works are identified as "derived from the RSA Data
+ * Security, Inc. MD4 Message-Digest Algorithm" in all material
+ * mentioning or referencing the derived work.
+ *
+ * RSA Data Security, Inc. makes no representations concerning either
+ * the merchantability of this software or the suitability of this
+ * software for any particular purpose. It is provided "as is"
+ * without express or implied warranty of any kind.
+ *
+ * These notices must be retained in any copies of any part of this
+ * documentation and/or software.
+
+For the test\testmd4.c component:
+
+ * This is derived from material copyright RSA Data Security, Inc.
+ * Their notice is reproduced below in its entirety.
+ *
+ * Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All
+ * rights reserved.
+ *
+ * RSA Data Security, Inc. makes no representations concerning either
+ * the merchantability of this software or the suitability of this
+ * software for any particular purpose. It is provided "as is"
+ * without express or implied warranty of any kind.
+ *
+ * These notices must be retained in any copies of any part of this
+ * documentation and/or software.
+
diff --git a/Makefile.in b/Makefile.in
index b885139d8bc..c3c203bcf42 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,101 +1,180 @@
+
+srcdir=@srcdir@
+VPATH=@srcdir@
+top_srcdir=@apr_srcdir@
+top_blddir=@apr_builddir@
+
 #
 # APR (Apache Portable Runtime) library Makefile.
 #
-SHELL=@SH@
+CPP = @CPP@
+
+# get substituted into some targets
+APR_MAJOR_VERSION=@APR_MAJOR_VERSION@
 
-#
-# Macros for compilation commands
-#
-@SET_MAKE@
-MFLAGS_STATIC=
-RM=@RM@
-CC=@CC@
-CFLAGS=@CFLAGS@ @OPTIM@
-LIBS=@LIBS@
-LDFLAGS=@LDFLAGS@ $(LIBS)
-RANLIB=@RANLIB@
 #
 # Macros for supporting directories
 #
 INCDIR=./include
-INCDIR1=../include
-INCLUDES=-I$(INCDIR) -I$(INCDIR1)
+OSDIR=$(top_srcdir)/include/arch/@OSDIR@
+DEFOSDIR=$(INCDIR)/arch/@DEFAULT_OSDIR@
+INCLUDES=-I$(INCDIR) -I$(OSDIR) -I$(DEFOSDIR) -I$(top_srcdir)/include/arch/@DEFAULT_OSDIR@ -I$(top_srcdir)/include -I$(top_srcdir)/include/private -I$(top_blddir)/include/private
 
 #
 # Macros for target determination
 #
-MODULES=@MODULES@
-SUBDIRS=@SUBDIRS@
-#shmem/@OSDIR@
+CLEAN_SUBDIRS= test
+INSTALL_SUBDIRS=@INSTALL_SUBDIRS@
 
-LIBAPR = @LIBPREFIX@apr.a
+TARGET_LIB = lib@APR_LIBNAME@.la
+APR_PCFILE = apr-$(APR_MAJOR_VERSION).pc
+APR_CONFIG = apr-$(APR_MAJOR_VERSION)-config
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
 
-#
-# Rules for turning inputs into outputs
-#
-.c.o:
-	$(CC) $(CFLAGS) -c $(INCLUDES) $<
+EXTRA_OBJECTS = @EXTRA_OBJECTS@
+APR_DSO_MODULES = @APR_DSO_MODULES@
+LINK_MODULE = $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) $(LT_LDFLAGS) $(ALL_CFLAGS) $(ALL_LDFLAGS) $(APRUTIL_LDFLAGS) -release $(APR_MAJOR_VERSION) -module -rpath $(APR_DSO_LIBDIR)
+APR_DSO_LIBDIR = @APR_DSO_LIBDIR@
+APRUTIL_EXPORT_LIBS = @APRUTIL_EXPORT_LIBS@
 
 #
 # Rules for building specific targets, starting with 'all' for
 # building the entire package.
 #
-all: Makefile $(LIBAPR)
-
-$(LIBAPR): $(MODULES) subdirs
-	@rm -rf objs
-	@mkdir objs
-	@rm -f $@
-	for i in $(SUBDIRS); do cp $$i/*.o objs ; done;
-	$(AR) cr $@ objs/*.o
-	$(RANLIB) $@
-
-clean: subdirs_clean
-	$(RM) -f *.o *.a *.so objs/*.o
-
-depend: subdirs_depend
-
-distclean: subdirs_distclean
-	-$(RM) -f include/apr.h include/apr_private.h include/apr_private.h.in
-	-$(RM) -f *.o *.a *.so
-	-$(RM) -f config.cache config.status config.log configure
-	-$(RM) -f Makefile
-	-$(RM) -rf objs
-	cd test; make distclean; cd ..
-
-subdirs:
-	@for i in $(SUBDIRS); do \
-	    echo "===> $(SDP)lib/apr/$$i"; \
-	    ( cd $$i && $(MAKE) $(MFLAGS_STATIC) SDP='$(SDP)' \
-		CC='$(CC)' AUX_CFLAGS='$(AUX_CFLAGS)' RANLIB='$(RANLIB)' ) \
-		|| exit 1; \
-	    echo "<=== $(SDP)lib/apr/$$i"; \
-	done;
-
-subdirs_depend:
-	@for i in $(SUBDIRS); do \
-	    echo "===> $(SDP)lib/apr/$$i"; \
-	    ( cd $$i && $(MAKE) $(MFLAGS_STATIC) SDP='$(SDP)' depend ) \
-		|| exit 1; \
-	    echo "<=== $(SDP)lib/apr/$$i"; \
-	done;
-
-subdirs_clean:
-	@for i in $(SUBDIRS); do \
-	    echo "===> $(SDP)lib/apr/$$i"; \
-	    ( cd $$i && $(MAKE) $(MFLAGS_STATIC) SDP='$(SDP)' clean ) \
-		|| exit 1; \
-	    echo "<=== $(SDP)lib/apr/$$i"; \
-	done;
-
-subdirs_distclean:
-	@for i in $(SUBDIRS); do \
-	    echo "===> $(SDP)lib/apr/$$i"; \
-	    ( cd $$i && $(MAKE) $(MFLAGS_STATIC) SDP='$(SDP)' distclean ) \
-		|| exit 1; \
-	    echo "<=== $(SDP)lib/apr/$$i"; \
-	done;
-
-install: all
-	
+TARGETS = $(TARGET_LIB) $(APR_DSO_MODULES) \
+	include/private/apr_escape_test_char.h apr.exp apr-config.out build/apr_rules.out
+
+LT_VERSION = @LT_VERSION@
+
+# bring in rules.mk for standard functionality
+@INCLUDE_RULES@
+@INCLUDE_OUTPUTS@
+
+CLEAN_TARGETS = apr-config.out apr.exp exports.c export_vars.c .make.dirs \
+	build/apr_rules.out tools/gen_test_char@EXEEXT@ \
+	tools/gen_test_char.o tools/gen_test_char.lo \
+	include/private/apr_escape_test_char.h
+DISTCLEAN_TARGETS = config.cache config.log config.status \
+	include/apr.h include/arch/unix/apr_private.h \
+	libtool $(APR_CONFIG) build/apr_rules.mk apr.pc \
+	build/pkg/pkginfo
+EXTRACLEAN_TARGETS = configure aclocal.m4 include/arch/unix/apr_private.h.in \
+	build-outputs.mk build/ltcf-c.sh build/aclocal.m4 \
+	build/ltconfig build/ltmain.sh \
+	build/argz.m4 build/libtool.m4 build/ltoptions.m4 \
+	build/ltsugar.m4 build/ltversion.m4 build/lt~obsolete.m4
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+bindir=@bindir@
+libdir=@libdir@
+includedir=@includedir@
+installbuilddir=@installbuilddir@
+
+LDADD_dbd_pgsql = @LDADD_dbd_pgsql@
+LDADD_dbd_oracle = @LDADD_dbd_oracle@
+LDADD_dbd_sqlite2 = @LDADD_dbd_sqlite2@
+LDADD_dbd_sqlite3 = @LDADD_dbd_sqlite3@
+LDADD_dbd_mysql = @LDADD_dbd_mysql@
+LDADD_dbd_odbc = @LDADD_dbd_odbc@
+LDADD_dbm_db = @LDADD_dbm_db@
+LDADD_dbm_gdbm = @LDADD_dbm_gdbm@
+LDADD_dbm_ndbm = @LDADD_dbm_ndbm@
+LDADD_crypto_openssl = @LDADD_crypto_openssl@
+LDADD_crypto_nss = @LDADD_crypto_nss@
+LDADD_crypto_commoncrypto = @LDADD_crypto_commoncrypto@
+
+# Create apr-config script suitable for the install tree
+apr-config.out: $(APR_CONFIG)
+	sed 's,^\(location=\).*$$,\1installed,' < $(APR_CONFIG) > $@
+
+# Create apr_rules.mk suitable for the install tree
+build/apr_rules.out: build/apr_rules.mk
+	sed -e 's,^\(apr_build.*=\).*$$,\1$(installbuilddir),' -e 's,^\(top_build.*=\).*$$,\1$(installbuilddir),' < build/apr_rules.mk > $@
+
+install: install-modules $(TARGETS)
+	$(APR_MKDIR) $(DESTDIR)$(libdir) $(DESTDIR)$(bindir) $(DESTDIR)$(installbuilddir) \
+		     $(DESTDIR)$(libdir)/pkgconfig $(DESTDIR)$(includedir)
+	$(INSTALL_DATA) $(top_blddir)/include/apr.h $(DESTDIR)$(includedir)
+	$(INSTALL_DATA) $(top_srcdir)/include/apu.h $(DESTDIR)$(includedir)
+	for f in $(top_srcdir)/include/apr_*.h $(top_srcdir)/include/apu_*.h; do \
+	    $(INSTALL_DATA) $${f} $(DESTDIR)$(includedir); \
+	done
+	for f in $(top_blddir)/include/apu_*.h; do \
+	    $(INSTALL_DATA) $${f} $(DESTDIR)$(includedir); \
+	done
+	$(LIBTOOL) --mode=install $(INSTALL) -m 755 $(TARGET_LIB) $(DESTDIR)$(libdir)
+	$(INSTALL_DATA) apr.exp $(DESTDIR)$(libdir)/apr.exp
+	$(INSTALL_DATA) apr.pc $(DESTDIR)$(libdir)/pkgconfig/$(APR_PCFILE)
+	for f in libtool shlibtool; do \
+	    if test -f $${f}; then $(INSTALL) -m 755 $${f} $(DESTDIR)$(installbuilddir); fi; \
+	done
+	$(INSTALL) -m 755 $(top_srcdir)/build/mkdir.sh $(DESTDIR)$(installbuilddir)
+	for f in make_exports.awk make_var_export.awk; do \
+	    $(INSTALL_DATA) $(top_srcdir)/build/$${f} $(DESTDIR)$(installbuilddir); \
+	done
+	$(INSTALL_DATA) build/apr_rules.out $(DESTDIR)$(installbuilddir)/apr_rules.mk
+	$(INSTALL) -m 755 apr-config.out $(DESTDIR)$(bindir)/$(APR_CONFIG)
+	@if [ $(INSTALL_SUBDIRS) != "none" ]; then \
+            for i in $(INSTALL_SUBDIRS); do \
+	        ( cd $$i ; $(MAKE) DESTDIR=$(DESTDIR) install ); \
+	    done \
+	fi
+
+$(TARGET_LIB): $(OBJECTS) $(EXTRA_OBJECTS)
+	$(LINK) @lib_target@ $(EXTRA_OBJECTS) $(ALL_LIBS) $(APRUTIL_EXPORT_LIBS)
+
+encoding/apr_escape.lo: include/private/apr_escape_test_char.h 
+
+install-modules: install-modules-@APR_HAVE_MODULES@
+
+install-modules-no:
+
+install-modules-yes: $(APR_DSO_MODULES)
+	$(APR_MKDIR) $(DESTDIR)$(APR_DSO_LIBDIR)
+	@for m in $(APR_DSO_MODULES); do $(LIBTOOL) $(LT_LTFLAGS) $(LTFLAGS) --mode=install $(INSTALL) -m 755 $$m $(DESTDIR)$(APR_DSO_LIBDIR); done
+
+exports.c: $(HEADERS)
+	$(APR_MKEXPORT) $(HEADERS) > $@
+
+export_vars.c: $(HEADERS)
+	$(APR_MKVAREXPORT) $(HEADERS) > $@
+
+apr.exp: exports.c export_vars.c
+	@echo "#! lib@APR_LIBNAME@.so" > $@
+	@echo "* This file was AUTOGENERATED at build time." >> $@
+	@echo "* Please do not edit by hand." >> $@
+	$(CPP) $(ALL_CPPFLAGS) $(ALL_INCLUDES) exports.c | grep "ap_hack_" | sed -e 's/^.*[)]\(.*\);$$/\1/' >> $@
+	$(CPP) $(ALL_CPPFLAGS) $(ALL_INCLUDES) export_vars.c | sed -e 's/^\#[^!]*//' | sed -e '/^$$/d' >> $@
+
+dox:
+	doxygen $(top_srcdir)/docs/doxygen.conf
+
+gcov: 
+	@build/run-gcov.sh
+
+test: check
+check: $(TARGET_LIB)
+	cd test && $(MAKE) all check
+
+etags:
+	etags `find . -name '*.[ch]'`
+
+OBJECTS_gen_test_char = tools/gen_test_char.lo $(LOCAL_LIBS)
+tools/gen_test_char.lo: tools/gen_test_char.c
+	$(APR_MKDIR) tools
+	$(LT_COMPILE)
+
+tools/gen_test_char@EXEEXT@: $(OBJECTS_gen_test_char)
+	$(LINK_PROG) $(OBJECTS_gen_test_char) $(ALL_LIBS)
+
+include/private/apr_escape_test_char.h: tools/gen_test_char@EXEEXT@
+	$(APR_MKDIR) include/private
+	tools/gen_test_char@EXEEXT@ > $@
+
+LINK_PROG = $(LIBTOOL) $(LTFLAGS) --mode=link $(COMPILE) $(LT_LDFLAGS) \
+	    @LT_NO_INSTALL@ $(ALL_LDFLAGS) -o $@
+
 # DO NOT REMOVE
+docs: $(INCDIR)/*.h
diff --git a/Makefile.win b/Makefile.win
new file mode 100644
index 00000000000..1db5bb2f822
--- /dev/null
+++ b/Makefile.win
@@ -0,0 +1,171 @@
+# Makefile.win for Win32 APR alone
+#
+# Targets are:
+#
+#     buildall - compile everything
+#     checkall - run APR regression tests
+#     install  - compile everything
+#     clean    - mop up everything
+#
+# You can override the build mechanism, choose only one;
+#
+#     USEMAK=1 - compile from exported make files
+#     USEDSW=1 - compile from .dsw / .dsp VC6 projects
+#     USESLN=1 - compile from converted .sln / .vcproj VC7+ files
+#
+# Define ARCH to your desired preference (your PATH must point
+# to the correct compiler tools!)  Choose only one;
+#
+#     ARCH="Win32 Release"
+#     ARCH="Win32 Debug"
+#     ARCH="x64 Release"
+#     ARCH="x64 Debug"
+#
+# For example;
+#
+#   nmake -f Makefile.win PREFIX=C:\APR buildall checkall install clean
+#
+
+!IF EXIST("apr.sln") && ([devenv /help > NUL 2>&1] == 0) \
+    && !defined(USEMAK) && !defined(USEDSW)
+USESLN=1
+USEMAK=0
+USEDSW=0
+!ELSEIF EXIST("apr.mak") && !defined(USEDSW)
+USESLN=0
+USEMAK=1
+USEDSW=0
+!ELSE
+USESLN=0
+USEMAK=0
+USEDSW=1
+!ENDIF
+
+PREFIX=..\apr-dist
+
+!IF [$(COMSPEC) /c cl /nologo /? \
+	| $(SystemRoot)\System32\find.exe "x64" >NUL ] == 0
+ARCH=x64 Release
+!ELSE
+ARCH=Win32 Release
+!ENDIF
+
+!MESSAGE ARCH        = $(ARCH)
+!MESSAGE PREFIX      = $(PREFIX)  (install path)
+
+
+# Utility and Translation things, nothing here for the user
+#
+!IF "$(ARCH)" == "Win32 Release"
+SLNARCH=Release|Win32
+ARCHOSPATH=Release
+LIBSOSPATH=LibR
+!ELSEIF "$(ARCH)" == "Win32 Debug"
+SLNARCH=Debug|Win32
+ARCHOSPATH=Debug
+LIBSOSPATH=LibD
+!ELSEIF "$(ARCH)" == "x64 Release"
+SLNARCH=Release|x64
+ARCHOSPATH=x64\Release
+LIBSOSPATH=x64\LibR
+!ELSEIF "$(ARCH)" == "x64 Debug"
+SLNARCH=Debug|x64
+ARCHOSPATH=x64\Debug
+LIBSOSPATH=x64\LibD
+!ENDIF
+
+!IFNDEF MAKEOPT
+# Only default the behavior if MAKEOPT= is omitted
+!IFDEF _NMAKE_VER
+# Microsoft NMake options
+MAKEOPT=-nologo
+!ELSEIF "$(MAKE)" == "make"
+# Borland make options?  Not really supported (yet)
+MAKEOPT=-s -N
+!ENDIF
+!ENDIF
+
+
+all: buildall checkall
+
+!IF $(USEMAK) == 1
+
+clean:
+	$(MAKE) $(MAKEOPT) -f Makefile.win ARCH="$(ARCH)" \
+		CTARGET=CLEAN buildall
+
+buildall:
+	$(MAKE) $(MAKEOPT) -f apr.mak         CFG="apr - $(ARCH)" RECURSE=0 $(CTARGET)
+	$(MAKE) $(MAKEOPT) -f libapr.mak      CFG="libapr - $(ARCH)" RECURSE=0 $(CTARGET)
+	cd build
+	 $(MAKE) $(MAKEOPT) -f aprapp.mak     CFG="aprapp - $(ARCH)" RECURSE=0 $(CTARGET)
+	 $(MAKE) $(MAKEOPT) -f libaprapp.mak  CFG="libaprapp - $(ARCH)" RECURSE=0 $(CTARGET)
+	cd ..
+
+!ELSEIF $(USESLN) == 1
+
+clean:
+	-devenv apr.sln /useenv /clean "$(SLNARCH)" /project libaprapp
+	-devenv apr.sln /useenv /clean "$(SLNARCH)" /project libapr
+	-devenv apr.sln /useenv /clean "$(SLNARCH)" /project aprapp
+	-devenv apr.sln /useenv /clean "$(SLNARCH)" /project apr
+
+buildall:
+	devenv apr.sln /useenv /build "$(SLNARCH)" /project apr
+	devenv apr.sln /useenv /build "$(SLNARCH)" /project aprapp
+	devenv apr.sln /useenv /build "$(SLNARCH)" /project libapr
+	devenv apr.sln /useenv /build "$(SLNARCH)" /project libaprapp
+
+!ELSE
+#	$(USEDSP) == 1
+
+clean:
+	-msdev apr.dsw /USEENV /MAKE "libaprapp - $(ARCH)" /CLEAN
+	-msdev apr.dsw /USEENV /MAKE "libapr - $(ARCH)" /CLEAN
+	-msdev apr.dsw /USEENV /MAKE "aprapp - $(ARCH)" /CLEAN
+	-msdev apr.dsw /USEENV /MAKE "apr - $(ARCH)" /CLEAN
+
+buildall:
+	@msdev apr.dsw /USEENV /MAKE "apr - $(ARCH)"
+	@msdev apr.dsw /USEENV /MAKE "aprapp - $(ARCH)"
+	@msdev apr.dsw /USEENV /MAKE "libapr - $(ARCH)"
+	@msdev apr.dsw /USEENV /MAKE "libaprapp - $(ARCH)"
+
+!ENDIF
+
+
+checkapr:
+	cd test
+	 $(MAKE) $(MAKEOPT) -f Makefile.win MODEL=static \
+		OUTDIR=$(LIBSOSPATH) check
+	 $(MAKE) $(MAKEOPT) -f Makefile.win MODEL=dynamic \
+		OUTDIR=$(ARCHOSPATH) check
+	 cd ..
+
+checkall: checkapr
+
+
+install:
+	echo Y >.y
+	echo A >.A
+	@if NOT EXIST "$(PREFIX)\."		mkdir "$(PREFIX)"
+	@if NOT EXIST "$(PREFIX)\bin\."		mkdir "$(PREFIX)\bin"
+	@if NOT EXIST "$(PREFIX)\include\."	mkdir "$(PREFIX)\include"
+	@if NOT EXIST "$(PREFIX)\lib\."		mkdir "$(PREFIX)\lib"
+	copy CHANGES "$(PREFIX)\CHANGES.txt" <.y
+	copy LICENSE "$(PREFIX)\LICENSE.txt" <.y
+	copy NOTICE  "$(PREFIX)\NOTICE.txt"  <.y
+	xcopy include\*.h		"$(PREFIX)\include\" /d < .a
+	copy $(LIBSOSPATH)\apr-2.lib		"$(PREFIX)\lib\" <.y
+	copy $(LIBSOSPATH)\apr-2.pdb		"$(PREFIX)\lib\" <.y
+	copy $(LIBSOSPATH)\aprapp-2.lib		"$(PREFIX)\lib\" <.y
+	copy $(LIBSOSPATH)\aprapp-2.pdb		"$(PREFIX)\lib\" <.y
+	copy $(ARCHOSPATH)\libaprapp-2.lib	"$(PREFIX)\lib\" <.y
+	copy $(ARCHOSPATH)\libaprapp-2.pdb	"$(PREFIX)\lib\" <.y
+	copy $(ARCHOSPATH)\libapr-2.lib		"$(PREFIX)\lib\" <.y
+	copy $(ARCHOSPATH)\libapr-2.exp		"$(PREFIX)\lib\" <.y
+	copy $(ARCHOSPATH)\libapr-2.dll		"$(PREFIX)\bin\" <.y
+	copy $(ARCHOSPATH)\libapr-2.pdb		"$(PREFIX)\bin\" <.y
+	del .y
+	del .a
+
diff --git a/NOTICE b/NOTICE
new file mode 100644
index 00000000000..e8117bf13a5
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,15 @@
+Apache Portable Runtime
+Copyright (c) 2000-2018 The Apache Software Foundation.
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+
+Portions of this software were developed at the National Center
+for Supercomputing Applications (NCSA) at the University of
+Illinois at Urbana-Champaign.
+
+This software contains code derived from the RSA Data Security
+Inc. MD5 Message-Digest Algorithm.
+
+This software contains code derived from UNIX V7, Copyright(C)
+Caldera International Inc.
diff --git a/NWGNUmakefile b/NWGNUmakefile
new file mode 100644
index 00000000000..9b472007760
--- /dev/null
+++ b/NWGNUmakefile
@@ -0,0 +1,465 @@
+#
+# Declare the sub-directories to be built here
+#
+
+SUBDIRS = \
+	build \
+	xml \
+	$(EOLIST)
+
+ifdef WITH_APR_DBD
+SUBDIRS += \
+	dbd \
+	$(EOLIST) 
+endif
+
+ifdef WITH_APR_DBM
+SUBDIRS += \
+	dbm \
+	$(EOLIST) 
+endif
+
+#
+# Get the 'head' of the build environment.  This includes default targets and
+# paths to tools
+#
+ifndef APR_WORK
+export APR_WORK = $(CURDIR)
+endif
+include $(APR_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 \
+			$(APR)/include/private \
+			$(APR)/include/arch/netware \
+			$(APR)/include/arch/unix \
+			$(APR)/dbm/sdbm \
+			$(APR)/random/unix \
+			$(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	= aprlib
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION	= Apache Portability Runtime Library $(VERSION_STR) $(VERSION_SKT)
+
+#
+# This is used by the '-threadname' directive.  If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME	=
+#
+# If this is specified, it will override VERSION value in
+# $(APR_WORK)/build/NWGNUenvironment.inc
+#
+NLM_VERSION	=
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE	=
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM	=
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM	=
+
+#
+# If this is specified it will be used by the link '-check' directive
+#
+NLM_CHECK_SYM	=
+
+#
+# If this is 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 $(APR)/misc/netware/apache.xdc.  XDCData can
+# be disabled by setting APACHE_UNIPROC in the environment
+#
+XDCDATA		=
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+	$(OBJDIR)/$(NLM_NAME).nlm \
+	$(EOLIST)
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+	$(OBJDIR)/aprlib.lib \
+	$(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+	$(OBJDIR)/libprews.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) \
+	$(APRLIB) \
+	$(APRXMLLIB) \
+	$(EOLIST)
+
+ifdef EXPATSDK
+ifdef EXPAT_LINK_STATIC
+FILES_nlm_libs += \
+	$(EXPAT_LIB) \
+	$(EOLIST)
+endif
+endif
+
+#
+# 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 = \
+	libc \
+	$(EOLIST)
+
+# Include the Winsock libraries if Winsock is being used
+ifndef USE_STDSOCKETS
+FILES_nlm_modules += ws2_32 \
+	$(EOLIST)
+endif
+
+ifdef EXPATSDK
+ifndef EXPAT_LINK_STATIC
+FILES_nlm_modules += \
+	$(EXPAT_NLM) \
+	$(EOLIST)
+endif
+endif
+
+#
+# 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 = \
+	@$(NOVI)/libc.imp \
+	@$(NOVI)/netware.imp \
+	$(EOLIST)
+
+# Include the Winsock imports if Winsock is being used
+ifndef USE_STDSOCKETS
+FILES_nlm_Ximports +=  \
+	@$(NOVI)/ws2nlm.imp \
+	$(EOLIST)
+FILES_nlm_imports +=  \
+	WSAStartupRTags \
+	WSACleanupRTag \
+	$(EOLIST)
+endif
+
+ifdef EXPATSDK
+ifndef EXPAT_LINK_STATIC
+FILES_nlm_Ximports += \
+	@$(EXPAT_IMP) \
+	$(EOLIST)
+endif
+endif
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+	@aprlib.imp \
+	$(EOLIST)
+
+#
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+	$(OBJDIR)/apr_atomic.o \
+	$(OBJDIR)/apr_base64.o \
+	$(OBJDIR)/apr_brigade.o \
+	$(OBJDIR)/apr_buckets.o \
+	$(OBJDIR)/apr_buckets_alloc.o \
+	$(OBJDIR)/apr_buckets_eos.o \
+	$(OBJDIR)/apr_buckets_file.o \
+	$(OBJDIR)/apr_buckets_flush.o \
+	$(OBJDIR)/apr_buckets_heap.o \
+	$(OBJDIR)/apr_buckets_mmap.o \
+	$(OBJDIR)/apr_buckets_pipe.o \
+	$(OBJDIR)/apr_buckets_pool.o \
+	$(OBJDIR)/apr_buckets_refcount.o \
+	$(OBJDIR)/apr_buckets_simple.o \
+	$(OBJDIR)/apr_buckets_socket.o \
+	$(OBJDIR)/apr_cpystrn.o \
+	$(OBJDIR)/apr_date.o \
+	$(OBJDIR)/apr_dbd.o \
+	$(OBJDIR)/apr_dbm.o \
+	$(OBJDIR)/apr_dbm_berkeleydb.o \
+	$(OBJDIR)/apr_dbm_sdbm.o \
+	$(OBJDIR)/apr_escape.o \
+	$(OBJDIR)/apr_fnmatch.o \
+	$(OBJDIR)/apr_getpass.o \
+	$(OBJDIR)/apr_hash.o \
+	$(OBJDIR)/apr_hooks.o \
+	$(OBJDIR)/apr_md4.o \
+	$(OBJDIR)/apr_md5.o \
+	$(OBJDIR)/apr_memcache.o \
+	$(OBJDIR)/apr_passwd.o \
+	$(OBJDIR)/apr_pools.o \
+	$(OBJDIR)/apr_queue.o \
+	$(OBJDIR)/apr_random.o \
+	$(OBJDIR)/apr_redis.o \
+	$(OBJDIR)/apr_reslist.o \
+	$(OBJDIR)/apr_rmm.o \
+	$(OBJDIR)/apr_sha1.o \
+	$(OBJDIR)/apr_siphash.o \
+ 	$(OBJDIR)/apr_skiplist.o \
+	$(OBJDIR)/apr_snprintf.o \
+	$(OBJDIR)/apr_strings.o \
+	$(OBJDIR)/apr_strmatch.o \
+	$(OBJDIR)/apr_strnatcmp.o \
+	$(OBJDIR)/apr_strtok.o \
+	$(OBJDIR)/apr_tables.o \
+	$(OBJDIR)/apr_thread_pool.o \
+	$(OBJDIR)/apr_uri.o \
+	$(OBJDIR)/apu_dso.o \
+	$(OBJDIR)/buffer.o \
+	$(OBJDIR)/charset.o \
+	$(OBJDIR)/crypt_blowfish.o \
+	$(OBJDIR)/common.o \
+	$(OBJDIR)/copy.o \
+	$(OBJDIR)/dir.o \
+	$(OBJDIR)/dso.o \
+	$(OBJDIR)/env.o \
+	$(OBJDIR)/errorcodes.o \
+	$(OBJDIR)/fileacc.o \
+	$(OBJDIR)/filedup.o \
+	$(OBJDIR)/filepath.o \
+	$(OBJDIR)/filepath_util.o \
+	$(OBJDIR)/filestat.o \
+	$(OBJDIR)/filesys.o \
+	$(OBJDIR)/flock.o \
+	$(OBJDIR)/fullrw.o \
+	$(OBJDIR)/getopt.o \
+	$(OBJDIR)/getuuid.o \
+	$(OBJDIR)/groupinfo.o \
+	$(OBJDIR)/inet_ntop.o \
+	$(OBJDIR)/inet_pton.o \
+	$(OBJDIR)/mktemp.o \
+	$(OBJDIR)/mmap.o \
+	$(OBJDIR)/multicast.o \
+	$(OBJDIR)/open.o \
+	$(OBJDIR)/otherchild.o \
+	$(OBJDIR)/pipe.o \
+	$(OBJDIR)/pollcb.o \
+	$(OBJDIR)/pollset.o \
+	$(OBJDIR)/printf.o \
+	$(OBJDIR)/proc.o \
+	$(OBJDIR)/proc_mutex.o \
+	$(OBJDIR)/procsup.o \
+	$(OBJDIR)/rand.o \
+	$(OBJDIR)/readwrite.o \
+	$(OBJDIR)/sdbm.o \
+	$(OBJDIR)/sdbm_hash.o \
+	$(OBJDIR)/sdbm_lock.o \
+	$(OBJDIR)/sdbm_pair.o \
+	$(OBJDIR)/seek.o \
+	$(OBJDIR)/select.o \
+	$(OBJDIR)/sendrecv.o \
+	$(OBJDIR)/sha2.o \
+	$(OBJDIR)/sha2_glue.o \
+	$(OBJDIR)/shm.o \
+	$(OBJDIR)/signals.o \
+	$(OBJDIR)/sockaddr.o \
+	$(OBJDIR)/socket_util.o \
+	$(OBJDIR)/sockets.o \
+	$(OBJDIR)/sockopt.o \
+	$(OBJDIR)/start.o \
+	$(OBJDIR)/tempdir.o \
+	$(OBJDIR)/thread.o \
+	$(OBJDIR)/thread_cond.o \
+	$(OBJDIR)/thread_mutex.o \
+	$(OBJDIR)/thread_rwlock.o \
+	$(OBJDIR)/threadpriv.o \
+	$(OBJDIR)/time.o \
+	$(OBJDIR)/timestr.o \
+	$(OBJDIR)/userinfo.o \
+	$(OBJDIR)/uuid.o \
+	$(OBJDIR)/version.o \
+	$(OBJDIR)/waitio.o \
+	$(OBJDIR)/wakeup.o \
+	$(OBJDIR)/xlate.o \
+	$(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 $(APR_WORK)/build/NWGNUhead.inc for examples)
+#
+
+install :: nlms $(INSTDIRS) FORCE
+	$(call COPY,$(APR)/$(TARGET_nlm),$(INSTALLBASE)/)
+ifndef DEST
+	-$(call COPY,$(APR)/STATUS,$(INSTALLBASE)/STATUS.apr)
+	-$(call COPY,$(APR)/LICENSE,$(INSTALLBASE)/)
+	-$(call COPY,$(APR)/CHANGES,$(INSTALLBASE)/CHANGES.apr)
+	@-$(call COPYR,$(APR)/docs,$(INSTALLBASE)/docs/)
+endif
+
+ifndef DEST
+installdev :: $(INSTDEVDIRS) FORCE
+	$(call COPY,$(APR)/include/*.h,$(INSTALLBASE)/include/)
+	$(call COPY,$(APR)/*.imp,$(INSTALLBASE)/lib/)
+	$(call COPY,$(APR)/misc/netware/*.xdc,$(INSTALLBASE)/lib/)
+	$(call COPY,$(APR)/$(TARGET_lib),$(INSTALLBASE)/lib/)
+	$(call COPY,$(APR)/$(TARGET_nlm),$(INSTALLBASE)/bin/)
+
+$(INSTDEVDIRS) ::
+	$(call MKDIR,$@)
+endif
+
+#
+# Any specialized rules here
+#
+
+vpath filepath.c file_io/win32
+vpath %.c atomic/netware:strings:tables:passwd:time/unix
+vpath %.c file_io/netware:file_io/unix:locks/netware:misc/netware:misc/unix
+vpath %.c threadproc/netware:poll/unix:shmem/unix:support/unix:random/unix
+vpath %.c dso/netware:memory/unix:mmap/unix:user/netware:util-misc
+vpath %.c buckets:crypto:dbd:dbm:dbm/sdbm:encoding:hooks:memcache:redis:misc:strmatch:uri:xlate
+
+# Use the win32 network_io if Winsock is being used
+ifndef USE_STDSOCKETS
+vpath %.c network_io/win32
+endif
+vpath %.c network_io/unix
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(APRBUILD)/NWGNUtail.inc
+
+
diff --git a/README b/README
new file mode 100644
index 00000000000..c97cd704601
--- /dev/null
+++ b/README
@@ -0,0 +1,235 @@
+Apache Portable Runtime Library (APR)
+=====================================
+
+   The Apache Portable Runtime Library provides a predictable and
+   consistent interface to underlying platform-specific
+   implementations, with an API to which software developers may code
+   and be assured of predictable if not identical behavior regardless
+   of the platform on which their software is built, relieving them of
+   the need to code special-case conditions to work around or take
+   advantage of platform-specific deficiencies or features.
+
+   APR and its companion libraries are implemented entirely in C
+   and provide a common programming interface across a wide variety
+   of operating system platforms without sacrificing performance.
+   Currently supported platforms include:
+
+     UNIX variants
+     Windows
+     Netware
+     Mac OS X
+     OS/2
+
+   To give a brief overview, the primary core
+   subsystems of APR 1.3 include the following:
+
+     Atomic operations
+     Dynamic Shared Object loading
+     File I/O
+     Locks (mutexes, condition variables, etc)
+     Memory management (high performance allocators)
+     Memory-mapped files
+     Multicast Sockets
+     Network I/O
+     Shared memory
+     Thread and Process management
+     Various data structures (tables, hashes, priority queues, etc)
+
+   APR 2.0 also provides a number of utility functions and library
+   compatibility interfaces.  These were formerly part of APR-util,
+   a seperate utility library in version 1 releases.  These include;
+
+     Hashing and UUID services
+     Multiple SQL DBD client interfaces
+     Multiple flat-database DBM client interfaces
+     Typesafe function Hooks abstraction
+     MemCache interface
+     Date parsing rourtines
+     Resource Lists
+     Thread Pools
+     Queues
+     Relocatable Memory Management functions
+     String filename-style pattern matching
+     URI Parsing
+     Charset translation (iconv based)
+     XML parsing (expat based)
+
+   For a more complete list, please refer to the following URLs:
+
+     http://apr.apache.org/docs/apr/modules.html
+
+   Users of APR 0.9 should be aware that migrating to the APR 1.x
+   programming interfaces may require some adjustments; APR 1.x is
+   neither source nor binary compatible with earlier APR 0.9 releases.
+   Users of APR 1.x can expect consistent interfaces and binary backwards
+   compatibility throughout the entire APR 1.x release cycle, as defined
+   in our versioning rules:
+
+     http://apr.apache.org/versioning.html
+
+   APR is already used extensively by the Apache HTTP Server
+   version 2 and the Subversion revision control system, to
+   name but a few.  We list all known projects using APR at
+   http://apr.apache.org/projects.html -- so please let us know
+   if you find our libraries useful in your own projects!
+
+
+Database Providers
+==================
+Interfaces for copy-left licensed MySQL and gdbm DBD drivers, and 
+Berkeley DB DBM all ship as part of the distribution.  To avoid licensing
+incompatibilities, these are not built by default.  To enable support, 
+the corresponding use the --with-{provider} option, but be aware that 
+these licenses may introduce licensing implications for your compiled code.
+Similarly, the bindings for propritary drivers such as Oracle must also be 
+explicitly enabled.
+
+Whenever distributing apr-util in combination with database client 
+drivers, always review the license requirements of all components.
+
+
+Using a Subversion Checkout on Unix
+===================================
+
+If you are building APR from SVN, you need to perform a prerequisite
+step.  You must have autoconf, libtool and python installed for this 
+to work.  The prerequisite is simply;
+
+  ./buildconf
+
+If you are building APR from a distribution tarball, buildconf is
+already run for you, and you do not need autoconf, libtool or python
+installed or to run buildconf unless you have patched APR's buildconf 
+inputs (such as configure.in, build.conf, virtually any file within 
+the build/ tree, or you add or remove source files).
+
+Remember when updating from svn that you must rerun ./buildconf again 
+to effect any changes made to the build schema in your fresh update.
+
+
+Configuring and Building APR on Unix
+====================================
+
+Simply;
+
+   ./configure --prefix=/desired/path/of/apr
+   make
+   make test
+   make install
+
+Configure has additional options, ./configure --help will offer you
+those choices.  You may also add CC=compiler CFLAGS="compiler flags"
+etc. prior to the ./configure statement (on the same line).  Please
+be warned, some flags must be passed as part of the CC command,
+itself, in order for autoconf to make the right determinations. Eg.;
+
+  CC="gcc -m64" ./configure --prefix=/desired/path/of/apr
+
+will inform APR that you are compiling to a 64 bit CPU, and autoconf
+must consider that when setting up all of APR's internal and external
+type declarations.
+
+For more verbose output from testall, you may wish to invoke testall
+with the flag;
+
+   cd test
+   ./testall -v
+
+
+Building APR RPM files on Linux
+===============================
+
+Run the following to create SRPMs:
+
+rpmbuild -ts apr-<version>.tar.bz2
+rpmbuild -ts apr-util-<version>.tar.bz2
+
+Run the following to create RPMs (or build from the SRPMs):
+
+rpmbuild -tb apr-<version>.tar.bz2
+rpmbuild -tb apr-util-<version>.tar.bz2
+
+Resolve dependencies as appropriate.
+
+
+Configuring and Building APR on Windows
+=======================================
+
+Using Visual Studio, you can build and run the test validation of APR.
+The Makefile.win make file has a bunch of documentation about it's
+options, but a trivial build is simply;
+
+  nmake -f Makefile.win 
+  nmake -f Makefile.win PREFIX=c:\desired\path\of\apr install
+
+Note you must manually modify the include\apr.hw file before you
+build to change default options, see the #define APR_HAS_... or the
+#define APR_HAVE_... statements.  Be careful, many of these aren't
+appropriate to be modified.  The most common change is 
+
+#define APR_HAVE_IPV6           1
+
+rather than 0 if this build of APR will be used strictly on machines
+with the IPv6 adapter support installed.
+
+It's trivial to include the apr.dsp (for a static library) or the
+libapr.dsp (for a dynamic library) in your own build project, or you
+can load apr.dsw in Visual Studio 2002 (.NET) or later, which will
+convert these for you into apr.sln and associated .vcproj files.
+
+When using APR as a dynamic library, nothing special is required,
+simply link to libapr-2.lib.  To use it as a static library, simply 
+define APR_DECLARE_STATIC before you include any apr header files 
+in your source, and link to apr-2.lib instead.
+
+On windows, selection of database drivers is via the environment values
+DBD_LIST (for mysql, oracle, pgsql, sqlite2 and/or sqlite3) 
+and DBM_LIST (db and/or gdbm).  DBD odbc and DBM sdbm are unconditionally
+compiled and installed, do not include these in the list.
+
+
+Generating Test Coverage information with gcc
+=============================================
+
+If you want to generate test coverage data, use the following steps:
+
+  ./buildconf
+  CFLAGS="-fprofile-arcs -ftest-coverage" ./configure
+  make
+  cd test
+  make
+  ./testall
+  cd ..
+  make gcov
+
+
+Cryptographic Software Notice
+=============================
+This distribution includes cryptographic software.  The country in 
+which you currently reside may have restrictions on the import, 
+possession, use, and/or re-export to another country, of 
+encryption software.  BEFORE using any encryption software, please 
+check your country's laws, regulations and policies concerning the
+import, possession, or use, and re-export of encryption software, to 
+see if this is permitted.  See http://www.wassenaar.org/ for more
+information.
+
+The U.S. Government Department of Commerce, Bureau of Industry and
+Security (BIS), has classified this software as Export Commodity 
+Control Number (ECCN) 5D002.C.1, which includes information security
+software using or performing cryptographic functions with asymmetric
+algorithms.  The form and manner of this Apache Software Foundation
+distribution makes it eligible for export under the License Exception
+ENC Technology Software Unrestricted (TSU) exception (see the BIS 
+Export Administration Regulations, Section 740.13) for both object 
+code and source code.
+
+The following provides more details on the included cryptographic
+software:
+
+  APR provides an abstract interface for symmetrical cryptographic
+  functions that make use of a general-purpose encryption library,
+  such as OpenSSL, NSS, or the operating system's platform-specific
+  facilities. This interface is known as the apr_crypto interface,
+  with implementation beneath the /crypto directory.
+
diff --git a/README.FREETDS b/README.FREETDS
new file mode 100644
index 00000000000..15eeeaf39a9
--- /dev/null
+++ b/README.FREETDS
@@ -0,0 +1,11 @@
+The APR DBD Driver for FreeTDS has been removed from the build.
+It is known to have problems, and we are not able to maintain it.
+
+The source code is still available.  If you want it and are able
+to manage maintenance for yourself, you can patch the build and
+work through issues that affect you, but you're on your own.
+
+We expect that for most users, the ODBC driver will serve as
+an alternative.
+
+Sorry.
diff --git a/README.cmake b/README.cmake
new file mode 100644
index 00000000000..380f97bce55
--- /dev/null
+++ b/README.cmake
@@ -0,0 +1,171 @@
+Experimental cmake-based build support for APR on Microsoft Windows
+
+Status
+------
+
+This build support is currently intended only for Microsoft Windows.
+
+This build support is experimental.  Specifically,
+
+* It does not support all features of APR.
+* Some components may not be built correctly and/or in a manner
+  compatible with the previous Windows build support.
+* Build interfaces, such as the mechanisms which are used to enable
+  optional functionality or specify prerequisites, may change from
+  release to release as feedback is received from users and bugs and
+  limitations are resolved.
+
+Important: Refer to the "Known Bugs and Limitations" section for further
+           information.
+
+           It is beyond the scope of this document to document or explain
+           how to utilize the various cmake features, such as different
+           build backends or provisions for finding support libraries.
+
+           Please refer to the cmake documentation for additional information
+           that applies to building any project with cmake.
+
+Prerequisites
+-------------
+
+The following tools must be in PATH:
+
+* cmake, version 2.8 or later
+  cmake version 3.1.3 or later is required to work with current OpenSSL
+  releases.  (OpenSSL is an optional prerequisite of APR.)
+* If using a command-line compiler: compiler and linker and related tools
+  (Refer to the cmake documentation for more information.)
+
+The following support libraries are mandatory:
+
+* Either expat or libxml2
+
+Additional support libraries allow optional features of APR to be enabled:
+
+* OpenSSL
+* many others potentially, though the build support isn't currently
+  implemented
+
+How to build
+------------
+
+1. cd to a clean directory for building (i.e., don't build in your
+   source tree)
+
+2. Some cmake backends may want your compile tools in PATH.  (Hint: "Visual
+   Studio Command Prompt")
+
+3. set CMAKE_LIBRARY_PATH=d:\path\to\prereq1\lib;d:\path\to\prereq2\lib;...
+
+4. set CMAKE_INCLUDE_PATH=d:\path\to\prereq1\include;d:\path\to\prereq2\include;...
+
+5. cmake -G "some backend, like 'NMake Makefiles'"
+     -DCMAKE_INSTALL_PREFIX=d:/path/to/aprinst
+     -DAPR-specific-flags
+     d:/path/to/aprsource
+
+   Alternately, use cmake-gui and update settings in the GUI.
+
+   APR feature flags:
+
+       Exactly one of APU_USE_EXPAT and APU_USE_LIBXML2 must be specified.
+
+       APU_USE_EXPAT          Use Expat as the underlying XML implementation
+                              Default: ON
+       APU_USE_LIBXML2        Use libxml2 as the underlying XML
+                              implementation
+                              Default: OFF
+       APR_INSTALL_PRIVATE_H  Install extra .h files which are required when
+                              building httpd and Subversion but which aren't
+                              intended for use by applications.
+                              Default: OFF
+       APU_HAVE_CRYPTO        Build crypt support (only the OpenSSL
+                              implementation is currently supported)
+                              Default: OFF
+       APU_HAVE_ODBC          Build ODBC DBD driver
+                              Default: ON
+       APR_HAVE_IPV6          Enable IPv6 support
+                              Default: ON
+       APR_BUILD_TESTAPR      Build APR test suite
+                              Default: OFF
+       TEST_STATIC_LIBS       Build the test suite to test the APR static
+                              library instead of the APR dynamic library.
+                              Default: OFF
+                              In order to build the test suite against both
+                              static and dynamic libraries, separate builds
+                              will be required, one with TEST_STATIC_LIBS
+                              set to ON.
+       MIN_WINDOWS_VER        Minimum Windows version supported by this build
+                              (This controls the setting of _WIN32_WINNT.)
+                              "Vista" or "Windows7" or a numeric value like
+                              "0x0601"
+                              Default: "Vista"
+                              For desktop/server equivalence or other values,
+                              refer to
+                              http://msdn.microsoft.com/en-us/library/windows/
+                              desktop/aa383745(v=vs.85).aspx
+       INSTALL_PDB            Install .pdb files if generated.
+                              Default: ON
+
+   LIBXML2_ICONV_INCLUDE_DIR, LIBXML2_ICONV_LIBRARIES
+
+       If using libxml2 for the XML implementation and the build of libxml2
+       requires iconv, set these variables to allow iconv includes
+       and libraries to be found.
+
+   CMAKE_C_FLAGS_RELEASE, _DEBUG, _RELWITHDEBINFO, _MINSIZEREL
+
+   CMAKE_BUILD_TYPE
+
+       For NMake Makefiles the choices are at least DEBUG, RELEASE,
+       RELWITHDEBINFO, and MINSIZEREL
+       Other backends make have other selections.
+
+6. build using chosen backend (e.g., "nmake install")
+
+Tested generators
+-----------------
+
+1. NMake Makefiles
+
+This has been tested successfully with the following:
+
+* Visual Studio 2008 64-bit (requires KB948127 hot fix)
+* Visual Studio 2012 64-bit
+
+2. Visual Studio 11 (Visual Studio 2012 project files)
+
+Known Bugs and Limitations
+--------------------------
+
+* If include/apr.h or other generated files have been created in the source
+  directory by another build system, they will be used unexpectedly and
+  cause the build to fail.
+* Options should be provided for remaining features, along with finding any
+  necessary libraries
+  + APR_POOL_DEBUG
+  + DBM:
+    . APU_HAVE_GDBM
+    . APU_HAVE_NDBM
+    . APU_HAVE_DB
+  + DBD:
+    . APU_HAVE_PGSQL
+    . APU_HAVE_MYSQL
+    . APU_HAVE_SQLITE3
+    . APU_HAVE_SQLITE2
+    . APU_HAVE_ORACLE
+  + CRYPTO:
+    . APU_HAVE_NSS
+  + APU_HAVE_ICONV
+* Static builds of APR modules are not supported.
+* XML implementation (i.e., Expat or libxml2) could support static XML impl
+  with apr-2.lib.
+
+Generally:
+
+* Many APR features have not been tested with this build.
+* Developers need to examine the existing Windows build in great detail and see
+  what is missing from the cmake-based build, whether a feature or some build
+  nuance.
+* Any feedback you can provide on your experiences with this build will be
+  helpful.
diff --git a/SConscript b/SConscript
new file mode 100644
index 00000000000..b2c60a8a991
--- /dev/null
+++ b/SConscript
@@ -0,0 +1,33 @@
+
+Import("env")
+
+files = env.core_lib_files()
+
+(major, minor, patch) = env.APRVersion()
+
+libapr = env.SharedLibrary('apr-%d' % (major), files)
+tests = Split("""
+  abts.c testutil.c
+  testtime.c teststr.c testvsn.c testipsub.c testshm.c
+  testmmap.c testud.c testtable.c testsleep.c testpools.c
+	testfmt.c testfile.c testdir.c testfileinfo.c testrand.c
+	testdso.c testoc.c testdup.c testsockets.c testproc.c
+	testpoll.c testlock.c testsockopt.c testpipe.c
+	testthread.c testhash.c testargs.c testnames.c testuser.c
+	testpath.c testenv.c testprocmutex.c testfnmatch.c
+	testatomic.c testflock.c testsock.c testglobalmutex.c
+	teststrnatcmp.c testfilecopy.c testtemp.c testlfs.c
+	testcond.c testuri.c testmemcache.c testdate.c
+	testxlate.c testdbd.c testrmm.c testmd4.c
+	teststrmatch.c testpass.c testcrypto.c testqueue.c
+	testbuckets.c testxml.c testdbm.c testuuid.c testmd5.c
+	testreslist.c dbd.c
+""")
+
+tenv = env.Clone()
+tenv.AppendUnique(LIBS = libapr)
+testall = tenv.Program('testall', source = ["test/"+t for t in tests])
+
+targets = [libapr, testall]
+
+Return("targets")
diff --git a/SConstruct b/SConstruct
new file mode 100644
index 00000000000..cdeb8b7ce39
--- /dev/null
+++ b/SConstruct
@@ -0,0 +1,49 @@
+#!/usr/bin/env scons
+#
+
+from build import APREnv
+
+EnsureSConsVersion(1, 1, 0)
+
+vars = Variables('build.py')
+
+vars.Add('prefix', 'Installation Prefix', '/usr/local')
+vars.Add('maintainer_mode', 'Turn on debugging and compile time warnings', 0)
+vars.Add('profile', 'Turn on profiling for the build (GCC)', 0)
+vars.Add('lfs', 'Large file support on 32-bit platforms', 1)
+vars.Add('ipv6', 'IPv6 support', 1)
+vars.Add(EnumVariable('pool_debug', 'Turn on pools debugging', 'no',
+                      allowed_values=('yes', 'no', 'verbose', 'verbose-alloc', 'lifetime', 'owner', 'all')))
+
+env = APREnv(args=ARGUMENTS, variables=vars)
+
+
+Help(vars.GenerateHelpText(env))
+
+env.APRHints()
+
+env = env.APRAutoconf()
+
+if env['maintainer_mode']:
+  if env.is_gcc():
+    env.AppendUnique(CPPFLAGS = ['-g', '-Wall', '-Wmissing-prototypes', '-Wstrict-prototypes', '-Wmissing-declarations'])
+
+if env['profile']:
+  env.Filter(CPPFLAGS = '-g')
+  env.AppendUnique(CPPFLAGS = ['-pg'])
+
+if env['pool_debug'] != 'no':
+  flags = {'yes': 1,
+           'verbose': 2,
+           'lifetime': 4,
+           'owner': 8,
+           'verbose-alloc': 16,
+            'all': 31}
+  env.AppendUnique(CPPFLAGS = "-DAPR_POOL_DEBUG=%d" % flags[env['pool_debug']])
+
+Export("env")
+
+# TODO: Support debug/release builds
+targets = SConscript("SConscript", variant_dir='builds/default', duplicate=0)
+
+env.Default(targets)
diff --git a/STATUS b/STATUS
new file mode 100644
index 00000000000..50a9e98c935
--- /dev/null
+++ b/STATUS
@@ -0,0 +1,558 @@
+APACHE PORTABLE RUNTIME (APR) LIBRARY STATUS:        -*- coding: utf-8 -*-
+Last modified at [$Date$]
+
+The current version of this file can be found at:
+
+  * http://svn.apache.org/repos/asf/apr/apr/trunk/STATUS
+
+
+NOTICE:
+
+Effective with version 2.0 , apr-util ceases to exist.  For reference,
+the final standalone apr-util can be found in subversion at:
+
+  * http://svn.apache.org/repos/asf/apr/apr-util/branches -r784519
+
+
+Patches considered for backport are noted in their branches' STATUS:
+
+  * http://svn.apache.org/repos/asf/apr/apr/branches/0.9.x/STATUS
+  * http://svn.apache.org/repos/asf/apr/apr/branches/1.3.x/STATUS
+  * http://svn.apache.org/repos/asf/apr/apr/branches/1.4.x/STATUS
+  * http://svn.apache.org/repos/asf/apr/apr/branches/1.5.x/STATUS
+  * http://svn.apache.org/repos/asf/apr/apr-util/branches/0.9.x/STATUS
+  * http://svn.apache.org/repos/asf/apr/apr-util/branches/1.3.x/STATUS
+  * http://svn.apache.org/repos/asf/apr/apr-util/branches/1.4.x/STATUS
+  * http://svn.apache.org/repos/asf/apr/apr-util/branches/1.5.x/STATUS
+
+Releases:
+    2.0.0     : in development on trunk/
+    1.7.0     : in development on branches/1.7.x
+    1.6.4     : in maintenance
+    1.6.3     : released October 22, 2017
+    1.6.2     : released June 14, 2017
+    1.6.1     : not released
+    1.6.0     : not released
+    1.5.2     : released April 29, 2015
+    1.5.1     : released April 20, 2014
+    1.5.0     : released November 18, 2013
+    1.4.8     : released June 21, 2013
+    1.4.7     : not released
+    1.4.6     : released Feb 14, 2012
+    1.4.5     : released May 22, 2011
+    1.4.4     : released May 9, 2011
+    1.4.3     : not released
+    1.4.2     : released April 3, 2010
+    1.4.1     : not released
+    1.4.0     : not released
+    1.3.9     : released September 23, 2009
+    1.3.8     : released August 6, 2009
+    1.3.7     : released July 23, 2009
+    1.3.6     : released July 4, 2009
+    1.3.5     : released June 5, 2009
+    1.3.4     : not released
+    1.3.3     : released August 14, 2008
+    1.3.2     : released June 23, 2008
+    1.3.1     : not released
+    1.3.0     : released June 3, 2008
+    1.2.12    : released November 25, 2007
+    1.2.11    : released September 6, 2007
+    1.2.10    : not released
+    1.2.9     : released June 7, 2007
+    1.2.8     : released December 4, 2006
+    1.2.7     : released April 14, 2006
+    1.2.6     : released March 25, 2006
+    1.2.5     : not released
+    1.2.4     : not released
+    1.2.3     : not released
+    1.2.2     : released October 11, 2005 
+    1.2.1     : released August 18, 2005
+    1.2.0     : not released
+    1.1.2     : no such version
+    1.1.1     : released March 17, 2005
+    1.1.0     : released January 25, 2005
+    1.0.1     : released November 19, 2004
+    1.0.0     : released September 1, 2004
+    0.9.18    : in maintenance
+    0.9.17    : released November 25, 2007
+    0.9.16    : released September 6, 2007
+    0.9.15    : not released
+    0.9.14    : released June 7, 2007
+    0.9.13    : released December 4, 2006
+    0.9.12    : released April 13, 2006
+    0.9.11    : released March 30, 2006
+    0.9.10    : tagged March 22, 2006, not released
+    0.9.9     : tagged January 30, 2006, not released
+    0.9.8     : tagged January 27, 2006, not released
+    0.9.7     : released October 11, 2005
+    0.9.6     : released February 4, 2005
+    0.9.5     : released November 19, 2004
+    0.9.4     : released September 25, 2003
+    0.9.3     : released April 3, 2003
+    0.9.2     : released March 22, 2003
+    0.9.1     : released September 11, 2002
+    0.9.0     : released August 28, 2002
+
+Bundled with httpd:
+    2.0a9     : released December 12, 2000
+    2.0a8     : released November 20, 2000
+    2.0a7     : released October 8, 2000
+    2.0a6     : released August 18, 2000
+    2.0a5     : released August 4, 2000
+    2.0a4     : released June 7, 2000
+    2.0a3     : released April 28, 2000
+    2.0a2     : released March 31, 2000
+    2.0a1     : released March 10, 2000
+
+Contributors looking for a mission:
+
+  * Just do an egrep on "TODO" or "XXX" in the source.
+
+  * Review the bug database at: http://issues.apache.org/bugzilla/
+
+  * Review the "PatchAvailable" bugs in the bug database:
+
+    https://issues.apache.org/bugzilla/buglist.cgi?bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&product=APR&keywords=PatchAvailable
+
+    After testing, you can append a comment saying "Reviewed and tested".
+
+  * Open bugs in the bug database.
+
+
+RELEASE SHOWSTOPPERS:
+
+  * apr_file_rotating_* on most platforms
+
+CURRENT VOTES:
+
+
+CURRENT test/testall -v EXCEPTIONS:
+
+    Please add any platform anomilies to the following exception list.
+
+    * 'testipsub' will tickle an Solaris 8 getaddrinfo() IPv6 bug,
+      causing the test to hang.  Configure with --disable-ipv6 if
+      using an unpatched Solaris 8 installation.
+
+    * The 'testdso' tests will not work if configured with
+      --disable-shared since the loadable modules cannot be built.
+
+    * 'testdso' fails on older versions of OpenBSD due to dlsym(NULL,
+      ...) segfaulting.
+
+    * Win32 Not Implemented tests 
+        poll: pollcb not implemented
+        procmutex: lacks fork() support
+        sock : Sync behavior causes us to skip one test
+        sockets: tcp6_socket/udp6_socket skipped for no IPv6 adapter
+        sockopt: TCP isn't corkable
+        users: username: Groups from apr_uid_get not implemented
+
+    * Win32 tests are known to fail when APR_HAVE_IPV6, but there is no
+      ipv6 adapter is loaded (even loopback is sufficient).  There are
+      obnoxious getaddrinfo() missing results from looking up a fixed
+      IPv4-IPv6 mixed notation address, which reflect a Win32 bug.
+        ipsub: One test fails for IPv6 with no IPv6 adapter configured
+        sock : One test fails for IPv6 with no IPv6 adapter configured
+
+
+ONGOING REMINDERS FOR STYLE/SUBSTANCE OF CONTRIBUTING TO APR:
+
+    * Flush out the test suite and make sure it passes on all platforms.
+      We currently have about 450 functions in APR and 147 tests.  That
+      means we have a large number of functions that we can't verify are
+      actually portable.  This TODO includes finishing the migration to the
+      unified test suite, and adding more tests to make the suite
+      comprehensive.
+
+    * Eliminate the TODO's and XXX's by using the doxygen @bug feature
+      to allow us to better track the open issues, and provide historical
+      bug lists that help porters understand what was wrong in the old
+      versions of APR that they would be upgrading from.
+
+    * Continue to review, deprecate and eliminate from 2.0 all namespace
+      un-protected names throughout include/apr_foo.h headers.
+
+
+RELEASE NON-SHOWSTOPPERS BUT WOULD BE REAL NICE TO WRAP THESE UP:
+
+    * Implement TOS for linux and solaris and bsd network API's.
+      The patches below implement only one of these API's, see the
+      pointer to mod_ftp in this bugzilla incident for hints to offer
+      all the necessary implementations, for starters.
+        http://qaix.com/apache-http-server/569-729-patch-add-ip-tos-support-read.shtml
+        https://issues.apache.org/bugzilla/show_bug.cgi?id=42848
+
+    * Need a proper fragmentation control API for clearing apr_pool's,
+      where the block alloc/clear/realloc sequence introduces more and
+      more unusable spaces in the physical blocks.  APR must provide
+      a mechanism to recognize such fragmented conditions, free the
+      physical pages, and allocate a new single pool block.  See also
+        http://svn.haxx.se/dev/archive-2008-10/0070.shtml
+
+    * Implement apr_pool_realloc for consumers such as apr_vformatter,
+      where the possibility to extend an allocation exists.  Given that
+      an apr function does this, external consumers should be allowed to.
+
+    * Need some architecture/OS specific versions of the atomic operations.
+	progress: generic, solaris Sparc, FreeBSD5, linux, and OS/390 done
+	need: AIX, AS400, HPUX
+
+    * The new lock API is a full replacement for the old API, but is
+      not yet complete on all platforms. Components that are incomplete
+      or missing include:
+      Netware: apr_proc_mutex_*() (Is proc_mutex unnecessary on Netware?)
+		* proc_mutex is not necessary on NetWare since the OS does
+		  not support processes.  The proc_mutex APIs actually
+		  redirect to the thread_mutex APIs. (bnicholes)
+      OS/2: apr_thread_cond_*(), apr_proc_mutex_*()
+
+      Less critical components that we may wish to add at some point:
+      Beos: apr_thread_rwlock_try*lock()
+            apr_proc_mutex_trylock()
+      Unix: apr_thread_rwlock_*() for platforms w/o rwlocks in pthread
+
+    * Need to contemplate apr_strftime... platforms vary.  OtherBill
+      suggested this solution (but has no time to implement):
+        Document our list of 'supported' escapes.
+        Run some autoconf/m4 magic against the complete list we support.
+        Move the strftime re-implementation from time/win32 to time/unix.
+        Add some APR_HAVE_STRFTIME magic to use the system fn, or fail
+        over to time/unix/strftime.c.
+        Message-ID: <025e01c1a891$bf41f660$94c0b0d0@v505>
+
+    * Using reentrant libraries with non-threaded APR
+        - Anecdotal evidence exists that suggests it is bad to
+          mix reentrant and non-reentrant libraries and therefore
+          we should always use the reentrant versions.
+        - Unfortunately, on some platforms (AIX 4.2.1) defining
+          the reentrant flag (-D_THREAD_SAFE) causes builds to fail,
+          and so one would expect --disable-threads to fix this.
+          Although this has been fixed for that particular version
+          of AIX, it may be useful to only enable the reentrant
+          versions when threads are enabled.
+        How will we deal with this issue once APR becomes a standalone
+        library? It is perfectly legitimate to have apps needing
+        both versions (threaded/reentrant and non-threaded/non-reentrant)
+        on the same machine.
+        Wrowe chuckles, uhm, it already is.  And seems most have shifted
+        to shipping threaded builds, of at least apr itself.
+
+    * Pools debugging
+        - Find a way to do check if a pool is used in multiple
+          threads, while the creation flags say it isn't.  IOW,
+          when the pool was created with APR_POOL_FNEWALLOCATOR,
+          but without APR_POOL_FLOCK.
+          Currently, no matter what the creation flags say, we always
+          create a lock.  Without it integrity_check() and
+          apr_pool_num_bytes() blow up (because they traverse pools
+          child lists that possibly belong to another thread, in
+          combination with the pool having no lock).  However,
+          this might actually hide problems like creating a child pool
+          of a pool belonging to another thread.
+          Maybe a debug function apr_pool_set_owner(apr_thread_t *) in
+          combination with extra checks in integrity_check() will point
+          out these problems.  apr_pool_set_owner() would need to be called
+          everytime the owner(the thread the pool is being used in) of
+          the pool changes.
+
+        - Implement apr_pool_join and apr_pool_lock.  Those functions
+          are noops at the moment.
+
+        - Add stats to the pools code.  We already have basic stats
+          in debug mode.  Stats that tell us about wasted memory
+          in the production code require more thought.
+            Status: Sander Striker is looking into this (low priority)
+
+        David says this is a 1.1 issue.
+
+    * Get OTHER_CHILD support into Win32
+        Status: Bill S. is looking into this
+
+    * SysV semaphore support isn't usable by Apache when started as
+      root because we don't have a way to allow the semaphore to be
+      used by the configured User and Group.  Current work-around:
+      change the initial permissions to 0666.  Needed code:  See
+      1.3's http_main.c, SysV sem flavor of accept_mutex_init().
+      Status: Jim will look into this
+      Update: Apache deals with this itself, though it might be nice
+              if APR could do something.
+
+    * Build scripts do not recognise AIX 4.2.1 pthreads
+      Justin says: "Is this still true?"
+
+    * FirstBill says we need a new procattr, APR_CREATE_SUSPENDED (or
+      something similar) to direct ap_create_process to create the
+      process suspended. We also need a call to wake up the suspended 
+      process.  This may not be able to be implemented everywhere though.
+        Status: OtherBill asks, why?  What is the benefit, how is it
+        portably implemented?  Unless this creates some tangible that
+        mirrors another platform, then I'm -1.
+
+    * Replace tables with a proper opaque ADT that has pluggable
+      implementations (including something like the existing data type,
+      plus hash tables for speed, with options for more later).
+	Status: fanf is working on this.
+
+    * add a version number to apr_initialize() as an extra failsafe against
+      (APR) library version skew.
+      MsgID: <Pine.LNX.4.10.10005231712380.31927-100000@nebula.lyra.org>
+      Status: Greg -1, Jeff +1, Ryan +1, Tony -0(?), david +1
+
+    * add apr_crypt() and APR_HAS_CRYPT for apps to determine whether the
+      crypt() function is available, and a way to call it (whether it is
+      located in libc, libcrypt, or libufc)
+      Justin says: Should apr_crypt() be in apr-util?
+      Wrowe answers: of course!  It's called openssl DES_fcrypt ;-)
+
+    * use os_(un)cork in network_io/unix/sendrecv.c for FreeBSD's
+      sendfile implementation.
+
+      david: The socket options stuff is now in and using it should
+             reduce the number of syscalls that are required for 
+             os_cork and uncork, so the code should be reviewed to
+             make use of the new calls.  If no-one beats me to it I'll
+             get around to it soonish...
+
+    * toss the per-Makefile setup of INCLUDES; shift to rules.mk.in
+        rbb: This is a bad thing IMHO.  If we do this, then we
+             can't use these makefiles for anything else.  For example,
+             apr-util
+
+    * add the rest of the pool accessor declare/impl macros.
+      Justin says: Both thread and file have the accessors now.  Any others?
+      Status: Greg volunteers
+
+    * I think apr_open_stderr() and friends *should* dup() the
+      descriptor.  That would allow the new/returned file to be closed
+      (via pool cleanup or manually) without accidentally closing
+      stderr/out.
+      wrowe: votes -1, reasons directly manipulate this through APR
+
+    * need to export (in code, not just build scripts) the shared
+      library extension (e.g. ".so") for the platform. clients need to
+      use this to construct filenames to pass to apr_dso_load()
+      -- note on Win32 we distinguish 'apache module' names from other 
+         'loadable module' names, so be careful with Apache's directive.
+         AIX, HPUX may use similar (.so for a 'module's name while the
+         defaults .a or .sl are used for libs.)
+
+    * Possible gmtime_r replacement in explode_time
+      On Solaris (and possibly others), the gmtime_r libc function obtains
+      a mutex.  We have seen 21/25 threads being blocked in this mutex on 
+      a threaded httpd MPM when requesting static pages.  It may be worth 
+      it to hand optimize this since there is no real need for a mutex at 
+      the system level (straight arithmetic from what I can tell).  If you 
+      have access to the Solaris source code:
+        osnet_volume/usr/src/lib/libc/port/gen/time_comm.c.
+
+    * Add a way to query APR for what features it has at runtime (i.e. 
+      threads).
+      Justin says: I'm not completely sold on this, but it has been mentioned 
+                   before and at least added to STATUS.
+
+    * apr_xlate.h generates a bunch of compiler warnings.
+      Jeff asks: which platform?
+      Justin says: Solaris with Forte 6.1.
+
+    * fcntl() oddness on Solaris.  Under high loads, fcntl() decides to
+      return error code 46 (ENOLCK).
+
+      httpd (prefork MPM) error log says (predictably):
+
+      (46)No record locks available: couldn't grab the accept mutex
+ 
+      All of the children report this and subsequently exits.  httpd is now 
+      hosed.  AFAICT, this does not look to be an out-of-fds error.
+ 
+      Solaris's man page says:
+        ENOLCK
+           The  cmd argument is F_SETLK, F_SETLK64, F_SETLKW,  or
+           F_SETLKW64  and  satisfying the lock or unlock request
+           would result in the number of locked  regions  in  the
+           system exceeding a system-imposed limit.
+
+      Justin says: What is this system-imposed limit and how do we change it?
+                   This gives me more rationale for switching the default
+                   interprocess lock mechanism to pthread (if available).
+
+      Explanation (from Kristofer Spinka <kspinka@style.net>):
+      ============
+        The system imposed default limit of outstanding lock requests is
+        512.
+        You can verify this by, in a contemporary version of Solaris:
+
+        # mdb -k
+        > tune_t_flckrec/D
+        tune_t_flckrec:
+        tune_t_flckrec: 512
+
+        This can be increased by adding the following to /etc/system:
+
+        set tune_t_flckrec=1024
+
+        and rebooting.
+
+        Of course "1024" can be any reasonable limit, although we do not know
+        what "reasonable" should be, so be conservative, only increase this as
+        necessary.
+
+    * There are some optimizations that can be done to the new
+      apr_proc_*() functions (on UNIX). One that may reduce pointer
+      indirection would be to make the apr_proc_mutex_unix_lock_methods_t
+      first-class members of the apr_proc_mutex_t structure.
+
+    * Condition variables are tricky enough to use, and even trickier
+      to implement properly. We could really use a better test case
+      for those subtle quirks that sometimes creep into CV implementations.
+
+    * Once we are fully satisfied with the new lock API, we can
+      begin to migrate the old API to be implemented on top of the
+      new one, or just decide to get rid of it altogether.
+      
+    * FreeBSD returns 45 (EOPNOTSUPP) when the lockfile is on a NFS
+      partition when you call fcntl(F_SETLKW).  It may be good if we 
+      can somehow detect this and error out when creating the lock
+      rather than waiting for the error to occur when acquiring lock.
+
+    * Fix autoconf tests for strerror_r on BeOS and remove the hack in
+      misc/unix/errorcodes.c to get error reporting working.  Committed as
+      the solution is elusive at present.
+
+    * implement APR_PROGRAM_ENV and APR_PROGRAM_PATH on BeOS, OS/2, Netware
+
+    * stat() on a few platforms (notably Solaris and AIX) succeeds for
+      a non-directory even if a trailing '/' was specified in the
+      name.  APR should perhaps simulate the normal -1/ENOTDIR
+      behavior in APR routines which retrieve information about the
+      file.  Note: Win2K fails GetFileAttributesEx in this scenario.
+      See OtherBill's comments in this message to dev@httpd.apache.org:
+      Message-Id: <5.1.0.14.2.20020315080852.00bce168@localhost>
+
+    * Identify and implement those protection bits that have general 
+        usefulness, perhaps hidden, generic read-only [immutable],
+        effective current user permissions, etc.
+
+    * dso getsym implementation are becoming very strict about returning
+      a fn pointer v.s. a data pointer, this should be split in apr_dso.
+
+Interface Changes Postponed for APR 2.0:
+
+    * apr_proc_other_child_register()'s write_fd argument should be removed
+      or made used.  The comment in the API previously said:
+
+         write_fd duplicates the proc->out stream, it's really
+         redundant and should be replaced in the APR 1.0 API with a
+         bitflag of which proc->in/out/err handles should be health
+         checked.  no platform currently tests the pipes health.
+
+    * apr_atomic_casptr() has the volatile qualifier in the wrong
+      place: should take "pointer to volatile pointer to void", not
+      "pointer to pointer to volatile void".
+
+    * apr_socket_sendfile(): the offset parameter should not be
+      pass-by-reference, or it should be updated to do something
+      useful.
+
+    * apr_password_get(): the bufsize parameter should not be
+      pass-by-reference.
+
+    * apr_allocator.h: apr_memnode_t's use of uint32_t's doesn't match
+      well with allocation sizes being apr_size_t, possibly this can
+      be improved by using apr_size_t throughout.
+
+    * apr_hash_count() should take a const apr_hash_t * argument.
+
+    * apr_ino_t should be an ino64_t in LFS builds.
+
+    * possible type renames:
+
+        apr_file_info_t                  from apr_finfo_t 
+        apr_file_attrs_t                 from apr_fileattrs_t
+        apr_file_seek_where_t            from apr_seek_where_t
+        apr_lock_mech_e                  from apr_lockmech_e
+        apr_time_interval_t              from apr_interval_time_t
+        apr_time_interval_short_t        from apr_short_interval_time_t
+
+    * wrowe writes:
+      Looking at bug 32520, it occurs to me that exploding times using the
+      apr_time_exp_* functions; it would make more sense to split ->tm_usec into
+
+        ->tm_msec thousandths (milleseconds)
+        ->tm_usec millionths  (microseconds)
+
+      for most display purposes.  It's trivial to roll them together with the
+      format string %03d%03d if that's what's desired, or display simply
+      %02d.%03d if millisecond resolution is desired.  It would also shrink
+      the fields to int's so unpacking would be slightly slower, using them
+      would be slightly faster, for what's likely to be little impact on
+      performance.
+
+    * The other-child API doesn't allow the apr_exit_why_e to be passed to the
+      application's maintenance function.  The expected usage is that the
+      application calls apr_proc_wait[_all_procs]() and is given back
+      apr_exit_why_e and exit_code_or_signal_num, thus losing the original
+      (on Unix, at least) representation which held both pieces of information
+      in an int.  Both pieces of data should be available to the maintenance 
+      function so that it has the opportunity to take different actions.  An
+      example would be to issue messages about probable misconfiguration when
+      receiving a certain exit code and trying to restart otherwise.  Thus, 
+      apr_proc_other_child_alert() should take an additional apr_exit_why_e 
+      parameter, as should the application-provided maintenance function.  The 
+      exit-why value would be ignored in the same circumstances as the existing 
+      status parameter: reason != APR_OC_REASON_DEATH.
+
+    * apr_file_gets() should take an apr_size_t size parameter?
+
+    * apr_table_vdo should not continue iterating through the keys
+      list once the callback function returns non-zero; see JCW's
+      comment in apr_tables.c.
+
+    * The library SONAME should vary for the different library ABIs - 
+      i.e. LFS support, IPv6 support or not.
+
+    * remove APR_POLL_LASTDESC from apr_datatype_e.
+
+    * Almost every API in APR depends on pools, but pool semantics
+      aren't a good match for a lot of applications.  We need to find
+      a way to support alternate allocators polymorphically without
+      a significant performance penalty.
+
+    * apr_global_mutex_child_init and apr_proc_mutex_child_init aren't
+      portable.  There are a variety of problems with the locking API when it
+      is used with apr_create_proc instead of apr_fork.  First, _child_init
+      doesn't take a lockmech_e parameter so it causes a segfault after the
+      apr_proc_create, because the proc_mutex field hasn't been initialized.
+      When the lockmech_e parameter is added, it _still_ doesn't work, because
+      some lock mechanisms expect to inherit from the parent process.  For
+      example, sys V semaphores don't have a file to open, so the child process
+      can't reaquire the lock.
+
+      jerenkrantz says: This is not a showstopper and I believe the above
+      analysis is slightly confusing.  The real problem here is that
+      apr_*_mutex_child_init assumes a shared memory space - that is, the
+      children processes have access to the parent apr_*_mutex_t pointer.  The
+      children just call child_init on the original, inherited apr_*_mutex_t.
+      Unlike globalmutexchild in test, apr_*_mutex_create is *not* intended to
+      be called from the child and subsequently call child_init.  Instead,
+      apr_create_proc is intended to exec separate processes with disjoint
+      memory addresses.  Currently, APR does not provide a cross-platform
+      mechanism for joining an already existing lock.  A simple
+      'apr_*_mutex_join' which is intended to be called from separate
+      processes to an already-existing lock would solve this problem.
+      child_init is not intended to be used this way.  Even with SysV
+      semaphores, using IPC_PRIVATE should still work due to the parent-child
+      relationship.  A strawman has been posted to dev@apr:
+      Message-Id: <213031CF0406DE1AC426A411@[10.0.1.137]>
+
+    * The return type of a thread function (void *) is inconsistent with
+      the type used in apr_thread_exit()/apr_thread_join() (apr_status_t).
+      The thread function's return type should be changed to apr_status_t
+      so that a return from the thread main function has the same effect
+      as apr_thread_exit().
+      See Message-Id: <E16JjZA-0007hg-00@zakath.apana.org.au> for thread
+      discussing this.
+        +1: BrianH, Aaron, david, jerenkrantz
+      Status: Deferred to 2.0.0 (API change)
+
+
diff --git a/acconfig.h b/acconfig.h
deleted file mode 100644
index 5ad3008c6a7..00000000000
--- a/acconfig.h
+++ /dev/null
@@ -1,71 +0,0 @@
-#ifndef APR_PRIVATE_H
-#define APR_PRIVATE_H
-
-/* So that we can use inline on some critical functions, and use
- * GNUC attributes (such as to get -Wall warnings for printf-like
- * functions).  Only do this in gcc 2.7 or later ... it may work
- * on earlier stuff, but why chance it.
- *
- * We've since discovered that the gcc shipped with NeXT systems
- * as "cc" is completely broken.  It claims to be __GNUC__ and so
- * on, but it doesn't implement half of the things that __GNUC__
- * means.  In particular it's missing inline and the __attribute__
- * stuff.  So we hack around it.  PR#1613. -djg
- */
-#if !defined(__GNUC__) || __GNUC__ < 2 || \
-    (__GNUC__ == 2 && __GNUC_MINOR__ < 7) ||\
-    defined(NEXT)
-#define ap_inline
-#define __attribute__(__x)
-#define ENUM_BITFIELD(e,n,w)  signed int n : w
-#else
-#define ap_inline __inline__
-#define USE_GNU_INLINE
-#define ENUM_BITFIELD(e,n,w)  e n : w
-#endif
-
-@TOP@
-
-/* Various #defines we need to know about */
-#undef HAVE_LOCK_EX
-#undef HAVE_F_SETLK
-#undef HAVE_PTHREAD_PROCESS_SHARED
-#undef DEV_RANDOM
-#undef HAVE_TRUERAND
-
-/* Cross process serialization techniques */
-#undef USE_FLOCK_SERIALIZE
-#undef USE_SYSVSEM_SERIALIZE
-#undef USE_FCNTL_SERIALIZE
-#undef USE_PROC_PTHREAD_SERIALIZE
-#undef USE_PTHREAD_SERIALIZE
-
-#undef READDIR_IS_THREAD_SAFE
-
-#undef NEED_RLIM_T
-#undef USEBCOPY
-
-#undef HAVE_GMTOFF
-#undef USE_THREADS
-
-#undef SIZEOF_SSIZE_T
-#undef SIZEOF_OFF_T
-
-@BOTTOM@
-
-/* Make sure we have ssize_t defined to be somethine */
-#undef ssize_t
-
-#if !defined(HAVE_PTHREAD_SIGMASK) && defined(_AIX)
-#define pthread_sigmask sigprocmask
-#endif
-
-#if !defined(HAVE_STRCASECMP) && defined(HAVE_STRICMP)
-#define strcasecmp(s1,s2) stricmp(s1,s2)
-#endif
-
-#if !defined(HAVE_SOCKLEN_T)
-typedef int socklen_t;
-#endif
-
-#endif /* APR_PRIVATE_H */
diff --git a/aclocal.m4 b/aclocal.m4
deleted file mode 100644
index ce2128a4a88..00000000000
--- a/aclocal.m4
+++ /dev/null
@@ -1,199 +0,0 @@
-dnl ##
-dnl ##
-dnl ##
-define(AC_USE_FUNCTION,[dnl
-AC_CHECK_FUNCS($1)
-if test ".$ac_func_$1" = .yes; then 
-AC_DEFINE(USE_$2)
-fi
-])dnl
-dnl ##
-dnl ##
-dnl ##
-define(AC_CHECK_DEFINE,[dnl
-AC_CACHE_CHECK(for $1 in $2, ac_cv_define_$1,
-AC_EGREP_CPP([YES_IS_DEFINED], [
-#include <$2>
-#ifdef $1
-YES_IS_DEFINED
-#endif
-], ac_cv_define_$1=yes; AC_DEFINE(HAVE_$1), ac_cv_define_$1=no)
-)])dnl
-dnl ##
-dnl ##
-dnl ##
-define(AC_IFALLYES,[dnl
-ac_rc=yes
-for ac_spec in $1; do
-    ac_type=`echo "$ac_spec" | sed -e 's/:.*$//'`
-    ac_item=`echo "$ac_spec" | sed -e 's/^.*://'`
-    case $ac_type in
-        header )
-            ac_item=`echo "$ac_item" | sed 'y%./+-%__p_%'`
-            ac_var="ac_cv_header_$ac_item"
-            ;;
-        file )
-            ac_item=`echo "$ac_item" | sed 'y%./+-%__p_%'`
-            ac_var="ac_cv_file_$ac_item"
-            ;;
-        func )   ac_var="ac_cv_func_$ac_item"   ;;
-        define ) ac_var="ac_cv_define_$ac_item" ;;
-        custom ) ac_var="$ac_item" ;;
-    esac
-    eval "ac_val=\$$ac_var"
-    if test ".$ac_val" != .yes; then
-        ac_rc=no
-        break
-    fi
-done
-if test ".$ac_rc" = .yes; then
-    :
-    $2
-else
-    :
-    $3
-fi
-])dnl
-dnl ##
-dnl ##
-dnl ##
-define(AC_BEGIN_DECISION,[dnl
-ac_decision_item='$1'
-ac_decision_msg='FAILED'
-ac_decision=''
-])dnl
-define(AC_DECIDE,[dnl
-ac_decision='$1'
-ac_decision_msg='$2'
-ac_decision_$1=yes
-ac_decision_$1_msg='$2'
-])dnl
-define(AC_DECISION_OVERRIDE,[dnl
-    ac_decision=''
-    for ac_item in $1; do
-         eval "ac_decision_this=\$ac_decision_${ac_item}"
-         if test ".$ac_decision_this" = .yes; then
-             ac_decision=$ac_item
-             eval "ac_decision_msg=\$ac_decision_${ac_item}_msg"
-         fi
-    done
-])dnl
-define(AC_DECISION_FORCE,[dnl
-ac_decision="$1"
-eval "ac_decision_msg=\"\$ac_decision_${ac_decision}_msg\""
-])dnl
-define(AC_END_DECISION,[dnl
-if test ".$ac_decision" = .; then
-    echo "[$]0:Error: decision on $ac_decision_item failed" 1>&2
-    exit 1
-else
-    if test ".$ac_decision_msg" = .; then
-        ac_decision_msg="$ac_decision"
-    fi
-    AC_DEFINE_UNQUOTED(${ac_decision_item})
-    AC_MSG_RESULT([decision on $ac_decision_item... $ac_decision_msg])
-fi
-])dnl
-
-dnl ### AC_TRY_RUN had some problems actually using a programs return code,
-dnl ### so I am re-working it here to be used in APR's configure script.
-dnl MY_TRY_RUN(PROGRAM, [ACTION-IF-TRUE [, ACTION-IF-FALSE
-dnl            [, ACTION-IF-CROSS-COMPILING]]])
-AC_DEFUN(MY_TRY_RUN,
-[if test "$cross_compiling" = yes; then
-  ifelse([$4], ,
-    [errprint(__file__:__line__: warning: [AC_TRY_RUN] called without default to allow cross compiling
-)dnl
-  AC_MSG_ERROR(can not run test program while cross compiling)],
-  [$4])
-else
-  MY_TRY_RUN_NATIVE([$1], [$2], [$3])
-fi
-])
-
-dnl Like AC_TRY_RUN but assumes a native-environment (non-cross) compiler.
-dnl MY_TRY_RUN_NATIVE(PROGRAM, [ACTION-IF-TRUE [, ACTION-IF-FALSE]])
-AC_DEFUN(MY_TRY_RUN_NATIVE,
-[cat > conftest.$ac_ext <<EOF
-[#]line __oline__ "configure"
-#include "confdefs.h"
-ifelse(AC_LANG, CPLUSPLUS, [#ifdef __cplusplus
-extern "C" void exit(int);
-#endif
-])dnl
-[$1]
-EOF
-if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
-then
-dnl Don't remove the temporary files here, so they can be examined.
-  ifelse([$2], , :, [$2])
-else
-ifelse([$3], , , [  $3 
-  rm -fr conftest*
-])dnl
-fi
-rm -fr conftest*])
-dnl A variant of AC_CHECK_SIZEOF which allows the checking of
-dnl sizes of non-builtin types
-dnl AC_CHECK_SIZEOF_EXTENDED(INCLUDES, TYPE [, CROSS_SIZE])
-AC_DEFUN(AC_CHECK_SIZEOF_EXTENDED,
-[changequote(<<,>>)dnl
-dnl The name to #define
-define(<<AC_TYPE_NAME>>, translit(sizeof_$2, [a-z *], [A-Z_P]))dnl
-dnl The cache variable
-define(<<AC_CV_NAME>>, translit(ac_cv_sizeof_$2, [ *],[<p>]))dnl
-changequote([, ])dnl
-AC_MSG_CHECKING(size of $2)
-AC_CACHE_VAL(AC_CV_NAME,
-[AC_TRY_RUN([#include <stdio.h>
-$1
-main()
-{
-  FILE *f=fopen("conftestval","w");
-  if (!f) exit(1);
-  fprintf(f, "%d\n", sizeof($2));
-  exit(0);
-}], AC_CV_NAME=`cat conftestval`, AC_CV_NAME=0, ifelse([$3],,,
-AC_CV_NAME=$3))])dnl
-AC_MSG_RESULT($AC_CV_NAME)
-AC_DEFINE_UNQUOTED(AC_TYPE_NAME, $AC_CV_NAME)
-undefine([AC_TYPE_NAME])dnl
-undefine([AC_CV_NAME])dnl
-])
-
-dnl 
-dnl check for socklen_t, fall back to unsigned int
-dnl
-
-AC_DEFUN(APR_CHECK_SOCKLEN_T,[
-AC_CACHE_CHECK(for socklen_t, ac_cv_socklen_t,[
-AC_TRY_COMPILE([
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-],[
-socklen_t foo = (socklen_t) 0;
-],[
-    ac_cv_socklen_t=yes
-],[
-    ac_cv_socklen_t=no
-])
-])
-
-if test "$ac_cv_socklen_t" = "yes"; then
-  AC_DEFINE(HAVE_SOCKLEN_T, 1, [Whether you have socklen_t])
-fi
-])
-
-dnl Check for ranlib but, unlike the check provided with autoconf, set
-dnl RANLIB to "true" if there is no ranlib instead of setting it to ":".
-dnl OS/390 doesn't have ranlib and the make utility doesn't parse "RANLIB=:" 
-dnl the way we might want it to.
-
-AC_DEFUN(AC_PROG_RANLIB_NC,
-[AC_CHECK_PROG(RANLIB, ranlib, ranlib, true)])
-
-sinclude(threads.m4)
diff --git a/apr-config.in b/apr-config.in
new file mode 100644
index 00000000000..84b407356b6
--- /dev/null
+++ b/apr-config.in
@@ -0,0 +1,251 @@
+#!/bin/sh
+# 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.
+#
+
+# APR script designed to allow easy command line access to APR configuration
+# parameters.
+
+APR_MAJOR_VERSION="@APR_MAJOR_VERSION@"
+APR_DOTTED_VERSION="@APR_DOTTED_VERSION@"
+
+prefix="@prefix@"
+exec_prefix="@exec_prefix@"
+bindir="@bindir@"
+libdir="@libdir@"
+datarootdir="@datadir@"
+datadir="@datadir@"
+installbuilddir="@installbuilddir@"
+includedir="@includedir@"
+
+CC="@CC@"
+CPP="@CPP@"
+SHELL="@SHELL@"
+CPPFLAGS="@EXTRA_CPPFLAGS@"
+CFLAGS="@EXTRA_CFLAGS@"
+LDFLAGS="@EXTRA_LDFLAGS@"
+LIBS="@EXTRA_LIBS@"
+EXTRA_INCLUDES="@EXTRA_INCLUDES@"
+SHLIBPATH_VAR="@shlibpath_var@"
+APR_SOURCE_DIR="@apr_srcdir@"
+APR_BUILD_DIR="@apr_builddir@"
+APR_SO_EXT="@so_ext@"
+APR_LIB_TARGET="@export_lib_target@"
+APR_LIBNAME="@APR_LIBNAME@"
+
+# NOTE: the following line is modified during 'make install': alter with care!
+location=@APR_CONFIG_LOCATION@
+
+show_usage()
+{
+    cat << EOF
+Usage: apr-$APR_MAJOR_VERSION-config [OPTION]
+
+Known values for OPTION are:
+  --prefix[=DIR]    change prefix to DIR
+  --bindir          print location where binaries are installed
+  --includedir      print location where headers are installed
+  --cc              print C compiler name
+  --cpp             print C preprocessor name and any required options
+  --cflags          print C compiler flags
+  --cppflags        print C preprocessor flags
+  --includes        print include information
+  --ldflags         print linker flags
+  --libs            print additional libraries to link against
+  --srcdir          print APR source directory
+  --installbuilddir print APR build helper directory
+  --link-ld         print link switch(es) for linking to APR
+  --link-libtool    print the libtool inputs for linking to APR
+  --shlib-path-var  print the name of the shared library path env var
+  --apr-la-file     print the path to the .la file, if available
+  --apr-so-ext      print the extensions of shared objects on this platform
+  --apr-lib-target  print the libtool target information
+  --apr-libtool     print the path to APR's libtool
+  --version         print the APR's version as a dotted triple
+  --help            print this help
+
+When linking with libtool, an application should do something like:
+  APR_LIBS="\`apr-$APR_MAJOR_VERSION-config --link-libtool --libs\`"
+or when linking directly:
+  APR_LIBS="\`apr-$APR_MAJOR_VERSION-config --link-ld --libs\`"
+
+An application should use the results of --cflags, --cppflags, --includes,
+and --ldflags in their build process.
+EOF
+}
+
+if test $# -eq 0; then
+    show_usage
+    exit 1
+fi
+
+if test "$location" = "installed"; then
+    LA_FILE="$libdir/lib${APR_LIBNAME}.la"
+else
+    LA_FILE="$APR_BUILD_DIR/lib${APR_LIBNAME}.la"
+fi
+
+flags=""
+
+while test $# -gt 0; do
+    # Normalize the prefix.
+    case "$1" in
+    -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+    *) optarg= ;;
+    esac
+
+    case "$1" in
+    # It is possible for the user to override our prefix.
+    --prefix=*)
+    prefix=$optarg
+    ;;
+    --prefix)
+    echo $prefix
+    exit 0
+    ;;
+    --bindir)
+    echo $bindir
+    exit 0
+    ;;
+    --includedir)
+    if test "$location" = "installed"; then
+        flags="$includedir"
+    elif test "$location" = "source"; then
+        flags="$APR_SOURCE_DIR/include"
+    else
+        # this is for VPATH builds
+        flags="$APR_BUILD_DIR/include $APR_SOURCE_DIR/include"
+    fi
+    echo $flags
+    exit 0
+    ;;
+    --cc)
+    echo $CC
+    exit 0
+    ;;
+    --cpp)
+    echo $CPP
+    exit 0
+    ;;
+    --cflags)
+    flags="$flags $CFLAGS"
+    ;;
+    --cppflags)
+    flags="$flags $CPPFLAGS"
+    ;;
+    --libs)
+    flags="$flags $LIBS"
+    ;;
+    --ldflags)
+    flags="$flags $LDFLAGS"
+    ;;
+    --includes)
+    if test "$location" = "installed"; then
+        flags="$flags -I$includedir $EXTRA_INCLUDES"
+    elif test "$location" = "source"; then
+        flags="$flags -I$APR_SOURCE_DIR/include $EXTRA_INCLUDES"
+    else
+        # this is for VPATH builds
+        flags="$flags -I$APR_BUILD_DIR/include -I$APR_SOURCE_DIR/include $EXTRA_INCLUDES"
+    fi
+    ;;
+    --srcdir)
+    echo $APR_SOURCE_DIR
+    exit 0
+    ;;
+    --installbuilddir)
+    if test "$location" = "installed"; then
+        echo "${installbuilddir}"
+    elif test "$location" = "source"; then
+        echo "$APR_SOURCE_DIR/build"
+    else
+        # this is for VPATH builds
+        echo "$APR_BUILD_DIR/build"
+    fi
+    exit 0
+    ;;
+    --version)
+    echo $APR_DOTTED_VERSION
+    exit 0
+    ;;
+    --link-ld)
+    if test "$location" = "installed"; then
+        ### avoid using -L if libdir is a "standard" location like /usr/lib
+        flags="$flags -L$libdir -l${APR_LIBNAME}"
+    else
+        ### this surely can't work since the library is in .libs?
+        flags="$flags -L$APR_BUILD_DIR -l${APR_LIBNAME}"
+    fi
+    ;;
+    --link-libtool)
+    # If the LA_FILE exists where we think it should be, use it.  If we're
+    # installed and the LA_FILE does not exist, assume to use -L/-l
+    # (the LA_FILE may not have been installed).  If we're building ourselves,
+    # we'll assume that at some point the .la file be created.
+    if test -f "$LA_FILE"; then
+        flags="$flags $LA_FILE"
+    elif test "$location" = "installed"; then
+        ### avoid using -L if libdir is a "standard" location like /usr/lib
+        # Since the user is specifying they are linking with libtool, we
+        # *know* that -R will be recognized by libtool.
+        flags="$flags -L$libdir -R$libdir -l${APR_LIBNAME}"
+    else
+        flags="$flags $LA_FILE"
+    fi
+    ;;
+    --shlib-path-var)
+    echo "$SHLIBPATH_VAR"
+    exit 0
+    ;;
+    --apr-la-file)
+    if test -f "$LA_FILE"; then
+        flags="$flags $LA_FILE"
+    fi
+    ;;
+    --apr-so-ext)
+    echo "$APR_SO_EXT"
+    exit 0
+    ;;
+    --apr-lib-target)
+    echo "$APR_LIB_TARGET"
+    exit 0
+    ;;
+    --apr-libtool)
+    if test "$location" = "installed"; then
+        echo "${installbuilddir}/libtool"
+    else
+        echo "$APR_BUILD_DIR/libtool"
+    fi
+    exit 0
+    ;;
+    --help)
+    show_usage
+    exit 0
+    ;;
+    *)
+    show_usage
+    exit 1
+    ;;
+    esac
+
+    # Next please.
+    shift
+done
+
+if test -n "$flags"; then
+  echo "$flags"
+fi
+
+exit 0
diff --git a/apr.dsp b/apr.dsp
index c30f9ecc16b..c5b3f480d3f 100644
--- a/apr.dsp
+++ b/apr.dsp
@@ -1,32 +1,36 @@
-# Microsoft Developer Studio Project File - Name="aprlib" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# Microsoft Developer Studio Project File - Name="apr" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
 # ** DO NOT EDIT **
 
 # TARGTYPE "Win32 (x86) Static Library" 0x0104
 
-CFG=aprlib - Win32 Debug
+CFG=apr - 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 "aprlib.mak".
+!MESSAGE NMAKE /f "apr.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 "aprlib.mak" CFG="aprlib - Win32 Debug"
+!MESSAGE NMAKE /f "apr.mak" CFG="apr - Win32 Release"
 !MESSAGE 
 !MESSAGE Possible choices for configuration are:
 !MESSAGE 
-!MESSAGE "aprlib - Win32 Release" (based on "Win32 (x86) Static Library")
-!MESSAGE "aprlib - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "apr - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "apr - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "apr - x64 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "apr - x64 Debug" (based on "Win32 (x86) Static Library")
 !MESSAGE 
 
 # Begin Project
+# PROP AllowPerConfigDependencies 0
 # PROP Scc_ProjName ""
 # PROP Scc_LocalPath ""
 CPP=cl.exe
+RSC=rc.exe
 
-!IF  "$(CFG)" == "aprlib - Win32 Release"
+!IF  "$(CFG)" == "apr - Win32 Release"
 
 # PROP BASE Use_MFC 0
 # PROP BASE Use_Debug_Libraries 0
@@ -38,17 +42,18 @@ CPP=cl.exe
 # PROP Output_Dir "LibR"
 # PROP Intermediate_Dir "LibR"
 # PROP Target_Dir ""
-# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "./include" /I "./inc" /I "./misc/win32" /I "./file_io/win32" /I "./time/win32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
-# SUBTRACT CPP /YX
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /Zi /O2 /Oy- /I "./include" /I "./include/private" /I "./include/arch/win32" /I "./include/arch/unix" /I "../expat/lib" /D "NDEBUG" /D "APR_DECLARE_STATIC" /D "XML_STATIC" /D "WIN32" /D "WINNT" /D "_WINDOWS" /Fo"$(INTDIR)\" /Fd"$(OUTDIR)\apr-2" /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
 BSC32=bscmake.exe
 # ADD BASE BSC32 /nologo
 # ADD BSC32 /nologo
 LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo /out:".\LibR\apr.lib"
-# ADD LIB32 /nologo /out:".\LibR\apr.lib"
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"LibR\apr-2.lib"
 
-!ELSEIF  "$(CFG)" == "aprlib - Win32 Debug"
+!ELSEIF  "$(CFG)" == "apr - Win32 Debug"
 
 # PROP BASE Use_MFC 0
 # PROP BASE Use_Debug_Libraries 1
@@ -61,191 +66,919 @@ LIB32=link.exe -lib
 # PROP Intermediate_Dir "LibD"
 # PROP Ignore_Export_Lib 0
 # PROP Target_Dir ""
-# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "./include" /I "./inc" /I "./misc/win32" /I "./file_io/win32" /I "./time/win32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
-# SUBTRACT CPP /YX
+# ADD BASE CPP /nologo /MDd /W3 /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /EHsc /c
+# ADD CPP /nologo /MDd /W3 /Zi /Od /I "./include" /I "./include/private" /I "./include/arch/win32" /I "./include/arch/unix" /I "../expat/lib" /D "_DEBUG" /D "APR_DECLARE_STATIC" /D "XML_STATIC" /D "WIN32" /D "WINNT" /D "_WINDOWS" /Fo"$(INTDIR)\" /Fd"$(OUTDIR)\apr-2" /FD /EHsc /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
 BSC32=bscmake.exe
 # ADD BASE BSC32 /nologo
 # ADD BSC32 /nologo
 LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo /out:".\LibD\apr.lib"
-# ADD LIB32 /nologo /out:".\LibD\apr.lib"
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"LibD\apr-2.lib"
+
+!ELSEIF  "$(CFG)" == "apr - x64 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "x64\LibR"
+# PROP BASE Intermediate_Dir "x64\LibR"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "x64\LibR"
+# PROP Intermediate_Dir "x64\LibR"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /Zi /O2 /Oy- /I "./include" /I "./include/private" /I "./include/arch/win32" /I "./include/arch/unix" /I "../expat/lib" /D "NDEBUG" /D "APR_DECLARE_STATIC" /D "XML_STATIC" /D "WIN32" /D "WINNT" /D "_WINDOWS" /Fo"$(INTDIR)\" /Fd"$(OUTDIR)\apr-2" /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"x64\LibR\apr-2.lib"
+
+!ELSEIF  "$(CFG)" == "apr - x64 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "x64\LibD"
+# PROP BASE Intermediate_Dir "x64\LibD"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "x64\LibD"
+# PROP Intermediate_Dir "x64\LibD"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /EHsc /c
+# ADD CPP /nologo /MDd /W3 /Zi /Od /I "./include" /I "./include/private" /I "./include/arch/win32" /I "./include/arch/unix" /I "../expat/lib" /D "_DEBUG" /D "APR_DECLARE_STATIC" /D "XML_STATIC" /D "WIN32" /D "WINNT" /D "_WINDOWS" /Fo"$(INTDIR)\" /Fd"$(OUTDIR)\apr-2" /FD /EHsc /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"x64\LibD\apr-2.lib"
 
 !ENDIF 
 
-# Begin Target
+# Begin Target
+
+# Name "apr - Win32 Release"
+# Name "apr - Win32 Debug"
+# Name "apr - x64 Release"
+# Name "apr - x64 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter ".c"
+# Begin Group "atomic"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\atomic\win32\apr_atomic.c
+# End Source File
+# End Group
+# Begin Group "buckets"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\buckets\apr_brigade.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_alloc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_eos.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_file.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_flush.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_heap.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_mmap.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_pipe.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_pool.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_refcount.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_simple.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_socket.c
+# End Source File
+# End Group
+# Begin Group "crypto"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\crypto\apr_crypto.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\crypto\apr_md4.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\crypto\apr_md5.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\crypto\apr_passwd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\crypto\apr_sha1.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\crypto\apr_siphash.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\crypto\crypt_blowfish.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\crypto\crypt_blowfish.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\crypto\getuuid.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\crypto\uuid.c
+# End Source File
+# End Group
+# Begin Group "dbd"
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\dbd\apr_dbd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbd\apr_dbd_mysql.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbd\apr_dbd_odbc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbd\apr_dbd_oracle.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbd\apr_dbd_pgsql.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbd\apr_dbd_sqlite2.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbd\apr_dbd_sqlite3.c
+# End Source File
+# End Group
+# Begin Group "dbm"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\dbm\apr_dbm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbm\apr_dbm_berkeleydb.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbm\apr_dbm_gdbm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbm\apr_dbm_sdbm.c
+# End Source File
+# End Group
+# Begin Group "dso"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\dso\win32\dso.c
+# End Source File
+# End Group
+# Begin Group "encoding"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\encoding\apr_base64.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\encoding\apr_escape.c
+# End Source File
+# End Group
+# Begin Group "file_io"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\file_io\win32\buffer.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\file_io\unix\copy.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\file_io\win32\dir.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\file_io\unix\fileacc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\file_io\win32\filedup.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\file_io\win32\filepath.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\file_io\unix\filepath_util.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\file_io\win32\filestat.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\file_io\win32\filesys.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\file_io\win32\flock.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\file_io\unix\fullrw.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\file_io\unix\mktemp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\file_io\win32\open.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\file_io\win32\pipe.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\file_io\win32\readwrite.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\file_io\win32\seek.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\file_io\unix\tempdir.c
+# End Source File
+# End Group
+# Begin Group "hooks"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\hooks\apr_hooks.c
+# End Source File
+# End Group
+# Begin Group "locks"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\locks\win32\proc_mutex.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\locks\win32\thread_cond.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\locks\win32\thread_mutex.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\locks\win32\thread_rwlock.c
+# End Source File
+# End Group
+# Begin Group "memcache"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\memcache\apr_memcache.c
+# End Source File
+# End Group
+# Begin Group "memory"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\memory\unix\apr_pools.c
+# End Source File
+# End Group
+# Begin Group "misc"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\misc\win32\apr_app.c
+# PROP Exclude_From_Build 1
+# End Source File
+# Begin Source File
+
+SOURCE=.\misc\win32\charset.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\misc\win32\env.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\misc\unix\errorcodes.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\misc\unix\getopt.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\misc\win32\internal.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\misc\win32\misc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\misc\unix\otherchild.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\misc\win32\rand.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\misc\win32\start.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\misc\win32\utf8.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\misc\unix\version.c
+# End Source File
+# End Group
+# Begin Group "mmap"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\mmap\unix\common.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mmap\win32\mmap.c
+# End Source File
+# End Group
+# Begin Group "network_io"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\network_io\unix\inet_ntop.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\network_io\unix\inet_pton.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\network_io\unix\multicast.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\network_io\win32\sendrecv.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\network_io\unix\sockaddr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\network_io\win32\sockets.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\network_io\unix\socket_util.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\network_io\win32\sockopt.c
+# End Source File
+# End Group
+# Begin Group "passwd"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\passwd\apr_getpass.c
+# End Source File
+# End Group
+# Begin Group "poll"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\poll\unix\pollcb.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\poll\unix\pollset.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\poll\unix\poll.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\poll\unix\select.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\poll\unix\wakeup.c
+# End Source File
+# End Group
+# Begin Group "random"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\random\unix\apr_random.c
+# End Source File
+# Begin Source File
 
-# Name "aprlib - Win32 Release"
-# Name "aprlib - Win32 Debug"
-# Begin Group "Source Files"
+SOURCE=.\random\unix\sha2.c
+# End Source File
+# Begin Source File
 
-# PROP Default_Filter ".c"
+SOURCE=.\random\unix\sha2_glue.c
+# End Source File
+# End Group
+# Begin Group "sdbm"
+
+# PROP Default_Filter ""
 # Begin Source File
 
-SOURCE=.\time\win32\access.c
+SOURCE=.\dbm\sdbm\sdbm.c
 # End Source File
 # Begin Source File
 
-SOURCE=.\lib\apr_cpystrn.c
+SOURCE=.\dbm\sdbm\sdbm_hash.c
 # End Source File
 # Begin Source File
 
-SOURCE=.\lib\apr_execve.c
+SOURCE=.\dbm\sdbm\sdbm_lock.c
 # End Source File
 # Begin Source File
 
-SOURCE=.\lib\apr_fnmatch.c
+SOURCE=.\dbm\sdbm\sdbm_pair.c
 # End Source File
 # Begin Source File
 
-SOURCE=.\lib\apr_getpass.c
+SOURCE=.\dbm\sdbm\sdbm_pair.h
 # End Source File
 # Begin Source File
 
-SOURCE=.\lib\apr_md5.c
+SOURCE=.\dbm\sdbm\sdbm_private.h
 # End Source File
 # Begin Source File
 
-SOURCE=.\lib\apr_pools.c
+SOURCE=.\dbm\sdbm\sdbm_tune.h
 # End Source File
+# End Group
+# Begin Group "shmem"
+
+# PROP Default_Filter ""
 # Begin Source File
 
-SOURCE=.\lib\apr_snprintf.c
+SOURCE=.\shmem\win32\shm.c
 # End Source File
+# End Group
+# Begin Group "strings"
+
+# PROP Default_Filter ""
 # Begin Source File
 
-SOURCE=.\lib\apr_strnatcmp.c
+SOURCE=.\strings\apr_cpystrn.c
 # End Source File
 # Begin Source File
 
-SOURCE=.\lib\apr_tables.c
+SOURCE=.\strings\apr_fnmatch.c
 # End Source File
 # Begin Source File
 
-SOURCE=.\aprlib.def
+SOURCE=.\strings\apr_snprintf.c
 # End Source File
 # Begin Source File
 
-SOURCE=.\misc\win32\canonerr.c
+SOURCE=.\strings\apr_strings.c
 # End Source File
 # Begin Source File
 
-SOURCE=.\file_io\win32\dir.c
+SOURCE=.\strings\apr_strnatcmp.c
 # End Source File
 # Begin Source File
 
-SOURCE=.\dso\win32\dso.c
+SOURCE=.\strings\apr_strtok.c
 # End Source File
+# End Group
+# Begin Group "strmatch"
+
+# PROP Default_Filter ""
 # Begin Source File
 
-SOURCE=.\misc\win32\errorcodes.c
+SOURCE=.\strmatch\apr_strmatch.c
 # End Source File
+# End Group
+# Begin Group "tables"
+
+# PROP Default_Filter ""
 # Begin Source File
 
-SOURCE=.\file_io\win32\fileacc.c
+SOURCE=.\tables\apr_hash.c
 # End Source File
 # Begin Source File
 
-SOURCE=.\file_io\win32\filedup.c
+SOURCE=.\tables\apr_tables.c
 # End Source File
 # Begin Source File
 
-SOURCE=.\file_io\win32\filestat.c
+SOURCE=.\tables\apr_skiplist.c
 # End Source File
+# End Group
+# Begin Group "threadproc"
+
+# PROP Default_Filter ""
 # Begin Source File
 
-SOURCE=.\misc\win32\getopt.c
+SOURCE=.\threadproc\win32\proc.c
 # End Source File
 # Begin Source File
 
-SOURCE=.\locks\win32\locks.c
+SOURCE=.\threadproc\win32\signals.c
 # End Source File
 # Begin Source File
 
-SOURCE=.\misc\win32\names.c
+SOURCE=.\threadproc\win32\thread.c
 # End Source File
 # Begin Source File
 
-SOURCE=.\file_io\win32\open.c
+SOURCE=.\threadproc\win32\threadpriv.c
 # End Source File
+# End Group
+# Begin Group "time"
+
+# PROP Default_Filter ""
 # Begin Source File
 
-SOURCE=.\file_io\win32\pipe.c
+SOURCE=.\time\win32\time.c
 # End Source File
 # Begin Source File
 
-SOURCE=.\network_io\win32\poll.c
+SOURCE=.\time\win32\timestr.c
 # End Source File
+# End Group
+# Begin Group "uri"
+
+# PROP Default_Filter ""
 # Begin Source File
 
-SOURCE=.\threadproc\win32\proc.c
+SOURCE=.\uri\apr_uri.c
 # End Source File
+# End Group
+# Begin Group "user"
+
+# PROP Default_Filter ""
 # Begin Source File
 
-SOURCE=.\misc\win32\rand.c
+SOURCE=.\user\win32\groupinfo.c
 # End Source File
 # Begin Source File
 
-SOURCE=.\file_io\win32\readwrite.c
+SOURCE=.\user\win32\userinfo.c
 # End Source File
+# End Group
+# Begin Group "util-misc"
+
+# PROP Default_Filter ""
 # Begin Source File
 
-SOURCE=.\file_io\win32\seek.c
+SOURCE=.\util-misc\apr_date.c
 # End Source File
 # Begin Source File
 
-SOURCE=.\network_io\win32\sendrecv.c
+SOURCE=.\util-misc\apu_dso.c
 # End Source File
 # Begin Source File
 
-SOURCE=.\threadproc\win32\signals.c
+SOURCE=.\util-misc\apr_queue.c
 # End Source File
 # Begin Source File
 
-SOURCE=.\network_io\win32\sockaddr.c
+SOURCE=.\util-misc\apr_reslist.c
 # End Source File
 # Begin Source File
 
-SOURCE=.\network_io\win32\sockets.c
+SOURCE=.\util-misc\apr_rmm.c
 # End Source File
 # Begin Source File
 
-SOURCE=.\network_io\win32\sockopt.c
+SOURCE=.\util-misc\apr_thread_pool.c
 # End Source File
+# End Group
+# Begin Group "xlate"
+
+# PROP Default_Filter ""
 # Begin Source File
 
-SOURCE=.\misc\win32\start.c
+SOURCE=.\xlate\xlate.c
+# End Source File
+# End Group
+# Begin Group "xml"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\xml\apr_xml.c
 # End Source File
 # Begin Source File
 
-SOURCE=.\threadproc\win32\thread.c
+SOURCE=.\xml\apr_xml_expat.c
+# End Source File
+# End Group
+# End Group
+# Begin Group "Private Header Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\include\arch\win32\apr_arch_atime.h
 # End Source File
 # Begin Source File
 
-SOURCE=.\threadproc\win32\threadpriv.c
+SOURCE=.\include\arch\win32\apr_arch_dso.h
 # End Source File
 # Begin Source File
 
-SOURCE=.\time\win32\time.c
+SOURCE=.\include\arch\win32\apr_arch_file_io.h
 # End Source File
 # Begin Source File
 
-SOURCE=.\time\win32\timestr.c
+SOURCE=.\include\arch\win32\apr_arch_inherit.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\arch\win32\apr_arch_misc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\arch\win32\apr_arch_networkio.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\arch\win32\apr_arch_thread_mutex.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\arch\win32\apr_arch_thread_rwlock.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\arch\win32\apr_arch_threadproc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\arch\win32\apr_arch_utf8.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\arch\win32\apr_private.h
 # End Source File
 # End Group
-# Begin Group "Header Files"
+# Begin Group "Public Header Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\include\apr.h.in
+# PROP Exclude_From_Build 1
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr.hnw
+# PROP Exclude_From_Build 1
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr.hw
+
+!IF  "$(CFG)" == "apr - Win32 Release"
+
+# Begin Custom Build - Creating apr.h from apr.hw, apr_escape_test_char.h from gen_test_char.exe
+InputPath=.\include\apr.hw
+
+".\include\apr.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	type .\include\apr.hw > .\include\apr.h
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "apr - Win32 Debug"
+
+# Begin Custom Build - Creating apr.h from apr.hw, apr_escape_test_char.h from gen_test_char.exe
+InputPath=.\include\apr.hw
+
+".\include\apr.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	type .\include\apr.hw > .\include\apr.h
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "apr - Win32 Release9x"
+
+# Begin Custom Build - Creating apr.h from apr.hw, apr_escape_test_char.h from gen_test_char.exe
+InputPath=.\include\apr.hw
+
+".\include\apr.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	type .\include\apr.hw > .\include\apr.h
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "apr - x64 Debug"
+
+# Begin Custom Build - Creating apr.h from apr.hw, apr_escape_test_char.h from gen_test_char.exe
+InputPath=.\include\apr.hw
+
+".\include\apr.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	type .\include\apr.hw > .\include\apr.h
+
+# End Custom Build
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_allocator.h
+# End Source File
+# Begin Source File
 
-# PROP Default_Filter ".h"
+SOURCE=.\include\apr_atomic.h
+# End Source File
 # Begin Source File
 
 SOURCE=.\include\apr_dso.h
 # End Source File
 # Begin Source File
 
+SOURCE=.\include\apr_env.h
+# End Source File
+# Begin Source File
+
 SOURCE=.\include\apr_errno.h
 # End Source File
 # Begin Source File
 
+SOURCE=.\include\apr_escape.h
+
+!IF  "$(CFG)" == "libapr - Win32 Release"
+
+# Begin Custom Build - Creating gen_test_char.exe and apr_escape_test_char.h
+InputPath=.\include\apr_escape.h
+
+".\include\apr_escape_test_char.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl.exe /nologo /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /I ".\include" /Fo.\Release\gen_test_char /Fe.\Release\gen_test_char.exe .\tools\gen_test_char.c 
+	.\Release\gen_test_char.exe > .\include\apr_escape_test_char.h
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "libapr - Win32 Debug"
+
+# Begin Custom Build - Creating gen_test_char.exe and apr_escape_test_char.h
+InputPath=.\include\apr_escape.h
+
+".\include\apr_escape_test_char.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl.exe /nologo /W3 /EHsc /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /I ".\include" /Fo.\Debug\gen_test_char /Fe.\Debug\gen_test_char.exe .\tools\gen_test_char.c  
+	.\Debug\gen_test_char.exe > .\include\apr_escape_test_char.h
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "libapr - Win32 Release9x"
+
+# Begin Custom Build - Creating gen_test_char.exe and apr_escape_test_char.h
+InputPath=.\include\apr_escape.h
+
+".\include\apr_escape_test_char.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl.exe /nologo /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /I ".\include" /Fo.\9x\Release\gen_test_char /Fe.\9x\Release\gen_test_char.exe .\tools\gen_test_char.c 
+	.\9x\Release\gen_test_char.exe > .\include\apr_escape_test_char.h
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "libapr - Win32 Debug9x"
+
+# Begin Custom Build - Creating gen_test_char.exe and apr_escape_test_char.h
+InputPath=.\include\apr_escape.h
+
+".\include\apr_escape_test_char.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl.exe /nologo /W3 /EHsc /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /I ".\include" /Fo.\9x\Debug\gen_test_char /Fe.\9x\Debug\gen_test_char.exe .\tools\gen_test_char.c  
+	.\9x\Debug\gen_test_char.exe > .\include\apr_escape_test_char.h
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "libapr - x64 Release"
+
+# Begin Custom Build - Creating gen_test_char.exe and apr_escape_test_char.h
+InputPath=.\include\apr_escape.h
+
+".\include\apr_escape_test_char.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl.exe /nologo /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /I ".\include" /Fo.\x64\Release\gen_test_char /Fe.\x64\Release\gen_test_char.exe .\tools\gen_test_char.c 
+	.\x64\Release\gen_test_char.exe > .\include\apr_escape_test_char.h
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "libapr - x64 Debug"
+
+# Begin Custom Build - Creating gen_test_char.exe and apr_escape_test_char.h
+InputPath=.\include\apr_escape.h
+
+".\include\apr_escape_test_char.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl.exe /nologo /W3 /EHsc /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /I ".\include" /Fo.\x64\Debug\gen_test_char /Fe.\x64\Debug\gen_test_char.exe .\tools\gen_test_char.c 
+	.\x64\Debug\gen_test_char.exe > .\include\apr_escape_test_char.h
+
+# End Custom Build
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_file_info.h
+# End Source File
+# Begin Source File
+
 SOURCE=.\include\apr_file_io.h
 # End Source File
 # Begin Source File
@@ -262,15 +995,23 @@ SOURCE=.\include\apr_getopt.h
 # End Source File
 # Begin Source File
 
-SOURCE=.\include\apr_lib.h
+SOURCE=.\include\apr_global_mutex.h
 # End Source File
 # Begin Source File
 
-SOURCE=.\include\apr_lock.h
+SOURCE=.\include\apr_hash.h
 # End Source File
 # Begin Source File
 
-SOURCE=.\include\apr_md5.h
+SOURCE=.\include\apr_inherit.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_lib.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_mmap.h
 # End Source File
 # Begin Source File
 
@@ -278,7 +1019,7 @@ SOURCE=.\include\apr_network_io.h
 # End Source File
 # Begin Source File
 
-SOURCE=.\inc\apr_pools.h
+SOURCE=.\include\apr_poll.h
 # End Source File
 # Begin Source File
 
@@ -290,7 +1031,19 @@ SOURCE=.\include\apr_portable.h
 # End Source File
 # Begin Source File
 
-SOURCE=.\include\apr_shmem.h
+SOURCE=.\include\apr_proc_mutex.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_random.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_ring.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_shm.h
 # End Source File
 # Begin Source File
 
@@ -298,117 +1051,157 @@ SOURCE=.\include\apr_signal.h
 # End Source File
 # Begin Source File
 
-SOURCE=.\include\apr_strnatcmp.h
+SOURCE=.\include\apr_skiplist.h
 # End Source File
 # Begin Source File
 
-SOURCE=.\include\apr_thread_proc.h
+SOURCE=.\include\apr_strings.h
 # End Source File
 # Begin Source File
 
-SOURCE=.\include\apr_time.h
+SOURCE=.\include\apr_support.h
 # End Source File
 # Begin Source File
 
-SOURCE=.\time\win32\atime.h
+SOURCE=.\include\apr_tables.h
 # End Source File
 # Begin Source File
 
-SOURCE=.\dso\win32\dso.h
+SOURCE=.\include\apr_thread_cond.h
 # End Source File
 # Begin Source File
 
-SOURCE=.\file_io\win32\fileio.h
+SOURCE=.\include\apr_thread_mutex.h
 # End Source File
 # Begin Source File
 
-SOURCE=.\locks\win32\locks.h
+SOURCE=.\include\apr_thread_proc.h
 # End Source File
 # Begin Source File
 
-SOURCE=.\misc\win32\misc.h
+SOURCE=.\include\apr_thread_rwlock.h
 # End Source File
 # Begin Source File
 
-SOURCE=.\network_io\win32\networkio.h
+SOURCE=.\include\apr_time.h
 # End Source File
 # Begin Source File
 
-SOURCE=.\threadproc\win32\threadproc.h
+SOURCE=.\include\apr_user.h
 # End Source File
-# End Group
-# Begin Group "Generated Header Files"
+# Begin Source File
 
-# PROP Default_Filter ""
+SOURCE=.\include\apr_version.h
+# End Source File
 # Begin Source File
 
-SOURCE=.\include\apr.h
+SOURCE=.\include\apr_want.h
 # End Source File
 # Begin Source File
 
-SOURCE=.\include\apr_private.h
+SOURCE=.\include\apu.h
 # End Source File
-# End Group
-# Begin Group "Internal Header Files"
+# Begin Source File
 
-# PROP Default_Filter ""
+SOURCE=.\include\private\apu_select_dbm.h.in
+# End Source File
 # Begin Source File
 
-SOURCE=.\include\apr_private.hw
+SOURCE=.\include\private\apu_select_dbm.hw
+
+!IF  "$(CFG)" == "apr - Win32 Release"
+
+# Begin Custom Build - Creating apu_select_dbm.h from apu_select_dbm.hw
+InputPath=.\include\private\apu_select_dbm.hw
+
+".\include\private\apu_select_dbm.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	type .\include\private\apu_select_dbm.hw > .\include\private\apu_select_dbm.h
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "apr - Win32 Debug"
+
+# Begin Custom Build - Creating apu_select_dbm.h from apu_select_dbm.hw
+InputPath=.\include\private\apu_select_dbm.hw
+
+".\include\private\apu_select_dbm.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	type .\include\private\apu_select_dbm.hw > .\include\private\apu_select_dbm.h
 
-!IF  "$(CFG)" == "aprlib - Win32 Release"
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "apr - x64 Release"
 
-# Begin Custom Build
-InputPath=.\include\apr_private.hw
+# Begin Custom Build - Creating apu_select_dbm.h from apu_select_dbm.hw
+InputPath=.\include\private\apu_select_dbm.hw
+
+".\include\private\apu_select_dbm.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	type .\include\private\apu_select_dbm.hw > .\include\private\apu_select_dbm.h
 
-".\include\apr_private.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
-	copy .\include\apr_private.hw .\include\apr_private.h > nul 
-	echo Created apr_private.h from apr_private.hw 
-	
 # End Custom Build
 
-!ELSEIF  "$(CFG)" == "aprlib - Win32 Debug"
+!ELSEIF  "$(CFG)" == "apr - x64 Debug"
+
+# Begin Custom Build - Creating apu_select_dbm.h from apu_select_dbm.hw
+InputPath=.\include\private\apu_select_dbm.hw
 
-# Begin Custom Build
-InputPath=.\include\apr_private.hw
+".\include\private\apu_select_dbm.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	type .\include\private\apu_select_dbm.hw > .\include\private\apu_select_dbm.h
 
-".\include\apr_private.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
-	copy .\include\apr_private.hw .\include\apr_private.h > nul 
-	echo Created apr_private.h from apr_private.hw 
-	
 # End Custom Build
 
 !ENDIF 
 
 # End Source File
-# End Group
-# Begin Group "External Header Files"
+# Begin Source File
 
-# PROP Default_Filter ""
+SOURCE=.\include\apu_want.h.in
+# End Source File
 # Begin Source File
 
-SOURCE=.\include\apr.hw
+SOURCE=.\include\apu_want.hnw
+# End Source File
+# Begin Source File
 
-!IF  "$(CFG)" == "aprlib - Win32 Release"
+SOURCE=.\include\apu_want.hw
 
-# Begin Custom Build
-InputPath=.\include\apr.hw
+!IF  "$(CFG)" == "apr - Win32 Release"
+
+# Begin Custom Build - Creating apu_want.h from apu_want.hw
+InputPath=.\include\apu_want.hw
+
+".\include\apu_want.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	type .\include\apu_want.hw > .\include\apu_want.h
 
-".\include\apr.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
-	copy .\include\apr.hw .\include\apr.h > nul 
-	echo Created apr.h from apr.hw 
-	
 # End Custom Build
 
-!ELSEIF  "$(CFG)" == "aprlib - Win32 Debug"
+!ELSEIF  "$(CFG)" == "apr - Win32 Debug"
 
-# Begin Custom Build
-InputPath=.\include\apr.hw
+# Begin Custom Build - Creating apu_want.h from apu_want.hw
+InputPath=.\include\apu_want.hw
+
+".\include\apu_want.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	type .\include\apu_want.hw > .\include\apu_want.h
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "apr - x64 Release"
+
+# Begin Custom Build - Creating apu_want.h from apu_want.hw
+InputPath=.\include\apu_want.hw
+
+".\include\apu_want.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	type .\include\apu_want.hw > .\include\apu_want.h
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "apr - x64 Debug"
+
+# Begin Custom Build - Creating apu_want.h from apu_want.hw
+InputPath=.\include\apu_want.hw
+
+".\include\apu_want.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	type .\include\apu_want.hw > .\include\apu_want.h
 
-".\include\apr.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
-	copy .\include\apr.hw .\include\apr.h > nul 
-	echo Created apr.h from apr.hw 
-	
 # End Custom Build
 
 !ENDIF 
diff --git a/test/test.dsw b/apr.dsw
similarity index 58%
rename from test/test.dsw
rename to apr.dsw
index af6f6901c60..ff7dadd8cb3 100644
--- a/test/test.dsw
+++ b/apr.dsw
@@ -1,9 +1,9 @@
-Microsoft Developer Studio Workspace File, Format Version 5.00
+Microsoft Developer Studio Workspace File, Format Version 6.00
 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
 
 ###############################################################################
 
-Project: "ab_apr"=.\ab_apr.dsp - Package Owner=<4>
+Project: "apr"=".\apr.dsp" - Package Owner=<4>
 
 Package=<5>
 {{{
@@ -15,19 +15,7 @@ Package=<4>
 
 ###############################################################################
 
-Project: "client"=.\client.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "server"=.\server.dsp - Package Owner=<4>
+Project: "aprapp"=".\build\aprapp.dsp" - Package Owner=<4>
 
 Package=<5>
 {{{
@@ -35,11 +23,14 @@ Package=<5>
 
 Package=<4>
 {{{
+    Begin Project Dependency
+    Project_Dep_Name preaprapp
+    End Project Dependency
 }}}
 
 ###############################################################################
 
-Project: "testarg"=.\testarg.dsp - Package Owner=<4>
+Project: "libapr"=".\libapr.dsp" - Package Owner=<4>
 
 Package=<5>
 {{{
@@ -51,7 +42,7 @@ Package=<4>
 
 ###############################################################################
 
-Project: "testfile"=.\testfile.dsp - Package Owner=<4>
+Project: "libaprapp"=".\build\libaprapp.dsp" - Package Owner=<4>
 
 Package=<5>
 {{{
@@ -59,11 +50,14 @@ Package=<5>
 
 Package=<4>
 {{{
+    Begin Project Dependency
+    Project_Dep_Name prelibaprapp
+    End Project Dependency
 }}}
 
 ###############################################################################
 
-Project: "testproc"=.\testproc.dsp - Package Owner=<4>
+Project: "preaprapp"=".\build\preaprapp.dsp" - Package Owner=<4>
 
 Package=<5>
 {{{
@@ -71,11 +65,14 @@ Package=<5>
 
 Package=<4>
 {{{
+    Begin Project Dependency
+    Project_Dep_Name apr
+    End Project Dependency
 }}}
 
 ###############################################################################
 
-Project: "testsock"=.\testsock.dsp - Package Owner=<4>
+Project: "prelibaprapp"=".\build\prelibaprapp.dsp" - Package Owner=<4>
 
 Package=<5>
 {{{
@@ -84,16 +81,13 @@ Package=<5>
 Package=<4>
 {{{
     Begin Project Dependency
-    Project_Dep_Name client
-    End Project Dependency
-    Begin Project Dependency
-    Project_Dep_Name server
+    Project_Dep_Name libapr
     End Project Dependency
 }}}
 
 ###############################################################################
 
-Project: "testthread"=.\testthread.dsp - Package Owner=<4>
+Project: "apr_crypto_nss"=".\crypto\apr_crypto_nss.dsp" - Package Owner=<4>
 
 Package=<5>
 {{{
@@ -101,11 +95,14 @@ Package=<5>
 
 Package=<4>
 {{{
+    Begin Project Dependency
+    Project_Dep_Name libapr
+    End Project Dependency
 }}}
 
 ###############################################################################
 
-Project: "timetest"=.\timetest.dsp - Package Owner=<4>
+Project: "apr_crypto_openssl"=".\crypto\apr_crypto_openssl.dsp" - Package Owner=<4>
 
 Package=<5>
 {{{
@@ -113,6 +110,9 @@ Package=<5>
 
 Package=<4>
 {{{
+    Begin Project Dependency
+    Project_Dep_Name libapr
+    End Project Dependency
 }}}
 
 ###############################################################################
diff --git a/apr.pc.in b/apr.pc.in
new file mode 100644
index 00000000000..318a81e26b7
--- /dev/null
+++ b/apr.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+APR_MAJOR_VERSION=@APR_MAJOR_VERSION@
+includedir=@includedir@
+
+Name: APR
+Description: The Apache Portable Runtime library
+Version: @APR_DOTTED_VERSION@
+Libs: -L${libdir} -l@APR_LIBNAME@ @EXTRA_LIBS@
+Cflags: @EXTRA_CPPFLAGS@ @EXTRA_CFLAGS@ -I${includedir}
diff --git a/aprlib.def b/aprlib.def
deleted file mode 100644
index b9fe301fef7..00000000000
--- a/aprlib.def
+++ /dev/null
@@ -1,251 +0,0 @@
-; aprlib.def :
-
-LIBRARY aprlib
-DESCRIPTION ''
-
-EXPORTS
-	; Add new API calls to the end of this list.
-	ap_opendir   @1
-	ap_closedir   @2
-	ap_readdir   @3
-	ap_rewinddir   @4
-	ap_make_dir   @5
-	ap_remove_dir   @6
-	ap_dir_entry_size   @7
-	ap_dir_entry_mtime   @8
-	ap_dir_entry_ftype   @9
-	ap_get_dir_filename   @10
-;	ap_get_filename   @11
-	ap_stat		  @11
-;	ap_get_filesize   @12
-;	ap_get_fileatime   @13
-;	ap_get_filectime   @14
-;	ap_make_iov   @15
-	ap_dupfile   @16
-	ap_getfileinfo   @17
-	ap_open   @18
-	ap_close   @19
-	ap_remove_file   @20
-	ap_create_pipe   @21
-	ap_read   @22
-	ap_write   @23
-	ap_seek   @24
-    	ap_get_filedata   @25
-    	ap_set_filedata   @26
-    	ap_get_os_file   @27
-	ap_put_os_file @28
-    	ap_get_os_dir   @29
-    	ap_putc   @30
-    	ap_getc   @31
-	ap_puts @32
-	ap_fgets @33
-	ap_flush @34
-    	ap_fprintf   @35
-    	ap_eof   @36
-;	ap_get_filetype @37
-	ap_writev @38
-	; locks
-	ap_create_lock   @39
-	ap_lock   @40
-	ap_unlock   @41
-	ap_destroy_lock   @42
-	ap_child_init_lock   @43
-	ap_get_lockdata   @44
-	ap_set_lockdata   @45
-	ap_get_os_lock   @46
-	ap_create_tcp_socket   @47
-	ap_shutdown   @48
-	ap_close_socket   @49
-	ap_bind   @50
-	ap_listen   @51
-	ap_accept   @52
-	ap_connect   @53
-	ap_get_remote_hostname   @54
-	ap_gethostname   @55
-	ap_send   @56
-	ap_recv   @57
-	ap_setsocketopt   @58
-	ap_sendv @59
-	ap_sendfile  @60
-	ap_setup_poll   @61
-	ap_poll   @62
-	ap_add_poll_socket   @63
-	ap_get_revents   @64
-	ap_get_socketdata   @65
-	ap_set_socketdata   @66
-	ap_get_polldata   @67
-	ap_set_polldata   @68
-	ap_put_os_sock @69
-	ap_get_os_sock   @70
-	ap_remove_poll_socket   @71
-	ap_clear_poll_sockets   @72
-;	ap_setipaddr @73
-;	ap_getipaddr @74
-;	ap_create_signal   @75
-;	ap_setup_signal   @76
-;       SignalHandling   @77
-;	ap_send_signal    @78
-;       thread_ready   @79
-	ap_createprocattr_init   @80
-	ap_setprocattr_io   @81
-	ap_setprocattr_dir   @82
-	ap_setprocattr_cmdtype   @83
-	ap_setprocattr_detach   @84
-	ap_create_process   @85
-	ap_get_childin   @86
-	ap_get_childout   @87
-	ap_get_childerr   @88
-	ap_wait_proc   @89
-	ap_kill   @90
-	ap_create_threadattr   @91
-	ap_setthreadattr_detach   @92
-	ap_getthreadattr_detach   @93
-	ap_create_thread   @94
-	ap_thread_exit   @95
-	ap_thread_join   @96
-	ap_thread_detach   @97
-;	ap_cancel_thread   @98
-	ap_create_thread_private   @99
-	ap_get_thread_private   @100
-	ap_set_thread_private   @101
-	ap_delete_thread_private   @102
-	ap_get_threaddata    @103
-	ap_set_threaddata    @104
-	ap_get_threadkeydata    @105
-	ap_set_threadkeydata    @106
-	ap_get_procdata    @107
-;	ap_set_procdata    @108
-	ap_get_os_proc   @109
-	ap_get_os_thread   @110
-	ap_get_os_threadkey   @111
-	ap_os_systemcase_filename   @112
-	canonical_filename   @113
-	ap_create_pool   @114
-	ap_destroy_context   @115
-;	WinTimeToUnixTime   @116
-;	ap_get_oslevel   @117
-	ap_get_userdata   @118
-	ap_set_userdata   @119
-	ap_initialize   @120
-	ap_getopt    @121
-	ap_opterr   @122 DATA
-	ap_optind   @123 DATA
-	ap_optopt   @124 DATA
-	ap_optreset   @125 DATA
-	ap_optarg   @126 DATA
-;	ap_make_time   @127
-	ap_ansi_time_to_ap_time @127
-;	ap_current_time   @128
-	ap_now		  @128
-;	ap_explode_time   @129
-	ap_explode_gmt	  @129
-;	ap_implode_time   @130
-	ap_explode_localtime @130
-;	ap_get_curtime   @131
-	ap_implode_time	 @131
-;	ap_get_sec   @132
-	ap_get_os_imp_time	@132
-;	ap_get_min   @133
-	ap_get_os_exp_time	@133
-;	ap_get_hour   @134
-	ap_put_os_imp_time	@134
-;	ap_get_mday   @135
-	ap_put_os_exp_time	@135
-;	ap_get_mon   @136
-	ap_ctime     @136
-;	ap_get_year   @137
-	ap_rfc822_date	@137
-;	ap_get_wday   @138
-	ap_strftime   @138
-;	ap_set_sec   @139
-;	ap_set_min   @140
-;	ap_set_hour   @141
-;	ap_set_mday   @142
-;	ap_set_mon   @143
-;	ap_set_year   @144
-;	ap_set_wday   @145
-;	ap_get_timedata   @146
-;	ap_set_timedata   @147
-;	ap_get_os_time   @148
-;	ap_timediff   @149
-	ap_MD5Final   @150
-	ap_MD5Init   @151
-	ap_MD5Update   @152
-	ap_cpystrn   @153
-	ap_register_cleanup   @154
-	ap_kill_cleanup   @155
-	ap_fnmatch   @156
-	ap_is_fnmatch   @157
-	ap_MD5Encode   @158
-	ap_validate_password   @159
-	ap_make_sub_pool   @160
-	ap_init_alloc   @161
-	ap_clear_pool   @162
-	ap_destroy_pool   @163
-	ap_bytes_in_pool   @164
-	ap_bytes_in_free_blocks   @165
-	ap_palloc   @166
-	ap_pcalloc   @167
-	ap_pstrdup   @168
-	ap_pstrndup   @169
-	ap_pstrcat   @170
-	ap_pvsprintf   @171
-	ap_psprintf   @172
-	ap_make_array   @173
-	ap_push_array   @174
-	ap_array_cat   @175
-	ap_copy_array   @176
-	ap_copy_array_hdr   @177
-	ap_append_arrays   @178
-	ap_array_pstrcat   @179
-	ap_make_table   @180
-	ap_copy_table   @181
-	ap_clear_table   @182
-	ap_table_get   @183
-	ap_table_set   @184
-	ap_table_setn   @185
-	ap_table_unset   @186
-	ap_table_merge   @187
-	ap_table_mergen   @188
-	ap_table_add   @189
-	ap_table_addn   @190
-	ap_overlay_tables @191
-	ap_table_do   @192
-	ap_overlap_tables   @193
-	ap_run_cleanup   @194
-	ap_cleanup_for_exec   @195
-	ap_null_cleanup   @196
-	ap_note_subprocess   @197
-;	ap_slack   @198
-	ap_vformatter   @199
-	ap_snprintf   @200
-	ap_vsnprintf   @201
-	ap_getpass   @202
-	ap_ungetc @203
-	ap_tokenize_to_argv @204
-	ap_filename_of_pathname @205
-	ap_get_remote_name @206
-	ap_get_local_name @207
-	ap_get_local_ipaddr @208
-	ap_set_local_ipaddr @209
-	ap_get_remote_ipaddr @210
-	ap_set_remote_ipaddr @211
-	ap_get_local_port @212
-	ap_set_local_port @213
-	ap_get_remote_port @214
-	ap_set_remote_port @215
-	ap_open_stderr @216
-        ap_set_pipe_timeout   @217
-        ap_terminate @218
-        ap_dso_load @219
-        ap_dso_unload @220
-        ap_dso_sym @221
-        ap_dso_init @222
-        ap_collapse_spaces @223
-	ap_month_snames @224
-	ap_day_snames @225
-	ap_canonical_error @226
-	ap_strerror @227
-	ap_generate_random_bytes @228
-	ap_strnatcmp @229
-	ap_strnatcasecmp @230
diff --git a/aprlib.dsp b/aprlib.dsp
deleted file mode 100644
index c30f9ecc16b..00000000000
--- a/aprlib.dsp
+++ /dev/null
@@ -1,419 +0,0 @@
-# Microsoft Developer Studio Project File - Name="aprlib" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 5.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Static Library" 0x0104
-
-CFG=aprlib - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "aprlib.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 "aprlib.mak" CFG="aprlib - Win32 Debug"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "aprlib - Win32 Release" (based on "Win32 (x86) Static Library")
-!MESSAGE "aprlib - Win32 Debug" (based on "Win32 (x86) Static Library")
-!MESSAGE 
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-
-!IF  "$(CFG)" == "aprlib - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "LibR"
-# PROP BASE Intermediate_Dir "LibR"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "LibR"
-# PROP Intermediate_Dir "LibR"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "./include" /I "./inc" /I "./misc/win32" /I "./file_io/win32" /I "./time/win32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
-# SUBTRACT CPP /YX
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo /out:".\LibR\apr.lib"
-# ADD LIB32 /nologo /out:".\LibR\apr.lib"
-
-!ELSEIF  "$(CFG)" == "aprlib - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "LibD"
-# PROP BASE Intermediate_Dir "LibD"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "LibD"
-# PROP Intermediate_Dir "LibD"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "./include" /I "./inc" /I "./misc/win32" /I "./file_io/win32" /I "./time/win32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
-# SUBTRACT CPP /YX
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo /out:".\LibD\apr.lib"
-# ADD LIB32 /nologo /out:".\LibD\apr.lib"
-
-!ENDIF 
-
-# Begin Target
-
-# Name "aprlib - Win32 Release"
-# Name "aprlib - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter ".c"
-# Begin Source File
-
-SOURCE=.\time\win32\access.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\lib\apr_cpystrn.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\lib\apr_execve.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\lib\apr_fnmatch.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\lib\apr_getpass.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\lib\apr_md5.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\lib\apr_pools.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\lib\apr_snprintf.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\lib\apr_strnatcmp.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\lib\apr_tables.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\aprlib.def
-# End Source File
-# Begin Source File
-
-SOURCE=.\misc\win32\canonerr.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\file_io\win32\dir.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\dso\win32\dso.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\misc\win32\errorcodes.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\file_io\win32\fileacc.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\file_io\win32\filedup.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\file_io\win32\filestat.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\misc\win32\getopt.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\locks\win32\locks.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\misc\win32\names.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\file_io\win32\open.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\file_io\win32\pipe.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\network_io\win32\poll.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\threadproc\win32\proc.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\misc\win32\rand.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\file_io\win32\readwrite.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\file_io\win32\seek.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\network_io\win32\sendrecv.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\threadproc\win32\signals.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\network_io\win32\sockaddr.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\network_io\win32\sockets.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\network_io\win32\sockopt.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\misc\win32\start.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\threadproc\win32\thread.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\threadproc\win32\threadpriv.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\time\win32\time.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\time\win32\timestr.c
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter ".h"
-# Begin Source File
-
-SOURCE=.\include\apr_dso.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\include\apr_errno.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\include\apr_file_io.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\include\apr_fnmatch.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\include\apr_general.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\include\apr_getopt.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\include\apr_lib.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\include\apr_lock.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\include\apr_md5.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\include\apr_network_io.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\inc\apr_pools.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\include\apr_pools.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\include\apr_portable.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\include\apr_shmem.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\include\apr_signal.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\include\apr_strnatcmp.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\include\apr_thread_proc.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\include\apr_time.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\time\win32\atime.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\dso\win32\dso.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\file_io\win32\fileio.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\locks\win32\locks.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\misc\win32\misc.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\network_io\win32\networkio.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\threadproc\win32\threadproc.h
-# End Source File
-# End Group
-# Begin Group "Generated Header Files"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=.\include\apr.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\include\apr_private.h
-# End Source File
-# End Group
-# Begin Group "Internal Header Files"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=.\include\apr_private.hw
-
-!IF  "$(CFG)" == "aprlib - Win32 Release"
-
-# Begin Custom Build
-InputPath=.\include\apr_private.hw
-
-".\include\apr_private.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
-	copy .\include\apr_private.hw .\include\apr_private.h > nul 
-	echo Created apr_private.h from apr_private.hw 
-	
-# End Custom Build
-
-!ELSEIF  "$(CFG)" == "aprlib - Win32 Debug"
-
-# Begin Custom Build
-InputPath=.\include\apr_private.hw
-
-".\include\apr_private.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
-	copy .\include\apr_private.hw .\include\apr_private.h > nul 
-	echo Created apr_private.h from apr_private.hw 
-	
-# End Custom Build
-
-!ENDIF 
-
-# End Source File
-# End Group
-# Begin Group "External Header Files"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=.\include\apr.hw
-
-!IF  "$(CFG)" == "aprlib - Win32 Release"
-
-# Begin Custom Build
-InputPath=.\include\apr.hw
-
-".\include\apr.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
-	copy .\include\apr.hw .\include\apr.h > nul 
-	echo Created apr.h from apr.hw 
-	
-# End Custom Build
-
-!ELSEIF  "$(CFG)" == "aprlib - Win32 Debug"
-
-# Begin Custom Build
-InputPath=.\include\apr.hw
-
-".\include\apr.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
-	copy .\include\apr.hw .\include\apr.h > nul 
-	echo Created apr.h from apr.hw 
-	
-# End Custom Build
-
-!ENDIF 
-
-# End Source File
-# End Group
-# End Target
-# End Project
diff --git a/aprlibdll.dsp b/aprlibdll.dsp
deleted file mode 100644
index 05f5831e2a3..00000000000
--- a/aprlibdll.dsp
+++ /dev/null
@@ -1,103 +0,0 @@
-# Microsoft Developer Studio Project File - Name="aprlibdll" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 5.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
-
-CFG=aprlibdll - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "aprlibdll.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 "aprlibdll.mak" CFG="aprlibdll - Win32 Debug"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "aprlibdll - Win32 Release" (based on\
- "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "aprlibdll - Win32 Debug" (based on\
- "Win32 (x86) Dynamic-Link Library")
-!MESSAGE 
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-MTL=midl.exe
-RSC=rc.exe
-
-!IF  "$(CFG)" == "aprlibdll - 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 /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "./include" /I "./inc" /I "./misc/win32" /I "./file_io/win32" /I "./time/win32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
-# SUBTRACT CPP /YX
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 apr.lib kernel32.lib advapi32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /map /machine:I386 /def:".\aprlib.def" /out:"Release/aprlib.dll" /libpath:"LibR" /base:@"..\..\os\win32\BaseAddr.ref",aprlib
-# ADD LINK32 apr.lib kernel32.lib advapi32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /map /machine:I386 /def:".\aprlib.def" /out:"Release/aprlib.dll" /libpath:"LibR" /base:@"..\..\os\win32\BaseAddr.ref",aprlib
-
-!ELSEIF  "$(CFG)" == "aprlibdll - 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 /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "./include" /I "./inc" /I "./misc/win32" /I "./file_io/win32" /I "./time/win32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
-# SUBTRACT CPP /YX
-# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 aprlib.lib kernel32.lib advapi32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /map /debug /machine:I386 /def:".\aprlib.def" /out:"Debug/aprlib.dll" /libpath:"LibD" /base:@"..\..\os\win32\BaseAddr.ref",aprlib
-# ADD LINK32 apr.lib kernel32.lib advapi32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /map /debug /machine:I386 /def:".\aprlib.def" /out:"Debug/aprlib.dll" /libpath:"LibD" /base:@"..\..\os\win32\BaseAddr.ref",aprlib
-
-!ENDIF 
-
-# Begin Target
-
-# Name "aprlibdll - Win32 Release"
-# Name "aprlibdll - Win32 Debug"
-# Begin Source File
-
-SOURCE=.\misc\win32\aprlib.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\aprlib.def
-# PROP Exclude_From_Build 1
-# End Source File
-# End Target
-# End Project
diff --git a/atomic/netware/apr_atomic.c b/atomic/netware/apr_atomic.c
new file mode 100644
index 00000000000..d7e00cd4e8f
--- /dev/null
+++ b/atomic/netware/apr_atomic.c
@@ -0,0 +1,75 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_atomic.h"
+
+#include <stdlib.h>
+
+APR_DECLARE(apr_status_t) apr_atomic_init(apr_pool_t *pool)
+{
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_uint32_t) apr_atomic_add32(volatile apr_uint32_t *mem, apr_uint32_t val)
+{
+    return atomic_xchgadd((unsigned long *)mem,(unsigned long)val);
+}
+
+APR_DECLARE(void) apr_atomic_sub32(volatile apr_uint32_t *mem, apr_uint32_t val)
+{
+    atomic_sub((unsigned long *)mem,(unsigned long)val);
+}
+
+APR_DECLARE(apr_uint32_t) apr_atomic_inc32(volatile apr_uint32_t *mem)
+{
+    return atomic_xchgadd((unsigned long *)mem, 1);
+}
+
+APR_DECLARE(void) apr_atomic_set32(volatile apr_uint32_t *mem, apr_uint32_t val)
+{
+    *mem = val;
+}
+
+APR_DECLARE(apr_uint32_t) apr_atomic_read32(volatile apr_uint32_t *mem)
+{
+    return *mem;
+}
+
+APR_DECLARE(apr_uint32_t) apr_atomic_cas32(volatile apr_uint32_t *mem, apr_uint32_t with,apr_uint32_t cmp)
+{
+    return atomic_cmpxchg((unsigned long *)mem,(unsigned long)cmp,(unsigned long)with);
+}
+
+APR_DECLARE(apr_uint32_t) apr_atomic_xchg32(volatile apr_uint32_t *mem, apr_uint32_t val)
+{
+    return atomic_xchg((unsigned long *)mem,(unsigned long)val);
+}
+
+APR_DECLARE(int) apr_atomic_dec32(volatile apr_uint32_t *mem) 
+{
+    return (atomic_xchgadd((unsigned long *)mem, 0xFFFFFFFF) - 1);
+}
+
+APR_DECLARE(void *) apr_atomic_casptr(void *volatile *mem, void *with, const void *cmp)
+{
+    return (void*)atomic_cmpxchg((unsigned long *)mem,(unsigned long)cmp,(unsigned long)with);
+}
+
+APR_DECLARE(void*) apr_atomic_xchgptr(void *volatile *mem, void *with)
+{
+    return (void*)atomic_xchg((unsigned long *)mem,(unsigned long)with);
+}
diff --git a/atomic/os390/atomic.c b/atomic/os390/atomic.c
new file mode 100644
index 00000000000..8fd1586022c
--- /dev/null
+++ b/atomic/os390/atomic.c
@@ -0,0 +1,137 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "apr.h"
+#include "apr_atomic.h"
+
+#include <stdlib.h>
+
+apr_status_t apr_atomic_init(apr_pool_t *p)
+{
+    return APR_SUCCESS;
+}
+
+apr_uint32_t apr_atomic_add32(volatile apr_uint32_t *mem, apr_uint32_t val)
+{
+    apr_uint32_t old, new_val; 
+
+    old = *mem;   /* old is automatically updated on cs failure */
+    do {
+        new_val = old + val;
+    } while (__cs(&old, (cs_t *)mem, new_val));
+    return old;
+}
+
+void apr_atomic_sub32(volatile apr_uint32_t *mem, apr_uint32_t val)
+{
+     apr_uint32_t old, new_val;
+
+     old = *mem;   /* old is automatically updated on cs failure */
+     do {
+         new_val = old - val;
+     } while (__cs(&old, (cs_t *)mem, new_val));
+}
+
+apr_uint32_t apr_atomic_inc32(volatile apr_uint32_t *mem)
+{
+    return apr_atomic_add32(mem, 1);
+}
+
+int apr_atomic_dec32(volatile apr_uint32_t *mem)
+{
+    apr_uint32_t old, new_val; 
+
+    old = *mem;   /* old is automatically updated on cs failure */
+    do {
+        new_val = old - 1;
+    } while (__cs(&old, (cs_t *)mem, new_val)); 
+
+    return new_val != 0;
+}
+
+apr_uint32_t apr_atomic_read32(volatile apr_uint32_t *mem)
+{
+    return *mem;
+}
+
+void apr_atomic_set32(volatile apr_uint32_t *mem, apr_uint32_t val)
+{
+    *mem = val;
+}
+
+apr_uint32_t apr_atomic_cas32(volatile apr_uint32_t *mem, apr_uint32_t swap, 
+                              apr_uint32_t cmp)
+{
+    apr_uint32_t old = cmp;
+    
+    __cs(&old, (cs_t *)mem, swap);
+    return old; /* old is automatically updated from mem on cs failure */
+}
+
+#if APR_SIZEOF_VOIDP == 4
+void *apr_atomic_casptr(void *volatile *mem_ptr,
+                        void *swap_ptr,
+                        const void *cmp_ptr)
+{
+     __cs1(&cmp_ptr,     /* automatically updated from mem on __cs1 failure  */
+           mem_ptr,      /* set from swap when __cs1 succeeds                */
+           &swap_ptr);
+     return (void *)cmp_ptr;
+}
+#elif APR_SIZEOF_VOIDP == 8
+void *apr_atomic_casptr(void *volatile *mem_ptr,
+                        void *swap_ptr,
+                        const void *cmp_ptr)
+{
+     __csg(&cmp_ptr,     /* automatically updated from mem on __csg failure  */
+           mem_ptr,      /* set from swap when __csg succeeds                */
+           &swap_ptr);  
+     return (void *)cmp_ptr;
+}
+#else
+#error APR_SIZEOF_VOIDP value not supported
+#endif /* APR_SIZEOF_VOIDP */
+
+apr_uint32_t apr_atomic_xchg32(volatile apr_uint32_t *mem, apr_uint32_t val)
+{
+    apr_uint32_t old, new_val; 
+
+    old = *mem;   /* old is automatically updated on cs failure */
+    do {
+        new_val = val;
+    } while (__cs(&old, (cs_t *)mem, new_val)); 
+
+    return old;
+}
+
+APR_DECLARE(void*) apr_atomic_xchgptr(void *volatile *mem_ptr, void *new_ptr)
+{
+    void *old_ptr;
+
+    old_ptr = *(void **)mem_ptr; /* old is automatically updated on cs failure */
+#if APR_SIZEOF_VOIDP == 4
+    do {
+    } while (__cs1(&old_ptr, mem_ptr, &new_ptr)); 
+#elif APR_SIZEOF_VOIDP == 8
+    do { 
+    } while (__csg(&old_ptr, mem_ptr, &new_ptr)); 
+#else
+#error APR_SIZEOF_VOIDP value not supported
+#endif /* APR_SIZEOF_VOIDP */
+
+    return old_ptr;
+}
diff --git a/atomic/unix/builtins.c b/atomic/unix/builtins.c
new file mode 100644
index 00000000000..ebf8833d193
--- /dev/null
+++ b/atomic/unix/builtins.c
@@ -0,0 +1,81 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_arch_atomic.h"
+
+#ifdef USE_ATOMICS_BUILTINS
+
+APR_DECLARE(apr_status_t) apr_atomic_init(apr_pool_t *p)
+{
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_uint32_t) apr_atomic_read32(volatile apr_uint32_t *mem)
+{
+    return *mem;
+}
+
+APR_DECLARE(void) apr_atomic_set32(volatile apr_uint32_t *mem, apr_uint32_t val)
+{
+    *mem = val;
+}
+
+APR_DECLARE(apr_uint32_t) apr_atomic_add32(volatile apr_uint32_t *mem, apr_uint32_t val)
+{
+    return __sync_fetch_and_add(mem, val);
+}
+
+APR_DECLARE(void) apr_atomic_sub32(volatile apr_uint32_t *mem, apr_uint32_t val)
+{
+    __sync_fetch_and_sub(mem, val);
+}
+
+APR_DECLARE(apr_uint32_t) apr_atomic_inc32(volatile apr_uint32_t *mem)
+{
+    return __sync_fetch_and_add(mem, 1);
+}
+
+APR_DECLARE(int) apr_atomic_dec32(volatile apr_uint32_t *mem)
+{
+    return __sync_sub_and_fetch(mem, 1);
+}
+
+APR_DECLARE(apr_uint32_t) apr_atomic_cas32(volatile apr_uint32_t *mem, apr_uint32_t with,
+                                           apr_uint32_t cmp)
+{
+    return __sync_val_compare_and_swap(mem, cmp, with);
+}
+
+APR_DECLARE(apr_uint32_t) apr_atomic_xchg32(volatile apr_uint32_t *mem, apr_uint32_t val)
+{
+    __sync_synchronize();
+
+    return __sync_lock_test_and_set(mem, val);
+}
+
+APR_DECLARE(void*) apr_atomic_casptr(void *volatile *mem, void *with, const void *cmp)
+{
+    return (void*) __sync_val_compare_and_swap(mem, cmp, with);
+}
+
+APR_DECLARE(void*) apr_atomic_xchgptr(void *volatile *mem, void *with)
+{
+    __sync_synchronize();
+
+    return (void*) __sync_lock_test_and_set(mem, with);
+}
+
+#endif /* USE_ATOMICS_BUILTINS */
diff --git a/atomic/unix/ia32.c b/atomic/unix/ia32.c
new file mode 100644
index 00000000000..9941af5f5f3
--- /dev/null
+++ b/atomic/unix/ia32.c
@@ -0,0 +1,127 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_arch_atomic.h"
+
+#ifdef USE_ATOMICS_IA32
+
+APR_DECLARE(apr_status_t) apr_atomic_init(apr_pool_t *p)
+{
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_uint32_t) apr_atomic_read32(volatile apr_uint32_t *mem)
+{
+    return *mem;
+}
+
+APR_DECLARE(void) apr_atomic_set32(volatile apr_uint32_t *mem, apr_uint32_t val)
+{
+    *mem = val;
+}
+
+APR_DECLARE(apr_uint32_t) apr_atomic_add32(volatile apr_uint32_t *mem, apr_uint32_t val)
+{
+    asm volatile ("lock; xaddl %0,%1"
+                  : "=r" (val), "=m" (*mem)
+                  : "0" (val), "m" (*mem)
+                  : "memory", "cc");
+    return val;
+}
+
+APR_DECLARE(void) apr_atomic_sub32(volatile apr_uint32_t *mem, apr_uint32_t val)
+{
+    asm volatile ("lock; subl %1, %0"
+                  : /* no output */
+                  : "m" (*(mem)), "r" (val)
+                  : "memory", "cc");
+}
+
+APR_DECLARE(apr_uint32_t) apr_atomic_inc32(volatile apr_uint32_t *mem)
+{
+    return apr_atomic_add32(mem, 1);
+}
+
+APR_DECLARE(int) apr_atomic_dec32(volatile apr_uint32_t *mem)
+{
+    unsigned char prev;
+
+    asm volatile ("lock; decl %0; setnz %1"
+                  : "=m" (*mem), "=qm" (prev)
+                  : "m" (*mem)
+                  : "memory");
+
+    return prev;
+}
+
+APR_DECLARE(apr_uint32_t) apr_atomic_cas32(volatile apr_uint32_t *mem, apr_uint32_t with,
+                                           apr_uint32_t cmp)
+{
+    apr_uint32_t prev;
+
+    asm volatile ("lock; cmpxchgl %1, %2"
+                  : "=a" (prev)
+                  : "r" (with), "m" (*(mem)), "0"(cmp)
+                  : "memory", "cc");
+    return prev;
+}
+
+APR_DECLARE(apr_uint32_t) apr_atomic_xchg32(volatile apr_uint32_t *mem, apr_uint32_t val)
+{
+    apr_uint32_t prev = val;
+
+    asm volatile ("xchgl %0, %1"
+                  : "=r" (prev), "+m" (*mem)
+                  : "0" (prev));
+    return prev;
+}
+
+APR_DECLARE(void*) apr_atomic_casptr(void *volatile *mem, void *with, const void *cmp)
+{
+    void *prev;
+#if APR_SIZEOF_VOIDP == 4
+    asm volatile ("lock; cmpxchgl %2, %1"
+                  : "=a" (prev), "=m" (*mem)
+                  : "r" (with), "m" (*mem), "0" (cmp));
+#elif APR_SIZEOF_VOIDP == 8
+    asm volatile ("lock; cmpxchgq %q2, %1"
+                  : "=a" (prev), "=m" (*mem)
+                  : "r" ((unsigned long)with), "m" (*mem),
+                    "0" ((unsigned long)cmp));
+#else
+#error APR_SIZEOF_VOIDP value not supported
+#endif
+    return prev;
+}
+
+APR_DECLARE(void*) apr_atomic_xchgptr(void *volatile *mem, void *with)
+{
+    void *prev;
+#if APR_SIZEOF_VOIDP == 4
+    asm volatile ("xchgl %2, %1"
+                  : "=a" (prev), "+m" (*mem)
+                  : "0" (with));
+#elif APR_SIZEOF_VOIDP == 8
+    asm volatile ("xchgq %q2, %1"
+                  : "=a" (prev), "+m" (*mem)
+                  : "0" (with));
+#else
+#error APR_SIZEOF_VOIDP value not supported
+#endif
+    return prev;
+}
+
+#endif /* USE_ATOMICS_IA32 */
diff --git a/atomic/unix/mutex.c b/atomic/unix/mutex.c
new file mode 100644
index 00000000000..4ec5451e144
--- /dev/null
+++ b/atomic/unix/mutex.c
@@ -0,0 +1,205 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_arch_atomic.h"
+
+#ifdef USE_ATOMICS_GENERIC
+
+#include <stdlib.h>
+
+#if APR_HAS_THREADS
+#   define DECLARE_MUTEX_LOCKED(name, mem)  \
+        apr_thread_mutex_t *name = mutex_hash(mem)
+#   define MUTEX_UNLOCK(name)                                   \
+        do {                                                    \
+            if (apr_thread_mutex_unlock(name) != APR_SUCCESS)   \
+                abort();                                        \
+        } while (0)
+#else
+#   define DECLARE_MUTEX_LOCKED(name, mem)
+#   define MUTEX_UNLOCK(name)
+#   warning Be warned: using stubs for all atomic operations
+#endif
+
+#if APR_HAS_THREADS
+
+static apr_thread_mutex_t **hash_mutex;
+
+#define NUM_ATOMIC_HASH 7
+/* shift by 2 to get rid of alignment issues */
+#define ATOMIC_HASH(x) (unsigned int)(((unsigned long)(x)>>2)%(unsigned int)NUM_ATOMIC_HASH)
+
+static apr_status_t atomic_cleanup(void *data)
+{
+    if (hash_mutex == data)
+        hash_mutex = NULL;
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_atomic_init(apr_pool_t *p)
+{
+    int i;
+    apr_status_t rv;
+
+    if (hash_mutex != NULL)
+        return APR_SUCCESS;
+
+    hash_mutex = apr_palloc(p, sizeof(apr_thread_mutex_t*) * NUM_ATOMIC_HASH);
+    apr_pool_cleanup_register(p, hash_mutex, atomic_cleanup,
+                              apr_pool_cleanup_null);
+
+    for (i = 0; i < NUM_ATOMIC_HASH; i++) {
+        rv = apr_thread_mutex_create(&(hash_mutex[i]),
+                                     APR_THREAD_MUTEX_DEFAULT, p);
+        if (rv != APR_SUCCESS) {
+           return rv;
+        }
+    }
+
+    return APR_SUCCESS;
+}
+
+static APR_INLINE apr_thread_mutex_t *mutex_hash(volatile apr_uint32_t *mem)
+{
+    apr_thread_mutex_t *mutex = hash_mutex[ATOMIC_HASH(mem)];
+
+    if (apr_thread_mutex_lock(mutex) != APR_SUCCESS) {
+        abort();
+    }
+
+    return mutex;
+}
+
+#else
+
+APR_DECLARE(apr_status_t) apr_atomic_init(apr_pool_t *p)
+{
+    return APR_SUCCESS;
+}
+
+#endif /* APR_HAS_THREADS */
+
+APR_DECLARE(apr_uint32_t) apr_atomic_read32(volatile apr_uint32_t *mem)
+{
+    return *mem;
+}
+
+APR_DECLARE(void) apr_atomic_set32(volatile apr_uint32_t *mem, apr_uint32_t val)
+{
+    DECLARE_MUTEX_LOCKED(mutex, mem);
+
+    *mem = val;
+
+    MUTEX_UNLOCK(mutex);
+}
+
+APR_DECLARE(apr_uint32_t) apr_atomic_add32(volatile apr_uint32_t *mem, apr_uint32_t val)
+{
+    apr_uint32_t old_value;
+    DECLARE_MUTEX_LOCKED(mutex, mem);
+
+    old_value = *mem;
+    *mem += val;
+
+    MUTEX_UNLOCK(mutex);
+
+    return old_value;
+}
+
+APR_DECLARE(void) apr_atomic_sub32(volatile apr_uint32_t *mem, apr_uint32_t val)
+{
+    DECLARE_MUTEX_LOCKED(mutex, mem);
+    *mem -= val;
+    MUTEX_UNLOCK(mutex);
+}
+
+APR_DECLARE(apr_uint32_t) apr_atomic_inc32(volatile apr_uint32_t *mem)
+{
+    return apr_atomic_add32(mem, 1);
+}
+
+APR_DECLARE(int) apr_atomic_dec32(volatile apr_uint32_t *mem)
+{
+    apr_uint32_t new;
+    DECLARE_MUTEX_LOCKED(mutex, mem);
+
+    (*mem)--;
+    new = *mem;
+
+    MUTEX_UNLOCK(mutex);
+
+    return new;
+}
+
+APR_DECLARE(apr_uint32_t) apr_atomic_cas32(volatile apr_uint32_t *mem, apr_uint32_t with,
+                              apr_uint32_t cmp)
+{
+    apr_uint32_t prev;
+    DECLARE_MUTEX_LOCKED(mutex, mem);
+
+    prev = *mem;
+    if (prev == cmp) {
+        *mem = with;
+    }
+
+    MUTEX_UNLOCK(mutex);
+
+    return prev;
+}
+
+APR_DECLARE(apr_uint32_t) apr_atomic_xchg32(volatile apr_uint32_t *mem, apr_uint32_t val)
+{
+    apr_uint32_t prev;
+    DECLARE_MUTEX_LOCKED(mutex, mem);
+
+    prev = *mem;
+    *mem = val;
+
+    MUTEX_UNLOCK(mutex);
+
+    return prev;
+}
+
+APR_DECLARE(void*) apr_atomic_casptr(void *volatile *mem, void *with, const void *cmp)
+{
+    void *prev;
+    DECLARE_MUTEX_LOCKED(mutex, *mem);
+
+    prev = *(void **)mem;
+    if (prev == cmp) {
+        *mem = with;
+    }
+
+    MUTEX_UNLOCK(mutex);
+
+    return prev;
+}
+
+APR_DECLARE(void*) apr_atomic_xchgptr(void *volatile *mem, void *with)
+{
+    void *prev;
+    DECLARE_MUTEX_LOCKED(mutex, *mem);
+
+    prev = *(void **)mem;
+    *mem = with;
+
+    MUTEX_UNLOCK(mutex);
+
+    return prev;
+}
+
+#endif /* USE_ATOMICS_GENERIC */
diff --git a/atomic/unix/ppc.c b/atomic/unix/ppc.c
new file mode 100644
index 00000000000..87c6900d384
--- /dev/null
+++ b/atomic/unix/ppc.c
@@ -0,0 +1,207 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_arch_atomic.h"
+
+#ifdef USE_ATOMICS_PPC
+
+#ifdef PPC405_ERRATA
+#   define PPC405_ERR77_SYNC   "    sync\n"
+#else
+#   define PPC405_ERR77_SYNC
+#endif
+
+APR_DECLARE(apr_status_t) apr_atomic_init(apr_pool_t *p)
+{
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_uint32_t) apr_atomic_read32(volatile apr_uint32_t *mem)
+{
+    return *mem;
+}
+
+APR_DECLARE(void) apr_atomic_set32(volatile apr_uint32_t *mem, apr_uint32_t val)
+{
+    *mem = val;
+}
+
+APR_DECLARE(apr_uint32_t) apr_atomic_add32(volatile apr_uint32_t *mem, apr_uint32_t val)
+{
+    apr_uint32_t prev, temp;
+
+    asm volatile ("1:\n"                       /* lost reservation     */
+                  "    lwarx   %0,0,%3\n"      /* load and reserve     */
+                  "    add     %1,%0,%4\n"     /* add val and prev     */
+                  PPC405_ERR77_SYNC            /* ppc405 Erratum 77    */
+                  "    stwcx.  %1,0,%3\n"      /* store new value      */
+                  "    bne-    1b\n"           /* loop if lost         */
+                  : "=&r" (prev), "=&r" (temp), "=m" (*mem)
+                  : "b" (mem), "r" (val)
+                  : "cc", "memory");
+
+    return prev;
+}
+
+APR_DECLARE(void) apr_atomic_sub32(volatile apr_uint32_t *mem, apr_uint32_t val)
+{
+    apr_uint32_t temp;
+
+    asm volatile ("1:\n"                       /* lost reservation     */
+                  "    lwarx   %0,0,%2\n"      /* load and reserve     */
+                  "    subf    %0,%3,%0\n"     /* subtract val         */
+                  PPC405_ERR77_SYNC            /* ppc405 Erratum 77    */
+                  "    stwcx.  %0,0,%2\n"      /* store new value      */
+                  "    bne-    1b\n"           /* loop if lost         */
+                  : "=&r" (temp), "=m" (*mem)
+                  : "b" (mem), "r" (val)
+                  : "cc", "memory");
+}
+
+APR_DECLARE(apr_uint32_t) apr_atomic_inc32(volatile apr_uint32_t *mem)
+{
+    apr_uint32_t prev;
+
+    asm volatile ("1:\n"                       /* lost reservation     */
+                  "    lwarx   %0,0,%2\n"      /* load and reserve     */
+                  "    addi    %0,%0,1\n"      /* add immediate        */
+                  PPC405_ERR77_SYNC            /* ppc405 Erratum 77    */
+                  "    stwcx.  %0,0,%2\n"      /* store new value      */
+                  "    bne-    1b\n"           /* loop if lost         */
+                  "    subi    %0,%0,1\n"      /* return old value     */
+                  : "=&b" (prev), "=m" (*mem)
+                  : "b" (mem), "m" (*mem)
+                  : "cc", "memory");
+
+    return prev;
+}
+
+APR_DECLARE(int) apr_atomic_dec32(volatile apr_uint32_t *mem)
+{
+    apr_uint32_t prev;
+
+    asm volatile ("1:\n"                       /* lost reservation     */
+                  "    lwarx   %0,0,%2\n"      /* load and reserve     */
+                  "    subi    %0,%0,1\n"      /* subtract immediate   */
+                  PPC405_ERR77_SYNC            /* ppc405 Erratum 77    */
+                  "    stwcx.  %0,0,%2\n"      /* store new value      */
+                  "    bne-    1b\n"           /* loop if lost         */
+                  : "=&b" (prev), "=m" (*mem)
+                  : "b" (mem), "m" (*mem)
+                  : "cc", "memory");
+
+    return prev;
+}
+
+APR_DECLARE(apr_uint32_t) apr_atomic_cas32(volatile apr_uint32_t *mem, apr_uint32_t with,
+                                           apr_uint32_t cmp)
+{
+    apr_uint32_t prev;
+
+    asm volatile ("1:\n"                       /* lost reservation     */
+                  "    lwarx   %0,0,%1\n"      /* load and reserve     */
+                  "    cmpw    %0,%3\n"        /* compare operands     */
+                  "    bne-    exit_%=\n"      /* skip if not equal    */
+                  PPC405_ERR77_SYNC            /* ppc405 Erratum 77    */
+                  "    stwcx.  %2,0,%1\n"      /* store new value      */
+                  "    bne-    1b\n"           /* loop if lost         */
+                  "exit_%=:\n"                 /* not equal            */
+                  : "=&r" (prev)
+                  : "b" (mem), "r" (with), "r" (cmp)
+                  : "cc", "memory");
+
+    return prev;
+}
+
+APR_DECLARE(apr_uint32_t) apr_atomic_xchg32(volatile apr_uint32_t *mem, apr_uint32_t val)
+{
+    apr_uint32_t prev;
+
+    asm volatile ("1:\n"                       /* lost reservation     */
+                  "    lwarx   %0,0,%1\n"      /* load and reserve     */
+                  PPC405_ERR77_SYNC            /* ppc405 Erratum 77    */
+                  "    stwcx.  %2,0,%1\n"      /* store new value      */
+                  "    bne-    1b"             /* loop if lost         */
+                  : "=&r" (prev)
+                  : "b" (mem), "r" (val)
+                  : "cc", "memory");
+
+    return prev;
+}
+
+APR_DECLARE(void*) apr_atomic_casptr(void *volatile *mem, void *with, const void *cmp)
+{
+    void *prev;
+#if APR_SIZEOF_VOIDP == 4
+    asm volatile ("1:\n"                       /* lost reservation     */
+                  "    lwarx   %0,0,%1\n"      /* load and reserve     */
+                  "    cmpw    %0,%3\n"        /* compare operands     */
+                  "    bne-    2f\n"           /* skip if not equal    */
+                  PPC405_ERR77_SYNC            /* ppc405 Erratum 77    */
+                  "    stwcx.  %2,0,%1\n"      /* store new value      */
+                  "    bne-    1b\n"           /* loop if lost         */
+                  "2:\n"                       /* not equal            */
+                  : "=&r" (prev)
+                  : "b" (mem), "r" (with), "r" (cmp)
+                  : "cc", "memory");
+#elif APR_SIZEOF_VOIDP == 8
+    asm volatile ("1:\n"                       /* lost reservation     */
+                  "    ldarx   %0,0,%1\n"      /* load and reserve     */
+                  "    cmpd    %0,%3\n"        /* compare operands     */
+                  "    bne-    2f\n"           /* skip if not equal    */
+                  PPC405_ERR77_SYNC            /* ppc405 Erratum 77    */
+                  "    stdcx.  %2,0,%1\n"      /* store new value      */
+                  "    bne-    1b\n"           /* loop if lost         */
+                  "2:\n"                       /* not equal            */
+                  : "=&r" (prev)
+                  : "b" (mem), "r" (with), "r" (cmp)
+                  : "cc", "memory");
+#else
+#error APR_SIZEOF_VOIDP value not supported
+#endif
+    return prev;
+}
+
+APR_DECLARE(void*) apr_atomic_xchgptr(void *volatile *mem, void *with)
+{
+    void *prev;
+#if APR_SIZEOF_VOIDP == 4
+    asm volatile ("1:\n"                       /* lost reservation     */
+                  "    lwarx   %0,0,%1\n"      /* load and reserve     */
+                  PPC405_ERR77_SYNC            /* ppc405 Erratum 77    */
+                  "    stwcx.  %2,0,%1\n"      /* store new value      */
+                  "    bne-    1b\n"           /* loop if lost         */
+                  "    isync\n"                /* memory barrier       */
+                  : "=&r" (prev)
+                  : "b" (mem), "r" (with)
+                  : "cc", "memory");
+#elif APR_SIZEOF_VOIDP == 8
+    asm volatile ("1:\n"                       /* lost reservation     */
+                  "    ldarx   %0,0,%1\n"      /* load and reserve     */
+                  PPC405_ERR77_SYNC            /* ppc405 Erratum 77    */
+                  "    stdcx.  %2,0,%1\n"      /* store new value      */
+                  "    bne-    1b\n"           /* loop if lost         */
+                  "    isync\n"                /* memory barrier       */
+                  : "=&r" (prev)
+                  : "b" (mem), "r" (with)
+                  : "cc", "memory");
+#else
+#error APR_SIZEOF_VOIDP value not supported
+#endif
+    return prev;
+}
+
+#endif /* USE_ATOMICS_PPC */
diff --git a/atomic/unix/s390.c b/atomic/unix/s390.c
new file mode 100644
index 00000000000..cc139b83795
--- /dev/null
+++ b/atomic/unix/s390.c
@@ -0,0 +1,155 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_arch_atomic.h"
+
+#ifdef USE_ATOMICS_S390
+
+APR_DECLARE(apr_status_t) apr_atomic_init(apr_pool_t *p)
+{
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_uint32_t) apr_atomic_read32(volatile apr_uint32_t *mem)
+{
+    return *mem;
+}
+
+APR_DECLARE(void) apr_atomic_set32(volatile apr_uint32_t *mem, apr_uint32_t val)
+{
+    *mem = val;
+}
+
+static APR_INLINE apr_uint32_t atomic_add(volatile apr_uint32_t *mem, apr_uint32_t val)
+{
+    apr_uint32_t prev = *mem, temp;
+
+    asm volatile ("loop_%=:\n"
+                  "    lr  %1,%0\n"
+                  "    alr %1,%3\n"
+                  "    cs  %0,%1,%2\n"
+                  "    jl  loop_%=\n"
+                  : "+d" (prev), "+d" (temp), "=Q" (*mem)
+                  : "d" (val), "m" (*mem)
+                  : "cc", "memory");
+
+    return prev;
+}
+
+APR_DECLARE(apr_uint32_t) apr_atomic_add32(volatile apr_uint32_t *mem, apr_uint32_t val)
+{
+    return atomic_add(mem, val);
+}
+
+APR_DECLARE(apr_uint32_t) apr_atomic_inc32(volatile apr_uint32_t *mem)
+{
+    return atomic_add(mem, 1);
+}
+
+static APR_INLINE apr_uint32_t atomic_sub(volatile apr_uint32_t *mem, apr_uint32_t val)
+{
+    apr_uint32_t prev = *mem, temp;
+
+    asm volatile ("loop_%=:\n"
+                  "    lr  %1,%0\n"
+                  "    slr %1,%3\n"
+                  "    cs  %0,%1,%2\n"
+                  "    jl  loop_%=\n"
+                  : "+d" (prev), "+d" (temp), "=Q" (*mem)
+                  : "d" (val), "m" (*mem)
+                  : "cc", "memory");
+
+    return temp;
+}
+
+APR_DECLARE(void) apr_atomic_sub32(volatile apr_uint32_t *mem, apr_uint32_t val)
+{
+    atomic_sub(mem, val);
+}
+
+APR_DECLARE(int) apr_atomic_dec32(volatile apr_uint32_t *mem)
+{
+    return atomic_sub(mem, 1);
+}
+
+APR_DECLARE(apr_uint32_t) apr_atomic_cas32(volatile apr_uint32_t *mem, apr_uint32_t with,
+                                           apr_uint32_t cmp)
+{
+    asm volatile ("    cs  %0,%2,%1\n"
+                  : "+d" (cmp), "=Q" (*mem)
+                  : "d" (with), "m" (*mem)
+                  : "cc", "memory");
+
+    return cmp;
+}
+
+APR_DECLARE(apr_uint32_t) apr_atomic_xchg32(volatile apr_uint32_t *mem, apr_uint32_t val)
+{
+    apr_uint32_t prev = *mem;
+
+    asm volatile ("loop_%=:\n"
+                  "    cs  %0,%2,%1\n"
+                  "    jl  loop_%=\n"
+                  : "+d" (prev), "=Q" (*mem)
+                  : "d" (val), "m" (*mem)
+                  : "cc", "memory");
+
+    return prev;
+}
+
+APR_DECLARE(void*) apr_atomic_casptr(void *volatile *mem, void *with, const void *cmp)
+{
+    void *prev = (void *) cmp;
+#if APR_SIZEOF_VOIDP == 4
+    asm volatile ("    cs  %0,%2,%1\n"
+                  : "+d" (prev), "=Q" (*mem)
+                  : "d" (with), "m" (*mem)
+                  : "cc", "memory");
+#elif APR_SIZEOF_VOIDP == 8
+    asm volatile ("    csg %0,%2,%1\n"
+                  : "+d" (prev), "=Q" (*mem)
+                  : "d" (with), "m" (*mem)
+                  : "cc", "memory");
+#else
+#error APR_SIZEOF_VOIDP value not supported
+#endif
+    return prev;
+}
+
+APR_DECLARE(void*) apr_atomic_xchgptr(void *volatile *mem, void *with)
+{
+    void *prev = (void *) *mem;
+#if APR_SIZEOF_VOIDP == 4
+    asm volatile ("loop_%=:\n"
+                  "    cs  %0,%2,%1\n"
+                  "    jl  loop_%=\n"
+                  : "+d" (prev), "=Q" (*mem)
+                  : "d" (with), "m" (*mem)
+                  : "cc", "memory");
+#elif APR_SIZEOF_VOIDP == 8
+    asm volatile ("loop_%=:\n"
+                  "    csg %0,%2,%1\n"
+                  "    jl  loop_%=\n"
+                  : "+d" (prev), "=Q" (*mem)
+                  : "d" (with), "m" (*mem)
+                  : "cc", "memory");
+#else
+#error APR_SIZEOF_VOIDP value not supported
+#endif
+    return prev;
+}
+
+#endif /* USE_ATOMICS_S390 */
diff --git a/atomic/unix/solaris.c b/atomic/unix/solaris.c
new file mode 100644
index 00000000000..a160f6808cd
--- /dev/null
+++ b/atomic/unix/solaris.c
@@ -0,0 +1,79 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_arch_atomic.h"
+
+#ifdef USE_ATOMICS_SOLARIS
+
+#include <atomic.h>
+
+APR_DECLARE(apr_status_t) apr_atomic_init(apr_pool_t *p)
+{
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_uint32_t) apr_atomic_read32(volatile apr_uint32_t *mem)
+{
+    return *mem;
+}
+
+APR_DECLARE(void) apr_atomic_set32(volatile apr_uint32_t *mem, apr_uint32_t val)
+{
+    *mem = val;
+}
+
+APR_DECLARE(apr_uint32_t) apr_atomic_add32(volatile apr_uint32_t *mem, apr_uint32_t val)
+{
+    return atomic_add_32_nv(mem, val) - val;
+}
+
+APR_DECLARE(void) apr_atomic_sub32(volatile apr_uint32_t *mem, apr_uint32_t val)
+{
+    atomic_add_32(mem, -val);
+}
+
+APR_DECLARE(apr_uint32_t) apr_atomic_inc32(volatile apr_uint32_t *mem)
+{
+    return atomic_inc_32_nv(mem) - 1;
+}
+
+APR_DECLARE(int) apr_atomic_dec32(volatile apr_uint32_t *mem)
+{
+    return atomic_dec_32_nv(mem);
+}
+
+APR_DECLARE(apr_uint32_t) apr_atomic_cas32(volatile apr_uint32_t *mem, apr_uint32_t with,
+                                           apr_uint32_t cmp)
+{
+    return atomic_cas_32(mem, cmp, with);
+}
+
+APR_DECLARE(apr_uint32_t) apr_atomic_xchg32(volatile apr_uint32_t *mem, apr_uint32_t val)
+{
+    return atomic_swap_32(mem, val);
+}
+
+APR_DECLARE(void*) apr_atomic_casptr(void *volatile *mem, void *with, const void *cmp)
+{
+    return atomic_cas_ptr(mem, (void*) cmp, with);
+}
+
+APR_DECLARE(void*) apr_atomic_xchgptr(void *volatile *mem, void *with)
+{
+    return atomic_swap_ptr(mem, with);
+}
+
+#endif /* USE_ATOMICS_SOLARIS */
diff --git a/atomic/win32/apr_atomic.c b/atomic/win32/apr_atomic.c
new file mode 100644
index 00000000000..9228d0a3da2
--- /dev/null
+++ b/atomic/win32/apr_atomic.c
@@ -0,0 +1,113 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_atomic.h"
+#include "apr_thread_mutex.h"
+
+APR_DECLARE(apr_status_t) apr_atomic_init(apr_pool_t *p)
+{
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_uint32_t) apr_atomic_add32(volatile apr_uint32_t *mem, apr_uint32_t val)
+{
+#if (defined(_M_IA64) || defined(_M_AMD64))
+    return InterlockedExchangeAdd(mem, val);
+#else
+    return InterlockedExchangeAdd((long *)mem, val);
+#endif
+}
+
+/* Of course we want the 2's compliment of the unsigned value, val */
+#ifdef _MSC_VER
+#pragma warning(disable: 4146)
+#endif
+
+APR_DECLARE(void) apr_atomic_sub32(volatile apr_uint32_t *mem, apr_uint32_t val)
+{
+#if (defined(_M_IA64) || defined(_M_AMD64))
+    InterlockedExchangeAdd(mem, -val);
+#else
+    InterlockedExchangeAdd((long *)mem, -val);
+#endif
+}
+
+APR_DECLARE(apr_uint32_t) apr_atomic_inc32(volatile apr_uint32_t *mem)
+{
+    /* we return old value, win32 returns new value :( */
+#if (defined(_M_IA64) || defined(_M_AMD64)) && !defined(RC_INVOKED)
+    return InterlockedIncrement(mem) - 1;
+#else
+    return InterlockedIncrement((long *)mem) - 1;
+#endif
+}
+
+APR_DECLARE(int) apr_atomic_dec32(volatile apr_uint32_t *mem)
+{
+#if (defined(_M_IA64) || defined(_M_AMD64)) && !defined(RC_INVOKED)
+    return InterlockedDecrement(mem);
+#else
+    return InterlockedDecrement((long *)mem);
+#endif
+}
+
+APR_DECLARE(void) apr_atomic_set32(volatile apr_uint32_t *mem, apr_uint32_t val)
+{
+#if (defined(_M_IA64) || defined(_M_AMD64)) && !defined(RC_INVOKED)
+    InterlockedExchange(mem, val);
+#else
+    InterlockedExchange((long*)mem, val);
+#endif
+}
+
+APR_DECLARE(apr_uint32_t) apr_atomic_read32(volatile apr_uint32_t *mem)
+{
+    return *mem;
+}
+
+APR_DECLARE(apr_uint32_t) apr_atomic_cas32(volatile apr_uint32_t *mem, apr_uint32_t with,
+                                           apr_uint32_t cmp)
+{
+#if (defined(_M_IA64) || defined(_M_AMD64)) && !defined(RC_INVOKED)
+    return InterlockedCompareExchange(mem, with, cmp);
+#else
+    return InterlockedCompareExchange((long*)mem, with, cmp);
+#endif
+}
+
+APR_DECLARE(void *) apr_atomic_casptr(void *volatile *mem, void *with, const void *cmp)
+{
+#if (defined(_M_IA64) || defined(_M_AMD64)) && !defined(RC_INVOKED)
+    return InterlockedCompareExchangePointer(mem, with, (void*)cmp);
+#else
+    return InterlockedCompareExchangePointer((void**)mem, with, (void*)cmp);
+#endif
+}
+
+APR_DECLARE(apr_uint32_t) apr_atomic_xchg32(volatile apr_uint32_t *mem, apr_uint32_t val)
+{
+#if (defined(_M_IA64) || defined(_M_AMD64)) && !defined(RC_INVOKED)
+    return InterlockedExchange(mem, val);
+#else
+    return InterlockedExchange((long *)mem, val);
+#endif
+}
+
+APR_DECLARE(void*) apr_atomic_xchgptr(void *volatile *mem, void *with)
+{
+    return InterlockedExchangePointer((void**)mem, with);
+}
diff --git a/buckets/apr_brigade.c b/buckets/apr_brigade.c
new file mode 100644
index 00000000000..42403f4a113
--- /dev/null
+++ b/buckets/apr_brigade.c
@@ -0,0 +1,762 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_lib.h"
+#include "apr_strings.h"
+#include "apr_pools.h"
+#include "apr_tables.h"
+#include "apr_buckets.h"
+#include "apr_errno.h"
+#define APR_WANT_MEMFUNC
+#define APR_WANT_STRFUNC
+#include "apr_want.h"
+
+#if APR_HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#endif
+
+static apr_status_t brigade_cleanup(void *data) 
+{
+    return apr_brigade_cleanup(data);
+}
+
+APR_DECLARE(apr_status_t) apr_brigade_cleanup(void *data)
+{
+    apr_bucket_brigade *b = data;
+    apr_bucket *e;
+    apr_bucket *prev = NULL;
+
+    APR_BRIGADE_CHECK_CONSISTENCY(b);
+
+    while (!APR_BRIGADE_EMPTY(b)) {
+        e = APR_BRIGADE_FIRST(b);
+        if (e == prev) {         /* PR#51062: prevent infinite loop on a corrupt brigade */
+            return APR_EGENERAL; /* FIXME: this should definitely be a "can't happen"!   */
+        }
+        prev = e;
+        apr_bucket_delete(e);
+    }
+    /* We don't need to free(bb) because it's allocated from a pool. */
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_brigade_destroy(apr_bucket_brigade *b)
+{
+#ifndef APR_BUCKET_DEBUG
+    return apr_pool_cleanup_run(b->p, b, brigade_cleanup);
+#else
+    apr_status_t rv;
+    
+    APR_BRIGADE_CHECK_CONSISTENCY(b);
+
+    rv = apr_pool_cleanup_run(b->p, b, brigade_cleanup);
+
+    /* Trigger consistency check failures if the brigade is
+     * re-used. */
+    b->p = NULL;
+    b->bucket_alloc = NULL;
+
+    return rv;
+#endif
+}
+
+APR_DECLARE(apr_bucket_brigade *) apr_brigade_create(apr_pool_t *p,
+                                                     apr_bucket_alloc_t *list)
+{
+    apr_bucket_brigade *b;
+
+    b = apr_palloc(p, sizeof(*b));
+    b->p = p;
+    b->bucket_alloc = list;
+
+    APR_RING_INIT(&b->list, apr_bucket, link);
+
+    apr_pool_cleanup_register(b->p, b, brigade_cleanup, apr_pool_cleanup_null);
+    return b;
+}
+
+APR_DECLARE(apr_bucket_brigade *) apr_brigade_split_ex(apr_bucket_brigade *b,
+                                                       apr_bucket *e,
+                                                       apr_bucket_brigade *a)
+{
+    apr_bucket *f;
+
+    if (!a) {
+        a = apr_brigade_create(b->p, b->bucket_alloc);
+    }
+    else if (!APR_BRIGADE_EMPTY(a)) {
+        apr_brigade_cleanup(a);
+    }
+    /* Return an empty brigade if there is nothing left in 
+     * the first brigade to split off 
+     */
+    if (e != APR_BRIGADE_SENTINEL(b)) {
+        f = APR_RING_LAST(&b->list);
+        APR_RING_UNSPLICE(e, f, link);
+        APR_RING_SPLICE_HEAD(&a->list, e, f, apr_bucket, link);
+    }
+
+    APR_BRIGADE_CHECK_CONSISTENCY(a);
+    APR_BRIGADE_CHECK_CONSISTENCY(b);
+
+    return a;
+}
+
+APR_DECLARE(apr_bucket_brigade *) apr_brigade_split(apr_bucket_brigade *b,
+                                                    apr_bucket *e)
+{
+    return apr_brigade_split_ex(b, e, NULL);
+}
+
+APR_DECLARE(apr_status_t) apr_brigade_partition(apr_bucket_brigade *b,
+                                                apr_off_t point,
+                                                apr_bucket **after_point)
+{
+    apr_bucket *e;
+    const char *s;
+    apr_size_t len;
+    apr_uint64_t point64;
+    apr_status_t rv;
+
+    if (point < 0) {
+        /* this could cause weird (not necessarily SEGV) things to happen */
+        return APR_EINVAL;
+    }
+    if (point == 0) {
+        *after_point = APR_BRIGADE_FIRST(b);
+        return APR_SUCCESS;
+    }
+
+    /*
+     * Try to reduce the following casting mess: We know that point will be
+     * larger equal 0 now and forever and thus that point (apr_off_t) and
+     * apr_size_t will fit into apr_uint64_t in any case.
+     */
+    point64 = (apr_uint64_t)point;
+
+    APR_BRIGADE_CHECK_CONSISTENCY(b);
+
+    for (e = APR_BRIGADE_FIRST(b);
+         e != APR_BRIGADE_SENTINEL(b);
+         e = APR_BUCKET_NEXT(e))
+    {
+        /* For an unknown length bucket, while 'point64' is beyond the possible
+         * size contained in apr_size_t, read and continue...
+         */
+        if ((e->length == (apr_size_t)(-1))
+            && (point64 > (apr_uint64_t)APR_SIZE_MAX)) {
+            /* point64 is too far out to simply split this bucket,
+             * we must fix this bucket's size and keep going... */
+            rv = apr_bucket_read(e, &s, &len, APR_BLOCK_READ);
+            if (rv != APR_SUCCESS) {
+                *after_point = e;
+                return rv;
+            }
+        }
+        else if ((point64 < (apr_uint64_t)e->length)
+                 || (e->length == (apr_size_t)(-1))) {
+            /* We already consumed buckets where point64 is beyond
+             * our interest ( point64 > APR_SIZE_MAX ), above.
+             * Here point falls between 0 and APR_SIZE_MAX
+             * and is within this bucket, or this bucket's len
+             * is undefined, so now we are ready to split it.
+             * First try to split the bucket natively... */
+            if ((rv = apr_bucket_split(e, (apr_size_t)point64)) 
+                    != APR_ENOTIMPL) {
+                *after_point = APR_BUCKET_NEXT(e);
+                return rv;
+            }
+
+            /* if the bucket cannot be split, we must read from it,
+             * changing its type to one that can be split */
+            rv = apr_bucket_read(e, &s, &len, APR_BLOCK_READ);
+            if (rv != APR_SUCCESS) {
+                *after_point = e;
+                return rv;
+            }
+
+            /* this assumes that len == e->length, which is okay because e
+             * might have been morphed by the apr_bucket_read() above, but
+             * if it was, the length would have been adjusted appropriately */
+            if (point64 < (apr_uint64_t)e->length) {
+                rv = apr_bucket_split(e, (apr_size_t)point64);
+                *after_point = APR_BUCKET_NEXT(e);
+                return rv;
+            }
+        }
+        if (point64 == (apr_uint64_t)e->length) {
+            *after_point = APR_BUCKET_NEXT(e);
+            return APR_SUCCESS;
+        }
+        point64 -= (apr_uint64_t)e->length;
+    }
+    *after_point = APR_BRIGADE_SENTINEL(b); 
+    return APR_INCOMPLETE;
+}
+
+APR_DECLARE(apr_status_t) apr_brigade_length(apr_bucket_brigade *bb,
+                                             int read_all, apr_off_t *length)
+{
+    apr_off_t total = 0;
+    apr_bucket *bkt;
+    apr_status_t status = APR_SUCCESS;
+
+    for (bkt = APR_BRIGADE_FIRST(bb);
+         bkt != APR_BRIGADE_SENTINEL(bb);
+         bkt = APR_BUCKET_NEXT(bkt))
+    {
+        if (bkt->length == (apr_size_t)(-1)) {
+            const char *ignore;
+            apr_size_t len;
+
+            if (!read_all) {
+                total = -1;
+                break;
+            }
+
+            if ((status = apr_bucket_read(bkt, &ignore, &len,
+                                          APR_BLOCK_READ)) != APR_SUCCESS) {
+                break;
+            }
+        }
+
+        total += bkt->length;
+    }
+
+    *length = total;
+    return status;
+}
+
+APR_DECLARE(apr_status_t) apr_brigade_flatten(apr_bucket_brigade *bb,
+                                              char *c, apr_size_t *len)
+{
+    apr_size_t actual = 0;
+    apr_bucket *b;
+ 
+    for (b = APR_BRIGADE_FIRST(bb);
+         b != APR_BRIGADE_SENTINEL(bb);
+         b = APR_BUCKET_NEXT(b))
+    {
+        const char *str;
+        apr_size_t str_len;
+        apr_status_t status;
+
+        status = apr_bucket_read(b, &str, &str_len, APR_BLOCK_READ);
+        if (status != APR_SUCCESS) {
+            return status;
+        }
+
+        /* If we would overflow. */
+        if (str_len + actual > *len) {
+            str_len = *len - actual;
+        }
+
+        /* XXX: It appears that overflow of the final bucket
+         * is DISCARDED without any warning to the caller.
+         *
+         * No, we only copy the data up to their requested size.  -- jre
+         */
+        memcpy(c, str, str_len);
+
+        c += str_len;
+        actual += str_len;
+
+        /* This could probably be actual == *len, but be safe from stray
+         * photons. */
+        if (actual >= *len) {
+            break;
+        }
+    }
+
+    *len = actual;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_brigade_pflatten(apr_bucket_brigade *bb,
+                                               char **c,
+                                               apr_size_t *len,
+                                               apr_pool_t *pool)
+{
+    apr_off_t actual;
+    apr_size_t total;
+    apr_status_t rv;
+
+    apr_brigade_length(bb, 1, &actual);
+    
+    /* XXX: This is dangerous beyond belief.  At least in the
+     * apr_brigade_flatten case, the user explicitly stated their
+     * buffer length - so we don't up and palloc 4GB for a single
+     * file bucket.  This API must grow a useful max boundry,
+     * either compiled-in or preset via the *len value.
+     *
+     * Shouldn't both fn's grow an additional return value for 
+     * the case that the brigade couldn't be flattened into the
+     * provided or allocated buffer (such as APR_EMOREDATA?)
+     * Not a failure, simply an advisory result.
+     */
+    total = (apr_size_t)actual;
+
+    *c = apr_palloc(pool, total);
+    
+    rv = apr_brigade_flatten(bb, *c, &total);
+
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
+    *len = total;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_brigade_split_line(apr_bucket_brigade *bbOut,
+                                                 apr_bucket_brigade *bbIn,
+                                                 apr_read_type_e block,
+                                                 apr_off_t maxbytes)
+{
+    apr_off_t readbytes = 0;
+    apr_bucket *prev = NULL;
+
+    while (!APR_BRIGADE_EMPTY(bbIn)) {
+        const char *pos;
+        const char *str;
+        apr_size_t len;
+        apr_status_t rv;
+        apr_bucket *e;
+
+        e = APR_BRIGADE_FIRST(bbIn);
+        if (e == prev) {         /* PR#51062: prevent infinite loop on a corrupt brigade */
+            return APR_EGENERAL; /* FIXME: this should definitely be a "can't happen"!   */
+        }
+        prev = e;
+        rv = apr_bucket_read(e, &str, &len, block);
+
+        if (rv != APR_SUCCESS) {
+            return rv;
+        }
+
+        pos = memchr(str, APR_ASCII_LF, len);
+        /* We found a match. */
+        if (pos != NULL) {
+            apr_bucket_split(e, pos - str + 1);
+            APR_BUCKET_REMOVE(e);
+            APR_BRIGADE_INSERT_TAIL(bbOut, e);
+            return APR_SUCCESS;
+        }
+        APR_BUCKET_REMOVE(e);
+        if (APR_BUCKET_IS_METADATA(e) || len > APR_BUCKET_BUFF_SIZE/4) {
+            APR_BRIGADE_INSERT_TAIL(bbOut, e);
+        }
+        else {
+            if (len > 0) {
+                rv = apr_brigade_write(bbOut, NULL, NULL, str, len);
+                if (rv != APR_SUCCESS) {
+                    return rv;
+                }
+            }
+            apr_bucket_destroy(e);
+        }
+        readbytes += len;
+        /* We didn't find an APR_ASCII_LF within the maximum line length. */
+        if (readbytes >= maxbytes) {
+            break;
+        }
+    }
+
+    return APR_SUCCESS;
+}
+
+
+APR_DECLARE(apr_status_t) apr_brigade_to_iovec(apr_bucket_brigade *b, 
+                                               struct iovec *vec, int *nvec)
+{
+    int left = *nvec;
+    apr_bucket *e;
+    struct iovec *orig;
+    apr_size_t iov_len;
+    const char *iov_base;
+    apr_status_t rv;
+
+    orig = vec;
+
+    for (e = APR_BRIGADE_FIRST(b);
+         e != APR_BRIGADE_SENTINEL(b);
+         e = APR_BUCKET_NEXT(e))
+    {
+        if (left-- == 0)
+            break;
+
+        rv = apr_bucket_read(e, &iov_base, &iov_len, APR_NONBLOCK_READ);
+        if (rv != APR_SUCCESS)
+            return rv;
+        /* Set indirectly since types differ: */
+        vec->iov_len = iov_len;
+        vec->iov_base = (void *)iov_base;
+        ++vec;
+    }
+
+    *nvec = (int)(vec - orig);
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_brigade_vputstrs(apr_bucket_brigade *b, 
+                                               apr_brigade_flush flush,
+                                               void *ctx,
+                                               va_list va)
+{
+#define MAX_VECS    8
+    struct iovec vec[MAX_VECS];
+    apr_size_t i = 0;
+
+    for (;;) {
+        char *str = va_arg(va, char *);
+        apr_status_t rv;
+
+        if (str == NULL)
+            break;
+
+        vec[i].iov_base = str;
+        vec[i].iov_len = strlen(str);
+        i++;
+
+        if (i == MAX_VECS) {
+            rv = apr_brigade_writev(b, flush, ctx, vec, i);
+            if (rv != APR_SUCCESS)
+                return rv;
+            i = 0;
+        }
+    }
+    if (i != 0)
+       return apr_brigade_writev(b, flush, ctx, vec, i);
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_brigade_putc(apr_bucket_brigade *b,
+                                           apr_brigade_flush flush, void *ctx,
+                                           const char c)
+{
+    return apr_brigade_write(b, flush, ctx, &c, 1);
+}
+
+APR_DECLARE(apr_status_t) apr_brigade_write(apr_bucket_brigade *b,
+                                            apr_brigade_flush flush,
+                                            void *ctx, 
+                                            const char *str, apr_size_t nbyte)
+{
+    apr_bucket *e = APR_BRIGADE_LAST(b);
+    apr_size_t remaining = APR_BUCKET_BUFF_SIZE;
+    char *buf = NULL;
+
+    /*
+     * If the last bucket is a heap bucket and its buffer is not shared with
+     * another bucket, we may write into that bucket.
+     */
+    if (!APR_BRIGADE_EMPTY(b) && APR_BUCKET_IS_HEAP(e)
+        && ((apr_bucket_heap *)(e->data))->refcount.refcount == 1) {
+        apr_bucket_heap *h = e->data;
+
+        /* HEAP bucket start offsets are always in-memory, safe to cast */
+        remaining = h->alloc_len - (e->length + (apr_size_t)e->start);
+        buf = h->base + e->start + e->length;
+    }
+
+    if (nbyte > remaining) {
+        /* either a buffer bucket exists but is full, 
+         * or no buffer bucket exists and the data is too big
+         * to buffer.  In either case, we should flush.  */
+        if (flush) {
+            e = apr_bucket_transient_create(str, nbyte, b->bucket_alloc);
+            APR_BRIGADE_INSERT_TAIL(b, e);
+            return flush(b, ctx);
+        }
+        else {
+            e = apr_bucket_heap_create(str, nbyte, NULL, b->bucket_alloc);
+            APR_BRIGADE_INSERT_TAIL(b, e);
+            return APR_SUCCESS;
+        }
+    }
+    else if (!buf) {
+        /* we don't have a buffer, but the data is small enough
+         * that we don't mind making a new buffer */
+        buf = apr_bucket_alloc(APR_BUCKET_BUFF_SIZE, b->bucket_alloc);
+        e = apr_bucket_heap_create(buf, APR_BUCKET_BUFF_SIZE,
+                                   apr_bucket_free, b->bucket_alloc);
+        APR_BRIGADE_INSERT_TAIL(b, e);
+        e->length = 0;   /* We are writing into the brigade, and
+                          * allocating more memory than we need.  This
+                          * ensures that the bucket thinks it is empty just
+                          * after we create it.  We'll fix the length
+                          * once we put data in it below.
+                          */
+    }
+
+    /* there is a sufficiently big buffer bucket available now */
+    memcpy(buf, str, nbyte);
+    e->length += nbyte;
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_brigade_writev(apr_bucket_brigade *b,
+                                             apr_brigade_flush flush,
+                                             void *ctx,
+                                             const struct iovec *vec,
+                                             apr_size_t nvec)
+{
+    apr_bucket *e;
+    apr_size_t total_len;
+    apr_size_t i;
+    char *buf;
+
+    /* Compute the total length of the data to be written.
+     */
+    total_len = 0;
+    for (i = 0; i < nvec; i++) {
+       total_len += vec[i].iov_len;
+    }
+
+    /* If the data to be written is very large, try to convert
+     * the iovec to transient buckets rather than copying.
+     */
+    if (total_len > APR_BUCKET_BUFF_SIZE) {
+        if (flush) {
+            for (i = 0; i < nvec; i++) {
+                e = apr_bucket_transient_create(vec[i].iov_base,
+                                                vec[i].iov_len,
+                                                b->bucket_alloc);
+                APR_BRIGADE_INSERT_TAIL(b, e);
+            }
+            return flush(b, ctx);
+        }
+        else {
+            for (i = 0; i < nvec; i++) {
+                e = apr_bucket_heap_create((const char *) vec[i].iov_base,
+                                           vec[i].iov_len, NULL,
+                                           b->bucket_alloc);
+                APR_BRIGADE_INSERT_TAIL(b, e);
+            }
+            return APR_SUCCESS;
+        }
+    }
+
+    i = 0;
+
+    /* If there is a heap bucket at the end of the brigade
+     * already, and its refcount is 1, copy into the existing bucket.
+     */
+    e = APR_BRIGADE_LAST(b);
+    if (!APR_BRIGADE_EMPTY(b) && APR_BUCKET_IS_HEAP(e)
+        && ((apr_bucket_heap *)(e->data))->refcount.refcount == 1) {
+        apr_bucket_heap *h = e->data;
+        apr_size_t remaining = h->alloc_len -
+            (e->length + (apr_size_t)e->start);
+        buf = h->base + e->start + e->length;
+
+        if (remaining >= total_len) {
+            /* Simple case: all the data will fit in the
+             * existing heap bucket
+             */
+            for (; i < nvec; i++) {
+                apr_size_t len = vec[i].iov_len;
+                memcpy(buf, (const void *) vec[i].iov_base, len);
+                buf += len;
+            }
+            e->length += total_len;
+            return APR_SUCCESS;
+        }
+        else {
+            /* More complicated case: not all of the data
+             * will fit in the existing heap bucket.  The
+             * total data size is <= APR_BUCKET_BUFF_SIZE,
+             * so we'll need only one additional bucket.
+             */
+            const char *start_buf = buf;
+            for (; i < nvec; i++) {
+                apr_size_t len = vec[i].iov_len;
+                if (len > remaining) {
+                    break;
+                }
+                memcpy(buf, (const void *) vec[i].iov_base, len);
+                buf += len;
+                remaining -= len;
+            }
+            e->length += (buf - start_buf);
+            total_len -= (buf - start_buf);
+
+            if (flush) {
+                apr_status_t rv = flush(b, ctx);
+                if (rv != APR_SUCCESS) {
+                    return rv;
+                }
+            }
+
+            /* Now fall through into the case below to
+             * allocate another heap bucket and copy the
+             * rest of the array.  (Note that i is not
+             * reset to zero here; it holds the index
+             * of the first vector element to be
+             * written to the new bucket.)
+             */
+        }
+    }
+
+    /* Allocate a new heap bucket, and copy the data into it.
+     * The checks above ensure that the amount of data to be
+     * written here is no larger than APR_BUCKET_BUFF_SIZE.
+     */
+    buf = apr_bucket_alloc(APR_BUCKET_BUFF_SIZE, b->bucket_alloc);
+    e = apr_bucket_heap_create(buf, APR_BUCKET_BUFF_SIZE,
+                               apr_bucket_free, b->bucket_alloc);
+    for (; i < nvec; i++) {
+        apr_size_t len = vec[i].iov_len;
+        memcpy(buf, (const void *) vec[i].iov_base, len);
+        buf += len;
+    }
+    e->length = total_len;
+    APR_BRIGADE_INSERT_TAIL(b, e);
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_brigade_puts(apr_bucket_brigade *bb,
+                                           apr_brigade_flush flush, void *ctx,
+                                           const char *str)
+{
+    return apr_brigade_write(bb, flush, ctx, str, strlen(str));
+}
+
+APR_DECLARE_NONSTD(apr_status_t) apr_brigade_putstrs(apr_bucket_brigade *b, 
+                                                     apr_brigade_flush flush,
+                                                     void *ctx, ...)
+{
+    va_list va;
+    apr_status_t rv;
+
+    va_start(va, ctx);
+    rv = apr_brigade_vputstrs(b, flush, ctx, va);
+    va_end(va);
+    return rv;
+}
+
+APR_DECLARE_NONSTD(apr_status_t) apr_brigade_printf(apr_bucket_brigade *b, 
+                                                    apr_brigade_flush flush,
+                                                    void *ctx, 
+                                                    const char *fmt, ...)
+{
+    va_list ap;
+    apr_status_t rv;
+
+    va_start(ap, fmt);
+    rv = apr_brigade_vprintf(b, flush, ctx, fmt, ap);
+    va_end(ap);
+    return rv;
+}
+
+struct brigade_vprintf_data_t {
+    apr_vformatter_buff_t vbuff;
+
+    apr_bucket_brigade *b;  /* associated brigade */
+    apr_brigade_flush *flusher; /* flushing function */
+    void *ctx;
+
+    char *cbuff; /* buffer to flush from */
+};
+
+static apr_status_t brigade_flush(apr_vformatter_buff_t *buff)
+{
+    /* callback function passed to ap_vformatter to be
+     * called when vformatter needs to buff and
+     * buff.curpos > buff.endpos
+     */
+
+    /* "downcast," have really passed a brigade_vprintf_data_t* */
+    struct brigade_vprintf_data_t *vd = (struct brigade_vprintf_data_t*)buff;
+    apr_status_t res = APR_SUCCESS;
+
+    res = apr_brigade_write(vd->b, *vd->flusher, vd->ctx, vd->cbuff,
+                          APR_BUCKET_BUFF_SIZE);
+
+    if(res != APR_SUCCESS) {
+      return -1;
+    }
+
+    vd->vbuff.curpos = vd->cbuff;
+    vd->vbuff.endpos = vd->cbuff + APR_BUCKET_BUFF_SIZE;
+
+    return res;
+}
+
+APR_DECLARE(apr_status_t) apr_brigade_vprintf(apr_bucket_brigade *b,
+                                              apr_brigade_flush flush,
+                                              void *ctx,
+                                              const char *fmt, va_list va)
+{
+    /* the cast, in order of appearance */
+    struct brigade_vprintf_data_t vd;
+    char buf[APR_BUCKET_BUFF_SIZE];
+    int written;
+
+    vd.vbuff.curpos = buf;
+    vd.vbuff.endpos = buf + APR_BUCKET_BUFF_SIZE;
+    vd.b = b;
+    vd.flusher = &flush;
+    vd.ctx = ctx;
+    vd.cbuff = buf;
+
+    written = apr_vformatter(brigade_flush, &vd.vbuff, fmt, va);
+
+    if (written == -1) {
+      return -1;
+    }
+
+    /* write out what remains in the buffer */
+    return apr_brigade_write(b, flush, ctx, buf, vd.vbuff.curpos - buf);
+}
+
+/* A "safe" maximum bucket size, 1Gb */
+#define MAX_BUCKET_SIZE (0x40000000)
+
+APR_DECLARE(apr_bucket *) apr_brigade_insert_file(apr_bucket_brigade *bb,
+                                                  apr_file_t *f,
+                                                  apr_off_t start,
+                                                  apr_off_t length,
+                                                  apr_pool_t *p)
+{
+    apr_bucket *e;
+
+    if (sizeof(apr_off_t) == sizeof(apr_size_t) || length < MAX_BUCKET_SIZE) {
+        e = apr_bucket_file_create(f, start, (apr_size_t)length, p, 
+                                   bb->bucket_alloc);
+    }
+    else {
+        /* Several buckets are needed. */        
+        e = apr_bucket_file_create(f, start, MAX_BUCKET_SIZE, p, 
+                                   bb->bucket_alloc);
+
+        while (length > MAX_BUCKET_SIZE) {
+            apr_bucket *ce;
+            apr_bucket_copy(e, &ce);
+            APR_BRIGADE_INSERT_TAIL(bb, ce);
+            e->start += MAX_BUCKET_SIZE;
+            length -= MAX_BUCKET_SIZE;
+        }
+        e->length = (apr_size_t)length; /* Resize just the last bucket */
+    }
+    
+    APR_BRIGADE_INSERT_TAIL(bb, e);
+    return e;
+}
diff --git a/buckets/apr_buckets.c b/buckets/apr_buckets.c
new file mode 100644
index 00000000000..0c2caa3755b
--- /dev/null
+++ b/buckets/apr_buckets.c
@@ -0,0 +1,46 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_buckets.h"
+
+APR_DECLARE_NONSTD(apr_status_t) apr_bucket_setaside_noop(apr_bucket *data,
+                                                          apr_pool_t *pool)
+{
+    return APR_SUCCESS;
+}
+
+APR_DECLARE_NONSTD(apr_status_t) apr_bucket_setaside_notimpl(apr_bucket *data,
+                                                             apr_pool_t *pool)
+{
+    return APR_ENOTIMPL;
+}
+
+APR_DECLARE_NONSTD(apr_status_t) apr_bucket_split_notimpl(apr_bucket *data,
+                                                          apr_size_t point)
+{
+    return APR_ENOTIMPL;
+}
+
+APR_DECLARE_NONSTD(apr_status_t) apr_bucket_copy_notimpl(apr_bucket *e,
+                                                         apr_bucket **c)
+{
+    return APR_ENOTIMPL;
+}
+
+APR_DECLARE_NONSTD(void) apr_bucket_destroy_noop(void *data)
+{
+    return;
+}
diff --git a/buckets/apr_buckets_alloc.c b/buckets/apr_buckets_alloc.c
new file mode 100644
index 00000000000..a2a25d42628
--- /dev/null
+++ b/buckets/apr_buckets_alloc.c
@@ -0,0 +1,240 @@
+/* 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 <stdlib.h>
+
+#include "apr_buckets.h"
+#include "apr_allocator.h"
+#include "apr_support.h"
+
+#define ALLOC_AMT (8192 - APR_MEMNODE_T_SIZE)
+
+typedef struct node_header_t {
+    apr_size_t size;
+    apr_bucket_alloc_t *alloc;
+    apr_memnode_t *memnode;
+    struct node_header_t *next;
+} node_header_t;
+
+#define SIZEOF_NODE_HEADER_T  APR_ALIGN_DEFAULT(sizeof(node_header_t))
+#define SMALL_NODE_SIZE       (APR_BUCKET_ALLOC_SIZE + SIZEOF_NODE_HEADER_T)
+
+/** A list of free memory from which new buckets or private bucket
+ *  structures can be allocated.
+ */
+struct apr_bucket_alloc_t {
+    apr_pool_t *pool;
+    apr_allocator_t *allocator;
+    node_header_t *freelist;
+    apr_memnode_t *blocks;
+};
+
+static apr_status_t alloc_cleanup(void *data)
+{
+    apr_bucket_alloc_t *list = data;
+#if APR_POOL_DEBUG
+    apr_allocator_t *allocator = NULL;
+#endif
+
+#if APR_POOL_DEBUG
+    if (list->pool && list->allocator != apr_pool_allocator_get(list->pool)) {
+        allocator = list->allocator;
+    }
+#endif
+
+    apr_allocator_free(list->allocator, list->blocks);
+
+#if APR_POOL_DEBUG
+    if (allocator) {
+        apr_allocator_destroy(allocator);
+    }
+#endif
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE_NONSTD(apr_bucket_alloc_t *) apr_bucket_alloc_create(apr_pool_t *p)
+{
+    apr_allocator_t *allocator = apr_pool_allocator_get(p);
+    apr_bucket_alloc_t *list;
+
+#if APR_POOL_DEBUG
+    /* may be NULL for debug mode. */
+    if (allocator == NULL) {
+        if (apr_allocator_create(&allocator) != APR_SUCCESS) {
+            apr_abortfunc_t fn = apr_pool_abort_get(p);
+            if (fn)
+                (fn)(APR_ENOMEM);
+            abort();
+        }
+    }
+#endif
+    list = apr_bucket_alloc_create_ex(allocator);
+    if (list == NULL) {
+            apr_abortfunc_t fn = apr_pool_abort_get(p);
+            if (fn)
+                (fn)(APR_ENOMEM);
+            abort();
+    }
+    list->pool = p;
+    apr_pool_cleanup_register(list->pool, list, alloc_cleanup,
+                              apr_pool_cleanup_null);
+
+    return list;
+}
+
+APR_DECLARE_NONSTD(apr_bucket_alloc_t *) apr_bucket_alloc_create_ex(
+                                             apr_allocator_t *allocator)
+{
+    apr_bucket_alloc_t *list;
+    apr_memnode_t *block;
+
+    block = apr_allocator_alloc(allocator, ALLOC_AMT);
+    if (!block) {
+        return NULL;
+    }
+    list = (apr_bucket_alloc_t *)block->first_avail;
+    list->pool = NULL;
+    list->allocator = allocator;
+    list->freelist = NULL;
+    list->blocks = block;
+    block->first_avail += APR_ALIGN_DEFAULT(sizeof(*list));
+    APR_VALGRIND_NOACCESS(block->first_avail,
+                          block->endp - block->first_avail);
+    return list;
+}
+
+APR_DECLARE_NONSTD(void) apr_bucket_alloc_destroy(apr_bucket_alloc_t *list)
+{
+    if (list->pool) {
+        apr_pool_cleanup_kill(list->pool, list, alloc_cleanup);
+    }
+
+    apr_allocator_free(list->allocator, list->blocks);
+
+#if APR_POOL_DEBUG
+    if (list->pool && list->allocator != apr_pool_allocator_get(list->pool)) {
+        apr_allocator_destroy(list->allocator);
+    }
+#endif
+}
+
+APR_DECLARE_NONSTD(apr_size_t) apr_bucket_alloc_aligned_floor(apr_bucket_alloc_t *list,
+                                                              apr_size_t size)
+{
+    if (size <= SMALL_NODE_SIZE) {
+        size = SMALL_NODE_SIZE;
+    }
+    else {
+        if (size < APR_MEMNODE_T_SIZE) {
+            size = apr_allocator_align(list->allocator, 0);
+        }
+        else {
+            size = apr_allocator_align(list->allocator,
+                                       size - APR_MEMNODE_T_SIZE);
+        }
+        size -= APR_MEMNODE_T_SIZE;
+    }
+    size -= SIZEOF_NODE_HEADER_T;
+    return size;
+}
+
+APR_DECLARE_NONSTD(void *) apr_bucket_alloc(apr_size_t in_size,
+                                            apr_bucket_alloc_t *list)
+{
+    node_header_t *node;
+    apr_memnode_t *active = list->blocks;
+    char *endp;
+    apr_size_t size;
+
+    size = in_size + SIZEOF_NODE_HEADER_T;
+    if (size <= SMALL_NODE_SIZE) {
+        if (list->freelist) {
+            node = list->freelist;
+            list->freelist = node->next;
+            APR_VALGRIND_UNDEFINED((char *)node + SIZEOF_NODE_HEADER_T,
+                                   SMALL_NODE_SIZE - SIZEOF_NODE_HEADER_T);
+        }
+        else {
+            endp = active->first_avail + SMALL_NODE_SIZE;
+            if (endp >= active->endp) {
+                list->blocks = apr_allocator_alloc(list->allocator, ALLOC_AMT);
+                if (!list->blocks) {
+                    list->blocks = active;
+                    return NULL;
+                }
+                list->blocks->next = active;
+                active = list->blocks;
+                endp = active->first_avail + SMALL_NODE_SIZE;
+                APR_VALGRIND_NOACCESS(active->first_avail,
+                                      active->endp - active->first_avail);
+            }
+            node = (node_header_t *)active->first_avail;
+            APR_VALGRIND_UNDEFINED(node, SMALL_NODE_SIZE);
+            node->alloc = list;
+            node->memnode = active;
+            node->size = SMALL_NODE_SIZE;
+            active->first_avail = endp;
+        }
+    }
+    else {
+        apr_memnode_t *memnode = apr_allocator_alloc(list->allocator, size);
+        if (!memnode) {
+            return NULL;
+        }
+        node = (node_header_t *)memnode->first_avail;
+        node->alloc = list;
+        node->memnode = memnode;
+        node->size = size;
+    }
+    return ((char *)node) + SIZEOF_NODE_HEADER_T;
+}
+
+#ifdef APR_BUCKET_DEBUG
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+static void check_not_already_free(node_header_t *node)
+{
+    apr_bucket_alloc_t *list = node->alloc;
+    node_header_t *curr = list->freelist;
+
+    while (curr) {
+        if (node == curr) {
+            abort();
+        }
+        curr = curr->next;
+    }
+}
+#else
+#define check_not_already_free(node)
+#endif
+
+APR_DECLARE_NONSTD(void) apr_bucket_free(void *mem)
+{
+    node_header_t *node = (node_header_t *)((char *)mem - SIZEOF_NODE_HEADER_T);
+    apr_bucket_alloc_t *list = node->alloc;
+
+    if (node->size == SMALL_NODE_SIZE) {
+        check_not_already_free(node);
+        node->next = list->freelist;
+        list->freelist = node;
+        APR_VALGRIND_NOACCESS(mem, SMALL_NODE_SIZE - SIZEOF_NODE_HEADER_T);
+    }
+    else {
+        apr_allocator_free(list->allocator, node->memnode);
+    }
+}
diff --git a/buckets/apr_buckets_eos.c b/buckets/apr_buckets_eos.c
new file mode 100644
index 00000000000..446cd3c23c1
--- /dev/null
+++ b/buckets/apr_buckets_eos.c
@@ -0,0 +1,54 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_buckets.h"
+
+static apr_status_t eos_bucket_read(apr_bucket *b, const char **str, 
+                                    apr_size_t *len, apr_read_type_e block)
+{
+    *str = NULL;
+    *len = 0;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_bucket *) apr_bucket_eos_make(apr_bucket *b)
+{
+    b->length      = 0;
+    b->start       = 0;
+    b->data        = NULL;
+    b->type        = &apr_bucket_type_eos;
+    
+    return b;
+}
+
+APR_DECLARE(apr_bucket *) apr_bucket_eos_create(apr_bucket_alloc_t *list)
+{
+    apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
+
+    APR_BUCKET_INIT(b);
+    b->free = apr_bucket_free;
+    b->list = list;
+    return apr_bucket_eos_make(b);
+}
+
+APR_DECLARE_DATA const apr_bucket_type_t apr_bucket_type_eos = {
+    "EOS", 5, APR_BUCKET_METADATA,
+    apr_bucket_destroy_noop,
+    eos_bucket_read,
+    apr_bucket_setaside_noop,
+    apr_bucket_split_notimpl,
+    apr_bucket_simple_copy
+};
diff --git a/buckets/apr_buckets_file.c b/buckets/apr_buckets_file.c
new file mode 100644
index 00000000000..82bb2d1721e
--- /dev/null
+++ b/buckets/apr_buckets_file.c
@@ -0,0 +1,242 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_general.h"
+#include "apr_file_io.h"
+#include "apr_buckets.h"
+
+#if APR_HAS_MMAP
+#include "apr_mmap.h"
+
+/* mmap support for static files based on ideas from John Heidemann's
+ * patch against 1.0.5.  See
+ * <http://www.isi.edu/~johnh/SOFTWARE/APACHE/index.html>.
+ */
+
+#endif /* APR_HAS_MMAP */
+
+static void file_bucket_destroy(void *data)
+{
+    apr_bucket_file *f = data;
+
+    if (apr_bucket_shared_destroy(f)) {
+        /* no need to close the file here; it will get
+         * done automatically when the pool gets cleaned up */
+        apr_bucket_free(f);
+    }
+}
+
+#if APR_HAS_MMAP
+static int file_make_mmap(apr_bucket *e, apr_size_t filelength,
+                           apr_off_t fileoffset, apr_pool_t *p)
+{
+    apr_bucket_file *a = e->data;
+    apr_mmap_t *mm;
+
+    if (!a->can_mmap) {
+        return 0;
+    }
+
+    if (filelength > APR_MMAP_LIMIT) {
+        if (apr_mmap_create(&mm, a->fd, fileoffset, APR_MMAP_LIMIT,
+                            APR_MMAP_READ, p) != APR_SUCCESS)
+        {
+            return 0;
+        }
+        apr_bucket_split(e, APR_MMAP_LIMIT);
+        filelength = APR_MMAP_LIMIT;
+    }
+    else if ((filelength < APR_MMAP_THRESHOLD) ||
+             (apr_mmap_create(&mm, a->fd, fileoffset, filelength,
+                              APR_MMAP_READ, p) != APR_SUCCESS))
+    {
+        return 0;
+    }
+    apr_bucket_mmap_make(e, mm, 0, filelength);
+    file_bucket_destroy(a);
+    return 1;
+}
+#endif
+
+static apr_status_t file_bucket_read(apr_bucket *e, const char **str,
+                                     apr_size_t *len, apr_read_type_e block)
+{
+    apr_bucket_file *a = e->data;
+    apr_file_t *f = a->fd;
+    apr_bucket *b = NULL;
+    char *buf;
+    apr_status_t rv;
+    apr_size_t filelength = e->length;  /* bytes remaining in file past offset */
+    apr_off_t fileoffset = e->start;
+#if APR_HAS_THREADS && !APR_HAS_XTHREAD_FILES
+    apr_int32_t flags;
+#endif
+
+#if APR_HAS_MMAP
+    if (file_make_mmap(e, filelength, fileoffset, a->readpool)) {
+        return apr_bucket_read(e, str, len, block);
+    }
+#endif
+
+#if APR_HAS_THREADS && !APR_HAS_XTHREAD_FILES
+    if ((flags = apr_file_flags_get(f)) & APR_FOPEN_XTHREAD) {
+        /* this file descriptor is shared across multiple threads and
+         * this OS doesn't support that natively, so as a workaround
+         * we must reopen the file into a->readpool */
+        const char *fname;
+        apr_file_name_get(&fname, f);
+
+        rv = apr_file_open(&f, fname, (flags & ~APR_FOPEN_XTHREAD), 0, a->readpool);
+        if (rv != APR_SUCCESS)
+            return rv;
+
+        a->fd = f;
+    }
+#endif
+
+    *str = NULL;  /* in case we die prematurely */
+    *len = (filelength > a->read_size) ? a->read_size : filelength;
+    buf = apr_bucket_alloc(*len, e->list);
+
+    /* Handle offset ... */
+    rv = apr_file_seek(f, APR_SET, &fileoffset);
+    if (rv != APR_SUCCESS) {
+        apr_bucket_free(buf);
+        return rv;
+    }
+    rv = apr_file_read(f, buf, len);
+    if (rv != APR_SUCCESS && rv != APR_EOF) {
+        apr_bucket_free(buf);
+        return rv;
+    }
+    filelength -= *len;
+    /*
+     * Change the current bucket to refer to what we read,
+     * even if we read nothing because we hit EOF.
+     */
+    apr_bucket_heap_make(e, buf, *len, apr_bucket_free);
+
+    /* If we have more to read from the file, then create another bucket */
+    if (filelength > 0 && rv != APR_EOF) {
+        /* for efficiency, we can just build a new apr_bucket struct
+         * to wrap around the existing file bucket */
+        b = apr_bucket_alloc(sizeof(*b), e->list);
+        b->start  = fileoffset + (*len);
+        b->length = filelength;
+        b->data   = a;
+        b->type   = &apr_bucket_type_file;
+        b->free   = apr_bucket_free;
+        b->list   = e->list;
+        APR_BUCKET_INSERT_AFTER(e, b);
+    }
+    else {
+        file_bucket_destroy(a);
+    }
+
+    *str = buf;
+    return rv;
+}
+
+APR_DECLARE(apr_bucket *) apr_bucket_file_make(apr_bucket *b, apr_file_t *fd,
+                                               apr_off_t offset,
+                                               apr_size_t len, apr_pool_t *p)
+{
+    apr_bucket_file *f;
+
+    f = apr_bucket_alloc(sizeof(*f), b->list);
+    f->fd = fd;
+    f->readpool = p;
+#if APR_HAS_MMAP
+    f->can_mmap = 1;
+#endif
+    f->read_size = APR_BUCKET_BUFF_SIZE;
+
+    b = apr_bucket_shared_make(b, f, offset, len);
+    b->type = &apr_bucket_type_file;
+
+    return b;
+}
+
+APR_DECLARE(apr_bucket *) apr_bucket_file_create(apr_file_t *fd,
+                                                 apr_off_t offset,
+                                                 apr_size_t len, apr_pool_t *p,
+                                                 apr_bucket_alloc_t *list)
+{
+    apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
+
+    APR_BUCKET_INIT(b);
+    b->free = apr_bucket_free;
+    b->list = list;
+    return apr_bucket_file_make(b, fd, offset, len, p);
+}
+
+APR_DECLARE(apr_status_t) apr_bucket_file_enable_mmap(apr_bucket *e,
+                                                      int enabled)
+{
+#if APR_HAS_MMAP
+    apr_bucket_file *a = e->data;
+    a->can_mmap = enabled;
+    return APR_SUCCESS;
+#else
+    return APR_ENOTIMPL;
+#endif /* APR_HAS_MMAP */
+}
+
+APR_DECLARE(apr_status_t) apr_bucket_file_set_buf_size(apr_bucket *e,
+                                                       apr_size_t size)
+{
+    apr_bucket_file *a = e->data;
+
+    if (size <= APR_BUCKET_BUFF_SIZE) {
+        a->read_size = APR_BUCKET_BUFF_SIZE;
+    }
+    else {
+        apr_size_t floor = apr_bucket_alloc_aligned_floor(e->list, size);
+        a->read_size = (size < floor) ? size : floor;
+    }
+
+    return APR_SUCCESS;
+}
+
+static apr_status_t file_bucket_setaside(apr_bucket *data, apr_pool_t *reqpool)
+{
+    apr_bucket_file *a = data->data;
+    apr_file_t *fd = NULL;
+    apr_file_t *f = a->fd;
+    apr_pool_t *curpool = apr_file_pool_get(f);
+
+    if (apr_pool_is_ancestor(curpool, reqpool)) {
+        return APR_SUCCESS;
+    }
+
+    if (!apr_pool_is_ancestor(a->readpool, reqpool)) {
+        a->readpool = reqpool;
+    }
+
+    apr_file_setaside(&fd, f, reqpool);
+    a->fd = fd;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE_DATA const apr_bucket_type_t apr_bucket_type_file = {
+    "FILE", 5, APR_BUCKET_DATA,
+    file_bucket_destroy,
+    file_bucket_read,
+    file_bucket_setaside,
+    apr_bucket_shared_split,
+    apr_bucket_shared_copy
+};
diff --git a/buckets/apr_buckets_flush.c b/buckets/apr_buckets_flush.c
new file mode 100644
index 00000000000..dbb4fb9ba04
--- /dev/null
+++ b/buckets/apr_buckets_flush.c
@@ -0,0 +1,54 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_buckets.h"
+
+static apr_status_t flush_bucket_read(apr_bucket *b, const char **str, 
+                                      apr_size_t *len, apr_read_type_e block)
+{
+    *str = NULL;
+    *len = 0;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_bucket *) apr_bucket_flush_make(apr_bucket *b)
+{
+    b->length      = 0;
+    b->start       = 0;
+    b->data        = NULL;
+    b->type        = &apr_bucket_type_flush;
+    
+    return b;
+}
+
+APR_DECLARE(apr_bucket *) apr_bucket_flush_create(apr_bucket_alloc_t *list)
+{
+    apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
+
+    APR_BUCKET_INIT(b);
+    b->free = apr_bucket_free;
+    b->list = list;
+    return apr_bucket_flush_make(b);
+}
+
+APR_DECLARE_DATA const apr_bucket_type_t apr_bucket_type_flush = {
+    "FLUSH", 5, APR_BUCKET_METADATA, 
+    apr_bucket_destroy_noop,
+    flush_bucket_read,
+    apr_bucket_setaside_noop,
+    apr_bucket_split_notimpl,
+    apr_bucket_simple_copy
+};
diff --git a/buckets/apr_buckets_heap.c b/buckets/apr_buckets_heap.c
new file mode 100644
index 00000000000..7405d2caffc
--- /dev/null
+++ b/buckets/apr_buckets_heap.c
@@ -0,0 +1,96 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_buckets.h"
+#define APR_WANT_MEMFUNC
+#include "apr_want.h"
+
+static apr_status_t heap_bucket_read(apr_bucket *b, const char **str, 
+                                     apr_size_t *len, apr_read_type_e block)
+{
+    apr_bucket_heap *h = b->data;
+
+    *str = h->base + b->start;
+    *len = b->length;
+    return APR_SUCCESS;
+}
+
+static void heap_bucket_destroy(void *data)
+{
+    apr_bucket_heap *h = data;
+
+    if (apr_bucket_shared_destroy(h)) {
+        (*h->free_func)(h->base);
+        apr_bucket_free(h);
+    }
+}
+
+/* Warning: if you change this function, be sure to
+ * change apr_bucket_pool_make() too! */
+APR_DECLARE(apr_bucket *) apr_bucket_heap_make(apr_bucket *b, const char *buf,
+                                               apr_size_t length,
+                                               void (*free_func)(void *data))
+{
+    apr_bucket_heap *h;
+
+    h = apr_bucket_alloc(sizeof(*h), b->list);
+
+    if (!free_func) {
+        h->alloc_len = length;
+        h->base = apr_bucket_alloc(h->alloc_len, b->list);
+        if (h->base == NULL) {
+            apr_bucket_free(h);
+            return NULL;
+        }
+        h->free_func = apr_bucket_free;
+        memcpy(h->base, buf, length);
+    }
+    else {
+        /* XXX: we lose the const qualifier here which indicates
+         * there's something screwy with the API...
+         */
+        h->base = (char *) buf;
+        h->alloc_len = length;
+        h->free_func = free_func;
+    }
+
+    b = apr_bucket_shared_make(b, h, 0, length);
+    b->type = &apr_bucket_type_heap;
+
+    return b;
+}
+
+APR_DECLARE(apr_bucket *) apr_bucket_heap_create(const char *buf,
+                                                 apr_size_t length,
+                                                 void (*free_func)(void *data),
+                                                 apr_bucket_alloc_t *list)
+{
+    apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
+
+    APR_BUCKET_INIT(b);
+    b->free = apr_bucket_free;
+    b->list = list;
+    return apr_bucket_heap_make(b, buf, length, free_func);
+}
+
+APR_DECLARE_DATA const apr_bucket_type_t apr_bucket_type_heap = {
+    "HEAP", 5, APR_BUCKET_DATA,
+    heap_bucket_destroy,
+    heap_bucket_read,
+    apr_bucket_setaside_noop,
+    apr_bucket_shared_split,
+    apr_bucket_shared_copy
+};
diff --git a/buckets/apr_buckets_mmap.c b/buckets/apr_buckets_mmap.c
new file mode 100644
index 00000000000..116b7886811
--- /dev/null
+++ b/buckets/apr_buckets_mmap.c
@@ -0,0 +1,144 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_buckets.h"
+
+#if APR_HAS_MMAP
+
+static apr_status_t mmap_bucket_read(apr_bucket *b, const char **str, 
+                                     apr_size_t *length, apr_read_type_e block)
+{
+    apr_bucket_mmap *m = b->data;
+    apr_status_t ok;
+    void *addr;
+   
+    if (!m->mmap) {
+        /* the apr_mmap_t was already cleaned up out from under us */
+        return APR_EINVAL;
+    }
+
+    ok = apr_mmap_offset(&addr, m->mmap, b->start);
+    if (ok != APR_SUCCESS) {
+        return ok;
+    }
+    *str = addr;
+    *length = b->length;
+    return APR_SUCCESS;
+}
+
+static apr_status_t mmap_bucket_cleanup(void *data)
+{
+    /* the apr_mmap_t is about to disappear out from under us, so we
+     * have no choice but to pretend it doesn't exist anymore.  the
+     * refcount is now useless because there's nothing to refer to
+     * anymore.  so the only valid action on any remaining referrer
+     * is to delete it.  no more reads, no more anything. */
+    apr_bucket_mmap *m = data;
+
+    m->mmap = NULL;
+    return APR_SUCCESS;
+}
+
+static void mmap_bucket_destroy(void *data)
+{
+    apr_bucket_mmap *m = data;
+
+    if (apr_bucket_shared_destroy(m)) {
+        if (m->mmap) {
+            apr_pool_cleanup_kill(m->mmap->cntxt, m, mmap_bucket_cleanup);
+            apr_mmap_delete(m->mmap);
+        }
+        apr_bucket_free(m);
+    }
+}
+
+/*
+ * XXX: are the start and length arguments useful?
+ */
+APR_DECLARE(apr_bucket *) apr_bucket_mmap_make(apr_bucket *b, apr_mmap_t *mm, 
+                                               apr_off_t start, 
+                                               apr_size_t length)
+{
+    apr_bucket_mmap *m;
+
+    m = apr_bucket_alloc(sizeof(*m), b->list);
+    m->mmap = mm;
+
+    apr_pool_cleanup_register(mm->cntxt, m, mmap_bucket_cleanup,
+                              apr_pool_cleanup_null);
+
+    b = apr_bucket_shared_make(b, m, start, length);
+    b->type = &apr_bucket_type_mmap;
+
+    return b;
+}
+
+
+APR_DECLARE(apr_bucket *) apr_bucket_mmap_create(apr_mmap_t *mm, 
+                                                 apr_off_t start, 
+                                                 apr_size_t length,
+                                                 apr_bucket_alloc_t *list)
+{
+    apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
+
+    APR_BUCKET_INIT(b);
+    b->free = apr_bucket_free;
+    b->list = list;
+    return apr_bucket_mmap_make(b, mm, start, length);
+}
+
+static apr_status_t mmap_bucket_setaside(apr_bucket *b, apr_pool_t *p)
+{
+    apr_bucket_mmap *m = b->data;
+    apr_mmap_t *mm = m->mmap;
+    apr_mmap_t *new_mm;
+    apr_status_t ok;
+
+    if (!mm) {
+        /* the apr_mmap_t was already cleaned up out from under us */
+        return APR_EINVAL;
+    }
+
+    /* shortcut if possible */
+    if (apr_pool_is_ancestor(mm->cntxt, p)) {
+        return APR_SUCCESS;
+    }
+
+    /* duplicate apr_mmap_t into new pool */
+    ok = apr_mmap_dup(&new_mm, mm, p);
+    if (ok != APR_SUCCESS) {
+        return ok;
+    }
+
+    /* decrement refcount on old apr_bucket_mmap */
+    mmap_bucket_destroy(m);
+
+    /* create new apr_bucket_mmap pointing to new apr_mmap_t */
+    apr_bucket_mmap_make(b, new_mm, b->start, b->length);
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE_DATA const apr_bucket_type_t apr_bucket_type_mmap = {
+    "MMAP", 5, APR_BUCKET_DATA,
+    mmap_bucket_destroy,
+    mmap_bucket_read,
+    mmap_bucket_setaside,
+    apr_bucket_shared_split,
+    apr_bucket_shared_copy
+};
+
+#endif
diff --git a/buckets/apr_buckets_pipe.c b/buckets/apr_buckets_pipe.c
new file mode 100644
index 00000000000..574610b02d7
--- /dev/null
+++ b/buckets/apr_buckets_pipe.c
@@ -0,0 +1,119 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_buckets.h"
+
+static apr_status_t pipe_bucket_read(apr_bucket *a, const char **str,
+                                     apr_size_t *len, apr_read_type_e block)
+{
+    apr_file_t *p = a->data;
+    char *buf;
+    apr_status_t rv;
+    apr_interval_time_t timeout;
+
+    if (block == APR_NONBLOCK_READ) {
+        apr_file_pipe_timeout_get(p, &timeout);
+        apr_file_pipe_timeout_set(p, 0);
+    }
+
+    *str = NULL;
+    *len = APR_BUCKET_BUFF_SIZE;
+    buf = apr_bucket_alloc(*len, a->list); /* XXX: check for failure? */
+
+    rv = apr_file_read(p, buf, len);
+
+    if (block == APR_NONBLOCK_READ) {
+        apr_file_pipe_timeout_set(p, timeout);
+    }
+
+    if (rv != APR_SUCCESS && rv != APR_EOF) {
+        apr_bucket_free(buf);
+        return rv;
+    }
+    /*
+     * If there's more to read we have to keep the rest of the pipe
+     * for later.  Otherwise, we'll close the pipe.
+     * XXX: Note that more complicated bucket types that 
+     * refer to data not in memory and must therefore have a read()
+     * function similar to this one should be wary of copying this
+     * code because if they have a destroy function they probably
+     * want to migrate the bucket's subordinate structure from the
+     * old bucket to a raw new one and adjust it as appropriate,
+     * rather than destroying the old one and creating a completely
+     * new bucket.
+     */
+    if (*len > 0) {
+        apr_bucket_heap *h;
+        /* Change the current bucket to refer to what we read */
+        a = apr_bucket_heap_make(a, buf, *len, apr_bucket_free);
+        h = a->data;
+        h->alloc_len = APR_BUCKET_BUFF_SIZE; /* note the real buffer size */
+        *str = buf;
+        APR_BUCKET_INSERT_AFTER(a, apr_bucket_pipe_create(p, a->list));
+    }
+    else {
+        apr_bucket_free(buf);
+        a = apr_bucket_immortal_make(a, "", 0);
+        *str = a->data;
+        if (rv == APR_EOF) {
+            apr_file_close(p);
+        }
+    }
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_bucket *) apr_bucket_pipe_make(apr_bucket *b, apr_file_t *p)
+{
+    /*
+     * A pipe is closed when the end is reached in pipe_bucket_read().  If
+     * the pipe isn't read to the end (e.g., error path), the pipe will be
+     * closed when its pool goes away.
+     *
+     * Note that typically the pipe is allocated from the request pool
+     * so it will disappear when the request is finished. However the
+     * core filter may decide to set aside the tail end of a CGI
+     * response if the connection is pipelined. This turns out not to
+     * be a problem because the core will have read to the end of the
+     * stream so the bucket(s) that it sets aside will be the heap
+     * buckets created by pipe_bucket_read() above.
+     */
+    b->type        = &apr_bucket_type_pipe;
+    b->length      = (apr_size_t)(-1);
+    b->start       = -1;
+    b->data        = p;
+    
+    return b;
+}
+
+APR_DECLARE(apr_bucket *) apr_bucket_pipe_create(apr_file_t *p,
+                                                 apr_bucket_alloc_t *list)
+{
+    apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
+
+    APR_BUCKET_INIT(b);
+    b->free = apr_bucket_free;
+    b->list = list;
+    return apr_bucket_pipe_make(b, p);
+}
+
+APR_DECLARE_DATA const apr_bucket_type_t apr_bucket_type_pipe = {
+    "PIPE", 5, APR_BUCKET_DATA, 
+    apr_bucket_destroy_noop,
+    pipe_bucket_read,
+    apr_bucket_setaside_notimpl,
+    apr_bucket_split_notimpl,
+    apr_bucket_copy_notimpl
+};
diff --git a/buckets/apr_buckets_pool.c b/buckets/apr_buckets_pool.c
new file mode 100644
index 00000000000..da6029072e0
--- /dev/null
+++ b/buckets/apr_buckets_pool.c
@@ -0,0 +1,142 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_buckets.h"
+#define APR_WANT_MEMFUNC
+#include "apr_want.h"
+
+static apr_status_t pool_bucket_cleanup(void *data)
+{
+    apr_bucket_pool *p = data;
+
+    /*
+     * If the pool gets cleaned up, we have to copy the data out
+     * of the pool and onto the heap.  But the apr_buckets out there
+     * that point to this pool bucket need to be notified such that
+     * they can morph themselves into a regular heap bucket the next
+     * time they try to read.  To avoid having to manipulate
+     * reference counts and b->data pointers, the apr_bucket_pool
+     * actually _contains_ an apr_bucket_heap as its first element,
+     * so the two share their apr_bucket_refcount member, and you
+     * can typecast a pool bucket struct to make it look like a
+     * regular old heap bucket struct.
+     */
+    p->heap.base = apr_bucket_alloc(p->heap.alloc_len, p->list);
+    memcpy(p->heap.base, p->base, p->heap.alloc_len);
+    p->base = NULL;
+    p->pool = NULL;
+
+    return APR_SUCCESS;
+}
+
+static apr_status_t pool_bucket_read(apr_bucket *b, const char **str, 
+                                     apr_size_t *len, apr_read_type_e block)
+{
+    apr_bucket_pool *p = b->data;
+    const char *base = p->base;
+
+    if (p->pool == NULL) {
+        /*
+         * pool has been cleaned up... masquerade as a heap bucket from now
+         * on. subsequent bucket operations will use the heap bucket code.
+         */
+        b->type = &apr_bucket_type_heap;
+        base = p->heap.base;
+    }
+    *str = base + b->start;
+    *len = b->length;
+    return APR_SUCCESS;
+}
+
+static void pool_bucket_destroy(void *data)
+{
+    apr_bucket_pool *p = data;
+
+    /* If the pool is cleaned up before the last reference goes
+     * away, the data is really now on the heap; heap_destroy() takes
+     * over.  free() in heap_destroy() thinks it's freeing
+     * an apr_bucket_heap, when in reality it's freeing the whole
+     * apr_bucket_pool for us.
+     */
+    if (p->pool) {
+        /* the shared resource is still in the pool
+         * because the pool has not been cleaned up yet
+         */
+        if (apr_bucket_shared_destroy(p)) {
+            apr_pool_cleanup_kill(p->pool, p, pool_bucket_cleanup);
+            apr_bucket_free(p);
+        }
+    }
+    else {
+        /* the shared resource is no longer in the pool, it's
+         * on the heap, but this reference still thinks it's a pool
+         * bucket.  we should just go ahead and pass control to
+         * heap_destroy() for it since it doesn't know any better.
+         */
+        apr_bucket_type_heap.destroy(p);
+    }
+}
+
+APR_DECLARE(apr_bucket *) apr_bucket_pool_make(apr_bucket *b,
+                      const char *buf, apr_size_t length, apr_pool_t *pool)
+{
+    apr_bucket_pool *p;
+
+    p = apr_bucket_alloc(sizeof(*p), b->list);
+
+    /* XXX: we lose the const qualifier here which indicates
+     * there's something screwy with the API...
+     */
+    /* XXX: why is this?  buf is const, p->base is const... what's
+     * the problem?  --jcw */
+    p->base = (char *) buf;
+    p->pool = pool;
+    p->list = b->list;
+
+    b = apr_bucket_shared_make(b, p, 0, length);
+    b->type = &apr_bucket_type_pool;
+
+    /* pre-initialize heap bucket member */
+    p->heap.alloc_len = length;
+    p->heap.base      = NULL;
+    p->heap.free_func = apr_bucket_free;
+
+    apr_pool_cleanup_register(p->pool, p, pool_bucket_cleanup,
+                              apr_pool_cleanup_null);
+    return b;
+}
+
+APR_DECLARE(apr_bucket *) apr_bucket_pool_create(const char *buf,
+                                                 apr_size_t length,
+                                                 apr_pool_t *pool,
+                                                 apr_bucket_alloc_t *list)
+{
+    apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
+
+    APR_BUCKET_INIT(b);
+    b->free = apr_bucket_free;
+    b->list = list;
+    return apr_bucket_pool_make(b, buf, length, pool);
+}
+
+APR_DECLARE_DATA const apr_bucket_type_t apr_bucket_type_pool = {
+    "POOL", 5, APR_BUCKET_DATA,
+    pool_bucket_destroy,
+    pool_bucket_read,
+    apr_bucket_setaside_noop, /* don't need to setaside thanks to the cleanup*/
+    apr_bucket_shared_split,
+    apr_bucket_shared_copy
+};
diff --git a/buckets/apr_buckets_refcount.c b/buckets/apr_buckets_refcount.c
new file mode 100644
index 00000000000..b1b57897bce
--- /dev/null
+++ b/buckets/apr_buckets_refcount.c
@@ -0,0 +1,64 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_buckets.h"
+
+APR_DECLARE_NONSTD(apr_status_t) apr_bucket_shared_split(apr_bucket *a,
+                                                         apr_size_t point)
+{
+    apr_bucket_refcount *r = a->data;
+    apr_status_t rv;
+
+    if ((rv = apr_bucket_simple_split(a, point)) != APR_SUCCESS) {
+        return rv;
+    }
+    r->refcount++;
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE_NONSTD(apr_status_t) apr_bucket_shared_copy(apr_bucket *a,
+                                                        apr_bucket **b)
+{
+    apr_bucket_refcount *r = a->data;
+
+    apr_bucket_simple_copy(a, b);
+    r->refcount++;
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(int) apr_bucket_shared_destroy(void *data)
+{
+    apr_bucket_refcount *r = data;
+    r->refcount--;
+    return (r->refcount == 0);
+}
+
+APR_DECLARE(apr_bucket *) apr_bucket_shared_make(apr_bucket *b, void *data,
+                                                 apr_off_t start,
+                                                 apr_size_t length)
+{
+    apr_bucket_refcount *r = data;
+
+    b->data   = r;
+    b->start  = start;
+    b->length = length;
+    /* caller initializes the type field */
+    r->refcount = 1;
+
+    return b;
+}
diff --git a/buckets/apr_buckets_simple.c b/buckets/apr_buckets_simple.c
new file mode 100644
index 00000000000..14f11ba7d80
--- /dev/null
+++ b/buckets/apr_buckets_simple.c
@@ -0,0 +1,137 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_buckets.h"
+
+APR_DECLARE_NONSTD(apr_status_t) apr_bucket_simple_copy(apr_bucket *a,
+                                                        apr_bucket **b)
+{
+    *b = apr_bucket_alloc(sizeof(**b), a->list); /* XXX: check for failure? */
+    **b = *a;
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE_NONSTD(apr_status_t) apr_bucket_simple_split(apr_bucket *a,
+                                                         apr_size_t point)
+{
+    apr_bucket *b;
+
+    if (point > a->length) {
+        return APR_EINVAL;
+    }
+
+    apr_bucket_simple_copy(a, &b);
+
+    a->length  = point;
+    b->length -= point;
+    b->start  += point;
+
+    APR_BUCKET_INSERT_AFTER(a, b);
+
+    return APR_SUCCESS;
+}
+
+static apr_status_t simple_bucket_read(apr_bucket *b, const char **str, 
+                                       apr_size_t *len, apr_read_type_e block)
+{
+    *str = (char *)b->data + b->start;
+    *len = b->length;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_bucket *) apr_bucket_immortal_make(apr_bucket *b,
+                                                   const char *buf,
+                                                   apr_size_t length)
+{
+    b->data   = (char *)buf;
+    b->length = length;
+    b->start  = 0;
+    b->type   = &apr_bucket_type_immortal;
+
+    return b;
+}
+
+APR_DECLARE(apr_bucket *) apr_bucket_immortal_create(const char *buf,
+                                                     apr_size_t length,
+                                                     apr_bucket_alloc_t *list)
+{
+    apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
+
+    APR_BUCKET_INIT(b);
+    b->free = apr_bucket_free;
+    b->list = list;
+    return apr_bucket_immortal_make(b, buf, length);
+}
+
+/*
+ * XXX: This function could do with some tweaking to reduce memory
+ * usage in various cases, e.g. share buffers in the heap between all
+ * the buckets that are set aside, or even spool set-aside data to
+ * disk if it gets too voluminous (but if it does then that's probably
+ * a bug elsewhere). There should probably be a apr_brigade_setaside()
+ * function that co-ordinates the action of all the bucket setaside
+ * functions to improve memory efficiency.
+ */
+static apr_status_t transient_bucket_setaside(apr_bucket *b, apr_pool_t *pool)
+{
+    b = apr_bucket_heap_make(b, (char *)b->data + b->start, b->length, NULL);
+    if (b == NULL) {
+        return APR_ENOMEM;
+    }
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_bucket *) apr_bucket_transient_make(apr_bucket *b,
+                                                    const char *buf,
+                                                    apr_size_t length)
+{
+    b->data   = (char *)buf;
+    b->length = length;
+    b->start  = 0;
+    b->type   = &apr_bucket_type_transient;
+    return b;
+}
+
+APR_DECLARE(apr_bucket *) apr_bucket_transient_create(const char *buf,
+                                                      apr_size_t length,
+                                                      apr_bucket_alloc_t *list)
+{
+    apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
+
+    APR_BUCKET_INIT(b);
+    b->free = apr_bucket_free;
+    b->list = list;
+    return apr_bucket_transient_make(b, buf, length);
+}
+
+const apr_bucket_type_t apr_bucket_type_immortal = {
+    "IMMORTAL", 5, APR_BUCKET_DATA,
+    apr_bucket_destroy_noop,
+    simple_bucket_read,
+    apr_bucket_setaside_noop,
+    apr_bucket_simple_split,
+    apr_bucket_simple_copy
+};
+
+APR_DECLARE_DATA const apr_bucket_type_t apr_bucket_type_transient = {
+    "TRANSIENT", 5, APR_BUCKET_DATA,
+    apr_bucket_destroy_noop, 
+    simple_bucket_read,
+    transient_bucket_setaside,
+    apr_bucket_simple_split,
+    apr_bucket_simple_copy
+};
diff --git a/buckets/apr_buckets_socket.c b/buckets/apr_buckets_socket.c
new file mode 100644
index 00000000000..5563049622a
--- /dev/null
+++ b/buckets/apr_buckets_socket.c
@@ -0,0 +1,114 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_buckets.h"
+
+static apr_status_t socket_bucket_read(apr_bucket *a, const char **str,
+                                       apr_size_t *len, apr_read_type_e block)
+{
+    apr_socket_t *p = a->data;
+    char *buf;
+    apr_status_t rv;
+    apr_interval_time_t timeout;
+
+    if (block == APR_NONBLOCK_READ) {
+        apr_socket_timeout_get(p, &timeout);
+        apr_socket_timeout_set(p, 0);
+    }
+
+    *str = NULL;
+    *len = APR_BUCKET_BUFF_SIZE;
+    buf = apr_bucket_alloc(*len, a->list); /* XXX: check for failure? */
+
+    rv = apr_socket_recv(p, buf, len);
+
+    if (block == APR_NONBLOCK_READ) {
+        apr_socket_timeout_set(p, timeout);
+    }
+
+    if (rv != APR_SUCCESS && rv != APR_EOF) {
+        apr_bucket_free(buf);
+        return rv;
+    }
+    /*
+     * If there's more to read we have to keep the rest of the socket
+     * for later. XXX: Note that more complicated bucket types that
+     * refer to data not in memory and must therefore have a read()
+     * function similar to this one should be wary of copying this
+     * code because if they have a destroy function they probably
+     * want to migrate the bucket's subordinate structure from the
+     * old bucket to a raw new one and adjust it as appropriate,
+     * rather than destroying the old one and creating a completely
+     * new bucket.
+     *
+     * Even if there is nothing more to read, don't close the socket here
+     * as we have to use it to send any response :)  We could shut it 
+     * down for reading, but there is no benefit to doing so.
+     */
+    if (*len > 0) {
+        apr_bucket_heap *h;
+        /* Change the current bucket to refer to what we read */
+        a = apr_bucket_heap_make(a, buf, *len, apr_bucket_free);
+        h = a->data;
+        h->alloc_len = APR_BUCKET_BUFF_SIZE; /* note the real buffer size */
+        *str = buf;
+        APR_BUCKET_INSERT_AFTER(a, apr_bucket_socket_create(p, a->list));
+    }
+    else {
+        apr_bucket_free(buf);
+        a = apr_bucket_immortal_make(a, "", 0);
+        *str = a->data;
+    }
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_bucket *) apr_bucket_socket_make(apr_bucket *b, apr_socket_t *p)
+{
+    /*
+     * XXX: We rely on a cleanup on some pool or other to actually
+     * destroy the socket. We should probably explicitly call apr to
+     * destroy it instead.
+     *
+     * Note that typically the socket is allocated from the connection pool
+     * so it will disappear when the connection is finished. 
+     */
+    b->type        = &apr_bucket_type_socket;
+    b->length      = (apr_size_t)(-1);
+    b->start       = -1;
+    b->data        = p;
+
+    return b;
+}
+
+APR_DECLARE(apr_bucket *) apr_bucket_socket_create(apr_socket_t *p,
+                                                   apr_bucket_alloc_t *list)
+{
+    apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
+
+    APR_BUCKET_INIT(b);
+    b->free = apr_bucket_free;
+    b->list = list;
+    return apr_bucket_socket_make(b, p);
+}
+
+APR_DECLARE_DATA const apr_bucket_type_t apr_bucket_type_socket = {
+    "SOCKET", 5, APR_BUCKET_DATA,
+    apr_bucket_destroy_noop,
+    socket_bucket_read,
+    apr_bucket_setaside_notimpl, 
+    apr_bucket_split_notimpl,
+    apr_bucket_copy_notimpl
+};
diff --git a/build.conf b/build.conf
new file mode 100644
index 00000000000..d01fd1dc627
--- /dev/null
+++ b/build.conf
@@ -0,0 +1,112 @@
+#
+# Configuration file for APR. Used by APR/build/gen-build.py
+#
+
+[options]
+
+# paths to platform-independent .c files to build
+paths =
+  passwd/*.c
+  strings/*.c
+  tables/*.c
+  buckets/*.c
+  crypto/apr_crypto.c
+  crypto/apr_md4.c
+  crypto/apr_md5.c
+  crypto/apr_passwd.c
+  crypto/apr_sha1.c
+  crypto/apr_siphash.c
+  crypto/getuuid.c
+  crypto/uuid.c
+  crypto/crypt_blowfish.c
+  dbm/apr_dbm_sdbm.c
+  dbm/apr_dbm.c
+  dbm/sdbm/*.c
+  encoding/*.c
+  hooks/*.c
+  misc/*.c
+  memcache/*.c
+  redis/*.c
+  uri/apr_uri.c
+  xml/*.c
+  strmatch/*.c
+  xlate/*.c
+  dbd/apr_dbd.c
+  util-misc/*.c
+  
+
+# directories that have platform-specific code in them. the resulting
+# pattern will be: SUBDIR/PLATFORM/*.c
+platform_dirs =
+  dso file_io locks memory misc mmap network_io poll random
+  shmem support threadproc time user atomic
+
+# all the public headers
+headers = include/*.h
+
+# aplibtool is manually built by the configure process
+# build/aplibtool.c
+
+# we have a recursive makefile for the test files (for now)
+# test/*.c
+
+dsp = libapr.dsp
+
+modules =
+  crypto_openssl crypto_nss crypto_commoncrypto dbd_pgsql
+  dbd_sqlite2 dbd_sqlite3 dbd_oracle dbd_mysql dbd_odbc
+  dbm_db dbm_gdbm dbm_ndbm
+
+# gen_uri_delim.c
+
+# we have a recursive makefile for the test files (for now)
+# test/*.c
+
+[crypto_commoncrypto]
+paths = crypto/apr_crypto_commoncrypto.c
+target = crypto/apr_crypto_commoncrypto.la
+
+[crypto_openssl]
+paths = crypto/apr_crypto_openssl.c
+target = crypto/apr_crypto_openssl.la
+
+[crypto_nss]
+paths = crypto/apr_crypto_nss.c
+target = crypto/apr_crypto_nss.la
+
+[dbd_pgsql]
+paths = dbd/apr_dbd_pgsql.c
+target = dbd/apr_dbd_pgsql.la
+
+[dbd_sqlite2]
+paths = dbd/apr_dbd_sqlite2.c
+target = dbd/apr_dbd_sqlite2.la
+
+[dbd_sqlite3]
+paths = dbd/apr_dbd_sqlite3.c
+target = dbd/apr_dbd_sqlite3.la
+
+[dbd_oracle]
+paths = dbd/apr_dbd_oracle.c
+target = dbd/apr_dbd_oracle.la
+
+[dbd_mysql]
+paths = dbd/apr_dbd_mysql.c
+target = dbd/apr_dbd_mysql.la
+
+[dbd_odbc]
+paths = dbd/apr_dbd_odbc.c
+target = dbd/apr_dbd_odbc.la
+
+[dbm_db]
+paths = dbm/apr_dbm_berkeleydb.c
+target = dbm/apr_dbm_db.la
+
+[dbm_gdbm]
+paths = dbm/apr_dbm_gdbm.c
+target = dbm/apr_dbm_gdbm.la
+
+[dbm_ndbm]
+paths = dbm/apr_dbm_ndbm.c
+target = dbm/apr_dbm_ndbm.la
+
diff --git a/helpers/MakeEtags b/build/MakeEtags
similarity index 58%
rename from helpers/MakeEtags
rename to build/MakeEtags
index 25f6bdab176..3b82c3a8c2a 100755
--- a/helpers/MakeEtags
+++ b/build/MakeEtags
@@ -1,33 +1,34 @@
 #!/bin/sh
 
 # This file illustrates how to generate a useful TAGS file via etags
-# for emacs.  This should be invoked from the src directory i.e.:
-#   > helpers/MakeEtags
-# and will create a TAGS file in the src directory.
+# for emacs.  This should be invoked from the top source directory i.e.:
+#   > build/MakeEtags
+# and will create a TAGS file in the top source directory.
 
 # This script falls under the Apache License.
 # See http://www.apache.org/docs/LICENSE
 
-# Once you have created src/TAGS in emacs you'll need to setup
-# tag-table-alist with an entry to assure it finds the single src/TAGS
+# Once you have created ./TAGS in emacs you'll need to setup
+# tag-table-alist with an entry to assure it finds the single ./TAGS
 # file from the many source directories.  Something along these lines:
 # (setq tag-table-alist
-#	'(("/home/me/work/apache-1.3/src/" 
-#	   . "/home/me/work/apache-1.3/src/")
+#	'(("/home/me/work/apr-x.y/" . "/home/me/work/apr-x.y/")
+#	  ("/home/me/work/apr-util-x.y/" . "/home/me/work/apr-util-x.y/")
+#	  ("/home/me/work/httpd-x.y/" . "/home/me/work/httpd-x.y/")
 #	 ))
 
 # This requires a special version of etags, i.e. the
 # one called "Exuberant ctags" available at:
-#    http://fly.hiwaay.net/~darren/ctags/
+#    http://ctags.sourceforge.net/
 # Once that is setup you'll need to point to the
 # executable here:
 
-etags=~/local/bin/etags
+etags=${ETAGS-etags}
 
 # Exuberant etags is necessary since it can ignore some defined symbols
 # that obscure the function signatures.
 
-ignore=API_EXPORT,API_EXPORT_NONSTD,__declspec
+ignore=AP_DECLARE,AP_DECLARE_NONSTD,__declspec,APR_DECLARE,APR_DECLARE_NONSTD
 
 # Create an etags file at the root of the source
 # tree, then create symbol links to it from each
diff --git a/build/NWGNUenvironment.inc b/build/NWGNUenvironment.inc
new file mode 100644
index 00000000000..9b6c5e4761c
--- /dev/null
+++ b/build/NWGNUenvironment.inc
@@ -0,0 +1,392 @@
+#
+# Setup needed Tools and Libraries
+#
+
+ifeq "$(wildcard $(APR_WORK)/build/NWGNUcustom.inc)" "$(APR_WORK)/build/NWGNUcustom.inc"
+include $(APR_WORK)/build/NWGNUcustom.inc
+CUSTOM_INI = $(AP_WORK)/NWGNUcustom.ini
+endif
+
+ifndef VERBOSE
+.SILENT:
+endif
+
+#
+# Treat like an include
+#
+ifndef EnvironmentDefined
+
+#
+# simple macros for parsing makefiles
+#
+EOLIST:=
+EMPTY :=
+COMMA := ,
+SPACE := $(EMPTY) $(EMPTY)
+
+#
+# Base environment
+#
+
+# Try and handle case issues
+ifndef NOVELLLIBC
+ifdef NovellLibC
+NOVELLLIBC = $(NovellLibC)
+endif
+endif
+
+ifndef NOVELLLIBC
+NOVELLLIBC = C:/novell/ndk/libc
+endif
+ifneq "$(wildcard $(NOVELLLIBC)/include/ndkvers.h)" "$(NOVELLLIBC)/include/ndkvers.h"
+$(error NOVELLLIBC does not point to a valid Novell LIBC SDK) 
+endif
+
+ifdef EXPATSDK
+ifeq "$(wildcard $(EXPATSDK)/include/expat.h)" "$(EXPATSDK)/include/expat.h"
+EXPAT_IMP = $(EXPATSDK)/imports/expatlbc.imp
+EXPAT_INC = $(EXPATSDK)/include
+EXPAT_LIB = $(EXPATSDK)/lib/expat.lib
+EXPAT_NLM = EXPATLBC
+else
+$(error EXPATSDK does not point to a valid EXPAT SDK) 
+endif
+endif
+ifdef EXPATSRC
+ifeq "$(wildcard $(EXPATSRC)/lib/xmlparse.c)" "$(EXPATSRC)/lib/xmlparse.c"
+EXPAT_INC = $(EXPATSRC)/lib
+EXPAT_LIB = $(EXPATSRC)/lib/$(OBJDIR)/expat.lib
+else
+$(error EXPATSRC does not point to a valid EXPAT source tree) 
+endif
+endif
+ifndef EXPAT_INC
+$(error neither EXPATSDK nor EXPATSRC defined - cant compile without EXPAT SDK or source tree) 
+endif
+
+# If LM_LICENSE_FILE isn't defined, define a variable that can be used to
+# restart make with it defined
+ifndef LM_LICENSE_FILE
+NO_LICENSE_FILE = NO_LICENSE_FILE
+endif
+
+#
+# Set the Release type that you want to build, possible values are:
+#
+#  debug	- full debug switches are set
+#  noopt	- normal switches are set
+#  release	- optimization switches are set (default)
+
+ifdef reltype
+RELEASE = $(reltype)
+endif
+
+ifdef RELTYPE
+RELEASE = $(RELTYPE)
+endif
+
+ifdef debug
+RELEASE = debug
+endif
+
+ifdef DEBUG
+RELEASE = debug
+endif
+
+ifdef noopt
+RELEASE = noopt
+endif
+
+ifdef NOOPT
+RELEASE = noopt
+endif
+
+ifdef optimized
+RELEASE = release
+endif
+
+ifdef OPTIMIZED
+RELEASE = release
+endif
+
+ifndef RELEASE
+RELEASE = release
+endif
+
+ifeq "$(strip $(RELEASE))" "optimized"
+RELEASE = release
+endif
+
+OBJDIR = obj_$(RELEASE)
+
+#
+# Setup compiler information
+#
+
+ifdef METROWERKS
+# MetroWerks NLM tools
+#ifndef METROWERKS
+#METROWERKS = $(ProgramFiles)\Metrowerks\CodeWarrior
+#endif
+
+CC	= mwccnlm -w nocmdline -gccinc
+CPP	= $(CC)
+CPRE	= $(CC) -EP
+LINK	= mwldnlm -w nocmdline
+AR	= $(LINK) -type library -o
+WIN_CC	= mwcc
+
+ifneq ($(findstring /sh,$(SHELL)),/sh)
+PATH:=$(PATH);$(METROWERKS)\bin;$(METROWERKS)\Other Metrowerks Tools\Command Line Tools
+endif
+
+# MetroWerks static Libraries
+CLIB3S	= $(METROWERKS)/Novell Support/Metrowerks Support/Libraries/Runtime/mwcrtl.lib
+MATH3S	=
+PLIB3S	= $(METROWERKS)/Novell Support/Metrowerks Support/Libraries/MSL C++/MWCPP.lib
+
+ifeq "$(OS)" "Windows_NT"
+# MetroWerks Win32 build flags to create build tools
+MWCW_MSL         = "$(METROWERKS)/MSL"
+MWCW_W32         = "$(METROWERKS)/Win32-x86 Support"
+CC_FOR_BUILD     = $(WIN_CC)
+CFLAGS_FOR_BUILD =  -O2 -gccinc -nodefaults -proc 586 -w off
+CFLAGS_FOR_BUILD += -ir $(MWCW_MSL) -ir $(MWCW_W32) -lr $(MWCW_MSL) -lr $(MWCW_W32)
+CFLAGS_FOR_BUILD += -lMSL_All_x86.lib -lkernel32.lib -luser32.lib
+else
+# GNUC build flags to create build tools
+CC_FOR_BUILD     = gcc
+CFLAGS_FOR_BUILD = -Wall -O2
+endif
+
+# Base compile flags
+# and prefix or precompiled header added here.
+
+# The default flags are as follows:
+#
+# -w nocmdline          disable command-line driver/parser warnings
+# -gccinc               search directory of referencing file first for #includes
+# -Cpp_exceptions off   disable C++ exceptions
+# -RTTI off             disable C++ run-time typing information
+# -align 4              align on 4 byte bounderies
+# -proc PII             generate code base on Pentium II instruction set
+# -inst mmx             use MMX extensions (not used)
+
+CFLAGS	= -proc PII -align 4
+CPFLAGS	= -Cpp_exceptions off -RTTI off
+
+ifdef CC_MAX_ERRORS
+CFLAGS += -maxerrors $(CC_MAX_ERRORS)
+else
+CFLAGS += -maxerrors 1
+endif
+
+ifeq "$(REQUIRE_PROTOTYPES)" "1"
+CFLAGS	+= -r
+endif
+
+# -g                    generate debugging information
+# -O0                   level 0 optimizations
+ifeq "$(RELEASE)" "debug"
+CFLAGS	+= -g -O0
+endif
+
+# -O4,p                 level 4 optimizations, optimize for speed
+ifeq "$(RELEASE)" "release"
+CFLAGS	+= -O4,p
+endif
+
+PRELUDE	= $(NOVI)/libcpre.o
+
+else
+# GNU NLM tools (gcc / nlmconv)
+
+CC	= gcc
+CPP	= g++
+CPRE	= $(CC) -P -E
+LINK	= nlmconv
+AR	= ar cru
+RANLIB	= ranlib
+
+CFLAGS	= -m32 -fno-builtin -fpcc-struct-return -fno-strict-aliasing
+CFLAGS	+= -fpack-struct=4
+CFLAGS	+= -Wall
+CFLAGS	+= -Wdeclaration-after-statement -Wmissing-declarations -Wmissing-prototypes
+
+ifdef MAINTAINER
+CFLAGS	+= \
+	-W -Wpointer-arith -Wwrite-strings -Wunused -Wshadow -Winline \
+	-Wnested-externs -Wcast-align -Wtype-limits -Wstrict-prototypes \
+	-Wfloat-equal -Wno-multichar -Wsign-compare -Wundef -Wendif-labels \
+	-Wold-style-declaration -Wmissing-parameter-type -Wempty-body \
+	-Wclobbered -Wignored-qualifiers -Wconversion -Wvla -pedantic
+endif
+
+# -g                    generate debugging information
+# -O0                   level 0 optimizations
+ifeq "$(RELEASE)" "debug"
+CFLAGS	+= -g -O0
+endif
+
+# -O3                   level 3 optimizations, optimize for speed
+ifeq "$(RELEASE)" "release"
+CFLAGS	+= -O3
+endif
+
+PRELUDE	= $(NOVI)/libcpre.gcc.o
+
+endif
+
+# -include apr_arch_pre_nw.h      #include apr_arch_pre_nw.h for all files
+CFLAGS	+= -include apr_arch_pre_nw.h
+
+
+# Setup build tools
+AWK	= awk
+
+#
+# Declare Command and tool macros here
+#
+
+ifeq ($(findstring /sh,$(SHELL)),/sh)
+DEL	= rm -f $1
+RMDIR	= rm -rf $1
+MKDIR	= mkdir -p $1
+COPY	= cp -av $1 $2
+COPYR	= cp -ar $1 $2
+ECHONL	= echo ""
+DL	= '
+CAT	= cat
+else
+ifeq "$(OS)" "Windows_NT"
+DEL	= $(shell if exist $(subst /,\,$1) del /q /f 2>NUL $(subst /,\,$1))
+RMDIR	= $(shell if exist $(subst /,\,$1)\NUL rd /q /s 2>NUL $(subst /,\,$1))
+else
+DEL	= $(shell if exist $(subst /,\,$1) del 2>NUL $(subst /,\,$1))
+RMDIR	= $(shell if exist $(subst /,\,$1)\NUL deltree /y 2>NUL $(subst /,\,$1))
+endif
+ECHONL	= $(ComSpec) /c echo.
+MKDIR	= $(shell if not exist $(subst /,\,$1)\NUL md 2>NUL $(subst /,\,$1))
+COPY	= copy /y 2>NUL $(subst /,\,$1) $(subst /,\,$2)
+COPYR	= xcopy /y /e 2>NUL $(subst /,\,$1) $(subst /,\,$2)
+CAT	= type
+endif
+
+ifdef IPV6
+ifndef USE_STDSOCKETS
+USE_STDSOCKETS=1
+endif
+endif
+
+NOVI	= $(NOVELLLIBC)/imports
+INCDIRS	= $(NOVELLLIBC)/include
+
+DEFINES	= -DNETWARE
+ifdef USE_STDSOCKETS
+DEFINES	+= -DUSE_BSD_SOCKETS
+else
+DEFINES	+= -DUSE_WINSOCK
+INCDIRS	+= $(NOVELLLIBC)/include/winsock
+endif
+ifndef DEBUG
+DEFINES	+= -DNDEBUG
+endif
+
+ifdef USE_STDSOCKETS
+VERSION_SKT = (BSDSOCK)
+else
+VERSION_SKT = (WINSOCK)
+endif
+
+#
+# Declare major project deliverables output directories here
+#
+
+ifdef DEST
+INSTALL = $(DEST)
+ifeq (\, $(findstring \,$(INSTALL)))
+INSTDIRS = $(DEST)
+endif
+endif
+
+ifdef dest
+INSTALL = $(dest)
+ifeq (\, $(findstring \,$(INSTALL)))
+INSTDIRS = $(dest)
+endif
+endif
+
+ifndef INSTALL
+INSTALL = $(APR_WORK)/Dist
+INSTDIRS = $(APR_WORK)/Dist
+BASEDIR = Apr
+endif
+
+# Add support for building IPV6 alongside
+ifneq "$(IPV6)" ""
+DEFINES += -DNW_BUILD_IPV6
+# INCDIRS := $(NOVELLLIBC)/include/winsock/IPV6 $(INCDIRS)
+
+ifneq "$(findstring IPV6,$(OBJDIR))" "IPV6"
+OBJDIR := $(OBJDIR)_IPV6
+endif
+        
+ifneq "$(findstring IPV6,$(INSTALL))" "IPV6"
+INSTALL := $(INSTALL)_IPV6
+endif        
+
+ifneq "$(findstring IPV6,$(INSTDIRS))" "IPV6"
+INSTDIRS := $(INSTDIRS)_IPV6
+endif
+
+endif
+
+ifdef DEST
+
+ifndef BASEDIR
+BASEDIR = Apache2
+endif
+
+endif
+
+INSTALLBASE := $(INSTALL)/$(BASEDIR)
+
+INSTDEVDIRS := \
+	$(INSTDIRS) \
+	$(INSTALLBASE) \
+	$(INSTALLBASE)/include \
+	$(INSTALLBASE)/lib \
+	$(INSTALLBASE)/bin 
+
+INSTDIRS += \
+	$(INSTALLBASE)
+
+#
+# Common directories
+#
+
+APR		= $(subst \,/,$(APR_WORK))
+APRBUILD	= $(APR)/build
+APRXML		= $(APR)/xml
+APRTEST		= $(APR)/test
+
+#
+# Internal Libraries
+#
+
+APRLIB		= $(APR)/$(OBJDIR)/aprlib.lib
+APRXMLLIB	= $(APRXML)/$(OBJDIR)/xml.lib
+
+#
+# Additional general defines
+#
+
+EnvironmentDefined = 1
+endif # ifndef EnvironmentDefined
+
+# This is always set so that it will show up in lower directories
+
+ifdef Path
+Path = $(PATH)
+endif
+
diff --git a/build/NWGNUhead.inc b/build/NWGNUhead.inc
new file mode 100644
index 00000000000..316454dcbec
--- /dev/null
+++ b/build/NWGNUhead.inc
@@ -0,0 +1,102 @@
+#
+# Obtain the global build environment
+#
+
+include $(APR_WORK)/build/NWGNUenvironment.inc
+
+#
+# Define base targets and rules
+# 
+
+TARGETS = libs nlms install clobber_libs clobber_nlms clean installdev
+
+.PHONY : $(TARGETS) default all help $(NO_LICENSE_FILE)
+
+# Here is where we will use the NO_LICENSE_FILE variable to see if we need to
+# restart the make with it defined
+
+ifdef NO_LICENSE_FILE
+
+default: NO_LICENSE_FILE
+
+all: NO_LICENSE_FILE
+
+install :: NO_LICENSE_FILE
+
+installdev :: NO_LICENSE_FILE
+
+NO_LICENSE_FILE :
+	$(MAKE) $(MAKECMDGOALS) -f NWGNUmakefile RELEASE=$(RELEASE) DEST="$(INSTALL)" LM_LICENSE_FILE="$(METROWERKS)/license.dat"
+
+else # LM_LICENSE_FILE must be defined so use the real targets
+
+default: $(SUBDIRS) libs nlms
+
+all: $(SUBDIRS) libs nlms install
+
+$(TARGETS) :: $(SUBDIRS)
+
+endif #NO_LICENSE_FILE check
+
+help :
+	@echo $(DL)targets for RELEASE=$(RELEASE):$(DL)
+	@echo $(DL)(default) . . . . libs nlms$(DL)
+	@echo $(DL)all . . . . . . . does everything (libs nlms install)$(DL)
+	@echo $(DL)libs. . . . . . . builds all libs$(DL)
+	@echo $(DL)nlms. . . . . . . builds all nlms$(DL)
+	@echo $(DL)install . . . . . builds libs and nlms and copies install files to$(DL)
+	@echo $(DL)                  "$(INSTALL)"$(DL)
+	@echo $(DL)installdev. . . . copies headers and files needed for development to$(DL)
+	@echo $(DL)                  "$(INSTALL)"$(DL)
+	@echo $(DL)clean . . . . . . deletes $(OBJDIR) dirs, *.err, and *.map$(DL)
+	@echo $(DL)clobber_all . . . deletes all possible output from the make$(DL)
+	@echo $(DL)clobber_install . deletes all files in $(INSTALL)$(DL)
+	@$(ECHONL)
+	@echo $(DL)Multiple targets can be used on a single make command line -$(DL)
+	@echo $(DL)(i.e. $(MAKE) clean all)$(DL)
+	@$(ECHONL)
+	@echo $(DL)You can also specify RELEASE=debug, RELEASE=noopt, or RELEASE=release$(DL)
+	@echo $(DL)The default is RELEASE=release$(DL)
+
+clobber_all :: clean clobber_install
+
+clobber_install ::
+	$(call RMDIR,$(INSTALL))
+
+test :: default
+	$(MAKE) -C $(APRTEST) -f NWGNUmakefile RELEASE=$(RELEASE) DEST="$(INSTALL)" LM_LICENSE_FILE="$(LM_LICENSE_FILE)"
+
+#
+# build recursive targets
+#
+
+$(SUBDIRS) : FORCE
+ifneq "$(MAKECMDGOALS)" "clean"
+ifneq "$(findstring clobber_,$(MAKECMDGOALS))" "clobber_"
+	@$(ECHONL)
+	@echo Building $(CURDIR)/$@
+endif
+endif
+	$(MAKE) -C $@ $(MAKECMDGOALS) -f NWGNUmakefile RELEASE=$(RELEASE) DEST="$(INSTALL)" LM_LICENSE_FILE="$(LM_LICENSE_FILE)"
+	@$(ECHONL)
+
+FORCE : ;
+
+#
+# Standard targets
+#
+
+clean :: $(SUBDIRS)
+	@echo Cleaning up $(CURDIR)
+	$(call RMDIR,$(OBJDIR))
+	$(call DEL,*.err)
+	$(call DEL,*.map)
+	$(call DEL,*.tmp)
+#	$(call DEL,*.d)
+
+test-clean ::
+	$(MAKE) -C $(APRTEST) -f NWGNUmakefile clean
+
+$(OBJDIR) ::
+	$(call MKDIR,$@)
+
diff --git a/build/NWGNUmakefile b/build/NWGNUmakefile
new file mode 100644
index 00000000000..3d323be4496
--- /dev/null
+++ b/build/NWGNUmakefile
@@ -0,0 +1,89 @@
+#
+# 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 $(APR_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 \
+	$(APR)/include/private \
+	$(APR)/include/arch/netware \
+	$(APR)/include/arch/unix \
+	$(APRBUILD) \
+	$(EOLIST)
+
+FILES_prebuild_headers = \
+	$(APR)/include/apr.h \
+	$(APR)/include/apu_want.h \
+	$(APR)/include/private/apu_select_dbm.h \
+	$(APR)/include/private/apr_escape_test_char.h \
+	$(EOLIST)
+
+nlms :: $(APR)/aprlib.imp
+
+$(APR)/aprlib.imp : make_nw_export.awk nw_export.i
+	@echo $(DL)GEN  $@$(DL)
+	$(AWK) -v EXPPREFIX=APR$(VERSION_MAJMIN) -f $^ >$@
+
+nw_export.i : nw_export.h $(FILES_prebuild_headers) $(CCOPT_DEPENDS)
+	@echo $(DL)GEN  $@$(DL)
+	$(CPRE) $(CCFLAGS) -DGENEXPORTS $< -o $@
+
+%.h: %.hnw
+	@echo Creating $@
+	$(call COPY,$<,$@)
+
+%.h: %.hw
+	@echo Creating $@
+	$(call COPY,$<,$@)
+
+$(APR)/include/private/apr_escape_test_char.h: gen_test_char.exe $(APR)/tools/gen_test_char.c
+	@echo $(DL)GEN  $@$(DL)
+	$< > $@
+
+%.exe: $(APR)/tools/%.c
+	@echo $(DL)Creating Build Helper $@$(DL)
+	$(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) -DCROSS_COMPILE $< -o $@
+
+#
+# You can use this target if all that is needed is to copy files to the
+# installation area
+#
+install :: nlms FORCE
+
+
+clean ::
+	$(call DEL,nw_export.i)
+	$(call DEL,cc.opt)
+	$(call DEL,NWGNUversion.inc)
+	$(call DEL,$(APR)/aprlib.imp)
+	$(foreach file,$(FILES_prebuild_headers),$(call DEL,$(file)))
+	$(call DEL,gen_test_char.exe)
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(APRBUILD)/NWGNUtail.inc
+
+
diff --git a/build/NWGNUtail.inc b/build/NWGNUtail.inc
new file mode 100644
index 00000000000..b98ed96f7f8
--- /dev/null
+++ b/build/NWGNUtail.inc
@@ -0,0 +1,383 @@
+#
+# This contains final targets and should be included at the end of any
+# NWGNUmakefile file
+#
+
+#
+# If we are going to create an nlm, make sure we have assigned variables to
+# use during the link.
+#
+ifndef NLM_NAME
+NLM_NAME = $(TARGET_nlm)
+endif
+
+ifndef NLM_DESCRIPTION
+NLM_DESCRIPTION = $(NLM_NAME)
+endif
+
+ifndef NLM_THREAD_NAME
+NLM_THREAD_NAME = $(NLM_NAME) Thread
+endif
+
+ifndef NLM_SCREEN_NAME
+NLM_SCREEN_NAME = DEFAULT
+endif
+
+ifndef NLM_COPYRIGHT
+NLM_COPYRIGHT = Licensed under the Apache License, Version 2.0
+endif
+
+ifeq "$(NLM_FLAGS)" ""
+#NLM_FLAGS = AUTOUNLOAD, PSEUDOPREEMPTION
+NLM_FLAGS = flag_on 72
+endif
+
+ifeq "$(NLM_STACK_SIZE)" ""
+NLM_STACK_SIZE = 65536
+endif
+
+ifeq "$(NLM_ENTRY_SYM)" ""
+NLM_ENTRY_SYM = _LibCPrelude
+endif
+
+ifeq "$(NLM_EXIT_SYM)" ""
+NLM_EXIT_SYM = _LibCPostlude
+endif
+
+ifeq "$(NLM_VERSION)" ""
+NLM_VERSION = $(VERSION)
+endif
+
+# if APACHE_UNIPROC is defined, don't include XDCData
+ifndef APACHE_UNIPROC
+ifneq "$(XDCDATA)" ""
+NLM_XDCDATA = $(XDCDATA)
+else
+NLM_XDCDATA = $(APR)/misc/netware/apr.xdc
+endif
+endif
+ 
+#
+# Create dependency lists based on the files available
+#
+
+CCOPT_DEPENDS			= \
+				$(APRBUILD)/NWGNUhead.inc \
+				$(APRBUILD)/NWGNUenvironment.inc \
+				$(APRBUILD)/NWGNUtail.inc \
+				NWGNUmakefile \
+				$(CUSTOM_INI) \
+				$(EOLIST)
+
+CPPOPT_DEPENDS			= \
+				$(APRBUILD)/NWGNUhead.inc \
+				$(APRBUILD)/NWGNUenvironment.inc \
+				$(APRBUILD)/NWGNUtail.inc \
+				NWGNUmakefile \
+				$(CUSTOM_INI) \
+				$(EOLIST)
+
+$(NLM_NAME)_LINKOPT_DEPENDS	= \
+				$(TARGET_lib) \
+				$(APRBUILD)/NWGNUenvironment.inc \
+				NWGNUmakefile \
+				$(APRBUILD)/NWGNUtail.inc \
+				$(CUSTOM_INI) \
+				$(VERSION_INC) \
+				$(EOLIST)
+
+ifeq "$(words $(strip $(TARGET_lib)))" "1"
+LIB_NAME			= $(basename $(notdir $(TARGET_lib)))
+$(LIB_NAME)_LIBLST_DEPENDS	= \
+				$(FILES_lib_objs) \
+				$(APRBUILD)/NWGNUenvironment.inc \
+				NWGNUmakefile \
+				$(APRBUILD)/NWGNUtail.inc \
+				$(CUSTOM_INI) \
+				$(EOLIST)
+endif
+
+ifeq "$(wildcard NWGNU$(LIB_NAME))" "NWGNU$(LIB_NAME)"
+$(LIB_NAME)_LIBLST_DEPENDS	+= NWGNU$(LIB_NAME)
+endif
+
+ifeq "$(wildcard NWGNU$(NLM_NAME))" "NWGNU$(NLM_NAME)"
+$(NLM_NAME)_LINKOPT_DEPENDS	+= NWGNU$(NLM_NAME)
+CCOPT_DEPENDS			+= NWGNU$(NLM_NAME)
+CPPOPT_DEPENDS			+= NWGNU$(NLM_NAME)
+endif
+
+#
+# Generic compiler rules
+#
+
+ifneq "$(MAKECMDGOALS)" "clean"
+ifneq "$(findstring clobber_,$(MAKECMDGOALS))" "clobber_"
+$(APRBUILD)/NWGNUversion.inc : $(APRBUILD)/nw_ver.awk $(APR)/include/apr_version.h
+	@echo $(DL)GEN  $@$(DL)
+	$(AWK) -f $^ $(APR)/.svn/all-wcprops > $@
+
+-include $(APRBUILD)/NWGNUversion.inc
+
+ifneq "$(strip $(VERSION_STR))" ""
+VERSION_INC = $(APRBUILD)/NWGNUversion.inc
+else
+VERSION		= 2,0,0
+VERSION_STR	= 2.0.0
+VERSION_MAJMIN	= 20
+endif
+endif
+endif
+ifeq "$(USE_SVNREV)" "1"
+ifneq "$(strip $(SVN_REVISION))" ""
+CFLAGS	+= -DAPR_IS_DEV_STRING=\"$(SVN_REVISION)\"
+endif
+endif
+
+ifeq "$(words $(strip $(TARGET_nlm)))" "1"
+INCLUDE_BLDCMDS	= 1
+CCOPT_NAME	= $(NLM_NAME)
+endif
+
+ifeq "$(words $(strip $(TARGET_lib)))" "1"
+INCLUDE_BLDCMDS	= 1
+CCOPT_NAME	= $(LIB_NAME)
+endif
+
+CCFLAGS = 
+ifneq "$(strip $(CFLAGS))" ""
+CCFLAGS += $(CFLAGS)
+endif
+ifneq "$(strip $(XCFLAGS))" ""
+CCFLAGS += $(XCFLAGS)
+endif
+ifneq "$(strip $(XINCDIRS))" ""
+CCFLAGS += $(foreach xincdir,$(strip $(XINCDIRS)),-I$(xincdir))
+endif
+ifneq "$(strip $(INCDIRS))" ""
+CCFLAGS += $(foreach incdir,$(strip $(INCDIRS)),-I$(incdir))
+endif
+ifneq "$(strip $(DEFINES))" ""
+CCFLAGS += $(DEFINES)
+endif
+ifneq "$(strip $(XDEFINES))" ""
+CCFLAGS += $(XDEFINES)
+endif
+
+ifeq "$(INCLUDE_BLDCMDS)" "1"
+
+$(OBJDIR)/%.o: %.c $(CCOPT_DEPENDS)
+	@echo $(DL)CC   $<$(DL)
+ifdef VERBOSE
+	@echo CCOPT_DEPENDS=$(CCOPT_DEPENDS)
+endif
+	$(CC) $(CCFLAGS) -c -o $@ $<
+
+CCPFLAGS = $(CPFLAGS) $(CCFLAGS)
+
+$(OBJDIR)/%.o: %.cpp $(CPPOPT_DEPENDS)
+	@echo $(DL)CPP  $<$(DL)
+ifdef VERBOSE
+	@echo CPPOPT_DEPENDS=$(CPPOPT_DEPENDS)
+endif
+	$(CPP) $(CCPFLAGS) -c -o $@ $<
+
+endif # one target nlm or lib
+
+#
+# Rules to build libraries
+#
+
+# If we only have one target library then build it
+
+ifeq "$(words $(strip $(TARGET_lib)))" "1"
+
+$(TARGET_lib) : $(OBJDIR)/$(LIB_NAME)_lib.lst
+	$(call DEL,$@)
+	@echo $(DL)AR   $@$(DL)
+	$(AR) $@ @$<
+ifdef RANLIB
+	$(RANLIB) $@
+endif
+
+$(OBJDIR)/aprlib_lib.lst: $(aprlib_LIBLST_DEPENDS)
+	$(call DEL,$@)
+ifneq "$(strip $(FILES_lib_objs))" ""
+	@echo $(DL)GEN  $@$(DL)
+	@echo $(DL)$(wordlist 1, 10, $(FILES_lib_objs))$(DL)>> $@
+	@echo $(DL)$(wordlist 11, 20, $(FILES_lib_objs))$(DL)>> $@
+	@echo $(DL)$(wordlist 21, 30, $(FILES_lib_objs))$(DL)>> $@
+	@echo $(DL)$(wordlist 31, 40, $(FILES_lib_objs))$(DL)>> $@
+	@echo $(DL)$(wordlist 41, 50, $(FILES_lib_objs))$(DL)>> $@
+	@echo $(DL)$(wordlist 51, 60, $(FILES_lib_objs))$(DL)>> $@
+	@echo $(DL)$(wordlist 61, 70, $(FILES_lib_objs))$(DL)>> $@
+	@echo $(DL)$(wordlist 71, 80, $(FILES_lib_objs))$(DL)>> $@
+	@echo $(DL)$(wordlist 81, 90, $(FILES_lib_objs))$(DL)>> $@
+	@echo $(DL)$(wordlist 91, 100, $(FILES_lib_objs))$(DL)>> $@
+	@echo $(DL)$(wordlist 101, 110, $(FILES_lib_objs))$(DL)>> $@
+	@echo $(DL)$(wordlist 111, 120, $(FILES_lib_objs))$(DL)>> $@
+endif
+
+$(OBJDIR)/%_lib.lst: $($(LIB_NAME)_LIBLST_DEPENDS)
+	$(call DEL,$@)
+ifneq "$(strip $(FILES_lib_objs))" ""
+	@echo $(DL)GEN  $@$(DL)
+	@echo $(DL)$(FILES_lib_objs)$(DL)>> $@
+endif
+
+else # We must have more than one target library so load the individual makefiles
+
+$(OBJDIR)/%.lib: NWGNU% $(APRBUILD)/NWGNUhead.inc $(APRBUILD)/NWGNUtail.inc $(APRBUILD)/NWGNUenvironment.inc FORCE
+	@echo $(DL)Calling $<$(DL)
+	$(MAKE) -f $< $(MAKECMDGOALS) RELEASE=$(RELEASE)
+
+endif
+
+#
+# Rules to build nlms.
+#
+
+# If we only have one target NLM then build it
+ifeq "$(words $(strip $(TARGET_nlm)))" "1"
+
+$(TARGET_nlm) : $(FILES_nlm_objs) $(FILES_nlm_libs) $(OBJDIR)/$(NLM_NAME)_link.opt $(OBJDIR)/$(NLM_NAME)_link.def
+	@echo $(DL)LINK $@$(DL)
+	$(LINK) @$(OBJDIR)/$(NLM_NAME)_link.opt
+
+# This will force the link option file to be rebuilt if we change the
+# corresponding makefile
+
+$(OBJDIR)/$(NLM_NAME)_link.opt : $($(NLM_NAME)_LINKOPT_DEPENDS)
+	$(call DEL,$@)
+	@echo $(DL)GEN  $@$(DL)
+ifeq "$(findstring mwldnlm,$(LINK))" "mwldnlm" # for Metrowerks CodeWarrior
+	@echo $(DL)# Do not edit this file - it is created by make!$(DL) > $@
+	@echo $(DL)# All your changes will be lost!!$(DL)>> $@
+	@echo $(DL)-nlmversion=$(NLM_VERSION)$(DL)>> $@
+	@echo $(DL)-warnings off$(DL)>> $@
+	@echo $(DL)-zerobss$(DL)>> $@
+	@echo $(DL)-nodefaults$(DL)>> $@
+	@echo $(DL)-map $(OBJDIR)/$(NLM_NAME).map$(DL)>> $@
+	@echo $(DL)-o $(TARGET_nlm)$(DL)>> $@
+ifneq "$(FILE_nlm_copyright)" ""
+	@-$(CAT) $(FILE_nlm_copyright) >> $@
+endif
+ifeq "$(RELEASE)" "debug"
+	@echo $(DL)-g$(DL)>> $@
+	@echo $(DL)-sym codeview4$(DL)>> $@
+	@echo $(DL)-osym $(OBJDIR)/$(NLM_NAME).sym$(DL)>> $@
+endif
+	@echo $(DL)-sym internal$(DL)>> $@
+	@echo $(DL)-L$(APR)/misc/netware$(DL)>> $@
+	@echo $(DL)-L"$(METROWERKS)/Novell Support/Metrowerks Support/Libraries/Runtime"$(DL)>> $@
+	@echo $(DL)-L"$(METROWERKS)/Novell Support/Metrowerks Support/Libraries/MSL C++"$(DL)>> $@
+ifneq "$(IPV6)" ""
+	@echo $(DL)-L$(NOVELLLIBC)/include/winsock/IPV6$(DL)>> $@
+endif
+	@echo $(DL)-L$(NOVELLLIBC)/imports$(DL)>> $@
+ifneq "$(strip $(XLFLAGS))" ""
+	@echo $(DL)$(XLFLAGS)$(DL)>> $@
+endif
+ifneq "$(strip $(FILES_nlm_objs))" ""
+	@echo $(DL)$(foreach objfile,$(strip $(FILES_nlm_objs)),$(objfile))$(DL)>> $@
+endif
+ifneq "$(FILES_nlm_libs)" ""
+	@echo $(DL)$(foreach libpath,$(dir $(strip $(FILES_nlm_libs))),-L$(libpath))$(DL)>> $@
+	@echo $(DL)$(foreach libfile,$(notdir $(strip $(FILES_nlm_libs))),-l$(libfile))$(DL)>> $@
+endif
+ifneq "$(FILES_nlm_Ximports)" ""
+	@echo $(DL)$(foreach imppath,$(dir $(strip $(FILES_nlm_Ximports))),$(subst @,-L,$(imppath)))$(DL)>> $@
+endif
+	@echo $(DL)-commandfile $(@:.opt=.def)$(DL)>> $@
+else # for GNU nlmconv
+	@echo $(DL)-UT $(@:.opt=.def)$(DL)>> $@
+endif
+
+$(OBJDIR)/$(NLM_NAME)_link.def : $($(NLM_NAME)_LINKOPT_DEPENDS)
+	$(call DEL,$@)
+	@echo $(DL)GEN  $@$(DL)
+	@echo $(DL)# Do not edit this file - it is created by make!$(DL)> $@
+	@echo $(DL)# All your changes will be lost!!$(DL)>> $@
+ifneq "$(FILE_nlm_msg)" ""
+	@echo $(DL)Messages $(FILE_nlm_msg)$(DL)>> $@
+endif
+ifneq "$(FILE_nlm_hlp)" ""
+	@echo $(DL)Help $(FILE_nlm_hlp)$(DL)>> $@
+endif
+ifeq "$(FILE_nlm_copyright)" ""
+	@echo $(DL)copyright "$(NLM_COPYRIGHT)"$(DL)>> $@
+endif
+	@echo $(DL)description "$(NLM_DESCRIPTION)"$(DL)>> $@
+	@echo $(DL)threadname "$(NLM_THREAD_NAME)"$(DL)>> $@
+	@echo $(DL)screenname "$(NLM_SCREEN_NAME)"$(DL)>> $@
+	@echo $(DL)stacksize $(subst K,000,$(subst k,K,$(strip $(NLM_STACK_SIZE))))$(DL)>> $@
+	@echo $(DL)$(strip $(NLM_FLAGS))$(DL)>> $@
+	@echo $(DL)start $(NLM_ENTRY_SYM)$(DL)>> $@
+	@echo $(DL)exit $(NLM_EXIT_SYM)$(DL)>> $@
+ifneq "$(NLM_CHECK_SYM)" ""
+	@echo $(DL)check $(NLM_CHECK_SYM)$(DL)>> $@
+endif
+ifneq "$(FILES_nlm_modules)" ""
+	@echo $(DL)module $(strip $(FILES_nlm_modules))$(DL)>> $@
+endif
+ifneq "$(FILES_nlm_imports)" ""
+	@echo $(DL)import $(strip $(FILES_nlm_imports))$(DL)>> $@
+endif
+ifeq "$(findstring mwldnlm,$(LINK))" "mwldnlm" # for Metrowerks CodeWarrior
+ifneq "$(FILES_nlm_Ximports)" ""
+	@echo $(DL)import $(foreach import,$(notdir $(strip $(FILES_nlm_Ximports))),@$(import))$(DL)>> $@
+endif
+ifneq "$(FILES_nlm_exports)" ""
+	@echo $(DL)export $(foreach export,$(subst $(SPACE),$(COMMA),$(strip $(FILES_nlm_exports))),$(export))$(DL)>> $@
+endif
+ifneq "$(NLM_XDCDATA)" ""
+	@echo $(DL)xdcdata $(notdir $(NLM_XDCDATA))$(DL)>> $@
+endif
+	@echo $(DL)map $(OBJDIR)/$(NLM_NAME).map$(DL)>> $@
+else # for GNU nlmconv
+ifneq "$(FILES_nlm_Ximports)" ""
+	@echo $(DL)import $(strip $(FILES_nlm_Ximports))$(DL)>> $@
+endif
+ifneq "$(FILES_nlm_exports)" ""
+	@echo $(DL)export $(foreach export,$(subst $(SPACE),$(COMMA),$(strip $(FILES_nlm_exports))),$(export))$(DL)>> $@
+endif
+ifneq "$(NLM_XDCDATA)" ""
+	@echo $(DL)xdcdata $(NLM_XDCDATA)$(DL)>> $@
+endif
+ifneq "$(strip $(FILES_nlm_objs))" ""
+	@echo $(DL)input $(strip $(FILES_nlm_objs))$(DL)>> $@
+endif
+ifneq "$(FILES_nlm_libs)" ""
+	@echo $(DL)input $(strip $(FILES_nlm_libs))$(DL)>> $@
+endif
+	@echo $(DL)output $(TARGET_nlm)$(DL)>> $@
+ifeq "$(RELEASE)" "debug"
+	@echo $(DL)debug$(DL)>> $@
+endif
+	@echo $(DL)version $(NLM_VERSION) $(DL)>> $@
+endif
+
+else # more than one target so look for individual makefiles.
+
+# Only include these if NO_LICENSE_FILE isn't set to prevent excessive
+# recursion
+
+ifndef NO_LICENSE_FILE
+
+$(OBJDIR)/%.nlm: NWGNU% $(APRBUILD)/NWGNUhead.inc $(APRBUILD)/NWGNUtail.inc $(APRBUILD)/NWGNUenvironment.inc $(CUSTOM_INI) $(VERSION_INC) FORCE
+	@echo $(DL)Calling $<$(DL)
+	$(MAKE) -f $< $(MAKECMDGOALS) RELEASE=$(RELEASE)
+	@$(ECHONL)
+
+else
+
+$(TARGET_nlm):
+
+endif # NO_LICENSE_FILE
+
+endif # multiple targets
+
+$(INSTDIRS) ::
+	$(call MKDIR,$@)
+
+
diff --git a/helpers/PrintPath b/build/PrintPath
similarity index 74%
rename from helpers/PrintPath
rename to build/PrintPath
index 68435f3744c..2a2b48b6349 100755
--- a/helpers/PrintPath
+++ b/build/PrintPath
@@ -1,4 +1,21 @@
 #!/bin/sh
+#
+# 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.
+#
+#
 # Look for program[s] somewhere in $PATH.
 #
 # Options:
@@ -12,9 +29,6 @@
 #
 # Initially written by Jim Jagielski for the Apache configuration mechanism
 #  (with kudos to Kernighan/Pike)
-#
-# This script falls under the Apache License.
-# See http://www.apache.org/docs/LICENSE
 
 ##
 # Some "constants"
@@ -45,7 +59,7 @@ done
 #
 # First of all, all OS/2 programs have the '.exe' extension.
 # Next, we adjust PATH (or what was given to us as PATH) to
-# be whitespace seperated directories.
+# be whitespace separated directories.
 # Finally, we try to determine the best flag to use for
 # test/[] to look for an executable file. OS/2 just has '-r'
 # but with other OSs, we do some funny stuff to check to see
diff --git a/build/__init__.py b/build/__init__.py
new file mode 100644
index 00000000000..b03ce7247f7
--- /dev/null
+++ b/build/__init__.py
@@ -0,0 +1 @@
+from aprenv import *
diff --git a/build/aplibtool.c b/build/aplibtool.c
new file mode 100644
index 00000000000..1604e051ca2
--- /dev/null
+++ b/build/aplibtool.c
@@ -0,0 +1,913 @@
+/* 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 <stdio.h>
+#include <process.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <dirent.h>
+
+typedef char bool;
+#define false 0
+#define true (!false)
+
+bool silent = false;
+bool shared = false;
+bool export_all = false;
+enum mode_t { mCompile, mLink, mInstall };
+enum output_type_t { otGeneral, otObject, otProgram, otStaticLibrary, otDynamicLibrary };
+
+#ifdef __EMX__
+#  define SHELL_CMD  "sh"
+#  define CC         "gcc"
+#  define GEN_EXPORTS "emxexp"
+#  define DEF2IMPLIB_CMD "emximp"
+#  define SHARE_SW   "-Zdll -Zmtd"
+#  define USE_OMF true
+#  define TRUNCATE_DLL_NAME
+#  define DYNAMIC_LIB_EXT "dll"
+#  define EXE_EXT ".exe"
+
+#  if USE_OMF
+     /* OMF is the native format under OS/2 */
+#    define STATIC_LIB_EXT "lib"
+#    define OBJECT_EXT     "obj"
+#    define LIBRARIAN      "emxomfar -p256"
+#  else
+     /* but the alternative, a.out, can fork() which is sometimes necessary */
+#    define STATIC_LIB_EXT "a"
+#    define OBJECT_EXT     "o"
+#    define LIBRARIAN      "ar"
+#  endif
+#endif
+
+
+typedef struct {
+    char *arglist[1024];
+    int num_args;
+    enum mode_t mode;
+    enum output_type_t output_type;
+    char *output_name;
+    char *stub_name;
+    char *tmp_dirs[1024];
+    int num_tmp_dirs;
+    char *obj_files[1024];
+    int num_obj_files;
+    char *dep_libs[1024];
+    int num_dep_libs;
+} cmd_data_t;
+
+void parse_args(int argc, char *argv[], cmd_data_t *cmd_data);
+bool parse_long_opt(char *arg, cmd_data_t *cmd_data);
+int parse_short_opt(char *arg, cmd_data_t *cmd_data);
+bool parse_input_file_name(char *arg, cmd_data_t *cmd_data);
+bool parse_output_file_name(char *arg, cmd_data_t *cmd_data);
+void post_parse_fixup(cmd_data_t *cmd_data);
+void append_depenent_libs(cmd_data_t *cmd_data);
+int execute_command(cmd_data_t *cmd_data);
+char *shell_esc(const char *str);
+void cleanup_tmp_dirs(cmd_data_t *cmd_data);
+void generate_def_file(cmd_data_t *cmd_data);
+char *nameof(char *fullpath);
+char *truncate_dll_name(char *path);
+void add_dep_lib(char *lib, cmd_data_t *cmd_data);
+void add_lib_dep_libs(char *la_file, cmd_data_t *cmd_data);
+void write_dep_libs(FILE *stub_handle, cmd_data_t *cmd_data);
+
+
+int main(int argc, char *argv[])
+{
+    int rc;
+    cmd_data_t cmd_data;
+
+    memset(&cmd_data, 0, sizeof(cmd_data));
+    cmd_data.mode = mCompile;
+    cmd_data.output_type = otGeneral;
+
+    parse_args(argc, argv, &cmd_data);
+    rc = execute_command(&cmd_data);
+
+    if (rc == 0 && cmd_data.stub_name) {
+        FILE *stub_handle = fopen(cmd_data.stub_name, "w");
+
+        if (cmd_data.output_type == otStaticLibrary) {
+            write_dep_libs(stub_handle, &cmd_data);
+        }
+
+        fclose(stub_handle);
+    }
+
+    cleanup_tmp_dirs(&cmd_data);
+    return rc;
+}
+
+
+
+void parse_args(int argc, char *argv[], cmd_data_t *cmd_data)
+{
+    int a;
+    char *arg;
+    bool argused;
+
+    for (a=1; a < argc; a++) {
+        arg = argv[a];
+        argused = false;
+
+        if (arg[0] == '-') {
+            if (arg[1] == '-') {
+                argused = parse_long_opt(arg + 2, cmd_data);
+            } else if (arg[1] == 'o' && a+1 < argc) {
+                cmd_data->arglist[cmd_data->num_args++] = arg;
+                arg = argv[++a];
+                argused = parse_output_file_name(arg, cmd_data);
+            } else {
+                int num_used = parse_short_opt(arg + 1, cmd_data);
+                argused = num_used > 0;
+
+                if (num_used > 1) {
+                    a += num_used - 1;
+                }
+            }
+        } else {
+            argused = parse_input_file_name(arg, cmd_data);
+        }
+
+        if (!argused) {
+            cmd_data->arglist[cmd_data->num_args++] = arg;
+        }
+    }
+
+    post_parse_fixup(cmd_data);
+
+    if (cmd_data->output_type == otProgram || cmd_data->output_type == otDynamicLibrary) {
+        append_depenent_libs(cmd_data);
+    }
+}
+
+
+
+bool parse_long_opt(char *arg, cmd_data_t *cmd_data)
+{
+    char *equal_pos = strchr(arg, '=');
+    char var[50];
+    char value[500];
+
+    if (equal_pos) {
+        strncpy(var, arg, equal_pos - arg);
+        var[equal_pos - arg] = 0;
+        strcpy(value, equal_pos + 1);
+    } else {
+        strcpy(var, arg);
+    }
+
+    if (strcmp(var, "silent") == 0 || strcmp(var, "quiet") == 0) {
+        silent = true;
+    } else if (strcmp(var, "mode") == 0) {
+        if (strcmp(value, "compile") == 0) {
+            cmd_data->mode = mCompile;
+            cmd_data->output_type = otObject;
+        }
+
+        if (strcmp(value, "link") == 0) {
+            cmd_data->mode = mLink;
+        }
+
+        if (strcmp(value, "install") == 0) {
+            cmd_data->mode = mInstall;
+        }
+    } else if (strcmp(var, "shared") == 0) {
+        shared = true;
+    } else if (strcmp(var, "export-all") == 0) {
+        export_all = true;
+    } else if (strcmp(var, "tag") == 0) {
+      /* What's this for? Ignore for now */
+    } else {
+        return false;
+    }
+
+    return true;
+}
+
+
+
+int parse_short_opt(char *arg, cmd_data_t *cmd_data)
+{
+    if (strcmp(arg, "export-dynamic") == 0) {
+        return 1;
+    }
+
+    if (strcmp(arg, "module") == 0) {
+        shared = true;
+        return 1;
+    }
+
+    if (strcmp(arg, "Zexe") == 0) {
+        return 1;
+    }
+
+    if (strcmp(arg, "avoid-version") == 0) {
+        return 1;
+    }
+
+    if (strcmp(arg, "prefer-pic") == 0) {
+        return 1;
+    }
+
+    if (strcmp(arg, "prefer-non-pic") == 0) {
+        return 1;
+    }
+
+    if (strcmp(arg, "version-info") == 0 ) {
+        return 2;
+    }
+
+    if (strcmp(arg, "no-install") == 0) {
+        return 1;
+    }
+
+    if (strcmp(arg, "release") == 0 ) {
+        return 2;
+    }
+
+    if (strcmp(arg, "export-symbols-regex") == 0) {
+        return 2;
+    }
+
+    return 0;
+}
+
+
+
+void parse_la_input_file_name(char *arg, cmd_data_t *cmd_data)
+{
+    char *name = strrchr(arg, '/');
+    char *ext;
+    char *newarg;
+    int pathlen;
+
+    if (name == NULL) {
+        name = strrchr(arg, '\\');
+
+        if (name == NULL) {
+            name = arg;
+        } else {
+            name++;
+        }
+    } else {
+        name++;
+    }
+
+    pathlen = name - arg;
+    newarg = (char *)malloc(strlen(arg) + 10);
+    strcpy(newarg, arg);
+    newarg[pathlen] = 0;
+    strcat(newarg, ".libs/");
+
+    if (strncmp(name, "lib", 3) == 0) {
+        name += 3;
+    }
+
+    strcat(newarg, name);
+    ext = strrchr(newarg, '.') + 1;
+
+    if (shared && cmd_data->mode == mInstall) {
+        strcpy(ext, DYNAMIC_LIB_EXT);
+        newarg = truncate_dll_name(newarg);
+    } else {
+        strcpy(ext, STATIC_LIB_EXT);
+    }
+
+    cmd_data->arglist[cmd_data->num_args++] = newarg;
+}
+
+
+
+bool parse_input_file_name(char *arg, cmd_data_t *cmd_data)
+{
+    char *ext = strrchr(arg, '.');
+    char *name = strrchr(arg, '/');
+    char *newarg;
+
+    if (!ext) {
+        return false;
+    }
+
+    ext++;
+
+    if (name == NULL) {
+        name = strrchr(arg, '\\');
+
+        if (name == NULL) {
+            name = arg;
+        } else {
+            name++;
+        }
+    } else {
+        name++;
+    }
+
+    if (strcmp(ext, "lo") == 0) {
+        newarg = (char *)malloc(strlen(arg) + 10);
+        strcpy(newarg, arg);
+        strcpy(newarg + (ext - arg), OBJECT_EXT);
+        cmd_data->arglist[cmd_data->num_args++] = newarg;
+        cmd_data->obj_files[cmd_data->num_obj_files++] = newarg;
+        return true;
+    }
+
+    if (strcmp(ext, "la") == 0) {
+        add_lib_dep_libs(arg, cmd_data);
+        parse_la_input_file_name(arg, cmd_data);
+        return true;
+    }
+
+    if (strcmp(ext, "c") == 0) {
+        if (cmd_data->stub_name == NULL) {
+            cmd_data->stub_name = (char *)malloc(strlen(arg) + 4);
+            strcpy(cmd_data->stub_name, arg);
+            strcpy(strrchr(cmd_data->stub_name, '.') + 1, "lo");
+        }
+    }
+
+    if (strcmp(name, CC) == 0 || strcmp(name, CC EXE_EXT) == 0) {
+        if (cmd_data->output_type == otGeneral) {
+            cmd_data->output_type = otObject;
+        }
+    }
+
+    return false;
+}
+
+
+
+bool parse_output_file_name(char *arg, cmd_data_t *cmd_data)
+{
+    char *name = strrchr(arg, '/');
+    char *ext = strrchr(arg, '.');
+    char *newarg = NULL, *newext;
+
+    if (name == NULL) {
+        name = strrchr(arg, '\\');
+
+        if (name == NULL) {
+            name = arg;
+        } else {
+            name++;
+        }
+    } else {
+        name++;
+    }
+
+    if (!ext || stricmp(ext, EXE_EXT) == 0) {
+        cmd_data->output_type = otProgram;
+        newarg = (char *)malloc(strlen(arg) + 5);
+        strcpy(newarg, arg);
+
+        if (!ext) {
+            strcat(newarg, EXE_EXT);
+            cmd_data->stub_name = arg;
+        }
+
+        cmd_data->arglist[cmd_data->num_args++] = newarg;
+        cmd_data->output_name = newarg;
+        return true;
+    }
+
+    ext++;
+
+    if (strcmp(ext, "exe") == 0) {
+        cmd_data->output_type = otProgram;
+        cmd_data->output_name = newarg;
+        return false;
+    }
+
+    if (strcmp(ext, "dll") == 0) {
+        cmd_data->output_type = otDynamicLibrary;
+        cmd_data->output_name = newarg;
+        return false;
+    }
+
+    if (strcmp(ext, "la") == 0) {
+        cmd_data->stub_name = arg;
+        cmd_data->output_type = shared ? otDynamicLibrary : otStaticLibrary;
+        newarg = (char *)malloc(strlen(arg) + 10);
+        mkdir(".libs", 0);
+        strcpy(newarg, ".libs/");
+
+        if (strrchr(arg, '/')) {
+          arg = strrchr(arg, '/') + 1;
+        }
+
+        if (strncmp(arg, "lib", 3) == 0) {
+            arg += 3;
+        }
+
+        strcat(newarg, arg);
+        newext = strrchr(newarg, '.') + 1;
+        strcpy(newext, shared ? DYNAMIC_LIB_EXT : STATIC_LIB_EXT);
+
+#ifdef TRUNCATE_DLL_NAME
+        if (shared) {
+          newarg = truncate_dll_name(newarg);
+        }
+#endif
+
+        cmd_data->arglist[cmd_data->num_args++] = newarg;
+        cmd_data->output_name = newarg;
+        return true;
+    }
+
+    if (strcmp(ext, "lo") == 0) {
+        cmd_data->stub_name = arg;
+        cmd_data->output_type = otObject;
+        newarg = (char *)malloc(strlen(arg) + 2);
+        strcpy(newarg, arg);
+        ext = strrchr(newarg, '.') + 1;
+        strcpy(ext, OBJECT_EXT);
+        cmd_data->arglist[cmd_data->num_args++] = newarg;
+        cmd_data->output_name = newarg;
+        return true;
+    }
+
+    return false;
+}
+
+
+
+void post_parse_fixup(cmd_data_t *cmd_data)
+{
+    int a;
+    char *arg;
+    char *ext;
+
+    if (cmd_data->output_type == otStaticLibrary && cmd_data->mode == mLink) {
+        /* We do a real hatchet job on the args when making a static library
+         * removing all compiler switches & any other cruft that ar won't like
+         * We also need to explode any libraries listed
+         */
+
+        for (a=0; a < cmd_data->num_args; a++) {
+            arg = cmd_data->arglist[a];
+
+            if (arg) {
+                ext = strrchr(arg, '.');
+
+                if (ext) {
+                    ext++;
+                }
+
+                if (arg[0] == '-') {
+                    cmd_data->arglist[a] = NULL;
+
+                    if (strcmp(arg, "-rpath") == 0 && a+1 < cmd_data->num_args) {
+                        cmd_data->arglist[a+1] = NULL;
+                    }
+
+                    if (strcmp(arg, "-R") == 0 && a+1 < cmd_data->num_args) {
+                        cmd_data->arglist[a+1] = NULL;
+                    }
+
+                    if (strcmp(arg, "-version-info") == 0 && a+1 < cmd_data->num_args) {
+                        cmd_data->arglist[a+1] = NULL;
+                    }
+
+                    if (strcmp(arg, "-Zstack") == 0 && a+1 < cmd_data->num_args) {
+                        cmd_data->arglist[a+1] = NULL;
+                    }
+
+                    if (strcmp(arg, "-o") == 0) {
+                        a++;
+                    }
+
+                    if (arg[1] == 'l') {
+                        add_dep_lib(arg, cmd_data);
+                    }
+                }
+
+                if (strcmp(arg, CC) == 0 || strcmp(arg, CC EXE_EXT) == 0) {
+                    cmd_data->arglist[a] = LIBRARIAN " cr";
+                }
+
+                if (ext) {
+                    if (strcmp(ext, "h") == 0 || strcmp(ext, "c") == 0) {
+                        /* ignore source files, they don't belong in a library */
+                        cmd_data->arglist[a] = NULL;
+                    }
+
+                    if (strcmp(ext, STATIC_LIB_EXT) == 0) {
+                        cmd_data->arglist[a] = NULL;
+                    }
+                }
+            }
+        }
+    }
+
+    if (cmd_data->output_type == otDynamicLibrary) {
+        for (a=0; a < cmd_data->num_args; a++) {
+            arg = cmd_data->arglist[a];
+
+            if (arg) {
+                if (strcmp(arg, "-rpath") == 0 && a+1 < cmd_data->num_args) {
+                    cmd_data->arglist[a] = NULL;
+                    cmd_data->arglist[a+1] = NULL;
+                }
+            }
+        }
+
+        if (export_all) {
+            generate_def_file(cmd_data);
+        }
+    }
+
+    if (cmd_data->output_type == otProgram || cmd_data->output_type == otGeneral) {
+        for (a=0; a < cmd_data->num_args; a++) {
+            arg = cmd_data->arglist[a];
+
+            if (arg) {
+                if (strcmp(arg, "-rpath") == 0 && a+1 < cmd_data->num_args) {
+                    cmd_data->arglist[a] = NULL;
+                    cmd_data->arglist[a+1] = NULL;
+                }
+            }
+        }
+    }
+
+#if USE_OMF
+    if (cmd_data->output_type == otObject ||
+        cmd_data->output_type == otProgram ||
+        cmd_data->output_type == otDynamicLibrary) {
+        cmd_data->arglist[cmd_data->num_args++] = "-Zomf";
+    }
+#endif
+
+    if (shared && (cmd_data->output_type == otObject || cmd_data->output_type == otDynamicLibrary)) {
+        cmd_data->arglist[cmd_data->num_args++] = SHARE_SW;
+    }
+}
+
+
+
+void append_depenent_libs(cmd_data_t *cmd_data)
+{
+    int l;
+
+    for (l = 0; l < cmd_data->num_dep_libs; l++) {
+        char *arg = cmd_data->dep_libs[l];
+        char *ext = strrchr(arg, '.');
+
+        if (ext && strcmp(ext, ".la") == 0) {
+            parse_la_input_file_name(cmd_data->dep_libs[l], cmd_data);
+        }
+        else {
+            cmd_data->arglist[cmd_data->num_args++] = arg;
+        }
+    }
+}
+
+
+
+int execute_command(cmd_data_t *cmd_data)
+{
+    int target = 0;
+    char *command;
+    int a, total_len = 0;
+    char *args[4];
+
+    for (a=0; a < cmd_data->num_args; a++) {
+        if (cmd_data->arglist[a]) {
+            total_len += strlen(cmd_data->arglist[a]) + 1;
+        }
+    }
+
+    command = (char *)malloc( total_len );
+    command[0] = 0;
+
+    for (a=0; a < cmd_data->num_args; a++) {
+        if (cmd_data->arglist[a]) {
+            strcat(command, cmd_data->arglist[a]);
+            strcat(command, " ");
+        }
+    }
+
+    command[strlen(command)-1] = 0;
+
+    if (!silent) {
+        puts(command);
+    }
+
+    cmd_data->num_args = target;
+    cmd_data->arglist[cmd_data->num_args] = NULL;
+    command = shell_esc(command);
+
+    args[0] = SHELL_CMD;
+    args[1] = "-c";
+    args[2] = command;
+    args[3] = NULL;
+    return spawnvp(P_WAIT, args[0], args);
+}
+
+
+
+char *shell_esc(const char *str)
+{
+    char *cmd;
+    unsigned char *d;
+    const unsigned char *s;
+
+    cmd = (char *)malloc(2 * strlen(str) + 1);
+    d = (unsigned char *)cmd;
+    s = (const unsigned char *)str;
+
+    for (; *s; ++s) {
+        if (*s == '"' || *s == '\\') {
+            *d++ = '\\';
+        }
+        *d++ = *s;
+    }
+
+    *d = '\0';
+    return cmd;
+}
+
+
+
+void add_dep_lib(char *lib, cmd_data_t *cmd_data)
+{
+    int l;
+
+    while (isspace(*lib)) {
+        lib++;
+    }
+
+    if (*lib) {
+        for (l = 0; l < cmd_data->num_dep_libs; l++) {
+            if (stricmp(cmd_data->dep_libs[l], lib) == 0) {
+                return;
+            }
+        }
+    }
+
+    if (*lib) {
+        cmd_data->dep_libs[cmd_data->num_dep_libs++] = strdup(lib);
+    }
+}
+
+
+
+void write_dep_libs(FILE *stub_handle, cmd_data_t *cmd_data)
+{
+    int l;
+    char cwd[MAXPATHLEN];
+
+    getwd(cwd);
+    fputs("dependency_libs='", stub_handle);
+
+    for (l = 0; l < cmd_data->num_dep_libs; l++) {
+        if (l) {
+            fputs(" ", stub_handle);
+        }
+
+        if (cmd_data->dep_libs[l][0] != '/' && cmd_data->dep_libs[l][0] != '-') {
+            fprintf(stub_handle, "%s/%s", cwd, cmd_data->dep_libs[l]);
+        }
+        else {
+            fputs(cmd_data->dep_libs[l], stub_handle);
+        }
+    }
+
+    fputs("'\n", stub_handle);
+}
+
+
+
+void add_lib_dep_libs(char *la_file, cmd_data_t *cmd_data)
+{
+    FILE *hla;
+    char line[16384];
+
+    add_dep_lib(la_file, cmd_data);
+    hla = fopen(la_file, "r");
+
+    if (hla == NULL) {
+        fprintf(stderr, "warning: couldn't open %s\n", la_file);
+        return;
+    }
+
+    while (fgets(line, sizeof(line), hla) != NULL) {
+        char *pos = strchr(line, '=');
+
+        if (pos) {
+            *pos = 0;
+            pos++;
+
+            if (*pos == '\'') {
+                char *end;
+                pos++;
+                end = strchr(pos, '\'');
+
+                if (end != NULL) {
+                    *end = 0;
+                }
+            }
+
+            if (strcmp(line, "dependency_libs") == 0) {
+                while (*pos) {
+                    char *end = strchr(pos, ' ');
+
+                    if (end != NULL) {
+                        *end = 0;
+                    }
+
+                    add_dep_lib(pos, cmd_data);
+
+                    if (end) {
+                        pos = end + 1;
+                    }
+                    else {
+                        break;
+                    }
+                }
+            }
+        }
+    }
+
+    fclose(hla);
+}
+
+
+
+void cleanup_tmp_dir(char *dirname)
+{
+    DIR *dir;
+    struct dirent *entry;
+    char fullname[1024];
+
+    dir = opendir(dirname);
+
+    if (dir == NULL)
+        return;
+
+    while ((entry = readdir(dir)) != NULL) {
+        if (entry->d_name[0] != '.') {
+            strcpy(fullname, dirname);
+            strcat(fullname, "/");
+            strcat(fullname, entry->d_name);
+            remove(fullname);
+        }
+    }
+
+    rmdir(dirname);
+}
+
+
+
+void cleanup_tmp_dirs(cmd_data_t *cmd_data)
+{
+    int d;
+
+    for (d=0; d < cmd_data->num_tmp_dirs; d++) {
+        cleanup_tmp_dir(cmd_data->tmp_dirs[d]);
+    }
+}
+
+
+
+void generate_def_file(cmd_data_t *cmd_data)
+{
+    char def_file[1024];
+    char implib_file[1024];
+    char *ext;
+    FILE *hDef;
+    char *export_args[1024];
+    int num_export_args = 0;
+    char *cmd;
+    int cmd_size = 0;
+    int a;
+
+    if (cmd_data->output_name) {
+        strcpy(def_file, cmd_data->output_name);
+        strcat(def_file, ".def");
+        hDef = fopen(def_file, "w");
+
+        if (hDef != NULL) {
+            fprintf(hDef, "LIBRARY '%s' INITINSTANCE\n", nameof(cmd_data->output_name));
+            fprintf(hDef, "DATA NONSHARED\n");
+            fprintf(hDef, "EXPORTS\n");
+            fclose(hDef);
+
+            for (a=0; a < cmd_data->num_obj_files; a++) {
+                cmd_size += strlen(cmd_data->obj_files[a]) + 1;
+            }
+
+            cmd_size += strlen(GEN_EXPORTS) + strlen(def_file) + 3;
+            cmd = (char *)malloc(cmd_size);
+            strcpy(cmd, GEN_EXPORTS);
+
+            for (a=0; a < cmd_data->num_obj_files; a++) {
+                strcat(cmd, " ");
+                strcat(cmd, cmd_data->obj_files[a] );
+            }
+
+            strcat(cmd, ">>");
+            strcat(cmd, def_file);
+            puts(cmd);
+            export_args[num_export_args++] = SHELL_CMD;
+            export_args[num_export_args++] = "-c";
+            export_args[num_export_args++] = cmd;
+            export_args[num_export_args++] = NULL;
+            spawnvp(P_WAIT, export_args[0], export_args);
+            cmd_data->arglist[cmd_data->num_args++] = strdup(def_file);
+
+            /* Now make an import library for the dll */
+            num_export_args = 0;
+            export_args[num_export_args++] = DEF2IMPLIB_CMD;
+            export_args[num_export_args++] = "-o";
+
+            strcpy(implib_file, ".libs/");
+            strcat(implib_file, cmd_data->stub_name);
+            ext = strrchr(implib_file, '.');
+
+            if (ext)
+                *ext = 0;
+
+            strcat(implib_file, ".");
+            strcat(implib_file, STATIC_LIB_EXT);
+
+            export_args[num_export_args++] = implib_file;
+            export_args[num_export_args++] = def_file;
+            export_args[num_export_args++] = NULL;
+            spawnvp(P_WAIT, export_args[0], export_args);
+        }
+    }
+}
+
+
+
+/* returns just a file's name without path or extension */
+char *nameof(char *fullpath)
+{
+    char buffer[1024];
+    char *ext;
+    char *name = strrchr(fullpath, '/');
+
+    if (name == NULL) {
+        name = strrchr(fullpath, '\\');
+    }
+
+    if (name == NULL) {
+        name = fullpath;
+    } else {
+        name++;
+    }
+
+    strcpy(buffer, name);
+    ext = strrchr(buffer, '.');
+
+    if (ext) {
+        *ext = 0;
+        return strdup(buffer);
+    }
+
+    return name;
+}
+
+
+
+char *truncate_dll_name(char *path)
+{
+    /* Cut DLL name down to 8 characters after removing any mod_ prefix */
+    char *tmppath = strdup(path);
+    char *newname = strrchr(tmppath, '/') + 1;
+    char *ext = strrchr(tmppath, '.');
+    int len;
+
+    if (ext == NULL)
+        return tmppath;
+
+    len = ext - newname;
+
+    if (strncmp(newname, "mod_", 4) == 0) {
+        strcpy(newname, newname + 4);
+        len -= 4;
+    }
+
+    if (len > 8) {
+        strcpy(newname + 8, strchr(newname, '.'));
+    }
+
+    return tmppath;
+}
diff --git a/build/apr_common.m4 b/build/apr_common.m4
new file mode 100644
index 00000000000..6b5c0f033b9
--- /dev/null
+++ b/build/apr_common.m4
@@ -0,0 +1,990 @@
+dnl -------------------------------------------------------- -*- autoconf -*-
+dnl Licensed to the Apache Software Foundation (ASF) under one or more
+dnl contributor license agreements.  See the NOTICE file distributed with
+dnl this work for additional information regarding copyright ownership.
+dnl The ASF licenses this file to You under the Apache License, Version 2.0
+dnl (the "License"); you may not use this file except in compliance with
+dnl the License.  You may obtain a copy of the License at
+dnl
+dnl     http://www.apache.org/licenses/LICENSE-2.0
+dnl
+dnl Unless required by applicable law or agreed to in writing, software
+dnl distributed under the License is distributed on an "AS IS" BASIS,
+dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+dnl See the License for the specific language governing permissions and
+dnl limitations under the License.
+
+dnl
+dnl apr_common.m4: APR's general-purpose autoconf macros
+dnl
+
+dnl
+dnl APR_CONFIG_NICE(filename)
+dnl
+dnl Saves a snapshot of the configure command-line for later reuse
+dnl
+AC_DEFUN([APR_CONFIG_NICE], [
+  rm -f $1
+  cat >$1<<EOF
+#! /bin/sh
+#
+# Created by configure
+
+EOF
+  if test -n "$CC"; then
+    echo "CC=\"$CC\"; export CC" >> $1
+  fi
+  if test -n "$CFLAGS"; then
+    echo "CFLAGS=\"$CFLAGS\"; export CFLAGS" >> $1
+  fi
+  if test -n "$CPPFLAGS"; then
+    echo "CPPFLAGS=\"$CPPFLAGS\"; export CPPFLAGS" >> $1
+  fi
+  if test -n "$LDFLAGS"; then
+    echo "LDFLAGS=\"$LDFLAGS\"; export LDFLAGS" >> $1
+  fi
+  if test -n "$LTFLAGS"; then
+    echo "LTFLAGS=\"$LTFLAGS\"; export LTFLAGS" >> $1
+  fi
+  if test -n "$LIBS"; then
+    echo "LIBS=\"$LIBS\"; export LIBS" >> $1
+  fi
+  if test -n "$INCLUDES"; then
+    echo "INCLUDES=\"$INCLUDES\"; export INCLUDES" >> $1
+  fi
+  if test -n "$NOTEST_CFLAGS"; then
+    echo "NOTEST_CFLAGS=\"$NOTEST_CFLAGS\"; export NOTEST_CFLAGS" >> $1
+  fi
+  if test -n "$NOTEST_CPPFLAGS"; then
+    echo "NOTEST_CPPFLAGS=\"$NOTEST_CPPFLAGS\"; export NOTEST_CPPFLAGS" >> $1
+  fi
+  if test -n "$NOTEST_LDFLAGS"; then
+    echo "NOTEST_LDFLAGS=\"$NOTEST_LDFLAGS\"; export NOTEST_LDFLAGS" >> $1
+  fi
+  if test -n "$NOTEST_LIBS"; then
+    echo "NOTEST_LIBS=\"$NOTEST_LIBS\"; export NOTEST_LIBS" >> $1
+  fi
+
+  # Retrieve command-line arguments.
+  eval "set x $[0] $ac_configure_args"
+  shift
+
+  for arg
+  do
+    APR_EXPAND_VAR(arg, $arg)
+    echo "\"[$]arg\" \\" >> $1
+  done
+  echo '"[$]@"' >> $1
+  chmod +x $1
+])dnl
+
+dnl APR_MKDIR_P_CHECK(fallback-mkdir-p)
+dnl checks whether mkdir -p works
+AC_DEFUN([APR_MKDIR_P_CHECK], [
+  AC_CACHE_CHECK(for working mkdir -p, ac_cv_mkdir_p,[
+    test -d conftestdir && rm -rf conftestdir
+    mkdir -p conftestdir/somedir >/dev/null 2>&1
+    if test -d conftestdir/somedir; then
+      ac_cv_mkdir_p=yes
+    else
+      ac_cv_mkdir_p=no
+    fi
+    rm -rf conftestdir
+  ])
+  if test "$ac_cv_mkdir_p" = "yes"; then
+      mkdir_p="mkdir -p"
+  else
+      mkdir_p="$1"
+  fi
+])
+
+dnl
+dnl APR_SUBDIR_CONFIG(dir [, sub-package-cmdline-args, args-to-drop])
+dnl
+dnl dir: directory to find configure in
+dnl sub-package-cmdline-args: arguments to add to the invocation (optional)
+dnl args-to-drop: arguments to drop from the invocation (optional)
+dnl
+dnl Note: This macro relies on ac_configure_args being set properly.
+dnl
+dnl The args-to-drop argument is shoved into a case statement, so
+dnl multiple arguments can be separated with a |.
+dnl
+dnl Note: Older versions of autoconf do not single-quote args, while 2.54+
+dnl places quotes around every argument.  So, if you want to drop the
+dnl argument called --enable-layout, you must pass the third argument as:
+dnl [--enable-layout=*|\'--enable-layout=*]
+dnl
+dnl Trying to optimize this is left as an exercise to the reader who wants
+dnl to put up with more autoconf craziness.  I give up.
+dnl
+AC_DEFUN([APR_SUBDIR_CONFIG], [
+  # save our work to this point; this allows the sub-package to use it
+  AC_CACHE_SAVE
+
+  echo "configuring package in $1 now"
+  ac_popdir=`pwd`
+  apr_config_subdirs="$1"
+  test -d $1 || $mkdir_p $1
+  ac_abs_srcdir=`(cd $srcdir/$1 && pwd)`
+  cd $1
+
+changequote(, )dnl
+      # A "../" for each directory in /$config_subdirs.
+      ac_dots=`echo $apr_config_subdirs|sed -e 's%^\./%%' -e 's%[^/]$%&/%' -e 's%[^/]*/%../%g'`
+changequote([, ])dnl
+
+  # Make the cache file pathname absolute for the subdirs
+  # required to correctly handle subdirs that might actually
+  # be symlinks
+  case "$cache_file" in
+  /*) # already absolute
+    ac_sub_cache_file=$cache_file ;;
+  *)  # Was relative path.
+    ac_sub_cache_file="$ac_popdir/$cache_file" ;;
+  esac
+
+  ifelse($3, [], [apr_configure_args=$ac_configure_args],[
+  apr_configure_args=
+  apr_sep=
+  for apr_configure_arg in $ac_configure_args
+  do
+    case "$apr_configure_arg" in
+      $3)
+        continue ;;
+    esac
+    apr_configure_args="$apr_configure_args$apr_sep'$apr_configure_arg'"
+    apr_sep=" "
+  done
+  ])
+
+  dnl autoconf doesn't add --silent to ac_configure_args; explicitly pass it
+  test "x$silent" = "xyes" && apr_configure_args="$apr_configure_args --silent"
+
+  dnl AC_CONFIG_SUBDIRS silences option warnings, emulate this for 2.62
+  apr_configure_args="--disable-option-checking $apr_configure_args" 
+
+  dnl The eval makes quoting arguments work - specifically the second argument
+  dnl where the quoting mechanisms used is "" rather than [].
+  dnl
+  dnl We need to execute another shell because some autoconf/shell combinations
+  dnl will choke after doing repeated APR_SUBDIR_CONFIG()s.  (Namely Solaris
+  dnl and autoconf-2.54+)
+  if eval $SHELL $ac_abs_srcdir/configure $apr_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_abs_srcdir $2
+  then :
+    echo "$1 configured properly"
+  else
+    echo "configure failed for $1"
+    exit 1
+  fi
+
+  cd $ac_popdir
+
+  # grab any updates from the sub-package
+  AC_CACHE_LOAD
+])dnl
+
+dnl
+dnl APR_SAVE_THE_ENVIRONMENT(variable_name)
+dnl
+dnl Stores the variable (usually a Makefile macro) for later restoration
+dnl
+AC_DEFUN([APR_SAVE_THE_ENVIRONMENT], [
+  apr_ste_save_$1="$$1"
+])dnl
+
+dnl
+dnl APR_RESTORE_THE_ENVIRONMENT(variable_name, prefix_)
+dnl
+dnl Uses the previously saved variable content to figure out what configure
+dnl has added to the variable, moving the new bits to prefix_variable_name
+dnl and restoring the original variable contents.  This makes it possible
+dnl for a user to override configure when it does something stupid.
+dnl
+AC_DEFUN([APR_RESTORE_THE_ENVIRONMENT], [
+dnl Check whether $apr_ste_save_$1 is empty or
+dnl only whitespace. The verbatim "X" is token number 1,
+dnl the following whitespace will be ignored.
+set X $apr_ste_save_$1
+if test ${#} -eq 1; then
+  $2$1="$$1"
+  $1=
+else
+  if test "x$apr_ste_save_$1" = "x$$1"; then
+    $2$1=
+  else
+    $2$1=`echo "$$1" | sed -e "s%${apr_ste_save_$1}%%"`
+    $1="$apr_ste_save_$1"
+  fi
+fi
+if test "x$silent" != "xyes"; then
+  echo "  restoring $1 to \"$$1\""
+  echo "  setting $2$1 to \"$$2$1\""
+fi
+AC_SUBST($2$1)
+])dnl
+
+dnl
+dnl APR_SETIFNULL(variable, value)
+dnl
+dnl  Set variable iff it's currently null
+dnl
+AC_DEFUN([APR_SETIFNULL], [
+  if test -z "$$1"; then
+    test "x$silent" != "xyes" && echo "  setting $1 to \"$2\""
+    $1="$2"
+  fi
+])dnl
+
+dnl
+dnl APR_SETVAR(variable, value)
+dnl
+dnl  Set variable no matter what
+dnl
+AC_DEFUN([APR_SETVAR], [
+  test "x$silent" != "xyes" && echo "  forcing $1 to \"$2\""
+  $1="$2"
+])dnl
+
+dnl
+dnl APR_ADDTO(variable, value)
+dnl
+dnl  Add value to variable
+dnl
+AC_DEFUN([APR_ADDTO], [
+  if test "x$$1" = "x"; then
+    test "x$silent" != "xyes" && echo "  setting $1 to \"$2\""
+    $1="$2"
+  else
+    apr_addto_bugger="$2"
+    for i in $apr_addto_bugger; do
+      apr_addto_duplicate="0"
+      for j in $$1; do
+        if test "x$i" = "x$j"; then
+          apr_addto_duplicate="1"
+          break
+        fi
+      done
+      if test $apr_addto_duplicate = "0"; then
+        test "x$silent" != "xyes" && echo "  adding \"$i\" to $1"
+        $1="$$1 $i"
+      fi
+    done
+  fi
+])dnl
+
+dnl
+dnl APR_REMOVEFROM(variable, value)
+dnl
+dnl Remove a value from a variable
+dnl
+AC_DEFUN([APR_REMOVEFROM], [
+  if test "x$$1" = "x$2"; then
+    test "x$silent" != "xyes" && echo "  nulling $1"
+    $1=""
+  else
+    apr_new_bugger=""
+    apr_removed=0
+    for i in $$1; do
+      if test "x$i" != "x$2"; then
+        apr_new_bugger="$apr_new_bugger $i"
+      else
+        apr_removed=1
+      fi
+    done
+    if test $apr_removed = "1"; then
+      test "x$silent" != "xyes" && echo "  removed \"$2\" from $1"
+      $1=$apr_new_bugger
+    fi
+  fi
+]) dnl
+
+dnl
+dnl APR_CHECK_DEFINE_FILES( symbol, header_file [header_file ...] )
+dnl
+AC_DEFUN([APR_CHECK_DEFINE_FILES], [
+  AC_CACHE_CHECK([for $1 in $2],ac_cv_define_$1,[
+    ac_cv_define_$1=no
+    for curhdr in $2
+    do
+      AC_EGREP_CPP(YES_IS_DEFINED, [
+#include <$curhdr>
+#ifdef $1
+YES_IS_DEFINED
+#endif
+      ], ac_cv_define_$1=yes)
+    done
+  ])
+  if test "$ac_cv_define_$1" = "yes"; then
+    AC_DEFINE(HAVE_$1, 1, [Define if $1 is defined])
+  fi
+])
+
+
+dnl
+dnl APR_CHECK_DEFINE(symbol, header_file)
+dnl
+AC_DEFUN([APR_CHECK_DEFINE], [
+  AC_CACHE_CHECK([for $1 in $2],ac_cv_define_$1,[
+    AC_EGREP_CPP(YES_IS_DEFINED, [
+#include <$2>
+#ifdef $1
+YES_IS_DEFINED
+#endif
+    ], ac_cv_define_$1=yes, ac_cv_define_$1=no)
+  ])
+  if test "$ac_cv_define_$1" = "yes"; then
+    AC_DEFINE(HAVE_$1, 1, [Define if $1 is defined in $2])
+  fi
+])
+
+dnl
+dnl APR_CHECK_APR_DEFINE( symbol )
+dnl
+AC_DEFUN([APR_CHECK_APR_DEFINE], [
+apr_old_cppflags=$CPPFLAGS
+CPPFLAGS="$CPPFLAGS $INCLUDES"
+AC_EGREP_CPP(YES_IS_DEFINED, [
+#include <apr.h>
+#if $1
+YES_IS_DEFINED
+#endif
+], ac_cv_define_$1=yes, ac_cv_define_$1=no)
+CPPFLAGS=$apr_old_cppflags
+])
+
+dnl APR_CHECK_FILE(filename); set ac_cv_file_filename to
+dnl "yes" if 'filename' is readable, else "no".
+dnl @deprecated! - use AC_CHECK_FILE instead
+AC_DEFUN([APR_CHECK_FILE], [
+dnl Pick a safe variable name
+define([apr_cvname], ac_cv_file_[]translit([$1], [./+-], [__p_]))
+AC_CACHE_CHECK([for $1], [apr_cvname],
+[if test -r $1; then
+   apr_cvname=yes
+ else
+   apr_cvname=no
+ fi])
+])
+
+define(APR_IFALLYES,[dnl
+ac_rc=yes
+for ac_spec in $1; do
+    ac_type=`echo "$ac_spec" | sed -e 's/:.*$//'`
+    ac_item=`echo "$ac_spec" | sed -e 's/^.*://'`
+    case $ac_type in
+        header )
+            ac_item=`echo "$ac_item" | sed 'y%./+-%__p_%'`
+            ac_var="ac_cv_header_$ac_item"
+            ;;
+        file )
+            ac_item=`echo "$ac_item" | sed 'y%./+-%__p_%'`
+            ac_var="ac_cv_file_$ac_item"
+            ;;
+        func )   ac_var="ac_cv_func_$ac_item"   ;;
+        struct ) ac_var="ac_cv_struct_$ac_item" ;;
+        define ) ac_var="ac_cv_define_$ac_item" ;;
+        custom ) ac_var="$ac_item" ;;
+    esac
+    eval "ac_val=\$$ac_var"
+    if test ".$ac_val" != .yes; then
+        ac_rc=no
+        break
+    fi
+done
+if test ".$ac_rc" = .yes; then
+    :
+    $2
+else
+    :
+    $3
+fi
+])
+
+
+define(APR_BEGIN_DECISION,[dnl
+ac_decision_item='$1'
+ac_decision_msg='FAILED'
+ac_decision=''
+])
+
+
+AC_DEFUN([APR_DECIDE],[dnl
+dnl Define the flag (or not) in apr_private.h via autoheader
+AH_TEMPLATE($1, [Define if $2 will be used])
+ac_decision='$1'
+ac_decision_msg='$2'
+ac_decision_$1=yes
+ac_decision_$1_msg='$2'
+])
+
+
+define(APR_DECISION_OVERRIDE,[dnl
+    ac_decision=''
+    for ac_item in $1; do
+         eval "ac_decision_this=\$ac_decision_${ac_item}"
+         if test ".$ac_decision_this" = .yes; then
+             ac_decision=$ac_item
+             eval "ac_decision_msg=\$ac_decision_${ac_item}_msg"
+         fi
+    done
+])
+
+
+define(APR_DECISION_FORCE,[dnl
+ac_decision="$1"
+eval "ac_decision_msg=\"\$ac_decision_${ac_decision}_msg\""
+])
+
+
+define(APR_END_DECISION,[dnl
+if test ".$ac_decision" = .; then
+    echo "[$]0:Error: decision on $ac_decision_item failed" 1>&2
+    exit 1
+else
+    if test ".$ac_decision_msg" = .; then
+        ac_decision_msg="$ac_decision"
+    fi
+    AC_DEFINE_UNQUOTED(${ac_decision_item})
+    AC_MSG_RESULT([decision on $ac_decision_item... $ac_decision_msg])
+fi
+])
+
+
+dnl
+dnl APR_CHECK_SIZEOF_EXTENDED(INCLUDES, TYPE [, CROSS_SIZE])
+dnl
+dnl A variant of AC_CHECK_SIZEOF which allows the checking of
+dnl sizes of non-builtin types
+dnl
+AC_DEFUN([APR_CHECK_SIZEOF_EXTENDED],
+[changequote(<<, >>)dnl
+dnl The name to #define.
+define(<<AC_TYPE_NAME>>, translit(sizeof_$2, [a-z *], [A-Z_P]))dnl
+dnl The cache variable name.
+define(<<AC_CV_NAME>>, translit(ac_cv_sizeof_$2, [ *], [_p]))dnl
+changequote([, ])dnl
+AC_MSG_CHECKING(size of $2)
+AC_CACHE_VAL(AC_CV_NAME,
+[AC_TRY_RUN([#include <stdio.h>
+$1
+#ifdef WIN32
+#define binmode "b"
+#else
+#define binmode
+#endif
+main()
+{
+  FILE *f=fopen("conftestval", "w" binmode);
+  if (!f) exit(1);
+  fprintf(f, "%d\n", sizeof($2));
+  exit(0);
+}], AC_CV_NAME=`cat conftestval`, AC_CV_NAME=0, ifelse([$3],,,
+AC_CV_NAME=$3))])dnl
+AC_MSG_RESULT($AC_CV_NAME)
+AC_DEFINE_UNQUOTED(AC_TYPE_NAME, $AC_CV_NAME, [The size of ]$2)
+undefine([AC_TYPE_NAME])dnl
+undefine([AC_CV_NAME])dnl
+])
+
+
+dnl
+dnl APR_TRY_COMPILE_NO_WARNING(INCLUDES, FUNCTION-BODY,
+dnl             [ACTIONS-IF-NO-WARNINGS], [ACTIONS-IF-WARNINGS])
+dnl
+dnl Tries a compile test with warnings activated so that the result
+dnl is false if the code doesn't compile cleanly.  For compilers
+dnl where it is not known how to activate a "fail-on-error" mode,
+dnl it is undefined which of the sets of actions will be run.
+dnl
+AC_DEFUN([APR_TRY_COMPILE_NO_WARNING],
+[apr_save_CFLAGS=$CFLAGS
+ CFLAGS="$CFLAGS $CFLAGS_WARN"
+ if test "$ac_cv_prog_gcc" = "yes"; then 
+   CFLAGS="$CFLAGS -Werror"
+ fi
+ AC_COMPILE_IFELSE(
+  [AC_LANG_SOURCE(
+   [#include "confdefs.h"
+   ]
+   [[$1]]
+   [int main(int argc, const char *const *argv) {]
+   [[$2]]
+   [   return 0; }]
+  )],
+  [$3], [$4])
+ CFLAGS=$apr_save_CFLAGS
+])
+
+dnl
+dnl APR_CHECK_STRERROR_R_RC
+dnl
+dnl  Decide which style of retcode is used by this system's 
+dnl  strerror_r().  It either returns int (0 for success, -1
+dnl  for failure), or it returns a pointer to the error 
+dnl  string.
+dnl
+dnl
+AC_DEFUN([APR_CHECK_STRERROR_R_RC], [
+AC_MSG_CHECKING(for type of return code from strerror_r)
+AC_TRY_RUN([
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+main()
+{
+  char buf[1024];
+  if (strerror_r(ERANGE, buf, sizeof buf) < 1) {
+    exit(0);
+  }
+  else {
+    exit(1);
+  }
+}], [
+    ac_cv_strerror_r_rc_int=yes ], [
+    ac_cv_strerror_r_rc_int=no ], [
+    ac_cv_strerror_r_rc_int=no ] )
+if test "x$ac_cv_strerror_r_rc_int" = xyes; then
+  AC_DEFINE(STRERROR_R_RC_INT, 1, [Define if strerror returns int])
+  msg="int"
+else
+  msg="pointer"
+fi
+AC_MSG_RESULT([$msg])
+] )
+
+dnl
+dnl APR_CHECK_DIRENT_INODE
+dnl
+dnl  Decide if d_fileno or d_ino are available in the dirent
+dnl  structure on this platform.  Single UNIX Spec says d_ino,
+dnl  BSD uses d_fileno.  Undef to find the real beast.
+dnl
+AC_DEFUN([APR_CHECK_DIRENT_INODE], [
+AC_CACHE_CHECK([for inode member of struct dirent], apr_cv_dirent_inode, [
+apr_cv_dirent_inode=no
+AC_TRY_COMPILE([
+#include <sys/types.h>
+#include <dirent.h>
+],[
+#ifdef d_ino
+#undef d_ino
+#endif
+struct dirent de; de.d_fileno;
+], apr_cv_dirent_inode=d_fileno)
+if test "$apr_cv_dirent_inode" = "no"; then
+AC_TRY_COMPILE([
+#include <sys/types.h>
+#include <dirent.h>
+],[
+#ifdef d_fileno
+#undef d_fileno
+#endif
+struct dirent de; de.d_ino;
+], apr_cv_dirent_inode=d_ino)
+fi
+])
+if test "$apr_cv_dirent_inode" != "no"; then
+  AC_DEFINE_UNQUOTED(DIRENT_INODE, $apr_cv_dirent_inode, 
+    [Define if struct dirent has an inode member])
+fi
+])
+
+dnl
+dnl APR_CHECK_DIRENT_TYPE
+dnl
+dnl  Decide if d_type is available in the dirent structure 
+dnl  on this platform.  Not part of the Single UNIX Spec.
+dnl  Note that this is worthless without DT_xxx macros, so
+dnl  look for one while we are at it.
+dnl
+AC_DEFUN([APR_CHECK_DIRENT_TYPE], [
+AC_CACHE_CHECK([for file type member of struct dirent], apr_cv_dirent_type,[
+apr_cv_dirent_type=no
+AC_TRY_COMPILE([
+#include <sys/types.h>
+#include <dirent.h>
+],[
+struct dirent de; de.d_type = DT_REG;
+], apr_cv_dirent_type=d_type)
+])
+if test "$apr_cv_dirent_type" != "no"; then
+  AC_DEFINE_UNQUOTED(DIRENT_TYPE, $apr_cv_dirent_type, 
+    [Define if struct dirent has a d_type member]) 
+fi
+])
+
+dnl the following is a newline, a space, a tab, and a backslash (the
+dnl backslash is used by the shell to skip newlines, but m4 sees it;
+dnl treat it like whitespace).
+dnl WARNING: don't reindent these lines, or the space/tab will be lost!
+define([apr_whitespace],[
+ 	\])
+
+dnl
+dnl APR_COMMA_ARGS(ARG1 ...)
+dnl  convert the whitespace-separated arguments into comman-separated
+dnl  arguments.
+dnl
+dnl APR_FOREACH(CODE-BLOCK, ARG1, ARG2, ...)
+dnl  subsitute CODE-BLOCK for each ARG[i]. "eachval" will be set to ARG[i]
+dnl  within each iteration.
+dnl
+changequote({,})
+define({APR_COMMA_ARGS},{patsubst([$}{1],[[}apr_whitespace{]+],[,])})
+define({APR_FOREACH},
+  {ifelse($}{2,,,
+          [define([eachval],
+                  $}{2)$}{1[]APR_FOREACH([$}{1],
+                                         builtin([shift],
+                                                 builtin([shift], $}{@)))])})
+changequote([,])
+
+dnl APR_FLAG_HEADERS(HEADER-FILE ... [, FLAG-TO-SET ] [, "yes" ])
+dnl  we set FLAG-TO-SET to 1 if we find HEADER-FILE, otherwise we set to 0
+dnl  if FLAG-TO-SET is null, we automagically determine it's name
+dnl  by changing all "/" to "_" in the HEADER-FILE and dropping
+dnl  all "." and "-" chars. If the 3rd parameter is "yes" then instead of
+dnl  setting to 1 or 0, we set FLAG-TO-SET to yes or no.
+dnl  
+AC_DEFUN([APR_FLAG_HEADERS], [
+AC_CHECK_HEADERS($1)
+for aprt_i in $1
+do
+    ac_safe=`echo "$aprt_i" | sed 'y%./+-%__p_%'`
+    aprt_2=`echo "$aprt_i" | sed -e 's%/%_%g' -e 's/\.//g' -e 's/-//g'`
+    if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+       eval "ifelse($2,,$aprt_2,$2)=ifelse($3,yes,yes,1)"
+    else
+       eval "ifelse($2,,$aprt_2,$2)=ifelse($3,yes,no,0)"
+    fi
+done
+])
+
+dnl APR_FLAG_FUNCS(FUNC ... [, FLAG-TO-SET] [, "yes" ])
+dnl  if FLAG-TO-SET is null, we automagically determine it's name
+dnl  prepending "have_" to the function name in FUNC, otherwise
+dnl  we use what's provided as FLAG-TO-SET. If the 3rd parameter
+dnl  is "yes" then instead of setting to 1 or 0, we set FLAG-TO-SET
+dnl  to yes or no.
+dnl
+AC_DEFUN([APR_FLAG_FUNCS], [
+AC_CHECK_FUNCS($1)
+for aprt_j in $1
+do
+    aprt_3="have_$aprt_j"
+    if eval "test \"`echo '$ac_cv_func_'$aprt_j`\" = yes"; then
+       eval "ifelse($2,,$aprt_3,$2)=ifelse($3,yes,yes,1)"
+    else
+       eval "ifelse($2,,$aprt_3,$2)=ifelse($3,yes,no,0)"
+    fi
+done
+])
+
+dnl Iteratively interpolate the contents of the second argument
+dnl until interpolation offers no new result. Then assign the
+dnl final result to $1.
+dnl
+dnl Example:
+dnl
+dnl foo=1
+dnl bar='${foo}/2'
+dnl baz='${bar}/3'
+dnl APR_EXPAND_VAR(fraz, $baz)
+dnl   $fraz is now "1/2/3"
+dnl 
+AC_DEFUN([APR_EXPAND_VAR], [
+ap_last=
+ap_cur="$2"
+while test "x${ap_cur}" != "x${ap_last}";
+do
+  ap_last="${ap_cur}"
+  ap_cur=`eval "echo ${ap_cur}"`
+done
+$1="${ap_cur}"
+])
+
+dnl
+dnl Removes the value of $3 from the string in $2, strips of any leading
+dnl slashes, and returns the value in $1.
+dnl
+dnl Example:
+dnl orig_path="${prefix}/bar"
+dnl APR_PATH_RELATIVE(final_path, $orig_path, $prefix)
+dnl    $final_path now contains "bar"
+AC_DEFUN([APR_PATH_RELATIVE], [
+ap_stripped=`echo $2 | sed -e "s#^$3##"`
+# check if the stripping was successful
+if test "x$2" != "x${ap_stripped}"; then
+    # it was, so strip of any leading slashes
+    $1="`echo ${ap_stripped} | sed -e 's#^/*##'`"
+else
+    # it wasn't so return the original
+    $1="$2"
+fi
+])
+
+dnl APR_HELP_STRING(LHS, RHS)
+dnl Autoconf 2.50 can not handle substr correctly.  It does have 
+dnl AC_HELP_STRING, so let's try to call it if we can.
+dnl Note: this define must be on one line so that it can be properly returned
+dnl as the help string.  When using this macro with a multi-line RHS, ensure
+dnl that you surround the macro invocation with []s
+AC_DEFUN([APR_HELP_STRING], [ifelse(regexp(AC_ACVERSION, 2\.1), -1, AC_HELP_STRING([$1],[$2]),[  ][$1] substr([                       ],len($1))[$2])])
+
+dnl
+dnl APR_LAYOUT(configlayout, layoutname [, extravars])
+dnl
+AC_DEFUN([APR_LAYOUT], [
+  if test ! -f $srcdir/config.layout; then
+    echo "** Error: Layout file $srcdir/config.layout not found"
+    echo "** Error: Cannot use undefined layout '$LAYOUT'"
+    exit 1
+  fi
+  # Catch layout names including a slash which will otherwise
+  # confuse the heck out of the sed script.
+  case $2 in
+  */*) 
+    echo "** Error: $2 is not a valid layout name"
+    exit 1 ;;
+  esac
+  pldconf=./config.pld
+  changequote({,})
+  sed -e "1s/[ 	]*<[lL]ayout[ 	]*$2[ 	]*>[ 	]*//;1t" \
+      -e "1,/[ 	]*<[lL]ayout[ 	]*$2[ 	]*>[ 	]*/d" \
+      -e '/[ 	]*<\/Layout>[ 	]*/,$d' \
+      -e "s/^[ 	]*//g" \
+      -e "s/:[ 	]*/=\'/g" \
+      -e "s/[ 	]*$/'/g" \
+      $1 > $pldconf
+  layout_name=$2
+  if test ! -s $pldconf; then
+    echo "** Error: unable to find layout $layout_name"
+    exit 1
+  fi
+  . $pldconf
+  rm $pldconf
+  for var in prefix exec_prefix bindir sbindir libexecdir mandir \
+             sysconfdir datadir includedir localstatedir runtimedir \
+             logfiledir libdir installbuilddir libsuffix $3; do
+    eval "val=\"\$$var\""
+    case $val in
+      *+)
+        val=`echo $val | sed -e 's;\+$;;'`
+        eval "$var=\"\$val\""
+        autosuffix=yes
+        ;;
+      *)
+        autosuffix=no
+        ;;
+    esac
+    val=`echo $val | sed -e 's:\(.\)/*$:\1:'`
+    val=`echo $val | sed -e 's:[\$]\([a-z_]*\):${\1}:g'`
+    if test "$autosuffix" = "yes"; then
+      if echo $val | grep apache >/dev/null; then
+        addtarget=no
+      else
+        addtarget=yes
+      fi
+      if test "$addtarget" = "yes"; then
+        val="$val/apache2"
+      fi
+    fi
+    eval "$var='$val'"
+  done
+  changequote([,])
+])dnl
+
+dnl
+dnl APR_ENABLE_LAYOUT(default layout name [, extra vars])
+dnl
+AC_DEFUN([APR_ENABLE_LAYOUT], [
+AC_ARG_ENABLE(layout,
+[  --enable-layout=LAYOUT],[
+  LAYOUT=$enableval
+])
+
+if test -z "$LAYOUT"; then
+  LAYOUT="$1"
+fi
+APR_LAYOUT($srcdir/config.layout, $LAYOUT, $2)
+
+AC_MSG_CHECKING(for chosen layout)
+AC_MSG_RESULT($layout_name)
+])
+
+
+dnl
+dnl APR_PARSE_ARGUMENTS
+dnl a reimplementation of autoconf's argument parser,
+dnl used here to allow us to co-exist layouts and argument based
+dnl set ups.
+AC_DEFUN([APR_PARSE_ARGUMENTS], [
+ac_prev=
+# Retrieve the command-line arguments.  The eval is needed because
+# the arguments are quoted to preserve accuracy.
+eval "set x $ac_configure_args"
+shift
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval "$ac_prev=\$ac_option"
+    ac_prev=
+    continue
+  fi
+
+  ac_optarg=`expr "x$ac_option" : 'x[[^=]]*=\(.*\)'`
+
+  case $ac_option in
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir="$ac_optarg" ;;
+
+  -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+  | --da=*)
+    datadir="$ac_optarg" ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix="$ac_optarg" ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir="$ac_optarg" ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir="$ac_optarg" ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir="$ac_optarg" ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir="$ac_optarg" ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst \
+  | --locals | --local | --loca | --loc | --lo)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+  | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+    localstatedir="$ac_optarg" ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir="$ac_optarg" ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix="$ac_optarg" ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir="$ac_optarg" ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir="$ac_optarg" ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir="$ac_optarg" ;;
+
+  esac
+done
+
+# Be sure to have absolute paths.
+for ac_var in exec_prefix prefix
+do
+  eval ac_val=$`echo $ac_var`
+  case $ac_val in
+    [[\\/$]]* | ?:[[\\/]]* | NONE | '' ) ;;
+    *)  AC_MSG_ERROR([expected an absolute path for --$ac_var: $ac_val]);;
+  esac
+done
+
+])dnl
+
+dnl
+dnl APR_CHECK_DEPEND
+dnl
+dnl Determine what program we can use to generate .deps-style dependencies
+dnl
+AC_DEFUN([APR_CHECK_DEPEND], [
+dnl Try to determine what depend program we can use
+dnl All GCC-variants should have -MM.
+dnl If not, then we can check on those, too.
+if test "$GCC" = "yes"; then
+  MKDEP='$(CC) -MM'
+else
+  rm -f conftest.c
+dnl <sys/types.h> should be available everywhere!
+  cat > conftest.c <<EOF
+#include <sys/types.h>
+  int main() { return 0; }
+EOF
+  MKDEP="true"
+  for i in "$CC -MM" "$CC -M" "$CPP -MM" "$CPP -M" "cpp -M"; do
+    AC_MSG_CHECKING([if $i can create proper make dependencies])
+    if $i conftest.c 2>/dev/null | grep 'conftest.o: conftest.c' >/dev/null; then
+      MKDEP=$i
+      AC_MSG_RESULT(yes)
+      break;
+    fi
+    AC_MSG_RESULT(no)
+  done
+  rm -f conftest.c
+fi
+
+AC_SUBST(MKDEP)
+])
+
+dnl
+dnl APR_CHECK_TYPES_COMPATIBLE(TYPE-1, TYPE-2, [ACTION-IF-TRUE])
+dnl
+dnl Try to determine whether two types are the same. Only works
+dnl for gcc and icc.
+dnl
+AC_DEFUN([APR_CHECK_TYPES_COMPATIBLE], [
+define([apr_cvname], apr_cv_typematch_[]translit([$1], [ ], [_])_[]translit([$2], [ ], [_]))
+AC_CACHE_CHECK([whether $1 and $2 are the same], apr_cvname, [
+AC_TRY_COMPILE(AC_INCLUDES_DEFAULT, [
+    int foo[0 - !__builtin_types_compatible_p($1, $2)];
+], [apr_cvname=yes
+$3], [apr_cvname=no])])
+])
diff --git a/build/apr_hints.m4 b/build/apr_hints.m4
new file mode 100644
index 00000000000..fd3d33de059
--- /dev/null
+++ b/build/apr_hints.m4
@@ -0,0 +1,522 @@
+dnl -------------------------------------------------------- -*- autoconf -*-
+dnl Licensed to the Apache Software Foundation (ASF) under one or more
+dnl contributor license agreements.  See the NOTICE file distributed with
+dnl this work for additional information regarding copyright ownership.
+dnl The ASF licenses this file to You under the Apache License, Version 2.0
+dnl (the "License"); you may not use this file except in compliance with
+dnl the License.  You may obtain a copy of the License at
+dnl
+dnl     http://www.apache.org/licenses/LICENSE-2.0
+dnl
+dnl Unless required by applicable law or agreed to in writing, software
+dnl distributed under the License is distributed on an "AS IS" BASIS,
+dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+dnl See the License for the specific language governing permissions and
+dnl limitations under the License.
+
+dnl -----------------------------------------------------------------
+dnl apr_hints.m4: APR's autoconf macros for platform-specific hints
+dnl
+dnl  We preload various configure settings depending
+dnl  on previously obtained platform knowledge.
+dnl  We allow all settings to be overridden from
+dnl  the command-line.
+dnl
+dnl  We maintain the "format" that we've used
+dnl  under 1.3.x, so we don't exactly follow
+dnl  what is "recommended" by autoconf.
+
+dnl
+dnl APR_PRELOAD
+dnl
+dnl  Preload various ENV/makefile params such as CC, CFLAGS, etc
+dnl  based on outside knowledge
+dnl
+dnl  Generally, we force the setting of CC, and add flags
+dnl  to CFLAGS, CPPFLAGS, LIBS and LDFLAGS. 
+dnl
+AC_DEFUN(APR_PRELOAD, [
+if test "x$apr_preload_done" != "xyes" ; then
+
+  apr_preload_done="yes"
+
+  echo "Applying APR hints file rules for $host"
+
+  case "$host" in
+    *mint)
+	APR_ADDTO(CPPFLAGS, [-DMINT -D_GNU_SOURCE])
+	;;
+    *MPE/iX*)
+	APR_ADDTO(CPPFLAGS, [-DMPE -D_POSIX_SOURCE -D_SOCKET_SOURCE])
+	APR_ADDTO(LIBS, [-lsvipc -lcurses])
+	APR_ADDTO(LDFLAGS, [-Xlinker \"-WL,cap=ia,ba,ph;nmstack=1024000\"])
+	;;
+    *-apple-aux3*)
+	APR_ADDTO(CPPFLAGS, [-DAUX3 -D_POSIX_SOURCE])
+	APR_ADDTO(LIBS, [-lposix -lbsd])
+	APR_ADDTO(LDFLAGS, [-s])
+	APR_SETVAR(SHELL, [/bin/ksh])
+	;;
+    *-ibm-aix*)
+	APR_ADDTO(CPPFLAGS, [-U__STR__ -D_THREAD_SAFE])
+        dnl _USR_IRS gets us the hstrerror() proto in netdb.h
+        case $host in
+            *-ibm-aix4.3)
+	        APR_ADDTO(CPPFLAGS, [-D_USE_IRS])
+	        ;;
+            *-ibm-aix5*)
+	        APR_ADDTO(CPPFLAGS, [-D_USE_IRS])
+	        ;;
+            *-ibm-aix4.3.*)
+                APR_ADDTO(CPPFLAGS, [-D_USE_IRS])
+                ;;
+        esac
+        dnl If using xlc, remember it, and give it the right options.
+        if $CC 2>&1 | grep 'xlc' > /dev/null; then
+          APR_SETIFNULL(AIX_XLC, [yes])
+          APR_ADDTO(CFLAGS, [-qHALT=E])
+        fi
+	APR_SETIFNULL(apr_sysvsem_is_global, [yes])
+	APR_SETIFNULL(apr_lock_method, [USE_SYSVSEM_SERIALIZE])
+        case $host in
+            *-ibm-aix3* | *-ibm-aix4.1.*)
+                ;;
+            *)
+                APR_ADDTO(LDFLAGS, [-Wl,-brtl])
+                ;;
+	esac
+        ;;
+    *-apollo-*)
+	APR_ADDTO(CPPFLAGS, [-DAPOLLO])
+	;;
+    *-dg-dgux*)
+	APR_ADDTO(CPPFLAGS, [-DDGUX])
+	;;
+    *-os2*)
+	APR_SETVAR(SHELL, [sh])
+	APR_SETIFNULL(apr_gethostbyname_is_thread_safe, [yes])
+	APR_SETIFNULL(apr_gethostbyaddr_is_thread_safe, [yes])
+	APR_SETIFNULL(apr_getservbyname_is_thread_safe, [yes])
+	;;
+    *-hi-hiux)
+	APR_ADDTO(CPPFLAGS, [-DHIUX])
+	;;
+    *-hp-hpux11.*)
+	APR_ADDTO(CPPFLAGS, [-DHPUX11 -D_REENTRANT -D_HPUX_SOURCE])
+	;;
+    *-hp-hpux10.*)
+ 	case $host in
+ 	  *-hp-hpux10.01)
+dnl	       # We know this is a problem in 10.01.
+dnl	       # Not a problem in 10.20.  Otherwise, who knows?
+	       APR_ADDTO(CPPFLAGS, [-DSELECT_NEEDS_CAST])
+	       ;;	     
+ 	esac
+	APR_ADDTO(CPPFLAGS, [-D_REENTRANT])
+	;;
+    *-hp-hpux*)
+	APR_ADDTO(CPPFLAGS, [-DHPUX -D_REENTRANT])
+	;;
+    *-linux*)
+	APR_ADDTO(CPPFLAGS, [-DLINUX -D_REENTRANT -D_GNU_SOURCE])
+	;;
+    *-lynx-lynxos)
+	APR_ADDTO(CPPFLAGS, [-D__NO_INCLUDE_WARN__ -DLYNXOS])
+	APR_ADDTO(LIBS, [-lbsd])
+	;;
+    *486-*-bsdi*)
+	APR_ADDTO(CFLAGS, [-m486])
+	;;
+    *-*-bsdi*)
+        case $host in
+            *bsdi4.1)
+                APR_ADDTO(CFLAGS, [-D_REENTRANT])
+                ;;
+        esac
+        ;;
+    *-openbsd*)
+	APR_ADDTO(CPPFLAGS, [-D_POSIX_THREADS])
+        # binding to an ephemeral port fails on OpenBSD so override
+        # the test for O_NONBLOCK inheritance across accept().
+        APR_SETIFNULL(ac_cv_o_nonblock_inherited, [yes])
+	;;
+    *-netbsd*)
+	APR_ADDTO(CPPFLAGS, [-DNETBSD])
+        # fcntl() lies about O_NONBLOCK on an accept()ed socket (PR kern/26950)
+        APR_SETIFNULL(ac_cv_o_nonblock_inherited, [yes])
+	;;
+    *-freebsd*)
+        APR_SETIFNULL(apr_lock_method, [USE_FLOCK_SERIALIZE])
+        if test -x /sbin/sysctl; then
+            os_version=`/sbin/sysctl -n kern.osreldate`
+        else
+            os_version=000000
+        fi
+        # 502102 is when libc_r switched to libpthread (aka libkse).
+        if test $os_version -ge "502102"; then
+          apr_cv_pthreads_cflags="none"
+          apr_cv_pthreads_lib="-lpthread"
+        else
+          APR_ADDTO(CPPFLAGS, [-D_THREAD_SAFE -D_REENTRANT])
+          APR_SETIFNULL(enable_threads, [no])
+        fi
+        # prevent use of KQueue before FreeBSD 4.8
+        if test $os_version -lt "480000"; then
+          APR_SETIFNULL(ac_cv_func_kqueue, no)
+        fi
+	;;
+    *-k*bsd*-gnu)
+        APR_ADDTO(CPPFLAGS, [-D_REENTRANT -D_GNU_SOURCE])
+        ;;
+    *-gnu*|*-GNU*)
+        APR_ADDTO(CPPFLAGS, [-D_REENTRANT -D_GNU_SOURCE -DHURD])
+        ;;
+    *-next-nextstep*)
+	APR_SETIFNULL(CFLAGS, [-O])
+	APR_ADDTO(CPPFLAGS, [-DNEXT])
+	;;
+    *-next-openstep*)
+	APR_SETIFNULL(CFLAGS, [-O])
+	APR_ADDTO(CPPFLAGS, [-DNEXT])
+	;;
+    *-apple-rhapsody*)
+	APR_ADDTO(CPPFLAGS, [-DRHAPSODY])
+	;;
+    *-apple-darwin*)
+        APR_ADDTO(CPPFLAGS, [-DDARWIN -DSIGPROCMASK_SETS_THREAD_MASK])
+        APR_SETIFNULL(apr_posixsem_is_global, [yes])
+        case $host in
+            *-apple-darwin[[1-9]].*)
+                # APR's use of kqueue has triggered kernel panics for some
+                # 10.5.x (Darwin 9.x) users when running the entire test suite.
+                # In 10.4.x, use of kqueue would cause the socket tests to hang.
+                # 10.6+ (Darwin 10.x is supposed to fix the KQueue issues
+                APR_SETIFNULL(ac_cv_func_kqueue, [no]) 
+                APR_SETIFNULL(ac_cv_func_poll, [no]) # See issue 34332
+            ;;
+            *-apple-darwin1?.*)
+                APR_ADDTO(CPPFLAGS, [-DDARWIN_10])
+            ;;
+        esac
+	;;
+    *-dec-osf*)
+	APR_ADDTO(CPPFLAGS, [-DOSF1])
+        # process-shared mutexes don't seem to work in Tru64 5.0
+        APR_SETIFNULL(apr_cv_process_shared_works, [no])
+	;;
+    *-nto-qnx*)
+	;;
+    *-qnx)
+	APR_ADDTO(CPPFLAGS, [-DQNX])
+	APR_ADDTO(LIBS, [-N128k -lunix])
+	;;
+    *-qnx32)
+	APR_ADDTO(CPPFLAGS, [-DQNX])
+	APR_ADDTO(CFLAGS, [-mf -3])
+	APR_ADDTO(LIBS, [-N128k -lunix])
+	;;
+    *-isc4*)
+	APR_ADDTO(CPPFLAGS, [-posix -DISC])
+	APR_ADDTO(LDFLAGS, [-posix])
+	APR_ADDTO(LIBS, [-linet])
+	;;
+    *-sco3.2v[[234]]*)
+	APR_ADDTO(CPPFLAGS, [-DSCO -D_REENTRANT])
+	if test "$GCC" = "no"; then
+	    APR_ADDTO(CFLAGS, [-Oacgiltz])
+	fi
+	APR_ADDTO(LIBS, [-lPW -lmalloc])
+	;;
+    *-sco3.2v5*)
+	APR_ADDTO(CPPFLAGS, [-DSCO5 -D_REENTRANT])
+	;;
+    *-sco_sv*|*-SCO_SV*)
+	APR_ADDTO(CPPFLAGS, [-DSCO -D_REENTRANT])
+	APR_ADDTO(LIBS, [-lPW -lmalloc])
+	;;
+    *-solaris2*)
+    	PLATOSVERS=`echo $host | sed 's/^.*solaris2.//'`
+	APR_ADDTO(CPPFLAGS, [-DSOLARIS2=$PLATOSVERS -D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT])
+        if test $PLATOSVERS -eq 10; then
+            # pthread_mutex_timedlock is broken on Solaris 10.
+            # It can block without timeout in case of EDEADLK.
+            APR_SETIFNULL(ac_cv_func_pthread_mutex_timedlock, [no])
+        fi
+        if test $PLATOSVERS -ge 10; then
+            APR_SETIFNULL(apr_lock_method, [USE_PROC_PTHREAD_SERIALIZE])
+        else
+            APR_SETIFNULL(apr_lock_method, [USE_FCNTL_SERIALIZE])
+        fi
+        # readdir64_r error handling seems broken on Solaris (at least
+        # up till 2.8) -- it will return -1 at end-of-directory.
+        APR_SETIFNULL(ac_cv_func_readdir64_r, [no])
+	;;
+    *-sunos4*)
+	APR_ADDTO(CPPFLAGS, [-DSUNOS4])
+	;;
+    *-unixware1)
+	APR_ADDTO(CPPFLAGS, [-DUW=100])
+	;;
+    *-unixware2)
+	APR_ADDTO(CPPFLAGS, [-DUW=200])
+	APR_ADDTO(LIBS, [-lgen])
+	;;
+    *-unixware211)
+	APR_ADDTO(CPPFLAGS, [-DUW=211])
+	APR_ADDTO(LIBS, [-lgen])
+	;;
+    *-unixware212)
+	APR_ADDTO(CPPFLAGS, [-DUW=212])
+	APR_ADDTO(LIBS, [-lgen])
+	;;
+    *-unixware7)
+	APR_ADDTO(CPPFLAGS, [-DUW=700])
+	APR_ADDTO(LIBS, [-lgen])
+	;;
+    maxion-*-sysv4*)
+	APR_ADDTO(CPPFLAGS, [-DSVR4])
+	APR_ADDTO(LIBS, [-lc -lgen])
+	;;
+    *-*-powermax*)
+	APR_ADDTO(CPPFLAGS, [-DSVR4])
+	APR_ADDTO(LIBS, [-lgen])
+	;;
+    TPF)
+       APR_ADDTO(CPPFLAGS, [-DTPF -D_POSIX_SOURCE])
+       ;;
+    bs2000*-siemens-sysv*)
+	APR_SETIFNULL(CFLAGS, [-O])
+	APR_ADDTO(CPPFLAGS, [-DSVR4 -D_XPG_IV -D_KMEMUSER])
+	APR_ADDTO(LIBS, [-lsocket])
+	APR_SETIFNULL(enable_threads, [no])
+	;;
+    *-siemens-sysv4*)
+	APR_ADDTO(CPPFLAGS, [-DSVR4 -D_XPG_IV -DHAS_DLFCN -DUSE_MMAP_FILES -DUSE_SYSVSEM_SERIALIZED_ACCEPT])
+	APR_ADDTO(LIBS, [-lc])
+	;;
+    pyramid-pyramid-svr4)
+	APR_ADDTO(CPPFLAGS, [-DSVR4 -DNO_LONG_DOUBLE])
+	APR_ADDTO(LIBS, [-lc])
+	;;
+    DS/90\ 7000-*-sysv4*)
+	APR_ADDTO(CPPFLAGS, [-DUXPDS])
+	;;
+    *-tandem-sysv4*)
+	APR_ADDTO(CPPFLAGS, [-DSVR4])
+	;;
+    *-ncr-sysv4)
+	APR_ADDTO(CPPFLAGS, [-DSVR4 -DMPRAS])
+	APR_ADDTO(LIBS, [-lc -L/usr/ucblib -lucb])
+	;;
+    *-sysv4*)
+	APR_ADDTO(CPPFLAGS, [-DSVR4])
+	APR_ADDTO(LIBS, [-lc])
+	;;
+    88k-encore-sysv4)
+	APR_ADDTO(CPPFLAGS, [-DSVR4 -DENCORE])
+	APR_ADDTO(LIBS, [-lPW])
+	;;
+    *-uts*)
+	PLATOSVERS=`echo $host | sed 's/^.*,//'`
+	case $PLATOSVERS in
+	    2*) APR_ADDTO(CPPFLAGS, [-DUTS21])
+	        APR_ADDTO(CFLAGS, [-Xa -eft])
+	        APR_ADDTO(LIBS, [-lbsd -la])
+	        ;;
+	    *)  APR_ADDTO(CPPFLAGS, [-DSVR4])
+	        APR_ADDTO(CFLAGS, [-Xa])
+	        ;;
+	esac
+	;;
+    *-ultrix)
+	APR_ADDTO(CPPFLAGS, [-DULTRIX])
+	APR_SETVAR(SHELL, [/bin/sh5])
+	;;
+    *powerpc-tenon-machten*)
+	APR_ADDTO(LDFLAGS, [-Xlstack=0x14000 -Xldelcsect])
+	;;
+    *-machten*)
+	APR_ADDTO(LDFLAGS, [-stack 0x14000])
+	;;
+    *convex-v11*)
+	APR_ADDTO(CPPFLAGS, [-DCONVEXOS11])
+	APR_SETIFNULL(CFLAGS, [-O1])
+	APR_ADDTO(CFLAGS, [-ext])
+	;;
+    i860-intel-osf1)
+	APR_ADDTO(CPPFLAGS, [-DPARAGON])
+	;;
+    *-sequent-ptx2.*.*)
+	APR_ADDTO(CPPFLAGS, [-DSEQUENT=20])
+	APR_ADDTO(CFLAGS, [-Wc,-pw])
+	APR_ADDTO(LIBS, [-linet -lc -lseq])
+	;;
+    *-sequent-ptx4.0.*)
+	APR_ADDTO(CPPFLAGS, [-DSEQUENT=40])
+	APR_ADDTO(CFLAGS, [-Wc,-pw])
+	APR_ADDTO(LIBS, [-linet -lc])
+	;;
+    *-sequent-ptx4.[[123]].*)
+	APR_ADDTO(CPPFLAGS, [-DSEQUENT=41])
+	APR_ADDTO(CFLAGS, [-Wc,-pw])
+	APR_ADDTO(LIBS, [-lc])
+	;;
+    *-sequent-ptx4.4.*)
+	APR_ADDTO(CPPFLAGS, [-DSEQUENT=44])
+	APR_ADDTO(CFLAGS, [-Wc,-pw])
+	APR_ADDTO(LIBS, [-lc])
+	;;
+    *-sequent-ptx4.5.*)
+	APR_ADDTO(CPPFLAGS, [-DSEQUENT=45])
+	APR_ADDTO(CFLAGS, [-Wc,-pw])
+	APR_ADDTO(LIBS, [-lc])
+	;;
+    *-sequent-ptx5.0.*)
+	APR_ADDTO(CPPFLAGS, [-DSEQUENT=50])
+	APR_ADDTO(CFLAGS, [-Wc,-pw])
+	APR_ADDTO(LIBS, [-lc])
+	;;
+    *NEWS-OS*)
+	APR_ADDTO(CPPFLAGS, [-DNEWSOS])
+	;;
+    *-riscix)
+	APR_ADDTO(CPPFLAGS, [-DRISCIX])
+	APR_SETIFNULL(CFLAGS, [-O])
+	;;
+    *-irix*)
+	APR_ADDTO(CPPFLAGS, [-D_POSIX_THREAD_SAFE_FUNCTIONS])
+	;;
+    *beos*)
+        APR_ADDTO(CPPFLAGS, [-DBEOS])
+        PLATOSVERS=`uname -r`
+        APR_SETIFNULL(apr_process_lock_is_global, [yes])
+        case $PLATOSVERS in
+            5.0.4)
+                APR_ADDTO(LDFLAGS, [-L/boot/beos/system/lib])
+                APR_ADDTO(LIBS, [-lbind -lsocket])
+                APR_ADDTO(CPPFLAGS,[-DBONE7])
+                ;;
+            5.1)
+                APR_ADDTO(LDFLAGS, [-L/boot/beos/system/lib])
+                APR_ADDTO(LIBS, [-lbind -lsocket])
+                ;;
+	esac
+	APR_ADDTO(CPPFLAGS, [-DSIGPROCMASK_SETS_THREAD_MASK])
+        ;;
+    4850-*.*)
+	APR_ADDTO(CPPFLAGS, [-DSVR4 -DMPRAS])
+	APR_ADDTO(LIBS, [-lc -L/usr/ucblib -lucb])
+	;;
+    drs6000*)
+	APR_ADDTO(CPPFLAGS, [-DSVR4])
+	APR_ADDTO(LIBS, [-lc -L/usr/ucblib -lucb])
+	;;
+    m88k-*-CX/SX|CYBER)
+	APR_ADDTO(CPPFLAGS, [-D_CX_SX])
+	APR_ADDTO(CFLAGS, [-Xa])
+	;;
+    *-tandem-oss)
+	APR_ADDTO(CPPFLAGS, [-D_TANDEM_SOURCE -D_XOPEN_SOURCE_EXTENDED=1])
+	;;
+    *-ibm-os390)
+        APR_SETIFNULL(apr_lock_method, [USE_SYSVSEM_SERIALIZE])
+        APR_SETIFNULL(apr_sysvsem_is_global, [yes])
+        APR_SETIFNULL(apr_gethostbyname_is_thread_safe, [yes])
+        APR_SETIFNULL(apr_gethostbyaddr_is_thread_safe, [yes])
+        APR_SETIFNULL(apr_getservbyname_is_thread_safe, [yes])
+        AC_DEFINE(HAVE_ZOS_PTHREADS, 1, [Define for z/OS pthread API nuances])
+        APR_ADDTO(CPPFLAGS, [-U_NO_PROTO -DSIGPROCMASK_SETS_THREAD_MASK -DTCP_NODELAY=1])
+        ;;
+    *-ibm-as400)
+        APR_SETIFNULL(apr_lock_method, [USE_SYSVSEM_SERIALIZE])
+        APR_SETIFNULL(apr_process_lock_is_global, [yes])
+        APR_SETIFNULL(apr_gethostbyname_is_thread_safe, [yes])
+        APR_SETIFNULL(apr_gethostbyaddr_is_thread_safe, [yes])
+        APR_SETIFNULL(apr_getservbyname_is_thread_safe, [yes])
+        ;;
+    *mingw*)
+        APR_ADDTO(INTERNAL_CPPFLAGS, -DBINPATH=$apr_builddir/test/.libs)
+        APR_ADDTO(CPPFLAGS, [-DWIN32 -D__MSVCRT__])
+        APR_ADDTO(LDFLAGS, [-Wl,--enable-auto-import,--subsystem,console])
+        APR_SETIFNULL(have_unicode_fs, [1])
+        APR_SETIFNULL(have_proc_invoked, [1])
+        APR_SETIFNULL(apr_lock_method, [win32])
+        APR_SETIFNULL(apr_process_lock_is_global, [yes])
+        APR_SETIFNULL(apr_cv_use_lfs64, [yes])
+        APR_SETIFNULL(apr_cv_osuuid, [yes])
+        APR_SETIFNULL(apr_cv_tcp_nodelay_with_cork, [no])
+        APR_SETIFNULL(apr_thread_func, [__stdcall])
+        APR_SETIFNULL(ac_cv_o_nonblock_inherited, [yes])
+        APR_SETIFNULL(ac_cv_tcp_nodelay_inherited, [yes])
+        APR_SETIFNULL(ac_cv_file__dev_zero, [no])
+        APR_SETIFNULL(ac_cv_func_setpgrp_void, [no])
+        APR_SETIFNULL(ac_cv_func_mmap, [yes])
+        APR_SETIFNULL(ac_cv_define_sockaddr_in6, [yes])
+        APR_SETIFNULL(ac_cv_working_getaddrinfo, [yes])
+        APR_SETIFNULL(ac_cv_working_getnameinfo, [yes])
+        APR_SETIFNULL(ac_cv_func_gai_strerror, [yes])
+        case $host in
+            *mingw32*)
+                APR_SETIFNULL(apr_has_xthread_files, [1])
+                APR_SETIFNULL(apr_has_user, [1])
+                APR_SETIFNULL(apr_procattr_user_set_requires_password, [1])
+                dnl The real function is TransmitFile(), not sendfile(), but
+                dnl this bypasses the Linux/Solaris/AIX/etc. test and enables
+                dnl the TransmitFile() implementation.
+                APR_SETIFNULL(ac_cv_func_sendfile, [yes])
+                ;;
+            *mingwce)
+                APR_SETIFNULL(apr_has_xthread_files, [0])
+                APR_SETIFNULL(apr_has_user, [0])
+                APR_SETIFNULL(apr_procattr_user_set_requires_password, [0])
+                APR_SETIFNULL(ac_cv_func_sendfile, [no])
+                ;;
+        esac
+        ;;
+  esac
+
+fi
+])
+
+dnl
+dnl APR_CC_HINTS
+dnl
+dnl  Allows us to provide a default choice of compiler which
+dnl  the user can override.
+AC_DEFUN(APR_CC_HINTS, [
+case "$host" in
+  *-apple-aux3*)
+      APR_SETIFNULL(CC, [gcc])
+      ;;
+  bs2000*-siemens-sysv*)
+      APR_SETIFNULL(CC, [c89 -XLLML -XLLMK -XL -Kno_integer_overflow])
+      ;;
+  *convex-v11*)
+      APR_SETIFNULL(CC, [cc])
+      ;;
+  *-ibm-os390)
+      APR_SETIFNULL(CC, [cc])
+      ;;
+  *-ibm-as400)
+      APR_SETIFNULL(CC, [icc])
+      ;;
+  *-isc4*)
+      APR_SETIFNULL(CC, [gcc])
+      ;;
+  m88k-*-CX/SX|CYBER)
+      APR_SETIFNULL(CC, [cc])
+      ;;
+  *-next-openstep*)
+      APR_SETIFNULL(CC, [cc])
+      ;;
+  *-qnx32)
+      APR_SETIFNULL(CC, [cc -F])
+      ;;
+  *-tandem-oss)
+      APR_SETIFNULL(CC, [c89])
+      ;;
+  TPF)
+      APR_SETIFNULL(CC, [c89])
+      ;;
+esac
+])
diff --git a/build/apr_network.m4 b/build/apr_network.m4
new file mode 100644
index 00000000000..24889828308
--- /dev/null
+++ b/build/apr_network.m4
@@ -0,0 +1,994 @@
+dnl -------------------------------------------------------- -*- autoconf -*-
+dnl Licensed to the Apache Software Foundation (ASF) under one or more
+dnl contributor license agreements.  See the NOTICE file distributed with
+dnl this work for additional information regarding copyright ownership.
+dnl The ASF licenses this file to You under the Apache License, Version 2.0
+dnl (the "License"); you may not use this file except in compliance with
+dnl the License.  You may obtain a copy of the License at
+dnl
+dnl     http://www.apache.org/licenses/LICENSE-2.0
+dnl
+dnl Unless required by applicable law or agreed to in writing, software
+dnl distributed under the License is distributed on an "AS IS" BASIS,
+dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+dnl See the License for the specific language governing permissions and
+dnl limitations under the License.
+
+dnl -----------------------------------------------------------------
+dnl apr_network.m4: APR's autoconf macros for testing network support
+dnl
+
+dnl
+dnl check for type in_addr
+dnl
+AC_DEFUN(APR_TYPE_IN_ADDR,[
+  AC_CACHE_CHECK(for type in_addr, ac_cv_type_in_addr,[
+  AC_TRY_COMPILE([
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_WINSOCK2_H
+#include <winsock2.h>
+#endif
+],[
+ struct in_addr arg;
+ arg.s_addr = htonl(INADDR_ANY);
+], [ ac_cv_type_in_addr="yes"] , [
+ac_cv_type_in_addr="no"])
+])
+])
+
+dnl
+dnl check for working getaddrinfo()
+dnl
+dnl Note that if the system doesn't have gai_strerror(), we
+dnl can't use getaddrinfo() because we can't get strings
+dnl describing the error codes.
+dnl
+AC_DEFUN([APR_CHECK_WORKING_GETADDRINFO], [
+  AC_CACHE_CHECK(for working getaddrinfo, ac_cv_working_getaddrinfo,[
+  AC_TRY_RUN( [
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+int main(void) {
+    struct addrinfo hints, *ai;
+    int error;
+
+    memset(&hints, 0, sizeof(hints));
+    hints.ai_family = AF_UNSPEC;
+    hints.ai_socktype = SOCK_STREAM;
+    error = getaddrinfo("127.0.0.1", NULL, &hints, &ai);
+    if (error) {
+        exit(1);
+    }
+    if (ai->ai_addr->sa_family != AF_INET) {
+        exit(1);
+    }
+    exit(0);
+}
+],[
+  ac_cv_working_getaddrinfo="yes"
+],[
+  ac_cv_working_getaddrinfo="no"
+],[
+  ac_cv_working_getaddrinfo="yes"
+])])
+if test "$ac_cv_working_getaddrinfo" = "yes"; then
+  if test "$ac_cv_func_gai_strerror" != "yes"; then
+    ac_cv_working_getaddrinfo="no"
+  else
+    AC_DEFINE(HAVE_GETADDRINFO, 1, [Define if getaddrinfo exists and works well enough for APR])
+  fi
+fi
+])
+
+dnl Check whether the AI_ADDRCONFIG flag can be used with getaddrinfo
+AC_DEFUN([APR_CHECK_GETADDRINFO_ADDRCONFIG], [
+  AC_CACHE_CHECK(for working AI_ADDRCONFIG, apr_cv_gai_addrconfig, [
+  AC_TRY_RUN([
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+int main(int argc, char **argv) {
+    struct addrinfo hints, *ai;
+
+    memset(&hints, 0, sizeof(hints));
+    hints.ai_family = AF_UNSPEC;
+    hints.ai_socktype = SOCK_STREAM;
+    hints.ai_flags = AI_ADDRCONFIG;
+    return getaddrinfo("localhost", NULL, &hints, &ai) != 0;
+}], [apr_cv_gai_addrconfig=yes], 
+    [apr_cv_gai_addrconfig=no],
+    [apr_cv_gai_addrconfig=no])])
+
+if test $apr_cv_gai_addrconfig = yes; then
+   AC_DEFINE(HAVE_GAI_ADDRCONFIG, 1, [Define if getaddrinfo accepts the AI_ADDRCONFIG flag])
+fi
+])
+
+dnl
+dnl check for working getnameinfo()
+dnl
+AC_DEFUN([APR_CHECK_WORKING_GETNAMEINFO], [
+  AC_CACHE_CHECK(for working getnameinfo, ac_cv_working_getnameinfo,[
+  AC_TRY_RUN( [
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+int main(void) {
+    struct sockaddr_in sa;
+    char hbuf[256];
+    int error;
+
+    sa.sin_family = AF_INET;
+    sa.sin_port = 0;
+    sa.sin_addr.s_addr = inet_addr("127.0.0.1");
+#ifdef SIN6_LEN
+    sa.sin_len = sizeof(sa);
+#endif
+
+    error = getnameinfo((const struct sockaddr *)&sa, sizeof(sa),
+                        hbuf, 256, NULL, 0,
+                        NI_NUMERICHOST);
+    if (error) {
+        exit(1);
+    } else {
+        exit(0);
+    }
+}
+],[
+  ac_cv_working_getnameinfo="yes"
+],[
+  ac_cv_working_getnameinfo="no"
+],[
+  ac_cv_working_getnameinfo="yes"
+])])
+if test "$ac_cv_working_getnameinfo" = "yes"; then
+  AC_DEFINE(HAVE_GETNAMEINFO, 1, [Define if getnameinfo exists])
+fi
+])
+
+dnl
+dnl check for negative error codes for getaddrinfo()
+dnl
+AC_DEFUN([APR_CHECK_NEGATIVE_EAI], [
+  AC_CACHE_CHECK(for negative error codes for getaddrinfo, ac_cv_negative_eai,[
+  AC_TRY_RUN( [
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
+int main(void) {
+    if (EAI_ADDRFAMILY < 0) {
+        exit(0);
+    }
+    exit(1);
+}
+],[
+  ac_cv_negative_eai="yes"
+],[
+  ac_cv_negative_eai="no"
+],[
+  ac_cv_negative_eai="no"
+])])
+if test "$ac_cv_negative_eai" = "yes"; then
+  AC_DEFINE(NEGATIVE_EAI, 1, [Define if EAI_ error codes from getaddrinfo are negative])
+fi
+])
+
+dnl
+dnl Checks the definition of gethostbyname_r and gethostbyaddr_r
+dnl which are different for glibc, solaris and assorted other operating
+dnl systems
+dnl
+dnl Note that this test is executed too early to see if we have all of
+dnl the headers.
+AC_DEFUN([APR_CHECK_GETHOSTBYNAME_R_STYLE], [
+
+dnl Try and compile a glibc2 gethostbyname_r piece of code, and set the
+dnl style of the routines to glibc2 on success
+AC_CACHE_CHECK([style of gethostbyname_r routine], ac_cv_gethostbyname_r_style,
+APR_TRY_COMPILE_NO_WARNING([
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+],[
+int tmp = gethostbyname_r((const char *) 0, (struct hostent *) 0, 
+                          (char *) 0, 0, (struct hostent **) 0, &tmp);
+/* use tmp to suppress the warning */
+tmp=0;
+], ac_cv_gethostbyname_r_style=glibc2, ac_cv_gethostbyname_r_style=none))
+
+if test "$ac_cv_gethostbyname_r_style" = "glibc2"; then
+    AC_DEFINE(GETHOSTBYNAME_R_GLIBC2, 1, [Define if gethostbyname_r has the glibc style])
+fi
+
+AC_CACHE_CHECK([3rd argument to the gethostbyname_r routines], ac_cv_gethostbyname_r_arg,
+APR_TRY_COMPILE_NO_WARNING([
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+],[
+int tmp = gethostbyname_r((const char *) 0, (struct hostent *) 0, 
+                          (struct hostent_data *) 0);
+/* use tmp to suppress the warning */
+tmp=0;
+], ac_cv_gethostbyname_r_arg=hostent_data, ac_cv_gethostbyname_r_arg=char))
+
+if test "$ac_cv_gethostbyname_r_arg" = "hostent_data"; then
+    AC_DEFINE(GETHOSTBYNAME_R_HOSTENT_DATA, 1, [Define if gethostbyname_r has the hostent_data for the third argument])
+fi
+])
+
+dnl
+dnl Checks the definition of getservbyname_r
+dnl which are different for glibc, solaris and assorted other operating
+dnl systems
+dnl
+dnl Note that this test is executed too early to see if we have all of
+dnl the headers.
+AC_DEFUN([APR_CHECK_GETSERVBYNAME_R_STYLE], [
+
+dnl Try and compile a glibc2 getservbyname_r piece of code, and set the
+dnl style of the routines to glibc2 on success
+AC_CACHE_CHECK([style of getservbyname_r routine], ac_cv_getservbyname_r_style, [
+APR_TRY_COMPILE_NO_WARNING([
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+],[
+int tmp = getservbyname_r((const char *) 0, (const char *) 0,
+                          (struct servent *) 0, (char *) 0, 0,
+                          (struct servent **) 0);
+/* use tmp to suppress the warning */
+tmp=0;
+], ac_cv_getservbyname_r_style=glibc2, ac_cv_getservbyname_r_style=none)
+
+if test "$ac_cv_getservbyname_r_style" = "none"; then
+    dnl Try and compile a Solaris getservbyname_r piece of code, and set the
+    dnl style of the routines to solaris on success
+    APR_TRY_COMPILE_NO_WARNING([
+    #ifdef HAVE_SYS_TYPES_H
+    #include <sys/types.h>
+    #endif
+    #ifdef HAVE_NETINET_IN_H
+    #include <netinet/in.h>
+    #endif
+    #ifdef HAVE_ARPA_INET_H
+    #include <arpa/inet.h>
+    #endif
+    #ifdef HAVE_NETDB_H
+    #include <netdb.h>
+    #endif
+    #ifdef HAVE_STDLIB_H
+    #include <stdlib.h>
+    #endif
+    ],[
+    struct servent *tmp = getservbyname_r((const char *) 0, (const char *) 0,
+                                          (struct servent *) 0, (char *) 0, 0);
+    /* use tmp to suppress the warning */
+    tmp=NULL;
+    ], ac_cv_getservbyname_r_style=solaris, ac_cv_getservbyname_r_style=none)
+fi
+
+if test "$ac_cv_getservbyname_r_style" = "none"; then
+    dnl Try and compile a OSF/1 getservbyname_r piece of code, and set the
+    dnl style of the routines to osf1 on success
+    APR_TRY_COMPILE_NO_WARNING([
+    #ifdef HAVE_SYS_TYPES_H
+    #include <sys/types.h>
+    #endif
+    #ifdef HAVE_NETINET_IN_H
+    #include <netinet/in.h>
+    #endif
+    #ifdef HAVE_ARPA_INET_H
+    #include <arpa/inet.h>
+    #endif
+    #ifdef HAVE_NETDB_H
+    #include <netdb.h>
+    #endif
+    #ifdef HAVE_STDLIB_H
+    #include <stdlib.h>
+    #endif
+    ],[
+    int tmp = getservbyname_r((const char *) 0, (const char *) 0,
+                              (struct servent *) 0, (struct servent_data *) 0);
+    /* use tmp to suppress the warning */
+    tmp=0;
+    ], ac_cv_getservbyname_r_style=osf1, ac_cv_getservbyname_r_style=none)
+fi
+])
+
+if test "$ac_cv_getservbyname_r_style" = "glibc2"; then
+    AC_DEFINE(GETSERVBYNAME_R_GLIBC2, 1, [Define if getservbyname_r has the glibc style])
+elif test "$ac_cv_getservbyname_r_style" = "solaris"; then
+    AC_DEFINE(GETSERVBYNAME_R_SOLARIS, 1, [Define if getservbyname_r has the Solaris style])
+elif test "$ac_cv_getservbyname_r_style" = "osf1"; then
+    AC_DEFINE(GETSERVBYNAME_R_OSF1, 1, [Define if getservbyname_r has the OSF/1 style])
+fi
+])
+
+dnl
+dnl see if TCP_NODELAY setting is inherited from listening sockets
+dnl
+AC_DEFUN([APR_CHECK_TCP_NODELAY_INHERITED], [
+  AC_CACHE_CHECK(if TCP_NODELAY setting is inherited from listening sockets, ac_cv_tcp_nodelay_inherited,[
+  AC_TRY_RUN( [
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETINET_TCP_H
+#include <netinet/tcp.h>
+#endif
+#ifndef HAVE_SOCKLEN_T
+typedef int socklen_t;
+#endif
+int main(void) {
+    int listen_s, connected_s, client_s;
+    int listen_port, rc;
+    struct sockaddr_in sa;
+    socklen_t sa_len;
+    socklen_t option_len;
+    int option;
+
+    listen_s = socket(AF_INET, SOCK_STREAM, 0);
+    if (listen_s < 0) {
+        perror("socket");
+        exit(1);
+    }
+    option = 1;
+    rc = setsockopt(listen_s, IPPROTO_TCP, TCP_NODELAY, &option, sizeof option);
+    if (rc < 0) {
+        perror("setsockopt TCP_NODELAY");
+        exit(1);
+    }
+    memset(&sa, 0, sizeof sa);
+    sa.sin_family = AF_INET;
+#ifdef BEOS
+    sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+#endif
+    /* leave port 0 to get ephemeral */
+    rc = bind(listen_s, (struct sockaddr *)&sa, sizeof sa);
+    if (rc < 0) {
+        perror("bind for ephemeral port");
+        exit(1);
+    }
+    /* find ephemeral port */
+    sa_len = sizeof(sa);
+    rc = getsockname(listen_s, (struct sockaddr *)&sa, &sa_len);
+    if (rc < 0) {
+        perror("getsockname");
+        exit(1);
+    }
+    listen_port = sa.sin_port;
+    rc = listen(listen_s, 5);
+    if (rc < 0) {
+        perror("listen");
+        exit(1);
+    }
+    client_s = socket(AF_INET, SOCK_STREAM, 0);
+    if (client_s < 0) {
+        perror("socket");
+        exit(1);
+    }
+    memset(&sa, 0, sizeof sa);
+    sa.sin_family = AF_INET;
+    sa.sin_port   = listen_port;
+#ifdef BEOS
+    sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+#endif
+    /* leave sin_addr all zeros to use loopback */
+    rc = connect(client_s, (struct sockaddr *)&sa, sizeof sa);
+    if (rc < 0) {
+        perror("connect");
+        exit(1);
+    }
+    sa_len = sizeof sa;
+    connected_s = accept(listen_s, (struct sockaddr *)&sa, &sa_len);
+    if (connected_s < 0) {
+        perror("accept");
+        exit(1);
+    }
+    option_len = sizeof option;
+    rc = getsockopt(connected_s, IPPROTO_TCP, TCP_NODELAY, &option, &option_len);
+    if (rc < 0) {
+        perror("getsockopt");
+        exit(1);
+    }
+    if (!option) {
+        fprintf(stderr, "TCP_NODELAY is not set in the child.\n");
+        exit(1);
+    }
+    return 0;
+}
+],[
+    ac_cv_tcp_nodelay_inherited="yes"
+],[
+    ac_cv_tcp_nodelay_inherited="no"
+],[
+    ac_cv_tcp_nodelay_inherited="yes"
+])])
+if test "$ac_cv_tcp_nodelay_inherited" = "yes"; then
+    tcp_nodelay_inherited=1
+else
+    tcp_nodelay_inherited=0
+fi
+])
+
+dnl
+dnl Determine whether TCP_NODELAY and TCP_CORK can both be set
+dnl on a TCP socket.
+dnl
+AC_DEFUN([APR_CHECK_TCP_NODELAY_WITH_CORK], [
+AC_CACHE_CHECK([whether TCP_NODELAY and TCP_CORK can both be enabled],
+[apr_cv_tcp_nodelay_with_cork],
+[AC_RUN_IFELSE([AC_LANG_PROGRAM([[
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETINET_TCP_H
+#include <netinet/tcp.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+]], [[
+    int fd, flag, rc;
+
+    fd = socket(AF_INET, SOCK_STREAM, 0);
+    if (fd < 0) {
+       exit(1);
+    }
+
+    flag = 1;
+    rc = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof flag);
+    if (rc < 0) {
+        perror("setsockopt TCP_NODELAY");
+        exit(2);
+    }
+
+    flag = 1;
+    rc = setsockopt(fd, IPPROTO_TCP, TCP_CORK, &flag, sizeof flag);
+    if (rc < 0) {
+        perror("setsockopt TCP_CORK");
+        exit(3);
+    }
+
+    exit(0);
+]])], [apr_cv_tcp_nodelay_with_cork=yes], [apr_cv_tcp_nodelay_with_cork=no])])
+
+if test "$apr_cv_tcp_nodelay_with_cork" = "yes"; then
+  AC_DEFINE([HAVE_TCP_NODELAY_WITH_CORK], 1,
+            [Define if TCP_NODELAY and TCP_CORK can be enabled at the same time])
+fi
+])
+
+
+dnl
+dnl see if O_NONBLOCK setting is inherited from listening sockets
+dnl
+AC_DEFUN([APR_CHECK_O_NONBLOCK_INHERITED], [
+  AC_CACHE_CHECK(if O_NONBLOCK setting is inherited from listening sockets, ac_cv_o_nonblock_inherited,[
+  AC_TRY_RUN( [
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETINET_TCP_H
+#include <netinet/tcp.h>
+#endif
+#ifndef HAVE_SOCKLEN_T
+typedef int socklen_t;
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+int main(void) {
+    int listen_s, connected_s, client_s;
+    int listen_port, rc;
+    struct sockaddr_in sa;
+    socklen_t sa_len;
+    fd_set fds;
+    struct timeval tv;
+
+    listen_s = socket(AF_INET, SOCK_STREAM, 0);
+    if (listen_s < 0) {
+        perror("socket");
+        exit(1);
+    }
+    memset(&sa, 0, sizeof sa);
+    sa.sin_family = AF_INET;
+#ifdef BEOS
+    sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+#endif
+    /* leave port 0 to get ephemeral */
+    rc = bind(listen_s, (struct sockaddr *)&sa, sizeof sa);
+    if (rc < 0) {
+        perror("bind for ephemeral port");
+        exit(1);
+    }
+    /* find ephemeral port */
+    sa_len = sizeof(sa);
+    rc = getsockname(listen_s, (struct sockaddr *)&sa, &sa_len);
+    if (rc < 0) {
+        perror("getsockname");
+        exit(1);
+    }
+    listen_port = sa.sin_port;
+    rc = listen(listen_s, 5);
+    if (rc < 0) {
+        perror("listen");
+        exit(1);
+    }
+    rc = fcntl(listen_s, F_SETFL, O_NONBLOCK);
+    if (rc < 0) {
+        perror("fcntl(F_SETFL)");
+        exit(1);
+    }
+    client_s = socket(AF_INET, SOCK_STREAM, 0);
+    if (client_s < 0) {
+        perror("socket");
+        exit(1);
+    }
+    memset(&sa, 0, sizeof sa);
+    sa.sin_family = AF_INET;
+    sa.sin_port   = listen_port;
+#ifdef BEOS
+    sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+#endif
+    /* leave sin_addr all zeros to use loopback */
+    rc = connect(client_s, (struct sockaddr *)&sa, sizeof sa);
+    if (rc < 0) {
+        perror("connect");
+        exit(1);
+    }
+    sa_len = sizeof sa;
+    /* 1 second select timeout */
+    tv.tv_sec = 1;
+    tv.tv_usec = 0;
+    /* Set up fd set */
+    FD_ZERO(&fds);
+    FD_SET(listen_s, &fds);
+    /* Wait for socket to become readable */
+    rc = select(listen_s + 1, &fds, NULL, NULL, &tv);
+    if (rc < 0) {
+        perror("select");
+        exit(1);
+    }
+    if (rc == 0) {
+        fprintf(stderr, "Socket failed to become readable (timeout)\n");
+        exit(1);
+    }
+    if (!FD_ISSET(listen_s, &fds)) {
+        fprintf(stderr, "Socket failed to become readable (selected another fd)\n");
+        exit(1);
+    }
+    connected_s = accept(listen_s, (struct sockaddr *)&sa, &sa_len);
+    if (connected_s < 0) {
+        perror("accept");
+        exit(1);
+    }
+    rc = fcntl(connected_s, F_GETFL, 0);
+    if (rc < 0) {
+        perror("fcntl(F_GETFL)");
+        exit(1);
+    }
+    if (!(rc & O_NONBLOCK)) {
+        fprintf(stderr, "O_NONBLOCK is not set in the child.\n");
+        exit(1);
+    }
+    return 0;
+}
+],[
+    ac_cv_o_nonblock_inherited="yes"
+],[
+    ac_cv_o_nonblock_inherited="no"
+],[
+    ac_cv_o_nonblock_inherited="yes"
+])])
+if test "$ac_cv_o_nonblock_inherited" = "yes"; then
+    o_nonblock_inherited=1
+else
+    o_nonblock_inherited=0
+fi
+])
+
+dnl 
+dnl check for socklen_t, fall back to unsigned int
+dnl
+AC_DEFUN([APR_CHECK_SOCKLEN_T], [
+AC_CACHE_CHECK(for socklen_t, ac_cv_socklen_t,[
+AC_TRY_COMPILE([
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+],[
+socklen_t foo = (socklen_t) 0;
+],[
+    ac_cv_socklen_t=yes
+],[
+    ac_cv_socklen_t=no
+])
+])
+
+if test "$ac_cv_socklen_t" = "yes"; then
+  AC_DEFINE(HAVE_SOCKLEN_T, 1, [Whether you have socklen_t])
+fi
+])
+
+
+AC_DEFUN([APR_CHECK_INET_ADDR], [
+AC_CACHE_CHECK(for inet_addr, ac_cv_func_inet_addr,[
+AC_TRY_COMPILE([
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+],[
+inet_addr("127.0.0.1");
+],[
+    ac_cv_func_inet_addr=yes
+],[
+    ac_cv_func_inet_addr=no
+])
+])
+
+if test "$ac_cv_func_inet_addr" = "yes"; then
+  have_inet_addr=1
+else
+  have_inet_addr=0
+fi
+])
+
+
+AC_DEFUN([APR_CHECK_INET_NETWORK], [
+AC_CACHE_CHECK(for inet_network, ac_cv_func_inet_network,[
+AC_TRY_COMPILE([
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+],[
+inet_network("127.0.0.1");
+],[
+    ac_cv_func_inet_network=yes
+],[
+    ac_cv_func_inet_network=no
+])
+])
+
+if test "$ac_cv_func_inet_network" = "yes"; then
+  have_inet_network=1
+else
+  have_inet_network=0
+fi
+])
+
+dnl Check for presence of struct sockaddr_storage.
+AC_DEFUN([APR_CHECK_SOCKADDR_STORAGE], [
+AC_CACHE_CHECK(for sockaddr_storage, apr_cv_define_sockaddr_storage,[
+AC_TRY_COMPILE([
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+],[struct sockaddr_storage sa;],
+[apr_cv_define_sockaddr_storage=yes],
+[apr_cv_define_sockaddr_storage=no])])
+
+if test "$apr_cv_define_sockaddr_storage" = "yes"; then
+  have_sa_storage=1
+else
+  have_sa_storage=0
+fi
+AC_SUBST(have_sa_storage)
+])
+
+dnl Check for presence of struct sockaddr_in6.
+AC_DEFUN([APR_CHECK_SOCKADDR_IN6], [
+AC_CACHE_CHECK(for sockaddr_in6, ac_cv_define_sockaddr_in6,[
+AC_TRY_COMPILE([
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+],[
+struct sockaddr_in6 sa;
+],[
+    ac_cv_define_sockaddr_in6=yes
+],[
+    ac_cv_define_sockaddr_in6=no
+])
+])
+
+if test "$ac_cv_define_sockaddr_in6" = "yes"; then
+  have_sockaddr_in6=1
+else
+  have_sockaddr_in6=0
+fi
+])
+
+dnl Check for presence of struct sockaddr_un.
+AC_DEFUN([APR_CHECK_SOCKADDR_UN], [
+AC_CACHE_CHECK(for sockaddr_un, ac_cv_define_sockaddr_un,[
+AC_TRY_COMPILE([
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_SYS_UN_H
+#include <sys/un.h>
+#endif
+],[
+struct sockaddr_un sa;
+],[
+    ac_cv_define_sockaddr_un=yes
+],[
+    ac_cv_define_sockaddr_un=no
+])
+])
+
+if test "$ac_cv_define_sockaddr_un" = "yes"; then
+  have_sockaddr_un=1
+else
+  have_sockaddr_un=0
+fi
+AC_SUBST(have_sockaddr_un)
+])
+
+dnl
+dnl APR_H_ERRNO_COMPILE_CHECK
+dnl
+AC_DEFUN([APR_H_ERRNO_COMPILE_CHECK], [
+  if test x$1 != x; then
+    CPPFLAGS="-D$1 $CPPFLAGS"
+  fi
+  AC_TRY_COMPILE([
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+],[
+int h_e = h_errno;
+],[
+  if test x$1 != x; then
+    ac_cv_h_errno_cppflags="$1"
+  else
+    ac_cv_h_errno_cppflags=yes
+  fi
+],[
+  ac_cv_h_errno_cppflags=no
+])])
+
+
+dnl
+dnl APR_CHECK_SCTP
+dnl
+dnl check for presence of SCTP protocol support
+dnl
+AC_DEFUN([APR_CHECK_SCTP],
+[
+  AC_CACHE_CHECK([whether SCTP is supported], [apr_cv_sctp], [
+  AC_TRY_RUN([
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETINET_SCTP_H
+#include <netinet/sctp.h>
+#endif
+#ifdef HAVE_NETINET_SCTP_UIO_H
+#include <netinet/sctp_uio.h>
+#endif
+#include <stdlib.h>
+int main(void) {
+    int s, opt = 1;
+    if ((s = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP)) < 0)
+       exit(1);
+    if (setsockopt(s, IPPROTO_SCTP, SCTP_NODELAY, &opt, sizeof(int)) < 0)
+       exit(2);
+    exit(0);
+}], [apr_cv_sctp=yes], [apr_cv_sctp=no], [apr_cv_sctp=no])])
+
+if test "$apr_cv_sctp" = "yes"; then
+    have_sctp=1
+else
+    have_sctp=0
+fi
+])
+
+dnl APR_CHECK_MCAST: check for multicast interfaces
+AC_DEFUN([APR_CHECK_MCAST], [
+AC_CACHE_CHECK([for struct ip_mreq], [apr_cv_struct_ipmreq], [
+AC_TRY_COMPILE([
+#include <sys/types.h>
+#include <netinet/in.h>
+], [
+    struct ip_mreq mip;
+    mip.imr_interface.s_addr = INADDR_ANY;
+], [apr_cv_struct_ipmreq=yes], [apr_cv_struct_ipmreq=no], [apr_cv_struct_ipmreq=yes])])
+
+if test $apr_cv_struct_ipmreq = yes; then
+   AC_DEFINE([HAVE_STRUCT_IPMREQ], 1, [Define if struct impreq was found])
+fi
+])
+
+dnl
+dnl APR_CHECK_H_ERRNO_FLAG
+dnl
+dnl checks which flags are necessary for <netdb.h> to define h_errno
+dnl
+AC_DEFUN([APR_CHECK_H_ERRNO_FLAG], [
+  AC_MSG_CHECKING([for h_errno in netdb.h])
+  AC_CACHE_VAL(ac_cv_h_errno_cppflags,[
+    APR_H_ERRNO_COMPILE_CHECK
+    if test "$ac_cv_h_errno_cppflags" = "no"; then
+      ac_save="$CPPFLAGS"
+      for flag in _XOPEN_SOURCE_EXTENDED; do
+        APR_H_ERRNO_COMPILE_CHECK($flag)
+        if test "$ac_cv_h_errno_cppflags" != "no"; then
+          break
+        fi
+      done
+      CPPFLAGS="$ac_save"
+    fi
+  ])
+  if test "$ac_cv_h_errno_cppflags" != "no"; then
+    if test "$ac_cv_h_errno_cppflags" != "yes"; then
+      CPPFLAGS="-D$ac_cv_h_errno_cppflags $CPPFLAGS"
+      AC_MSG_RESULT([yes, with -D$ac_cv_h_errno_cppflags])
+    else
+      AC_MSG_RESULT([$ac_cv_h_errno_cppflags])
+    fi
+  else
+    AC_MSG_RESULT([$ac_cv_h_errno_cppflags])
+  fi
+])
+
+
+AC_DEFUN([APR_EBCDIC], [
+  AC_CACHE_CHECK([whether system uses EBCDIC],ac_cv_ebcdic,[
+  AC_TRY_RUN( [
+int main(void) { 
+  return (unsigned char)'A' != (unsigned char)0xC1; 
+} 
+],[
+  ac_cv_ebcdic="yes"
+],[
+  ac_cv_ebcdic="no"
+],[
+  ac_cv_ebcdic="no"
+])])
+  if test "$ac_cv_ebcdic" = "yes"; then
+    apr_charset_ebcdic=1
+  else
+    apr_charset_ebcdic=0
+  fi
+  AC_SUBST(apr_charset_ebcdic)
+])
+
diff --git a/build/apr_rules.mk.in b/build/apr_rules.mk.in
new file mode 100644
index 00000000000..9362a20efcf
--- /dev/null
+++ b/build/apr_rules.mk.in
@@ -0,0 +1,211 @@
+# 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.
+#
+#
+
+#
+# rules.mk: standard rules for APR
+#
+
+@SET_MAKE@
+
+#
+# Configuration variables
+#
+apr_builddir=@apr_builddir@
+apr_builders=@apr_builders@
+
+# Some layouts require knowing what version we are at.
+APR_MAJOR_VERSION=@APR_MAJOR_VERSION@
+APR_DOTTED_VERSION=@APR_DOTTED_VERSION@
+
+CC=@CC@
+RM=@RM@
+AWK=@AWK@
+SHELL=@SHELL@
+LIBTOOL=@LIBTOOL@
+
+# compilation and linking flags that are supposed to be set only by the user.
+# configure adds to them for tests, but we restore them at the end.
+#
+CFLAGS=@CFLAGS@
+CPPFLAGS=@CPPFLAGS@
+LDFLAGS=@LDFLAGS@
+LIBS=@LIBS@
+DEFS=@DEFS@
+
+# anything added to the standard flags by configure is moved to EXTRA_*
+# at the end of the process.
+#
+EXTRA_CFLAGS=@EXTRA_CFLAGS@
+EXTRA_CPPFLAGS=@EXTRA_CPPFLAGS@
+EXTRA_LDFLAGS=@EXTRA_LDFLAGS@
+EXTRA_LIBS=@EXTRA_LIBS@
+EXTRA_INCLUDES=@EXTRA_INCLUDES@
+
+# CPPFLAGS which are used only while building APR itself
+#
+INTERNAL_CPPFLAGS=@INTERNAL_CPPFLAGS@
+
+# NOTEST_* are flags and libraries that can be added by the user without
+# causing them to be used in configure tests (necessary for things like
+# -Werror and other strict warnings that maintainers like to use).
+#
+NOTEST_CFLAGS=@NOTEST_CFLAGS@
+NOTEST_CPPFLAGS=@NOTEST_CPPFLAGS@
+NOTEST_LDFLAGS=@NOTEST_LDFLAGS@
+NOTEST_LIBS=@NOTEST_LIBS@
+
+# Finally, combine all of the flags together in the proper order so that
+# the user-defined flags can always override the configure ones, if needed.
+# Note that includes are listed after the flags because -I options have
+# left-to-right precedence and CPPFLAGS may include user-defined overrides.
+#
+ALL_CFLAGS   = $(EXTRA_CFLAGS) $(NOTEST_CFLAGS) $(CFLAGS)
+ALL_CPPFLAGS = $(DEFS) $(INTERNAL_CPPFLAGS) $(EXTRA_CPPFLAGS) $(NOTEST_CPPFLAGS) $(CPPFLAGS)
+ALL_LDFLAGS  = $(EXTRA_LDFLAGS) $(NOTEST_LDFLAGS) $(LDFLAGS)
+ALL_LIBS     = $(LIBS) $(NOTEST_LIBS) $(EXTRA_LIBS)
+ALL_INCLUDES = $(INCLUDES) $(EXTRA_INCLUDES)
+
+LTFLAGS      = @LTFLAGS@
+LT_LDFLAGS   = @LT_LDFLAGS@
+
+# The set of object files that will be linked into the target library.
+# The build-outputs.mk specifies a different set for each platform. The
+# configure script will select the appropriate set.
+#
+OBJECTS      = @OBJECTS_PLATFORM@
+
+#
+# Basic macro setup
+#
+COMPILE      = $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(ALL_INCLUDES)
+LT_COMPILE   = @lt_compile@
+
+LINK         = @link@
+
+APR_MKDIR        = $(apr_builders)/mkdir.sh
+APR_MKEXPORT     = $(AWK) -f $(apr_builders)/make_exports.awk
+APR_MKVAREXPORT  = $(AWK) -f $(apr_builders)/make_var_export.awk
+MKDEP            = @MKDEP@
+
+#
+# Standard build rules
+#
+all: all-recursive
+depend: depend-recursive
+clean: clean-recursive
+distclean: distclean-recursive
+extraclean: extraclean-recursive
+
+install: all-recursive
+
+
+all-recursive depend-recursive:
+	@otarget=`echo $@ | sed s/-recursive//`; \
+	list='$(SOURCE_DIRS)'; \
+	for i in $$list; do \
+	    if test -f "$$i/Makefile"; then \
+		target="$$otarget"; \
+		echo "Making $$target in $$i"; \
+		if test "$$i" = "."; then \
+		    made_local=yes; \
+		    target="local-$$target"; \
+		fi; \
+		(cd $$i && $(MAKE) $$target) || exit 1; \
+	    fi; \
+	done; \
+        if test "$$otarget" = "all" && test -z "$(TARGETS)"; then \
+	    made_local=yes; \
+	fi; \
+	if test "$$made_local" != "yes"; then \
+	    $(MAKE) "local-$$otarget" || exit 1; \
+	fi
+
+clean-recursive distclean-recursive extraclean-recursive:
+	@otarget=`echo $@ | sed s/-recursive//`; \
+	list='$(CLEAN_SUBDIRS)'; \
+	for i in $$list; do \
+	    if test -f "$$i/Makefile"; then \
+		target="$$otarget"; \
+		echo "Making $$target in $$i"; \
+		if test "$$i" = "."; then \
+		    made_local=yes; \
+		    target="local-$$target"; \
+		fi; \
+		(cd $$i && $(MAKE) $$target); \
+	    fi; \
+	done; \
+        if test "$$otarget" = "all" && test -z "$(TARGETS)"; then \
+	    made_local=yes; \
+	fi; \
+	if test "$$made_local" != "yes"; then \
+	    $(MAKE) "local-$$otarget"; \
+	fi
+
+# autoconf 2.5x is creating a 'autom4te.cache' directory
+# In case someone ran autoconf by hand, get rid of that directory
+# as well.
+local-clean: x-local-clean
+	@list='. $(SOURCE_DIRS)'; \
+	for i in $$list; do \
+	    echo $(RM) -f $$i/*.o $$i/*.lo $$i/*.a $$i/*.la $$i/*.so $$i/*.obj; \
+	    $(RM) -f $$i/*.o $$i/*.lo $$i/*.a $$i/*.la $$i/*.so $$i/*.obj; \
+	    echo $(RM) -rf $$i/.libs; \
+	    $(RM) -rf $$i/.libs; \
+        done
+	$(RM) -f $(CLEAN_TARGETS) $(PROGRAMS)
+	$(RM) -rf autom4te.cache
+
+local-distclean: local-clean x-local-distclean
+	$(RM) -f Makefile $(DISTCLEAN_TARGETS)
+
+local-extraclean: local-distclean x-local-extraclean
+	@if test -n "$(EXTRACLEAN_TARGETS)"; then \
+	    echo $(RM) -f $(EXTRACLEAN_TARGETS) ; \
+	    $(RM) -f $(EXTRACLEAN_TARGETS) ; \
+	fi
+
+local-all: $(TARGETS)
+
+local-depend: x-local-depend
+	@if test -n "`ls $(srcdir)/*.c 2> /dev/null`"; then \
+		$(RM) -f .deps; \
+		list='$(srcdir)/*.c'; \
+		for i in $$list; do \
+			$(MKDEP) $(ALL_CPPFLAGS) $(ALL_INCLUDES) $$i | sed 's/\.o:/.lo:/' >> .deps; \
+		done; \
+	fi
+
+# to be filled in by the actual Makefile
+x-local-depend x-local-clean x-local-distclean x-local-extraclean:
+
+#
+# Implicit rules for creating outputs from input files
+#
+.SUFFIXES:
+.SUFFIXES: .c .lo .o
+
+.c.o:
+	$(COMPILE) -c $<
+
+.c.lo:
+	$(LT_COMPILE)
+
+.PHONY: all all-recursive local-all install \
+	depend depend-recursive local-depend x-local-depend \
+	clean clean-recursive local-clean x-local-clean \
+	distclean distclean-recursive local-distclean x-local-distclean \
+	extraclean extraclean-recursive local-extraclean x-local-extraclean
diff --git a/build/apr_threads.m4 b/build/apr_threads.m4
new file mode 100644
index 00000000000..cbc677b1467
--- /dev/null
+++ b/build/apr_threads.m4
@@ -0,0 +1,283 @@
+dnl -------------------------------------------------------- -*- autoconf -*-
+dnl Licensed to the Apache Software Foundation (ASF) under one or more
+dnl contributor license agreements.  See the NOTICE file distributed with
+dnl this work for additional information regarding copyright ownership.
+dnl The ASF licenses this file to You under the Apache License, Version 2.0
+dnl (the "License"); you may not use this file except in compliance with
+dnl the License.  You may obtain a copy of the License at
+dnl
+dnl     http://www.apache.org/licenses/LICENSE-2.0
+dnl
+dnl Unless required by applicable law or agreed to in writing, software
+dnl distributed under the License is distributed on an "AS IS" BASIS,
+dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+dnl See the License for the specific language governing permissions and
+dnl limitations under the License.
+
+dnl -----------------------------------------------------------------
+dnl apr_threads.m4: APR's autoconf macros for testing thread support
+dnl
+
+dnl
+dnl APR_CHECK_PTHREADS_H([ ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
+dnl
+dnl gcc issues warnings when parsing AIX 4.3.3's pthread.h
+dnl which causes autoconf to incorrectly conclude that
+dnl pthreads is not available.
+dnl Turn off warnings if we're using gcc.
+dnl
+AC_DEFUN(APR_CHECK_PTHREADS_H, [
+  if test "$GCC" = "yes"; then
+    SAVE_FL="$CPPFLAGS"
+    CPPFLAGS="$CPPFLAGS -w"
+    AC_CHECK_HEADERS(pthread.h, [ $1 ] , [ $2 ] )
+    CPPFLAGS="$SAVE_FL"
+  else
+    AC_CHECK_HEADERS(pthread.h, [ $1 ] , [ $2 ] )
+  fi
+])dnl
+
+
+dnl
+dnl APR_CHECK_PTHREAD_GETSPECIFIC_TWO_ARGS
+dnl
+AC_DEFUN(APR_CHECK_PTHREAD_GETSPECIFIC_TWO_ARGS, [
+AC_CACHE_CHECK(whether pthread_getspecific takes two arguments, ac_cv_pthread_getspecific_two_args,[
+AC_TRY_COMPILE([
+#include <pthread.h>
+],[
+pthread_key_t key;
+void *tmp;
+pthread_getspecific(key,&tmp);
+],[
+    ac_cv_pthread_getspecific_two_args=yes
+],[
+    ac_cv_pthread_getspecific_two_args=no
+])
+])
+
+if test "$ac_cv_pthread_getspecific_two_args" = "yes"; then
+  AC_DEFINE(PTHREAD_GETSPECIFIC_TAKES_TWO_ARGS, 1, [Define if pthread_getspecific() has two args])
+fi
+])dnl
+
+
+dnl
+dnl APR_CHECK_PTHREAD_ATTR_GETDETACHSTATE_ONE_ARG
+dnl
+AC_DEFUN(APR_CHECK_PTHREAD_ATTR_GETDETACHSTATE_ONE_ARG, [
+AC_CACHE_CHECK(whether pthread_attr_getdetachstate takes one argument, ac_cv_pthread_attr_getdetachstate_one_arg,[
+AC_TRY_COMPILE([
+#include <pthread.h>
+],[
+pthread_attr_t *attr;
+pthread_attr_getdetachstate(attr);
+],[
+    ac_cv_pthread_attr_getdetachstate_one_arg=yes
+],[
+    ac_cv_pthread_attr_getdetachstate_one_arg=no
+])
+])
+
+if test "$ac_cv_pthread_attr_getdetachstate_one_arg" = "yes"; then
+  AC_DEFINE(PTHREAD_ATTR_GETDETACHSTATE_TAKES_ONE_ARG, 1, [Define if pthread_attr_getdetachstate() has one arg])
+fi
+])dnl
+
+
+dnl
+dnl APR_PTHREADS_TRY_RUN(actions-if-success)
+dnl
+dnl Try running a program which uses pthreads, executing the
+dnl actions-if-success commands on success.
+dnl
+AC_DEFUN(APR_PTHREADS_TRY_RUN, [
+AC_TRY_RUN( [
+#include <pthread.h>
+#include <stddef.h>
+
+void *thread_routine(void *data) {
+    return data;
+}
+
+int main() {
+    pthread_t thd;
+    pthread_mutexattr_t mattr;
+    pthread_once_t once_init = PTHREAD_ONCE_INIT;
+    int data = 1;
+    pthread_mutexattr_init(&mattr);
+    return pthread_create(&thd, NULL, thread_routine, &data);
+} ], [apr_p_t_r=yes], [apr_p_t_r=no], [apr_p_t_r=no])
+
+if test $apr_p_t_r = yes; then
+  $1
+fi
+
+])dnl
+
+
+dnl
+dnl APR_PTHREADS_CHECK()
+dnl
+dnl Try to find a way to enable POSIX threads.  Sets the 
+dnl pthreads_working variable to "yes" on success.
+dnl
+AC_DEFUN([APR_PTHREADS_CHECK], [
+
+AC_CACHE_CHECK([for CFLAGS needed for pthreads], [apr_cv_pthreads_cflags],
+[apr_ptc_cflags=$CFLAGS
+ for flag in none -kthread -pthread -pthreads -mt -mthreads -Kthread -threads; do 
+    CFLAGS=$apr_ptc_cflags
+    test "x$flag" != "xnone" && CFLAGS="$CFLAGS $flag"
+    APR_PTHREADS_TRY_RUN([
+      apr_cv_pthreads_cflags="$flag"
+      break
+    ])
+ done
+ CFLAGS=$apr_ptc_cflags
+])
+
+if test -n "$apr_cv_pthreads_cflags"; then
+   pthreads_working=yes
+   if test "x$apr_cv_pthreads_cflags" != "xnone"; then
+     APR_ADDTO(CFLAGS,[$apr_cv_pthreads_cflags])
+   fi
+fi
+
+# The CFLAGS may or may not be sufficient to ensure that libapr
+# depends on the pthreads library: some versions of libtool
+# drop -pthread when passed on the link line; some versions of
+# gcc ignore -pthread when linking a shared object.  So always
+# try and add the relevant library to LIBS too.
+
+AC_CACHE_CHECK([for LIBS needed for pthreads], [apr_cv_pthreads_lib], [
+  apr_ptc_libs=$LIBS
+  for lib in -lpthread -lpthreads -lc_r; do
+    LIBS="$apr_ptc_libs $lib"
+    APR_PTHREADS_TRY_RUN([
+      apr_cv_pthreads_lib=$lib
+      break
+    ])
+  done
+  LIBS=$apr_ptc_libs
+])
+
+if test -n "$apr_cv_pthreads_lib"; then
+   pthreads_working=yes
+   APR_ADDTO(LIBS,[$apr_cv_pthreads_lib])
+fi
+
+if test "$pthreads_working" = "yes"; then
+  threads_result="POSIX Threads found"
+else
+  threads_result="POSIX Threads not found"
+fi
+])dnl
+
+dnl
+dnl APR_PTHREADS_CHECK_SAVE
+dnl APR_PTHREADS_CHECK_RESTORE
+dnl
+dnl Save the global environment variables that might be modified during
+dnl the checks for threading support so that they can restored if the
+dnl result is not what the caller wanted.
+dnl
+AC_DEFUN(APR_PTHREADS_CHECK_SAVE, [
+  apr_pthsv_CFLAGS="$CFLAGS"
+  apr_pthsv_LIBS="$LIBS"
+])dnl
+
+AC_DEFUN(APR_PTHREADS_CHECK_RESTORE, [
+  CFLAGS="$apr_pthsv_CFLAGS"
+  LIBS="$apr_pthsv_LIBS"
+])dnl
+
+dnl
+dnl APR_CHECK_SIGWAIT_ONE_ARG
+dnl
+AC_DEFUN([APR_CHECK_SIGWAIT_ONE_ARG], [
+  AC_CACHE_CHECK(whether sigwait takes one argument,ac_cv_sigwait_one_arg,[
+  AC_TRY_COMPILE([
+#if defined(__NETBSD__) || defined(DARWIN)
+    /* When using the unproven-pthreads package, we need to pull in this
+     * header to get a prototype for sigwait().  Else things will fail later
+     * on.  XXX Should probably be fixed in the unproven-pthreads package.
+     * Darwin is declaring sigwait() in the wrong place as well.
+     */
+#include <pthread.h>
+#endif
+#include <signal.h>
+],[
+  sigset_t set;
+ 
+  sigwait(&set);
+],[
+  ac_cv_sigwait_one_arg=yes
+],[
+  ac_cv_sigwait_one_arg=no
+])])
+  if test "$ac_cv_sigwait_one_arg" = "yes"; then
+    AC_DEFINE(SIGWAIT_TAKES_ONE_ARG,1,[ ])
+  fi
+])
+
+dnl Check for recursive mutex support (per SUSv3).
+AC_DEFUN([APR_CHECK_PTHREAD_RECURSIVE_MUTEX], [
+  AC_CACHE_CHECK([for recursive mutex support], [apr_cv_mutex_recursive],
+[AC_TRY_RUN([#include <sys/types.h>
+#include <pthread.h>
+#include <stdlib.h>
+
+int main() {
+    pthread_mutexattr_t attr;
+    pthread_mutex_t m;
+
+    exit (pthread_mutexattr_init(&attr) 
+          || pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)
+          || pthread_mutex_init(&m, &attr));
+}], [apr_cv_mutex_recursive=yes], [apr_cv_mutex_recursive=no], 
+[apr_cv_mutex_recursive=no])])
+
+if test "$apr_cv_mutex_recursive" = "yes"; then
+   AC_DEFINE([HAVE_PTHREAD_MUTEX_RECURSIVE], 1,
+             [Define if recursive pthread mutexes are available])
+fi
+])
+
+dnl Check for robust process-shared mutex support
+AC_DEFUN([APR_CHECK_PTHREAD_ROBUST_SHARED_MUTEX], [
+AC_CACHE_CHECK([for robust cross-process mutex support], 
+[apr_cv_mutex_robust_shared],
+[AC_TRY_RUN([
+#include <sys/types.h>
+#include <pthread.h>
+#include <stdlib.h>
+
+int main(int argc, char **argv)
+{
+    pthread_mutex_t mutex;
+    pthread_mutexattr_t attr;
+
+    if (pthread_mutexattr_init(&attr))
+        exit(1);
+    if (pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED))
+        exit(2);
+    if (pthread_mutexattr_setrobust_np(&attr, PTHREAD_MUTEX_ROBUST_NP))
+        exit(3);
+    if (pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT))
+        exit(4);
+    if (pthread_mutex_init(&mutex, &attr))
+        exit(5);
+    if (pthread_mutexattr_destroy(&attr))
+        exit(6);
+    if (pthread_mutex_destroy(&mutex))
+        exit(7);
+
+    exit(0);
+}], [apr_cv_mutex_robust_shared=yes], [apr_cv_mutex_robust_shared=no])])
+
+if test "$apr_cv_mutex_robust_shared" = "yes"; then
+   AC_DEFINE([HAVE_PTHREAD_MUTEX_ROBUST], 1,
+             [Define if cross-process robust mutexes are available])
+fi
+])
diff --git a/build/apr_win32.m4 b/build/apr_win32.m4
new file mode 100644
index 00000000000..f98137421a1
--- /dev/null
+++ b/build/apr_win32.m4
@@ -0,0 +1,33 @@
+
+dnl if $2 contains '@dd', links against mingw symbols
+dnl otherwise calls AC_CHECK_LIB
+AC_DEFUN([APR_CHECK_DLL_FUNC],[
+m4_define($1_function_name,m4_substr($2,0,m4_index($2,[@])))
+m4_define($1_function_arglength,m4_substr($2,m4_incr(m4_index($2,[@]))))
+m4_define($1_[function_name]_arglength,m4_substr($2,m4_incr(m4_index($2,[@]))))
+dnl m4_define(apr_check_dll_id,$1_m4_defn($1_function_name))
+
+AC_CACHE_CHECK([for $2 in $1],[ac_cv_lib_$1_]$1_function_name,[
+
+ac_func_search_save_LIBS=$LIBS
+LIBS="$LIBS -l$1"
+
+AC_TRY_LINK([
+#pragma pack(1)
+struct x {
+]m4_for([byte_id], 1, m4_defn([$1_function_name_arglength]), 1,[[ char c]]byte_id;
+)[};
+__stdcall ]$1_function_name[(]struct x[);],[
+struct x s = {0};
+]$1_function_name[(s)],
+[ac_cv_lib_$1_]$1_function_name[=yes],[ac_cv_lib_$1_]$1_function_name[=no])
+LIBS=$ac_func_search_save_LIBS
+])dnl AC_CACHE_CHECK
+
+AS_IF([test $ac_cv_lib_$1_]$1_function_name[ = yes],
+      [m4_default([$3], [AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_LIB$1),,Enable if this library is available)
+  LIBS="-l$1 $LIBS"
+])],
+    [$4])dnl
+])
+
diff --git a/build/aprapp.dsp b/build/aprapp.dsp
new file mode 100644
index 00000000000..30fcc1d56bb
--- /dev/null
+++ b/build/aprapp.dsp
@@ -0,0 +1,140 @@
+# Microsoft Developer Studio Project File - Name="aprapp" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=aprapp - 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 "aprapp.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 "aprapp.mak" CFG="aprapp - Win32 Release"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "aprapp - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "aprapp - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "aprapp - x64 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "aprapp - x64 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "aprapp - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "..\LibR"
+# PROP BASE Intermediate_Dir "LibR"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\LibR"
+# PROP Intermediate_Dir "LibR"
+# 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 "../include/arch" /I "../include/arch/win32" /I "../include/arch/unix" /D "NDEBUG" /D "WINNT" /D "WIN32" /D "_WINDOWS" /D APR_APP /D "APR_DECLARE_STATIC" /Fo"$(INTDIR)\" /Fd"$(OUTDIR)\aprapp-2" /FD /c
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\LibR\aprapp-2.lib"
+
+!ELSEIF  "$(CFG)" == "aprapp - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "..\LibD"
+# PROP BASE Intermediate_Dir "LibD"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\LibD"
+# PROP Intermediate_Dir "LibD"
+# 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 "../include/arch" /I "../include/arch/win32" /I "../include/arch/unix" /D "_DEBUG" /D "WINNT" /D "WIN32" /D "_WINDOWS" /D APR_APP /D "APR_DECLARE_STATIC" /Fo"$(INTDIR)\" /Fd"$(OUTDIR)\aprapp-2" /FD /c
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\LibD\aprapp-2.lib"
+
+!ELSEIF  "$(CFG)" == "aprapp - x64 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "..\x64\LibR"
+# PROP BASE Intermediate_Dir "x64\LibR"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\x64\LibR"
+# PROP Intermediate_Dir "x64\LibR"
+# 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 "../include/arch" /I "../include/arch/win32" /I "../include/arch/unix" /D "NDEBUG" /D "WINNT" /D "WIN32" /D "_WINDOWS" /D APR_APP /D "APR_DECLARE_STATIC" /Fo"$(INTDIR)\" /Fd"$(OUTDIR)\aprapp-2" /FD /c
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\x64\LibR\aprapp-2.lib"
+
+!ELSEIF  "$(CFG)" == "aprapp - x64 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "..\x64\LibD"
+# PROP BASE Intermediate_Dir "x64\LibD"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\x64\LibD"
+# PROP Intermediate_Dir "x64\LibD"
+# 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 "../include/arch" /I "../include/arch/win32" /I "../include/arch/unix" /D "_DEBUG" /D "WINNT" /D "WIN32" /D "_WINDOWS" /D APR_APP /D "APR_DECLARE_STATIC" /Fo"$(INTDIR)\" /Fd"$(OUTDIR)\aprapp-2" /FD /c
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\x64\LibD\aprapp-2.lib"
+
+!ENDIF 
+
+# Begin Target
+
+# Name "aprapp - Win32 Release"
+# Name "aprapp - Win32 Debug"
+# Name "aprapp - x64 Release"
+# Name "aprapp - x64 Debug"
+# Begin Source File
+
+SOURCE=..\misc\win32\apr_app.c
+# End Source File
+# End Target
+# End Project
diff --git a/build/aprconf.py b/build/aprconf.py
new file mode 100644
index 00000000000..74df43f1341
--- /dev/null
+++ b/build/aprconf.py
@@ -0,0 +1,432 @@
+import os
+import sys
+
+class APRConfigureBase:
+    def __init__(self, env):
+        self.env = env
+
+    def Check_apr_big_endian(self, context):
+        import struct
+        context.Message("Checking for big endianess... ")
+        array = struct.pack('cccc', '\x01', '\x02', '\x03', '\x04')
+        i = struct.unpack('i', array)
+        if i == struct.unpack('>i', array):
+            context.Result('yes')
+            return 1
+        else:
+            context.Result('no')
+            return 0
+
+    def CheckFile(self, context, path):
+        context.Message("Checking if %s exists... " % (path))
+        if os.path.exists(path):
+            context.Result('yes')
+            return 1
+        else:
+            context.Result('no')
+            return 0
+
+    def CheckTypesCompatible(self, context, t1, t2, includes):
+        context.Message('Checking %s is the same as %s... ' % (t1, t2))
+        source = """
+    %s
+void main(void)
+{
+    int foo[0 - !__builtin_types_compatible_p(%s, %s)];
+}
+    """  % (includes, t1, t2)
+        result = context.TryCompile(source, '.c')
+        self.env.Filter(CPPFLAGS = ['-D_LARGEFILE64_SOURCE'])
+        context.Result(result)
+        return result
+
+    def Check_apr_atomic_builtins(self, context):
+        context.Message('Checking whether the compiler provides atomic builtins... ')
+        source = """
+int main()
+{
+    unsigned long val = 1010, tmp, *mem = &val;
+
+    if (__sync_fetch_and_add(&val, 1010) != 1010 || val != 2020)
+        return 1;
+
+    tmp = val;
+
+    if (__sync_fetch_and_sub(mem, 1010) != tmp || val != 1010)
+        return 1;
+
+    if (__sync_sub_and_fetch(&val, 1010) != 0 || val != 0)
+        return 1;
+
+    tmp = 3030;
+
+    if (__sync_val_compare_and_swap(mem, 0, tmp) != 0 || val != tmp)
+        return 1;
+
+    if (__sync_lock_test_and_set(&val, 4040) != 3030)
+        return 1;
+
+    mem = &tmp;
+
+    if (__sync_val_compare_and_swap(&mem, &tmp, &val) != &tmp)
+        return 1;
+
+    __sync_synchronize();
+
+    if (mem != &val)
+        return 1;
+
+    return 0;
+}
+    """
+        result = context.TryRun(source, '.c')
+        context.Result(result[0] == 1)
+        return result[0] == 1
+
+    def Check_apr_ebcdic(self, context):
+        context.Message('Checking whether system uses EBCDIC.. ')
+        source = """
+int main(void) { 
+  return (unsigned char)'A' != (unsigned char)0xC1; 
+}"""
+        result = context.TryRun(source, '.c')
+        context.Result(result[0] == 1)
+        return result[0] == 1
+        
+    def Check_apr_nonblock_inherited(self, context):
+        context.Message('Checking whether O_NONBLOCK setting is inherited from listening sockets... ')
+        source = """
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETINET_TCP_H
+#include <netinet/tcp.h>
+#endif
+#ifndef HAVE_SOCKLEN_T
+typedef int socklen_t;
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+int main(void) {
+    int listen_s, connected_s, client_s;
+    int listen_port, rc;
+    struct sockaddr_in sa;
+    socklen_t sa_len;
+
+    listen_s = socket(AF_INET, SOCK_STREAM, 0);
+    if (listen_s < 0) {
+        perror("socket");
+        exit(1);
+    }
+    memset(&sa, 0, sizeof sa);
+    sa.sin_family = AF_INET;
+#ifdef BEOS
+    sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+#endif
+    /* leave port 0 to get ephemeral */
+    rc = bind(listen_s, (struct sockaddr *)&sa, sizeof sa);
+    if (rc < 0) {
+        perror("bind for ephemeral port");
+        exit(1);
+    }
+    /* find ephemeral port */
+    sa_len = sizeof(sa);
+    rc = getsockname(listen_s, (struct sockaddr *)&sa, &sa_len);
+    if (rc < 0) {
+        perror("getsockname");
+        exit(1);
+    }
+    listen_port = sa.sin_port;
+    rc = listen(listen_s, 5);
+    if (rc < 0) {
+        perror("listen");
+        exit(1);
+    }
+    rc = fcntl(listen_s, F_SETFL, O_NONBLOCK);
+    if (rc < 0) {
+        perror("fcntl(F_SETFL)");
+        exit(1);
+    }
+    client_s = socket(AF_INET, SOCK_STREAM, 0);
+    if (client_s < 0) {
+        perror("socket");
+        exit(1);
+    }
+    memset(&sa, 0, sizeof sa);
+    sa.sin_family = AF_INET;
+    sa.sin_port   = listen_port;
+#ifdef BEOS
+    sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+#endif
+    /* leave sin_addr all zeros to use loopback */
+    rc = connect(client_s, (struct sockaddr *)&sa, sizeof sa);
+    if (rc < 0) {
+        perror("connect");
+        exit(1);
+    }
+    sa_len = sizeof sa;
+    connected_s = accept(listen_s, (struct sockaddr *)&sa, &sa_len);
+    if (connected_s < 0) {
+        perror("accept");
+        exit(1);
+    }
+    rc = fcntl(connected_s, F_GETFL, 0);
+    if (rc < 0) {
+        perror("fcntl(F_GETFL)");
+        exit(1);
+    }
+    if (!(rc & O_NONBLOCK)) {
+        fprintf(stderr, "O_NONBLOCK is not set in the child.\n");
+        exit(1);
+    }
+    return 0;
+}"""
+        result = context.TryRun(source, '.c')
+        context.Result(result[0] == 1)
+        return result[0] == 1
+
+    def Check_apr_largefile64(self, context):
+        context.Message('Checking whether to enable -D_LARGEFILE64_SOURCE... ')
+        self.env.AppendUnique(CPPFLAGS = ['-D_LARGEFILE64_SOURCE'])
+        source = """
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+void main(void)
+{
+    int fd, ret = 0;
+    struct stat64 st;
+    off64_t off = 4242;
+
+    if (sizeof(off64_t) != 8 || sizeof(off_t) != 4)
+       exit(1);
+    if ((fd = open("conftest.lfs", O_LARGEFILE|O_CREAT|O_WRONLY, 0644)) < 0)
+       exit(2);
+    if (ftruncate64(fd, off) != 0)
+       ret = 3;
+    else if (fstat64(fd, &st) != 0 || st.st_size != off)
+       ret = 4;
+    else if (lseek64(fd, off, SEEK_SET) != off)
+       ret = 5;
+    else if (close(fd) != 0)
+       ret = 6;
+    else if (lstat64("conftest.lfs", &st) != 0 || st.st_size != off)
+       ret = 7;
+    else if (stat64("conftest.lfs", &st) != 0 || st.st_size != off)
+       ret = 8;
+    unlink("conftest.lfs");
+
+    exit(ret);
+}"""
+        result = context.TryRun(source, '.c')
+        self.env.Filter(CPPFLAGS = ['-D_LARGEFILE64_SOURCE'])
+        context.Result(result[0] == 1)
+        return result[0] == 1
+
+
+    def Check_apr_mmap_mapping_dev_zero(self, context):
+        context.Message('Checking for mmap that can map /dev/zero... ')
+        source = """
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+    int main()
+    {
+        int fd;
+        void *m;
+        fd = open("/dev/zero", O_RDWR);
+        if (fd < 0) {
+            return 1;
+        }
+        m = mmap(0, sizeof(void*), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+        if (m == (void *)-1) {  /* aka MAP_FAILED */
+            return 2;
+        }
+        if (munmap(m, sizeof(void*)) < 0) {
+            return 3;
+        }
+        return 0;
+    }
+        """
+        result = context.TryRun(source, '.c')
+        context.Result(result[0] == 1)
+        return result[0] == 1
+
+    def Check_apr_semaphores(self, context):
+        context.Message('Checking for sem_open, sem_close, sem_unlink... ')
+        source = """
+#include <errno.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <semaphore.h>
+#ifndef SEM_FAILED
+#define SEM_FAILED (-1)
+#endif
+main()
+{
+    sem_t *psem;
+    const char *sem_name = "/apr_autoconf";
+
+    psem = sem_open(sem_name, O_CREAT, 0644, 1);
+    if (psem == (sem_t *)SEM_FAILED) {
+	exit(1);
+    }
+    sem_close(psem);
+    psem = sem_open(sem_name, O_CREAT | O_EXCL, 0644, 1);
+    if (psem != (sem_t *)SEM_FAILED) {
+        sem_close(psem);
+        exit(1);
+    }
+    sem_unlink(sem_name);
+    exit(0);
+}
+        """
+        result = context.TryCompile(source, '.c')
+        context.Result(result)
+        return result
+
+    def Check_apr_check_tcp_nodelay_inherited(self, context):
+        context.Message('Checking for tcp nodelay inherited... ')
+        source = """
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+int main(void) {
+    int listen_s, connected_s, client_s;
+    int listen_port, rc;
+    struct sockaddr_in sa;
+    socklen_t sa_len;
+    socklen_t option_len;
+    int option;
+
+    listen_s = socket(AF_INET, SOCK_STREAM, 0);
+    if (listen_s < 0) {
+        perror("socket");
+        exit(1);
+    }
+    option = 1;
+    rc = setsockopt(listen_s, IPPROTO_TCP, TCP_NODELAY, &option, sizeof option);
+    if (rc < 0) {
+        perror("setsockopt TCP_NODELAY");
+        exit(1);
+    }
+    memset(&sa, 0, sizeof sa);
+    sa.sin_family = AF_INET;
+#ifdef BEOS
+    sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+#endif
+    /* leave port 0 to get ephemeral */
+    rc = bind(listen_s, (struct sockaddr *)&sa, sizeof sa);
+    if (rc < 0) {
+        perror("bind for ephemeral port");
+        exit(1);
+    }
+    /* find ephemeral port */
+    sa_len = sizeof(sa);
+    rc = getsockname(listen_s, (struct sockaddr *)&sa, &sa_len);
+    if (rc < 0) {
+        perror("getsockname");
+        exit(1);
+    }
+    listen_port = sa.sin_port;
+    rc = listen(listen_s, 5);
+    if (rc < 0) {
+        perror("listen");
+        exit(1);
+    }
+    client_s = socket(AF_INET, SOCK_STREAM, 0);
+    if (client_s < 0) {
+        perror("socket");
+        exit(1);
+    }
+    memset(&sa, 0, sizeof sa);
+    sa.sin_family = AF_INET;
+    sa.sin_port   = listen_port;
+#ifdef BEOS
+    sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+#endif
+    /* leave sin_addr all zeros to use loopback */
+    rc = connect(client_s, (struct sockaddr *)&sa, sizeof sa);
+    if (rc < 0) {
+        perror("connect");
+        exit(1);
+    }
+    sa_len = sizeof sa;
+    connected_s = accept(listen_s, (struct sockaddr *)&sa, &sa_len);
+    if (connected_s < 0) {
+        perror("accept");
+        exit(1);
+    }
+    option_len = sizeof option;
+    rc = getsockopt(connected_s, IPPROTO_TCP, TCP_NODELAY, &option, &option_len);
+    if (rc < 0) {
+        perror("getsockopt");
+        exit(1);
+    }
+    if (!option) {
+        fprintf(stderr, "TCP_NODELAY is not set in the child.\n");
+        exit(1);
+    }
+    return 0;
+} """ 
+        result = context.TryRun(source, '.c') 
+        context.Result(result[0] == 1)
+        return result[0] == 1
+
+    def Check_apr_semun(self, context):
+        context.Message('Checking for semun... ')
+        source = """
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+main()
+{
+    union semun arg;
+    semctl(0, 0, 0, arg);
+    exit(0);
+}
+        """
+        result = context.TryCompile(source, '.c')
+        context.Result(result)
+        return result
+
+    def Check_apr_sctp(self, context):
+        context.Message('Checking for sctp support... ')
+        source = """
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/sctp.h>
+#include <netinet/sctp_uio.h>
+#include <stdlib.h>
+int main(void) {
+    int s, opt = 1;
+    if ((s = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP)) < 0)
+       exit(1);
+    if (setsockopt(s, IPPROTO_SCTP, SCTP_NODELAY, &opt, sizeof(int)) < 0)
+       exit(2);
+    exit(0);
+}
+"""
+        result = context.TryRun(source, '.c') 
+        context.Result(result[0] == 1)
+        return result[0] == 1
+
+class APRConfigure(APRConfigureBase):
+    def __init__(self, env):
+        APRConfigureBase.__init__(self, env)
diff --git a/build/aprenv.py b/build/aprenv.py
new file mode 100644
index 00000000000..b1e7c0c30ef
--- /dev/null
+++ b/build/aprenv.py
@@ -0,0 +1,693 @@
+#
+#
+
+from SCons.Environment import Environment
+from os.path import join as pjoin
+import aprconf
+import re
+import os
+import traceback
+
+_platforms = [ 
+    'aix', 
+    'beos', 
+    'netware', 
+    'os2', 
+    'os390', 
+    'unix', 
+    'win32' 
+]
+
+_platform_dirs = [
+    'atomic',
+    'dso',
+    'file_io',
+    'helpers',
+    'locks',
+    'memory',
+    'misc',
+    'mmap',
+    'network_io',
+    'passwd',
+    'poll',
+    'random',
+    'shmem',
+    'strings',
+    'support',
+    'tables',
+    'threadproc',
+    'time',
+    'user'
+]
+
+_simple_dirs = [
+    'buckets',
+    'crypto',
+    'dbd',
+    'dbm',
+    'dbm/sdbm',
+    'encoding',
+    'hooks',
+    'memcache',
+    'tables',
+    'strings',
+    'strmatch',
+    'util-misc',
+    'uri',
+    'xlate',
+    'xml'
+]
+
+class APREnv(Environment):
+  def __init__(self, parent=None, args=None, **kw):
+    Environment.__init__(self, ENV=os.environ,
+                         tools = ['default', 'subst'],
+                         toolpath = [pjoin(os.getcwd(), 'build')],
+                          **kw)
+
+    # See SCons/Platform/__init__.py for possible values
+    if self['PLATFORM'] in _platforms:
+      self['APR_PLATFORM'] = self['PLATFORM']
+    else:
+      self['APR_PLATFORM'] = 'unix'
+      
+    # if no *.c files are found in the original APR_PLATFORM, we switch to 
+    # using this fallback platform.
+    self['APR_FALLBACK_PLATFORM'] = 'unix'
+
+    self.AppendUnique(CPPPATH = ['include', 'include/private', 'include/arch/'+self['APR_PLATFORM']])
+    self.autoconf = aprconf.APRConfigure(self)
+    self.AppendUnique(LIBS = ['expat'])
+
+  def is_gcc(self):
+    # TOOD: This detection should be smarter, need look at SCons Internals
+    # for how it works/base it on the Tool selection.
+    return self['CC'] == 'gcc'
+
+  def core_lib_files(self):
+    rv = []
+    for d in _platform_dirs:
+      p = pjoin(d, self['APR_PLATFORM'], '*.c')
+      files = self.Glob(p)
+      if not files and self['APR_PLATFORM'] != self['APR_FALLBACK_PLATFORM']:
+        p = pjoin(d, self['APR_FALLBACK_PLATFORM'], '*.c')
+        files = self.Glob(p)
+      rv.extend(files)
+
+    for d in _simple_dirs:
+      p = pjoin(d, '*.c')
+      files = self.Glob(p)
+      rv.extend(files)
+    return rv
+
+  def APRVersion(self):
+    if not self.has_key('APR_VERSION'):
+      self['APR_VERSION'] = self.read_version('APR', '#include/apr_version.h')
+    return self['APR_VERSION']
+
+  def read_version(self, prefix, path):
+    version_re = re.compile("(.*)%s_(?P<id>MAJOR|MINOR|PATCH)_VERSION(\s+)(?P<num>\d)(.*)" % prefix)
+    versions = {}
+    fp = self.File(path).get_contents()
+    for line in fp.splitlines():
+      m = version_re.match(line)
+      if m:
+        versions[m.group('id')] = int(m.group('num'))
+    return (versions['MAJOR'], versions['MINOR'], versions['PATCH'])
+
+  def Filter(self, **kw):
+    for k in kw.keys():
+      self[k] = [x for x in self[k] if x is not kw[k]]
+
+  def APRHints(self):
+    # TOOD: port more from apr_hints.m4
+    if self['PLATFORM'] == 'darwin':
+      self.AppendUnique(CPPFLAGS=['-DDARWIN', '-DSIGPROCMASK_SETS_THREAD_MASK'])
+
+
+  def critical_value(self, f, value, *args):
+    rv = f(*args)
+
+    if rv != value:
+      traceback.print_stack()
+      print "Critial Test failed."
+      self.Exit(1)
+    return rv
+
+  def critical(self, f, *args):
+    rv = f(*args)
+
+    if not rv:
+      traceback.print_stack()
+      print "Critial Test failed."
+      self.Exit(1)
+
+  def APRAutoconf(self):
+    self.apr_config_h = 'include/arch/%s/apr_private.h' % (self['APR_PLATFORM'])
+    self.apu_config_h = 'include/private/apu_config.h'
+    subst = {}
+
+    if self.GetOption('clean') or self.GetOption('help'):
+      return self
+
+    # TODO Port header detection here etc
+    conf = self.Configure(custom_tests = {
+        'CheckFile':
+            self.autoconf.CheckFile,
+        'CheckTypesCompatible': 
+            self.autoconf.CheckTypesCompatible,
+        'Check_apr_atomic_builtins': 
+            self.autoconf.Check_apr_atomic_builtins,
+        'Check_apr_largefile64': 
+            self.autoconf.Check_apr_largefile64,
+        'Check_apr_big_endian': 
+            self.autoconf.Check_apr_big_endian,
+        'Check_apr_mmap_mapping_dev_zero': 
+            self.autoconf.Check_apr_mmap_mapping_dev_zero,
+        'Check_apr_semaphores':
+            self.autoconf.Check_apr_semaphores,
+        'Check_apr_semun':
+            self.autoconf.Check_apr_semun,
+        'Check_apr_check_tcp_nodelay_inherited':
+            self.autoconf.Check_apr_check_tcp_nodelay_inherited,
+        'Check_apr_nonblock_inherited':
+            self.autoconf.Check_apr_nonblock_inherited,
+        'Check_apr_ebcdic':
+            self.autoconf.Check_apr_ebcdic,
+        'Check_apr_sctp':
+            self.autoconf.Check_apr_sctp,
+        },
+        config_h = self.apr_config_h)
+
+    # Do we have a working C Compiler?
+    self.critical(conf.CheckCC)
+
+    flag_headers = self.Split("""ByteOrder.h
+    conio.h
+    crypt.h
+    ctype.h
+    dir.h
+    dirent.h
+    dl.h
+    dlfcn.h
+    errno.h
+    fcntl.h
+    grp.h
+    io.h
+    limits.h
+    mach-o/dyld.h
+    malloc.h
+    memory.h
+    netdb.h
+    osreldate.h
+    poll.h
+    process.h
+    pwd.h
+    semaphore.h
+    signal.h
+    stdarg.h
+    stddef.h
+    stdio.h
+    stdlib.h
+    string.h
+    strings.h
+    sysapi.h
+    sysgtime.h
+    termios.h
+    time.h
+    tpfeq.h
+    tpfio.h
+    unistd.h
+    unix.h
+    windows.h
+    winsock2.h
+    arpa/inet.h
+    kernel/OS.h
+    net/errno.h
+    netinet/in.h
+    netinet/sctp.h
+    netinet/tcp.h
+    netinet/sctp_uio.h
+    sys/file.h
+    sys/ioctl.h
+    sys/mman.h
+    sys/param.h        
+    sys/poll.h
+    sys/resource.h
+    sys/select.h
+    sys/sem.h
+    sys/sendfile.h
+    sys/signal.h
+    sys/socket.h
+    sys/sockio.h
+    sys/stat.h
+    sys/sysctl.h
+    sys/syslimits.h
+    sys/time.h
+    sys/types.h
+    sys/uio.h
+    sys/un.h
+    sys/wait.h
+    pthread.h
+    """)
+    for x in flag_headers:
+      s = x.replace('/', '_').replace('.', '').replace('-', '')
+      if conf.CheckCHeader(x):
+        subst['@%s@' % (s)] = 1
+      else:
+        subst['@%s@' % (s)] = 0
+        
+    sizeof_char = conf.CheckTypeSize('char')
+    sizeof_int = self.critical_value(conf.CheckTypeSize, 4, 'int')
+    subst['@int_value@'] = 'int'
+    sizeof_long = conf.CheckTypeSize('long')
+    sizeof_short = self.critical_value(conf.CheckTypeSize, 2, 'short')
+    subst['@short_value@'] = 'short'
+    sizeof_long_long = conf.CheckTypeSize('long long')
+    sizeof_longlong = conf.CheckTypeSize('longlong')
+    sizeof_pid_t = conf.CheckTypeSize('pid_t', includes='#include <sys/types.h>')
+    sizeof_off_t = conf.CheckTypeSize('off_t', includes='#include <sys/types.h>')
+    sizeof_size_t = conf.CheckTypeSize('size_t', includes='#include <sys/types.h>')
+    sizeof_ssize_t = conf.CheckTypeSize('ssize_t', includes='#include <sys/types.h>')
+    subst['@voidp_size@'] = conf.CheckTypeSize('void*')
+
+    if sizeof_size_t:
+      subst['@size_t_value@'] = 'size_t'
+      subst['@size_t_fmt@'] = '#define APR_SIZE_T_FMT "lu"'
+    else:
+      subst['@size_t_value@'] = 'apr_int32_t'
+      subst['@size_t_fmt@'] = '#define APR_SIZE_T_FMT "u"'
+
+    if sizeof_ssize_t:
+      subst['@ssize_t_value@'] = 'ssize_t'
+      subst['@ssize_t_fmt@'] = '#define APR_SSIZE_T_FMT "ld"'
+    else:
+      subst['@ssize_t_value@'] = 'apr_int32_t'
+      subst['@ssize_t_fmt@'] = '#define APR_SSIZE_T_FMT "d"'
+
+    if conf.Check_apr_big_endian():
+      subst['@bigendian@'] = 1
+    else:
+      subst['@bigendian@'] = 0
+    # Now we need to find what apr_int64_t (sizeof == 8) will be.
+    # The first match is our preference.
+    if sizeof_int == 8:
+      subst['@int64_literal@'] = '#define APR_INT64_C(val) (val)'
+      subst['@uint64_literal@'] = '#define APR_UINT64_C(val) (val##U)'
+      subst['@int64_t_fmt@'] = '#define APR_INT64_T_FMT "d"'
+      subst['@uint64_t_fmt@'] = '#define APR_UINT64_T_FMT "u"'
+      subst['@uint64_t_hex_fmt@'] = '#define APR_UINT64_T_HEX_FMT "x"'
+      subst['@int64_value@'] = 'int'
+      subst['@long_value@'] = 'int'
+      subst['@int64_strfn=@'] = 'strtoi'
+    elif sizeof_long == 8:
+      subst['@int64_literal@'] = '#define APR_INT64_C(val) (val##L)'
+      subst['@uint64_literal@'] = '#define APR_UINT64_C(val) (val##UL)'
+      subst['@int64_t_fmt@'] = '#define APR_INT64_T_FMT "ld"'
+      subst['@uint64_t_fmt@'] = '#define APR_UINT64_T_FMT "lu"'
+      subst['@uint64_t_hex_fmt@'] = '#define APR_UINT64_T_HEX_FMT "lx"'
+      subst['@int64_value@'] = 'long'
+      subst['@long_value@'] = 'long'
+      subst['@int64_strfn=@'] = 'strtol'
+    elif sizeof_long_long == 8:
+      subst['@int64_literal@'] = '#define APR_INT64_C(val) (val##LL)'
+      subst['@uint64_literal@'] = '#define APR_UINT64_C(val) (val##ULL)'
+      # Linux, Solaris, FreeBSD all support ll with printf.
+      # BSD 4.4 originated 'q'.  Solaris is more popular and 
+      # doesn't support 'q'.  Solaris wins.  Exceptions can
+      # go to the OS-dependent section.
+      subst['@int64_t_fmt@'] = '#define APR_INT64_T_FMT "lld"'
+      subst['@uint64_t_fmt@'] = '#define APR_UINT64_T_FMT "llu"'
+      subst['@uint64_t_hex_fmt@'] = '#define APR_UINT64_T_HEX_FMT "llx"'
+      subst['@int64_value@'] = 'long long'
+      subst['@long_value@'] = 'long long'
+      subst['@int64_strfn=@'] = 'strtoll'
+    elif sizeof_longlong == 8:
+      subst['@int64_literal@'] = '#define APR_INT64_C(val) (val##LL)'
+      subst['@uint64_literal@'] = '#define APR_UINT64_C(val) (val##ULL)'
+      subst['@int64_t_fmt@'] = '#define APR_INT64_T_FMT "qd"'
+      subst['@uint64_t_fmt@'] = '#define APR_UINT64_T_FMT "qu"'
+      subst['@uint64_t_hex_fmt@'] = '#define APR_UINT64_T_HEX_FMT "qx"'
+      subst['@int64_value@'] = '__int64'
+      subst['@long_value@'] = '__int64'
+      subst['@int64_strfn=@'] = 'strtoll'
+    else:
+      print("could not detect a 64-bit integer type")
+      self.Exit(1)
+
+    if conf.CheckDeclaration('INT64_C', includes='#include <stdint.h>'):
+      subst['@int64_literal@'] = '#define APR_INT64_C(val) INT64_C(val)'
+      subst['@uint64_literal@'] = '#define APR_UINT64_C(val) UINT64_C(val)'
+      subst['@stdint@'] = 1
+
+    if sizeof_pid_t == sizeof_short:
+      subst['@pid_t_fmt@'] = '#define APR_PID_T_FMT "hd"'
+    elif sizeof_pid_t == sizeof_int:
+      subst['@pid_t_fmt@'] = '#define APR_PID_T_FMT "d"'
+    elif sizeof_pid_t == sizeof_long:
+      subst['@pid_t_fmt@'] = '#define APR_PID_T_FMT "ld"'
+    elif sizeof_pid_t == sizeof_long_long:
+      subst['@pid_t_fmt@'] = '#define APR_PID_T_FMT APR_INT64_T_FMT'
+    else:
+      subst['@pid_t_fmt@'] = '#error Can not determine the proper size for pid_t'
+    
+    # TODO: Per OS changing of these
+
+    if conf.Check_apr_largefile64():
+      self.AppendUnique(CPPFLAGS = ['-D_LARGEFILE64_SOURCE'])
+
+    aprlfs=0
+    if self['lfs'] and sizeof_off_t == 4:
+      # Check whether the transitional LFS API is sufficient
+      aprlfs=1
+      for f in ['mmap64', 'sendfile64', 'sendfilev64', 'mkstemp64', 'readdir64_r']:
+        conf.CheckFunc(f)
+    elif sizeof_off_t == sizeof_size_t:
+      aprlfs=1
+
+    if aprlfs and sizeof_off_t == 4:
+      # LFS is go!
+      subst['@off_t_fmt@'] = '#define APR_OFF_T_FMT APR_INT64_T_FMT'
+      subst['@off_t_value@'] = 'off64_t'
+      subst['@off_t_strfn@'] = 'apr_strtoi64'
+    elif sizeof_off_t == 4 and sizeof_long == 4:
+      # Special case: off_t may change size with _FILE_OFFSET_BITS
+      # on 32-bit systems with LFS support.  To avoid compatibility
+      # issues when other packages do define _FILE_OFFSET_BITS,
+      # hard-code apr_off_t to long.
+      subst['@off_t_fmt@'] = '#define APR_OFF_T_FMT "ld"'
+      subst['@off_t_value@'] = 'long'
+      subst['@off_t_strfn@'] = 'strtol'
+    elif sizeof_off_t != 0:
+      subst['@off_t_value@'] = 'off_t'
+      if sizeof_off_t == sizeof_long:
+        subst['@off_t_fmt@'] = '#define APR_OFF_T_FMT "ld"'
+        subst['@off_t_strfn@'] = 'strtol'
+      elif sizeof_off_t == sizeof_int:
+        subst['@off_t_fmt@'] = '#define APR_OFF_T_FMT "d"'
+        subst['@off_t_strfn@'] = 'strtoi'
+      elif sizeof_off_t == sizeof_long_long:
+        subst['@off_t_fmt@'] = '#define APR_OFF_T_FMT APR_INT64_T_FMT'
+        subst['@off_t_strfn@'] = 'apr_strtoi64'
+      else:
+        print("could not determine the size of off_t")
+        self.Exit(1)
+    else:
+      # Fallback on int
+      subst['@off_t_fmt@'] = '#define APR_OFF_T_FMT "d"'
+      subst['@off_t_value@'] = 'apr_int32_t'
+      subst['@off_t_strfn@'] = 'strtoi'
+
+    if conf.Check_apr_atomic_builtins():
+      conf.Define('HAVE_ATOMIC_BUILTINS', 1)
+
+    if not conf.CheckType('size_t', includes='#include <sys/types.h>'):
+      subst['@size_t_value@'] = 'apr_int32_t'
+
+    if not conf.CheckType('ssize_t', includes='#include <sys/types.h>'):
+      subst['@ssize_t_value@'] = 'apr_int32_t'
+
+    if not conf.CheckType('socklen_t', includes='#include <sys/socket.h>'):
+      subst['@socklen_t_value@'] = 'int'
+    else:
+      if self['PLATFORM'] == 'hpux' and sizeof_long == 8:
+        # 64-bit HP-UX requires 32-bit socklens in
+        # kernel, but user-space declarations say
+        # 64-bit (socklen_t == size_t == long).
+        # This will result in many compile warnings,
+        # but we're functionally busted otherwise.
+        subst['@socklen_t_value@'] = 'int'
+      else:
+        subst['@socklen_t_value@'] = 'socklen_t'
+        
+    # Regardless of whether _LARGEFILE64_SOURCE is used, on 32-bit
+    # platforms _FILE_OFFSET_BITS will affect the size of ino_t and hence
+    # the build-time ABI may be different from the apparent ABI when using
+    # APR with another package which *does* define _FILE_OFFSET_BITS.
+    # (Exactly as per the case above with off_t where LFS is *not* used)
+    #
+    # To be safe, hard-code apr_ino_t as 'unsigned long' iff that is
+    # exactly the size of ino_t here; otherwise use ino_t as existing
+    # releases did.  To be correct, apr_ino_t should have been made an
+    # ino64_t as apr_off_t is off64_t, but this can't be done now without
+    # breaking ABI.
+    subst['@ino_t_value@'] = 'ino_t'
+    if sizeof_long == 4 and conf.CheckTypesCompatible('ino_t', 'unsigned long', '#include <fts.h>'):
+      subst['@ino_t_value@'] = 'unsigned long'
+
+    # check for mmap functions
+    # store the results into mmap_results dictionary for use later
+    mmap_funcs = ['mmap', 'mmap', 'shm_open', 'shm_unlink', 'shm_get',
+            'shmat', 'shmdt', 'shmctl']
+    mmap_results = dict([[k, conf.CheckFunc(k)] for k in mmap_funcs])
+
+    # check for mmap mapping dev zero
+    if mmap_results['mmap'] and \
+       conf.CheckFile("/dev/zero") and \
+       conf.Check_apr_mmap_mapping_dev_zero():
+           subst['@havemmapzero@'] = 1
+    else:
+        subst['@havemmapzero@'] = 0
+
+    # check for locking mechanisms
+    if conf.Check_apr_semaphores():
+        subst['@hassysvser@'] = 1
+    else:
+        subst['@hassysvser@'] = 0
+
+    if conf.CheckDeclaration('F_SETLK', '#include <fcntl.h>'):
+        subst['@hasfcntlser@'] = 1
+    else:
+        subst['@hasfcntlser@'] = 0
+
+    if conf.CheckFunc('flock'):
+        subst['@hasflockser@'] = 1
+    else:
+        subst['@hasflockser@'] = 0
+
+    apr_tcp_nopush_flag="0"
+    if conf.CheckDeclaration('TCP_CORK', '#include <netinet/tcp.h>'):
+        subst['@have_corkable_tcp@'] = 1
+        apr_tcp_nopush_flag="TCP_CORK"
+    else:
+        subst['@have_corkable_tcp@'] = 0
+
+    if conf.CheckDeclaration('TCP_NOPUSH', '#include <netinet/tcp.h>'):
+        subst['@apr_tcp_nopush_flag@'] = 3
+        subst['@have_corkable_tcp@'] = 1
+
+    subst['@apr_tcp_nopush_flag@'] = apr_tcp_nopush_flag
+
+    if conf.CheckFunc('flock'):
+        subst['@hasflockser@'] = 1
+    else:
+        subst['@hasflockser@'] = 0
+
+    if conf.CheckFunc('getrlimit'):
+        subst['@have_getrlimit@'] = 1
+    else:
+        subst['@have_getrlimit@'] = 0
+
+    if conf.CheckFunc('setrlimit'):
+        subst['@have_setrlimit@'] = 1
+    else:
+        subst['@have_setrlimit@'] = 0
+
+    if conf.CheckType('struct in_addr', includes='#include <netinet/in.h>'):
+        subst['@have_in_addr@'] = 1
+    else:
+        subst['@have_in_addr@'] = 0
+
+    if conf.CheckType('struct sockaddr_storage', includes='#include <netinet/in.h>'):
+        subst['@have_sa_storage@'] = 1
+    else:
+        subst['@have_sa_storage@'] = 0
+
+    if conf.CheckType('struct rlimit', includes='#include <sys/resource.h>'):
+        subst['@struct_rlimit@'] = 1
+    else:
+        subst['@struct_rlimit@'] = 0
+
+    if conf.Check_apr_semun():
+        subst['@have_union_semun@'] = 1
+    else:
+        subst['@have_union_semun@'] = 0
+
+    check_functions = [
+        'inet_addr',
+        'inet_network',
+        'memmove',
+        'sigaction',
+        'sigsuspend',
+        'sigwait',
+        'strdup',
+        'stricmp',
+        'strcasecmp',
+        'strncasecmp',
+        'strnicmp',
+        'strstr',
+        'memchr',
+        'iovec',
+        'fork',
+        'mmap',
+        'uuid_create',
+        'uuid_generate',
+        'waitpid'
+    ]
+
+    for func in check_functions:
+        if conf.CheckFunc(func):
+            subst['@have_%s@' % func] = 1
+        else:
+            subst['@have_%s@' % func] = 0
+
+    if self['PLATFORM'] in ['sunos']:
+      conf.Define("SIGWAIT_TAKES_ONE_ARG")
+
+    # Set Features
+    # TODO: Not done yet
+    subst['@sharedmem@'] = 1
+    subst['@threads@'] = 1
+    subst['@sendfile@'] = 0
+    subst['@mmap@'] = subst['@have_mmap@']
+    subst['@fork@'] = subst['@have_fork@']
+    subst['@rand@'] = 0
+    subst['@oc@'] = 0
+    subst['@aprdso@'] = 0
+    subst['@have_unicode_fs@'] = 0
+    subst['@have_proc_invoked@'] = 0
+    subst['@aprlfs@'] = 0
+    subst['@osuuid@'] = subst['@have_uuid_generate@'] or subst['@have_uuid_create@']
+    subst['@file_as_socket@'] = 1
+
+    # check for IPv6 (the user is allowed to disable this via commandline
+    # options
+    subst['@have_ipv6@'] = 0
+    if self['ipv6']:
+        if conf.CheckType('struct sockaddr_in6', 
+                          includes='#include <netinet/in.h>') and \
+           conf.CheckFunc('getaddrinfo') and \
+           conf.CheckFunc('getnameinfo'):
+            subst['@have_ipv6@'] = 1
+
+    if conf.CheckDeclaration('SO_ACCEPTFILTER', '#include <sys/socket.h>'):
+        subst['@acceptfilter@'] = 1
+    else:
+        subst['@acceptfilter@'] = 0
+
+    if conf.CheckDeclaration('IPPROTO_SCTP', '#include <netinet/in.h>') and \
+        conf.Check_apr_sctp():
+        subst['@have_sctp@'] = 1
+    else:
+        subst['@have_sctp@'] = 0
+
+    if conf.CheckDeclaration('SO_ACCEPTFILTER', '#include <sys/socket.h>'):
+        subst['@acceptfilter@'] = 1
+    else:
+        subst['@acceptfilter@'] = 0
+
+    if conf.Check_apr_check_tcp_nodelay_inherited():
+        subst['@tcp_nodelay_inherited@'] = 1
+    else:
+        subst['@tcp_nodelay_inherited@'] = 0
+
+    if conf.Check_apr_nonblock_inherited():
+        subst['@o_nonblock_inherited@'] = 1
+    else:
+        subst['@o_nonblock_inherited@'] = 0
+
+    if conf.Check_apr_ebcdic():
+        subst['@apr_charset_ebcdic@'] = 1
+    else:
+        subst['@apr_charset_ebcdic@'] = 0
+
+    if conf.CheckType('struct iovec', includes='#include <sys/types.h>\n#include <sys/uio.h>'):
+      subst['@have_iovec@'] = 1
+    else:
+      subst['@have_iovec@'] = 0
+    
+
+    if conf.CheckType('struct sockaddr_un', includes='#include <sys/un.h>'):
+      subst['@have_sockaddr_un@'] = 1
+    else:
+      subst['@have_sockaddr_un@'] = 0
+
+    subst['@proc_mutex_is_global@'] = 0
+    if self['PLATFORM'] in ['os2', 'beos', 'win32', 'cygwin']:
+      subst['@proc_mutex_is_global@'] = 1
+  
+    # note: the current APR use of shared mutex requires /dev/zero
+    if conf.CheckFile('/dev/zero') and \
+        conf.CheckDeclaration('PTHREAD_PROCESS_SHARED', includes='#include <pthread.h>') and \
+        conf.CheckFunc('pthread_mutexattr_setpshared'):
+      subst['@hasprocpthreadser@'] = 1
+    else:
+      subst['@hasprocpthreadser@'] = 0
+    
+    
+    subst['@havemmaptmp@'] = 0
+    subst['@havemmapshm@'] = 0
+    subst['@haveshmgetanon@'] = 0
+    subst['@haveshmget@'] = 0
+    subst['@havemmapanon@'] = 0
+    subst['@havebeosarea@'] = 0
+
+    subst['@usemmaptmp@'] = 0
+    subst['@usemmapshm@'] = 0
+    subst['@usemmapzero@'] = 0
+    subst['@useshmgetanon@'] = 0
+    subst['@useshmget@'] = 0
+    subst['@usemmapanon@'] = 0
+    subst['@usebeosarea@'] = 0
+
+    subst['@flockser@'] = 0
+    subst['@sysvser@'] = 0
+    subst['@posixser@'] = 0
+    subst['@fcntlser@'] = 0
+    subst['@procpthreadser@'] = 0 
+    subst['@pthreadser@'] = 0
+    subst['@hasposixser@'] = 0
+    subst['@proclockglobal@'] = 0
+
+    if self['APR_PLATFORM'] in ['win32']:
+      subst['@eolstr@'] = "\\\\r\\\\n"
+    else:
+      subst['@eolstr@'] = "\\\\n"
+
+    subst['@shlibpath_var@'] = pjoin(self['prefix'], 'lib')
+
+    # APR Util things to fix:
+    subst['@apu_have_sdbm@'] = 1
+    subst['@apu_have_gdbm@'] = 0
+    subst['@apu_have_ndbm@'] = 0
+    subst['@apu_have_db@'] = 0
+    subst['@apu_use_sdbm@'] = 1
+    subst['@apu_use_ndbm@'] = 0
+    subst['@apu_use_gdbm@'] = 0
+    subst['@apu_use_db@'] = 0
+
+    subst['@apu_db_version@'] = 0
+
+    subst['@apu_have_pgsql@'] = 0
+    subst['@apu_have_mysql@'] = 0
+    subst['@apu_have_sqlite3@'] = 0
+    subst['@apu_have_sqlite2@'] = 0
+    subst['@apu_have_oracle@'] = 0
+    subst['@apu_have_odbc@'] = 0
+
+
+    subst['@apu_have_crypto@'] = 0
+    subst['@apu_have_openssl@'] = 0
+    subst['@apu_have_nss@'] = 0
+
+    subst['@have_iconv@'] = 0
+    
+    self.SubstFile('include/apr.h', 'include/apr.h.in', SUBST_DICT = subst)
+    self.SubstFile('include/apu.h', 'include/apu.h.in', SUBST_DICT = subst)
+    self.SubstFile('include/apu_want.h', 'include/apu_want.h.in', SUBST_DICT = subst)
+    self.SubstFile('include/private/apu_select_dbm.h', 'include/private/apu_select_dbm.h.in', SUBST_DICT = subst)
+    if hasattr(conf, "config_h_text"):
+      conf.Define("APR_OFF_T_STRFN", subst['@off_t_strfn@'])
+      conf.config_h_text = conf.config_h_text + '#include "arch/apr_private_common.h"\n'
+ 
+    return conf.Finish()
diff --git a/build/apu-conf.m4 b/build/apu-conf.m4
new file mode 100644
index 00000000000..61f27d83b77
--- /dev/null
+++ b/build/apu-conf.m4
@@ -0,0 +1,74 @@
+dnl -------------------------------------------------------- -*- autoconf -*-
+dnl Licensed to the Apache Software Foundation (ASF) under one or more
+dnl contributor license agreements.  See the NOTICE file distributed with
+dnl this work for additional information regarding copyright ownership.
+dnl The ASF licenses this file to You under the Apache License, Version 2.0
+dnl (the "License"); you may not use this file except in compliance with
+dnl the License.  You may obtain a copy of the License at
+dnl
+dnl     http://www.apache.org/licenses/LICENSE-2.0
+dnl
+dnl Unless required by applicable law or agreed to in writing, software
+dnl distributed under the License is distributed on an "AS IS" BASIS,
+dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+dnl See the License for the specific language governing permissions and
+dnl limitations under the License.
+
+
+dnl
+dnl custom autoconf rules for APRUTIL
+dnl
+
+dnl
+dnl APU_FIND_APR: figure out where APR is located
+dnl
+AC_DEFUN([APU_FIND_APR], [
+
+  dnl use the find_apr.m4 script to locate APR. sets apr_found and apr_config
+  APR_FIND_APR(,,,[2])
+  if test "$apr_found" = "no"; then
+    AC_MSG_ERROR(APR could not be located. Please use the --with-apr option.)
+  fi
+
+  APR_BUILD_DIR="`$apr_config --installbuilddir`"
+
+  dnl make APR_BUILD_DIR an absolute directory (we'll need it in the
+  dnl sub-projects in some cases)
+  APR_BUILD_DIR="`cd $APR_BUILD_DIR && pwd`"
+
+  APR_INCLUDES="`$apr_config --includes`"
+  APR_LIBS="`$apr_config --link-libtool --libs`"
+  APR_SO_EXT="`$apr_config --apr-so-ext`"
+  APR_LIB_TARGET="`$apr_config --apr-lib-target`"
+
+  AC_SUBST(APR_INCLUDES)
+  AC_SUBST(APR_LIBS)
+  AC_SUBST(APR_BUILD_DIR)
+])
+
+
+dnl
+dnl APU_CHECK_CRYPT_R_STYLE
+dnl
+dnl  Decide which of a couple of flavors of crypt_r() is necessary for
+dnl  this platform.
+dnl
+AC_DEFUN([APU_CHECK_CRYPT_R_STYLE], [
+
+AC_CACHE_CHECK([style of crypt_r], apr_cv_crypt_r_style, 
+[AC_TRY_COMPILE([#include <crypt.h>],
+ [CRYPTD buffer;
+  crypt_r("passwd", "hash", &buffer);], 
+ [apr_cv_crypt_r_style=cryptd],
+ [AC_TRY_COMPILE([#include <crypt.h>],
+  [struct crypt_data buffer;
+   crypt_r("passwd", "hash", &buffer);], 
+  [apr_cv_crypt_r_style=struct_crypt_data],
+  [apr_cv_crypt_r_style=none])])])
+
+if test "$apr_cv_crypt_r_style" = "cryptd"; then
+   AC_DEFINE(CRYPT_R_CRYPTD, 1, [Define if crypt_r has uses CRYPTD])
+elif test "$apr_cv_crypt_r_style" = "struct_crypt_data"; then
+   AC_DEFINE(CRYPT_R_STRUCT_CRYPT_DATA, 1, [Define if crypt_r uses struct crypt_data])
+fi
+])
diff --git a/build/apu-hints.m4 b/build/apu-hints.m4
new file mode 100644
index 00000000000..6d6784a8d5c
--- /dev/null
+++ b/build/apu-hints.m4
@@ -0,0 +1,62 @@
+dnl -------------------------------------------------------- -*- autoconf -*-
+dnl Licensed to the Apache Software Foundation (ASF) under one or more
+dnl contributor license agreements.  See the NOTICE file distributed with
+dnl this work for additional information regarding copyright ownership.
+dnl The ASF licenses this file to You under the Apache License, Version 2.0
+dnl (the "License"); you may not use this file except in compliance with
+dnl the License.  You may obtain a copy of the License at
+dnl
+dnl     http://www.apache.org/licenses/LICENSE-2.0
+dnl
+dnl Unless required by applicable law or agreed to in writing, software
+dnl distributed under the License is distributed on an "AS IS" BASIS,
+dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+dnl See the License for the specific language governing permissions and
+dnl limitations under the License.
+
+dnl -----------------------------------------------------------------
+dnl apu-hints.m4: apr-util's autoconf macros for platform-specific hints
+dnl
+dnl  We preload various configure settings depending
+dnl  on previously obtained platform knowledge.
+dnl  We allow all settings to be overridden from
+dnl  the command-line.
+
+dnl
+dnl APU_PRELOAD
+dnl
+dnl  Preload various build parameters based on outside knowledge.
+dnl
+AC_DEFUN([APU_PRELOAD], [
+if test "x$apu_preload_done" != "xyes" ; then
+    apu_preload_done="yes"
+
+    echo "Applying apr-util hints file rules for $host"
+
+    case "$host" in
+    *-dec-osf*)
+        APR_SETIFNULL(apu_crypt_threadsafe, [1])
+        ;;
+    *-hp-hpux11.*)
+        APR_SETIFNULL(apu_crypt_threadsafe, [1])
+        ;;
+    *-ibm-aix4*|*-ibm-aix5.1*)
+        APR_SETIFNULL(apu_iconv_inbuf_const, [1])
+        ;;
+    *-ibm-os390)
+        APR_SETIFNULL(apu_crypt_threadsafe, [1])
+        ;;
+    *-solaris2*)
+        APR_SETIFNULL(apu_iconv_inbuf_const, [1])
+        APR_SETIFNULL(apu_crypt_threadsafe, [1])
+        AC_SEARCH_LIBS(fdatasync, [rt posix4])
+        ;;
+    *-sco3.2v5*)
+	APR_SETIFNULL(apu_db_xtra_libs, [-lsocket])
+	;;
+    esac
+
+fi
+])
+
+
diff --git a/build/buildcheck.sh b/build/buildcheck.sh
new file mode 100755
index 00000000000..ab5df445c4a
--- /dev/null
+++ b/build/buildcheck.sh
@@ -0,0 +1,70 @@
+#! /bin/sh
+
+echo "buildconf: checking installation..."
+res=0
+
+# any python
+python=`build/PrintPath python`
+if test -z "$python"; then
+  echo "buildconf: python not found."
+  echo "           You need python installed"
+  echo "           to build APR from SVN."
+  res=1
+else
+  py_version=`python -c 'import sys; print sys.version' 2>&1|sed 's/ .*//;q'`
+  echo "buildconf: python version $py_version (ok)"
+fi
+
+# autoconf 2.59 or newer
+ac_version=`${AUTOCONF:-autoconf} --version 2>/dev/null|sed -e 's/^[^0-9]*//;s/[a-z]* *$//;q'`
+if test -z "$ac_version"; then
+  echo "buildconf: autoconf not found."
+  echo "           You need autoconf version 2.59 or newer installed"
+  echo "           to build APR from SVN."
+  res=1
+else
+  IFS=.; set $ac_version; IFS=' '
+  if test "$1" = "2" -a "$2" -lt "59" || test "$1" -lt "2"; then
+    echo "buildconf: autoconf version $ac_version found."
+    echo "           You need autoconf version 2.59 or newer installed"
+    echo "           to build APR from SVN."
+    res=1
+  else
+    echo "buildconf: autoconf version $ac_version (ok)"
+  fi
+fi
+
+# Sample libtool --version outputs:
+# ltmain.sh (GNU libtool) 1.3.3 (1.385.2.181 1999/07/02 15:49:11)
+# ltmain.sh (GNU libtool 1.1361 2004/01/02 23:10:52) 1.5a
+# output is multiline from 1.5 onwards
+
+# Require libtool 1.4 or newer
+libtool=`build/PrintPath glibtool1 glibtool libtool libtool15 libtool14`
+lt_pversion=`$libtool --version 2>/dev/null|sed -e 's/([^)]*)//g;s/^[^0-9]*//;s/[- ].*//g;q'`
+if test -z "$lt_pversion"; then
+  echo "buildconf: libtool not found."
+  echo "           You need libtool version 1.4 or newer installed"
+  echo "           to build APR from SVN."
+  res=1
+else
+  lt_version=`echo $lt_pversion|sed -e 's/\([a-z]*\)$/.\1/'`
+  IFS=.; set $lt_version; IFS=' '
+  lt_status="good"
+  if test "$1" = "1"; then
+    if test "$2" -lt "4"; then
+      lt_status="bad"
+    fi
+  fi
+  if test $lt_status = "good"; then
+    echo "buildconf: libtool version $lt_pversion (ok)"
+  else
+    echo "buildconf: libtool version $lt_pversion found."
+    echo "           You need libtool version 1.4 or newer installed"
+    echo "           to build APR from SVN."
+    res=1
+  fi
+fi
+
+exit $res
+
diff --git a/build/config.guess b/build/config.guess
new file mode 100755
index 00000000000..588fe82a42a
--- /dev/null
+++ b/build/config.guess
@@ -0,0 +1,1466 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright 1992-2018 Free Software Foundation, Inc.
+
+timestamp='2018-01-01'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that
+# program.  This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
+#
+# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
+#
+# You can get the latest version of this script from:
+# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
+#
+# Please send patches to <config-patches@gnu.org>.
+
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Options:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright 1992-2018 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help" >&2
+       exit 1 ;;
+    * )
+       break ;;
+  esac
+done
+
+if test $# != 0; then
+  echo "$me: too many arguments$help" >&2
+  exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,)    echo "int x;" > $dummy.c ;
+	for c in cc gcc c89 c99 ; do
+	  if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+	     CC_FOR_BUILD="$c"; break ;
+	  fi ;
+	done ;
+	if test x"$CC_FOR_BUILD" = x ; then
+	  CC_FOR_BUILD=no_compiler_found ;
+	fi
+	;;
+ ,,*)   CC_FOR_BUILD=$CC ;;
+ ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+	PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+case "${UNAME_SYSTEM}" in
+Linux|GNU|GNU/*)
+	# If the system lacks a compiler, then just pick glibc.
+	# We could probably try harder.
+	LIBC=gnu
+
+	eval $set_cc_for_build
+	cat <<-EOF > $dummy.c
+	#include <features.h>
+	#if defined(__UCLIBC__)
+	LIBC=uclibc
+	#elif defined(__dietlibc__)
+	LIBC=dietlibc
+	#else
+	LIBC=gnu
+	#endif
+	EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
+	;;
+esac
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+    *:NetBSD:*:*)
+	# NetBSD (nbsd) targets should (where applicable) match one or
+	# more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
+	# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
+	# switched to ELF, *-*-netbsd* would select the old
+	# object file format.  This provides both forward
+	# compatibility and a consistent mechanism for selecting the
+	# object file format.
+	#
+	# Note: NetBSD doesn't particularly care about the vendor
+	# portion of the name.  We always set it to "unknown".
+	sysctl="sysctl -n hw.machine_arch"
+	UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
+	    /sbin/$sysctl 2>/dev/null || \
+	    /usr/sbin/$sysctl 2>/dev/null || \
+	    echo unknown)`
+	case "${UNAME_MACHINE_ARCH}" in
+	    armeb) machine=armeb-unknown ;;
+	    arm*) machine=arm-unknown ;;
+	    sh3el) machine=shl-unknown ;;
+	    sh3eb) machine=sh-unknown ;;
+	    sh5el) machine=sh5le-unknown ;;
+	    earmv*)
+		arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
+		endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'`
+		machine=${arch}${endian}-unknown
+		;;
+	    *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+	esac
+	# The Operating System including object format, if it has switched
+	# to ELF recently (or will in the future) and ABI.
+	case "${UNAME_MACHINE_ARCH}" in
+	    earm*)
+		os=netbsdelf
+		;;
+	    arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+		eval $set_cc_for_build
+		if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+			| grep -q __ELF__
+		then
+		    # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+		    # Return netbsd for either.  FIX?
+		    os=netbsd
+		else
+		    os=netbsdelf
+		fi
+		;;
+	    *)
+		os=netbsd
+		;;
+	esac
+	# Determine ABI tags.
+	case "${UNAME_MACHINE_ARCH}" in
+	    earm*)
+		expr='s/^earmv[0-9]/-eabi/;s/eb$//'
+		abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"`
+		;;
+	esac
+	# The OS release
+	# Debian GNU/NetBSD machines have a different userland, and
+	# thus, need a distinct triplet. However, they do not need
+	# kernel version information, so it can be replaced with a
+	# suitable tag, in the style of linux-gnu.
+	case "${UNAME_VERSION}" in
+	    Debian*)
+		release='-gnu'
+		;;
+	    *)
+		release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2`
+		;;
+	esac
+	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+	# contains redundant information, the shorter form:
+	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+	echo "${machine}-${os}${release}${abi}"
+	exit ;;
+    *:Bitrig:*:*)
+	UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
+	echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
+	exit ;;
+    *:OpenBSD:*:*)
+	UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+	echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+	exit ;;
+    *:LibertyBSD:*:*)
+	UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
+	echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE}
+	exit ;;
+    *:MidnightBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-midnightbsd${UNAME_RELEASE}
+	exit ;;
+    *:ekkoBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+	exit ;;
+    *:SolidBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+	exit ;;
+    macppc:MirBSD:*:*)
+	echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+	exit ;;
+    *:MirBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+	exit ;;
+    *:Sortix:*:*)
+	echo ${UNAME_MACHINE}-unknown-sortix
+	exit ;;
+    *:Redox:*:*)
+	echo ${UNAME_MACHINE}-unknown-redox
+	exit ;;
+    mips:OSF1:*.*)
+        echo mips-dec-osf1
+        exit ;;
+    alpha:OSF1:*:*)
+	case $UNAME_RELEASE in
+	*4.0)
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+		;;
+	*5.*)
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+		;;
+	esac
+	# According to Compaq, /usr/sbin/psrinfo has been available on
+	# OSF/1 and Tru64 systems produced since 1995.  I hope that
+	# covers most systems running today.  This code pipes the CPU
+	# types through head -n 1, so we only detect the type of CPU 0.
+	ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+	case "$ALPHA_CPU_TYPE" in
+	    "EV4 (21064)")
+		UNAME_MACHINE=alpha ;;
+	    "EV4.5 (21064)")
+		UNAME_MACHINE=alpha ;;
+	    "LCA4 (21066/21068)")
+		UNAME_MACHINE=alpha ;;
+	    "EV5 (21164)")
+		UNAME_MACHINE=alphaev5 ;;
+	    "EV5.6 (21164A)")
+		UNAME_MACHINE=alphaev56 ;;
+	    "EV5.6 (21164PC)")
+		UNAME_MACHINE=alphapca56 ;;
+	    "EV5.7 (21164PC)")
+		UNAME_MACHINE=alphapca57 ;;
+	    "EV6 (21264)")
+		UNAME_MACHINE=alphaev6 ;;
+	    "EV6.7 (21264A)")
+		UNAME_MACHINE=alphaev67 ;;
+	    "EV6.8CB (21264C)")
+		UNAME_MACHINE=alphaev68 ;;
+	    "EV6.8AL (21264B)")
+		UNAME_MACHINE=alphaev68 ;;
+	    "EV6.8CX (21264D)")
+		UNAME_MACHINE=alphaev68 ;;
+	    "EV6.9A (21264/EV69A)")
+		UNAME_MACHINE=alphaev69 ;;
+	    "EV7 (21364)")
+		UNAME_MACHINE=alphaev7 ;;
+	    "EV7.9 (21364A)")
+		UNAME_MACHINE=alphaev79 ;;
+	esac
+	# A Pn.n version is a patched version.
+	# A Vn.n version is a released version.
+	# A Tn.n version is a released field test version.
+	# A Xn.n version is an unreleased experimental baselevel.
+	# 1.2 uses "1.2" for uname -r.
+	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+	# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
+	exitcode=$?
+	trap '' 0
+	exit $exitcode ;;
+    Amiga*:UNIX_System_V:4.0:*)
+	echo m68k-unknown-sysv4
+	exit ;;
+    *:[Aa]miga[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-amigaos
+	exit ;;
+    *:[Mm]orph[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-morphos
+	exit ;;
+    *:OS/390:*:*)
+	echo i370-ibm-openedition
+	exit ;;
+    *:z/VM:*:*)
+	echo s390-ibm-zvmoe
+	exit ;;
+    *:OS400:*:*)
+	echo powerpc-ibm-os400
+	exit ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+	echo arm-acorn-riscix${UNAME_RELEASE}
+	exit ;;
+    arm*:riscos:*:*|arm*:RISCOS:*:*)
+	echo arm-unknown-riscos
+	exit ;;
+    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+	echo hppa1.1-hitachi-hiuxmpp
+	exit ;;
+    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+	# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+	if test "`(/bin/universe) 2>/dev/null`" = att ; then
+		echo pyramid-pyramid-sysv3
+	else
+		echo pyramid-pyramid-bsd
+	fi
+	exit ;;
+    NILE*:*:*:dcosx)
+	echo pyramid-pyramid-svr4
+	exit ;;
+    DRS?6000:unix:4.0:6*)
+	echo sparc-icl-nx6
+	exit ;;
+    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+	case `/usr/bin/uname -p` in
+	    sparc) echo sparc-icl-nx7; exit ;;
+	esac ;;
+    s390x:SunOS:*:*)
+	echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4H:SunOS:5.*:*)
+	echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+	echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
+	echo i386-pc-auroraux${UNAME_RELEASE}
+	exit ;;
+    i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+	eval $set_cc_for_build
+	SUN_ARCH=i386
+	# If there is a compiler, see if it is configured for 64-bit objects.
+	# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
+	# This test works for both compilers.
+	if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
+	    if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
+		(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+		grep IS_64BIT_ARCH >/dev/null
+	    then
+		SUN_ARCH=x86_64
+	    fi
+	fi
+	echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:6*:*)
+	# According to config.sub, this is the proper way to canonicalize
+	# SunOS6.  Hard to guess exactly what SunOS6 will be like, but
+	# it's likely to be more like Solaris than SunOS4.
+	echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:*:*)
+	case "`/usr/bin/arch -k`" in
+	    Series*|S4*)
+		UNAME_RELEASE=`uname -v`
+		;;
+	esac
+	# Japanese Language versions have a version number like `4.1.3-JL'.
+	echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+	exit ;;
+    sun3*:SunOS:*:*)
+	echo m68k-sun-sunos${UNAME_RELEASE}
+	exit ;;
+    sun*:*:4.2BSD:*)
+	UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+	test "x${UNAME_RELEASE}" = x && UNAME_RELEASE=3
+	case "`/bin/arch`" in
+	    sun3)
+		echo m68k-sun-sunos${UNAME_RELEASE}
+		;;
+	    sun4)
+		echo sparc-sun-sunos${UNAME_RELEASE}
+		;;
+	esac
+	exit ;;
+    aushp:SunOS:*:*)
+	echo sparc-auspex-sunos${UNAME_RELEASE}
+	exit ;;
+    # The situation for MiNT is a little confusing.  The machine name
+    # can be virtually everything (everything which is not
+    # "atarist" or "atariste" at least should have a processor
+    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
+    # to the lowercase version "mint" (or "freemint").  Finally
+    # the system name "TOS" denotes a system which is actually not
+    # MiNT.  But MiNT is downward compatible to TOS, so this should
+    # be no problem.
+    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+	echo m68k-atari-mint${UNAME_RELEASE}
+	exit ;;
+    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+	echo m68k-atari-mint${UNAME_RELEASE}
+	exit ;;
+    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+	echo m68k-atari-mint${UNAME_RELEASE}
+	exit ;;
+    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+	echo m68k-milan-mint${UNAME_RELEASE}
+	exit ;;
+    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+	echo m68k-hades-mint${UNAME_RELEASE}
+	exit ;;
+    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+	echo m68k-unknown-mint${UNAME_RELEASE}
+	exit ;;
+    m68k:machten:*:*)
+	echo m68k-apple-machten${UNAME_RELEASE}
+	exit ;;
+    powerpc:machten:*:*)
+	echo powerpc-apple-machten${UNAME_RELEASE}
+	exit ;;
+    RISC*:Mach:*:*)
+	echo mips-dec-mach_bsd4.3
+	exit ;;
+    RISC*:ULTRIX:*:*)
+	echo mips-dec-ultrix${UNAME_RELEASE}
+	exit ;;
+    VAX*:ULTRIX*:*:*)
+	echo vax-dec-ultrix${UNAME_RELEASE}
+	exit ;;
+    2020:CLIX:*:* | 2430:CLIX:*:*)
+	echo clipper-intergraph-clix${UNAME_RELEASE}
+	exit ;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+	int main (int argc, char *argv[]) {
+#else
+	int main (argc, argv) int argc; char *argv[]; {
+#endif
+	#if defined (host_mips) && defined (MIPSEB)
+	#if defined (SYSTYPE_SYSV)
+	  printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_SVR4)
+	  printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+	  printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0);
+	#endif
+	#endif
+	  exit (-1);
+	}
+EOF
+	$CC_FOR_BUILD -o $dummy $dummy.c &&
+	  dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+	  SYSTEM_NAME=`$dummy $dummyarg` &&
+	    { echo "$SYSTEM_NAME"; exit; }
+	echo mips-mips-riscos${UNAME_RELEASE}
+	exit ;;
+    Motorola:PowerMAX_OS:*:*)
+	echo powerpc-motorola-powermax
+	exit ;;
+    Motorola:*:4.3:PL8-*)
+	echo powerpc-harris-powermax
+	exit ;;
+    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+	echo powerpc-harris-powermax
+	exit ;;
+    Night_Hawk:Power_UNIX:*:*)
+	echo powerpc-harris-powerunix
+	exit ;;
+    m88k:CX/UX:7*:*)
+	echo m88k-harris-cxux7
+	exit ;;
+    m88k:*:4*:R4*)
+	echo m88k-motorola-sysv4
+	exit ;;
+    m88k:*:3*:R3*)
+	echo m88k-motorola-sysv3
+	exit ;;
+    AViiON:dgux:*:*)
+	# DG/UX returns AViiON for all architectures
+	UNAME_PROCESSOR=`/usr/bin/uname -p`
+	if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+	then
+	    if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+	       [ ${TARGET_BINARY_INTERFACE}x = x ]
+	    then
+		echo m88k-dg-dgux${UNAME_RELEASE}
+	    else
+		echo m88k-dg-dguxbcs${UNAME_RELEASE}
+	    fi
+	else
+	    echo i586-dg-dgux${UNAME_RELEASE}
+	fi
+	exit ;;
+    M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
+	echo m88k-dolphin-sysv3
+	exit ;;
+    M88*:*:R3*:*)
+	# Delta 88k system running SVR3
+	echo m88k-motorola-sysv3
+	exit ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+	echo m88k-tektronix-sysv3
+	exit ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+	echo m68k-tektronix-bsd
+	exit ;;
+    *:IRIX*:*:*)
+	echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+	exit ;;
+    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+	echo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id
+	exit ;;               # Note that: echo "'`uname -s`'" gives 'AIX '
+    i*86:AIX:*:*)
+	echo i386-ibm-aix
+	exit ;;
+    ia64:AIX:*:*)
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+	exit ;;
+    *:AIX:2:3)
+	if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+		eval $set_cc_for_build
+		sed 's/^		//' << EOF >$dummy.c
+		#include <sys/systemcfg.h>
+
+		main()
+			{
+			if (!__power_pc())
+				exit(1);
+			puts("powerpc-ibm-aix3.2.5");
+			exit(0);
+			}
+EOF
+		if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+		then
+			echo "$SYSTEM_NAME"
+		else
+			echo rs6000-ibm-aix3.2.5
+		fi
+	elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+		echo rs6000-ibm-aix3.2.4
+	else
+		echo rs6000-ibm-aix3.2
+	fi
+	exit ;;
+    *:AIX:*:[4567])
+	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+	if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+		IBM_ARCH=rs6000
+	else
+		IBM_ARCH=powerpc
+	fi
+	if [ -x /usr/bin/lslpp ] ; then
+		IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
+			   awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+	exit ;;
+    *:AIX:*:*)
+	echo rs6000-ibm-aix
+	exit ;;
+    ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*)
+	echo romp-ibm-bsd4.4
+	exit ;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
+	echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+	exit ;;                             # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+	echo rs6000-bull-bosx
+	exit ;;
+    DPX/2?00:B.O.S.:*:*)
+	echo m68k-bull-sysv3
+	exit ;;
+    9000/[34]??:4.3bsd:1.*:*)
+	echo m68k-hp-bsd
+	exit ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+	echo m68k-hp-bsd4.4
+	exit ;;
+    9000/[34678]??:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	case "${UNAME_MACHINE}" in
+	    9000/31?)            HP_ARCH=m68000 ;;
+	    9000/[34]??)         HP_ARCH=m68k ;;
+	    9000/[678][0-9][0-9])
+		if [ -x /usr/bin/getconf ]; then
+		    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+		    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+		    case "${sc_cpu_version}" in
+		      523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0
+		      528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1
+		      532)                      # CPU_PA_RISC2_0
+			case "${sc_kernel_bits}" in
+			  32) HP_ARCH=hppa2.0n ;;
+			  64) HP_ARCH=hppa2.0w ;;
+			  '') HP_ARCH=hppa2.0 ;;   # HP-UX 10.20
+			esac ;;
+		    esac
+		fi
+		if [ "${HP_ARCH}" = "" ]; then
+		    eval $set_cc_for_build
+		    sed 's/^		//' << EOF >$dummy.c
+
+		#define _HPUX_SOURCE
+		#include <stdlib.h>
+		#include <unistd.h>
+
+		int main ()
+		{
+		#if defined(_SC_KERNEL_BITS)
+		    long bits = sysconf(_SC_KERNEL_BITS);
+		#endif
+		    long cpu  = sysconf (_SC_CPU_VERSION);
+
+		    switch (cpu)
+			{
+			case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+			case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+			case CPU_PA_RISC2_0:
+		#if defined(_SC_KERNEL_BITS)
+			    switch (bits)
+				{
+				case 64: puts ("hppa2.0w"); break;
+				case 32: puts ("hppa2.0n"); break;
+				default: puts ("hppa2.0"); break;
+				} break;
+		#else  /* !defined(_SC_KERNEL_BITS) */
+			    puts ("hppa2.0"); break;
+		#endif
+			default: puts ("hppa1.0"); break;
+			}
+		    exit (0);
+		}
+EOF
+		    (CCOPTS="" $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+		    test -z "$HP_ARCH" && HP_ARCH=hppa
+		fi ;;
+	esac
+	if [ ${HP_ARCH} = hppa2.0w ]
+	then
+	    eval $set_cc_for_build
+
+	    # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+	    # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler
+	    # generating 64-bit code.  GNU and HP use different nomenclature:
+	    #
+	    # $ CC_FOR_BUILD=cc ./config.guess
+	    # => hppa2.0w-hp-hpux11.23
+	    # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+	    # => hppa64-hp-hpux11.23
+
+	    if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) |
+		grep -q __LP64__
+	    then
+		HP_ARCH=hppa2.0w
+	    else
+		HP_ARCH=hppa64
+	    fi
+	fi
+	echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+	exit ;;
+    ia64:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	echo ia64-hp-hpux${HPUX_REV}
+	exit ;;
+    3050*:HI-UX:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#include <unistd.h>
+	int
+	main ()
+	{
+	  long cpu = sysconf (_SC_CPU_VERSION);
+	  /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+	     true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
+	     results, however.  */
+	  if (CPU_IS_PA_RISC (cpu))
+	    {
+	      switch (cpu)
+		{
+		  case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+		  default: puts ("hppa-hitachi-hiuxwe2"); break;
+		}
+	    }
+	  else if (CPU_IS_HP_MC68K (cpu))
+	    puts ("m68k-hitachi-hiuxwe2");
+	  else puts ("unknown-hitachi-hiuxwe2");
+	  exit (0);
+	}
+EOF
+	$CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+		{ echo "$SYSTEM_NAME"; exit; }
+	echo unknown-hitachi-hiuxwe2
+	exit ;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*)
+	echo hppa1.1-hp-bsd
+	exit ;;
+    9000/8??:4.3bsd:*:*)
+	echo hppa1.0-hp-bsd
+	exit ;;
+    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+	echo hppa1.0-hp-mpeix
+	exit ;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*)
+	echo hppa1.1-hp-osf
+	exit ;;
+    hp8??:OSF1:*:*)
+	echo hppa1.0-hp-osf
+	exit ;;
+    i*86:OSF1:*:*)
+	if [ -x /usr/sbin/sysversion ] ; then
+	    echo ${UNAME_MACHINE}-unknown-osf1mk
+	else
+	    echo ${UNAME_MACHINE}-unknown-osf1
+	fi
+	exit ;;
+    parisc*:Lites*:*:*)
+	echo hppa1.1-hp-lites
+	exit ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+	echo c1-convex-bsd
+	exit ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+	exit ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+	echo c34-convex-bsd
+	exit ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+	echo c38-convex-bsd
+	exit ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+	echo c4-convex-bsd
+	exit ;;
+    CRAY*Y-MP:*:*:*)
+	echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*[A-Z]90:*:*:*)
+	echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+	| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+	      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+	      -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*TS:*:*:*)
+	echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*T3E:*:*:*)
+	echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*SV1:*:*:*)
+	echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    *:UNICOS/mp:*:*)
+	echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+	FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+	FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
+	FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+	echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+	exit ;;
+    5000:UNIX_System_V:4.*:*)
+	FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
+	FUJITSU_REL=`echo ${UNAME_RELEASE} | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
+	echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+	exit ;;
+    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+	exit ;;
+    sparc*:BSD/OS:*:*)
+	echo sparc-unknown-bsdi${UNAME_RELEASE}
+	exit ;;
+    *:BSD/OS:*:*)
+	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+	exit ;;
+    *:FreeBSD:*:*)
+	UNAME_PROCESSOR=`/usr/bin/uname -p`
+	case ${UNAME_PROCESSOR} in
+	    amd64)
+		UNAME_PROCESSOR=x86_64 ;;
+	    i386)
+		UNAME_PROCESSOR=i586 ;;
+	esac
+	echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+	exit ;;
+    i*:CYGWIN*:*)
+	echo ${UNAME_MACHINE}-pc-cygwin
+	exit ;;
+    *:MINGW64*:*)
+	echo ${UNAME_MACHINE}-pc-mingw64
+	exit ;;
+    *:MINGW*:*)
+	echo ${UNAME_MACHINE}-pc-mingw32
+	exit ;;
+    *:MSYS*:*)
+	echo ${UNAME_MACHINE}-pc-msys
+	exit ;;
+    i*:PW*:*)
+	echo ${UNAME_MACHINE}-pc-pw32
+	exit ;;
+    *:Interix*:*)
+	case ${UNAME_MACHINE} in
+	    x86)
+		echo i586-pc-interix${UNAME_RELEASE}
+		exit ;;
+	    authenticamd | genuineintel | EM64T)
+		echo x86_64-unknown-interix${UNAME_RELEASE}
+		exit ;;
+	    IA64)
+		echo ia64-unknown-interix${UNAME_RELEASE}
+		exit ;;
+	esac ;;
+    i*:UWIN*:*)
+	echo ${UNAME_MACHINE}-pc-uwin
+	exit ;;
+    amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+	echo x86_64-unknown-cygwin
+	exit ;;
+    prep*:SunOS:5.*:*)
+	echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    *:GNU:*:*)
+	# the GNU system
+	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+	exit ;;
+    *:GNU/*:*:*)
+	# other systems with GNU libc and userland
+	echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
+	exit ;;
+    i*86:Minix:*:*)
+	echo ${UNAME_MACHINE}-pc-minix
+	exit ;;
+    aarch64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    aarch64_be:Linux:*:*)
+	UNAME_MACHINE=aarch64_be
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    alpha:Linux:*:*)
+	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+	  EV5)   UNAME_MACHINE=alphaev5 ;;
+	  EV56)  UNAME_MACHINE=alphaev56 ;;
+	  PCA56) UNAME_MACHINE=alphapca56 ;;
+	  PCA57) UNAME_MACHINE=alphapca56 ;;
+	  EV6)   UNAME_MACHINE=alphaev6 ;;
+	  EV67)  UNAME_MACHINE=alphaev67 ;;
+	  EV68*) UNAME_MACHINE=alphaev68 ;;
+	esac
+	objdump --private-headers /bin/sh | grep -q ld.so.1
+	if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    arc:Linux:*:* | arceb:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    arm*:Linux:*:*)
+	eval $set_cc_for_build
+	if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+	    | grep -q __ARM_EABI__
+	then
+	    echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	else
+	    if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
+		| grep -q __ARM_PCS_VFP
+	    then
+		echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
+	    else
+		echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf
+	    fi
+	fi
+	exit ;;
+    avr32*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    cris:Linux:*:*)
+	echo ${UNAME_MACHINE}-axis-linux-${LIBC}
+	exit ;;
+    crisv32:Linux:*:*)
+	echo ${UNAME_MACHINE}-axis-linux-${LIBC}
+	exit ;;
+    e2k:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    frv:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    hexagon:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    i*86:Linux:*:*)
+	echo ${UNAME_MACHINE}-pc-linux-${LIBC}
+	exit ;;
+    ia64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    k1om:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    m32r*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    m68*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    mips:Linux:*:* | mips64:Linux:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#undef CPU
+	#undef ${UNAME_MACHINE}
+	#undef ${UNAME_MACHINE}el
+	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+	CPU=${UNAME_MACHINE}el
+	#else
+	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+	CPU=${UNAME_MACHINE}
+	#else
+	CPU=
+	#endif
+	#endif
+EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
+	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
+	;;
+    mips64el:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    openrisc*:Linux:*:*)
+	echo or1k-unknown-linux-${LIBC}
+	exit ;;
+    or32:Linux:*:* | or1k*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    padre:Linux:*:*)
+	echo sparc-unknown-linux-${LIBC}
+	exit ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+	echo hppa64-unknown-linux-${LIBC}
+	exit ;;
+    parisc:Linux:*:* | hppa:Linux:*:*)
+	# Look for CPU level
+	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+	  PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
+	  PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
+	  *)    echo hppa-unknown-linux-${LIBC} ;;
+	esac
+	exit ;;
+    ppc64:Linux:*:*)
+	echo powerpc64-unknown-linux-${LIBC}
+	exit ;;
+    ppc:Linux:*:*)
+	echo powerpc-unknown-linux-${LIBC}
+	exit ;;
+    ppc64le:Linux:*:*)
+	echo powerpc64le-unknown-linux-${LIBC}
+	exit ;;
+    ppcle:Linux:*:*)
+	echo powerpcle-unknown-linux-${LIBC}
+	exit ;;
+    riscv32:Linux:*:* | riscv64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    s390:Linux:*:* | s390x:Linux:*:*)
+	echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
+	exit ;;
+    sh64*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    sh*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    sparc:Linux:*:* | sparc64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    tile*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    vax:Linux:*:*)
+	echo ${UNAME_MACHINE}-dec-linux-${LIBC}
+	exit ;;
+    x86_64:Linux:*:*)
+	echo ${UNAME_MACHINE}-pc-linux-${LIBC}
+	exit ;;
+    xtensa*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    i*86:DYNIX/ptx:4*:*)
+	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+	# earlier versions are messed up and put the nodename in both
+	# sysname and nodename.
+	echo i386-sequent-sysv4
+	exit ;;
+    i*86:UNIX_SV:4.2MP:2.*)
+	# Unixware is an offshoot of SVR4, but it has its own version
+	# number series starting with 2...
+	# I am not positive that other SVR4 systems won't match this,
+	# I just have to hope.  -- rms.
+	# Use sysv4.2uw... so that sysv4* matches it.
+	echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+	exit ;;
+    i*86:OS/2:*:*)
+	# If we were able to find `uname', then EMX Unix compatibility
+	# is probably installed.
+	echo ${UNAME_MACHINE}-pc-os2-emx
+	exit ;;
+    i*86:XTS-300:*:STOP)
+	echo ${UNAME_MACHINE}-unknown-stop
+	exit ;;
+    i*86:atheos:*:*)
+	echo ${UNAME_MACHINE}-unknown-atheos
+	exit ;;
+    i*86:syllable:*:*)
+	echo ${UNAME_MACHINE}-pc-syllable
+	exit ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
+	echo i386-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    i*86:*DOS:*:*)
+	echo ${UNAME_MACHINE}-pc-msdosdjgpp
+	exit ;;
+    i*86:*:4.*:*)
+	UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+		echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+	else
+		echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+	fi
+	exit ;;
+    i*86:*:5:[678]*)
+	# UnixWare 7.x, OpenUNIX and OpenServer 6.
+	case `/bin/uname -X | grep "^Machine"` in
+	    *486*)	     UNAME_MACHINE=i486 ;;
+	    *Pentium)	     UNAME_MACHINE=i586 ;;
+	    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+	esac
+	echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+	exit ;;
+    i*86:*:3.2:*)
+	if test -f /usr/options/cb.name; then
+		UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+		echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+	elif /bin/uname -X 2>/dev/null >/dev/null ; then
+		UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+		(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+		(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+			&& UNAME_MACHINE=i586
+		(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+	else
+		echo ${UNAME_MACHINE}-pc-sysv32
+	fi
+	exit ;;
+    pc:*:*:*)
+	# Left here for compatibility:
+	# uname -m prints for DJGPP always 'pc', but it prints nothing about
+	# the processor, so we play safe by assuming i586.
+	# Note: whatever this is, it MUST be the same as what config.sub
+	# prints for the "djgpp" host, or else GDB configure will decide that
+	# this is a cross-build.
+	echo i586-pc-msdosdjgpp
+	exit ;;
+    Intel:Mach:3*:*)
+	echo i386-pc-mach3
+	exit ;;
+    paragon:*:*:*)
+	echo i860-intel-osf1
+	exit ;;
+    i860:*:4.*:*) # i860-SVR4
+	if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+	  echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+	else # Add other i860-SVR4 vendors below as they are discovered.
+	  echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
+	fi
+	exit ;;
+    mini*:CTIX:SYS*5:*)
+	# "miniframe"
+	echo m68010-convergent-sysv
+	exit ;;
+    mc68k:UNIX:SYSTEM5:3.51m)
+	echo m68k-convergent-sysv
+	exit ;;
+    M680?0:D-NIX:5.3:*)
+	echo m68k-diab-dnix
+	exit ;;
+    M68*:*:R3V[5678]*:*)
+	test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+	OS_REL=''
+	test -r /etc/.relid \
+	&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	  && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+	  && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	  && { echo i486-ncr-sysv4; exit; } ;;
+    NCR*:*:4.2:* | MPRAS*:*:4.2:*)
+	OS_REL='.3'
+	test -r /etc/.relid \
+	    && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	    && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+	    && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
+	    && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+	echo m68k-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    mc68030:UNIX_System_V:4.*:*)
+	echo m68k-atari-sysv4
+	exit ;;
+    TSUNAMI:LynxOS:2.*:*)
+	echo sparc-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    rs6000:LynxOS:2.*:*)
+	echo rs6000-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
+	echo powerpc-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    SM[BE]S:UNIX_SV:*:*)
+	echo mips-dde-sysv${UNAME_RELEASE}
+	exit ;;
+    RM*:ReliantUNIX-*:*:*)
+	echo mips-sni-sysv4
+	exit ;;
+    RM*:SINIX-*:*:*)
+	echo mips-sni-sysv4
+	exit ;;
+    *:SINIX-*:*:*)
+	if uname -p 2>/dev/null >/dev/null ; then
+		UNAME_MACHINE=`(uname -p) 2>/dev/null`
+		echo ${UNAME_MACHINE}-sni-sysv4
+	else
+		echo ns32k-sni-sysv
+	fi
+	exit ;;
+    PENTIUM:*:4.0*:*)	# Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+			# says <Richard.M.Bartel@ccMail.Census.GOV>
+	echo i586-unisys-sysv4
+	exit ;;
+    *:UNIX_System_V:4*:FTX*)
+	# From Gerald Hewes <hewes@openmarket.com>.
+	# How about differentiating between stratus architectures? -djm
+	echo hppa1.1-stratus-sysv4
+	exit ;;
+    *:*:*:FTX*)
+	# From seanf@swdc.stratus.com.
+	echo i860-stratus-sysv4
+	exit ;;
+    i*86:VOS:*:*)
+	# From Paul.Green@stratus.com.
+	echo ${UNAME_MACHINE}-stratus-vos
+	exit ;;
+    *:VOS:*:*)
+	# From Paul.Green@stratus.com.
+	echo hppa1.1-stratus-vos
+	exit ;;
+    mc68*:A/UX:*:*)
+	echo m68k-apple-aux${UNAME_RELEASE}
+	exit ;;
+    news*:NEWS-OS:6*:*)
+	echo mips-sony-newsos6
+	exit ;;
+    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+	if [ -d /usr/nec ]; then
+		echo mips-nec-sysv${UNAME_RELEASE}
+	else
+		echo mips-unknown-sysv${UNAME_RELEASE}
+	fi
+	exit ;;
+    BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
+	echo powerpc-be-beos
+	exit ;;
+    BeMac:BeOS:*:*)	# BeOS running on Mac or Mac clone, PPC only.
+	echo powerpc-apple-beos
+	exit ;;
+    BePC:BeOS:*:*)	# BeOS running on Intel PC compatible.
+	echo i586-pc-beos
+	exit ;;
+    BePC:Haiku:*:*)	# Haiku running on Intel PC compatible.
+	echo i586-pc-haiku
+	exit ;;
+    x86_64:Haiku:*:*)
+	echo x86_64-unknown-haiku
+	exit ;;
+    SX-4:SUPER-UX:*:*)
+	echo sx4-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-5:SUPER-UX:*:*)
+	echo sx5-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-6:SUPER-UX:*:*)
+	echo sx6-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-7:SUPER-UX:*:*)
+	echo sx7-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-8:SUPER-UX:*:*)
+	echo sx8-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-8R:SUPER-UX:*:*)
+	echo sx8r-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-ACE:SUPER-UX:*:*)
+	echo sxace-nec-superux${UNAME_RELEASE}
+	exit ;;
+    Power*:Rhapsody:*:*)
+	echo powerpc-apple-rhapsody${UNAME_RELEASE}
+	exit ;;
+    *:Rhapsody:*:*)
+	echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+	exit ;;
+    *:Darwin:*:*)
+	UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+	eval $set_cc_for_build
+	if test "$UNAME_PROCESSOR" = unknown ; then
+	    UNAME_PROCESSOR=powerpc
+	fi
+	if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
+	    if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
+		if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+		       (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+		       grep IS_64BIT_ARCH >/dev/null
+		then
+		    case $UNAME_PROCESSOR in
+			i386) UNAME_PROCESSOR=x86_64 ;;
+			powerpc) UNAME_PROCESSOR=powerpc64 ;;
+		    esac
+		fi
+		# On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc
+		if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \
+		       (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+		       grep IS_PPC >/dev/null
+		then
+		    UNAME_PROCESSOR=powerpc
+		fi
+	    fi
+	elif test "$UNAME_PROCESSOR" = i386 ; then
+	    # Avoid executing cc on OS X 10.9, as it ships with a stub
+	    # that puts up a graphical alert prompting to install
+	    # developer tools.  Any system running Mac OS X 10.7 or
+	    # later (Darwin 11 and later) is required to have a 64-bit
+	    # processor. This is not true of the ARM version of Darwin
+	    # that Apple uses in portable devices.
+	    UNAME_PROCESSOR=x86_64
+	fi
+	echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+	exit ;;
+    *:procnto*:*:* | *:QNX:[0123456789]*:*)
+	UNAME_PROCESSOR=`uname -p`
+	if test "$UNAME_PROCESSOR" = x86; then
+		UNAME_PROCESSOR=i386
+		UNAME_MACHINE=pc
+	fi
+	echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+	exit ;;
+    *:QNX:*:4*)
+	echo i386-pc-qnx
+	exit ;;
+    NEO-*:NONSTOP_KERNEL:*:*)
+	echo neo-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    NSE-*:NONSTOP_KERNEL:*:*)
+	echo nse-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    NSR-*:NONSTOP_KERNEL:*:*)
+	echo nsr-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    NSX-*:NONSTOP_KERNEL:*:*)
+	echo nsx-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    *:NonStop-UX:*:*)
+	echo mips-compaq-nonstopux
+	exit ;;
+    BS2000:POSIX*:*:*)
+	echo bs2000-siemens-sysv
+	exit ;;
+    DS/*:UNIX_System_V:*:*)
+	echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+	exit ;;
+    *:Plan9:*:*)
+	# "uname -m" is not consistent, so use $cputype instead. 386
+	# is converted to i386 for consistency with other x86
+	# operating systems.
+	if test "$cputype" = 386; then
+	    UNAME_MACHINE=i386
+	else
+	    UNAME_MACHINE="$cputype"
+	fi
+	echo ${UNAME_MACHINE}-unknown-plan9
+	exit ;;
+    *:TOPS-10:*:*)
+	echo pdp10-unknown-tops10
+	exit ;;
+    *:TENEX:*:*)
+	echo pdp10-unknown-tenex
+	exit ;;
+    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+	echo pdp10-dec-tops20
+	exit ;;
+    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+	echo pdp10-xkl-tops20
+	exit ;;
+    *:TOPS-20:*:*)
+	echo pdp10-unknown-tops20
+	exit ;;
+    *:ITS:*:*)
+	echo pdp10-unknown-its
+	exit ;;
+    SEI:*:*:SEIUX)
+	echo mips-sei-seiux${UNAME_RELEASE}
+	exit ;;
+    *:DragonFly:*:*)
+	echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+	exit ;;
+    *:*VMS:*:*)
+	UNAME_MACHINE=`(uname -p) 2>/dev/null`
+	case "${UNAME_MACHINE}" in
+	    A*) echo alpha-dec-vms ; exit ;;
+	    I*) echo ia64-dec-vms ; exit ;;
+	    V*) echo vax-dec-vms ; exit ;;
+	esac ;;
+    *:XENIX:*:SysV)
+	echo i386-pc-xenix
+	exit ;;
+    i*86:skyos:*:*)
+	echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE} | sed -e 's/ .*$//'`
+	exit ;;
+    i*86:rdos:*:*)
+	echo ${UNAME_MACHINE}-pc-rdos
+	exit ;;
+    i*86:AROS:*:*)
+	echo ${UNAME_MACHINE}-pc-aros
+	exit ;;
+    x86_64:VMkernel:*:*)
+	echo ${UNAME_MACHINE}-unknown-esx
+	exit ;;
+    amd64:Isilon\ OneFS:*:*)
+	echo x86_64-unknown-onefs
+	exit ;;
+esac
+
+echo "$0: unable to guess system type" >&2
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}" in
+    mips:Linux | mips64:Linux)
+	# If we got here on MIPS GNU/Linux, output extra information.
+	cat >&2 <<EOF
+
+NOTE: MIPS GNU/Linux systems require a C compiler to fully recognize
+the system type. Please install a C compiler and try again.
+EOF
+	;;
+esac
+
+cat >&2 <<EOF
+
+This script (version $timestamp), has failed to recognize the
+operating system you are using. If your script is old, overwrite *all*
+copies of config.guess and config.sub with the latest versions from:
+
+  https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
+and
+  https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
+
+If $0 has already been updated, send the following data and any
+information you think might be pertinent to config-patches@gnu.org to
+provide the necessary information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo               = `(hostinfo) 2>/dev/null`
+/bin/universe          = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch              = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM  = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-functions 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/config.sub b/build/config.sub
similarity index 50%
rename from config.sub
rename to build/config.sub
index 8e7cdd62ce4..f2632cd8a2b 100755
--- a/config.sub
+++ b/build/config.sub
@@ -1,35 +1,40 @@
 #! /bin/sh
-# Configuration validation subroutine script, version 1.1.
-#   Copyright (C) 1991, 92-97, 1998, 1999 Free Software Foundation, Inc.
-# This file is (in principle) common to ALL GNU software.
-# The presence of a machine in this file suggests that SOME GNU software
-# can handle that machine.  It does not imply ALL GNU software can.
-#
-# This file is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
+# Configuration validation subroutine script.
+#   Copyright 1992-2018 Free Software Foundation, Inc.
+
+timestamp='2018-01-01'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
 # (at your option) any later version.
 #
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
+#
 # As a special exception to the GNU General Public License, if you
 # distribute this file as part of a program that contains a
 # configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
+# the same distribution terms that you use for the rest of that
+# program.  This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
+
 
+# Please send patches to <config-patches@gnu.org>.
+#
 # Configuration subroutine to validate and canonicalize a configuration type.
 # Supply the specified configuration type as an argument.
 # If it is invalid, we print an error message on stderr and exit with code 1.
 # Otherwise, we print the canonical config type on stdout and succeed.
 
+# You can get the latest version of this script from:
+# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
+
 # This file is supposed to be the same for all GNU packages
 # and recognize all the CPU types, system types and aliases
 # that are meaningful with *any* GNU software.
@@ -45,33 +50,82 @@
 #	CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
 # It is wrong to echo any other type of specification.
 
-if [ x$1 = x ]
-then
-	echo Configuration name missing. 1>&2
-	echo "Usage: $0 CPU-MFR-OPSYS" 1>&2
-	echo "or     $0 ALIAS" 1>&2
-	echo where ALIAS is a recognized configuration type. 1>&2
-	exit 1
-fi
+me=`echo "$0" | sed -e 's,.*/,,'`
 
-# First pass through any local machine types.
-case $1 in
-	*local*)
-		echo $1
-		exit 0
-		;;
-	*)
-	;;
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
+
+Canonicalize a configuration name.
+
+Options:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright 1992-2018 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help"
+       exit 1 ;;
+
+    *local*)
+       # First pass through any local machine types.
+       echo $1
+       exit ;;
+
+    * )
+       break ;;
+  esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+    exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+    exit 1;;
 esac
 
 # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
 # Here we must recognize all the valid KERNEL-OS combinations.
 maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
 case $maybe_os in
-  linux-gnu*)
+  nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
+  linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
+  knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \
+  kopensolaris*-gnu* | cloudabi*-eabi* | \
+  storm-chaos* | os2-emx* | rtmk-nova*)
     os=-$maybe_os
     basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
     ;;
+  android-linux)
+    os=-linux-android
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
+    ;;
   *)
     basic_machine=`echo $1 | sed 's/-[^-]*$//'`
     if [ $basic_machine != $1 ]
@@ -94,10 +148,13 @@ case $os in
 	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
 	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
 	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
-	-apple)
+	-apple | -axis | -knuth | -cray | -microblaze*)
 		os=
 		basic_machine=$1
 		;;
+	-bluegene*)
+		os=-cnk
+		;;
 	-sim | -cisco | -oki | -wec | -winbond)
 		os=
 		basic_machine=$1
@@ -105,12 +162,24 @@ case $os in
 	-scout)
 		;;
 	-wrs)
-		os=vxworks
+		os=-vxworks
+		basic_machine=$1
+		;;
+	-chorusos*)
+		os=-chorusos
+		basic_machine=$1
+		;;
+	-chorusrdb)
+		os=-chorusrdb
 		basic_machine=$1
 		;;
 	-hiux*)
 		os=-hiuxwe2
 		;;
+	-sco6)
+		os=-sco5v6
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
 	-sco5)
 		os=-sco3.2v5
 		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
@@ -127,6 +196,10 @@ case $os in
 		# Don't forget version if it is 3.2v4 or newer.
 		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
 		;;
+	-sco5v6*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
 	-sco*)
 		os=-sco3.2v2
 		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
@@ -144,45 +217,147 @@ case $os in
 	-isc*)
 		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
 		;;
+	-lynx*178)
+		os=-lynxos178
+		;;
+	-lynx*5)
+		os=-lynxos5
+		;;
 	-lynx*)
 		os=-lynxos
 		;;
 	-ptx*)
 		basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
 		;;
-	-windowsnt*)
-		os=`echo $os | sed -e 's/windowsnt/winnt/'`
-		;;
 	-psos*)
 		os=-psos
 		;;
+	-mint | -mint[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
 esac
 
 # Decode aliases for certain CPU-COMPANY combinations.
 case $basic_machine in
 	# Recognize the basic CPU types without company name.
 	# Some are omitted here because they have special meanings below.
-	tahoe | i860 | m32r | m68k | m68000 | m88k | ns32k | arc | arm \
-		| arme[lb] | pyramid | mn10200 | mn10300 | tron | a29k \
-		| 580 | i960 | h8300 \
-		| hppa | hppa1.0 | hppa1.1 | hppa2.0 | hppa2.0w | hppa2.0n \
-		| alpha | alphaev[4-7] | alphaev56 | alphapca5[67] \
-		| we32k | ns16k | clipper | i370 | sh | powerpc | powerpcle \
-		| 1750a | dsp16xx | pdp11 | mips16 | mips64 | mipsel | mips64el \
-		| mips64orion | mips64orionel | mipstx39 | mipstx39el \
-		| mips64vr4300 | mips64vr4300el | mips64vr4100 | mips64vr4100el \
-		| mips64vr5000 | miprs64vr5000el \
-		| armv[34][lb] | sparc | sparclet | sparclite | sparc64 | sparcv9 | v850 | c4x \
-		| thumb | d10v)
+	1750a | 580 \
+	| a29k \
+	| aarch64 | aarch64_be \
+	| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+	| am33_2.0 \
+	| arc | arceb \
+	| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
+	| avr | avr32 \
+	| ba \
+	| be32 | be64 \
+	| bfin \
+	| c4x | c8051 | clipper \
+	| d10v | d30v | dlx | dsp16xx \
+	| e2k | epiphany \
+	| fido | fr30 | frv | ft32 \
+	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+	| hexagon \
+	| i370 | i860 | i960 | ia16 | ia64 \
+	| ip2k | iq2000 \
+	| k1om \
+	| le32 | le64 \
+	| lm32 \
+	| m32c | m32r | m32rle | m68000 | m68k | m88k \
+	| maxq | mb | microblaze | microblazeel | mcore | mep | metag \
+	| mips | mipsbe | mipseb | mipsel | mipsle \
+	| mips16 \
+	| mips64 | mips64el \
+	| mips64octeon | mips64octeonel \
+	| mips64orion | mips64orionel \
+	| mips64r5900 | mips64r5900el \
+	| mips64vr | mips64vrel \
+	| mips64vr4100 | mips64vr4100el \
+	| mips64vr4300 | mips64vr4300el \
+	| mips64vr5000 | mips64vr5000el \
+	| mips64vr5900 | mips64vr5900el \
+	| mipsisa32 | mipsisa32el \
+	| mipsisa32r2 | mipsisa32r2el \
+	| mipsisa32r6 | mipsisa32r6el \
+	| mipsisa64 | mipsisa64el \
+	| mipsisa64r2 | mipsisa64r2el \
+	| mipsisa64r6 | mipsisa64r6el \
+	| mipsisa64sb1 | mipsisa64sb1el \
+	| mipsisa64sr71k | mipsisa64sr71kel \
+	| mipsr5900 | mipsr5900el \
+	| mipstx39 | mipstx39el \
+	| mn10200 | mn10300 \
+	| moxie \
+	| mt \
+	| msp430 \
+	| nds32 | nds32le | nds32be \
+	| nios | nios2 | nios2eb | nios2el \
+	| ns16k | ns32k \
+	| open8 | or1k | or1knd | or32 \
+	| pdp10 | pdp11 | pj | pjl \
+	| powerpc | powerpc64 | powerpc64le | powerpcle \
+	| pru \
+	| pyramid \
+	| riscv32 | riscv64 \
+	| rl78 | rx \
+	| score \
+	| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+	| sh64 | sh64le \
+	| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+	| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+	| spu \
+	| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
+	| ubicom32 \
+	| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
+	| visium \
+	| wasm32 \
+	| x86 | xc16x | xstormy16 | xtensa \
+	| z8k | z80)
+		basic_machine=$basic_machine-unknown
+		;;
+	c54x)
+		basic_machine=tic54x-unknown
+		;;
+	c55x)
+		basic_machine=tic55x-unknown
+		;;
+	c6x)
+		basic_machine=tic6x-unknown
+		;;
+	leon|leon[3-9])
+		basic_machine=sparc-$basic_machine
+		;;
+	m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
 		basic_machine=$basic_machine-unknown
+		os=-none
 		;;
-	m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | z8k | v70 | h8500 | w65)
+	m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+		;;
+	ms1)
+		basic_machine=mt-unknown
+		;;
+
+	strongarm | thumb | xscale)
+		basic_machine=arm-unknown
+		;;
+	xgate)
+		basic_machine=$basic_machine-unknown
+		os=-none
+		;;
+	xscaleeb)
+		basic_machine=armeb-unknown
+		;;
+
+	xscaleel)
+		basic_machine=armel-unknown
 		;;
 
 	# We use `pc' rather than `unknown'
 	# because (1) that's what they normally are, and
 	# (2) the word "unknown" tends to confuse beginning users.
-	i[34567]86)
+	i*86 | x86_64)
 	  basic_machine=$basic_machine-pc
 	  ;;
 	# Object if more than one company name word.
@@ -191,24 +366,93 @@ case $basic_machine in
 		exit 1
 		;;
 	# Recognize the basic CPU types with company name.
-	vax-* | tahoe-* | i[34567]86-* | i860-* | m32r-* | m68k-* | m68000-* \
-	      | m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | arm-* | c[123]* \
-	      | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \
-	      | power-* | none-* | 580-* | cray2-* | h8300-* | h8500-* | i960-* \
-	      | xmp-* | ymp-* \
-	      | hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* | hppa2.0w-* | hppa2.0n-* \
-	      | alpha-* | alphaev[4-7]-* | alphaev56-* | alphapca5[67]-* \
-	      | we32k-* | cydra-* | ns16k-* | pn-* | np1-* | xps100-* \
-	      | clipper-* | orion-* \
-	      | sparclite-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \
-	      | sparc64-* | sparcv9-* | sparc86x-* | mips16-* | mips64-* | mipsel-* \
-	      | mips64el-* | mips64orion-* | mips64orionel-* \
-	      | mips64vr4100-* | mips64vr4100el-* | mips64vr4300-* | mips64vr4300el-* \
-	      | mipstx39-* | mipstx39el-* \
-	      | armv[34][lb]-* \
-	      | f301-* | armv*-* | t3e-* \
-	      | m88110-* | m680[01234]0-* | m683?2-* | m68360-* | z8k-* | d10v-* \
-	      | thumb-* | v850-* | d30v-* | tic30-* | c30-* )
+	580-* \
+	| a29k-* \
+	| aarch64-* | aarch64_be-* \
+	| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+	| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
+	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
+	| avr-* | avr32-* \
+	| ba-* \
+	| be32-* | be64-* \
+	| bfin-* | bs2000-* \
+	| c[123]* | c30-* | [cjt]90-* | c4x-* \
+	| c8051-* | clipper-* | craynv-* | cydra-* \
+	| d10v-* | d30v-* | dlx-* \
+	| e2k-* | elxsi-* \
+	| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+	| h8300-* | h8500-* \
+	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+	| hexagon-* \
+	| i*86-* | i860-* | i960-* | ia16-* | ia64-* \
+	| ip2k-* | iq2000-* \
+	| k1om-* \
+	| le32-* | le64-* \
+	| lm32-* \
+	| m32c-* | m32r-* | m32rle-* \
+	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+	| m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
+	| microblaze-* | microblazeel-* \
+	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+	| mips16-* \
+	| mips64-* | mips64el-* \
+	| mips64octeon-* | mips64octeonel-* \
+	| mips64orion-* | mips64orionel-* \
+	| mips64r5900-* | mips64r5900el-* \
+	| mips64vr-* | mips64vrel-* \
+	| mips64vr4100-* | mips64vr4100el-* \
+	| mips64vr4300-* | mips64vr4300el-* \
+	| mips64vr5000-* | mips64vr5000el-* \
+	| mips64vr5900-* | mips64vr5900el-* \
+	| mipsisa32-* | mipsisa32el-* \
+	| mipsisa32r2-* | mipsisa32r2el-* \
+	| mipsisa32r6-* | mipsisa32r6el-* \
+	| mipsisa64-* | mipsisa64el-* \
+	| mipsisa64r2-* | mipsisa64r2el-* \
+	| mipsisa64r6-* | mipsisa64r6el-* \
+	| mipsisa64sb1-* | mipsisa64sb1el-* \
+	| mipsisa64sr71k-* | mipsisa64sr71kel-* \
+	| mipsr5900-* | mipsr5900el-* \
+	| mipstx39-* | mipstx39el-* \
+	| mmix-* \
+	| mt-* \
+	| msp430-* \
+	| nds32-* | nds32le-* | nds32be-* \
+	| nios-* | nios2-* | nios2eb-* | nios2el-* \
+	| none-* | np1-* | ns16k-* | ns32k-* \
+	| open8-* \
+	| or1k*-* \
+	| orion-* \
+	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
+	| pru-* \
+	| pyramid-* \
+	| riscv32-* | riscv64-* \
+	| rl78-* | romp-* | rs6000-* | rx-* \
+	| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+	| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+	| sparclite-* \
+	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \
+	| tahoe-* \
+	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+	| tile*-* \
+	| tron-* \
+	| ubicom32-* \
+	| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
+	| vax-* \
+	| visium-* \
+	| wasm32-* \
+	| we32k-* \
+	| x86-* | x86_64-* | xc16x-* | xps100-* \
+	| xstormy16-* | xtensa*-* \
+	| ymp-* \
+	| z8k-* | z80-*)
+		;;
+	# Recognize the basic CPU types without company name, with glob match.
+	xtensa*)
+		basic_machine=$basic_machine-unknown
 		;;
 	# Recognize the various machine names and aliases which stand
 	# for a CPU type and a company and sometimes even an OS.
@@ -226,6 +470,9 @@ case $basic_machine in
 		basic_machine=a29k-amd
 		os=-udi
 		;;
+	abacus)
+		basic_machine=abacus-unknown
+		;;
 	adobe68k)
 		basic_machine=m68010-adobe
 		os=-scout
@@ -240,19 +487,25 @@ case $basic_machine in
 		basic_machine=a29k-none
 		os=-bsd
 		;;
+	amd64)
+		basic_machine=x86_64-pc
+		;;
+	amd64-*)
+		basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
 	amdahl)
 		basic_machine=580-amdahl
 		os=-sysv
 		;;
 	amiga | amiga-*)
-		basic_machine=m68k-cbm
+		basic_machine=m68k-unknown
 		;;
 	amigaos | amigados)
-		basic_machine=m68k-cbm
+		basic_machine=m68k-unknown
 		os=-amigaos
 		;;
 	amigaunix | amix)
-		basic_machine=m68k-cbm
+		basic_machine=m68k-unknown
 		os=-sysv4
 		;;
 	apollo68)
@@ -263,6 +516,13 @@ case $basic_machine in
 		basic_machine=m68k-apollo
 		os=-bsd
 		;;
+	aros)
+		basic_machine=i386-pc
+		os=-aros
+		;;
+	asmjs)
+		basic_machine=asmjs-unknown
+		;;
 	aux)
 		basic_machine=m68k-apple
 		os=-aux
@@ -271,6 +531,35 @@ case $basic_machine in
 		basic_machine=ns32k-sequent
 		os=-dynix
 		;;
+	blackfin)
+		basic_machine=bfin-unknown
+		os=-linux
+		;;
+	blackfin-*)
+		basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	bluegene*)
+		basic_machine=powerpc-ibm
+		os=-cnk
+		;;
+	c54x-*)
+		basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	c55x-*)
+		basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	c6x-*)
+		basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	c90)
+		basic_machine=c90-cray
+		os=-unicos
+		;;
+	cegcc)
+		basic_machine=arm-unknown
+		os=-cegcc
+		;;
 	convex-c1)
 		basic_machine=c1-convex
 		os=-bsd
@@ -291,27 +580,45 @@ case $basic_machine in
 		basic_machine=c38-convex
 		os=-bsd
 		;;
-	cray | ymp)
-		basic_machine=ymp-cray
+	cray | j90)
+		basic_machine=j90-cray
 		os=-unicos
 		;;
-	cray2)
-		basic_machine=cray2-cray
-		os=-unicos
+	craynv)
+		basic_machine=craynv-cray
+		os=-unicosmp
 		;;
-	[ctj]90-cray)
-		basic_machine=c90-cray
-		os=-unicos
+	cr16 | cr16-*)
+		basic_machine=cr16-unknown
+		os=-elf
 		;;
 	crds | unos)
 		basic_machine=m68k-crds
 		;;
+	crisv32 | crisv32-* | etraxfs*)
+		basic_machine=crisv32-axis
+		;;
+	cris | cris-* | etrax*)
+		basic_machine=cris-axis
+		;;
+	crx)
+		basic_machine=crx-unknown
+		os=-elf
+		;;
 	da30 | da30-*)
 		basic_machine=m68k-da30
 		;;
 	decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
 		basic_machine=mips-dec
 		;;
+	decsystem10* | dec10*)
+		basic_machine=pdp10-dec
+		os=-tops10
+		;;
+	decsystem20* | dec20*)
+		basic_machine=pdp10-dec
+		os=-tops20
+		;;
 	delta | 3300 | motorola-3300 | motorola-delta \
 	      | 3300-motorola | delta-motorola)
 		basic_machine=m68k-motorola
@@ -320,14 +627,30 @@ case $basic_machine in
 		basic_machine=m88k-motorola
 		os=-sysv3
 		;;
+	dicos)
+		basic_machine=i686-pc
+		os=-dicos
+		;;
+	djgpp)
+		basic_machine=i586-pc
+		os=-msdosdjgpp
+		;;
 	dpx20 | dpx20-*)
 		basic_machine=rs6000-bull
 		os=-bosx
 		;;
-	dpx2* | dpx2*-bull)
+	dpx2*)
 		basic_machine=m68k-bull
 		os=-sysv3
 		;;
+	e500v[12])
+		basic_machine=powerpc-unknown
+		os=$os"spe"
+		;;
+	e500v[12]-*)
+		basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=$os"spe"
+		;;
 	ebmon29k)
 		basic_machine=a29k-amd
 		os=-ebmon
@@ -353,6 +676,10 @@ case $basic_machine in
 		basic_machine=tron-gmicro
 		os=-sysv
 		;;
+	go32)
+		basic_machine=i386-pc
+		os=-go32
+		;;
 	h3050r* | hiux*)
 		basic_machine=hppa1.1-hitachi
 		os=-hiuxwe2
@@ -426,22 +753,20 @@ case $basic_machine in
 		;;
 	i370-ibm* | ibm*)
 		basic_machine=i370-ibm
-		os=-mvs
 		;;
-# I'm not sure what "Sysv32" means.  Should this be sysv3.2?
-	i[34567]86v32)
+	i*86v32)
 		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
 		os=-sysv32
 		;;
-	i[34567]86v4*)
+	i*86v4*)
 		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
 		os=-sysv4
 		;;
-	i[34567]86v)
+	i*86v)
 		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
 		os=-sysv
 		;;
-	i[34567]86sol2)
+	i*86sol2)
 		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
 		os=-solaris2
 		;;
@@ -453,14 +778,6 @@ case $basic_machine in
 		basic_machine=i386-unknown
 		os=-vsta
 		;;
-	i386-go32 | go32)
-		basic_machine=i386-unknown
-		os=-go32
-		;;
-	i386-mingw32 | mingw32)
-		basic_machine=i386-unknown
-		os=-mingw32
-		;;
 	iris | iris4d)
 		basic_machine=mips-sgi
 		case $os in
@@ -475,6 +792,17 @@ case $basic_machine in
 		basic_machine=m68k-isi
 		os=-sysv
 		;;
+	leon-*|leon[3-9]-*)
+		basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'`
+		;;
+	m68knommu)
+		basic_machine=m68k-unknown
+		os=-linux
+		;;
+	m68knommu-*)
+		basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
 	m88k-omron*)
 		basic_machine=m88k-omron
 		;;
@@ -486,21 +814,28 @@ case $basic_machine in
 		basic_machine=ns32k-utek
 		os=-sysv
 		;;
+	microblaze*)
+		basic_machine=microblaze-xilinx
+		;;
+	mingw64)
+		basic_machine=x86_64-pc
+		os=-mingw64
+		;;
+	mingw32)
+		basic_machine=i686-pc
+		os=-mingw32
+		;;
+	mingw32ce)
+		basic_machine=arm-unknown
+		os=-mingw32ce
+		;;
 	miniframe)
 		basic_machine=m68000-convergent
 		;;
-	*mint | *MiNT)
+	*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
 		basic_machine=m68k-atari
 		os=-mint
 		;;
-	mipsel*-linux*)
-		basic_machine=mipsel-unknown
-		os=-linux-gnu
-		;;
-	mips*-linux*)
-		basic_machine=mips-unknown
-		os=-linux-gnu
-		;;
 	mips3*-*)
 		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
 		;;
@@ -511,10 +846,33 @@ case $basic_machine in
 		basic_machine=m68k-rom68k
 		os=-coff
 		;;
+	morphos)
+		basic_machine=powerpc-unknown
+		os=-morphos
+		;;
+	moxiebox)
+		basic_machine=moxie-unknown
+		os=-moxiebox
+		;;
 	msdos)
-		basic_machine=i386-unknown
+		basic_machine=i386-pc
 		os=-msdos
 		;;
+	ms1-*)
+		basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+		;;
+	msys)
+		basic_machine=i686-pc
+		os=-msys
+		;;
+	mvs)
+		basic_machine=i370-ibm
+		os=-mvs
+		;;
+	nacl)
+		basic_machine=le32-unknown
+		os=-nacl
+		;;
 	ncr3000)
 		basic_machine=i486-ncr
 		os=-sysv4
@@ -524,7 +882,7 @@ case $basic_machine in
 		os=-netbsd
 		;;
 	netwinder)
-		basic_machine=armv4l-corel
+		basic_machine=armv4l-rebel
 		os=-linux
 		;;
 	news | news700 | news800 | news900)
@@ -543,7 +901,7 @@ case $basic_machine in
 		basic_machine=v70-nec
 		os=-sysv
 		;;
-	next | m*-next )
+	next | m*-next)
 		basic_machine=m68k-next
 		case $os in
 		    -nextstep* )
@@ -572,13 +930,36 @@ case $basic_machine in
 		basic_machine=i960-intel
 		os=-mon960
 		;;
+	nonstopux)
+		basic_machine=mips-compaq
+		os=-nonstopux
+		;;
 	np1)
 		basic_machine=np1-gould
 		;;
+	neo-tandem)
+		basic_machine=neo-tandem
+		;;
+	nse-tandem)
+		basic_machine=nse-tandem
+		;;
+	nsr-tandem)
+		basic_machine=nsr-tandem
+		;;
+	nsx-tandem)
+		basic_machine=nsx-tandem
+		;;
 	op50n-* | op60c-*)
 		basic_machine=hppa1.1-oki
 		os=-proelf
 		;;
+	openrisc | openrisc-*)
+		basic_machine=or32-unknown
+		;;
+	os400)
+		basic_machine=powerpc-ibm
+		os=-os400
+		;;
 	OSE68000 | ose68000)
 		basic_machine=m68000-ericsson
 		os=-ose
@@ -595,51 +976,94 @@ case $basic_machine in
 		basic_machine=i860-intel
 		os=-osf
 		;;
+	parisc)
+		basic_machine=hppa-unknown
+		os=-linux
+		;;
+	parisc-*)
+		basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
 	pbd)
 		basic_machine=sparc-tti
 		;;
 	pbb)
 		basic_machine=m68k-tti
 		;;
-        pc532 | pc532-*)
+	pc532 | pc532-*)
 		basic_machine=ns32k-pc532
 		;;
-	pentium | p5 | k5 | k6 | nexen)
+	pc98)
+		basic_machine=i386-pc
+		;;
+	pc98-*)
+		basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentium | p5 | k5 | k6 | nexgen | viac3)
 		basic_machine=i586-pc
 		;;
-	pentiumpro | p6 | 6x86)
+	pentiumpro | p6 | 6x86 | athlon | athlon_*)
+		basic_machine=i686-pc
+		;;
+	pentiumii | pentium2 | pentiumiii | pentium3)
 		basic_machine=i686-pc
 		;;
-	pentiumii | pentium2)
+	pentium4)
 		basic_machine=i786-pc
 		;;
-	pentium-* | p5-* | k5-* | k6-* | nexen-*)
+	pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
 		basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
 		;;
-	pentiumpro-* | p6-* | 6x86-*)
+	pentiumpro-* | p6-* | 6x86-* | athlon-*)
 		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
 		;;
-	pentiumii-* | pentium2-*)
+	pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentium4-*)
 		basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
 		;;
 	pn)
 		basic_machine=pn-gould
 		;;
-	power)	basic_machine=rs6000-ibm
+	power)	basic_machine=power-ibm
 		;;
-	ppc)	basic_machine=powerpc-unknown
-	        ;;
-	ppc-*)	basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+	ppc | ppcbe)	basic_machine=powerpc-unknown
 		;;
-	ppcle | powerpclittle | ppc-le | powerpc-little)
+	ppc-* | ppcbe-*)
+		basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppcle | powerpclittle)
 		basic_machine=powerpcle-unknown
-	        ;;
+		;;
 	ppcle-* | powerpclittle-*)
 		basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
 		;;
+	ppc64)	basic_machine=powerpc64-unknown
+		;;
+	ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppc64le | powerpc64little)
+		basic_machine=powerpc64le-unknown
+		;;
+	ppc64le-* | powerpc64little-*)
+		basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
 	ps2)
 		basic_machine=i386-ibm
 		;;
+	pw32)
+		basic_machine=i586-unknown
+		os=-pw32
+		;;
+	rdos | rdos64)
+		basic_machine=x86_64-pc
+		os=-rdos
+		;;
+	rdos32)
+		basic_machine=i386-pc
+		os=-rdos
+		;;
 	rom68k)
 		basic_machine=m68k-rom68k
 		os=-coff
@@ -650,10 +1074,30 @@ case $basic_machine in
 	rtpc | rtpc-*)
 		basic_machine=romp-ibm
 		;;
+	s390 | s390-*)
+		basic_machine=s390-ibm
+		;;
+	s390x | s390x-*)
+		basic_machine=s390x-ibm
+		;;
 	sa29200)
 		basic_machine=a29k-amd
 		os=-udi
 		;;
+	sb1)
+		basic_machine=mipsisa64sb1-unknown
+		;;
+	sb1el)
+		basic_machine=mipsisa64sb1el-unknown
+		;;
+	sde)
+		basic_machine=mipsisa32-sde
+		os=-elf
+		;;
+	sei)
+		basic_machine=mips-sei
+		os=-seiux
+		;;
 	sequent)
 		basic_machine=i386-sequent
 		;;
@@ -661,7 +1105,13 @@ case $basic_machine in
 		basic_machine=sh-hitachi
 		os=-hms
 		;;
-	sparclite-wrs)
+	sh5el)
+		basic_machine=sh5le-unknown
+		;;
+	sh64)
+		basic_machine=sh64-unknown
+		;;
+	sparclite-wrs | simso-wrs)
 		basic_machine=sparclite-wrs
 		os=-vxworks
 		;;
@@ -679,6 +1129,9 @@ case $basic_machine in
 		basic_machine=i860-stratus
 		os=-sysv4
 		;;
+	strongarm-* | thumb-*)
+		basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
 	sun2)
 		basic_machine=m68000-sun
 		;;
@@ -719,23 +1172,43 @@ case $basic_machine in
 	sun386 | sun386i | roadrunner)
 		basic_machine=i386-sun
 		;;
+	sv1)
+		basic_machine=sv1-cray
+		os=-unicos
+		;;
 	symmetry)
 		basic_machine=i386-sequent
 		os=-dynix
 		;;
 	t3e)
-		basic_machine=t3e-cray
+		basic_machine=alphaev5-cray
+		os=-unicos
+		;;
+	t90)
+		basic_machine=t90-cray
 		os=-unicos
 		;;
+	tile*)
+		basic_machine=$basic_machine-unknown
+		os=-linux-gnu
+		;;
 	tx39)
 		basic_machine=mipstx39-unknown
 		;;
 	tx39el)
 		basic_machine=mipstx39el-unknown
 		;;
+	toad1)
+		basic_machine=pdp10-xkl
+		os=-tops20
+		;;
 	tower | tower-32)
 		basic_machine=m68k-ncr
 		;;
+	tpf)
+		basic_machine=s390x-ibm
+		os=-tpf
+		;;
 	udi29k)
 		basic_machine=a29k-amd
 		os=-udi
@@ -757,8 +1230,8 @@ case $basic_machine in
 		os=-vms
 		;;
 	vpp*|vx|vx-*)
-               basic_machine=f301-fujitsu
-               ;;
+		basic_machine=f301-fujitsu
+		;;
 	vxworks960)
 		basic_machine=i960-wrs
 		os=-vxworks
@@ -771,6 +1244,9 @@ case $basic_machine in
 		basic_machine=a29k-wrs
 		os=-vxworks
 		;;
+	wasm32)
+		basic_machine=wasm32-unknown
+		;;
 	w65*)
 		basic_machine=w65-wdc
 		os=-none
@@ -779,17 +1255,31 @@ case $basic_machine in
 		basic_machine=hppa1.1-winbond
 		os=-proelf
 		;;
-	xmp)
-		basic_machine=xmp-cray
-		os=-unicos
+	x64)
+		basic_machine=x86_64-pc
+		;;
+	xbox)
+		basic_machine=i686-pc
+		os=-mingw32
 		;;
-        xps | xps100)
+	xps | xps100)
 		basic_machine=xps100-honeywell
 		;;
+	xscale-* | xscalee[bl]-*)
+		basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
+		;;
+	ymp)
+		basic_machine=ymp-cray
+		os=-unicos
+		;;
 	z8k-*-coff)
 		basic_machine=z8k-unknown
 		os=-sim
 		;;
+	z80-*-coff)
+		basic_machine=z80-unknown
+		os=-sim
+		;;
 	none)
 		basic_machine=none-none
 		os=-none
@@ -806,32 +1296,35 @@ case $basic_machine in
 	op60c)
 		basic_machine=hppa1.1-oki
 		;;
-	mips)
-		if [ x$os = x-linux-gnu ]; then
-			basic_machine=mips-unknown
-		else
-			basic_machine=mips-mips
-		fi
-		;;
 	romp)
 		basic_machine=romp-ibm
 		;;
+	mmix)
+		basic_machine=mmix-knuth
+		;;
 	rs6000)
 		basic_machine=rs6000-ibm
 		;;
 	vax)
 		basic_machine=vax-dec
 		;;
+	pdp10)
+		# there are many clones, so DEC is not a safe bet
+		basic_machine=pdp10-unknown
+		;;
 	pdp11)
 		basic_machine=pdp11-dec
 		;;
 	we32k)
 		basic_machine=we32k-att
 		;;
-	sparc | sparcv9)
+	sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
+		basic_machine=sh-unknown
+		;;
+	sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
 		basic_machine=sparc-sun
 		;;
-        cydra)
+	cydra)
 		basic_machine=cydra-cydrome
 		;;
 	orion)
@@ -846,9 +1339,8 @@ case $basic_machine in
 	pmac | pmac-mpw)
 		basic_machine=powerpc-apple
 		;;
-	c4x*)
-		basic_machine=c4x-none
-		os=-coff
+	*-unknown)
+		# Make sure to match an already-canonicalized machine name.
 		;;
 	*)
 		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
@@ -873,9 +1365,12 @@ esac
 if [ x"$os" != x"" ]
 then
 case $os in
-        # First match some system type aliases
-        # that might get confused with valid system types.
+	# First match some system type aliases that might get confused
+	# with valid system types.
 	# -solaris* is a basic system type, with this one exception.
+	-auroraux)
+		os=-auroraux
+		;;
 	-solaris1 | -solaris1.*)
 		os=`echo $os | sed -e 's|solaris1|sunos4|'`
 		;;
@@ -891,35 +1386,63 @@ case $os in
 	-gnu/linux*)
 		os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
 		;;
-	-os2_emx)
-		;;
-	# First accept the basic system types.
+	# Now accept the basic system types.
 	# The portable systems comes first.
-	# Each alternative MUST END IN A *, to match a version number.
+	# Each alternative MUST end in a * to match a version number.
 	# -sysv* is not here because it comes later, after sysvr4.
 	-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
-	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
-	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
+	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
+	      | -sym* | -kopensolaris* | -plan9* \
 	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
-	      | -aos* \
+	      | -aos* | -aros* | -cloudabi* | -sortix* \
 	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
 	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
-	      | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
-	      | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+	      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+	      | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \
+	      | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+	      | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
 	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
 	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
-	      | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
-	      | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
-	      | -interix* | -uwin* | -rhapsody* | -openstep* | -oskit*)
+	      | -chorusos* | -chorusrdb* | -cegcc* | -glidix* \
+	      | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+	      | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
+	      | -linux-newlib* | -linux-musl* | -linux-uclibc* \
+	      | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
+	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \
+	      | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox* | -bme*)
 	# Remember, each alternative MUST END IN *, to match a version number.
 		;;
+	-qnx*)
+		case $basic_machine in
+		    x86-* | i*86-*)
+			;;
+		    *)
+			os=-nto$os
+			;;
+		esac
+		;;
+	-nto-qnx*)
+		;;
+	-nto*)
+		os=`echo $os | sed -e 's|nto|nto-qnx|'`
+		;;
 	-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
-	      | -windows* | -osx | -abug | -netware* | -os9* | -beos* \
-	      | -macos* | -mpw* | -magic* | -mon960* | -lnews*)
+	      | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+	      | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
 		;;
 	-mac*)
 		os=`echo $os | sed -e 's|mac|macos|'`
 		;;
+	-linux-dietlibc)
+		os=-linux-dietlibc
+		;;
 	-linux*)
 		os=`echo $os | sed -e 's|linux|linux-gnu|'`
 		;;
@@ -929,6 +1452,15 @@ case $os in
 	-sunos6*)
 		os=`echo $os | sed -e 's|sunos6|solaris3|'`
 		;;
+	-opened*)
+		os=-openedition
+		;;
+	-os400*)
+		os=-os400
+		;;
+	-wince*)
+		os=-wince
+		;;
 	-osfrose*)
 		os=-osfrose
 		;;
@@ -944,14 +1476,26 @@ case $os in
 	-acis*)
 		os=-aos
 		;;
+	-atheos*)
+		os=-atheos
+		;;
+	-syllable*)
+		os=-syllable
+		;;
 	-386bsd)
 		os=-bsd
 		;;
 	-ctix* | -uts*)
 		os=-sysv
 		;;
-	-ns2 )
-	        os=-nextstep2
+	-nova*)
+		os=-rtmk-nova
+		;;
+	-ns2)
+		os=-nextstep2
+		;;
+	-nsk*)
+		os=-nsk
 		;;
 	# Preserve the version number of sinix5.
 	-sinix5.*)
@@ -960,6 +1504,9 @@ case $os in
 	-sinix*)
 		os=-sysv4
 		;;
+	-tpf*)
+		os=-tpf
+		;;
 	-triton*)
 		os=-sysv3
 		;;
@@ -987,8 +1534,34 @@ case $os in
 	-xenix)
 		os=-xenix
 		;;
-        -*mint | -*MiNT)
-	        os=-mint
+	-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+		os=-mint
+		;;
+	-aros*)
+		os=-aros
+		;;
+	-zvmoe)
+		os=-zvmoe
+		;;
+	-dicos*)
+		os=-dicos
+		;;
+	-pikeos*)
+		# Until real need of OS specific support for
+		# particular features comes up, bare metal
+		# configurations are quite functional.
+		case $basic_machine in
+		    arm*)
+			os=-eabi
+			;;
+		    *)
+			os=-elf
+			;;
+		esac
+		;;
+	-nacl*)
+		;;
+	-ios)
 		;;
 	-none)
 		;;
@@ -1012,16 +1585,44 @@ else
 # system, and we'll never get to this point.
 
 case $basic_machine in
+	score-*)
+		os=-elf
+		;;
+	spu-*)
+		os=-elf
+		;;
 	*-acorn)
 		os=-riscix1.2
 		;;
-	arm*-corel)
+	arm*-rebel)
 		os=-linux
 		;;
 	arm*-semi)
 		os=-aout
 		;;
-        pdp11-*)
+	c4x-* | tic4x-*)
+		os=-coff
+		;;
+	c8051-*)
+		os=-elf
+		;;
+	hexagon-*)
+		os=-elf
+		;;
+	tic54x-*)
+		os=-coff
+		;;
+	tic55x-*)
+		os=-coff
+		;;
+	tic6x-*)
+		os=-coff
+		;;
+	# This must come before the *-dec entry.
+	pdp10-*)
+		os=-tops20
+		;;
+	pdp11-*)
 		os=-none
 		;;
 	*-dec | vax-*)
@@ -1035,31 +1636,43 @@ case $basic_machine in
 		;;
 	m68000-sun)
 		os=-sunos3
-		# This also exists in the configure program, but was not the
-		# default.
-		# os=-sunos4
 		;;
 	m68*-cisco)
 		os=-aout
 		;;
+	mep-*)
+		os=-elf
+		;;
 	mips*-cisco)
 		os=-elf
 		;;
 	mips*-*)
 		os=-elf
 		;;
+	or32-*)
+		os=-coff
+		;;
 	*-tti)	# must be before sparc entry or we get the wrong os.
 		os=-sysv3
 		;;
 	sparc-* | *-sun)
 		os=-sunos4.1.1
 		;;
+	pru-*)
+		os=-elf
+		;;
 	*-be)
 		os=-beos
 		;;
+	*-haiku)
+		os=-haiku
+		;;
 	*-ibm)
 		os=-aix
 		;;
+	*-knuth)
+		os=-mmixware
+		;;
 	*-wec)
 		os=-proelf
 		;;
@@ -1093,7 +1706,7 @@ case $basic_machine in
 	m88k-omron*)
 		os=-luna
 		;;
-	*-next )
+	*-next)
 		os=-nextstep
 		;;
 	*-sequent)
@@ -1111,25 +1724,25 @@ case $basic_machine in
 	*-next)
 		os=-nextstep3
 		;;
-        *-gould)
+	*-gould)
 		os=-sysv
 		;;
-        *-highlevel)
+	*-highlevel)
 		os=-bsd
 		;;
 	*-encore)
 		os=-bsd
 		;;
-        *-sgi)
+	*-sgi)
 		os=-irix
 		;;
-        *-siemens)
+	*-siemens)
 		os=-sysv4
 		;;
 	*-masscomp)
 		os=-rtu
 		;;
-	f301-fujitsu)
+	f30[01]-fujitsu | f700-fujitsu)
 		os=-uxpv
 		;;
 	*-rom68k)
@@ -1162,7 +1775,7 @@ case $basic_machine in
 			-sunos*)
 				vendor=sun
 				;;
-			-aix*)
+			-cnk*|-aix*)
 				vendor=ibm
 				;;
 			-beos*)
@@ -1189,13 +1802,19 @@ case $basic_machine in
 			-genix*)
 				vendor=ns
 				;;
-			-mvs*)
+			-mvs* | -opened*)
+				vendor=ibm
+				;;
+			-os400*)
 				vendor=ibm
 				;;
 			-ptx*)
 				vendor=sequent
 				;;
-			-vxsim* | -vxworks*)
+			-tpf*)
+				vendor=ibm
+				;;
+			-vxsim* | -vxworks* | -windiss*)
 				vendor=wrs
 				;;
 			-aux*)
@@ -1207,12 +1826,23 @@ case $basic_machine in
 			-mpw* | -macos*)
 				vendor=apple
 				;;
-			-*mint | -*MiNT)
+			-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
 				vendor=atari
 				;;
+			-vos*)
+				vendor=stratus
+				;;
 		esac
 		basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
 		;;
 esac
 
 echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-functions 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/build/crypto.m4 b/build/crypto.m4
new file mode 100644
index 00000000000..e972494d719
--- /dev/null
+++ b/build/crypto.m4
@@ -0,0 +1,290 @@
+dnl -------------------------------------------------------- -*- autoconf -*-
+dnl Copyright 2006 The Apache Software Foundation or its licensors, as
+dnl applicable.
+dnl
+dnl Licensed under the Apache License, Version 2.0 (the "License");
+dnl you may not use this file except in compliance with the License.
+dnl You may obtain a copy of the License at
+dnl
+dnl     http://www.apache.org/licenses/LICENSE-2.0
+dnl
+dnl Unless required by applicable law or agreed to in writing, software
+dnl distributed under the License is distributed on an "AS IS" BASIS,
+dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+dnl See the License for the specific language governing permissions and
+dnl limitations under the License.
+
+dnl
+dnl Crypto module
+dnl
+
+dnl
+dnl APU_CHECK_CRYPTO: look for crypto libraries and headers
+dnl
+AC_DEFUN([APU_CHECK_CRYPTO], [
+  apu_have_crypto=0
+  apu_have_openssl=0
+  apu_have_nss=0
+  apu_have_commoncrypto=0
+
+  old_libs="$LIBS"
+  old_cppflags="$CPPFLAGS"
+  old_ldflags="$LDFLAGS"
+
+  AC_ARG_WITH([crypto], [APR_HELP_STRING([--with-crypto], [enable crypto support])],
+  [
+    cryptolibs="openssl nss commoncrypto"
+
+    if test "$withval" = "yes"; then
+
+      crypto_library_enabled=0
+      for cryptolib in $cryptolibs; do
+        eval v=\$with_$cryptolib
+        if test "$v" != "" -a "$v" != "no"; then
+          crypto_library_enabled=1
+        fi
+      done
+
+      if test "$crypto_library_enabled" = "0"; then
+        for cryptolib in $cryptolibs; do
+          eval v=\$with_$cryptolib
+          if test "$v" != "no"; then
+            eval with_$cryptolib=yes
+            crypto_library_enabled=1
+          fi
+        done
+	if test "$crypto_library_enabled" = "1"; then
+          AC_MSG_NOTICE([Crypto was requested but no crypto library was found; autodetecting possible libraries])
+        else
+          AC_ERROR([Crypto was requested but all possible crypto libraries were disabled.])
+	fi
+      fi
+
+      APU_CHECK_CRYPTO_OPENSSL
+      APU_CHECK_CRYPTO_NSS
+      APU_CHECK_CRYPTO_COMMONCRYPTO
+      dnl add checks for other varieties of ssl here
+      if test "$apu_have_crypto" = "0"; then
+        AC_ERROR([Crypto was requested but no crypto library could be enabled; specify the location of a crypto library using --with-openssl, --with-nss, and/or --with-commoncrypto.])
+      fi
+    fi
+  ], [
+      apu_have_crypto=0
+  ])
+
+  AC_SUBST(apu_have_crypto)
+
+])
+dnl
+
+AC_DEFUN([APU_CHECK_CRYPTO_OPENSSL], [
+  openssl_have_headers=0
+  openssl_have_libs=0
+
+  old_libs="$LIBS"
+  old_cppflags="$CPPFLAGS"
+  old_ldflags="$LDFLAGS"
+
+  AC_ARG_WITH([openssl], 
+  [APR_HELP_STRING([--with-openssl=DIR], [specify location of OpenSSL])],
+  [
+    if test "$withval" = "yes"; then
+      AC_CHECK_HEADERS(openssl/x509.h, [openssl_have_headers=1])
+      AC_CHECK_LIB(crypto, EVP_CIPHER_CTX_new, AC_CHECK_LIB(ssl, SSL_accept, [openssl_have_libs=1],,-lcrypto))
+      if test "$openssl_have_headers" != "0" && test "$openssl_have_libs" != "0"; then
+        apu_have_openssl=1
+      fi
+    elif test "$withval" = "no"; then
+      apu_have_openssl=0
+    else
+
+      openssl_CPPFLAGS="-I$withval/include"
+      openssl_LDFLAGS="-L$withval/lib "
+
+      APR_ADDTO(CPPFLAGS, [$openssl_CPPFLAGS])
+      APR_ADDTO(LDFLAGS, [$openssl_LDFLAGS])
+
+      AC_MSG_NOTICE(checking for openssl in $withval)
+      AC_CHECK_HEADERS(openssl/x509.h, [openssl_have_headers=1])
+      AC_CHECK_LIB(crypto, EVP_CIPHER_CTX_new, AC_CHECK_LIB(ssl, SSL_accept, [openssl_have_libs=1],,-lcrypto))
+      if test "$openssl_have_headers" != "0" && test "$openssl_have_libs" != "0"; then
+        apu_have_openssl=1
+        APR_ADDTO(LDFLAGS, [-L$withval/lib])
+        APR_ADDTO(INCLUDES, [-I$withval/include])
+      fi
+
+      AC_CHECK_DECLS([EVP_PKEY_CTX_new], [], [],
+                     [#include <openssl/evp.h>])
+
+    fi
+  ], [
+    apu_have_openssl=0
+  ])
+
+  AC_SUBST(apu_have_openssl)
+
+  dnl Since we have already done the AC_CHECK_LIB tests, if we have it, 
+  dnl we know the library is there.
+  if test "$apu_have_openssl" = "1"; then
+    APR_ADDTO(LDADD_crypto_openssl, [$openssl_LDFLAGS -lssl -lcrypto])
+    apu_have_crypto=1
+
+    AC_MSG_CHECKING([for const input buffers in OpenSSL])
+    AC_TRY_COMPILE([#include <openssl/rsa.h>],
+        [ const unsigned char * buf;
+          unsigned char * outbuf;
+          RSA rsa;
+
+                RSA_private_decrypt(1,
+                                                        buf,
+                                                        outbuf,
+                                                        &rsa,
+                                                        RSA_PKCS1_PADDING);
+
+        ],
+        [AC_MSG_RESULT([yes])]
+        [AC_DEFINE([CRYPTO_OPENSSL_CONST_BUFFERS], 1, [Define that OpenSSL uses const buffers])],
+        [AC_MSG_RESULT([no])])
+
+  fi  
+  AC_SUBST(LDADD_crypto_openssl)
+  AC_SUBST(apu_have_crypto)
+
+  LIBS="$old_libs"
+  CPPFLAGS="$old_cppflags"
+  LDFLAGS="$old_ldflags"
+])
+
+AC_DEFUN([APU_CHECK_CRYPTO_NSS], [
+  nss_have_libs=0
+
+  old_libs="$LIBS"
+  old_cppflags="$CPPFLAGS"
+  old_ldflags="$LDFLAGS"
+
+  AC_ARG_WITH([nss], 
+  [APR_HELP_STRING([--with-nss=DIR], [specify location of NSS])],
+  [
+    if test "$withval" = "yes"; then
+      AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
+      if test -n "$PKG_CONFIG"; then
+        nss_CPPFLAGS=`$PKG_CONFIG --cflags-only-I nss`
+        nss_LDFLAGS=`$PKG_CONFIG --libs nss`
+        APR_ADDTO(CPPFLAGS, [$nss_CPPFLAGS])
+        APR_ADDTO(LDFLAGS, [$nss_LDFLAGS])
+      fi
+      nss_have_prerrorh=0
+      nss_have_nssh=0
+      nss_have_pk11pubh=0
+      AC_CHECK_HEADERS(prerror.h, [nss_have_prerrorh=1])
+      AC_CHECK_HEADERS(nss/nss.h nss.h, [nss_have_nssh=1])
+      AC_CHECK_HEADERS(nss/pk11pub.h pk11pub.h, [nss_have_pk11pubh=1])
+      nss_have_headers=${nss_have_prerrorh}${nss_have_nssh}${nss_have_pk11pubh}
+      AC_CHECK_LIB(nspr4, PR_Initialize, AC_CHECK_LIB(nss3, PK11_CreatePBEV2AlgorithmID, [nss_have_libs=1],,-lnspr4))
+      if test "$nss_have_headers" = "111" && test "$nss_have_libs" != "0"; then
+        apu_have_nss=1
+      fi
+    elif test "$withval" = "no"; then
+      apu_have_nss=0
+    elif test "x$withval" != "x"; then
+
+      nss_CPPFLAGS="-I$withval/include/nss -I$withval/include/nss3 -I$withval/include/nspr -I$withval/include/nspr4 -I$withval/include -I$withval/../public"
+      nss_LDFLAGS="-L$withval/lib "
+
+      APR_ADDTO(CPPFLAGS, [$nss_CPPFLAGS])
+      APR_ADDTO(LDFLAGS, [$nss_LDFLAGS])
+
+      AC_MSG_NOTICE(checking for nss in $withval)
+      nss_have_prerrorh=0
+      nss_have_nssh=0
+      nss_have_pk11pubh=0
+      AC_CHECK_HEADERS(prerror.h, [nss_have_prerrorh=1])
+      AC_CHECK_HEADERS(nss/nss.h nss.h, [nss_have_nssh=1])
+      AC_CHECK_HEADERS(nss/pk11pub.h pk11pub.h, [nss_have_pk11pubh=1])
+      nss_have_headers=${nss_have_prerrorh}${nss_have_nssh}${nss_have_pk11pubh}
+      AC_CHECK_LIB(nspr4, PR_Initialize, AC_CHECK_LIB(nss3, PK11_CreatePBEV2AlgorithmID, [nss_have_libs=1],,-lnspr4))
+      if test "$nss_have_headers" = "111" && test "$nss_have_libs" != "0"; then
+        apu_have_nss=1
+      fi
+
+    fi
+    if test "$apu_have_nss" != "0"; then
+      APR_ADDTO(INCLUDES, [$nss_CPPFLAGS])
+    fi
+  ], [
+    apu_have_nss=0
+  ])
+
+  AC_SUBST(apu_have_nss)
+
+  dnl Since we have already done the AC_CHECK_LIB tests, if we have it, 
+  dnl we know the library is there.
+  if test "$apu_have_nss" = "1"; then
+    APR_ADDTO(LDADD_crypto_nss, [$nss_LDFLAGS -lnspr4 -lnss3])
+    apu_have_crypto=1
+  fi
+  AC_SUBST(LDADD_crypto_nss)
+  AC_SUBST(apu_have_crypto)
+
+  LIBS="$old_libs"
+  CPPFLAGS="$old_cppflags"
+  LDFLAGS="$old_ldflags"
+])
+
+AC_DEFUN([APU_CHECK_CRYPTO_COMMONCRYPTO], [
+  apu_have_commoncrypto=0
+  commoncrypto_have_headers=0
+  commoncrypto_have_libs=0
+
+  old_libs="$LIBS"
+  old_cppflags="$CPPFLAGS"
+  old_ldflags="$LDFLAGS"
+
+  AC_ARG_WITH([commoncrypto], 
+  [APR_HELP_STRING([--with-commoncrypto=DIR], [specify location of CommonCrypto])],
+  [
+    if test "$withval" = "yes"; then
+      AC_CHECK_HEADERS(CommonCrypto/CommonKeyDerivation.h, [commoncrypto_have_headers=1])
+      AC_CHECK_LIB(System, CCKeyDerivationPBKDF, AC_CHECK_LIB(System, CCCryptorCreate, [commoncrypto_have_libs=1],,-lcrypto))
+      if test "$commoncrypto_have_headers" != "0" && test "$commoncrypto_have_libs" != "0"; then
+        apu_have_commoncrypto=1
+      fi
+    elif test "$withval" = "no"; then
+      apu_have_commoncrypto=0
+    else
+
+      commoncrypto_CPPFLAGS="-I$withval/include"
+      commoncrypto_LDFLAGS="-L$withval/lib "
+
+      APR_ADDTO(CPPFLAGS, [$commoncrypto_CPPFLAGS])
+      APR_ADDTO(LDFLAGS, [$commoncrypto_LDFLAGS])
+
+      AC_MSG_NOTICE(checking for commoncrypto in $withval)
+      AC_CHECK_HEADERS(CommonCrypto/CommonKeyDerivation.h, [commoncrypto_have_headers=1])
+      AC_CHECK_LIB(System, CCKeyDerivationPBKDF, AC_CHECK_LIB(System, CCCryptorCreate, [commoncrypto_have_libs=1],,-lcrypto))
+      if test "$commoncrypto_have_headers" != "0" && test "$commoncrypto_have_libs" != "0"; then
+        apu_have_commoncrypto=1
+        APR_ADDTO(LDFLAGS, [-L$withval/lib])
+        APR_ADDTO(INCLUDES, [-I$withval/include])
+      fi
+
+    fi
+  ], [
+    apu_have_commoncrypto=0
+  ])
+
+  dnl Since we have already done the AC_CHECK_LIB tests, if we have it, 
+  dnl we know the library is there.
+  if test "$apu_have_commoncrypto" = "1"; then
+    apu_have_crypto=1
+  fi
+  AC_SUBST(apu_have_commoncrypto)
+  AC_SUBST(LDADD_crypto_commoncrypto)
+  AC_SUBST(apu_have_crypto)
+
+  LIBS="$old_libs"
+  CPPFLAGS="$old_cppflags"
+  LDFLAGS="$old_ldflags"
+])
+
+dnl
diff --git a/build/cvtdsp.pl b/build/cvtdsp.pl
new file mode 100644
index 00000000000..becb75bd5ed
--- /dev/null
+++ b/build/cvtdsp.pl
@@ -0,0 +1,605 @@
+use IO::File;
+use File::Find;
+
+if ($ARGV[0] eq '-6') {
+    find(\&tovc6, '.');
+}
+elsif ($ARGV[0] eq '-5') {
+    find(\&tovc5, '.');
+}
+elsif ($ARGV[0] eq '-2005') {
+    find(\&tovc2005, '.');
+}
+elsif ($ARGV[0] eq '-w3') {
+    find(\&tow3, '.');
+}
+elsif ($ARGV[0] eq '-w4') {
+    find(\&tow4, '.');
+}
+elsif ($ARGV[0] eq '-ia64') {
+    find(\&tovc64, '.');
+}
+elsif ($ARGV[0] eq '-d') {
+    find(\&todebugpools, '.');
+}
+elsif ($ARGV[0] eq '-b') {
+    find(\&tobrowse, '.');
+}
+elsif ($ARGV[0] eq '-mt') {
+    find(\&addmt, '.');
+}
+elsif ($ARGV[0] eq '-m') {
+        ## 0 - conapp, 1 - dll lib, 2 - static lib
+        $dsptype = 2;
+        $name = "apr";
+        onemake();
+}
+else {
+    print "Specify -5 or -6 for Visual Studio 5 or 6 (98) .dsp format\n";
+    print "Specify -w3 or -w4 for .dsp build with warning level 3 or 4 (strict)\n\n";
+    print "Specify -ia64 for build targeted at Itanium (req's psdk tools)\n\n";
+    print "Specify -p for extreme pool debugging\n\n";
+    print "Specify -mt to add .manifest embedding\n\n";
+    die "Missing argument";
+}
+
+sub addmt { 
+    my $outpath, $outtype;
+
+    if (m|\.dsp$|) {
+        $oname = $_;
+        $tname = '.#' . $_;
+        $verchg = 0;
+        $srcfl = new IO::File $oname, "r" || die;
+        $dstfl = new IO::File $tname, "w" || die;
+        while ($src = <$srcfl>) {
+            if ($src =~ m|^# TARGTYPE .+ Application|) {
+                $outtype = ".exe"
+            }
+            if ($src =~ m|^# TARGTYPE .+ Dynamic-Link|) {
+                $outtype = ".dll"
+            }
+            if ($src =~ m|^# PROP Output_Dir "(.+)"|) {
+                $outdir = $1;
+                $outpath = $oname;
+                $outpath =~ s|\.dsp||;
+                $outpath =  ".\\" . $outdir . "\\" . $outpath . $outtype;
+            }
+            if ($src =~ m|^# ADD (BASE )?LINK32 .+ /out:"([^"]+)"|) {
+                $outpath = $2;
+                $outpath =~ s|/|\\|;
+                $outpath = ".\\" . $outpath if (!($outpath =~ m|^\.|));
+                $src =~ s|/out:"([^"]+)"|/out:"$outpath"|;
+            }
+            if (defined($outpath) && ($src =~ m|^# Begin Special Build Tool|)) {
+                undef $outpath;
+            }
+            if (defined($outpath) && defined($outtype) && ($src =~ m|^\s*$|)) {
+                print $dstfl '# Begin Special Build Tool' . "\n";
+                print $dstfl 'TargetPath=' . $outpath . "\n";
+                print $dstfl 'SOURCE="$(InputPath)"' . "\n";
+                print $dstfl 'PostBuild_Desc=Embed .manifest' . "\n";
+                print $dstfl 'PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2' . "\n";
+                print $dstfl '# End Special Build Tool' . "\n";
+                $verchg = -1;
+                undef $outpath;
+            }
+            print $dstfl $src;
+        }
+        undef $outtype if (defined($outtype));
+        undef $outpath if (defined($outpath));
+        undef $srcfl;
+        undef $dstfl;
+        if ($verchg) {
+            unlink $oname || die;
+            rename $tname, $oname || die;
+            print "Added manifest to " . $oname . " in " . $File::Find::dir . "\n"; 
+        }
+        else {
+            unlink $tname;
+        }
+    }
+}
+sub tovc5 { 
+
+    if (m|\.dsp$|) {
+        $oname = $_;
+        $tname = '.#' . $_;
+        $verchg = 0;
+        $srcfl = new IO::File $oname, "r" || die;
+        $dstfl = new IO::File $tname, "w" || die;
+        while ($src = <$srcfl>) {
+            if ($src =~ s|Format Version 6\.00|Format Version 5\.00|) {
+                $verchg = -1;
+            }
+            if ($src =~ s|^(# ADD CPP .*)/ZI (.*)|$1/Zi $2|) {
+                $verchg = -1;
+            }
+            if ($src =~ s|^(# ADD BASE CPP .*)/ZI (.*)|$1/Zi $2|) {
+                $verchg = -1;
+            }
+            if ($src =~ s|^(# ADD CPP .*)/EHsc (.*)|$1/GX $2|) {
+                $verchg = -1;
+            }
+            if ($src =~ s|^(# ADD BASE CPP .*)/EHsc (.*)|$1/GX $2|) {
+                $verchg = -1;
+            }
+            while ($src =~ s|^(# ADD RSC .*)/d "([^ ="]+)=([^"]+)"|$1/d $2="$3"|) {
+                $verchg = -1;
+            }
+            if ($src !~ m|^# PROP AllowPerConfigDependencies|) {
+                print $dstfl $src; }
+            else {
+                $verchg = -1;
+            }
+        }
+        undef $srcfl;
+        undef $dstfl;
+        if ($verchg) {
+            unlink $oname || die;
+            rename $tname, $oname || die;
+            print "Converted VC6 project " . $oname . " to VC5 in " . $File::Find::dir . "\n"; 
+        }
+        else {
+            unlink $tname;
+        }
+    }
+}
+
+sub tovc6 { 
+
+    if (m|\.dsp$|) {
+        $oname = $_;
+        $tname = '.#' . $_;
+        $verchg = 0;
+        $srcfl = new IO::File $_, "r" || die;
+        $dstfl = new IO::File $tname, "w" || die;
+        while ($src = <$srcfl>) {
+            if ($src =~ s|Format Version 5\.00|Format Version 6\.00|) {
+                $verchg = -1;
+            }
+            if ($src =~ s|^(!MESSAGE .*)\\\n|$1|) {
+                $cont = <$srcfl>;
+                $src = $src . $cont;
+                $verchg = -1;
+            }
+            if ($src =~ s|^(# ADD CPP .*)/GX (.*)|$1/EHsc $2|) {
+                $verchg = -1;
+            }
+            if ($src =~ s|^(# ADD BASE CPP .*)/GX (.*)|$1/EHsc $2|) {
+                $verchg = -1;
+            }
+            while ($src =~ s|^(# ADD RSC .*)/d "([^ ="]+)=([^"]+)"|$1/d $2="$3"|) {
+                $verchg = -1;
+            }
+            print $dstfl $src; 
+            if ($verchg && $src =~ m|^# Begin Project|) {
+                print $dstfl "# PROP AllowPerConfigDependencies 0\n"; 
+            }
+        }
+        undef $srcfl;
+        undef $dstfl;
+        if ($verchg) {
+            unlink $oname || die;
+            rename $tname, $oname || die;
+            print "Converted VC5 project " . $oname . " to VC6 in " . $File::Find::dir . "\n"; 
+        }
+        else {
+            unlink $tname;
+        }
+    }
+}
+
+sub tovc2005 { 
+
+    if (m|\.dsp$| || m|\.mak$|) {
+        $oname = $_;
+        $tname = '.#' . $_;
+        $verchg = 0;
+        $srcfl = new IO::File $_, "r" || die;
+        $dstfl = new IO::File $tname, "w" || die;
+        while ($src = <$srcfl>) {
+            if ($src =~ s|(\bCPP.*) /GX(.*)|$1 /EHsc$2|) {
+                $verchg = -1;
+            }
+            if ($src =~ s|(\bLINK32.*) /machine:I386(.*)|$1$2|) {
+                $verchg = -1;
+            }
+            while ($src =~ s|^(# ADD RSC .*)/d ([^ ="]+)="([^"]+)"|$1/d "$2=$3"|) {
+                $verchg = -1;
+            }
+            print $dstfl $src; 
+        }
+        undef $srcfl;
+        undef $dstfl;
+        if ($verchg) {
+            unlink $oname || die;
+            rename $tname, $oname || die;
+            print "Converted project " . $oname . " to 2005 in " . $File::Find::dir . "\n"; 
+        }
+        else {
+            unlink $tname;
+        }
+    }
+}
+
+sub tow3 { 
+
+    if (m|\.dsp$| || m|\.mak$|) {
+        $oname = $_;
+        $tname = '.#' . $_;
+        $verchg = 0;
+        $srcfl = new IO::File $_, "r" || die;
+        $dstfl = new IO::File $tname, "w" || die;
+        while ($src = <$srcfl>) {
+            while ($src =~ m|\\\n$|) {
+                $src = $src . <$srcfl>
+            }
+            if ($src =~ s|(\bCPP.*) /W4(.*)|$1 /W3$2|) {
+                $verchg = -1;
+            }
+            print $dstfl $src; 
+        }
+        undef $srcfl;
+        undef $dstfl;
+        if ($verchg) {
+            unlink $oname || die;
+            rename $tname, $oname || die;
+            print "Converted project " . $oname . " to warn:3 in " . $File::Find::dir . "\n"; 
+        }
+        else {
+            unlink $tname;
+        }
+    }
+}
+
+sub tow4 { 
+
+    if (m|\.dsp$| || m|\.mak$|) {
+        $oname = $_;
+        $tname = '.#' . $_;
+        $verchg = 0;
+        $srcfl = new IO::File $_, "r" || die;
+        $dstfl = new IO::File $tname, "w" || die;
+        while ($src = <$srcfl>) {
+            while ($src =~ m|\\\n$|) {
+                $src = $src . <$srcfl>
+            }
+            if ($src =~ s|(\bCPP.*) /W3(.*)|$1 /W4$2|) {
+                $verchg = -1;
+            }
+            print $dstfl $src; 
+        }
+        undef $srcfl;
+        undef $dstfl;
+        if ($verchg) {
+            unlink $oname || die;
+            rename $tname, $oname || die;
+            print "Converted project " . $oname . " to warn:4 " . $File::Find::dir . "\n"; 
+        }
+        else {
+            unlink $tname;
+        }
+    }
+}
+
+sub tovc64 { 
+
+    if (m|\.dsp$| || m|\.mak$|) {
+        $oname = $_;
+        $tname = '.#' . $_;
+        $verchg = 0;
+        $srcfl = new IO::File $_, "r" || die;
+        $dstfl = new IO::File $tname, "w" || die;
+        while ($src = <$srcfl>) {
+            while ($src =~ m|\\\n$|) {
+                $src = $src . <$srcfl>
+            }
+            if ($src =~ s|Win32 \(x86\) (Release)|Win32 (IA64) $1|s) {
+                $verchg = -1;
+            }
+            if ($src =~ s|Win32 \(x86\) (Debug)|Win32 (IA64) $1|s) {
+                $verchg = -1;
+            }
+            if ($src =~ s| - Win32 (Release)| - Win32 (IA64) $1|s) {
+                $verchg = -1;
+            }
+            if ($src =~ s| - Win32 (Debug)| - Win32 (IA64) $1|s) {
+                $verchg = -1;
+            }
+            # Cross compilation exceptions
+            if (!(m|gen[^/]*$| || m|dftables[^/]*$|)) {
+                if ($src =~ s|(\bCPP.* /W3)(.*) /FD(.*)|$1 /As64 /Wp64$2$3|s) {
+                    $verchg = -1;
+                }
+                if ($src =~ s|(\bLINK.*/machine):I386(.*)|$1:IA64$2|s) {
+                    $verchg = -1;
+                }
+            }
+            else {
+                if ($src =~ s|(\bCPP.* /W3)(.*) /FD(.*)|$1 /As32 /Wp64$2$3|s) {
+                    $verchg = -1;
+                }
+            }
+            print $dstfl $src; 
+        }
+        undef $srcfl;
+        undef $dstfl;
+        if ($verchg) {
+            unlink $oname || die;
+            rename $tname, $oname || die;
+            print "Converted build file " . $oname . " to Win64 in " . $File::Find::dir . "\n"; 
+        }
+        else {
+            unlink $tname;
+        }
+    }
+}
+
+sub todebugpools { 
+
+    if (m|\.dsp$|) {
+        $oname = $_;
+        $tname = '.#' . $_;
+        $verchg = 0;
+        $srcfl = new IO::File $oname, "r" || die;
+        $dstfl = new IO::File $tname, "w" || die;
+        while ($src = <$srcfl>) {
+            if ($src =~ s|^(# ADD CPP .* /D "_DEBUG" )|$1/D "APR_POOL_DEBUG" |) {
+                $verchg = -1;
+                if ($oname =~ /apr\.dsp$/) {
+                    $src =~ s|^(# ADD CPP .* /D "_DEBUG" )|$1/D "POOL_DEBUG" |;
+                }
+            }
+            print $dstfl $src; 
+        }
+        undef $srcfl;
+        undef $dstfl;
+        if ($verchg) {
+            unlink $oname || die;
+            rename $tname, $oname || die;
+            print "Converted project " . $oname . " to debug pools in " . $File::Find::dir . "\n"; 
+        }
+        else {
+            unlink $tname;
+        }
+    }
+}
+
+sub tobrowsesources { 
+
+    if (m|\.dsp$|) {
+        $oname = $_;
+        $tname = '.#' . $_;
+        $verchg = 0;
+        $srcfl = new IO::File $oname, "r" || die;
+        $dstfl = new IO::File $tname, "w" || die;
+        while ($src = <$srcfl>) {
+            if ($src =~ s|^(# ADD CPP .*)( /Fd)|$1 /Fr "/httpd-2.0/srclib/apr"$2|) {
+                $verchg = -1;
+            }
+            print $dstfl $src; 
+        }
+        undef $srcfl;
+        undef $dstfl;
+        if ($verchg) {
+            unlink $oname || die;
+            rename $tname, $oname || die;
+            print "Converted project " . $oname . " to browse sources in " . $File::Find::dir . "\n"; 
+        }
+        else {
+            unlink $tname;
+        }
+    }
+}
+
+sub frommakefiles {
+
+    if (m|\.mak\.in$|) {
+        $oname = $_;
+        $dname = $_;
+        $_ =~ s/\.mak\.in/.dsp/;
+        $verchg = 0;
+        $srcfl = new IO::File $oname, "r" || die;
+        $dstfl = new IO::File $tname, "w" || die;
+        while ($src = <$srcfl>) {
+            if ($src =~ s|^(# ADD CPP .*)( /Fd)|$1 /Fr "/httpd-2.0/srclib/apr"$2|) {
+                $verchg = -1;
+            }
+            print $dstfl $src; 
+        }
+        undef $srcfl;
+        undef $dstfl;
+        if ($verchg) {
+            unlink $oname || die;
+            rename $tname, $oname || die;
+            print "Converted project " . $oname . " to browse sources in " . $File::Find::dir . "\n"; 
+        }
+        else {
+            unlink $tname;
+        }
+    }
+}
+
+
+sub onemake {
+
+    if ($dsptype == 0) {
+        $cdefs = qq{/D "WIN32" /D "_CONSOLE"};
+        $lmodel = qq{/subsystem:console};
+        $targname = "Win32 (x86) Console Application";
+        $targid = "0x0103";
+        $debpath = "Debug"; $relpath = "Release";
+    } elsif ($dsptype == 1) {
+        $cdefs = qq{/D "WIN32" /D "_WINDOWS"};
+        $lmodel = qq{/subsystem:windows /dll};
+        $targname = "Win32 (x86) Dynamic-Link Library";
+        $targid = "0x0102";
+        $debpath = "Debug"; $relpath = "Release";
+    } elsif($dsptype == 2) {
+        $cdefs = qq{/D "WIN32" /D "_CONSOLE"};
+        $lmodel = qq{/subsystem:console};
+        $targname = "Win32 (x86) Static Library";
+        $targid = "0x0104";
+        $debpath = "LibD"; $relpath = "LibR";
+    }
+        $file = dspheader();
+
+
+        $second = "";
+
+        $model = "Release";
+        $usedebuglib = "0";
+        $debugdef = "NDEBUG";
+        $cflags = "/MD /W3 /O2";
+        $cincl = qq{/I "./include" /I "./os/win32" /I "./srclib/apr/include" /I "./srclib/apr-util/include"};
+        $lflags = qq{/map};
+        $file .= dsponemodel();
+
+        $second = "ELSE";
+        $model = "Debug";
+        $usedebuglib = "1";
+        $debugdef = "_DEBUG";
+        $cflags = "/MDd /W3 /GX /Zi /Od";
+        $cincl = qq{/I "./include" /I "./os/win32" /I "./srclib/apr/include" /I "./srclib/apr-util/include"};
+        $lflags = qq{/incremental:no /debug};
+        $file .= dsponemodel();
+
+        $file .= qq{
+!ENDIF 
+
+# Begin Target
+
+# Name "$name - Win32 Release"
+# Name "$name - Win32 Debug"
+};
+
+        $toroot = ".";
+
+#HERE IS OUR FOREACH!
+        $file .= qq{# Begin Source File
+
+SOURCE=./server/main.c
+# End Source File
+};
+
+    if ($dsptype == 0) {
+        #HERE IS OUR ICON!
+        $icon="$toroot/build/win32/apache.ico";
+        $file .= qq{# Begin Source File
+
+SOURCE=$icon
+# End Source File
+};
+        $icon = "icon=" . $icon . " ";
+    }
+    if ($dsptype == 0 || $dsptype == 1) {
+        $file .= qq{
+# Begin Source File
+
+SOURCE=./$name.rc
+# End Source File
+# Begin Source File
+
+SOURCE=$toroot/include/ap_release.h
+# PROP Ignore_Default_Tool 1
+# Begin Custom Build - Creating Version Resource
+InputPath=$toroot/include/ap_release.h $toroot/build/win32/win32ver.awk
+
+"./$name.rc" : \$(SOURCE) "\$(INTDIR)" "\$(OUTDIR)"
+        awk -f $toroot/build/win32/win32ver.awk $name "Apache HTTP Server" $toroot/include/ap_release.h $icon> ./Apache.rc
+
+# End Custom Build
+# End Source File
+};
+    }
+        $file .= qq{
+# End Target
+# End Project
+};
+        print $file;
+}
+
+sub dspheader {
+    if ($dsptype == 1) {
+        $midl = "MTL=midl.exe\n";
+    } else {
+        $midl = ""
+    }
+qq{# Microsoft Developer Studio Project File - Name="$name" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "$targname" $targid
+
+CFG=$name - 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 "$name.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 "$name.mak" CFG="$name - Win32 Release"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "$name - Win32 Release" (based on "$targname")
+!MESSAGE "$name - Win32 Debug" (based on "$targname")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+${midl}RSC=rc.exe
+};
+}
+sub dsponemodel {
+    if ($model eq "Release") {
+        $targpath = $relpath;
+    } else {
+        $targpath = $debpath;
+    }
+    if ($dsptype == 1) {
+        $midl = 
+qq{# ADD BASE MTL /nologo /D "$debugdef" /win32
+# ADD MTL /nologo /D "$debugdef" /mktyplib203 /win32
+};  }
+    if ($dsptype == 2) {
+        $linkop = qq{LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+};
+    } else {
+        $linkop = qq{LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib ws2_32.lib mswsock.lib /nologo $lmodel $lflags /machine:I386
+# ADD LINK32 kernel32.lib user32.lib advapi32.lib ws2_32.lib mswsock.lib /nologo $lmodel $lflags /machine:I386
+};
+    }        
+
+qq{
+!${second}IF  "\$(CFG)" == "$name - Win32 $model"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries $usedebuglib
+# PROP BASE Output_Dir "$targpath"
+# PROP BASE Intermediate_Dir "$targpath"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries $usedebuglib
+# PROP Output_Dir "$targpath"
+# PROP Intermediate_Dir "$targpath"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo $cflags $cincl /D "$debugdef" $cdefs /FD /c
+# ADD CPP /nologo $cflags $cincl /D "$debugdef" $cdefs /Fd"$targpath/$name" /FD /c
+${midl}# ADD BASE RSC /l 0x409 /d "$debugdef"
+# ADD RSC /l 0x409 /d "$debugdef"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+$linkop};
+}
\ No newline at end of file
diff --git a/build/dbd.m4 b/build/dbd.m4
new file mode 100644
index 00000000000..77e3af10ab8
--- /dev/null
+++ b/build/dbd.m4
@@ -0,0 +1,513 @@
+dnl -------------------------------------------------------- -*- autoconf -*-
+dnl Licensed to the Apache Software Foundation (ASF) under one or more
+dnl contributor license agreements.  See the NOTICE file distributed with
+dnl this work for additional information regarding copyright ownership.
+dnl The ASF licenses this file to You under the Apache License, Version 2.0
+dnl (the "License"); you may not use this file except in compliance with
+dnl the License.  You may obtain a copy of the License at
+dnl
+dnl     http://www.apache.org/licenses/LICENSE-2.0
+dnl
+dnl Unless required by applicable law or agreed to in writing, software
+dnl distributed under the License is distributed on an "AS IS" BASIS,
+dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+dnl See the License for the specific language governing permissions and
+dnl limitations under the License.
+
+dnl
+dnl DBD module
+dnl
+
+dnl
+dnl APU_CHECK_DBD: compile backends for apr_dbd.
+dnl
+AC_DEFUN([APU_CHECK_DBD], [
+  apu_have_pgsql=0
+
+  old_libs="$LIBS"
+  old_cppflags="$CPPFLAGS"
+  old_ldflags="$LDFLAGS"
+
+  AC_ARG_WITH([pgsql], APR_HELP_STRING([--with-pgsql=DIR], [specify PostgreSQL location]),
+  [
+    if test "$withval" = "yes"; then
+      AC_PATH_TOOL([PGSQL_CONFIG],[pg_config])
+      if test "x$PGSQL_CONFIG" != 'x'; then
+        pgsql_CPPFLAGS="-I`$PGSQL_CONFIG --includedir`"
+        pgsql_LDFLAGS="-L`$PGSQL_CONFIG --libdir`"
+
+        APR_ADDTO(CPPFLAGS, [$pgsql_CPPFLAGS])
+        APR_ADDTO(LDFLAGS, [$pgsql_LDFLAGS])
+      fi
+
+      AC_CHECK_HEADERS(libpq-fe.h, [
+        AC_CHECK_LIB(pq, PQsendQueryPrepared, [apu_have_pgsql=1],[
+        if test "x$PGSQL_CONFIG" != 'x'; then
+          unset ac_cv_lib_pq_PQsendQueryPrepared
+          pgsql_LIBS="`$PGSQL_CONFIG --libs`"
+          APR_ADDTO(LIBS, [$pgsql_LIBS])
+          AC_CHECK_LIB(pq, PQsendQueryPrepared, [apu_have_pgsql=1])
+        fi
+        ])
+      ])
+      if test "$apu_have_pgsql" = "0"; then
+        AC_CHECK_HEADERS(postgresql/libpq-fe.h, [
+          AC_CHECK_LIB(pq, PQsendQueryPrepared, [apu_have_pgsql=1],[
+          if test "x$PGSQL_CONFIG" != 'x'; then
+            unset ac_cv_lib_pq_PQsendQueryPrepared
+            pgsql_LIBS="`$PGSQL_CONFIG --libs`"
+            APR_ADDTO(LIBS, [$pgsql_LIBS])
+            AC_CHECK_LIB(pq, PQsendQueryPrepared, [apu_have_pgsql=1])
+          fi
+          ])
+        ])
+      fi
+      if test "$apu_have_pgsql" != "0" && test "x$PGSQL_CONFIG" != 'x'; then
+        APR_ADDTO(INCLUDES, [$pgsql_CPPFLAGS])
+      fi
+    elif test "$withval" = "no"; then
+      :
+    else
+      AC_PATH_TOOL([PGSQL_CONFIG],[pg_config],,[$withval/bin])
+      if test "x$PGSQL_CONFIG" != 'x'; then
+        pgsql_CPPFLAGS="-I`$PGSQL_CONFIG --includedir`"
+        pgsql_LDFLAGS="-L`$PGSQL_CONFIG --libdir`"
+      else
+        pgsql_CPPFLAGS="-I$withval/include"
+        pgsql_LDFLAGS="-L$withval/lib "
+      fi
+
+      APR_ADDTO(CPPFLAGS, [$pgsql_CPPFLAGS])
+      APR_ADDTO(LDFLAGS, [$pgsql_LDFLAGS])
+
+      AC_MSG_NOTICE(checking for pgsql in $withval)
+      AC_CHECK_HEADERS(libpq-fe.h, [
+        AC_CHECK_LIB(pq, PQsendQueryPrepared, [apu_have_pgsql=1],[
+        if test "x$PGSQL_CONFIG" != 'x'; then
+          unset ac_cv_lib_pq_PQsendQueryPrepared
+          pgsql_LIBS="`$PGSQL_CONFIG --libs`"
+          APR_ADDTO(LIBS, [$pgsql_LIBS])
+          AC_CHECK_LIB(pq, PQsendQueryPrepared, [apu_have_pgsql=1])
+        fi
+        ])
+      ])
+      if test "$apu_have_pgsql" != "1"; then
+        AC_CHECK_HEADERS(postgresql/libpq-fe.h, [
+          AC_CHECK_LIB(pq, PQsendQueryPrepared, [apu_have_pgsql=1],[
+          if test "x$PGSQL_CONFIG" != 'x'; then
+            unset ac_cv_lib_pq_PQsendQueryPrepared
+            pgsql_LIBS="`$PGSQL_CONFIG --libs`"
+            APR_ADDTO(LIBS, [$pgsql_LIBS])
+            AC_CHECK_LIB(pq, PQsendQueryPrepared, [apu_have_pgsql=1])
+          fi
+          ])
+        ])
+      fi
+      if test "$apu_have_pgsql" != "0"; then
+        APR_ADDTO(INCLUDES, [$pgsql_CPPFLAGS])
+      fi
+    fi
+  ], [
+    AC_PATH_TOOL([PGSQL_CONFIG],[pg_config])
+    if test "x$PGSQL_CONFIG" != 'x'; then
+      pgsql_CPPFLAGS="-I`$PGSQL_CONFIG --includedir`"
+      pgsql_LDFLAGS="-L`$PGSQL_CONFIG --libdir`"
+
+      APR_ADDTO(CPPFLAGS, [$pgsql_CPPFLAGS])
+      APR_ADDTO(LDFLAGS, [$pgsql_LDFLAGS])
+    fi
+
+    AC_CHECK_HEADERS(libpq-fe.h, [
+      AC_CHECK_LIB(pq, PQsendQueryPrepared, [apu_have_pgsql=1],[
+      if test "x$PGSQL_CONFIG" != 'x'; then
+        unset ac_cv_lib_pq_PQsendQueryPrepared
+        pgsql_LIBS="`$PGSQL_CONFIG --libs`"
+        APR_ADDTO(LIBS, [$pgsql_LIBS])
+        AC_CHECK_LIB(pq, PQsendQueryPrepared, [apu_have_pgsql=1])
+      fi
+      ])
+    ])
+    if test "$apu_have_pgsql" = "0"; then
+      AC_CHECK_HEADERS(postgresql/libpq-fe.h, [
+        AC_CHECK_LIB(pq, PQsendQueryPrepared, [apu_have_pgsql=1],[
+        if test "x$PGSQL_CONFIG" != 'x'; then
+          unset ac_cv_lib_pq_PQsendQueryPrepared
+          pgsql_LIBS="`$PGSQL_CONFIG --libs`"
+          APR_ADDTO(LIBS, [$pgsql_LIBS])
+          AC_CHECK_LIB(pq, PQsendQueryPrepared, [apu_have_pgsql=1])
+        fi
+        ])
+      ])
+    fi
+    if test "$apu_have_pgsql" != "0" && test "x$PGSQL_CONFIG" != 'x'; then
+      APR_ADDTO(INCLUDES, [$pgsql_CPPFLAGS])
+    fi
+  ])
+  AC_SUBST(apu_have_pgsql)
+  dnl Since we have already done the AC_CHECK_LIB tests, if we have it, 
+  dnl we know the library is there.
+  if test "$apu_have_pgsql" = "1"; then
+    APR_ADDTO(LDADD_dbd_pgsql, [$pgsql_LDFLAGS -lpq $pgsql_LIBS])
+  fi
+  AC_SUBST(LDADD_dbd_pgsql)
+
+  LIBS="$old_libs"
+  CPPFLAGS="$old_cppflags"
+  LDFLAGS="$old_ldflags"
+])
+dnl
+AC_DEFUN([APU_CHECK_DBD_MYSQL], [
+  apu_have_mysql=0
+
+  old_libs="$LIBS"
+  old_cppflags="$CPPFLAGS"
+  old_ldflags="$LDFLAGS"
+
+  AC_ARG_WITH([mysql], APR_HELP_STRING([--with-mysql=DIR], [enable MySQL DBD driver]),
+  [
+    if test "$withval" = "yes"; then
+      AC_PATH_TOOL([MYSQL_CONFIG],[mysql_config])
+      if test "x$MYSQL_CONFIG" != 'x'; then
+        mysql_CPPFLAGS="`$MYSQL_CONFIG --include`"
+        mysql_LDFLAGS="`$MYSQL_CONFIG --libs_r | sed -e 's/-l[[^ ]]\+//g'`"
+        mysql_LIBS="`$MYSQL_CONFIG --libs_r`"
+
+        APR_ADDTO(CPPFLAGS, [$mysql_CPPFLAGS])
+        APR_ADDTO(LIBS, [$mysql_LIBS])
+      fi
+
+      AC_CHECK_HEADERS([mysql.h my_global.h my_sys.h],
+                       AC_CHECK_LIB(mysqlclient, mysql_init, [apu_have_mysql=1]),
+                       [apu_have_mysql=0; break],
+                       [#include <my_global.h>])
+      if test "$apu_have_mysql" = "0"; then
+        AC_CHECK_HEADERS([mysql/mysql.h mysql/my_global.h mysql/my_sys.h],
+                         AC_CHECK_LIB(mysqlclient, mysql_init, [apu_have_mysql=1]),
+                         [apu_have_mysql=0; break],
+                         [#include <mysql/my_global.h>])
+      fi
+      if test "$apu_have_mysql" != "0" && test "x$MYSQL_CONFIG" != 'x'; then
+        APR_ADDTO(INCLUDES, [$mysql_CPPFLAGS])
+      fi
+    elif test "$withval" = "no"; then
+      :
+    else
+      AC_PATH_TOOL([MYSQL_CONFIG],[mysql_config],,[$withval/bin])
+      if test "x$MYSQL_CONFIG" != 'x'; then
+        mysql_CPPFLAGS="`$MYSQL_CONFIG --include`"
+        mysql_LDFLAGS="`$MYSQL_CONFIG --libs_r | sed -e 's/-l[[^ ]]\+//g'`"
+        mysql_LIBS="`$MYSQL_CONFIG --libs_r`"
+      else
+        mysql_CPPFLAGS="-I$withval/include"
+        mysql_LDFLAGS="-L$withval/lib "
+      fi
+
+      APR_ADDTO(CPPFLAGS, [$mysql_CPPFLAGS])
+      APR_ADDTO(LDFLAGS, [$mysql_LDFLAGS])
+      APR_ADDTO(LIBS, [$mysql_LIBS])
+
+      AC_MSG_NOTICE(checking for mysql in $withval)
+      AC_CHECK_HEADERS([mysql.h my_global.h my_sys.h],
+                       AC_CHECK_LIB(mysqlclient, mysql_init, [apu_have_mysql=1]),
+                       [apu_have_mysql=0; break],
+                       [#include <my_global.h>])
+
+      if test "$apu_have_mysql" != "1"; then
+        AC_CHECK_HEADERS([mysql/mysql.h mysql/my_global.h mysql/my_sys.h],
+                         AC_CHECK_LIB(mysqlclient, mysql_init, [apu_have_mysql=1]),
+                         [apu_have_mysql=0; break],
+                         [#include <mysql/my_global.h>])
+      fi
+      if test "$apu_have_mysql" != "0"; then
+        APR_ADDTO(INCLUDES, [$mysql_CPPFLAGS])
+      fi
+    fi
+  ])
+
+  AC_SUBST(apu_have_mysql)
+
+  dnl Since we have already done the AC_CHECK_LIB tests, if we have it, 
+  dnl we know the library is there.
+  if test "$apu_have_mysql" = "1"; then
+    APR_ADDTO(LDADD_dbd_mysql, [$mysql_LDFLAGS -lmysqlclient $mysql_LIBS])
+  fi
+  AC_SUBST(LDADD_dbd_mysql)
+
+  LIBS="$old_libs"
+  CPPFLAGS="$old_cppflags"
+  LDFLAGS="$old_ldflags"
+])
+dnl
+AC_DEFUN([APU_CHECK_DBD_SQLITE3], [
+  apu_have_sqlite3=0
+
+  old_libs="$LIBS"
+  old_cppflags="$CPPFLAGS"
+  old_ldflags="$LDFLAGS"
+
+  AC_ARG_WITH([sqlite3], APR_HELP_STRING([--with-sqlite3=DIR], [enable sqlite3 DBD driver]),
+  [
+    if test "$withval" = "yes"; then
+      AC_CHECK_HEADERS(sqlite3.h, AC_CHECK_LIB(sqlite3, sqlite3_open, [apu_have_sqlite3=1]))
+    elif test "$withval" = "no"; then
+      :
+    else
+      sqlite3_CPPFLAGS="-I$withval/include"
+      sqlite3_LDFLAGS="-L$withval/lib "
+
+      APR_ADDTO(CPPFLAGS, [$sqlite3_CPPFLAGS])
+      APR_ADDTO(LDFLAGS, [$sqlite3_LDFLAGS])
+
+      AC_MSG_NOTICE(checking for sqlite3 in $withval)
+      AC_CHECK_HEADERS(sqlite3.h, AC_CHECK_LIB(sqlite3, sqlite3_open, [apu_have_sqlite3=1]))
+      if test "$apu_have_sqlite3" != "0"; then
+        APR_ADDTO(INCLUDES, [-I$withval/include])
+      fi
+    fi
+  ], [
+    AC_CHECK_HEADERS(sqlite3.h, AC_CHECK_LIB(sqlite3, sqlite3_open, [apu_have_sqlite3=1]))
+  ])
+
+  AC_SUBST(apu_have_sqlite3)
+
+  dnl Since we have already done the AC_CHECK_LIB tests, if we have it, 
+  dnl we know the library is there.
+  if test "$apu_have_sqlite3" = "1"; then
+    APR_ADDTO(LDADD_dbd_sqlite3, [$sqlite3_LDFLAGS -lsqlite3])
+  fi
+  AC_SUBST(LDADD_dbd_sqlite3)
+
+  LIBS="$old_libs"
+  CPPFLAGS="$old_cppflags"
+  LDFLAGS="$old_ldflags"
+])
+dnl
+AC_DEFUN([APU_CHECK_DBD_SQLITE2], [
+  apu_have_sqlite2=0
+
+  old_libs="$LIBS"
+  old_cppflags="$CPPFLAGS"
+  old_ldflags="$LDFLAGS"
+
+  AC_ARG_WITH([sqlite2], APR_HELP_STRING([--with-sqlite2=DIR], [enable sqlite2 DBD driver]),
+  [
+    if test "$withval" = "yes"; then
+      AC_CHECK_HEADERS(sqlite.h, AC_CHECK_LIB(sqlite, sqlite_open, [apu_have_sqlite2=1]))
+    elif test "$withval" = "no"; then
+      :
+    else
+      sqlite2_CPPFLAGS="-I$withval/include"
+      sqlite2_LDFLAGS="-L$withval/lib "
+
+      APR_ADDTO(CPPFLAGS, [$sqlite2_CPPFLAGS])
+      APR_ADDTO(LDFLAGS, [$sqlite2_LDFLAGS])
+
+      AC_MSG_NOTICE(checking for sqlite2 in $withval)
+      AC_CHECK_HEADERS(sqlite.h, AC_CHECK_LIB(sqlite, sqlite_open, [apu_have_sqlite2=1]))
+      if test "$apu_have_sqlite2" != "0"; then
+        APR_ADDTO(INCLUDES, [-I$withval/include])
+      fi
+    fi
+  ], [
+    AC_CHECK_HEADERS(sqlite.h, AC_CHECK_LIB(sqlite, sqlite_open, [apu_have_sqlite2=1]))
+  ])
+
+  AC_SUBST(apu_have_sqlite2)
+
+  dnl Since we have already done the AC_CHECK_LIB tests, if we have it, 
+  dnl we know the library is there.
+  if test "$apu_have_sqlite2" = "1"; then
+    APR_ADDTO(LDADD_dbd_sqlite2, [$sqlite2_LDFLAGS -lsqlite])
+  fi
+  AC_SUBST(LDADD_dbd_sqlite2)
+
+  LIBS="$old_libs"
+  CPPFLAGS="$old_cppflags"
+  LDFLAGS="$old_ldflags"
+])
+dnl
+AC_DEFUN([APU_CHECK_DBD_ORACLE], [
+  apu_have_oracle=0
+
+  old_libs="$LIBS"
+  old_cppflags="$CPPFLAGS"
+  old_ldflags="$LDFLAGS"
+
+  AC_ARG_WITH([oracle-include],
+    APR_HELP_STRING([--with-oracle-include=DIR], [path to Oracle include files]))
+  AC_ARG_WITH([oracle], 
+    APR_HELP_STRING([--with-oracle=DIR], [enable Oracle DBD driver; giving ORACLE_HOME as DIR]),
+  [
+    if test "$withval" = "yes"; then
+      if test -n "$with_oracle_include"; then
+        oracle_CPPFLAGS="$CPPFLAGS -I$with_oracle_include"
+        APR_ADDTO(INCLUDES, [-I$with_oracle_include])
+      fi
+
+      APR_ADDTO(CPPFLAGS, [$oracle_CPPFLAGS])
+
+      AC_CHECK_HEADERS(oci.h, AC_CHECK_LIB(clntsh, OCIEnvCreate, [apu_have_oracle=1],[
+        unset ac_cv_lib_clntsh_OCIEnvCreate
+        oracle_LIBS="-lnnz11"
+        APR_ADDTO(LIBS, [$oracle_LIBS])
+        AC_CHECK_LIB(clntsh, OCIEnvCreate, [apu_have_oracle=1],[
+          unset ac_cv_lib_clntsh_OCIEnvCreate
+          APR_REMOVEFROM(LIBS, [$oracle_LIBS])
+          oracle_LIBS="-lnnz10"
+          APR_ADDTO(LIBS, [$oracle_LIBS])
+          AC_CHECK_LIB(clntsh, OCIEnvCreate, [apu_have_oracle=1])
+        ])
+      ]))
+    elif test "$withval" = "no"; then
+      :
+    else
+      if test -n "$with_oracle_include"; then
+        oracle_CPPFLAGS="$CPPFLAGS -I$with_oracle_include"
+        APR_ADDTO(INCLUDES, [-I$with_oracle_include])
+      else
+        oracle_CPPFLAGS="-I$withval/rdbms/demo -I$withval/rdbms/public"
+      fi
+      oracle_LDFLAGS="-L$withval/lib "
+
+      APR_ADDTO(CPPFLAGS, [$oracle_CPPFLAGS])
+      APR_ADDTO(LDFLAGS, [$oracle_LDFLAGS])
+
+      AC_MSG_NOTICE(checking for oracle in $withval)
+      AC_CHECK_HEADERS(oci.h, AC_CHECK_LIB(clntsh, OCIEnvCreate, [apu_have_oracle=1],[
+        unset ac_cv_lib_clntsh_OCIEnvCreate
+        oracle_LIBS="-lnnz11"
+        APR_ADDTO(LIBS, [$oracle_LIBS])
+        AC_CHECK_LIB(clntsh, OCIEnvCreate, [apu_have_oracle=1],[
+          unset ac_cv_lib_clntsh_OCIEnvCreate
+          APR_REMOVEFROM(LIBS, [$oracle_LIBS])
+          oracle_LIBS="-lnnz10"
+          APR_ADDTO(LIBS, [$oracle_LIBS])
+          AC_CHECK_LIB(clntsh, OCIEnvCreate, [apu_have_oracle=1])
+        ])
+      ]))
+      if test "$apu_have_oracle" != "0"; then
+        oracle_LDFLAGS="$oracle_LDFLAGS -R$withval/lib"
+        if test -z "$with_oracle_include"; then
+          APR_ADDTO(INCLUDES, [-I$withval/rdbms/demo -I$withval/rdbms/public])
+        fi
+      fi
+    fi
+  ])
+
+  AC_SUBST(apu_have_oracle)
+
+  dnl Since we have already done the AC_CHECK_LIB tests, if we have it, 
+  dnl we know the library is there.
+  if test "$apu_have_oracle" = "1"; then
+    APR_ADDTO(LDADD_dbd_oracle, [$oracle_LDFLAGS -lclntsh $oracle_LIBS])
+  fi
+  AC_SUBST(LDADD_dbd_oracle)
+
+  LIBS="$old_libs"
+  CPPFLAGS="$old_cppflags"
+  LDFLAGS="$old_ldflags"
+])
+
+dnl
+
+AC_DEFUN([APU_CHECK_DBD_ODBC], [
+  apu_have_odbc=0
+
+  old_libs="$LIBS"
+  old_cppflags="$CPPFLAGS"
+  old_ldflags="$LDFLAGS"
+
+  AC_ARG_WITH([odbc], APR_HELP_STRING([--with-odbc=DIR], [specify ODBC location]),
+  [
+    if test "$withval" = "yes"; then
+      AC_PATH_TOOL([ODBC_CONFIG],[odbc_config])
+      if test "x$ODBC_CONFIG" != 'x'; then
+        odbc_CPPFLAGS="-I`$ODBC_CONFIG --include-prefix`"
+        odbc_LDFLAGS="-L`$ODBC_CONFIG --lib-prefix`"
+        odbc_LIBS="`$ODBC_CONFIG --libs`"
+
+        APR_ADDTO(CPPFLAGS, [$odbc_CPPFLAGS])
+        APR_ADDTO(LDFLAGS, [$odbc_LDFLAGS])
+        APR_ADDTO(LIBS, [$odbc_LIBS])
+      fi
+
+      AC_CHECK_HEADERS(sql.h, AC_CHECK_LIB(odbc, SQLAllocHandle, [apu_have_odbc=1]))
+      if test "$apu_have_odbc" = "0"; then
+        AC_CHECK_HEADERS(odbc/sql.h, AC_CHECK_LIB(odbc, SQLAllocHandle, [apu_have_odbc=1]))
+      fi
+      if test "$apu_have_odbc" != "0" && test "x$ODBC_CONFIG" != 'x'; then
+        APR_ADDTO(INCLUDES, [$odbc_CPPFLAGS])
+      fi
+    elif test "$withval" = "no"; then
+      :
+    else
+      AC_PATH_TOOL([ODBC_CONFIG],[odbc_config],,[$withval/bin])
+      if test "x$ODBC_CONFIG" != 'x'; then
+        odbc_CPPFLAGS="-I`$ODBC_CONFIG --include-prefix`"
+        odbc_LDFLAGS="-L`$ODBC_CONFIG --lib-prefix`"
+        odbc_LIBS="`$ODBC_CONFIG --libs`"
+      else
+        if test -f "$withval" && test -x "$withval"; then 
+          odbc_CPPFLAGS="-I`$withval --include-prefix`"
+          odbc_LDFLAGS="-L`$withval --lib-prefix`"
+          odbc_LIBS="`$withval --libs`"
+        else
+          odbc_CPPFLAGS="-I$withval/include"
+          odbc_LDFLAGS="-L$withval/lib "
+        fi
+      fi
+
+      APR_ADDTO(CPPFLAGS, [$odbc_CPPFLAGS])
+      APR_ADDTO(LDFLAGS, [$odbc_LDFLAGS])
+      APR_ADDTO(LIBS, [$odbc_LIBS])
+
+      AC_MSG_NOTICE(checking for odbc in $withval)
+      AC_CHECK_HEADERS(sql.h, AC_CHECK_LIB(odbc, SQLAllocHandle, [apu_have_odbc=1]))
+      if test "$apu_have_odbc" = "0"; then
+        AC_CHECK_HEADERS(odbc/sql.h, AC_CHECK_LIB(odbc, SQLAllocHandle, [apu_have_odbc=1]))
+      fi
+      if test "$apu_have_odbc" != "0" && test "x$ODBC_CONFIG" != 'x'; then
+        APR_ADDTO(INCLUDES, [$odbc_CPPFLAGS])
+      fi
+    fi
+  ], [
+    AC_PATH_TOOL([ODBC_CONFIG],[odbc_config])
+    if test "x$ODBC_CONFIG" != 'x'; then
+      odbc_CPPFLAGS="-I`$ODBC_CONFIG --include-prefix`"
+      odbc_LDFLAGS="-L`$ODBC_CONFIG --lib-prefix`"
+      odbc_LIBS="`$ODBC_CONFIG --libs`"
+
+      APR_ADDTO(CPPFLAGS, [$odbc_CPPFLAGS])
+      APR_ADDTO(LDFLAGS, [$odbc_LDFLAGS])
+      APR_ADDTO(LIBS, [$odbc_LIBS])
+    fi
+
+    AC_CHECK_HEADERS(sql.h, AC_CHECK_LIB(odbc, SQLAllocHandle, [apu_have_odbc=1]))
+    if test "$apu_have_odbc" = "0"; then
+      AC_CHECK_HEADERS(odbc/sql.h, AC_CHECK_LIB(odbc, SQLAllocHandle, [apu_have_odbc=1]))
+    fi
+    if test "$apu_have_odbc" != "0" && test "x$ODBC_CONFIG" != 'x'; then
+      APR_ADDTO(INCLUDES, [$odbc_CPPFLAGS])
+    fi
+  ])
+  AC_SUBST(apu_have_odbc)
+  dnl Since we have already done the AC_CHECK_LIB tests, if we have it, 
+  dnl we know the library is there.
+  if test "$apu_have_odbc" = "1"; then
+    APR_ADDTO(LDADD_dbd_odbc, [$odbc_LDFLAGS -lodbc $odbc_LIBS])
+  fi
+  AC_SUBST(LDADD_dbd_odbc)
+
+  LIBS="$old_libs"
+  CPPFLAGS="$old_cppflags"
+  LDFLAGS="$old_ldflags"
+
+  apu_dbd_tests=""
+  test $apu_have_oracle = 1 &&  apu_dbd_tests="$apu_dbd_tests oracle"
+  test $apu_have_pgsql = 1 &&   apu_dbd_tests="$apu_dbd_tests pgsql"
+  test $apu_have_mysql = 1 &&   apu_dbd_tests="$apu_dbd_tests mysql"
+  test $apu_have_sqlite2 = 1 && apu_dbd_tests="$apu_dbd_tests sqlite2"
+  test $apu_have_sqlite3 = 1 && apu_dbd_tests="$apu_dbd_tests sqlite3"
+  test $apu_have_odbc = 1 &&    apu_dbd_tests="$apu_dbd_tests odbc"
+  AC_SUBST(apu_dbd_tests)
+])
diff --git a/build/dbm.m4 b/build/dbm.m4
new file mode 100644
index 00000000000..bbe9c863a60
--- /dev/null
+++ b/build/dbm.m4
@@ -0,0 +1,745 @@
+dnl -------------------------------------------------------- -*- autoconf -*-
+dnl Licensed to the Apache Software Foundation (ASF) under one or more
+dnl contributor license agreements.  See the NOTICE file distributed with
+dnl this work for additional information regarding copyright ownership.
+dnl The ASF licenses this file to You under the Apache License, Version 2.0
+dnl (the "License"); you may not use this file except in compliance with
+dnl the License.  You may obtain a copy of the License at
+dnl
+dnl     http://www.apache.org/licenses/LICENSE-2.0
+dnl
+dnl Unless required by applicable law or agreed to in writing, software
+dnl distributed under the License is distributed on an "AS IS" BASIS,
+dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+dnl See the License for the specific language governing permissions and
+dnl limitations under the License.
+
+
+dnl
+dnl DBM module
+dnl
+
+dnl   APU_LIB_BERKELEY_DB(major, minor, patch, places, headers, libnames)
+dnl
+dnl   Search for a useable version of Berkeley DB in a number of
+dnl   common places.  The installed DB must be no older than the
+dnl   version given by MAJOR, MINOR, and PATCH.  All of these
+dnl   arguments are allowed to be '-1', indicating we don't care.
+dnl   PLACES is a list of places to search for a Berkeley DB
+dnl   installation.  HEADERS is a list of headers to try.  LIBNAMES
+dnl   is a list of names of the library to attempt to link against,
+dnl   typically 'db' and 'db4'.
+dnl
+dnl   If we find a useable version, set CPPFLAGS and LIBS as
+dnl   appropriate, and set the shell variable `apu_have_db' to
+dnl   `1', and apu_db_lib to the matching lib name, and apu_db_header
+dnl   to the header to use.  Otherwise, set `apu_have_db' to `0'.
+dnl
+dnl   This macro also checks for the `--with-berkeley-db=PATH' flag;
+dnl   if given, the macro will use the PATH specified, and the
+dnl   configuration script will die if it can't find the library.  If
+dnl   the user gives the `--without-berkeley-db' flag, the entire
+dnl   search is skipped.
+dnl
+dnl   We cache the results of individual searches under particular
+dnl   prefixes, not the overall result of whether we found Berkeley
+dnl   DB.  That way, the user can re-run the configure script with
+dnl   different --with-berkeley-db switch values, without interference
+dnl   from the cache.
+
+
+AC_DEFUN([APU_CHECK_BERKELEY_DB], [
+  bdb_version=$1
+  if test "$2" != "-1"; then
+    bdb_version="$bdb_version.$2"
+    if test "$3" != "-1"; then
+      bdb_version="$bdb_version.$3"
+    fi
+  fi
+  bdb_places=$4
+  bdb_default_search_headers=$5
+  bdb_default_search_lib_names=$6
+
+  apu_have_db=0
+
+  # Save the original values of the flags we tweak.
+  apu_check_lib_save_libs="$LIBS"
+  apu_check_lib_save_ldflags="$LDFLAGS"
+  apu_check_lib_save_cppflags="$CPPFLAGS"
+
+  # The variable `found' is the prefix under which we've found
+  # Berkeley DB, or `not' if we haven't found it anywhere yet.
+  found=not
+  for bdb_place in $bdb_places; do
+
+    LDFLAGS="$apu_check_lib_save_ldflags"
+    CPPFLAGS="$apu_check_lib_save_cppflags"
+    case "$bdb_place" in
+      "std" )
+        description="the standard places"
+      ;;
+      *":"* )
+        header="`echo $bdb_place | sed -e 's/:.*$//'`"
+        lib="`echo $bdb_place | sed -e 's/^.*://'`"
+        CPPFLAGS="$CPPFLAGS -I$header"
+        LDFLAGS="$LDFLAGS -L$lib"
+        description="$header and $lib"
+      ;;
+      * )
+        if test -d $bdb_place; then
+          LDFLAGS="$LDFLAGS -L$bdb_place/lib"
+          CPPFLAGS="$CPPFLAGS -I$bdb_place/include"
+        else
+          AC_MSG_CHECKING([for Berkeley DB $bdb_version in $bdb_place])
+          AC_MSG_RESULT([directory not found])
+          continue
+        fi
+        description="$bdb_place"
+      ;;
+    esac
+
+    # Since there is no AC_MSG_NOTICE in autoconf 2.13, we use this
+    # trick to display a message instead.
+    AC_MSG_CHECKING([for Berkeley DB $bdb_version in $description])
+    AC_MSG_RESULT()
+
+    for bdb_libname in $bdb_default_search_lib_names; do
+      for bdb_header in $bdb_default_search_headers; do
+        # Clear the header cache variable for each location
+        changequote(,)
+        cache_id="`echo ac_cv_header_${bdb_header} \
+                 | sed -e 's/[^a-zA-Z0-9_]/_/g'`"
+        changequote([,])
+        unset $cache_id
+        AC_CHECK_HEADER([$bdb_header], [
+          if test "$1" = "3" -o "$1" = "4" -o "$1" = "5" -o "$1" = "6"; then
+            # We generate a separate cache variable for each prefix and libname
+            # we search under.  That way, we avoid caching information that
+            # changes if the user runs `configure' with a different set of
+            # switches.
+            changequote(,)
+            cache_id="`echo apu_cv_check_berkeley_db_$1_$2_$3_${bdb_header}_${bdb_libname}_in_${bdb_place} \
+                     | sed -e 's/[^a-zA-Z0-9_]/_/g'`"
+            changequote([,])
+
+            AC_MSG_CHECKING([for -l$bdb_libname])
+            dnl We can't use AC_CACHE_CHECK here, because that won't print out
+            dnl the value of the computed cache variable properly.
+            AC_CACHE_VAL($cache_id,
+              [
+                APU_TRY_BERKELEY_DB($1, $2, $3, $bdb_header, $bdb_libname)
+                eval "$cache_id=$apu_try_berkeley_db"
+              ])
+            result="`eval echo '$'$cache_id`"
+            AC_MSG_RESULT($result)
+          elif test "$1" = "1"; then
+            AC_CHECK_LIB($bdb_libname,
+              dbopen,
+              [result=yes],
+              [result=no]
+            )
+          elif test "$1" = "2"; then
+            AC_CHECK_LIB($bdb_libname,
+              db_open,
+              [result=yes],
+              [result=no]
+            )
+          fi
+        ], [result="no"])
+        
+        # If we found it, no need to search any more.
+        if test "$result" = "yes"; then
+          found="$bdb_place"
+          break
+        fi
+      done
+      test "$found" != "not" && break
+    done
+    test "$found" != "not" && break
+  done
+
+  # Restore the original values of the flags we tweak.
+  LDFLAGS="$apu_check_lib_save_ldflags"
+  CPPFLAGS="$apu_check_lib_save_cppflags"
+
+  case "$found" in
+  "not")
+    apu_have_db=0
+    ;;
+  "std")
+    apu_db_header=$bdb_header
+    apu_db_lib=$bdb_libname
+    apu_have_db=1
+    ;;
+  *":"*)
+    header="`echo $found | sed -e 's/:.*$//'`"
+    lib="`echo $found | sed -e 's/^.*://'`"
+
+    APR_ADDTO(INCLUDES, [-I$header])
+    APR_ADDTO(LDFLAGS, [-L$lib])
+    apu_db_header=$bdb_header
+    apu_db_lib=$bdb_libname
+    apu_have_db=1
+    ;;
+  *)
+    APR_ADDTO(INCLUDES, [-I$found/include])
+    APR_ADDTO(LDFLAGS, [-L$found/lib])
+    apu_db_header=$bdb_header
+    apu_db_lib=$bdb_libname
+    apu_have_db=1
+    ;;
+  esac
+])
+
+
+dnl   APU_TRY_BERKELEY_DB(major, minor, patch, header, libname)
+dnl
+dnl   A subroutine of APU_CHECK_BERKELEY_DB.
+dnl
+dnl   Check that a new-enough version of Berkeley DB is installed.
+dnl   "New enough" means no older than the version given by MAJOR,
+dnl   MINOR, and PATCH.  The result of the test is not cached; no
+dnl   messages are printed.  Use HEADER as the header file to include.
+dnl   Use LIBNAME as the library to link against.
+dnl   (e.g. LIBNAME should usually be "db" or "db4".)
+dnl
+dnl   Set the shell variable `apu_try_berkeley_db' to `yes' if we found
+dnl   an appropriate version installed, or `no' otherwise.
+dnl
+dnl   This macro uses the Berkeley DB library function `db_version' to
+dnl   find the version.  If the library installed doesn't have this
+dnl   function, then this macro assumes it is too old.
+
+dnl   NOTE: This is pretty messed up.  It seems that the FreeBSD port of
+dnl   Berkeley DB 4 puts the header file in /usr/local/include/db4, but the
+dnl   database library in /usr/local/lib, as libdb4.[a|so].  There is no
+dnl   /usr/local/include/db.h.  So if you check for /usr/local first, you'll
+dnl   get the old header file from /usr/include, and the new library from
+dnl   /usr/local/lib.  Disaster.  Thus this test compares the version constants
+dnl   in the db.h header with the ones returned by db_version().
+
+
+AC_DEFUN([APU_TRY_BERKELEY_DB],
+  [
+    apu_try_berkeley_db_save_libs="$LIBS"
+
+    apu_check_berkeley_db_major=$1
+    apu_check_berkeley_db_minor=$2
+    apu_check_berkeley_db_patch=$3
+    apu_try_berkeley_db_header=$4
+    apu_try_berkeley_db_libname=$5
+
+    LIBS="$LIBS -l$apu_try_berkeley_db_libname"
+    AC_TRY_RUN(
+      [
+#include <stdlib.h>
+#include <stdio.h>
+#include <$apu_try_berkeley_db_header>
+main ()
+{
+  int major, minor, patch;
+
+  db_version(&major, &minor, &patch);
+
+  /* Sanity check: ensure that db.h constants actually match the db library */
+  if (major != DB_VERSION_MAJOR
+      || minor != DB_VERSION_MINOR
+      || patch != DB_VERSION_PATCH)
+    exit (1);
+
+  /* Run-time check:  ensure the library claims to be the correct version. */
+
+  if ($apu_check_berkeley_db_major != -1) {
+    if (major < $apu_check_berkeley_db_major)
+      exit (1);
+    if (major > $apu_check_berkeley_db_major)
+      exit (0);
+  }
+
+  if ($apu_check_berkeley_db_minor != -1) {
+    if (minor < $apu_check_berkeley_db_minor)
+      exit (1);
+    if (minor > $apu_check_berkeley_db_minor)
+      exit (0);
+  }
+
+  if ($apu_check_berkeley_db_patch == -1
+      || patch >= $apu_check_berkeley_db_patch)
+    exit (0);
+  else
+    exit (1);
+}
+      ],
+      [apu_try_berkeley_db=yes],
+      [apu_try_berkeley_db=no],
+      [apu_try_berkeley_db=yes]
+    )
+
+    LIBS="$apu_try_berkeley_db_save_libs"
+  ]
+)
+
+
+dnl
+dnl APU_CHECK_DB1: is DB1 present?
+dnl
+dnl if present: sets apu_db_header, apu_db_lib, and apu_db_version
+dnl
+AC_DEFUN([APU_CHECK_DB1], [
+  places=$1
+  if test -z "$places"; then
+    places="std"
+  fi
+  APU_CHECK_BERKELEY_DB(1, 0, 0,
+    "$places",
+    "db1/db.h db.h",
+    "db1"
+  )
+  if test "$apu_have_db" = "1"; then
+    apu_db_version=1
+  fi
+])
+
+
+dnl
+dnl APU_CHECK_DB185: is DB1.85 present?
+dnl
+dnl if present: sets apu_db_header, apu_db_lib, and apu_db_version
+dnl
+dnl NB: BerkelyDB v2 and above can be compiled in 1.85 mode
+dnl which has a libdb not libdb1 or libdb185
+AC_DEFUN([APU_CHECK_DB185], [
+  places=$1
+  if test -z "$places"; then
+    places="std"
+  fi
+  APU_CHECK_BERKELEY_DB(1, -1, -1,
+    "$places",
+    "db_185.h",
+    "db"
+  )
+  if test "$apu_have_db" = "1"; then
+    apu_db_version=185
+  fi
+])
+
+
+dnl
+dnl APU_CHECK_DB2: is DB2 present?
+dnl
+dnl if present: sets apu_db_header, apu_db_lib, and apu_db_version
+dnl
+AC_DEFUN([APU_CHECK_DB2], [
+  places=$1
+  if test -z "$places"; then
+    places="std"
+  fi
+  APU_CHECK_BERKELEY_DB(2, -1, -1,
+    "$places",
+    "db2/db.h db.h",
+    "db2 db"
+  )
+  if test "$apu_have_db" = "1"; then
+    apu_db_version=2
+  fi
+])
+
+
+dnl
+dnl APU_CHECK_DB3: is DB3 present?
+dnl
+dnl if present: sets apu_db_header, apu_db_lib, and apu_db_version
+dnl
+AC_DEFUN([APU_CHECK_DB3], [
+  places=$1
+  if test -z "$places"; then
+    places="std"
+  fi
+  APU_CHECK_BERKELEY_DB(3, -1, -1,
+    "$places",
+    "db3/db.h db.h",
+    "db3 db"
+  )
+  if test "$apu_have_db" = "1"; then
+    apu_db_version=3
+  fi
+])
+
+
+dnl
+dnl APU_CHECK_DBXY: is DBX.Y present?
+dnl
+dnl if present: sets apu_db_header, apu_db_lib, and apu_db_version
+dnl
+AC_DEFUN([APU_CHECK_DBXY], [
+  places=$1
+  db_major=$2
+  db_minor=$3
+  if test -z "$places"; then
+    places="std /usr/local /usr/local/BerkeleyDB.${db_major}.${db_minor} /boot/home/config"
+  fi
+  APU_CHECK_BERKELEY_DB("${db_major}", "${db_minor}", "-1",
+    "$places",
+    "db${db_major}${db_minor}/db.h db${db_major}/db.h db.h",
+    "db-${db_major}.${db_minor} db${db_major}-${db_major}.${db_minor} db${db_major}${db_minor} db-${db_major} db${db_major} db"
+  )
+  if test "$apu_have_db" = "1"; then
+    apu_db_version=${db_major}
+  fi
+])
+
+
+AC_DEFUN([APU_CHECK_DB], [
+  requested=$1
+  check_places=$2
+
+  case "$requested" in
+  db)
+    APU_CHECK_DB_ALL("$check_places")
+    if test "$apu_have_db" = "0"; then
+      AC_MSG_ERROR(Berkeley db requested, but not found)
+    fi
+    ;;
+  db1)
+    APU_CHECK_DB1("$check_places")
+    if test "$apu_db_version" != "1"; then
+      AC_MSG_ERROR(Berkeley db1 not found)
+    fi
+    ;;
+  db185)
+    APU_CHECK_DB185("$check_places")
+    if test "$apu_db_version" != "185"; then
+      AC_MSG_ERROR(Berkeley db185 not found)
+    fi
+    ;;
+  db2)
+    APU_CHECK_DB2("$check_places")
+    if test "$apu_db_version" != "2"; then
+      AC_MSG_ERROR(Berkeley db2 not found)
+    fi
+    ;;
+  db3)
+    APU_CHECK_DB3("$check_places")
+    if test "$apu_db_version" != "3"; then
+      AC_MSG_ERROR(Berkeley db3 not found)
+    fi
+    ;;
+  db[[456]][[0-9]])
+    db_major=`echo "$requested" | sed -e 's/db//' -e 's/.$//'`
+    db_minor=`echo "$requested" | sed -e 's/db//' -e 's/.//'`
+    APU_CHECK_DBXY("$check_places", "$db_major", "$db_minor")
+    if test "$apu_db_version" != "$db_major"; then
+      AC_MSG_ERROR(Berkeley db$db_major not found)
+    fi
+    ;;
+  db[[456]])
+    db_major=`echo "$requested" | sed -e 's/db//'`
+    # Start version search at version x.9
+    db_minor=9
+    while [[ $db_minor -ge 0 ]]
+    do
+      APU_CHECK_DBXY("$check_places", "$db_major", "$db_minor")
+      if test "$apu_have_db" = "1"; then
+        break
+      fi
+      db_minor=`expr $db_minor - 1`
+    done
+    if test "$apu_db_version" != "$db_major"; then
+      AC_MSG_ERROR(Berkeley db$db_major not found)
+    fi
+    ;;
+  default)
+    APU_CHECK_DB_ALL("$check_places")
+    ;;
+  esac
+])
+
+dnl
+dnl APU_CHECK_DB_ALL: Try all Berkeley DB versions, from 6.X to 1.
+dnl
+AC_DEFUN([APU_CHECK_DB_ALL], [
+  all_places=$1
+
+  # Start version search at version 6.9
+  db_version=69
+  while [[ $db_version -ge 40 ]]
+  do
+    db_major=`echo $db_version | sed -e 's/.$//'`
+    db_minor=`echo $db_version | sed -e 's/.//'`
+    APU_CHECK_DBXY("$all_places", "$db_major", "$db_minor")
+    if test "$apu_have_db" = "1"; then
+      break
+    fi
+    db_version=`expr $db_version - 1`
+  done
+  if test "$apu_have_db" = "0"; then
+    APU_CHECK_DB3("$all_places")
+  fi
+  if test "$apu_have_db" = "0"; then
+    APU_CHECK_DB2("$all_places")
+  fi
+  if test "$apu_have_db" = "0"; then
+    APU_CHECK_DB1("$all_places")
+  fi
+  if test "$apu_have_db" = "0"; then
+    APU_CHECK_DB185("$all_places")
+  fi
+  AC_MSG_CHECKING(for Berkeley DB)
+  if test "$apu_have_db" = "1"; then
+    AC_MSG_RESULT(found db$apu_db_version)
+  else
+    AC_MSG_RESULT(not found)
+  fi
+])
+
+
+dnl
+dnl APU_CHECK_DBM: see what kind of DBM backend to use for apr_dbm.
+dnl
+AC_DEFUN([APU_CHECK_DBM], [
+  apu_use_sdbm=0
+  apu_use_ndbm=0
+  apu_use_gdbm=0
+  apu_use_db=0
+  dnl it's in our codebase
+  apu_have_sdbm=1
+  apu_have_gdbm=0
+  apu_have_ndbm=0
+  apu_have_db=0
+
+  apu_db_header=db.h                # default so apu_select_dbm.h is syntactically correct
+  apu_db_version=0
+
+  # Maximum supported version announced in help string.
+  # Although we search for all versions up to 6.9,
+  # we should only include existing versions in our
+  # help string.
+  dbm_list="sdbm, gdbm, ndbm, db, db1, db185, db2, db3, db4"
+  db_max_version=48
+  db_min_version=41
+  db_version="$db_min_version"
+  while [[ $db_version -le $db_max_version ]]
+  do
+    dbm_list="$dbm_list, db$db_version"
+    db_version=`expr $db_version + 1`
+  done
+  db_max_version=53
+  db_min_version=50
+  db_version="$db_min_version"
+  while [[ $db_version -le $db_max_version ]]
+  do
+    dbm_list="$dbm_list, db$db_version"
+    db_version=`expr $db_version + 1`
+  done
+  db_max_version=60
+  db_min_version=60
+  db_version="$db_min_version"
+  while [[ $db_version -le $db_max_version ]]
+  do
+    dbm_list="$dbm_list, db$db_version"
+    db_version=`expr $db_version + 1`
+  done
+
+  AC_ARG_WITH(dbm, [APR_HELP_STRING([--with-dbm=DBM], [choose the DBM type to use.
+      DBM={sdbm,gdbm,ndbm,db,db1,db185,db2,db3,db4,db4X,db5X,db6X} for some X=0,...,9])],
+  [
+    if test "$withval" = "yes"; then
+      AC_MSG_ERROR([--with-dbm needs to specify a DBM type to use.
+        One of: $dbm_list])
+    fi
+    requested="$withval"
+  ], [
+    requested=default
+  ])
+
+  dnl We don't pull in GDBM unless the user asks for it, since it's GPL
+  AC_ARG_WITH([gdbm], [APR_HELP_STRING([--with-gdbm=DIR], [enable GDBM support])],
+  [
+    apu_have_gdbm=0
+    if test "$withval" = "yes"; then
+      AC_CHECK_HEADER(gdbm.h, AC_CHECK_LIB(gdbm, gdbm_open, [apu_have_gdbm=1]))
+    elif test "$withval" = "no"; then
+      apu_have_gdbm=0
+    else
+      saved_cppflags="$CPPFLAGS"
+      saved_ldflags="$LDFLAGS"
+      CPPFLAGS="$CPPFLAGS -I$withval/include"
+      LDFLAGS="$LDFLAGS -L$withval/lib "
+
+      AC_MSG_CHECKING(checking for gdbm in $withval)
+      AC_CHECK_HEADER(gdbm.h, AC_CHECK_LIB(gdbm, gdbm_open, [apu_have_gdbm=1]))
+      if test "$apu_have_gdbm" != "0"; then
+        APR_ADDTO(LDFLAGS, [-L$withval/lib])
+        APR_ADDTO(INCLUDES, [-I$withval/include])
+      fi
+      CPPFLAGS="$saved_cppflags"
+      LDFLAGS="$saved_ldflags"
+    fi
+  ])
+
+  AC_ARG_WITH([ndbm], [APR_HELP_STRING([--with-ndbm=PATH], [
+      Find the NDBM header and library in `PATH/include' and 
+      `PATH/lib'.  If PATH is of the form `HEADER:LIB', then search 
+      for header files in HEADER, and the library in LIB.  If you omit
+      the `=PATH' part completely, the configure script will search
+      for NDBM in a number of standard places.])],
+  [
+    apu_have_ndbm=0
+    if test "$withval" = "yes"; then
+      AC_MSG_CHECKING(checking for ndbm in the usual places)
+      apu_want_ndbm=1
+      NDBM_INC=""
+      NDBM_LDFLAGS=""
+    elif test "$withval" = "no"; then
+      apu_want_ndbm=0
+    else
+      apu_want_ndbm=1
+      case "$withval" in
+        *":"*)
+          NDBM_INC="-I`echo $withval |sed -e 's/:.*$//'`"
+          NDBM_LDFLAGS="-L`echo $withval |sed -e 's/^.*://'`"
+          AC_MSG_CHECKING(checking for ndbm includes with $NDBM_INC libs with $NDBM_LDFLAGS )
+        ;;
+        *)
+          NDBM_INC="-I$withval/include"
+          NDBM_LDFLAGS="-L$withval/lib"
+          AC_MSG_CHECKING(checking for ndbm includes in $withval)
+        ;;
+      esac
+    fi
+
+    save_cppflags="$CPPFLAGS"
+    save_ldflags="$LDFLAGS"
+    CPPFLAGS="$CPPFLAGS $NDBM_INC"
+    LDFLAGS="$LDFLAGS $NDBM_LDFLAGS"
+    dnl db_ndbm_open is what sleepcat's compatibility library actually has in it's lib
+    if test "$apu_want_ndbm" != "0"; then
+      AC_CHECK_HEADER(ndbm.h, 
+        AC_CHECK_LIB(c, dbm_open, [apu_have_ndbm=1;apu_ndbm_lib=c],
+          AC_CHECK_LIB(dbm, dbm_open, [apu_have_ndbm=1;apu_ndbm_lib=dbm],
+            AC_CHECK_LIB(db, dbm_open, [apu_have_ndbm=1;apu_ndbm_lib=db],
+              AC_CHECK_LIB(db, __db_ndbm_open, [apu_have_ndbm=1;apu_ndbm_lib=db])
+            )
+          )
+        )
+      )
+      if test "$apu_have_ndbm" != "0";  then
+        if test "$withval" != "yes"; then
+          APR_ADDTO(INCLUDES, [$NDBM_INC])
+          APR_ADDTO(LDFLAGS, [$NDBM_LDFLAGS])
+        fi
+      elif test "$withval" != "yes"; then
+        AC_ERROR( NDBM not found in the specified directory)
+      fi
+    fi
+    CPPFLAGS="$save_cppflags"
+    LDFLAGS="$save_ldflags"
+  ], [
+    dnl don't check it no one has asked us for it
+    apu_have_ndbm=0
+  ])
+
+
+  if test -n "$apu_db_xtra_libs"; then
+    saveddbxtralibs="$LIBS"
+    LIBS="$apu_db_xtra_libs $LIBS"
+  fi
+
+  dnl We're going to try to find the highest version of Berkeley DB supported.
+  dnl
+  dnl Note that we only do this if the user requested it, since the Sleepycat
+  dnl license is viral and requires distribution of source along with programs
+  dnl that use it.
+  AC_ARG_WITH([berkeley-db], [APR_HELP_STRING([--with-berkeley-db=PATH],
+      [Find the Berkeley DB header and library in `PATH/include' and
+      `PATH/lib'.  If PATH is of the form `HEADER:LIB', then search
+      for header files in HEADER, and the library in LIB.  If you omit
+      the `=PATH' part completely, the configure script will search
+      for Berkeley DB in a number of standard places.])],
+  [
+    if test "$withval" = "yes"; then
+      apu_want_db=1
+      user_places=""
+    elif test "$withval" = "no"; then
+      apu_want_db=0
+    else
+      apu_want_db=1
+      user_places="$withval"
+    fi
+
+    if test "$apu_want_db" != "0"; then
+      APU_CHECK_DB($requested, $user_places)
+      if test "$apu_have_db" = "0"; then
+        AC_ERROR(Berkeley DB not found.)
+      fi
+    fi 
+  ])
+
+  if test -n "$apu_db_xtra_libs"; then
+    LIBS="$saveddbxtralibs"
+  fi
+
+  case "$requested" in
+    sdbm | gdbm | ndbm | db)
+      eval "apu_use_$requested=1"
+      apu_default_dbm=$requested
+      ;;
+    db185 | db[[123456]])
+      apu_use_db=1
+      apu_default_dbm=$requested
+      ;;
+    db[[456]][[0-9]])
+      apu_use_db=1
+      apu_default_dbm=`echo $requested | sed -e 's/.$//'`
+      ;;
+    default)
+      dnl ### use more sophisticated DBMs for the default?
+      apu_default_dbm="sdbm (default)"
+      apu_use_sdbm=1
+      ;;
+    *)
+      AC_MSG_ERROR([--with-dbm=$requested is an unknown DBM type.
+        Use one of: $dbm_list])
+      ;;
+  esac
+
+  dnl Yes, it'd be nice if we could collate the output in an order
+  dnl so that the AC_MSG_CHECKING would be output before the actual
+  dnl checks, but it isn't happening now.
+  AC_MSG_CHECKING(for default DBM)
+  AC_MSG_RESULT($apu_default_dbm)
+
+  AC_SUBST(apu_use_sdbm)
+  AC_SUBST(apu_use_gdbm)
+  AC_SUBST(apu_use_ndbm)
+  AC_SUBST(apu_use_db)
+
+  AC_SUBST(apu_have_sdbm)
+  AC_SUBST(apu_have_gdbm)
+  AC_SUBST(apu_have_ndbm)
+  AC_SUBST(apu_have_db)
+  AC_SUBST(apu_db_header)
+  AC_SUBST(apu_db_version)
+
+  if test "$apu_have_db" = "1"; then
+    APR_ADDTO(LDADD_dbm_db, [-l$apu_db_lib])
+    if test -n "apu_db_xtra_libs"; then
+      APR_ADDTO(LDADD_dbm_db, [$apu_db_xtra_libs])
+    fi
+  fi
+
+  dnl Since we have already done the AC_CHECK_LIB tests, if we have it, 
+  dnl we know the library is there.
+  if test "$apu_have_gdbm" = "1"; then
+    APR_ADDTO(LDADD_dbm_gdbm, [-lgdbm])
+  fi
+
+  if test "$apu_have_ndbm" = "1"; then
+    APR_ADDTO(LDADD_dbm_ndbm, [-l$apu_ndbm_lib])
+  fi
+
+  AC_SUBST(LDADD_dbm_db)
+  AC_SUBST(LDADD_dbm_gdbm)
+  AC_SUBST(LDADD_dbm_ndbm)
+])
+
diff --git a/build/dso.m4 b/build/dso.m4
new file mode 100644
index 00000000000..26dd4128119
--- /dev/null
+++ b/build/dso.m4
@@ -0,0 +1,98 @@
+dnl -------------------------------------------------------- -*- autoconf -*-
+dnl Licensed to the Apache Software Foundation (ASF) under one or more
+dnl contributor license agreements.  See the NOTICE file distributed with
+dnl this work for additional information regarding copyright ownership.
+dnl The ASF licenses this file to You under the Apache License, Version 2.0
+dnl (the "License"); you may not use this file except in compliance with
+dnl the License.  You may obtain a copy of the License at
+dnl
+dnl     http://www.apache.org/licenses/LICENSE-2.0
+dnl
+dnl Unless required by applicable law or agreed to in writing, software
+dnl distributed under the License is distributed on an "AS IS" BASIS,
+dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+dnl See the License for the specific language governing permissions and
+dnl limitations under the License.
+
+dnl
+dnl DSO module
+dnl
+
+AC_DEFUN([APR_MODULAR_DSO], [
+
+  AC_ARG_ENABLE([modular-dso], 
+     APR_HELP_STRING([--disable-modular-dso],
+       [disable DSO build of modular components]))
+
+  if test "$enable_modular_dso" = "no"; then
+     apr_modular_dso="0"
+  else
+     apr_modular_dso=$aprdso
+  fi
+
+  if test "$apr_modular_dso" = "0"; then
+
+     # Statically link the drivers:
+     objs=
+     test $apu_have_openssl = 1 && objs="$objs crypto/apr_crypto_openssl.lo"
+     test $apu_have_nss = 1 && objs="$objs crypto/apr_crypto_nss.lo"
+     test $apu_have_commoncrypto = 1 && objs="$objs crypto/apr_crypto_commoncrypto.lo"
+     test $apu_have_oracle = 1 && objs="$objs dbd/apr_dbd_oracle.lo"
+     test $apu_have_pgsql = 1 && objs="$objs dbd/apr_dbd_pgsql.lo"
+     test $apu_have_mysql = 1 && objs="$objs dbd/apr_dbd_mysql.lo"
+     test $apu_have_sqlite2 = 1 && objs="$objs dbd/apr_dbd_sqlite2.lo"
+     test $apu_have_sqlite3 = 1 && objs="$objs dbd/apr_dbd_sqlite3.lo"
+     test $apu_have_odbc = 1 && objs="$objs dbd/apr_dbd_odbc.lo"
+     test $apu_have_db = 1 && objs="$objs dbm/apr_dbm_berkeleydb.lo"
+     test $apu_have_gdbm = 1 && objs="$objs dbm/apr_dbm_gdbm.lo"
+     test $apu_have_ndbm = 1 && objs="$objs dbm/apr_dbm_ndbm.lo"
+     EXTRA_OBJECTS="$EXTRA_OBJECTS $objs"
+
+     # Use libtool *.la for mysql if available
+     if test $apu_have_mysql = 1; then
+       for flag in $LDADD_dbd_mysql
+       do
+         dir=`echo $flag | grep "^-L" | sed s:-L::`
+         if test "x$dir" != 'x'; then
+           if test -f "$dir/libmysqlclient_r.la"; then
+             LDADD_dbd_mysql=$dir/libmysqlclient_r.la
+             break
+           fi
+         fi
+       done
+     fi
+
+     LIBS="$LIBS $LDADD_crypto_openssl $LDADD_crypto_nss $LDADD_crypto_commoncrypto"
+     LIBS="$LIBS $LDADD_dbd_pgsql $LDADD_dbd_sqlite2 $LDADD_dbd_sqlite3 $LDADD_dbd_oracle $LDADD_dbd_mysql $LDADD_dbd_odbc"
+     LIBS="$LIBS $LDADD_dbm_db $LDADD_dbm_gdbm $LDADD_dbm_ndbm"
+     APRUTIL_EXPORT_LIBS="$APRUTIL_EXPORT_LIBS $LDADD_crypto_openssl $LDADD_crypto_nss $LDADD_crypto_commoncrypto"
+     APRUTIL_EXPORT_LIBS="$APRUTIL_EXPORT_LIBS $LDADD_dbd_pgsql $LDADD_dbd_sqlite2 $LDADD_dbd_sqlite3 $LDADD_dbd_oracle $LDADD_dbd_mysql $LDADD_dbd_odbc"
+     APRUTIL_EXPORT_LIBS="$APRUTIL_EXPORT_LIBS $LDADD_dbm_db $LDADD_dbm_gdbm $LDADD_dbm_ndbm"
+
+  else
+
+     # Build the drivers as loadable modules:
+     dsos=
+     test $apu_have_openssl = 1 && dsos="$dsos crypto/apr_crypto_openssl.la"
+     test $apu_have_nss = 1 && dsos="$dsos crypto/apr_crypto_nss.la"
+     test $apu_have_commoncrypto = 1 && dsos="$dsos crypto/apr_crypto_commoncrypto.la"
+     test $apu_have_oracle = 1 && dsos="$dsos dbd/apr_dbd_oracle.la"
+     test $apu_have_pgsql = 1 && dsos="$dsos dbd/apr_dbd_pgsql.la"
+     test $apu_have_mysql = 1 && dsos="$dsos dbd/apr_dbd_mysql.la"
+     test $apu_have_sqlite2 = 1 && dsos="$dsos dbd/apr_dbd_sqlite2.la"
+     test $apu_have_sqlite3 = 1 && dsos="$dsos dbd/apr_dbd_sqlite3.la"
+     test $apu_have_odbc = 1 && dsos="$dsos dbd/apr_dbd_odbc.la"
+     test $apu_have_db = 1 && dsos="$dsos dbm/apr_dbm_db.la"
+     test $apu_have_gdbm = 1 && dsos="$dsos dbm/apr_dbm_gdbm.la"
+     test $apu_have_ndbm = 1 && dsos="$dsos dbm/apr_dbm_ndbm.la"
+
+     if test -n "$dsos"; then
+        APR_DSO_MODULES="$APR_DSO_MODULES $dsos"
+     fi
+
+     AC_MSG_NOTICE([Using modular DSO build])
+  fi
+
+  AC_DEFINE_UNQUOTED([APR_HAVE_MODULAR_DSO], $apr_modular_dso,
+     [Define to 1 if modular components are built as DSOs])
+])
diff --git a/build/find_apr.m4 b/build/find_apr.m4
new file mode 100644
index 00000000000..925e523f81d
--- /dev/null
+++ b/build/find_apr.m4
@@ -0,0 +1,202 @@
+dnl -------------------------------------------------------- -*- autoconf -*-
+dnl Licensed to the Apache Software Foundation (ASF) under one or more
+dnl contributor license agreements.  See the NOTICE file distributed with
+dnl this work for additional information regarding copyright ownership.
+dnl The ASF licenses this file to You under the Apache License, Version 2.0
+dnl (the "License"); you may not use this file except in compliance with
+dnl the License.  You may obtain a copy of the License at
+dnl
+dnl     http://www.apache.org/licenses/LICENSE-2.0
+dnl
+dnl Unless required by applicable law or agreed to in writing, software
+dnl distributed under the License is distributed on an "AS IS" BASIS,
+dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+dnl See the License for the specific language governing permissions and
+dnl limitations under the License.
+
+dnl
+dnl find_apr.m4 : locate the APR include files and libraries
+dnl
+dnl This macro file can be used by applications to find and use the APR
+dnl library. It provides a standardized mechanism for using APR. It supports
+dnl embedding APR into the application source, or locating an installed
+dnl copy of APR.
+dnl
+dnl APR_FIND_APR(srcdir, builddir, implicit-install-check, acceptable-majors,
+dnl              detailed-check)
+dnl
+dnl   where srcdir is the location of the bundled APR source directory, or
+dnl   empty if source is not bundled.
+dnl
+dnl   where builddir is the location where the bundled APR will will be built,
+dnl   or empty if the build will occur in the srcdir.
+dnl
+dnl   where implicit-install-check set to 1 indicates if there is no
+dnl   --with-apr option specified, we will look for installed copies.
+dnl
+dnl   where acceptable-majors is a space separated list of acceptable major
+dnl   version numbers. Often only a single major version will be acceptable.
+dnl   If multiple versions are specified, and --with-apr=PREFIX or the
+dnl   implicit installed search are used, then the first (leftmost) version
+dnl   in the list that is found will be used.  Currently defaults to [0 1].
+dnl
+dnl   where detailed-check is an M4 macro which sets the apr_acceptable to
+dnl   either "yes" or "no". The macro will be invoked for each installed
+dnl   copy of APR found, with the apr_config variable set appropriately.
+dnl   Only installed copies of APR which are considered acceptable by
+dnl   this macro will be considered found. If no installed copies are
+dnl   considered acceptable by this macro, apr_found will be set to either
+dnl   either "no" or "reconfig".
+dnl
+dnl Sets the following variables on exit:
+dnl
+dnl   apr_found : "yes", "no", "reconfig"
+dnl
+dnl   apr_config : If the apr-config tool exists, this refers to it. If
+dnl                apr_found is "reconfig", then the bundled directory
+dnl                should be reconfigured *before* using apr_config.
+dnl
+dnl Note: this macro file assumes that apr-config has been installed; it
+dnl       is normally considered a required part of an APR installation.
+dnl
+dnl If a bundled source directory is available and needs to be (re)configured,
+dnl then apr_found is set to "reconfig". The caller should reconfigure the
+dnl (passed-in) source directory, placing the result in the build directory,
+dnl as appropriate.
+dnl
+dnl If apr_found is "yes" or "reconfig", then the caller should use the
+dnl value of apr_config to fetch any necessary build/link information.
+dnl
+
+AC_DEFUN([APR_FIND_APR], [
+  apr_found="no"
+
+  if test "$target_os" = "os2-emx"; then
+    # Scripts don't pass test -x on OS/2
+    TEST_X="test -f"
+  else
+    TEST_X="test -x"
+  fi
+
+  ifelse([$4], [], [
+         ifdef(AC_WARNING,AC_WARNING([$0: missing argument 4 (acceptable-majors): Defaulting to APR 0.x then APR 1.x]))
+         acceptable_majors="0 1"],
+         [acceptable_majors="$4"])
+
+  apr_temp_acceptable_apr_config=""
+  for apr_temp_major in $acceptable_majors
+  do
+    case $apr_temp_major in
+      0)
+      apr_temp_acceptable_apr_config="$apr_temp_acceptable_apr_config apr-config"
+      ;;
+      *)
+      apr_temp_acceptable_apr_config="$apr_temp_acceptable_apr_config apr-$apr_temp_major-config"
+      ;;
+    esac
+  done
+
+  AC_MSG_CHECKING(for APR)
+  AC_ARG_WITH(apr,
+  [  --with-apr=PATH         prefix for installed APR or the full path to 
+                             apr-config],
+  [
+    if test "$withval" = "no" || test "$withval" = "yes"; then
+      AC_MSG_ERROR([--with-apr requires a directory or file to be provided])
+    fi
+
+    for apr_temp_apr_config_file in $apr_temp_acceptable_apr_config
+    do
+      for lookdir in "$withval/bin" "$withval"
+      do
+        if $TEST_X "$lookdir/$apr_temp_apr_config_file"; then
+          apr_config="$lookdir/$apr_temp_apr_config_file"
+          ifelse([$5], [], [], [
+          apr_acceptable="yes"
+          $5
+          if test "$apr_acceptable" != "yes"; then
+            AC_MSG_WARN([Found APR in $apr_config, but we think it is considered unacceptable])
+            continue
+          fi])
+          apr_found="yes"
+          break 2
+        fi
+      done
+    done
+
+    if test "$apr_found" != "yes" && $TEST_X "$withval" && $withval --help > /dev/null 2>&1 ; then
+      apr_config="$withval"
+      ifelse([$5], [], [apr_found="yes"], [
+          apr_acceptable="yes"
+          $5
+          if test "$apr_acceptable" = "yes"; then
+                apr_found="yes"
+          fi])
+    fi
+
+    dnl if --with-apr is used, it is a fatal error for its argument
+    dnl to be invalid
+    if test "$apr_found" != "yes"; then
+      AC_MSG_ERROR([the --with-apr parameter is incorrect. It must specify an install prefix, a build directory, or an apr-config file.])
+    fi
+  ],[
+    dnl If we allow installed copies, check those before using bundled copy.
+    if test -n "$3" && test "$3" = "1"; then
+      for apr_temp_apr_config_file in $apr_temp_acceptable_apr_config
+      do
+        if $apr_temp_apr_config_file --help > /dev/null 2>&1 ; then
+          apr_config="$apr_temp_apr_config_file"
+          ifelse([$5], [], [], [
+          apr_acceptable="yes"
+          $5
+          if test "$apr_acceptable" != "yes"; then
+            AC_MSG_WARN([skipped APR at $apr_config, version not acceptable])
+            continue
+          fi])
+          apr_found="yes"
+          break
+        else
+          dnl look in some standard places
+          for lookdir in /usr /usr/local /usr/local/apr /opt/apr; do
+            if $TEST_X "$lookdir/bin/$apr_temp_apr_config_file"; then
+              apr_config="$lookdir/bin/$apr_temp_apr_config_file"
+              ifelse([$5], [], [], [
+              apr_acceptable="yes"
+              $5
+              if test "$apr_acceptable" != "yes"; then
+                AC_MSG_WARN([skipped APR at $apr_config, version not acceptable])
+                continue
+              fi])
+              apr_found="yes"
+              break 2
+            fi
+          done
+        fi
+      done
+    fi
+    dnl if we have not found anything yet and have bundled source, use that
+    if test "$apr_found" = "no" && test -d "$1"; then
+      apr_temp_abs_srcdir="`cd \"$1\" && pwd`"
+      apr_found="reconfig"
+      apr_bundled_major="`sed -n '/#define.*APR_MAJOR_VERSION/s/^[^0-9]*\([0-9]*\).*$/\1/p' \"$1/include/apr_version.h\"`"
+      case $apr_bundled_major in
+        "")
+          AC_MSG_ERROR([failed to find major version of bundled APR])
+        ;;
+        0)
+          apr_temp_apr_config_file="apr-config"
+        ;;
+        *)
+          apr_temp_apr_config_file="apr-$apr_bundled_major-config"
+        ;;
+      esac
+      if test -n "$2"; then
+        apr_config="$2/$apr_temp_apr_config_file"
+      else
+        apr_config="$1/$apr_temp_apr_config_file"
+      fi
+    fi
+  ])
+
+  AC_MSG_RESULT($apr_found)
+])
diff --git a/build/fixwin32mak.pl b/build/fixwin32mak.pl
new file mode 100644
index 00000000000..6f53987ecf8
--- /dev/null
+++ b/build/fixwin32mak.pl
@@ -0,0 +1,167 @@
+#
+# fixwin32mak.pl ::: Apache/Win32 maintanace program
+#
+# This program, launched from the build/ directory, replaces all nasty absoulute paths
+# in the win32 .mak files with the appropriate relative root.
+#
+# Run this program prior to committing or packaging any newly exported make files.
+
+use Cwd;
+use IO::File;
+use File::Find;
+
+$root = cwd;
+# ignore our own direcory (allowing us to move into any parallel tree)
+$root =~ s|^.:(.*)?$|cd "$1|;
+$root =~ s|/|\\\\|g;
+$altroot = $root;
+$altroot =~ s| ".:| "|;
+print "Stripping " . $root . " and " . $altroot . "\n";
+find(\&fixcwd, '.');
+
+# Given this pattern that disregarded the RECURSE flag...
+#
+# !IF "$(RECURSE)" == "0" 
+# 
+# ALL : "$(OUTDIR)\mod_charset_lite.so"
+# 
+# !ELSE 
+# 
+# ALL : "libhttpd - Win32 Release" "libaprutil - Win32 Release" "libapr - Win32 Release" "$(OUTDIR)\mod_charset_lite.so"
+# 
+# !ENDIF 
+#...
+# DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep
+#...
+# ALL : $(DS_POSTBUILD_DEP)
+#
+# $(DS_POSTBUILD_DEP) : "libhttpd - Win32 Release" "libaprutil - Win32 Release" "libapr - Win32 Release" "$(OUTDIR)\mod_charset_lite.so"
+#
+# we will axe the final ALL : clause,
+# strip all but the final element from $(DS_POSTBUILD_DEP) : clause
+# move the DS_POSTBUILD_DEP assignment above the IF (for true ALL : targets)
+# and in pass 2, append the $(DS_POSTBUILD_DEP) to the valid ALL : targets
+
+
+sub fixcwd { 
+    if (m|.mak$|) {
+        $thisroot = $File::Find::dir;
+        $thisroot =~ s|^./(.*)$|$1|;
+        $thisroot =~ s|/|\\\\|g;
+        $thisroot = $root . "\\\\" . $thisroot;
+        $thisaltroot = $altroot . "\\\\" . $thisroot;
+        $oname = $_;
+        $tname = '.#' . $_;
+        $verchg = 0;
+        $postdep = 0;
+        $srcfl = new IO::File $_, "r" || die;
+        $dstfl = new IO::File $tname, "w" || die;
+        while ($src = <$srcfl>) {
+            if ($src =~ m|^DS_POSTBUILD_DEP=.+$|) {
+                $postdepval = $src;
+            }
+            if ($src =~ s|^ALL : \$\(DS_POSTBUILD_DEP\)||) {
+                $postdep = -1;
+                $verchg = -1;
+                $src = <$srcfl>;
+                $src = <$srcfl> if ($src =~ m|^$|);
+            }
+            if ($postdep) {
+                $src =~ s|^(\$\(DS_POSTBUILD_DEP\)) :.+(\"[^\"]+\")$|"$1" : $2|;
+            }
+            if ($src =~ m|^\s*($root[^\"]*)\".*$|) {
+                $orig = $thisroot;
+            } elsif ($src =~ m|^\s*($altroot[^\"]*)\".*$|) {
+                $orig = $thisaltroot;
+            }
+            if (defined($orig)) {
+                $repl = "cd \".";
+                while (!($src =~ s|$orig|$repl|)) {
+                   if (!($orig =~ s|^(.*)\\\\[^\\]+$|$1|)) {
+                       break;
+                   }
+                   $repl .= "\\..";
+                }
+                print "Replaced " . $orig . " with " . $repl . "\n";
+                $verchg = -1;
+                undef $orig;
+            }
+            # With modern LINK.EXE linkers, there is a different LINK for
+            # each platform, and it's determined by the file path.  Best
+            # that here, after we compiled the code to the default CPU,
+            # that we also link here to the default CPU.  Omitting the
+            # /machine spec from the .dsp was not enough, MSVC put it back.
+            #
+            if ($src =~ s#^(LINK32_FLAGS=.*) /machine:(x|IX|I3)86 #$1 #i) {
+                $verchg = -1;
+            }
+            print $dstfl $src; 
+        }
+        undef $srcfl;
+        undef $dstfl;
+        if ($verchg) {
+            if ($postdep) {
+                $srcfl = new IO::File $tname, "r" || die;
+                $dstfl = new IO::File $oname, "w" || die;
+                while ($src = <$srcfl>) {
+                    if ($src =~ m|^INTDIR=|) {
+                        print $dstfl $src;
+                        $src = $postdepval;
+                    }
+                    $src =~ s|^(ALL : .+)$|$1 "\$\(DS_POSTBUILD_DEP\)"|;
+                    print $dstfl $src;
+                }
+                undef $srcfl;
+                undef $dstfl;
+                unlink $tname || die;
+                print "Corrected post-dependency within " . $oname . " in " . $File::Find::dir . "\n"; 
+            }
+            else {
+                unlink $oname || die;
+                rename $tname, $oname || die;
+                print "Corrected absolute paths within " . $oname . " in " . $File::Find::dir . "\n"; 
+            }
+        }
+        else {
+            unlink $tname;
+        }
+        $dname = $oname;
+        $dname =~ s/.mak$/.dsp/;
+        @dstat = stat($dname);
+        @ostat = stat($oname);    
+        if ($ostat[9] && $dstat[9] && ($ostat[9] != $dstat[9])) {
+            @onames = ($oname);
+            utime $dstat[9], $dstat[9], @onames;
+            print "Touched datestamp for " . $oname . " in " . $File::Find::dir . "\n"; 
+        }
+        $oname =~ s/.mak$/.dep/;
+        $verchg = 0;
+        $srcfl = new IO::File $oname, "r" || die;
+        $dstfl = new IO::File $tname, "w" || die;
+        while ($src = <$srcfl>) {
+            if (($src =~ m/^\t"(\.\.\\)+(apr|apr-util|apr-iconv)\\.*"\\/) || 
+                ($src =~ m/^\t\{\$\(INCLUDE\)\}".*"\\/)) {
+                $verchg = -1;
+            }
+            else {
+                print $dstfl $src;
+            }
+        }
+        undef $srcfl;
+        undef $dstfl;
+        if ($verchg) {
+            unlink $oname || die;
+            rename $tname, $oname || die;
+            print "Stripped external dependencies from " . $oname . " in " . $File::Find::dir . "\n"; 
+        }
+        else {
+            unlink $tname || die;
+        }
+        @ostat = stat($oname);    
+        if ($ostat[9] && $dstat[9] && ($ostat[9] != $dstat[9])) {
+            @onames = ($oname);
+            utime $dstat[9], $dstat[9], @onames;
+            print "Touched datestamp for " . $oname . " in " . $File::Find::dir . "\n"; 
+        }
+    }
+}
diff --git a/build/gen-build.py b/build/gen-build.py
new file mode 100755
index 00000000000..054422abcde
--- /dev/null
+++ b/build/gen-build.py
@@ -0,0 +1,247 @@
+#!/usr/bin/env python
+#
+# USAGE: gen-build.py TYPE
+#
+# where TYPE is one of: make, dsp, vcproj
+#
+# It reads build.conf from the current directory, and produces its output
+# into the current directory.
+#
+
+
+import os
+import ConfigParser
+import getopt
+import string
+import glob
+import re
+
+#import ezt
+
+#
+# legal platforms: aix, beos, netware, os2, os390, unix, win32
+# 'make' users: aix, beos, os2, os390, unix, win32 (mingw)
+#
+PLATFORMS = [ 'aix', 'beos', 'netware', 'os2', 'os390', 'unix', 'win32' ]
+MAKE_PLATFORMS = [
+  ('unix', None),
+  ('aix', 'unix'),
+  ('beos', 'unix'),
+  ('os2', 'unix'),
+  ('os390', 'unix'),
+  ('win32', 'unix'),
+  ]
+# note: MAKE_PLATFORMS is an ordered set. we want to generate unix symbols
+#       first, so that the later platforms can reference them.
+
+
+def main():
+  parser = ConfigParser.ConfigParser()
+  parser.read('build.conf')
+
+  if parser.has_option('options', 'dsp'):
+    dsp_file = parser.get('options', 'dsp')
+  else:
+    dsp_file = None
+
+  headers = get_files(parser.get('options', 'headers'))
+
+  # compute the relevant headers, along with the implied includes
+  legal_deps = { }
+  for fname in headers:
+    legal_deps[os.path.basename(fname)] = fname
+
+  h_deps = { }
+  for fname in headers:
+    h_deps[os.path.basename(fname)] = extract_deps(fname, legal_deps)
+  resolve_deps(h_deps)
+
+  f = open('build-outputs.mk', 'w')
+  f.write('# DO NOT EDIT. AUTOMATICALLY GENERATED.\n\n')
+
+  # write out the platform-independent files
+  files = get_files(parser.get('options', 'paths'))
+  objects, dirs = write_objects(f, legal_deps, h_deps, files)
+  f.write('\nOBJECTS_all = %s\n\n' % string.join(objects))
+
+  # for each platform and each subdirectory holding platform-specific files,
+  # write out their compilation rules, and an OBJECT_<subdir>_<plat> symbol.
+  for platform, parent in MAKE_PLATFORMS:
+
+    # record the object symbols to build for each platform
+    group = [ '$(OBJECTS_all)' ]
+
+    # If we're doing win32, we're going to look in the libapr.dsp file
+    # for those files that we have to manually add to our list.
+    inherit_parent = { }
+    if platform == 'win32' and dsp_file:
+      for line in open(dsp_file).readlines():
+        if line[:7] != 'SOURCE=':
+          continue
+        if line[7:].find('unix') != -1:
+          # skip the leading .\ and split it out
+          inherit_files = line[9:].strip().split('\\')
+          # change the .c to .lo
+          assert inherit_files[-1][-2:] == '.c'
+          inherit_files[-1] = inherit_files[-1][:-2] + '.lo'
+          # replace the \\'s with /'s
+          inherit_line = '/'.join(inherit_files)
+          if not inherit_parent.has_key(inherit_files[0]):
+            inherit_parent[inherit_files[0]] = []
+          inherit_parent[inherit_files[0]].append(inherit_line)
+
+    for subdir in string.split(parser.get('options', 'platform_dirs')):
+      path = '%s/%s' % (subdir, platform)
+      if not os.path.exists(path):
+        # this subdir doesn't have a subdir for this platform, so we'll
+        # use the parent-platform's set of symbols
+        if parent:
+          group.append('$(OBJECTS_%s_%s)' % (subdir, parent))
+        continue
+
+      # remember that this directory has files/objects
+      dirs[path] = None
+
+      # write out the compilation lines for this subdir
+      files = get_files(path + '/*.c')
+      objects, _unused = write_objects(f, legal_deps, h_deps, files)
+
+      if inherit_parent.has_key(subdir):
+        objects = objects + inherit_parent[subdir]
+
+      symname = 'OBJECTS_%s_%s' % (subdir, platform)
+
+      objects.sort()
+
+      # and write the symbol for the whole group
+      f.write('\n%s = %s\n\n' % (symname, string.join(objects)))
+
+      # and include that symbol in the group
+      group.append('$(%s)' % symname)
+
+    group.sort()
+
+    # write out a symbol which contains the necessary files
+    f.write('OBJECTS_%s = %s\n\n' % (platform, string.join(group)))
+
+  f.write('HEADERS = $(top_srcdir)/%s\n\n' % string.join(headers, ' $(top_srcdir)/'))
+  f.write('SOURCE_DIRS = %s $(EXTRA_SOURCE_DIRS)\n\n' % string.join(dirs.keys()))
+
+  if parser.has_option('options', 'modules'):
+    modules = parser.get('options', 'modules')
+
+    for mod in string.split(modules):
+      files = get_files(parser.get(mod, 'paths'))
+      objects, _unused = write_objects(f, legal_deps, h_deps, files)
+      flat_objects = string.join(objects)
+      f.write('OBJECTS_%s = %s\n' % (mod, flat_objects))
+
+      if parser.has_option(mod, 'target'):
+        target = parser.get(mod, 'target')
+        f.write('MODULE_%s = %s\n' % (mod, target))
+        f.write('%s: %s\n' % (target, flat_objects))
+        f.write('\t$(LINK_MODULE) -o $@ $(OBJECTS_%s) $(LDADD_%s)\n' % (mod, mod))
+
+      f.write('\n')
+
+  if parser.has_option('options', 'libraries'):
+    libs = parser.get('options', 'libraries')
+
+    for lib in string.split(libs):
+      files = get_files(parser.get(lib, 'paths'))
+      objects, _unused = write_objects(f, legal_deps, h_deps, files)
+      flat_objects = string.join(objects)
+      f.write('OBJECTS_%s = %s\n' % (lib, flat_objects))
+
+      if parser.has_option(lib, 'target'):
+        target = parser.get(lib, 'target')
+        f.write('MODULE_%s = %s\n' % (lib, target))
+        f.write('%s: $(OBJECTS_%s)\n' % (target, lib))
+        f.write('\t$(LINK_LIBRARY) -o $@ $(OBJECTS_%s) $(LDADD_%s)\n' % (lib, lib))
+
+      f.write('\n')
+
+  # Build a list of all necessary directories in build tree
+  alldirs = { }
+  for dir in dirs.keys():
+    d = dir
+    while d:
+      alldirs[d] = None
+      d = os.path.dirname(d)
+
+  # Sort so 'foo' is before 'foo/bar'
+  keys = alldirs.keys()
+  keys.sort()
+  f.write('BUILD_DIRS = %s\n\n' % string.join(keys))
+
+  f.write('.make.dirs: $(srcdir)/build-outputs.mk\n' \
+          '\t@for d in $(BUILD_DIRS); do test -d $$d || mkdir $$d; done\n' \
+          '\t@echo timestamp > $@\n')
+
+
+def write_objects(f, legal_deps, h_deps, files):
+  dirs = { }
+  objects = [ ]
+
+  for file in files:
+    if file[-10:] == '/apr_app.c':
+      continue
+    assert file[-2:] == '.c'
+    obj = file[:-2] + '.lo'
+    objects.append(obj)
+
+    dirs[os.path.dirname(file)] = None
+
+    # what headers does this file include, along with the implied headers
+    deps = extract_deps(file, legal_deps)
+    for hdr in deps.keys():
+      deps.update(h_deps.get(hdr, {}))
+
+    vals = deps.values()
+    vals.sort()
+    f.write('%s: %s .make.dirs %s\n' % (obj, file, string.join(vals)))
+
+  objects.sort()
+
+  return objects, dirs
+
+
+def extract_deps(fname, legal_deps):
+  "Extract the headers this file includes."
+  deps = { }
+  for line in open(fname).readlines():
+    if line[:8] != '#include':
+      continue
+    inc = _re_include.match(line).group(1)
+    if inc in legal_deps.keys():
+      deps[inc] = legal_deps[inc]
+  return deps
+_re_include = re.compile('#include *["<](.*)[">]')
+
+
+def resolve_deps(header_deps):
+  "Alter the provided dictionary to flatten includes-of-includes."
+  altered = 1
+  while altered:
+    altered = 0
+    for hdr, deps in header_deps.items():
+      # print hdr, deps
+      start = len(deps)
+      for dep in deps.keys():
+        deps.update(header_deps.get(dep, {}))
+      if len(deps) != start:
+        altered = 1
+
+def clean_path(path):
+    return path.replace("\\", "/")
+
+def get_files(patterns):
+  files = [ ]
+  for pat in string.split(patterns):
+    files.extend(map(clean_path, glob.glob(pat)))
+  files.sort()
+  return files
+
+
+if __name__ == '__main__':
+  main()
diff --git a/build/get-version.sh b/build/get-version.sh
new file mode 100755
index 00000000000..fd685b22a8d
--- /dev/null
+++ b/build/get-version.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+#
+# extract version numbers from a header file
+#
+# USAGE: get-version.sh CMD VERSION_HEADER PREFIX
+#   where CMD is one of: all, major, libtool
+#   where PREFIX is the prefix to {MAJOR|MINOR|PATCH}_VERSION defines
+#
+#   get-version.sh all returns a dotted version number
+#   get-version.sh major returns just the major version number
+#   get-version.sh libtool returns a version "libtool -version-info" format
+#
+
+if test $# != 3; then
+  echo "USAGE: $0 CMD VERSION_HEADER PREFIX"
+  echo "  where CMD is one of: all, major, libtool"
+  exit 1
+fi
+
+major_sed="/#define.*$3_MAJOR_VERSION/s/^[^0-9]*\([0-9]*\).*$/\1/p"
+minor_sed="/#define.*$3_MINOR_VERSION/s/^[^0-9]*\([0-9]*\).*$/\1/p"
+patch_sed="/#define.*$3_PATCH_VERSION/s/^[^0-9]*\([0-9]*\).*$/\1/p"
+major="`sed -n $major_sed $2`"
+minor="`sed -n $minor_sed $2`"
+patch="`sed -n $patch_sed $2`"
+
+if test "$1" = "all"; then
+  echo ${major}.${minor}.${patch}
+elif test "$1" = "major"; then
+  echo ${major}
+elif test "$1" = "libtool"; then
+  # Yes, ${minor}:${patch}:${minor} is correct due to libtool idiocy.
+  echo ${minor}:${patch}:${minor}
+else
+  echo "ERROR: unknown version CMD ($1)"
+  exit 1
+fi
diff --git a/build/iconv.m4 b/build/iconv.m4
new file mode 100644
index 00000000000..f6eba10e7bb
--- /dev/null
+++ b/build/iconv.m4
@@ -0,0 +1,119 @@
+dnl -------------------------------------------------------- -*- autoconf -*-
+dnl Licensed to the Apache Software Foundation (ASF) under one or more
+dnl contributor license agreements.  See the NOTICE file distributed with
+dnl this work for additional information regarding copyright ownership.
+dnl The ASF licenses this file to You under the Apache License, Version 2.0
+dnl (the "License"); you may not use this file except in compliance with
+dnl the License.  You may obtain a copy of the License at
+dnl
+dnl     http://www.apache.org/licenses/LICENSE-2.0
+dnl
+dnl Unless required by applicable law or agreed to in writing, software
+dnl distributed under the License is distributed on an "AS IS" BASIS,
+dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+dnl See the License for the specific language governing permissions and
+dnl limitations under the License.
+
+dnl
+dnl APU_TRY_ICONV[ IF-SUCCESS, IF-FAILURE ]: try to compile for iconv.
+dnl
+AC_DEFUN([APU_TRY_ICONV], [
+  AC_TRY_LINK([
+#include <stdlib.h>
+#include <iconv.h>
+],
+[
+  iconv_t cd = iconv_open("", "");
+  iconv(cd, NULL, NULL, NULL, NULL);
+], [$1], [$2])
+])
+
+dnl
+dnl APU_FIND_ICONV: find an iconv library
+dnl
+AC_DEFUN([APU_FIND_ICONV], [
+
+apu_iconv_dir="unknown"
+want_iconv="1"
+AC_ARG_WITH(iconv,[  --with-iconv[=DIR]        path to iconv installation],
+  [ apu_iconv_dir="$withval"
+    if test "$apu_iconv_dir" = "no"; then
+      have_iconv="0"
+      want_iconv="0"
+    elif test "$apu_iconv_dir" != "yes"; then
+      if test -f "$apu_iconv_dir/include/iconv.h"; then
+        have_iconv="1"
+        APR_ADDTO(CPPFLAGS,[-I$apu_iconv_dir/include])
+        APR_ADDTO(LDFLAGS,[-L$apu_iconv_dir/lib])
+      fi
+    fi
+  ])
+
+if test "$want_iconv" = "1"; then
+  AC_CHECK_HEADER(iconv.h, [
+    APU_TRY_ICONV([ have_iconv="1" ], [
+
+    APR_ADDTO(LIBS,[-liconv])
+
+    APU_TRY_ICONV([
+      APR_ADDTO(LIBS,[-liconv])
+      APR_ADDTO(APRUTIL_EXPORT_LIBS,[-liconv])
+      have_iconv="1" ],
+      [ have_iconv="0" ])
+
+    APR_REMOVEFROM(LIBS,[-liconv])
+
+    ])
+  ], [ have_iconv="0" ])
+fi
+
+if test "$want_iconv" = "1" -a "$apu_iconv_dir" != "unknown"; then
+  if test "$have_iconv" != "1"; then
+    AC_MSG_ERROR([iconv support requested, but not found])
+  fi
+  APR_REMOVEFROM(CPPFLAGS,[-I$apu_iconv_dir/include])
+  APR_ADDTO(INCLUDES,[-I$apu_iconv_dir/include])
+  APR_ADDTO(LDFLAGS,[-L$apu_iconv_dir/lib])
+fi
+
+if test "$have_iconv" = "1"; then
+  APU_CHECK_ICONV_INBUF
+fi
+
+APR_FLAG_HEADERS(iconv.h langinfo.h)
+APR_FLAG_FUNCS(nl_langinfo)
+APR_CHECK_DEFINE(CODESET, langinfo.h, [CODESET defined in langinfo.h])
+
+AC_SUBST(have_iconv)
+])dnl
+
+dnl
+dnl APU_CHECK_ICONV_INBUF
+dnl
+dnl  Decide whether or not the inbuf parameter to iconv() is const.
+dnl
+dnl  We try to compile something without const.  If it fails to 
+dnl  compile, we assume that the system's iconv() has const.  
+dnl  Unfortunately, we won't realize when there was a compile
+dnl  warning, so we allow a variable -- apu_iconv_inbuf_const -- to
+dnl  be set in hints.m4 to specify whether or not iconv() has const
+dnl  on this parameter.
+dnl
+AC_DEFUN([APU_CHECK_ICONV_INBUF], [
+AC_MSG_CHECKING(for type of inbuf parameter to iconv)
+if test "x$apu_iconv_inbuf_const" = "x"; then
+    APR_TRY_COMPILE_NO_WARNING([
+    #include <stddef.h>
+    #include <iconv.h>
+    ],[
+    iconv(0,(char **)0,(size_t *)0,(char **)0,(size_t *)0);
+    ], apu_iconv_inbuf_const="0", apu_iconv_inbuf_const="1")
+fi
+if test "$apu_iconv_inbuf_const" = "1"; then
+    AC_DEFINE(APU_ICONV_INBUF_CONST, 1, [Define if the inbuf parm to iconv() is const char **])
+    msg="const char **"
+else
+    msg="char **"
+fi
+AC_MSG_RESULT([$msg])
+])dnl
diff --git a/helpers/install.sh b/build/install.sh
similarity index 100%
rename from helpers/install.sh
rename to build/install.sh
diff --git a/build/jlibtool.c b/build/jlibtool.c
new file mode 100644
index 00000000000..892e26d5653
--- /dev/null
+++ b/build/jlibtool.c
@@ -0,0 +1,2056 @@
+/* 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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#if !defined(__MINGW32__)
+#include <sys/wait.h>
+#endif
+#include <unistd.h>
+#include <dirent.h>
+#include <errno.h>
+#include <assert.h>
+
+#ifdef __EMX__
+#  define SHELL_CMD  "sh"
+#  define GEN_EXPORTS "emxexp"
+#  define DEF2IMPLIB_CMD "emximp"
+#  define SHARE_SW   "-Zdll -Zmtd"
+#  define USE_OMF 1
+#  define TRUNCATE_DLL_NAME
+#  define DYNAMIC_LIB_EXT "dll"
+#  define EXE_EXT ".exe"
+
+#  if USE_OMF
+     /* OMF is the native format under OS/2 */
+#    define STATIC_LIB_EXT "lib"
+#    define OBJECT_EXT     "obj"
+#    define LIBRARIAN      "emxomfar"
+#    define LIBRARIAN_OPTS "cr"
+#  else
+     /* but the alternative, a.out, can fork() which is sometimes necessary */
+#    define STATIC_LIB_EXT "a"
+#    define OBJECT_EXT     "o"
+#    define LIBRARIAN      "ar"
+#    define LIBRARIAN_OPTS "cr"
+#  endif
+#endif
+
+#if defined(__APPLE__)
+#  define SHELL_CMD  "/bin/sh"
+#  define DYNAMIC_LIB_EXT "dylib"
+#  define MODULE_LIB_EXT  "bundle"
+#  define STATIC_LIB_EXT "a"
+#  define OBJECT_EXT     "o"
+#  define LIBRARIAN      "ar"
+#  define LIBRARIAN_OPTS "cr"
+/* man libtool(1) documents ranlib option of -c.  */
+#  define RANLIB "ranlib"
+#  define PIC_FLAG "-fPIC -fno-common"
+#  define SHARED_OPTS "-dynamiclib"
+#  define MODULE_OPTS "-bundle -dynamic"
+#  define DYNAMIC_LINK_OPTS "-flat_namespace"
+#  define DYNAMIC_LINK_UNDEFINED "-undefined suppress"
+#  define dynamic_link_version_func darwin_dynamic_link_function
+#  define DYNAMIC_INSTALL_NAME "-install_name"
+#  define DYNAMIC_LINK_NO_INSTALL "-dylib_file"
+#  define HAS_REALPATH
+/*-install_name  /Users/jerenk/apache-2.0-cvs/lib/libapr.0.dylib -compatibility_version 1 -current_version 1.0 */
+#  define LD_LIBRARY_PATH "DYLD_LIBRARY_PATH"
+#endif
+
+#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__)
+#  define SHELL_CMD  "/bin/sh"
+#  define DYNAMIC_LIB_EXT "so"
+#  define MODULE_LIB_EXT  "so"
+#  define STATIC_LIB_EXT "a"
+#  define OBJECT_EXT     "o"
+#  define LIBRARIAN      "ar"
+#  define LIBRARIAN_OPTS "cr"
+#  define RANLIB "ranlib"
+#  define PIC_FLAG "-fPIC"
+#  define RPATH "-rpath"
+#  define SHARED_OPTS "-shared"
+#  define MODULE_OPTS "-shared"
+#  define DYNAMIC_LINK_OPTS "-export-dynamic"
+#  define LINKER_FLAG_PREFIX "-Wl,"
+#  define ADD_MINUS_L
+#  define LD_RUN_PATH "LD_RUN_PATH"
+#  define LD_LIBRARY_PATH "LD_LIBRARY_PATH"
+#endif
+
+#if defined(sun)
+#  define SHELL_CMD  "/bin/sh"
+#  define DYNAMIC_LIB_EXT "so"
+#  define MODULE_LIB_EXT  "so"
+#  define STATIC_LIB_EXT "a"
+#  define OBJECT_EXT     "o"
+#  define LIBRARIAN      "ar"
+#  define LIBRARIAN_OPTS "cr"
+#  define RANLIB "ranlib"
+#  define PIC_FLAG "-KPIC"
+#  define RPATH "-R"
+#  define SHARED_OPTS "-G"
+#  define MODULE_OPTS "-G"
+#  define DYNAMIC_LINK_OPTS ""
+#  define LINKER_FLAG_NO_EQUALS
+#  define ADD_MINUS_L
+#  define HAS_REALPATH
+#  define LD_RUN_PATH "LD_RUN_PATH"
+#  define LD_LIBRARY_PATH "LD_LIBRARY_PATH"
+#endif
+
+#if defined(_OSD_POSIX)
+#  define SHELL_CMD  "/usr/bin/sh"
+#  define DYNAMIC_LIB_EXT "so"
+#  define MODULE_LIB_EXT  "so"
+#  define STATIC_LIB_EXT "a"
+#  define OBJECT_EXT     "o"
+#  define LIBRARIAN      "ar"
+#  define LIBRARIAN_OPTS "cr"
+#  define SHARED_OPTS "-G"
+#  define MODULE_OPTS "-G"
+#  define LINKER_FLAG_PREFIX "-Wl,"
+#  define NEED_SNPRINTF
+#endif
+
+#if defined(sinix) && defined(mips) && defined(__SNI_TARG_UNIX)
+#  define SHELL_CMD  "/usr/bin/sh"
+#  define DYNAMIC_LIB_EXT "so"
+#  define MODULE_LIB_EXT  "so"
+#  define STATIC_LIB_EXT "a"
+#  define OBJECT_EXT     "o"
+#  define LIBRARIAN      "ar"
+#  define LIBRARIAN_OPTS "cr"
+#  define RPATH "-Brpath"
+#  define SHARED_OPTS "-G"
+#  define MODULE_OPTS "-G"
+#  define DYNAMIC_LINK_OPTS "-Wl,-Blargedynsym"
+#  define LINKER_FLAG_PREFIX "-Wl,"
+#  define NEED_SNPRINTF
+#  define LD_RUN_PATH "LD_RUN_PATH"
+#  define LD_LIBRARY_PATH "LD_LIBRARY_PATH"
+#endif
+
+#if defined(__MINGW32__)
+#  define SHELL_CMD "sh"
+#  define DYNAMIC_LIB_EXT "dll"
+#  define MODULE_LIB_EXT  "dll"
+#  define STATIC_LIB_EXT "a"
+#  define OBJECT_EXT     "o"
+#  define LIBRARIAN      "ar"
+#  define LIBRARIAN_OPTS "cr"
+#  define RANLIB "ranlib"
+#  define LINKER_FLAG_PREFIX "-Wl,"
+#  define SHARED_OPTS "-shared"
+#  define MODULE_OPTS "-shared"
+#  define MKDIR_NO_UMASK
+#  define EXE_EXT ".exe"
+#endif
+
+#ifndef SHELL_CMD
+#error Unsupported platform: Please add defines for SHELL_CMD etc. for your platform.
+#endif
+
+#ifdef NEED_SNPRINTF
+#include <stdarg.h>
+#endif
+
+#ifdef __EMX__
+#include <process.h>
+#endif
+
+#ifndef PATH_MAX
+#define PATH_MAX 1024
+#endif
+
+
+/* We want to say we are libtool 1.4 for shlibtool compatibility. */
+#define VERSION "1.4"
+
+enum tool_mode_t {
+    mUnknown,
+    mCompile,
+    mLink,
+    mInstall,
+};
+
+enum output_t {
+    otGeneral,
+    otObject,
+    otProgram,
+    otLibrary,
+    otStaticLibraryOnly,
+    otDynamicLibraryOnly,
+    otModule,
+};
+
+enum pic_mode_e {
+    pic_UNKNOWN,
+    pic_PREFER,
+    pic_AVOID,
+};
+
+enum shared_mode_e {
+    share_UNSET,
+    share_STATIC,
+    share_SHARED,
+};
+
+enum lib_type {
+    type_UNKNOWN,
+    type_DYNAMIC_LIB,
+    type_STATIC_LIB,
+    type_MODULE_LIB,
+    type_OBJECT,
+};
+
+typedef struct {
+    const char **vals;
+    int num; 
+} count_chars;
+
+typedef struct {
+    const char *normal;
+    const char *install;
+} library_name;
+
+typedef struct {
+    count_chars *normal;
+    count_chars *install;
+    count_chars *dependencies;
+} library_opts;
+
+typedef struct {
+    int silent;
+    enum shared_mode_e shared;
+    int export_all;
+    int dry_run;
+    enum pic_mode_e pic_mode;
+    int export_dynamic;
+    int no_install;
+} options_t;
+
+typedef struct {
+    enum tool_mode_t mode;
+    enum output_t output;
+    options_t options;
+
+    char *output_name;
+    char *fake_output_name;
+    char *basename;
+
+    const char *install_path;
+    const char *compiler;
+    const char *program;
+    count_chars *program_opts;
+
+    count_chars *arglist;
+    count_chars *tmp_dirs;
+    count_chars *obj_files;
+    count_chars *dep_rpaths;
+    count_chars *rpaths;
+
+    library_name static_name;
+    library_name shared_name;
+    library_name module_name;
+
+    library_opts static_opts;
+    library_opts shared_opts;
+
+    const char *version_info;
+    const char *undefined_flag;
+} command_t;
+
+#ifdef RPATH
+void add_rpath(count_chars *cc, const char *path);
+#endif
+
+#if defined(NEED_SNPRINTF)
+/* Write at most n characters to the buffer in str, return the
+ * number of chars written or -1 if the buffer would have been
+ * overflowed.
+ *
+ * This is portable to any POSIX-compliant system has /dev/null
+ */
+static FILE *f=NULL;
+static int vsnprintf( char *str, size_t n, const char *fmt, va_list ap )
+{
+       int res;
+
+       if (f == NULL)
+               f = fopen("/dev/null","w");
+       if (f == NULL)
+               return -1;
+
+       setvbuf( f, str, _IOFBF, n );
+
+       res = vfprintf( f, fmt, ap );
+
+       if ( res > 0 && res < n ) {
+               res = vsprintf( str, fmt, ap );
+       }
+       return res;
+}
+static int snprintf( char *str, size_t n, const char *fmt, ... )
+{
+        va_list ap;
+        int res;
+ 
+        va_start( ap, fmt );
+        res = vsnprintf( str, n, fmt, ap );
+        va_end( ap );
+        return res;
+}
+#endif
+
+void init_count_chars(count_chars *cc)
+{
+    cc->vals = (const char**)malloc(PATH_MAX*sizeof(char*));
+    cc->num = 0;
+}
+
+void clear_count_chars(count_chars *cc)
+{
+    int i;
+    for (i = 0; i < cc->num; i++) {
+        cc->vals[i] = 0;
+    }
+
+    cc->num = 0;
+}
+
+void push_count_chars(count_chars *cc, const char *newval)
+{
+    cc->vals[cc->num++] = newval;
+}
+
+void pop_count_chars(count_chars *cc)
+{
+    cc->num--;
+}
+
+void insert_count_chars(count_chars *cc, const char *newval, int position)
+{
+    int i;
+
+    for (i = cc->num; i > position; i--) {
+        cc->vals[i] = cc->vals[i-1];
+    }
+
+    cc->vals[position] = newval;
+    cc->num++;
+}
+
+void append_count_chars(count_chars *cc, count_chars *cctoadd)
+{
+    int i;
+    for (i = 0; i < cctoadd->num; i++) {
+        if (cctoadd->vals[i]) {
+            push_count_chars(cc, cctoadd->vals[i]);
+        }
+    }
+}
+
+const char *flatten_count_chars(count_chars *cc, int space)
+{
+    int i, size;
+    char *newval;
+
+    size = 0;
+    for (i = 0; i < cc->num; i++) {
+        if (cc->vals[i]) {
+            size += strlen(cc->vals[i]) + 1;
+            if (space) {
+              size++;
+            }
+        }
+    }
+
+    newval = (char*)malloc(size + 1);
+    newval[0] = 0;
+
+    for (i = 0; i < cc->num; i++) {
+        if (cc->vals[i]) {
+            strcat(newval, cc->vals[i]);
+            if (space) {
+                strcat(newval, " ");
+            }
+        }
+    }
+
+    return newval;
+}
+
+char *shell_esc(const char *str)
+{
+    int in_quote = 0;
+    char *cmd;
+    unsigned char *d;
+    const unsigned char *s;
+
+    cmd = (char *)malloc(2 * strlen(str) + 3);
+    d = (unsigned char *)cmd;
+    s = (const unsigned char *)str;
+
+#ifdef __MINGW32__
+    *d++ = '\"';
+#endif
+
+    for (; *s; ++s) {
+        if (*s == '"') {
+            *d++ = '\\';
+            in_quote++;
+        }
+        else if (*s == '\\' || (*s == ' ' && (in_quote % 2))) {
+            *d++ = '\\';
+        }
+        *d++ = *s;
+    }
+
+#ifdef __MINGW32__
+    *d++ = '\"';
+#endif
+
+    *d = '\0';
+    return cmd;
+}
+
+int external_spawn(command_t *cmd, const char *file, const char **argv)
+{
+    if (!cmd->options.silent) {
+        const char **argument = argv;
+        printf("Executing: ");
+        while (*argument) {
+            printf("%s ", *argument);
+            argument++;
+        }
+        puts("");
+    }
+
+    if (cmd->options.dry_run) {
+        return 0;
+    }
+#if defined(__EMX__) || defined(__MINGW32__)
+    return spawnvp(P_WAIT, argv[0], argv);
+#else
+    {
+        pid_t pid;
+        pid = fork();
+        if (pid == 0) {
+            return execvp(argv[0], (char**)argv);
+        }
+        else {
+            int statuscode;
+            waitpid(pid, &statuscode, 0);
+            if (WIFEXITED(statuscode)) {
+                return WEXITSTATUS(statuscode);
+            }
+            return 0;
+        }
+    }
+#endif
+}
+
+int run_command(command_t *cmd_data, count_chars *cc)
+{
+    char *command;
+    const char *spawn_args[4];
+    count_chars tmpcc;
+
+    init_count_chars(&tmpcc);
+
+    if (cmd_data->program) {
+        push_count_chars(&tmpcc, cmd_data->program);
+    }
+
+    append_count_chars(&tmpcc, cmd_data->program_opts);
+
+    append_count_chars(&tmpcc, cc);
+
+    command = shell_esc(flatten_count_chars(&tmpcc, 1));
+
+    spawn_args[0] = SHELL_CMD;
+    spawn_args[1] = "-c";
+    spawn_args[2] = command;
+    spawn_args[3] = NULL;
+    return external_spawn(cmd_data, spawn_args[0], (const char**)spawn_args);
+}
+
+/*
+ * print configuration
+ * shlibpath_var is used in configure.
+ */
+void print_config()
+{
+#ifdef LD_RUN_PATH
+    printf("runpath_var=%s\n", LD_RUN_PATH);
+#endif
+#ifdef LD_LIBRARY_PATH
+    printf("shlibpath_var=%s\n", LD_LIBRARY_PATH);
+#endif
+#ifdef SHELL_CMD
+    printf("SHELL=\"%s\"\n", SHELL_CMD);
+#endif
+}
+/*
+ * Add a directory to the runtime library search path.
+ */
+void add_runtimedirlib(char *arg, command_t *cmd_data)
+{
+#ifdef RPATH
+    add_rpath(cmd_data->shared_opts.dependencies, arg);
+#else
+#endif
+}
+
+int parse_long_opt(char *arg, command_t *cmd_data)
+{
+    char *equal_pos = strchr(arg, '=');
+    char var[50];
+    char value[500];
+
+    if (equal_pos) {
+        strncpy(var, arg, equal_pos - arg);
+        var[equal_pos - arg] = 0;
+        strcpy(value, equal_pos + 1);
+    } else {
+        strcpy(var, arg);
+    }
+
+    if (strcmp(var, "silent") == 0) {
+        cmd_data->options.silent = 1;
+    } else if (strcmp(var, "mode") == 0) {
+        if (strcmp(value, "compile") == 0) {
+            cmd_data->mode = mCompile;
+            cmd_data->output = otObject;
+        }
+
+        if (strcmp(value, "link") == 0) {
+            cmd_data->mode = mLink;
+            cmd_data->output = otLibrary;
+        }
+
+        if (strcmp(value, "install") == 0) {
+            cmd_data->mode = mInstall;
+        }
+    } else if (strcmp(var, "shared") == 0) {
+        if (cmd_data->mode == mLink) {
+            cmd_data->output = otDynamicLibraryOnly;
+        }
+        cmd_data->options.shared = share_SHARED;
+    } else if (strcmp(var, "export-all") == 0) {
+        cmd_data->options.export_all = 1;
+    } else if (strcmp(var, "dry-run") == 0) {
+        printf("Dry-run mode on!\n");
+        cmd_data->options.dry_run = 1;
+    } else if (strcmp(var, "version") == 0) {
+        printf("Version " VERSION "\n");
+    } else if (strcmp(var, "help") == 0) {
+        printf("Sorry.  No help available.\n");
+    } else if (strcmp(var, "config") == 0) {
+        print_config();
+    } else if (strcmp(var, "tag") == 0) {
+        if (strcmp(value, "CC") == 0) {
+            /* Do nothing. */
+        }
+        if (strcmp(value, "CXX") == 0) {
+            /* Do nothing. */
+        }
+    } else {
+        return 0;
+    }
+
+    return 1;
+}
+
+/* Return 1 if we eat it. */
+int parse_short_opt(char *arg, command_t *cmd_data)
+{
+    if (strcmp(arg, "export-dynamic") == 0) {
+        cmd_data->options.export_dynamic = 1;
+        return 1;
+    }
+
+    if (strcmp(arg, "module") == 0) {
+        cmd_data->output = otModule;
+        return 1;
+    }
+
+    if (strcmp(arg, "shared") == 0) {
+        if (cmd_data->mode == mLink) {
+            cmd_data->output = otDynamicLibraryOnly;
+        }
+        cmd_data->options.shared = share_SHARED;
+        return 1;
+    }
+
+    if (strcmp(arg, "Zexe") == 0) {
+        return 1;
+    }
+
+    if (strcmp(arg, "avoid-version") == 0) {
+        return 1;
+    }
+
+    if (strcmp(arg, "prefer-pic") == 0) {
+        cmd_data->options.pic_mode = pic_PREFER;
+        return 1;
+    }
+
+    if (strcmp(arg, "prefer-non-pic") == 0) {
+        cmd_data->options.pic_mode = pic_AVOID;
+        return 1;
+    }
+
+    if (strcmp(arg, "static") == 0) {
+        cmd_data->options.shared = share_STATIC;
+        return 1;
+    }
+
+    if (cmd_data->mode == mLink) {
+        if (strcmp(arg, "no-install") == 0) {
+            cmd_data->options.no_install = 1;
+            return 1;
+        }
+        if (arg[0] == 'L' || arg[0] == 'l') {
+            /* Hack... */
+            arg--;
+            push_count_chars(cmd_data->shared_opts.dependencies, arg);
+            return 1;
+        } else if (arg[0] == 'R' && arg[1]) {
+            /* -Rdir Add dir to runtime library search path. */
+            add_runtimedirlib(&arg[1], cmd_data);
+            return 1;
+        }
+    }
+    return 0;
+}
+
+char *truncate_dll_name(char *path)
+{
+    /* Cut DLL name down to 8 characters after removing any mod_ prefix */
+    char *tmppath = strdup(path);
+    char *newname = strrchr(tmppath, '/') + 1;
+    char *ext = strrchr(tmppath, '.');
+    int len;
+
+    if (ext == NULL)
+        return tmppath;
+
+    len = ext - newname;
+
+    if (strncmp(newname, "mod_", 4) == 0) {
+        strcpy(newname, newname + 4);
+        len -= 4;
+    }
+
+    if (len > 8) {
+        strcpy(newname + 8, strchr(newname, '.'));
+    }
+
+    return tmppath;
+}
+
+long safe_strtol(const char *nptr, const char **endptr, int base)
+{
+    long rv;
+
+    errno = 0;
+
+    rv = strtol(nptr, (char**)endptr, 10);
+
+    if (errno == ERANGE) {
+        return 0;
+    }
+
+    return rv; 
+}
+
+void safe_mkdir(const char *path)
+{
+    mode_t old_umask;
+
+    old_umask = umask(0);
+    umask(old_umask);
+
+#ifdef MKDIR_NO_UMASK
+    mkdir(path);
+#else
+    mkdir(path, ~old_umask);
+#endif
+}
+
+/* returns just a file's name without the path */
+const char *jlibtool_basename(const char *fullpath)
+{
+    const char *name = strrchr(fullpath, '/');
+
+    if (name == NULL) {
+        name = strrchr(fullpath, '\\');
+    }
+
+    if (name == NULL) {
+        name = fullpath;
+    } else {
+        name++;
+    }
+
+    return name;
+}
+
+/* returns just a file's name without path or extension */
+const char *nameof(const char *fullpath)
+{
+    const char *name;
+    const char *ext;
+
+    name = jlibtool_basename(fullpath);
+    ext = strrchr(name, '.');
+
+    if (ext) {
+        char *trimmed;
+        trimmed = malloc(ext - name + 1);
+        strncpy(trimmed, name, ext - name);
+        trimmed[ext-name] = 0;
+        return trimmed;
+    }
+
+    return name;
+}
+
+/* version_info is in the form of MAJOR:MINOR:PATCH */
+const char *darwin_dynamic_link_function(const char *version_info)
+{
+    char *newarg;
+    long major, minor, patch;
+
+    major = 0;
+    minor = 0;
+    patch = 0;
+
+    if (version_info) {
+        major = safe_strtol(version_info, &version_info, 10);
+
+        if (version_info) {
+            if (version_info[0] == ':') {
+                version_info++;
+            }
+
+            minor = safe_strtol(version_info, &version_info, 10);
+
+            if (version_info) {
+                if (version_info[0] == ':') {
+                    version_info++;
+                }
+
+                patch = safe_strtol(version_info, &version_info, 10);
+
+            }
+        }
+    }
+
+    /* Avoid -dylib_compatibility_version must be greater than zero errors. */
+    if (major == 0) {
+        major = 1;
+    }
+    newarg = (char*)malloc(100);
+    snprintf(newarg, 99,
+             "-compatibility_version %ld -current_version %ld.%ld",
+             major, major, minor);
+
+    return newarg;
+}
+
+/* genlib values
+ * 0 - static
+ * 1 - dynamic
+ * 2 - module
+ */
+char *gen_library_name(const char *name, int genlib)
+{
+    char *newarg, *newext;
+
+    newarg = (char *)malloc(strlen(name) + 11);
+    strcpy(newarg, ".libs/");
+
+    if (genlib == 2 && strncmp(name, "lib", 3) == 0) {
+        name += 3;
+    }
+
+    if (genlib == 2) {
+        strcat(newarg, jlibtool_basename(name));
+    }
+    else {
+        strcat(newarg, name);
+    }
+
+    newext = strrchr(newarg, '.') + 1;
+
+    switch (genlib) {
+    case 0:
+        strcpy(newext, STATIC_LIB_EXT);
+        break;
+    case 1:
+        strcpy(newext, DYNAMIC_LIB_EXT);
+        break;
+    case 2:
+        strcpy(newext, MODULE_LIB_EXT);
+        break;
+    }
+
+    return newarg;
+}
+
+/* genlib values
+ * 0 - static
+ * 1 - dynamic
+ * 2 - module
+ */
+char *gen_install_name(const char *name, int genlib)
+{
+    struct stat sb;
+    char *newname;
+    int rv;
+
+    newname = gen_library_name(name, genlib);
+
+    /* Check if it exists. If not, return NULL.  */
+    rv = stat(newname, &sb);
+
+    if (rv) {
+        return NULL;
+    }
+
+    return newname;
+}
+
+char *check_object_exists(command_t *cmd, const char *arg, int arglen)
+{
+    char *newarg, *ext;
+    int pass, rv;
+
+    newarg = (char *)malloc(arglen + 10);
+    memcpy(newarg, arg, arglen);
+    newarg[arglen] = 0;
+    ext = newarg + arglen;
+
+    pass = 0;
+
+    do {
+        struct stat sb;
+
+        switch (pass) {
+        case 0:
+            strcpy(ext, OBJECT_EXT);
+            break;
+/*
+        case 1:
+            strcpy(ext, NO_PIC_EXT);
+            break;
+*/
+        default:
+            break;
+        } 
+
+        if (!cmd->options.silent) {
+            printf("Checking (obj): %s\n", newarg);
+        }
+        rv = stat(newarg, &sb);
+    }
+    while (rv != 0 && ++pass < 1);
+
+    if (rv == 0) {
+        if (pass == 1) {
+            cmd->options.pic_mode = pic_AVOID;
+        }
+        return newarg;
+    }
+
+    return NULL;
+}
+
+/* libdircheck values:
+ * 0 - no .libs suffix
+ * 1 - .libs suffix
+ */
+char *check_library_exists(command_t *cmd, const char *arg, int pathlen,
+                           int libdircheck, enum lib_type *libtype)
+{
+    char *newarg, *ext;
+    int pass, rv, newpathlen;
+
+    newarg = (char *)malloc(strlen(arg) + 10);
+    strcpy(newarg, arg);
+    newarg[pathlen] = 0;
+
+    newpathlen = pathlen;
+    if (libdircheck) {
+        strcat(newarg, ".libs/");
+        newpathlen += sizeof(".libs/") - 1;
+    }
+
+    strcpy(newarg+newpathlen, arg+pathlen);
+    ext = strrchr(newarg, '.') + 1;
+
+    pass = 0;
+
+    do {
+        struct stat sb;
+
+        switch (pass) {
+        case 0:
+            if (cmd->options.pic_mode != pic_AVOID &&
+                cmd->options.shared != share_STATIC) {
+                strcpy(ext, DYNAMIC_LIB_EXT);
+                *libtype = type_DYNAMIC_LIB;
+                break;
+            }
+            pass = 1;
+            /* Fall through */
+        case 1:
+            strcpy(ext, STATIC_LIB_EXT);
+            *libtype = type_STATIC_LIB;
+            break;
+        case 2:
+            strcpy(ext, MODULE_LIB_EXT);
+            *libtype = type_MODULE_LIB;
+            break;
+        case 3:
+            strcpy(ext, OBJECT_EXT);
+            *libtype = type_OBJECT;
+            break;
+        default:
+            *libtype = type_UNKNOWN;
+            break;
+        } 
+
+        if (!cmd->options.silent) {
+            printf("Checking (lib): %s\n", newarg);
+        }
+        rv = stat(newarg, &sb);
+    }
+    while (rv != 0 && ++pass < 4);
+
+    if (rv == 0) {
+        return newarg;
+    }
+
+    return NULL;
+}
+
+char * load_install_path(const char *arg)
+{
+    FILE *f;
+    char *path;
+
+    path = malloc(PATH_MAX);
+
+    f = fopen(arg,"r");
+    if (f == NULL) {
+        return NULL;
+    }
+    fgets(path, PATH_MAX, f);
+    fclose(f);
+    if (path[strlen(path)-1] == '\n') {
+        path[strlen(path)-1] = '\0';
+    }
+    /* Check that we have an absolute path.
+     * Otherwise the file could be a GNU libtool file.
+     */
+    if (path[0] != '/') {
+        return NULL;
+    }
+    return path;
+}
+
+char * load_noinstall_path(const char *arg, int pathlen)
+{
+    char *newarg, *expanded_path;
+    int newpathlen;
+
+    newarg = (char *)malloc(strlen(arg) + 10);
+    strcpy(newarg, arg);
+    newarg[pathlen] = 0;
+
+    newpathlen = pathlen;
+    strcat(newarg, ".libs");
+    newpathlen += sizeof(".libs") - 1;
+    newarg[newpathlen] = 0;
+
+#ifdef HAS_REALPATH
+    expanded_path = malloc(PATH_MAX);
+    expanded_path = realpath(newarg, expanded_path);
+    /* Uh, oh.  There was an error.  Fall back on our first guess. */
+    if (!expanded_path) {
+        expanded_path = newarg;
+    }
+#else
+    /* We might get ../ or something goofy.  Oh, well. */
+    expanded_path = newarg;
+#endif
+
+    return expanded_path;
+}
+
+void add_dynamic_link_opts(command_t *cmd_data, count_chars *args)
+{
+#ifdef DYNAMIC_LINK_OPTS
+    if (cmd_data->options.pic_mode != pic_AVOID) {
+        if (!cmd_data->options.silent) {
+           printf("Adding: %s\n", DYNAMIC_LINK_OPTS);
+        }
+        push_count_chars(args, DYNAMIC_LINK_OPTS);
+        if (cmd_data->undefined_flag) {
+            push_count_chars(args, "-undefined");
+#if defined(__APPLE__)
+            /* -undefined dynamic_lookup is used by the bundled Python in
+             * 10.4, but if we don't set MACOSX_DEPLOYMENT_TARGET to 10.3+,
+             * we'll get a linker error if we pass this flag.
+             */
+            if (strcasecmp(cmd_data->undefined_flag,
+                           "dynamic_lookup") == 0) {
+                insert_count_chars(cmd_data->program_opts,
+                                   "MACOSX_DEPLOYMENT_TARGET=10.3", 0);
+            }
+#endif
+            push_count_chars(args, cmd_data->undefined_flag);
+        }
+        else {
+#ifdef DYNAMIC_LINK_UNDEFINED
+            if (!cmd_data->options.silent) {
+                printf("Adding: %s\n", DYNAMIC_LINK_UNDEFINED);
+            }
+            push_count_chars(args, DYNAMIC_LINK_UNDEFINED);
+#endif
+        }
+    }
+#endif
+}
+
+/* Read the final install location and add it to runtime library search path. */
+#ifdef RPATH
+void add_rpath(count_chars *cc, const char *path)
+{
+    int size = 0;
+    char *tmp;
+
+#ifdef LINKER_FLAG_PREFIX
+    size = strlen(LINKER_FLAG_PREFIX);
+#endif
+    size = size + strlen(path) + strlen(RPATH) + 2;
+    tmp = malloc(size);
+    if (tmp == NULL) {
+        return;
+    }
+#ifdef LINKER_FLAG_PREFIX
+    strcpy(tmp, LINKER_FLAG_PREFIX);
+    strcat(tmp, RPATH);
+#else
+    strcpy(tmp, RPATH);
+#endif
+#ifndef LINKER_FLAG_NO_EQUALS
+    strcat(tmp, "=");
+#endif
+    strcat(tmp, path);
+
+    push_count_chars(cc, tmp);
+}
+
+void add_rpath_file(count_chars *cc, const char *arg)
+{
+    const char *path;
+
+    path = load_install_path(arg);
+    if (path) {
+        add_rpath(cc, path);
+    }
+}
+
+void add_rpath_noinstall(count_chars *cc, const char *arg, int pathlen)
+{
+    const char *path;
+
+    path = load_noinstall_path(arg, pathlen);
+    if (path) {
+        add_rpath(cc, path);
+    }
+}
+#endif
+
+#ifdef DYNAMIC_LINK_NO_INSTALL
+void add_dylink_noinstall(count_chars *cc, const char *arg, int pathlen,
+                          int extlen)
+{
+    const char *install_path, *current_path, *name;
+    char *exp_argument;
+    int i_p_len, c_p_len, name_len, dyext_len, cur_len;
+
+    install_path = load_install_path(arg);
+    current_path = load_noinstall_path(arg, pathlen);
+
+    if (!install_path || !current_path) {
+        return;
+    }
+
+    push_count_chars(cc, DYNAMIC_LINK_NO_INSTALL);
+
+    i_p_len = strlen(install_path);
+    c_p_len = strlen(current_path);
+
+    name = arg+pathlen;
+    name_len = extlen-pathlen;
+    dyext_len = sizeof(DYNAMIC_LIB_EXT) - 1;
+
+    /* No, we need to replace the extension. */
+    exp_argument = (char *)malloc(i_p_len + c_p_len + (name_len*2) +
+                                  (dyext_len*2) + 2);
+
+    cur_len = 0;
+    strcpy(exp_argument, install_path);
+    cur_len += i_p_len;
+    exp_argument[cur_len++] = '/';
+    strncpy(exp_argument+cur_len, name, extlen-pathlen);
+    cur_len += name_len;
+    strcpy(exp_argument+cur_len, DYNAMIC_LIB_EXT);
+    cur_len += dyext_len;
+    exp_argument[cur_len++] = ':';
+    strcpy(exp_argument+cur_len, current_path);
+    cur_len += c_p_len;
+    exp_argument[cur_len++] = '/';
+    strncpy(exp_argument+cur_len, name, extlen-pathlen);
+    cur_len += name_len;
+    strcpy(exp_argument+cur_len, DYNAMIC_LIB_EXT);
+    cur_len += dyext_len;
+
+    push_count_chars(cc, exp_argument);
+}
+#endif
+
+/* use -L -llibname to allow to use installed libraries */
+void add_minus_l(count_chars *cc, const char *arg)
+{
+    char *newarg;
+    char *name = strrchr(arg, '/');
+    char *file = strrchr(arg, '.');
+    char *lib  = strstr(name, "lib");
+
+    if (name !=NULL && file != NULL && lib == name+1) {
+        *name = '\0';
+        *file = '\0';
+        file = name;
+        file = file+4;
+        push_count_chars(cc, "-L");
+        push_count_chars(cc, arg);
+        /* we need one argument like -lapr-1 */
+        newarg = malloc(strlen(file) + 3);
+        strcpy(newarg, "-l");
+        strcat(newarg, file);
+        push_count_chars(cc, newarg);
+    } else {
+        push_count_chars(cc, arg);
+    }
+}
+
+void add_linker_flag_prefix(count_chars *cc, const char *arg)
+{
+#ifndef LINKER_FLAG_PREFIX
+    push_count_chars(cc, arg);
+#else
+    char *newarg;
+    newarg = (char*)malloc(strlen(arg) + sizeof(LINKER_FLAG_PREFIX) + 1);
+    strcpy(newarg, LINKER_FLAG_PREFIX);
+    strcat(newarg, arg);
+    push_count_chars(cc, newarg);
+#endif
+}
+
+int explode_static_lib(command_t *cmd_data, const char *lib)
+{
+    count_chars tmpdir_cc, libname_cc;
+    const char *tmpdir, *libname;
+    char savewd[PATH_MAX];
+    const char *name;
+    DIR *dir;
+    struct dirent *entry;
+    const char *lib_args[4];
+
+    /* Bah! */
+    if (cmd_data->options.dry_run) {
+        return 0;
+    }
+
+    name = jlibtool_basename(lib);
+
+    init_count_chars(&tmpdir_cc);
+    push_count_chars(&tmpdir_cc, ".libs/");
+    push_count_chars(&tmpdir_cc, name);
+    push_count_chars(&tmpdir_cc, ".exploded/");
+    tmpdir = flatten_count_chars(&tmpdir_cc, 0);
+
+    if (!cmd_data->options.silent) {
+        printf("Making: %s\n", tmpdir);
+    }
+    safe_mkdir(tmpdir);
+
+    push_count_chars(cmd_data->tmp_dirs, tmpdir);
+
+    getcwd(savewd, sizeof(savewd));
+
+    if (chdir(tmpdir) != 0) {
+        if (!cmd_data->options.silent) {
+            printf("Warning: could not explode %s\n", lib);
+        }
+        return 1;
+    }
+
+    if (lib[0] == '/') {
+        libname = lib;
+    }
+    else {
+        init_count_chars(&libname_cc);
+        push_count_chars(&libname_cc, "../../");
+        push_count_chars(&libname_cc, lib);
+        libname = flatten_count_chars(&libname_cc, 0);
+    }
+
+    lib_args[0] = LIBRARIAN;
+    lib_args[1] = "x";
+    lib_args[2] = libname;
+    lib_args[3] = NULL;
+
+    external_spawn(cmd_data, LIBRARIAN, lib_args);
+
+    chdir(savewd);
+    dir = opendir(tmpdir);
+
+    while ((entry = readdir(dir)) != NULL) {
+#if defined(__APPLE__) && defined(RANLIB)
+        /* Apple inserts __.SYMDEF which isn't needed.
+         * Leopard (10.5+) can also add '__.SYMDEF SORTED' which isn't
+         * much fun either.  Just skip them.
+         */
+        if (strstr(entry->d_name, "__.SYMDEF") != NULL) {
+            continue;
+        }
+#endif
+        if (entry->d_name[0] != '.') {
+            push_count_chars(&tmpdir_cc, entry->d_name);
+            name = flatten_count_chars(&tmpdir_cc, 0);
+            if (!cmd_data->options.silent) {
+                printf("Adding: %s\n", name);
+            }
+            push_count_chars(cmd_data->obj_files, name);
+            pop_count_chars(&tmpdir_cc);
+        }
+    }
+
+    closedir(dir);
+    return 0;
+}
+
+int parse_input_file_name(char *arg, command_t *cmd_data)
+{
+    char *ext = strrchr(arg, '.');
+    char *name = strrchr(arg, '/');
+    int pathlen;
+    enum lib_type libtype;
+    char *newarg;
+
+    if (!ext) {
+        return 0;
+    }
+
+    ext++;
+
+    if (name == NULL) {
+        name = strrchr(arg, '\\');
+
+        if (name == NULL) {
+            name = arg;
+        } else {
+            name++;
+        }
+    } else {
+        name++;
+    }
+
+    pathlen = name - arg;
+
+    if (strcmp(ext, "lo") == 0) {
+        newarg = check_object_exists(cmd_data, arg, ext - arg);
+        if (!newarg) {
+            printf("Can not find suitable object file for %s\n", arg);
+            exit(1);
+        }
+        if (cmd_data->mode != mLink) {
+            push_count_chars(cmd_data->arglist, newarg);
+        }
+        else {
+            push_count_chars(cmd_data->obj_files, newarg);
+        }
+        return 1;
+    }
+
+    if (strcmp(ext, "la") == 0) {
+        switch (cmd_data->mode) {
+        case mLink:
+            /* Try the .libs dir first! */
+            newarg = check_library_exists(cmd_data, arg, pathlen, 1, &libtype);
+            if (!newarg) {
+                /* Try the normal dir next. */
+                newarg = check_library_exists(cmd_data, arg, pathlen, 0, &libtype);
+                if (!newarg) {
+                    printf("Can not find suitable library for %s\n", arg);
+                    exit(1);
+                }
+            }
+
+            /* It is not ok to just add the file: a library may added with:
+               1 - -L path library_name. (For *.so in Linux).
+               2 - library_name.
+             */
+#ifdef ADD_MINUS_L
+            if (libtype == type_DYNAMIC_LIB) {
+                 add_minus_l(cmd_data->shared_opts.dependencies, newarg);
+            } else if (cmd_data->output == otLibrary &&
+                       libtype == type_STATIC_LIB) {
+                explode_static_lib(cmd_data, newarg);
+            } else {
+                 push_count_chars(cmd_data->shared_opts.dependencies, newarg);
+            }
+#else
+            if (cmd_data->output == otLibrary && libtype == type_STATIC_LIB) {
+                explode_static_lib(cmd_data, newarg);
+            }
+            else {
+                push_count_chars(cmd_data->shared_opts.dependencies, newarg);
+            }
+#endif
+            if (libtype == type_DYNAMIC_LIB) {
+                if (cmd_data->options.no_install) {
+#ifdef RPATH
+                    add_rpath_noinstall(cmd_data->shared_opts.dependencies,
+                                        arg, pathlen);
+#endif
+#ifdef DYNAMIC_LINK_NO_INSTALL
+                    /*
+                     * This doesn't work as Darwin's linker has no way to
+                     * override at link-time the search paths for a
+                     * non-installed library.
+                     */
+                    /*
+                    add_dylink_noinstall(cmd_data->shared_opts.dependencies,
+                                         arg, pathlen, ext - arg);
+                    */
+#endif
+                }
+                else {
+#ifdef RPATH
+                    add_rpath_file(cmd_data->shared_opts.dependencies, arg);
+#endif
+                }
+            }
+            break;
+        case mInstall:
+            /* If we've already recorded a library to install, we're most
+             * likely getting the .la file that we want to install as.
+             * The problem is that we need to add it as the directory,
+             * not the .la file itself.  Otherwise, we'll do odd things.
+             */
+            if (cmd_data->output == otLibrary) {
+                arg[pathlen] = '\0';
+                push_count_chars(cmd_data->arglist, arg);
+            }
+            else {
+                cmd_data->output = otLibrary;
+                cmd_data->output_name = arg;
+                cmd_data->static_name.install = gen_install_name(arg, 0);
+                cmd_data->shared_name.install = gen_install_name(arg, 1);
+                cmd_data->module_name.install = gen_install_name(arg, 2);
+            }
+            break;
+        default:
+            break;
+        }
+        return 1;
+    }
+
+    if (strcmp(ext, "c") == 0) {
+        /* If we don't already have an idea what our output name will be. */
+        if (cmd_data->basename == NULL) {
+            cmd_data->basename = (char *)malloc(strlen(arg) + 4);
+            strcpy(cmd_data->basename, arg);
+            strcpy(strrchr(cmd_data->basename, '.') + 1, "lo");
+
+            cmd_data->fake_output_name = strrchr(cmd_data->basename, '/');
+            if (cmd_data->fake_output_name) {
+                cmd_data->fake_output_name++;
+            }
+            else {
+                cmd_data->fake_output_name = cmd_data->basename;
+            }
+        }
+    }
+
+    return 0;
+}
+
+int parse_output_file_name(char *arg, command_t *cmd_data)
+{
+    char *name = strrchr(arg, '/');
+    char *ext = strrchr(arg, '.');
+    char *newarg = NULL;
+    int pathlen;
+
+    cmd_data->fake_output_name = arg;
+
+    if (name) {
+        name++;
+    }
+    else {
+        name = strrchr(arg, '\\');
+
+        if (name == NULL) {
+            name = arg;
+        }
+        else {
+            name++;
+        }
+    }
+
+#ifdef EXE_EXT
+    if (!ext || strcmp(ext, EXE_EXT) == 0) {
+#else
+    if (!ext) {
+#endif
+        cmd_data->basename = arg;
+        cmd_data->output = otProgram;
+#if defined(_OSD_POSIX)
+        cmd_data->options.pic_mode = pic_AVOID;
+#endif
+        newarg = (char *)malloc(strlen(arg) + 5);
+        strcpy(newarg, arg);
+#ifdef EXE_EXT
+        if (!ext) {
+            strcat(newarg, EXE_EXT);
+        }
+#endif
+        cmd_data->output_name = newarg;
+        return 1;
+    }
+
+    ext++;
+    pathlen = name - arg;
+
+    if (strcmp(ext, "la") == 0) {
+        assert(cmd_data->mode == mLink);
+
+        cmd_data->basename = arg;
+        cmd_data->static_name.normal = gen_library_name(arg, 0);
+        cmd_data->shared_name.normal = gen_library_name(arg, 1);
+        cmd_data->module_name.normal = gen_library_name(arg, 2);
+        cmd_data->static_name.install = gen_install_name(arg, 0);
+        cmd_data->shared_name.install = gen_install_name(arg, 1);
+        cmd_data->module_name.install = gen_install_name(arg, 2);
+
+#ifdef TRUNCATE_DLL_NAME
+        if (shared) {
+          arg = truncate_dll_name(arg);
+        }
+#endif
+
+        cmd_data->output_name = arg;
+        return 1;
+    }
+
+    if (strcmp(ext, "lo") == 0) {
+        cmd_data->basename = arg;
+        cmd_data->output = otObject;
+        newarg = (char *)malloc(strlen(arg) + 2);
+        strcpy(newarg, arg);
+        ext = strrchr(newarg, '.') + 1;
+        strcpy(ext, OBJECT_EXT);
+        cmd_data->output_name = newarg;
+        return 1;
+    }
+
+    return 0;
+}
+
+void parse_args(int argc, char *argv[], command_t *cmd_data)
+{
+    int a;
+    char *arg;
+    int argused;
+
+    for (a = 1; a < argc; a++) {
+        arg = argv[a];
+        argused = 1;
+
+        if (arg[0] == '-') {
+            if (arg[1] == '-') {
+                argused = parse_long_opt(arg + 2, cmd_data);
+            }
+            else {
+                argused = parse_short_opt(arg + 1, cmd_data);
+            }
+
+            /* We haven't done anything with it yet, try some of the
+             * more complicated short opts... */
+            if (argused == 0 && a + 1 < argc) {
+                if (arg[1] == 'o' && !arg[2]) {
+                    arg = argv[++a];
+                    argused = parse_output_file_name(arg, cmd_data);
+                } else if (strcmp(arg+1, "MT") == 0) {
+                    if (!cmd_data->options.silent) {
+                        printf("Adding: %s\n", arg);
+                    }
+                    push_count_chars(cmd_data->arglist, arg);
+                    arg = argv[++a];
+                    if (!cmd_data->options.silent) {
+                        printf(" %s\n", arg);
+                    }
+                    push_count_chars(cmd_data->arglist, arg);
+                    argused = 1;
+                } else if (strcmp(arg+1, "rpath") == 0) {
+                    /* Aha, we should try to link both! */
+                    cmd_data->install_path = argv[++a];
+                    argused = 1;
+                } else if (strcmp(arg+1, "release") == 0) {
+                    /* Store for later deciphering */
+                    cmd_data->version_info = argv[++a];
+                    argused = 1;
+                } else if (strcmp(arg+1, "version-info") == 0) {
+                    /* Store for later deciphering */
+                    cmd_data->version_info = argv[++a];
+                    argused = 1;
+                } else if (strcmp(arg+1, "export-symbols-regex") == 0) {
+                    /* Skip the argument. */
+                    ++a;
+                    argused = 1;
+                } else if (strcmp(arg+1, "release") == 0) {
+                    /* Skip the argument. */
+                    ++a;
+                    argused = 1;
+                } else if (strcmp(arg+1, "undefined") == 0) {
+                    cmd_data->undefined_flag = argv[++a];
+                    argused = 1;
+                } else if (arg[1] == 'R' && !arg[2]) {
+                    /* -R dir Add dir to runtime library search path. */
+                    add_runtimedirlib(argv[++a], cmd_data);
+                    argused = 1;
+                }
+            }
+        } else {
+            argused = parse_input_file_name(arg, cmd_data);
+        }
+
+        if (!argused) {
+            if (!cmd_data->options.silent) {
+                printf("Adding: %s\n", arg);
+            }
+            push_count_chars(cmd_data->arglist, arg);
+        }
+    }
+
+}
+
+#ifdef GEN_EXPORTS
+void generate_def_file(command_t *cmd_data)
+{
+    char def_file[1024];
+    char implib_file[1024];
+    char *ext;
+    FILE *hDef;
+    char *export_args[1024];
+    int num_export_args = 0;
+    char *cmd;
+    int cmd_size = 0;
+    int a;
+
+    if (cmd_data->output_name) {
+        strcpy(def_file, cmd_data->output_name);
+        strcat(def_file, ".def");
+        hDef = fopen(def_file, "w");
+
+        if (hDef != NULL) {
+            fprintf(hDef, "LIBRARY '%s' INITINSTANCE\n", nameof(cmd_data->output_name));
+            fprintf(hDef, "DATA NONSHARED\n");
+            fprintf(hDef, "EXPORTS\n");
+            fclose(hDef);
+
+            for (a = 0; a < cmd_data->num_obj_files; a++) {
+                cmd_size += strlen(cmd_data->obj_files[a]) + 1;
+            }
+
+            cmd_size += strlen(GEN_EXPORTS) + strlen(def_file) + 3;
+            cmd = (char *)malloc(cmd_size);
+            strcpy(cmd, GEN_EXPORTS);
+
+            for (a=0; a < cmd_data->num_obj_files; a++) {
+                strcat(cmd, " ");
+                strcat(cmd, cmd_data->obj_files[a] );
+            }
+
+            strcat(cmd, ">>");
+            strcat(cmd, def_file);
+            puts(cmd);
+            export_args[num_export_args++] = SHELL_CMD;
+            export_args[num_export_args++] = "-c";
+            export_args[num_export_args++] = cmd;
+            export_args[num_export_args++] = NULL;
+            external_spawn(cmd_data, export_args[0], (const char**)export_args);
+            cmd_data->arglist[cmd_data->num_args++] = strdup(def_file);
+
+            /* Now make an import library for the dll */
+            num_export_args = 0;
+            export_args[num_export_args++] = DEF2IMPLIB_CMD;
+            export_args[num_export_args++] = "-o";
+
+            strcpy(implib_file, ".libs/");
+            strcat(implib_file, cmd_data->basename);
+            ext = strrchr(implib_file, '.');
+
+            if (ext)
+                *ext = 0;
+
+            strcat(implib_file, ".");
+            strcat(implib_file, STATIC_LIB_EXT);
+
+            export_args[num_export_args++] = implib_file;
+            export_args[num_export_args++] = def_file;
+            export_args[num_export_args++] = NULL;
+            external_spawn(cmd_data, export_args[0], (const char**)export_args);
+
+        }
+    }
+}
+#endif
+
+const char* expand_path(const char *relpath)
+{
+    char foo[PATH_MAX], *newpath;
+
+    getcwd(foo, PATH_MAX-1);
+    newpath = (char*)malloc(strlen(foo)+strlen(relpath)+2);
+    strcpy(newpath, foo);
+    strcat(newpath, "/");
+    strcat(newpath, relpath);
+    return newpath;
+}
+
+void link_fixup(command_t *c)
+{
+    /* If we were passed an -rpath directive, we need to build
+     * shared objects too.  Otherwise, we should only create static
+     * libraries.
+     */
+    if (!c->install_path && (c->output == otDynamicLibraryOnly ||
+        c->output == otModule || c->output == otLibrary)) {
+        c->output = otStaticLibraryOnly;
+    }
+
+    if (c->output == otDynamicLibraryOnly ||
+        c->output == otModule ||
+        c->output == otLibrary) {
+
+        push_count_chars(c->shared_opts.normal, "-o");
+        if (c->output == otModule) {
+            push_count_chars(c->shared_opts.normal, c->module_name.normal);
+        }
+        else {
+            char *tmp;
+            push_count_chars(c->shared_opts.normal, c->shared_name.normal);
+#ifdef DYNAMIC_INSTALL_NAME
+            push_count_chars(c->shared_opts.normal, DYNAMIC_INSTALL_NAME);
+
+            tmp = (char*)malloc(PATH_MAX);
+            strcpy(tmp, c->install_path);
+            strcat(tmp, strrchr(c->shared_name.normal, '/'));
+            push_count_chars(c->shared_opts.normal, tmp);
+#endif
+        }
+
+        append_count_chars(c->shared_opts.normal, c->obj_files);
+        append_count_chars(c->shared_opts.normal, c->shared_opts.dependencies);
+
+        if (c->options.export_all) {
+#ifdef GEN_EXPORTS
+            generate_def_file(c);
+#endif
+        }
+    }
+
+    if (c->output == otLibrary || c->output == otStaticLibraryOnly) {
+        push_count_chars(c->static_opts.normal, "-o");
+        push_count_chars(c->static_opts.normal, c->output_name);
+    }
+
+    if (c->output == otProgram) {
+        if (c->output_name) {
+            push_count_chars(c->arglist, "-o");
+            push_count_chars(c->arglist, c->output_name);
+            append_count_chars(c->arglist, c->obj_files);
+            append_count_chars(c->arglist, c->shared_opts.dependencies);
+            add_dynamic_link_opts(c, c->arglist);
+        }
+    }
+}
+
+void post_parse_fixup(command_t *cmd_data)
+{
+    switch (cmd_data->mode)
+    {
+    case mCompile:
+#ifdef PIC_FLAG
+        if (cmd_data->options.pic_mode != pic_AVOID) {
+            push_count_chars(cmd_data->arglist, PIC_FLAG);
+        }
+#endif
+        if (cmd_data->output_name) {
+            push_count_chars(cmd_data->arglist, "-o");
+            push_count_chars(cmd_data->arglist, cmd_data->output_name);
+        }
+        break;
+    case mLink:
+        link_fixup(cmd_data);
+        break;
+    case mInstall:
+        if (cmd_data->output == otLibrary) {
+            link_fixup(cmd_data);
+        }
+    default:
+        break;
+    }
+
+#if USE_OMF
+    if (cmd_data->output == otObject ||
+        cmd_data->output == otProgram ||
+        cmd_data->output == otLibrary ||
+        cmd_data->output == otDynamicLibraryOnly) {
+        push_count_chars(cmd_data->arglist, "-Zomf");
+    }
+#endif
+
+    if (cmd_data->options.shared &&
+            (cmd_data->output == otObject ||
+             cmd_data->output == otLibrary ||
+             cmd_data->output == otDynamicLibraryOnly)) {
+#ifdef SHARE_SW
+        push_count_chars(cmd_data->arglist, SHARE_SW);
+#endif
+    }
+}
+
+int run_mode(command_t *cmd_data)
+{
+    int rv;
+    count_chars *cctemp;
+
+    cctemp = (count_chars*)malloc(sizeof(count_chars));
+    init_count_chars(cctemp);
+
+    switch (cmd_data->mode)
+    {
+    case mCompile:
+        rv = run_command(cmd_data, cmd_data->arglist);
+        if (rv) {
+            return rv;
+        }
+        break;
+    case mInstall:
+        /* Well, we'll assume it's a file going to a directory... */
+        /* For brain-dead install-sh based scripts, we have to repeat
+         * the command N-times.  install-sh should die.
+         */
+        if (!cmd_data->output_name) {
+            rv = run_command(cmd_data, cmd_data->arglist);
+            if (rv) {
+                return rv;
+            }
+        }
+        if (cmd_data->output_name) {
+            append_count_chars(cctemp, cmd_data->arglist);
+            insert_count_chars(cctemp,
+                               cmd_data->output_name,
+                               cctemp->num - 1);
+            rv = run_command(cmd_data, cctemp);
+            if (rv) {
+                return rv;
+            }
+            clear_count_chars(cctemp);
+        }
+        if (cmd_data->static_name.install) {
+            append_count_chars(cctemp, cmd_data->arglist);
+            insert_count_chars(cctemp,
+                               cmd_data->static_name.install,
+                               cctemp->num - 1);
+            rv = run_command(cmd_data, cctemp);
+            if (rv) {
+                return rv;
+            }
+#if defined(__APPLE__) && defined(RANLIB)
+            /* From the Apple libtool(1) manpage on Tiger/10.4:
+             * ----
+             * With  the way libraries used to be created, errors were possible
+             * if the library was modified with ar(1) and  the  table  of
+             * contents  was  not updated  by  rerunning ranlib(1).  Thus the
+             * link editor, ld, warns when the modification date of a library
+             * is more  recent  than  the  creation date  of its table of
+             * contents.  Unfortunately, this means that you get the warning
+             * even if you only copy the library.
+             * ----
+             *
+             * This means that when we install the static archive, we need to
+             * rerun ranlib afterwards.
+             */
+            const char *lib_args[3], *static_lib_name;
+            char *tmp;
+            size_t len1, len2;
+            len1 = strlen(cmd_data->arglist->vals[cmd_data->arglist->num - 1]);
+
+            static_lib_name = jlibtool_basename(cmd_data->static_name.install);
+            len2 = strlen(static_lib_name);
+
+            tmp = malloc(len1 + len2 + 2);
+
+            snprintf(tmp, len1 + len2 + 2, "%s/%s",
+                    cmd_data->arglist->vals[cmd_data->arglist->num - 1],
+                    static_lib_name);
+
+            lib_args[0] = RANLIB;
+            lib_args[1] = tmp;
+            lib_args[2] = NULL;
+            external_spawn(cmd_data, RANLIB, lib_args);
+            free(tmp);
+#endif
+            clear_count_chars(cctemp);
+        }
+        if (cmd_data->shared_name.install) {
+            append_count_chars(cctemp, cmd_data->arglist);
+            insert_count_chars(cctemp,
+                               cmd_data->shared_name.install,
+                               cctemp->num - 1);
+            rv = run_command(cmd_data, cctemp);
+            if (rv) {
+                return rv;
+            }
+            clear_count_chars(cctemp);
+        }
+        if (cmd_data->module_name.install) {
+            append_count_chars(cctemp, cmd_data->arglist);
+            insert_count_chars(cctemp,
+                               cmd_data->module_name.install,
+                               cctemp->num - 1);
+            rv = run_command(cmd_data, cctemp);
+            if (rv) {
+                return rv;
+            }
+            clear_count_chars(cctemp);
+        }
+        break;
+    case mLink:
+        if (!cmd_data->options.dry_run) {
+            /* Check first to see if the dir already exists! */
+            safe_mkdir(".libs");
+        }
+
+        if (cmd_data->output == otStaticLibraryOnly ||
+            cmd_data->output == otLibrary) {
+#ifdef RANLIB
+            const char *lib_args[3];
+#endif
+            /* Removes compiler! */
+            cmd_data->program = LIBRARIAN;
+            push_count_chars(cmd_data->program_opts, LIBRARIAN_OPTS);
+            push_count_chars(cmd_data->program_opts,
+                             cmd_data->static_name.normal);
+
+            rv = run_command(cmd_data, cmd_data->obj_files);
+            if (rv) {
+                return rv;
+            }
+
+#ifdef RANLIB
+            lib_args[0] = RANLIB;
+            lib_args[1] = cmd_data->static_name.normal;
+            lib_args[2] = NULL;
+            external_spawn(cmd_data, RANLIB, lib_args);
+#endif
+        }
+
+        if (cmd_data->output == otDynamicLibraryOnly ||
+            cmd_data->output == otModule ||
+            cmd_data->output == otLibrary) {
+            cmd_data->program = NULL;
+            clear_count_chars(cmd_data->program_opts);
+
+            append_count_chars(cmd_data->program_opts, cmd_data->arglist);
+            if (cmd_data->output == otModule) {
+#ifdef MODULE_OPTS
+                push_count_chars(cmd_data->program_opts, MODULE_OPTS);
+#endif
+            } else {
+#ifdef SHARED_OPTS
+                push_count_chars(cmd_data->program_opts, SHARED_OPTS);
+#endif
+#ifdef dynamic_link_version_func
+                push_count_chars(cmd_data->program_opts,
+                             dynamic_link_version_func(cmd_data->version_info));
+#endif
+            }
+            add_dynamic_link_opts(cmd_data, cmd_data->program_opts);
+
+            rv = run_command(cmd_data, cmd_data->shared_opts.normal);
+            if (rv) {
+                return rv;
+            }
+        }
+        if (cmd_data->output == otProgram) {
+            rv = run_command(cmd_data, cmd_data->arglist);
+            if (rv) {
+                return rv;
+            }
+        }
+        break;
+    default:
+        break;
+    } 
+
+    return 0;
+}
+
+void cleanup_tmp_dir(const char *dirname)
+{
+    DIR *dir;
+    struct dirent *entry;
+    char fullname[1024];
+
+    dir = opendir(dirname);
+
+    if (dir == NULL)
+        return;
+
+    while ((entry = readdir(dir)) != NULL) {
+        if (entry->d_name[0] != '.') {
+            strcpy(fullname, dirname);
+            strcat(fullname, "/");
+            strcat(fullname, entry->d_name);
+            remove(fullname);
+        }
+    }
+
+    rmdir(dirname);
+}
+
+void cleanup_tmp_dirs(command_t *cmd_data)
+{
+    int d;
+
+    for (d = 0; d < cmd_data->tmp_dirs->num; d++) {
+        cleanup_tmp_dir(cmd_data->tmp_dirs->vals[d]);
+    }
+}
+
+int ensure_fake_uptodate(command_t *cmd_data)
+{
+    /* FIXME: could do the stat/touch here, but nah... */
+    const char *touch_args[3];
+
+    if (cmd_data->mode == mInstall) {
+        return 0;
+    }
+    if (!cmd_data->fake_output_name) {
+        return 0;
+    }
+
+    touch_args[0] = "touch";
+    touch_args[1] = cmd_data->fake_output_name;
+    touch_args[2] = NULL;
+    return external_spawn(cmd_data, "touch", touch_args);
+}
+
+/* Store the install path in the *.la file */
+int add_for_runtime(command_t *cmd_data)
+{
+    if (cmd_data->mode == mInstall) {
+        return 0;
+    }
+    if (cmd_data->output == otDynamicLibraryOnly ||
+        cmd_data->output == otLibrary) {
+        FILE *f=fopen(cmd_data->fake_output_name,"w");
+        if (f == NULL) {
+            return -1;
+        }
+        fprintf(f,"%s\n", cmd_data->install_path);
+        fclose(f);
+        return(0);
+    } else {
+        return(ensure_fake_uptodate(cmd_data));
+    }
+}
+
+int main(int argc, char *argv[])
+{
+    int rc;
+    command_t cmd_data;
+
+    memset(&cmd_data, 0, sizeof(cmd_data));
+
+    cmd_data.options.pic_mode = pic_UNKNOWN;
+
+    cmd_data.program_opts = (count_chars*)malloc(sizeof(count_chars));
+    init_count_chars(cmd_data.program_opts);
+    cmd_data.arglist = (count_chars*)malloc(sizeof(count_chars));
+    init_count_chars(cmd_data.arglist);
+    cmd_data.tmp_dirs = (count_chars*)malloc(sizeof(count_chars));
+    init_count_chars(cmd_data.tmp_dirs);
+    cmd_data.obj_files = (count_chars*)malloc(sizeof(count_chars));
+    init_count_chars(cmd_data.obj_files);
+    cmd_data.dep_rpaths = (count_chars*)malloc(sizeof(count_chars));
+    init_count_chars(cmd_data.dep_rpaths);
+    cmd_data.rpaths = (count_chars*)malloc(sizeof(count_chars));
+    init_count_chars(cmd_data.rpaths);
+    cmd_data.static_opts.normal = (count_chars*)malloc(sizeof(count_chars));
+    init_count_chars(cmd_data.static_opts.normal);
+    cmd_data.shared_opts.normal = (count_chars*)malloc(sizeof(count_chars));
+    init_count_chars(cmd_data.shared_opts.normal);
+    cmd_data.shared_opts.dependencies = (count_chars*)malloc(sizeof(count_chars));
+    init_count_chars(cmd_data.shared_opts.dependencies);
+
+    cmd_data.mode = mUnknown;
+    cmd_data.output = otGeneral;
+
+    parse_args(argc, argv, &cmd_data);
+    post_parse_fixup(&cmd_data);
+
+    if (cmd_data.mode == mUnknown) {
+        exit(0);
+    }
+
+    rc = run_mode(&cmd_data);
+
+    if (!rc) {
+       add_for_runtime(&cmd_data); 
+    }
+
+    cleanup_tmp_dirs(&cmd_data);
+    return rc;
+}
diff --git a/build/libaprapp.dsp b/build/libaprapp.dsp
new file mode 100644
index 00000000000..2e3d2001331
--- /dev/null
+++ b/build/libaprapp.dsp
@@ -0,0 +1,144 @@
+# Microsoft Developer Studio Project File - Name="libaprapp" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=libaprapp - 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 "libaprapp.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 "libaprapp.mak" CFG="libaprapp - Win32 Release"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "libaprapp - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "libaprapp - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "libaprapp - x64 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "libaprapp - x64 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "libaprapp - 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 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 "../include/arch" /I "../include/arch/win32" /I "../include/arch/unix" /D "NDEBUG" /D "WINNT" /D "WIN32" /D "_WINDOWS" /D "APR_APP" /Fo"$(INTDIR)\" /Fd"$(OUTDIR)\libaprapp-2" /FD /c
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\Release\libaprapp-2.lib"
+
+!ELSEIF  "$(CFG)" == "libaprapp - 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 "../include/arch" /I "../include/arch/win32" /I "../include/arch/unix" /D "_DEBUG" /D "WINNT" /D "WIN32" /D "_WINDOWS" /D "APR_APP" /Fo"$(INTDIR)\" /Fd"$(OUTDIR)\libaprapp-2" /FD /c
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\Debug\libaprapp-2.lib"
+
+!ELSEIF  "$(CFG)" == "libaprapp - x64 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "..\x64\Release"
+# PROP BASE Intermediate_Dir "x64\Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\x64\Release"
+# PROP Intermediate_Dir "x64\Release"
+# 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 "../include/arch" /I "../include/arch/win32" /I "../include/arch/unix" /D "NDEBUG" /D "WINNT" /D "WIN32" /D "_WINDOWS" /D "APR_APP" /Fo"$(INTDIR)\" /Fd"$(OUTDIR)\libaprapp-2" /FD /c
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\x64\Release\libaprapp-2.lib"
+
+!ELSEIF  "$(CFG)" == "libaprapp - x64 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "..\x64\Debug"
+# PROP BASE Intermediate_Dir "x64\Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\x64\Debug"
+# PROP Intermediate_Dir "x64\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 "../include/arch" /I "../include/arch/win32" /I "../include/arch/unix" /D "_DEBUG" /D "WINNT" /D "WIN32" /D "_WINDOWS" /D "APR_APP" /Fo"$(INTDIR)\" /Fd"$(OUTDIR)\libaprapp-2" /FD /c
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\x64\Debug\libaprapp-2.lib"
+
+!ENDIF 
+
+# Begin Target
+
+# Name "libaprapp - Win32 Release"
+# Name "libaprapp - Win32 Debug"
+# Name "libaprapp - x64 Release"
+# Name "libaprapp - x64 Debug"
+# Begin Source File
+
+SOURCE=..\misc\win32\apr_app.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\misc\win32\internal.c
+# End Source File
+# End Target
+# End Project
diff --git a/build/lineends.pl b/build/lineends.pl
new file mode 100644
index 00000000000..8aa735cc827
--- /dev/null
+++ b/build/lineends.pl
@@ -0,0 +1,150 @@
+#!/usr/local/bin/perl
+#
+#  Heuristically converts line endings to the current OS's preferred format
+#  
+#  All existing line endings must be identical (e.g. lf's only, or even
+#  the accidental cr.cr.lf sequence.)  If some lines end lf, and others as
+#  cr.lf, the file is presumed binary.  If the cr character appears anywhere
+#  except prefixed to an lf, the file is presumed binary.  If there is no 
+#  change in the resulting file size, or the file is binary, the conversion 
+#  is discarded.
+#  
+#  Todo: Handle NULL stdin characters gracefully.
+#
+
+use IO::File;
+use File::Find;
+
+# The ignore list is '-' seperated, with this leading hyphen and
+# trailing hyphens in ever concatinated list below.
+$ignore = "-";
+
+# Image formats
+$ignore .= "gif-jpg-jpeg-png-ico-bmp-";
+
+# Archive formats
+$ignore .= "tar-gz-z-zip-jar-war-bz2-tgz-";
+
+# Many document formats
+$ignore .= "eps-psd-pdf-chm-ai-";
+
+# Some encodings
+$ignore .= "ucs2-ucs4-";
+
+# Some binary objects
+$ignore .= "class-so-dll-exe-obj-lib-a-o-lo-slo-sl-dylib-";
+
+# Some build env files 
+$ignore .= "mcp-xdc-ncb-opt-pdb-ilk-exp-res-pch-idb-sbr-";
+
+$preservedate = 1;
+
+$forceending = 0;
+
+$givenpaths = 0;
+
+$notnative = 0;
+
+while (defined @ARGV[0]) {
+    if (@ARGV[0] eq '--touch') {
+        $preservedate = 0;
+    }
+    elsif (@ARGV[0] eq '--nocr') {
+        $notnative = -1;
+    }
+    elsif (@ARGV[0] eq '--cr') {
+        $notnative = 1;
+    }
+    elsif (@ARGV[0] eq '--force') {
+        $forceending = 1;
+    }
+    elsif (@ARGV[0] eq '--FORCE') {
+        $forceending = 2;
+    }
+    elsif (@ARGV[0] =~ m/^-/) {
+        die "What is " . @ARGV[0] . " supposed to mean?\n\n" 
+          . "Syntax:\t$0 [option()s] [path(s)]\n\n" . <<'OUTCH'
+Where:  paths specifies the top level directory to convert (default of '.')
+        options are;
+
+          --cr     keep/add one ^M
+          --nocr   remove ^M's
+          --touch  the datestamp (default: keeps date/attribs)
+          --force  mismatched corrections (unbalanced ^M's)
+          --FORCE  all files regardless of file name!
+
+OUTCH
+    }
+    else {
+        find(\&totxt, @ARGV[0]);
+        print "scanned " . @ARGV[0] . "\n";
+        $givenpaths = 1;
+    }
+    shift @ARGV;
+}
+
+if (!$givenpaths) {
+    find(\&totxt, '.');
+    print "did .\n";
+}
+
+sub totxt {
+        $oname = $_;
+        $tname = '.#' . $_;
+        if (!-f) {
+            return;
+        }
+        @exts = split /\./;
+        if ($forceending < 2) {
+            while ($#exts && ($ext = pop(@exts))) {
+                if ($ignore =~ m|-$ext-|i) {
+                    return;
+                }
+            }
+        }
+        return if ($File::Find::dir =~ m|^(.+/)?.svn(/.+)?$|);
+        @ostat = stat($oname);
+        $srcfl = new IO::File $oname, "r" or die;
+        $dstfl = new IO::File $tname, "w" or die;
+        binmode $srcfl; 
+        if ($notnative) {
+            binmode $dstfl;
+        }
+        undef $t;
+        while (<$srcfl>) { 
+            if (s/(\r*)\n$/\n/) {
+                $n = length $1;
+                if (!defined $t) { 
+                    $t = $n; 
+                }
+                if (!$forceending && (($n != $t) || m/\r/)) {
+                    print "mismatch in " .$oname. ":" .$n. " expected " .$t. "\n";
+                    undef $t;
+                    last;
+                }
+                elsif ($notnative > 0) {
+                    s/\n$/\r\n/; 
+                }
+            }
+            print $dstfl $_; 
+        }
+        if (defined $t && (tell $srcfl == tell $dstfl)) {
+            undef $t;
+        }
+        undef $srcfl;
+        undef $dstfl;
+        if (defined $t) {
+            unlink $oname or die;
+            rename $tname, $oname or die;
+            @anames = ($oname);
+            if ($preservedate) {
+                utime $ostat[9], $ostat[9], @anames;
+            }
+            chmod $ostat[2] & 07777, @anames;
+            chown $ostat[5], $ostat[6], @anames;
+            print "Converted file " . $oname . " to text in " . $File::Find::dir . "\n"; 
+        }
+        else {
+            unlink $tname or die;
+        }
+}
diff --git a/build/make_exports.awk b/build/make_exports.awk
new file mode 100644
index 00000000000..1d12fc65abe
--- /dev/null
+++ b/build/make_exports.awk
@@ -0,0 +1,150 @@
+
+BEGIN {
+    printf("/*\n")
+    printf(" * THIS FILE WAS AUTOGENERATED BY make_exports.awk\n")
+    printf(" *\n")
+    printf(" * This is an ugly hack that needs to be here, so\n")
+    printf(" * that libtool will link all of the APR functions\n")
+    printf(" * into server regardless of whether the base server\n")
+    printf(" * uses them.\n")
+    printf(" */\n")
+    printf("\n")
+    printf("#define CORE_PRIVATE\n")
+    printf("\n")
+    
+    for (i = 1; i < ARGC; i++) {
+        file = ARGV[i]
+        sub("([^/]*[/])*", "", file)
+        printf("#include \"%s\"\n", file)
+    }
+
+    printf("\n")
+    printf("const void *ap_ugly_hack = NULL;\n")
+    printf("\n")
+    
+    TYPE_NORMAL = 0
+    TYPE_HEADER = 1
+
+    stackptr = 0
+}
+
+function push(line) {
+    stack[stackptr] = line
+    stackptr++
+}
+
+function do_output() {
+    printf("/*\n")
+    printf(" * %s\n", FILENAME)
+    printf(" */\n")
+    
+    for (i = 0; i < stackptr; i++) {
+        printf("%s\n", stack[i])
+    }
+    
+    stackptr = 0
+
+    printf("\n");
+}
+
+function enter_scope(type) {
+    scope++
+    scope_type[scope] = type
+    scope_stack[scope] = stackptr
+    delete scope_used[scope]
+}
+
+function leave_scope() {
+    used = scope_used[scope]
+   
+    if (!used)
+        stackptr = scope_stack[scope]
+
+    scope--
+    if (used) {
+        scope_used[scope] = 1
+        
+        if (!scope)
+            do_output()
+    }
+}
+
+function add_symbol(symbol) {
+    if (!index(symbol, "#")) {
+        push("const void *ap_hack_" symbol " = (const void *)" symbol ";")
+        scope_used[scope] = 1
+    }
+}
+
+/^[ \t]*AP[RUI]?_(CORE_)?DECLARE[^(]*[(][^)]*[)]([^ ]* )*[^(]+[(]/ {
+    sub("[ \t]*AP[RUI]?_(CORE_)?DECLARE[^(]*[(][^)]*[)][ \t]*", "")
+    sub("[(].*", "")
+    sub("([^ ]* (^([ \t]*[(])))+", "")
+
+    add_symbol($0)
+    next
+}
+
+/^[ \t]*AP_DECLARE_HOOK[^(]*[(][^)]*/ {
+    split($0, args, ",")
+    symbol = args[2]
+    sub("^[ \t]+", "", symbol)
+    sub("[ \t]+$", "", symbol)
+
+    add_symbol("ap_hook_" symbol)
+    add_symbol("ap_hook_get_" symbol)
+    add_symbol("ap_run_" symbol)
+    next
+}
+
+/^[ \t]*APR_POOL_DECLARE_ACCESSOR[^(]*[(][^)]*[)]/ {
+    sub("[ \t]*APR_POOL_DECLARE_ACCESSOR[^(]*[(]", "", $0)
+    sub("[)].*$", "", $0)
+    add_symbol("apr_" $0 "_pool_get")
+    next
+}
+
+/^[ \t]*APR_DECLARE_INHERIT_SET[^(]*[(][^)]*[)]/ {
+    sub("[ \t]*APR_DECLARE_INHERIT_SET[^(]*[(]", "", $0)
+    sub("[)].*$", "", $0)
+    add_symbol("apr_" $0 "_inherit_set")
+    next
+}
+
+/^[ \t]*APR_DECLARE_INHERIT_UNSET[^(]*[(][^)]*[)]/ {
+    sub("[ \t]*APR_DECLARE_INHERIT_UNSET[^(]*[(]", "", $0)
+    sub("[)].*$", "", $0)
+    add_symbol("apr_" $0 "_inherit_unset")
+    next
+}
+
+/^#[ \t]*if(ndef| !defined[(])([^_]*_)*H/ {
+    enter_scope(TYPE_HEADER)
+    next
+}
+
+/^#[ \t]*if([n]?def)? / {
+    enter_scope(TYPE_NORMAL)
+    push($0)
+    next
+}
+
+/^#[ \t]*endif/ {
+    if (scope_type[scope] == TYPE_NORMAL)
+        push($0)
+        
+    leave_scope()
+    next
+}
+
+/^#[ \t]*else/ {
+    push($0)
+    next
+}
+
+/^#[ \t]*elif/ {
+    push($0)
+    next
+}
+
+
diff --git a/build/make_nw_export.awk b/build/make_nw_export.awk
new file mode 100644
index 00000000000..14f60ffdbb1
--- /dev/null
+++ b/build/make_nw_export.awk
@@ -0,0 +1,115 @@
+# 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.
+#
+# Based on apr's make_export.awk, which is
+# based on Ryan Bloom's make_export.pl
+#
+
+BEGIN {
+    add_symbol("apr_wait_for_io_or_timeout")
+}
+
+function add_symbol(sym_name) {
+    sub(" ", "", sym_name)
+    exports[++idx] = sym_name
+}
+
+# List of functions that we don't support, yet??
+#/apr_##name##_set_inherit/{next}
+#/apr_##name##_unset_inherit/{next}
+#/apr_##name##_perms_set/{next}
+/apr_socket_perms_set/{next}
+
+/^[ \t]*AP[RUI]?_DECLARE[^(]*[(][^)]*[)]([^ ]* )*[^(]+[(]/ {
+    sub("[ \t]*AP[RUI]?_DECLARE[^(]*[(][^)]*[)][ \t]*", "")
+    sub("[(].*", "")
+    sub("([^ ]* (^([ \t]*[(])))+", "")
+    add_symbol($0)
+    next
+}
+
+/^[ \t]*AP_DECLARE_HOOK[^(]*[(][^)]*/ {
+    split($0, args, ",")
+    symbol = args[2]
+    sub("^[ \t]+", "", symbol)
+    sub("[ \t]+$", "", symbol)
+    add_symbol("ap_hook_" symbol)
+    add_symbol("ap_hook_get_" symbol)
+    add_symbol("ap_run_" symbol)
+    next
+}
+
+/^[ \t]*APR_POOL_DECLARE_ACCESSOR[^(]*[(][^)]*[)]/ {
+    sub("[ \t]*APR_POOL_DECLARE_ACCESSOR[^(]*[(]", "", $0)
+    sub("[)].*$", "", $0)
+    add_symbol("apr_" $0 "_pool_get")
+    next
+}
+
+/^[ \t]*APR_DECLARE_INHERIT_SET[^(]*[(][^)]*[)]/ {
+    sub("[ \t]*APR_DECLARE_INHERIT_SET[^(]*[(]", "", $0)
+    sub("[)].*$", "", $0)
+    add_symbol("apr_" $0 "_inherit_set")
+    next
+}
+
+/^[ \t]*APR_DECLARE_INHERIT_UNSET[^(]*[(][^)]*[)]/ {
+    sub("[ \t]*APR_DECLARE_INHERIT_UNSET[^(]*[(]", "", $0)
+    sub("[)].*$", "", $0)
+    add_symbol("apr_" $0 "_inherit_unset")
+    next
+}
+
+#/^[ \t]*APR_PERMS_SET_IMPLEMENT[^(]*[(][^)]*[)]/ {
+#    sub("[ \t]*APR_PERMS_SET_IMPLEMENT[^(]*[(]", "", $0)
+#    sub("[)].*$", "", $0)
+#    add_symbol("apr_" $0 "_perms_set")
+#    next
+#}
+
+/^[ \t]*AP[RUI]?_DECLARE_DATA .*;/ {
+    gsub(/[*;\n\r]/, "", $NF)
+    gsub(/\[.*\]/, "", $NF)
+    add_symbol($NF)
+}
+
+
+END {
+    printf("Added %d symbols to export list.\n", idx) > "/dev/stderr"
+    # sort symbols with shell sort
+    increment = int(idx / 2)
+    while (increment > 0) {
+        for (i = increment+1; i <= idx; i++) {
+            j = i
+            temp = exports[i]
+            while ((j >= increment+1) && (exports[j-increment] > temp)) {
+                exports[j] = exports[j-increment]
+                j -= increment
+            }
+            exports[j] = temp
+        }
+        if (increment == 2)
+            increment = 1
+        else
+            increment = int(increment*5/11)
+    }
+    # print the array
+    printf(" (%s)\n", EXPPREFIX)
+    while (x < idx - 1) {
+        printf(" %s,\n", exports[++x])
+    }
+    printf(" %s\n", exports[++x])
+}
+
diff --git a/build/make_var_export.awk b/build/make_var_export.awk
new file mode 100644
index 00000000000..59922758d58
--- /dev/null
+++ b/build/make_var_export.awk
@@ -0,0 +1,59 @@
+# Based on apr's make_export.awk, which is
+# based on Ryan Bloom's make_export.pl
+
+/^#[ \t]*if(def)? (AP[RUI]?_|!?defined).*/ {
+	if (old_filename != FILENAME) {
+		if (old_filename != "") printf("%s", line)
+		macro_no = 0
+		found = 0
+		count = 0
+		old_filename = FILENAME
+		line = ""
+	}
+	macro_stack[macro_no++] = macro
+	macro = substr($0, length($1)+2)
+	count++
+	line = line "#ifdef " macro "\n"
+	next
+}
+
+/^#[ \t]*endif/ {
+	if (count > 0) {
+		count--
+		line = line "#endif /* " macro " */\n"
+		macro = macro_stack[--macro_no]
+	}
+	if (count == 0) {
+		if (found != 0) {
+			printf("%s", line)
+		}
+		line = ""
+	}
+	next
+}
+
+function add_symbol (sym_name) {
+	if (count) {
+		found++
+	}
+	for (i = 0; i < count; i++) {
+		line = line "\t"
+	}
+	line = line sym_name "\n"
+
+	if (count == 0) {
+		printf("%s", line)
+		line = ""
+	}
+}
+
+/^[ \t]*(extern[ \t]+)?AP[RUI]?_DECLARE_DATA .*;$/ {
+       varname = $NF;
+       gsub( /[*;]/, "", varname);
+       gsub( /\[.*\]/, "", varname);
+       add_symbol(varname);
+}
+
+END {
+	printf("%s", line)
+}
diff --git a/helpers/mkdir.sh b/build/mkdir.sh
similarity index 69%
rename from helpers/mkdir.sh
rename to build/mkdir.sh
index 4cd33c5671c..c59f03e181b 100755
--- a/helpers/mkdir.sh
+++ b/build/mkdir.sh
@@ -23,10 +23,18 @@ for file in ${1+"$@"} ; do
         pathcomp="$pathcomp$d"
         case "$pathcomp" in
             -* ) pathcomp=./$pathcomp ;;
+            ?: ) pathcomp="$pathcomp/" 
+                 continue ;;
         esac
         if test ! -d "$pathcomp"; then
             echo "mkdir $pathcomp" 1>&2
-            mkdir "$pathcomp" || errstatus=$?
+            thiserrstatus=0
+            mkdir "$pathcomp" || thiserrstatus=$?
+            # ignore errors due to races if a parallel mkdir.sh already
+            # created the dir
+            if test $thiserrstatus != 0 && test ! -d "$pathcomp" ; then
+                errstatus=$thiserrstatus
+            fi
         fi
         pathcomp="$pathcomp/"
     done
diff --git a/build/nw_export.h b/build/nw_export.h
new file mode 100644
index 00000000000..c69442e8c3e
--- /dev/null
+++ b/build/nw_export.h
@@ -0,0 +1,75 @@
+/* Must include apr.h / apu.h first so that we can undefine
+** the standard prototypes macros after it messes with them.
+*/
+#include "apr.h"
+
+#undef APR_DECLARE
+#undef APR_DECLARE_NONSTD
+#undef APR_DECLARE_HOOK
+#undef APR_POOL_DECLARE_ACCESSOR
+#undef APR_DECLARE_DATA
+
+/* Preprocess all of the standard APR headers. */
+#include "apr_allocator.h"
+#include "apr_anylock.h"
+#include "apr_atomic.h"
+#include "apr_base64.h"
+#include "apr_buckets.h"
+#include "apr_date.h"
+#include "apr_dbd.h"
+#include "apr_dbm.h"
+#include "apr_dbm_private.h"
+#include "apr_dso.h"
+#include "apr_env.h"
+#include "apr_errno.h"
+#include "apr_escape.h"
+#include "apr_file_info.h"
+#include "apr_file_io.h"
+#include "apr_fnmatch.h"
+#include "apr_general.h"
+#include "apr_getopt.h"
+#include "apr_global_mutex.h"
+#include "apr_hash.h"
+#include "apr_hooks.h"
+#include "apr_inherit.h"
+#include "apr_lib.h"
+#include "apr_md4.h"
+#include "apr_md5.h"
+#include "apr_memcache.h"
+#include "apr_mmap.h"
+#include "apr_network_io.h"
+#include "apr_optional.h"
+#include "apr_optional_hooks.h"
+#include "apr_poll.h"
+#include "apr_pools.h"
+#include "apr_portable.h"
+#include "apr_proc_mutex.h"
+#include "apr_queue.h"
+#include "apr_random.h"
+#include "apr_reslist.h"
+#include "apr_ring.h"
+#include "apr_rmm.h"
+#include "apr_sdbm.h"
+#include "apr_sha1.h"
+#include "apr_shm.h"
+#include "apr_signal.h"
+#include "apr_siphash.h"
+#include "apr_skiplist.h"
+#include "apr_strings.h"
+#include "apr_strmatch.h"
+#include "apr_support.h"
+#include "apr_tables.h"
+#include "apr_thread_cond.h"
+#include "apr_thread_mutex.h"
+#include "apr_thread_pool.h"
+#include "apr_thread_proc.h"
+#include "apr_thread_rwlock.h"
+#include "apr_time.h"
+#include "apr_uri.h"
+#include "apr_user.h"
+#include "apr_uuid.h"
+#include "apr_version.h"
+#include "apr_want.h"
+#include "apr_xlate.h"
+#include "apr_xml.h"
+#include "apu_want.h"
diff --git a/build/nw_ver.awk b/build/nw_ver.awk
new file mode 100644
index 00000000000..0285e990022
--- /dev/null
+++ b/build/nw_ver.awk
@@ -0,0 +1,70 @@
+# 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.
+
+BEGIN {
+
+  # fetch APR version numbers from input file and write them to STDOUT
+
+  while ((getline < ARGV[1]) > 0) {
+    if (match ($0, /^#define AP._MAJOR_VERSION/)) {
+      ver_major = $3;
+    }
+    else if (match ($0, /^#define AP._MINOR_VERSION/)) {
+      ver_minor = $3;
+    }
+    else if (match ($0, /^#define AP._PATCH_VERSION/)) {
+      ver_patch = $3;
+    }
+    else if (match ($0, /^#define AP._IS_DEV_VERSION/)) {
+      ver_devbuild = 1;
+    }
+  }
+  if (ver_devbuild) {
+    ver_dev = "-dev"
+    if (ARGV[2]) {
+      while ((getline < ARGV[2]) > 0) {
+        if (match ($0, /^\/repos\/asf\/!svn\/ver\/[0-9]+\/apr\/(apr|apr-util)\/(trunk|branches\/[0-9]\.[0-9]\.x)$/)) {
+          gsub(/^\/repos\/asf\/!svn\/ver\/|\/apr\/(apr|apr-util)\/(trunk|branches\/[0-9]\.[0-9]\.x)$/, "", $0);
+          ver_dev = svn_rev = "-r" $0;
+        }
+      }
+    }
+  }
+
+  if (WANTED) {
+    ver_num = ver_major * 1000000 + ver_minor * 1000 + ver_patch;
+    if (ver_num < WANTED) {
+      print "ERROR: APR version " ver_str " does NOT match!";
+      exit 1;
+    } else if (ver_num > (WANTED + 1000)) {
+      print "WARNING: APR version " ver_str " higher than expected!";
+      exit 0;
+    } else {
+      print "OK: APR version " ver_str "";
+      exit 0;
+    }
+  } else {
+    ver_nlm = ver_major "," ver_minor "," ver_patch;
+    ver_str = ver_major "." ver_minor "." ver_patch ver_dev;
+    print "VERSION = " ver_nlm "";
+    print "VERSION_STR = " ver_str "";
+    print "VERSION_MAJMIN = " ver_major ver_minor "";
+    # print "COPYRIGHT_STR = " copyright_str "";
+    print "SVN_REVISION = " svn_rev "";
+  }
+
+}
+
+
diff --git a/build/pkg/README b/build/pkg/README
new file mode 100644
index 00000000000..ce1c9b73a95
--- /dev/null
+++ b/build/pkg/README
@@ -0,0 +1,20 @@
+The script in this directory will attempt to build a Solaris package
+out of a source tree for APR.
+
+To build a package, make sure you are in the root of the source tree,
+and run:
+
+build/pkg/buildpkg.sh
+
+A Solaris package called apr-<version>-<architecture>-local.gz will be
+created in the root of the source tree.
+
+By default, if you attempt to build packages for apr-util, it will
+search for the sources for apr in:
+
+../apr
+
+You may override the location of apr like so:
+
+build/pkg/buildpkg.sh --with-apr=some/other/path
+
diff --git a/build/pkg/buildpkg.sh b/build/pkg/buildpkg.sh
new file mode 100755
index 00000000000..073e89d746f
--- /dev/null
+++ b/build/pkg/buildpkg.sh
@@ -0,0 +1,72 @@
+#!/bin/sh
+# 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.
+#
+#
+
+# buildpkg.sh: This script builds a Solaris PKG from the source tree
+#              provided.
+
+PREFIX=/usr/local
+TEMPDIR=/var/tmp/$USER/apr-root
+rm -rf $TEMPDIR
+
+apr_src_dir=.
+
+while test $# -gt 0 
+do
+  # Normalize
+  case "$1" in
+  -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+  *) optarg= ;;
+  esac
+
+  case "$1" in
+  --with-apr=*)
+  apr_src_dir=$optarg
+  ;;
+  esac
+
+  shift
+done
+
+if [ -f "$apr_src_dir/configure.in" ]; then
+  cd $apr_src_dir
+else
+  echo "The apr source could not be found within $apr_src_dir"
+  echo "Usage: buildpkg [--with-apr=dir]"
+  exit 1
+fi
+
+./configure --prefix=$PREFIX
+make
+make install DESTDIR=$TEMPDIR
+rm $TEMPDIR$PREFIX/lib/apr.exp
+. build/pkg/pkginfo
+cp build/pkg/pkginfo $TEMPDIR$PREFIX
+
+current=`pwd`
+cd $TEMPDIR$PREFIX
+echo "i pkginfo=./pkginfo" > prototype
+find . -print | grep -v ./prototype | grep -v ./pkginfo | pkgproto | awk '{print $1" "$2" "$3" "$4" root bin"}' >> prototype
+mkdir $TEMPDIR/pkg
+pkgmk -r $TEMPDIR$PREFIX -d $TEMPDIR/pkg
+
+cd $current
+pkgtrans -s $TEMPDIR/pkg $current/$NAME-$VERSION-$ARCH-local
+gzip $current/$NAME-$VERSION-$ARCH-local
+
+rm -rf $TEMPDIR
+
diff --git a/build/pkg/pkginfo.in b/build/pkg/pkginfo.in
new file mode 100644
index 00000000000..f389b26901a
--- /dev/null
+++ b/build/pkg/pkginfo.in
@@ -0,0 +1,11 @@
+PKG="ASFapr-1"
+NAME="apr"
+ARCH="@target_cpu@"
+VERSION="@APR_DOTTED_VERSION@"
+CATEGORY="application"
+VENDOR="Apache Software Foundation"
+EMAIL="dev@apr.apache.org"
+PSTAMP="dev@apr.apache.org"
+BASEDIR="@prefix@"
+CLASSES="none"
+
diff --git a/build/preaprapp.dsp b/build/preaprapp.dsp
new file mode 100644
index 00000000000..b17aa7b0786
--- /dev/null
+++ b/build/preaprapp.dsp
@@ -0,0 +1,131 @@
+# Microsoft Developer Studio Project File - Name="preaprapp" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) External Target" 0x0106
+
+CFG=preaprapp - 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 "preaprapp.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 "preaprapp.mak" CFG="preaprapp - Win32 Release"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "preaprapp - Win32 Release" (based on "Win32 (x86) External Target")
+!MESSAGE "preaprapp - Win32 Debug" (based on "Win32 (x86) External Target")
+!MESSAGE "preaprapp - x64 Release" (based on "Win32 (x86) External Target")
+!MESSAGE "preaprapp - x64 Debug" (based on "Win32 (x86) External Target")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+
+!IF  "$(CFG)" == "preaprapp - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir ""
+# PROP BASE Intermediate_Dir ""
+# PROP BASE Cmd_Line "NMAKE /nologo /f NUL"
+# PROP BASE Rebuild_Opt "/a"
+# PROP BASE Target_File "preaprapp.exe"
+# PROP BASE Bsc_Name "preaprapp.bsc"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ""
+# PROP Intermediate_Dir ""
+# PROP Cmd_Line "NMAKE /nologo /f NUL"
+# PROP Rebuild_Opt "/a"
+# PROP Bsc_Name ""
+# PROP Target_Dir ""
+
+!ELSEIF  "$(CFG)" == "preaprapp - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir ""
+# PROP BASE Intermediate_Dir ""
+# PROP BASE Cmd_Line "NMAKE /nologo /f NUL"
+# PROP BASE Rebuild_Opt "/a"
+# PROP BASE Target_File "preaprapp.exe"
+# PROP BASE Bsc_Name "preaprapp.bsc"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir ""
+# PROP Cmd_Line "NMAKE /nologo /f NUL"
+# PROP Rebuild_Opt "/a"
+# PROP Bsc_Name ""
+# PROP Target_Dir ""
+
+!ELSEIF  "$(CFG)" == "preaprapp - x64 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir ""
+# PROP BASE Intermediate_Dir ""
+# PROP BASE Cmd_Line "NMAKE /nologo /f NUL"
+# PROP BASE Rebuild_Opt "/a"
+# PROP BASE Target_File "preaprapp.exe"
+# PROP BASE Bsc_Name "preaprapp.bsc"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ""
+# PROP Intermediate_Dir ""
+# PROP Cmd_Line "NMAKE /nologo /f NUL"
+# PROP Rebuild_Opt "/a"
+# PROP Bsc_Name ""
+# PROP Target_Dir ""
+
+!ELSEIF  "$(CFG)" == "preaprapp - x64 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir ""
+# PROP BASE Intermediate_Dir ""
+# PROP BASE Cmd_Line "NMAKE /nologo /f NUL"
+# PROP BASE Rebuild_Opt "/a"
+# PROP BASE Target_File "preaprapp.exe"
+# PROP BASE Bsc_Name "preaprapp.bsc"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir ""
+# PROP Cmd_Line "NMAKE /nologo /f NUL"
+# PROP Rebuild_Opt "/a"
+# PROP Bsc_Name ""
+# PROP Target_Dir ""
+
+!ENDIF 
+
+# Begin Target
+
+# Name "preaprapp - Win32 Release"
+# Name "preaprapp - Win32 Debug"
+# Name "preaprapp - x64 Release"
+# Name "preaprapp - x64 Debug"
+
+!IF  "$(CFG)" == "preaprapp - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "preaprapp - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "preaprapp - x64 Release"
+
+!ELSEIF  "$(CFG)" == "preaprapp - x64 Debug"
+
+!ENDIF 
+
+# End Target
+# End Project
diff --git a/build/prelibaprapp.dsp b/build/prelibaprapp.dsp
new file mode 100644
index 00000000000..b370a14f34e
--- /dev/null
+++ b/build/prelibaprapp.dsp
@@ -0,0 +1,131 @@
+# Microsoft Developer Studio Project File - Name="prelibaprapp" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) External Target" 0x0106
+
+CFG=prelibaprapp - 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 "prelibaprapp.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 "prelibaprapp.mak" CFG="prelibaprapp - Win32 Release"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "prelibaprapp - Win32 Release" (based on "Win32 (x86) External Target")
+!MESSAGE "prelibaprapp - Win32 Debug" (based on "Win32 (x86) External Target")
+!MESSAGE "prelibaprapp - x64 Release" (based on "Win32 (x86) External Target")
+!MESSAGE "prelibaprapp - x64 Debug" (based on "Win32 (x86) External Target")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+
+!IF  "$(CFG)" == "prelibaprapp - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir ""
+# PROP BASE Intermediate_Dir ""
+# PROP BASE Cmd_Line "NMAKE /nologo /f NUL"
+# PROP BASE Rebuild_Opt "/a"
+# PROP BASE Target_File "prelibaprapp.exe"
+# PROP BASE Bsc_Name "prelibaprapp.bsc"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ""
+# PROP Intermediate_Dir ""
+# PROP Cmd_Line "NMAKE /nologo /f NUL"
+# PROP Rebuild_Opt "/a"
+# PROP Bsc_Name ""
+# PROP Target_Dir ""
+
+!ELSEIF  "$(CFG)" == "prelibaprapp - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir ""
+# PROP BASE Intermediate_Dir ""
+# PROP BASE Cmd_Line "NMAKE /nologo /f NUL"
+# PROP BASE Rebuild_Opt "/a"
+# PROP BASE Target_File "prelibaprapp.exe"
+# PROP BASE Bsc_Name "prelibaprapp.bsc"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir ""
+# PROP Cmd_Line "NMAKE /nologo /f NUL"
+# PROP Rebuild_Opt "/a"
+# PROP Bsc_Name ""
+# PROP Target_Dir ""
+
+!ELSEIF  "$(CFG)" == "prelibaprapp - x64 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir ""
+# PROP BASE Intermediate_Dir ""
+# PROP BASE Cmd_Line "NMAKE /nologo /f NUL"
+# PROP BASE Rebuild_Opt "/a"
+# PROP BASE Target_File "prelibaprapp.exe"
+# PROP BASE Bsc_Name "prelibaprapp.bsc"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ""
+# PROP Intermediate_Dir ""
+# PROP Cmd_Line "NMAKE /nologo /f NUL"
+# PROP Rebuild_Opt "/a"
+# PROP Bsc_Name ""
+# PROP Target_Dir ""
+
+!ELSEIF  "$(CFG)" == "prelibaprapp - x64 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir ""
+# PROP BASE Intermediate_Dir ""
+# PROP BASE Cmd_Line "NMAKE /nologo /f NUL"
+# PROP BASE Rebuild_Opt "/a"
+# PROP BASE Target_File "prelibaprapp.exe"
+# PROP BASE Bsc_Name "prelibaprapp.bsc"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir ""
+# PROP Cmd_Line "NMAKE /nologo /f NUL"
+# PROP Rebuild_Opt "/a"
+# PROP Bsc_Name ""
+# PROP Target_Dir ""
+
+!ENDIF 
+
+# Begin Target
+
+# Name "prelibaprapp - Win32 Release"
+# Name "prelibaprapp - Win32 Debug"
+# Name "prelibaprapp - x64 Release"
+# Name "prelibaprapp - x64 Debug"
+
+!IF  "$(CFG)" == "prelibaprapp - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "prelibaprapp - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "prelibaprapp - x64 Release"
+
+!ELSEIF  "$(CFG)" == "prelibaprapp - x64 Debug"
+
+!ENDIF 
+
+# End Target
+# End Project
diff --git a/build/rpm/apr.spec.in b/build/rpm/apr.spec.in
new file mode 100644
index 00000000000..4a2645527b6
--- /dev/null
+++ b/build/rpm/apr.spec.in
@@ -0,0 +1,201 @@
+
+%define aprver 2
+
+Summary: Apache Portable Runtime library
+Name: apr
+Version: APR_VERSION
+Release: APR_RELEASE
+License: Apache Software License
+Group: System Environment/Libraries
+URL: http://apr.apache.org/
+Source0: http://www.apache.org/dist/apr/%{name}-%{version}.tar.bz2
+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot
+BuildRequires: autoconf, libtool, doxygen, libuuid-devel, python
+
+%description
+The mission of the Apache Portable Runtime (APR) is to provide a
+free library of C data structures and routines, forming a system
+portability layer to as many operating systems as possible,
+including Unices, MS Win32, BeOS and OS/2.
+
+%package devel
+Group: Development/Libraries
+Summary: APR library development kit
+Requires: apr = %{version}
+
+%description devel
+This package provides the support files which can be used to 
+build applications using the APR library.  The mission of the
+Apache Portable Runtime (APR) is to provide a free library of 
+C data structures and routines.
+
+%package dbm
+Group: Development/Libraries 
+Summary: APR utility library DBM driver
+BuildRequires: db4-devel
+Requires: apr-util = %{version}-%{release}
+
+%description dbm
+This package provides the DBM driver for the apr-util.
+
+%package pgsql
+Group: Development/Libraries
+Summary: APR utility library PostgreSQL DBD driver
+BuildRequires: postgresql-devel
+Requires: apr-util = %{version}-%{release}
+
+%description pgsql
+This package provides the PostgreSQL driver for the apr-util
+DBD (database abstraction) interface.
+
+%package mysql
+Group: Development/Libraries
+Summary: APR utility library MySQL DBD driver
+BuildRequires: mysql-devel
+Requires: apr-util = %{version}-%{release}
+
+%description mysql
+This package provides the MySQL driver for the apr-util DBD
+(database abstraction) interface.
+
+%package sqlite
+Group: Development/Libraries
+Summary: APR utility library SQLite DBD driver
+BuildRequires: sqlite-devel >= 3.0.0
+Requires: apr-util = %{version}-%{release}
+
+%description sqlite
+This package provides the SQLite driver for the apr-util DBD
+(database abstraction) interface.
+
+%package odbc
+Group: Development/Libraries
+Summary: APR utility library ODBC DBD driver
+BuildRequires: unixODBC-devel
+Requires: apr-util = %{version}-%{release}
+
+%description odbc
+This package provides the ODBC driver for the apr-util DBD
+(database abstraction) interface.
+
+%package openssl
+Group: Development/Libraries
+Summary: APR utility library OpenSSL crypto support
+BuildRequires: openssl-devel
+Requires: apr-util = %{version}-%{release}
+
+%description openssl
+This package provides crypto support for apr-util based on OpenSSL.
+
+%package nss
+Group: Development/Libraries
+Summary: APR utility library NSS crypto support
+BuildRequires: nss-devel
+Requires: apr-util = %{version}-%{release}
+
+%description nss
+This package provides crypto support for apr-util based on Mozilla NSS.
+
+%prep
+%setup -q
+
+%build
+# regenerate configure script etc.
+./buildconf
+%configure \
+        --prefix=/usr \
+        --includedir=%{_includedir}/apr-%{aprver} \
+        --with-installbuilddir=%{_libdir}/apr/build-%{aprver} \
+        --with-devrandom=/dev/urandom \
+        --without-gdbm \
+        --with-sqlite3 --with-pgsql --with-mysql --with-odbc \
+        --with-berkeley-db \
+        --with-crypto --with-openssl --with-nss \
+        --without-sqlite2
+        CC=gcc CXX=g++
+make %{?_smp_mflags} && make dox
+
+%check
+# Run non-interactive tests
+pushd test
+make %{?_smp_mflags} all CFLAGS=-fno-strict-aliasing
+make check || exit 1
+popd
+
+%install
+rm -rf $RPM_BUILD_ROOT
+make install DESTDIR=$RPM_BUILD_ROOT
+
+# Move docs to more convenient location
+mv docs/dox/html html
+
+# Unpackaged files:
+rm -f $RPM_BUILD_ROOT%{_libdir}/apr.exp
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%post -p /sbin/ldconfig
+
+%postun -p /sbin/ldconfig
+
+%files
+%defattr(-,root,root,-)
+%doc CHANGES LICENSE NOTICE
+%{_libdir}/libapr-%{aprver}.so.*
+%dir %{_libdir}/apr-%{aprver}
+
+%files dbm
+%defattr(-,root,root,-)
+%{_libdir}/apr-%{aprver}/apr_dbm_db*
+
+%files pgsql
+%defattr(-,root,root,-)
+%{_libdir}/apr-%{aprver}/apr_dbd_pgsql*
+
+%files mysql
+%defattr(-,root,root,-)
+%{_libdir}/apr-%{aprver}/apr_dbd_mysql*
+
+%files sqlite
+%defattr(-,root,root,-)
+%{_libdir}/apr-%{aprver}/apr_dbd_sqlite*
+
+%files odbc
+%defattr(-,root,root,-)
+%{_libdir}/apr-%{aprver}/apr_dbd_odbc*
+
+%files openssl
+%defattr(-,root,root,-)
+%{_libdir}/apr-%{aprver}/apr_crypto_openssl*
+
+%files nss
+%defattr(-,root,root,-)
+%{_libdir}/apr-%{aprver}/apr_crypto_nss*
+
+%files devel
+%defattr(-,root,root,-)
+%doc docs/APRDesign.html docs/canonical_filenames.html
+%doc docs/incomplete_types docs/non_apr_programs
+%doc html
+%{_bindir}/apr*config
+%{_libdir}/libapr-%{aprver}.*a
+%{_libdir}/libapr-%{aprver}.so
+%dir %{_libdir}/apr
+%dir %{_libdir}/apr/build-%{aprver}
+%{_libdir}/apr/build-%{aprver}/*
+%{_libdir}/pkgconfig/apr-%{aprver}.pc
+%dir %{_includedir}/apr-%{aprver}
+%{_includedir}/apr-%{aprver}/*.h
+
+%changelog
+* Sat Aug 30 2008 Graham Leggett <minfrin@sharp.fm> 1.3.3
+- update to depend on the bzip2 binary
+- build depends on python
+
+* Tue Jun 22 2004 Graham Leggett <minfrin@sharp.fm> 1.0.0-1
+- update to support v1.0.0 of APR
+
+* Tue Jun 22 2004 Graham Leggett <minfrin@sharp.fm> 1.0.0-1
+- derived from Fedora Core apr.spec
+
diff --git a/build/run-gcov.sh b/build/run-gcov.sh
new file mode 100755
index 00000000000..98f911fc89a
--- /dev/null
+++ b/build/run-gcov.sh
@@ -0,0 +1,130 @@
+#!/bin/sh
+
+if [ ! -d coverage ]; then
+    mkdir coverage
+fi
+cd coverage
+
+# It would be really nice to find a better way to do this than copying the 
+# HTML into this script.  But, I am being lazy right now.
+cat > index.html << EOF
+<!-- This is a generated file, do not edit -->
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html>
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"/>
+    <meta name="author" content="APR Developers" /><meta name="email" content="dev@apr.apache.org" />
+    <title>Test Coverage</title>
+  </head>
+  <body bgcolor="#ffffff" text="#000000" link="#525D76">
+<p><a href="/"><img src="./images/apr_logo_wide.png" alt="The Apache Portable Runtime Project" border="0"/></a></p>
+ <table border="0" width="100%" cellspacing="4">
+  <tr>
+   <!-- LEFT SIDE NAVIGATION -->
+   <td valign="top" nowrap="nowrap">
+    <a href="http://apachecon.com/"
+    ><img src="http://www.apache.org/images/ac2003-150.gif" height="86"
+    width="150" border="0" alt="ApacheCon" /></a>
+          <p><b>Get Involved</b></p>
+   <menu compact="compact">
+         <li><a href="/anoncvs.txt">CVS</a></li>
+         <li><a href="/mailing-lists.html">Mailing Lists</a></li>
+         <li><a href="http://cvs.apache.org/snapshots/apr/">Snapshots</a></li>
+         <li><a href="/compiling_win32.html">Build on Win32</a></li>
+         <li><a href="/compiling_unix.html">Build on Unix</a></li>
+       </menu>
+     <p><b>Download!</b></p>
+   <menu compact="compact">
+         <li><a href="http://www.apache.org/dyn/closer.cgi/apr/">from a mirror</a></li>
+       </menu>
+     <p><b>Docs</b></p>
+   <menu compact="compact">
+         <li><a href="/docs/apr/">APR</a></li>
+         <li><a href="/docs/apr-util/">APR-util</a></li>
+         <li>APR-iconv</li>
+       </menu>
+     <p><b>Guidelines</b></p>
+   <menu compact="compact">
+         <li><a href="/guidelines.html">Project Guidelines</a></li>
+         <li><a href="/patches.html">Contributing</a></li>
+         <li><a href="/versioning.html">Version Numbers</a></li>
+      </menu>
+    <p><b><a href="/info/">Miscellaneous</a></b></p>
+  <menu compact="compact">
+        <li><a href="http://www.apache.org/LICENSE.txt">License</a></li>
+        <li><a href="/projects.html">Projects using APR</a></li>
+      </menu>
+  </td>
+  <!-- RIGHT SIDE INFORMATION -->
+  <td align="left" valign="top">
+  <table border="0" cellspacing="0" cellpadding="2" width="100%">
+  <tr><td bgcolor="#525D76">
+   <font color="#ffffff" face="arial,helvetica,sanserif">
+    <strong>APR Test Coverage</strong>
+   </font>
+  </td></tr>
+  <tr><td>
+   <blockquote>
+<p>This should give us some idea of how well our tests actually stress our
+code.  To generate this data, do the following:</p>
+<menu compact="compact">
+    <li>./buildconf</li>
+    <li>CFLAGS="-fprofile-arcs -ftest-coverage ./configure</li>
+    <li>make</li>
+    <li>cd test</li>
+    <li>make</li>
+    <li>./testall</li>
+    <li>cd ..</li>
+    <li>make gcov</li>
+</menu>
+<p>Note that this will only generate test coverage data for the testall script,
+but all tests should be moving to the unified framework, so this is correct.</p>
+   </blockquote>
+
+   <table border="0" width="100%" cellspacing="0">
+EOF
+
+for i in `find .. -name "*.bb" -maxdepth 1 | sort`; do
+    percent=`gcov $i -o .. | grep "%" | awk -F'%' {'print $1'}`
+    name=`echo $i | awk -F'/' {'print $2'}`
+    basename=`echo $name | awk -F'.' {'print $1'}` 
+
+    if [ "x$percent" = "x" ]; then
+        echo "<tr>" >> index.html
+        echo "<td bgcolor=#ffffff> Error generating data for $basename<br>" >> index.html
+        continue;	
+    fi
+    intpercent=`echo "$percent/1" | bc`
+    if [ $intpercent -lt 33 ]; then
+        color="#ffaaaa"
+    else if [ $intpercent -lt 66 ]; then
+        color="#ffff77"
+        else
+            color="#aaffaa"
+        fi
+    fi
+
+    echo "<tr>" >> index.html
+    echo "<td bgcolor=$color><a href=\"$basename.c.gcov\">$basename</a><br>" >> index.html
+    echo "<td bgcolor=$color>$percent% tested"  >> index.html
+done
+
+echo "</table><p>Last generated `date`</p>" >> index.html
+
+cat >> index.html << EOF
+</td></tr>
+</table>
+   <!-- FOOTER -->
+   <tr><td colspan="2"><hr noshade="noshade" size="1"/></td></tr>
+   <tr><td colspan="2" align="center">
+        <font size="-1">
+         <em>Copyright &#169; 1999-2004, The Apache Software Foundation</em>
+        </font>
+       </td>
+   </tr>
+  </table>
+ </body>
+</html>
+
+EOF
diff --git a/build/subst.py b/build/subst.py
new file mode 100644
index 00000000000..042035a8d8d
--- /dev/null
+++ b/build/subst.py
@@ -0,0 +1,68 @@
+#
+#
+#  Ported from <http://www.scons.org/wiki/SubstInFileBuilder>
+#  """ This code is freely available for your use. """
+#
+
+import re
+from SCons.Script import * 
+
+def do_subst_in_file(targetfile, sourcefile, dict):
+    """Replace all instances of the keys of dict with their values.
+    For example, if dict is {'%VERSION%': '1.2345', '%BASE%': 'MyProg'},
+    then all instances of %VERSION% in the file will be replaced with 1.2345 etc.
+    """
+    try:
+        f = open(sourcefile, 'rb')
+        contents = f.read()
+        f.close()
+    except:
+        raise SCons.Errors.UserError, "Can't read source file %s"%sourcefile
+    for (k,v) in dict.items():
+        contents = re.sub(k, v, contents)
+    try:
+        f = open(targetfile, 'wb')
+        f.write(contents)
+        f.close()
+    except:
+        raise SCons.Errors.UserError, "Can't write target file %s"%targetfile
+    return 0 # success
+
+def subst_in_file(target, source, env):
+    if not env.has_key('SUBST_DICT'):
+        raise SCons.Errors.UserError, "SubstFile requires SUBST_DICT to be set."
+    d = dict(env['SUBST_DICT']) # copy it
+    for (k,v) in d.items():
+        if callable(v):
+            d[k] = env.subst(v())
+        elif SCons.Util.is_String(v):
+            d[k]=env.subst(v)
+        else:
+            d[k] = SCons.Util.to_String(v)
+    for (t,s) in zip(target, source):
+        return do_subst_in_file(str(t), str(s), d)
+
+def subst_in_file_string(target, source, env):
+    """This is what gets printed on the console."""
+    return '\n'.join(['Substituting vars from %s into %s'%(str(s), str(t))
+                      for (t,s) in zip(target, source)])
+
+def subst_emitter(target, source, env):
+    """Add dependency from substituted SUBST_DICT to target.
+    Returns original target, source tuple unchanged.
+    """
+    d = env['SUBST_DICT'].copy() # copy it
+    for (k,v) in d.items():
+        if callable(v):
+            d[k] = env.subst(v())
+        elif SCons.Util.is_String(v):
+            d[k] = env.subst(v)
+    Depends(target, SCons.Node.Python.Value(d))
+    return target, source
+
+def generate(env):
+  subst_action=SCons.Action.Action(subst_in_file, subst_in_file_string)
+  env['BUILDERS']['SubstFile'] = Builder(action=subst_action, emitter=subst_emitter)
+
+def exists(env):
+    return 1
diff --git a/build/win32ver.awk b/build/win32ver.awk
new file mode 100644
index 00000000000..11be08072d0
--- /dev/null
+++ b/build/win32ver.awk
@@ -0,0 +1,124 @@
+BEGIN {
+
+  # ff bits: 1(debug), 2(prerelease), 4(patched), 8(vendor) and 32(special)
+  # debug is summed based on the /Define _DEBUG
+  # prerelease is based on the -dev extension,
+  # patched is based on a non-standard "-ver" extension, 
+  # special and vendor are toggled by their args.
+  #
+  ff = 0;
+
+  file=ARGV[1];
+  desc=ARGV[2];
+  rel_h=ARGV[3];
+
+  filename = file;
+  if (match(file, /\./)) {
+    sub(/\.[^\.]*$/, "", file);
+  }
+
+  i = 4;
+  while (length(ARGV[i])) {
+    if (match(ARGV[i], /icon=/)) {
+      icon = substr(ARGV[i], 6);
+    }
+    if (match(ARGV[i], /vendor=/)) {
+      vendor = substr(ARGV[i], 8);
+      ff = ff + 8;
+    }
+    if (match(ARGV[i], /special=/)) {
+      special = substr(ARGV[i], 9);
+      ff = ff + 32;
+    }
+    i = i + 1
+  }
+
+  i = i - 1;
+  while (i) {
+    delete ARGV[i];
+    i = i - 1;
+  }
+
+  while ((getline < rel_h) > 0) {
+    if (match ($0, /^#define AP._MAJOR_VERSION/)) {
+      ver_major = $3;
+    }
+    if (match ($0, /^#define AP._MINOR_VERSION/)) {
+      ver_minor = $3;
+    }
+    if (match ($0, /^#define AP._PATCH_VERSION/)) {
+      ver_patch = $3;
+    }
+    if (match ($0, /^#define AP._IS_DEV_VERSION/)) {
+      ver_suffix = "-dev";
+      ver_build = "0";
+    }
+    if (match ($0, /^#undef AP._IS_DEV_VERSION/)) {
+      ver_build = "100";
+    }
+    if (match ($0, /^.*Copyright /)) {
+      copyright = substr($0, RLENGTH + 1);
+    }
+  }
+  ver = ver_major "." ver_minor "." ver_patch ver_suffix;
+  verc = ver_major "," ver_minor "," ver_patch "," ver_build;   
+
+  if (length(vendor)) {
+    ff = ff + 8;
+  }
+
+  if (length(icon)) {
+    print "1 ICON DISCARDABLE \"" icon "\"";
+  }
+  print "1 VERSIONINFO";
+  print " FILEVERSION " verc "";
+  print " PRODUCTVERSION " verc "";
+  print " FILEFLAGSMASK 0x3fL";
+  print "#if defined(_DEBUG)"
+  print " FILEFLAGS 0x" sprintf("%02x", ff + 1) "L";
+  print "#else"
+  print " FILEFLAGS 0x" sprintf("%02x", ff) "L";
+  print "#endif"
+  print " FILEOS 0x40004L";
+  print " FILETYPE 0x1L";
+  print " FILESUBTYPE 0x0L";
+  print "BEGIN";
+  print "  BLOCK \"StringFileInfo\"";
+  print "  BEGIN";
+  print "    BLOCK \"040904b0\"";
+  print "    BEGIN";
+  print "    VALUE \"Comments\", "\
+  "\"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\\r\\n\\r\\n" \
+  "http://www.apache.org/licenses/LICENSE-2.0\\r\\n\\r\\n" \
+  "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.\\0\"";
+  print "      VALUE \"CompanyName\", \"Apache Software Foundation\\0\"";
+  print "      VALUE \"FileDescription\", \"" desc "\\0\"";
+  print "      VALUE \"FileVersion\", \"" ver "\\0\"";
+  print "      VALUE \"InternalName\", \"" file "\\0\"";
+  print "      VALUE \"LegalCopyright\", \"Copyright " copyright "\\0\"";
+  print "      VALUE \"OriginalFilename\", \"" filename "\\0\"";
+  if (vendor) {
+    print "      VALUE \"PrivateBuild\", \"" vendor "\\0\"";
+  }
+  if (special) {
+    print "      VALUE \"SpecialBuild\", \"" vendor "\\0\"";
+  }
+  print "      VALUE \"ProductName\", \"Apache Portable Runtime\\0\"";
+  print "      VALUE \"ProductVersion\", \"" ver "\\0\"";
+  print "    END";
+  print "  END";
+  print "  BLOCK \"VarFileInfo\"";
+  print "  BEGIN";
+  print "    VALUE \"Translation\", 0x409, 1200";
+  print "  END";
+  print "END";
+}
diff --git a/build/xml.m4 b/build/xml.m4
new file mode 100644
index 00000000000..3c31ea995a0
--- /dev/null
+++ b/build/xml.m4
@@ -0,0 +1,211 @@
+dnl -------------------------------------------------------- -*- autoconf -*-
+dnl Licensed to the Apache Software Foundation (ASF) under one or more
+dnl contributor license agreements.  See the NOTICE file distributed with
+dnl this work for additional information regarding copyright ownership.
+dnl The ASF licenses this file to You under the Apache License, Version 2.0
+dnl (the "License"); you may not use this file except in compliance with
+dnl the License.  You may obtain a copy of the License at
+dnl
+dnl     http://www.apache.org/licenses/LICENSE-2.0
+dnl
+dnl Unless required by applicable law or agreed to in writing, software
+dnl distributed under the License is distributed on an "AS IS" BASIS,
+dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+dnl See the License for the specific language governing permissions and
+dnl limitations under the License.
+
+
+dnl
+dnl APU_TRY_EXPAT_LINK(
+dnl      test-message, cache-var-name, hdrs, libs,
+dnl      [actions-on-success], [actions-on-failure])
+dnl         
+dnl Tests linking against expat with libraries 'libs' and includes
+dnl 'hdrs', passing message + cache-var-name to AC_CACHE_CHECK.
+dnl On success, sets $expat_libs to libs, sets $apu_has_expat to 1, 
+dnl and runs actions-on-success; on failure runs actions-on-failure.
+dnl
+AC_DEFUN([APU_TRY_EXPAT_LINK], [
+AC_CACHE_CHECK([$1], [$2], [
+  apu_expat_LIBS=$LIBS
+  apu_expat_CPPFLAGS=$CPPFLAGS
+  LIBS="$LIBS $4"
+  CPPFLAGS="$CPPFLAGS $INCLUDES"
+  AC_TRY_LINK([#include <stdlib.h>
+#include <$3>], [XML_ParserCreate(NULL);],
+    [$2=yes], [$2=no])
+  LIBS=$apu_expat_LIBS
+  CPPFLAGS=$apu_expat_CPPFLAGS
+])
+
+if test $[$2] = yes; then
+   AC_DEFINE([HAVE_]translit([$3], [a-z./], [A-Z__]), 1,
+             [Define if $3 is available])
+   apu_expat_libs="$4"
+   apu_has_expat=1
+   $5
+   AC_SUBST(apu_has_expat)
+else
+   apu_has_expat=0
+   $6
+fi
+])
+
+dnl
+dnl APU_SYSTEM_EXPAT: tests for a system expat installation
+dnl If present, sets $apu_has_expat to 1 and adjusts LDFLAGS/CPPFLAGS
+dnl appropriately.  This is mostly for compatibility with existing
+dnl expat releases; all but the first APU_TRY_EXPAT_LINK call could
+dnl be dropped later.
+dnl
+AC_DEFUN([APU_SYSTEM_EXPAT], [
+ 
+  APU_TRY_EXPAT_LINK([Expat 1.95.x], apu_cv_expat_system, 
+    [expat.h], [-lexpat])
+
+  if test $apu_has_expat = 0; then
+    APU_TRY_EXPAT_LINK([old Debian-packaged expat], apu_cv_expat_debian,
+       [xmltok/xmlparse.h], [-lxmlparse -lxmltok])
+  fi
+
+  if test $apu_has_expat = 0; then
+    APU_TRY_EXPAT_LINK([old FreeBSD-packaged expat], apu_cv_expat_freebsd,
+       [xml/xmlparse.h], [-lexpat])
+  fi
+
+  if test $apu_has_expat = 0; then
+    APU_TRY_EXPAT_LINK([Expat 1.0/1.1], apu_cv_expat_1011,
+       [xmlparse/xmlparse.h], [-lexpat])
+  fi
+
+  if test $apu_has_expat = 0; then
+    APR_ADDTO(LDFLAGS, [-L/usr/local/lib])
+    APR_ADDTO(INCLUDES, [-I/usr/local/include])
+ 
+    APU_TRY_EXPAT_LINK([Expat 1.95.x in /usr/local], 
+       apu_cv_expat_usrlocal, [expat.h], [-lexpat], [], [
+       APR_REMOVEFROM(LDFLAGS, [-L/usr/local/lib])
+       APR_REMOVEFROM(INCLUDES, [-I/usr/local/include])
+      ])
+  fi
+])
+
+
+dnl
+dnl APU_FIND_EXPAT: figure out where EXPAT is located (or use bundled)
+dnl
+AC_DEFUN([APU_FIND_EXPAT], [
+
+save_cppflags="$CPPFLAGS"
+
+apu_has_expat=0
+
+AC_ARG_WITH([expat],
+[  --with-expat=DIR        specify Expat location], [
+  if test "$withval" = "yes"; then
+    AC_MSG_ERROR([a directory must be specified for --with-expat])
+  elif test "$withval" = "no"; then
+    if test "$apu_has_libxml2" != "1"; then
+      AC_MSG_ERROR([An XML parser is required!  If you disable expat, you must select --with-libxml2])
+    fi
+  else
+    # Add given path to standard search paths if appropriate:
+    if test "$apu_has_libxml2" = "1"; then
+      AC_MSG_ERROR(Cannot build with both expat and libxml2 - please select one)
+    fi
+    if test "$withval" != "/usr"; then
+      APR_ADDTO(INCLUDES, [-I$withval/include])
+      APR_ADDTO(LDFLAGS, [-L$withval/lib])
+    fi
+  fi
+])
+
+if test "$apu_has_libxml2" != "1"; then
+  APU_SYSTEM_EXPAT
+
+  APR_ADDTO(APRUTIL_EXPORT_LIBS, [$apu_expat_libs])
+  APR_ADDTO(LIBS, [$apu_expat_libs])
+
+  APR_XML_DIR=$bundled_subdir
+  AC_SUBST(APR_XML_DIR)
+fi
+
+CPPFLAGS=$save_cppflags
+])
+
+
+dnl
+dnl APU_FIND_LIBXML2: figure out where LIBXML2 is located (or use bundled)
+dnl
+AC_DEFUN([APU_FIND_LIBXML2], [
+
+save_cppflags="$CPPFLAGS"
+
+apu_has_libxml2=0
+apu_try_libxml2=0
+
+AC_ARG_WITH([libxml2],
+[  --with-libxml2=DIR      specify libxml2 location], [
+  if test "$withval" = "yes"; then
+    apu_try_libxml2=1
+    APR_ADDTO(INCLUDES, [-I/usr/include/libxml2])
+  elif test "$withval" != "no"; then
+    apu_try_libxml2=1
+    APR_ADDTO(INCLUDES, [-I$withval/include/libxml2])
+    if test "$withval" != "/usr"; then
+      APR_ADDTO(LDFLAGS, [-L$withval/lib])
+    fi
+  fi
+  if test ${apu_try_libxml2} = "1" ; then
+
+    #test for libxml2
+    AC_CACHE_CHECK([libxml2], [apu_cv_libxml2], [
+      apu_libxml2_CPPFLAGS=$CPPFLAGS
+      apu_libxml2_LIBS="$LIBS -lxml2"
+      CPPFLAGS="$CPPFLAGS $INCLUDES"
+      LIBS="$LIBS -lxml2"
+      AC_TRY_LINK(
+        [#include <libxml/parser.h>],
+        [xmlSAXHandler sax; xmlCreatePushParserCtxt(&sax, NULL, NULL, 0, NULL);],
+        [apu_cv_libxml2=yes],
+        [apu_cv_libxml2=no],
+      )
+      CPPFLAGS=$apu_libxml2_CPPFLAGS
+      LIBS=$apu_libxml2_LIBS
+    ])
+    if test $apu_cv_libxml2 = yes ; then
+      AC_DEFINE([HAVE_LIBXML2_H], 1, [libxml2 found])
+      apu_has_libxml2=1
+    else
+      apu_has_libxml2=0
+    fi
+  fi
+])
+AC_SUBST(apu_has_libxml2)
+
+if test ${apu_has_libxml2} = "1" ; then
+  APR_ADDTO(APRUTIL_EXPORT_LIBS, [-lxml2])
+  APR_ADDTO(LIBS, [-lxml2])
+fi
+
+CPPFLAGS=$save_cppflags
+])
+
+dnl
+dnl APU_FIND_XML: Find an XML library
+dnl
+dnl Logic: we need exactly one but not both XML libraries
+dnl        Make expat the default for back-compatibility.
+dnl        Use libxml2 if a --with-libxml2 is specified (and works),
+dnl        otherwise expat.
+dnl
+AC_DEFUN([APU_FIND_XML], [
+APU_FIND_LIBXML2
+APU_FIND_EXPAT
+
+if test ${apu_has_expat} = "1" && test ${apu_has_libxml2} = "1" ; then
+  AC_MSG_ERROR(Cannot build with both expat and libxml2 - please select one)
+elif test ${apu_has_expat} != "1" && test ${apu_has_libxml2} != "1" ; then
+  AC_MSG_ERROR(No XML parser found!  Please specify --with-expat or --with-libxml2)
+fi
+])
diff --git a/buildconf b/buildconf
new file mode 100755
index 00000000000..113c3c7f620
--- /dev/null
+++ b/buildconf
@@ -0,0 +1,143 @@
+#!/bin/sh
+# 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.
+#
+#
+
+# buildconf: Build the support scripts needed to compile from a
+#            checked-out version of the source code.
+
+if [ "$1" = "--verbose" -o "$1" = "-v" ]; then
+    verbose="--verbose"
+    shift
+fi
+
+# Verify that the builder has the right config tools installed
+#
+build/buildcheck.sh $verbose || exit 1
+
+libtoolize=`build/PrintPath glibtoolize1 glibtoolize libtoolize15 libtoolize14 libtoolize`
+if [ "x$libtoolize" = "x" ]; then
+    echo "libtoolize not found in path"
+    exit 1
+fi
+
+# Create the libtool helper files
+#
+# Note: we copy (rather than link) them to simplify distribution.
+# Note: APR supplies its own config.guess and config.sub -- we do not
+#       rely on libtool's versions
+#
+echo "buildconf: copying libtool helper files using $libtoolize"
+
+# Remove any libtool files so one can switch between libtool versions
+# by simply rerunning the buildconf script.
+rm -f aclocal.m4 libtool.m4
+(cd build ; rm -f ltconfig ltmain.sh argz.m4 libtool.m4 ltoptions.m4 ltsugar.m4 ltversion.m4 lt~obsolete.m4)
+
+# Determine libtool version, because --copy behaves differently
+# w.r.t. copying libtool.m4
+lt_pversion=`$libtoolize --version 2>/dev/null|sed -e 's/([^)]*)//g;s/^[^0-9]*//;s/[- ].*//g;q'`
+lt_version=`echo $lt_pversion|sed -e 's/\([a-z]*\)$/.\1/'`
+IFS=.; set $lt_version; IFS=' '
+
+# libtool 1
+if test "$1" = "1"; then
+  $libtoolize --copy --automake
+  # Unlikely, maybe for old versions the file exists
+  if [ -f libtool.m4 ]; then 
+    ltfile=`pwd`/libtool.m4
+  else
+
+    # Extract all lines setting variables from libtoolize up until
+    # libtool_m4 gets set
+    ltfindcmd="`sed -n \"/=[^\\\`]/p;/libtool_m4=/{s/.*=/echo /p;q;}\" \
+                   < $libtoolize`"
+
+    # Get path to libtool.m4 either from LIBTOOL_M4 env var or our libtoolize based script
+    ltfile=${LIBTOOL_M4-`eval "$ltfindcmd"`}
+
+    # Expecting the code above to be very portable, but just in case...
+    if [ -z "$ltfile" -o ! -f "$ltfile" ]; then
+      ltpath=`dirname $libtoolize`
+      ltfile=`cd $ltpath/../share/aclocal ; pwd`/libtool.m4
+    fi
+  fi
+  if [ ! -f $ltfile ]; then
+    echo "$ltfile not found"
+    exit 1
+  fi
+  # Do we need this anymore?
+  echo "buildconf: Using libtool.m4 at ${ltfile}."
+  rm -f build/libtool.m4
+  cp -p $ltfile build/libtool.m4
+
+# libtool 2
+elif test "$1" = "2"; then
+  $libtoolize --copy --quiet $verbose
+fi
+
+# Replace top_builddir by apr_builddir.
+# Wouldn't it just be better to define top_builddir??
+# Not sure, would it interfere with httpd top_builddir when bundled?
+mv build/libtool.m4 build/libtool.m4.$$
+sed -e 's/\(LIBTOOL=.*\)top_build/\1apr_build/' < build/libtool.m4.$$ > build/libtool.m4
+rm -f build/libtool.m4.$$
+
+# Clean up any leftovers
+rm -f aclocal.m4 libtool.m4
+
+#
+# Generate the autoconf header and ./configure
+#
+echo "buildconf: creating include/arch/unix/apr_private.h.in ..."
+${AUTOHEADER:-autoheader} $verbose
+
+echo "buildconf: creating configure ..."
+### do some work to toss config.cache?
+${AUTOCONF:-autoconf} $verbose
+
+# Remove autoconf 2.5x's cache directory
+rm -rf autom4te*.cache
+
+echo "buildconf: generating 'make' outputs ..."
+build/gen-build.py $verbose make
+
+# Create RPM Spec file
+if [ -f `which cut` ]; then
+  echo "buildconf: rebuilding rpm spec file"
+  ( REVISION=`build/get-version.sh all include/apr_version.h APR`
+    VERSION=`echo $REVISION | cut -d- -s -f1`
+    RELEASE=`echo $REVISION | cut -d- -s -f2`
+    if [ "x$VERSION" = "x" ]; then
+      VERSION=$REVISION
+      RELEASE=1
+    fi
+    cat ./build/rpm/apr.spec.in | \
+    sed -e "s/APR_VERSION/$VERSION/" \
+        -e "s/APR_RELEASE/$RELEASE/" \
+    > apr.spec )
+fi
+
+# Verify the tree was clean, notify user if not (normal in development)
+#
+if [ -f "include/apr.h" -o -f "include/arch/unix/apr_private.h" -o \
+     -f "include/apu_want.h" -o -f "include/private/apu_select_dbm.h" ]; then
+    echo ""
+    echo "Generated include files already exist, the tree is not clean."
+    echo "The resulting build-outputs.mk file is incorrect"
+fi
+
+exit 0
diff --git a/config.guess b/config.guess
deleted file mode 100755
index 19b0a0a7182..00000000000
--- a/config.guess
+++ /dev/null
@@ -1,1091 +0,0 @@
-#! /bin/sh
-# Attempt to guess a canonical system name.
-#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999
-#   Free Software Foundation, Inc.
-#
-# This file is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-# Written by Per Bothner <bothner@cygnus.com>.
-# The master version of this file is at the FSF in /home/gd/gnu/lib.
-# Please send patches to the Autoconf mailing list <autoconf@gnu.org>.
-#
-# This script attempts to guess a canonical system name similar to
-# config.sub.  If it succeeds, it prints the system name on stdout, and
-# exits with 0.  Otherwise, it exits with 1.
-#
-# The plan is that this can be called by configure scripts if you
-# don't specify an explicit system type (host/target name).
-#
-# Only a few systems have been added to this list; please add others
-# (but try to keep the structure clean).
-#
-
-# Use $HOST_CC if defined. $CC may point to a cross-compiler
-if test x"$CC_FOR_BUILD" = x; then
-  if test x"$HOST_CC" != x; then
-    CC_FOR_BUILD="$HOST_CC"
-  else
-    if test x"$CC" != x; then
-      CC_FOR_BUILD="$CC"
-    else
-      CC_FOR_BUILD=cc
-    fi
-  fi
-fi
-
-
-# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
-# (ghazi@noc.rutgers.edu 8/24/94.)
-if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
-	PATH=$PATH:/.attbin ; export PATH
-fi
-
-UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
-UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
-UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
-UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
-
-dummy=dummy-$$
-trap 'rm -f $dummy.c $dummy.o $dummy; exit 1' 1 2 15
-
-# Note: order is significant - the case branches are not exclusive.
-
-case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
-    alpha:OSF1:*:*)
-	if test $UNAME_RELEASE = "V4.0"; then
-		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
-	fi
-	# A Vn.n version is a released version.
-	# A Tn.n version is a released field test version.
-	# A Xn.n version is an unreleased experimental baselevel.
-	# 1.2 uses "1.2" for uname -r.
-	cat <<EOF >$dummy.s
-	.globl main
-	.ent main
-main:
-	.frame \$30,0,\$26,0
-	.prologue 0
-	.long 0x47e03d80 # implver $0
-	lda \$2,259
-	.long 0x47e20c21 # amask $2,$1
-	srl \$1,8,\$2
-	sll \$2,2,\$2
-	sll \$0,3,\$0
-	addl \$1,\$0,\$0
-	addl \$2,\$0,\$0
-	ret \$31,(\$26),1
-	.end main
-EOF
-	$CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null
-	if test "$?" = 0 ; then
-		./$dummy
-		case "$?" in
-			7)
-				UNAME_MACHINE="alpha"
-				;;
-			15)
-				UNAME_MACHINE="alphaev5"
-				;;
-			14)
-				UNAME_MACHINE="alphaev56"
-				;;
-			10)
-				UNAME_MACHINE="alphapca56"
-				;;
-			16)
-				UNAME_MACHINE="alphaev6"
-				;;
-		esac
-	fi
-	rm -f $dummy.s $dummy
-	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
-	exit 0 ;;
-    Alpha\ *:Windows_NT*:*)
-	# How do we know it's Interix rather than the generic POSIX subsystem?
-	# Should we change UNAME_MACHINE based on the output of uname instead
-	# of the specific Alpha model?
-	echo alpha-pc-interix
-	exit 0 ;;
-    21064:Windows_NT:50:3)
-	echo alpha-dec-winnt3.5
-	exit 0 ;;
-    Amiga*:UNIX_System_V:4.0:*)
-	echo m68k-cbm-sysv4
-	exit 0;;
-    amiga:NetBSD:*:*)
-      echo m68k-cbm-netbsd${UNAME_RELEASE}
-      exit 0 ;;
-    amiga:OpenBSD:*:*)
-	echo m68k-unknown-openbsd${UNAME_RELEASE}
-	exit 0 ;;
-    *:[Aa]miga[Oo][Ss]:*:*)
-	echo ${UNAME_MACHINE}-unknown-amigaos
-	exit 0 ;;
-    arc64:OpenBSD:*:*)
-	echo mips64el-unknown-openbsd${UNAME_RELEASE}
-	exit 0 ;;
-    arc:OpenBSD:*:*)
-	echo mipsel-unknown-openbsd${UNAME_RELEASE}
-	exit 0 ;;
-    hkmips:OpenBSD:*:*)
-	echo mips-unknown-openbsd${UNAME_RELEASE}
-	exit 0 ;;
-    pmax:OpenBSD:*:*)
-	echo mipsel-unknown-openbsd${UNAME_RELEASE}
-	exit 0 ;;
-    sgi:OpenBSD:*:*)
-	echo mips-unknown-openbsd${UNAME_RELEASE}
-	exit 0 ;;
-    wgrisc:OpenBSD:*:*)
-	echo mipsel-unknown-openbsd${UNAME_RELEASE}
-	exit 0 ;;
-    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
-	echo arm-acorn-riscix${UNAME_RELEASE}
-	exit 0;;
-    arm32:NetBSD:*:*)
-	echo arm-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
-	exit 0 ;;
-    SR2?01:HI-UX/MPP:*:*)
-	echo hppa1.1-hitachi-hiuxmpp
-	exit 0;;
-    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
-	# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
-	if test "`(/bin/universe) 2>/dev/null`" = att ; then
-		echo pyramid-pyramid-sysv3
-	else
-		echo pyramid-pyramid-bsd
-	fi
-	exit 0 ;;
-    NILE*:*:*:dcosx)
-	echo pyramid-pyramid-svr4
-	exit 0 ;;
-    sun4H:SunOS:5.*:*)
-	echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
-	exit 0 ;;
-    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
-	echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
-	exit 0 ;;
-    i86pc:SunOS:5.*:*)
-	echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
-	exit 0 ;;
-    sun4*:SunOS:6*:*)
-	# According to config.sub, this is the proper way to canonicalize
-	# SunOS6.  Hard to guess exactly what SunOS6 will be like, but
-	# it's likely to be more like Solaris than SunOS4.
-	echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
-	exit 0 ;;
-    sun4*:SunOS:*:*)
-	case "`/usr/bin/arch -k`" in
-	    Series*|S4*)
-		UNAME_RELEASE=`uname -v`
-		;;
-	esac
-	# Japanese Language versions have a version number like `4.1.3-JL'.
-	echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
-	exit 0 ;;
-    sun3*:SunOS:*:*)
-	echo m68k-sun-sunos${UNAME_RELEASE}
-	exit 0 ;;
-    sun*:*:4.2BSD:*)
-	UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
-	test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
-	case "`/bin/arch`" in
-	    sun3)
-		echo m68k-sun-sunos${UNAME_RELEASE}
-		;;
-	    sun4)
-		echo sparc-sun-sunos${UNAME_RELEASE}
-		;;
-	esac
-	exit 0 ;;
-    aushp:SunOS:*:*)
-	echo sparc-auspex-sunos${UNAME_RELEASE}
-	exit 0 ;;
-    atari*:NetBSD:*:*)
-	echo m68k-atari-netbsd${UNAME_RELEASE}
-	exit 0 ;;
-    atari*:OpenBSD:*:*)
-	echo m68k-unknown-openbsd${UNAME_RELEASE}
-	exit 0 ;;
-    # The situation for MiNT is a little confusing.  The machine name
-    # can be virtually everything (everything which is not
-    # "atarist" or "atariste" at least should have a processor 
-    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
-    # to the lowercase version "mint" (or "freemint").  Finally
-    # the system name "TOS" denotes a system which is actually not
-    # MiNT.  But MiNT is downward compatible to TOS, so this should
-    # be no problem.
-    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
-        echo m68k-atari-mint${UNAME_RELEASE}
-	exit 0 ;;
-    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
-	echo m68k-atari-mint${UNAME_RELEASE}
-        exit 0 ;;
-    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
-        echo m68k-atari-mint${UNAME_RELEASE}
-	exit 0 ;;
-    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
-        echo m68k-milan-mint${UNAME_RELEASE}
-        exit 0 ;;
-    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
-        echo m68k-hades-mint${UNAME_RELEASE}
-        exit 0 ;;
-    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
-        echo m68k-unknown-mint${UNAME_RELEASE}
-        exit 0 ;;
-    sun3*:NetBSD:*:*)
-	echo m68k-sun-netbsd${UNAME_RELEASE}
-	exit 0 ;;
-    sun3*:OpenBSD:*:*)
-	echo m68k-unknown-openbsd${UNAME_RELEASE}
-	exit 0 ;;
-    mac68k:NetBSD:*:*)
-	echo m68k-apple-netbsd${UNAME_RELEASE}
-	exit 0 ;;
-    mac68k:OpenBSD:*:*)
-	echo m68k-unknown-openbsd${UNAME_RELEASE}
-	exit 0 ;;
-    mvme68k:OpenBSD:*:*)
-	echo m68k-unknown-openbsd${UNAME_RELEASE}
-	exit 0 ;;
-    mvme88k:OpenBSD:*:*)
-	echo m88k-unknown-openbsd${UNAME_RELEASE}
-	exit 0 ;;
-    powerpc:machten:*:*)
-	echo powerpc-apple-machten${UNAME_RELEASE}
-	exit 0 ;;
-    macppc:NetBSD:*:*)
-        echo powerpc-apple-netbsd${UNAME_RELEASE}
-        exit 0 ;;
-    RISC*:Mach:*:*)
-	echo mips-dec-mach_bsd4.3
-	exit 0 ;;
-    RISC*:ULTRIX:*:*)
-	echo mips-dec-ultrix${UNAME_RELEASE}
-	exit 0 ;;
-    VAX*:ULTRIX*:*:*)
-	echo vax-dec-ultrix${UNAME_RELEASE}
-	exit 0 ;;
-    2020:CLIX:*:* | 2430:CLIX:*:*)
-	echo clipper-intergraph-clix${UNAME_RELEASE}
-	exit 0 ;;
-    mips:*:*:UMIPS | mips:*:*:RISCos)
-	sed 's/^	//' << EOF >$dummy.c
-#ifdef __cplusplus
-	int main (int argc, char *argv[]) {
-#else
-	int main (argc, argv) int argc; char *argv[]; {
-#endif
-	#if defined (host_mips) && defined (MIPSEB)
-	#if defined (SYSTYPE_SYSV)
-	  printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
-	#endif
-	#if defined (SYSTYPE_SVR4)
-	  printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
-	#endif
-	#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
-	  printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
-	#endif
-	#endif
-	  exit (-1);
-	}
-EOF
-	$CC_FOR_BUILD $dummy.c -o $dummy \
-	  && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
-	  && rm $dummy.c $dummy && exit 0
-	rm -f $dummy.c $dummy
-	echo mips-mips-riscos${UNAME_RELEASE}
-	exit 0 ;;
-    Night_Hawk:Power_UNIX:*:*)
-	echo powerpc-harris-powerunix
-	exit 0 ;;
-    m88k:CX/UX:7*:*)
-	echo m88k-harris-cxux7
-	exit 0 ;;
-    m88k:*:4*:R4*)
-	echo m88k-motorola-sysv4
-	exit 0 ;;
-    m88k:*:3*:R3*)
-	echo m88k-motorola-sysv3
-	exit 0 ;;
-    AViiON:dgux:*:*)
-        # DG/UX returns AViiON for all architectures
-        UNAME_PROCESSOR=`/usr/bin/uname -p`
-        if [ $UNAME_PROCESSOR = mc88100 -o $UNAME_PROCESSOR = mc88110 ] ; then
-	if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \
-	     -o ${TARGET_BINARY_INTERFACE}x = x ] ; then
-		echo m88k-dg-dgux${UNAME_RELEASE}
-	else
-		echo m88k-dg-dguxbcs${UNAME_RELEASE}
-	fi
-        else echo i586-dg-dgux${UNAME_RELEASE}
-        fi
- 	exit 0 ;;
-    M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
-	echo m88k-dolphin-sysv3
-	exit 0 ;;
-    M88*:*:R3*:*)
-	# Delta 88k system running SVR3
-	echo m88k-motorola-sysv3
-	exit 0 ;;
-    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
-	echo m88k-tektronix-sysv3
-	exit 0 ;;
-    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
-	echo m68k-tektronix-bsd
-	exit 0 ;;
-    *:IRIX*:*:*)
-	echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
-	exit 0 ;;
-    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
-	echo romp-ibm-aix      # uname -m gives an 8 hex-code CPU id
-	exit 0 ;;              # Note that: echo "'`uname -s`'" gives 'AIX '
-    i?86:AIX:*:*)
-	echo i386-ibm-aix
-	exit 0 ;;
-    *:AIX:2:3)
-	if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
-		sed 's/^		//' << EOF >$dummy.c
-		#include <sys/systemcfg.h>
-
-		main()
-			{
-			if (!__power_pc())
-				exit(1);
-			puts("powerpc-ibm-aix3.2.5");
-			exit(0);
-			}
-EOF
-		$CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm $dummy.c $dummy && exit 0
-		rm -f $dummy.c $dummy
-		echo rs6000-ibm-aix3.2.5
-	elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
-		echo rs6000-ibm-aix3.2.4
-	else
-		echo rs6000-ibm-aix3.2
-	fi
-	exit 0 ;;
-    *:AIX:*:4)
-	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'`
-	if /usr/sbin/lsattr -EHl ${IBM_CPU_ID} | grep POWER >/dev/null 2>&1; then
-		IBM_ARCH=rs6000
-	else
-		IBM_ARCH=powerpc
-	fi
-	if [ -x /usr/bin/oslevel ] ; then
-		IBM_REV=`/usr/bin/oslevel`
-	else
-		IBM_REV=4.${UNAME_RELEASE}
-	fi
-	echo ${IBM_ARCH}-ibm-aix${IBM_REV}
-	exit 0 ;;
-    *:AIX:*:*)
-	echo rs6000-ibm-aix
-	exit 0 ;;
-    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
-	echo romp-ibm-bsd4.4
-	exit 0 ;;
-    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC NetBSD and
-	echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
-	exit 0 ;;                           # report: romp-ibm BSD 4.3
-    *:BOSX:*:*)
-	echo rs6000-bull-bosx
-	exit 0 ;;
-    DPX/2?00:B.O.S.:*:*)
-	echo m68k-bull-sysv3
-	exit 0 ;;
-    9000/[34]??:4.3bsd:1.*:*)
-	echo m68k-hp-bsd
-	exit 0 ;;
-    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
-	echo m68k-hp-bsd4.4
-	exit 0 ;;
-    9000/[34678]??:HP-UX:*:*)
-	case "${UNAME_MACHINE}" in
-	    9000/31? )            HP_ARCH=m68000 ;;
-	    9000/[34]?? )         HP_ARCH=m68k ;;
-	    9000/[678][0-9][0-9])
-              sed 's/^              //' << EOF >$dummy.c
-              #include <stdlib.h>
-              #include <unistd.h>
-
-              int main ()
-              {
-              #if defined(_SC_KERNEL_BITS)
-                  long bits = sysconf(_SC_KERNEL_BITS);
-              #endif
-                  long cpu  = sysconf (_SC_CPU_VERSION);
-
-                  switch (cpu)
-              	{
-              	case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
-              	case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
-              	case CPU_PA_RISC2_0:
-              #if defined(_SC_KERNEL_BITS)
-              	    switch (bits)
-              		{
-              		case 64: puts ("hppa2.0w"); break;
-              		case 32: puts ("hppa2.0n"); break;
-              		default: puts ("hppa2.0"); break;
-              		} break;
-              #else  /* !defined(_SC_KERNEL_BITS) */
-              	    puts ("hppa2.0"); break;
-              #endif
-              	default: puts ("hppa1.0"); break;
-              	}
-                  exit (0);
-              }
-EOF
-	($CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null ) && HP_ARCH=`./$dummy`
-	rm -f $dummy.c $dummy
-	esac
-	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
-	echo ${HP_ARCH}-hp-hpux${HPUX_REV}
-	exit 0 ;;
-    3050*:HI-UX:*:*)
-	sed 's/^	//' << EOF >$dummy.c
-	#include <unistd.h>
-	int
-	main ()
-	{
-	  long cpu = sysconf (_SC_CPU_VERSION);
-	  /* The order matters, because CPU_IS_HP_MC68K erroneously returns
-	     true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
-	     results, however.  */
-	  if (CPU_IS_PA_RISC (cpu))
-	    {
-	      switch (cpu)
-		{
-		  case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
-		  case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
-		  case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
-		  default: puts ("hppa-hitachi-hiuxwe2"); break;
-		}
-	    }
-	  else if (CPU_IS_HP_MC68K (cpu))
-	    puts ("m68k-hitachi-hiuxwe2");
-	  else puts ("unknown-hitachi-hiuxwe2");
-	  exit (0);
-	}
-EOF
-	$CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm $dummy.c $dummy && exit 0
-	rm -f $dummy.c $dummy
-	echo unknown-hitachi-hiuxwe2
-	exit 0 ;;
-    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
-	echo hppa1.1-hp-bsd
-	exit 0 ;;
-    9000/8??:4.3bsd:*:*)
-	echo hppa1.0-hp-bsd
-	exit 0 ;;
-    *9??*:MPE/iX:*:*)
-	echo hppa1.0-hp-mpeix
-	exit 0 ;;
-    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
-	echo hppa1.1-hp-osf
-	exit 0 ;;
-    hp8??:OSF1:*:*)
-	echo hppa1.0-hp-osf
-	exit 0 ;;
-    i?86:OSF1:*:*)
-	if [ -x /usr/sbin/sysversion ] ; then
-	    echo ${UNAME_MACHINE}-unknown-osf1mk
-	else
-	    echo ${UNAME_MACHINE}-unknown-osf1
-	fi
-	exit 0 ;;
-    parisc*:Lites*:*:*)
-	echo hppa1.1-hp-lites
-	exit 0 ;;
-    hppa*:OpenBSD:*:*)
-	echo hppa-unknown-openbsd
-	exit 0 ;;
-    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
-	echo c1-convex-bsd
-        exit 0 ;;
-    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
-	if getsysinfo -f scalar_acc
-	then echo c32-convex-bsd
-	else echo c2-convex-bsd
-	fi
-        exit 0 ;;
-    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
-	echo c34-convex-bsd
-        exit 0 ;;
-    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
-	echo c38-convex-bsd
-        exit 0 ;;
-    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
-	echo c4-convex-bsd
-        exit 0 ;;
-    CRAY*X-MP:*:*:*)
-	echo xmp-cray-unicos
-        exit 0 ;;
-    CRAY*Y-MP:*:*:*)
-	echo ymp-cray-unicos${UNAME_RELEASE}
-	exit 0 ;;
-    CRAY*[A-Z]90:*:*:*)
-	echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
-	| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
-	      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
-	exit 0 ;;
-    CRAY*TS:*:*:*)
-	echo t90-cray-unicos${UNAME_RELEASE}
-	exit 0 ;;
-    CRAY*T3E:*:*:*)
-	echo t3e-cray-unicosmk${UNAME_RELEASE}
-	exit 0 ;;
-    CRAY-2:*:*:*)
-	echo cray2-cray-unicos
-        exit 0 ;;
-    F300:UNIX_System_V:*:*)
-        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
-        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
-        echo "f300-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
-        exit 0 ;;
-    F301:UNIX_System_V:*:*)
-       echo f301-fujitsu-uxpv`echo $UNAME_RELEASE | sed 's/ .*//'`
-       exit 0 ;;
-    hp3[0-9][05]:NetBSD:*:*)
-	echo m68k-hp-netbsd${UNAME_RELEASE}
-	exit 0 ;;
-    hp300:OpenBSD:*:*)
-	echo m68k-unknown-openbsd${UNAME_RELEASE}
-	exit 0 ;;
-    i?86:BSD/386:*:* | i?86:BSD/OS:*:*)
-	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
-	exit 0 ;;
-    sparc*:BSD/OS:*:*)
-	echo sparc-unknown-bsdi${UNAME_RELEASE}
-	exit 0 ;;
-    *:BSD/OS:*:*)
-	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
-	exit 0 ;;
-    *:FreeBSD:*:*)
-	if test -x /usr/bin/objformat; then
-	    if test "elf" = "`/usr/bin/objformat`"; then
-		echo ${UNAME_MACHINE}-unknown-freebsdelf`echo ${UNAME_RELEASE}|sed -e 's/[-_].*//'`
-		exit 0
-	    fi
-	fi
-	echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
-	exit 0 ;;
-    *:NetBSD:*:*)
-	echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
-	exit 0 ;;
-    *:OpenBSD:*:*)
-	echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
-	exit 0 ;;
-    i*:CYGWIN*:*)
-	echo ${UNAME_MACHINE}-pc-cygwin
-	exit 0 ;;
-    i*:MINGW*:*)
-	echo ${UNAME_MACHINE}-pc-mingw32
-	exit 0 ;;
-    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
-	# How do we know it's Interix rather than the generic POSIX subsystem?
-	# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
-	# UNAME_MACHINE based on the output of uname instead of i386?
-	echo i386-pc-interix
-	exit 0 ;;
-    i*:UWIN*:*)
-	echo ${UNAME_MACHINE}-pc-uwin
-	exit 0 ;;
-    p*:CYGWIN*:*)
-	echo powerpcle-unknown-cygwin
-	exit 0 ;;
-    prep*:SunOS:5.*:*)
-	echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
-	exit 0 ;;
-    *:GNU:*:*)
-	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
-	exit 0 ;;
-    *:Linux:*:*)
-#	# uname on the ARM produces all sorts of strangeness, and we need to
-#	# filter it out.
-#	case "$UNAME_MACHINE" in
-#	  armv*)		      UNAME_MACHINE=$UNAME_MACHINE ;;
-#	  arm* | sa110*)	      UNAME_MACHINE="arm" ;;
-#	esac
-
-	# The BFD linker knows what the default object file format is, so
-	# first see if it will tell us. cd to the root directory to prevent
-	# problems with other programs or directories called `ld' in the path.
-	ld_help_string=`cd /; ld --help 2>&1`
-	ld_supported_emulations=`echo $ld_help_string \
-			 | sed -ne '/supported emulations:/!d
-				    s/[ 	][ 	]*/ /g
-				    s/.*supported emulations: *//
-				    s/ .*//
-				    p'`
-        case "$ld_supported_emulations" in
-	  i?86linux)  echo "${UNAME_MACHINE}-pc-linux-gnuaout"      ; exit 0 ;;
-	  i?86coff)   echo "${UNAME_MACHINE}-pc-linux-gnucoff"      ; exit 0 ;;
-	  sparclinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;;
-	  armlinux)   echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;;
-	  m68klinux)  echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;;
-	  elf32arm)   echo "${UNAME_MACHINE}-unknown-linux-gnu"     ; exit 0 ;;
-	  elf32ppc)
-		# Determine Lib Version
-		cat >$dummy.c <<EOF
-#include <features.h>
-#if defined(__GLIBC__)
-extern char __libc_version[];
-extern char __libc_release[];
-#endif
-main(argc, argv)
-     int argc;
-     char *argv[];
-{
-#if defined(__GLIBC__)
-  printf("%s %s\n", __libc_version, __libc_release);
-#else
-  printf("unkown\n");
-#endif
-  return 0;
-}
-EOF
-		LIBC=""
-		$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null
-		if test "$?" = 0 ; then
-			./$dummy | grep 1\.99 > /dev/null
-			if test "$?" = 0 ; then
-				LIBC="libc1"
-			fi
-		fi	
-		rm -f $dummy.c $dummy
-		echo powerpc-unknown-linux-gnu${LIBC} ; exit 0 ;;
-	esac
-
-	if test "${UNAME_MACHINE}" = "alpha" ; then
-		sed 's/^	//'  <<EOF >$dummy.s
-		.globl main
-		.ent main
-	main:
-		.frame \$30,0,\$26,0
-		.prologue 0
-		.long 0x47e03d80 # implver $0
-		lda \$2,259
-		.long 0x47e20c21 # amask $2,$1
-		srl \$1,8,\$2
-		sll \$2,2,\$2
-		sll \$0,3,\$0
-		addl \$1,\$0,\$0
-		addl \$2,\$0,\$0
-		ret \$31,(\$26),1
-		.end main
-EOF
-		LIBC=""
-		$CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null
-		if test "$?" = 0 ; then
-			./$dummy
-			case "$?" in
-			7)
-				UNAME_MACHINE="alpha"
-				;;
-			15)
-				UNAME_MACHINE="alphaev5"
-				;;
-			14)
-				UNAME_MACHINE="alphaev56"
-				;;
-			10)
-				UNAME_MACHINE="alphapca56"
-				;;
-			16)
-				UNAME_MACHINE="alphaev6"
-				;;
-			esac
-
-			objdump --private-headers $dummy | \
-			  grep ld.so.1 > /dev/null
-			if test "$?" = 0 ; then
-				LIBC="libc1"
-			fi
-		fi
-		rm -f $dummy.s $dummy
-		echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} ; exit 0
-	elif test "${UNAME_MACHINE}" = "mips" ; then
-	  cat >$dummy.c <<EOF
-#ifdef __cplusplus
-	int main (int argc, char *argv[]) {
-#else
-	int main (argc, argv) int argc; char *argv[]; {
-#endif
-#ifdef __MIPSEB__
-  printf ("%s-unknown-linux-gnu\n", argv[1]);
-#endif
-#ifdef __MIPSEL__
-  printf ("%sel-unknown-linux-gnu\n", argv[1]);
-#endif
-  return 0;
-}
-EOF
-	  $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm $dummy.c $dummy && exit 0
-	  rm -f $dummy.c $dummy
-	else
-	  # Either a pre-BFD a.out linker (linux-gnuoldld)
-	  # or one that does not give us useful --help.
-	  # GCC wants to distinguish between linux-gnuoldld and linux-gnuaout.
-	  # If ld does not provide *any* "supported emulations:"
-	  # that means it is gnuoldld.
-	  echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations:"
-	  test $? != 0 && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0
-
-	  case "${UNAME_MACHINE}" in
-	  i?86)
-	    VENDOR=pc;
-	    ;;
-	  *)
-	    VENDOR=unknown;
-	    ;;
-	  esac
-	  # Determine whether the default compiler is a.out or elf
-	  cat >$dummy.c <<EOF
-#include <features.h>
-#ifdef __cplusplus
-	int main (int argc, char *argv[]) {
-#else
-	int main (argc, argv) int argc; char *argv[]; {
-#endif
-#ifdef __ELF__
-# ifdef __GLIBC__
-#  if __GLIBC__ >= 2
-    printf ("%s-${VENDOR}-linux-gnu\n", argv[1]);
-#  else
-    printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]);
-#  endif
-# else
-   printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]);
-# endif
-#else
-  printf ("%s-${VENDOR}-linux-gnuaout\n", argv[1]);
-#endif
-  return 0;
-}
-EOF
-	  $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm $dummy.c $dummy && exit 0
-	  rm -f $dummy.c $dummy
-	fi ;;
-# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.  earlier versions
-# are messed up and put the nodename in both sysname and nodename.
-    i?86:DYNIX/ptx:4*:*)
-	echo i386-sequent-sysv4
-	exit 0 ;;
-    i?86:UNIX_SV:4.2MP:2.*)
-        # Unixware is an offshoot of SVR4, but it has its own version
-        # number series starting with 2...
-        # I am not positive that other SVR4 systems won't match this,
-	# I just have to hope.  -- rms.
-        # Use sysv4.2uw... so that sysv4* matches it.
-	echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
-	exit 0 ;;
-    i?86:*:4.*:* | i?86:SYSTEM_V:4.*:*)
-	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
-		echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE}
-	else
-		echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE}
-	fi
-	exit 0 ;;
-    i?86:*:5:7*)
-	UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
-	(/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
-	(/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) && UNAME_MACHINE=i586
-	(/bin/uname -X|egrep '^Machine.*Pent.*II' >/dev/null) && UNAME_MACHINE=i686
-	(/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) && UNAME_MACHINE=i585
-	echo ${UNAME_MACHINE}-${UNAME_SYSTEM}${UNAME_VERSION}-sysv${UNAME_RELEASE}
-	exit 0 ;;
-    i?86:*:3.2:*)
-	if test -f /usr/options/cb.name; then
-		UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
-		echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
-	elif /bin/uname -X 2>/dev/null >/dev/null ; then
-		UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
-		(/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
-		(/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
-			&& UNAME_MACHINE=i586
-		(/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \
-			&& UNAME_MACHINE=i686
-		(/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \
-			&& UNAME_MACHINE=i686
-		echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
-	else
-		echo ${UNAME_MACHINE}-pc-sysv32
-	fi
-	exit 0 ;;
-    pc:*:*:*)
-        # uname -m prints for DJGPP always 'pc', but it prints nothing about
-        # the processor, so we play safe by assuming i386.
-	echo i386-pc-msdosdjgpp
-        exit 0 ;;
-    Intel:Mach:3*:*)
-	echo i386-pc-mach3
-	exit 0 ;;
-    paragon:*:*:*)
-	echo i860-intel-osf1
-	exit 0 ;;
-    i860:*:4.*:*) # i860-SVR4
-	if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
-	  echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
-	else # Add other i860-SVR4 vendors below as they are discovered.
-	  echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
-	fi
-	exit 0 ;;
-    mini*:CTIX:SYS*5:*)
-	# "miniframe"
-	echo m68010-convergent-sysv
-	exit 0 ;;
-    M68*:*:R3V[567]*:*)
-	test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
-    3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0)
-	OS_REL=''
-	test -r /etc/.relid \
-	&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
-	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
-	  && echo i486-ncr-sysv4.3${OS_REL} && exit 0
-	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
-	  && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
-    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
-        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
-          && echo i486-ncr-sysv4 && exit 0 ;;
-    m68*:LynxOS:2.*:*)
-	echo m68k-unknown-lynxos${UNAME_RELEASE}
-	exit 0 ;;
-    mc68030:UNIX_System_V:4.*:*)
-	echo m68k-atari-sysv4
-	exit 0 ;;
-    i?86:LynxOS:2.*:* | i?86:LynxOS:3.[01]*:*)
-	echo i386-unknown-lynxos${UNAME_RELEASE}
-	exit 0 ;;
-    TSUNAMI:LynxOS:2.*:*)
-	echo sparc-unknown-lynxos${UNAME_RELEASE}
-	exit 0 ;;
-    rs6000:LynxOS:2.*:* | PowerPC:LynxOS:2.*:*)
-	echo rs6000-unknown-lynxos${UNAME_RELEASE}
-	exit 0 ;;
-    SM[BE]S:UNIX_SV:*:*)
-	echo mips-dde-sysv${UNAME_RELEASE}
-	exit 0 ;;
-    RM*:ReliantUNIX-*:*:*)
-	echo mips-sni-sysv4
-	exit 0 ;;
-    RM*:SINIX-*:*:*)
-	echo mips-sni-sysv4
-	exit 0 ;;
-    *:SINIX-*:*:*)
-	if uname -p 2>/dev/null >/dev/null ; then
-		UNAME_MACHINE=`(uname -p) 2>/dev/null`
-		echo ${UNAME_MACHINE}-sni-sysv4
-	else
-		echo ns32k-sni-sysv
-	fi
-	exit 0 ;;
-    PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
-                           # says <Richard.M.Bartel@ccMail.Census.GOV>
-        echo i586-unisys-sysv4
-        exit 0 ;;
-    *:UNIX_System_V:4*:FTX*)
-	# From Gerald Hewes <hewes@openmarket.com>.
-	# How about differentiating between stratus architectures? -djm
-	echo hppa1.1-stratus-sysv4
-	exit 0 ;;
-    *:*:*:FTX*)
-	# From seanf@swdc.stratus.com.
-	echo i860-stratus-sysv4
-	exit 0 ;;
-    mc68*:A/UX:*:*)
-	echo m68k-apple-aux${UNAME_RELEASE}
-	exit 0 ;;
-    news*:NEWS-OS:*:6*)
-	echo mips-sony-newsos6
-	exit 0 ;;
-    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
-	if [ -d /usr/nec ]; then
-	        echo mips-nec-sysv${UNAME_RELEASE}
-	else
-	        echo mips-unknown-sysv${UNAME_RELEASE}
-	fi
-        exit 0 ;;
-    BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
-	echo powerpc-be-beos
-	exit 0 ;;
-    BeMac:BeOS:*:*)	# BeOS running on Mac or Mac clone, PPC only.
-	echo powerpc-apple-beos
-	exit 0 ;;
-    BePC:BeOS:*:*)	# BeOS running on Intel PC compatible.
-	echo i586-pc-beos
-	exit 0 ;;
-    SX-4:SUPER-UX:*:*)
-	echo sx4-nec-superux${UNAME_RELEASE}
-	exit 0 ;;
-    SX-5:SUPER-UX:*:*)
-	echo sx5-nec-superux${UNAME_RELEASE}
-	exit 0 ;;
-    Power*:Rhapsody:*:*)
-	echo powerpc-apple-rhapsody${UNAME_RELEASE}
-	exit 0 ;;
-    *:Rhapsody:*:*)
-	echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
-	exit 0 ;;
-    *:OS/2:*:*)
-	echo "i386-pc-os2_emx"
-	exit 0;;
-esac
-
-#echo '(No uname command or uname output not recognized.)' 1>&2
-#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
-
-cat >$dummy.c <<EOF
-#ifdef _SEQUENT_
-# include <sys/types.h>
-# include <sys/utsname.h>
-#endif
-main ()
-{
-#if defined (sony)
-#if defined (MIPSEB)
-  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
-     I don't know....  */
-  printf ("mips-sony-bsd\n"); exit (0);
-#else
-#include <sys/param.h>
-  printf ("m68k-sony-newsos%s\n",
-#ifdef NEWSOS4
-          "4"
-#else
-	  ""
-#endif
-         ); exit (0);
-#endif
-#endif
-
-#if defined (__arm) && defined (__acorn) && defined (__unix)
-  printf ("arm-acorn-riscix"); exit (0);
-#endif
-
-#if defined (hp300) && !defined (hpux)
-  printf ("m68k-hp-bsd\n"); exit (0);
-#endif
-
-#if defined (NeXT)
-#if !defined (__ARCHITECTURE__)
-#define __ARCHITECTURE__ "m68k"
-#endif
-  int version;
-  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
-  if (version < 4)
-    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
-  else
-    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
-  exit (0);
-#endif
-
-#if defined (MULTIMAX) || defined (n16)
-#if defined (UMAXV)
-  printf ("ns32k-encore-sysv\n"); exit (0);
-#else
-#if defined (CMU)
-  printf ("ns32k-encore-mach\n"); exit (0);
-#else
-  printf ("ns32k-encore-bsd\n"); exit (0);
-#endif
-#endif
-#endif
-
-#if defined (__386BSD__)
-  printf ("i386-pc-bsd\n"); exit (0);
-#endif
-
-#if defined (sequent)
-#if defined (i386)
-  printf ("i386-sequent-dynix\n"); exit (0);
-#endif
-#if defined (ns32000)
-  printf ("ns32k-sequent-dynix\n"); exit (0);
-#endif
-#endif
-
-#if defined (_SEQUENT_)
-    struct utsname un;
-
-    uname(&un);
-
-    if (strncmp(un.version, "V2", 2) == 0) {
-	printf ("i386-sequent-ptx2\n"); exit (0);
-    }
-    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
-	printf ("i386-sequent-ptx1\n"); exit (0);
-    }
-    printf ("i386-sequent-ptx\n"); exit (0);
-
-#endif
-
-#if defined (vax)
-#if !defined (ultrix)
-  printf ("vax-dec-bsd\n"); exit (0);
-#else
-  printf ("vax-dec-ultrix\n"); exit (0);
-#endif
-#endif
-
-#if defined (alliant) && defined (i860)
-  printf ("i860-alliant-bsd\n"); exit (0);
-#endif
-
-  exit (1);
-}
-EOF
-
-$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm $dummy.c $dummy && exit 0
-rm -f $dummy.c $dummy
-
-# Apollos put the system type in the environment.
-
-test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
-
-# Convex versions that predate uname can use getsysinfo(1)
-
-if [ -x /usr/convex/getsysinfo ]
-then
-    case `getsysinfo -f cpu_type` in
-    c1*)
-	echo c1-convex-bsd
-	exit 0 ;;
-    c2*)
-	if getsysinfo -f scalar_acc
-	then echo c32-convex-bsd
-	else echo c2-convex-bsd
-	fi
-	exit 0 ;;
-    c34*)
-	echo c34-convex-bsd
-	exit 0 ;;
-    c38*)
-	echo c38-convex-bsd
-	exit 0 ;;
-    c4*)
-	echo c4-convex-bsd
-	exit 0 ;;
-    esac
-fi
-
-#echo '(Unable to guess system type)' 1>&2
-
-exit 1
diff --git a/config.layout b/config.layout
new file mode 100644
index 00000000000..0f42e84e273
--- /dev/null
+++ b/config.layout
@@ -0,0 +1,231 @@
+##
+##  config.layout -- Pre-defined Installation Path Layouts
+##
+##  Hints:
+##  - layouts can be loaded with configure's --enable-layout=ID option
+##  - when no --enable-layout option is given, the default layout is `apr'
+##  - a trailing plus character (`+') on paths is replaced with a 
+##    `/<target>' suffix where <target> is currently hardcoded to 'apr'.
+##    (This may become a configurable parameter at some point.)
+##
+
+#   Classical APR path layout designed for parallel installs.
+<Layout apr>
+    prefix:        /usr/local/apr
+    exec_prefix:   ${prefix}
+    bindir:        ${exec_prefix}/bin
+    sbindir:       ${exec_prefix}/bin
+    libdir:        ${exec_prefix}/lib
+    libexecdir:    ${exec_prefix}/modules
+    mandir:        ${prefix}/man
+    sysconfdir:    ${prefix}/conf
+    datadir:       ${prefix}
+    installbuilddir: ${datadir}/build-${APR_MAJOR_VERSION}
+    includedir:    ${prefix}/include/apr-${APR_MAJOR_VERSION}
+    localstatedir: ${prefix}
+    libsuffix:     -${APR_MAJOR_VERSION}
+</Layout>
+
+#   Classical single-installation APR path layout.
+<Layout classic>
+    prefix:        /usr/local/apr
+    exec_prefix:   ${prefix}
+    bindir:        ${exec_prefix}/bin
+    sbindir:       ${exec_prefix}/bin
+    libdir:        ${exec_prefix}/lib
+    libexecdir:    ${exec_prefix}/modules
+    mandir:        ${prefix}/man
+    sysconfdir:    ${prefix}/conf
+    datadir:       ${prefix}
+    installbuilddir: ${datadir}/build
+    includedir:    ${prefix}/include
+    localstatedir: ${prefix}
+</Layout>
+
+#   GNU standards conforming path layout.
+#   See FSF's GNU project `make-stds' document for details.
+<Layout GNU>
+    prefix:        /usr/local
+    exec_prefix:   ${prefix}
+    bindir:        ${exec_prefix}/bin
+    sbindir:       ${exec_prefix}/sbin
+    libdir:        ${exec_prefix}/lib
+    libexecdir:    ${exec_prefix}/libexec
+    mandir:        ${prefix}/man
+    sysconfdir:    ${prefix}/etc+
+    datadir:       ${prefix}/share+
+    installbuilddir: ${datadir}/build
+    includedir:    ${prefix}/include+
+    localstatedir: ${prefix}/var+
+    runtimedir:    ${localstatedir}/run
+</Layout>
+
+#   Mac OS X Server (Rhapsody)
+<Layout Mac OS X Server>
+    prefix:        /Local/Library/WebServer
+    exec_prefix:   /usr
+    bindir:        ${exec_prefix}/bin
+    sbindir:       ${exec_prefix}/sbin
+    libdir:        ${exec_prefix}/lib
+    libexecdir:    /System/Library/apr/Modules
+    mandir:        ${exec_prefix}/share/man
+    sysconfdir:    ${prefix}/Configuration
+    datadir:       ${prefix}
+    installbuilddir: /System/Library/apr/Build
+    includedir:    /System/Library/Frameworks/apr.framework/Versions/2.0/Headers
+    localstatedir: /var
+    runtimedir:    ${prefix}/Logs
+</Layout>
+
+#   Darwin/Mac OS Layout
+<Layout Darwin>
+    prefix:        /usr
+    exec_prefix:   ${prefix}
+    bindir:        ${exec_prefix}/bin
+    sbindir:       ${exec_prefix}/sbin
+    libdir:        ${exec_prefix}/lib
+    libexecdir:    ${exec_prefix}/libexec+
+    mandir:        ${prefix}/share/man
+    datadir:       /Library/WebServer
+    sysconfdir:    /etc+
+    installbuilddir: ${prefix}/share/httpd/build
+    includedir:    ${prefix}/include+
+    localstatedir: /var
+    runtimedir:    ${localstatedir}/run
+</Layout>
+
+#   Red Hat Linux 7.x layout
+<Layout RedHat>
+    prefix:        /usr
+    exec_prefix:   ${prefix}
+    bindir:        ${prefix}/bin
+    sbindir:       ${prefix}/sbin
+    libdir:        ${prefix}/lib
+    libexecdir:    ${prefix}/lib/apr
+    mandir:        ${prefix}/man
+    sysconfdir:    /etc/httpd/conf
+    datadir:       /var/www
+    installbuilddir: ${datadir}/build
+    includedir:    ${prefix}/include/apr
+    localstatedir: /var
+    runtimedir:    ${localstatedir}/run
+</Layout>     
+
+#   According to the /opt filesystem conventions
+<Layout opt>
+    prefix:        /opt/apr
+    exec_prefix:   ${prefix}
+    bindir:        ${exec_prefix}/bin
+    sbindir:       ${exec_prefix}/sbin
+    libdir:        ${exec_prefix}/lib
+    libexecdir:    ${exec_prefix}/libexec
+    mandir:        ${prefix}/man
+    sysconfdir:    /etc${prefix}
+    datadir:       ${prefix}/share
+    installbuilddir: ${datadir}/build
+    includedir:    ${prefix}/include
+    localstatedir: /var${prefix}
+    runtimedir:    ${localstatedir}/run
+</Layout>
+
+#  BeOS layout...
+<Layout beos>
+    prefix:        /boot/home/apr
+    exec_prefix:   ${prefix}
+    bindir:        ${exec_prefix}/bin
+    sbindir:       ${exec_prefix}/bin
+    libdir:        ${exec_prefix}/lib
+    libexecdir:    ${exec_prefix}/libexec
+    mandir:        ${prefix}/man
+    sysconfdir:    ${prefix}/conf
+    datadir:       ${prefix}
+    installbuilddir: ${datadir}/build
+    includedir:    ${prefix}/include
+    localstatedir: ${prefix}
+    runtimedir:    ${localstatedir}/logs
+</Layout>
+
+#   SuSE 6.x layout
+<Layout SuSE>
+    prefix:        /usr
+    exec_prefix:   ${prefix}
+    bindir:        ${prefix}/bin
+    sbindir:       ${prefix}/sbin
+    libdir:        ${prefix}/lib
+    libexecdir:    ${prefix}/lib/apr
+    mandir:        ${prefix}/share/man
+    sysconfdir:    /etc/httpd
+    datadir:       /usr/local/httpd
+    installbuilddir: ${datadir}/build
+    includedir:    ${prefix}/include/apr
+    localstatedir: /var/lib/httpd
+    runtimedir:    /var/run
+</Layout>
+
+#   BSD/OS layout
+<Layout BSDI>
+    prefix:        /var/www
+    exec_prefix:   /usr/contrib
+    bindir:        ${exec_prefix}/bin
+    sbindir:       ${exec_prefix}/bin
+    libdir:        ${exec_prefix}/lib
+    libexecdir:    ${exec_prefix}/libexec/apr
+    mandir:        ${exec_prefix}/man
+    sysconfdir:    ${prefix}/conf
+    datadir:       ${prefix}
+    installbuilddir: ${datadir}/build
+    includedir:    ${exec_prefix}/include/apr
+    localstatedir: /var
+    runtimedir:    ${localstatedir}/run
+</Layout>
+
+#   Solaris 8 Layout
+<Layout Solaris>
+    prefix:        /usr/apr
+    exec_prefix:   ${prefix}
+    bindir:        ${exec_prefix}/bin
+    sbindir:       ${exec_prefix}/bin
+    libdir:        ${exec_prefix}/lib
+    libexecdir:    ${exec_prefix}/libexec
+    mandir:        ${exec_prefix}/man
+    sysconfdir:    /etc/apr
+    datadir:       /var/apr
+    installbuilddir: ${datadir}/build
+    includedir:    ${exec_prefix}/include
+    localstatedir: ${prefix}
+    runtimedir:    /var/run
+</Layout>
+
+#   OpenBSD Layout
+<Layout OpenBSD>
+    prefix:        /var/www
+    exec_prefix:   /usr
+    bindir:        ${exec_prefix}/bin
+    sbindir:       ${exec_prefix}/sbin
+    libdir:        ${exec_prefix}/lib
+    libexecdir:    ${exec_prefix}/lib/apr/modules
+    mandir:        ${exec_prefix}/share/man
+    sysconfdir:    ${prefix}/conf
+    datadir:       ${prefix}
+    installbuilddir: ${prefix}/build
+    includedir:    ${exec_prefix}/lib/apr/include
+    localstatedir: ${prefix}
+    runtimedir:    ${prefix}/logs
+</Layout>
+
+# Debian layout
+<Layout Debian>
+    prefix:        
+    exec_prefix:   ${prefix}/usr
+    bindir:        ${exec_prefix}/bin
+    sbindir:       ${exec_prefix}/sbin
+    libdir:        ${exec_prefix}/lib
+    libexecdir:    ${exec_prefix}/lib/apr/modules
+    mandir:        ${exec_prefix}/share/man
+    datadir:       ${exec_prefix}/share/apr
+    includedir:    ${exec_prefix}/include/apr-${APR_MAJOR_VERSION}
+    localstatedir: ${prefix}/var/run
+    runtimedir:    ${prefix}/var/run
+    infodir:       ${exec_prefix}/share/info
+    libsuffix:    -${APR_MAJOR_VERSION}
+</Layout>
diff --git a/configure.in b/configure.in
index 0817ac7f37f..b9d537cdb56 100644
--- a/configure.in
+++ b/configure.in
@@ -1,214 +1,1568 @@
-dnl ##
-dnl ## Autoconf configuration file for APR
-dnl ##
+dnl 
+dnl Autoconf configuration file for APR
+dnl 
+dnl Process this file with autoconf to produce a configure script.
+dnl Use ./buildconf to prepare build files and run autoconf for APR.
 
+AC_PREREQ(2.59)
 
-AC_CONFIG_AUX_DIR(./helpers)
-echo "Configuring APR library"
-OS=`./config.guess`
-OS=`./config.sub $OS`
-echo "Platform: ${OS}"
+AC_INIT(build/apr_common.m4)
+AC_CONFIG_HEADER(include/arch/unix/apr_private.h)
+AC_CONFIG_AUX_DIR(build)
+AC_CONFIG_MACRO_DIR(build)
 
-dnl # Some initial steps for configuration.  We setup the default directory
-dnl # and which files are to be configured.
+dnl 
+dnl Include our own M4 macros along with those for libtool
+dnl 
+sinclude(build/apr_common.m4)
+sinclude(build/apr_network.m4)
+sinclude(build/apr_threads.m4)
+sinclude(build/apr_win32.m4)
+sinclude(build/apr_hints.m4)
+sinclude(build/libtool.m4)
+sinclude(build/ltsugar.m4)
+sinclude(build/argz.m4)
+sinclude(build/ltoptions.m4)
+sinclude(build/ltversion.m4)
+sinclude(build/lt~obsolete.m4)
 
-# These added to allow default directories to be used...
-DEFAULT_OSDIR="unix"
-echo "(Default will be ${DEFAULT_OSDIR})"
-MODULES="file_io network_io threadproc misc locks time mmap shmem dso i18n"
+sinclude(build/apu-conf.m4)
+sinclude(build/xml.m4)
+sinclude(build/apu-hints.m4)
+sinclude(build/crypto.m4)
+sinclude(build/dbm.m4)
+sinclude(build/dbd.m4)
+sinclude(build/dso.m4)
+sinclude(build/iconv.m4)
 
-dnl Process this file with autoconf to produce a configure script.
-AC_INIT(configure.in)
-AC_CONFIG_HEADER(include/apr_private.h)
+dnl Hard-coded top of apr_private.h:
+AH_TOP([
+#ifndef APR_PRIVATE_H
+#define APR_PRIVATE_H
+
+/* Pick up publicly advertised headers and symbols before the
+ * APR internal private headers and symbols
+ */
+#include <apr.h>
+])
+
+dnl Hard-coded inclusion at the tail end of apr_private.h:
+AH_BOTTOM([
+/* switch this on if we have a BeOS version below BONE */
+#if defined(BEOS) && !defined(HAVE_BONE_VERSION)
+#define BEOS_R5 1
+#else
+#define BEOS_BONE 1
+#endif
+
+/*
+ * Darwin 10's default compiler (gcc42) builds for both 64 and
+ * 32 bit architectures unless specifically told not to.
+ * In those cases, we need to override types depending on how
+ * we're being built at compile time.
+ * NOTE: This is an ugly work-around for Darwin's
+ * concept of universal binaries, a single package
+ * (executable, lib, etc...) which contains both 32
+ * and 64 bit versions. The issue is that if APR is
+ * built universally, if something else is compiled
+ * against it, some bit sizes will depend on whether
+ * it is 32 or 64 bit. This is determined by the __LP64__
+ * flag. Since we need to support both, we have to
+ * handle OS X unqiuely.
+ */
+#ifdef DARWIN_10
+
+#undef APR_OFF_T_STRFN
+#undef APR_INT64_STRFN
+#undef SIZEOF_LONG
+#undef SIZEOF_SIZE_T
+#undef SIZEOF_SSIZE_T
+#undef SIZEOF_VOIDP
+#undef SIZEOF_STRUCT_IOVEC
+
+#ifdef __LP64__
+ #define APR_INT64_STRFN strtol
+ #define SIZEOF_LONG    8
+ #define SIZEOF_SIZE_T  8
+ #define SIZEOF_SSIZE_T 8
+ #define SIZEOF_VOIDP   8
+ #define SIZEOF_STRUCT_IOVEC 16
+#else
+ #define APR_INT64_STRFN strtoll
+ #define SIZEOF_LONG    4
+ #define SIZEOF_SIZE_T  4
+ #define SIZEOF_SSIZE_T 4
+ #define SIZEOF_VOIDP   4
+ #define SIZEOF_STRUCT_IOVEC 8
+#endif
+
+#undef APR_OFF_T_STRFN
+#define APR_OFF_T_STRFN APR_INT64_STRFN
+ 
+
+#undef SETPGRP_VOID
+#ifdef __DARWIN_UNIX03
+ #define SETPGRP_VOID 1
+#else
+/* #undef SETPGRP_VOID */
+#endif
+ 
+#endif /* DARWIN_10 */
+
+#endif /* APR_PRIVATE_H */
+])
+
+dnl Save user-defined environment settings for later restoration
+dnl
+APR_SAVE_THE_ENVIRONMENT(CPPFLAGS)
+APR_SAVE_THE_ENVIRONMENT(CFLAGS)
+APR_SAVE_THE_ENVIRONMENT(LDFLAGS)
+APR_SAVE_THE_ENVIRONMENT(LIBS)
+APR_SAVE_THE_ENVIRONMENT(INCLUDES)
+
+dnl Generate ./config.nice for reproducing runs of configure
+dnl
+APR_CONFIG_NICE(config.nice)
+
+AC_CANONICAL_SYSTEM
+AC_MSG_NOTICE([Configuring APR library])
+AC_MSG_NOTICE([Platform: $host])
+
+dnl Some initial steps for configuration.  We setup the default directory
+dnl and which files are to be configured.
+
+dnl Setup the directory macros now
+
+# Absolute source/build directory
+apr_srcdir=`(cd $srcdir && pwd)`
+apr_builddir=`pwd`
+AC_SUBST(apr_srcdir)
+AC_SUBST(apr_builddir)
+
+if test "$apr_builddir" != "$apr_srcdir"; then
+  USE_VPATH=1
+  APR_CONFIG_LOCATION=build
+else
+  APR_CONFIG_LOCATION=source
+fi
 
-# Most platforms use a prefix of 'lib' on their library files.
-LIBPREFIX='lib'
+AC_SUBST(APR_CONFIG_LOCATION)
 
-dnl # Checks for programs.
+# Libtool might need this symbol -- it must point to the location of
+# the generated libtool script (not necessarily the "top" build dir).
+#
+top_builddir="$apr_builddir"
+AC_SUBST(top_builddir)
+
+# Directory containing apr build macros, helpers, and make rules
+# NOTE: make rules (apr_rules.mk) will be in the builddir for vpath
+#
+apr_buildout=$apr_builddir/build
+apr_builders=$apr_srcdir/build
+AC_SUBST(apr_builders)
+
+MKDIR=$apr_builders/mkdir.sh
+
+dnl Initialize mkdir -p functionality.
+APR_MKDIR_P_CHECK($apr_builders/mkdir.sh)
+
+# get our version information
+get_version="$apr_builders/get-version.sh"
+version_hdr="$apr_srcdir/include/apr_version.h"
+APR_MAJOR_VERSION="`$get_version major $version_hdr APR`"
+APR_DOTTED_VERSION="`$get_version all $version_hdr APR`"
+
+AC_SUBST(APR_DOTTED_VERSION)
+AC_SUBST(APR_MAJOR_VERSION)
+
+AC_MSG_NOTICE([APR Version: ${APR_DOTTED_VERSION}])
+
+dnl Enable the layout handling code, then reparse the prefix-style
+dnl arguments due to autoconf being a PITA.
+APR_ENABLE_LAYOUT(apr)
+dnl This must be synchronized to the prefix of the apr layout, to make
+dnl configure --help print the correct default.
+AC_PREFIX_DEFAULT([/usr/local/apr])
+APR_PARSE_ARGUMENTS
+
+dnl Set optional CC hints here in case autoconf makes an inappropriate choice.
+dnl This allows us to suggest what the compiler should be, but still
+dnl allows the user to override CC externally.
+APR_CC_HINTS
+
+dnl Do the various CC checks *before* preloading values. The preload code
+dnl may need to use compiler characteristics to make decisions. This macro
+dnl can only be used once within a configure script, so this prevents a
+dnl preload section from invoking the macro to get compiler info.
 AC_PROG_CC
-AC_PROG_RANLIB_NC
+
+dnl AC_PROG_SED is only avaliable in recent autoconf versions.
+dnl Use AC_CHECK_PROG instead if AC_PROG_SED is not present.
+ifdef([AC_PROG_SED],
+      [AC_PROG_SED],
+      [AC_CHECK_PROG(SED, sed, sed)])
+
+dnl Preload
+APR_PRELOAD
+
+dnl These added to allow default directories to be used...
+DEFAULT_OSDIR="unix"
+AC_MSG_NOTICE([(Default will be ${DEFAULT_OSDIR})])
+
+apr_modules="file_io network_io threadproc misc locks time mmap shmem user memory atomic poll support random"
+
+dnl Checks for programs.
 AC_PROG_MAKE_SET
+AC_PROG_CPP
+AC_PROG_AWK
+AC_PROG_LN_S
+AC_PROG_RANLIB
+AC_PROG_INSTALL
 AC_CHECK_PROG(RM, rm, rm)
-AC_CHECK_PROG(AR, ar, ar)
+AC_CHECK_TOOL(AS, as, as)
+AC_CHECK_TOOL(ASCPP, cpp, cpp)
+AC_CHECK_TOOL(AR, ar, ar)
 
-# This macro needs to be here in case we are on an AIX box.
+dnl Various OS checks that apparently set required flags
+ifdef([AC_USE_SYSTEM_EXTENSIONS], [
+AC_USE_SYSTEM_EXTENSIONS
+], [
 AC_AIX
+AC_MINIX
+])
+
+AC_ISC_POSIX
+APR_EBCDIC
+
+dnl this is our library name
+APR_LIBNAME="apr${libsuffix}"
+AC_SUBST(APR_LIBNAME)
+
+dnl prep libtool
+dnl
+AC_MSG_NOTICE([performing libtool configuration...])
+
+AC_ARG_ENABLE(experimental-libtool,[  --enable-experimental-libtool Use experimental custom libtool],
+  [experimental_libtool=$enableval],[experimental_libtool=no])
+
+dnl Workarounds for busted Libtool 2.x when we don't call AC_PROG_LIBTOOL
+if test "x$Xsed" = "x"; then
+  Xsed="$SED -e 1s/^X//"
+fi
 
-# Use /bin/sh if it exists, otherwise go looking for sh in the path
-if test ".$SH" = . -a -f /bin/sh; then
-  SH="/bin/sh"
+case $host in
+*-os2*)
+    # Use a custom-made libtool replacement
+    AC_MSG_NOTICE([using aplibtool])
+    LIBTOOL="$apr_builddir/build/aplibtool"
+    LIBTOOL_SRC="$apr_srcdir/build/aplibtool.c"
+    $CC $CFLAGS $CPPFLAGS -o $LIBTOOL.exe $LIBTOOL_SRC
+    ;;
+*)
+    if test "x$LTFLAGS" = "x"; then
+        LTFLAGS='--silent'
+    fi
+    if test "$experimental_libtool" = "yes"; then
+        # Use a custom-made libtool replacement
+        AC_MSG_NOTICE([using jlibtool])
+        LIBTOOL="$apr_builddir/libtool"
+        LIBTOOL_SRC="$apr_srcdir/build/jlibtool.c"
+        $CC $CFLAGS $CPPFLAGS -o $LIBTOOL $LIBTOOL_SRC
+        eval `$apr_builddir/libtool --config | grep "^shlibpath_var=[[A-Z_]]*$"`
+        if test "x$shlibpath_var" = "x"; then
+            shlibpath_var=REPLACE_WITH_YOUR_SHLIBPATH_VAR
+        fi
+    else
+    dnl libtoolize requires that the following not be indented
+    dnl should become LT_INIT(win32-dll)
+AC_LIBTOOL_WIN32_DLL
+AC_PROG_LIBTOOL
+        # get libtool's setting of shlibpath_var
+        eval `grep "^shlibpath_var=[[A-Z_]]*$" $apr_builddir/libtool`
+        if test "x$shlibpath_var" = "x"; then
+            shlibpath_var=REPLACE_WITH_YOUR_SHLIBPATH_VAR
+        fi
+    fi
+    ;;
+esac
+
+AC_ARG_WITH(installbuilddir, [  --with-installbuilddir=DIR location to store APR build files (defaults to '${datadir}/build')],
+  [ installbuilddir=$withval ], [ installbuilddir="${datadir}/build-${APR_MAJOR_VERSION}" ] )
+AC_SUBST(installbuilddir)
+
+AC_ARG_WITH(libtool, [  --without-libtool       avoid using libtool to link the library],
+  [ use_libtool=$withval ], [ use_libtool="yes" ] )
+
+if test "x$use_libtool" = "xyes"; then
+      lt_compile='$(LIBTOOL) $(LTFLAGS) --mode=compile $(COMPILE) -o $@ -c $< && touch $@'
+      LT_VERSION="-version-info `$get_version libtool $version_hdr APR`"
+      link="\$(LIBTOOL) \$(LTFLAGS) --mode=link \$(COMPILE) \$(LT_LDFLAGS) \$(LT_VERSION) \$(ALL_LDFLAGS) -o \$@"
+      so_ext='lo'
+      lib_target='-rpath $(libdir) $(OBJECTS)'
+      export_lib_target='-rpath \$(libdir) \$(OBJECTS)'
+else
+      lt_compile='$(COMPILE) -o $@ -c $<'
+      link='$(AR) cr $(TARGET_LIB) $(OBJECTS); $(RANLIB) $(TARGET_LIB)'
+      so_ext='o'
+      lib_target=''
+      export_lib_target=''
 fi
-AC_CHECK_PROG(SH, sh, sh)
 
-dnl #----------------------------- Checks for compiler flags
+case $host in
+    *-solaris2*)
+        apr_platform_runtime_link_flag="-R"
+        ;;
+    *-mingw* | *-cygwin*)
+        LT_LDFLAGS="$LT_LDFLAGS -no-undefined"
+        ;;
+    *)
+        ;;
+esac
+
+AC_SUBST(lt_compile)
+AC_SUBST(link)
+AC_SUBST(so_ext)
+AC_SUBST(lib_target)
+AC_SUBST(export_lib_target)
+AC_SUBST(shlibpath_var)
+AC_SUBST(LTFLAGS)
+AC_SUBST(LT_LDFLAGS)
+AC_SUBST(LT_VERSION)
+
+dnl ----------------------------- Checks for compiler flags
 nl='
 '
-echo $ac_n "${nl}Check for compiler flags..."
-AC_ARG_WITH(optim,[  --with-optim="FLAGS"      compiler optimisation flags],
-        [OPTIM="$withval"])
-
-AC_ARG_WITH(debug,[  --with-debug              Turn on debugging and compile tim
-e warnings],
-        [if test "$GCC" = "yes"; then CFLAGS="$CFLAGS -g -Wall"; else CFLAGS="$CFLAGS -g"; fi])
-
-dnl # this is the place to put specific options for platform/compiler
-dnl # combinations
-case "$OS:$CC" in
-    *-hp-hpux*:cc ) CFLAGS="$CFLAGS -Ae +DAportable" ;;
+AC_MSG_NOTICE([])
+AC_MSG_NOTICE([Check for compiler flags...])
+
+dnl AC_PROG_CC sets -g in CFLAGS (and -O2 for gcc) by default.
+dnl On OS/390 this causes the compiler to insert extra debugger
+dnl hook instructions.  That's fine for debug/maintainer builds, not fine
+dnl otherwise.
+
+case $host in
+    *os390)
+        if test "$ac_test_CFLAGS" != set; then
+           APR_REMOVEFROM(CFLAGS,-g)
+        fi
+        ;;
+esac
+
+AC_ARG_ENABLE(debug,[  --enable-debug          Turn on debugging and compile time warnings],
+  [APR_ADDTO(CFLAGS,-g)
+   if test "$GCC" = "yes"; then
+     APR_ADDTO(CFLAGS,-Wall)
+   elif test "$AIX_XLC" = "yes"; then
+     APR_ADDTO(CFLAGS,-qfullpath)
+   fi
+])dnl
+
+AC_ARG_ENABLE(maintainer-mode,[  --enable-maintainer-mode  Turn on debugging and compile time warnings],
+  [APR_ADDTO(CFLAGS,-g)
+   if test "$GCC" = "yes"; then
+     APR_ADDTO(CFLAGS,[-Wall -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations])
+      case `($CC --version) 2>/dev/null` in
+        *clang-900* | *"clang version 5.0.0"*)
+          APR_ADDTO(CFLAGS,[-Wno-error=strict-prototypes])
+          ;;
+      esac
+   elif test "$AIX_XLC" = "yes"; then
+     APR_ADDTO(CFLAGS,-qfullpath -qinitauto=FE -qcheck=all -qinfo=pro)
+   fi
+])dnl
+
+AC_ARG_ENABLE(profile,[  --enable-profile        Turn on profiling for the build (GCC)],
+  if test "$GCC" = "yes"; then
+    APR_ADDTO(CFLAGS, -pg)
+    APR_REMOVEFROM(CFLAGS, -g)
+    if test "$host" = "i586-pc-beos"; then
+        APR_REMOVEFROM(CFLAGS, -O2)
+        APR_ADDTO(CFLAGS, -O1)
+        APR_ADDTO(LDFLAGS, -p)
+    fi
+  fi
+)dnl
+
+AC_ARG_ENABLE(pool-debug,
+  [  --enable-pool-debug[[=yes|no|verbose|verbose-alloc|lifetime|owner|all]]    Turn on pools debugging],
+  [ if test -z "$enableval"; then
+        APR_ADDTO(CPPFLAGS, -DAPR_POOL_DEBUG=1)
+    elif test ! "$enableval" = "no"; then
+        apr_pool_debug=1
+    
+        for i in $enableval
+        do
+            flag=0
+        
+            case $i in
+            yes)
+                flag=1
+                ;;
+            verbose)
+                flag=2
+                ;;
+            lifetime)
+                flag=4
+                ;;
+            owner)
+                flag=8
+                ;;
+            verbose-alloc)
+                flag=16
+                ;;
+            all)
+                apr_pool_debug=31
+                ;;
+            *)
+                ;;
+            esac
+
+            if test $flag -gt 0; then
+                apr_pool_debug=`expr '(' $apr_pool_debug - $apr_pool_debug % \
+                    '(' $flag '*' 2 ')' ')' + $flag + $apr_pool_debug % $flag`
+            fi
+        done
+      
+        APR_ADDTO(CPPFLAGS, -DAPR_POOL_DEBUG=$apr_pool_debug)
+    fi
+  ])
+
+if test "$host" = "i586-pc-beos"; then
+  AC_ARG_ENABLE(malloc-debug,[  --enable-malloc-debug   Switch on malloc_debug for BeOS],
+    APR_REMOVEFROM(CFLAGS, -O2)
+    APR_ADDTO(CPPFLAGS, -fcheck-memory-usage -D_KERNEL_MODE)
+  ) dnl
+fi
+
+# this is the place to put specific options for platform/compiler
+# combinations
+case "$host:$CC" in
+    *-hp-hpux*:cc )
+	APR_ADDTO(CFLAGS,[-Ae +Z])
+	case $host in
+	  ia64-* )
+	    ;;
+          * )
+	    if echo "$CFLAGS " | grep '+DA' >/dev/null; then :
+	    else
+	      APR_ADDTO(CFLAGS,[+DAportable])
+	    fi 
+	    ;;
+        esac
+	;;
     powerpc-*-beos:mwcc* )
-        CPP="mwcc -E"
-        CC="mwcc"
-        AR="ar"
+	APR_SETVAR(CPP,[mwcc -E])
+	APR_SETVAR(CC,mwcc)
+	APR_SETVAR(AR,ar)
+	;;
+
+    dnl If building static APR, both the APR build and the app build
+    dnl need -DAPR_DECLARE_STATIC to generate the right linkage from    
+    dnl APR_DECLARE et al.
+    dnl If building dynamic APR, the APR build needs APR_DECLARE_EXPORT
+    dnl and the app build should have neither define.
+    *-mingw* | *-cygwin*)
+        if test "$enable_shared" = "yes"; then
+            APR_ADDTO(INTERNAL_CPPFLAGS, -DAPR_DECLARE_EXPORT)
+        else
+            APR_ADDTO(CPPFLAGS, -DAPR_DECLARE_STATIC)
+        fi
+        ;;
+esac
+
+AC_CACHE_CHECK([whether the compiler provides atomic builtins], [ap_cv_atomic_builtins],
+[AC_TRY_RUN([
+int main()
+{
+    unsigned long val = 1010, tmp, *mem = &val;
+
+    if (__sync_fetch_and_add(&val, 1010) != 1010 || val != 2020)
+        return 1;
+
+    tmp = val;
+
+    if (__sync_fetch_and_sub(mem, 1010) != tmp || val != 1010)
+        return 1;
+
+    if (__sync_sub_and_fetch(&val, 1010) != 0 || val != 0)
+        return 1;
+
+    tmp = 3030;
+
+    if (__sync_val_compare_and_swap(mem, 0, tmp) != 0 || val != tmp)
+        return 1;
+
+    if (__sync_lock_test_and_set(&val, 4040) != 3030)
+        return 1;
+
+    mem = &tmp;
+
+    if (__sync_val_compare_and_swap(&mem, &tmp, &val) != &tmp)
+        return 1;
+
+    __sync_synchronize();
+
+    if (mem != &val)
+        return 1;
+
+    return 0;
+}], [ap_cv_atomic_builtins=yes], [ap_cv_atomic_builtins=no], [ap_cv_atomic_builtins=no])])
+
+if test "$ap_cv_atomic_builtins" = "yes"; then
+    AC_DEFINE(HAVE_ATOMIC_BUILTINS, 1, [Define if compiler provides atomic builtins])
+fi
+
+AC_CACHE_CHECK([whether the compiler handles weak symbols], [ap_cv_weak_symbols],
+[AC_TRY_RUN([
+__attribute__ ((weak))
+int weak_noop(void)
+{
+    return 0;
+}
+int main()
+{
+    return weak_noop();
+}], [ap_cv_weak_symbols=yes], [ap_cv_weak_symbols=no], [ap_cv_weak_symbols=no])])
+
+if test "$ap_cv_weak_symbols" = "yes"; then
+    AC_DEFINE(HAVE_WEAK_SYMBOLS, 1, [Define if compiler handles weak symbols])
+fi
+
+case $host in
+    powerpc-405-*)
+        # The IBM ppc405cr processor has a bugged stwcx instruction.
+        AC_DEFINE(PPC405_ERRATA, 1, [Define on PowerPC 405 where errata 77 applies])
+        ;;
+    *)
         ;;
 esac
 
-case "$OS" in
+dnl Check the depend program we can use
+APR_CHECK_DEPEND
+
+proc_mutex_is_global=0
+
+config_subdirs="none"
+INSTALL_SUBDIRS="none"
+OBJECTS_PLATFORM='$(OBJECTS_unix)'
+
+case $host in
+   i386-ibm-aix* | *-ibm-aix[[1-2]].* | *-ibm-aix3.* | *-ibm-aix4.1 | *-ibm-aix4.1.* | *-ibm-aix4.2 | *-ibm-aix4.2.*)
+       OSDIR="aix"
+       APR_ADDTO(LDFLAGS,-lld)
+       eolstr="\\n"
+       OBJECTS_PLATFORM='$(OBJECTS_aix)'
+       ;;
    *-os2*)
-       CFLAGS="$CFLAGS -DOS2 -Zmt"
+       APR_ADDTO(CPPFLAGS,-DOS2)
+       APR_ADDTO(CFLAGS,-Zmt)
+       AC_CHECK_LIB(bsd, random)
        OSDIR="os2"
-       LIBPREFIX=""
-       enable_apr_threads="system_threads"
+       enable_threads="system_threads"
+       eolstr="\\r\\n"
+       file_as_socket="0"
+       proc_mutex_is_global=1
+       OBJECTS_PLATFORM='$(OBJECTS_os2)'
        ;;
    *beos*)
        OSDIR="beos"
-       CFLAGS="$CFLAGS -DBEOS"
-       enable_apr_threads="system_threads"
-       config_subdirs="shmem/unix/mm"
+       APR_ADDTO(CPPFLAGS,-DBEOS)
+       enable_threads="system_threads"
+       native_mmap_emul="1"
+       APR_CHECK_DEFINE(BONE_VERSION, sys/socket.h)
+       eolstr="\\n"
+       osver=`uname -r`
+       proc_mutex_is_global=1
+       OBJECTS_PLATFORM='$(OBJECTS_beos)'
+       case $osver in
+          5.0.4)
+             file_as_socket="1"
+             ;;
+          *)
+             file_as_socket="0"
+             ;;
+       esac
+       ;;
+   *apple-darwin*)
+       ac_cv_func_fdatasync="no" # Mac OS X wrongly reports it has fdatasync()
+       OSDIR="unix"
+       eolstr="\\n"
+       ;;
+   *os390)
+       OSDIR="os390"
+       OBJECTS_PLATFORM='$(OBJECTS_os390)'
+       eolstr="\\n"
+       ;;
+   *os400)
+       OSDIR="as400"
+       eolstr="\\n"
+       ;;
+   *mingw*)
+       OSDIR="win32"
+       enable_threads="system_threads"
+       eolstr="\\r\\n"
+       file_as_socket=0
+       proc_mutex_is_global=1
+       OBJECTS_PLATFORM='$(OBJECTS_win32)'
+       ;;
+   *cygwin*)
+       OSDIR="unix"
+       enable_threads="no"
+       eolstr="\\n"
+       ;;
+   *hpux10* ) 
+       enable_threads="no"
+       OSDIR="unix"
+       eolstr="\\n"
        ;;
    *)
        OSDIR="unix"
-       config_subdirs="shmem/unix/mm"
+       eolstr="\\n"
+       ;;
+esac
+
+AC_SUBST(OBJECTS_PLATFORM)
+
+# Check whether LFS has explicitly been disabled
+AC_ARG_ENABLE(lfs,[  --disable-lfs           Disable large file support on 32-bit platforms],
+[apr_lfs_choice=$enableval], [apr_lfs_choice=yes])
+
+if test "$apr_lfs_choice" = "yes"; then
+   # Check whether the transitional LFS API is sufficient
+   AC_CACHE_CHECK([whether to enable -D_LARGEFILE64_SOURCE], [apr_cv_use_lfs64], [
+   apr_save_CPPFLAGS=$CPPFLAGS
+   CPPFLAGS="$CPPFLAGS -D_LARGEFILE64_SOURCE"
+   AC_TRY_RUN([
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+void main(void)
+{
+    int fd, ret = 0;
+    struct stat64 st;
+    off64_t off = 4242;
+
+    if (sizeof(off64_t) != 8 || sizeof(off_t) != 4)
+       exit(1);
+    if ((fd = open("conftest.lfs", O_LARGEFILE|O_CREAT|O_WRONLY, 0644)) < 0)
+       exit(2);
+    if (ftruncate64(fd, off) != 0)
+       ret = 3;
+    else if (fstat64(fd, &st) != 0 || st.st_size != off)
+       ret = 4;
+    else if (lseek64(fd, off, SEEK_SET) != off)
+       ret = 5;
+    else if (close(fd) != 0)
+       ret = 6;
+    else if (lstat64("conftest.lfs", &st) != 0 || st.st_size != off)
+       ret = 7;
+    else if (stat64("conftest.lfs", &st) != 0 || st.st_size != off)
+       ret = 8;
+    unlink("conftest.lfs");
+
+    exit(ret);
+}], [apr_cv_use_lfs64=yes], [apr_cv_use_lfs64=no], [apr_cv_use_lfs64=no])
+   CPPFLAGS=$apr_save_CPPFLAGS])
+   if test "$apr_cv_use_lfs64" = "yes"; then
+      APR_ADDTO(CPPFLAGS, [-D_LARGEFILE64_SOURCE])
+   fi
+fi
+
+AC_ARG_ENABLE(nonportable-atomics,
+[  --enable-nonportable-atomics  Use optimized atomic code which may produce nonportable binaries],
+[if test $enableval = yes; then
+   force_generic_atomics=no
+ else
+   force_generic_atomics=yes
+ fi
+],
+[case $host_cpu in
+   i[[456]]86) force_generic_atomics=yes ;;
+   *) force_generic_atomics=no
+      case $host in
+         *solaris2.10*)
+            AC_TRY_COMPILE(
+                [#include <atomic.h>],
+                [void *ptr = NULL; atomic_cas_ptr(&ptr, NULL, NULL);],,
+                [force_generic_atomics=yes]
+            )
+            if test $force_generic_atomics = yes; then
+                AC_MSG_NOTICE([nonportable atomic support disabled, system needs Patch-ID 118884 or 118885])
+            fi
+            ;;
+      esac
+      ;;
+esac
+])
+
+if test $force_generic_atomics = yes; then
+   AC_DEFINE([USE_ATOMICS_GENERIC], 1,
+             [Define if use of generic atomics is requested])
+fi
+
+AC_SUBST(proc_mutex_is_global)
+AC_SUBST(eolstr)
+AC_SUBST(INSTALL_SUBDIRS)
+
+# For some platforms we need a version string which allows easy numeric
+# comparisons.
+case $host in
+    *freebsd*)
+        if test -x /sbin/sysctl; then
+            os_version=`/sbin/sysctl -n kern.osreldate`
+        else
+            os_version=000000
+        fi
+        ;;
+    *linux*)
+        os_major=[`uname -r | sed -e 's/\([1-9][0-9]*\)\..*/\1/'`]
+        os_minor=[`uname -r | sed -e 's/[1-9][0-9]*\.\([0-9]\+\)\..*/\1/'`]
+        if test $os_major -lt 2 -o \( $os_major -eq 2 -a $os_minor -lt 4 \); then
+            AC_MSG_WARN([Configured for pre-2.4 Linux $os_major.$os_minor])
+            os_pre24linux=1
+        else
+            os_pre24linux=0
+            AC_MSG_NOTICE([Configured for Linux $os_major.$os_minor])
+        fi
+        ;;
+    *os390)
+        os_version=`uname -r | sed -e 's/\.//g'`
+        ;;
+    *)
+        os_version=OS_VERSION_IS_NOT_SET
+        ;;
+esac
+
+AC_MSG_NOTICE([])
+AC_MSG_NOTICE([Checking for libraries...])
+
+dnl ----------------------------- Checks for Any required Libraries
+dnl Note: Autoconf will always append LIBS with an extra " " in AC_CHECK_LIB.
+dnl It should check for LIBS being empty and set LIBS equal to the new value 
+dnl without the extra " " in that case, but they didn't do that.  So, we
+dnl end up LIBS="-lm -lcrypt -lnsl  -ldl" which is an annoyance.
+case $host in
+   *-mingw*)
+      APR_ADDTO(LIBS,[-lshell32 -ladvapi32 -lws2_32 -lrpcrt4 -lmswsock])
+      ac_cv_func_CreateFileMapping=yes
+      ;;
+   *)
+      AC_SEARCH_LIBS(gethostbyname, nsl)
+      AC_SEARCH_LIBS(gethostname, nsl)
+      AC_SEARCH_LIBS(socket, socket)
+      AC_SEARCH_LIBS(crypt, crypt ufc)
+      AC_CHECK_LIB(truerand, main)
+      AC_SEARCH_LIBS(modf, m)
        ;;
 esac
 
-if test ".$SYS_SW" = ".AIX"; then
-    CFLAGS="$CFLAGS -U__STR__"
-    case "$SYS_KV" in
-        [12]*)
-            AC_DEFINE(USEBCOPY)
-            OSDIR="aix"
+dnl ----------------------------- Checking for Threads
+AC_MSG_NOTICE([${nl}Checking for Threads...])
+
+if test -z "$enable_threads"; then
+	AC_ARG_ENABLE(threads,
+	[  --enable-threads        Enable threading support in APR.],
+	[ enable_threads=$enableval] ,
+	[ APR_CHECK_PTHREADS_H([ enable_threads="pthread" ] ,
+	                       [ enable_threads="no" ] ) ] )
+fi
+
+if test "$enable_threads" = "no"; then
+    threads="0"
+    pthreadh="0"
+    pthreadser="0"
+else
+    if test "$enable_threads" = "pthread"; then
+# We have specified pthreads for our threading library, just make sure
+# that we have everything we need
+      APR_PTHREADS_CHECK_SAVE
+      APR_PTHREADS_CHECK
+      APR_CHECK_PTHREADS_H([
+          threads="1"
+          pthreadh="1"
+          pthreadser="1" ], [
+          threads="0"
+          pthreadh="0"
+          pthreadser="0"
+          APR_PTHREADS_CHECK_RESTORE ] )
+    elif test "$enable_threads" = "system_threads"; then
+        threads="1"
+        pthreadh="0"
+        pthreadser="0"
+    else
+# We basically specified that we wanted threads, but not how to implement
+# them.  In this case, just look for pthreads.  In the future, we can check
+# for other threading libraries as well.
+      APR_PTHREADS_CHECK_SAVE
+      APR_PTHREADS_CHECK
+      APR_CHECK_PTHREADS_H([
+          threads="1"
+          pthreadh="1"
+          pthreadser="1" ], [
+          threads="0"
+          pthreadser="0"
+          pthreadh="0"
+          APR_PTHREADS_CHECK_RESTORE ] )
+    fi
+    if test "$pthreadh" = "1"; then
+        APR_CHECK_PTHREAD_GETSPECIFIC_TWO_ARGS
+        APR_CHECK_PTHREAD_ATTR_GETDETACHSTATE_ONE_ARG
+        APR_CHECK_PTHREAD_RECURSIVE_MUTEX
+        AC_CHECK_FUNCS([pthread_key_delete pthread_rwlock_init \
+                        pthread_attr_setguardsize pthread_yield])
+
+        if test "$ac_cv_func_pthread_rwlock_init" = "yes"; then
+            dnl ----------------------------- Checking for pthread_rwlock_t
+            AC_CACHE_CHECK([for pthread_rwlock_t], [apr_cv_type_rwlock_t],
+            AC_TRY_COMPILE([#include <sys/types.h>
+#include <pthread.h>], [pthread_rwlock_t *rwlock;],
+              [apr_cv_type_rwlock_t=yes], [apr_cv_type_rwlock_t=no], 
+              [apr_cv_type_rwlock_t=no]))
+            if test "$apr_cv_type_rwlock_t" = "yes"; then
+               AC_DEFINE(HAVE_PTHREAD_RWLOCKS, 1, [Define if pthread rwlocks are available])
+            fi
+        fi
+
+        if test "$ac_cv_func_pthread_yield" = "no"; then
+            dnl ----------------------------- Checking for sched_yield
+            AC_CHECK_HEADERS([sched.h])
+            AC_CHECK_FUNCS([sched_yield])
+        fi
+    fi
+fi
+
+ac_cv_define_READDIR_IS_THREAD_SAFE=no
+ac_cv_define_GETHOSTBYNAME_IS_THREAD_SAFE=no
+ac_cv_define_GETHOSTBYADDR_IS_THREAD_SAFE=no
+ac_cv_define_GETSERVBYNAME_IS_THREAD_SAFE=no
+if test "$threads" = "1"; then
+    AC_MSG_NOTICE([APR will use threads])
+    AC_CHECK_LIB(c_r, readdir,
+        AC_DEFINE(READDIR_IS_THREAD_SAFE, 1, 
+                  [Define if readdir is thread safe]))
+    if test "x$apr_gethostbyname_is_thread_safe" = "x"; then
+        AC_CHECK_LIB(c_r, gethostbyname, apr_gethostbyname_is_thread_safe=yes)
+    fi
+    if test "$apr_gethostbyname_is_thread_safe" = "yes"; then
+        AC_DEFINE(GETHOSTBYNAME_IS_THREAD_SAFE, 1,
+                  [Define if gethostbyname is thread safe])
+    fi
+    if test "x$apr_gethostbyaddr_is_thread_safe" = "x"; then
+        AC_CHECK_LIB(c_r, gethostbyaddr, apr_gethostbyaddr_is_thread_safe=yes)
+    fi
+    if test "$apr_gethostbyaddr_is_thread_safe" = "yes"; then
+        AC_DEFINE(GETHOSTBYADDR_IS_THREAD_SAFE, 1, 
+                  [Define if gethostbyaddr is thread safe])
+    fi
+    if test "x$apr_getservbyname_is_thread_safe" = "x"; then
+        AC_CHECK_LIB(c_r, getservbyname, apr_getservbyname_is_thread_safe=yes)
+    fi
+    if test "$apr_getservbyname_is_thread_safe" = "yes"; then
+        AC_DEFINE(GETSERVBYNAME_IS_THREAD_SAFE, 1, 
+                  [Define if getservbyname is thread safe])
+    fi
+    AC_CHECK_FUNCS(gethostbyname_r gethostbyaddr_r getservbyname_r)
+else
+    AC_MSG_NOTICE([APR will be non-threaded])
+fi
+
+dnl Electric Fence malloc checker.
+dnl --with-efence specifies the path to Electric Fence.
+dnl This test should remain after the threads checks since libefence
+dnl may depend on libpthread.
+AC_ARG_WITH(efence, 
+  [  --with-efence[[=DIR]]     path to Electric Fence installation], 
+  [ apr_efence_dir="$withval"
+    if test "$apr_efence_dir" != "yes"; then
+      APR_ADDTO(LDFLAGS,[-L$apr_efence_dir/lib])
+      if test "x$apr_platform_runtime_link_flag" != "x"; then
+          APR_ADDTO(LDFLAGS, 
+                    [$apr_platform_runtime_link_flag$apr_efence_dir/lib])
+      fi
+    fi
+    AC_CHECK_LIB(efence, malloc, 
+                 [ APR_ADDTO(LIBS,-lefence) ],
+                 [ AC_MSG_ERROR(Electric Fence requested but not detected) ])
+  ])
+
+AC_ARG_WITH(valgrind,
+  [  --with-valgrind[[=DIR]]   Enable code to teach valgrind about apr pools
+                          (optionally: set path to valgrind headers) ],
+  [ if test "$withval" != no; then
+      if test "$withval" = yes; then
+        withval=/usr/include/valgrind
+      fi
+      APR_ADDTO(CPPFLAGS, -I$withval)
+      AC_CHECK_HEADERS(valgrind.h memcheck.h)
+      APR_IFALLYES(header:valgrind.h header:memcheck.h,
+        [AC_DEFINE(HAVE_VALGRIND, 1, [Compile in valgrind support]) ],
+        [AC_MSG_ERROR(valgrind headers not found) ]
+      )
+    fi ]
+)
+
+AC_CHECK_FUNCS(sigsuspend, [ have_sigsuspend="1" ], [ have_sigsuspend="0" ])
+AC_CHECK_FUNCS(sigwait, [ have_sigwait="1" ], [ have_sigwait="0" ]) 
+dnl AC_CHECK_FUNCS doesn't work for this on Tru64 since the function
+dnl is renamed in signal.h.  Todo: Autodetect
+case $host in
+    *alpha*-dec-osf* )
+        have_sigwait="1"
+        ;;
+esac
+
+AC_SUBST(threads)
+AC_SUBST(have_sigsuspend)
+AC_SUBST(have_sigwait)
+
+AC_CHECK_FUNCS(poll kqueue port_create)
+
+# Check for the Linux epoll interface; epoll* may be available in libc
+# but return ENOSYS on a pre-2.6 kernel, so do a run-time check.
+AC_CACHE_CHECK([for epoll support], [apr_cv_epoll],
+[AC_TRY_RUN([
+#include <sys/epoll.h>
+#include <unistd.h>
+
+int main()
+{
+    return epoll_create(5) == -1;
+}], [apr_cv_epoll=yes], [apr_cv_epoll=no], [apr_cv_epoll=no])])
+
+if test "$apr_cv_epoll" = "yes"; then
+   AC_DEFINE([HAVE_EPOLL], 1, [Define if the epoll interface is supported])
+fi
+
+dnl ----------------------------- Checking for extended file descriptor handling
+# test for epoll_create1
+AC_CACHE_CHECK([for epoll_create1 support], [apr_cv_epoll_create1],
+[AC_TRY_RUN([
+#include <sys/epoll.h>
+#include <unistd.h>
+
+int main()
+{
+    return epoll_create1(0) == -1;
+}], [apr_cv_epoll_create1=yes], [apr_cv_epoll_create1=no], [apr_cv_epoll_create1=no])])
+
+if test "$apr_cv_epoll_create1" = "yes"; then
+   AC_DEFINE([HAVE_EPOLL_CREATE1], 1, [Define if epoll_create1 function is supported])
+fi
+
+# Check for z/OS async i/o support.  
+AC_CACHE_CHECK([for asio -> message queue support], [apr_cv_aio_msgq],
+[AC_TRY_RUN([
+#define _AIO_OS390
+#include <aio.h>
+
+int main()
+{
+    struct aiocb a;
+
+    a.aio_notifytype = AIO_MSGQ;  /* use IPC message queue for notification */
+
+    return aio_cancel(2, NULL) == -1;
+}], [apr_cv_aio_msgq=yes], [apr_cv_aio_msgq=no], [apr_cv_aio_msgq=no])])
+
+if test "$apr_cv_aio_msgq" = "yes"; then
+   AC_DEFINE([HAVE_AIO_MSGQ], 1, [Define if async i/o supports message q's])
+fi
+
+# test for dup3
+AC_CACHE_CHECK([for dup3 support], [apr_cv_dup3],
+[AC_TRY_RUN([
+#include <unistd.h>
+
+int main()
+{
+    return dup3(STDOUT_FILENO, STDERR_FILENO, 0) == -1;
+}], [apr_cv_dup3=yes], [apr_cv_dup3=no], [apr_cv_dup3=no])])
+
+if test "$apr_cv_dup3" = "yes"; then
+   AC_DEFINE([HAVE_DUP3], 1, [Define if dup3 function is supported])
+fi
+
+# Test for accept4().  Create a non-blocking socket, bind it to
+# an unspecified port & address (kernel picks), and attempt to
+# call accept4() on it.  If the syscall is wired up (i.e. the
+# kernel is new enough), it should return EAGAIN.
+AC_CACHE_CHECK([for accept4 support], [apr_cv_accept4],
+[AC_TRY_RUN([
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+int main(int argc, char **argv)
+{
+    int fd, flags;
+    struct sockaddr_in sin;
+
+    if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
+        return 1;
+    flags = fcntl(fd, F_GETFL);
+    if (flags == -1 || fcntl(fd, F_SETFL, flags|O_NONBLOCK) == -1)
+        return 5;
+
+    memset(&sin, 0, sizeof sin);
+    sin.sin_family = AF_INET;
+    
+    if (bind(fd, (struct sockaddr *) &sin, sizeof sin) == -1)
+        return 2;
+    
+    if (listen(fd, 5) == -1)
+        return 3;
+
+    if (accept4(fd, NULL, 0, SOCK_NONBLOCK) == 0
+        || errno == EAGAIN || errno == EWOULDBLOCK)
+        return 0;
+
+    return 4;
+}], [apr_cv_accept4=yes], [apr_cv_accept4=no], [apr_cv_accept4=no])])
+
+if test "$apr_cv_accept4" = "yes"; then
+   AC_DEFINE([HAVE_ACCEPT4], 1, [Define if accept4 function is supported])
+fi
+
+AC_CACHE_CHECK([for SOCK_CLOEXEC support], [apr_cv_sock_cloexec],
+[AC_TRY_RUN([
+#include <sys/types.h>
+#include <sys/socket.h>
+
+int main()
+{
+    return socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, 0) == -1;
+}], [apr_cv_sock_cloexec=yes], [apr_cv_sock_cloexec=no], [apr_cv_sock_cloexec=no])])
+
+if test "$apr_cv_sock_cloexec" = "yes"; then
+   AC_DEFINE([HAVE_SOCK_CLOEXEC], 1, [Define if the SOCK_CLOEXEC flag is supported])
+fi
+
+dnl ----------------------------- Checking for fdatasync: OS X doesn't have it
+AC_CHECK_FUNCS(fdatasync)
+
+dnl ----------------------------- Checking for missing POSIX thread functions
+AC_CHECK_FUNCS([getpwnam_r getpwuid_r getgrnam_r getgrgid_r])
+
+dnl ----------------------------- Checking for Shared Memory Support 
+AC_MSG_NOTICE([])
+AC_MSG_NOTICE([Checking for Shared Memory Support...])
+
+# The real-time POSIX extensions (e.g. shm_*, sem_*) may only
+# be available if linking against librt.
+AC_SEARCH_LIBS(shm_open, rt)
+
+case $host in
+ *-sysv*)
+   ac_includes_default="$ac_includes_default
+#if HAVE_SYS_MUTEX_H /* needed to define lock_t for sys/shm.h */
+# include <sys/mutex.h>
+#endif";;
+esac
+
+AC_CHECK_HEADERS([sys/types.h sys/mman.h sys/ipc.h sys/mutex.h \
+                  sys/shm.h sys/file.h kernel/OS.h os2.h windows.h \
+                  net/if.h])
+AC_CHECK_FUNCS([mmap munmap shm_open shm_unlink shmget shmat shmdt shmctl \
+                create_area mprotect])
+
+APR_CHECK_DEFINE(MAP_ANON, sys/mman.h)
+AC_CHECK_FILE(/dev/zero)
+
+# Not all systems can mmap /dev/zero (such as HP-UX).  Check for that.
+if test "$ac_cv_func_mmap" = "yes" &&
+   test "$ac_cv_file__dev_zero" = "yes"; then
+    AC_MSG_CHECKING(for mmap that can map /dev/zero)
+    AC_TRY_RUN([
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+    int main()
+    {
+        int fd;
+        void *m;
+        fd = open("/dev/zero", O_RDWR);
+        if (fd < 0) {
+            return 1;
+        }
+        m = mmap(0, sizeof(void*), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+        if (m == (void *)-1) {  /* aka MAP_FAILED */
+            return 2;
+        }
+        if (munmap(m, sizeof(void*)) < 0) {
+            return 3;
+        }
+        return 0;
+    }], [], [ac_cv_file__dev_zero=no], [ac_cv_file__dev_zero=no])
+
+    AC_MSG_RESULT($ac_cv_file__dev_zero)
+fi
+
+# Now we determine which one is our anonymous shmem preference.
+haveshmgetanon="0"
+havemmapzero="0"
+havemmapanon="0"
+APR_BEGIN_DECISION([anonymous shared memory allocation method])
+APR_IFALLYES(header:sys/ipc.h header:sys/shm.h header:sys/file.h dnl
+             func:shmget func:shmat func:shmdt func:shmctl,
+             [haveshmgetanon="1"
+              APR_DECIDE(USE_SHMEM_SHMGET_ANON, [SysV IPC shmget()])])
+APR_IFALLYES(header:sys/mman.h func:mmap func:munmap file:/dev/zero,
+             [havemmapzero="1"
+              APR_DECIDE(USE_SHMEM_MMAP_ZERO, 
+                  [SVR4-style mmap() on /dev/zero])])
+APR_IFALLYES(header:sys/mman.h func:mmap func:munmap define:MAP_ANON,
+             [havemmapanon="1"
+              APR_DECIDE(USE_SHMEM_MMAP_ANON, 
+                  [4.4BSD-style mmap() via MAP_ANON])])
+APR_IFALLYES(header:os2.h,
+             [haveos2shm="1"
+              APR_DECIDE(USE_SHMEM_OS2_ANON, [OS/2 DosAllocSharedMem()])])
+APR_IFALLYES(header:kernel/OS.h func:create_area,
+             [havebeosshm="1"
+              APR_DECIDE(USE_SHMEM_BEOS_ANON,
+                         [BeOS areas])])
+APR_IFALLYES(header:windows.h func:CreateFileMapping,
+             [havewin32shm="1"
+              APR_DECIDE(USE_SHMEM_WIN32_ANON,
+                         [Windows CreateFileMapping()])])
+case $host in
+    *linux* ) 
+        # Linux has problems with MM_SHMT_MMANON even though it reports
+        # that it has it.
+        # FIXME - find exact 2.3 version that MMANON was fixed in.  It is
+        # confirmed fixed in 2.4 series.
+        if test $os_pre24linux -eq 1; then
+            AC_MSG_WARN([Disabling anon mmap() support for Linux pre-2.4])
+            APR_DECISION_OVERRIDE(USE_SHMEM_MMAP_ZERO USE_SHMEM_SHMGET_ANON)
+        fi
+        ;;
+    *hpux11* ) 
+        APR_DECISION_OVERRIDE(USE_SHMEM_SHMGET_ANON)
+        ;;
+esac
+APR_END_DECISION
+AC_DEFINE_UNQUOTED($ac_decision)
+
+useshmgetanon="0"
+usemmapzero="0"
+usemmapanon="0"
+
+case $ac_decision in
+    USE_SHMEM_SHMGET_ANON )
+        useshmgetanon="1"
+        ;;
+    USE_SHMEM_MMAP_ZERO )
+        usemmapzero="1"
+        ;;
+    USE_SHMEM_MMAP_ANON )
+        usemmapanon="1"
+        ;;
+esac
+
+AC_SUBST(useshmgetanon)
+AC_SUBST(usemmapzero)
+AC_SUBST(usemmapanon)
+AC_SUBST(haveshmgetanon)
+AC_SUBST(havemmapzero)
+AC_SUBST(havemmapanon)
+
+# Now we determine which one is our name-based shmem preference.
+havemmaptmp="0"
+havemmapshm="0"
+haveshmget="0"
+havebeosarea="0"
+haveos2shm="0"
+havewin32shm="0"
+APR_BEGIN_DECISION([namebased memory allocation method])
+APR_IFALLYES(header:sys/mman.h func:mmap func:munmap,
+             [havemmaptmp="1"
+              APR_DECIDE(USE_SHMEM_MMAP_TMP, 
+                  [Classical mmap() on temporary file])])
+APR_IFALLYES(header:sys/mman.h func:mmap func:munmap func:shm_open dnl
+             func:shm_unlink,
+             [havemmapshm="1"
+              APR_DECIDE(USE_SHMEM_MMAP_SHM, 
+                  [mmap() via POSIX.1 shm_open() on temporary file])])
+APR_IFALLYES(header:sys/ipc.h header:sys/shm.h header:sys/file.h dnl
+             func:shmget func:shmat func:shmdt func:shmctl,
+             [haveshmget="1"
+              APR_DECIDE(USE_SHMEM_SHMGET, [SysV IPC shmget()])])
+APR_IFALLYES(header:kernel/OS.h func:create_area,
+             [havebeosshm="1"
+              APR_DECIDE(USE_SHMEM_BEOS, [BeOS areas])])
+APR_IFALLYES(header:os2.h,
+             [haveos2shm="1"
+              APR_DECIDE(USE_SHMEM_OS2, [OS/2 DosAllocSharedMem()])])
+APR_IFALLYES(header:windows.h,
+             [havewin32shm="1"
+              APR_DECIDE(USE_SHMEM_WIN32, [Windows shared memory])])
+AC_ARG_ENABLE(posix-shm,
+[  --enable-posix-shm      Use POSIX shared memory (shm_open) if available],
+[
+if test "$havemmapshm" = "1"; then
+  APR_DECISION_OVERRIDE(USE_SHMEM_MMAP_SHM)
+fi
+])
+case $host in
+    *linux* ) 
+        # Linux pre-2.4 had problems with MM_SHMT_MMANON even though
+        # it reports that it has it.
+        if test $os_pre24linux -eq 1; then
+            APR_DECISION_OVERRIDE(USE_SHMEM_MMAP_TMP USE_SHMEM_MMAP_SHM dnl
+                                  USE_SHMEM_SHMGET)
+        fi
+        ;;
+esac
+APR_END_DECISION
+AC_DEFINE_UNQUOTED($ac_decision)
+
+usemmaptmp="0"
+usemmapshm="0"
+useshmget="0"
+usebeosarea="0"
+useos2shm="0"
+usewin32shm="0"
+
+case $ac_decision in
+    USE_SHMEM_MMAP_TMP )
+        usemmaptmp="1"
+        ;;
+    USE_SHMEM_MMAP_SHM )
+        usemmapshm="1"
+        ;;
+    USE_SHMEM_SHMGET )
+        useshmget="1"
+        ;;
+    USE_SHMEM_BEOS )
+        usebeosarea="1"
+        ;;
+    USE_SHMEM_OS2 )
+        useos2shm="1"
+        ;;
+    USE_SHMEM_WIN32 )
+        usewin32shm="1"
+        ;;
+esac
+
+# Do we have any shared memory support?
+if test "$usemmaptmp$usemmapshm$usemmapzero$useshmget$usemmapanon$usebeosarea$useos2shm$usewin32shm" = "00000000"; then
+  sharedmem="0"
+else
+  sharedmem="1"
+fi
+
+AC_SUBST(usemmaptmp)
+AC_SUBST(usemmapshm)
+AC_SUBST(useshmget)
+AC_SUBST(usebeosarea)
+AC_SUBST(useos2shm)
+AC_SUBST(usewin32shm)
+AC_SUBST(havemmaptmp)
+AC_SUBST(havemmapshm)
+AC_SUBST(haveshmget)
+AC_SUBST(havebeosarea)
+AC_SUBST(haveos2shm)
+AC_SUBST(havewin32shm)
+AC_SUBST(sharedmem)
+
+dnl ----------------------------- Checks for Any required Functions
+dnl Checks for library functions. (N.B. poll is further down)
+
+AC_FUNC_ALLOCA
+
+AC_CHECK_FUNCS([calloc setsid isinf isnan \
+                getenv putenv setenv unsetenv \
+                writev getifaddrs utime utimes])
+AC_CHECK_FUNCS(setrlimit, [ have_setrlimit="1" ], [ have_setrlimit="0" ]) 
+AC_CHECK_FUNCS(getrlimit, [ have_getrlimit="1" ], [ have_getrlimit="0" ]) 
+sendfile="0"
+AC_CHECK_LIB(sendfile, sendfilev)
+AC_CHECK_FUNCS(sendfile send_file sendfilev, [ sendfile="1" ])
+
+dnl THIS MUST COME AFTER THE THREAD TESTS - FreeBSD doesn't always have a
+dnl threaded poll() and we don't want to use sendfile on early FreeBSD 
+dnl systems if we are also using threads.
+
+AC_ARG_WITH(sendfile, [  --with-sendfile         Override decision to use sendfile],
+  [ if test "$withval" = "yes"; then
+        sendfile="1"
+    else
+        sendfile="0"
+    fi ], [
+    orig_sendfile=$sendfile
+    case $host in
+        *freebsd*)
+            # FreeBSD < 4.2 has issues with threads+sendfile
+            if test $os_version -le "401999"; then
+                if test "$threads" = "1"; then
+                    sendfile="0"
+                fi
+            fi
             ;;
-        3*)
-            AC_DEFINE(NEED_RLIM_T)
-            OSDIR="aix"
+        *alpha*-dec-osf* )
+            sendfile="0"
             ;;
-        41*)
-            AC_DEFINE(NEED_RLIM_T)
-            OSDIR="aix"
+        s390-*-linux-gnu)
+            # disable sendfile support for 2.2 on S/390
+            if test $os_pre24linux -eq 1; then
+                AC_MSG_WARN([Disabled sendfile support for Linux 2.2 on S/390])
+                sendfile="0"
+            fi
             ;;
-        42*)
-            OSDIR="aix"
+        *aix*)
+            # compiler-independent check for 64-bit build
+            AC_CHECK_SIZEOF(void*, 4)
+            if test "x$ac_cv_sizeof_voidp" = "x8"; then
+                # sendfile not working for 64-bit build
+                sendfile="0"
+            fi
             ;;
-    esac
-fi
-
-dnl #----------------------------- Checks for Any required Libraries
-AC_CHECK_LIB(dl, dlopen)
-AC_CHECK_LIB(nsl,gethostbyname)
-AC_CHECK_LIB(nsl,gethostname)
-AC_CHECK_LIB(socket,socket)
-AC_CHECK_LIB(crypt,crypt)
-AC_CHECK_LIB(ufc,crypt)
-AC_CHECK_LIB(truerand,main)
+    esac       
+    if test "$orig_sendfile" != "$sendfile"; then
+      AC_MSG_NOTICE([sendfile support disabled to avoid system problem])
+    fi ] )
+AC_SUBST(sendfile)
 
-dnl #----------------------------- Checks for Any required Functions
-dnl Checks for library functions.
-AC_CHECK_FUNCS(pthread_sigmask)
-AC_CHECK_FUNCS(strcasecmp stricmp poll setsid)
 AC_CHECK_FUNCS(sigaction, [ have_sigaction="1" ], [ have_sigaction="0" ]) 
-AC_CHECK_FUNCS(writev)
-AC_CHECK_FUNCS(sendfile, [ sendfile="1" ], [ sendfile="0" ])
+AC_DECL_SYS_SIGLIST
+
 AC_CHECK_FUNCS(fork, [ fork="1" ], [ fork="0" ])
-AC_CHECK_FUNCS(getpass)
-AC_CHECK_FUNC(inet_addr, [ inet_addr="1" ], [ inet_addr="0" ])
-AC_CHECK_FUNC(inet_network, [ inet_network="1" ], [ inet_network="0" ])
+APR_CHECK_INET_ADDR
+APR_CHECK_INET_NETWORK
+AC_SUBST(apr_inaddr_none)
 AC_CHECK_FUNC(_getch)
-AC_CHECK_FUNCS(gmtime_r localtime_r)
-AC_CHECK_FUNCS(iconv, [ iconv="1" ], [ iconv="0" ])
-AC_SUBST(sendfile)
+AC_CHECK_FUNCS(strerror_r, [ strerror_r="1" ], [ strerror_r="0" ])
+if test "$strerror_r" = "1"; then
+  APR_CHECK_STRERROR_R_RC
+fi
+AC_CHECK_FUNCS(mmap, [ mmap="1" ], [ mmap="0" ])
+if test "$native_mmap_emul" = "1"; then
+    mmap="1"
+fi
+AC_CHECK_FUNCS(memmove, [ have_memmove="1" ], [have_memmove="0" ])
+AC_CHECK_FUNCS([getpass getpassphrase gmtime_r localtime_r])
+case $host in
+    *-hp-hpux*)
+        dnl mkstemp is limited to 26 temporary files (a-z); use APR replacement
+        ;;
+    *)
+        AC_CHECK_FUNCS(mkstemp mkostemp)
+        ;;
+esac
+
 AC_SUBST(fork)
-AC_SUBST(inet_addr)
-AC_SUBST(inet_network)
+AC_SUBST(have_inet_addr)
+AC_SUBST(tcp_nodelay_inherited)
+AC_SUBST(o_nonblock_inherited)
+AC_SUBST(have_inet_network)
 AC_SUBST(have_sigaction)
-AC_SUBST(iconv)
+AC_SUBST(have_setrlimit)
+AC_SUBST(have_getrlimit)
+AC_SUBST(mmap)
+AC_SUBST(have_memmove)
 
+APR_CHECK_SIGWAIT_ONE_ARG
 
-dnl #----------------------------- Checks for Any required Headers
+dnl ----------------------------- Checks for Any required Headers
 AC_HEADER_STDC
 
-AC_CHECK_HEADERS(conio.h)
-AC_CHECK_HEADERS(crypt.h)
-AC_CHECK_HEADERS(ctype.h)
-AC_CHECK_HEADERS(dir.h)
-AC_CHECK_HEADERS(dirent.h, direnth="1", dirent="0")
-AC_CHECK_HEADERS(errno.h, errnoh="1", errnoh="0")
-AC_CHECK_HEADERS(net/errno.h)
-AC_CHECK_HEADERS(fcntl.h, fcntlh="1", fcntl="0")
-AC_CHECK_HEADERS(features.h)
-AC_CHECK_HEADERS(grp.h)
-AC_CHECK_HEADERS(io.h)
-AC_CHECK_HEADERS(limits.h)
-AC_CHECK_HEADERS(malloc.h)
-AC_CHECK_HEADERS(math.h)
-AC_CHECK_HEADERS(memory.h)
-AC_CHECK_HEADERS(netdb.h)
-AC_CHECK_HEADERS(osreldate.h)
-AC_CHECK_HEADERS(process.h)
-AC_CHECK_HEADERS(pwd.h)
-AC_CHECK_HEADERS(sys/sem.h)
-AC_CHECK_HEADERS(setjmp.h)
-AC_CHECK_HEADERS(signal.h, signalh="1", signalh="0")
-AC_CHECK_HEADERS(stdarg.h, stdargh="1", stdargh="0")
-AC_CHECK_HEADERS(stddef.h)
-AC_CHECK_HEADERS(stdio.h, stdioh="1", stdioh"0")
-AC_CHECK_HEADERS(stdlib.h)
-AC_CHECK_HEADERS(string.h)
-AC_CHECK_HEADERS(sysapi.h)
-AC_CHECK_HEADERS(sysgtime.h)
-AC_CHECK_HEADERS(termios.h)
-AC_CHECK_HEADERS(time.h)
-AC_CHECK_HEADERS(sys/time.h)
-AC_CHECK_HEADERS(sys/times.h)
-AC_CHECK_HEADERS(tpfeq.h)
-AC_CHECK_HEADERS(tpfio.h)
-AC_CHECK_HEADERS(sys/uio.h, sys_uioh="1", sys_uioh="0")
-AC_CHECK_HEADERS(unistd.h)
-AC_CHECK_HEADERS(poll.h)
-AC_CHECK_HEADERS(unix.h)
-AC_CHECK_HEADERS(arpa/inet.h)
-AC_CHECK_HEADERS(netinet/in.h, netinet_inh="1", netinet_inh="0")
-AC_CHECK_HEADERS(netinet/tcp.h)
-AC_CHECK_HEADERS(iconv.h)
-
-AC_CHECK_HEADERS(sys/file.h)
-AC_CHECK_HEADERS(sys/ioctl.h)
-AC_CHECK_HEADERS(sys/mman.h)
-AC_CHECK_HEADERS(sys/param.h)
-AC_CHECK_HEADERS(sys/resource.h)
-AC_CHECK_HEADERS(sys/select.h)
-AC_CHECK_HEADERS(sys/sendfile.h)
-AC_CHECK_HEADERS(sys/signal.h)
-AC_CHECK_HEADERS(sys/socket.h)
-AC_CHECK_HEADERS(sys/stat.h)
-AC_CHECK_HEADERS(sys/types.h, sys_typesh="1", sys_typesh="0")
-AC_CHECK_HEADERS(sys/wait.h)
-AC_CHECK_HEADERS(dlfcn.h)
-AC_CHECK_HEADERS(dl.h)
-
-AC_CHECK_HEADERS(kernel/OS.h)
+APR_FLAG_HEADERS(
+    aio.h               \
+    ByteOrder.h		\
+    conio.h		\
+    crypt.h		\
+    ctype.h		\
+    dir.h		\
+    dirent.h		\
+    dl.h		\
+    dlfcn.h		\
+    errno.h		\
+    fcntl.h		\
+    grp.h		\
+    ifaddrs.h           \
+    io.h		\
+    limits.h		\
+    mach-o/dyld.h	\
+    malloc.h		\
+    memory.h		\
+    netdb.h		\
+    osreldate.h		\
+    poll.h		\
+    process.h		\
+    pwd.h		\
+    semaphore.h		\
+    signal.h		\
+    stdarg.h		\
+    stddef.h		\
+    stdio.h		\
+    stdlib.h		\
+    string.h		\
+    strings.h		\
+    sysapi.h		\
+    sysgtime.h		\
+    termios.h		\
+    time.h		\
+    tpfeq.h		\
+    tpfio.h		\
+    unistd.h		\
+    unix.h		\
+    windows.h		\
+    winsock2.h		\
+    ws2tcpip.h		\
+    arpa/inet.h		\
+    kernel/OS.h		\
+    net/errno.h		\
+    netinet/in.h	\
+    netinet/sctp.h      \
+    netinet/sctp_uio.h  \
+    sys/file.h		\
+    sys/ioctl.h         \
+    sys/mman.h		\
+    sys/param.h         \
+    sys/poll.h		\
+    sys/resource.h	\
+    sys/select.h	\
+    sys/sem.h		\
+    sys/sendfile.h	\
+    sys/signal.h	\
+    sys/socket.h	\
+    sys/sockio.h	\
+    sys/stat.h          \
+    sys/sysctl.h	\
+    sys/syslimits.h	\
+    sys/time.h		\
+    sys/types.h		\
+    sys/uio.h		\
+    sys/un.h		\
+    sys/wait.h)
 
+# Windows' <mswsock.h> requires <windows.h> first
+AC_CACHE_CHECK([for mswsock.h], [apr_cv_hdr_mswsock_h],
+[AC_TRY_CPP(
+[#include <windows.h>
+#include <mswsock.h>
+], [apr_cv_hdr_mswsock_h=yes], [apr_cv_hdr_mswsock_h=no])])
+if test "$apr_cv_hdr_mswsock_h" = "yes"; then
+   mswsockh=1
+else
+   mswsockh=0
+fi
+
+# IRIX 6.5 has a problem in <netinet/tcp.h> which prevents it from
+# being included by itself.  Check for <netinet/tcp.h> manually,
+# including another header file first.
+AC_CACHE_CHECK([for netinet/tcp.h], [apr_cv_hdr_netinet_tcp_h],
+[AC_TRY_CPP(
+[#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#include <netinet/tcp.h>
+], [apr_cv_hdr_netinet_tcp_h=yes], [apr_cv_hdr_netinet_tcp_h=no])])
+if test "$apr_cv_hdr_netinet_tcp_h" = "yes"; then
+   netinet_tcph=1
+   AC_DEFINE([HAVE_NETINET_TCP_H], 1, [Defined if netinet/tcp.h is present])
+else
+   netinet_tcph=0
+fi
+
+AC_SUBST(aioh)
+AC_SUBST(arpa_ineth)
+AC_SUBST(conioh)
+AC_SUBST(ctypeh)
+AC_SUBST(crypth)
 AC_SUBST(errnoh)
 AC_SUBST(direnth)
 AC_SUBST(fcntlh)
+AC_SUBST(ioh)
+AC_SUBST(ifaddrsh)
+AC_SUBST(limitsh)
+AC_SUBST(mswsockh)
+AC_SUBST(netdbh)
 AC_SUBST(netinet_inh)
+AC_SUBST(netinet_sctph)
+AC_SUBST(netinet_sctp_uioh)
+AC_SUBST(netinet_tcph)
 AC_SUBST(stdargh)
+AC_SUBST(stddefh)
 AC_SUBST(stdioh)
+AC_SUBST(stdlibh)
+AC_SUBST(stringh)
+AC_SUBST(stringsh)
+AC_SUBST(sys_ioctlh)
+AC_SUBST(sys_sendfileh)
+AC_SUBST(sys_signalh)
+AC_SUBST(sys_socketh)
+AC_SUBST(sys_sockioh)
+AC_SUBST(sys_syslimitsh)
 AC_SUBST(sys_typesh)
+AC_SUBST(sys_timeh)
 AC_SUBST(sys_uioh)
+AC_SUBST(sys_unh)
+AC_SUBST(timeh)
+AC_SUBST(unistdh)
 AC_SUBST(signalh)
+AC_SUBST(sys_waith)
+AC_SUBST(processh)
 AC_SUBST(pthreadh)
+AC_SUBST(semaphoreh)
+AC_SUBST(windowsh)
+AC_SUBST(winsock2h)
+AC_SUBST(ws2tcpiph)
+
+# Checking for h_errno in <netdb.h>
+if test "$netdbh" = "1"; then
+  APR_CHECK_H_ERRNO_FLAG
+  if test "$ac_cv_h_errno_cflags" = "no"; then
+    AC_MSG_ERROR([can not find h_errno in netdb.h])
+  fi
+fi
+
+AC_ARG_ENABLE(allocator-uses-mmap,
+  [  --enable-allocator-uses-mmap    Use mmap in apr_allocator instead of malloc ],
+  [ if test "$enableval" = "yes"; then
+        APR_IFALLYES(header:sys/mman.h func:mmap func:munmap define:MAP_ANON,
+                     [AC_DEFINE(APR_ALLOCATOR_USES_MMAP, 1,
+                                [Define if apr_allocator should use mmap]) ],
+                     [AC_MSG_ERROR([mmap()/MAP_ANON not supported]) ]
+                   )
+    fi ]
+)
 
-dnl #----------------------------- Checks for standard typedefs
+AC_ARG_ENABLE(allocator-guard-pages,
+  [  --enable-allocator-guard-pages  Use guard pages in apr_allocator
+                                  (implies --enable-allocator-uses-mmap) ] ,
+  [ if test "$enableval" = "yes"; then
+        APR_IFALLYES(header:sys/mman.h func:mmap func:munmap func:mprotect define:MAP_ANON,
+                     [AC_DEFINE(APR_ALLOCATOR_GUARD_PAGES, 1,
+                                [Define if apr_allocator should use guard pages]) ],
+                     [AC_MSG_ERROR([mmap()/MAP_ANON/mprotect() not supported]) ]
+                   )
+    fi ]
+)
+
+
+AC_ARG_ENABLE(pool-concurrency-check,
+  [  --enable-pool-concurrency-check Check for concurrent usage of memory pools],
+  [ if test "$enableval" = "yes"; then
+    AC_DEFINE(APR_POOL_CONCURRENCY_CHECK, 1,
+               [Define if pool functions should abort if concurrent usage is detected])
+    fi ]
+)
+
+dnl ----------------------------- Checks for standard typedefs
 AC_TYPE_OFF_T
 AC_TYPE_PID_T
 AC_TYPE_SIZE_T
@@ -216,17 +1570,24 @@ AC_TYPE_UID_T
 AC_CHECK_TYPE(ssize_t, int)
 AC_C_INLINE
 AC_C_CONST
-AC_TYPE_SIZE_T
 AC_FUNC_SETPGRP
 
 APR_CHECK_SOCKLEN_T
 
-dnl # Checks for integer size
+dnl Checks for pointer size
+AC_CHECK_SIZEOF(void*, 4)
+
+if test "x$ac_cv_sizeof_voidp" != "x"; then
+    voidp_size=$ac_cv_sizeof_voidp
+else
+    AC_ERROR([Cannot determine size of void*])
+fi
+
+dnl Checks for integer size
 AC_CHECK_SIZEOF(char, 1)
 AC_CHECK_SIZEOF(int, 4)
 AC_CHECK_SIZEOF(long, 4)
 AC_CHECK_SIZEOF(short, 2)
-AC_CHECK_SIZEOF(long double, 12)
 AC_CHECK_SIZEOF(long long, 8)
 
 if test "$ac_cv_sizeof_short" = "2"; then
@@ -235,134 +1596,605 @@ fi
 if test "$ac_cv_sizeof_int" = "4"; then
     int_value=int
 fi
-if test "$ac_cv_sizeof_long" = "8"; then
+# Now we need to find what apr_int64_t (sizeof == 8) will be.
+# The first match is our preference.
+if test "$ac_cv_sizeof_int" = "8"; then
+    int64_literal='#define APR_INT64_C(val) (val)'
+    uint64_literal='#define APR_UINT64_C(val) (val##U)'
+    int64_t_fmt='#define APR_INT64_T_FMT "d"'
+    uint64_t_fmt='#define APR_UINT64_T_FMT "u"'
+    uint64_t_hex_fmt='#define APR_UINT64_T_HEX_FMT "x"'
+    int64_value="int"
+    long_value=int
+    int64_strfn="strtoi"
+elif test "$ac_cv_sizeof_long" = "8"; then
+    int64_literal='#define APR_INT64_C(val) (val##L)'
+    uint64_literal='#define APR_UINT64_C(val) (val##UL)'
+    int64_t_fmt='#define APR_INT64_T_FMT "ld"'
+    uint64_t_fmt='#define APR_UINT64_T_FMT "lu"'
+    uint64_t_hex_fmt='#define APR_UINT64_T_HEX_FMT "lx"'
+    int64_value="long"
     long_value=long
-fi
-if test "$ac_cv_sizeof_long_double" = "8"; then
-    long_value="long double"
-fi
-if test "$ac_cv_sizeof_long_long" = "8"; then
+    int64_strfn="strtol"
+elif test "$ac_cv_sizeof_long_long" = "8"; then
+    int64_literal='#define APR_INT64_C(val) (val##LL)'
+    uint64_literal='#define APR_UINT64_C(val) (val##ULL)'
+    # Linux, Solaris, FreeBSD all support ll with printf.
+    # BSD 4.4 originated 'q'.  Solaris is more popular and 
+    # doesn't support 'q'.  Solaris wins.  Exceptions can
+    # go to the OS-dependent section.
+    int64_t_fmt='#define APR_INT64_T_FMT "lld"'
+    uint64_t_fmt='#define APR_UINT64_T_FMT "llu"'
+    uint64_t_hex_fmt='#define APR_UINT64_T_HEX_FMT "llx"'
+    int64_value="long long"
     long_value="long long"
-fi
-if test "$ac_cv_sizeof_longlong" = "8"; then
+    int64_strfn="strtoll"
+elif test "$ac_cv_sizeof_longlong" = "8"; then
+    int64_literal='#define APR_INT64_C(val) (val##LL)'
+    uint64_literal='#define APR_UINT64_C(val) (val##ULL)'
+    int64_t_fmt='#define APR_INT64_T_FMT "qd"'
+    uint64_t_fmt='#define APR_UINT64_T_FMT "qu"'
+    uint64_t_hex_fmt='#define APR_UINT64_T_HEX_FMT "qx"'
+    int64_value="__int64"
     long_value="__int64"
+    int64_strfn="strtoll"
+else
+    # int64_literal may be overriden if your compiler thinks you have
+    # a 64-bit value but APR does not agree.
+    AC_ERROR([could not detect a 64-bit integer type])
 fi
 
-if test "$ac_cv_type_off_t" = "yes"; then
-    off_t_value="off_t"
+# If present, allow the C99 macro INT64_C to override our conversion.
+#
+# HP-UX's ANSI C compiler provides this without any includes, so we
+# will first look for INT64_C without adding stdint.h
+AC_CACHE_CHECK([for INT64_C], [apr_cv_define_INT64_C], [
+AC_EGREP_CPP(YES_IS_DEFINED,
+[#ifdef INT64_C
+YES_IS_DEFINED
+#endif], [apr_cv_define_INT64_C=yes], [
+    # Now check for INT64_C in stdint.h
+    AC_EGREP_CPP(YES_IS_DEFINED, [#include <stdint.h>
+#ifdef INT64_C
+YES_IS_DEFINED
+#endif], [apr_cv_define_INT64_C=yes], [apr_cv_define_INT64_C=no])])])
+
+if test "$apr_cv_define_INT64_C" = "yes"; then
+    int64_literal='#define APR_INT64_C(val) INT64_C(val)'
+    uint64_literal='#define APR_UINT64_C(val) UINT64_C(val)'
+    stdint=1
 else
-    off_t_value="ap_int32_t"
+    stdint=0
 fi
+
 if test "$ac_cv_type_size_t" = "yes"; then
     size_t_value="size_t"
 else
-    size_t_value="ap_int32_t"
+    size_t_value="apr_int32_t"
 fi
 if test "$ac_cv_type_ssize_t" = "yes"; then
     ssize_t_value="ssize_t"
 else
-    ssize_t_value="ap_int32_t"
+    ssize_t_value="apr_int32_t"
+fi
+if test "$ac_cv_socklen_t" = "yes"; then
+    socklen_t_value="socklen_t"
+    case $host in
+        *-hp-hpux*)
+            if test "$ac_cv_sizeof_long" = "8"; then
+                # 64-bit HP-UX requires 32-bit socklens in
+                # kernel, but user-space declarations say
+                # 64-bit (socklen_t == size_t == long).
+                # This will result in many compile warnings,
+                # but we're functionally busted otherwise.
+                socklen_t_value="int"
+            fi
+            ;;
+    esac
+else
+    socklen_t_value="int"
+fi
+
+APR_CHECK_SIZEOF_EXTENDED([#include <sys/types.h>], pid_t, 8)
+
+if test "$ac_cv_sizeof_pid_t" = "$ac_cv_sizeof_short"; then
+    pid_t_fmt='#define APR_PID_T_FMT "hd"'
+elif test "$ac_cv_sizeof_pid_t" = "$ac_cv_sizeof_int"; then
+    pid_t_fmt='#define APR_PID_T_FMT "d"'
+elif test "$ac_cv_sizeof_pid_t" = "$ac_cv_sizeof_long"; then
+    pid_t_fmt='#define APR_PID_T_FMT "ld"'
+elif test "$ac_cv_sizeof_pid_t" = "$ac_cv_sizeof_long_long"; then
+    pid_t_fmt='#define APR_PID_T_FMT APR_INT64_T_FMT'
+else
+    pid_t_fmt='#error Can not determine the proper size for pid_t'
+fi
+
+# Basically, we have tried to figure out the correct format strings
+# for APR types which vary between platforms, but we don't always get
+# it right.
+case $host in
+   s390*linux*)
+       # uniquely, the 31-bit Linux/s390 uses "unsigned long int"
+       # for size_t rather than "unsigned int":
+       size_t_fmt="lu"
+       ssize_t_fmt="ld"
+       ;;
+   *-os2*)
+       size_t_fmt="lu"
+       ;;
+   *-solaris*)
+       if test "$ac_cv_sizeof_long" = "8"; then
+         pid_t_fmt='#define APR_PID_T_FMT "d"'
+       else
+         pid_t_fmt='#define APR_PID_T_FMT "ld"'
+       fi
+       ;;
+   *aix4*|*aix5*)
+       ssize_t_fmt="ld"
+       size_t_fmt="lu"
+       ;;
+    *beos*)
+        ssize_t_fmt="ld"
+        size_t_fmt="ld"
+        ;;
+    *apple-darwin*)
+        osver=`uname -r`
+        case $osver in
+           [[0-7]].*)
+              ssize_t_fmt="d"
+              ;;
+           *)
+              ssize_t_fmt="ld"
+              ;;
+        esac
+        size_t_fmt="lu"
+        ;;
+    *-mingw*)
+        int64_t_fmt='#define APR_INT64_T_FMT "I64d"'
+        uint64_t_fmt='#define APR_UINT64_T_FMT "I64u"'
+        uint64_t_hex_fmt='#define APR_UINT64_T_HEX_FMT "I64x"'
+        int64_value="__int64"
+        long_value="__int64"
+        int64_strfn="_strtoi64"
+        ;;
+esac
+
+APR_CHECK_TYPES_COMPATIBLE(ssize_t, int, [ssize_t_fmt="d"])
+APR_CHECK_TYPES_COMPATIBLE(ssize_t, long, [ssize_t_fmt="ld"])
+APR_CHECK_TYPES_COMPATIBLE(size_t, unsigned int, [size_t_fmt="u"])
+APR_CHECK_TYPES_COMPATIBLE(size_t, unsigned long, [size_t_fmt="lu"])
+
+APR_CHECK_SIZEOF_EXTENDED([#include <sys/types.h>], ssize_t, 8)
+
+AC_MSG_CHECKING([which format to use for apr_ssize_t])
+if test -n "$ssize_t_fmt"; then
+    AC_MSG_RESULT(%$ssize_t_fmt)
+elif test "$ac_cv_sizeof_ssize_t" = "$ac_cv_sizeof_int"; then
+    ssize_t_fmt="d"
+    AC_MSG_RESULT(%d)
+elif test "$ac_cv_sizeof_ssize_t" = "$ac_cv_sizeof_long"; then
+    ssize_t_fmt="ld"
+    AC_MSG_RESULT(%ld)
+else
+    AC_ERROR([could not determine the proper format for apr_ssize_t])
+fi
+
+ssize_t_fmt="#define APR_SSIZE_T_FMT \"$ssize_t_fmt\""
+
+APR_CHECK_SIZEOF_EXTENDED([#include <stddef.h>], size_t, 8)
+
+AC_MSG_CHECKING([which format to use for apr_size_t])
+if test -n "$size_t_fmt"; then
+    AC_MSG_RESULT(%$size_t_fmt)
+elif test "$ac_cv_sizeof_size_t" = "$ac_cv_sizeof_int"; then
+    size_t_fmt="d"
+    AC_MSG_RESULT(%d)
+elif test "$ac_cv_sizeof_size_t" = "$ac_cv_sizeof_long"; then
+    size_t_fmt="ld"
+    AC_MSG_RESULT(%ld)
+else
+    AC_ERROR([could not determine the proper format for apr_size_t])
+fi
+
+size_t_fmt="#define APR_SIZE_T_FMT \"$size_t_fmt\""
+
+APR_CHECK_SIZEOF_EXTENDED([#include <sys/types.h>], off_t, 8)
+
+if test "${ac_cv_sizeof_off_t}${apr_cv_use_lfs64}" = "4yes"; then
+    # Enable LFS
+    aprlfs=1
+    AC_CHECK_FUNCS([mmap64 sendfile64 sendfilev64 readdir64_r])
+    case $host in
+        *-hp-hpux*)
+            dnl mkstemp64 is limited to 26 temporary files (a-z); use APR replacement
+            ;;
+        *)
+            AC_CHECK_FUNCS(mkstemp64 mkostemp64)
+            ;;
+    esac
+elif test "${ac_cv_sizeof_off_t}" != "${ac_cv_sizeof_size_t}"; then
+    # unsure of using -gt above is as portable, can can't forsee where
+    # off_t can legitimately be smaller than size_t
+    aprlfs=1
+else
+    aprlfs=0     
+fi
+
+AC_MSG_CHECKING([which type to use for apr_off_t])
+if test "${ac_cv_sizeof_off_t}${apr_cv_use_lfs64}" = "4yes"; then
+    # LFS is go!
+    off_t_fmt='#define APR_OFF_T_FMT APR_INT64_T_FMT'
+    off_t_value='off64_t'
+    off_t_strfn='apr_strtoi64'
+elif test "${ac_cv_sizeof_off_t}x${ac_cv_sizeof_long}" = "4x4"; then
+    # Special case: off_t may change size with _FILE_OFFSET_BITS
+    # on 32-bit systems with LFS support.  To avoid compatibility
+    # issues when other packages do define _FILE_OFFSET_BITS,
+    # hard-code apr_off_t to long.
+    off_t_value=long
+    off_t_fmt='#define APR_OFF_T_FMT "ld"'
+    off_t_strfn='strtol'
+elif test "$ac_cv_type_off_t" = "yes"; then
+    off_t_value=off_t
+    # off_t is more commonly a long than an int; prefer that case
+    # where int and long are the same size.
+    if test "$ac_cv_sizeof_off_t" = "$ac_cv_sizeof_long"; then
+        off_t_fmt='#define APR_OFF_T_FMT "ld"'
+        off_t_strfn='strtol'
+    elif test "$ac_cv_sizeof_off_t" = "$ac_cv_sizeof_int"; then
+        off_t_fmt='#define APR_OFF_T_FMT "d"'
+        off_t_strfn='strtoi'
+    elif test "$ac_cv_sizeof_off_t" = "$ac_cv_sizeof_long_long"; then
+        off_t_fmt='#define APR_OFF_T_FMT APR_INT64_T_FMT'
+        off_t_strfn='apr_strtoi64'
+    else
+        AC_ERROR([could not determine the size of off_t])
+    fi
+    # Per OS tuning...
+    case $host in
+    *-mingw*)
+        off_t_value=apr_int64_t
+        off_t_fmt='#define APR_OFF_T_FMT "I64d"'
+        off_t_strfn='_strtoi64'
+        ;;
+    esac
+else
+    # Fallback on int
+    off_t_value=apr_int64_t
+    off_t_fmt='#define APR_OFF_T_FMT "d"'
+    off_t_strfn='strtoi'
 fi
+AC_MSG_RESULT($off_t_value)
 
-AC_CHECK_SIZEOF_EXTENDED([#include <sys/types.h>], ssize_t, 8)
+# Regardless of whether _LARGEFILE64_SOURCE is used, on some
+# platforms _FILE_OFFSET_BITS will affect the size of ino_t and hence
+# the build-time ABI may be different from the apparent ABI when using
+# APR with another package which *does* define _FILE_OFFSET_BITS.
+# (Exactly as per the case above with off_t where LFS is *not* used)
+#
+# To be safe, hard-code apr_ino_t as 'unsigned long' or 'unsigned int'
+# iff that is exactly the size of ino_t here; otherwise use ino_t as existing
+# releases did.  To be correct, apr_ino_t should have been made an
+# ino64_t as apr_off_t is off64_t, but this can't be done now without
+# breaking ABI.
 
-if test "$ac_cv_sizeof_ssize_t" = "$ac_cv_sizeof_int"; then
-    ssize_t_fmt='#define APR_SSIZE_T_FMT "d"'
-elif test "$ac_cv_sizeof_ssize_t" = "$ac_cv_sizeof_long"; then
-    ssize_t_fmt='#define APR_SSIZE_T_FMT "ld"'
+# Per OS tuning...
+case $host in
+*mingw*)
+    ino_t_value=apr_int64_t
+    ;;
+*)
+    ino_t_value=ino_t
+    APR_CHECK_SIZEOF_EXTENDED(AC_INCLUDES_DEFAULT, ino_t, $ac_cv_sizeof_long)
+    if test $ac_cv_sizeof_ino_t = 4; then
+        if test $ac_cv_sizeof_long = 4; then
+            ino_t_value="unsigned long"
+        else
+            ino_t_value="unsigned int"
+        fi
+    fi
+    ;;
+esac
+AC_MSG_NOTICE([using $ino_t_value for ino_t])
+
+# Checks for endianness
+AC_C_BIGENDIAN
+if test $ac_cv_c_bigendian = yes; then
+    bigendian=1
 else
-    ssize_t_fmt='#error Can not determine the proper size for ssize_t'
+    bigendian=0
 fi
 
-AC_CHECK_SIZEOF_EXTENDED([#include <sys/types.h>], off_t, 8)
-
-if test "$ac_cv_sizeof_off_t" = "$ac_cv_sizeof_int"; then
-    off_t_fmt='#define APR_OFF_T_FMT "d"'
-elif test "$ac_cv_sizeof_off_t" = "$ac_cv_sizeof_long"; then
-    off_t_fmt='#define APR_OFF_T_FMT "ld"'
-elif test "$ac_cv_sizeof_off_t" = "$ac_cv_sizeof_long_long"; then
-    off_t_fmt='#define APR_OFF_T_FMT "qd"'
+APR_CHECK_SIZEOF_EXTENDED([#include <sys/types.h>
+#include <sys/uio.h>],struct iovec,0)
+if test "$ac_cv_sizeof_struct_iovec" = "0"; then
+    have_iovec=0
 else
-    off_t_fmt='#error Can not determine the proper size for off_t'
+    have_iovec=1
 fi
 
+AC_SUBST(voidp_size)
 AC_SUBST(short_value)
 AC_SUBST(int_value)
 AC_SUBST(long_value)
+AC_SUBST(int64_value)
 AC_SUBST(off_t_value)
 AC_SUBST(size_t_value)
 AC_SUBST(ssize_t_value)
+AC_SUBST(socklen_t_value)
+AC_SUBST(int64_t_fmt) 
+AC_SUBST(uint64_t_fmt) 
+AC_SUBST(uint64_t_hex_fmt) 
 AC_SUBST(ssize_t_fmt) 
+AC_SUBST(size_t_fmt)
 AC_SUBST(off_t_fmt) 
+AC_SUBST(pid_t_fmt)
+AC_SUBST(int64_literal) 
+AC_SUBST(uint64_literal) 
+AC_SUBST(stdint) 
+AC_SUBST(bigendian)
+AC_SUBST(aprlfs)
+AC_SUBST(have_iovec)
+AC_SUBST(ino_t_value)
 
-dnl #----------------------------- Checking for Threads
-echo $ac_n "${nl}Checking for Threads...${nl}"
-AC_CACHE_CHECK([for threads], ac_cv_enable_threads,
-  [ AC_ARG_ENABLE(threads,
-    [  --enable-threads  Enable threading support in APR.],
-    [ ac_cv_enable_threads=$enableval] ,
-    [ AC_CHECK_HEADERS(pthread.h,
-                   [ ac_cv_enable_threads="pthread" ] ,
-                   [ ac_cv_enable_threads="no" ] ) ] ) ] )
-
-if test "$ac_cv_enable_threads" = "no"; then
-    threads="0"
-    pthreadh="0"
-else
-    REENTRANCY_FLAGS
-    if test "$ac_cv_enable_threads" = "pthread"; then
-# We have specified pthreads for our threading library, just make sure
-# that we have everything we need
-      PTHREADS_CHECK
-      AC_CHECK_HEADERS(pthread.h, [
-          threads="1"
-          pthreadh="1"
-          AC_DEFINE(USE_THREADS) ], [
-          threads="0"
-          pthreadh="0" ] )
-    elif test "$enable_apr_threads" = "system_threads"; then
-          threads="1"
-          pthreadh="0"
-    else
-# We basically specified that we wanted threads, but not how to implement
-# them.  In this case, just look for pthreads.  In the future, we can check
-# for other threading libraries as well.
-      PTHREADS_CHECK
-      AC_CHECK_HEADERS(pthread.h, [
-          threads="1"
-          pthreadh="1"
-          AC_DEFINE(USE_THREADS) ], [
-          threads="0"
-          pthreadh="0" ] )
-    fi
+dnl ----------------------------- Checking for string functions
+AC_CHECK_FUNCS(strnicmp, have_strnicmp="1", have_strnicmp="0")
+AC_CHECK_FUNCS(strncasecmp, have_strncasecmp="1", have_strncasecmp="0")
+AC_CHECK_FUNCS(stricmp, have_stricmp="1", have_stricmp="0")
+AC_CHECK_FUNCS(strcasecmp, have_strcasecmp="1", have_strcasecmp="0")
+AC_CHECK_FUNCS(strdup, have_strdup="1", have_strdup="0")
+AC_CHECK_FUNCS(strstr, have_strstr="1", have_strstr="0")
+AC_CHECK_FUNCS(memchr, have_memchr="1", have_memchr="0")
+AC_CHECK_FUNC($int64_strfn, have_int64_strfn="1", have_int64_strfn="0")
+
+dnl ----------------------------- We have a fallback position
+if test "$have_int64_strfn" = "0" && test "$int64_strfn" = "strtoll"; then
+    int64_strfn="strtoq"
+    AC_CHECK_FUNC(strtoq, [have_int64_strfn=1], [have_int64_strfn=0])
 fi
 
-ac_cv_define_READDIR_IS_THREAD_SAFE=no
-AC_CHECK_LIB(c_r, readdir, AC_DEFINE(READDIR_IS_THREAD_SAFE))
+if test "$have_int64_strfn" = "1"; then
+  AC_DEFINE_UNQUOTED(APR_INT64_STRFN, [$int64_strfn],
+      [Define as function which can be used for conversion of strings to apr_int64_t])
+fi
 
-if test "$threads" = "1"; then
-    echo "APR will use threads"
-else
-    echo "APR will be non-threaded"
+AC_SUBST(have_strnicmp)
+AC_SUBST(have_strncasecmp)
+AC_SUBST(have_stricmp)
+AC_SUBST(have_strcasecmp)
+AC_SUBST(have_strdup)
+AC_SUBST(have_strstr)
+AC_SUBST(have_memchr)
+
+AC_CACHE_CHECK([for memset_s support], [apr_cv_memset_s],
+[AC_TRY_RUN([
+#ifdef HAVE_STRING_H
+#define __STDC_WANT_LIB_EXT1__ 1
+#include <string.h>
+#endif
+
+int main(int argc, const char **argv)
+{
+    char buf[1] = {1};
+    return memset_s(buf, sizeof buf, 0, sizeof buf) != 0 || *buf != '\0';
+}], [apr_cv_memset_s=yes], [apr_cv_memset_s=no], [apr_cv_memset_s=no])])
+
+if test "$apr_cv_memset_s" = "yes"; then
+   AC_DEFINE([HAVE_MEMSET_S], 1, [Define if memset_s function is supported])
 fi
 
-AC_SUBST(threads)
+AC_CACHE_CHECK([for explicit_bzero support], [apr_cv_explicit_bzero],
+[AC_TRY_RUN([
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
 
-dnl #----------------------------- Checking for MMAP 
-echo $ac_n "${nl}Checking for MMAP...${nl}"
-AC_FUNC_MMAP
-if test "$ac_cv_func_mmap_fixed_mapped" = "yes"; then
-    mmap="1"
+int main(int argc, const char **argv)
+{
+    char buf[1] = {1};
+    explicit_bzero(buf, sizeof buf);
+    return *buf != '\0';
+}], [apr_cv_explicit_bzero=yes], [apr_cv_explicit_bzero=no], [apr_cv_explicit_bzero=no])])
+
+if test "$apr_cv_explicit_bzero" = "yes"; then
+   AC_DEFINE([HAVE_EXPLICIT_BZERO], 1, [Define if explicit_bzero function is supported])
+fi
+
+if test "$off_t_strfn" = "apr_strtoi64" && test "$have_int64_strfn" = "1"; then
+    off_t_strfn=$int64_strfn
+fi
+AC_DEFINE_UNQUOTED(APR_OFF_T_STRFN, [$off_t_strfn],
+          [Define as function used for conversion of strings to apr_off_t])
+
+dnl ----------------------------- Checking for DSO support
+AC_MSG_NOTICE([])
+AC_MSG_NOTICE([Checking for DSO...])
+
+AC_ARG_ENABLE(dso,
+  [  --disable-dso           Disable DSO support ],
+  [if test "x$enableval" = "xyes"; then
+      dsotype=any
+   else
+      dsotype=$enableval
+   fi
+  ], [dsotype=any])
+
+if test "$dsotype" = "any"; then
+    if test "$dsotype" = "any"; then
+      case $host in
+        *darwin[[0-8]]\.*) 
+          # Original Darwin, not for 9.0!:
+          AC_CHECK_FUNC(NSLinkModule, [dsotype=dyld]);;
+        hppa*-hpux[[1-9]]\.*|hppa*-hpux1[[01]]*)
+          # shl is specific to parisc hpux SOM binaries, not used for 64 bit
+          AC_CHECK_LIB(dld, shl_load, [have_shl=1])
+          if test "$ac_cv_sizeof_voidp$have_shl" = "41"; then
+            dsotype=shl; APR_ADDTO(LIBS,-ldld)
+          fi;;
+        *-mingw*|*-os2*)
+          # several 'other's below probably belong up here.  If they always
+          # use a platform implementation and shouldn't test the dlopen/dlfcn
+          # features, then bring them up here.
+          # But if they -should- optionally use dlfcn, and/or need the config
+          # detection of dlopen/dlsym, do not move them up.
+          dsotype=other ;;
+      esac
+    fi
+    # Normal POSIX:
+    if test "$dsotype" = "any"; then
+      AC_CHECK_FUNC(dlopen, [dsotype=dlfcn])
+    fi
+    if test "$dsotype" = "any"; then
+      AC_CHECK_LIB(dl, dlopen, [dsotype=dlfcn; APR_ADDTO(LIBS,-ldl)])
+    fi
+    if test "$dsotype" = "dlfcn"; then
+        # ReliantUnix has dlopen() in libc but dlsym() in libdl :(
+        AC_CHECK_FUNC(dlsym, [], 
+          [AC_CHECK_LIB(dl, dlsym, 
+             [APR_ADDTO(LIBS, -ldl)],
+             [dsotype=any
+              AC_MSG_WARN([Weird: dlopen() was found but dlsym() was not found!])])])
+    fi
+    if test "$dsotype" = "any"; then
+      # BeOS:
+      AC_CHECK_LIB(root, load_image, [dsotype=other])
+    fi
+    # Everything else:
+    if test "$dsotype" = "any"; then
+        case $host in
+        *os390|*os400|*-aix*)
+          # Some -aix5 will use dl, no hassles.  Keep that pattern here.
+          dsotype=other ;;
+        *-hpux*)
+          if test "$have_shl" = "1"; then
+            dsotype=shl; APR_ADDTO(LIBS,-ldld)
+          fi;;
+        esac
+    fi
+fi
+
+if test "$dsotype" = "any"; then
+    AC_MSG_ERROR([Could not detect suitable DSO implementation])
+elif test "$dsotype" = "no"; then
+    aprdso="0"
 else
-    mmap="0"
+    case "$dsotype" in
+    dlfcn) AC_DEFINE(DSO_USE_DLFCN, 1, [Define if DSO support uses dlfcn.h]);;
+    shl)   AC_DEFINE(DSO_USE_SHL, 1, [Define if DSO support uses shl_load]);;
+    dyld)  AC_DEFINE(DSO_USE_DYLD, 1, [Define if DSO support uses dyld.h]);;
+    other) ;; # Use whatever is in dso/OSDIR
+    *) AC_MSG_ERROR([Unknown DSO implementation "$dsotype"]);;
+    esac
+    aprdso="1"
+    apr_modules="$apr_modules dso"
+fi
+
+AC_SUBST(aprdso)
+
+dnl ----------------------------- Checking for Processes
+AC_MSG_NOTICE([])
+AC_MSG_NOTICE([Checking for Processes...])
+
+AC_CHECK_FUNCS(waitpid)
+
+AC_ARG_ENABLE(other-child,
+  [  --enable-other-child    Enable reliable child processes ],
+  [ if test "$enableval" = "yes"; then
+        oc="1"
+    else
+        oc="0"
+    fi ],
+  [ oc=1 ] ) 
+  
+AC_SUBST(oc) 
+
+if test -z "$have_proc_invoked"; then
+  have_proc_invoked="0"
+fi
+
+AC_SUBST(have_proc_invoked)
+
+AC_MSG_CHECKING(for Variable Length Arrays)
+APR_TRY_COMPILE_NO_WARNING([],
+[
+    int foo[argc];
+    foo[0] = 0;
+], vla_msg=yes, vla_msg=no )
+AC_MSG_RESULT([$vla_msg])
+if test "$vla_msg" = "yes"; then
+    AC_DEFINE(HAVE_VLA, 1, [Define if C compiler supports VLA])
 fi
-AC_SUBST(mmap)
 
-dnl #----------------------------- Checking for Locking Characteristics 
-echo $ac_n "${nl}Checking for Locking..."
+AC_CACHE_CHECK(struct rlimit,ac_cv_struct_rlimit,[
+AC_TRY_RUN([
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+main()
+{
+    struct rlimit limit;
+    limit.rlim_cur = 0;
+    limit.rlim_max = 0;
+    exit(0);
+}], [
+    ac_cv_struct_rlimit=yes ], [
+    ac_cv_struct_rlimit=no ], [
+    ac_cv_struct_rlimit=no ] ) ] )
+struct_rlimit=0
+test "x$ac_cv_struct_rlimit" = xyes && struct_rlimit=1
+AC_SUBST(struct_rlimit)
+
+dnl ----------------------------- Checking for Locking Characteristics 
+AC_MSG_NOTICE([])
+AC_MSG_NOTICE([Checking for Locking...])
+
+AC_CHECK_FUNCS(semget semctl semop semtimedop flock)
+APR_IFALLYES(func:semtimedop, have_semtimedop="1", have_semtimedop="0")
+
+AC_CHECK_HEADERS(semaphore.h)
+AC_SEARCH_LIBS(sem_open, rt)
+AC_CHECK_FUNCS(sem_close sem_unlink sem_post sem_wait sem_timedwait)
+APR_IFALLYES(func:sem_timedwait, have_sem_timedwait="1", have_sem_timedwait="0")
+
+AC_CHECK_HEADERS(OS.h)
+AC_CHECK_FUNCS(create_sem acquire_sem acquire_sem_etc)
+APR_IFALLYES(header:OS.h func:acquire_sem_etc, have_acquire_sem_etc="1", have_acquire_sem_etc="0")
+
+# Some systems return ENOSYS from sem_open.
+AC_CACHE_CHECK(for working sem_open,ac_cv_func_sem_open,[
+AC_TRY_RUN([
+#include <errno.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <semaphore.h>
+#ifndef SEM_FAILED
+#define SEM_FAILED (-1)
+#endif
+main()
+{
+    sem_t *psem;
+    const char *sem_name = "/apr_autoconf";
+
+    psem = sem_open(sem_name, O_CREAT, 0644, 1);
+    if (psem == (sem_t *)SEM_FAILED) {
+	exit(1);
+    }
+    sem_close(psem);
+    psem = sem_open(sem_name, O_CREAT | O_EXCL, 0644, 1);
+    if (psem != (sem_t *)SEM_FAILED) {
+        sem_close(psem);
+        exit(1);
+    }
+    sem_unlink(sem_name);
+    exit(0);
+}], [ac_cv_func_sem_open=yes], [ac_cv_func_sem_open=no],
+[ac_cv_func_sem_open=no])])
 
 # It's stupid, but not all platforms have union semun, even those that need it.
-AC_MSG_CHECKING(looking for union semun in sys/sem.h)
+AC_MSG_CHECKING(for union semun in sys/sem.h)
 AC_TRY_COMPILE([
 #include <sys/types.h>
 #include <sys/ipc.h>
@@ -378,167 +2210,799 @@ AC_MSG_RESULT([$msg])
 AC_SUBST(have_union_semun)
 
 dnl Checks for libraries.
-AC_CHECK_DEFINE(LOCK_EX, sys/file.h)
-AC_CHECK_DEFINE(F_SETLK, fcntl.h)
+APR_CHECK_DEFINE(LOCK_EX, sys/file.h)
+APR_CHECK_DEFINE(F_SETLK, fcntl.h)
+APR_CHECK_DEFINE(SEM_UNDO, sys/sem.h)
+
+# We are assuming that if the platform doesn't have POLLIN, it doesn't have
+# any POLL definitions.
+APR_CHECK_DEFINE_FILES(POLLIN, poll.h sys/poll.h)
 
-pthreadser="0"
 if test "$threads" = "1"; then
-    AC_CHECK_DEFINE(PTHREAD_PROCESS_SHARED, pthread.h)
-    AC_CHECK_FUNC(pthread_mutex_init, [
-        AC_DEFINE(USE_PTHREAD_SERIALIZE)
-        pthreadser="1" ])
-fi
-AC_BEGIN_DECISION([lock implementation method])
-AC_IFALLYES(custom:union_semun,
-            AC_DECIDE(USE_SYSVSEM_SERIALIZE, [SysV IPC semget()]))
-AC_IFALLYES(header:sys/file.h define:LOCK_EX,
-            AC_DECIDE(USE_FLOCK_SERIALIZE, [4.2BSD-style flock()]))
-AC_IFALLYES(header:fcntl.h define:F_SETLK,
-            AC_DECIDE(USE_FCNTL_SERIALIZE, [SVR4-style fcntl()]))
-AC_IFALLYES(header:pthread.h define:PTHREAD_PROCESS_SHARED dnl
-            custom:with_pthread_cross,
-            AC_DECIDE(USE_PROC_PTHREAD_SERIALIZE, [pthread mutex]))
-dnl AC_DECISION_FORCE(USE_FCNTL_SERIALIZE)
-AC_END_DECISION
+    APR_CHECK_DEFINE(PTHREAD_PROCESS_SHARED, pthread.h)
+    AC_CHECK_FUNCS(pthread_mutex_timedlock pthread_mutexattr_setpshared)
+    APR_IFALLYES(header:pthread.h func:pthread_mutex_timedlock,
+                 have_pthread_mutex_timedlock="1", have_pthread_mutex_timedlock="0")
+    AC_SUBST(have_pthread_mutex_timedlock)
+    # Some systems have setpshared and define PROCESS_SHARED, but don't 
+    # really support PROCESS_SHARED locks.  So, we must validate that we 
+    # can go through the steps without receiving some sort of system error.
+    # Linux and older versions of AIX have this problem.
+    APR_IFALLYES(header:pthread.h define:PTHREAD_PROCESS_SHARED func:pthread_mutexattr_setpshared, [
+      AC_CACHE_CHECK([for working PROCESS_SHARED locks], apr_cv_process_shared_works, [
+      AC_TRY_RUN([
+#include <sys/types.h>
+#include <pthread.h>
+        int main()
+        {
+            pthread_mutex_t mutex;
+            pthread_mutexattr_t attr;
+            if (pthread_mutexattr_init(&attr))
+                exit(1);
+            if (pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED))
+                exit(2);
+            if (pthread_mutex_init(&mutex, &attr))
+                exit(3);
+            if (pthread_mutexattr_destroy(&attr))
+                exit(4);
+            if (pthread_mutex_destroy(&mutex))
+                exit(5);
+            exit(0);
+        }], [apr_cv_process_shared_works=yes], [apr_cv_process_shared_works=no])])
+      # Override detection of pthread_mutexattr_setpshared
+      ac_cv_func_pthread_mutexattr_setpshared=$apr_cv_process_shared_works])
+
+    if test "$ac_cv_func_pthread_mutexattr_setpshared" = "yes"; then
+        APR_CHECK_PTHREAD_ROBUST_SHARED_MUTEX
+    fi
+fi
+
+# See which lock mechanisms we can support on this system.
+APR_IFALLYES(header:semaphore.h func:sem_open func:sem_close dnl
+             func:sem_unlink func:sem_post func:sem_wait,
+             hasposixser="1", hasposixser="0")
+APR_IFALLYES(func:semget func:semctl func:semop define:SEM_UNDO,
+             hassysvser="1", hassysvser="0")
+APR_IFALLYES(func:flock define:LOCK_EX, hasflockser="1", hasflockser="0")
+APR_IFALLYES(header:fcntl.h define:F_SETLK, hasfcntlser="1", hasfcntlser="0")
+# note: the current APR use of shared mutex requires /dev/zero
+APR_IFALLYES(header:pthread.h define:PTHREAD_PROCESS_SHARED dnl
+             func:pthread_mutexattr_setpshared dnl
+             file:/dev/zero,
+             hasprocpthreadser="1", hasprocpthreadser="0")
+APR_IFALLYES(header:OS.h func:create_sem, hasbeossem="1", hasbeossem="0")
+
+AC_CHECK_FUNCS(pthread_condattr_setpshared)
+APR_IFALLYES(header:pthread.h func:pthread_condattr_setpshared,
+             have_pthread_condattr_setpshared="1", have_pthread_condattr_setpshared="0")
+AC_SUBST(have_pthread_condattr_setpshared)
+
+# See which lock mechanism we'll select by default on this system.
+# The last APR_DECIDE to execute sets the default.
+# At this stage, we match the ordering in Apache 1.3
+# which is (highest to lowest): sysvsem -> fcntl -> flock.
+# POSIX semaphores and cross-process pthread mutexes are not
+# used by default since they have less desirable behaviour when
+# e.g. a process holding the mutex segfaults.
+# The BEOSSEM decision doesn't require any substitutions but is
+# included here to prevent the fcntl() branch being selected
+# from the decision making.
+APR_BEGIN_DECISION([apr_lock implementation method])
+APR_IFALLYES(func:flock define:LOCK_EX,
+            APR_DECIDE(USE_FLOCK_SERIALIZE, [4.2BSD-style flock()]))
+APR_IFALLYES(header:fcntl.h define:F_SETLK,
+            APR_DECIDE(USE_FCNTL_SERIALIZE, [SVR4-style fcntl()]))
+APR_IFALLYES(func:semget func:semctl func:semop define:SEM_UNDO,
+            APR_DECIDE(USE_SYSVSEM_SERIALIZE, [SysV IPC semget()]))
+APR_IFALLYES(header:OS.h func:create_sem func:acquire_sem func:acquire_sem_etc, 
+            APR_DECIDE(USE_BEOSSEM, [BeOS Semaphores])) 
+if test "x$apr_lock_method" != "x"; then
+    APR_DECISION_FORCE($apr_lock_method)
+fi
+APR_END_DECISION
 AC_DEFINE_UNQUOTED($ac_decision)
 
 flockser="0"
 sysvser="0"
+posixser="0"
 procpthreadser="0"
 fcntlser="0"
 case $ac_decision in
     USE_FLOCK_SERIALIZE )
         flockser="1"
         ;;
+    USE_FCNTL_SERIALIZE )
+        fcntlser="1"
+        ;;
     USE_SYSVSEM_SERIALIZE )
         sysvser="1"
         ;;
-    USE_FCNTL_SERIALIZE )
-        fcntlser="1"
+    USE_POSIXSEM_SERIALIZE )
+        posixser="1"
         ;;
     USE_PROC_PTHREAD_SERIALIZE )
         procpthreadser="1"
         ;;
+    USE_BEOSSEM )
+        beossem="1"
+        ;;
 esac
 
+if test $hasfcntlser = "1"; then
+AC_MSG_CHECKING(if fcntl returns EACCES when F_SETLK is already held)
+AC_TRY_RUN([
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+#if defined(HAVE_UNISTD_H)
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <errno.h>
+
+int fd;
+struct flock proc_mutex_lock_it = {0};
+const char *fname = "conftest.fcntl";
+
+int main()
+{
+    int rc, status;;
+    proc_mutex_lock_it.l_whence = SEEK_SET;   /* from current point */
+    proc_mutex_lock_it.l_type = F_WRLCK;      /* set exclusive/write lock */
+
+    fd = creat(fname, S_IRWXU);
+    unlink(fname);
+
+    if (rc = lockit()) {
+        exit(-1);
+    }
+
+    if (fork()) {
+        wait(&status);
+    }
+    else {
+      return(lockit());
+    }
+
+    close(fd);
+    exit(WEXITSTATUS(status) != EACCES);
+}
+
+int lockit() {
+    int rc;
+    do {
+        rc = fcntl(fd, F_SETLK, &proc_mutex_lock_it);
+    } while ( rc < 0 && errno == EINTR);
+
+    return (rc < 0) ? errno : 0;
+}], [apr_fcntl_tryacquire_eacces=1], [apr_fcntl_tryacquire_eacces=0], [apr_fcntl_tryacquire_eacces=0])
+fi
+
+if test "$apr_fcntl_tryacquire_eacces" = "1"; then
+  AC_DEFINE(FCNTL_TRYACQUIRE_EACCES, 1, [Define if fcntl returns EACCES when F_SETLK is already held])
+  AC_MSG_RESULT(yes)
+else
+  AC_MSG_RESULT(no)
+fi
+
+
+AC_SUBST(hasflockser)
+AC_SUBST(hassysvser)
+AC_SUBST(hasposixser)
+AC_SUBST(hasfcntlser)
+AC_SUBST(hasprocpthreadser)
 AC_SUBST(flockser)
 AC_SUBST(sysvser)
+AC_SUBST(posixser)
 AC_SUBST(fcntlser)
 AC_SUBST(procpthreadser)
 AC_SUBST(pthreadser)
 
-dnl #----------------------------- Checking for Shared Memory Support 
-echo $ac_n "${nl}Checking for Shared Memory Support...${nl}"
-
-# run the MM config script regardless of whether we are going to use
-# it or not.  When we have a much better idea of who is using MM, we can
-# run this on a more conditional basis.
-AC_CONFIG_SUBDIRS($config_subdirs)
-
-AC_MSG_CHECKING(Checking for Shared memory support)
-AC_ARG_ENABLE(shmem,
-  [ --enable-shmem  Enable shared memory support in APR. ],
-  [ ],
-  ac_cv_enable_shmem="mm" )
-
-sharedmem="0"
-anonymous_shm="0"
-filebased_shm="0"
-keybased_shm="0"
-if test "$ac_cv_enable_shmem" = "mm"; then
-  sharedmem="1"
-  anonymous_shm="1"
-  AC_MSG_RESULT(anonymous)
-elif test "$ac_cv_enable_shmem" = "file"; then
-  sharedmem="1"
-  filebased_shm="1"
-  AC_MSG_RESULT(file based)
-elif test "$ac_cv_enable_shmem" = "key"; then
-  sharedmem="1"
-  keybased_shm="1"
-  AC_MSG_RESULT(key based)
+AC_MSG_CHECKING(if all interprocess locks affect threads)
+if test "x$apr_process_lock_is_global" = "xyes"; then
+    proclockglobal="1"
+    AC_MSG_RESULT(yes)
+else
+    proclockglobal="0"
+    AC_MSG_RESULT(no)
+fi
+
+AC_SUBST(proclockglobal)
+
+AC_MSG_CHECKING(if POSIX sems affect threads in the same process)
+if test "x$apr_posixsem_is_global" = "xyes"; then
+  AC_DEFINE(POSIXSEM_IS_GLOBAL, 1, 
+            [Define if POSIX semaphores affect threads within the process])
+  AC_MSG_RESULT(yes)
 else
   AC_MSG_RESULT(no)
 fi
-AC_SUBST(sharedmem)
-AC_SUBST(anonymous_shm)
-AC_SUBST(filebased_shm)
-AC_SUBST(keybased_shm)
- 
-dnl #----------------------------- Checking for /dev/random 
-AC_MSG_CHECKING(for /dev/random)
 
-if test -r "/dev/random"; then
-    AC_DEFINE(DEV_RANDOM, [/dev/random])
-    AC_MSG_RESULT(/dev/random)
+AC_MSG_CHECKING(if SysV sems affect threads in the same process)
+if test "x$apr_sysvsem_is_global" = "xyes"; then
+  AC_DEFINE(SYSVSEM_IS_GLOBAL, 1,
+            [Define if SysV semaphores affect threads within the process])
+  AC_MSG_RESULT(yes)
+else
+  AC_MSG_RESULT(no)
+fi
+
+AC_MSG_CHECKING(if fcntl locks affect threads in the same process)
+if test "x$apr_fcntl_is_global" = "xyes"; then
+  AC_DEFINE(FCNTL_IS_GLOBAL, 1,
+            [Define if fcntl locks affect threads within the process])
+  AC_MSG_RESULT(yes)
+else
+  AC_MSG_RESULT(no)
+fi
+
+AC_MSG_CHECKING(if flock locks affect threads in the same process)
+if test "x$apr_flock_is_global" = "xyes"; then
+  AC_DEFINE(FLOCK_IS_GLOBAL, 1,
+            [Define if flock locks affect threads within the process])
+  AC_MSG_RESULT(yes)
+else
+  AC_MSG_RESULT(no)
+fi
+
+dnl ----------------------------- Checking for /dev/random 
+AC_CHECK_HEADERS(sys/random.h)
+AC_CHECK_FUNCS(getrandom)
+
+AC_CHECK_HEADERS(sys/syscall.h)
+AC_CHECK_HEADERS(linux/random.h)
+AC_CHECK_DECLS([SYS_getrandom], [], [], [#include <sys/syscall.h>])
+
+AC_CHECK_FUNCS(arc4random_buf)
+
+AC_MSG_CHECKING(for entropy source)
+
+why_no_rand=""
+
+AC_ARG_WITH(egd, 
+  [  --with-egd[[=DIR]]        use EGD-compatible socket],
+  [ AC_DEFINE(HAVE_EGD, 1, [Define if EGD is supported])
+    if test "$withval" = "yes"; then
+        AC_DEFINE_UNQUOTED(EGD_DEFAULT_SOCKET, ["/var/run/egd-pool","/dev/egd-pool","/etc/egd-pool","/etc/entropy"], 
+         [Define to list of paths to EGD sockets])
+    else
+        AC_DEFINE_UNQUOTED(EGD_DEFAULT_SOCKET, ["$withval"])
+    fi
+    AC_MSG_RESULT(EGD-compatible daemon)
     rand="1"
-elif test -f "/dev/urandom"; then
-    AC_DEFINE(DEV_RANDOM, [/dev/urandom])
-    AC_MSG_RESULT(/dev/urandom)
+  ])
+
+if test "$rand" != "1"; then
+  if test "$ac_cv_func_getrandom" = yes; then
+    AC_MSG_RESULT(getrandom)
     rand="1"
-else
-    AC_MSG_RESULT(not found);
-    if test "$ac_cv_lib_truerand_main" = "yes"; then
-        rand="1"
+  elif test "$ac_cv_have_decl_SYS_getrandom" = yes; then
+    AC_MSG_RESULT(SYS_getrandom)
+    rand="1"
+  fi
+fi
+
+if test "$rand" != "1"; then
+  if test "$ac_cv_func_arc4random_buf" = yes; then
+    AC_MSG_RESULT(arc4random)
+    rand="1"
+  fi
+fi
+
+if test "$rand" != "1"; then
+  AC_ARG_WITH(devrandom,
+    [  --with-devrandom[[=DEV]]  use /dev/random or compatible [[searches by default]]],
+    [ apr_devrandom="$withval" ], [ apr_devrandom="yes" ])
+
+  if test "$apr_devrandom" = "yes"; then
+    # /dev/random on OpenBSD doesn't provide random data, so
+    # prefer /dev/arandom, which does; see random(4).
+    for f in /dev/arandom /dev/urandom /dev/random; do
+      if test -r $f; then
+        apr_devrandom=$f
+        rand=1
+        break
+      fi
+    done
+  elif test "$apr_devrandom" != "no"; then
+    if test -r "$apr_devrandom"; then
+      rand="1"
     else
-        rand="0"
+      AC_ERROR([$apr_devrandom not found or unreadable.])
     fi
+  fi
+
+  if test "$rand" = "1"; then
+    case $host in
+      *os390)
+        if test $os_version -lt 1700; then
+          rand="0"
+          why_no_rand=" ($apr_devrandom unusable on z/OS before V1R7)"
+        fi
+        ;;
+    esac
+  fi
+
+  if test "$rand" = "1"; then
+    AC_DEFINE_UNQUOTED(DEV_RANDOM, ["$apr_devrandom"], [Define to path of random device])
+    AC_MSG_RESULT([$apr_devrandom])
+  fi
+fi
+
+if test "$rand" != "1"; then
+    case $host in
+        # we have built in support for OS/2
+        *-os2*)
+            AC_MSG_RESULT([Using OS/2 builtin random])
+            rand="1"
+            ;;
+        *)
+            if test "$rand" != "1"; then
+              if test "$ac_cv_lib_truerand_main" = "yes"; then
+                AC_DEFINE(HAVE_TRUERAND, 1, [Define if truerand is supported])
+                AC_MSG_RESULT(truerand)
+                rand="1"
+              else
+                AC_MSG_RESULT(not found$why_no_rand)
+                rand="0"
+              fi
+            fi
+            ;;
+    esac
 fi
 
 AC_SUBST(rand)
-dnl #----------------------------- Checking for Time Support 
-echo $ac_n "${nl}Checking for Time Support...${nl}"
-AC_CACHE_CHECK([for tm_gmtoff in struct tm], ac_cv_struct_tm_gmtoff,
-[AC_TRY_COMPILE([#include <sys/types.h>
-#include <$ac_cv_struct_tm>], [struct tm tm; tm.tm_gmtoff;],
-  ac_cv_struct_tm_gmtoff=yes, ac_cv_struct_tm_gmtoff=no)])
 
-if test "$ac_cv_struct_tm_gmtoff" = "yes"; then
-    AC_DEFINE(HAVE_GMTOFF)
+dnl ----------------------------- Checking for File Info Support 
+AC_MSG_NOTICE([])
+AC_MSG_NOTICE([Checking for File Info Support...])
+AC_CHECK_MEMBERS([struct stat.st_blocks, struct stat.st_atimensec,
+struct stat.st_ctimensec, struct stat.st_mtimensec, struct stat.st_atim.tv_nsec,
+struct stat.st_ctim.tv_nsec, struct stat.st_mtim.tv_nsec,
+struct stat.st_atime_n, struct stat.st_ctime_n, struct stat.st_mtime_n],,,[
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif])
+
+APR_CHECK_DIRENT_INODE
+APR_CHECK_DIRENT_TYPE
+
+dnl ----------------------------- Checking for UUID Support 
+AC_MSG_NOTICE([])
+AC_MSG_NOTICE([Checking for OS UUID Support...])
+
+AC_CHECK_HEADERS(uuid.h uuid/uuid.h sys/uuid.h, break)
+
+apr_revert_save_LIBS=$LIBS
+
+# Prefer the flavor(s) that live in libc;
+AC_SEARCH_LIBS(uuid_create, uuid)
+AC_SEARCH_LIBS(uuid_generate, uuid)
+if test "$ac_cv_search_uuid_create" = "none required" -o \
+        "$ac_cv_search_uuid_generate" = "none required"; then
+ LIBS=$apr_revert_save_LIBS
 fi
 
-dnl #----------------------------- Checking for Networking Support 
-echo $ac_n "${nl}Checking for Networking support..."
-AC_MSG_CHECKING(looking for in_addr in netinet/in.h)
-AC_TRY_COMPILE([
-#include <netinet/in.h>
-],[
-struct in_addr arg;
-arg.s_addr = htonl(INADDR_ANY);
-], [ have_in_addr="1" 
-msg=yes ] , [ have_in_addr="0"
-msg=no ])
-AC_MSG_RESULT([$msg])
+AC_CHECK_FUNCS(uuid_create uuid_generate)
+
+AC_CACHE_CHECK([for os uuid usability], [apr_cv_osuuid], [
+# Ensure this test closely mirrors misc/unix/rand.c!
+uuid_includes="
+#if defined(HAVE_SYS_TYPES_H)
+#include <sys/types.h>
+#endif
+#if defined(HAVE_UNISTD_H)
+#include <unistd.h>
+#endif
+#if defined(HAVE_UUID_H)
+#include <uuid.h>
+#elif defined(HAVE_UUID_UUID_H)
+#include <uuid/uuid.h>
+#elif defined(HAVE_SYS_UUID_H)
+#include <sys/uuid.h>
+#endif
+"
+ apr_cv_osuuid=no
+ if test $ac_cv_func_uuid_create = yes; then
+  AC_TRY_LINK([$uuid_includes], [
+    uuid_t g;
+    uint32_t s;
+    uuid_create(&g, &s);
+    if (s == uuid_s_ok) s = 0;
+  ], [apr_cv_osuuid=yes], [apr_cv_func_uuid_create=no])
+ fi
+ if test $ac_cv_func_uuid_generate = yes; then
+  AC_TRY_LINK([$uuid_includes], [
+    uuid_t g;
+    uuid_generate(g);
+  ], [apr_cv_osuuid=yes], [apr_cv_func_uuid_generate=no])
+ fi 
+])
+
+if test $apr_cv_osuuid = yes; then
+  osuuid="1"
+else
+  osuuid="0"
+  LIBS=$apr_revert_save_LIBS
+fi
+AC_SUBST(osuuid)
+
+
+dnl ----------------------------- Checking for Time Support 
+AC_MSG_NOTICE([])
+AC_MSG_NOTICE([Checking for Time Support...])
+
+AC_CHECK_MEMBERS([struct tm.tm_gmtoff, struct tm.__tm_gmtoff],,,[
+#include <sys/types.h>
+#include <time.h>])
+
+dnl ----------------------------- Checking for Networking Support 
+AC_MSG_NOTICE([])
+AC_MSG_NOTICE([Checking for Networking support...])
+APR_TYPE_IN_ADDR
+if test "$ac_cv_type_in_addr" = "yes"; then
+  have_in_addr="1"
+else
+  have_in_addr="0"
+fi
+
+AC_MSG_CHECKING([if fd == socket on this platform])
+if test "x$file_as_socket" != "x0" ; then
+    file_as_socket="1";
+    AC_MSG_RESULT([yes])
+else
+    AC_MSG_RESULT([no])
+fi
 
 AC_SUBST(have_in_addr)
+AC_SUBST(file_as_socket)
+
+if test "$ac_cv_func_poll $file_as_socket" = "yes 1"; then
+    AC_DEFINE(WAITIO_USES_POLL, 1,
+              [Define if apr_wait_for_io_or_timeout() uses poll(2)])
+fi
+
+# Check the types only if we have gethostbyname_r
+if test "$ac_cv_func_gethostbyname_r" = "yes"; then
+    APR_CHECK_GETHOSTBYNAME_R_STYLE
+fi
+
+# Check the types only if we have getservbyname_r
+if test "$ac_cv_func_getservbyname_r" = "yes"; then
+    APR_CHECK_GETSERVBYNAME_R_STYLE
+fi
+
+APR_CHECK_TCP_NODELAY_INHERITED
+APR_CHECK_O_NONBLOCK_INHERITED
+APR_CHECK_TCP_NODELAY_WITH_CORK
+
+# Look for a way of corking TCP...
+APR_CHECK_DEFINE(TCP_CORK, netinet/tcp.h)
+APR_CHECK_DEFINE(TCP_NOPUSH, netinet/tcp.h)
+apr_tcp_nopush_flag="0"
+have_corkable_tcp="0"
+if test "x$ac_cv_define_TCP_CORK" = "xyes"; then
+    apr_tcp_nopush_flag="TCP_CORK"
+    have_corkable_tcp="1"
+else
+    case $host in
+        *linux*)
+            AC_EGREP_CPP(yes,[
+#include <linux/socket.h>
+#ifdef TCP_CORK
+yes
+#endif
+            ],[
+                apr_tcp_nopush_flag="3"
+                have_corkable_tcp="1"
+            ])
+            ;;
+        *)
+            ;;
+    esac
+fi
+if test "x$ac_cv_define_TCP_NOPUSH" = "xyes"; then
+    apr_tcp_nopush_flag="TCP_NOPUSH"
+    have_corkable_tcp="1"
+fi
+
+APR_CHECK_DEFINE(SO_ACCEPTFILTER, sys/socket.h)
+if test "x$ac_cv_define_SO_ACCEPTFILTER" = "xyes"; then
+    acceptfilter="1"
+else
+    acceptfilter="0"
+fi
+
+APR_CHECK_SCTP
+APR_CHECK_MCAST
+
+AC_SUBST(apr_tcp_nopush_flag)
+AC_SUBST(have_corkable_tcp)
+AC_SUBST(acceptfilter)
+AC_SUBST(have_sctp)
 
-dnl #----------------------------- Construct the files
+AC_CHECK_FUNCS(set_h_errno)
+
+AC_MSG_NOTICE([])
+AC_MSG_NOTICE([Checking for IPv6 Networking support...])
+dnl Start of checking for IPv6 support...
+
+AC_ARG_ENABLE(ipv6,
+  [  --disable-ipv6          Disable IPv6 support in APR.],
+  [ if test "$enableval" = "no"; then
+        user_disabled_ipv6=1
+    fi ],
+  [ user_disabled_ipv6=0 ] )
+
+case $host in
+  *)
+    broken_ipv6=0
+esac
+
+AC_SEARCH_LIBS(getaddrinfo, socket inet6)
+AC_SEARCH_LIBS(gai_strerror, socket inet6)
+AC_SEARCH_LIBS(getnameinfo, socket inet6)
+AC_CHECK_FUNCS(gai_strerror if_nametoindex if_indextoname)
+APR_CHECK_WORKING_GETADDRINFO
+APR_CHECK_NEGATIVE_EAI
+APR_CHECK_WORKING_GETNAMEINFO
+APR_CHECK_SOCKADDR_IN6
+APR_CHECK_SOCKADDR_STORAGE
+APR_CHECK_SOCKADDR_UN
+
+have_ipv6="0"
+if test "$user_disabled_ipv6" = 1; then
+    ipv6_result="no -- disabled by user"
+else
+    if test "x$broken_ipv6" = "x0"; then
+        if test "x$have_sockaddr_in6" = "x1"; then
+            if test "x$ac_cv_working_getaddrinfo" = "xyes"; then
+                if test "x$ac_cv_working_getnameinfo" = "xyes"; then
+                    APR_CHECK_GETADDRINFO_ADDRCONFIG
+                    have_ipv6="1"
+                    ipv6_result="yes"
+                else
+                    ipv6_result="no -- no getnameinfo"
+                fi
+            else
+                ipv6_result="no -- no working getaddrinfo"
+            fi
+        else
+            ipv6_result="no -- no sockaddr_in6"
+        fi
+    else
+        ipv6_result="no -- the platform has known problems supporting IPv6"
+    fi
+fi
+
+AC_MSG_CHECKING(if APR supports IPv6)
+AC_MSG_RESULT($ipv6_result)
+
+AC_SUBST(have_ipv6)
+
+# hstrerror is only needed if IPv6 is not enabled,
+# so getaddrinfo/gai_strerror are not used.
+if test $have_ipv6 = 0; then
+  AC_SEARCH_LIBS(hstrerror, resolv,
+    [AC_DEFINE(HAVE_HSTRERROR, 1, [Define if hstrerror is present])])
+fi
+
+dnl Check for langinfo support
+
+AC_CHECK_HEADERS(langinfo.h)
+AC_CHECK_FUNCS(nl_langinfo)
+
+dnl ------------------------------ Defaults for some platform nuances
+
+dnl Do we have a Win32-centric Unicode FS?
+APR_SETIFNULL(have_unicode_fs, [0])
+AC_SUBST(have_unicode_fs)
+
+APR_SETIFNULL(apr_has_xthread_files, [0])
+AC_SUBST(apr_has_xthread_files)
+
+APR_SETIFNULL(apr_procattr_user_set_requires_password, [0])
+AC_SUBST(apr_procattr_user_set_requires_password)
+
+APR_SETIFNULL(apr_thread_func, [])
+AC_SUBST(apr_thread_func)
+
+APR_SETIFNULL(apr_has_user, [1])
+AC_SUBST(apr_has_user)
+
+dnl ------------------------------ APR-util stuff 
+
+APU_PRELOAD
+
+dnl Find crypto libraries
+APU_CHECK_CRYPTO
+
+dnl Find DBM and DBD backends to use.
+APU_CHECK_DBM
+APU_CHECK_DBD
+APU_CHECK_DBD_MYSQL
+APU_CHECK_DBD_SQLITE3
+APU_CHECK_DBD_SQLITE2
+APU_CHECK_DBD_ORACLE
+APU_CHECK_DBD_ODBC
+
+dnl select an XML parser
+APU_FIND_XML
+
+dnl Find iconv implementations
+APU_FIND_ICONV
+
+dnl Enable DSO build; must be last:
+APR_MODULAR_DSO
+
+AC_SEARCH_LIBS(crypt, crypt ufc)
+AC_MSG_CHECKING(if system crypt() function is threadsafe)
+if test "x$apu_crypt_threadsafe" = "x1"; then
+  AC_DEFINE(APU_CRYPT_THREADSAFE, 1, [Define if the system crypt() function is threadsafe])
+  msg="yes"
+else
+  msg="no"
+fi
+AC_MSG_RESULT([$msg])
+
+AC_CHECK_FUNCS(crypt_r, [ crypt_r="1" ], [ crypt_r="0" ])
+if test "$crypt_r" = "1"; then
+  APU_CHECK_CRYPT_R_STYLE
+fi
+
+APRUTIL_LIBNAME="aprutil${libsuffix}"
+AC_SUBST(APRUTIL_LIBNAME)
+
+# Set up destination directory for DSOs.
+APR_DSO_LIBDIR="\${libdir}/apr-${APR_MAJOR_VERSION}"
+# Set APU_HAVE_MODULES appropriately for the Makefile
+if test -n "$APR_DSO_MODULES"; then 
+   APR_HAVE_MODULES=yes
+else
+   APR_HAVE_MODULES=no
+fi
+APR_EXPAND_VAR(abs_dso_libdir, $APR_DSO_LIBDIR)
+AC_DEFINE_UNQUOTED([APR_DSO_LIBDIR], ["$abs_dso_libdir"],
+                   [Define to be absolute path to DSO directory])
+AC_SUBST(APR_HAVE_MODULES)
+AC_SUBST(APR_DSO_LIBDIR)
+AC_SUBST(APR_DSO_MODULES)
+AC_SUBST(EXTRA_OBJECTS)
+
+dnl XXX FIXME; used for -lexpat, -liconv etc?
+AC_SUBST(APRUTIL_EXPORT_LIBS)
+
+dnl
+dnl Prep all the flags and stuff for compilation and export to other builds
+dnl
+APR_ADDTO(LIBS, [$APRUTIL_LIBS])
+
+AC_SUBST(LDFLAGS)
+
+
+
+dnl ----------------------------- Finalize the variables
+
+AC_MSG_NOTICE([])
+AC_MSG_NOTICE([Restore user-defined environment settings...])
+
+APR_RESTORE_THE_ENVIRONMENT(CPPFLAGS, EXTRA_)
+APR_RESTORE_THE_ENVIRONMENT(CFLAGS, EXTRA_)
+APR_RESTORE_THE_ENVIRONMENT(LDFLAGS, EXTRA_)
+APR_RESTORE_THE_ENVIRONMENT(LIBS, EXTRA_)
+APR_RESTORE_THE_ENVIRONMENT(INCLUDES, EXTRA_)
+AC_SUBST(NOTEST_CPPFLAGS)
+AC_SUBST(NOTEST_CFLAGS)
+AC_SUBST(NOTEST_LDFLAGS)
+AC_SUBST(NOTEST_LIBS)
+AC_SUBST(NOTEST_INCLUDES)
+
+dnl ----------------------------- Construct the files
+
+AC_SUBST(INTERNAL_CPPFLAGS)
 AC_SUBST(LDLIBS)
-AC_SUBST(OPTIM)
-AC_SUBST(RANLIB)
+AC_SUBST(INCLUDES)
 AC_SUBST(AR)
 AC_SUBST(RM)
 AC_SUBST(OSDIR)
 AC_SUBST(DEFAULT_OSDIR)
-AC_SUBST(LIBPREFIX)
 AC_SUBST(EXEEXT)
+AC_SUBST(LIBTOOL_LIBS)
+
+# Use -no-install or -no-fast-install to link the test 
+# programs on all platforms but Darwin, where it would cause
+# the programs to be linked against installed versions of
+# libapr instead of those just built.
+case $host in
+    *-apple-darwin*)
+        LT_NO_INSTALL=""
+        ;;
+    *-mingw*)
+        LT_NO_INSTALL="-no-fast-install"
+        ;;
+    *)
+        LT_NO_INSTALL="-no-install"
+        ;;
+esac
+AC_SUBST(LT_NO_INSTALL)
 
-echo "Construct Makefiles and header files."
-MAKEFILE1="Makefile lib/Makefile "
-SUBDIRS="lib "
-for dir in $MODULES
-do
-    if test -f $dir/$OSDIR/Makefile.in; then
-        MAKEFILE2="$MAKEFILE2 $dir/$OSDIR/Makefile "
-        SUBDIRS="$SUBDIRS $dir/$OSDIR "
+#
+# BSD/OS (BSDi) needs to use a different include syntax in the Makefiles
+#
+case $host in
+*bsdi*)
+    # Check whether they've installed GNU make
+    if make --version > /dev/null 2>&1; then 
+	INCLUDE_RULES="include $apr_buildout/apr_rules.mk"
+	INCLUDE_OUTPUTS="include $apr_srcdir/build-outputs.mk"
     else
-        MAKEFILE2="$MAKEFILE2 $dir/$DEFAULT_OSDIR/Makefile "
-        SUBDIRS="$SUBDIRS $dir/$DEFAULT_OSDIR "
+	# BSDi make
+	INCLUDE_RULES=".include \"$apr_buildout/apr_rules.mk\""
+	INCLUDE_OUTPUTS=".include \"$apr_srcdir/build-outputs.mk\""
     fi
+    ;;
+*)
+    INCLUDE_RULES="include $apr_buildout/apr_rules.mk"
+    INCLUDE_OUTPUTS="include $apr_srcdir/build-outputs.mk"
+    ;;
+esac
+AC_SUBST(INCLUDE_RULES)
+AC_SUBST(INCLUDE_OUTPUTS)
+
+AC_CONFIG_FILES([Makefile
+                 include/apr.h
+                 build/apr_rules.mk
+                 build/pkg/pkginfo
+                 apr-$APR_MAJOR_VERSION-config:apr-config.in
+                 apr.pc])
+
+if test -d $srcdir/test; then
+   AC_CONFIG_FILES([test/Makefile test/internal/Makefile])
+fi
+
+AC_CONFIG_FILES([include/private/apu_select_dbm.h
+                 include/apu_want.h])
+
+dir=include/arch/unix
+test -d $dir || $MKDIR $dir
+
+AC_CONFIG_COMMANDS([default], [
+# Commands run at the end of config.status:
+for i in $APR_SAVE_HEADERS; do
+  if cmp -s $i $i.save 2>/dev/null; then
+    mv $i.save $i
+    AC_MSG_NOTICE([$i is unchanged])
+  fi
+  rm -f $i.save
 done
+chmod +x apr-$APR_MAJOR_VERSION-config
+],[
+dnl This section is expanded by configure UNQUOTED so variable 
+dnl references must be backslash-escaped as necessary.
 
-MAKEFILE3="test/Makefile"
-AC_SUBST(SUBDIRS)
-AC_SUBST(MODULES)
-AC_OUTPUT($MAKEFILE1 $MAKEFILE2 $MAKEFILE3 include/apr.h)
+# Commands run at the beginning of config.status:
+APR_SAVE_HEADERS="include/apr.h include/arch/unix/apr_private.h"
+APR_MAJOR_VERSION=$APR_MAJOR_VERSION
+APR_PLATFORM=$host
+
+for apri in \${APR_SAVE_HEADERS}; do
+  test -r \${apri} && mv \${apri} \${apri}.save
+done
+])
 
+AC_OUTPUT
diff --git a/crypto/apr_crypto.c b/crypto/apr_crypto.c
new file mode 100644
index 00000000000..3b50ca531f2
--- /dev/null
+++ b/crypto/apr_crypto.c
@@ -0,0 +1,602 @@
+/* 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 <ctype.h>
+#include <stdio.h>
+
+#include "apu.h"
+#include "apr_private.h"
+#include "apr_pools.h"
+#include "apr_dso.h"
+#include "apr_strings.h"
+#include "apr_hash.h"
+#include "apr_thread_mutex.h"
+#include "apr_lib.h"
+
+#if APU_HAVE_CRYPTO
+
+#include "apu_internal.h"
+#include "apr_crypto_internal.h"
+#include "apr_crypto.h"
+#include "apr_version.h"
+
+static apr_hash_t *drivers = NULL;
+
+#define ERROR_SIZE 1024
+
+#define CLEANUP_CAST (apr_status_t (*)(void*))
+
+APR_TYPEDEF_STRUCT(apr_crypto_t,
+    apr_pool_t *pool;
+    apr_crypto_driver_t *provider;
+)
+
+APR_TYPEDEF_STRUCT(apr_crypto_key_t,
+    apr_pool_t *pool;
+    apr_crypto_driver_t *provider;
+    const apr_crypto_t *f;
+)
+
+APR_TYPEDEF_STRUCT(apr_crypto_block_t,
+    apr_pool_t *pool;
+    apr_crypto_driver_t *provider;
+    const apr_crypto_t *f;
+)
+
+typedef struct apr_crypto_clear_t {
+    void *buffer;
+    apr_size_t size;
+} apr_crypto_clear_t;
+
+#if !APR_HAVE_MODULAR_DSO
+#define DRIVER_LOAD(name,driver_name,pool,params,rv,result) \
+    {   \
+        extern const apr_crypto_driver_t driver_name; \
+        apr_hash_set(drivers,name,APR_HASH_KEY_STRING,&driver_name); \
+        if (driver_name.init) {     \
+            rv = driver_name.init(pool, params, result); \
+        }  \
+        *driver = &driver_name; \
+    }
+#endif
+
+static apr_status_t apr_crypto_term(void *ptr)
+{
+    /* set drivers to NULL so init can work again */
+    drivers = NULL;
+
+    /* Everything else we need is handled by cleanups registered
+     * when we created mutexes and loaded DSOs
+     */
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_crypto_init(apr_pool_t *pool)
+{
+    apr_status_t ret = APR_SUCCESS;
+    apr_pool_t *parent;
+
+    if (drivers != NULL) {
+        return APR_SUCCESS;
+    }
+
+    /* Top level pool scope, need process-scope lifetime */
+    for (parent = apr_pool_parent_get(pool);
+         parent && parent != pool;
+         parent = apr_pool_parent_get(pool))
+        pool = parent;
+#if APR_HAVE_MODULAR_DSO
+    /* deprecate in 2.0 - permit implicit initialization */
+    apu_dso_init(pool);
+#endif
+    drivers = apr_hash_make(pool);
+
+    apr_pool_cleanup_register(pool, NULL, apr_crypto_term,
+            apr_pool_cleanup_null);
+
+    return ret;
+}
+
+static apr_status_t crypto_clear(void *ptr)
+{
+    apr_crypto_clear_t *clear = (apr_crypto_clear_t *)ptr;
+
+    apr_crypto_memzero(clear->buffer, clear->size);
+    clear->buffer = NULL;
+    clear->size = 0;
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_crypto_clear(apr_pool_t *pool,
+        void *buffer, apr_size_t size)
+{
+    apr_crypto_clear_t *clear = apr_palloc(pool, sizeof(apr_crypto_clear_t));
+
+    clear->buffer = buffer;
+    clear->size = size;
+
+    apr_pool_cleanup_register(pool, clear, crypto_clear,
+            apr_pool_cleanup_null);
+
+    return APR_SUCCESS;
+}
+
+#if defined(HAVE_WEAK_SYMBOLS)
+void apr__memzero_explicit(void *buffer, apr_size_t size);
+
+__attribute__ ((weak))
+void apr__memzero_explicit(void *buffer, apr_size_t size)
+{
+    memset(buffer, 0, size);
+}
+#endif
+
+APR_DECLARE(apr_status_t) apr_crypto_memzero(void *buffer, apr_size_t size)
+{
+#if defined(WIN32)
+    SecureZeroMemory(buffer, size);
+#elif defined(HAVE_MEMSET_S)
+    if (size) {
+        return memset_s(buffer, (rsize_t)size, 0, (rsize_t)size);
+    }
+#elif defined(HAVE_EXPLICIT_BZERO)
+    explicit_bzero(buffer, size);
+#elif defined(HAVE_WEAK_SYMBOLS)
+    apr__memzero_explicit(buffer, size);
+#else
+    apr_size_t i;
+    volatile unsigned char *volatile ptr = buffer;
+    for (i = 0; i < size; ++i) {
+        ptr[i] = 0;
+    }
+#endif
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(int) apr_crypto_equals(const void *buf1, const void *buf2,
+                                   apr_size_t size)
+{
+    const unsigned char *p1 = buf1;
+    const unsigned char *p2 = buf2;
+    unsigned char diff = 0;
+    apr_size_t i;
+
+    for (i = 0; i < size; ++i) {
+        diff |= p1[i] ^ p2[i];
+    }
+
+    return 1 & ((diff - 1) >> 8);
+}
+
+APR_DECLARE(apr_status_t) apr_crypto_get_driver(
+        const apr_crypto_driver_t **driver, const char *name,
+        const char *params, const apu_err_t **result, apr_pool_t *pool)
+{
+#if APR_HAVE_MODULAR_DSO
+    char modname[32];
+    char symname[34];
+    apr_dso_handle_t *dso;
+    apr_dso_handle_sym_t symbol;
+#endif
+    apr_status_t rv;
+
+    if (result) {
+        *result = NULL; /* until further notice */
+    }
+
+#if APR_HAVE_MODULAR_DSO
+    rv = apu_dso_mutex_lock();
+    if (rv) {
+        return rv;
+    }
+#endif
+    *driver = apr_hash_get(drivers, name, APR_HASH_KEY_STRING);
+    if (*driver) {
+#if APR_HAVE_MODULAR_DSO
+        apu_dso_mutex_unlock();
+#endif
+        return APR_SUCCESS;
+    }
+
+#if APR_HAVE_MODULAR_DSO
+    /* The driver DSO must have exactly the same lifetime as the
+     * drivers hash table; ignore the passed-in pool */
+    pool = apr_hash_pool_get(drivers);
+
+#if defined(NETWARE)
+    apr_snprintf(modname, sizeof(modname), "crypto%s.nlm", name);
+#elif defined(WIN32) || defined(__CYGWIN__)
+    apr_snprintf(modname, sizeof(modname),
+            "apr_crypto_%s-" APR_STRINGIFY(APR_MAJOR_VERSION) ".dll", name);
+#else
+    apr_snprintf(modname, sizeof(modname),
+            "apr_crypto_%s-" APR_STRINGIFY(APR_MAJOR_VERSION) ".so", name);
+#endif
+    apr_snprintf(symname, sizeof(symname), "apr_crypto_%s_driver", name);
+    rv = apu_dso_load(&dso, &symbol, modname, symname, pool);
+    if (rv == APR_SUCCESS || rv == APR_EINIT) { /* previously loaded?!? */
+        apr_crypto_driver_t *d = symbol;
+        rv = APR_SUCCESS;
+        if (d->init) {
+            rv = d->init(pool, params, result);
+        }
+        if (APR_SUCCESS == rv) {
+            *driver = symbol;
+            name = apr_pstrdup(pool, name);
+            apr_hash_set(drivers, name, APR_HASH_KEY_STRING, *driver);
+        }
+    }
+    apu_dso_mutex_unlock();
+
+    if (APR_SUCCESS != rv && result && !*result) {
+        char *buffer = apr_pcalloc(pool, ERROR_SIZE);
+        apu_err_t *err = apr_pcalloc(pool, sizeof(apu_err_t));
+        if (err && buffer) {
+            apr_dso_error(dso, buffer, ERROR_SIZE - 1);
+            err->msg = buffer;
+            err->reason = apr_pstrdup(pool, modname);
+            *result = err;
+        }
+    }
+
+#else /* not builtin and !APR_HAS_DSO => not implemented */
+    rv = APR_ENOTIMPL;
+
+    /* Load statically-linked drivers: */
+#if APU_HAVE_OPENSSL
+    if (name[0] == 'o' && !strcmp(name, "openssl")) {
+        DRIVER_LOAD("openssl", apr_crypto_openssl_driver, pool, params, rv, result);
+    }
+#endif
+#if APU_HAVE_NSS
+    if (name[0] == 'n' && !strcmp(name, "nss")) {
+        DRIVER_LOAD("nss", apr_crypto_nss_driver, pool, params, rv, result);
+    }
+#endif
+#if APU_HAVE_COMMONCRYPTO
+    if (name[0] == 'c' && !strcmp(name, "commoncrypto")) {
+        DRIVER_LOAD("commoncrypto", apr_crypto_commoncrypto_driver, pool, params, rv, result);
+    }
+#endif
+#if APU_HAVE_MSCAPI
+    if (name[0] == 'm' && !strcmp(name, "mscapi")) {
+        DRIVER_LOAD("mscapi", apr_crypto_mscapi_driver, pool, params, rv, result);
+    }
+#endif
+#if APU_HAVE_MSCNG
+    if (name[0] == 'm' && !strcmp(name, "mscng")) {
+        DRIVER_LOAD("mscng", apr_crypto_mscng_driver, pool, params, rv, result);
+    }
+#endif
+
+#endif
+
+    return rv;
+}
+
+/**
+ * @brief Return the name of the driver.
+ *
+ * @param driver - The driver in use.
+ * @return The name of the driver.
+ */
+APR_DECLARE(const char *)apr_crypto_driver_name(
+        const apr_crypto_driver_t *driver)
+{
+    return driver->name;
+}
+
+/**
+ * @brief Get the result of the last operation on a context. If the result
+ *        is NULL, the operation was successful.
+ * @param result - the result structure
+ * @param f - context pointer
+ * @return APR_SUCCESS for success
+ */
+APR_DECLARE(apr_status_t) apr_crypto_error(const apu_err_t **result,
+        const apr_crypto_t *f)
+{
+    return f->provider->error(result, f);
+}
+
+/**
+ * @brief Create a context for supporting encryption. Keys, certificates,
+ *        algorithms and other parameters will be set per context. More than
+ *        one context can be created at one time. A cleanup will be automatically
+ *        registered with the given pool to guarantee a graceful shutdown.
+ * @param f - context pointer will be written here
+ * @param driver - driver to use
+ * @param params - array of key parameters
+ * @param pool - process pool
+ * @return APR_ENOENGINE when the engine specified does not exist. APR_EINITENGINE
+ * if the engine cannot be initialised.
+ * @remarks NSS: currently no params are supported.
+ * @remarks OpenSSL: the params can have "engine" as a key, followed by an equal
+ *  sign and a value.
+ */
+APR_DECLARE(apr_status_t) apr_crypto_make(apr_crypto_t **f,
+        const apr_crypto_driver_t *driver, const char *params, apr_pool_t *pool)
+{
+    return driver->make(f, driver, params, pool);
+}
+
+/**
+ * @brief Get a hash table of key types, keyed by the name of the type against
+ * a pointer to apr_crypto_block_key_type_t, which in turn begins with an
+ * integer.
+ *
+ * @param types - hashtable of key types keyed to constants.
+ * @param f - encryption context
+ * @return APR_SUCCESS for success
+ */
+APR_DECLARE(apr_status_t) apr_crypto_get_block_key_types(apr_hash_t **types,
+        const apr_crypto_t *f)
+{
+    return f->provider->get_block_key_types(types, f);
+}
+
+/**
+ * @brief Get a hash table of key modes, keyed by the name of the mode against
+ * a pointer to apr_crypto_block_key_mode_t, which in turn begins with an
+ * integer.
+ *
+ * @param modes - hashtable of key modes keyed to constants.
+ * @param f - encryption context
+ * @return APR_SUCCESS for success
+ */
+APR_DECLARE(apr_status_t) apr_crypto_get_block_key_modes(apr_hash_t **modes,
+        const apr_crypto_t *f)
+{
+    return f->provider->get_block_key_modes(modes, f);
+}
+
+/**
+ * @brief Create a key from the provided secret or passphrase. The key is cleaned
+ *        up when the context is cleaned, and may be reused with multiple encryption
+ *        or decryption operations.
+ * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
+ *       *key is not NULL, *key must point at a previously created structure.
+ * @param key The key returned, see note.
+ * @param rec The key record, from which the key will be derived.
+ * @param f The context to use.
+ * @param p The pool to use.
+ * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
+ *         error occurred while generating the key. APR_ENOCIPHER if the type or mode
+ *         is not supported by the particular backend. APR_EKEYTYPE if the key type is
+ *         not known. APR_EPADDING if padding was requested but is not supported.
+ *         APR_ENOTIMPL if not implemented.
+ */
+APR_DECLARE(apr_status_t) apr_crypto_key(apr_crypto_key_t **key,
+        const apr_crypto_key_rec_t *rec, const apr_crypto_t *f, apr_pool_t *p)
+{
+    return f->provider->key(key, rec, f, p);
+}
+
+/**
+ * @brief Create a key from the given passphrase. By default, the PBKDF2
+ *        algorithm is used to generate the key from the passphrase. It is expected
+ *        that the same pass phrase will generate the same key, regardless of the
+ *        backend crypto platform used. The key is cleaned up when the context
+ *        is cleaned, and may be reused with multiple encryption or decryption
+ *        operations.
+ * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
+ *       *key is not NULL, *key must point at a previously created structure.
+ * @param key The key returned, see note.
+ * @param ivSize The size of the initialisation vector will be returned, based
+ *               on whether an IV is relevant for this type of crypto.
+ * @param pass The passphrase to use.
+ * @param passLen The passphrase length in bytes
+ * @param salt The salt to use.
+ * @param saltLen The salt length in bytes
+ * @param type 3DES_192, AES_128, AES_192, AES_256.
+ * @param mode Electronic Code Book / Cipher Block Chaining.
+ * @param doPad Pad if necessary.
+ * @param iterations Number of iterations to use in algorithm
+ * @param f The context to use.
+ * @param p The pool to use.
+ * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
+ *         error occurred while generating the key. APR_ENOCIPHER if the type or mode
+ *         is not supported by the particular backend. APR_EKEYTYPE if the key type is
+ *         not known. APR_EPADDING if padding was requested but is not supported.
+ *         APR_ENOTIMPL if not implemented.
+ */
+APR_DECLARE(apr_status_t) apr_crypto_passphrase(apr_crypto_key_t **key,
+        apr_size_t *ivSize, const char *pass, apr_size_t passLen,
+        const unsigned char * salt, apr_size_t saltLen,
+        const apr_crypto_block_key_type_e type,
+        const apr_crypto_block_key_mode_e mode, const int doPad,
+        const int iterations, const apr_crypto_t *f, apr_pool_t *p)
+{
+    return f->provider->passphrase(key, ivSize, pass, passLen, salt, saltLen,
+            type, mode, doPad, iterations, f, p);
+}
+
+/**
+ * @brief Initialise a context for encrypting arbitrary data using the given key.
+ * @note If *ctx is NULL, a apr_crypto_block_t will be created from a pool. If
+ *       *ctx is not NULL, *ctx must point at a previously created structure.
+ * @param ctx The block context returned, see note.
+ * @param iv Optional initialisation vector. If the buffer pointed to is NULL,
+ *           an IV will be created at random, in space allocated from the pool.
+ *           If the buffer pointed to is not NULL, the IV in the buffer will be
+ *           used.
+ * @param key The key structure to use.
+ * @param blockSize The block size of the cipher.
+ * @param p The pool to use.
+ * @return Returns APR_ENOIV if an initialisation vector is required but not specified.
+ *         Returns APR_EINIT if the backend failed to initialise the context. Returns
+ *         APR_ENOTIMPL if not implemented.
+ */
+APR_DECLARE(apr_status_t) apr_crypto_block_encrypt_init(
+        apr_crypto_block_t **ctx, const unsigned char **iv,
+        const apr_crypto_key_t *key, apr_size_t *blockSize, apr_pool_t *p)
+{
+    return key->provider->block_encrypt_init(ctx, iv, key, blockSize, p);
+}
+
+/**
+ * @brief Encrypt data provided by in, write it to out.
+ * @note The number of bytes written will be written to outlen. If
+ *       out is NULL, outlen will contain the maximum size of the
+ *       buffer needed to hold the data, including any data
+ *       generated by apr_crypto_block_encrypt_finish below. If *out points
+ *       to NULL, a buffer sufficiently large will be created from
+ *       the pool provided. If *out points to a not-NULL value, this
+ *       value will be used as a buffer instead.
+ * @param out Address of a buffer to which data will be written,
+ *        see note.
+ * @param outlen Length of the output will be written here.
+ * @param in Address of the buffer to read.
+ * @param inlen Length of the buffer to read.
+ * @param ctx The block context to use.
+ * @return APR_ECRYPT if an error occurred. Returns APR_ENOTIMPL if
+ *         not implemented.
+ */
+APR_DECLARE(apr_status_t) apr_crypto_block_encrypt(unsigned char **out,
+        apr_size_t *outlen, const unsigned char *in, apr_size_t inlen,
+        apr_crypto_block_t *ctx)
+{
+    return ctx->provider->block_encrypt(out, outlen, in, inlen, ctx);
+}
+
+/**
+ * @brief Encrypt final data block, write it to out.
+ * @note If necessary the final block will be written out after being
+ *       padded. Typically the final block will be written to the
+ *       same buffer used by apr_crypto_block_encrypt, offset by the
+ *       number of bytes returned as actually written by the
+ *       apr_crypto_block_encrypt() call. After this call, the context
+ *       is cleaned and can be reused by apr_crypto_block_encrypt_init().
+ * @param out Address of a buffer to which data will be written. This
+ *            buffer must already exist, and is usually the same
+ *            buffer used by apr_evp_crypt(). See note.
+ * @param outlen Length of the output will be written here.
+ * @param ctx The block context to use.
+ * @return APR_ECRYPT if an error occurred.
+ * @return APR_EPADDING if padding was enabled and the block was incorrectly
+ *         formatted.
+ * @return APR_ENOTIMPL if not implemented.
+ */
+APR_DECLARE(apr_status_t) apr_crypto_block_encrypt_finish(unsigned char *out,
+        apr_size_t *outlen, apr_crypto_block_t *ctx)
+{
+    return ctx->provider->block_encrypt_finish(out, outlen, ctx);
+}
+
+/**
+ * @brief Initialise a context for decrypting arbitrary data using the given key.
+ * @note If *ctx is NULL, a apr_crypto_block_t will be created from a pool. If
+ *       *ctx is not NULL, *ctx must point at a previously created structure.
+ * @param ctx The block context returned, see note.
+ * @param blockSize The block size of the cipher.
+ * @param iv Optional initialisation vector.
+ * @param key The key structure to use.
+ * @param p The pool to use.
+ * @return Returns APR_ENOIV if an initialisation vector is required but not specified.
+ *         Returns APR_EINIT if the backend failed to initialise the context. Returns
+ *         APR_ENOTIMPL if not implemented.
+ */
+APR_DECLARE(apr_status_t) apr_crypto_block_decrypt_init(
+        apr_crypto_block_t **ctx, apr_size_t *blockSize,
+        const unsigned char *iv, const apr_crypto_key_t *key, apr_pool_t *p)
+{
+    return key->provider->block_decrypt_init(ctx, blockSize, iv, key, p);
+}
+
+/**
+ * @brief Decrypt data provided by in, write it to out.
+ * @note The number of bytes written will be written to outlen. If
+ *       out is NULL, outlen will contain the maximum size of the
+ *       buffer needed to hold the data, including any data
+ *       generated by apr_crypto_block_decrypt_finish below. If *out points
+ *       to NULL, a buffer sufficiently large will be created from
+ *       the pool provided. If *out points to a not-NULL value, this
+ *       value will be used as a buffer instead.
+ * @param out Address of a buffer to which data will be written,
+ *        see note.
+ * @param outlen Length of the output will be written here.
+ * @param in Address of the buffer to read.
+ * @param inlen Length of the buffer to read.
+ * @param ctx The block context to use.
+ * @return APR_ECRYPT if an error occurred. Returns APR_ENOTIMPL if
+ *         not implemented.
+ */
+APR_DECLARE(apr_status_t) apr_crypto_block_decrypt(unsigned char **out,
+        apr_size_t *outlen, const unsigned char *in, apr_size_t inlen,
+        apr_crypto_block_t *ctx)
+{
+    return ctx->provider->block_decrypt(out, outlen, in, inlen, ctx);
+}
+
+/**
+ * @brief Decrypt final data block, write it to out.
+ * @note If necessary the final block will be written out after being
+ *       padded. Typically the final block will be written to the
+ *       same buffer used by apr_crypto_block_decrypt, offset by the
+ *       number of bytes returned as actually written by the
+ *       apr_crypto_block_decrypt() call. After this call, the context
+ *       is cleaned and can be reused by apr_crypto_block_decrypt_init().
+ * @param out Address of a buffer to which data will be written. This
+ *            buffer must already exist, and is usually the same
+ *            buffer used by apr_evp_crypt(). See note.
+ * @param outlen Length of the output will be written here.
+ * @param ctx The block context to use.
+ * @return APR_ECRYPT if an error occurred.
+ * @return APR_EPADDING if padding was enabled and the block was incorrectly
+ *         formatted.
+ * @return APR_ENOTIMPL if not implemented.
+ */
+APR_DECLARE(apr_status_t) apr_crypto_block_decrypt_finish(unsigned char *out,
+        apr_size_t *outlen, apr_crypto_block_t *ctx)
+{
+    return ctx->provider->block_decrypt_finish(out, outlen, ctx);
+}
+
+/**
+ * @brief Clean encryption / decryption context.
+ * @note After cleanup, a context is free to be reused if necessary.
+ * @param ctx The block context to use.
+ * @return Returns APR_ENOTIMPL if not supported.
+ */
+APR_DECLARE(apr_status_t) apr_crypto_block_cleanup(apr_crypto_block_t *ctx)
+{
+    return ctx->provider->block_cleanup(ctx);
+}
+
+/**
+ * @brief Clean encryption / decryption context.
+ * @note After cleanup, a context is free to be reused if necessary.
+ * @param f The context to use.
+ * @return Returns APR_ENOTIMPL if not supported.
+ */
+APR_DECLARE(apr_status_t) apr_crypto_cleanup(apr_crypto_t *f)
+{
+    return f->provider->cleanup(f);
+}
+
+/**
+ * @brief Shutdown the crypto library.
+ * @note After shutdown, it is expected that the init function can be called again.
+ * @param driver - driver to use
+ * @return Returns APR_ENOTIMPL if not supported.
+ */
+APR_DECLARE(apr_status_t) apr_crypto_shutdown(const apr_crypto_driver_t *driver)
+{
+    return driver->shutdown();
+}
+
+#endif /* APU_HAVE_CRYPTO */
diff --git a/crypto/apr_crypto_commoncrypto.c b/crypto/apr_crypto_commoncrypto.c
new file mode 100644
index 00000000000..9138933067f
--- /dev/null
+++ b/crypto/apr_crypto_commoncrypto.c
@@ -0,0 +1,906 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_lib.h"
+#include "apu.h"
+#include "apr_private.h"
+#include "apu_errno.h"
+
+#include <ctype.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "apr_strings.h"
+#include "apr_time.h"
+#include "apr_buckets.h"
+#include "apr_random.h"
+
+#include "apr_crypto_internal.h"
+
+#if APU_HAVE_CRYPTO
+
+#include <CommonCrypto/CommonCrypto.h>
+
+#define LOG_PREFIX "apr_crypto_commoncrypto: "
+
+struct apr_crypto_t
+{
+    apr_pool_t *pool;
+    const apr_crypto_driver_t *provider;
+    apu_err_t *result;
+    apr_hash_t *types;
+    apr_hash_t *modes;
+    apr_random_t *rng;
+};
+
+struct apr_crypto_key_t
+{
+    apr_pool_t *pool;
+    const apr_crypto_driver_t *provider;
+    const apr_crypto_t *f;
+    CCAlgorithm algorithm;
+    CCOptions options;
+    unsigned char *key;
+    int keyLen;
+    int ivSize;
+    apr_size_t blockSize;
+};
+
+struct apr_crypto_block_t
+{
+    apr_pool_t *pool;
+    const apr_crypto_driver_t *provider;
+    const apr_crypto_t *f;
+    const apr_crypto_key_t *key;
+    CCCryptorRef ref;
+};
+
+static struct apr_crypto_block_key_type_t key_types[] =
+{
+{ APR_KEY_3DES_192, 24, 8, 8 },
+{ APR_KEY_AES_128, 16, 16, 16 },
+{ APR_KEY_AES_192, 24, 16, 16 },
+{ APR_KEY_AES_256, 32, 16, 16 } };
+
+static struct apr_crypto_block_key_mode_t key_modes[] =
+{
+{ APR_MODE_ECB },
+{ APR_MODE_CBC } };
+
+/**
+ * Fetch the most recent error from this driver.
+ */
+static apr_status_t crypto_error(const apu_err_t **result,
+        const apr_crypto_t *f)
+{
+    *result = f->result;
+    return APR_SUCCESS;
+}
+
+/**
+ * Shutdown the crypto library and release resources.
+ */
+static apr_status_t crypto_shutdown(void)
+{
+    return APR_SUCCESS;
+}
+
+static apr_status_t crypto_shutdown_helper(void *data)
+{
+    return crypto_shutdown();
+}
+
+/**
+ * Initialise the crypto library and perform one time initialisation.
+ */
+static apr_status_t crypto_init(apr_pool_t *pool, const char *params,
+        const apu_err_t **result)
+{
+
+    apr_pool_cleanup_register(pool, pool, crypto_shutdown_helper,
+            apr_pool_cleanup_null);
+
+    return APR_SUCCESS;
+}
+
+/**
+ * @brief Clean encryption / decryption context.
+ * @note After cleanup, a context is free to be reused if necessary.
+ * @param ctx The block context to use.
+ * @return Returns APR_ENOTIMPL if not supported.
+ */
+static apr_status_t crypto_block_cleanup(apr_crypto_block_t *ctx)
+{
+
+    if (ctx->ref) {
+        CCCryptorRelease(ctx->ref);
+        ctx->ref = NULL;
+    }
+
+    return APR_SUCCESS;
+
+}
+
+static apr_status_t crypto_block_cleanup_helper(void *data)
+{
+    apr_crypto_block_t *block = (apr_crypto_block_t *) data;
+    return crypto_block_cleanup(block);
+}
+
+/**
+ * @brief Clean encryption / decryption context.
+ * @note After cleanup, a context is free to be reused if necessary.
+ * @param f The context to use.
+ * @return Returns APR_ENOTIMPL if not supported.
+ */
+static apr_status_t crypto_cleanup(apr_crypto_t *f)
+{
+
+    return APR_SUCCESS;
+
+}
+
+static apr_status_t crypto_cleanup_helper(void *data)
+{
+    apr_crypto_t *f = (apr_crypto_t *) data;
+    return crypto_cleanup(f);
+}
+
+/**
+ * @brief Create a context for supporting encryption. Keys, certificates,
+ *        algorithms and other parameters will be set per context. More than
+ *        one context can be created at one time. A cleanup will be automatically
+ *        registered with the given pool to guarantee a graceful shutdown.
+ * @param f - context pointer will be written here
+ * @param provider - provider to use
+ * @param params - array of key parameters
+ * @param pool - process pool
+ * @return APR_ENOENGINE when the engine specified does not exist. APR_EINITENGINE
+ * if the engine cannot be initialised.
+ */
+static apr_status_t crypto_make(apr_crypto_t **ff,
+        const apr_crypto_driver_t *provider, const char *params,
+        apr_pool_t *pool)
+{
+    apr_crypto_t *f = apr_pcalloc(pool, sizeof(apr_crypto_t));
+    apr_status_t rv;
+
+    if (!f) {
+        return APR_ENOMEM;
+    }
+    *ff = f;
+    f->pool = pool;
+    f->provider = provider;
+
+    /* seed the secure random number generator */
+    f->rng = apr_random_standard_new(pool);
+    if (!f->rng) {
+        return APR_ENOMEM;
+    }
+    do {
+        unsigned char seed[8];
+        rv = apr_generate_random_bytes(seed, sizeof(seed));
+        if (rv != APR_SUCCESS) {
+            return rv;
+        }
+        apr_random_add_entropy(f->rng, seed, sizeof(seed));
+        rv = apr_random_secure_ready(f->rng);
+    } while (rv == APR_ENOTENOUGHENTROPY);
+
+    f->result = apr_pcalloc(pool, sizeof(apu_err_t));
+    if (!f->result) {
+        return APR_ENOMEM;
+    }
+
+    f->types = apr_hash_make(pool);
+    if (!f->types) {
+        return APR_ENOMEM;
+    }
+    apr_hash_set(f->types, "3des192", APR_HASH_KEY_STRING, &(key_types[0]));
+    apr_hash_set(f->types, "aes128", APR_HASH_KEY_STRING, &(key_types[1]));
+    apr_hash_set(f->types, "aes192", APR_HASH_KEY_STRING, &(key_types[2]));
+    apr_hash_set(f->types, "aes256", APR_HASH_KEY_STRING, &(key_types[3]));
+
+    f->modes = apr_hash_make(pool);
+    if (!f->modes) {
+        return APR_ENOMEM;
+    }
+    apr_hash_set(f->modes, "ecb", APR_HASH_KEY_STRING, &(key_modes[0]));
+    apr_hash_set(f->modes, "cbc", APR_HASH_KEY_STRING, &(key_modes[1]));
+
+    apr_pool_cleanup_register(pool, f, crypto_cleanup_helper,
+            apr_pool_cleanup_null);
+
+    return APR_SUCCESS;
+
+}
+
+/**
+ * @brief Get a hash table of key types, keyed by the name of the type against
+ * a pointer to apr_crypto_block_key_type_t.
+ *
+ * @param types - hashtable of key types keyed to constants.
+ * @param f - encryption context
+ * @return APR_SUCCESS for success
+ */
+static apr_status_t crypto_get_block_key_types(apr_hash_t **types,
+        const apr_crypto_t *f)
+{
+    *types = f->types;
+    return APR_SUCCESS;
+}
+
+/**
+ * @brief Get a hash table of key modes, keyed by the name of the mode against
+ * a pointer to apr_crypto_block_key_mode_t.
+ *
+ * @param modes - hashtable of key modes keyed to constants.
+ * @param f - encryption context
+ * @return APR_SUCCESS for success
+ */
+static apr_status_t crypto_get_block_key_modes(apr_hash_t **modes,
+        const apr_crypto_t *f)
+{
+    *modes = f->modes;
+    return APR_SUCCESS;
+}
+
+/*
+ * Work out which mechanism to use.
+ */
+static apr_status_t crypto_cipher_mechanism(apr_crypto_key_t *key,
+        const apr_crypto_block_key_type_e type,
+        const apr_crypto_block_key_mode_e mode, const int doPad, apr_pool_t *p)
+{
+    /* handle padding */
+    key->options = doPad ? kCCOptionPKCS7Padding : 0;
+
+    /* determine the algorithm to be used */
+    switch (type) {
+
+    case (APR_KEY_3DES_192):
+
+        /* A 3DES key */
+        if (mode == APR_MODE_CBC) {
+            key->algorithm = kCCAlgorithm3DES;
+            key->keyLen = kCCKeySize3DES;
+            key->ivSize = kCCBlockSize3DES;
+            key->blockSize = kCCBlockSize3DES;
+        }
+        else {
+            key->algorithm = kCCAlgorithm3DES;
+            key->options += kCCOptionECBMode;
+            key->keyLen = kCCKeySize3DES;
+            key->ivSize = 0;
+            key->blockSize = kCCBlockSize3DES;
+        }
+        break;
+
+    case (APR_KEY_AES_128):
+
+        if (mode == APR_MODE_CBC) {
+            key->algorithm = kCCAlgorithmAES128;
+            key->keyLen = kCCKeySizeAES128;
+            key->ivSize = kCCBlockSizeAES128;
+            key->blockSize = kCCBlockSizeAES128;
+        }
+        else {
+            key->algorithm = kCCAlgorithmAES128;
+            key->options += kCCOptionECBMode;
+            key->keyLen = kCCKeySizeAES128;
+            key->ivSize = 0;
+            key->blockSize = kCCBlockSizeAES128;
+        }
+        break;
+
+    case (APR_KEY_AES_192):
+
+        if (mode == APR_MODE_CBC) {
+            key->algorithm = kCCAlgorithmAES128;
+            key->keyLen = kCCKeySizeAES192;
+            key->ivSize = kCCBlockSizeAES128;
+            key->blockSize = kCCBlockSizeAES128;
+        }
+        else {
+            key->algorithm = kCCAlgorithmAES128;
+            key->options += kCCOptionECBMode;
+            key->keyLen = kCCKeySizeAES192;
+            key->ivSize = 0;
+            key->blockSize = kCCBlockSizeAES128;
+        }
+        break;
+
+    case (APR_KEY_AES_256):
+
+        if (mode == APR_MODE_CBC) {
+            key->algorithm = kCCAlgorithmAES128;
+            key->keyLen = kCCKeySizeAES256;
+            key->ivSize = kCCBlockSizeAES128;
+            key->blockSize = kCCBlockSizeAES128;
+        }
+        else {
+            key->algorithm = kCCAlgorithmAES128;
+            key->options += kCCOptionECBMode;
+            key->keyLen = kCCKeySizeAES256;
+            key->ivSize = 0;
+            key->blockSize = kCCBlockSizeAES128;
+        }
+        break;
+
+    default:
+
+        /* TODO: Support CAST, Blowfish */
+
+        /* unknown key type, give up */
+        return APR_EKEYTYPE;
+
+    }
+
+    /* make space for the key */
+    key->key = apr_palloc(p, key->keyLen);
+    if (!key->key) {
+        return APR_ENOMEM;
+    }
+    apr_crypto_clear(p, key->key, key->keyLen);
+
+    return APR_SUCCESS;
+}
+
+/**
+ * @brief Create a key from the provided secret or passphrase. The key is cleaned
+ *        up when the context is cleaned, and may be reused with multiple encryption
+ *        or decryption operations.
+ * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
+ *       *key is not NULL, *key must point at a previously created structure.
+ * @param key The key returned, see note.
+ * @param rec The key record, from which the key will be derived.
+ * @param f The context to use.
+ * @param p The pool to use.
+ * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
+ *         error occurred while generating the key. APR_ENOCIPHER if the type or mode
+ *         is not supported by the particular backend. APR_EKEYTYPE if the key type is
+ *         not known. APR_EPADDING if padding was requested but is not supported.
+ *         APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_key(apr_crypto_key_t **k,
+        const apr_crypto_key_rec_t *rec, const apr_crypto_t *f, apr_pool_t *p)
+{
+    apr_status_t rv;
+    apr_crypto_key_t *key = *k;
+
+    if (!key) {
+        *k = key = apr_pcalloc(p, sizeof *key);
+    }
+    if (!key) {
+        return APR_ENOMEM;
+    }
+
+    key->f = f;
+    key->provider = f->provider;
+
+    /* decide on what cipher mechanism we will be using */
+    rv = crypto_cipher_mechanism(key, rec->type, rec->mode, rec->pad, p);
+    if (APR_SUCCESS != rv) {
+        return rv;
+    }
+
+    switch (rec->ktype) {
+
+    case APR_CRYPTO_KTYPE_PASSPHRASE: {
+
+        /* generate the key */
+        if ((f->result->rc = CCKeyDerivationPBKDF(kCCPBKDF2,
+                rec->k.passphrase.pass, rec->k.passphrase.passLen,
+                rec->k.passphrase.salt, rec->k.passphrase.saltLen,
+                kCCPRFHmacAlgSHA1, rec->k.passphrase.iterations, key->key,
+                key->keyLen)) == kCCParamError) {
+            return APR_ENOKEY;
+        }
+
+        break;
+    }
+
+    case APR_CRYPTO_KTYPE_SECRET: {
+
+        /* sanity check - key correct size? */
+        if (rec->k.secret.secretLen != key->keyLen) {
+            return APR_EKEYLENGTH;
+        }
+
+        /* copy the key */
+        memcpy(key->key, rec->k.secret.secret, rec->k.secret.secretLen);
+
+        break;
+    }
+
+    default: {
+
+        return APR_ENOKEY;
+
+    }
+    }
+
+    return APR_SUCCESS;
+}
+
+/**
+ * @brief Create a key from the given passphrase. By default, the PBKDF2
+ *        algorithm is used to generate the key from the passphrase. It is expected
+ *        that the same pass phrase will generate the same key, regardless of the
+ *        backend crypto platform used. The key is cleaned up when the context
+ *        is cleaned, and may be reused with multiple encryption or decryption
+ *        operations.
+ * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
+ *       *key is not NULL, *key must point at a previously created structure.
+ * @param key The key returned, see note.
+ * @param ivSize The size of the initialisation vector will be returned, based
+ *               on whether an IV is relevant for this type of crypto.
+ * @param pass The passphrase to use.
+ * @param passLen The passphrase length in bytes
+ * @param salt The salt to use.
+ * @param saltLen The salt length in bytes
+ * @param type 3DES_192, AES_128, AES_192, AES_256.
+ * @param mode Electronic Code Book / Cipher Block Chaining.
+ * @param doPad Pad if necessary.
+ * @param iterations Iteration count
+ * @param f The context to use.
+ * @param p The pool to use.
+ * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
+ *         error occurred while generating the key. APR_ENOCIPHER if the type or mode
+ *         is not supported by the particular backend. APR_EKEYTYPE if the key type is
+ *         not known. APR_EPADDING if padding was requested but is not supported.
+ *         APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_passphrase(apr_crypto_key_t **k, apr_size_t *ivSize,
+        const char *pass, apr_size_t passLen, const unsigned char * salt,
+        apr_size_t saltLen, const apr_crypto_block_key_type_e type,
+        const apr_crypto_block_key_mode_e mode, const int doPad,
+        const int iterations, const apr_crypto_t *f, apr_pool_t *p)
+{
+    apr_status_t rv;
+    apr_crypto_key_t *key = *k;
+
+    if (!key) {
+        *k = key = apr_pcalloc(p, sizeof *key);
+        if (!key) {
+            return APR_ENOMEM;
+        }
+    }
+
+    key->f = f;
+    key->provider = f->provider;
+
+    /* decide on what cipher mechanism we will be using */
+    rv = crypto_cipher_mechanism(key, type, mode, doPad, p);
+    if (APR_SUCCESS != rv) {
+        return rv;
+    }
+
+    /* generate the key */
+    if ((f->result->rc = CCKeyDerivationPBKDF(kCCPBKDF2, pass, passLen, salt,
+            saltLen, kCCPRFHmacAlgSHA1, iterations, key->key, key->keyLen))
+            == kCCParamError) {
+        return APR_ENOKEY;
+    }
+
+    if (ivSize) {
+        *ivSize = key->ivSize;
+    }
+
+    return APR_SUCCESS;
+}
+
+/**
+ * @brief Initialise a context for encrypting arbitrary data using the given key.
+ * @note If *ctx is NULL, a apr_crypto_block_t will be created from a pool. If
+ *       *ctx is not NULL, *ctx must point at a previously created structure.
+ * @param ctx The block context returned, see note.
+ * @param iv Optional initialisation vector. If the buffer pointed to is NULL,
+ *           an IV will be created at random, in space allocated from the pool.
+ *           If the buffer pointed to is not NULL, the IV in the buffer will be
+ *           used.
+ * @param key The key structure.
+ * @param blockSize The block size of the cipher.
+ * @param p The pool to use.
+ * @return Returns APR_ENOIV if an initialisation vector is required but not specified.
+ *         Returns APR_EINIT if the backend failed to initialise the context. Returns
+ *         APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_block_encrypt_init(apr_crypto_block_t **ctx,
+        const unsigned char **iv, const apr_crypto_key_t *key,
+        apr_size_t *blockSize, apr_pool_t *p)
+{
+    unsigned char *usedIv;
+    apr_crypto_block_t *block = *ctx;
+    if (!block) {
+        *ctx = block = apr_pcalloc(p, sizeof(apr_crypto_block_t));
+    }
+    if (!block) {
+        return APR_ENOMEM;
+    }
+    block->f = key->f;
+    block->pool = p;
+    block->provider = key->provider;
+    block->key = key;
+
+    apr_pool_cleanup_register(p, block, crypto_block_cleanup_helper,
+            apr_pool_cleanup_null);
+
+    /* generate an IV, if necessary */
+    usedIv = NULL;
+    if (key->ivSize) {
+        if (iv == NULL) {
+            return APR_ENOIV;
+        }
+        if (*iv == NULL) {
+            apr_status_t status;
+            usedIv = apr_pcalloc(p, key->ivSize);
+            if (!usedIv) {
+                return APR_ENOMEM;
+            }
+            apr_crypto_clear(p, usedIv, key->ivSize);
+            status = apr_random_secure_bytes(block->f->rng, usedIv,
+                    key->ivSize);
+            if (APR_SUCCESS != status) {
+                return status;
+            }
+            *iv = usedIv;
+        }
+        else {
+            usedIv = (unsigned char *) *iv;
+        }
+    }
+
+    /* create a new context for encryption */
+    switch ((block->f->result->rc = CCCryptorCreate(kCCEncrypt, key->algorithm,
+            key->options, key->key, key->keyLen, usedIv, &block->ref))) {
+    case kCCSuccess: {
+        break;
+    }
+    case kCCParamError: {
+        return APR_EINIT;
+    }
+    case kCCMemoryFailure: {
+        return APR_ENOMEM;
+    }
+    case kCCAlignmentError: {
+        return APR_EPADDING;
+    }
+    case kCCUnimplemented: {
+        return APR_ENOTIMPL;
+    }
+    default: {
+        return APR_EINIT;
+    }
+    }
+
+    if (blockSize) {
+        *blockSize = key->blockSize;
+    }
+
+    return APR_SUCCESS;
+
+}
+
+/**
+ * @brief Encrypt data provided by in, write it to out.
+ * @note The number of bytes written will be written to outlen. If
+ *       out is NULL, outlen will contain the maximum size of the
+ *       buffer needed to hold the data, including any data
+ *       generated by apr_crypto_block_encrypt_finish below. If *out points
+ *       to NULL, a buffer sufficiently large will be created from
+ *       the pool provided. If *out points to a not-NULL value, this
+ *       value will be used as a buffer instead.
+ * @param out Address of a buffer to which data will be written,
+ *        see note.
+ * @param outlen Length of the output will be written here.
+ * @param in Address of the buffer to read.
+ * @param inlen Length of the buffer to read.
+ * @param ctx The block context to use.
+ * @return APR_ECRYPT if an error occurred. Returns APR_ENOTIMPL if
+ *         not implemented.
+ */
+static apr_status_t crypto_block_encrypt(unsigned char **out,
+        apr_size_t *outlen, const unsigned char *in, apr_size_t inlen,
+        apr_crypto_block_t *ctx)
+{
+    apr_size_t outl = *outlen;
+    unsigned char *buffer;
+
+    /* are we after the maximum size of the out buffer? */
+    if (!out) {
+        *outlen = CCCryptorGetOutputLength(ctx->ref, inlen, 1);
+        return APR_SUCCESS;
+    }
+
+    /* must we allocate the output buffer from a pool? */
+    if (!*out) {
+        outl = CCCryptorGetOutputLength(ctx->ref, inlen, 1);
+        buffer = apr_palloc(ctx->pool, outl);
+        if (!buffer) {
+            return APR_ENOMEM;
+        }
+        apr_crypto_clear(ctx->pool, buffer, outl);
+        *out = buffer;
+    }
+
+    switch ((ctx->f->result->rc = CCCryptorUpdate(ctx->ref, in, inlen, (*out),
+            outl, &outl))) {
+    case kCCSuccess: {
+        break;
+    }
+    case kCCBufferTooSmall: {
+        return APR_ENOSPACE;
+    }
+    default: {
+        return APR_ECRYPT;
+    }
+    }
+    *outlen = outl;
+
+    return APR_SUCCESS;
+
+}
+
+/**
+ * @brief Encrypt final data block, write it to out.
+ * @note If necessary the final block will be written out after being
+ *       padded. Typically the final block will be written to the
+ *       same buffer used by apr_crypto_block_encrypt, offset by the
+ *       number of bytes returned as actually written by the
+ *       apr_crypto_block_encrypt() call. After this call, the context
+ *       is cleaned and can be reused by apr_crypto_block_encrypt_init().
+ * @param out Address of a buffer to which data will be written. This
+ *            buffer must already exist, and is usually the same
+ *            buffer used by apr_evp_crypt(). See note.
+ * @param outlen Length of the output will be written here.
+ * @param ctx The block context to use.
+ * @return APR_ECRYPT if an error occurred.
+ * @return APR_EPADDING if padding was enabled and the block was incorrectly
+ *         formatted.
+ * @return APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_block_encrypt_finish(unsigned char *out,
+        apr_size_t *outlen, apr_crypto_block_t *ctx)
+{
+    apr_size_t len = *outlen;
+
+    ctx->f->result->rc = CCCryptorFinal(ctx->ref, out,
+            CCCryptorGetOutputLength(ctx->ref, 0, 1), &len);
+
+    /* always clean up */
+    crypto_block_cleanup(ctx);
+
+    switch (ctx->f->result->rc) {
+    case kCCSuccess: {
+        break;
+    }
+    case kCCBufferTooSmall: {
+        return APR_ENOSPACE;
+    }
+    case kCCAlignmentError: {
+        return APR_EPADDING;
+    }
+    case kCCDecodeError: {
+        return APR_ECRYPT;
+    }
+    default: {
+        return APR_ECRYPT;
+    }
+    }
+    *outlen = len;
+
+    return APR_SUCCESS;
+
+}
+
+/**
+ * @brief Initialise a context for decrypting arbitrary data using the given key.
+ * @note If *ctx is NULL, a apr_crypto_block_t will be created from a pool. If
+ *       *ctx is not NULL, *ctx must point at a previously created structure.
+ * @param ctx The block context returned, see note.
+ * @param blockSize The block size of the cipher.
+ * @param iv Optional initialisation vector. If the buffer pointed to is NULL,
+ *           an IV will be created at random, in space allocated from the pool.
+ *           If the buffer is not NULL, the IV in the buffer will be used.
+ * @param key The key structure.
+ * @param p The pool to use.
+ * @return Returns APR_ENOIV if an initialisation vector is required but not specified.
+ *         Returns APR_EINIT if the backend failed to initialise the context. Returns
+ *         APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_block_decrypt_init(apr_crypto_block_t **ctx,
+        apr_size_t *blockSize, const unsigned char *iv,
+        const apr_crypto_key_t *key, apr_pool_t *p)
+{
+    apr_crypto_block_t *block = *ctx;
+    if (!block) {
+        *ctx = block = apr_pcalloc(p, sizeof(apr_crypto_block_t));
+    }
+    if (!block) {
+        return APR_ENOMEM;
+    }
+    block->f = key->f;
+    block->pool = p;
+    block->provider = key->provider;
+
+    apr_pool_cleanup_register(p, block, crypto_block_cleanup_helper,
+            apr_pool_cleanup_null);
+
+    /* generate an IV, if necessary */
+    if (key->ivSize) {
+        if (iv == NULL) {
+            return APR_ENOIV;
+        }
+    }
+
+    /* create a new context for decryption */
+    switch ((block->f->result->rc = CCCryptorCreate(kCCDecrypt, key->algorithm,
+            key->options, key->key, key->keyLen, iv, &block->ref))) {
+    case kCCSuccess: {
+        break;
+    }
+    case kCCParamError: {
+        return APR_EINIT;
+    }
+    case kCCMemoryFailure: {
+        return APR_ENOMEM;
+    }
+    case kCCAlignmentError: {
+        return APR_EPADDING;
+    }
+    case kCCUnimplemented: {
+        return APR_ENOTIMPL;
+    }
+    default: {
+        return APR_EINIT;
+    }
+    }
+
+    if (blockSize) {
+        *blockSize = key->blockSize;
+    }
+
+    return APR_SUCCESS;
+
+}
+
+/**
+ * @brief Decrypt data provided by in, write it to out.
+ * @note The number of bytes written will be written to outlen. If
+ *       out is NULL, outlen will contain the maximum size of the
+ *       buffer needed to hold the data, including any data
+ *       generated by apr_crypto_block_decrypt_finish below. If *out points
+ *       to NULL, a buffer sufficiently large will be created from
+ *       the pool provided. If *out points to a not-NULL value, this
+ *       value will be used as a buffer instead.
+ * @param out Address of a buffer to which data will be written,
+ *        see note.
+ * @param outlen Length of the output will be written here.
+ * @param in Address of the buffer to read.
+ * @param inlen Length of the buffer to read.
+ * @param ctx The block context to use.
+ * @return APR_ECRYPT if an error occurred. Returns APR_ENOTIMPL if
+ *         not implemented.
+ */
+static apr_status_t crypto_block_decrypt(unsigned char **out,
+        apr_size_t *outlen, const unsigned char *in, apr_size_t inlen,
+        apr_crypto_block_t *ctx)
+{
+    apr_size_t outl = *outlen;
+    unsigned char *buffer;
+
+    /* are we after the maximum size of the out buffer? */
+    if (!out) {
+        *outlen = CCCryptorGetOutputLength(ctx->ref, inlen, 1);
+        return APR_SUCCESS;
+    }
+
+    /* must we allocate the output buffer from a pool? */
+    if (!*out) {
+        outl = CCCryptorGetOutputLength(ctx->ref, inlen, 1);
+        buffer = apr_palloc(ctx->pool, outl);
+        if (!buffer) {
+            return APR_ENOMEM;
+        }
+        apr_crypto_clear(ctx->pool, buffer, outl);
+        *out = buffer;
+    }
+
+    switch ((ctx->f->result->rc = CCCryptorUpdate(ctx->ref, in, inlen, (*out),
+            outl, &outl))) {
+    case kCCSuccess: {
+        break;
+    }
+    case kCCBufferTooSmall: {
+        return APR_ENOSPACE;
+    }
+    default: {
+        return APR_ECRYPT;
+    }
+    }
+    *outlen = outl;
+
+    return APR_SUCCESS;
+
+}
+
+/**
+ * @brief Decrypt final data block, write it to out.
+ * @note If necessary the final block will be written out after being
+ *       padded. Typically the final block will be written to the
+ *       same buffer used by apr_crypto_block_decrypt, offset by the
+ *       number of bytes returned as actually written by the
+ *       apr_crypto_block_decrypt() call. After this call, the context
+ *       is cleaned and can be reused by apr_crypto_block_decrypt_init().
+ * @param out Address of a buffer to which data will be written. This
+ *            buffer must already exist, and is usually the same
+ *            buffer used by apr_evp_crypt(). See note.
+ * @param outlen Length of the output will be written here.
+ * @param ctx The block context to use.
+ * @return APR_ECRYPT if an error occurred.
+ * @return APR_EPADDING if padding was enabled and the block was incorrectly
+ *         formatted.
+ * @return APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_block_decrypt_finish(unsigned char *out,
+        apr_size_t *outlen, apr_crypto_block_t *ctx)
+{
+    apr_size_t len = *outlen;
+
+    ctx->f->result->rc = CCCryptorFinal(ctx->ref, out,
+            CCCryptorGetOutputLength(ctx->ref, 0, 1), &len);
+
+    /* always clean up */
+    crypto_block_cleanup(ctx);
+
+    switch (ctx->f->result->rc) {
+    case kCCSuccess: {
+        break;
+    }
+    case kCCBufferTooSmall: {
+        return APR_ENOSPACE;
+    }
+    case kCCAlignmentError: {
+        return APR_EPADDING;
+    }
+    case kCCDecodeError: {
+        return APR_ECRYPT;
+    }
+    default: {
+        return APR_ECRYPT;
+    }
+    }
+    *outlen = len;
+
+    return APR_SUCCESS;
+
+}
+
+/**
+ * OSX Common Crypto module.
+ */
+APR_MODULE_DECLARE_DATA const apr_crypto_driver_t apr_crypto_commoncrypto_driver =
+{
+        "commoncrypto", crypto_init, crypto_make, crypto_get_block_key_types,
+        crypto_get_block_key_modes, crypto_passphrase,
+        crypto_block_encrypt_init, crypto_block_encrypt,
+        crypto_block_encrypt_finish, crypto_block_decrypt_init,
+        crypto_block_decrypt, crypto_block_decrypt_finish, crypto_block_cleanup,
+        crypto_cleanup, crypto_shutdown, crypto_error, crypto_key
+};
+
+#endif
diff --git a/crypto/apr_crypto_nss.c b/crypto/apr_crypto_nss.c
new file mode 100644
index 00000000000..1c3bb2c6afa
--- /dev/null
+++ b/crypto/apr_crypto_nss.c
@@ -0,0 +1,1097 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_lib.h"
+#include "apu.h"
+#include "apr_private.h"
+#include "apu_errno.h"
+
+#include <ctype.h>
+#include <stdlib.h>
+
+#include "apr_strings.h"
+#include "apr_time.h"
+#include "apr_buckets.h"
+
+#include "apr_crypto_internal.h"
+
+#if APU_HAVE_CRYPTO
+
+#include <prerror.h>
+
+#ifdef HAVE_NSS_NSS_H
+#include <nss/nss.h>
+#endif
+#ifdef HAVE_NSS_H
+#include <nss.h>
+#endif
+
+#ifdef HAVE_NSS_PK11PUB_H
+#include <nss/pk11pub.h>
+#endif
+#ifdef HAVE_PK11PUB_H
+#include <pk11pub.h>
+#endif
+
+struct apr_crypto_t {
+    apr_pool_t *pool;
+    const apr_crypto_driver_t *provider;
+    apu_err_t *result;
+    apr_crypto_config_t *config;
+    apr_hash_t *types;
+    apr_hash_t *modes;
+};
+
+struct apr_crypto_config_t {
+       void *opaque;
+};
+
+struct apr_crypto_key_t {
+    apr_pool_t *pool;
+    const apr_crypto_driver_t *provider;
+    const apr_crypto_t *f;
+    CK_MECHANISM_TYPE cipherMech;
+    SECOidTag cipherOid;
+    PK11SymKey *symKey;
+    int ivSize;
+    int keyLength;
+};
+
+struct apr_crypto_block_t {
+    apr_pool_t *pool;
+    const apr_crypto_driver_t *provider;
+    const apr_crypto_t *f;
+    PK11Context *ctx;
+    apr_crypto_key_t *key;
+    SECItem *secParam;
+    int blockSize;
+};
+
+static struct apr_crypto_block_key_type_t key_types[] =
+{
+{ APR_KEY_3DES_192, 24, 8, 8 },
+{ APR_KEY_AES_128, 16, 16, 16 },
+{ APR_KEY_AES_192, 24, 16, 16 },
+{ APR_KEY_AES_256, 32, 16, 16 } };
+
+static struct apr_crypto_block_key_mode_t key_modes[] =
+{
+{ APR_MODE_ECB },
+{ APR_MODE_CBC } };
+
+/* sufficient space to wrap a key */
+#define BUFFER_SIZE 128
+
+/**
+ * Fetch the most recent error from this driver.
+ */
+static apr_status_t crypto_error(const apu_err_t **result,
+        const apr_crypto_t *f)
+{
+    *result = f->result;
+    return APR_SUCCESS;
+}
+
+/**
+ * Shutdown the crypto library and release resources.
+ *
+ * It is safe to shut down twice.
+ */
+static apr_status_t crypto_shutdown(void)
+{
+    if (NSS_IsInitialized()) {
+        SECStatus s = NSS_Shutdown();
+        if (s != SECSuccess) {
+            fprintf(stderr, "NSS failed to shutdown, possible leak: %d: %s",
+                PR_GetError(), PR_ErrorToName(s));
+            return APR_EINIT;
+        }
+    }
+    return APR_SUCCESS;
+}
+
+static apr_status_t crypto_shutdown_helper(void *data)
+{
+    return crypto_shutdown();
+}
+
+/**
+ * Initialise the crypto library and perform one time initialisation.
+ */
+static apr_status_t crypto_init(apr_pool_t *pool, const char *params,
+        const apu_err_t **result)
+{
+    SECStatus s;
+    const char *dir = NULL;
+    const char *keyPrefix = NULL;
+    const char *certPrefix = NULL;
+    const char *secmod = NULL;
+    int noinit = 0;
+    PRUint32 flags = 0;
+
+    struct {
+        const char *field;
+        const char *value;
+        int set;
+    } fields[] = {
+        { "dir", NULL, 0 },
+        { "key3", NULL, 0 },
+        { "cert7", NULL, 0 },
+        { "secmod", NULL, 0 },
+        { "noinit", NULL, 0 },
+        { NULL, NULL, 0 }
+    };
+    const char *ptr;
+    size_t klen;
+    char **elts = NULL;
+    char *elt;
+    int i = 0, j;
+    apr_status_t status;
+
+    if (params) {
+        if (APR_SUCCESS != (status = apr_tokenize_to_argv(params, &elts, pool))) {
+            return status;
+        }
+        while ((elt = elts[i])) {
+            ptr = strchr(elt, '=');
+            if (ptr) {
+                for (klen = ptr - elt; klen && apr_isspace(elt[klen - 1]); --klen)
+                    ;
+                ptr++;
+            }
+            else {
+                for (klen = strlen(elt); klen && apr_isspace(elt[klen - 1]); --klen)
+                    ;
+            }
+            elt[klen] = 0;
+
+            for (j = 0; fields[j].field != NULL; ++j) {
+                if (klen && !strcasecmp(fields[j].field, elt)) {
+                    fields[j].set = 1;
+                    if (ptr) {
+                        fields[j].value = ptr;
+                    }
+                    break;
+                }
+            }
+
+            i++;
+        }
+        dir = fields[0].value;
+        keyPrefix = fields[1].value;
+        certPrefix = fields[2].value;
+        secmod = fields[3].value;
+        noinit = fields[4].set;
+    }
+
+    /* if we've been asked to bypass, do so here */
+    if (noinit) {
+        return APR_SUCCESS;
+    }
+
+    /* sanity check - we can only initialise NSS once */
+    if (NSS_IsInitialized()) {
+        return APR_EREINIT;
+    }
+
+    if (keyPrefix || certPrefix || secmod) {
+        s = NSS_Initialize(dir, certPrefix, keyPrefix, secmod, flags);
+    }
+    else if (dir) {
+        s = NSS_InitReadWrite(dir);
+    }
+    else {
+        s = NSS_NoDB_Init(NULL);
+    }
+    if (s != SECSuccess) {
+        if (result) {
+            /* Note: all memory must be owned by the caller, in case we're unloaded */
+            apu_err_t *err = apr_pcalloc(pool, sizeof(apu_err_t));
+            err->rc = PR_GetError();
+            err->msg = apr_pstrdup(pool, PR_ErrorToName(s));
+            err->reason = apr_pstrdup(pool, "Error during 'nss' initialisation");
+            *result = err;
+        }
+
+        return APR_ECRYPT;
+    }
+
+    apr_pool_cleanup_register(pool, pool, crypto_shutdown_helper,
+            apr_pool_cleanup_null);
+
+    return APR_SUCCESS;
+
+}
+
+/**
+ * @brief Clean encryption / decryption context.
+ * @note After cleanup, a context is free to be reused if necessary.
+ * @param f The context to use.
+ * @return Returns APR_ENOTIMPL if not supported.
+ */
+static apr_status_t crypto_block_cleanup(apr_crypto_block_t *block)
+{
+
+    if (block->secParam) {
+        SECITEM_FreeItem(block->secParam, PR_TRUE);
+        block->secParam = NULL;
+    }
+
+    if (block->ctx) {
+        PK11_DestroyContext(block->ctx, PR_TRUE);
+        block->ctx = NULL;
+    }
+
+    return APR_SUCCESS;
+
+}
+
+static apr_status_t crypto_block_cleanup_helper(void *data)
+{
+    apr_crypto_block_t *block = (apr_crypto_block_t *) data;
+    return crypto_block_cleanup(block);
+}
+
+static apr_status_t crypto_key_cleanup(void *data)
+{
+    apr_crypto_key_t *key = data;
+    if (key->symKey) {
+        PK11_FreeSymKey(key->symKey);
+        key->symKey = NULL;
+    }
+    return APR_SUCCESS;
+}
+/**
+ * @brief Clean encryption / decryption context.
+ * @note After cleanup, a context is free to be reused if necessary.
+ * @param f The context to use.
+ * @return Returns APR_ENOTIMPL if not supported.
+ */
+static apr_status_t crypto_cleanup(apr_crypto_t *f)
+{
+    return APR_SUCCESS;
+}
+
+static apr_status_t crypto_cleanup_helper(void *data)
+{
+    apr_crypto_t *f = (apr_crypto_t *) data;
+    return crypto_cleanup(f);
+}
+
+/**
+ * @brief Create a context for supporting encryption. Keys, certificates,
+ *        algorithms and other parameters will be set per context. More than
+ *        one context can be created at one time. A cleanup will be automatically
+ *        registered with the given pool to guarantee a graceful shutdown.
+ * @param f - context pointer will be written here
+ * @param provider - provider to use
+ * @param params - parameter string
+ * @param pool - process pool
+ * @return APR_ENOENGINE when the engine specified does not exist. APR_EINITENGINE
+ * if the engine cannot be initialised.
+ */
+static apr_status_t crypto_make(apr_crypto_t **ff,
+        const apr_crypto_driver_t *provider, const char *params,
+        apr_pool_t *pool)
+{
+    apr_crypto_config_t *config = NULL;
+    apr_crypto_t *f;
+
+    f = apr_pcalloc(pool, sizeof(apr_crypto_t));
+    if (!f) {
+        return APR_ENOMEM;
+    }
+    *ff = f;
+    f->pool = pool;
+    f->provider = provider;
+    config = f->config = apr_pcalloc(pool, sizeof(apr_crypto_config_t));
+    if (!config) {
+        return APR_ENOMEM;
+    }
+    f->result = apr_pcalloc(pool, sizeof(apu_err_t));
+    if (!f->result) {
+        return APR_ENOMEM;
+    }
+
+    f->types = apr_hash_make(pool);
+    if (!f->types) {
+        return APR_ENOMEM;
+    }
+    apr_hash_set(f->types, "3des192", APR_HASH_KEY_STRING, &(key_types[0]));
+    apr_hash_set(f->types, "aes128", APR_HASH_KEY_STRING, &(key_types[1]));
+    apr_hash_set(f->types, "aes192", APR_HASH_KEY_STRING, &(key_types[2]));
+    apr_hash_set(f->types, "aes256", APR_HASH_KEY_STRING, &(key_types[3]));
+
+    f->modes = apr_hash_make(pool);
+    if (!f->modes) {
+        return APR_ENOMEM;
+    }
+    apr_hash_set(f->modes, "ecb", APR_HASH_KEY_STRING, &(key_modes[0]));
+    apr_hash_set(f->modes, "cbc", APR_HASH_KEY_STRING, &(key_modes[1]));
+
+    apr_pool_cleanup_register(pool, f, crypto_cleanup_helper,
+            apr_pool_cleanup_null);
+
+    return APR_SUCCESS;
+
+}
+
+/**
+ * @brief Get a hash table of key types, keyed by the name of the type against
+ * a pointer to apr_crypto_block_key_type_t.
+ *
+ * @param types - hashtable of key types keyed to constants.
+ * @param f - encryption context
+ * @return APR_SUCCESS for success
+ */
+static apr_status_t crypto_get_block_key_types(apr_hash_t **types,
+        const apr_crypto_t *f)
+{
+    *types = f->types;
+    return APR_SUCCESS;
+}
+
+/**
+ * @brief Get a hash table of key modes, keyed by the name of the mode against
+ * a pointer to apr_crypto_block_key_mode_t.
+ *
+ * @param modes - hashtable of key modes keyed to constants.
+ * @param f - encryption context
+ * @return APR_SUCCESS for success
+ */
+static apr_status_t crypto_get_block_key_modes(apr_hash_t **modes,
+        const apr_crypto_t *f)
+{
+    *modes = f->modes;
+    return APR_SUCCESS;
+}
+
+/*
+ * Work out which mechanism to use.
+ */
+static apr_status_t crypto_cipher_mechanism(apr_crypto_key_t *key,
+        const apr_crypto_block_key_type_e type,
+        const apr_crypto_block_key_mode_e mode, const int doPad)
+{
+
+    /* decide on what cipher mechanism we will be using */
+    switch (type) {
+
+    case (APR_KEY_3DES_192):
+        if (APR_MODE_CBC == mode) {
+            key->cipherOid = SEC_OID_DES_EDE3_CBC;
+        }
+        else if (APR_MODE_ECB == mode) {
+            return APR_ENOCIPHER;
+            /* No OID for CKM_DES3_ECB; */
+        }
+        key->keyLength = 24;
+        break;
+    case (APR_KEY_AES_128):
+        if (APR_MODE_CBC == mode) {
+            key->cipherOid = SEC_OID_AES_128_CBC;
+        }
+        else {
+            key->cipherOid = SEC_OID_AES_128_ECB;
+        }
+        key->keyLength = 16;
+        break;
+    case (APR_KEY_AES_192):
+        if (APR_MODE_CBC == mode) {
+            key->cipherOid = SEC_OID_AES_192_CBC;
+        }
+        else {
+            key->cipherOid = SEC_OID_AES_192_ECB;
+        }
+        key->keyLength = 24;
+        break;
+    case (APR_KEY_AES_256):
+        if (APR_MODE_CBC == mode) {
+            key->cipherOid = SEC_OID_AES_256_CBC;
+        }
+        else {
+            key->cipherOid = SEC_OID_AES_256_ECB;
+        }
+        key->keyLength = 32;
+        break;
+    default:
+        /* unknown key type, give up */
+        return APR_EKEYTYPE;
+    }
+
+    /* AES_128_CBC --> CKM_AES_CBC --> CKM_AES_CBC_PAD */
+    key->cipherMech = PK11_AlgtagToMechanism(key->cipherOid);
+    if (key->cipherMech == CKM_INVALID_MECHANISM) {
+        return APR_ENOCIPHER;
+    }
+    if (doPad) {
+        CK_MECHANISM_TYPE paddedMech;
+        paddedMech = PK11_GetPadMechanism(key->cipherMech);
+        if (CKM_INVALID_MECHANISM == paddedMech
+                || key->cipherMech == paddedMech) {
+            return APR_EPADDING;
+        }
+        key->cipherMech = paddedMech;
+    }
+
+    key->ivSize = PK11_GetIVLength(key->cipherMech);
+
+    return APR_SUCCESS;
+}
+
+/**
+ * @brief Create a key from the provided secret or passphrase. The key is cleaned
+ *        up when the context is cleaned, and may be reused with multiple encryption
+ *        or decryption operations.
+ * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
+ *       *key is not NULL, *key must point at a previously created structure.
+ * @param key The key returned, see note.
+ * @param rec The key record, from which the key will be derived.
+ * @param f The context to use.
+ * @param p The pool to use.
+ * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
+ *         error occurred while generating the key. APR_ENOCIPHER if the type or mode
+ *         is not supported by the particular backend. APR_EKEYTYPE if the key type is
+ *         not known. APR_EPADDING if padding was requested but is not supported.
+ *         APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_key(apr_crypto_key_t **k,
+        const apr_crypto_key_rec_t *rec, const apr_crypto_t *f, apr_pool_t *p)
+{
+    apr_status_t rv = APR_SUCCESS;
+    PK11SlotInfo *slot, *tslot;
+    PK11SymKey *tkey;
+    SECItem secretItem;
+    SECItem wrappedItem;
+    SECItem *secParam;
+    PK11Context *ctx;
+    SECStatus s;
+    SECItem passItem;
+    SECItem saltItem;
+    SECAlgorithmID *algid;
+    void *wincx = NULL; /* what is wincx? */
+    apr_crypto_key_t *key;
+    int blockSize;
+    int remainder;
+
+    key = *k;
+    if (!key) {
+        *k = key = apr_pcalloc(p, sizeof *key);
+        if (!key) {
+            return APR_ENOMEM;
+        }
+        apr_pool_cleanup_register(p, key, crypto_key_cleanup,
+                                  apr_pool_cleanup_null);
+    }
+
+    key->f = f;
+    key->provider = f->provider;
+
+    /* decide on what cipher mechanism we will be using */
+    rv = crypto_cipher_mechanism(key, rec->type, rec->mode, rec->pad);
+    if (APR_SUCCESS != rv) {
+        return rv;
+    }
+
+    switch (rec->ktype) {
+
+    case APR_CRYPTO_KTYPE_PASSPHRASE: {
+
+        /* Turn the raw passphrase and salt into SECItems */
+        passItem.data = (unsigned char*) rec->k.passphrase.pass;
+        passItem.len = rec->k.passphrase.passLen;
+        saltItem.data = (unsigned char*) rec->k.passphrase.salt;
+        saltItem.len = rec->k.passphrase.saltLen;
+
+        /* generate the key */
+        /* pbeAlg and cipherAlg are the same. */
+        algid = PK11_CreatePBEV2AlgorithmID(key->cipherOid, key->cipherOid,
+                SEC_OID_HMAC_SHA1, key->keyLength,
+                rec->k.passphrase.iterations, &saltItem);
+        if (algid) {
+            slot = PK11_GetBestSlot(key->cipherMech, wincx);
+            if (slot) {
+                key->symKey = PK11_PBEKeyGen(slot, algid, &passItem, PR_FALSE,
+                        wincx);
+                PK11_FreeSlot(slot);
+            }
+            SECOID_DestroyAlgorithmID(algid, PR_TRUE);
+        }
+
+        break;
+    }
+
+    case APR_CRYPTO_KTYPE_SECRET: {
+
+        /*
+         * NSS is by default in FIPS mode, which disallows the use of unencrypted
+         * symmetrical keys. As per http://permalink.gmane.org/gmane.comp.mozilla.crypto/7947
+         * we do the following:
+         *
+         * 1. Generate a (temporary) symmetric key in NSS.
+         * 2. Use that symmetric key to encrypt your symmetric key as data.
+         * 3. Unwrap your wrapped symmetric key, using the symmetric key
+         * you generated in Step 1 as the unwrapping key.
+         *
+         * http://permalink.gmane.org/gmane.comp.mozilla.crypto/7947
+         */
+
+        /* generate the key */
+        slot = PK11_GetBestSlot(key->cipherMech, NULL);
+        if (slot) {
+            unsigned char data[BUFFER_SIZE];
+
+            /* sanity check - key correct size? */
+            if (rec->k.secret.secretLen != key->keyLength) {
+                PK11_FreeSlot(slot);
+                return APR_EKEYLENGTH;
+            }
+
+            tslot = PK11_GetBestSlot(CKM_AES_ECB, NULL);
+            if (tslot) {
+
+                /* generate a temporary wrapping key */
+                tkey = PK11_KeyGen(tslot, CKM_AES_ECB, 0, PK11_GetBestKeyLength(tslot, CKM_AES_ECB), 0);
+
+                /* prepare the key to wrap */
+                secretItem.data = (unsigned char *) rec->k.secret.secret;
+                secretItem.len = rec->k.secret.secretLen;
+
+                /* ensure our key matches the blocksize */
+                secParam = PK11_GenerateNewParam(CKM_AES_ECB, tkey);
+                blockSize = PK11_GetBlockSize(CKM_AES_ECB, secParam);
+                remainder = rec->k.secret.secretLen % blockSize;
+                if (remainder) {
+                    secretItem.data =
+                            apr_pcalloc(p, rec->k.secret.secretLen + remainder);
+                    apr_crypto_clear(p, secretItem.data,
+                            rec->k.secret.secretLen);
+                    memcpy(secretItem.data, rec->k.secret.secret,
+                            rec->k.secret.secretLen);
+                    secretItem.len += remainder;
+                }
+
+                /* prepare a space for the wrapped key */
+                wrappedItem.data = data;
+
+                /* wrap the key */
+                ctx = PK11_CreateContextBySymKey(CKM_AES_ECB, CKA_ENCRYPT, tkey,
+                        secParam);
+                if (ctx) {
+                    s = PK11_CipherOp(ctx, wrappedItem.data,
+                            (int *) (&wrappedItem.len), BUFFER_SIZE,
+                            secretItem.data, secretItem.len);
+                    if (s == SECSuccess) {
+
+                        /* unwrap the key again */
+                        key->symKey = PK11_UnwrapSymKeyWithFlags(tkey,
+                                CKM_AES_ECB, NULL, &wrappedItem,
+                                key->cipherMech, CKA_ENCRYPT,
+                                rec->k.secret.secretLen, 0);
+
+                    }
+
+                    PK11_DestroyContext(ctx, PR_TRUE);
+                }
+
+                /* clean up */
+                SECITEM_FreeItem(secParam, PR_TRUE);
+                PK11_FreeSymKey(tkey);
+                PK11_FreeSlot(tslot);
+
+            }
+
+            PK11_FreeSlot(slot);
+        }
+
+        break;
+    }
+
+    default: {
+
+        return APR_ENOKEY;
+
+    }
+    }
+
+    /* sanity check? */
+    if (!key->symKey) {
+        PRErrorCode perr = PORT_GetError();
+        if (perr) {
+            f->result->rc = perr;
+            f->result->msg = PR_ErrorToName(perr);
+            rv = APR_ENOKEY;
+        }
+    }
+
+    return rv;
+}
+
+/**
+ * @brief Create a key from the given passphrase. By default, the PBKDF2
+ *        algorithm is used to generate the key from the passphrase. It is expected
+ *        that the same pass phrase will generate the same key, regardless of the
+ *        backend crypto platform used. The key is cleaned up when the context
+ *        is cleaned, and may be reused with multiple encryption or decryption
+ *        operations.
+ * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
+ *       *key is not NULL, *key must point at a previously created structure.
+ * @param key The key returned, see note.
+ * @param ivSize The size of the initialisation vector will be returned, based
+ *               on whether an IV is relevant for this type of crypto.
+ * @param pass The passphrase to use.
+ * @param passLen The passphrase length in bytes
+ * @param salt The salt to use.
+ * @param saltLen The salt length in bytes
+ * @param type 3DES_192, AES_128, AES_192, AES_256.
+ * @param mode Electronic Code Book / Cipher Block Chaining.
+ * @param doPad Pad if necessary.
+ * @param iterations Iteration count
+ * @param f The context to use.
+ * @param p The pool to use.
+ * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
+ *         error occurred while generating the key. APR_ENOCIPHER if the type or mode
+ *         is not supported by the particular backend. APR_EKEYTYPE if the key type is
+ *         not known. APR_EPADDING if padding was requested but is not supported.
+ *         APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_passphrase(apr_crypto_key_t **k, apr_size_t *ivSize,
+        const char *pass, apr_size_t passLen, const unsigned char * salt,
+        apr_size_t saltLen, const apr_crypto_block_key_type_e type,
+        const apr_crypto_block_key_mode_e mode, const int doPad,
+        const int iterations, const apr_crypto_t *f, apr_pool_t *p)
+{
+    apr_status_t rv = APR_SUCCESS;
+    PK11SlotInfo * slot;
+    SECItem passItem;
+    SECItem saltItem;
+    SECAlgorithmID *algid;
+    void *wincx = NULL; /* what is wincx? */
+    apr_crypto_key_t *key = *k;
+
+    if (!key) {
+        *k = key = apr_pcalloc(p, sizeof *key);
+        if (!key) {
+            return APR_ENOMEM;
+        }
+        apr_pool_cleanup_register(p, key, crypto_key_cleanup,
+                                  apr_pool_cleanup_null);
+    }
+
+    key->f = f;
+    key->provider = f->provider;
+
+    /* decide on what cipher mechanism we will be using */
+    rv = crypto_cipher_mechanism(key, type, mode, doPad);
+    if (APR_SUCCESS != rv) {
+        return rv;
+    }
+
+    /* Turn the raw passphrase and salt into SECItems */
+    passItem.data = (unsigned char*) pass;
+    passItem.len = passLen;
+    saltItem.data = (unsigned char*) salt;
+    saltItem.len = saltLen;
+
+    /* generate the key */
+    /* pbeAlg and cipherAlg are the same. */
+    algid = PK11_CreatePBEV2AlgorithmID(key->cipherOid, key->cipherOid,
+            SEC_OID_HMAC_SHA1, key->keyLength, iterations, &saltItem);
+    if (algid) {
+        slot = PK11_GetBestSlot(key->cipherMech, wincx);
+        if (slot) {
+            key->symKey = PK11_PBEKeyGen(slot, algid, &passItem, PR_FALSE,
+                    wincx);
+            PK11_FreeSlot(slot);
+        }
+        SECOID_DestroyAlgorithmID(algid, PR_TRUE);
+    }
+
+    /* sanity check? */
+    if (!key->symKey) {
+        PRErrorCode perr = PORT_GetError();
+        if (perr) {
+            f->result->rc = perr;
+            f->result->msg = PR_ErrorToName(perr);
+            rv = APR_ENOKEY;
+        }
+    }
+
+    if (ivSize) {
+        *ivSize = key->ivSize;
+    }
+
+    return rv;
+}
+
+/**
+ * @brief Initialise a context for encrypting arbitrary data using the given key.
+ * @note If *ctx is NULL, a apr_crypto_block_t will be created from a pool. If
+ *       *ctx is not NULL, *ctx must point at a previously created structure.
+ * @param ctx The block context returned, see note.
+ * @param iv Optional initialisation vector. If the buffer pointed to is NULL,
+ *           an IV will be created at random, in space allocated from the pool.
+ *           If the buffer pointed to is not NULL, the IV in the buffer will be
+ *           used.
+ * @param key The key structure.
+ * @param blockSize The block size of the cipher.
+ * @param p The pool to use.
+ * @return Returns APR_ENOIV if an initialisation vector is required but not specified.
+ *         Returns APR_EINIT if the backend failed to initialise the context. Returns
+ *         APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_block_encrypt_init(apr_crypto_block_t **ctx,
+        const unsigned char **iv, const apr_crypto_key_t *key,
+        apr_size_t *blockSize, apr_pool_t *p)
+{
+    PRErrorCode perr;
+    SECItem ivItem;
+    unsigned char * usedIv;
+    apr_crypto_block_t *block = *ctx;
+    if (!block) {
+        *ctx = block = apr_pcalloc(p, sizeof(apr_crypto_block_t));
+    }
+    if (!block) {
+        return APR_ENOMEM;
+    }
+    block->f = key->f;
+    block->pool = p;
+    block->provider = key->provider;
+
+    apr_pool_cleanup_register(p, block, crypto_block_cleanup_helper,
+            apr_pool_cleanup_null);
+
+    if (key->ivSize) {
+        if (iv == NULL) {
+            return APR_ENOIV;
+        }
+        if (*iv == NULL) {
+            SECStatus s;
+            usedIv = apr_pcalloc(p, key->ivSize);
+            if (!usedIv) {
+                return APR_ENOMEM;
+            }
+            apr_crypto_clear(p, usedIv, key->ivSize);
+            s = PK11_GenerateRandom(usedIv, key->ivSize);
+            if (s != SECSuccess) {
+                return APR_ENOIV;
+            }
+            *iv = usedIv;
+        }
+        else {
+            usedIv = (unsigned char *) *iv;
+        }
+        ivItem.data = usedIv;
+        ivItem.len = key->ivSize;
+        block->secParam = PK11_ParamFromIV(key->cipherMech, &ivItem);
+    }
+    else {
+        block->secParam = PK11_GenerateNewParam(key->cipherMech, key->symKey);
+    }
+    block->blockSize = PK11_GetBlockSize(key->cipherMech, block->secParam);
+    block->ctx = PK11_CreateContextBySymKey(key->cipherMech, CKA_ENCRYPT,
+            key->symKey, block->secParam);
+
+    /* did an error occur? */
+    perr = PORT_GetError();
+    if (perr || !block->ctx) {
+        key->f->result->rc = perr;
+        key->f->result->msg = PR_ErrorToName(perr);
+        return APR_EINIT;
+    }
+
+    if (blockSize) {
+        *blockSize = PK11_GetBlockSize(key->cipherMech, block->secParam);
+    }
+
+    return APR_SUCCESS;
+
+}
+
+/**
+ * @brief Encrypt data provided by in, write it to out.
+ * @note The number of bytes written will be written to outlen. If
+ *       out is NULL, outlen will contain the maximum size of the
+ *       buffer needed to hold the data, including any data
+ *       generated by apr_crypto_block_encrypt_finish below. If *out points
+ *       to NULL, a buffer sufficiently large will be created from
+ *       the pool provided. If *out points to a not-NULL value, this
+ *       value will be used as a buffer instead.
+ * @param out Address of a buffer to which data will be written,
+ *        see note.
+ * @param outlen Length of the output will be written here.
+ * @param in Address of the buffer to read.
+ * @param inlen Length of the buffer to read.
+ * @param ctx The block context to use.
+ * @return APR_ECRYPT if an error occurred. Returns APR_ENOTIMPL if
+ *         not implemented.
+ */
+static apr_status_t crypto_block_encrypt(unsigned char **out,
+        apr_size_t *outlen, const unsigned char *in, apr_size_t inlen,
+        apr_crypto_block_t *block)
+{
+
+    unsigned char *buffer;
+    int outl = (int) *outlen;
+    SECStatus s;
+    if (!out) {
+        *outlen = inlen + block->blockSize;
+        return APR_SUCCESS;
+    }
+    if (!*out) {
+        buffer = apr_palloc(block->pool, inlen + block->blockSize);
+        if (!buffer) {
+            return APR_ENOMEM;
+        }
+        apr_crypto_clear(block->pool, buffer, inlen + block->blockSize);
+        *out = buffer;
+    }
+
+    s = PK11_CipherOp(block->ctx, *out, &outl, inlen, (unsigned char*) in,
+            inlen);
+    if (s != SECSuccess) {
+        PRErrorCode perr = PORT_GetError();
+        if (perr) {
+            block->f->result->rc = perr;
+            block->f->result->msg = PR_ErrorToName(perr);
+        }
+        return APR_ECRYPT;
+    }
+    *outlen = outl;
+
+    return APR_SUCCESS;
+
+}
+
+/**
+ * @brief Encrypt final data block, write it to out.
+ * @note If necessary the final block will be written out after being
+ *       padded. Typically the final block will be written to the
+ *       same buffer used by apr_crypto_block_encrypt, offset by the
+ *       number of bytes returned as actually written by the
+ *       apr_crypto_block_encrypt() call. After this call, the context
+ *       is cleaned and can be reused by apr_crypto_block_encrypt_init().
+ * @param out Address of a buffer to which data will be written. This
+ *            buffer must already exist, and is usually the same
+ *            buffer used by apr_evp_crypt(). See note.
+ * @param outlen Length of the output will be written here.
+ * @param ctx The block context to use.
+ * @return APR_ECRYPT if an error occurred.
+ * @return APR_EPADDING if padding was enabled and the block was incorrectly
+ *         formatted.
+ * @return APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_block_encrypt_finish(unsigned char *out,
+        apr_size_t *outlen, apr_crypto_block_t *block)
+{
+
+    apr_status_t rv = APR_SUCCESS;
+    unsigned int outl = *outlen;
+
+    SECStatus s = PK11_DigestFinal(block->ctx, out, &outl, block->blockSize);
+    *outlen = outl;
+
+    if (s != SECSuccess) {
+        PRErrorCode perr = PORT_GetError();
+        if (perr) {
+            block->f->result->rc = perr;
+            block->f->result->msg = PR_ErrorToName(perr);
+        }
+        rv = APR_ECRYPT;
+    }
+    crypto_block_cleanup(block);
+
+    return rv;
+
+}
+
+/**
+ * @brief Initialise a context for decrypting arbitrary data using the given key.
+ * @note If *ctx is NULL, a apr_crypto_block_t will be created from a pool. If
+ *       *ctx is not NULL, *ctx must point at a previously created structure.
+ * @param ctx The block context returned, see note.
+ * @param blockSize The block size of the cipher.
+ * @param iv Optional initialisation vector. If the buffer pointed to is NULL,
+ *           an IV will be created at random, in space allocated from the pool.
+ *           If the buffer is not NULL, the IV in the buffer will be used.
+ * @param key The key structure.
+ * @param p The pool to use.
+ * @return Returns APR_ENOIV if an initialisation vector is required but not specified.
+ *         Returns APR_EINIT if the backend failed to initialise the context. Returns
+ *         APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_block_decrypt_init(apr_crypto_block_t **ctx,
+        apr_size_t *blockSize, const unsigned char *iv,
+        const apr_crypto_key_t *key, apr_pool_t *p)
+{
+    PRErrorCode perr;
+    apr_crypto_block_t *block = *ctx;
+    if (!block) {
+        *ctx = block = apr_pcalloc(p, sizeof(apr_crypto_block_t));
+    }
+    if (!block) {
+        return APR_ENOMEM;
+    }
+    block->f = key->f;
+    block->pool = p;
+    block->provider = key->provider;
+
+    apr_pool_cleanup_register(p, block, crypto_block_cleanup_helper,
+            apr_pool_cleanup_null);
+
+    if (key->ivSize) {
+        SECItem ivItem;
+        if (iv == NULL) {
+            return APR_ENOIV; /* Cannot initialise without an IV */
+        }
+        ivItem.data = (unsigned char*) iv;
+        ivItem.len = key->ivSize;
+        block->secParam = PK11_ParamFromIV(key->cipherMech, &ivItem);
+    }
+    else {
+        block->secParam = PK11_GenerateNewParam(key->cipherMech, key->symKey);
+    }
+    block->blockSize = PK11_GetBlockSize(key->cipherMech, block->secParam);
+    block->ctx = PK11_CreateContextBySymKey(key->cipherMech, CKA_DECRYPT,
+            key->symKey, block->secParam);
+
+    /* did an error occur? */
+    perr = PORT_GetError();
+    if (perr || !block->ctx) {
+        key->f->result->rc = perr;
+        key->f->result->msg = PR_ErrorToName(perr);
+        return APR_EINIT;
+    }
+
+    if (blockSize) {
+        *blockSize = PK11_GetBlockSize(key->cipherMech, block->secParam);
+    }
+
+    return APR_SUCCESS;
+
+}
+
+/**
+ * @brief Decrypt data provided by in, write it to out.
+ * @note The number of bytes written will be written to outlen. If
+ *       out is NULL, outlen will contain the maximum size of the
+ *       buffer needed to hold the data, including any data
+ *       generated by apr_crypto_block_decrypt_finish below. If *out points
+ *       to NULL, a buffer sufficiently large will be created from
+ *       the pool provided. If *out points to a not-NULL value, this
+ *       value will be used as a buffer instead.
+ * @param out Address of a buffer to which data will be written,
+ *        see note.
+ * @param outlen Length of the output will be written here.
+ * @param in Address of the buffer to read.
+ * @param inlen Length of the buffer to read.
+ * @param ctx The block context to use.
+ * @return APR_ECRYPT if an error occurred. Returns APR_ENOTIMPL if
+ *         not implemented.
+ */
+static apr_status_t crypto_block_decrypt(unsigned char **out,
+        apr_size_t *outlen, const unsigned char *in, apr_size_t inlen,
+        apr_crypto_block_t *block)
+{
+
+    unsigned char *buffer;
+    int outl = (int) *outlen;
+    SECStatus s;
+    if (!out) {
+        *outlen = inlen + block->blockSize;
+        return APR_SUCCESS;
+    }
+    if (!*out) {
+        buffer = apr_palloc(block->pool, inlen + block->blockSize);
+        if (!buffer) {
+            return APR_ENOMEM;
+        }
+        apr_crypto_clear(block->pool, buffer, inlen + block->blockSize);
+        *out = buffer;
+    }
+
+    s = PK11_CipherOp(block->ctx, *out, &outl, inlen, (unsigned char*) in,
+            inlen);
+    if (s != SECSuccess) {
+        PRErrorCode perr = PORT_GetError();
+        if (perr) {
+            block->f->result->rc = perr;
+            block->f->result->msg = PR_ErrorToName(perr);
+        }
+        return APR_ECRYPT;
+    }
+    *outlen = outl;
+
+    return APR_SUCCESS;
+
+}
+
+/**
+ * @brief Decrypt final data block, write it to out.
+ * @note If necessary the final block will be written out after being
+ *       padded. Typically the final block will be written to the
+ *       same buffer used by apr_crypto_block_decrypt, offset by the
+ *       number of bytes returned as actually written by the
+ *       apr_crypto_block_decrypt() call. After this call, the context
+ *       is cleaned and can be reused by apr_crypto_block_decrypt_init().
+ * @param out Address of a buffer to which data will be written. This
+ *            buffer must already exist, and is usually the same
+ *            buffer used by apr_evp_crypt(). See note.
+ * @param outlen Length of the output will be written here.
+ * @param ctx The block context to use.
+ * @return APR_ECRYPT if an error occurred.
+ * @return APR_EPADDING if padding was enabled and the block was incorrectly
+ *         formatted.
+ * @return APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_block_decrypt_finish(unsigned char *out,
+        apr_size_t *outlen, apr_crypto_block_t *block)
+{
+
+    apr_status_t rv = APR_SUCCESS;
+    unsigned int outl = *outlen;
+
+    SECStatus s = PK11_DigestFinal(block->ctx, out, &outl, block->blockSize);
+    *outlen = outl;
+
+    if (s != SECSuccess) {
+        PRErrorCode perr = PORT_GetError();
+        if (perr) {
+            block->f->result->rc = perr;
+            block->f->result->msg = PR_ErrorToName(perr);
+        }
+        rv = APR_ECRYPT;
+    }
+    crypto_block_cleanup(block);
+
+    return rv;
+
+}
+
+/**
+ * NSS module.
+ */
+APR_MODULE_DECLARE_DATA const apr_crypto_driver_t apr_crypto_nss_driver = {
+    "nss", crypto_init, crypto_make, crypto_get_block_key_types,
+    crypto_get_block_key_modes, crypto_passphrase,
+    crypto_block_encrypt_init, crypto_block_encrypt,
+    crypto_block_encrypt_finish, crypto_block_decrypt_init,
+    crypto_block_decrypt, crypto_block_decrypt_finish,
+    crypto_block_cleanup, crypto_cleanup, crypto_shutdown, crypto_error,
+    crypto_key
+};
+
+#endif
diff --git a/crypto/apr_crypto_nss.dsp b/crypto/apr_crypto_nss.dsp
new file mode 100644
index 00000000000..663b240c47b
--- /dev/null
+++ b/crypto/apr_crypto_nss.dsp
@@ -0,0 +1,203 @@
+# Microsoft Developer Studio Project File - Name="apr_crypto_nss" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=apr_crypto_nss - 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 "apr_crypto_nss.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 "apr_crypto_nss.mak" CFG="apr_crypto_nss - Win32 Release"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "apr_crypto_nss - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_crypto_nss - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_crypto_nss - x64 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_crypto_nss - x64 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)" == "apr_crypto_nss - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /Zi /O2 /Oy- /I "../include" /I "../../apr/include" /I "../include/private" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_NSS=1 /D HAVE_NSS_H=1 /D HAVE_PK11PUB_H=1 /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_crypto_nss_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /fo"Release/apr_crypto_nss-1.res" /d DLL_NAME="apr_crypto_nss" /d "NDEBUG" /d "APU_VERSION_ONLY" /I "../include" /I "../../apr/include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib nss3.lib nspr4.lib /nologo /base:"0x6F110000" /subsystem:windows /dll /incremental:no /debug /opt:ref
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib nss3.lib nspr4.lib nspr4.lib /nologo /base:"0x6F110000" /subsystem:windows /dll /incremental:no /debug /out:"Release\apr_crypto_nss-1.dll" /pdb:"Release\apr_crypto_nss-1.pdb" /implib:"Release\apr_crypto_nss-1.lib" /MACHINE:X86 /opt:ref
+# Begin Special Build Tool
+TargetPath=Release\apr_crypto_nss-1.dll
+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)" == "apr_crypto_nss - 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 /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /EHsc /c
+# ADD CPP /nologo /MDd /W3 /Zi /Od /I "../include" /I "../../apr/include" /I "../include/private" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_NSS=1 /D HAVE_NSS_H=1 /D HAVE_PK11PUB_H=1 /D /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_crypto_nss_src" /FD /EHsc /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /fo"Debug/apr_crypto_nss-1.res" /d DLL_NAME="apr_crypto_nss" /d "_DEBUG" /d "APU_VERSION_ONLY" /I "../include" /I "../../apr/include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib nss3.lib nspr4.lib /nologo /base:"0x6F110000" /subsystem:windows /dll /incremental:no /debug
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib nss3.lib nspr4.lib /nologo /base:"0x6F110000" /subsystem:windows /dll /incremental:no /debug /out:"Debug\apr_crypto_nss-1.dll" /pdb:"Debug\apr_crypto_nss-1.pdb" /implib:"Debug\apr_crypto_nss-1.lib" /MACHINE:X86
+# Begin Special Build Tool
+TargetPath=Debug\apr_crypto_nss-1.dll
+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)" == "apr_crypto_nss - x64 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "x64\Release"
+# PROP BASE Intermediate_Dir "x64\Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "x64\Release"
+# PROP Intermediate_Dir "x64\Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /Zi /O2 /Oy- /I "../include" /I "../../apr/include" /I "../include/private" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_NSS=1 /D HAVE_NSS_H=1 /D HAVE_PK11PUB_H=1 /D /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_crypto_nss_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /fo"x64/Release/apr_crypto_nss-1.res" /d DLL_NAME="apr_crypto_nss" /d "NDEBUG" /d "APU_VERSION_ONLY" /I "../include" /I "../../apr/include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib nss3.lib nspr4.lib /nologo /base:"0x6F110000" /subsystem:windows /dll /incremental:no /debug /opt:ref
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib nss3.lib nspr4.lib /nologo /base:"0x6F110000" /subsystem:windows /dll /incremental:no /debug /out:"x64\Release\apr_crypto_nss-1.dll" /pdb:"x64\Release\apr_crypto_nss-1.pdb" /implib:"x64\Release\apr_crypto_nss-1.lib" /MACHINE:X64 /opt:ref
+# Begin Special Build Tool
+TargetPath=x64\Release\apr_crypto_nss-1.dll
+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)" == "apr_crypto_nss - x64 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "x64\Debug"
+# PROP BASE Intermediate_Dir "x64\Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "x64\Debug"
+# PROP Intermediate_Dir "x64\Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /EHsc /c
+# ADD CPP /nologo /MDd /W3 /Zi /Od /I "../include" /I "../../apr/include" /I "../include/private" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_NSS=1 /D HAVE_NSS_H=1 /D HAVE_PK11PUB_H=1 /D /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_crypto_nss_src" /FD /EHsc /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /fo"x64/Debug/apr_crypto_nss-1.res" /d DLL_NAME="apr_crypto_nss" /d "_DEBUG" /d "APU_VERSION_ONLY" /I "../include" /I "../../apr/include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib nss3.lib nspr4.lib /nologo /base:"0x6F110000" /subsystem:windows /dll /incremental:no /debug
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib nss3.lib nspr4.lib /nologo /base:"0x6F110000" /subsystem:windows /dll /incremental:no /debug /out:"x64\Debug\apr_crypto_nss-1.dll" /pdb:"x64\Debug\apr_crypto_nss-1.pdb" /implib:"x64\Debug\apr_crypto_nss-1.lib" /MACHINE:X64
+# Begin Special Build Tool
+TargetPath=x64\Debug\apr_crypto_nss-1.dll
+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 "apr_crypto_nss - Win32 Release"
+# Name "apr_crypto_nss - Win32 Debug"
+# Name "apr_crypto_nss - x64 Release"
+# Name "apr_crypto_nss - x64 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\apr_crypto_nss.c
+# End Source File
+# End Group
+# Begin Group "Public Header Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\include\apr_crypto.h
+# End Source File
+# End Group
+# Begin Group "Internal Header Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\include\private\apu_config.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\private\apu_internal.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\libaprutil.rc
+# End Source File
+# End Target
+# End Project
diff --git a/crypto/apr_crypto_openssl.c b/crypto/apr_crypto_openssl.c
new file mode 100644
index 00000000000..db4d5354558
--- /dev/null
+++ b/crypto/apr_crypto_openssl.c
@@ -0,0 +1,952 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_lib.h"
+#include "apu.h"
+#include "apr_private.h"
+#include "apu_errno.h"
+
+#include <ctype.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "apr_strings.h"
+#include "apr_time.h"
+#include "apr_buckets.h"
+
+#include "apr_crypto_internal.h"
+
+#if APU_HAVE_CRYPTO
+
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+#include <openssl/engine.h>
+
+#define LOG_PREFIX "apr_crypto_openssl: "
+
+#ifndef APR_USE_OPENSSL_PRE_1_1_API
+#if defined(LIBRESSL_VERSION_NUMBER)
+/* LibreSSL declares OPENSSL_VERSION_NUMBER == 2.0 but does not include most
+ * changes from OpenSSL >= 1.1 (new functions, macros, deprecations, ...), so
+ * we have to work around this...
+ */
+#define APR_USE_OPENSSL_PRE_1_1_API (1)
+#else
+#define APR_USE_OPENSSL_PRE_1_1_API (OPENSSL_VERSION_NUMBER < 0x10100000L)
+#endif
+#endif
+
+struct apr_crypto_t {
+    apr_pool_t *pool;
+    const apr_crypto_driver_t *provider;
+    apu_err_t *result;
+    apr_crypto_config_t *config;
+    apr_hash_t *types;
+    apr_hash_t *modes;
+};
+
+struct apr_crypto_config_t {
+    ENGINE *engine;
+};
+
+struct apr_crypto_key_t {
+    apr_pool_t *pool;
+    const apr_crypto_driver_t *provider;
+    const apr_crypto_t *f;
+    const EVP_CIPHER * cipher;
+    unsigned char *key;
+    int keyLen;
+    int doPad;
+    int ivSize;
+};
+
+struct apr_crypto_block_t {
+    apr_pool_t *pool;
+    const apr_crypto_driver_t *provider;
+    const apr_crypto_t *f;
+    EVP_CIPHER_CTX *cipherCtx;
+    int initialised;
+    int ivSize;
+    int blockSize;
+    int doPad;
+};
+
+static struct apr_crypto_block_key_type_t key_types[] =
+{
+{ APR_KEY_3DES_192, 24, 8, 8 },
+{ APR_KEY_AES_128, 16, 16, 16 },
+{ APR_KEY_AES_192, 24, 16, 16 },
+{ APR_KEY_AES_256, 32, 16, 16 } };
+
+static struct apr_crypto_block_key_mode_t key_modes[] =
+{
+{ APR_MODE_ECB },
+{ APR_MODE_CBC } };
+
+/* sufficient space to wrap a key */
+#define BUFFER_SIZE 128
+
+/**
+ * Fetch the most recent error from this driver.
+ */
+static apr_status_t crypto_error(const apu_err_t **result,
+        const apr_crypto_t *f)
+{
+    *result = f->result;
+    return APR_SUCCESS;
+}
+
+/**
+ * Shutdown the crypto library and release resources.
+ */
+static apr_status_t crypto_shutdown(void)
+{
+#if APR_USE_OPENSSL_PRE_1_1_API
+    ERR_free_strings();
+    EVP_cleanup();
+    ENGINE_cleanup();
+#endif
+    return APR_SUCCESS;
+}
+
+static apr_status_t crypto_shutdown_helper(void *data)
+{
+    return crypto_shutdown();
+}
+
+/**
+ * Initialise the crypto library and perform one time initialisation.
+ */
+static apr_status_t crypto_init(apr_pool_t *pool, const char *params,
+        const apu_err_t **result)
+{
+#if APR_USE_OPENSSL_PRE_1_1_API
+    (void)CRYPTO_malloc_init();
+    ERR_load_crypto_strings();
+    /* SSL_load_error_strings(); */
+    OpenSSL_add_all_algorithms();
+#else
+    OPENSSL_malloc_init();
+#endif
+    ENGINE_load_builtin_engines();
+    ENGINE_register_all_complete();
+
+    apr_pool_cleanup_register(pool, pool, crypto_shutdown_helper,
+            apr_pool_cleanup_null);
+
+    return APR_SUCCESS;
+}
+
+/**
+ * @brief Clean encryption / decryption context.
+ * @note After cleanup, a context is free to be reused if necessary.
+ * @param ctx The block context to use.
+ * @return Returns APR_ENOTIMPL if not supported.
+ */
+static apr_status_t crypto_block_cleanup(apr_crypto_block_t *ctx)
+{
+
+    if (ctx->initialised) {
+        EVP_CIPHER_CTX_free(ctx->cipherCtx);
+        ctx->initialised = 0;
+    }
+
+    return APR_SUCCESS;
+
+}
+
+static apr_status_t crypto_block_cleanup_helper(void *data)
+{
+    apr_crypto_block_t *block = (apr_crypto_block_t *) data;
+    return crypto_block_cleanup(block);
+}
+
+/**
+ * @brief Clean encryption / decryption context.
+ * @note After cleanup, a context is free to be reused if necessary.
+ * @param f The context to use.
+ * @return Returns APR_ENOTIMPL if not supported.
+ */
+static apr_status_t crypto_cleanup(apr_crypto_t *f)
+{
+
+    if (f->config->engine) {
+        ENGINE_finish(f->config->engine);
+        ENGINE_free(f->config->engine);
+        f->config->engine = NULL;
+    }
+    return APR_SUCCESS;
+
+}
+
+static apr_status_t crypto_cleanup_helper(void *data)
+{
+    apr_crypto_t *f = (apr_crypto_t *) data;
+    return crypto_cleanup(f);
+}
+
+/**
+ * @brief Create a context for supporting encryption. Keys, certificates,
+ *        algorithms and other parameters will be set per context. More than
+ *        one context can be created at one time. A cleanup will be automatically
+ *        registered with the given pool to guarantee a graceful shutdown.
+ * @param f - context pointer will be written here
+ * @param provider - provider to use
+ * @param params - array of key parameters
+ * @param pool - process pool
+ * @return APR_ENOENGINE when the engine specified does not exist. APR_EINITENGINE
+ * if the engine cannot be initialised.
+ */
+static apr_status_t crypto_make(apr_crypto_t **ff,
+        const apr_crypto_driver_t *provider, const char *params,
+        apr_pool_t *pool)
+{
+    apr_crypto_config_t *config = NULL;
+    apr_crypto_t *f = apr_pcalloc(pool, sizeof(apr_crypto_t));
+
+    const char *engine = NULL;
+
+    struct {
+        const char *field;
+        const char *value;
+        int set;
+    } fields[] = {
+        { "engine", NULL, 0 },
+        { NULL, NULL, 0 }
+    };
+    const char *ptr;
+    size_t klen;
+    char **elts = NULL;
+    char *elt;
+    int i = 0, j;
+    apr_status_t status;
+
+    if (params) {
+        if (APR_SUCCESS != (status = apr_tokenize_to_argv(params, &elts, pool))) {
+            return status;
+        }
+        while ((elt = elts[i])) {
+            ptr = strchr(elt, '=');
+            if (ptr) {
+                for (klen = ptr - elt; klen && apr_isspace(elt[klen - 1]); --klen)
+                    ;
+                ptr++;
+            }
+            else {
+                for (klen = strlen(elt); klen && apr_isspace(elt[klen - 1]); --klen)
+                    ;
+            }
+            elt[klen] = 0;
+
+            for (j = 0; fields[j].field != NULL; ++j) {
+                if (!strcasecmp(fields[j].field, elt)) {
+                    fields[j].set = 1;
+                    if (ptr) {
+                        fields[j].value = ptr;
+                    }
+                    break;
+                }
+            }
+
+            i++;
+        }
+        engine = fields[0].value;
+    }
+
+    if (!f) {
+        return APR_ENOMEM;
+    }
+    *ff = f;
+    f->pool = pool;
+    f->provider = provider;
+    config = f->config = apr_pcalloc(pool, sizeof(apr_crypto_config_t));
+    if (!config) {
+        return APR_ENOMEM;
+    }
+
+    f->result = apr_pcalloc(pool, sizeof(apu_err_t));
+    if (!f->result) {
+        return APR_ENOMEM;
+    }
+
+    f->types = apr_hash_make(pool);
+    if (!f->types) {
+        return APR_ENOMEM;
+    }
+    apr_hash_set(f->types, "3des192", APR_HASH_KEY_STRING, &(key_types[0]));
+    apr_hash_set(f->types, "aes128", APR_HASH_KEY_STRING, &(key_types[1]));
+    apr_hash_set(f->types, "aes192", APR_HASH_KEY_STRING, &(key_types[2]));
+    apr_hash_set(f->types, "aes256", APR_HASH_KEY_STRING, &(key_types[3]));
+
+    f->modes = apr_hash_make(pool);
+    if (!f->modes) {
+        return APR_ENOMEM;
+    }
+    apr_hash_set(f->modes, "ecb", APR_HASH_KEY_STRING, &(key_modes[0]));
+    apr_hash_set(f->modes, "cbc", APR_HASH_KEY_STRING, &(key_modes[1]));
+
+    apr_pool_cleanup_register(pool, f, crypto_cleanup_helper,
+            apr_pool_cleanup_null);
+
+    if (engine) {
+        config->engine = ENGINE_by_id(engine);
+        if (!config->engine) {
+            return APR_ENOENGINE;
+        }
+        if (!ENGINE_init(config->engine)) {
+            ENGINE_free(config->engine);
+            config->engine = NULL;
+            return APR_EINITENGINE;
+        }
+    }
+
+    return APR_SUCCESS;
+
+}
+
+/**
+ * @brief Get a hash table of key types, keyed by the name of the type against
+ * a pointer to apr_crypto_block_key_type_t.
+ *
+ * @param types - hashtable of key types keyed to constants.
+ * @param f - encryption context
+ * @return APR_SUCCESS for success
+ */
+static apr_status_t crypto_get_block_key_types(apr_hash_t **types,
+        const apr_crypto_t *f)
+{
+    *types = f->types;
+    return APR_SUCCESS;
+}
+
+/**
+ * @brief Get a hash table of key modes, keyed by the name of the mode against
+ * a pointer to apr_crypto_block_key_mode_t.
+ *
+ * @param modes - hashtable of key modes keyed to constants.
+ * @param f - encryption context
+ * @return APR_SUCCESS for success
+ */
+static apr_status_t crypto_get_block_key_modes(apr_hash_t **modes,
+        const apr_crypto_t *f)
+{
+    *modes = f->modes;
+    return APR_SUCCESS;
+}
+
+/*
+ * Work out which mechanism to use.
+ */
+static apr_status_t crypto_cipher_mechanism(apr_crypto_key_t *key,
+        const apr_crypto_block_key_type_e type,
+        const apr_crypto_block_key_mode_e mode, const int doPad, apr_pool_t *p)
+{
+    /* determine the cipher to be used */
+    switch (type) {
+
+    case (APR_KEY_3DES_192):
+
+        /* A 3DES key */
+        if (mode == APR_MODE_CBC) {
+            key->cipher = EVP_des_ede3_cbc();
+        }
+        else {
+            key->cipher = EVP_des_ede3_ecb();
+        }
+        break;
+
+    case (APR_KEY_AES_128):
+
+        if (mode == APR_MODE_CBC) {
+            key->cipher = EVP_aes_128_cbc();
+        }
+        else {
+            key->cipher = EVP_aes_128_ecb();
+        }
+        break;
+
+    case (APR_KEY_AES_192):
+
+        if (mode == APR_MODE_CBC) {
+            key->cipher = EVP_aes_192_cbc();
+        }
+        else {
+            key->cipher = EVP_aes_192_ecb();
+        }
+        break;
+
+    case (APR_KEY_AES_256):
+
+        if (mode == APR_MODE_CBC) {
+            key->cipher = EVP_aes_256_cbc();
+        }
+        else {
+            key->cipher = EVP_aes_256_ecb();
+        }
+        break;
+
+    default:
+
+        /* unknown key type, give up */
+        return APR_EKEYTYPE;
+
+    }
+
+    /* find the length of the key we need */
+    key->keyLen = EVP_CIPHER_key_length(key->cipher);
+
+    /* make space for the key */
+    key->key = apr_pcalloc(p, key->keyLen);
+    if (!key->key) {
+        return APR_ENOMEM;
+    }
+    apr_crypto_clear(p, key->key, key->keyLen);
+
+    return APR_SUCCESS;
+}
+
+/**
+ * @brief Create a key from the provided secret or passphrase. The key is cleaned
+ *        up when the context is cleaned, and may be reused with multiple encryption
+ *        or decryption operations.
+ * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
+ *       *key is not NULL, *key must point at a previously created structure.
+ * @param key The key returned, see note.
+ * @param rec The key record, from which the key will be derived.
+ * @param f The context to use.
+ * @param p The pool to use.
+ * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
+ *         error occurred while generating the key. APR_ENOCIPHER if the type or mode
+ *         is not supported by the particular backend. APR_EKEYTYPE if the key type is
+ *         not known. APR_EPADDING if padding was requested but is not supported.
+ *         APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_key(apr_crypto_key_t **k,
+        const apr_crypto_key_rec_t *rec, const apr_crypto_t *f, apr_pool_t *p)
+{
+    apr_crypto_key_t *key = *k;
+    apr_status_t rv;
+
+    if (!key) {
+        *k = key = apr_pcalloc(p, sizeof *key);
+        if (!key) {
+            return APR_ENOMEM;
+        }
+    }
+
+    key->f = f;
+    key->provider = f->provider;
+
+    /* decide on what cipher mechanism we will be using */
+    rv = crypto_cipher_mechanism(key, rec->type, rec->mode, rec->pad, p);
+    if (APR_SUCCESS != rv) {
+        return rv;
+    }
+
+    switch (rec->ktype) {
+
+    case APR_CRYPTO_KTYPE_PASSPHRASE: {
+
+        /* generate the key */
+        if (PKCS5_PBKDF2_HMAC_SHA1(rec->k.passphrase.pass,
+                rec->k.passphrase.passLen,
+                (unsigned char *) rec->k.passphrase.salt,
+                rec->k.passphrase.saltLen, rec->k.passphrase.iterations,
+                key->keyLen, key->key) == 0) {
+            return APR_ENOKEY;
+        }
+
+        break;
+    }
+
+    case APR_CRYPTO_KTYPE_SECRET: {
+
+        /* sanity check - key correct size? */
+        if (rec->k.secret.secretLen != key->keyLen) {
+            return APR_EKEYLENGTH;
+        }
+
+        /* copy the key */
+        memcpy(key->key, rec->k.secret.secret, rec->k.secret.secretLen);
+
+        break;
+    }
+
+    default: {
+
+        return APR_ENOKEY;
+
+    }
+    }
+
+    key->doPad = rec->pad;
+
+    /* note: openssl incorrectly returns non zero IV size values for ECB
+     * algorithms, so work around this by ignoring the IV size.
+     */
+    if (APR_MODE_ECB != rec->mode) {
+        key->ivSize = EVP_CIPHER_iv_length(key->cipher);
+    }
+
+    return APR_SUCCESS;
+}
+
+/**
+ * @brief Create a key from the given passphrase. By default, the PBKDF2
+ *        algorithm is used to generate the key from the passphrase. It is expected
+ *        that the same pass phrase will generate the same key, regardless of the
+ *        backend crypto platform used. The key is cleaned up when the context
+ *        is cleaned, and may be reused with multiple encryption or decryption
+ *        operations.
+ * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
+ *       *key is not NULL, *key must point at a previously created structure.
+ * @param key The key returned, see note.
+ * @param ivSize The size of the initialisation vector will be returned, based
+ *               on whether an IV is relevant for this type of crypto.
+ * @param pass The passphrase to use.
+ * @param passLen The passphrase length in bytes
+ * @param salt The salt to use.
+ * @param saltLen The salt length in bytes
+ * @param type 3DES_192, AES_128, AES_192, AES_256.
+ * @param mode Electronic Code Book / Cipher Block Chaining.
+ * @param doPad Pad if necessary.
+ * @param iterations Iteration count
+ * @param f The context to use.
+ * @param p The pool to use.
+ * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
+ *         error occurred while generating the key. APR_ENOCIPHER if the type or mode
+ *         is not supported by the particular backend. APR_EKEYTYPE if the key type is
+ *         not known. APR_EPADDING if padding was requested but is not supported.
+ *         APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_passphrase(apr_crypto_key_t **k, apr_size_t *ivSize,
+        const char *pass, apr_size_t passLen, const unsigned char * salt,
+        apr_size_t saltLen, const apr_crypto_block_key_type_e type,
+        const apr_crypto_block_key_mode_e mode, const int doPad,
+        const int iterations, const apr_crypto_t *f, apr_pool_t *p)
+{
+    apr_crypto_key_t *key = *k;
+    apr_status_t rv;
+
+    if (!key) {
+        *k = key = apr_pcalloc(p, sizeof *key);
+        if (!key) {
+            return APR_ENOMEM;
+        }
+    }
+
+    key->f = f;
+    key->provider = f->provider;
+
+    /* decide on what cipher mechanism we will be using */
+    rv = crypto_cipher_mechanism(key, type, mode, doPad, p);
+    if (APR_SUCCESS != rv) {
+        return rv;
+    }
+
+    /* generate the key */
+    if (PKCS5_PBKDF2_HMAC_SHA1(pass, passLen, (unsigned char *) salt, saltLen,
+            iterations, key->keyLen, key->key) == 0) {
+        return APR_ENOKEY;
+    }
+
+    key->doPad = doPad;
+
+    /* note: openssl incorrectly returns non zero IV size values for ECB
+     * algorithms, so work around this by ignoring the IV size.
+     */
+    if (APR_MODE_ECB != mode) {
+        key->ivSize = EVP_CIPHER_iv_length(key->cipher);
+    }
+    if (ivSize) {
+        *ivSize = key->ivSize;
+    }
+
+    return APR_SUCCESS;
+}
+
+/**
+ * @brief Initialise a context for encrypting arbitrary data using the given key.
+ * @note If *ctx is NULL, a apr_crypto_block_t will be created from a pool. If
+ *       *ctx is not NULL, *ctx must point at a previously created structure.
+ * @param ctx The block context returned, see note.
+ * @param iv Optional initialisation vector. If the buffer pointed to is NULL,
+ *           an IV will be created at random, in space allocated from the pool.
+ *           If the buffer pointed to is not NULL, the IV in the buffer will be
+ *           used.
+ * @param key The key structure.
+ * @param blockSize The block size of the cipher.
+ * @param p The pool to use.
+ * @return Returns APR_ENOIV if an initialisation vector is required but not specified.
+ *         Returns APR_EINIT if the backend failed to initialise the context. Returns
+ *         APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_block_encrypt_init(apr_crypto_block_t **ctx,
+        const unsigned char **iv, const apr_crypto_key_t *key,
+        apr_size_t *blockSize, apr_pool_t *p)
+{
+    unsigned char *usedIv;
+    apr_crypto_config_t *config = key->f->config;
+    apr_crypto_block_t *block = *ctx;
+    if (!block) {
+        *ctx = block = apr_pcalloc(p, sizeof(apr_crypto_block_t));
+    }
+    if (!block) {
+        return APR_ENOMEM;
+    }
+    block->f = key->f;
+    block->pool = p;
+    block->provider = key->provider;
+
+    apr_pool_cleanup_register(p, block, crypto_block_cleanup_helper,
+            apr_pool_cleanup_null);
+
+    /* create a new context for encryption */
+    if (!block->initialised) {
+        block->cipherCtx = EVP_CIPHER_CTX_new();
+        block->initialised = 1;
+    }
+
+    /* generate an IV, if necessary */
+    usedIv = NULL;
+    if (key->ivSize) {
+        if (iv == NULL) {
+            return APR_ENOIV;
+        }
+        if (*iv == NULL) {
+            usedIv = apr_pcalloc(p, key->ivSize);
+            if (!usedIv) {
+                return APR_ENOMEM;
+            }
+            apr_crypto_clear(p, usedIv, key->ivSize);
+            if (!((RAND_status() == 1)
+                    && (RAND_bytes(usedIv, key->ivSize) == 1))) {
+                return APR_ENOIV;
+            }
+            *iv = usedIv;
+        }
+        else {
+            usedIv = (unsigned char *) *iv;
+        }
+    }
+
+    /* set up our encryption context */
+#if CRYPTO_OPENSSL_CONST_BUFFERS
+    if (!EVP_EncryptInit_ex(block->cipherCtx, key->cipher, config->engine,
+            key->key, usedIv)) {
+#else
+        if (!EVP_EncryptInit_ex(block->cipherCtx, key->cipher, config->engine, (unsigned char *) key->key, (unsigned char *) usedIv)) {
+#endif
+        return APR_EINIT;
+    }
+
+    /* Clear up any read padding */
+    if (!EVP_CIPHER_CTX_set_padding(block->cipherCtx, key->doPad)) {
+        return APR_EPADDING;
+    }
+
+    if (blockSize) {
+        *blockSize = EVP_CIPHER_block_size(key->cipher);
+    }
+
+    return APR_SUCCESS;
+
+}
+
+/**
+ * @brief Encrypt data provided by in, write it to out.
+ * @note The number of bytes written will be written to outlen. If
+ *       out is NULL, outlen will contain the maximum size of the
+ *       buffer needed to hold the data, including any data
+ *       generated by apr_crypto_block_encrypt_finish below. If *out points
+ *       to NULL, a buffer sufficiently large will be created from
+ *       the pool provided. If *out points to a not-NULL value, this
+ *       value will be used as a buffer instead.
+ * @param out Address of a buffer to which data will be written,
+ *        see note.
+ * @param outlen Length of the output will be written here.
+ * @param in Address of the buffer to read.
+ * @param inlen Length of the buffer to read.
+ * @param ctx The block context to use.
+ * @return APR_ECRYPT if an error occurred. Returns APR_ENOTIMPL if
+ *         not implemented.
+ */
+static apr_status_t crypto_block_encrypt(unsigned char **out,
+        apr_size_t *outlen, const unsigned char *in, apr_size_t inlen,
+        apr_crypto_block_t *ctx)
+{
+    int outl = *outlen;
+    unsigned char *buffer;
+
+    /* are we after the maximum size of the out buffer? */
+    if (!out) {
+        *outlen = inlen + EVP_MAX_BLOCK_LENGTH;
+        return APR_SUCCESS;
+    }
+
+    /* must we allocate the output buffer from a pool? */
+    if (!*out) {
+        buffer = apr_palloc(ctx->pool, inlen + EVP_MAX_BLOCK_LENGTH);
+        if (!buffer) {
+            return APR_ENOMEM;
+        }
+        apr_crypto_clear(ctx->pool, buffer, inlen + EVP_MAX_BLOCK_LENGTH);
+        *out = buffer;
+    }
+
+#if CRYPT_OPENSSL_CONST_BUFFERS
+    if (!EVP_EncryptUpdate(ctx->cipherCtx, (*out), &outl, in, inlen)) {
+#else
+    if (!EVP_EncryptUpdate(ctx->cipherCtx, (*out), &outl,
+            (unsigned char *) in, inlen)) {
+#endif
+#if APR_USE_OPENSSL_PRE_1_1_API
+        EVP_CIPHER_CTX_cleanup(ctx->cipherCtx);
+#else
+        EVP_CIPHER_CTX_reset(ctx->cipherCtx);
+#endif
+        return APR_ECRYPT;
+    }
+    *outlen = outl;
+
+    return APR_SUCCESS;
+
+}
+
+/**
+ * @brief Encrypt final data block, write it to out.
+ * @note If necessary the final block will be written out after being
+ *       padded. Typically the final block will be written to the
+ *       same buffer used by apr_crypto_block_encrypt, offset by the
+ *       number of bytes returned as actually written by the
+ *       apr_crypto_block_encrypt() call. After this call, the context
+ *       is cleaned and can be reused by apr_crypto_block_encrypt_init().
+ * @param out Address of a buffer to which data will be written. This
+ *            buffer must already exist, and is usually the same
+ *            buffer used by apr_evp_crypt(). See note.
+ * @param outlen Length of the output will be written here.
+ * @param ctx The block context to use.
+ * @return APR_ECRYPT if an error occurred.
+ * @return APR_EPADDING if padding was enabled and the block was incorrectly
+ *         formatted.
+ * @return APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_block_encrypt_finish(unsigned char *out,
+        apr_size_t *outlen, apr_crypto_block_t *ctx)
+{
+    apr_status_t rc = APR_SUCCESS;
+    int len = *outlen;
+
+    if (EVP_EncryptFinal_ex(ctx->cipherCtx, out, &len) == 0) {
+        rc = APR_EPADDING;
+    }
+    else {
+        *outlen = len;
+    }
+#if APR_USE_OPENSSL_PRE_1_1_API
+    EVP_CIPHER_CTX_cleanup(ctx->cipherCtx);
+#else
+    EVP_CIPHER_CTX_reset(ctx->cipherCtx);
+#endif
+
+    return rc;
+
+}
+
+/**
+ * @brief Initialise a context for decrypting arbitrary data using the given key.
+ * @note If *ctx is NULL, a apr_crypto_block_t will be created from a pool. If
+ *       *ctx is not NULL, *ctx must point at a previously created structure.
+ * @param ctx The block context returned, see note.
+ * @param blockSize The block size of the cipher.
+ * @param iv Optional initialisation vector. If the buffer pointed to is NULL,
+ *           an IV will be created at random, in space allocated from the pool.
+ *           If the buffer is not NULL, the IV in the buffer will be used.
+ * @param key The key structure.
+ * @param p The pool to use.
+ * @return Returns APR_ENOIV if an initialisation vector is required but not specified.
+ *         Returns APR_EINIT if the backend failed to initialise the context. Returns
+ *         APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_block_decrypt_init(apr_crypto_block_t **ctx,
+        apr_size_t *blockSize, const unsigned char *iv,
+        const apr_crypto_key_t *key, apr_pool_t *p)
+{
+    apr_crypto_config_t *config = key->f->config;
+    apr_crypto_block_t *block = *ctx;
+    if (!block) {
+        *ctx = block = apr_pcalloc(p, sizeof(apr_crypto_block_t));
+    }
+    if (!block) {
+        return APR_ENOMEM;
+    }
+    block->f = key->f;
+    block->pool = p;
+    block->provider = key->provider;
+
+    apr_pool_cleanup_register(p, block, crypto_block_cleanup_helper,
+            apr_pool_cleanup_null);
+
+    /* create a new context for encryption */
+    if (!block->initialised) {
+        block->cipherCtx = EVP_CIPHER_CTX_new();
+        block->initialised = 1;
+    }
+
+    /* generate an IV, if necessary */
+    if (key->ivSize) {
+        if (iv == NULL) {
+            return APR_ENOIV;
+        }
+    }
+
+    /* set up our encryption context */
+#if CRYPTO_OPENSSL_CONST_BUFFERS
+    if (!EVP_DecryptInit_ex(block->cipherCtx, key->cipher, config->engine,
+            key->key, iv)) {
+#else
+        if (!EVP_DecryptInit_ex(block->cipherCtx, key->cipher, config->engine, (unsigned char *) key->key, (unsigned char *) iv)) {
+#endif
+        return APR_EINIT;
+    }
+
+    /* Clear up any read padding */
+    if (!EVP_CIPHER_CTX_set_padding(block->cipherCtx, key->doPad)) {
+        return APR_EPADDING;
+    }
+
+    if (blockSize) {
+        *blockSize = EVP_CIPHER_block_size(key->cipher);
+    }
+
+    return APR_SUCCESS;
+
+}
+
+/**
+ * @brief Decrypt data provided by in, write it to out.
+ * @note The number of bytes written will be written to outlen. If
+ *       out is NULL, outlen will contain the maximum size of the
+ *       buffer needed to hold the data, including any data
+ *       generated by apr_crypto_block_decrypt_finish below. If *out points
+ *       to NULL, a buffer sufficiently large will be created from
+ *       the pool provided. If *out points to a not-NULL value, this
+ *       value will be used as a buffer instead.
+ * @param out Address of a buffer to which data will be written,
+ *        see note.
+ * @param outlen Length of the output will be written here.
+ * @param in Address of the buffer to read.
+ * @param inlen Length of the buffer to read.
+ * @param ctx The block context to use.
+ * @return APR_ECRYPT if an error occurred. Returns APR_ENOTIMPL if
+ *         not implemented.
+ */
+static apr_status_t crypto_block_decrypt(unsigned char **out,
+        apr_size_t *outlen, const unsigned char *in, apr_size_t inlen,
+        apr_crypto_block_t *ctx)
+{
+    int outl = *outlen;
+    unsigned char *buffer;
+
+    /* are we after the maximum size of the out buffer? */
+    if (!out) {
+        *outlen = inlen + EVP_MAX_BLOCK_LENGTH;
+        return APR_SUCCESS;
+    }
+
+    /* must we allocate the output buffer from a pool? */
+    if (!(*out)) {
+        buffer = apr_palloc(ctx->pool, inlen + EVP_MAX_BLOCK_LENGTH);
+        if (!buffer) {
+            return APR_ENOMEM;
+        }
+        apr_crypto_clear(ctx->pool, buffer, inlen + EVP_MAX_BLOCK_LENGTH);
+        *out = buffer;
+    }
+
+#if CRYPT_OPENSSL_CONST_BUFFERS
+    if (!EVP_DecryptUpdate(ctx->cipherCtx, *out, &outl, in, inlen)) {
+#else
+    if (!EVP_DecryptUpdate(ctx->cipherCtx, *out, &outl, (unsigned char *) in,
+            inlen)) {
+#endif
+#if APR_USE_OPENSSL_PRE_1_1_API
+        EVP_CIPHER_CTX_cleanup(ctx->cipherCtx);
+#else
+        EVP_CIPHER_CTX_reset(ctx->cipherCtx);
+#endif
+        return APR_ECRYPT;
+    }
+    *outlen = outl;
+
+    return APR_SUCCESS;
+
+}
+
+/**
+ * @brief Decrypt final data block, write it to out.
+ * @note If necessary the final block will be written out after being
+ *       padded. Typically the final block will be written to the
+ *       same buffer used by apr_crypto_block_decrypt, offset by the
+ *       number of bytes returned as actually written by the
+ *       apr_crypto_block_decrypt() call. After this call, the context
+ *       is cleaned and can be reused by apr_crypto_block_decrypt_init().
+ * @param out Address of a buffer to which data will be written. This
+ *            buffer must already exist, and is usually the same
+ *            buffer used by apr_evp_crypt(). See note.
+ * @param outlen Length of the output will be written here.
+ * @param ctx The block context to use.
+ * @return APR_ECRYPT if an error occurred.
+ * @return APR_EPADDING if padding was enabled and the block was incorrectly
+ *         formatted.
+ * @return APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_block_decrypt_finish(unsigned char *out,
+        apr_size_t *outlen, apr_crypto_block_t *ctx)
+{
+    apr_status_t rc = APR_SUCCESS;
+    int len = *outlen;
+
+    if (EVP_DecryptFinal_ex(ctx->cipherCtx, out, &len) == 0) {
+        rc = APR_EPADDING;
+    }
+    else {
+        *outlen = len;
+    }
+#if APR_USE_OPENSSL_PRE_1_1_API
+    EVP_CIPHER_CTX_cleanup(ctx->cipherCtx);
+#else
+    EVP_CIPHER_CTX_reset(ctx->cipherCtx);
+#endif
+
+    return rc;
+
+}
+
+/**
+ * OpenSSL module.
+ */
+APR_MODULE_DECLARE_DATA const apr_crypto_driver_t apr_crypto_openssl_driver = {
+    "openssl", crypto_init, crypto_make, crypto_get_block_key_types,
+    crypto_get_block_key_modes, crypto_passphrase,
+    crypto_block_encrypt_init, crypto_block_encrypt,
+    crypto_block_encrypt_finish, crypto_block_decrypt_init,
+    crypto_block_decrypt, crypto_block_decrypt_finish,
+    crypto_block_cleanup, crypto_cleanup, crypto_shutdown, crypto_error,
+    crypto_key
+};
+
+#endif
diff --git a/crypto/apr_crypto_openssl.dsp b/crypto/apr_crypto_openssl.dsp
new file mode 100644
index 00000000000..90114ce4352
--- /dev/null
+++ b/crypto/apr_crypto_openssl.dsp
@@ -0,0 +1,203 @@
+# Microsoft Developer Studio Project File - Name="apr_crypto_openssl" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=apr_crypto_openssl - 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 "apr_crypto_openssl.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 "apr_crypto_openssl.mak" CFG="apr_crypto_openssl - Win32 Release"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "apr_crypto_openssl - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_crypto_openssl - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_crypto_openssl - x64 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_crypto_openssl - x64 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)" == "apr_crypto_openssl - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /Zi /O2 /Oy- /I "../include" /I "../../apr/include" /I "../include/private" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_OPENSSL=1 /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_crypto_openssl_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /fo"Release/apr_crypto_openssl-1.res" /d DLL_NAME="apr_crypto_openssl" /d "NDEBUG" /d "APU_VERSION_ONLY" /I "../include" /I "../../apr/include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libeay32.lib ssleay32.lib /nologo /base:"0x6F100000" /subsystem:windows /dll /incremental:no /debug /opt:ref
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libeay32.lib ssleay32.lib /nologo /base:"0x6F100000" /subsystem:windows /dll /incremental:no /debug /out:"Release\apr_crypto_openssl-1.dll" /pdb:"Release\apr_crypto_openssl-1.pdb" /implib:"Release\apr_crypto_openssl-1.lib" /MACHINE:X86 /opt:ref
+# Begin Special Build Tool
+TargetPath=Release\apr_crypto_openssl-1.dll
+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)" == "apr_crypto_openssl - 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 /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /EHsc /c
+# ADD CPP /nologo /MDd /W3 /Zi /Od /I "../include" /I "../../apr/include" /I "../include/private" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_OPENSSL=1 /D /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_crypto_openssl_src" /FD /EHsc /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /fo"Debug/apr_crypto_openssl-1.res" /d DLL_NAME="apr_crypto_openssl" /d "_DEBUG" /d "APU_VERSION_ONLY" /I "../include" /I "../../apr/include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libeay32.lib ssleay32.lib /nologo /base:"0x6F100000" /subsystem:windows /dll /incremental:no /debug
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libeay32.lib ssleay32.lib /nologo /base:"0x6F100000" /subsystem:windows /dll /incremental:no /debug /out:"Debug\apr_crypto_openssl-1.dll" /pdb:"Debug\apr_crypto_openssl-1.pdb" /implib:"Debug\apr_crypto_openssl-1.lib" /MACHINE:X86
+# Begin Special Build Tool
+TargetPath=Debug\apr_crypto_openssl-1.dll
+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)" == "apr_crypto_openssl - x64 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "x64\Release"
+# PROP BASE Intermediate_Dir "x64\Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "x64\Release"
+# PROP Intermediate_Dir "x64\Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /Zi /O2 /Oy- /I "../include" /I "../../apr/include" /I "../include/private" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_OPENSSL=1 /D /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_crypto_openssl_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /fo"x64/Release/apr_crypto_openssl-1.res" /d DLL_NAME="apr_crypto_openssl" /d "NDEBUG" /d "APU_VERSION_ONLY" /I "../include" /I "../../apr/include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libeay32.lib ssleay32.lib /nologo /base:"0x6F100000" /subsystem:windows /dll /incremental:no /debug /opt:ref
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libeay32.lib ssleay32.lib /nologo /base:"0x6F100000" /subsystem:windows /dll /incremental:no /debug /out:"x64\Release\apr_crypto_openssl-1.dll" /pdb:"x64\Release\apr_crypto_openssl-1.pdb" /implib:"x64\Release\apr_crypto_openssl-1.lib" /MACHINE:X64 /opt:ref
+# Begin Special Build Tool
+TargetPath=x64\Release\apr_crypto_openssl-1.dll
+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)" == "apr_crypto_openssl - x64 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "x64\Debug"
+# PROP BASE Intermediate_Dir "x64\Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "x64\Debug"
+# PROP Intermediate_Dir "x64\Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /EHsc /c
+# ADD CPP /nologo /MDd /W3 /Zi /Od /I "../include" /I "../../apr/include" /I "../include/private" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_OPENSSL=1 /D /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_crypto_openssl_src" /FD /EHsc /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /fo"x64/Debug/apr_crypto_openssl-1.res" /d DLL_NAME="apr_crypto_openssl" /d "_DEBUG" /d "APU_VERSION_ONLY" /I "../include" /I "../../apr/include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libeay32.lib ssleay32.lib /nologo /base:"0x6F100000" /subsystem:windows /dll /incremental:no /debug
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libeay32.lib ssleay32.lib /nologo /base:"0x6F100000" /subsystem:windows /dll /incremental:no /debug /out:"x64\Debug\apr_crypto_openssl-1.dll" /pdb:"x64\Debug\apr_crypto_openssl-1.pdb" /implib:"x64\Debug\apr_crypto_openssl-1.lib" /MACHINE:X64
+# Begin Special Build Tool
+TargetPath=x64\Debug\apr_crypto_openssl-1.dll
+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 "apr_crypto_openssl - Win32 Release"
+# Name "apr_crypto_openssl - Win32 Debug"
+# Name "apr_crypto_openssl - x64 Release"
+# Name "apr_crypto_openssl - x64 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\apr_crypto_openssl.c
+# End Source File
+# End Group
+# Begin Group "Public Header Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\include\apr_crypto.h
+# End Source File
+# End Group
+# Begin Group "Internal Header Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\include\private\apu_config.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\private\apu_internal.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\libaprutil.rc
+# End Source File
+# End Target
+# End Project
diff --git a/crypto/apr_md4.c b/crypto/apr_md4.c
new file mode 100644
index 00000000000..d983cbae5c2
--- /dev/null
+++ b/crypto/apr_md4.c
@@ -0,0 +1,404 @@
+/* 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 is derived from material copyright RSA Data Security, Inc.
+ * Their notice is reproduced below in its entirety.
+ *
+ * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+ * rights reserved.
+ *
+ * License to copy and use this software is granted provided that it
+ * is identified as the "RSA Data Security, Inc. MD4 Message-Digest
+ * Algorithm" in all material mentioning or referencing this software
+ * or this function.
+ *
+ * License is also granted to make and use derivative works provided
+ * that such works are identified as "derived from the RSA Data
+ * Security, Inc. MD4 Message-Digest Algorithm" in all material
+ * mentioning or referencing the derived work.
+ *
+ * RSA Data Security, Inc. makes no representations concerning either
+ * the merchantability of this software or the suitability of this
+ * software for any particular purpose. It is provided "as is"
+ * without express or implied warranty of any kind.
+ *
+ * These notices must be retained in any copies of any part of this
+ * documentation and/or software.
+ */
+
+#include "apr_strings.h"
+#include "apr_md4.h"
+#include "apr_lib.h"
+
+#if APR_HAVE_STRING_H
+#include <string.h>
+#endif
+#if APR_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+/* Constants for MD4Transform routine.
+ */
+ 
+#define S11 3
+#define S12 7
+#define S13 11
+#define S14 19
+#define S21 3
+#define S22 5
+#define S23 9
+#define S24 13
+#define S31 3
+#define S32 9
+#define S33 11
+#define S34 15
+ 
+static void MD4Transform(apr_uint32_t state[4], const unsigned char block[64]);
+static void Encode(unsigned char *output, const apr_uint32_t *input,
+                   unsigned int len);
+static void Decode(apr_uint32_t *output, const unsigned char *input,
+                   unsigned int len);
+
+static unsigned char PADDING[64] =
+{
+    0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+#if APR_CHARSET_EBCDIC
+static apr_xlate_t *xlate_ebcdic_to_ascii; /* used in apr_md4_encode() */
+#endif
+
+/* F, G and I are basic MD4 functions.
+ */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+
+/* ROTATE_LEFT rotates x left n bits.
+ */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG and HH are transformations for rounds 1, 2 and 3 */
+/* Rotation is separate from addition to prevent recomputation */
+
+#define FF(a, b, c, d, x, s) { \
+  (a) += F ((b), (c), (d)) + (x); \
+  (a) = ROTATE_LEFT ((a), (s)); \
+  }
+#define GG(a, b, c, d, x, s) { \
+  (a) += G ((b), (c), (d)) + (x) + (apr_uint32_t)0x5a827999; \
+  (a) = ROTATE_LEFT ((a), (s)); \
+  }
+#define HH(a, b, c, d, x, s) { \
+  (a) += H ((b), (c), (d)) + (x) + (apr_uint32_t)0x6ed9eba1; \
+  (a) = ROTATE_LEFT ((a), (s)); \
+  }
+
+/* MD4 initialization. Begins an MD4 operation, writing a new context.
+ */
+APR_DECLARE(apr_status_t) apr_md4_init(apr_md4_ctx_t *context)
+{
+    context->count[0] = context->count[1] = 0;
+
+    /* Load magic initialization constants. */
+    context->state[0] = 0x67452301;
+    context->state[1] = 0xefcdab89;
+    context->state[2] = 0x98badcfe;
+    context->state[3] = 0x10325476;
+    
+#if APR_HAS_XLATE
+    context->xlate = NULL;
+#endif
+
+    return APR_SUCCESS;
+}
+
+#if APR_HAS_XLATE
+/* MD4 translation setup.  Provides the APR translation handle
+ * to be used for translating the content before calculating the
+ * digest.
+ */
+APR_DECLARE(apr_status_t) apr_md4_set_xlate(apr_md4_ctx_t *context, 
+                                            apr_xlate_t *xlate)
+{
+    apr_status_t rv;
+    int is_sb;
+
+    /* TODO: remove the single-byte-only restriction from this code
+     */
+    rv = apr_xlate_sb_get(xlate, &is_sb);
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+    if (!is_sb) {
+        return APR_EINVAL;
+    }
+    context->xlate = xlate;
+    return APR_SUCCESS;
+}
+#endif /* APR_HAS_XLATE */
+
+/* MD4 block update operation. Continues an MD4 message-digest
+ * operation, processing another message block, and updating the
+ * context.
+ */
+APR_DECLARE(apr_status_t) apr_md4_update(apr_md4_ctx_t *context,
+                                         const unsigned char *input,
+                                         apr_size_t inputLen)
+{
+    unsigned int i, idx, partLen;
+#if APR_HAS_XLATE
+    apr_size_t inbytes_left, outbytes_left;
+#endif
+
+    /* Compute number of bytes mod 64 */
+    idx = (unsigned int)((context->count[0] >> 3) & 0x3F);
+
+    /* Update number of bits */
+    if ((context->count[0] += ((apr_uint32_t)inputLen << 3)) 
+            < ((apr_uint32_t)inputLen << 3))
+        context->count[1]++;
+    context->count[1] += (apr_uint32_t)inputLen >> 29;
+
+    partLen = 64 - idx;
+
+    /* Transform as many times as possible. */
+#if !APR_HAS_XLATE
+    if (inputLen >= partLen) {
+        memcpy(&context->buffer[idx], input, partLen);
+        MD4Transform(context->state, context->buffer);
+
+        for (i = partLen; i + 63 < inputLen; i += 64)
+            MD4Transform(context->state, &input[i]);
+
+        idx = 0;
+    }
+    else
+        i = 0;
+
+    /* Buffer remaining input */
+    memcpy(&context->buffer[idx], &input[i], inputLen - i);
+#else /*APR_HAS_XLATE*/
+    if (inputLen >= partLen) {
+        if (context->xlate) {
+            inbytes_left = outbytes_left = partLen;
+            apr_xlate_conv_buffer(context->xlate, (const char *)input, 
+                                  &inbytes_left, 
+                                  (char *)&context->buffer[idx], 
+                                  &outbytes_left);
+        }
+        else {
+            memcpy(&context->buffer[idx], input, partLen);
+        }
+        MD4Transform(context->state, context->buffer);
+
+        for (i = partLen; i + 63 < inputLen; i += 64) {
+            if (context->xlate) {
+                unsigned char inp_tmp[64];
+                inbytes_left = outbytes_left = 64;
+                apr_xlate_conv_buffer(context->xlate, (const char *)&input[i], 
+                                      &inbytes_left,
+                                      (char *)inp_tmp, &outbytes_left);
+                MD4Transform(context->state, inp_tmp);
+            }
+            else {
+                MD4Transform(context->state, &input[i]);
+            }
+        }
+
+        idx = 0;
+    }
+    else
+        i = 0;
+
+    /* Buffer remaining input */
+    if (context->xlate) {
+        inbytes_left = outbytes_left = inputLen - i;
+        apr_xlate_conv_buffer(context->xlate, (const char *)&input[i], 
+                              &inbytes_left, (char *)&context->buffer[idx], 
+                              &outbytes_left);
+    }
+    else {
+        memcpy(&context->buffer[idx], &input[i], inputLen - i);
+    }
+#endif /*APR_HAS_XLATE*/
+    return APR_SUCCESS;
+}
+
+/* MD4 finalization. Ends an MD4 message-digest operation, writing the
+ * the message digest and zeroizing the context.
+ */
+APR_DECLARE(apr_status_t) apr_md4_final(
+                                    unsigned char digest[APR_MD4_DIGESTSIZE],
+                                    apr_md4_ctx_t *context)
+{
+    unsigned char bits[8];
+    unsigned int idx, padLen;
+
+    /* Save number of bits */
+    Encode(bits, context->count, 8);
+
+#if APR_HAS_XLATE
+    /* apr_md4_update() should not translate for this final round. */
+    context->xlate = NULL;
+#endif /*APR_HAS_XLATE*/
+
+    /* Pad out to 56 mod 64. */
+    idx = (unsigned int) ((context->count[0] >> 3) & 0x3f);
+    padLen = (idx < 56) ? (56 - idx) : (120 - idx);
+    apr_md4_update(context, PADDING, padLen);
+
+    /* Append length (before padding) */
+    apr_md4_update(context, bits, 8);
+
+    /* Store state in digest */
+    Encode(digest, context->state, APR_MD4_DIGESTSIZE);
+
+    /* Zeroize sensitive information. */
+    memset(context, 0, sizeof(*context));
+    
+    return APR_SUCCESS;
+}
+
+/* MD4 computation in one step (init, update, final)
+ */
+APR_DECLARE(apr_status_t) apr_md4(unsigned char digest[APR_MD4_DIGESTSIZE],
+                                  const unsigned char *input,
+                                  apr_size_t inputLen)
+{
+    apr_md4_ctx_t ctx;
+    apr_status_t rv;
+
+    apr_md4_init(&ctx);
+
+    if ((rv = apr_md4_update(&ctx, input, inputLen)) != APR_SUCCESS)
+        return rv;
+
+    return apr_md4_final(digest, &ctx);
+}
+
+/* MD4 basic transformation. Transforms state based on block. */
+static void MD4Transform(apr_uint32_t state[4], const unsigned char block[64])
+{
+    apr_uint32_t a = state[0], b = state[1], c = state[2], d = state[3],
+                 x[APR_MD4_DIGESTSIZE];
+
+    Decode(x, block, 64);
+
+    /* Round 1 */
+    FF (a, b, c, d, x[ 0], S11); /* 1 */
+    FF (d, a, b, c, x[ 1], S12); /* 2 */
+    FF (c, d, a, b, x[ 2], S13); /* 3 */
+    FF (b, c, d, a, x[ 3], S14); /* 4 */
+    FF (a, b, c, d, x[ 4], S11); /* 5 */
+    FF (d, a, b, c, x[ 5], S12); /* 6 */
+    FF (c, d, a, b, x[ 6], S13); /* 7 */
+    FF (b, c, d, a, x[ 7], S14); /* 8 */
+    FF (a, b, c, d, x[ 8], S11); /* 9 */
+    FF (d, a, b, c, x[ 9], S12); /* 10 */
+    FF (c, d, a, b, x[10], S13); /* 11 */
+    FF (b, c, d, a, x[11], S14); /* 12 */
+    FF (a, b, c, d, x[12], S11); /* 13 */
+    FF (d, a, b, c, x[13], S12); /* 14 */
+    FF (c, d, a, b, x[14], S13); /* 15 */
+    FF (b, c, d, a, x[15], S14); /* 16 */
+
+    /* Round 2 */
+    GG (a, b, c, d, x[ 0], S21); /* 17 */
+    GG (d, a, b, c, x[ 4], S22); /* 18 */
+    GG (c, d, a, b, x[ 8], S23); /* 19 */
+    GG (b, c, d, a, x[12], S24); /* 20 */
+    GG (a, b, c, d, x[ 1], S21); /* 21 */
+    GG (d, a, b, c, x[ 5], S22); /* 22 */
+    GG (c, d, a, b, x[ 9], S23); /* 23 */
+    GG (b, c, d, a, x[13], S24); /* 24 */
+    GG (a, b, c, d, x[ 2], S21); /* 25 */
+    GG (d, a, b, c, x[ 6], S22); /* 26 */
+    GG (c, d, a, b, x[10], S23); /* 27 */
+    GG (b, c, d, a, x[14], S24); /* 28 */
+    GG (a, b, c, d, x[ 3], S21); /* 29 */
+    GG (d, a, b, c, x[ 7], S22); /* 30 */
+    GG (c, d, a, b, x[11], S23); /* 31 */
+    GG (b, c, d, a, x[15], S24); /* 32 */
+
+    /* Round 3 */
+    HH (a, b, c, d, x[ 0], S31); /* 33 */
+    HH (d, a, b, c, x[ 8], S32); /* 34 */
+    HH (c, d, a, b, x[ 4], S33); /* 35 */
+    HH (b, c, d, a, x[12], S34); /* 36 */
+    HH (a, b, c, d, x[ 2], S31); /* 37 */
+    HH (d, a, b, c, x[10], S32); /* 38 */
+    HH (c, d, a, b, x[ 6], S33); /* 39 */
+    HH (b, c, d, a, x[14], S34); /* 40 */
+    HH (a, b, c, d, x[ 1], S31); /* 41 */
+    HH (d, a, b, c, x[ 9], S32); /* 42 */
+    HH (c, d, a, b, x[ 5], S33); /* 43 */
+    HH (b, c, d, a, x[13], S34); /* 44 */
+    HH (a, b, c, d, x[ 3], S31); /* 45 */
+    HH (d, a, b, c, x[11], S32); /* 46 */
+    HH (c, d, a, b, x[ 7], S33); /* 47 */
+    HH (b, c, d, a, x[15], S34); /* 48 */
+
+    state[0] += a;
+    state[1] += b;
+    state[2] += c;
+    state[3] += d;
+    
+    /* Zeroize sensitive information. */
+    memset(x, 0, sizeof(x));
+}
+
+/* Encodes input (apr_uint32_t) into output (unsigned char). Assumes len is
+ * a multiple of 4.
+ */
+static void Encode(unsigned char *output, const apr_uint32_t *input,
+                   unsigned int len)
+{
+    unsigned int i, j;
+    apr_uint32_t k;
+
+    for (i = 0, j = 0; j < len; i++, j += 4) {
+        k = input[i];
+        output[j]     = (unsigned char)(k & 0xff);
+        output[j + 1] = (unsigned char)((k >> 8)  & 0xff);
+        output[j + 2] = (unsigned char)((k >> 16) & 0xff);
+        output[j + 3] = (unsigned char)((k >> 24) & 0xff);
+    }
+}
+
+/* Decodes input (unsigned char) into output (apr_uint32_t). Assumes len is
+ * a multiple of 4.
+ */
+static void Decode(apr_uint32_t *output, const unsigned char *input,
+                   unsigned int len)
+{
+    unsigned int i, j;
+
+    for (i = 0, j = 0; j < len; i++, j += 4)
+        output[i] = ((apr_uint32_t)input[j])             |
+                    (((apr_uint32_t)input[j + 1]) << 8)  |
+                    (((apr_uint32_t)input[j + 2]) << 16) |
+                    (((apr_uint32_t)input[j + 3]) << 24);
+}
+
+#if APR_CHARSET_EBCDIC
+APR_DECLARE(apr_status_t) apr_MD4InitEBCDIC(apr_xlate_t *xlate)
+{
+    xlate_ebcdic_to_ascii = xlate;
+    return APR_SUCCESS;
+}
+#endif
diff --git a/crypto/apr_md5.c b/crypto/apr_md5.c
new file mode 100644
index 00000000000..2aa0b4c4977
--- /dev/null
+++ b/crypto/apr_md5.c
@@ -0,0 +1,666 @@
+/*
+ * This is work is derived from material Copyright RSA Data Security, Inc.
+ *
+ * The RSA copyright statement and Licence for that original material is
+ * included below. This is followed by the Apache copyright statement and
+ * licence for the modifications made to that material.
+ */
+
+/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
+ */
+
+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+   rights reserved.
+
+   License to copy and use this software is granted provided that it
+   is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+   Algorithm" in all material mentioning or referencing this software
+   or this function.
+
+   License is also granted to make and use derivative works provided
+   that such works are identified as "derived from the RSA Data
+   Security, Inc. MD5 Message-Digest Algorithm" in all material
+   mentioning or referencing the derived work.
+
+   RSA Data Security, Inc. makes no representations concerning either
+   the merchantability of this software or the suitability of this
+   software for any particular purpose. It is provided "as is"
+   without express or implied warranty of any kind.
+
+   These notices must be retained in any copies of any part of this
+   documentation and/or software.
+ */
+
+/* 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.
+ */
+
+/*
+ * The apr_md5_encode() routine uses much code obtained from the FreeBSD 3.0
+ * MD5 crypt() function, which is licenced as follows:
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <phk@login.dknet.dk> wrote this file.  As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
+ * ----------------------------------------------------------------------------
+ */
+#include "apr_strings.h"
+#include "apr_md5.h"
+#include "apr_lib.h"
+#include "apr_private.h"
+
+#if APR_HAVE_STRING_H
+#include <string.h>
+#endif
+
+/* Constants for MD5Transform routine.
+ */
+
+#define S11 7
+#define S12 12
+#define S13 17
+#define S14 22
+#define S21 5
+#define S22 9
+#define S23 14
+#define S24 20
+#define S31 4
+#define S32 11
+#define S33 16
+#define S34 23
+#define S41 6
+#define S42 10
+#define S43 15
+#define S44 21
+
+static void MD5Transform(apr_uint32_t state[4], const unsigned char block[64]);
+static void Encode(unsigned char *output, const apr_uint32_t *input,
+                   unsigned int len);
+static void Decode(apr_uint32_t *output, const unsigned char *input,
+                   unsigned int len);
+
+static const unsigned char PADDING[64] =
+{
+    0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+#if APR_CHARSET_EBCDIC
+static apr_xlate_t *xlate_ebcdic_to_ascii; /* used in apr_md5_encode() */
+#endif
+#define DO_XLATE 0
+#define SKIP_XLATE 1
+
+/* F, G, H and I are basic MD5 functions.
+ */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~z)))
+
+/* ROTATE_LEFT rotates x left n bits.
+ */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
+ * Rotation is separate from addition to prevent recomputation.
+ */
+#define FF(a, b, c, d, x, s, ac) { \
+ (a) += F ((b), (c), (d)) + (x) + (apr_uint32_t)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+  }
+#define GG(a, b, c, d, x, s, ac) { \
+ (a) += G ((b), (c), (d)) + (x) + (apr_uint32_t)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+  }
+#define HH(a, b, c, d, x, s, ac) { \
+ (a) += H ((b), (c), (d)) + (x) + (apr_uint32_t)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+  }
+#define II(a, b, c, d, x, s, ac) { \
+ (a) += I ((b), (c), (d)) + (x) + (apr_uint32_t)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+  }
+
+/* MD5 initialization. Begins an MD5 operation, writing a new context.
+ */
+APR_DECLARE(apr_status_t) apr_md5_init(apr_md5_ctx_t *context)
+{
+    context->count[0] = context->count[1] = 0;
+    
+    /* Load magic initialization constants. */
+    context->state[0] = 0x67452301;
+    context->state[1] = 0xefcdab89;
+    context->state[2] = 0x98badcfe;
+    context->state[3] = 0x10325476;
+    context->xlate = NULL;
+    
+    return APR_SUCCESS;
+}
+
+/* MD5 translation setup.  Provides the APR translation handle
+ * to be used for translating the content before calculating the
+ * digest.
+ */
+APR_DECLARE(apr_status_t) apr_md5_set_xlate(apr_md5_ctx_t *context, 
+                                            apr_xlate_t *xlate)
+{
+#if APR_HAS_XLATE
+    apr_status_t rv;
+    int is_sb;
+
+    /* TODO: remove the single-byte-only restriction from this code
+     */
+    rv = apr_xlate_sb_get(xlate, &is_sb);
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+    if (!is_sb) {
+        return APR_EINVAL;
+    }
+    context->xlate = xlate;
+    return APR_SUCCESS;
+#else
+    return APR_ENOTIMPL;
+#endif /* APR_HAS_XLATE */
+}
+
+/* MD5 block update operation. Continues an MD5 message-digest
+ * operation, processing another message block, and updating the
+ * context.
+ */
+static apr_status_t md5_update_buffer(apr_md5_ctx_t *context,
+                                      const void *vinput,
+                                      apr_size_t inputLen,
+                                      int xlate_buffer)
+{
+    const unsigned char *input = vinput;
+    unsigned int i, idx, partLen;
+#if APR_HAS_XLATE
+    apr_size_t inbytes_left, outbytes_left;
+#endif
+
+    /* Compute number of bytes mod 64 */
+    idx = (unsigned int)((context->count[0] >> 3) & 0x3F);
+
+    /* Update number of bits */
+    if ((context->count[0] += ((apr_uint32_t)inputLen << 3)) 
+            < ((apr_uint32_t)inputLen << 3))
+        context->count[1]++;
+    context->count[1] += (apr_uint32_t)inputLen >> 29;
+
+    partLen = 64 - idx;
+
+    /* Transform as many times as possible. */
+#if !APR_HAS_XLATE
+    if (inputLen >= partLen) {
+        memcpy(&context->buffer[idx], input, partLen);
+        MD5Transform(context->state, context->buffer);
+
+        for (i = partLen; i + 63 < inputLen; i += 64)
+            MD5Transform(context->state, &input[i]);
+
+        idx = 0;
+    }
+    else
+        i = 0;
+
+    /* Buffer remaining input */
+    memcpy(&context->buffer[idx], &input[i], inputLen - i);
+#else /*APR_HAS_XLATE*/
+    if (inputLen >= partLen) {
+        if (context->xlate && (xlate_buffer == DO_XLATE)) {
+            inbytes_left = outbytes_left = partLen;
+            apr_xlate_conv_buffer(context->xlate, (const char *)input, 
+                                  &inbytes_left,
+                                  (char *)&context->buffer[idx], 
+                                  &outbytes_left);
+        }
+        else {
+            memcpy(&context->buffer[idx], input, partLen);
+        }
+        MD5Transform(context->state, context->buffer);
+
+        for (i = partLen; i + 63 < inputLen; i += 64) {
+            if (context->xlate && (xlate_buffer == DO_XLATE)) {
+                unsigned char inp_tmp[64];
+                inbytes_left = outbytes_left = 64;
+                apr_xlate_conv_buffer(context->xlate, (const char *)&input[i], 
+                                      &inbytes_left, (char *)inp_tmp, 
+                                      &outbytes_left);
+                MD5Transform(context->state, inp_tmp);
+            }
+            else {
+                MD5Transform(context->state, &input[i]);
+            }
+        }
+
+        idx = 0;
+    }
+    else
+        i = 0;
+
+    /* Buffer remaining input */
+    if (context->xlate && (xlate_buffer == DO_XLATE)) {
+        inbytes_left = outbytes_left = inputLen - i;
+        apr_xlate_conv_buffer(context->xlate, (const char *)&input[i], 
+                              &inbytes_left, (char *)&context->buffer[idx], 
+                              &outbytes_left);
+    }
+    else {
+        memcpy(&context->buffer[idx], &input[i], inputLen - i);
+    }
+#endif /*APR_HAS_XLATE*/
+    return APR_SUCCESS;
+}
+
+/* MD5 block update operation. API with the default setting 
+ * for EBCDIC translations
+ */  
+APR_DECLARE(apr_status_t) apr_md5_update(apr_md5_ctx_t *context,
+                                         const void *input,
+                                         apr_size_t inputLen)
+{
+    return md5_update_buffer(context, input, inputLen, DO_XLATE);
+}
+
+/* MD5 finalization. Ends an MD5 message-digest operation, writing the
+ * the message digest and zeroizing the context.
+ */
+APR_DECLARE(apr_status_t) apr_md5_final(unsigned char digest[APR_MD5_DIGESTSIZE],
+                                        apr_md5_ctx_t *context)
+{
+    unsigned char bits[8];
+    unsigned int idx, padLen;
+
+    /* Save number of bits */
+    Encode(bits, context->count, 8);
+
+#if APR_HAS_XLATE
+    /* apr_md5_update() should not translate for this final round. */
+    context->xlate = NULL;
+#endif /*APR_HAS_XLATE*/
+
+    /* Pad out to 56 mod 64. */
+    idx = (unsigned int)((context->count[0] >> 3) & 0x3f);
+    padLen = (idx < 56) ? (56 - idx) : (120 - idx);
+    apr_md5_update(context, PADDING, padLen);
+
+    /* Append length (before padding) */
+    apr_md5_update(context, bits, 8);
+
+    /* Store state in digest */
+    Encode(digest, context->state, APR_MD5_DIGESTSIZE);
+
+    /* Zeroize sensitive information. */
+    memset(context, 0, sizeof(*context));
+    
+    return APR_SUCCESS;
+}
+
+/* MD5 in one step (init, update, final)
+ */
+APR_DECLARE(apr_status_t) apr_md5(unsigned char digest[APR_MD5_DIGESTSIZE],
+                                  const void *_input,
+                                  apr_size_t inputLen)
+{
+    const unsigned char *input = _input;
+    apr_md5_ctx_t ctx;
+    apr_status_t rv;
+
+    apr_md5_init(&ctx);
+
+    if ((rv = apr_md5_update(&ctx, input, inputLen)) != APR_SUCCESS)
+        return rv;
+
+    return apr_md5_final(digest, &ctx);
+}
+
+/* MD5 basic transformation. Transforms state based on block. */
+static void MD5Transform(apr_uint32_t state[4], const unsigned char block[64])
+{
+    apr_uint32_t a = state[0], b = state[1], c = state[2], d = state[3],
+                 tmpbuf[APR_MD5_DIGESTSIZE];
+    const apr_uint32_t *x;
+
+#if !APR_IS_BIGENDIAN
+    if ((apr_uintptr_t)block % sizeof(apr_uint32_t) == 0) {
+        x = (apr_uint32_t *)block;
+    } else
+#endif
+    {
+        Decode(tmpbuf, block, 64);
+	x = tmpbuf;
+    }
+
+    /* Round 1 */
+    FF(a, b, c, d, x[0],  S11, 0xd76aa478); /* 1 */
+    FF(d, a, b, c, x[1],  S12, 0xe8c7b756); /* 2 */
+    FF(c, d, a, b, x[2],  S13, 0x242070db); /* 3 */
+    FF(b, c, d, a, x[3],  S14, 0xc1bdceee); /* 4 */
+    FF(a, b, c, d, x[4],  S11, 0xf57c0faf); /* 5 */
+    FF(d, a, b, c, x[5],  S12, 0x4787c62a); /* 6 */
+    FF(c, d, a, b, x[6],  S13, 0xa8304613); /* 7 */
+    FF(b, c, d, a, x[7],  S14, 0xfd469501); /* 8 */
+    FF(a, b, c, d, x[8],  S11, 0x698098d8); /* 9 */
+    FF(d, a, b, c, x[9],  S12, 0x8b44f7af); /* 10 */
+    FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
+    FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
+    FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
+    FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
+    FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
+    FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
+
+    /* Round 2 */
+    GG(a, b, c, d, x[1],  S21, 0xf61e2562); /* 17 */
+    GG(d, a, b, c, x[6],  S22, 0xc040b340); /* 18 */
+    GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
+    GG(b, c, d, a, x[0],  S24, 0xe9b6c7aa); /* 20 */
+    GG(a, b, c, d, x[5],  S21, 0xd62f105d); /* 21 */
+    GG(d, a, b, c, x[10], S22, 0x2441453);  /* 22 */
+    GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
+    GG(b, c, d, a, x[4],  S24, 0xe7d3fbc8); /* 24 */
+    GG(a, b, c, d, x[9],  S21, 0x21e1cde6); /* 25 */
+    GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
+    GG(c, d, a, b, x[3],  S23, 0xf4d50d87); /* 27 */
+    GG(b, c, d, a, x[8],  S24, 0x455a14ed); /* 28 */
+    GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
+    GG(d, a, b, c, x[2],  S22, 0xfcefa3f8); /* 30 */
+    GG(c, d, a, b, x[7],  S23, 0x676f02d9); /* 31 */
+    GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
+
+    /* Round 3 */
+    HH(a, b, c, d, x[5],  S31, 0xfffa3942); /* 33 */
+    HH(d, a, b, c, x[8],  S32, 0x8771f681); /* 34 */
+    HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
+    HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
+    HH(a, b, c, d, x[1],  S31, 0xa4beea44); /* 37 */
+    HH(d, a, b, c, x[4],  S32, 0x4bdecfa9); /* 38 */
+    HH(c, d, a, b, x[7],  S33, 0xf6bb4b60); /* 39 */
+    HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
+    HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
+    HH(d, a, b, c, x[0],  S32, 0xeaa127fa); /* 42 */
+    HH(c, d, a, b, x[3],  S33, 0xd4ef3085); /* 43 */
+    HH(b, c, d, a, x[6],  S34, 0x4881d05);  /* 44 */
+    HH(a, b, c, d, x[9],  S31, 0xd9d4d039); /* 45 */
+    HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
+    HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
+    HH(b, c, d, a, x[2],  S34, 0xc4ac5665); /* 48 */
+
+    /* Round 4 */
+    II(a, b, c, d, x[0],  S41, 0xf4292244); /* 49 */
+    II(d, a, b, c, x[7],  S42, 0x432aff97); /* 50 */
+    II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
+    II(b, c, d, a, x[5],  S44, 0xfc93a039); /* 52 */
+    II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
+    II(d, a, b, c, x[3],  S42, 0x8f0ccc92); /* 54 */
+    II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
+    II(b, c, d, a, x[1],  S44, 0x85845dd1); /* 56 */
+    II(a, b, c, d, x[8],  S41, 0x6fa87e4f); /* 57 */
+    II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
+    II(c, d, a, b, x[6],  S43, 0xa3014314); /* 59 */
+    II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
+    II(a, b, c, d, x[4],  S41, 0xf7537e82); /* 61 */
+    II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
+    II(c, d, a, b, x[2],  S43, 0x2ad7d2bb); /* 63 */
+    II(b, c, d, a, x[9],  S44, 0xeb86d391); /* 64 */
+
+    state[0] += a;
+    state[1] += b;
+    state[2] += c;
+    state[3] += d;
+
+#if !APR_IS_BIGENDIAN
+    if (x == tmpbuf)
+#endif
+    {
+        /* Zeroize sensitive information. */
+        memset(tmpbuf, 0, sizeof(tmpbuf));
+    }
+}
+
+/* Encodes input (apr_uint32_t) into output (unsigned char). Assumes len is
+ * a multiple of 4.
+ */
+static void Encode(unsigned char *output, const apr_uint32_t *input,
+                   unsigned int len)
+{
+    unsigned int i, j;
+    apr_uint32_t k;
+
+    for (i = 0, j = 0; j < len; i++, j += 4) {
+        k = input[i];
+        output[j]     = (unsigned char)(k & 0xff);
+        output[j + 1] = (unsigned char)((k >> 8) & 0xff);
+        output[j + 2] = (unsigned char)((k >> 16) & 0xff);
+        output[j + 3] = (unsigned char)((k >> 24) & 0xff);
+    }
+}
+
+/* Decodes input (unsigned char) into output (apr_uint32_t). Assumes len is
+ * a multiple of 4.
+ */
+static void Decode(apr_uint32_t *output, const unsigned char *input,
+                   unsigned int len)
+{
+    unsigned int i, j;
+
+    for (i = 0, j = 0; j < len; i++, j += 4)
+        output[i] = ((apr_uint32_t)input[j])             |
+                    (((apr_uint32_t)input[j + 1]) << 8)  |
+                    (((apr_uint32_t)input[j + 2]) << 16) |
+                    (((apr_uint32_t)input[j + 3]) << 24);
+}
+
+#if APR_CHARSET_EBCDIC
+APR_DECLARE(apr_status_t) apr_MD5InitEBCDIC(apr_xlate_t *xlate)
+{
+    xlate_ebcdic_to_ascii = xlate;
+    return APR_SUCCESS;
+}
+#endif
+
+/*
+ * Define the Magic String prefix that identifies a password as being
+ * hashed using our algorithm.
+ */
+static const char * const apr1_id = "$apr1$";
+
+/*
+ * The following MD5 password encryption code was largely borrowed from
+ * the FreeBSD 3.0 /usr/src/lib/libcrypt/crypt.c file, which is
+ * licenced as stated at the top of this file.
+ */
+
+static void to64(char *s, unsigned long v, int n)
+{
+    static unsigned char itoa64[] =         /* 0 ... 63 => ASCII - 64 */
+        "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+    while (--n >= 0) {
+        *s++ = itoa64[v&0x3f];
+        v >>= 6;
+    }
+}
+
+APR_DECLARE(apr_status_t) apr_md5_encode(const char *pw, const char *salt,
+                             char *result, apr_size_t nbytes)
+{
+    /*
+     * Minimum size is 8 bytes for salt, plus 1 for the trailing NUL,
+     * plus 4 for the '$' separators, plus the password hash itself.
+     * Let's leave a goodly amount of leeway.
+     */
+
+    char passwd[120], *p;
+    const char *sp, *ep;
+    unsigned char final[APR_MD5_DIGESTSIZE];
+    apr_ssize_t sl, pl, i;
+    apr_md5_ctx_t ctx, ctx1;
+    unsigned long l;
+
+    /* 
+     * Refine the salt first.  It's possible we were given an already-hashed
+     * string as the salt argument, so extract the actual salt value from it
+     * if so.  Otherwise just use the string up to the first '$' as the salt.
+     */
+    sp = salt;
+
+    /*
+     * If it starts with the magic string, then skip that.
+     */
+    if (!strncmp(sp, apr1_id, strlen(apr1_id))) {
+        sp += strlen(apr1_id);
+    }
+
+    /*
+     * It stops at the first '$' or 8 chars, whichever comes first
+     */
+    for (ep = sp; (*ep != '\0') && (*ep != '$') && (ep < (sp + 8)); ep++) {
+        continue;
+    }
+
+    /*
+     * Get the length of the true salt
+     */
+    sl = ep - sp;
+
+    /*
+     * 'Time to make the doughnuts..'
+     */
+    apr_md5_init(&ctx);
+#if APR_CHARSET_EBCDIC
+    apr_md5_set_xlate(&ctx, xlate_ebcdic_to_ascii);
+#endif
+    
+    /*
+     * The password first, since that is what is most unknown
+     */
+    apr_md5_update(&ctx, pw, strlen(pw));
+
+    /*
+     * Then our magic string
+     */
+    apr_md5_update(&ctx, apr1_id, strlen(apr1_id));
+
+    /*
+     * Then the raw salt
+     */
+    apr_md5_update(&ctx, sp, sl);
+
+    /*
+     * Then just as many characters of the MD5(pw, salt, pw)
+     */
+    apr_md5_init(&ctx1);
+#if APR_CHARSET_EBCDIC
+    apr_md5_set_xlate(&ctx1, xlate_ebcdic_to_ascii);
+#endif
+    apr_md5_update(&ctx1, pw, strlen(pw));
+    apr_md5_update(&ctx1, sp, sl);
+    apr_md5_update(&ctx1, pw, strlen(pw));
+    apr_md5_final(final, &ctx1);
+    for (pl = strlen(pw); pl > 0; pl -= APR_MD5_DIGESTSIZE) {
+        md5_update_buffer(&ctx, final,
+                      (pl > APR_MD5_DIGESTSIZE) ? APR_MD5_DIGESTSIZE : pl, SKIP_XLATE);
+    }
+
+    /*
+     * Don't leave anything around in vm they could use.
+     */
+    memset(final, 0, sizeof(final));
+
+    /*
+     * Then something really weird...
+     */
+    for (i = strlen(pw); i != 0; i >>= 1) {
+        if (i & 1) {
+            md5_update_buffer(&ctx, final, 1, SKIP_XLATE);
+        }
+        else {
+            apr_md5_update(&ctx, pw, 1);
+        }
+    }
+
+    /*
+     * Now make the output string.  We know our limitations, so we
+     * can use the string routines without bounds checking.
+     */
+    strcpy(passwd, apr1_id);
+    strncat(passwd, sp, sl);
+    strcat(passwd, "$");
+
+    apr_md5_final(final, &ctx);
+
+    /*
+     * And now, just to make sure things don't run too fast..
+     * On a 60 Mhz Pentium this takes 34 msec, so you would
+     * need 30 seconds to build a 1000 entry dictionary...
+     */
+    for (i = 0; i < 1000; i++) {
+        apr_md5_init(&ctx1);
+         /*
+          * apr_md5_final clears out ctx1.xlate at the end of each loop,
+          * so need to to set it each time through
+          */
+#if APR_CHARSET_EBCDIC
+        apr_md5_set_xlate(&ctx1, xlate_ebcdic_to_ascii);
+#endif
+        if (i & 1) {
+            apr_md5_update(&ctx1, pw, strlen(pw));
+        }
+        else {
+            md5_update_buffer(&ctx1, final, APR_MD5_DIGESTSIZE, SKIP_XLATE);
+        }
+        if (i % 3) {
+            apr_md5_update(&ctx1, sp, sl);
+        }
+
+        if (i % 7) {
+            apr_md5_update(&ctx1, pw, strlen(pw));
+        }
+
+        if (i & 1) {
+            md5_update_buffer(&ctx1, final, APR_MD5_DIGESTSIZE, SKIP_XLATE);
+        }
+        else {
+            apr_md5_update(&ctx1, pw, strlen(pw));
+        }
+        apr_md5_final(final,&ctx1);
+    }
+
+    p = passwd + strlen(passwd);
+
+    l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(p, l, 4); p += 4;
+    l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(p, l, 4); p += 4;
+    l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(p, l, 4); p += 4;
+    l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(p, l, 4); p += 4;
+    l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; to64(p, l, 4); p += 4;
+    l =                    final[11]                ; to64(p, l, 2); p += 2;
+    *p = '\0';
+
+    /*
+     * Don't leave anything around in vm they could use.
+     */
+    memset(final, 0, sizeof(final));
+
+    apr_cpystrn(result, passwd, nbytes - 1);
+    return APR_SUCCESS;
+}
diff --git a/crypto/apr_passwd.c b/crypto/apr_passwd.c
new file mode 100644
index 00000000000..01e9860b857
--- /dev/null
+++ b/crypto/apr_passwd.c
@@ -0,0 +1,226 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_strings.h"
+#include "apr_md5.h"
+#include "apr_lib.h"
+#include "apr_private.h"
+#include "apr_sha1.h"
+#include "crypt_blowfish.h"
+
+#if APR_HAVE_STRING_H
+#include <string.h>
+#endif
+#if APR_HAVE_CRYPT_H
+#include <crypt.h>
+#endif
+#if APR_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if APR_HAVE_PTHREAD_H
+#include <pthread.h>
+#endif
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+static const char * const apr1_id = "$apr1$";
+
+#if !defined(WIN32) && !defined(BEOS) && !defined(NETWARE)
+#if defined(APU_CRYPT_THREADSAFE) || !APR_HAS_THREADS || \
+    defined(CRYPT_R_CRYPTD) || defined(CRYPT_R_STRUCT_CRYPT_DATA)
+
+#define crypt_mutex_lock()
+#define crypt_mutex_unlock()
+
+#elif APR_HAVE_PTHREAD_H && defined(PTHREAD_MUTEX_INITIALIZER)
+
+static pthread_mutex_t crypt_mutex = PTHREAD_MUTEX_INITIALIZER;
+static void crypt_mutex_lock(void)
+{
+    pthread_mutex_lock(&crypt_mutex);
+}
+
+static void crypt_mutex_unlock(void)
+{
+    pthread_mutex_unlock(&crypt_mutex);
+}
+
+#elif defined(OS2)
+
+static HMTX crypt_mutex = 0;
+static void crypt_mutex_lock()
+{
+    if (crypt_mutex == 0) {
+        /* Prevent race condition where two threads could try to create the
+         * mutex concurrently
+         */
+        DosEnterCritSec();
+
+        if (crypt_mutex == 0) {
+            DosCreateMutexSem(NULL, &crypt_mutex, 0, FALSE);
+        }
+
+        DosExitCritSec();
+    }
+
+    DosRequestMutexSem(crypt_mutex, SEM_INDEFINITE_WAIT);
+}
+
+static void crypt_mutex_unlock()
+{
+    DosReleaseMutexSem(crypt_mutex);
+}
+
+#else
+
+#error apr_password_validate() is not threadsafe.  rebuild APR without thread support.
+
+#endif
+#endif
+
+#if defined(WIN32) || defined(BEOS) || defined(NETWARE) || defined(__ANDROID__)
+#define CRYPT_MISSING 1
+#else
+#define CRYPT_MISSING 0
+#endif
+
+/*
+ * Validate a plaintext password against a smashed one.  Uses either
+ * crypt() (if available) or apr_md5_encode() or apr_sha1_base64(), depending
+ * upon the format of the smashed input password.  Returns APR_SUCCESS if
+ * they match, or APR_EMISMATCH if they don't.  If the platform doesn't
+ * support crypt, then the default check is against a clear text string.
+ */
+APR_DECLARE(apr_status_t) apr_password_validate(const char *passwd, 
+                                                const char *hash)
+{
+    char sample[200];
+#if !CRYPT_MISSING
+    char *crypt_pw;
+#endif
+    if (hash[0] == '$'
+        && hash[1] == '2'
+        && (hash[2] == 'a' || hash[2] == 'y')
+        && hash[3] == '$') {
+        if (_crypt_blowfish_rn(passwd, hash, sample, sizeof(sample)) == NULL)
+            return APR_FROM_OS_ERROR(errno);
+    }
+    else if (!strncmp(hash, apr1_id, strlen(apr1_id))) {
+        /*
+         * The hash was created using our custom algorithm.
+         */
+        apr_md5_encode(passwd, hash, sample, sizeof(sample));
+    }
+    else if (!strncmp(hash, APR_SHA1PW_ID, APR_SHA1PW_IDLEN)) {
+         apr_sha1_base64(passwd, (int)strlen(passwd), sample);
+    }
+    else {
+        /*
+         * It's not our algorithm, so feed it to crypt() if possible.
+         */
+#if CRYPT_MISSING
+        return (strcmp(passwd, hash) == 0) ? APR_SUCCESS : APR_EMISMATCH;
+#elif defined(CRYPT_R_CRYPTD)
+        apr_status_t rv;
+        CRYPTD *buffer = malloc(sizeof(*buffer));
+
+        if (buffer == NULL)
+            return APR_ENOMEM;
+        crypt_pw = crypt_r(passwd, hash, buffer);
+        if (!crypt_pw)
+            rv = APR_EMISMATCH;
+        else
+            rv = (strcmp(crypt_pw, hash) == 0) ? APR_SUCCESS : APR_EMISMATCH;
+        free(buffer);
+        return rv;
+#elif defined(CRYPT_R_STRUCT_CRYPT_DATA)
+        apr_status_t rv;
+        struct crypt_data *buffer = malloc(sizeof(*buffer));
+
+        if (buffer == NULL)
+            return APR_ENOMEM;
+
+#ifdef __GLIBC_PREREQ
+        /*
+         * For not too old glibc (>= 2.3.2), it's enough to set
+         * buffer.initialized = 0. For < 2.3.2 and for other platforms,
+         * we need to zero the whole struct.
+         */
+#if __GLIBC_PREREQ(2,4)
+#define USE_CRYPT_DATA_INITALIZED
+#endif
+#endif
+
+#ifdef USE_CRYPT_DATA_INITALIZED
+        buffer->initialized = 0;
+#else
+        memset(buffer, 0, sizeof(*buffer));
+#endif
+
+        crypt_pw = crypt_r(passwd, hash, buffer);
+        if (!crypt_pw)
+            rv = APR_EMISMATCH;
+        else
+            rv = (strcmp(crypt_pw, hash) == 0) ? APR_SUCCESS : APR_EMISMATCH;
+        free(buffer);
+        return rv;
+#else
+        /* Do a bit of sanity checking since we know that crypt_r()
+         * should always be used for threaded builds on AIX, and
+         * problems in configure logic can result in the wrong
+         * choice being made.
+         */
+#if defined(_AIX) && APR_HAS_THREADS
+#error Configuration error!  crypt_r() should have been selected!
+#endif
+        {
+            apr_status_t rv;
+
+            /* Handle thread safety issues by holding a mutex around the
+             * call to crypt().
+             */
+            crypt_mutex_lock();
+            crypt_pw = crypt(passwd, hash);
+            if (!crypt_pw) {
+                rv = APR_EMISMATCH;
+            }
+            else {
+                rv = (strcmp(crypt_pw, hash) == 0) ? APR_SUCCESS : APR_EMISMATCH;
+            }
+            crypt_mutex_unlock();
+            return rv;
+        }
+#endif
+    }
+    return (strcmp(sample, hash) == 0) ? APR_SUCCESS : APR_EMISMATCH;
+}
+
+static const char * const bcrypt_id = "$2y$";
+APR_DECLARE(apr_status_t) apr_bcrypt_encode(const char *pw,
+                                            unsigned int count,
+                                            const unsigned char *salt,
+                                            apr_size_t salt_len,
+                                            char *out, apr_size_t out_len)
+{
+    char setting[40];
+    if (_crypt_gensalt_blowfish_rn(bcrypt_id, count, (const char *)salt,
+                                   salt_len, setting, sizeof(setting)) == NULL)
+        return APR_FROM_OS_ERROR(errno);
+    if (_crypt_blowfish_rn(pw, setting, out, out_len) == NULL)
+        return APR_FROM_OS_ERROR(errno);
+    return APR_SUCCESS;
+}
diff --git a/crypto/apr_sha1.c b/crypto/apr_sha1.c
new file mode 100644
index 00000000000..4ac8b73afdb
--- /dev/null
+++ b/crypto/apr_sha1.c
@@ -0,0 +1,368 @@
+/* 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.
+ */
+
+/*
+ * The exported function:
+ *
+ *     apr_sha1_base64(const char *clear, int len, char *out);
+ *
+ * provides a means to SHA1 crypt/encode a plaintext password in
+ * a way which makes password files compatible with those commonly
+ * used in netscape web and ldap installations. It was put together
+ * by Clinton Wong <clintdw@netcom.com>, who also notes that:
+ *
+ * Note: SHA1 support is useful for migration purposes, but is less
+ *     secure than Apache's password format, since Apache's (MD5)
+ *     password format uses a random eight character salt to generate
+ *     one of many possible hashes for the same password.  Netscape
+ *     uses plain SHA1 without a salt, so the same password
+ *     will always generate the same hash, making it easier
+ *     to break since the search space is smaller.
+ *
+ * See also the documentation in support/SHA1 as to hints on how to
+ * migrate an existing netscape installation and other supplied utitlites.
+ *
+ * This software also makes use of the following component:
+ *
+ * NIST Secure Hash Algorithm
+ *      heavily modified by Uwe Hollerbach uh@alumni.caltech edu
+ *      from Peter C. Gutmann's implementation as found in
+ *      Applied Cryptography by Bruce Schneier
+ *      This code is hereby placed in the public domain
+ */
+
+#include "apr_sha1.h"
+#include "apr_base64.h"
+#include "apr_strings.h"
+#include "apr_lib.h"
+#if APR_CHARSET_EBCDIC
+#include "apr_xlate.h"
+#endif /*APR_CHARSET_EBCDIC*/
+#include <string.h>
+
+/* a bit faster & bigger, if defined */
+#define UNROLL_LOOPS
+
+/* NIST's proposed modification to SHA, 7/11/94 */
+#define USE_MODIFIED_SHA
+
+/* SHA f()-functions */
+#define f1(x,y,z)   ((x & y) | (~x & z))
+#define f2(x,y,z)   (x ^ y ^ z)
+#define f3(x,y,z)   ((x & y) | (x & z) | (y & z))
+#define f4(x,y,z)   (x ^ y ^ z)
+
+/* SHA constants */
+#define CONST1      0x5a827999L
+#define CONST2      0x6ed9eba1L
+#define CONST3      0x8f1bbcdcL
+#define CONST4      0xca62c1d6L
+
+/* 32-bit rotate */
+
+#define ROT32(x,n)  ((x << n) | (x >> (32 - n)))
+
+#define FUNC(n,i) \
+    temp = ROT32(A,5) + f##n(B,C,D) + E + W[i] + CONST##n; \
+    E = D; D = C; C = ROT32(B,30); B = A; A = temp
+
+#define SHA_BLOCKSIZE           64
+
+#if APR_CHARSET_EBCDIC
+static apr_xlate_t *ebcdic2ascii_xlate;
+
+APR_DECLARE(apr_status_t) apr_SHA1InitEBCDIC(apr_xlate_t *x)
+{
+    apr_status_t rv;
+    int onoff;
+
+    /* Only single-byte conversion is supported.
+     */
+    rv = apr_xlate_sb_get(x, &onoff);
+    if (rv) {
+        return rv;
+    }
+    if (!onoff) { /* If conversion is not single-byte-only */
+        return APR_EINVAL;
+    }
+    ebcdic2ascii_xlate = x;
+    return APR_SUCCESS;
+}
+#endif
+
+/* do SHA transformation */
+static void sha_transform(apr_sha1_ctx_t *sha_info)
+{
+    int i;
+    apr_uint32_t temp, A, B, C, D, E, W[80];
+
+    for (i = 0; i < 16; ++i) {
+        W[i] = sha_info->data[i];
+    }
+    for (i = 16; i < 80; ++i) {
+        W[i] = W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16];
+#ifdef USE_MODIFIED_SHA
+        W[i] = ROT32(W[i], 1);
+#endif /* USE_MODIFIED_SHA */
+    }
+    A = sha_info->digest[0];
+    B = sha_info->digest[1];
+    C = sha_info->digest[2];
+    D = sha_info->digest[3];
+    E = sha_info->digest[4];
+#ifdef UNROLL_LOOPS
+    FUNC(1, 0);  FUNC(1, 1);  FUNC(1, 2);  FUNC(1, 3);  FUNC(1, 4);
+    FUNC(1, 5);  FUNC(1, 6);  FUNC(1, 7);  FUNC(1, 8);  FUNC(1, 9);
+    FUNC(1,10);  FUNC(1,11);  FUNC(1,12);  FUNC(1,13);  FUNC(1,14);
+    FUNC(1,15);  FUNC(1,16);  FUNC(1,17);  FUNC(1,18);  FUNC(1,19);
+
+    FUNC(2,20);  FUNC(2,21);  FUNC(2,22);  FUNC(2,23);  FUNC(2,24);
+    FUNC(2,25);  FUNC(2,26);  FUNC(2,27);  FUNC(2,28);  FUNC(2,29);
+    FUNC(2,30);  FUNC(2,31);  FUNC(2,32);  FUNC(2,33);  FUNC(2,34);
+    FUNC(2,35);  FUNC(2,36);  FUNC(2,37);  FUNC(2,38);  FUNC(2,39);
+
+    FUNC(3,40);  FUNC(3,41);  FUNC(3,42);  FUNC(3,43);  FUNC(3,44);
+    FUNC(3,45);  FUNC(3,46);  FUNC(3,47);  FUNC(3,48);  FUNC(3,49);
+    FUNC(3,50);  FUNC(3,51);  FUNC(3,52);  FUNC(3,53);  FUNC(3,54);
+    FUNC(3,55);  FUNC(3,56);  FUNC(3,57);  FUNC(3,58);  FUNC(3,59);
+
+    FUNC(4,60);  FUNC(4,61);  FUNC(4,62);  FUNC(4,63);  FUNC(4,64);
+    FUNC(4,65);  FUNC(4,66);  FUNC(4,67);  FUNC(4,68);  FUNC(4,69);
+    FUNC(4,70);  FUNC(4,71);  FUNC(4,72);  FUNC(4,73);  FUNC(4,74);
+    FUNC(4,75);  FUNC(4,76);  FUNC(4,77);  FUNC(4,78);  FUNC(4,79);
+#else /* !UNROLL_LOOPS */
+    for (i = 0; i < 20; ++i) {
+        FUNC(1,i);
+    }
+    for (i = 20; i < 40; ++i) {
+        FUNC(2,i);
+    }
+    for (i = 40; i < 60; ++i) {
+        FUNC(3,i);
+    }
+    for (i = 60; i < 80; ++i) {
+        FUNC(4,i);
+    }
+#endif /* !UNROLL_LOOPS */
+    sha_info->digest[0] += A;
+    sha_info->digest[1] += B;
+    sha_info->digest[2] += C;
+    sha_info->digest[3] += D;
+    sha_info->digest[4] += E;
+}
+
+union endianTest {
+    long Long;
+    char Char[sizeof(long)];
+};
+
+static char isLittleEndian(void)
+{
+    static union endianTest u;
+    u.Long = 1;
+    return (u.Char[0] == 1);
+}
+
+/* change endianness of data */
+
+/* count is the number of bytes to do an endian flip */
+static void maybe_byte_reverse(apr_uint32_t *buffer, int count)
+{
+    int i;
+    apr_byte_t ct[4], *cp;
+
+    if (isLittleEndian()) { /* do the swap only if it is little endian */
+        count /= sizeof(apr_uint32_t);
+        cp = (apr_byte_t *) buffer;
+        for (i = 0; i < count; ++i) {
+            ct[0] = cp[0];
+            ct[1] = cp[1];
+            ct[2] = cp[2];
+            ct[3] = cp[3];
+            cp[0] = ct[3];
+            cp[1] = ct[2];
+            cp[2] = ct[1];
+            cp[3] = ct[0];
+            cp += sizeof(apr_uint32_t);
+        }
+    }
+}
+
+/* initialize the SHA digest */
+
+APR_DECLARE(void) apr_sha1_init(apr_sha1_ctx_t *sha_info)
+{
+    sha_info->digest[0] = 0x67452301L;
+    sha_info->digest[1] = 0xefcdab89L;
+    sha_info->digest[2] = 0x98badcfeL;
+    sha_info->digest[3] = 0x10325476L;
+    sha_info->digest[4] = 0xc3d2e1f0L;
+    sha_info->count_lo = 0L;
+    sha_info->count_hi = 0L;
+    sha_info->local = 0;
+}
+
+/* update the SHA digest */
+
+APR_DECLARE(void) apr_sha1_update_binary(apr_sha1_ctx_t *sha_info,
+                                     const unsigned char *buffer,
+                                     unsigned int count)
+{
+    unsigned int i;
+
+    if ((sha_info->count_lo + ((apr_uint32_t) count << 3)) < sha_info->count_lo) {
+        ++sha_info->count_hi;
+    }
+    sha_info->count_lo += (apr_uint32_t) count << 3;
+    sha_info->count_hi += (apr_uint32_t) count >> 29;
+    if (sha_info->local) {
+        i = SHA_BLOCKSIZE - sha_info->local;
+        if (i > count) {
+            i = count;
+        }
+        memcpy(((apr_byte_t *) sha_info->data) + sha_info->local, buffer, i);
+        count -= i;
+        buffer += i;
+        sha_info->local += i;
+        if (sha_info->local == SHA_BLOCKSIZE) {
+            maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
+            sha_transform(sha_info);
+        }
+        else {
+            return;
+        }
+    }
+    while (count >= SHA_BLOCKSIZE) {
+        memcpy(sha_info->data, buffer, SHA_BLOCKSIZE);
+        buffer += SHA_BLOCKSIZE;
+        count -= SHA_BLOCKSIZE;
+        maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
+        sha_transform(sha_info);
+    }
+    memcpy(sha_info->data, buffer, count);
+    sha_info->local = count;
+}
+
+APR_DECLARE(void) apr_sha1_update(apr_sha1_ctx_t *sha_info, const char *buf,
+                              unsigned int count)
+{
+#if APR_CHARSET_EBCDIC
+    int i;
+    const apr_byte_t *buffer = (const apr_byte_t *) buf;
+    apr_size_t inbytes_left, outbytes_left;
+
+    if ((sha_info->count_lo + ((apr_uint32_t) count << 3)) < sha_info->count_lo) {
+        ++sha_info->count_hi;
+    }
+    sha_info->count_lo += (apr_uint32_t) count << 3;
+    sha_info->count_hi += (apr_uint32_t) count >> 29;
+    /* Is there a remainder of the previous Update operation? */
+    if (sha_info->local) {
+        i = SHA_BLOCKSIZE - sha_info->local;
+        if (i > count) {
+            i = count;
+        }
+        inbytes_left = outbytes_left = i;
+        apr_xlate_conv_buffer(ebcdic2ascii_xlate, buffer, &inbytes_left,
+                              ((apr_byte_t *) sha_info->data) + sha_info->local,
+                              &outbytes_left);
+        count -= i;
+        buffer += i;
+        sha_info->local += i;
+        if (sha_info->local == SHA_BLOCKSIZE) {
+            maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
+            sha_transform(sha_info);
+        }
+        else {
+            return;
+        }
+    }
+    while (count >= SHA_BLOCKSIZE) {
+        inbytes_left = outbytes_left = SHA_BLOCKSIZE;
+        apr_xlate_conv_buffer(ebcdic2ascii_xlate, buffer, &inbytes_left,
+                              (apr_byte_t *) sha_info->data, &outbytes_left);
+        buffer += SHA_BLOCKSIZE;
+        count -= SHA_BLOCKSIZE;
+        maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
+        sha_transform(sha_info);
+    }
+    inbytes_left = outbytes_left = count;
+    apr_xlate_conv_buffer(ebcdic2ascii_xlate, buffer, &inbytes_left,
+                          (apr_byte_t *) sha_info->data, &outbytes_left);
+    sha_info->local = count;
+#else
+    apr_sha1_update_binary(sha_info, (const unsigned char *) buf, count);
+#endif
+}
+
+/* finish computing the SHA digest */
+
+APR_DECLARE(void) apr_sha1_final(unsigned char digest[APR_SHA1_DIGESTSIZE],
+                             apr_sha1_ctx_t *sha_info)
+{
+    int count, i, j;
+    apr_uint32_t lo_bit_count, hi_bit_count, k;
+
+    lo_bit_count = sha_info->count_lo;
+    hi_bit_count = sha_info->count_hi;
+    count = (int) ((lo_bit_count >> 3) & 0x3f);
+    ((apr_byte_t *) sha_info->data)[count++] = 0x80;
+    if (count > SHA_BLOCKSIZE - 8) {
+        memset(((apr_byte_t *) sha_info->data) + count, 0, SHA_BLOCKSIZE - count);
+        maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
+        sha_transform(sha_info);
+        memset((apr_byte_t *) sha_info->data, 0, SHA_BLOCKSIZE - 8);
+    }
+    else {
+        memset(((apr_byte_t *) sha_info->data) + count, 0,
+               SHA_BLOCKSIZE - 8 - count);
+    }
+    maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
+    sha_info->data[14] = hi_bit_count;
+    sha_info->data[15] = lo_bit_count;
+    sha_transform(sha_info);
+
+    for (i = 0, j = 0; j < APR_SHA1_DIGESTSIZE; i++) {
+        k = sha_info->digest[i];
+        digest[j++] = (unsigned char) ((k >> 24) & 0xff);
+        digest[j++] = (unsigned char) ((k >> 16) & 0xff);
+        digest[j++] = (unsigned char) ((k >> 8) & 0xff);
+        digest[j++] = (unsigned char) (k & 0xff);
+    }
+}
+
+
+APR_DECLARE(void) apr_sha1_base64(const char *clear, int len, char *out)
+{
+    int l;
+    apr_sha1_ctx_t context;
+    apr_byte_t digest[APR_SHA1_DIGESTSIZE];
+
+    apr_sha1_init(&context);
+    apr_sha1_update(&context, clear, len);
+    apr_sha1_final(digest, &context);
+
+    /* private marker. */
+    apr_cpystrn(out, APR_SHA1PW_ID, APR_SHA1PW_IDLEN + 1);
+
+    /* SHA1 hash is always 20 chars */
+    l = apr_base64_encode_binary(out + APR_SHA1PW_IDLEN, digest, sizeof(digest));
+    out[l + APR_SHA1PW_IDLEN] = '\0';
+
+    /*
+     * output of base64 encoded SHA1 is always 28 chars + APR_SHA1PW_IDLEN
+     */
+}
diff --git a/crypto/apr_siphash.c b/crypto/apr_siphash.c
new file mode 100644
index 00000000000..41cff70f231
--- /dev/null
+++ b/crypto/apr_siphash.c
@@ -0,0 +1,196 @@
+/* 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.
+ */
+
+/*
+ * SipHash (C reference implementation, APR-ized), originating from:
+ *      https://131002.net/siphash/siphash24.c.
+ */
+
+#include "apr_siphash.h"
+
+#define ROTL64(x, n) (((x) << (n)) | ((x) >> (64 - (n))))
+
+#define U8TO64_LE(p) \
+    (((apr_uint64_t)((p)[0])      ) | \
+     ((apr_uint64_t)((p)[1]) <<  8) | \
+     ((apr_uint64_t)((p)[2]) << 16) | \
+     ((apr_uint64_t)((p)[3]) << 24) | \
+     ((apr_uint64_t)((p)[4]) << 32) | \
+     ((apr_uint64_t)((p)[5]) << 40) | \
+     ((apr_uint64_t)((p)[6]) << 48) | \
+     ((apr_uint64_t)((p)[7]) << 56))
+
+#define U64TO8_LE(p, v) \
+do { \
+    (p)[0] = (unsigned char)((v)      ); \
+    (p)[1] = (unsigned char)((v) >>  8); \
+    (p)[2] = (unsigned char)((v) >> 16); \
+    (p)[3] = (unsigned char)((v) >> 24); \
+    (p)[4] = (unsigned char)((v) >> 32); \
+    (p)[5] = (unsigned char)((v) >> 40); \
+    (p)[6] = (unsigned char)((v) >> 48); \
+    (p)[7] = (unsigned char)((v) >> 56); \
+} while (0)
+
+#define SIPROUND() \
+do { \
+    v0 += v1; v1=ROTL64(v1,13); v1 ^= v0; v0=ROTL64(v0,32); \
+    v2 += v3; v3=ROTL64(v3,16); v3 ^= v2; \
+    v0 += v3; v3=ROTL64(v3,21); v3 ^= v0; \
+    v2 += v1; v1=ROTL64(v1,17); v1 ^= v2; v2=ROTL64(v2,32); \
+} while(0)
+
+#define SIPHASH(r, s, n, k) \
+do { \
+    const unsigned char *ptr, *end; \
+    apr_uint64_t v0, v1, v2, v3, m; \
+    apr_uint64_t k0, k1; \
+    unsigned int rem; \
+    \
+    k0 = U8TO64_LE(k + 0); \
+    k1 = U8TO64_LE(k + 8); \
+    v3 = k1 ^ (apr_uint64_t)0x7465646279746573ULL; \
+    v2 = k0 ^ (apr_uint64_t)0x6c7967656e657261ULL; \
+    v1 = k1 ^ (apr_uint64_t)0x646f72616e646f6dULL; \
+    v0 = k0 ^ (apr_uint64_t)0x736f6d6570736575ULL; \
+    \
+    rem = (unsigned int)(n & 0x7); \
+    for (ptr = s, end = ptr + n - rem; ptr < end; ptr += 8) { \
+        m = U8TO64_LE(ptr); \
+        v3 ^= m; \
+        cROUNDS \
+        v0 ^= m; \
+    } \
+    m = (apr_uint64_t)(n & 0xff) << 56; \
+    switch (rem) { \
+        case 7: m |= (apr_uint64_t)ptr[6] << 48; \
+        case 6: m |= (apr_uint64_t)ptr[5] << 40; \
+        case 5: m |= (apr_uint64_t)ptr[4] << 32; \
+        case 4: m |= (apr_uint64_t)ptr[3] << 24; \
+        case 3: m |= (apr_uint64_t)ptr[2] << 16; \
+        case 2: m |= (apr_uint64_t)ptr[1] << 8; \
+        case 1: m |= (apr_uint64_t)ptr[0]; \
+        case 0: break; \
+    } \
+    v3 ^= m; \
+    cROUNDS \
+    v0 ^= m; \
+    \
+    v2 ^= 0xff; \
+    dROUNDS \
+    \
+    r = v0 ^ v1 ^ v2 ^ v3; \
+} while (0)
+
+APR_DECLARE(apr_uint64_t) apr_siphash(const void *src, apr_size_t len,
+                              const unsigned char key[APR_SIPHASH_KSIZE],
+                                      unsigned int c, unsigned int d)
+{
+    apr_uint64_t h;
+    unsigned int i;
+
+#undef  cROUNDS
+#define cROUNDS \
+        for (i = 0; i < c; ++i) { \
+            SIPROUND(); \
+        }
+
+#undef  dROUNDS
+#define dROUNDS \
+        for (i = 0; i < d; ++i) { \
+            SIPROUND(); \
+        }
+
+    SIPHASH(h, src, len, key);
+    return h;
+}
+
+APR_DECLARE(void) apr_siphash_auth(unsigned char out[APR_SIPHASH_DSIZE],
+                                   const void *src, apr_size_t len,
+                             const unsigned char key[APR_SIPHASH_KSIZE],
+                                   unsigned int c, unsigned int d)
+{
+    apr_uint64_t h;
+    h = apr_siphash(src, len, key, c, d);
+    U64TO8_LE(out, h);
+}
+
+APR_DECLARE(apr_uint64_t) apr_siphash24(const void *src, apr_size_t len,
+                               const unsigned char key[APR_SIPHASH_KSIZE])
+{
+    apr_uint64_t h;
+
+#undef  cROUNDS
+#define cROUNDS \
+        SIPROUND(); \
+        SIPROUND();
+
+#undef  dROUNDS
+#define dROUNDS \
+        SIPROUND(); \
+        SIPROUND(); \
+        SIPROUND(); \
+        SIPROUND();
+
+    SIPHASH(h, src, len, key);
+    return h;
+}
+
+APR_DECLARE(void) apr_siphash24_auth(unsigned char out[APR_SIPHASH_DSIZE],
+                                     const void *src, apr_size_t len,
+                               const unsigned char key[APR_SIPHASH_KSIZE])
+{
+    apr_uint64_t h;
+    h = apr_siphash24(src, len, key);
+    U64TO8_LE(out, h);
+}
+
+APR_DECLARE(apr_uint64_t) apr_siphash48(const void *src, apr_size_t len,
+                               const unsigned char key[APR_SIPHASH_KSIZE])
+{
+    apr_uint64_t h;
+
+#undef  cROUNDS
+#define cROUNDS \
+        SIPROUND(); \
+        SIPROUND(); \
+        SIPROUND(); \
+        SIPROUND();
+
+#undef  dROUNDS
+#define dROUNDS \
+        SIPROUND(); \
+        SIPROUND(); \
+        SIPROUND(); \
+        SIPROUND(); \
+        SIPROUND(); \
+        SIPROUND(); \
+        SIPROUND(); \
+        SIPROUND();
+
+    SIPHASH(h, src, len, key);
+    return h;
+}
+
+APR_DECLARE(void) apr_siphash48_auth(unsigned char out[APR_SIPHASH_DSIZE],
+                                     const void *src, apr_size_t len,
+                               const unsigned char key[APR_SIPHASH_KSIZE])
+{
+    apr_uint64_t h;
+    h = apr_siphash48(src, len, key);
+    U64TO8_LE(out, h);
+}
+
diff --git a/crypto/crypt_blowfish.c b/crypto/crypt_blowfish.c
new file mode 100644
index 00000000000..3d306cf8d3f
--- /dev/null
+++ b/crypto/crypt_blowfish.c
@@ -0,0 +1,902 @@
+/*
+ * The crypt_blowfish homepage is:
+ *
+ *	http://www.openwall.com/crypt/
+ *
+ * This code comes from John the Ripper password cracker, with reentrant
+ * and crypt(3) interfaces added, but optimizations specific to password
+ * cracking removed.
+ *
+ * Written by Solar Designer <solar at openwall.com> in 1998-2011.
+ * No copyright is claimed, and the software is hereby placed in the public
+ * domain.  In case this attempt to disclaim copyright and place the software
+ * in the public domain is deemed null and void, then the software is
+ * Copyright (c) 1998-2011 Solar Designer and it is hereby released to the
+ * general public under the following terms:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted.
+ *
+ * There's ABSOLUTELY NO WARRANTY, express or implied.
+ *
+ * It is my intent that you should be able to use this on your system,
+ * as part of a software package, or anywhere else to improve security,
+ * ensure compatibility, or for any other purpose.  I would appreciate
+ * it if you give credit where it is due and keep your modifications in
+ * the public domain as well, but I don't require that in order to let
+ * you place this code and any modifications you make under a license
+ * of your choice.
+ *
+ * This implementation is mostly compatible with OpenBSD's bcrypt.c (prefix
+ * "$2a$") by Niels Provos <provos at citi.umich.edu>, and uses some of his
+ * ideas.  The password hashing algorithm was designed by David Mazieres
+ * <dm at lcs.mit.edu>.  For more information on the level of compatibility,
+ * prefer refer to the comments in BF_set_key() below and to the included
+ * crypt(3) man page.
+ *
+ * There's a paper on the algorithm that explains its design decisions:
+ *
+ *	http://www.usenix.org/events/usenix99/provos.html
+ *
+ * Some of the tricks in BF_ROUND might be inspired by Eric Young's
+ * Blowfish library (I can't be sure if I would think of something if I
+ * hadn't seen his code).
+ */
+
+#include <string.h>
+
+#include <errno.h>
+#ifndef __set_errno
+#define __set_errno(val) errno = (val)
+#endif
+
+/* Just to make sure the prototypes match the actual definitions */
+#include "crypt_blowfish.h"
+
+#ifdef __i386__
+#define BF_ASM				0
+#define BF_SCALE			1
+#elif defined(__x86_64__) || defined(__alpha__) || defined(__hppa__)
+#define BF_ASM				0
+#define BF_SCALE			1
+#else
+#define BF_ASM				0
+#define BF_SCALE			0
+#endif
+
+typedef unsigned int BF_word;
+typedef signed int BF_word_signed;
+
+/* Number of Blowfish rounds, this is also hardcoded into a few places */
+#define BF_N				16
+
+typedef BF_word BF_key[BF_N + 2];
+
+typedef struct {
+	BF_word S[4][0x100];
+	BF_key P;
+} BF_ctx;
+
+/*
+ * Magic IV for 64 Blowfish encryptions that we do at the end.
+ * The string is "OrpheanBeholderScryDoubt" on big-endian.
+ */
+static BF_word BF_magic_w[6] = {
+	0x4F727068, 0x65616E42, 0x65686F6C,
+	0x64657253, 0x63727944, 0x6F756274
+};
+
+/*
+ * P-box and S-box tables initialized with digits of Pi.
+ */
+static BF_ctx BF_init_state = {
+	{
+		{
+			0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
+			0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
+			0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
+			0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
+			0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
+			0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
+			0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
+			0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
+			0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
+			0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
+			0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
+			0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
+			0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
+			0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
+			0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
+			0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
+			0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
+			0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
+			0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
+			0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
+			0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
+			0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
+			0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
+			0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
+			0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
+			0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
+			0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
+			0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
+			0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
+			0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
+			0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
+			0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
+			0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
+			0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
+			0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
+			0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
+			0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
+			0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
+			0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
+			0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
+			0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
+			0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
+			0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
+			0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
+			0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
+			0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
+			0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
+			0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
+			0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
+			0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
+			0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
+			0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
+			0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
+			0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
+			0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
+			0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
+			0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
+			0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
+			0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
+			0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
+			0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
+			0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
+			0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
+			0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a
+		}, {
+			0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
+			0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
+			0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
+			0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
+			0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
+			0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
+			0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
+			0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
+			0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
+			0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
+			0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
+			0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
+			0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
+			0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
+			0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
+			0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
+			0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
+			0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
+			0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
+			0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
+			0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
+			0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
+			0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
+			0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
+			0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
+			0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
+			0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
+			0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
+			0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
+			0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
+			0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
+			0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
+			0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
+			0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
+			0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
+			0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
+			0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
+			0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
+			0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
+			0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
+			0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
+			0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
+			0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
+			0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
+			0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
+			0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
+			0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
+			0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
+			0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
+			0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
+			0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
+			0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
+			0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
+			0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
+			0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
+			0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
+			0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
+			0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
+			0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
+			0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
+			0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
+			0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
+			0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
+			0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7
+		}, {
+			0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
+			0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
+			0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
+			0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
+			0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
+			0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
+			0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
+			0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
+			0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
+			0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
+			0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
+			0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
+			0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
+			0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
+			0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
+			0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
+			0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
+			0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
+			0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
+			0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
+			0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
+			0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
+			0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
+			0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
+			0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
+			0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
+			0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
+			0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
+			0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
+			0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
+			0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
+			0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
+			0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
+			0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
+			0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
+			0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
+			0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
+			0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
+			0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
+			0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
+			0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
+			0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
+			0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
+			0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
+			0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
+			0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
+			0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
+			0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
+			0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
+			0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
+			0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
+			0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
+			0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
+			0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
+			0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
+			0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
+			0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
+			0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
+			0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
+			0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
+			0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
+			0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
+			0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
+			0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0
+		}, {
+			0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
+			0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
+			0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
+			0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
+			0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
+			0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
+			0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
+			0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
+			0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
+			0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
+			0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
+			0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
+			0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
+			0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
+			0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
+			0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
+			0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
+			0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
+			0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
+			0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
+			0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
+			0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
+			0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
+			0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
+			0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
+			0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
+			0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
+			0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
+			0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
+			0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
+			0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
+			0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
+			0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
+			0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
+			0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
+			0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
+			0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
+			0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
+			0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
+			0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
+			0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
+			0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
+			0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
+			0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
+			0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
+			0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
+			0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
+			0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
+			0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
+			0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
+			0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
+			0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
+			0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
+			0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
+			0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
+			0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
+			0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
+			0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
+			0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
+			0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
+			0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
+			0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
+			0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
+			0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
+		}
+	}, {
+		0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
+		0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
+		0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
+		0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
+		0x9216d5d9, 0x8979fb1b
+	}
+};
+
+static unsigned char BF_itoa64[64 + 1] =
+	"./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+
+static unsigned char BF_atoi64[0x60] = {
+	64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 1,
+	54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 64, 64, 64, 64, 64,
+	64, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+	17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 64, 64, 64, 64, 64,
+	64, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
+	43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 64, 64, 64, 64, 64
+};
+
+#define BF_safe_atoi64(dst, src) \
+{ \
+	tmp = (unsigned char)(src); \
+	if ((unsigned int)(tmp -= 0x20) >= 0x60) return -1; \
+	tmp = BF_atoi64[tmp]; \
+	if (tmp > 63) return -1; \
+	(dst) = tmp; \
+}
+
+static int BF_decode(BF_word *dst, const char *src, int size)
+{
+	unsigned char *dptr = (unsigned char *)dst;
+	unsigned char *end = dptr + size;
+	const unsigned char *sptr = (const unsigned char *)src;
+	unsigned int tmp, c1, c2, c3, c4;
+
+	do {
+		BF_safe_atoi64(c1, *sptr++);
+		BF_safe_atoi64(c2, *sptr++);
+		*dptr++ = (c1 << 2) | ((c2 & 0x30) >> 4);
+		if (dptr >= end) break;
+
+		BF_safe_atoi64(c3, *sptr++);
+		*dptr++ = ((c2 & 0x0F) << 4) | ((c3 & 0x3C) >> 2);
+		if (dptr >= end) break;
+
+		BF_safe_atoi64(c4, *sptr++);
+		*dptr++ = ((c3 & 0x03) << 6) | c4;
+	} while (dptr < end);
+
+	return 0;
+}
+
+static void BF_encode(char *dst, const BF_word *src, int size)
+{
+	const unsigned char *sptr = (const unsigned char *)src;
+	const unsigned char *end = sptr + size;
+	unsigned char *dptr = (unsigned char *)dst;
+	unsigned int c1, c2;
+
+	do {
+		c1 = *sptr++;
+		*dptr++ = BF_itoa64[c1 >> 2];
+		c1 = (c1 & 0x03) << 4;
+		if (sptr >= end) {
+			*dptr++ = BF_itoa64[c1];
+			break;
+		}
+
+		c2 = *sptr++;
+		c1 |= c2 >> 4;
+		*dptr++ = BF_itoa64[c1];
+		c1 = (c2 & 0x0f) << 2;
+		if (sptr >= end) {
+			*dptr++ = BF_itoa64[c1];
+			break;
+		}
+
+		c2 = *sptr++;
+		c1 |= c2 >> 6;
+		*dptr++ = BF_itoa64[c1];
+		*dptr++ = BF_itoa64[c2 & 0x3f];
+	} while (sptr < end);
+}
+
+static void BF_swap(BF_word *x, int count)
+{
+	static int endianness_check = 1;
+	char *is_little_endian = (char *)&endianness_check;
+	BF_word tmp;
+
+	if (*is_little_endian)
+	do {
+		tmp = *x;
+		tmp = (tmp << 16) | (tmp >> 16);
+		*x++ = ((tmp & 0x00FF00FF) << 8) | ((tmp >> 8) & 0x00FF00FF);
+	} while (--count);
+}
+
+#if BF_SCALE
+/* Architectures which can shift addresses left by 2 bits with no extra cost */
+#define BF_ROUND(L, R, N) \
+	tmp1 = L & 0xFF; \
+	tmp2 = L >> 8; \
+	tmp2 &= 0xFF; \
+	tmp3 = L >> 16; \
+	tmp3 &= 0xFF; \
+	tmp4 = L >> 24; \
+	tmp1 = data.ctx.S[3][tmp1]; \
+	tmp2 = data.ctx.S[2][tmp2]; \
+	tmp3 = data.ctx.S[1][tmp3]; \
+	tmp3 += data.ctx.S[0][tmp4]; \
+	tmp3 ^= tmp2; \
+	R ^= data.ctx.P[N + 1]; \
+	tmp3 += tmp1; \
+	R ^= tmp3;
+#else
+/* Architectures with no complicated addressing modes supported */
+#define BF_INDEX(S, i) \
+	(*((BF_word *)(((unsigned char *)S) + (i))))
+#define BF_ROUND(L, R, N) \
+	tmp1 = L & 0xFF; \
+	tmp1 <<= 2; \
+	tmp2 = L >> 6; \
+	tmp2 &= 0x3FC; \
+	tmp3 = L >> 14; \
+	tmp3 &= 0x3FC; \
+	tmp4 = L >> 22; \
+	tmp4 &= 0x3FC; \
+	tmp1 = BF_INDEX(data.ctx.S[3], tmp1); \
+	tmp2 = BF_INDEX(data.ctx.S[2], tmp2); \
+	tmp3 = BF_INDEX(data.ctx.S[1], tmp3); \
+	tmp3 += BF_INDEX(data.ctx.S[0], tmp4); \
+	tmp3 ^= tmp2; \
+	R ^= data.ctx.P[N + 1]; \
+	tmp3 += tmp1; \
+	R ^= tmp3;
+#endif
+
+/*
+ * Encrypt one block, BF_N is hardcoded here.
+ */
+#define BF_ENCRYPT \
+	L ^= data.ctx.P[0]; \
+	BF_ROUND(L, R, 0); \
+	BF_ROUND(R, L, 1); \
+	BF_ROUND(L, R, 2); \
+	BF_ROUND(R, L, 3); \
+	BF_ROUND(L, R, 4); \
+	BF_ROUND(R, L, 5); \
+	BF_ROUND(L, R, 6); \
+	BF_ROUND(R, L, 7); \
+	BF_ROUND(L, R, 8); \
+	BF_ROUND(R, L, 9); \
+	BF_ROUND(L, R, 10); \
+	BF_ROUND(R, L, 11); \
+	BF_ROUND(L, R, 12); \
+	BF_ROUND(R, L, 13); \
+	BF_ROUND(L, R, 14); \
+	BF_ROUND(R, L, 15); \
+	tmp4 = R; \
+	R = L; \
+	L = tmp4 ^ data.ctx.P[BF_N + 1];
+
+#if BF_ASM
+#define BF_body() \
+	_BF_body_r(&data.ctx);
+#else
+#define BF_body() \
+	L = R = 0; \
+	ptr = data.ctx.P; \
+	do { \
+		ptr += 2; \
+		BF_ENCRYPT; \
+		*(ptr - 2) = L; \
+		*(ptr - 1) = R; \
+	} while (ptr < &data.ctx.P[BF_N + 2]); \
+\
+	ptr = data.ctx.S[0]; \
+	do { \
+		ptr += 2; \
+		BF_ENCRYPT; \
+		*(ptr - 2) = L; \
+		*(ptr - 1) = R; \
+	} while (ptr < &data.ctx.S[3][0xFF]);
+#endif
+
+static void BF_set_key(const char *key, BF_key expanded, BF_key initial,
+    unsigned char flags)
+{
+	const char *ptr = key;
+	unsigned int bug, i, j;
+	BF_word safety, sign, diff, tmp[2];
+
+/*
+ * There was a sign extension bug in older revisions of this function.  While
+ * we would have liked to simply fix the bug and move on, we have to provide
+ * a backwards compatibility feature (essentially the bug) for some systems and
+ * a safety measure for some others.  The latter is needed because for certain
+ * multiple inputs to the buggy algorithm there exist easily found inputs to
+ * the correct algorithm that produce the same hash.  Thus, we optionally
+ * deviate from the correct algorithm just enough to avoid such collisions.
+ * While the bug itself affected the majority of passwords containing
+ * characters with the 8th bit set (although only a percentage of those in a
+ * collision-producing way), the anti-collision safety measure affects
+ * only a subset of passwords containing the '\xff' character (not even all of
+ * those passwords, just some of them).  This character is not found in valid
+ * UTF-8 sequences and is rarely used in popular 8-bit character encodings.
+ * Thus, the safety measure is unlikely to cause much annoyance, and is a
+ * reasonable tradeoff to use when authenticating against existing hashes that
+ * are not reliably known to have been computed with the correct algorithm.
+ *
+ * We use an approach that tries to minimize side-channel leaks of password
+ * information - that is, we mostly use fixed-cost bitwise operations instead
+ * of branches or table lookups.  (One conditional branch based on password
+ * length remains.  It is not part of the bug aftermath, though, and is
+ * difficult and possibly unreasonable to avoid given the use of C strings by
+ * the caller, which results in similar timing leaks anyway.)
+ *
+ * For actual implementation, we set an array index in the variable "bug"
+ * (0 means no bug, 1 means sign extension bug emulation) and a flag in the
+ * variable "safety" (bit 16 is set when the safety measure is requested).
+ * Valid combinations of settings are:
+ *
+ * Prefix "$2a$": bug = 0, safety = 0x10000
+ * Prefix "$2x$": bug = 1, safety = 0
+ * Prefix "$2y$": bug = 0, safety = 0
+ */
+	bug = (unsigned int)flags & 1;
+	safety = ((BF_word)flags & 2) << 15;
+
+	sign = diff = 0;
+
+	for (i = 0; i < BF_N + 2; i++) {
+		tmp[0] = tmp[1] = 0;
+		for (j = 0; j < 4; j++) {
+			tmp[0] <<= 8;
+			tmp[0] |= (unsigned char)*ptr; /* correct */
+			tmp[1] <<= 8;
+			tmp[1] |= (BF_word_signed)(signed char)*ptr; /* bug */
+/*
+ * Sign extension in the first char has no effect - nothing to overwrite yet,
+ * and those extra 24 bits will be fully shifted out of the 32-bit word.  For
+ * chars 2, 3, 4 in each four-char block, we set bit 7 of "sign" if sign
+ * extension in tmp[1] occurs.  Once this flag is set, it remains set.
+ */
+			if (j)
+				sign |= tmp[1] & 0x80;
+			if (!*ptr)
+				ptr = key;
+			else
+				ptr++;
+		}
+		diff |= tmp[0] ^ tmp[1]; /* Non-zero on any differences */
+
+		expanded[i] = tmp[bug];
+		initial[i] = BF_init_state.P[i] ^ tmp[bug];
+	}
+
+/*
+ * At this point, "diff" is zero iff the correct and buggy algorithms produced
+ * exactly the same result.  If so and if "sign" is non-zero, which indicates
+ * that there was a non-benign sign extension, this means that we have a
+ * collision between the correctly computed hash for this password and a set of
+ * passwords that could be supplied to the buggy algorithm.  Our safety measure
+ * is meant to protect from such many-buggy to one-correct collisions, by
+ * deviating from the correct algorithm in such cases.  Let's check for this.
+ */
+	diff |= diff >> 16; /* still zero iff exact match */
+	diff &= 0xffff; /* ditto */
+	diff += 0xffff; /* bit 16 set iff "diff" was non-zero (on non-match) */
+	sign <<= 9; /* move the non-benign sign extension flag to bit 16 */
+	sign &= ~diff & safety; /* action needed? */
+
+/*
+ * If we have determined that we need to deviate from the correct algorithm,
+ * flip bit 16 in initial expanded key.  (The choice of 16 is arbitrary, but
+ * let's stick to it now.  It came out of the approach we used above, and it's
+ * not any worse than any other choice we could make.)
+ *
+ * It is crucial that we don't do the same to the expanded key used in the main
+ * Eksblowfish loop.  By doing it to only one of these two, we deviate from a
+ * state that could be directly specified by a password to the buggy algorithm
+ * (and to the fully correct one as well, but that's a side-effect).
+ */
+	initial[0] ^= sign;
+}
+
+static char *BF_crypt(const char *key, const char *setting,
+	char *output, int size,
+	BF_word min)
+{
+#if BF_ASM
+	extern void _BF_body_r(BF_ctx *ctx);
+#endif
+	static const unsigned char flags_by_subtype[26] =
+		{2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 0};
+	struct {
+		BF_ctx ctx;
+		BF_key expanded_key;
+		union {
+			BF_word salt[4];
+			BF_word output[6];
+		} binary;
+	} data;
+	BF_word L, R;
+	BF_word tmp1, tmp2, tmp3, tmp4;
+	BF_word *ptr;
+	BF_word count;
+	int i;
+
+	if (size < 7 + 22 + 31 + 1) {
+		__set_errno(ERANGE);
+		return NULL;
+	}
+
+	if (setting[0] != '$' ||
+	    setting[1] != '2' ||
+	    setting[2] < 'a' || setting[2] > 'z' ||
+	    !flags_by_subtype[(unsigned int)(unsigned char)setting[2] - 'a'] ||
+	    setting[3] != '$' ||
+	    setting[4] < '0' || setting[4] > '1' ||
+	    setting[5] < '0' || setting[5] > '9' ||
+	    (setting[4] == '1' && setting[5] > '7') ||
+	    setting[6] != '$') {
+		__set_errno(EINVAL);
+		return NULL;
+	}
+
+	count = (BF_word)1 << ((setting[4] - '0') * 10 + (setting[5] - '0'));
+	if (count < min || BF_decode(data.binary.salt, &setting[7], 16)) {
+		__set_errno(EINVAL);
+		return NULL;
+	}
+	BF_swap(data.binary.salt, 4);
+
+	BF_set_key(key, data.expanded_key, data.ctx.P,
+	    flags_by_subtype[(unsigned int)(unsigned char)setting[2] - 'a']);
+
+	memcpy(data.ctx.S, BF_init_state.S, sizeof(data.ctx.S));
+
+	L = R = 0;
+	for (i = 0; i < BF_N + 2; i += 2) {
+		L ^= data.binary.salt[i & 2];
+		R ^= data.binary.salt[(i & 2) + 1];
+		BF_ENCRYPT;
+		data.ctx.P[i] = L;
+		data.ctx.P[i + 1] = R;
+	}
+
+	ptr = data.ctx.S[0];
+	do {
+		ptr += 4;
+		L ^= data.binary.salt[(BF_N + 2) & 3];
+		R ^= data.binary.salt[(BF_N + 3) & 3];
+		BF_ENCRYPT;
+		*(ptr - 4) = L;
+		*(ptr - 3) = R;
+
+		L ^= data.binary.salt[(BF_N + 4) & 3];
+		R ^= data.binary.salt[(BF_N + 5) & 3];
+		BF_ENCRYPT;
+		*(ptr - 2) = L;
+		*(ptr - 1) = R;
+	} while (ptr < &data.ctx.S[3][0xFF]);
+
+	do {
+		int done;
+
+		for (i = 0; i < BF_N + 2; i += 2) {
+			data.ctx.P[i] ^= data.expanded_key[i];
+			data.ctx.P[i + 1] ^= data.expanded_key[i + 1];
+		}
+
+		done = 0;
+		do {
+			BF_body();
+			if (done)
+				break;
+			done = 1;
+
+			tmp1 = data.binary.salt[0];
+			tmp2 = data.binary.salt[1];
+			tmp3 = data.binary.salt[2];
+			tmp4 = data.binary.salt[3];
+			for (i = 0; i < BF_N; i += 4) {
+				data.ctx.P[i] ^= tmp1;
+				data.ctx.P[i + 1] ^= tmp2;
+				data.ctx.P[i + 2] ^= tmp3;
+				data.ctx.P[i + 3] ^= tmp4;
+			}
+			data.ctx.P[16] ^= tmp1;
+			data.ctx.P[17] ^= tmp2;
+		} while (1);
+	} while (--count);
+
+	for (i = 0; i < 6; i += 2) {
+		L = BF_magic_w[i];
+		R = BF_magic_w[i + 1];
+
+		count = 64;
+		do {
+			BF_ENCRYPT;
+		} while (--count);
+
+		data.binary.output[i] = L;
+		data.binary.output[i + 1] = R;
+	}
+
+	memcpy(output, setting, 7 + 22 - 1);
+	output[7 + 22 - 1] = BF_itoa64[(int)
+		BF_atoi64[(int)setting[7 + 22 - 1] - 0x20] & 0x30];
+
+/* This has to be bug-compatible with the original implementation, so
+ * only encode 23 of the 24 bytes. :-) */
+	BF_swap(data.binary.output, 6);
+	BF_encode(&output[7 + 22], data.binary.output, 23);
+	output[7 + 22 + 31] = '\0';
+
+	return output;
+}
+
+int _crypt_output_magic(const char *setting, char *output, int size)
+{
+	if (size < 3)
+		return -1;
+
+	output[0] = '*';
+	output[1] = '0';
+	output[2] = '\0';
+
+	if (setting[0] == '*' && setting[1] == '0')
+		output[1] = '1';
+
+	return 0;
+}
+
+/*
+ * Please preserve the runtime self-test.  It serves two purposes at once:
+ *
+ * 1. We really can't afford the risk of producing incompatible hashes e.g.
+ * when there's something like gcc bug 26587 again, whereas an application or
+ * library integrating this code might not also integrate our external tests or
+ * it might not run them after every build.  Even if it does, the miscompile
+ * might only occur on the production build, but not on a testing build (such
+ * as because of different optimization settings).  It is painful to recover
+ * from incorrectly-computed hashes - merely fixing whatever broke is not
+ * enough.  Thus, a proactive measure like this self-test is needed.
+ *
+ * 2. We don't want to leave sensitive data from our actual password hash
+ * computation on the stack or in registers.  Previous revisions of the code
+ * would do explicit cleanups, but simply running the self-test after hash
+ * computation is more reliable.
+ *
+ * The performance cost of this quick self-test is around 0.6% at the "$2a$08"
+ * setting.
+ */
+char *_crypt_blowfish_rn(const char *key, const char *setting,
+	char *output, int size)
+{
+	const char *test_key = "8b \xd0\xc1\xd2\xcf\xcc\xd8";
+	const char *test_setting = "$2a$00$abcdefghijklmnopqrstuu";
+	static const char * const test_hash[2] =
+		{"VUrPmXD6q/nVSSp7pNDhCR9071IfIRe\0\x55", /* $2x$ */
+		"i1D709vfamulimlGcq0qq3UvuUasvEa\0\x55"}; /* $2a$, $2y$ */
+	char *retval;
+	const char *p;
+	int save_errno, ok;
+	struct {
+		char s[7 + 22 + 1];
+		char o[7 + 22 + 31 + 1 + 1 + 1];
+	} buf;
+
+/* Hash the supplied password */
+	_crypt_output_magic(setting, output, size);
+	retval = BF_crypt(key, setting, output, size, 16);
+	save_errno = errno;
+
+/*
+ * Do a quick self-test.  It is important that we make both calls to BF_crypt()
+ * from the same scope such that they likely use the same stack locations,
+ * which makes the second call overwrite the first call's sensitive data on the
+ * stack and makes it more likely that any alignment related issues would be
+ * detected by the self-test.
+ */
+	memcpy(buf.s, test_setting, sizeof(buf.s));
+	if (retval)
+		buf.s[2] = setting[2];
+	memset(buf.o, 0x55, sizeof(buf.o));
+	buf.o[sizeof(buf.o) - 1] = 0;
+	p = BF_crypt(test_key, buf.s, buf.o, sizeof(buf.o) - (1 + 1), 1);
+
+	ok = (p == buf.o &&
+	    !memcmp(p, buf.s, 7 + 22) &&
+	    !memcmp(p + (7 + 22),
+	    test_hash[(unsigned int)(unsigned char)buf.s[2] & 1],
+	    31 + 1 + 1 + 1));
+
+	{
+		const char *k = "\xff\xa3" "34" "\xff\xff\xff\xa3" "345";
+		BF_key ae, ai, ye, yi;
+		BF_set_key(k, ae, ai, 2); /* $2a$ */
+		BF_set_key(k, ye, yi, 4); /* $2y$ */
+		ai[0] ^= 0x10000; /* undo the safety (for comparison) */
+		ok = ok && ai[0] == 0xdb9c59bc && ye[17] == 0x33343500 &&
+		    !memcmp(ae, ye, sizeof(ae)) &&
+		    !memcmp(ai, yi, sizeof(ai));
+	}
+
+	__set_errno(save_errno);
+	if (ok)
+		return retval;
+
+/* Should not happen */
+	_crypt_output_magic(setting, output, size);
+	__set_errno(EINVAL); /* pretend we don't support this hash type */
+	return NULL;
+}
+
+char *_crypt_gensalt_blowfish_rn(const char *prefix, unsigned long count,
+	const char *input, int size, char *output, int output_size)
+{
+	if (size < 16 || output_size < 7 + 22 + 1 ||
+	    (count && (count < 4 || count > 17)) ||
+	    prefix[0] != '$' || prefix[1] != '2' ||
+	    (prefix[2] != 'a' && prefix[2] != 'y')) {
+		if (output_size > 0) output[0] = '\0';
+		__set_errno((output_size < 7 + 22 + 1) ? ERANGE : EINVAL);
+		return NULL;
+	}
+
+	if (!count) count = 5;
+
+	output[0] = '$';
+	output[1] = '2';
+	output[2] = prefix[2];
+	output[3] = '$';
+	output[4] = '0' + count / 10;
+	output[5] = '0' + count % 10;
+	output[6] = '$';
+
+	BF_encode(&output[7], (const BF_word *)input, 16);
+	output[7 + 22] = '\0';
+
+	return output;
+}
diff --git a/crypto/crypt_blowfish.h b/crypto/crypt_blowfish.h
new file mode 100644
index 00000000000..2ee0d8c1d80
--- /dev/null
+++ b/crypto/crypt_blowfish.h
@@ -0,0 +1,27 @@
+/*
+ * Written by Solar Designer <solar at openwall.com> in 2000-2011.
+ * No copyright is claimed, and the software is hereby placed in the public
+ * domain.  In case this attempt to disclaim copyright and place the software
+ * in the public domain is deemed null and void, then the software is
+ * Copyright (c) 2000-2011 Solar Designer and it is hereby released to the
+ * general public under the following terms:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted.
+ *
+ * There's ABSOLUTELY NO WARRANTY, express or implied.
+ *
+ * See crypt_blowfish.c for more information.
+ */
+
+#ifndef _CRYPT_BLOWFISH_H
+#define _CRYPT_BLOWFISH_H
+
+extern int _crypt_output_magic(const char *setting, char *output, int size);
+extern char *_crypt_blowfish_rn(const char *key, const char *setting,
+	char *output, int size);
+extern char *_crypt_gensalt_blowfish_rn(const char *prefix,
+	unsigned long count,
+	const char *input, int size, char *output, int output_size);
+
+#endif
diff --git a/crypto/getuuid.c b/crypto/getuuid.c
new file mode 100644
index 00000000000..94845b024c9
--- /dev/null
+++ b/crypto/getuuid.c
@@ -0,0 +1,208 @@
+/* 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 attempts to generate V1 UUIDs according to the Internet Draft
+ * located at http://www.webdav.org/specs/draft-leach-uuids-guids-01.txt
+ */
+#include "apr.h"
+#include "apr_uuid.h"
+#include "apr_md5.h"
+#include "apr_general.h"
+#include "apr_portable.h"
+
+
+#if APR_HAVE_UNISTD_H
+#include <unistd.h>     /* for getpid, gethostname */
+#endif
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h>     /* for rand, srand */
+#endif
+
+
+#if APR_HAVE_STRING_H
+#include <string.h>
+#endif
+#if APR_HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#if APR_HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#if APR_HAVE_SYS_TIME_H
+#include <sys/time.h>   /* for gettimeofday */
+#endif
+
+#define NODE_LENGTH 6
+
+static int uuid_state_seqnum;
+static unsigned char uuid_state_node[NODE_LENGTH] = { 0 };
+
+
+static void get_random_info(unsigned char node[NODE_LENGTH])
+{
+#if APR_HAS_RANDOM
+
+    (void) apr_generate_random_bytes(node, NODE_LENGTH);
+
+#else
+
+    unsigned char seed[APR_MD5_DIGESTSIZE];
+    apr_md5_ctx_t c;
+
+    /* ### probably should revise some of this to be a bit more portable */
+
+    /* Leach & Salz use Linux-specific struct sysinfo;
+     * replace with pid/tid for portability (in the spirit of mod_unique_id) */
+    struct {
+        /* Add thread id here, if applicable, when we get to pthread or apr */
+        pid_t pid;
+#ifdef NETWARE
+        apr_uint64_t t;
+#else
+        struct timeval t;
+#endif
+        char hostname[257];
+
+    } r;
+
+    apr_md5_init(&c);
+#ifdef NETWARE
+    r.pid = NXThreadGetId();
+    NXGetTime(NX_SINCE_BOOT, NX_USECONDS, &(r.t));
+#else
+    r.pid = getpid();
+    gettimeofday(&r.t, (struct timezone *)0);
+#endif
+    gethostname(r.hostname, 256);
+    apr_md5_update(&c, (const unsigned char *)&r, sizeof(r));
+    apr_md5_final(seed, &c);
+
+    memcpy(node, seed, NODE_LENGTH);    /* use a subset of the seed bytes */
+#endif
+}
+
+/* This implementation generates a random node ID instead of a
+   system-dependent call to get IEEE node ID. This is also more secure:
+   we aren't passing out our MAC address.
+*/
+static void get_pseudo_node_identifier(unsigned char *node)
+{
+    get_random_info(node);
+    node[0] |= 0x01;                    /* this designates a random multicast node ID */
+}
+
+static void get_system_time(apr_uint64_t *uuid_time)
+{
+    /* ### fix this call to be more portable? */
+    *uuid_time = apr_time_now();
+
+    /* Offset between UUID formatted times and Unix formatted times.
+       UUID UTC base time is October 15, 1582.
+       Unix base time is January 1, 1970.      */
+    *uuid_time = (*uuid_time * 10) + APR_TIME_C(0x01B21DD213814000);
+}
+
+/* true_random -- generate a crypto-quality random number. */
+static int true_random(void)
+{
+    apr_uint64_t time_now;
+
+#if APR_HAS_RANDOM
+    unsigned char buf[2];
+
+    if (apr_generate_random_bytes(buf, 2) == APR_SUCCESS) {
+        return (buf[0] << 8) | buf[1];
+    }
+#endif
+
+    /* crap. this isn't crypto quality, but it will be Good Enough */
+
+    time_now = apr_time_now();
+    srand((unsigned int)(((time_now >> 32) ^ time_now) & 0xffffffff));
+
+    return rand() & 0x0FFFF;
+}
+
+static void init_state(void)
+{
+    uuid_state_seqnum = true_random();
+    get_pseudo_node_identifier(uuid_state_node);
+}
+
+static void get_current_time(apr_uint64_t *timestamp)
+{
+    /* ### this needs to be made thread-safe! */
+
+    apr_uint64_t time_now;
+    static apr_uint64_t time_last = 0;
+    static apr_uint64_t fudge = 0;
+
+    get_system_time(&time_now);
+        
+    /* if clock reading changed since last UUID generated... */
+    if (time_last != time_now) {
+        /* The clock reading has changed since the last UUID was generated.
+           Reset the fudge factor. if we are generating them too fast, then
+           the fudge may need to be reset to something greater than zero. */
+        if (time_last + fudge > time_now)
+            fudge = time_last + fudge - time_now + 1;
+        else
+            fudge = 0;
+        time_last = time_now;
+    }
+    else {
+        /* We generated two really fast. Bump the fudge factor. */
+        ++fudge;
+    }
+
+    *timestamp = time_now + fudge;
+}
+
+APR_DECLARE(void) apr_uuid_get(apr_uuid_t *uuid)
+{
+    apr_uint64_t timestamp;
+    unsigned char *d = uuid->data;
+
+#if APR_HAS_OS_UUID
+    if (apr_os_uuid_get(d) == APR_SUCCESS) {
+        return;
+    }
+#endif /* !APR_HAS_OS_UUID */
+
+    if (!uuid_state_node[0])
+        init_state();
+
+    get_current_time(&timestamp);
+
+    /* time_low, uint32 */
+    d[3] = (unsigned char)timestamp;
+    d[2] = (unsigned char)(timestamp >> 8);
+    d[1] = (unsigned char)(timestamp >> 16);
+    d[0] = (unsigned char)(timestamp >> 24);
+    /* time_mid, uint16 */
+    d[5] = (unsigned char)(timestamp >> 32);
+    d[4] = (unsigned char)(timestamp >> 40);
+    /* time_hi_and_version, uint16 */
+    d[7] = (unsigned char)(timestamp >> 48);
+    d[6] = (unsigned char)(((timestamp >> 56) & 0x0F) | 0x10);
+    /* clock_seq_hi_and_reserved, uint8 */
+    d[8] = (unsigned char)(((uuid_state_seqnum >> 8) & 0x3F) | 0x80);
+    /* clock_seq_low, uint8 */
+    d[9] = (unsigned char)uuid_state_seqnum;
+    /* node, byte[6] */
+    memcpy(&d[10], uuid_state_node, NODE_LENGTH);
+}
diff --git a/crypto/uuid.c b/crypto/uuid.c
new file mode 100644
index 00000000000..9b095920943
--- /dev/null
+++ b/crypto/uuid.c
@@ -0,0 +1,130 @@
+/* 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 <stdio.h>      /* for sprintf */
+
+#include "apr.h"
+#include "apr_uuid.h"
+#include "apr_errno.h"
+#include "apr_lib.h"
+
+
+APR_DECLARE(void) apr_uuid_format(char *buffer, const apr_uuid_t *uuid)
+{
+    const unsigned char *d = uuid->data;
+
+    sprintf(buffer,
+            "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+            d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7],
+            d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
+}
+
+/* convert a pair of hex digits to an integer value [0,255] */
+#if 'A' == 65
+static unsigned char parse_hexpair(const char *s)
+{
+    int result;
+    int temp;
+
+    result = s[0] - '0';
+    if (result > 48)
+        result = (result - 39) << 4;
+    else if (result > 16)
+        result = (result - 7) << 4;
+    else
+        result = result << 4;
+
+    temp = s[1] - '0';
+    if (temp > 48)
+        result |= temp - 39;
+    else if (temp > 16)
+        result |= temp - 7;
+    else
+        result |= temp;
+
+    return (unsigned char)result;
+}
+#else
+static unsigned char parse_hexpair(const char *s)
+{
+    int result;
+
+    if (isdigit(*s)) {
+        result = (*s - '0') << 4;
+    }
+    else {
+        if (isupper(*s)) {
+            result = (*s - 'A' + 10) << 4;
+        }
+        else {
+            result = (*s - 'a' + 10) << 4;
+        }
+    }
+
+    ++s;
+    if (isdigit(*s)) {
+        result |= (*s - '0');
+    }
+    else {
+        if (isupper(*s)) {
+            result |= (*s - 'A' + 10);
+        }
+        else {
+            result |= (*s - 'a' + 10);
+        }
+    }
+
+    return (unsigned char)result;
+}
+#endif
+
+APR_DECLARE(apr_status_t) apr_uuid_parse(apr_uuid_t *uuid,
+                                         const char *uuid_str)
+{
+    int i;
+    unsigned char *d = uuid->data;
+
+    for (i = 0; i < 36; ++i) {
+        char c = uuid_str[i];
+        if (!apr_isxdigit(c) &&
+            !(c == '-' && (i == 8 || i == 13 || i == 18 || i == 23)))
+            /* ### need a better value */
+            return APR_BADARG;
+    }
+    if (uuid_str[36] != '\0') {
+        /* ### need a better value */
+        return APR_BADARG;
+    }
+
+    d[0] = parse_hexpair(&uuid_str[0]);
+    d[1] = parse_hexpair(&uuid_str[2]);
+    d[2] = parse_hexpair(&uuid_str[4]);
+    d[3] = parse_hexpair(&uuid_str[6]);
+
+    d[4] = parse_hexpair(&uuid_str[9]);
+    d[5] = parse_hexpair(&uuid_str[11]);
+
+    d[6] = parse_hexpair(&uuid_str[14]);
+    d[7] = parse_hexpair(&uuid_str[16]);
+
+    d[8] = parse_hexpair(&uuid_str[19]);
+    d[9] = parse_hexpair(&uuid_str[21]);
+
+    for (i = 6; i--;)
+        d[10 + i] = parse_hexpair(&uuid_str[i*2+24]);
+
+    return APR_SUCCESS;
+}
diff --git a/dbd/NWGNUdbdmysql b/dbd/NWGNUdbdmysql
new file mode 100644
index 00000000000..bc799eb52a0
--- /dev/null
+++ b/dbd/NWGNUdbdmysql
@@ -0,0 +1,290 @@
+#
+# 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
+#
+
+ifndef EnvironmentDefined
+include $(APR_WORK)/build/NWGNUhead.inc
+endif
+
+#
+# build this level's files
+
+#
+# Make sure all needed macro's are defined
+#
+
+# LINK_STATIC = 1
+
+# for now defined here - should finally go into build/NWGNUenvironment.inc
+MYSQL_INC = $(MYSQLSDK)/include
+MYSQL_IMP = $(MYSQLSDK)/lib/libmysql.imp
+MYSQL_LIB = $(MYSQLSDK)/lib/libmysqlclient_r.lib $(MYSQLSDK)/lib/libz.lib
+MYSQL_NLM = libmysql
+ifneq "$(wildcard $(MYSQL_INC)/mysql.h)" "$(MYSQL_INC)/mysql.h"
+$(error MYSQLSDK does not point to a valid MySQL SDK) 
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS	+= \
+			$(APR)/include \
+			$(APR)/include/private \
+			$(APR)/include/arch/netware \
+			$(MYSQL_INC) \
+			$(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS		+= \
+			$(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES	+= \
+			-DAPU_DSO_MODULE_BUILD \
+			-DAPU_HAVE_MYSQL=1 \
+			-DHAVE_MYSQL_H \
+			$(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS		+= \
+			$(EOLIST)
+
+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	= dbdmysql
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION	= Apache Portability Runtime Library $(VERSION_STR) DBD MySQL Driver Module
+
+#
+# This is used by the '-threadname' directive.  If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME	= dbdmysql
+
+#
+# If this is specified, it will override VERSION value in
+# $(APR_WORK)/build/NWGNUenvironment.inc
+#
+NLM_VERSION	=
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE	=
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM	=
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM	=
+
+#
+# If this is specified it will be used by the link '-check' directive
+#
+NLM_CHECK_SYM	=
+
+#
+# If these are specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS	=
+
+#
+# If this is specified it will be linked in with the XDCData option in the def
+# file instead of the default of $(NWOS)/apache.xdc.  XDCData can be disabled
+# by setting APACHE_UNIPROC in the environment
+#
+XDCDATA		=
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+	$(OBJDIR)/$(NLM_NAME).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)/apr_dbd_mysql.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)
+
+ifeq ($(LINK_STATIC),1)
+FILES_nlm_libs += \
+	$(MYSQL_LIB) \
+	$(EOLIST)
+endif
+
+#
+# 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)
+
+ifneq ($(LINK_STATIC),1)
+FILES_nlm_modules += \
+	$(MYSQL_NLM) \
+	$(EOLIST)
+endif
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+	@$(APR)/aprlib.imp \
+	@$(NOVI)/libc.imp \
+	$(EOLIST)
+
+ifneq ($(LINK_STATIC),1)
+FILES_nlm_Ximports += \
+	@$(MYSQL_IMP) \
+	$(EOLIST)
+endif
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+	apr_dbd_mysql_driver \
+	$(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 $(APR_WORK)/build/NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(APRBUILD)/NWGNUtail.inc
+
diff --git a/dbd/NWGNUdbdpgsql b/dbd/NWGNUdbdpgsql
new file mode 100644
index 00000000000..61946df51f6
--- /dev/null
+++ b/dbd/NWGNUdbdpgsql
@@ -0,0 +1,292 @@
+#
+# 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
+#
+
+ifndef EnvironmentDefined
+include $(APR_WORK)/build/NWGNUhead.inc
+endif
+
+#
+# build this level's files
+
+#
+# Make sure all needed macro's are defined
+#
+
+# LINK_STATIC = 1
+
+# for now defined here - should finally go into build/NWGNUenvironment.inc
+PGSQL_INC = $(PGSQLSDK)/inc
+PGSQL_IMP = $(PGSQLSDK)/imp/libpq.imp
+PGSQL_LIB = $(PGSQLSDK)/lib/libpq.lib
+PGSQL_NLM = libpq
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS	+= \
+			$(APR)/include \
+			$(APR)/include/private \
+			$(APR)/include/arch/netware \
+			$(PGSQL_INC) \
+			$(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS		+= \
+			$(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES	+= \
+			-DAPU_DSO_MODULE_BUILD \
+			-DAPU_HAVE_PGSQL=1 \
+			-DHAVE_LIBPQ_FE_H \
+			$(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS		+= \
+			$(EOLIST)
+
+ifdef LINK_STATIC
+XLFLAGS		+= \
+			$(EOLIST)
+else
+XLFLAGS		+= \
+			$(EOLIST)
+endif
+
+#
+# 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	= dbdpgsql
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION	= Apache Portability Runtime Library $(VERSION_STR) DBD PostgreSQL Driver Module
+
+#
+# This is used by the '-threadname' directive.  If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME	= dbdpgsql
+
+#
+# If this is specified, it will override VERSION value in
+# $(APR_WORK)/build/NWGNUenvironment.inc
+#
+NLM_VERSION	=
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE	=
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM	=
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM	=
+
+#
+# If this is specified it will be used by the link '-check' directive
+#
+NLM_CHECK_SYM	=
+
+#
+# If these are specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS	=
+
+#
+# If this is specified it will be linked in with the XDCData option in the def
+# file instead of the default of $(NWOS)/apache.xdc.  XDCData can be disabled
+# by setting APACHE_UNIPROC in the environment
+#
+XDCDATA		=
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+	$(OBJDIR)/$(NLM_NAME).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)/apr_dbd_pgsql.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)
+
+ifeq ($(LINK_STATIC),1)
+FILES_nlm_libs += \
+	$(PGSQL_LIB) \
+	$(EOLIST)
+endif
+
+#
+# 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)
+
+ifneq ($(LINK_STATIC),1)
+FILES_nlm_modules += \
+	$(PGSQL_NLM) \
+	$(EOLIST)
+endif
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+	@$(APR)/aprlib.imp \
+	@$(NOVI)/libc.imp \
+	$(EOLIST)
+
+ifneq ($(LINK_STATIC),1)
+FILES_nlm_Ximports += \
+	@$(PGSQL_IMP) \
+	$(EOLIST)
+endif
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+	apr_dbd_pgsql_driver \
+	$(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 $(APR_WORK)/build/NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(APRBUILD)/NWGNUtail.inc
+
diff --git a/dbd/NWGNUdbdsqli2 b/dbd/NWGNUdbdsqli2
new file mode 100644
index 00000000000..8887a53ffa9
--- /dev/null
+++ b/dbd/NWGNUdbdsqli2
@@ -0,0 +1,291 @@
+#
+# 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
+#
+
+ifndef EnvironmentDefined
+include $(APR_WORK)/build/NWGNUhead.inc
+endif
+
+#
+# build this level's files
+
+#
+# Make sure all needed macro's are defined
+#
+
+# LINK_STATIC = 1
+
+# for now defined here - should finally go into build/NWGNUenvironment.inc
+SQLITE2_INC = $(SQLITE2SDK)/src
+SQLITE2_IMP = $(SQLITE2SDK)/lsqlite2.imp
+SQLITE2_LIB = $(SQLITE2SDK)/lsqlite2.lib
+SQLITE2_NLM = lsqlite2
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS	+= \
+			$(APR)/include \
+			$(APR)/include/private \
+			$(APR)/include/arch/netware \
+			$(SQLITE2_INC) \
+			$(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS		+= \
+			$(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES	+= \
+			-DAPU_DSO_MODULE_BUILD \
+			-DAPU_HAVE_SQLITE2=1 \
+			$(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS		+= \
+			$(EOLIST)
+
+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	= dbdsqli2
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION	= Apache Portability Runtime Library $(VERSION_STR) DBD SQLite2 Driver Module
+
+#
+# This is used by the '-threadname' directive.  If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME	= dbdsqli2
+
+#
+# If this is specified, it will override VERSION value in
+# $(APR_WORK)/build/NWGNUenvironment.inc
+#
+NLM_VERSION	=
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE	=
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM	=
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM	=
+
+#
+# If this is specified it will be used by the link '-check' directive
+#
+NLM_CHECK_SYM	=
+
+#
+# If these are specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS	=
+
+#
+# If this is specified it will be linked in with the XDCData option in the def
+# file instead of the default of $(NWOS)/apache.xdc.  XDCData can be disabled
+# by setting APACHE_UNIPROC in the environment
+#
+XDCDATA		=
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+	$(OBJDIR)/$(NLM_NAME).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)/apr_dbd_sqlite2.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)
+
+ifeq ($(LINK_STATIC),1)
+FILES_nlm_libs += \
+	$(SQLITE2_LIB) \
+	$(EOLIST)
+endif
+
+#
+# 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)
+
+ifneq ($(LINK_STATIC),1)
+FILES_nlm_modules += \
+	$(SQLITE2_NLM) \
+	$(EOLIST)
+endif
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+	@$(APR)/aprlib.imp \
+	@$(NOVI)/libc.imp \
+	$(EOLIST)
+
+FILES_nlm_imports = \
+	apr_dbd_mutex_lock \
+	apr_dbd_mutex_unlock \
+	$(EOLIST)
+
+ifneq ($(LINK_STATIC),1)
+FILES_nlm_Ximports += \
+	@$(SQLITE2_IMP) \
+	$(EOLIST)
+endif
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+	apr_dbd_sqlite2_driver \
+	$(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 $(APR_WORK)/build/NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(APRBUILD)/NWGNUtail.inc
+
diff --git a/dbd/NWGNUdbdsqli3 b/dbd/NWGNUdbdsqli3
new file mode 100644
index 00000000000..cf495d21cfc
--- /dev/null
+++ b/dbd/NWGNUdbdsqli3
@@ -0,0 +1,291 @@
+#
+# 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
+#
+
+ifndef EnvironmentDefined
+include $(APR_WORK)/build/NWGNUhead.inc
+endif
+
+#
+# build this level's files
+
+#
+# Make sure all needed macro's are defined
+#
+
+# LINK_STATIC = 1
+
+# for now defined here - should finally go into build/NWGNUenvironment.inc
+SQLITE3_INC = $(SQLITE3SDK)/src
+SQLITE3_IMP = $(SQLITE3SDK)/lsqlite3.imp
+SQLITE3_LIB = $(SQLITE3SDK)/lsqlite3.lib
+SQLITE3_NLM = lsqlite3
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS	+= \
+			$(APR)/include \
+			$(APR)/include/private \
+			$(APR)/include/arch/netware \
+			$(SQLITE3_INC) \
+			$(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS		+= \
+			$(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES	+= \
+			-DAPU_DSO_MODULE_BUILD \
+			-DAPU_HAVE_SQLITE3=1 \
+			$(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS		+= \
+			$(EOLIST)
+
+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	= dbdsqli3
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION	= Apache Portability Runtime Library $(VERSION_STR) DBD SQLite3 Driver Module
+
+#
+# This is used by the '-threadname' directive.  If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME	= dbdsqli3
+
+#
+# If this is specified, it will override VERSION value in
+# $(APR_WORK)/build/NWGNUenvironment.inc
+#
+NLM_VERSION	=
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE	=
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM	=
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM	=
+
+#
+# If this is specified it will be used by the link '-check' directive
+#
+NLM_CHECK_SYM	=
+
+#
+# If these are specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS	=
+
+#
+# If this is specified it will be linked in with the XDCData option in the def
+# file instead of the default of $(NWOS)/apache.xdc.  XDCData can be disabled
+# by setting APACHE_UNIPROC in the environment
+#
+XDCDATA		=
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+	$(OBJDIR)/$(NLM_NAME).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)/apr_dbd_sqlite3.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)
+
+ifeq ($(LINK_STATIC),1)
+FILES_nlm_libs += \
+	$(SQLITE3_LIB) \
+	$(EOLIST)
+endif
+
+#
+# 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)
+
+ifneq ($(LINK_STATIC),1)
+FILES_nlm_modules += \
+	$(SQLITE3_NLM) \
+	$(EOLIST)
+endif
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+	@$(APR)/aprlib.imp \
+	@$(NOVI)/libc.imp \
+	$(EOLIST)
+
+FILES_nlm_imports = \
+	apr_dbd_mutex_lock \
+	apr_dbd_mutex_unlock \
+	$(EOLIST)
+
+ifneq ($(LINK_STATIC),1)
+FILES_nlm_Ximports += \
+	@$(SQLITE3_IMP) \
+	$(EOLIST)
+endif
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+	apr_dbd_sqlite3_driver \
+	$(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 $(APR_WORK)/build/NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(APRBUILD)/NWGNUtail.inc
+
diff --git a/dbd/NWGNUmakefile b/dbd/NWGNUmakefile
new file mode 100644
index 00000000000..90f8aae20d8
--- /dev/null
+++ b/dbd/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 $(APR_WORK)/build/NWGNUhead.inc
+
+#
+# build this level's files
+
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS	+= \
+			$(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS		+= \
+			$(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES	+= \
+			$(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS		+= \
+			$(EOLIST)
+
+#
+# These values will be appended to the correct variables based on the value of
+# RELEASE
+#
+ifeq "$(RELEASE)" "debug"
+XINCDIRS	+= \
+			$(EOLIST)
+
+XCFLAGS		+= \
+			$(EOLIST)
+
+XDEFINES	+= \
+			$(EOLIST)
+
+XLFLAGS		+= \
+			$(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "noopt"
+XINCDIRS	+= \
+			$(EOLIST)
+
+XCFLAGS		+= \
+			$(EOLIST)
+
+XDEFINES	+= \
+			$(EOLIST)
+
+XLFLAGS		+= \
+			$(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "release"
+XINCDIRS	+= \
+			$(EOLIST)
+
+XCFLAGS		+= \
+			$(EOLIST)
+
+XDEFINES	+= \
+			$(EOLIST)
+
+XLFLAGS		+= \
+			$(EOLIST)
+endif
+
+#
+# These are used by the link target if an NLM is being generated
+# This is used by the link 'name' directive to name the nlm.  If left blank
+# TARGET_nlm (see below) will be used.
+#
+NLM_NAME	=
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION	=
+
+#
+# This is used by the '-threadname' directive.  If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME	=
+
+#
+# If this is specified, it will override VERSION value in
+# $(APR_WORK)/build/NWGNUenvironment.inc
+#
+NLM_VERSION	=
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE	=
+
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM	=
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM	=
+
+#
+# If this is specified it will be used by the link '-check' directive
+#
+NLM_CHECK_SYM	=
+
+#
+# If these are specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS	=
+
+#
+# If this is specified it will be linked in with the XDCData option in the def
+# file instead of the default of $(NWOS)/apache.xdc.  XDCData can be disabled
+# by setting APACHE_UNIPROC in the environment
+#
+XDCDATA		=
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+	$(EOLIST)
+
+ifeq "$(APU_HAVE_MYSQL)" "1"
+TARGET_nlm += $(OBJDIR)/dbdmysql.nlm $(OBJDIR)/dbdmysql.nlm $(EOLIST)
+endif
+ifeq "$(APU_HAVE_PGSQL)" "1"
+TARGET_nlm += $(OBJDIR)/dbdpgsql.nlm $(OBJDIR)/dbdpgsql.nlm $(EOLIST)
+endif
+ifeq "$(APU_HAVE_SQLITE2)" "1"
+TARGET_nlm += $(OBJDIR)/dbdsqli2.nlm $(OBJDIR)/dbdsqli2.nlm $(EOLIST)
+endif
+ifeq "$(APU_HAVE_SQLITE3)" "1"
+TARGET_nlm += $(OBJDIR)/dbdsqli3.nlm $(OBJDIR)/dbdsqli3.nlm $(EOLIST)
+endif
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+	$(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+	$(EOLIST)
+
+#
+# These are the LIB files needed to create the NLM target above.
+# These will be added as a library command in the link.opt file.
+#
+FILES_nlm_libs = \
+	$(EOLIST)
+
+#
+# These are the modules that the above NLM target depends on to load.
+# These will be added as a module command in the link.opt file.
+#
+FILES_nlm_modules = \
+	$(EOLIST)
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+	$(EOLIST)
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+	$(EOLIST)
+
+#
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+	$(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the
+# correct place.  (See $(APR_WORK)/build/NWGNUhead.inc for examples)
+#
+install :: nlms $(INSTDIRS) FORCE
+	$(call COPY,$(OBJDIR)/*.nlm,$(INSTALLBASE)/)
+
+#
+# Any specialized rules here
+#
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(APRBUILD)/NWGNUtail.inc
+
+
diff --git a/dbd/apr_dbd.c b/dbd/apr_dbd.c
new file mode 100644
index 00000000000..be7b61be8ce
--- /dev/null
+++ b/dbd/apr_dbd.c
@@ -0,0 +1,572 @@
+/* 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 <ctype.h>
+#include <stdio.h>
+
+#include "apu.h"
+#include "apr_private.h"
+#include "apr_pools.h"
+#include "apr_dso.h"
+#include "apr_strings.h"
+#include "apr_hash.h"
+#include "apr_thread_mutex.h"
+#include "apr_lib.h"
+#include "apr_atomic.h"
+#include "apr_version.h"
+
+#include "apu_internal.h"
+#include "apr_dbd_internal.h"
+#include "apr_dbd.h"
+
+static apr_hash_t *drivers = NULL;
+static apr_uint32_t initialised = 0, in_init = 1;
+
+#define CLEANUP_CAST (apr_status_t (*)(void*))
+
+#if APR_HAS_THREADS
+/* deprecated, but required for existing providers.  Existing and new
+ * providers should be refactored to use a provider-specific mutex so
+ * that different providers do not block one another.
+ * In APR 1.3 this is no longer used for dso module loading, and
+ * apu_dso_mutex_[un]lock is used instead.
+ * In APR 2.0 this should become entirely local to libaprutil-2.so and
+ * no longer be exported.
+ */
+static apr_thread_mutex_t* mutex = NULL;
+APR_DECLARE(apr_status_t) apr_dbd_mutex_lock()
+{
+    return apr_thread_mutex_lock(mutex);
+}
+APR_DECLARE(apr_status_t) apr_dbd_mutex_unlock()
+{
+    return apr_thread_mutex_unlock(mutex);
+}
+#else
+APR_DECLARE(apr_status_t) apr_dbd_mutex_lock() {
+    return APR_SUCCESS;
+}
+APR_DECLARE(apr_status_t) apr_dbd_mutex_unlock() {
+    return APR_SUCCESS;
+}
+#endif
+
+#if !APR_HAVE_MODULAR_DSO
+#define DRIVER_LOAD(name,driver,pool) \
+    {   \
+        extern const apr_dbd_driver_t driver; \
+        apr_hash_set(drivers,name,APR_HASH_KEY_STRING,&driver); \
+        if (driver.init) {     \
+            driver.init(pool); \
+        }  \
+    }
+#endif
+
+static apr_status_t apr_dbd_term(void *ptr)
+{
+    /* set drivers to NULL so init can work again */
+    drivers = NULL;
+
+    /* Everything else we need is handled by cleanups registered
+     * when we created mutexes and loaded DSOs
+     */
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_dbd_init(apr_pool_t *pool)
+{
+    apr_status_t ret = APR_SUCCESS;
+    apr_pool_t *parent;
+
+    if (apr_atomic_inc32(&initialised)) {
+        apr_atomic_set32(&initialised, 1); /* prevent wrap-around */
+
+        while (apr_atomic_read32(&in_init)) /* wait until we get fully inited */
+            ;
+
+        return APR_SUCCESS;
+    }
+
+    /* Top level pool scope, need process-scope lifetime */
+    for (parent = apr_pool_parent_get(pool);
+        parent && parent != pool;
+        parent = apr_pool_parent_get(pool))
+       pool = parent;
+#if APR_HAVE_MODULAR_DSO
+    /* deprecate in 2.0 - permit implicit initialization */
+    apu_dso_init(pool);
+#endif
+
+    drivers = apr_hash_make(pool);
+
+#if APR_HAS_THREADS
+    ret = apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_DEFAULT, pool);
+    /* This already registers a pool cleanup */
+#endif
+
+#if !APR_HAVE_MODULAR_DSO
+
+    /* Load statically-linked drivers: */
+#if APU_HAVE_MYSQL
+    DRIVER_LOAD("mysql", apr_dbd_mysql_driver, pool);
+#endif
+#if APU_HAVE_PGSQL
+    DRIVER_LOAD("pgsql", apr_dbd_pgsql_driver, pool);
+#endif
+#if APU_HAVE_SQLITE3
+    DRIVER_LOAD("sqlite3", apr_dbd_sqlite3_driver, pool);
+#endif
+#if APU_HAVE_SQLITE2
+    DRIVER_LOAD("sqlite2", apr_dbd_sqlite2_driver, pool);
+#endif
+#if APU_HAVE_ORACLE
+    DRIVER_LOAD("oracle", apr_dbd_oracle_driver, pool);
+#endif
+#if APU_HAVE_ODBC
+    DRIVER_LOAD("odbc", apr_dbd_odbc_driver, pool);
+#endif
+#if APU_HAVE_SOME_OTHER_BACKEND
+    DRIVER_LOAD("firebird", apr_dbd_other_driver, pool);
+#endif
+#endif /* APR_HAVE_MODULAR_DSO */
+
+    apr_pool_cleanup_register(pool, NULL, apr_dbd_term,
+                              apr_pool_cleanup_null);
+
+    apr_atomic_dec32(&in_init);
+
+    return ret;
+}
+
+APR_DECLARE(apr_status_t) apr_dbd_get_driver(apr_pool_t *pool, const char *name,
+                                             const apr_dbd_driver_t **driver)
+{
+#if APR_HAVE_MODULAR_DSO
+    char modname[32];
+    char symname[34];
+    apr_dso_handle_sym_t symbol;
+#endif
+    apr_status_t rv;
+
+#if APR_HAVE_MODULAR_DSO
+    rv = apu_dso_mutex_lock();
+    if (rv) {
+        return rv;
+    }
+#endif
+    *driver = apr_hash_get(drivers, name, APR_HASH_KEY_STRING);
+    if (*driver) {
+#if APR_HAVE_MODULAR_DSO
+        apu_dso_mutex_unlock();
+#endif
+        return APR_SUCCESS;
+    }
+
+#if APR_HAVE_MODULAR_DSO
+    /* The driver DSO must have exactly the same lifetime as the
+     * drivers hash table; ignore the passed-in pool */
+    pool = apr_hash_pool_get(drivers);
+
+#if defined(NETWARE)
+    apr_snprintf(modname, sizeof(modname), "dbd%s.nlm", name);
+#elif defined(WIN32) || defined(__CYGWIN__)
+    apr_snprintf(modname, sizeof(modname),
+                 "apr_dbd_%s-" APR_STRINGIFY(APR_MAJOR_VERSION) ".dll", name);
+#else
+    apr_snprintf(modname, sizeof(modname),
+                 "apr_dbd_%s-" APR_STRINGIFY(APR_MAJOR_VERSION) ".so", name);
+#endif
+    apr_snprintf(symname, sizeof(symname), "apr_dbd_%s_driver", name);
+    rv = apu_dso_load(NULL, &symbol, modname, symname, pool);
+    if (rv == APR_SUCCESS || rv == APR_EINIT) { /* previously loaded?!? */
+        *driver = symbol;
+        name = apr_pstrdup(pool, name);
+        apr_hash_set(drivers, name, APR_HASH_KEY_STRING, *driver);
+        rv = APR_SUCCESS;
+        if ((*driver)->init) {
+            (*driver)->init(pool);
+        }
+    }
+    apu_dso_mutex_unlock();
+
+#else /* not builtin and !APR_HAVE_MODULAR_DSO => not implemented */
+    rv = APR_ENOTIMPL;
+#endif
+
+    return rv;
+}
+
+APR_DECLARE(apr_status_t) apr_dbd_open_ex(const apr_dbd_driver_t *driver,
+                                          apr_pool_t *pool, const char *params,
+                                          apr_dbd_t **handle,
+                                          const char **error)
+{
+    apr_status_t rv;
+    *handle = (driver->open)(pool, params, error);
+    if (*handle == NULL) {
+        return APR_EGENERAL;
+    }
+    rv = apr_dbd_check_conn(driver, pool, *handle);
+    if ((rv != APR_SUCCESS) && (rv != APR_ENOTIMPL)) {
+        /* XXX: rv is APR error code, but apr_dbd_error() takes int! */
+        if (error) {
+            *error = apr_dbd_error(driver, *handle, rv);
+        }
+        apr_dbd_close(driver, *handle);
+        return APR_EGENERAL;
+    }
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_dbd_open(const apr_dbd_driver_t *driver,
+                                       apr_pool_t *pool, const char *params,
+                                       apr_dbd_t **handle)
+{
+    return apr_dbd_open_ex(driver,pool,params,handle,NULL);
+}
+
+APR_DECLARE(int) apr_dbd_transaction_start(const apr_dbd_driver_t *driver,
+                                           apr_pool_t *pool, apr_dbd_t *handle,
+                                           apr_dbd_transaction_t **trans)
+{
+    int ret = driver->start_transaction(pool, handle, trans);
+    if (*trans) {
+        apr_pool_cleanup_register(pool, *trans,
+                                  CLEANUP_CAST driver->end_transaction,
+                                  apr_pool_cleanup_null);
+    }
+    return ret;
+}
+
+APR_DECLARE(int) apr_dbd_transaction_end(const apr_dbd_driver_t *driver,
+                                         apr_pool_t *pool,
+                                         apr_dbd_transaction_t *trans)
+{
+    apr_pool_cleanup_kill(pool, trans, CLEANUP_CAST driver->end_transaction);
+    return driver->end_transaction(trans);
+}
+
+APR_DECLARE(int) apr_dbd_transaction_mode_get(const apr_dbd_driver_t *driver,
+                                              apr_dbd_transaction_t *trans)
+{
+    return driver->transaction_mode_get(trans);
+}
+
+APR_DECLARE(int) apr_dbd_transaction_mode_set(const apr_dbd_driver_t *driver,
+                                              apr_dbd_transaction_t *trans,
+                                              int mode)
+{
+    return driver->transaction_mode_set(trans, mode);
+}
+
+APR_DECLARE(apr_status_t) apr_dbd_close(const apr_dbd_driver_t *driver,
+                                        apr_dbd_t *handle)
+{
+    return driver->close(handle);
+}
+
+APR_DECLARE(const char*) apr_dbd_name(const apr_dbd_driver_t *driver)
+{
+    return driver->name;
+}
+
+APR_DECLARE(void*) apr_dbd_native_handle(const apr_dbd_driver_t *driver,
+                                         apr_dbd_t *handle)
+{
+    return driver->native_handle(handle);
+}
+
+APR_DECLARE(int) apr_dbd_check_conn(const apr_dbd_driver_t *driver,
+                                    apr_pool_t *pool,
+                                    apr_dbd_t *handle)
+{
+    return driver->check_conn(pool, handle);
+}
+
+APR_DECLARE(int) apr_dbd_set_dbname(const apr_dbd_driver_t *driver,
+                                    apr_pool_t *pool,
+                                    apr_dbd_t *handle, const char *name)
+{
+    return driver->set_dbname(pool,handle,name);
+}
+
+APR_DECLARE(int) apr_dbd_query(const apr_dbd_driver_t *driver,
+                               apr_dbd_t *handle,
+                               int *nrows, const char *statement)
+{
+    return driver->query(handle,nrows,statement);
+}
+
+APR_DECLARE(int) apr_dbd_select(const apr_dbd_driver_t *driver,
+                                apr_pool_t *pool,
+                                apr_dbd_t *handle, apr_dbd_results_t **res,
+                                const char *statement, int random)
+{
+    return driver->select(pool,handle,res,statement,random);
+}
+
+APR_DECLARE(int) apr_dbd_num_cols(const apr_dbd_driver_t *driver,
+                                  apr_dbd_results_t *res)
+{
+    return driver->num_cols(res);
+}
+
+APR_DECLARE(int) apr_dbd_num_tuples(const apr_dbd_driver_t *driver,
+                                    apr_dbd_results_t *res)
+{
+    return driver->num_tuples(res);
+}
+
+APR_DECLARE(int) apr_dbd_get_row(const apr_dbd_driver_t *driver,
+                                 apr_pool_t *pool,
+                                 apr_dbd_results_t *res, apr_dbd_row_t **row,
+                                 int rownum)
+{
+    return driver->get_row(pool,res,row,rownum);
+}
+
+APR_DECLARE(const char*) apr_dbd_get_entry(const apr_dbd_driver_t *driver,
+                                           apr_dbd_row_t *row, int col)
+{
+    return driver->get_entry(row,col);
+}
+
+APR_DECLARE(const char*) apr_dbd_get_name(const apr_dbd_driver_t *driver,
+                                          apr_dbd_results_t *res, int col)
+{
+    return driver->get_name(res,col);
+}
+
+APR_DECLARE(const char*) apr_dbd_error(const apr_dbd_driver_t *driver,
+                                       apr_dbd_t *handle, int errnum)
+{
+    return driver->error(handle,errnum);
+}
+
+APR_DECLARE(const char*) apr_dbd_escape(const apr_dbd_driver_t *driver,
+                                        apr_pool_t *pool, const char *string,
+                                        apr_dbd_t *handle)
+{
+    return driver->escape(pool,string,handle);
+}
+
+APR_DECLARE(int) apr_dbd_prepare(const apr_dbd_driver_t *driver,
+                                 apr_pool_t *pool,
+                                 apr_dbd_t *handle, const char *query,
+                                 const char *label,
+                                 apr_dbd_prepared_t **statement)
+{
+    size_t qlen;
+    int i, nargs = 0, nvals = 0;
+    char *p, *pq;
+    const char *q;
+    apr_dbd_type_e *t;
+
+    if (!driver->pformat) {
+        return APR_ENOTIMPL;
+    }
+
+    /* find the number of parameters in the query */
+    for (q = query; *q; q++) {
+        if (q[0] == '%') {
+            if (apr_isalpha(q[1])) {
+                nargs++;
+            } else if (q[1] == '%') {
+                q++;
+            }
+        }
+    }
+    nvals = nargs;
+
+    qlen = strlen(query) +
+           nargs * (strlen(driver->pformat) + sizeof(nargs) * 3 + 2) + 1;
+    pq = apr_palloc(pool, qlen);
+    t = apr_pcalloc(pool, sizeof(*t) * nargs);
+
+    for (p = pq, q = query, i = 0; *q; q++) {
+        if (q[0] == '%') {
+            if (apr_isalpha(q[1])) {
+                switch (q[1]) {
+                case 'd': t[i] = APR_DBD_TYPE_INT;   break;
+                case 'u': t[i] = APR_DBD_TYPE_UINT;  break;
+                case 'f': t[i] = APR_DBD_TYPE_FLOAT; break;
+                case 'h':
+                    switch (q[2]) {
+                    case 'h':
+                        switch (q[3]){
+                        case 'd': t[i] = APR_DBD_TYPE_TINY;  q += 2; break;
+                        case 'u': t[i] = APR_DBD_TYPE_UTINY; q += 2; break;
+                        }
+                        break;
+                    case 'd': t[i] = APR_DBD_TYPE_SHORT;  q++; break;
+                    case 'u': t[i] = APR_DBD_TYPE_USHORT; q++; break;
+                    }
+                    break;
+                case 'l':
+                    switch (q[2]) {
+                    case 'l':
+                        switch (q[3]){
+                        case 'd': t[i] = APR_DBD_TYPE_LONGLONG;  q += 2; break;
+                        case 'u': t[i] = APR_DBD_TYPE_ULONGLONG; q += 2; break;
+                        }
+                        break;
+                    case 'd': t[i] = APR_DBD_TYPE_LONG;   q++; break;
+                    case 'u': t[i] = APR_DBD_TYPE_ULONG;  q++; break;
+                    case 'f': t[i] = APR_DBD_TYPE_DOUBLE; q++; break;
+                    }
+                    break;
+                case 'p':
+                    if (q[2] == 'D') {
+                        switch (q[3]) {
+                        case 't': t[i] = APR_DBD_TYPE_TEXT;       q += 2; break;
+                        case 'i': t[i] = APR_DBD_TYPE_TIME;       q += 2; break;
+                        case 'd': t[i] = APR_DBD_TYPE_DATE;       q += 2; break;
+                        case 'a': t[i] = APR_DBD_TYPE_DATETIME;   q += 2; break;
+                        case 's': t[i] = APR_DBD_TYPE_TIMESTAMP;  q += 2; break;
+                        case 'z': t[i] = APR_DBD_TYPE_ZTIMESTAMP; q += 2; break;
+                        case 'b': t[i] = APR_DBD_TYPE_BLOB;       q += 2; break;
+                        case 'c': t[i] = APR_DBD_TYPE_CLOB;       q += 2; break;
+                        case 'n': t[i] = APR_DBD_TYPE_NULL;       q += 2; break;
+                        }
+                    }
+                    break;
+                }
+                q++;
+
+                switch (t[i]) {
+                case APR_DBD_TYPE_NONE: /* by default, we expect strings */
+                    t[i] = APR_DBD_TYPE_STRING;
+                    break;
+                case APR_DBD_TYPE_BLOB:
+                case APR_DBD_TYPE_CLOB: /* three (3) more values passed in */
+                    nvals += 3;
+                    break;
+                default:
+                    break;
+                }
+
+                /* insert database specific parameter reference */
+                p += apr_snprintf(p, qlen - (p - pq), driver->pformat, ++i);
+            } else if (q[1] == '%') { /* reduce %% to % */
+                *p++ = *q++;
+            } else {
+                *p++ = *q;
+            }
+        } else {
+            *p++ = *q;
+        }
+    }
+    *p = '\0';
+
+    return driver->prepare(pool,handle,pq,label,nargs,nvals,t,statement);
+}
+
+APR_DECLARE(int) apr_dbd_pquery(const apr_dbd_driver_t *driver,
+                                apr_pool_t *pool,
+                                apr_dbd_t *handle, int *nrows,
+                                apr_dbd_prepared_t *statement,
+                                int nargs, const char **args)
+{
+    return driver->pquery(pool,handle,nrows,statement,args);
+}
+
+APR_DECLARE(int) apr_dbd_pselect(const apr_dbd_driver_t *driver,
+                                 apr_pool_t *pool,
+                                 apr_dbd_t *handle, apr_dbd_results_t **res,
+                                 apr_dbd_prepared_t *statement, int random,
+                                 int nargs, const char **args)
+{
+    return driver->pselect(pool,handle,res,statement,random,args);
+}
+
+APR_DECLARE_NONSTD(int) apr_dbd_pvquery(const apr_dbd_driver_t *driver,
+                                        apr_pool_t *pool,
+                                        apr_dbd_t *handle, int *nrows,
+                                        apr_dbd_prepared_t *statement, ...)
+{
+    int ret;
+    va_list args;
+    va_start(args, statement);
+    ret = driver->pvquery(pool,handle,nrows,statement,args);
+    va_end(args);
+    return ret;
+}
+
+APR_DECLARE_NONSTD(int) apr_dbd_pvselect(const apr_dbd_driver_t *driver,
+                                         apr_pool_t *pool, apr_dbd_t *handle,
+                                         apr_dbd_results_t **res,
+                                         apr_dbd_prepared_t *statement,
+                                         int random, ...)
+{
+    int ret;
+    va_list args;
+    va_start(args, random);
+    ret = driver->pvselect(pool,handle,res,statement,random,args);
+    va_end(args);
+    return ret;
+}
+
+APR_DECLARE(int) apr_dbd_pbquery(const apr_dbd_driver_t *driver,
+                                 apr_pool_t *pool,
+                                 apr_dbd_t *handle, int *nrows,
+                                 apr_dbd_prepared_t *statement,
+                                 const void **args)
+{
+    return driver->pbquery(pool,handle,nrows,statement,args);
+}
+
+APR_DECLARE(int) apr_dbd_pbselect(const apr_dbd_driver_t *driver,
+                                  apr_pool_t *pool,
+                                  apr_dbd_t *handle, apr_dbd_results_t **res,
+                                  apr_dbd_prepared_t *statement, int random,
+                                  const void **args)
+{
+    return driver->pbselect(pool,handle,res,statement,random,args);
+}
+
+APR_DECLARE_NONSTD(int) apr_dbd_pvbquery(const apr_dbd_driver_t *driver,
+                                         apr_pool_t *pool,
+                                         apr_dbd_t *handle, int *nrows,
+                                         apr_dbd_prepared_t *statement, ...)
+{
+    int ret;
+    va_list args;
+    va_start(args, statement);
+    ret = driver->pvbquery(pool,handle,nrows,statement,args);
+    va_end(args);
+    return ret;
+}
+
+APR_DECLARE_NONSTD(int) apr_dbd_pvbselect(const apr_dbd_driver_t *driver,
+                                          apr_pool_t *pool, apr_dbd_t *handle,
+                                          apr_dbd_results_t **res,
+                                          apr_dbd_prepared_t *statement,
+                                          int random, ...)
+{
+    int ret;
+    va_list args;
+    va_start(args, random);
+    ret = driver->pvbselect(pool,handle,res,statement,random,args);
+    va_end(args);
+    return ret;
+}
+
+APR_DECLARE(apr_status_t) apr_dbd_datum_get(const apr_dbd_driver_t *driver,
+                                            apr_dbd_row_t *row, int col,
+                                            apr_dbd_type_e type, void *data)
+{
+    return driver->datum_get(row,col,type,data);
+}
diff --git a/dbd/apr_dbd_mysql.c b/dbd/apr_dbd_mysql.c
new file mode 100644
index 00000000000..9d715855b21
--- /dev/null
+++ b/dbd/apr_dbd_mysql.c
@@ -0,0 +1,1335 @@
+/* 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 "apu.h"
+
+#if APU_HAVE_MYSQL
+
+#include "apr_private.h"
+
+#include <ctype.h>
+#include <stdlib.h>
+
+#if defined(HAVE_MYSQL_MYSQL_H)
+#if defined(HAVE_MYSQL_MY_GLOBAL_H)
+#include <mysql/my_global.h>
+#if defined(HAVE_MYSQL_MY_SYS_H)
+#include <mysql/my_sys.h>
+#endif
+#endif
+#include <mysql/mysql.h>
+#include <mysql/errmsg.h>
+#else /* !defined(HAVE_MYSQL_MYSQL_H) */
+#if defined(HAVE_MY_GLOBAL_H) 
+#include <my_global.h>
+#if defined(HAVE_MY_SYS_H)
+#include <my_sys.h>
+#endif
+#endif
+#include <mysql.h>
+#include <errmsg.h>
+#endif
+
+#include "apr_strings.h"
+#include "apr_lib.h"
+#include "apr_buckets.h"
+
+#include "apr_dbd_internal.h"
+
+/* default maximum field size 1 MB */
+#define FIELDSIZE 1048575
+
+struct apr_dbd_prepared_t {
+    MYSQL_STMT* stmt;
+    int nargs;
+    int nvals;
+    apr_dbd_type_e *types;
+};
+
+struct apr_dbd_transaction_t {
+    int mode;
+    int errnum;
+    apr_dbd_t *handle;
+};
+
+struct apr_dbd_t {
+    MYSQL* conn ;
+    apr_dbd_transaction_t* trans ;
+    unsigned long fldsz;
+};
+
+struct apr_dbd_results_t {
+    int random;
+    MYSQL_RES *res;
+    MYSQL_STMT *statement;
+    MYSQL_BIND *bind;
+    apr_pool_t *pool;
+};
+struct apr_dbd_row_t {
+    MYSQL_ROW row;
+    apr_dbd_results_t *res;
+    unsigned long *len;
+};
+
+/* MySQL specific bucket for BLOB types */
+typedef struct apr_bucket_lob apr_bucket_lob;
+/**
+ * A bucket referring to a MySQL BLOB
+ */
+struct apr_bucket_lob {
+    /** Number of buckets using this memory */
+    apr_bucket_refcount  refcount;
+    /** The row this bucket refers to */
+    const apr_dbd_row_t *row;
+    /** The column this bucket refers to */
+    int col;
+    /** The pool into which any needed structures should
+     *  be created while reading from this bucket */
+    apr_pool_t *readpool;
+};
+
+static void lob_bucket_destroy(void *data);
+static apr_status_t lob_bucket_read(apr_bucket *e, const char **str,
+                                    apr_size_t *len, apr_read_type_e block);
+static apr_bucket *apr_bucket_lob_make(apr_bucket *b,
+                                       const apr_dbd_row_t *row, int col,
+                                       apr_off_t offset, apr_size_t len,
+                                       apr_pool_t *p);
+static apr_bucket *apr_bucket_lob_create(const apr_dbd_row_t *row, int col,
+                                         apr_off_t offset,
+                                         apr_size_t len, apr_pool_t *p,
+                                         apr_bucket_alloc_t *list);
+static int dbd_mysql_num_cols(apr_dbd_results_t *res);
+
+static const apr_bucket_type_t apr_bucket_type_lob = {
+    "LOB", 5, APR_BUCKET_DATA,
+    lob_bucket_destroy,
+    lob_bucket_read,
+    apr_bucket_setaside_notimpl,
+    apr_bucket_shared_split,
+    apr_bucket_shared_copy
+};
+
+static void lob_bucket_destroy(void *data)
+{
+    apr_bucket_lob *f = data;
+
+    if (apr_bucket_shared_destroy(f)) {
+        /* no need to destroy database objects here; it will get
+         * done automatically when the pool gets cleaned up */
+        apr_bucket_free(f);
+    }
+}
+
+static apr_status_t lob_bucket_read(apr_bucket *e, const char **str,
+                                    apr_size_t *len, apr_read_type_e block)
+{
+    apr_bucket_lob *a = e->data;
+    const apr_dbd_row_t *row = a->row;
+    apr_dbd_results_t *res = row->res;
+    int col = a->col;
+    apr_bucket *b = NULL;
+    int rv;
+    apr_size_t blength = e->length;  /* bytes remaining in file past offset */
+    apr_off_t boffset = e->start;
+    MYSQL_BIND *bind = &res->bind[col];
+
+    *str = NULL;  /* in case we die prematurely */
+
+    /* fetch from offset if not at the beginning */
+    if (boffset > 0) {
+        rv = mysql_stmt_fetch_column(res->statement, bind, col,
+                                     (unsigned long) boffset);
+        if (rv != 0) {
+            return APR_EGENERAL;
+        }
+    }
+    blength -= blength > bind->buffer_length ? bind->buffer_length : blength;
+    *len = e->length - blength;
+    *str = bind->buffer;
+
+    /* allocate new buffer, since we used this one for the bucket */
+    bind->buffer = apr_palloc(res->pool, bind->buffer_length);
+
+    /*
+     * Change the current bucket to refer to what we read,
+     * even if we read nothing because we hit EOF.
+     */
+    apr_bucket_pool_make(e, *str, *len, res->pool);
+
+    /* If we have more to read from the field, then create another bucket */
+    if (blength > 0) {
+        /* for efficiency, we can just build a new apr_bucket struct
+         * to wrap around the existing LOB bucket */
+        b = apr_bucket_alloc(sizeof(*b), e->list);
+        b->start  = boffset + *len;
+        b->length = blength;
+        b->data   = a;
+        b->type   = &apr_bucket_type_lob;
+        b->free   = apr_bucket_free;
+        b->list   = e->list;
+        APR_BUCKET_INSERT_AFTER(e, b);
+    }
+    else {
+        lob_bucket_destroy(a);
+    }
+
+    return APR_SUCCESS;
+}
+
+static apr_bucket *apr_bucket_lob_make(apr_bucket *b,
+                                       const apr_dbd_row_t *row, int col,
+                                       apr_off_t offset, apr_size_t len,
+                                       apr_pool_t *p)
+{
+    apr_bucket_lob *f;
+
+    f = apr_bucket_alloc(sizeof(*f), b->list);
+    f->row = row;
+    f->col = col;
+    f->readpool = p;
+
+    b = apr_bucket_shared_make(b, f, offset, len);
+    b->type = &apr_bucket_type_lob;
+
+    return b;
+}
+
+static apr_bucket *apr_bucket_lob_create(const apr_dbd_row_t *row, int col,
+                                         apr_off_t offset,
+                                         apr_size_t len, apr_pool_t *p,
+                                         apr_bucket_alloc_t *list)
+{
+    apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
+
+    APR_BUCKET_INIT(b);
+    b->free = apr_bucket_free;
+    b->list = list;
+    return apr_bucket_lob_make(b, row, col, offset, len, p);
+}
+
+static apr_status_t free_result(void *data)
+{
+    mysql_free_result(data);
+    return APR_SUCCESS;
+}
+
+static int dbd_mysql_select(apr_pool_t *pool, apr_dbd_t *sql,
+                            apr_dbd_results_t **results,
+                            const char *query, int seek)
+{
+    int sz;
+    int ret;
+    if (sql->trans && sql->trans->errnum) {
+        return sql->trans->errnum;
+    }
+    ret = mysql_query(sql->conn, query);
+    if (!ret) {
+        if (sz = mysql_field_count(sql->conn), sz > 0) {
+            if (!*results) {
+                *results = apr_palloc(pool, sizeof(apr_dbd_results_t));
+            }
+            (*results)->random = seek;
+            (*results)->statement = NULL;
+            (*results)->pool = pool;
+            if (seek) {
+                (*results)->res = mysql_store_result(sql->conn);
+            }
+            else {
+                (*results)->res = mysql_use_result(sql->conn);
+            }
+            apr_pool_cleanup_register(pool, (*results)->res,
+                                      free_result,apr_pool_cleanup_null);
+        }
+    } else {
+        ret = mysql_errno(sql->conn);
+    }
+
+    if (TXN_NOTICE_ERRORS(sql->trans)) {
+        sql->trans->errnum = ret;
+    }
+    return ret;
+}
+
+static const char *dbd_mysql_get_name(const apr_dbd_results_t *res, int n)
+{
+    if ((n < 0) || (n >= (int) mysql_num_fields(res->res))) {
+        return NULL;
+    }
+
+    return mysql_fetch_fields(res->res)[n].name;
+}
+
+static int dbd_mysql_get_row(apr_pool_t *pool, apr_dbd_results_t *res,
+                             apr_dbd_row_t **row, int rownum)
+{
+    MYSQL_ROW r = NULL;
+    int ret = 0;
+
+    if (res->statement) {
+        if (res->random) {
+            if (rownum > 0) {
+                mysql_stmt_data_seek(res->statement, (my_ulonglong) --rownum);
+            }
+            else {
+                return -1; /* invalid row */
+            }
+        }
+        ret = mysql_stmt_fetch(res->statement);
+        switch (ret) {
+        case 1:
+            ret = mysql_stmt_errno(res->statement);
+            break;
+        case MYSQL_NO_DATA:
+            ret = -1;
+            break;
+        default:
+            ret = 0; /* bad luck - get_entry will deal with this */
+            break;
+        }
+    }
+    else {
+        if (res->random) {
+            if (rownum > 0) {
+                mysql_data_seek(res->res, (my_ulonglong) --rownum);
+            }
+            else {
+                return -1; /* invalid row */
+            }
+        }
+        r = mysql_fetch_row(res->res);
+        if (r == NULL) {
+            ret = -1;
+        }
+    }
+    if (ret == 0) {
+        if (!*row) {
+            *row = apr_palloc(pool, sizeof(apr_dbd_row_t));
+        }
+        (*row)->row = r;
+        (*row)->res = res;
+        (*row)->len = mysql_fetch_lengths(res->res);
+    }
+    else {
+        apr_pool_cleanup_run(res->pool, res->res, free_result);
+    }
+    return ret;
+}
+#if 0
+/* An improved API that was proposed but not followed up */
+static int dbd_mysql_get_entry(const apr_dbd_row_t *row, int n,
+                               apr_dbd_datum_t *val)
+{
+    MYSQL_BIND *bind;
+    if (dbd_mysql_num_cols(row->res) <= n) {
+    	return NULL;
+    }
+    if (row->res->statement) {
+        bind = &row->res->bind[n];
+        if (mysql_stmt_fetch_column(row->res->statement, bind, n, 0) != 0) {
+            val->type = APR_DBD_VALUE_NULL;
+            return -1;
+        }
+        if (*bind->is_null) {
+            val->type = APR_DBD_VALUE_NULL;
+            return -1;
+        }
+        else {
+            val->type = APR_DBD_VALUE_STRING;
+            val->value.stringval = bind->buffer;
+        }
+    }
+    else {
+        val->type = APR_DBD_VALUE_STRING;
+        val->value.stringval = row->row[n];
+    }
+    return 0;
+}
+#else
+
+static const char *dbd_mysql_get_entry(const apr_dbd_row_t *row, int n)
+{
+    MYSQL_BIND *bind;
+    const char *result = NULL;
+    if (dbd_mysql_num_cols(row->res) <= n) {
+    	return NULL;
+    }
+    if (row->res->statement) {
+        bind = &row->res->bind[n];
+        if (mysql_stmt_fetch_column(row->res->statement, bind, n, 0) != 0) {
+            return NULL;
+        }
+        if (*bind->is_null) {
+            return NULL;
+        }
+        else {
+            result = bind->buffer;
+        }
+    }
+    else {
+        result = row->row[n];
+    }
+    if (result != NULL) {
+        /* need to copy this - PR 46421
+         * Don't know why, when it apparently came from an array
+         * in the first place.
+         */
+        result = apr_pstrdup(row->res->pool, result);
+    }
+    return result;
+}
+#endif
+
+static apr_status_t dbd_mysql_datum_get(const apr_dbd_row_t *row, int n,
+                                        apr_dbd_type_e type, void *data)
+{
+    if (row->res->statement) {
+        MYSQL_BIND *bind = &row->res->bind[n];
+        unsigned long len = *bind->length;
+
+        if (mysql_stmt_fetch_column(row->res->statement, bind, n, 0) != 0) {
+            return APR_EGENERAL;
+        }
+
+        if (*bind->is_null) {
+            return APR_ENOENT;
+        }
+
+        switch (type) {
+        case APR_DBD_TYPE_TINY:
+            *(char*)data = atoi(bind->buffer);
+            break;
+        case APR_DBD_TYPE_UTINY:
+            *(unsigned char*)data = atoi(bind->buffer);
+            break;
+        case APR_DBD_TYPE_SHORT:
+            *(short*)data = atoi(bind->buffer);
+            break;
+        case APR_DBD_TYPE_USHORT:
+            *(unsigned short*)data = atoi(bind->buffer);
+            break;
+        case APR_DBD_TYPE_INT:
+            *(int*)data = atoi(bind->buffer);
+            break;
+        case APR_DBD_TYPE_UINT:
+            *(unsigned int*)data = atoi(bind->buffer);
+            break;
+        case APR_DBD_TYPE_LONG:
+            *(long*)data = atol(bind->buffer);
+            break;
+        case APR_DBD_TYPE_ULONG:
+            *(unsigned long*)data = atol(bind->buffer);
+            break;
+        case APR_DBD_TYPE_LONGLONG:
+            *(apr_int64_t*)data = apr_atoi64(bind->buffer);
+            break;
+        case APR_DBD_TYPE_ULONGLONG:
+            *(apr_uint64_t*)data = apr_atoi64(bind->buffer);
+            break;
+        case APR_DBD_TYPE_FLOAT:
+            *(float*)data = (float) atof(bind->buffer);
+            break;
+        case APR_DBD_TYPE_DOUBLE:
+            *(double*)data = atof(bind->buffer);
+            break;
+        case APR_DBD_TYPE_STRING:
+        case APR_DBD_TYPE_TEXT:
+        case APR_DBD_TYPE_TIME:
+        case APR_DBD_TYPE_DATE:
+        case APR_DBD_TYPE_DATETIME:
+        case APR_DBD_TYPE_TIMESTAMP:
+        case APR_DBD_TYPE_ZTIMESTAMP:
+            *((char*)bind->buffer+bind->buffer_length-1) = '\0';
+            *(char**)data = bind->buffer;
+            break;
+        case APR_DBD_TYPE_BLOB:
+        case APR_DBD_TYPE_CLOB:
+            {
+            apr_bucket *e;
+            apr_bucket_brigade *b = (apr_bucket_brigade*)data;
+
+            e = apr_bucket_lob_create(row, n, 0, len,
+                                      row->res->pool, b->bucket_alloc);
+            APR_BRIGADE_INSERT_TAIL(b, e);
+            }
+            break;
+        case APR_DBD_TYPE_NULL:
+            *(void**)data = NULL;
+            break;
+        default:
+            return APR_EGENERAL;
+        }
+    }
+    else {
+        if (row->row[n] == NULL) {
+            return APR_ENOENT;
+        }
+
+        switch (type) {
+        case APR_DBD_TYPE_TINY:
+            *(char*)data = atoi(row->row[n]);
+            break;
+        case APR_DBD_TYPE_UTINY:
+            *(unsigned char*)data = atoi(row->row[n]);
+            break;
+        case APR_DBD_TYPE_SHORT:
+            *(short*)data = atoi(row->row[n]);
+            break;
+        case APR_DBD_TYPE_USHORT:
+            *(unsigned short*)data = atoi(row->row[n]);
+            break;
+        case APR_DBD_TYPE_INT:
+            *(int*)data = atoi(row->row[n]);
+            break;
+        case APR_DBD_TYPE_UINT:
+            *(unsigned int*)data = atoi(row->row[n]);
+            break;
+        case APR_DBD_TYPE_LONG:
+            *(long*)data = atol(row->row[n]);
+            break;
+        case APR_DBD_TYPE_ULONG:
+            *(unsigned long*)data = atol(row->row[n]);
+            break;
+        case APR_DBD_TYPE_LONGLONG:
+            *(apr_int64_t*)data = apr_atoi64(row->row[n]);
+            break;
+        case APR_DBD_TYPE_ULONGLONG:
+            *(apr_uint64_t*)data = apr_atoi64(row->row[n]);
+            break;
+        case APR_DBD_TYPE_FLOAT:
+            *(float*)data = (float) atof(row->row[n]);
+            break;
+        case APR_DBD_TYPE_DOUBLE:
+            *(double*)data = atof(row->row[n]);
+            break;
+        case APR_DBD_TYPE_STRING:
+        case APR_DBD_TYPE_TEXT:
+        case APR_DBD_TYPE_TIME:
+        case APR_DBD_TYPE_DATE:
+        case APR_DBD_TYPE_DATETIME:
+        case APR_DBD_TYPE_TIMESTAMP:
+        case APR_DBD_TYPE_ZTIMESTAMP:
+            *(char**)data = row->row[n];
+            break;
+        case APR_DBD_TYPE_BLOB:
+        case APR_DBD_TYPE_CLOB:
+            {
+            apr_bucket *e;
+            apr_bucket_brigade *b = (apr_bucket_brigade*)data;
+
+            e = apr_bucket_pool_create(row->row[n], row->len[n],
+                                       row->res->pool, b->bucket_alloc);
+            APR_BRIGADE_INSERT_TAIL(b, e);
+            }
+            break;
+        case APR_DBD_TYPE_NULL:
+            *(void**)data = NULL;
+            break;
+        default:
+            return APR_EGENERAL;
+        }
+    }
+    return 0;
+}
+
+static const char *dbd_mysql_error(apr_dbd_t *sql, int n)
+{
+    return mysql_error(sql->conn);
+}
+
+static int dbd_mysql_query(apr_dbd_t *sql, int *nrows, const char *query)
+{
+    int ret;
+    if (sql->trans && sql->trans->errnum) {
+        return sql->trans->errnum;
+    }
+    ret = mysql_query(sql->conn, query);
+    if (ret != 0) {
+        ret = mysql_errno(sql->conn);
+    }
+    *nrows = (int) mysql_affected_rows(sql->conn);
+    if (TXN_NOTICE_ERRORS(sql->trans)) {
+        sql->trans->errnum = ret;
+    }
+    return ret;
+}
+
+static const char *dbd_mysql_escape(apr_pool_t *pool, const char *arg,
+                                    apr_dbd_t *sql)
+{
+    unsigned long len = strlen(arg);
+    char *ret = apr_palloc(pool, 2*len + 1);
+    mysql_real_escape_string(sql->conn, ret, arg, len);
+    return ret;
+}
+
+static apr_status_t stmt_close(void *data)
+{
+    mysql_stmt_close(data);
+    return APR_SUCCESS;
+}
+
+static int dbd_mysql_prepare(apr_pool_t *pool, apr_dbd_t *sql,
+                             const char *query, const char *label,
+                             int nargs, int nvals, apr_dbd_type_e *types,
+                             apr_dbd_prepared_t **statement)
+{
+    /* Translate from apr_dbd to native query format */
+    int ret;
+
+    if (!*statement) {
+        *statement = apr_palloc(pool, sizeof(apr_dbd_prepared_t));
+    }
+    (*statement)->stmt = mysql_stmt_init(sql->conn);
+
+    if ((*statement)->stmt) {
+        apr_pool_cleanup_register(pool, (*statement)->stmt,
+                                  stmt_close, apr_pool_cleanup_null);
+        ret = mysql_stmt_prepare((*statement)->stmt, query, strlen(query));
+
+        if (ret != 0) {
+            ret = mysql_stmt_errno((*statement)->stmt);
+        }
+
+        (*statement)->nargs = nargs;
+        (*statement)->nvals = nvals;
+        (*statement)->types = types;
+
+        return ret;
+    }
+
+    return CR_OUT_OF_MEMORY;
+}
+
+static void dbd_mysql_bind(apr_dbd_prepared_t *statement,
+                           const char **values, MYSQL_BIND *bind)
+{
+    int i, j;
+
+    for (i = 0, j = 0; i < statement->nargs; i++, j++) {
+        bind[i].length = &bind[i].buffer_length;
+        bind[i].is_unsigned = 0;
+        bind[i].is_null = NULL;
+
+        if (values[j] == NULL) {
+            bind[i].buffer_type = MYSQL_TYPE_NULL;
+        }
+        else {
+            switch (statement->types[i]) {
+            case APR_DBD_TYPE_BLOB:
+            case APR_DBD_TYPE_CLOB:
+                bind[i].buffer_type = MYSQL_TYPE_LONG_BLOB;
+                bind[i].buffer = (void*)values[j];
+                bind[i].buffer_length = atol(values[++j]);
+
+                /* skip table and column */
+                j += 2;
+                break;
+            default:
+                bind[i].buffer_type = MYSQL_TYPE_VAR_STRING;
+                bind[i].buffer = (void*)values[j];
+                bind[i].buffer_length = strlen(values[j]);
+                break;
+            }
+        }
+    }
+
+    return;
+}
+
+static int dbd_mysql_pquery_internal(apr_pool_t *pool, apr_dbd_t *sql,
+                                     int *nrows, apr_dbd_prepared_t *statement,
+                                     MYSQL_BIND *bind)
+{
+    int ret;
+
+    ret = mysql_stmt_bind_param(statement->stmt, bind);
+    if (ret != 0) {
+        *nrows = 0;
+        ret = mysql_stmt_errno(statement->stmt);
+    }
+    else {
+        ret = mysql_stmt_execute(statement->stmt);
+        if (ret != 0) {
+            ret = mysql_stmt_errno(statement->stmt);
+        }
+        *nrows = (int) mysql_stmt_affected_rows(statement->stmt);
+    }
+
+    return ret;
+}
+
+static int dbd_mysql_pquery(apr_pool_t *pool, apr_dbd_t *sql,
+                            int *nrows, apr_dbd_prepared_t *statement,
+                            const char **values)
+{
+    MYSQL_BIND *bind;
+    int ret;
+
+    if (sql->trans && sql->trans->errnum) {
+        return sql->trans->errnum;
+    }
+
+    bind = apr_palloc(pool, statement->nargs * sizeof(MYSQL_BIND));
+
+    dbd_mysql_bind(statement, values, bind);
+
+    ret = dbd_mysql_pquery_internal(pool, sql, nrows, statement, bind);
+
+    if (TXN_NOTICE_ERRORS(sql->trans)) {
+        sql->trans->errnum = ret;
+    }
+    return ret;
+}
+
+static int dbd_mysql_pvquery(apr_pool_t *pool, apr_dbd_t *sql, int *nrows,
+                             apr_dbd_prepared_t *statement, va_list args)
+{
+    const char **values;
+    int i;
+
+    if (sql->trans && sql->trans->errnum) {
+        return sql->trans->errnum;
+    }
+
+    values = apr_palloc(pool, sizeof(*values) * statement->nvals);
+
+    for (i = 0; i < statement->nvals; i++) {
+        values[i] = va_arg(args, const char*);
+    }
+
+    return dbd_mysql_pquery(pool, sql, nrows, statement, values);
+}
+
+static int dbd_mysql_pselect_internal(apr_pool_t *pool, apr_dbd_t *sql,
+                                      apr_dbd_results_t **res,
+                                      apr_dbd_prepared_t *statement,
+                                      int random, MYSQL_BIND *bind)
+{
+    int nfields, i;
+    my_bool *is_nullr;
+#if MYSQL_VERSION_ID >= 50000
+    my_bool *error;
+#endif
+    int ret;
+    unsigned long *length, maxlen;
+
+    ret = mysql_stmt_bind_param(statement->stmt, bind);
+    if (ret == 0) {
+        ret = mysql_stmt_execute(statement->stmt);
+        if (!ret) {
+            if (!*res) {
+                *res = apr_pcalloc(pool, sizeof(apr_dbd_results_t));
+            }
+            (*res)->random = random;
+            (*res)->statement = statement->stmt;
+            (*res)->res = mysql_stmt_result_metadata(statement->stmt);
+            (*res)->pool = pool;
+            apr_pool_cleanup_register(pool, (*res)->res,
+                                      free_result, apr_pool_cleanup_null);
+            nfields = mysql_num_fields((*res)->res);
+            if (!(*res)->bind) {
+                (*res)->bind = apr_palloc(pool, nfields*sizeof(MYSQL_BIND));
+                length = apr_pcalloc(pool, nfields*sizeof(unsigned long));
+#if MYSQL_VERSION_ID >= 50000
+                error = apr_palloc(pool, nfields*sizeof(my_bool));
+#endif
+                is_nullr = apr_pcalloc(pool, nfields*sizeof(my_bool));
+                for ( i = 0; i < nfields; ++i ) {
+                    maxlen = ((*res)->res->fields[i].length < sql->fldsz ?
+                              (*res)->res->fields[i].length : sql->fldsz) + 1;
+                    if ((*res)->res->fields[i].type == MYSQL_TYPE_BLOB) {
+                        (*res)->bind[i].buffer_type = MYSQL_TYPE_LONG_BLOB;
+                    }
+                    else {
+                        (*res)->bind[i].buffer_type = MYSQL_TYPE_VAR_STRING;
+                    }
+                    (*res)->bind[i].buffer_length = maxlen;
+                    (*res)->bind[i].length = &length[i];
+                    (*res)->bind[i].buffer = apr_palloc(pool, maxlen);
+                    (*res)->bind[i].is_null = is_nullr+i;
+#if MYSQL_VERSION_ID >= 50000
+                    (*res)->bind[i].error = error+i;
+#endif
+                }
+            }
+            ret = mysql_stmt_bind_result(statement->stmt, (*res)->bind);
+            if (!ret) {
+                ret = mysql_stmt_store_result(statement->stmt);
+            }
+        }
+    }
+    if (ret != 0) {
+        ret = mysql_stmt_errno(statement->stmt);
+    }
+
+    return ret;
+}
+
+static int dbd_mysql_pselect(apr_pool_t *pool, apr_dbd_t *sql,
+                             apr_dbd_results_t **res,
+                             apr_dbd_prepared_t *statement, int random,
+                             const char **args)
+{
+    int ret;
+    MYSQL_BIND *bind;
+
+    if (sql->trans && sql->trans->errnum) {
+        return sql->trans->errnum;
+    }
+
+    bind = apr_palloc(pool, statement->nargs * sizeof(MYSQL_BIND));
+
+    dbd_mysql_bind(statement, args, bind);
+
+    ret = dbd_mysql_pselect_internal(pool, sql,  res, statement, random, bind);
+
+    if (TXN_NOTICE_ERRORS(sql->trans)) {
+        sql->trans->errnum = ret;
+    }
+    return ret;
+}
+
+static int dbd_mysql_pvselect(apr_pool_t *pool, apr_dbd_t *sql,
+                              apr_dbd_results_t **res,
+                              apr_dbd_prepared_t *statement, int random,
+                              va_list args)
+{
+    const char **values;
+    int i;
+
+    if (sql->trans && sql->trans->errnum) {
+        return sql->trans->errnum;
+    }
+
+    values = apr_palloc(pool, sizeof(*values) * statement->nvals);
+
+    for (i = 0; i < statement->nvals; i++) {
+        values[i] = va_arg(args, const char*);
+    }
+
+    return dbd_mysql_pselect(pool, sql, res, statement, random, values);
+}
+
+static void dbd_mysql_bbind(apr_pool_t *pool, apr_dbd_prepared_t *statement,
+                            const void **values, MYSQL_BIND *bind)
+{
+    void *arg;
+    int i, j;
+    apr_dbd_type_e type;
+
+    for (i = 0, j = 0; i < statement->nargs; i++, j++) {
+        arg = (void *)values[j];
+
+        bind[i].length = &bind[i].buffer_length;
+        bind[i].is_null = NULL;
+
+        type = (arg == NULL ? APR_DBD_TYPE_NULL : statement->types[i]);
+        switch (type) {
+        case APR_DBD_TYPE_TINY:
+            bind[i].buffer = arg;
+            bind[i].buffer_type = MYSQL_TYPE_TINY;
+            bind[i].is_unsigned = 0;
+            break;
+        case APR_DBD_TYPE_UTINY:
+            bind[i].buffer = arg;
+            bind[i].buffer_type = MYSQL_TYPE_TINY;
+            bind[i].is_unsigned = 1;
+            break;
+        case APR_DBD_TYPE_SHORT:
+            bind[i].buffer = arg;
+            bind[i].buffer_type = MYSQL_TYPE_SHORT;
+            bind[i].is_unsigned = 0;
+            break;
+        case APR_DBD_TYPE_USHORT:
+            bind[i].buffer = arg;
+            bind[i].buffer_type = MYSQL_TYPE_SHORT;
+            bind[i].is_unsigned = 1;
+            break;
+        case APR_DBD_TYPE_INT:
+            bind[i].buffer = arg;
+            bind[i].buffer_type = MYSQL_TYPE_LONG;
+            bind[i].is_unsigned = 0;
+            break;
+        case APR_DBD_TYPE_UINT:
+            bind[i].buffer = arg;
+            bind[i].buffer_type = MYSQL_TYPE_LONG;
+            bind[i].is_unsigned = 1;
+            break;
+        case APR_DBD_TYPE_LONG:
+            if (sizeof(int) == sizeof(long)) {
+                bind[i].buffer = arg;
+            }
+            else {
+                bind[i].buffer = apr_palloc(pool, sizeof(int));
+                *(int*)bind[i].buffer = *(long*)arg;
+            }
+            bind[i].buffer_type = MYSQL_TYPE_LONG;
+            bind[i].is_unsigned = 0;
+            break;
+        case APR_DBD_TYPE_ULONG:
+            if (sizeof(unsigned int) == sizeof(unsigned long)) {
+                bind[i].buffer = arg;
+            }
+            else {
+                bind[i].buffer = apr_palloc(pool, sizeof(unsigned int));
+                *(unsigned int*)bind[i].buffer = *(unsigned long*)arg;
+            }
+            bind[i].buffer_type = MYSQL_TYPE_LONG;
+            bind[i].is_unsigned = 1;
+            break;
+        case APR_DBD_TYPE_LONGLONG:
+            if (sizeof(my_ulonglong) == sizeof(apr_int64_t)) {
+                bind[i].buffer = arg;
+                bind[i].buffer_type = MYSQL_TYPE_LONGLONG;
+            }
+            else { /* have to downsize, long long is not portable */
+                bind[i].buffer = apr_palloc(pool, sizeof(long));
+                *(long*)bind[i].buffer = (long) *(apr_int64_t*)arg;
+                bind[i].buffer_type = MYSQL_TYPE_LONG;
+            }
+            bind[i].is_unsigned = 0;
+            break;
+        case APR_DBD_TYPE_ULONGLONG:
+            if (sizeof(my_ulonglong) == sizeof(apr_uint64_t)) {
+                bind[i].buffer = arg;
+                bind[i].buffer_type = MYSQL_TYPE_LONGLONG;
+            }
+            else { /* have to downsize, long long is not portable */
+                bind[i].buffer = apr_palloc(pool, sizeof(long));
+                *(unsigned long*)bind[i].buffer =
+                    (unsigned long) *(apr_uint64_t*)arg;
+                bind[i].buffer_type = MYSQL_TYPE_LONG;
+            }
+            bind[i].is_unsigned = 1;
+            break;
+        case APR_DBD_TYPE_FLOAT:
+            bind[i].buffer = arg;
+            bind[i].buffer_type = MYSQL_TYPE_FLOAT;
+            bind[i].is_unsigned = 0;
+            break;
+        case APR_DBD_TYPE_DOUBLE:
+            bind[i].buffer = arg;
+            bind[i].buffer_type = MYSQL_TYPE_DOUBLE;
+            bind[i].is_unsigned = 0;
+            break;
+        case APR_DBD_TYPE_STRING:
+        case APR_DBD_TYPE_TEXT:
+        case APR_DBD_TYPE_TIME:
+        case APR_DBD_TYPE_DATE:
+        case APR_DBD_TYPE_DATETIME:
+        case APR_DBD_TYPE_TIMESTAMP:
+        case APR_DBD_TYPE_ZTIMESTAMP:
+            bind[i].buffer = arg;
+            bind[i].buffer_type = MYSQL_TYPE_VAR_STRING;
+            bind[i].is_unsigned = 0;
+            bind[i].buffer_length = strlen((const char *)arg);
+            break;
+        case APR_DBD_TYPE_BLOB:
+        case APR_DBD_TYPE_CLOB:
+            bind[i].buffer = (void *)arg;
+            bind[i].buffer_type = MYSQL_TYPE_LONG_BLOB;
+            bind[i].is_unsigned = 0;
+            bind[i].buffer_length = *(apr_size_t*)values[++j];
+
+            /* skip table and column */
+            j += 2;
+            break;
+        case APR_DBD_TYPE_NULL:
+        default:
+            bind[i].buffer_type = MYSQL_TYPE_NULL;
+            break;
+        }
+    }
+
+    return;
+}
+
+static int dbd_mysql_pbquery(apr_pool_t *pool, apr_dbd_t *sql,
+                             int *nrows, apr_dbd_prepared_t *statement,
+                             const void **values)
+{
+    MYSQL_BIND *bind;
+    int ret;
+
+    if (sql->trans && sql->trans->errnum) {
+        return sql->trans->errnum;
+    }
+
+    bind = apr_palloc(pool, statement->nargs * sizeof(MYSQL_BIND));
+
+    dbd_mysql_bbind(pool, statement, values, bind);
+
+    ret = dbd_mysql_pquery_internal(pool, sql, nrows, statement, bind);
+
+    if (TXN_NOTICE_ERRORS(sql->trans)) {
+        sql->trans->errnum = ret;
+    }
+    return ret;
+}
+
+static int dbd_mysql_pvbquery(apr_pool_t *pool, apr_dbd_t *sql, int *nrows,
+                              apr_dbd_prepared_t *statement, va_list args)
+{
+    const void **values;
+    int i;
+
+    if (sql->trans && sql->trans->errnum) {
+        return sql->trans->errnum;
+    }
+
+    values = apr_palloc(pool, sizeof(*values) * statement->nvals);
+
+    for (i = 0; i < statement->nvals; i++) {
+        values[i] = va_arg(args, const void*);
+    }
+
+    return dbd_mysql_pbquery(pool, sql, nrows, statement, values);
+}
+
+static int dbd_mysql_pbselect(apr_pool_t *pool, apr_dbd_t *sql,
+                              apr_dbd_results_t **res,
+                              apr_dbd_prepared_t *statement, int random,
+                              const void **args)
+{
+    int ret;
+    MYSQL_BIND *bind;
+
+    if (sql->trans && sql->trans->errnum) {
+        return sql->trans->errnum;
+    }
+
+    bind = apr_palloc(pool, statement->nargs * sizeof(MYSQL_BIND));
+
+    dbd_mysql_bbind(pool, statement, args, bind);
+
+    ret = dbd_mysql_pselect_internal(pool, sql,  res, statement, random, bind);
+
+    if (TXN_NOTICE_ERRORS(sql->trans)) {
+        sql->trans->errnum = ret;
+    }
+    return ret;
+}
+
+static int dbd_mysql_pvbselect(apr_pool_t *pool, apr_dbd_t *sql,
+                               apr_dbd_results_t **res,
+                               apr_dbd_prepared_t *statement, int random,
+                               va_list args)
+{
+    const void **values;
+    int i;
+
+    if (sql->trans && sql->trans->errnum) {
+        return sql->trans->errnum;
+    }
+
+    values = apr_palloc(pool, sizeof(*values) * statement->nvals);
+
+    for (i = 0; i < statement->nvals; i++) {
+        values[i] = va_arg(args, const void*);
+    }
+
+    return dbd_mysql_pbselect(pool, sql, res, statement, random, values);
+}
+
+static int dbd_mysql_end_transaction(apr_dbd_transaction_t *trans)
+{
+    int ret = -1;
+    if (trans) {
+        /* rollback on error or explicit rollback request */
+        if (trans->errnum || TXN_DO_ROLLBACK(trans)) {
+            trans->errnum = 0;
+            ret = mysql_rollback(trans->handle->conn);
+        }
+        else {
+            ret = mysql_commit(trans->handle->conn);
+        }
+        ret |= mysql_autocommit(trans->handle->conn, 1);
+        trans->handle->trans = NULL;
+    }
+    return ret;
+}
+/* Whether or not transactions work depends on whether the
+ * underlying DB supports them within MySQL.  Unfortunately
+ * it fails silently with the default InnoDB.
+ */
+
+static int dbd_mysql_transaction(apr_pool_t *pool, apr_dbd_t *handle,
+                                 apr_dbd_transaction_t **trans)
+{
+    /* Don't try recursive transactions here */
+    if (handle->trans) {
+        dbd_mysql_end_transaction(handle->trans) ;
+    }
+    if (!*trans) {
+        *trans = apr_pcalloc(pool, sizeof(apr_dbd_transaction_t));
+    }
+    (*trans)->errnum = mysql_autocommit(handle->conn, 0);
+    (*trans)->handle = handle;
+    handle->trans = *trans;
+    return (*trans)->errnum;
+}
+
+static int dbd_mysql_transaction_mode_get(apr_dbd_transaction_t *trans)
+{
+    if (!trans)
+        return APR_DBD_TRANSACTION_COMMIT;
+
+    return trans->mode;
+}
+
+static int dbd_mysql_transaction_mode_set(apr_dbd_transaction_t *trans,
+                                          int mode)
+{
+    if (!trans)
+        return APR_DBD_TRANSACTION_COMMIT;
+
+    return trans->mode = (mode & TXN_MODE_BITS);
+}
+
+static apr_dbd_t *dbd_mysql_open(apr_pool_t *pool, const char *params,
+                                 const char **error)
+{
+    static const char *const delims = " \r\n\t;|,";
+    const char *ptr;
+    int i;
+    const char *key;
+    size_t klen;
+    const char *value;
+    size_t vlen;
+#if MYSQL_VERSION_ID >= 50013
+    my_bool do_reconnect = 1;
+#endif
+    MYSQL *real_conn;
+    unsigned long flags = 0;
+
+    struct {
+        const char *field;
+        const char *value;
+    } fields[] = {
+        {"host", NULL},
+        {"user", NULL},
+        {"pass", NULL},
+        {"dbname", NULL},
+        {"port", NULL},
+        {"sock", NULL},
+        {"flags", NULL},
+        {"fldsz", NULL},
+        {"group", NULL},
+#if MYSQL_VERSION_ID >= 50013
+        {"reconnect", NULL},
+        {"connecttimeout", NULL},
+        {"readtimeout", NULL},
+        {"writetimeout", NULL},
+#endif
+        {NULL, NULL}
+    };
+    unsigned int port = 0;
+#if MYSQL_VERSION_ID >= 50013
+    unsigned int timeout = 0;
+#endif
+    apr_dbd_t *sql = apr_pcalloc(pool, sizeof(apr_dbd_t));
+    sql->fldsz = FIELDSIZE;
+    sql->conn = mysql_init(sql->conn);
+    if ( sql->conn == NULL ) {
+        return NULL;
+    }
+    for (ptr = strchr(params, '='); ptr; ptr = strchr(ptr, '=')) {
+        /* don't dereference memory that may not belong to us */
+        if (ptr == params) {
+            ++ptr;
+            continue;
+        }
+        for (key = ptr-1; apr_isspace(*key); --key);
+        klen = 0;
+        while (apr_isalpha(*key)) {
+            /* don't parse backwards off the start of the string */
+            if (key == params) {
+                --key;
+                ++klen;
+                break;
+            }
+            --key;
+            ++klen;
+        }
+        ++key;
+        for (value = ptr+1; apr_isspace(*value); ++value);
+        vlen = strcspn(value, delims);
+        for (i = 0; fields[i].field != NULL; i++) {
+            if (!strncasecmp(fields[i].field, key, klen)) {
+                fields[i].value = apr_pstrndup(pool, value, vlen);
+                break;
+            }
+        }
+        ptr = value+vlen;
+    }
+    if (fields[4].value != NULL) {
+        port = atoi(fields[4].value);
+    }
+    if (fields[6].value != NULL &&
+        !strcmp(fields[6].value, "CLIENT_FOUND_ROWS")) {
+        flags |= CLIENT_FOUND_ROWS; /* only option we know */
+    }
+    if (fields[7].value != NULL) {
+        sql->fldsz = atol(fields[7].value);
+    }
+    if (fields[8].value != NULL) {
+         mysql_options(sql->conn, MYSQL_READ_DEFAULT_GROUP, fields[8].value);
+    }
+#if MYSQL_VERSION_ID >= 50013
+    if (fields[9].value != NULL) {
+         do_reconnect = atoi(fields[9].value) ? 1 : 0;
+    }
+    if (fields[10].value != NULL) {
+        timeout = atoi(fields[10].value);
+        mysql_options(sql->conn, MYSQL_OPT_CONNECT_TIMEOUT,
+                      (const void *)&timeout);
+    }
+    if (fields[11].value != NULL) {
+        timeout = atoi(fields[11].value);
+        mysql_options(sql->conn, MYSQL_OPT_READ_TIMEOUT,
+                      (const void *)&timeout);
+    }
+    if (fields[12].value != NULL) {
+        timeout = atoi(fields[12].value);
+        mysql_options(sql->conn, MYSQL_OPT_WRITE_TIMEOUT,
+                      (const void *)&timeout);
+    }
+#endif
+
+#if MYSQL_VERSION_ID >= 50013
+    /* the MySQL manual says this should be BEFORE mysql_real_connect */
+    mysql_options(sql->conn, MYSQL_OPT_RECONNECT, &do_reconnect);
+#endif
+
+    real_conn = mysql_real_connect(sql->conn, fields[0].value,
+                                   fields[1].value, fields[2].value,
+                                   fields[3].value, port,
+                                   fields[5].value, flags);
+
+    if(real_conn == NULL) {
+        if (error) {
+            *error = apr_pstrdup(pool, mysql_error(sql->conn));
+        }
+        mysql_close(sql->conn);
+        return NULL;
+    }
+
+#if MYSQL_VERSION_ID >= 50013
+    /* Some say this should be AFTER mysql_real_connect */
+    mysql_options(sql->conn, MYSQL_OPT_RECONNECT, &do_reconnect);
+#endif
+
+    return sql;
+}
+
+static apr_status_t dbd_mysql_close(apr_dbd_t *handle)
+{
+    mysql_close(handle->conn);
+    return APR_SUCCESS;
+}
+
+static apr_status_t dbd_mysql_check_conn(apr_pool_t *pool,
+                                         apr_dbd_t *handle)
+{
+    return mysql_ping(handle->conn) ? APR_EGENERAL : APR_SUCCESS;
+}
+
+static int dbd_mysql_select_db(apr_pool_t *pool, apr_dbd_t* handle,
+                               const char* name)
+{
+    return mysql_select_db(handle->conn, name);
+}
+
+static void *dbd_mysql_native(apr_dbd_t *handle)
+{
+    return handle->conn;
+}
+
+static int dbd_mysql_num_cols(apr_dbd_results_t *res)
+{
+    if (res->statement) {
+        return mysql_stmt_field_count(res->statement);
+    }
+    else {
+        return mysql_num_fields(res->res);
+    }
+}
+
+static int dbd_mysql_num_tuples(apr_dbd_results_t *res)
+{
+    if (res->random) {
+        if (res->statement) {
+            return (int) mysql_stmt_num_rows(res->statement);
+        }
+        else {
+            return (int) mysql_num_rows(res->res);
+        }
+    }
+    else {
+        return -1;
+    }
+}
+
+static apr_status_t thread_end(void *data)
+{
+    mysql_thread_end();
+    return APR_SUCCESS;
+}
+
+static void dbd_mysql_init(apr_pool_t *pool)
+{
+    my_init();
+    mysql_thread_init();
+
+    /* FIXME: this is a guess; find out what it really does */
+    apr_pool_cleanup_register(pool, NULL, thread_end, apr_pool_cleanup_null);
+}
+APR_MODULE_DECLARE_DATA const apr_dbd_driver_t apr_dbd_mysql_driver = {
+    "mysql",
+    dbd_mysql_init,
+    dbd_mysql_native,
+    dbd_mysql_open,
+    dbd_mysql_check_conn,
+    dbd_mysql_close,
+    dbd_mysql_select_db,
+    dbd_mysql_transaction,
+    dbd_mysql_end_transaction,
+    dbd_mysql_query,
+    dbd_mysql_select,
+    dbd_mysql_num_cols,
+    dbd_mysql_num_tuples,
+    dbd_mysql_get_row,
+    dbd_mysql_get_entry,
+    dbd_mysql_error,
+    dbd_mysql_escape,
+    dbd_mysql_prepare,
+    dbd_mysql_pvquery,
+    dbd_mysql_pvselect,
+    dbd_mysql_pquery,
+    dbd_mysql_pselect,
+    dbd_mysql_get_name,
+    dbd_mysql_transaction_mode_get,
+    dbd_mysql_transaction_mode_set,
+    "?",
+    dbd_mysql_pvbquery,
+    dbd_mysql_pvbselect,
+    dbd_mysql_pbquery,
+    dbd_mysql_pbselect,
+    dbd_mysql_datum_get
+};
+
+#endif
diff --git a/dbd/apr_dbd_mysql.dsp b/dbd/apr_dbd_mysql.dsp
new file mode 100644
index 00000000000..dbaff5d3e33
--- /dev/null
+++ b/dbd/apr_dbd_mysql.dsp
@@ -0,0 +1,207 @@
+# Microsoft Developer Studio Project File - Name="apr_dbd_mysql" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=apr_dbd_mysql - 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 "apr_dbd_mysql.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 "apr_dbd_mysql.mak" CFG="apr_dbd_mysql - Win32 Release"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "apr_dbd_mysql - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_dbd_mysql - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_dbd_mysql - x64 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_dbd_mysql - x64 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)" == "apr_dbd_mysql - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /Zi /O2 /Oy- /I "../include" /I "../include/arch/win32" /I "../include/private" /I "../../mysql/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_MYSQL=1 /D "HAVE_MYSQL_H" /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbd_mysql_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /fo"Release/apr_dbd_mysql-1.res" /d DLL_NAME="apr_dbd_mysql" /d "NDEBUG" /d "APU_VERSION_ONLY" /I "../include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libmysql.lib /nologo /base:"0x6EF50000" /subsystem:windows /dll /incremental:no /debug /opt:ref
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libmysql.lib /nologo /base:"0x6EF50000" /subsystem:windows /dll /incremental:no /debug /libpath:"..\..\mysql\lib" /out:"Release\apr_dbd_mysql-1.dll" /pdb:"Release\apr_dbd_mysql-1.pdb" /implib:"Release\apr_dbd_mysql-1.lib" /MACHINE:X86 /opt:ref
+# Begin Special Build Tool
+TargetPath=Release\apr_dbd_mysql-1.dll
+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)" == "apr_dbd_mysql - 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 /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /EHsc /c
+# ADD CPP /nologo /MDd /W3 /Zi /Od /I "../include" /I "../include/arch/win32" /I "../include/private" /I "../../mysql/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_MYSQL=1 /D "HAVE_MYSQL_H" /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbd_mysql_src" /FD /EHsc /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /fo"Debug/apr_dbd_mysql-1.res" /d DLL_NAME="apr_dbd_mysql" /d "_DEBUG" /d "APU_VERSION_ONLY" /I "../include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libmysqld.lib /nologo /base:"0x6EF50000" /subsystem:windows /dll /incremental:no /debug
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libmysqld.lib /nologo /base:"0x6EF50000" /subsystem:windows /dll /incremental:no /debug /libpath:"..\..\mysql\lib" /out:"Debug\apr_dbd_mysql-1.dll" /pdb:"Debug\apr_dbd_mysql-1.pdb" /implib:"Debug\apr_dbd_mysql-1.lib" /MACHINE:X86
+# Begin Special Build Tool
+TargetPath=Debug\apr_dbd_mysql-1.dll
+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)" == "apr_dbd_mysql - x64 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "x64\Release"
+# PROP BASE Intermediate_Dir "x64\Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "x64\Release"
+# PROP Intermediate_Dir "x64\Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /Zi /O2 /Oy- /I "../include" /I "../include/arch/win32" /I "../include/private" /I "../../mysql/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_MYSQL=1 /D "HAVE_MYSQL_H" /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbd_mysql_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /fo"x64/Release/apr_dbd_mysql-1.res" /d DLL_NAME="apr_dbd_mysql" /d "NDEBUG" /d "APU_VERSION_ONLY" /I "../include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libmysql.lib /nologo /base:"0x6EF50000" /subsystem:windows /dll /incremental:no /debug /opt:ref
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libmysql.lib /nologo /base:"0x6EF50000" /subsystem:windows /dll /incremental:no /debug /libpath:"..\..\mysql\lib" /out:"x64\Release\apr_dbd_mysql-1.dll" /pdb:"x64\Release\apr_dbd_mysql-1.pdb" /implib:"x64\Release\apr_dbd_mysql-1.lib" /MACHINE:X64 /opt:ref
+# Begin Special Build Tool
+TargetPath=x64\Release\apr_dbd_mysql-1.dll
+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)" == "apr_dbd_mysql - x64 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "x64\Debug"
+# PROP BASE Intermediate_Dir "x64\Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "x64\Debug"
+# PROP Intermediate_Dir "x64\Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /EHsc /c
+# ADD CPP /nologo /MDd /W3 /Zi /Od /I "../include" /I "../include/arch/win32" /I "../include/private" /I "../../mysql/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_MYSQL=1 /D "HAVE_MYSQL_H" /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbd_mysql_src" /FD /EHsc /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /fo"x64/Debug/apr_dbd_mysql-1.res" /d DLL_NAME="apr_dbd_mysql" /d "_DEBUG" /d "APU_VERSION_ONLY" /I "../include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libmysqld.lib /nologo /base:"0x6EF50000" /subsystem:windows /dll /incremental:no /debug
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libmysqld.lib /nologo /base:"0x6EF50000" /subsystem:windows /dll /incremental:no /debug /libpath:"..\..\mysql\lib" /out:"x64\Debug\apr_dbd_mysql-1.dll" /pdb:"x64\Debug\apr_dbd_mysql-1.pdb" /implib:"x64\Debug\apr_dbd_mysql-1.lib" /MACHINE:X64
+# Begin Special Build Tool
+TargetPath=x64\Debug\apr_dbd_mysql-1.dll
+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 "apr_dbd_mysql - Win32 Release"
+# Name "apr_dbd_mysql - Win32 Debug"
+# Name "apr_dbd_mysql - x64 Release"
+# Name "apr_dbd_mysql - x64 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\apr_dbd_mysql.c
+# End Source File
+# End Group
+# Begin Group "Public Header Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\include\apr_dbd.h
+# End Source File
+# End Group
+# Begin Group "Internal Header Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\include\private\apu_config.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\private\apu_dbd_internal.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\private\apu_internal.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\libapr.rc
+# End Source File
+# End Target
+# End Project
diff --git a/dbd/apr_dbd_odbc.c b/dbd/apr_dbd_odbc.c
new file mode 100644
index 00000000000..65306792026
--- /dev/null
+++ b/dbd/apr_dbd_odbc.c
@@ -0,0 +1,1734 @@
+/* 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 "apu.h"
+#include "apr_private.h"
+#if APU_HAVE_ODBC
+
+#include "apr.h"
+#include "apr_strings.h"
+#include "apr_buckets.h"
+#include "apr_env.h"
+#include "apr_file_io.h"
+#include "apr_file_info.h"
+#include "apr_dbd_internal.h"
+#include "apr_thread_proc.h"
+#include "apr_version.h"
+
+#include <stdlib.h>
+
+/* If library is ODBC-V2, use macros for limited ODBC-V2 support 
+ * No random access in V2.
+ */
+#ifdef ODBCV2
+#define ODBCVER 0x0200
+#include "apr_dbd_odbc_v2.h"
+#endif
+
+/* standard ODBC include files */
+#ifdef HAVE_SQL_H
+#include <sql.h>
+#include <sqlext.h>
+#elif defined(HAVE_ODBC_SQL_H)
+#include <odbc/sql.h>
+#include <odbc/sqlext.h>
+#endif
+
+/* Driver name is "odbc" and the entry point is 'apr_dbd_odbc_driver' 
+ * unless ODBC_DRIVER_NAME is defined and it is linked with another db library which
+ * is ODBC source-compatible. e.g. DB2, Informix, TimesTen, mysql.  
+ */
+#ifndef ODBC_DRIVER_NAME
+#define ODBC_DRIVER_NAME odbc
+#endif
+#define STRINGIFY(x) #x
+#define NAMIFY2(n) apr_dbd_##n##_driver
+#define NAMIFY1(n) NAMIFY2(n)
+#define ODBC_DRIVER_STRING STRINGIFY(ODBC_DRIVER_NAME)
+#define ODBC_DRIVER_ENTRY NAMIFY1(ODBC_DRIVER_NAME)
+
+/* Required APR version for this driver */
+#define DRIVER_APR_VERSION_MAJOR APR_MAJOR_VERSION
+#define DRIVER_APR_VERSION_MINOR APR_MINOR_VERSION
+
+static SQLHANDLE henv = NULL;           /* ODBC ENV handle is process-wide */
+
+/* Use a CHECK_ERROR macro so we can grab the source line numbers
+ * for error reports
+ */
+static void check_error(apr_dbd_t *a, const char *step, SQLRETURN rc,
+                 SQLSMALLINT type, SQLHANDLE h, int line);
+#define CHECK_ERROR(a,s,r,t,h)  check_error(a,s,r,t,h, __LINE__)
+
+#define SOURCE_FILE __FILE__            /* source file for error messages */
+#define MAX_ERROR_STRING 1024           /* max length of message in dbc */
+#define MAX_COLUMN_NAME 256             /* longest column name recognized */
+#define DEFAULT_BUFFER_SIZE 1024        /* value for defaultBufferSize */
+
+#define MAX_PARAMS  20
+#define DEFAULTSEPS " \t\r\n,="
+#define CSINGLEQUOTE '\''
+#define SSINGLEQUOTE "\'"
+
+#define TEXTMODE 1              /* used for text (APR 1.2) mode params */
+#define BINARYMODE 0            /* used for binary (APR 1.3+) mode params */
+
+/* Identify datatypes which are LOBs 
+ * - DB2 DRDA driver uses undefined types -98 and -99 for CLOB & BLOB
+ */
+#define IS_LOB(t)  (t == SQL_LONGVARCHAR \
+     || t == SQL_LONGVARBINARY || t == SQL_VARBINARY \
+     || t == -98 || t == -99)
+
+/* These types are CLOBs 
+ * - DB2 DRDA driver uses undefined type -98 for CLOB
+ */
+#define IS_CLOB(t) \
+    (t == SQL_LONGVARCHAR || t == -98)
+
+/* Convert a SQL result to an APR result */
+#define APR_FROM_SQL_RESULT(rc) \
+    (SQL_SUCCEEDED(rc) ? APR_SUCCESS : APR_EGENERAL)
+
+/* DBD opaque structures */
+struct apr_dbd_t
+{
+    SQLHANDLE dbc;              /* SQL connection handle - NULL after close */
+    apr_pool_t *pool;           /* connection lifetime pool */
+    char *dbname;               /* ODBC datasource */
+    int lasterrorcode;
+    int lineNumber;
+    char lastError[MAX_ERROR_STRING];
+    int defaultBufferSize;      /* used for CLOBs in text mode, 
+                                 * and when fld size is indeterminate */
+    apr_intptr_t transaction_mode;
+    apr_intptr_t dboptions;     /* driver options re SQLGetData */
+    apr_intptr_t default_transaction_mode;
+    int can_commit;             /* controls end_trans behavior */
+};
+
+struct apr_dbd_results_t
+{
+    SQLHANDLE stmt;             /* parent sql statement handle */
+    SQLHANDLE dbc;              /* parent sql connection handle */
+    apr_pool_t *pool;           /* pool from query or select */
+    apr_dbd_t *apr_dbd;         /* parent DBD connection handle */
+    int random;                 /* random access requested */
+    int ncols;                  /* number of columns */
+    int isclosed;               /* cursor has been closed */
+    char **colnames;            /* array of column names (NULL until used) */
+    SQLPOINTER *colptrs;        /* pointers to column data */
+    SQLINTEGER *colsizes;       /* sizes for columns (enough for txt or bin) */
+    SQLINTEGER *coltextsizes;   /* max-sizes if converted to text */
+    SQLSMALLINT *coltypes;      /* array of SQL data types for columns */
+    SQLLEN *colinds;            /* array of SQL data indicator/strlens */
+    int *colstate;              /* array of column states
+                                 * - avail, bound, present, unavail 
+                                 */
+    int *all_data_fetched;      /* flags data as all fetched, for LOBs  */
+    void *data;                 /* buffer for all data for one row */
+};
+
+enum                            /* results column states */
+{
+    COL_AVAIL,                  /* data may be retrieved with SQLGetData */
+    COL_PRESENT,                /* data has been retrieved with SQLGetData */
+    COL_BOUND,                  /* column is bound to colptr */
+    COL_RETRIEVED,              /* all data from column has been returned */
+    COL_UNAVAIL                 /* column is unavailable because ODBC driver
+                                 *  requires that columns be retrieved
+                                 *  in ascending order and a higher col 
+                                 *  was accessed
+                                 */
+};
+
+struct apr_dbd_row_t {
+    SQLHANDLE stmt;             /* parent ODBC statement handle */
+    SQLHANDLE dbc;              /* parent ODBC connection handle */
+    apr_pool_t *pool;           /* pool from get_row */
+    apr_dbd_results_t *res;
+};
+
+struct apr_dbd_transaction_t {
+    SQLHANDLE dbc;              /* parent ODBC connection handle */
+    apr_dbd_t *apr_dbd;         /* parent DBD connection handle */
+};
+
+struct apr_dbd_prepared_t {
+    SQLHANDLE stmt;             /* ODBC statement handle */
+    SQLHANDLE dbc;              /* parent ODBC connection handle */
+    apr_dbd_t *apr_dbd;
+    int nargs;
+    int nvals;
+    int *types;                 /* array of DBD data types */
+};
+
+static void odbc_lob_bucket_destroy(void *data);
+static apr_status_t odbc_lob_bucket_setaside(apr_bucket *e, apr_pool_t *pool);
+static apr_status_t odbc_lob_bucket_read(apr_bucket *e, const char **str,
+                                         apr_size_t *len, apr_read_type_e block);
+
+/* the ODBC LOB bucket type */
+static const apr_bucket_type_t odbc_bucket_type = {
+    "ODBC_LOB", 5, APR_BUCKET_DATA,
+    odbc_lob_bucket_destroy,
+    odbc_lob_bucket_read,
+    odbc_lob_bucket_setaside,
+    apr_bucket_shared_split,
+    apr_bucket_shared_copy
+};
+
+/* ODBC LOB bucket data */
+typedef struct {
+    /** Ref count for shared bucket */
+    apr_bucket_refcount  refcount;
+    const apr_dbd_row_t *row;
+    int col;
+    SQLSMALLINT type;
+} odbc_bucket;
+
+/* SQL datatype mappings to DBD datatypes 
+ * These tables must correspond *exactly* to the apr_dbd_type_e enum 
+ * in apr_dbd.h
+ */
+
+/* ODBC "C" types to DBD datatypes  */
+static SQLSMALLINT const sqlCtype[] = {
+    SQL_C_DEFAULT,                  /* APR_DBD_TYPE_NONE              */
+    SQL_C_STINYINT,                 /* APR_DBD_TYPE_TINY,       \%hhd */
+    SQL_C_UTINYINT,                 /* APR_DBD_TYPE_UTINY,      \%hhu */
+    SQL_C_SSHORT,                   /* APR_DBD_TYPE_SHORT,      \%hd  */
+    SQL_C_USHORT,                   /* APR_DBD_TYPE_USHORT,     \%hu  */
+    SQL_C_SLONG,                    /* APR_DBD_TYPE_INT,        \%d   */
+    SQL_C_ULONG,                    /* APR_DBD_TYPE_UINT,       \%u   */
+    SQL_C_SLONG,                    /* APR_DBD_TYPE_LONG,       \%ld  */
+    SQL_C_ULONG,                    /* APR_DBD_TYPE_ULONG,      \%lu  */
+    SQL_C_SBIGINT,                  /* APR_DBD_TYPE_LONGLONG,   \%lld */
+    SQL_C_UBIGINT,                  /* APR_DBD_TYPE_ULONGLONG,  \%llu */
+    SQL_C_FLOAT,                    /* APR_DBD_TYPE_FLOAT,      \%f   */
+    SQL_C_DOUBLE,                   /* APR_DBD_TYPE_DOUBLE,     \%lf  */
+    SQL_C_CHAR,                     /* APR_DBD_TYPE_STRING,     \%s   */
+    SQL_C_CHAR,                     /* APR_DBD_TYPE_TEXT,       \%pDt */
+    SQL_C_CHAR, /*SQL_C_TYPE_TIME,      APR_DBD_TYPE_TIME,       \%pDi */
+    SQL_C_CHAR, /*SQL_C_TYPE_DATE,      APR_DBD_TYPE_DATE,       \%pDd */
+    SQL_C_CHAR, /*SQL_C_TYPE_TIMESTAMP, APR_DBD_TYPE_DATETIME,   \%pDa */
+    SQL_C_CHAR, /*SQL_C_TYPE_TIMESTAMP, APR_DBD_TYPE_TIMESTAMP,  \%pDs */
+    SQL_C_CHAR, /*SQL_C_TYPE_TIMESTAMP, APR_DBD_TYPE_ZTIMESTAMP, \%pDz */
+    SQL_LONGVARBINARY,              /* APR_DBD_TYPE_BLOB,       \%pDb */
+    SQL_LONGVARCHAR,                /* APR_DBD_TYPE_CLOB,       \%pDc */
+    SQL_TYPE_NULL                   /* APR_DBD_TYPE_NULL        \%pDn */
+};
+#define NUM_APR_DBD_TYPES (sizeof(sqlCtype) / sizeof(sqlCtype[0]))
+
+/*  ODBC Base types to DBD datatypes */
+static SQLSMALLINT const sqlBaseType[] = {
+    SQL_C_DEFAULT,              /* APR_DBD_TYPE_NONE              */
+    SQL_TINYINT,                /* APR_DBD_TYPE_TINY,       \%hhd */
+    SQL_TINYINT,                /* APR_DBD_TYPE_UTINY,      \%hhu */
+    SQL_SMALLINT,               /* APR_DBD_TYPE_SHORT,      \%hd  */
+    SQL_SMALLINT,               /* APR_DBD_TYPE_USHORT,     \%hu  */
+    SQL_INTEGER,                /* APR_DBD_TYPE_INT,        \%d   */
+    SQL_INTEGER,                /* APR_DBD_TYPE_UINT,       \%u   */
+    SQL_INTEGER,                /* APR_DBD_TYPE_LONG,       \%ld  */
+    SQL_INTEGER,                /* APR_DBD_TYPE_ULONG,      \%lu  */
+    SQL_BIGINT,                 /* APR_DBD_TYPE_LONGLONG,   \%lld */
+    SQL_BIGINT,                 /* APR_DBD_TYPE_ULONGLONG,  \%llu */
+    SQL_FLOAT,                  /* APR_DBD_TYPE_FLOAT,      \%f   */
+    SQL_DOUBLE,                 /* APR_DBD_TYPE_DOUBLE,     \%lf  */
+    SQL_CHAR,                   /* APR_DBD_TYPE_STRING,     \%s   */
+    SQL_CHAR,                   /* APR_DBD_TYPE_TEXT,       \%pDt */
+    SQL_CHAR, /*SQL_TIME,          APR_DBD_TYPE_TIME,       \%pDi */
+    SQL_CHAR, /*SQL_DATE,          APR_DBD_TYPE_DATE,       \%pDd */
+    SQL_CHAR, /*SQL_TIMESTAMP,     APR_DBD_TYPE_DATETIME,   \%pDa */
+    SQL_CHAR, /*SQL_TIMESTAMP,     APR_DBD_TYPE_TIMESTAMP,  \%pDs */
+    SQL_CHAR, /*SQL_TIMESTAMP,     APR_DBD_TYPE_ZTIMESTAMP, \%pDz */
+    SQL_LONGVARBINARY,          /* APR_DBD_TYPE_BLOB,       \%pDb */
+    SQL_LONGVARCHAR,            /* APR_DBD_TYPE_CLOB,       \%pDc */
+    SQL_TYPE_NULL               /* APR_DBD_TYPE_NULL        \%pDn */
+};
+
+/*  result sizes for DBD datatypes (-1 for null-terminated) */
+static int const sqlSizes[] = {
+    0,
+    sizeof(char),               /**< \%hhd out: char* */
+    sizeof(unsigned char),      /**< \%hhu out: unsigned char* */
+    sizeof(short),              /**< \%hd  out: short* */
+    sizeof(unsigned short),     /**< \%hu  out: unsigned short* */
+    sizeof(int),                /**< \%d   out: int* */
+    sizeof(unsigned int),       /**< \%u   out: unsigned int* */
+    sizeof(long),               /**< \%ld  out: long* */
+    sizeof(unsigned long),      /**< \%lu  out: unsigned long* */
+    sizeof(apr_int64_t),        /**< \%lld out: apr_int64_t* */
+    sizeof(apr_uint64_t),       /**< \%llu out: apr_uint64_t* */
+    sizeof(float),              /**< \%f   out: float* */
+    sizeof(double),             /**< \%lf  out: double* */
+    -1,                         /**< \%s   out: char** */
+    -1,                         /**< \%pDt out: char** */
+    -1,                         /**< \%pDi out: char** */
+    -1,                         /**< \%pDd out: char** */
+    -1,                         /**< \%pDa out: char** */
+    -1,                         /**< \%pDs out: char** */
+    -1,                         /**< \%pDz out: char** */
+    sizeof(apr_bucket_brigade), /**< \%pDb out: apr_bucket_brigade* */
+    sizeof(apr_bucket_brigade), /**< \%pDc out: apr_bucket_brigade* */
+    0                           /**< \%pDn : in: void*, out: void** */
+};
+
+/*
+ * local functions
+ */
+
+/* close any open results for the connection */
+static apr_status_t odbc_close_results(void *d)
+{
+    apr_dbd_results_t *dbr = (apr_dbd_results_t *)d;
+    SQLRETURN rc = SQL_SUCCESS;
+    
+    if (dbr && dbr->apr_dbd && dbr->apr_dbd->dbc) {
+    	if (!dbr->isclosed)
+            rc = SQLCloseCursor(dbr->stmt);
+    	dbr->isclosed = 1;
+    }
+    return APR_FROM_SQL_RESULT(rc);
+}
+
+/* close the ODBC statement handle from a  prepare */
+static apr_status_t odbc_close_pstmt(void *s)
+{   
+    SQLRETURN rc = APR_SUCCESS;
+    apr_dbd_prepared_t *statement = s;
+
+    /* stmt is closed if connection has already been closed */
+    if (statement) {
+        SQLHANDLE hstmt = statement->stmt;
+
+        if (hstmt && statement->apr_dbd && statement->apr_dbd->dbc) {
+            rc = SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
+        }
+        statement->stmt = NULL;
+    }
+    return APR_FROM_SQL_RESULT(rc);
+}
+
+/* close: close/release a connection obtained from open() */
+static apr_status_t odbc_close(apr_dbd_t *handle)
+{
+    SQLRETURN rc = SQL_SUCCESS;
+
+    if (handle->dbc) {
+        rc = SQLDisconnect(handle->dbc);
+        CHECK_ERROR(handle, "SQLDisconnect", rc, SQL_HANDLE_DBC, handle->dbc);
+        rc = SQLFreeHandle(SQL_HANDLE_DBC, handle->dbc);
+        CHECK_ERROR(handle, "SQLFreeHandle (DBC)", rc, SQL_HANDLE_ENV, henv);
+        handle->dbc = NULL;
+    }
+    return APR_FROM_SQL_RESULT(rc);
+}
+
+/* odbc_close re-defined for passing to pool cleanup */
+static apr_status_t odbc_close_cleanup(void *handle)
+{
+    return odbc_close((apr_dbd_t *)handle);
+}
+
+/* close the ODBC environment handle at process termination */
+static apr_status_t odbc_close_env(SQLHANDLE henv)
+{   
+    SQLRETURN rc;
+
+    rc = SQLFreeHandle(SQL_HANDLE_ENV, henv);
+    henv = NULL;
+    return APR_FROM_SQL_RESULT(rc);
+}
+
+/* setup the arrays in results for all the returned columns */
+static SQLRETURN odbc_set_result_column(int icol, apr_dbd_results_t *res, 
+                                        SQLHANDLE stmt)
+{
+    SQLRETURN rc;
+    apr_intptr_t maxsize, textsize, realsize, type, isunsigned = 1;
+
+    /* discover the sql type */
+    rc = SQLColAttribute(stmt, icol + 1, SQL_DESC_UNSIGNED, NULL, 0, NULL,
+                         (SQLPOINTER)&isunsigned);
+    isunsigned = (isunsigned == SQL_TRUE);
+
+    rc = SQLColAttribute(stmt, icol + 1, SQL_DESC_TYPE, NULL, 0, NULL,
+                         (SQLPOINTER)&type);
+    if (!SQL_SUCCEEDED(rc) || type == SQL_UNKNOWN_TYPE) {
+        /* MANY ODBC v2 datasources only supply CONCISE_TYPE */
+        rc = SQLColAttribute(stmt, icol + 1, SQL_DESC_CONCISE_TYPE, NULL,
+                             0, NULL, (SQLPOINTER)&type);
+    }
+
+    if (!SQL_SUCCEEDED(rc)) {
+        /* if still unknown make it CHAR */
+        type = SQL_C_CHAR;
+    }
+
+    switch (type) {
+    case SQL_INTEGER:
+    case SQL_SMALLINT:
+    case SQL_TINYINT:
+    case SQL_BIGINT:
+      /* fix these numeric binary types up as signed/unsigned for C types */
+      type += (isunsigned) ? SQL_UNSIGNED_OFFSET : SQL_SIGNED_OFFSET;
+      break;
+    /* LOB types are not changed to C types */
+    case SQL_LONGVARCHAR: 
+        type = SQL_LONGVARCHAR; 
+        break;
+    case SQL_LONGVARBINARY: 
+        type = SQL_LONGVARBINARY; 
+        break;
+    case SQL_FLOAT : 
+        type = SQL_C_FLOAT; 
+        break;
+    case SQL_DOUBLE : 
+        type = SQL_C_DOUBLE; 
+        break;
+
+    /* DBD wants times as strings */
+    case SQL_TIMESTAMP:      
+    case SQL_DATE:
+    case SQL_TIME:
+    default:
+      type = SQL_C_CHAR;
+    }
+
+    res->coltypes[icol] = (SQLSMALLINT)type;
+
+    /* size if retrieved as text */
+    rc = SQLColAttribute(stmt, icol + 1, SQL_DESC_DISPLAY_SIZE, NULL, 0,
+                         NULL, (SQLPOINTER)&textsize);
+    if (!SQL_SUCCEEDED(rc) || textsize < 0) {
+        textsize = res->apr_dbd->defaultBufferSize;
+    }
+    /* for null-term, which sometimes isn't included */
+    textsize++;
+
+    /* real size */
+    rc = SQLColAttribute(stmt, icol + 1, SQL_DESC_OCTET_LENGTH, NULL, 0,
+                         NULL, (SQLPOINTER)&realsize);
+    if (!SQL_SUCCEEDED(rc)) {
+        realsize = textsize;
+    }
+
+    maxsize = (textsize > realsize) ? textsize : realsize;
+    if (IS_LOB(type) || maxsize <= 0) {
+        /* LOB types are never bound and have a NULL colptr for binary.
+         * Ingore their real (1-2gb) length & use a default - the larger
+         * of defaultBufferSize or APR_BUCKET_BUFF_SIZE.
+         * If not a LOB, but simply unknown length - always use defaultBufferSize.
+         */
+        maxsize = res->apr_dbd->defaultBufferSize;
+        if (IS_LOB(type) && maxsize < APR_BUCKET_BUFF_SIZE) {
+            maxsize = APR_BUCKET_BUFF_SIZE;
+        }
+
+        res->colptrs[icol] =  NULL;
+        res->colstate[icol] = COL_AVAIL;
+        res->colsizes[icol] = (SQLINTEGER)maxsize;
+        rc = SQL_SUCCESS;
+    }
+    else {
+        res->colptrs[icol] = apr_pcalloc(res->pool, maxsize);
+        res->colsizes[icol] = (SQLINTEGER)maxsize;
+        if (res->apr_dbd->dboptions & SQL_GD_BOUND) {
+            /* we are allowed to call SQLGetData if we need to */
+            rc = SQLBindCol(stmt, icol + 1, res->coltypes[icol], 
+                            res->colptrs[icol], maxsize, 
+                            &(res->colinds[icol]));
+            CHECK_ERROR(res->apr_dbd, "SQLBindCol", rc, SQL_HANDLE_STMT,
+                        stmt);
+            res->colstate[icol] = SQL_SUCCEEDED(rc) ? COL_BOUND : COL_AVAIL;
+        }
+        else {
+            /* this driver won't allow us to call SQLGetData on bound 
+             * columns - so don't bind any
+             */
+            res->colstate[icol] = COL_AVAIL;
+            rc = SQL_SUCCESS;
+        }
+    }
+    return rc;
+}
+
+/* create and populate an apr_dbd_results_t for a select */
+static SQLRETURN odbc_create_results(apr_dbd_t *handle, SQLHANDLE hstmt,
+                                     apr_pool_t *pool, const int random,
+                                     apr_dbd_results_t **res)
+{
+    SQLRETURN rc;
+    SQLSMALLINT ncols;
+
+    *res = apr_pcalloc(pool, sizeof(apr_dbd_results_t));
+    (*res)->stmt = hstmt;
+    (*res)->dbc = handle->dbc;
+    (*res)->pool = pool;
+    (*res)->random = random;
+    (*res)->apr_dbd = handle;
+    rc = SQLNumResultCols(hstmt, &ncols);
+    CHECK_ERROR(handle, "SQLNumResultCols", rc, SQL_HANDLE_STMT, hstmt);
+    (*res)->ncols = ncols;
+
+    if (SQL_SUCCEEDED(rc)) {
+        int i;
+
+        (*res)->colnames = apr_pcalloc(pool, ncols * sizeof(char *));
+        (*res)->colptrs = apr_pcalloc(pool, ncols * sizeof(void *));
+        (*res)->colsizes = apr_pcalloc(pool, ncols * sizeof(SQLINTEGER));
+        (*res)->coltypes = apr_pcalloc(pool, ncols * sizeof(SQLSMALLINT));
+        (*res)->colinds = apr_pcalloc(pool, ncols * sizeof(SQLLEN));
+        (*res)->colstate = apr_pcalloc(pool, ncols * sizeof(int));
+        (*res)->ncols = ncols;
+
+        for (i = 0; i < ncols; i++) {
+            odbc_set_result_column(i, (*res), hstmt);
+        }
+    }
+    return rc;
+}
+
+
+/* bind a parameter - input params only, does not support output parameters */
+static SQLRETURN odbc_bind_param(apr_pool_t *pool,
+                                 apr_dbd_prepared_t *statement, const int narg,
+                                 const SQLSMALLINT type, int *argp,
+                                 const void **args, const int textmode)
+{
+    SQLRETURN rc;
+    SQLSMALLINT baseType, cType;
+    void *ptr;
+    SQLULEN len;
+    SQLLEN *indicator;
+    static SQLLEN nullValue = SQL_NULL_DATA;
+    static SQLSMALLINT inOut = SQL_PARAM_INPUT;     /* only input params */
+
+    /* bind a NULL data value */
+    if (args[*argp] == NULL || type == APR_DBD_TYPE_NULL) {
+        baseType = SQL_CHAR;
+        cType = SQL_C_CHAR;
+        ptr = &nullValue;
+        len = sizeof(SQLINTEGER);
+        indicator = &nullValue;
+        (*argp)++;
+    }
+    /* bind a non-NULL data value */
+    else {
+        if (type < 0 || type >= NUM_APR_DBD_TYPES) {
+            return APR_EGENERAL;
+        }
+
+        baseType = sqlBaseType[type];
+        cType = sqlCtype[type];
+        indicator = NULL;
+        /* LOBs */
+        if (IS_LOB(cType)) {
+            ptr = (void *)args[*argp];
+            len = (SQLULEN) * (apr_size_t *)args[*argp + 1];
+            cType = (IS_CLOB(cType)) ? SQL_C_CHAR : SQL_C_DEFAULT;
+            (*argp) += 4;  /* LOBs consume 4 args (last two are unused) */
+        }
+        /* non-LOBs */
+        else {
+            switch (baseType) {
+            case SQL_CHAR:
+            case SQL_DATE:
+            case SQL_TIME:
+            case SQL_TIMESTAMP:
+                ptr = (void *)args[*argp];
+                len = (SQLULEN)strlen(ptr);
+                break;
+            case SQL_TINYINT:
+                ptr = apr_palloc(pool, sizeof(unsigned char));
+                len = sizeof(unsigned char);
+                *(unsigned char *)ptr =
+                    (textmode ?
+                     atoi(args[*argp]) : *(unsigned char *)args[*argp]);
+                break;
+            case SQL_SMALLINT:
+                ptr = apr_palloc(pool, sizeof(short));
+                len = sizeof(short);
+                *(short *)ptr =
+                    (textmode ? atoi(args[*argp]) : *(short *)args[*argp]);
+                break;
+            case SQL_INTEGER:
+                ptr = apr_palloc(pool, sizeof(int));
+                len = sizeof(int);
+                *(long *)ptr =
+                    (textmode ? atol(args[*argp]) : *(long *)args[*argp]);
+                break;
+            case SQL_FLOAT:
+                ptr = apr_palloc(pool, sizeof(float));
+                len = sizeof(float);
+                *(float *)ptr =
+                    (textmode ?
+                     (float)atof(args[*argp]) : *(float *)args[*argp]);
+                break;
+            case SQL_DOUBLE:
+                ptr = apr_palloc(pool, sizeof(double));
+                len = sizeof(double);
+                *(double *)ptr =
+                    (textmode ? atof(args[*argp]) : *(double *)
+                     args[*argp]);
+                break;
+            case SQL_BIGINT:
+                ptr = apr_palloc(pool, sizeof(apr_int64_t));
+                len = sizeof(apr_int64_t);
+                *(apr_int64_t *)ptr =
+                    (textmode ?
+                     apr_atoi64(args[*argp]) : *(apr_int64_t *)args[*argp]);
+                break;
+            default:
+                return APR_EGENERAL;
+            }
+            (*argp)++;          /* non LOBs consume one argument */
+        }
+    }
+    rc = SQLBindParameter(statement->stmt, narg, inOut, cType, 
+                          baseType, len, 0, ptr, len, indicator);
+    CHECK_ERROR(statement->apr_dbd, "SQLBindParameter", rc, SQL_HANDLE_STMT,
+                statement->stmt);
+    return rc;
+}
+
+/* LOB / Bucket Brigade functions */
+
+/* bucket type specific destroy */
+static void odbc_lob_bucket_destroy(void *data)
+{
+    odbc_bucket *bd = data;
+
+    if (apr_bucket_shared_destroy(bd))
+        apr_bucket_free(bd);
+}
+
+/* set aside a bucket if possible */
+static apr_status_t odbc_lob_bucket_setaside(apr_bucket *e, apr_pool_t *pool)
+{
+    odbc_bucket *bd = (odbc_bucket *)e->data;
+
+    /* Unlikely - but if the row pool is ancestor of this pool then it is OK */
+    if (apr_pool_is_ancestor(bd->row->pool, pool))
+        return APR_SUCCESS;
+    
+    return apr_bucket_setaside_notimpl(e, pool);
+}
+
+/* split a bucket into a heap bucket followed by a LOB bkt w/remaining data */
+static apr_status_t odbc_lob_bucket_read(apr_bucket *e, const char **str,
+                                         apr_size_t *len, apr_read_type_e block)
+{
+    SQLRETURN rc;
+    SQLLEN len_indicator;
+    SQLSMALLINT type;
+    odbc_bucket *bd = (odbc_bucket *)e->data;
+    apr_bucket *nxt;
+    void *buf;
+    int bufsize = bd->row->res->apr_dbd->defaultBufferSize;
+    int eos;
+    
+    /* C type is CHAR for CLOBs, DEFAULT for BLOBs */
+    type = bd->row->res->coltypes[bd->col];
+    type = (type == SQL_LONGVARCHAR) ? SQL_C_CHAR : SQL_C_DEFAULT;
+
+    /* LOB buffers are always at least APR_BUCKET_BUFF_SIZE, 
+     *   but they may be much bigger per the BUFSIZE parameter.
+     */
+    if (bufsize < APR_BUCKET_BUFF_SIZE)
+        bufsize = APR_BUCKET_BUFF_SIZE;
+
+    buf = apr_bucket_alloc(bufsize, e->list);
+    *str = NULL;
+    *len = 0;
+
+    rc = SQLGetData(bd->row->res->stmt, bd->col + 1, 
+                    type, buf, bufsize, 
+                    &len_indicator);
+
+    CHECK_ERROR(bd->row->res->apr_dbd, "SQLGetData", rc, 
+                SQL_HANDLE_STMT, bd->row->res->stmt);
+    
+    if (rc == SQL_NO_DATA || len_indicator == SQL_NULL_DATA || len_indicator < 0)
+        len_indicator = 0;
+
+    if (SQL_SUCCEEDED(rc) || rc == SQL_NO_DATA) {
+
+        if (rc == SQL_SUCCESS_WITH_INFO
+            && (len_indicator == SQL_NO_TOTAL || len_indicator >= bufsize)) {
+            /* not the last read = a full buffer. CLOBs have a null terminator */
+            *len = bufsize - (IS_CLOB(bd->type) ? 1 : 0 );
+
+             eos = 0;
+        }
+        else {
+            /* the last read - len_indicator is supposed to be the length, 
+             * but some driver get this wrong and return the total length.
+             * We try to handle both interpretations.
+             */
+            *len =  (len_indicator > bufsize 
+                     && len_indicator >= (SQLLEN)e->start)
+                ? (len_indicator - (SQLLEN)e->start) : len_indicator;
+
+            eos = 1;
+        }
+
+        if (!eos) {
+            /* Create a new LOB bucket to append and append it */
+            nxt = apr_bucket_alloc(sizeof(apr_bucket *), e->list);
+            APR_BUCKET_INIT(nxt);
+            nxt->length = -1;
+            nxt->data   = e->data;
+            nxt->type   = &odbc_bucket_type;
+            nxt->free   = apr_bucket_free;
+            nxt->list   = e->list;
+            nxt->start  = e->start + *len;
+            APR_BUCKET_INSERT_AFTER(e, nxt);
+        }
+        else {
+            odbc_lob_bucket_destroy(e->data);
+        }
+        /* make current bucket into a heap bucket */
+        apr_bucket_heap_make(e, buf, *len, apr_bucket_free);
+        *str = buf;
+
+        /* No data is success in this context */
+        rc = SQL_SUCCESS;
+    }
+    return APR_FROM_SQL_RESULT(rc);
+}
+
+/* Create a bucket brigade on the row pool for a LOB column */
+static apr_status_t odbc_create_bucket(const apr_dbd_row_t *row, const int col, 
+                                       SQLSMALLINT type, apr_bucket_brigade *bb)
+{
+    apr_bucket_alloc_t *list = bb->bucket_alloc;
+    apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
+    odbc_bucket *bd = apr_bucket_alloc(sizeof(odbc_bucket), list);
+    apr_bucket *eos = apr_bucket_eos_create(list);
+    
+    bd->row = row;
+    bd->col = col;
+    bd->type = type;
+
+    APR_BUCKET_INIT(b);
+    b->type = &odbc_bucket_type;
+    b->free = apr_bucket_free;
+    b->list = list;
+    /* LOB lengths are unknown in ODBC */
+    b = apr_bucket_shared_make(b, bd, 0, -1);
+
+    APR_BRIGADE_INSERT_TAIL(bb, b);
+    APR_BRIGADE_INSERT_TAIL(bb, eos);
+
+    return APR_SUCCESS;
+}
+
+/* returns a data pointer for a column,  returns NULL for NULL value,
+ * return -1 if data not available
+ */
+static void *odbc_get(const apr_dbd_row_t *row, const int col, 
+                      const SQLSMALLINT sqltype)
+{
+    SQLRETURN rc;
+    SQLLEN indicator;
+    int state = row->res->colstate[col];
+    apr_intptr_t options = row->res->apr_dbd->dboptions;
+
+    switch (state) {
+    case (COL_UNAVAIL):
+        return (void *)-1;
+    case (COL_RETRIEVED):
+        return NULL;
+
+    case (COL_BOUND):
+    case (COL_PRESENT): 
+        if (sqltype == row->res->coltypes[col]) {
+            /* same type and we already have the data */
+            row->res->colstate[col] = COL_RETRIEVED;
+            return (row->res->colinds[col] == SQL_NULL_DATA) ? 
+                NULL : row->res->colptrs[col];
+        }
+    }
+
+    /* we need to get the data now */
+    if (!(options & SQL_GD_ANY_ORDER)) {
+        /* this ODBC driver requires columns to be retrieved in order,
+         * so we attempt to get every prior un-gotten non-LOB column
+         */
+        int i;
+        for (i = 0; i < col; i++) {
+            if (row->res->colstate[i] == COL_AVAIL) {
+                if (IS_LOB(row->res->coltypes[i]))
+                       row->res->colstate[i] = COL_UNAVAIL;
+                else {
+                    odbc_get(row, i, row->res->coltypes[i]);
+                    row->res->colstate[i] = COL_PRESENT;
+                }
+            }
+        }
+    }
+
+    if ((state == COL_BOUND && !(options & SQL_GD_BOUND)))
+        /* this driver won't let us re-get bound columns */
+        return (void *)-1;
+
+    /* a LOB might not have a buffer allocated yet - so create one */
+    if (!row->res->colptrs[col])
+        row->res->colptrs[col] = apr_pcalloc(row->pool, row->res->colsizes[col]);
+
+    rc = SQLGetData(row->res->stmt, col + 1, sqltype, row->res->colptrs[col],
+                    row->res->colsizes[col], &indicator);
+    CHECK_ERROR(row->res->apr_dbd, "SQLGetData", rc, SQL_HANDLE_STMT, 
+                row->res->stmt);
+    if (indicator == SQL_NULL_DATA || rc == SQL_NO_DATA)
+        return NULL;
+
+    if (SQL_SUCCEEDED(rc)) {
+        /* whatever it was originally, it is now this sqltype */
+        row->res->coltypes[col] = sqltype;
+        /* this allows getting CLOBs in text mode by calling get_entry
+         *   until it returns NULL
+         */
+        row->res->colstate[col] = 
+            (rc == SQL_SUCCESS_WITH_INFO) ? COL_AVAIL : COL_RETRIEVED;
+        return row->res->colptrs[col];
+    }
+    else
+        return (void *)-1;
+}
+
+/* Parse the parameter string for open */
+static apr_status_t odbc_parse_params(apr_pool_t *pool, const char *params,
+                               int *connect, SQLCHAR **datasource, 
+                               SQLCHAR **user, SQLCHAR **password, 
+                               int *defaultBufferSize, int *nattrs,
+                               int **attrs, apr_intptr_t **attrvals)
+{
+    char *seps, *last, *next, *name[MAX_PARAMS], *val[MAX_PARAMS];
+    int nparams = 0, i, j;
+
+    *attrs = apr_pcalloc(pool, MAX_PARAMS * sizeof(char *));
+    *attrvals = apr_pcalloc(pool, MAX_PARAMS * sizeof(apr_intptr_t));
+    *nattrs = 0;
+    seps = DEFAULTSEPS;
+    name[nparams] = apr_strtok(apr_pstrdup(pool, params), seps, &last);
+
+    /* no params is OK here - let connect return a more useful error msg */
+    if (!name[nparams])
+        return SQL_SUCCESS;
+
+    do {
+        if (last[strspn(last, seps)] == CSINGLEQUOTE) {
+            last += strspn(last, seps);
+            seps=SSINGLEQUOTE;
+        }
+        val[nparams] = apr_strtok(NULL, seps, &last);
+        seps = DEFAULTSEPS;
+
+        ++nparams;
+        next = apr_strtok(NULL, seps, &last);
+        if (!next) {
+            break;
+        }
+        if (nparams >= MAX_PARAMS) {
+            /* too many parameters, no place to store */
+            return APR_EGENERAL;
+        }
+        name[nparams] = next;
+    } while (1);
+
+    for (j = i = 0; i < nparams; i++) {
+        if (!apr_strnatcasecmp(name[i], "CONNECT")) {
+            *datasource = (SQLCHAR *)apr_pstrdup(pool, val[i]);
+            *connect = 1;
+        }
+        else if (!apr_strnatcasecmp(name[i], "DATASOURCE")) {
+            *datasource = (SQLCHAR *)apr_pstrdup(pool, val[i]);
+            *connect = 0;
+        }
+        else if (!apr_strnatcasecmp(name[i], "USER")) {
+            *user = (SQLCHAR *)apr_pstrdup(pool, val[i]);
+        }
+        else if (!apr_strnatcasecmp(name[i], "PASSWORD")) {
+            *password = (SQLCHAR *)apr_pstrdup(pool, val[i]);
+        }
+        else if (!apr_strnatcasecmp(name[i], "BUFSIZE")) {
+            *defaultBufferSize = atoi(val[i]);
+        }
+        else if (!apr_strnatcasecmp(name[i], "ACCESS")) {
+            if (!apr_strnatcasecmp(val[i], "READ_ONLY"))
+                (*attrvals)[j] = SQL_MODE_READ_ONLY;
+            else if (!apr_strnatcasecmp(val[i], "READ_WRITE"))
+                (*attrvals)[j] = SQL_MODE_READ_WRITE;
+            else
+                return SQL_ERROR;
+            (*attrs)[j++] = SQL_ATTR_ACCESS_MODE;
+        }
+        else if (!apr_strnatcasecmp(name[i], "CTIMEOUT")) {
+            (*attrvals)[j] = atoi(val[i]);
+            (*attrs)[j++] = SQL_ATTR_LOGIN_TIMEOUT;
+        }
+        else if (!apr_strnatcasecmp(name[i], "STIMEOUT")) {
+            (*attrvals)[j] = atoi(val[i]);
+            (*attrs)[j++] = SQL_ATTR_CONNECTION_TIMEOUT;
+        }
+        else if (!apr_strnatcasecmp(name[i], "TXMODE")) {
+            if (!apr_strnatcasecmp(val[i], "READ_UNCOMMITTED"))
+                (*attrvals)[j] = SQL_TXN_READ_UNCOMMITTED;
+            else if (!apr_strnatcasecmp(val[i], "READ_COMMITTED"))
+                (*attrvals)[j] = SQL_TXN_READ_COMMITTED;
+            else if (!apr_strnatcasecmp(val[i], "REPEATABLE_READ"))
+                (*attrvals)[j] = SQL_TXN_REPEATABLE_READ;
+            else if (!apr_strnatcasecmp(val[i], "SERIALIZABLE"))
+                (*attrvals)[j] = SQL_TXN_SERIALIZABLE;
+            else if (!apr_strnatcasecmp(val[i], "DEFAULT"))
+                continue;
+            else
+                return SQL_ERROR;
+            (*attrs)[j++] = SQL_ATTR_TXN_ISOLATION;
+        }
+        else
+            return SQL_ERROR;
+    }
+    *nattrs = j;
+    return (*datasource && *defaultBufferSize) ? APR_SUCCESS : SQL_ERROR;
+}
+
+/* common handling after ODBC calls - save error info (code and text) in dbc */
+static void check_error(apr_dbd_t *dbc, const char *step, SQLRETURN rc,
+                 SQLSMALLINT type, SQLHANDLE h, int line)
+{
+    SQLCHAR buffer[512];
+    SQLCHAR sqlstate[128];
+    SQLINTEGER native;
+    SQLSMALLINT reslength;
+    char *res, *p, *end, *logval = NULL;
+    int i;
+
+    /* set info about last error in dbc  - fast return for SQL_SUCCESS  */
+    if (rc == SQL_SUCCESS) {
+        char successMsg[] = "[dbd_odbc] SQL_SUCCESS ";
+        apr_size_t successMsgLen = sizeof successMsg - 1;
+
+        dbc->lasterrorcode = SQL_SUCCESS;
+        apr_cpystrn(dbc->lastError, successMsg, sizeof dbc->lastError);
+        apr_cpystrn(dbc->lastError + successMsgLen, step,
+                    sizeof dbc->lastError - successMsgLen);
+        return;
+    }
+    switch (rc) {
+    case SQL_INVALID_HANDLE:
+        res = "SQL_INVALID_HANDLE";
+        break;
+    case SQL_ERROR:
+        res = "SQL_ERROR";
+        break;
+    case SQL_SUCCESS_WITH_INFO:
+        res = "SQL_SUCCESS_WITH_INFO";
+        break;
+    case SQL_STILL_EXECUTING:
+        res = "SQL_STILL_EXECUTING";
+        break;
+    case SQL_NEED_DATA:
+        res = "SQL_NEED_DATA";
+        break;
+    case SQL_NO_DATA:
+        res = "SQL_NO_DATA";
+        break;
+    default:
+        res = "unrecognized SQL return code";
+    }
+    /* these two returns are expected during normal execution */
+    if (rc != SQL_SUCCESS_WITH_INFO && rc != SQL_NO_DATA 
+        && dbc->can_commit != APR_DBD_TRANSACTION_IGNORE_ERRORS) {
+        dbc->can_commit = APR_DBD_TRANSACTION_ROLLBACK;
+    }
+    p = dbc->lastError;
+    end = p + sizeof(dbc->lastError);
+    dbc->lasterrorcode = rc;
+    p += sprintf(p, "[dbd_odbc] %.64s returned %.30s (%d) at %.24s:%d ",
+                 step, res, rc, SOURCE_FILE, line - 1);
+    for (i = 1, rc = 0; rc == 0; i++) {
+        rc = SQLGetDiagRec(type, h, i, sqlstate, &native, buffer, 
+                            sizeof(buffer), &reslength);
+        if (SQL_SUCCEEDED(rc) && (p < (end - 280))) 
+            p += sprintf(p, "%.256s %.20s ", buffer, sqlstate);
+    }
+    apr_env_get(&logval, "apr_dbd_odbc_log", dbc->pool);
+    /* if env var was set or call was init/open (no dbname) - log to stderr */
+    if (logval || !dbc->dbname ) {
+        char timestamp[APR_CTIME_LEN];
+
+        apr_file_t *se;
+        apr_ctime(timestamp, apr_time_now());
+        apr_file_open_stderr(&se, dbc->pool);
+        apr_file_printf(se, "[%s] %s\n", timestamp, dbc->lastError);
+    }
+}
+
+static APR_INLINE int odbc_check_rollback(apr_dbd_t *handle)
+{
+    if (handle->can_commit == APR_DBD_TRANSACTION_ROLLBACK) {
+        handle->lasterrorcode = SQL_ERROR;
+        apr_cpystrn(handle->lastError, "[dbd_odbc] Rollback pending ",
+                    sizeof handle->lastError);
+        return 1;
+    }
+    return 0;
+}
+
+/*
+ *   public functions per DBD driver API
+ */
+
+/** init: allow driver to perform once-only initialisation. **/
+static void odbc_init(apr_pool_t *pool)
+{
+    SQLRETURN rc;
+    char *step;
+    apr_version_t aprver;
+    
+    apr_version(&aprver);
+    if (aprver.major != DRIVER_APR_VERSION_MAJOR 
+        || aprver.minor != DRIVER_APR_VERSION_MINOR) {
+            apr_file_t *se;
+
+            apr_file_open_stderr(&se, pool);
+            apr_file_printf(se, "Incorrect " ODBC_DRIVER_STRING " dbd driver version\n"
+                "Attempt to load APR version %d.%d driver with APR version %d.%d\n",
+                DRIVER_APR_VERSION_MAJOR, DRIVER_APR_VERSION_MINOR, 
+                aprver.major, aprver.minor);
+        abort();
+    }
+
+    if (henv) 
+        return;
+
+    step = "SQLAllocHandle (SQL_HANDLE_ENV)";
+    rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
+    apr_pool_cleanup_register(pool, henv, odbc_close_env, apr_pool_cleanup_null);
+    if (SQL_SUCCEEDED(rc)) {
+        step = "SQLSetEnvAttr";
+        rc = SQLSetEnvAttr(henv,SQL_ATTR_ODBC_VERSION,
+                          (SQLPOINTER)SQL_OV_ODBC3, 0);
+    }
+    else {
+        apr_dbd_t tmp_dbc;
+        SQLHANDLE err_h = henv;
+
+        tmp_dbc.pool = pool;
+        tmp_dbc.dbname = NULL;
+        CHECK_ERROR(&tmp_dbc, step, rc, SQL_HANDLE_ENV, err_h);
+    }
+}
+
+/** native_handle: return the native database handle of the underlying db **/
+static void *odbc_native_handle(apr_dbd_t *handle)
+{
+    return handle->dbc;
+}
+
+/** open: obtain a database connection from the server rec. **/
+
+/* It would be more efficient to allocate a single statement handle 
+ * here - but SQL_ATTR_CURSOR_SCROLLABLE must be set before
+ * SQLPrepare, and we don't know whether random-access is
+ * specified until SQLExecute so we cannot.
+ */
+
+static apr_dbd_t *odbc_open(apr_pool_t *pool, const char *params, const char **error)
+{
+    SQLRETURN rc;
+    SQLHANDLE hdbc = NULL;
+    apr_dbd_t *handle;
+    char *err_step;
+    int err_htype, i;
+    int defaultBufferSize = DEFAULT_BUFFER_SIZE;
+    SQLHANDLE err_h = NULL;
+    SQLCHAR  *datasource = (SQLCHAR *)"", *user = (SQLCHAR *)"",
+             *password = (SQLCHAR *)"";
+    int nattrs = 0, *attrs = NULL,  connect = 0;
+    apr_intptr_t *attrvals = NULL;
+
+    err_step = "SQLAllocHandle (SQL_HANDLE_DBC)";
+    err_htype = SQL_HANDLE_ENV;
+    err_h = henv;
+    rc = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
+    if (SQL_SUCCEEDED(rc)) {
+        err_step = "Invalid DBD Parameters - open";
+        err_htype = SQL_HANDLE_DBC;
+        err_h = hdbc;
+        rc = odbc_parse_params(pool, params, &connect, &datasource, &user,
+                               &password, &defaultBufferSize, &nattrs, &attrs,
+                               &attrvals);
+    }
+    if (SQL_SUCCEEDED(rc)) {
+        for (i = 0; i < nattrs && SQL_SUCCEEDED(rc); i++) {
+            err_step = "SQLSetConnectAttr (from DBD Parameters)";
+            err_htype = SQL_HANDLE_DBC;
+            err_h = hdbc;
+            rc = SQLSetConnectAttr(hdbc, attrs[i], (SQLPOINTER)attrvals[i], 0);
+        }
+    }
+    if (SQL_SUCCEEDED(rc)) {
+        if (connect) {
+            SQLCHAR out[1024];
+            SQLSMALLINT outlen;
+
+            err_step = "SQLDriverConnect";
+            err_htype = SQL_HANDLE_DBC;
+            err_h = hdbc;
+            rc = SQLDriverConnect(hdbc, NULL, datasource,
+                        (SQLSMALLINT)strlen((char *)datasource),
+                        out, sizeof(out), &outlen, SQL_DRIVER_NOPROMPT);
+        }
+        else {
+            err_step = "SQLConnect";
+            err_htype = SQL_HANDLE_DBC;
+            err_h = hdbc;
+            rc = SQLConnect(hdbc, datasource,
+                        (SQLSMALLINT)strlen((char *)datasource),
+                        user, (SQLSMALLINT)strlen((char *)user),
+                        password, (SQLSMALLINT)strlen((char *)password));
+        }
+    }
+    if (SQL_SUCCEEDED(rc)) {
+        handle = apr_pcalloc(pool, sizeof(apr_dbd_t));
+        handle->dbname = apr_pstrdup(pool, (char *)datasource);
+        handle->dbc = hdbc;
+        handle->pool = pool;
+        handle->defaultBufferSize = defaultBufferSize;
+        CHECK_ERROR(handle, "SQLConnect", rc, SQL_HANDLE_DBC, handle->dbc);
+        handle->default_transaction_mode = 0;
+        handle->can_commit = APR_DBD_TRANSACTION_IGNORE_ERRORS;
+        SQLGetInfo(hdbc, SQL_DEFAULT_TXN_ISOLATION,
+                   &(handle->default_transaction_mode), sizeof(apr_intptr_t), NULL);
+        handle->transaction_mode = handle->default_transaction_mode;
+        SQLGetInfo(hdbc, SQL_GETDATA_EXTENSIONS ,&(handle->dboptions),
+                   sizeof(apr_intptr_t), NULL);
+        apr_pool_cleanup_register(pool, handle, odbc_close_cleanup, apr_pool_cleanup_null);
+        return handle;
+    }
+    else {
+        apr_dbd_t tmp_dbc;
+
+        tmp_dbc.pool = pool;
+        tmp_dbc.dbname = NULL;
+        CHECK_ERROR(&tmp_dbc, err_step, rc, err_htype, err_h);
+        if (error)
+            *error = apr_pstrdup(pool, tmp_dbc.lastError);
+        if (hdbc)
+            SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
+        return NULL;
+    }
+}
+
+/** check_conn: check status of a database connection **/
+static apr_status_t odbc_check_conn(apr_pool_t *pool, apr_dbd_t *handle)
+{
+    SQLUINTEGER isDead;
+    SQLRETURN   rc;
+
+    rc = SQLGetConnectAttr(handle->dbc, SQL_ATTR_CONNECTION_DEAD, &isDead,
+                            sizeof(SQLUINTEGER), NULL);
+    CHECK_ERROR(handle, "SQLGetConnectAttr (SQL_ATTR_CONNECTION_DEAD)", rc,
+                SQL_HANDLE_DBC, handle->dbc);
+    /* if driver cannot check connection, say so */
+    if (rc != SQL_SUCCESS)
+        return APR_ENOTIMPL;
+
+    return (isDead == SQL_CD_FALSE) ? APR_SUCCESS : APR_EGENERAL;
+}
+
+/** set_dbname: select database name.  May be a no-op if not supported. **/
+static int odbc_set_dbname(apr_pool_t*pool, apr_dbd_t *handle,
+                           const char *name)
+{
+    if (apr_strnatcmp(name, handle->dbname)) {
+        return APR_EGENERAL;        /* It's illegal to change dbname in ODBC */
+    }
+    CHECK_ERROR(handle, "set_dbname (no-op)", SQL_SUCCESS, SQL_HANDLE_DBC,
+                handle->dbc);
+    return APR_SUCCESS;             /* OK if it's the same name */
+}
+
+/** transaction: start a transaction.  May be a no-op. **/
+static int odbc_start_transaction(apr_pool_t *pool, apr_dbd_t *handle,
+                                  apr_dbd_transaction_t **trans)
+{
+    SQLRETURN rc = SQL_SUCCESS;
+
+    if (handle->transaction_mode) {
+        rc = SQLSetConnectAttr(handle->dbc, SQL_ATTR_TXN_ISOLATION,
+                               (SQLPOINTER)handle->transaction_mode, 0);
+        CHECK_ERROR(handle, "SQLSetConnectAttr (SQL_ATTR_TXN_ISOLATION)", rc,
+                    SQL_HANDLE_DBC, handle->dbc);
+    }
+    if (SQL_SUCCEEDED(rc)) {
+        /* turn off autocommit for transactions */
+        rc = SQLSetConnectAttr(handle->dbc, SQL_ATTR_AUTOCOMMIT,
+                               SQL_AUTOCOMMIT_OFF, 0);
+        CHECK_ERROR(handle, "SQLSetConnectAttr (SQL_ATTR_AUTOCOMMIT)", rc,
+                    SQL_HANDLE_DBC, handle->dbc);
+    }
+    if (SQL_SUCCEEDED(rc)) {
+        *trans = apr_palloc(pool, sizeof(apr_dbd_transaction_t));
+        (*trans)->dbc = handle->dbc;
+        (*trans)->apr_dbd = handle;
+    }
+    handle->can_commit = APR_DBD_TRANSACTION_COMMIT;
+    return APR_FROM_SQL_RESULT(rc);
+}
+
+/** end_transaction: end a transaction **/
+static int odbc_end_transaction(apr_dbd_transaction_t *trans)
+{
+    SQLRETURN rc;
+    int action = (trans->apr_dbd->can_commit != APR_DBD_TRANSACTION_ROLLBACK) 
+        ? SQL_COMMIT : SQL_ROLLBACK;
+
+    rc = SQLEndTran(SQL_HANDLE_DBC, trans->dbc, action);
+    CHECK_ERROR(trans->apr_dbd, "SQLEndTran", rc, SQL_HANDLE_DBC, trans->dbc);
+    if (SQL_SUCCEEDED(rc)) {
+        rc = SQLSetConnectAttr(trans->dbc, SQL_ATTR_AUTOCOMMIT,
+                               (SQLPOINTER)SQL_AUTOCOMMIT_ON, 0);
+        CHECK_ERROR(trans->apr_dbd, "SQLSetConnectAttr (SQL_ATTR_AUTOCOMMIT)",
+                    rc, SQL_HANDLE_DBC, trans->dbc);
+    }
+    trans->apr_dbd->can_commit = APR_DBD_TRANSACTION_IGNORE_ERRORS;
+    return APR_FROM_SQL_RESULT(rc);
+}
+
+/** query: execute an SQL statement which doesn't return a result set **/
+static int odbc_query(apr_dbd_t *handle, int *nrows, const char *statement)
+{
+    SQLRETURN rc;
+    SQLHANDLE hstmt = NULL;
+    size_t len = strlen(statement);
+
+    if (odbc_check_rollback(handle))
+        return APR_EGENERAL;
+
+    rc = SQLAllocHandle(SQL_HANDLE_STMT, handle->dbc, &hstmt);
+    CHECK_ERROR(handle, "SQLAllocHandle (STMT)", rc, SQL_HANDLE_DBC,
+                handle->dbc);
+    if (!SQL_SUCCEEDED(rc))
+        return APR_FROM_SQL_RESULT(rc);
+
+    rc = SQLExecDirect(hstmt, (SQLCHAR *)statement, (SQLINTEGER)len);
+    CHECK_ERROR(handle, "SQLExecDirect", rc, SQL_HANDLE_STMT, hstmt);
+
+    if (SQL_SUCCEEDED(rc)) {
+        SQLLEN rowcount;
+
+        rc = SQLRowCount(hstmt, &rowcount);
+        *nrows = (int)rowcount;
+        CHECK_ERROR(handle, "SQLRowCount", rc, SQL_HANDLE_STMT, hstmt);
+    }
+
+    SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
+    return APR_FROM_SQL_RESULT(rc);
+}
+
+/** select: execute an SQL statement which returns a result set **/
+static int odbc_select(apr_pool_t *pool, apr_dbd_t *handle,
+                       apr_dbd_results_t **res, const char *statement,
+                       int random)
+{
+    SQLRETURN rc;
+    SQLHANDLE hstmt;
+    apr_dbd_prepared_t *stmt;
+    size_t len = strlen(statement);
+
+    if (odbc_check_rollback(handle))
+        return APR_EGENERAL;
+
+    rc = SQLAllocHandle(SQL_HANDLE_STMT, handle->dbc, &hstmt);
+    CHECK_ERROR(handle, "SQLAllocHandle (STMT)", rc, SQL_HANDLE_DBC,
+                handle->dbc);
+    if (!SQL_SUCCEEDED(rc))
+        return APR_FROM_SQL_RESULT(rc);
+    /* Prepare an apr_dbd_prepared_t for pool cleanup, even though this
+     * is not a prepared statement.  We want the same cleanup mechanism.
+     */
+    stmt = apr_pcalloc(pool, sizeof(apr_dbd_prepared_t));
+    stmt->apr_dbd = handle;
+    stmt->dbc = handle->dbc;
+    stmt->stmt = hstmt;
+    apr_pool_cleanup_register(pool, stmt, odbc_close_pstmt, apr_pool_cleanup_null);
+    if (random) {
+        rc = SQLSetStmtAttr(hstmt, SQL_ATTR_CURSOR_SCROLLABLE,
+                            (SQLPOINTER)SQL_SCROLLABLE, 0);
+        CHECK_ERROR(handle, "SQLSetStmtAttr (SQL_ATTR_CURSOR_SCROLLABLE)", rc,
+                    SQL_HANDLE_STMT, hstmt);
+    }
+    if (SQL_SUCCEEDED(rc)) {
+        rc = SQLExecDirect(hstmt, (SQLCHAR *)statement, (SQLINTEGER)len);
+        CHECK_ERROR(handle, "SQLExecDirect", rc, SQL_HANDLE_STMT, hstmt);
+    }
+    if (SQL_SUCCEEDED(rc)) {
+        rc = odbc_create_results(handle, hstmt, pool, random, res);
+        apr_pool_cleanup_register(pool, *res, 
+                                  odbc_close_results, apr_pool_cleanup_null);
+    }
+    return APR_FROM_SQL_RESULT(rc);
+}
+
+/** num_cols: get the number of columns in a results set **/
+static int odbc_num_cols(apr_dbd_results_t *res)
+{
+    return res->ncols;
+}
+
+/** num_tuples: get the number of rows in a results set **/
+static int odbc_num_tuples(apr_dbd_results_t *res)
+{
+    SQLRETURN rc;
+    SQLLEN nrows;
+
+    rc = SQLRowCount(res->stmt, &nrows);
+    CHECK_ERROR(res->apr_dbd, "SQLRowCount", rc, SQL_HANDLE_STMT, res->stmt);
+    return SQL_SUCCEEDED(rc) ? (int)nrows : -1;
+}
+
+/** get_row: get a row from a result set **/
+static int odbc_get_row(apr_pool_t *pool, apr_dbd_results_t *res,
+                        apr_dbd_row_t **row, int rownum)
+{
+    SQLRETURN rc;
+    char *fetchtype;
+    int c;
+
+    *row = apr_pcalloc(pool, sizeof(apr_dbd_row_t));
+    (*row)->stmt = res->stmt;
+    (*row)->dbc = res->dbc;
+    (*row)->res = res;
+    (*row)->pool = res->pool;
+
+    /* mark all the columns as needing SQLGetData unless they are bound  */
+    for (c = 0; c < res->ncols; c++) {
+        if (res->colstate[c] != COL_BOUND) {
+            res->colstate[c] = COL_AVAIL;
+        }
+        /* some drivers do not null-term zero-len CHAR data */
+        if (res->colptrs[c])
+            *(char *)res->colptrs[c] = 0; 
+    }
+    if (res->random && (rownum > 0)) {
+        fetchtype = "SQLFetchScroll";
+        rc = SQLFetchScroll(res->stmt, SQL_FETCH_ABSOLUTE, rownum);
+    }
+    else {
+        fetchtype = "SQLFetch";
+        rc = SQLFetch(res->stmt);
+    }
+    CHECK_ERROR(res->apr_dbd, fetchtype, rc, SQL_HANDLE_STMT, res->stmt);
+    (*row)->stmt = res->stmt;
+    if (!SQL_SUCCEEDED(rc) && !res->random) {
+        /* early close on any error (usually SQL_NO_DATA) if fetching
+         * sequentially to release resources ASAP
+         */
+        odbc_close_results(res);
+        return -1;
+    }
+    return SQL_SUCCEEDED(rc) ? 0 : -1;
+}
+
+/** datum_get: get a binary entry from a row **/
+static apr_status_t odbc_datum_get(const apr_dbd_row_t *row, int col,
+                                   apr_dbd_type_e dbdtype, void *data)
+{
+    SQLSMALLINT sqltype;
+    void *p;
+    int len;
+
+    if (col >= row->res->ncols)
+        return APR_EGENERAL;
+
+    if (dbdtype < 0 || dbdtype >= NUM_APR_DBD_TYPES) {
+        data = NULL;            /* invalid type */
+        return APR_EGENERAL;
+    }
+
+    len = sqlSizes[dbdtype];
+    sqltype = sqlCtype[dbdtype];
+
+    /* must not memcpy a brigade, sentinals are relative to orig loc */
+    if (IS_LOB(sqltype)) 
+        return odbc_create_bucket(row, col, sqltype, data);
+
+    p = odbc_get(row, col, sqltype);
+    if (p == (void *)-1)
+        return APR_EGENERAL;
+
+    if (p == NULL)
+        return APR_ENOENT;          /* SQL NULL value */
+    
+    if (len < 0)
+       *(char**)data = (char *)p;
+    else
+        memcpy(data, p, len);
+    
+    return APR_SUCCESS;
+
+}
+
+/** get_entry: get an entry from a row (string data) **/
+static const char *odbc_get_entry(const apr_dbd_row_t *row, int col)
+{
+    void *p;
+
+    if (col >= row->res->ncols)
+        return NULL;
+
+    p = odbc_get(row, col, SQL_C_CHAR);
+
+    /* NULL or invalid (-1) */
+    if (p == NULL || p == (void *)-1)
+        return p;     
+    else
+        return apr_pstrdup(row->pool, p);   
+}
+
+/** error: get current error message (if any) **/
+static const char *odbc_error(apr_dbd_t *handle, int errnum)
+{   
+    return (handle) ? handle->lastError : "[dbd_odbc]No error message available";
+}
+
+/** escape: escape a string so it is safe for use in query/select **/
+static const char *odbc_escape(apr_pool_t *pool, const char *s,
+                               apr_dbd_t *handle)
+{   
+    char *newstr, *src, *dst, *sq;
+    int qcount;
+
+    /* return the original if there are no single-quotes */
+    if (!(sq = strchr(s, '\''))) 
+        return (char *)s;
+    /* count the single-quotes and allocate a new buffer */
+    for (qcount = 1; (sq = strchr(sq + 1, '\'')); )
+        qcount++;
+    newstr = apr_palloc(pool, strlen(s) + qcount + 1);
+
+    /* move chars, doubling all single-quotes */
+    src = (char *)s;
+    for (dst = newstr; *src; src++) {
+        if ((*dst++ = *src) == '\'')  
+            *dst++ = '\'';
+    }
+    *dst = 0;
+    return newstr;
+}
+
+/** prepare: prepare a statement **/
+static int odbc_prepare(apr_pool_t *pool, apr_dbd_t *handle,
+                        const char *query, const char *label, int nargs,
+                        int nvals, apr_dbd_type_e *types,
+                        apr_dbd_prepared_t **statement)
+{
+    SQLRETURN rc;
+    size_t len = strlen(query);
+
+    if (odbc_check_rollback(handle))
+        return APR_EGENERAL;
+
+    *statement = apr_pcalloc(pool, sizeof(apr_dbd_prepared_t));
+    (*statement)->dbc = handle->dbc;
+    (*statement)->apr_dbd = handle;
+    (*statement)->nargs = nargs;
+    (*statement)->nvals = nvals;
+    (*statement)->types =
+        apr_pmemdup(pool, types, nargs * sizeof(apr_dbd_type_e));
+    rc = SQLAllocHandle(SQL_HANDLE_STMT, handle->dbc, &((*statement)->stmt));
+    apr_pool_cleanup_register(pool, *statement, 
+                              odbc_close_pstmt, apr_pool_cleanup_null);
+    CHECK_ERROR(handle, "SQLAllocHandle (STMT)", rc,
+                SQL_HANDLE_DBC, handle->dbc);
+    rc = SQLPrepare((*statement)->stmt, (SQLCHAR *)query, (SQLINTEGER)len);
+    CHECK_ERROR(handle, "SQLPrepare", rc, SQL_HANDLE_STMT,
+                (*statement)->stmt);
+    return APR_FROM_SQL_RESULT(rc);
+}
+
+/** pquery: query using a prepared statement + args **/
+static int odbc_pquery(apr_pool_t *pool, apr_dbd_t *handle, int *nrows,
+                       apr_dbd_prepared_t *statement, const char **args)
+{
+    SQLRETURN rc = SQL_SUCCESS;
+    int i, argp;
+
+    if (odbc_check_rollback(handle))
+        return APR_EGENERAL;
+
+    for (i = argp = 0; i < statement->nargs && SQL_SUCCEEDED(rc); i++) {
+        rc = odbc_bind_param(pool, statement, i + 1, statement->types[i],
+                             &argp, (const void **)args, TEXTMODE);
+    }
+    if (SQL_SUCCEEDED(rc)) {
+        rc = SQLExecute(statement->stmt);
+        CHECK_ERROR(handle, "SQLExecute", rc, SQL_HANDLE_STMT,
+                    statement->stmt);
+    }
+    if (SQL_SUCCEEDED(rc)) {
+        SQLLEN rowcount;
+
+        rc = SQLRowCount(statement->stmt, &rowcount);
+        *nrows = (int)rowcount;
+        CHECK_ERROR(handle, "SQLRowCount", rc, SQL_HANDLE_STMT,
+                    statement->stmt);
+    }
+    return APR_FROM_SQL_RESULT(rc);
+}
+
+/** pvquery: query using a prepared statement + args **/
+static int odbc_pvquery(apr_pool_t *pool, apr_dbd_t *handle, int *nrows,
+                        apr_dbd_prepared_t *statement, va_list args)
+{
+    const char **values;
+    int i;
+
+    values = apr_palloc(pool, sizeof(*values) * statement->nvals);
+    for (i = 0; i < statement->nvals; i++)
+        values[i] = va_arg(args, const char *);
+    return odbc_pquery(pool, handle, nrows, statement, values);
+}
+
+/** pselect: select using a prepared statement + args **/
+static int odbc_pselect(apr_pool_t *pool, apr_dbd_t *handle,
+                        apr_dbd_results_t **res, apr_dbd_prepared_t *statement,
+                        int random, const char **args)
+{
+    SQLRETURN rc = SQL_SUCCESS;
+    int i, argp;
+
+    if (odbc_check_rollback(handle))
+        return APR_EGENERAL;
+
+    if (random) {
+        rc = SQLSetStmtAttr(statement->stmt, SQL_ATTR_CURSOR_SCROLLABLE,
+                            (SQLPOINTER)SQL_SCROLLABLE, 0);
+        CHECK_ERROR(handle, "SQLSetStmtAttr (SQL_ATTR_CURSOR_SCROLLABLE)",
+                    rc, SQL_HANDLE_STMT, statement->stmt);
+    }
+    if (SQL_SUCCEEDED(rc)) {
+        for (i = argp = 0; i < statement->nargs && SQL_SUCCEEDED(rc); i++) {
+            rc = odbc_bind_param(pool, statement, i + 1, statement->types[i],
+                                 &argp, (const void **)args, TEXTMODE);
+        }
+    }
+    if (SQL_SUCCEEDED(rc)) {
+        rc = SQLExecute(statement->stmt);
+        CHECK_ERROR(handle, "SQLExecute", rc, SQL_HANDLE_STMT,
+                    statement->stmt);
+    }
+    if (SQL_SUCCEEDED(rc)) {
+        rc = odbc_create_results(handle, statement->stmt, pool, random, res);
+        apr_pool_cleanup_register(pool, *res,
+                                  odbc_close_results, apr_pool_cleanup_null);
+    }
+    return APR_FROM_SQL_RESULT(rc);
+}
+
+/** pvselect: select using a prepared statement + args **/
+static int odbc_pvselect(apr_pool_t *pool, apr_dbd_t *handle,
+                         apr_dbd_results_t **res,
+                         apr_dbd_prepared_t *statement, int random,
+                         va_list args)
+{
+    const char **values;
+    int i;
+
+    values = apr_palloc(pool, sizeof(*values) * statement->nvals);
+    for (i = 0; i < statement->nvals; i++)
+        values[i] = va_arg(args, const char *);
+    return odbc_pselect(pool, handle, res, statement, random, values);
+}
+
+/** get_name: get a column title from a result set **/
+static const char *odbc_get_name(const apr_dbd_results_t *res, int col)
+{
+    SQLRETURN rc;
+    char buffer[MAX_COLUMN_NAME];
+    SQLSMALLINT colnamelength, coltype, coldecimal, colnullable;
+    SQLULEN colsize;
+
+    if (col >= res->ncols)
+        return NULL;            /* bogus column number */
+    if (res->colnames[col] != NULL)
+        return res->colnames[col];      /* we already retrieved it */
+    rc = SQLDescribeCol(res->stmt, col + 1,
+                        (SQLCHAR *)buffer, sizeof(buffer), &colnamelength,
+                        &coltype, &colsize, &coldecimal, &colnullable);
+    CHECK_ERROR(res->apr_dbd, "SQLDescribeCol", rc,
+                SQL_HANDLE_STMT, res->stmt);
+    res->colnames[col] = apr_pstrdup(res->pool, buffer);
+    return res->colnames[col];
+}
+
+/** transaction_mode_get: get the mode of transaction **/
+static int odbc_transaction_mode_get(apr_dbd_transaction_t *trans)
+{
+    return (int)trans->apr_dbd->can_commit;
+}
+
+/** transaction_mode_set: set the mode of transaction **/
+static int odbc_transaction_mode_set(apr_dbd_transaction_t *trans, int mode)
+{
+    int legal = (  APR_DBD_TRANSACTION_IGNORE_ERRORS
+                 | APR_DBD_TRANSACTION_COMMIT
+                 | APR_DBD_TRANSACTION_ROLLBACK);
+
+    if ((mode & legal) != mode)
+        return APR_EGENERAL;
+
+    trans->apr_dbd->can_commit = mode;
+    return APR_SUCCESS;
+}
+
+/** pbquery: query using a prepared statement + binary args **/
+static int odbc_pbquery(apr_pool_t *pool, apr_dbd_t *handle, int *nrows,
+                        apr_dbd_prepared_t *statement, const void **args)
+{
+    SQLRETURN rc = SQL_SUCCESS;
+    int i, argp;
+
+    if (odbc_check_rollback(handle))
+        return APR_EGENERAL;
+
+    for (i = argp = 0; i < statement->nargs && SQL_SUCCEEDED(rc); i++)
+        rc = odbc_bind_param(pool, statement, i + 1, statement->types[i],
+                             &argp, args, BINARYMODE);
+
+    if (SQL_SUCCEEDED(rc)) {
+        rc = SQLExecute(statement->stmt);
+        CHECK_ERROR(handle, "SQLExecute", rc, SQL_HANDLE_STMT,
+                    statement->stmt);
+    }
+    if (SQL_SUCCEEDED(rc)) {
+        SQLLEN rowcount;
+
+        rc = SQLRowCount(statement->stmt, &rowcount);
+        *nrows = (int)rowcount;
+        CHECK_ERROR(handle, "SQLRowCount", rc, SQL_HANDLE_STMT,
+                    statement->stmt);
+    }
+    return APR_FROM_SQL_RESULT(rc);
+}
+
+/** pbselect: select using a prepared statement + binary args **/
+static int odbc_pbselect(apr_pool_t *pool, apr_dbd_t *handle,
+                         apr_dbd_results_t **res,
+                         apr_dbd_prepared_t *statement,
+                         int random, const void **args)
+{
+    SQLRETURN rc = SQL_SUCCESS;
+    int i, argp;
+
+    if (odbc_check_rollback(handle))
+        return APR_EGENERAL;
+
+    if (random) {
+        rc = SQLSetStmtAttr(statement->stmt, SQL_ATTR_CURSOR_SCROLLABLE,
+                            (SQLPOINTER)SQL_SCROLLABLE, 0);
+        CHECK_ERROR(handle, "SQLSetStmtAttr (SQL_ATTR_CURSOR_SCROLLABLE)",
+                    rc, SQL_HANDLE_STMT, statement->stmt);
+    }
+    if (SQL_SUCCEEDED(rc)) {
+        for (i = argp = 0; i < statement->nargs && SQL_SUCCEEDED(rc); i++) {
+            rc = odbc_bind_param(pool, statement, i + 1, statement->types[i],
+                                 &argp, args, BINARYMODE);
+        }
+    }
+    if (SQL_SUCCEEDED(rc)) {
+        rc = SQLExecute(statement->stmt);
+        CHECK_ERROR(handle, "SQLExecute", rc, SQL_HANDLE_STMT,
+                    statement->stmt);
+    }
+    if (SQL_SUCCEEDED(rc)) {
+        rc = odbc_create_results(handle, statement->stmt, pool, random, res);
+        apr_pool_cleanup_register(pool, *res,
+                                  odbc_close_results, apr_pool_cleanup_null);
+    }
+
+    return APR_FROM_SQL_RESULT(rc);
+}
+
+/** pvbquery: query using a prepared statement + binary args **/
+static int odbc_pvbquery(apr_pool_t *pool, apr_dbd_t *handle, int *nrows,
+                         apr_dbd_prepared_t *statement, va_list args)
+{
+    const char **values;
+    int i;
+
+    values = apr_palloc(pool, sizeof(*values) * statement->nvals);
+    for (i = 0; i < statement->nvals; i++)
+        values[i] = va_arg(args, const char *);
+    return odbc_pbquery(pool, handle, nrows, statement, (const void **)values);
+}
+
+/** pvbselect: select using a prepared statement + binary args **/
+static int odbc_pvbselect(apr_pool_t *pool, apr_dbd_t *handle,
+                          apr_dbd_results_t **res,
+                          apr_dbd_prepared_t *statement,
+                          int random, va_list args)
+{
+    const char **values;
+    int i;
+
+    values = apr_palloc(pool, sizeof(*values) * statement->nvals);
+    for (i = 0; i < statement->nvals; i++)
+        values[i] = va_arg(args, const char *);
+    return odbc_pbselect(pool, handle, res, statement, random, (const void **)values);
+}
+
+APR_MODULE_DECLARE_DATA const apr_dbd_driver_t ODBC_DRIVER_ENTRY = {
+    ODBC_DRIVER_STRING,
+    odbc_init,
+    odbc_native_handle,
+    odbc_open,
+    odbc_check_conn,
+    odbc_close,
+    odbc_set_dbname,
+    odbc_start_transaction,
+    odbc_end_transaction,
+    odbc_query,
+    odbc_select,
+    odbc_num_cols,
+    odbc_num_tuples,
+    odbc_get_row,
+    odbc_get_entry,
+    odbc_error,
+    odbc_escape,
+    odbc_prepare,
+    odbc_pvquery,
+    odbc_pvselect,
+    odbc_pquery,
+    odbc_pselect,
+    odbc_get_name,
+    odbc_transaction_mode_get,
+    odbc_transaction_mode_set,
+    "?",
+    odbc_pvbquery,
+    odbc_pvbselect,
+    odbc_pbquery,
+    odbc_pbselect,
+    odbc_datum_get
+};
+
+#endif
diff --git a/dbd/apr_dbd_odbc.dsp b/dbd/apr_dbd_odbc.dsp
new file mode 100644
index 00000000000..3ea69f1a304
--- /dev/null
+++ b/dbd/apr_dbd_odbc.dsp
@@ -0,0 +1,191 @@
+# Microsoft Developer Studio Project File - Name="apr_dbd_odbc" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=apr_dbd_odbc - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "apr_dbd_odbc.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 "apr_dbd_odbc.mak" CFG="apr_dbd_odbc - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "apr_dbd_odbc - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_dbd_odbc - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_dbd_odbc - x64 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_dbd_odbc - x64 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)" == "apr_dbd_odbc - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /Zi /O2 /Oy- /I "../include" /I "../include/arch/win32" /I "../include/private" /D "NDEBUG" /D "HAVE_SQL_H" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_ODBC=1 /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbd_odbc_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /fo"Release/apr_dbd_odbc-1.res" /d DLL_NAME="apr_dbd_odbc" /d "NDEBUG" /d "APU_VERSION_ONLY" /I "../include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib odbc32.lib odbccp32.lib /nologo /base:"0x6EF00000" /subsystem:windows /dll /incremental:no /debug 
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib odbc32.lib odbccp32.lib /nologo /base:"0x6EF00000" /subsystem:windows /dll /incremental:no /debug /out:"Release\apr_dbd_odbc-1.dll" /implib:"Release\apr_dbd_odbc-1.lib" /MACHINE:X86 /opt:ref
+# Begin Special Build Tool
+TargetPath=Release\apr_dbd_odbc-1.dll
+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)" == "apr_dbd_odbc - 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 /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /EHsc /c
+# ADD CPP /nologo /MDd /W3 /Zi /Od /I "../include" /I "../include/arch/win32" /I "../include/private" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_ODBC=1 /D "HAVE_SQL_H" /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbd_odbc_src" /FD /EHsc /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /fo"Debug/apr_dbd_odbc-1.res" /d DLL_NAME="apr_dbd_odbc" /d "_DEBUG" /d "APU_VERSION_ONLY" /I "../include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib odbc32.lib odbccp32.lib /nologo /base:"0x6EF00000" /subsystem:windows /dll /incremental:no /debug 
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib odbc32.lib odbccp32.lib /nologo /base:"0x6EF00000" /subsystem:windows /dll /incremental:no /debug /out:"Debug\apr_dbd_odbc-1.dll" /implib:"Debug\apr_dbd_odbc-1.lib" /MACHINE:X86
+# Begin Special Build Tool
+TargetPath=Debug\apr_dbd_odbc-1.dll
+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)" == "apr_dbd_odbc - x64 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "x64\Release"
+# PROP BASE Intermediate_Dir "x64\Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "x64\Release"
+# PROP Intermediate_Dir "x64\Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /Zi /O2 /Oy- /I "../include" /I "../include/arch/win32" /I "../include/private" /D "NDEBUG" /D "HAVE_SQL_H" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_ODBC=1 /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbd_odbc_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /fo"x64\Release/apr_dbd_odbc-1.res" /d DLL_NAME="apr_dbd_odbc" /d "NDEBUG" /d "APU_VERSION_ONLY" /I "../include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib odbc32.lib odbccp32.lib /nologo /base:"0x6EF00000" /subsystem:windows /dll /incremental:no /debug 
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib odbc32.lib odbccp32.lib /nologo /base:"0x6EF00000" /subsystem:windows /dll /incremental:no /debug /out:"x64\Release\apr_dbd_odbc-1.dll" /implib:"x64\Release\apr_dbd_odbc-1.lib" /MACHINE:X64 /opt:ref
+# Begin Special Build Tool
+TargetPath=x64\Release\apr_dbd_odbc-1.dll
+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)" == "apr_dbd_odbc - x64 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "x64\Debug"
+# PROP BASE Intermediate_Dir "x64\Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "x64\Debug"
+# PROP Intermediate_Dir "x64\Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /EHsc /c
+# ADD CPP /nologo /MDd /W3 /Zi /Od /I "../include" /I "../include/arch/win32" /I "../include/private" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_ODBC=1 /D "HAVE_SQL_H" /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbd_odbc_src" /FD /EHsc /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /fo"x64/debug/apr_dbd_odbc-1.res" /d DLL_NAME="apr_dbd_odbc" /d "_DEBUG" /d "APU_VERSION_ONLY" /I "../include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib odbc32.lib odbccp32.lib /nologo /base:"0x6EF00000" /subsystem:windows /dll /incremental:no /debug 
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib odbc32.lib odbccp32.lib /nologo /base:"0x6EF00000" /subsystem:windows /dll /incremental:no /debug /out:"x64\Debug\apr_dbd_odbc-1.dll" /implib:"x64\Debug\apr_dbd_odbc-1.lib" /MACHINE:X64
+# Begin Special Build Tool
+TargetPath=x64\Debug\apr_dbd_odbc-1.dll
+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 "apr_dbd_odbc - Win32 Release"
+# Name "apr_dbd_odbc - Win32 Debug"
+# Name "apr_dbd_odbc - x64 Release"
+# Name "apr_dbd_odbc - x64 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\apr_dbd_odbc.c
+# End Source File
+# End Group
+# Begin Group "Public Header Files"
+
+# PROP Default_Filter ".h"
+# Begin Source File
+
+SOURCE=..\include\apr_dbd.h
+# End Source File
+# End Group
+# Begin Group "Internal Header Files"
+
+# PROP Default_Filter ".h"
+# End Group
+# End Target
+# End Project
diff --git a/dbd/apr_dbd_oracle.c b/dbd/apr_dbd_oracle.c
new file mode 100644
index 00000000000..a851e1f925c
--- /dev/null
+++ b/dbd/apr_dbd_oracle.c
@@ -0,0 +1,2221 @@
+/* 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.
+ */
+
+/* Developed initially by Nick Kew and Chris Darroch.
+ * Contributed to the APR project by kind permission of
+ * Pearson Education Core Technology Group (CTG),
+ * formerly Central Media Group (CMG).
+ */
+
+/* apr_dbd_oracle - a painful attempt
+ *
+ * Based first on the documentation at
+ * http://download-west.oracle.com/docs/cd/B10501_01/appdev.920/a96584/toc.htm
+ *
+ * Those docs have a lot of internal inconsistencies, contradictions, etc
+ * So I've snarfed the demo programs (from Oracle 8, not included in
+ * the current downloadable oracle), and used code from them.
+ *
+ * Why do cdemo81.c and cdemo82.c do the same thing in very different ways?
+ * e.g. cdemo82 releases all its handle on shutdown; cdemo81 doesn't
+ *
+ * All the ORA* functions return a "sword".  Some of them are documented;
+ * others aren't.  So I've adopted a policy of using switch statements
+ * everywhere, even when we're not doing anything with the return values.
+ *
+ * This makes no attempt at performance tuning, such as setting
+ * prefetch cache size.  We need some actual performance data
+ * to make that meaningful.  Input from someone with experience
+ * as a sysop using oracle would be a good start.
+ */
+
+/* shut compiler up */
+#ifdef DEBUG
+#define int_errorcode int errorcode
+#else
+#define int_errorcode
+#endif
+
+#include "apu.h"
+#include "apr_private.h"
+
+#if APU_HAVE_ORACLE
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <oci.h>
+
+#include "apr_strings.h"
+#include "apr_lib.h"
+#include "apr_time.h"
+#include "apr_hash.h"
+#include "apr_buckets.h"
+
+#define TRANS_TIMEOUT 30
+#define MAX_ARG_LEN 256 /* in line with other apr_dbd drivers.  We alloc this
+                         * lots of times, so a large value gets hungry.
+                         * Should really make it configurable
+                         */
+#define DEFAULT_LONG_SIZE 4096
+#define DBD_ORACLE_MAX_COLUMNS 256
+#define NUMERIC_FIELD_SIZE 32
+
+#define CHECK_CONN_QUERY "SELECT 1 FROM dual"
+
+#define ERR_BUF_SIZE 200
+
+#ifdef DEBUG
+#include <stdio.h>
+#endif
+
+#include "apr_dbd_internal.h"
+
+/* declarations */
+static const char *dbd_oracle_error(apr_dbd_t *sql, int n);
+static int dbd_oracle_prepare(apr_pool_t *pool, apr_dbd_t *sql,
+                              const char *query, const char *label,
+                              int nargs, int nvals, apr_dbd_type_e *types,
+                              apr_dbd_prepared_t **statement);
+static int outputParams(apr_dbd_t*, apr_dbd_prepared_t*);
+static int dbd_oracle_pselect(apr_pool_t *pool, apr_dbd_t *sql,
+                              apr_dbd_results_t **results,
+                              apr_dbd_prepared_t *statement,
+                              int seek, const char **values);
+static int dbd_oracle_pquery(apr_pool_t *pool, apr_dbd_t *sql,
+                             int *nrows, apr_dbd_prepared_t *statement,
+                             const char **values);
+static int dbd_oracle_start_transaction(apr_pool_t *pool, apr_dbd_t *sql,
+                                        apr_dbd_transaction_t **trans);
+static int dbd_oracle_end_transaction(apr_dbd_transaction_t *trans);
+
+struct apr_dbd_transaction_t {
+    int mode;
+    enum { TRANS_NONE, TRANS_ERROR, TRANS_1, TRANS_2 } status;
+    apr_dbd_t *handle;
+    OCITrans *trans;
+    OCISnapshot *snapshot1;
+    OCISnapshot *snapshot2;
+};
+
+struct apr_dbd_results_t {
+    apr_pool_t *pool;
+    apr_dbd_t* handle;
+    unsigned int rownum;
+    int seek;
+    int nrows;
+    apr_dbd_prepared_t *statement;
+};
+
+struct apr_dbd_t {
+    sword status;
+    OCIError *err;
+    OCIServer *svr;
+    OCISvcCtx *svc;
+    OCISession *auth;
+    apr_dbd_transaction_t* trans;
+    apr_pool_t *pool;
+    char buf[ERR_BUF_SIZE]; /* for error messages */
+    apr_size_t long_size;
+    apr_dbd_prepared_t *check_conn_stmt;
+};
+
+struct apr_dbd_row_t {
+    int n;
+    apr_dbd_results_t *res;
+    apr_pool_t *pool;
+};
+
+typedef struct {
+    apr_dbd_type_e type;
+    sb2 ind;
+    sb4 len;
+    OCIBind *bind;
+    union {
+        void *raw;
+        char *sval;
+        int ival;
+        unsigned int uval;
+        double fval;
+        OCILobLocator *lobval;
+    } value;
+} bind_arg;
+
+typedef struct {
+    int type;
+    sb2 ind;
+    ub2 len;         /* length of actual output */
+    OCIDefine *defn;
+    apr_size_t sz;   /* length of buf for output */
+    union {
+        void *raw;
+        char *sval;
+        OCILobLocator *lobval;
+    } buf;
+    const char *name;
+} define_arg;
+
+struct apr_dbd_prepared_t {
+    OCIStmt *stmt;
+    int nargs;
+    int nvals;
+    bind_arg *args;
+    int nout;
+    define_arg *out;
+    apr_dbd_t *handle;
+    apr_pool_t *pool;
+    ub2 type;
+};
+
+/* AFAICT from the docs, the OCIEnv thingey can be used async
+ * across threads, so lets have a global one.
+ *
+ * We'll need shorter-lived envs to deal with requests and connections
+ *
+ * Hmmm, that doesn't work: we don't have a usermem framework.
+ * OK, forget about using APR pools here, until we figure out
+ * the right way to do it (if such a thing exists).
+ */
+static OCIEnv *dbd_oracle_env = NULL;
+
+/* Oracle specific bucket for BLOB/CLOB types */
+typedef struct apr_bucket_lob apr_bucket_lob;
+/**
+ * A bucket referring to a Oracle BLOB/CLOB
+ */
+struct apr_bucket_lob {
+    /** Number of buckets using this memory */
+    apr_bucket_refcount  refcount;
+    /** The row this bucket refers to */
+    const apr_dbd_row_t *row;
+    /** The column this bucket refers to */
+    int col;
+    /** The pool into which any needed structures should
+     *  be created while reading from this bucket */
+    apr_pool_t *readpool;
+};
+
+static void lob_bucket_destroy(void *data);
+static apr_status_t lob_bucket_read(apr_bucket *e, const char **str,
+                                    apr_size_t *len, apr_read_type_e block);
+static apr_bucket *apr_bucket_lob_make(apr_bucket *b,
+                                       const apr_dbd_row_t *row, int col,
+                                       apr_off_t offset, apr_size_t len,
+                                       apr_pool_t *p);
+static apr_bucket *apr_bucket_lob_create(const apr_dbd_row_t *row, int col,
+                                         apr_off_t offset,
+                                         apr_size_t len, apr_pool_t *p,
+                                         apr_bucket_alloc_t *list);
+
+static const apr_bucket_type_t apr_bucket_type_lob = {
+    "LOB", 5, APR_BUCKET_DATA,
+    lob_bucket_destroy,
+    lob_bucket_read,
+    apr_bucket_setaside_notimpl,
+    apr_bucket_shared_split,
+    apr_bucket_shared_copy
+};
+
+static void lob_bucket_destroy(void *data)
+{
+    apr_bucket_lob *f = data;
+
+    if (apr_bucket_shared_destroy(f)) {
+        /* no need to destroy database objects here; it will get
+         * done automatically when the pool gets cleaned up */
+        apr_bucket_free(f);
+    }
+}
+
+static apr_status_t lob_bucket_read(apr_bucket *e, const char **str,
+                                    apr_size_t *len, apr_read_type_e block)
+{
+    apr_bucket_lob *a = e->data;
+    const apr_dbd_row_t *row = a->row;
+    apr_dbd_results_t *res = row->res;
+    int col = a->col;
+    apr_bucket *b = NULL;
+    apr_size_t blength = e->length;  /* bytes remaining in file past offset */
+    apr_off_t boffset = e->start;
+    define_arg *val = &res->statement->out[col];
+    apr_dbd_t *sql = res->handle;
+/* Only with 10g, unfortunately
+    oraub8 length = APR_BUCKET_BUFF_SIZE;
+*/
+    ub4 length = APR_BUCKET_BUFF_SIZE;
+    char *buf = NULL;
+
+    *str = NULL;  /* in case we die prematurely */
+
+    /* fetch from offset if not at the beginning */
+    buf = apr_palloc(row->pool, APR_BUCKET_BUFF_SIZE);
+    sql->status = OCILobRead(sql->svc, sql->err, val->buf.lobval,
+                             &length, 1 + (size_t)boffset,
+                             (dvoid*) buf, APR_BUCKET_BUFF_SIZE,
+                             NULL, NULL, 0, SQLCS_IMPLICIT);
+/* Only with 10g, unfortunately
+    sql->status = OCILobRead2(sql->svc, sql->err, val->buf.lobval,
+                              &length, NULL, 1 + boffset,
+                              (dvoid*) buf, APR_BUCKET_BUFF_SIZE,
+                              OCI_ONE_PIECE, NULL, NULL, 0, SQLCS_IMPLICIT);
+*/
+    if (sql->status != OCI_SUCCESS) {
+        return APR_EGENERAL;
+    }
+    blength -= length;
+    *len = length;
+    *str = buf;
+
+    /*
+     * Change the current bucket to refer to what we read,
+     * even if we read nothing because we hit EOF.
+     */
+    apr_bucket_pool_make(e, *str, *len, res->pool);
+
+    /* If we have more to read from the field, then create another bucket */
+    if (blength > 0) {
+        /* for efficiency, we can just build a new apr_bucket struct
+         * to wrap around the existing LOB bucket */
+        b = apr_bucket_alloc(sizeof(*b), e->list);
+        b->start  = boffset + *len;
+        b->length = blength;
+        b->data   = a;
+        b->type   = &apr_bucket_type_lob;
+        b->free   = apr_bucket_free;
+        b->list   = e->list;
+        APR_BUCKET_INSERT_AFTER(e, b);
+    }
+    else {
+        lob_bucket_destroy(a);
+    }
+
+    return APR_SUCCESS;
+}
+
+static apr_bucket *apr_bucket_lob_make(apr_bucket *b,
+                                       const apr_dbd_row_t *row, int col,
+                                       apr_off_t offset, apr_size_t len,
+                                       apr_pool_t *p)
+{
+    apr_bucket_lob *f;
+
+    f = apr_bucket_alloc(sizeof(*f), b->list);
+    f->row = row;
+    f->col = col;
+    f->readpool = p;
+
+    b = apr_bucket_shared_make(b, f, offset, len);
+    b->type = &apr_bucket_type_lob;
+
+    return b;
+}
+
+static apr_bucket *apr_bucket_lob_create(const apr_dbd_row_t *row, int col,
+                                         apr_off_t offset,
+                                         apr_size_t len, apr_pool_t *p,
+                                         apr_bucket_alloc_t *list)
+{
+    apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
+
+    APR_BUCKET_INIT(b);
+    b->free = apr_bucket_free;
+    b->list = list;
+    return apr_bucket_lob_make(b, row, col, offset, len, p);
+}
+
+static apr_status_t dbd_free_lobdesc(void *lob)
+{
+    switch (OCIDescriptorFree(lob, OCI_DTYPE_LOB)) {
+    case OCI_SUCCESS:
+        return APR_SUCCESS;
+    default:
+        return APR_EGENERAL;
+    }
+}
+
+static apr_status_t dbd_free_snapshot(void *snap)
+{
+    switch (OCIDescriptorFree(snap, OCI_DTYPE_SNAP)) {
+    case OCI_SUCCESS:
+        return APR_SUCCESS;
+    default:
+        return APR_EGENERAL;
+    }
+}
+
+static void dbd_oracle_init(apr_pool_t *pool)
+{
+    if (dbd_oracle_env == NULL) {
+        /* Sadly, OCI_SHARED seems to be impossible to use, due to
+         * various Oracle bugs.  See, for example, Oracle MetaLink bug 2972890
+         * and PHP bug http://bugs.php.net/bug.php?id=23733
+         */
+#ifdef OCI_NEW_LENGTH_SEMANTICS
+        OCIEnvCreate(&dbd_oracle_env, OCI_THREADED|OCI_NEW_LENGTH_SEMANTICS,
+                     NULL, NULL, NULL, NULL, 0, NULL);
+#else
+        OCIEnvCreate(&dbd_oracle_env, OCI_THREADED,
+                     NULL, NULL, NULL, NULL, 0, NULL);
+#endif
+    }
+}
+
+static apr_dbd_t *dbd_oracle_open(apr_pool_t *pool, const char *params,
+                                  const char **error)
+{
+    apr_dbd_t *ret = apr_pcalloc(pool, sizeof(apr_dbd_t));
+    int errorcode;
+
+    char *BLANK = "";
+    struct {
+        const char *field;
+        char *value;
+    } fields[] = {
+        {"user", BLANK},
+        {"pass", BLANK},
+        {"dbname", BLANK},
+        {"server", BLANK},
+        {NULL, NULL}
+    };
+    int i;
+    const char *ptr;
+    const char *key;
+    size_t klen;
+    const char *value;
+    size_t vlen;
+    static const char *const delims = " \r\n\t;|,";
+
+    ret->pool = pool;
+    ret->long_size = DEFAULT_LONG_SIZE;
+
+    /* snitch parsing from the MySQL driver */
+    for (ptr = strchr(params, '='); ptr; ptr = strchr(ptr, '=')) {
+        /* don't dereference memory that may not belong to us */
+        if (ptr == params) {
+            ++ptr;
+            continue;
+        }
+        for (key = ptr-1; apr_isspace(*key); --key);
+        klen = 0;
+        while (apr_isalpha(*key)) {
+            if (key == params) {
+                /* Don't parse off the front of the params */
+                --key;
+                ++klen;
+                break;
+            }
+            --key;
+            ++klen;
+        }
+        ++key;
+        for (value = ptr+1; apr_isspace(*value); ++value);
+        vlen = strcspn(value, delims);
+        for (i=0; fields[i].field != NULL; ++i) {
+            if (!strncasecmp(fields[i].field, key, klen)) {
+                fields[i].value = apr_pstrndup(pool, value, vlen);
+                break;
+            }
+        }
+        ptr = value+vlen;
+    }
+
+    ret->status = OCIHandleAlloc(dbd_oracle_env, (dvoid**)&ret->err,
+                                 OCI_HTYPE_ERROR, 0, NULL);
+    switch (ret->status) {
+    default:
+#ifdef DEBUG
+        printf("ret->status is %d\n", ret->status);
+        break;
+#else
+        return NULL;
+#endif
+    case OCI_SUCCESS:
+        break;
+    }
+
+    ret->status = OCIHandleAlloc(dbd_oracle_env, (dvoid**)&ret->svr,
+                                 OCI_HTYPE_SERVER, 0, NULL);
+    switch (ret->status) {
+    default:
+#ifdef DEBUG
+        OCIErrorGet(ret->err, 1, NULL, &errorcode, ret->buf,
+                    sizeof(ret->buf), OCI_HTYPE_ERROR);
+        printf("OPEN ERROR %d (alloc svr): %s\n", ret->status, ret->buf);
+        break;
+#else
+        if (error) {
+            *error = apr_pcalloc(pool, ERR_BUF_SIZE);
+            OCIErrorGet(ret->err, 1, NULL, &errorcode, (unsigned char*)(*error),
+                        ERR_BUF_SIZE, OCI_HTYPE_ERROR);
+        }
+        return NULL;
+#endif
+    case OCI_SUCCESS:
+        break;
+    }
+
+    ret->status = OCIHandleAlloc(dbd_oracle_env, (dvoid**)&ret->svc,
+                                 OCI_HTYPE_SVCCTX, 0, NULL);
+    switch (ret->status) {
+    default:
+#ifdef DEBUG
+        OCIErrorGet(ret->err, 1, NULL, &errorcode, ret->buf,
+                    sizeof(ret->buf), OCI_HTYPE_ERROR);
+        printf("OPEN ERROR %d (alloc svc): %s\n", ret->status, ret->buf);
+        break;
+#else
+        if (error) {
+            *error = apr_pcalloc(pool, ERR_BUF_SIZE);
+            OCIErrorGet(ret->err, 1, NULL, &errorcode, (unsigned char*)(*error),
+                        ERR_BUF_SIZE, OCI_HTYPE_ERROR);
+        }
+        return NULL;
+#endif
+    case OCI_SUCCESS:
+        break;
+    }
+
+/* All the examples use the #else */
+#if CAN_DO_LOGIN
+    ret->status = OCILogon(dbd_oracle_env, ret->err, &ret->svc, fields[0].value,
+                     strlen(fields[0].value), fields[1].value,
+                     strlen(fields[1].value), fields[2].value,
+                     strlen(fields[2].value));
+    switch (ret->status) {
+    default:
+#ifdef DEBUG
+        OCIErrorGet(ret->err, 1, NULL, &errorcode, ret->buf,
+                    sizeof(ret->buf), OCI_HTYPE_ERROR);
+        printf("OPEN ERROR: %s\n", ret->buf);
+        break;
+#else
+        if (error) {
+            *error = apr_pcalloc(pool, ERR_BUF_SIZE);
+            OCIErrorGet(ret->err, 1, NULL, &errorcode, (unsigned char*)(*error),
+                        ERR_BUF_SIZE, OCI_HTYPE_ERROR);
+        }
+        return NULL;
+#endif
+    case OCI_SUCCESS:
+        break;
+    }
+#else
+    ret->status = OCIServerAttach(ret->svr, ret->err, (text*) fields[3].value,
+                                  strlen(fields[3].value), OCI_DEFAULT);
+    switch (ret->status) {
+    default:
+#ifdef DEBUG
+        OCIErrorGet(ret->err, 1, NULL, &errorcode, ret->buf,
+                    sizeof(ret->buf), OCI_HTYPE_ERROR);
+        printf("OPEN ERROR %d (server attach): %s\n", ret->status, ret->buf);
+        break;
+#else
+        if (error) {
+            *error = apr_pcalloc(pool, ERR_BUF_SIZE);
+            OCIErrorGet(ret->err, 1, NULL, &errorcode, (unsigned char*)(*error),
+                        ERR_BUF_SIZE, OCI_HTYPE_ERROR);
+        }
+        return NULL;
+#endif
+    case OCI_SUCCESS:
+        break;
+    }
+    ret->status = OCIAttrSet(ret->svc, OCI_HTYPE_SVCCTX, ret->svr, 0,
+                        OCI_ATTR_SERVER, ret->err);
+    switch (ret->status) {
+    default:
+#ifdef DEBUG
+        OCIErrorGet(ret->err, 1, NULL, &errorcode, ret->buf,
+                    sizeof(ret->buf), OCI_HTYPE_ERROR);
+        printf("OPEN ERROR %d (attr set): %s\n", ret->status, ret->buf);
+        break;
+#else
+        if (error) {
+            *error = apr_pcalloc(pool, ERR_BUF_SIZE);
+            OCIErrorGet(ret->err, 1, NULL, &errorcode, (unsigned char*)(*error),
+                        ERR_BUF_SIZE, OCI_HTYPE_ERROR);
+        }
+        return NULL;
+#endif
+    case OCI_SUCCESS:
+        break;
+    }
+    ret->status = OCIHandleAlloc(dbd_oracle_env, (dvoid**)&ret->auth,
+                            OCI_HTYPE_SESSION, 0, NULL);
+    switch (ret->status) {
+    default:
+#ifdef DEBUG
+        OCIErrorGet(ret->err, 1, NULL, &errorcode, ret->buf,
+                    sizeof(ret->buf), OCI_HTYPE_ERROR);
+        printf("OPEN ERROR %d (alloc auth): %s\n", ret->status, ret->buf);
+        break;
+#else
+        if (error) {
+            *error = apr_pcalloc(pool, ERR_BUF_SIZE);
+            OCIErrorGet(ret->err, 1, NULL, &errorcode, (unsigned char*)(*error),
+                        ERR_BUF_SIZE, OCI_HTYPE_ERROR);
+        }
+        return NULL;
+#endif
+    case OCI_SUCCESS:
+        break;
+    }
+    ret->status = OCIAttrSet(ret->auth, OCI_HTYPE_SESSION, fields[0].value,
+                        strlen(fields[0].value), OCI_ATTR_USERNAME, ret->err);
+    switch (ret->status) {
+    default:
+#ifdef DEBUG
+        OCIErrorGet(ret->err, 1, NULL, &errorcode, ret->buf,
+                    sizeof(ret->buf), OCI_HTYPE_ERROR);
+        printf("OPEN ERROR %d (attr username): %s\n", ret->status, ret->buf);
+        break;
+#else
+        if (error) {
+            *error = apr_pcalloc(pool, ERR_BUF_SIZE);
+            OCIErrorGet(ret->err, 1, NULL, &errorcode, (unsigned char*)(*error),
+                        ERR_BUF_SIZE, OCI_HTYPE_ERROR);
+        }
+        return NULL;
+#endif
+    case OCI_SUCCESS:
+        break;
+    }
+    ret->status = OCIAttrSet(ret->auth, OCI_HTYPE_SESSION, fields[1].value,
+                        strlen(fields[1].value), OCI_ATTR_PASSWORD, ret->err);
+    switch (ret->status) {
+    default:
+#ifdef DEBUG
+        OCIErrorGet(ret->err, 1, NULL, &errorcode, ret->buf,
+                    sizeof(ret->buf), OCI_HTYPE_ERROR);
+        printf("OPEN ERROR %d (attr password): %s\n", ret->status, ret->buf);
+        break;
+#else
+        if (error) {
+            *error = apr_pcalloc(pool, ERR_BUF_SIZE);
+            OCIErrorGet(ret->err, 1, NULL, &errorcode, (unsigned char*)(*error),
+                        ERR_BUF_SIZE, OCI_HTYPE_ERROR);
+        }
+        return NULL;
+#endif
+    case OCI_SUCCESS:
+        break;
+    }
+    ret->status = OCISessionBegin(ret->svc, ret->err, ret->auth,
+                             OCI_CRED_RDBMS, OCI_DEFAULT);
+    switch (ret->status) {
+    default:
+#ifdef DEBUG
+        OCIErrorGet(ret->err, 1, NULL, &errorcode, ret->buf,
+                    sizeof(ret->buf), OCI_HTYPE_ERROR);
+        printf("OPEN ERROR %d (session begin): %s\n", ret->status, ret->buf);
+        break;
+#else
+        if (error) {
+            *error = apr_pcalloc(pool, ERR_BUF_SIZE);
+            OCIErrorGet(ret->err, 1, NULL, &errorcode, (unsigned char*)(*error),
+                        ERR_BUF_SIZE, OCI_HTYPE_ERROR);
+        }
+        return NULL;
+#endif
+    case OCI_SUCCESS:
+        break;
+    }
+    ret->status = OCIAttrSet(ret->svc, OCI_HTYPE_SVCCTX, ret->auth, 0,
+                        OCI_ATTR_SESSION, ret->err);
+    switch (ret->status) {
+    default:
+#ifdef DEBUG
+        OCIErrorGet(ret->err, 1, NULL, &errorcode, ret->buf,
+                    sizeof(ret->buf), OCI_HTYPE_ERROR);
+        printf("OPEN ERROR %d (attr session): %s\n", ret->status, ret->buf);
+#else
+        if (error) {
+            *error = apr_pcalloc(pool, ERR_BUF_SIZE);
+            OCIErrorGet(ret->err, 1, NULL, &errorcode, (unsigned char*)(*error),
+                        ERR_BUF_SIZE, OCI_HTYPE_ERROR);
+        }
+        return NULL;
+#endif
+        break;
+    case OCI_SUCCESS:
+        break;
+    }
+#endif
+
+    if(dbd_oracle_prepare(pool, ret, CHECK_CONN_QUERY, NULL, 0, 0, NULL,
+                          &ret->check_conn_stmt) != 0) {
+        return NULL;
+    }
+
+    return ret;
+}
+
+#ifdef EXPORT_NATIVE_FUNCS
+static apr_size_t dbd_oracle_long_size_set(apr_dbd_t *sql,
+                                           apr_size_t long_size)
+{
+    apr_size_t old_size = sql->long_size;
+    sql->long_size = long_size;
+    return old_size;
+}
+#endif
+
+static const char *dbd_oracle_get_name(const apr_dbd_results_t *res, int n)
+{
+    define_arg *val = &res->statement->out[n];
+
+    if ((n < 0) || (n >= res->statement->nout)) {
+        return NULL;
+    }
+    return val->name;
+}
+
+static int dbd_oracle_get_row(apr_pool_t *pool, apr_dbd_results_t *res,
+                              apr_dbd_row_t **rowp, int rownum)
+{
+    apr_dbd_row_t *row = *rowp;
+    apr_dbd_t *sql = res->handle;
+    int_errorcode;
+
+    if (row == NULL) {
+        row = apr_palloc(pool, sizeof(apr_dbd_row_t));
+        *rowp = row;
+        row->res = res;
+        /* Oracle starts counting at 1 according to the docs */
+        row->n = res->seek ? rownum : 1;
+        row->pool = pool;
+    }
+    else {
+        if (res->seek) {
+            row->n = rownum;
+        }
+        else {
+            ++row->n;
+        }
+    }
+
+    if (res->seek) {
+        sql->status = OCIStmtFetch2(res->statement->stmt, res->handle->err, 1,
+                                    OCI_FETCH_ABSOLUTE, row->n, OCI_DEFAULT);
+    }
+    else {
+        sql->status = OCIStmtFetch2(res->statement->stmt, res->handle->err, 1,
+                                    OCI_FETCH_NEXT, 0, OCI_DEFAULT);
+    }
+    switch (sql->status) {
+    case OCI_SUCCESS:
+        (*rowp)->res = res;
+        return 0;
+    case OCI_NO_DATA:
+        return -1;
+    case OCI_ERROR:
+#ifdef DEBUG
+        OCIErrorGet(sql->err, 1, NULL, &errorcode,
+                    sql->buf, sizeof(sql->buf), OCI_HTYPE_ERROR);
+        printf("Execute error %d: %s\n", sql->status, sql->buf);
+#endif
+        /* fallthrough */
+    default:
+        return 1;
+    }
+    return 0;
+}
+
+static const char *dbd_oracle_error(apr_dbd_t *sql, int n)
+{
+    /* This is ugly.  Needs us to pass in a buffer of unknown size.
+     * Either we put it on the handle, or we have to keep allocing/copying
+     */
+    sb4 errorcode;
+
+    switch (sql->status) {
+    case OCI_SUCCESS:
+        return "OCI_SUCCESS";
+    case OCI_SUCCESS_WITH_INFO:
+        return "OCI_SUCCESS_WITH_INFO";
+    case OCI_NEED_DATA:
+        return "OCI_NEED_DATA";
+    case OCI_NO_DATA:
+        return "OCI_NO_DATA";
+    case OCI_INVALID_HANDLE:
+        return "OCI_INVALID_HANDLE";
+    case OCI_STILL_EXECUTING:
+        return "OCI_STILL_EXECUTING";
+    case OCI_CONTINUE:
+        return "OCI_CONTINUE";
+    }
+
+    switch (OCIErrorGet(sql->err, 1, NULL, &errorcode,
+                        (text*) sql->buf, sizeof(sql->buf), OCI_HTYPE_ERROR)) {
+    case OCI_SUCCESS:
+        return sql->buf; 
+    default:
+        return "internal error: OCIErrorGet failed";
+    }
+}
+
+static apr_status_t freeStatement(void *statement)
+{
+    int rv = APR_SUCCESS;
+    OCIStmt *stmt = ((apr_dbd_prepared_t*)statement)->stmt;
+
+#ifdef PREPARE2
+    OCIError *err;
+
+    if (OCIHandleAlloc(dbd_oracle_env, (dvoid**)&err, OCI_HTYPE_ERROR,
+                       0, NULL) != OCI_SUCCESS) {
+        return APR_EGENERAL;
+    }
+    if (OCIStmtRelease(stmt, err, NULL, 0, OCI_DEFAULT) != OCI_SUCCESS) {
+        rv = APR_EGENERAL;
+    }
+    if (OCIHandleFree(err, OCI_HTYPE_ERROR) != OCI_SUCCESS) {
+        rv = APR_EGENERAL;
+    }
+#else
+    if (OCIHandleFree(stmt, OCI_HTYPE_STMT) != OCI_SUCCESS) {
+        rv = APR_EGENERAL;
+    }
+#endif
+
+    return rv;
+}
+
+static int dbd_oracle_select(apr_pool_t *pool, apr_dbd_t *sql,
+                             apr_dbd_results_t **results,
+                             const char *query, int seek)
+{
+    int ret = 0;
+    apr_dbd_prepared_t *statement = NULL;
+
+    ret = dbd_oracle_prepare(pool, sql, query, NULL, 0, 0, NULL, &statement);
+    if (ret != 0) {
+        return ret;
+    }
+
+    ret = dbd_oracle_pselect(pool, sql, results, statement, seek, NULL);
+    if (ret != 0) {
+        return ret;
+    }
+
+    return ret;
+}
+
+static int dbd_oracle_query(apr_dbd_t *sql, int *nrows, const char *query)
+{
+    int ret = 0;
+    apr_pool_t *pool;
+    apr_dbd_prepared_t *statement = NULL;
+
+    if (sql->trans && sql->trans->status == TRANS_ERROR) {
+        return 1;
+    }
+
+    /* make our own pool so that APR allocations don't linger and so that
+     * both Stmt and LOB handles are cleaned up (LOB handles may be
+     * allocated when preparing APR_DBD_TYPE_CLOB/BLOBs)
+     */
+    apr_pool_create(&pool, sql->pool);
+
+    ret = dbd_oracle_prepare(pool, sql, query, NULL, 0, 0, NULL, &statement);
+    if (ret == 0) {
+        ret = dbd_oracle_pquery(pool, sql, nrows, statement, NULL);
+        if (ret == 0) {
+            sql->status = OCIAttrGet(statement->stmt, OCI_HTYPE_STMT,
+                                     nrows, 0, OCI_ATTR_ROW_COUNT,
+                                     sql->err);
+        }
+    }
+
+    apr_pool_destroy(pool);
+
+    return ret;
+}
+
+static const char *dbd_oracle_escape(apr_pool_t *pool, const char *arg,
+                                     apr_dbd_t *sql)
+{
+    return arg;        /* OCI has no concept of string escape */
+}
+
+static int dbd_oracle_prepare(apr_pool_t *pool, apr_dbd_t *sql,
+                              const char *query, const char *label,
+                              int nargs, int nvals, apr_dbd_type_e *types,
+                              apr_dbd_prepared_t **statement)
+{
+    int ret = 0;
+    int i;
+    apr_dbd_prepared_t *stmt ;
+
+    if (*statement == NULL) {
+        *statement = apr_pcalloc(pool, sizeof(apr_dbd_prepared_t));
+    }
+    stmt = *statement;
+    stmt->handle = sql;
+    stmt->pool = pool;
+    stmt->nargs = nargs;
+    stmt->nvals = nvals;
+
+    /* populate our own args, if any */
+    if (nargs > 0) {
+        stmt->args = apr_pcalloc(pool, nargs*sizeof(bind_arg));
+        for (i = 0; i < nargs; i++) {
+            stmt->args[i].type = types[i];
+        }
+    }
+
+    sql->status = OCIHandleAlloc(dbd_oracle_env, (dvoid**) &stmt->stmt,
+                                 OCI_HTYPE_STMT, 0, NULL);
+    if (sql->status != OCI_SUCCESS) {
+        return 1;
+    }
+
+    sql->status = OCIStmtPrepare(stmt->stmt, sql->err, (text*) query,
+                                 strlen(query), OCI_NTV_SYNTAX, OCI_DEFAULT);
+    if (sql->status != OCI_SUCCESS) {
+        OCIHandleFree(stmt->stmt, OCI_HTYPE_STMT);
+        return 1;
+    }
+
+    apr_pool_cleanup_register(pool, stmt, freeStatement,
+                              apr_pool_cleanup_null);
+
+    /* Perl gets statement type here */
+    sql->status = OCIAttrGet(stmt->stmt, OCI_HTYPE_STMT, &stmt->type, 0,
+                             OCI_ATTR_STMT_TYPE, sql->err);
+    if (sql->status != OCI_SUCCESS) {
+        return 1;
+    }
+
+/* Perl sets PREFETCH_MEMORY here, but the docs say there's a working default */
+#if 0
+    sql->status = OCIAttrSet(stmt->stmt, OCI_HTYPE_STMT, &prefetch_size,
+                             sizeof(prefetch_size), OCI_ATTR_PREFETCH_MEMORY,
+                             sql->err);
+    if (sql->status != OCI_SUCCESS) {
+        return 1;
+    }
+#endif
+
+    if (stmt->type == OCI_STMT_SELECT) {
+        ret = outputParams(sql, stmt);
+    }
+    return ret;
+}
+
+static void dbd_oracle_bind(apr_dbd_prepared_t *statement, const char **values)
+{
+    OCIStmt *stmt = statement->stmt;
+    apr_dbd_t *sql = statement->handle;
+    int i, j;
+    sb2 null_ind = -1;
+
+    for (i = 0, j = 0; i < statement->nargs; i++, j++) {
+        if (values[j] == NULL) {
+            sql->status = OCIBindByPos(stmt, &statement->args[i].bind,
+                                       sql->err, i + 1,
+                                       NULL, 0, SQLT_STR,
+                                       &null_ind, NULL,
+                                       (ub2) 0, (ub4) 0,
+                                       (ub4 *) 0, OCI_DEFAULT);
+        }
+        else {
+            switch (statement->args[i].type) {
+            case APR_DBD_TYPE_BLOB:
+                {
+                char *data = (char *)values[j];
+                int size = atoi((char*)values[++j]);
+
+                /* skip table and column for now */
+                j += 2;
+
+                sql->status = OCIBindByPos(stmt, &statement->args[i].bind,
+                                           sql->err, i + 1,
+                                           data, size, SQLT_LBI,
+                                           &statement->args[i].ind,
+                                           NULL,
+                                           (ub2) 0, (ub4) 0,
+                                           (ub4 *) 0, OCI_DEFAULT);
+                }
+                break;
+            case APR_DBD_TYPE_CLOB:
+                {
+                char *data = (char *)values[j];
+                int size = atoi((char*)values[++j]);
+
+                /* skip table and column for now */
+                j += 2;
+
+                sql->status = OCIBindByPos(stmt, &statement->args[i].bind,
+                                           sql->err, i + 1,
+                                           data, size, SQLT_LNG,
+                                           &statement->args[i].ind,
+                                           NULL,
+                                           (ub2) 0, (ub4) 0,
+                                           (ub4 *) 0, OCI_DEFAULT);
+                }
+                break;
+            default:
+                sql->status = OCIBindByPos(stmt, &statement->args[i].bind,
+                                           sql->err, i + 1,
+                                           (dvoid*) values[j],
+                                           strlen(values[j]) + 1,
+                                           SQLT_STR,
+                                           &statement->args[i].ind,
+                                           NULL,
+                                           (ub2) 0, (ub4) 0,
+                                           (ub4 *) 0, OCI_DEFAULT);
+                break;
+            }
+        }
+
+        if (sql->status != OCI_SUCCESS) {
+            return;
+        }
+    }
+
+    return;
+}
+
+static int outputParams(apr_dbd_t *sql, apr_dbd_prepared_t *stmt)
+{
+    OCIParam *parms;
+    int i;
+    ub2 paramtype[DBD_ORACLE_MAX_COLUMNS];
+    ub2 paramsize[DBD_ORACLE_MAX_COLUMNS];
+    char *paramname[DBD_ORACLE_MAX_COLUMNS];
+    ub4 paramnamelen[DBD_ORACLE_MAX_COLUMNS];
+    int_errorcode;
+
+    /* Perl uses 0 where we used 1 */
+    sql->status = OCIStmtExecute(sql->svc, stmt->stmt, sql->err, 0, 0,
+                                 NULL, NULL, OCI_DESCRIBE_ONLY);
+    switch (sql->status) {
+    case OCI_SUCCESS:
+    case OCI_SUCCESS_WITH_INFO:
+        break;
+    case OCI_ERROR:
+#ifdef DEBUG
+        OCIErrorGet(sql->err, 1, NULL, &errorcode,
+                    sql->buf, sizeof(sql->buf), OCI_HTYPE_ERROR);
+        printf("Describing prepared statement: %s\n", sql->buf);
+#endif
+    default:
+        return 1;
+    }
+    while (sql->status == OCI_SUCCESS) {
+        sql->status = OCIParamGet(stmt->stmt, OCI_HTYPE_STMT,
+                                  sql->err, (dvoid**)&parms, stmt->nout+1);
+        switch (sql->status) {
+        case OCI_SUCCESS:
+            sql->status = OCIAttrGet(parms, OCI_DTYPE_PARAM,
+                                     &paramtype[stmt->nout],
+                                     0, OCI_ATTR_DATA_TYPE, sql->err);
+            sql->status = OCIAttrGet(parms, OCI_DTYPE_PARAM,
+                                     &paramsize[stmt->nout],
+                                     0, OCI_ATTR_DATA_SIZE, sql->err);
+            sql->status = OCIAttrGet(parms, OCI_DTYPE_PARAM,
+                                     &paramname[stmt->nout],
+                                     &paramnamelen[stmt->nout],
+                                     OCI_ATTR_NAME, sql->err);
+            ++stmt->nout;
+        }
+    }
+    switch (sql->status) {
+    case OCI_SUCCESS:
+        break;
+    case OCI_ERROR:
+        break;        /* this is what we expect at end-of-loop */
+    default:
+        return 1;
+    }
+
+    /* OK, the above works.  We have the params; now OCIDefine them */
+    stmt->out = apr_palloc(stmt->pool, stmt->nout*sizeof(define_arg));
+    for (i=0; i<stmt->nout; ++i) {
+        stmt->out[i].type = paramtype[i];
+        stmt->out[i].len = stmt->out[i].sz = paramsize[i];
+        stmt->out[i].name = apr_pstrmemdup(stmt->pool,
+                                           paramname[i], paramnamelen[i]);
+        switch (stmt->out[i].type) {
+        default:
+            switch (stmt->out[i].type) {
+            case SQLT_NUM:           /* 2: numeric, Perl worst case=130+38+3 */
+                stmt->out[i].sz = 171;
+                break;
+            case SQLT_CHR:           /* 1: char */
+            case SQLT_AFC:           /* 96: ANSI fixed char */
+                stmt->out[i].sz *= 4; /* ugh, wasteful UCS-4 handling */
+                break;
+            case SQLT_DAT:           /* 12: date, depends on NLS date format */
+                stmt->out[i].sz = 75;
+                break;
+            case SQLT_BIN:           /* 23: raw binary, perhaps UTF-16? */
+                stmt->out[i].sz *= 2;
+                break;
+            case SQLT_RID:           /* 11: rowid */
+            case SQLT_RDD:           /* 104: rowid descriptor */
+                stmt->out[i].sz = 20;
+                break;
+            case SQLT_TIMESTAMP:     /* 187: timestamp */
+            case SQLT_TIMESTAMP_TZ:  /* 188: timestamp with time zone */
+            case SQLT_INTERVAL_YM:   /* 189: interval year-to-month */
+            case SQLT_INTERVAL_DS:   /* 190: interval day-to-second */
+            case SQLT_TIMESTAMP_LTZ: /* 232: timestamp with local time zone */
+                stmt->out[i].sz = 75;
+                break;
+            default:
+#ifdef DEBUG
+                printf("Unsupported data type: %d\n", stmt->out[i].type);
+#endif
+                break;
+            }
+            ++stmt->out[i].sz;
+            stmt->out[i].buf.raw = apr_palloc(stmt->pool, stmt->out[i].sz);
+            sql->status = OCIDefineByPos(stmt->stmt, &stmt->out[i].defn,
+                                         sql->err, i+1,
+                                         stmt->out[i].buf.sval,
+                                         stmt->out[i].sz, SQLT_STR,
+                                         &stmt->out[i].ind, &stmt->out[i].len,
+                                         0, OCI_DEFAULT);
+            break;
+        case SQLT_LNG: /* 8: long */
+            stmt->out[i].sz = sql->long_size * 4 + 4; /* ugh, UCS-4 handling */
+            stmt->out[i].buf.raw = apr_palloc(stmt->pool, stmt->out[i].sz);
+            sql->status = OCIDefineByPos(stmt->stmt, &stmt->out[i].defn,
+                                         sql->err, i+1,
+                                         stmt->out[i].buf.raw,
+                                         stmt->out[i].sz, SQLT_LVC,
+                                         &stmt->out[i].ind, NULL,
+                                         0, OCI_DEFAULT);
+            break;
+        case SQLT_LBI: /* 24: long binary, perhaps UTF-16? */
+            stmt->out[i].sz = sql->long_size * 2 + 4; /* room for int prefix */
+            stmt->out[i].buf.raw = apr_palloc(stmt->pool, stmt->out[i].sz);
+            sql->status = OCIDefineByPos(stmt->stmt, &stmt->out[i].defn,
+                                         sql->err, i+1,
+                                         stmt->out[i].buf.raw,
+                                         stmt->out[i].sz, SQLT_LVB,
+                                         &stmt->out[i].ind, NULL,
+                                         0, OCI_DEFAULT);
+            break;
+        case SQLT_BLOB: /* 113 */
+        case SQLT_CLOB: /* 112 */
+/*http://download-west.oracle.com/docs/cd/B10501_01/appdev.920/a96584/oci05bnd.htm#434937*/
+            sql->status = OCIDescriptorAlloc(dbd_oracle_env,
+                                             (dvoid**)&stmt->out[i].buf.lobval,
+                                             OCI_DTYPE_LOB, 0, NULL);
+            apr_pool_cleanup_register(stmt->pool, stmt->out[i].buf.lobval,
+                                      dbd_free_lobdesc,
+                                      apr_pool_cleanup_null);
+            sql->status = OCIDefineByPos(stmt->stmt, &stmt->out[i].defn,
+                                         sql->err, i+1,
+                                         (dvoid*) &stmt->out[i].buf.lobval,
+                                         -1, stmt->out[i].type,
+                                         &stmt->out[i].ind, &stmt->out[i].len,
+                                         0, OCI_DEFAULT);
+            break;
+        }
+        switch (sql->status) {
+        case OCI_SUCCESS:
+            break;
+        default:
+            return 1;
+        }
+    }
+    return 0;
+}
+
+static int dbd_oracle_pquery(apr_pool_t *pool, apr_dbd_t *sql,
+                             int *nrows, apr_dbd_prepared_t *statement,
+                             const char **values)
+{
+    OCISnapshot *oldsnapshot = NULL;
+    OCISnapshot *newsnapshot = NULL;
+    apr_dbd_transaction_t* trans = sql->trans;
+    int exec_mode;
+    int_errorcode;
+
+    if (trans) {
+        switch (trans->status) {
+        case TRANS_ERROR:
+            return -1;
+        case TRANS_NONE:
+            trans = NULL;
+            break;
+        case TRANS_1:
+            oldsnapshot = trans->snapshot1;
+            newsnapshot = trans->snapshot2;
+            trans->status = TRANS_2;
+            break;
+        case TRANS_2:
+            oldsnapshot = trans->snapshot2;
+            newsnapshot = trans->snapshot1;
+            trans->status = TRANS_1;
+            break;
+        }
+        exec_mode = OCI_DEFAULT;
+    }
+    else {
+        exec_mode = OCI_COMMIT_ON_SUCCESS;
+    }
+
+    dbd_oracle_bind(statement, values);
+
+    sql->status = OCIStmtExecute(sql->svc, statement->stmt, sql->err, 1, 0,
+                                 oldsnapshot, newsnapshot, exec_mode);
+    switch (sql->status) {
+    case OCI_SUCCESS:
+        break;
+    case OCI_ERROR:
+#ifdef DEBUG
+        OCIErrorGet(sql->err, 1, NULL, &errorcode,
+                    sql->buf, sizeof(sql->buf), OCI_HTYPE_ERROR);
+        printf("Execute error %d: %s\n", sql->status, sql->buf);
+#endif
+        /* fallthrough */
+    default:
+        if (TXN_NOTICE_ERRORS(trans)) {
+            trans->status = TRANS_ERROR;
+        }
+        return 1;
+    }
+
+    sql->status = OCIAttrGet(statement->stmt, OCI_HTYPE_STMT, nrows, 0,
+                             OCI_ATTR_ROW_COUNT, sql->err);
+    return 0;
+}
+
+static int dbd_oracle_pvquery(apr_pool_t *pool, apr_dbd_t *sql,
+                              int *nrows, apr_dbd_prepared_t *statement,
+                              va_list args)
+{
+    const char **values;
+    int i;
+
+    if (sql->trans && sql->trans->status == TRANS_ERROR) {
+        return -1;
+    }
+
+    values = apr_palloc(pool, sizeof(*values) * statement->nvals);
+
+    for (i = 0; i < statement->nvals; i++) {
+        values[i] = va_arg(args, const char*);
+    }
+
+    return dbd_oracle_pquery(pool, sql, nrows, statement, values);
+}
+
+static int dbd_oracle_pselect(apr_pool_t *pool, apr_dbd_t *sql,
+                              apr_dbd_results_t **results,
+                              apr_dbd_prepared_t *statement,
+                              int seek, const char **values)
+{
+    int exec_mode = seek ? OCI_STMT_SCROLLABLE_READONLY : OCI_DEFAULT;
+    OCISnapshot *oldsnapshot = NULL;
+    OCISnapshot *newsnapshot = NULL;
+    apr_dbd_transaction_t* trans = sql->trans;
+    int_errorcode;
+
+    if (trans) {
+        switch (trans->status) {
+        case TRANS_ERROR:
+            return 1;
+        case TRANS_NONE:
+            trans = NULL;
+            break;
+        case TRANS_1:
+            oldsnapshot = trans->snapshot1;
+            newsnapshot = trans->snapshot2;
+            trans->status = TRANS_2;
+            break;
+        case TRANS_2:
+            oldsnapshot = trans->snapshot2;
+            newsnapshot = trans->snapshot1;
+            trans->status = TRANS_1;
+            break;
+        }
+    }
+
+    dbd_oracle_bind(statement, values);
+
+    sql->status = OCIStmtExecute(sql->svc, statement->stmt, sql->err, 0, 0,
+                                 oldsnapshot, newsnapshot, exec_mode);
+    switch (sql->status) {
+    case OCI_SUCCESS:
+        break;
+    case OCI_ERROR:
+#ifdef DEBUG
+        OCIErrorGet(sql->err, 1, NULL, &errorcode,
+                    sql->buf, sizeof(sql->buf), OCI_HTYPE_ERROR);
+        printf("Executing prepared statement: %s\n", sql->buf);
+#endif
+        /* fallthrough */
+    default:
+        if (TXN_NOTICE_ERRORS(trans)) {
+            trans->status = TRANS_ERROR;
+        }
+        return 1;
+    }
+
+    if (!*results) {
+        *results = apr_palloc(pool, sizeof(apr_dbd_results_t));
+    }
+    (*results)->handle = sql;
+    (*results)->statement = statement;
+    (*results)->seek = seek;
+    (*results)->rownum = seek ? 0 : -1;
+    (*results)->pool = pool;
+
+    return 0;
+}
+
+static int dbd_oracle_pvselect(apr_pool_t *pool, apr_dbd_t *sql,
+                               apr_dbd_results_t **results,
+                               apr_dbd_prepared_t *statement,
+                               int seek, va_list args)
+{
+    const char **values;
+    int i;
+
+    if (sql->trans && sql->trans->status == TRANS_ERROR) {
+        return -1;
+    }
+
+    values = apr_palloc(pool, sizeof(*values) * statement->nvals);
+
+    for (i = 0; i < statement->nvals; i++) {
+        values[i] = va_arg(args, const char*);
+    }
+
+    return dbd_oracle_pselect(pool, sql, results, statement, seek, values);
+}
+
+static void dbd_oracle_bbind(apr_dbd_prepared_t * statement,
+                             const void **values)
+{
+    OCIStmt *stmt = statement->stmt;
+    apr_dbd_t *sql = statement->handle;
+    int i, j;
+    sb2 null_ind = -1;
+    apr_dbd_type_e type;
+
+    for (i = 0, j = 0; i < statement->nargs; i++, j++) {
+        type = (values[j] == NULL ? APR_DBD_TYPE_NULL
+                                  : statement->args[i].type);
+
+        switch (type) {
+        case APR_DBD_TYPE_TINY:
+            statement->args[i].value.ival = *(char*)values[j];
+            sql->status = OCIBindByPos(stmt, &statement->args[i].bind,
+                                       sql->err, i + 1,
+                                       &statement->args[i].value.ival,
+                                       sizeof(statement->args[i].value.ival),
+                                       SQLT_INT,
+                                       &statement->args[i].ind, NULL,
+                                       (ub2) 0, (ub4) 0,
+                                       (ub4 *) 0, OCI_DEFAULT);
+            break;
+        case APR_DBD_TYPE_UTINY:
+            statement->args[i].value.uval = *(unsigned char*)values[j];
+            sql->status = OCIBindByPos(stmt, &statement->args[i].bind,
+                                       sql->err, i + 1,
+                                       &statement->args[i].value.uval,
+                                       sizeof(statement->args[i].value.uval),
+                                       SQLT_UIN,
+                                       &statement->args[i].ind, NULL,
+                                       (ub2) 0, (ub4) 0,
+                                       (ub4 *) 0, OCI_DEFAULT);
+            break;
+        case APR_DBD_TYPE_SHORT:
+            statement->args[i].value.ival = *(short*)values[j];
+            sql->status = OCIBindByPos(stmt, &statement->args[i].bind,
+                                       sql->err, i + 1,
+                                       &statement->args[i].value.ival,
+                                       sizeof(statement->args[i].value.ival),
+                                       SQLT_INT,
+                                       &statement->args[i].ind, NULL,
+                                       (ub2) 0, (ub4) 0,
+                                       (ub4 *) 0, OCI_DEFAULT);
+            break;
+        case APR_DBD_TYPE_USHORT:
+            statement->args[i].value.uval = *(unsigned short*)values[j];
+            sql->status = OCIBindByPos(stmt, &statement->args[i].bind,
+                                       sql->err, i + 1,
+                                       &statement->args[i].value.uval,
+                                       sizeof(statement->args[i].value.uval),
+                                       SQLT_UIN,
+                                       &statement->args[i].ind, NULL,
+                                       (ub2) 0, (ub4) 0,
+                                       (ub4 *) 0, OCI_DEFAULT);
+            break;
+        case APR_DBD_TYPE_INT:
+            statement->args[i].value.ival = *(int*)values[j];
+            sql->status = OCIBindByPos(stmt, &statement->args[i].bind,
+                                       sql->err, i + 1,
+                                       &statement->args[i].value.ival,
+                                       sizeof(statement->args[i].value.ival),
+                                       SQLT_INT,
+                                       &statement->args[i].ind, NULL,
+                                       (ub2) 0, (ub4) 0,
+                                       (ub4 *) 0, OCI_DEFAULT);
+            break;
+        case APR_DBD_TYPE_UINT:
+            statement->args[i].value.uval = *(unsigned int*)values[j];
+            sql->status = OCIBindByPos(stmt, &statement->args[i].bind,
+                                       sql->err, i + 1,
+                                       &statement->args[i].value.uval,
+                                       sizeof(statement->args[i].value.uval),
+                                       SQLT_UIN,
+                                       &statement->args[i].ind, NULL,
+                                       (ub2) 0, (ub4) 0,
+                                       (ub4 *) 0, OCI_DEFAULT);
+            break;
+        case APR_DBD_TYPE_LONG:
+            statement->args[i].value.sval =
+                apr_psprintf(statement->pool, "%ld", *(long*)values[j]);
+            sql->status = OCIBindByPos(stmt, &statement->args[i].bind,
+                                       sql->err, i + 1,
+                                       statement->args[i].value.sval,
+                                       strlen(statement->args[i].value.sval)+1,
+                                       SQLT_STR,
+                                       &statement->args[i].ind, NULL,
+                                       (ub2) 0, (ub4) 0,
+                                       (ub4 *) 0, OCI_DEFAULT);
+            break;
+        case APR_DBD_TYPE_ULONG:
+            statement->args[i].value.sval =
+                apr_psprintf(statement->pool, "%lu",
+                                              *(unsigned long*)values[j]);
+            sql->status = OCIBindByPos(stmt, &statement->args[i].bind,
+                                       sql->err, i + 1,
+                                       statement->args[i].value.sval,
+                                       strlen(statement->args[i].value.sval)+1,
+                                       SQLT_STR,
+                                       &statement->args[i].ind, NULL,
+                                       (ub2) 0, (ub4) 0,
+                                       (ub4 *) 0, OCI_DEFAULT);
+            break;
+        case APR_DBD_TYPE_LONGLONG:
+            statement->args[i].value.sval =
+                apr_psprintf(statement->pool, "%" APR_INT64_T_FMT,
+                                              *(apr_int64_t*)values[j]);
+            sql->status = OCIBindByPos(stmt, &statement->args[i].bind,
+                                       sql->err, i + 1,
+                                       statement->args[i].value.sval,
+                                       strlen(statement->args[i].value.sval)+1,
+                                       SQLT_STR,
+                                       &statement->args[i].ind, NULL,
+                                       (ub2) 0, (ub4) 0,
+                                       (ub4 *) 0, OCI_DEFAULT);
+            break;
+        case APR_DBD_TYPE_ULONGLONG:
+            statement->args[i].value.sval =
+                apr_psprintf(statement->pool, "%" APR_UINT64_T_FMT,
+                                              *(apr_uint64_t*)values[j]);
+            sql->status = OCIBindByPos(stmt, &statement->args[i].bind,
+                                       sql->err, i + 1,
+                                       statement->args[i].value.sval,
+                                       strlen(statement->args[i].value.sval)+1,
+                                       SQLT_UIN,
+                                       &statement->args[i].ind, NULL,
+                                       (ub2) 0, (ub4) 0,
+                                       (ub4 *) 0, OCI_DEFAULT);
+            break;
+        case APR_DBD_TYPE_FLOAT:
+            statement->args[i].value.fval = *(float*)values[j];
+            sql->status = OCIBindByPos(stmt, &statement->args[i].bind,
+                                       sql->err, i + 1,
+                                       &statement->args[i].value.fval,
+                                       sizeof(statement->args[i].value.fval),
+                                       SQLT_FLT,
+                                       &statement->args[i].ind, NULL,
+                                       (ub2) 0, (ub4) 0,
+                                       (ub4 *) 0, OCI_DEFAULT);
+            break;
+        case APR_DBD_TYPE_DOUBLE:
+            statement->args[i].value.fval = *(double*)values[j];
+            sql->status = OCIBindByPos(stmt, &statement->args[i].bind,
+                                       sql->err, i + 1,
+                                       &statement->args[i].value.fval,
+                                       sizeof(statement->args[i].value.fval),
+                                       SQLT_FLT,
+                                       &statement->args[i].ind, NULL,
+                                       (ub2) 0, (ub4) 0,
+                                       (ub4 *) 0, OCI_DEFAULT);
+            break;
+        case APR_DBD_TYPE_STRING:
+        case APR_DBD_TYPE_TEXT:
+        case APR_DBD_TYPE_TIME:
+        case APR_DBD_TYPE_DATE:
+        case APR_DBD_TYPE_DATETIME:
+        case APR_DBD_TYPE_TIMESTAMP:
+        case APR_DBD_TYPE_ZTIMESTAMP:
+            sql->status = OCIBindByPos(stmt, &statement->args[i].bind,
+                                       sql->err, i + 1,
+                                       (dvoid*) values[j],
+                                       strlen(values[j]) + 1,
+                                       SQLT_STR,
+                                       &statement->args[i].ind, NULL,
+                                       (ub2) 0, (ub4) 0,
+                                       (ub4 *) 0, OCI_DEFAULT);
+            break;
+        case APR_DBD_TYPE_BLOB:
+            {
+            char *data = (char *)values[j];
+            apr_size_t size = *(apr_size_t*)values[++j];
+
+            /* skip table and column for now */
+            j += 2;
+
+            sql->status = OCIBindByPos(stmt, &statement->args[i].bind,
+                                       sql->err, i + 1,
+                                       data, size, SQLT_LBI,
+                                       &statement->args[i].ind,
+                                       NULL,
+                                       (ub2) 0, (ub4) 0,
+                                       (ub4 *) 0, OCI_DEFAULT);
+            }
+            break;
+        case APR_DBD_TYPE_CLOB:
+            {
+            char *data = (char *)values[j];
+            apr_size_t size = *(apr_size_t*)values[++j];
+
+            /* skip table and column for now */
+            j += 2;
+
+            sql->status = OCIBindByPos(stmt, &statement->args[i].bind,
+                                       sql->err, i + 1,
+                                       data, size, SQLT_LNG,
+                                       &statement->args[i].ind,
+                                       NULL,
+                                       (ub2) 0, (ub4) 0,
+                                       (ub4 *) 0, OCI_DEFAULT);
+            }
+            break;
+        case APR_DBD_TYPE_NULL:
+        default:
+            sql->status = OCIBindByPos(stmt, &statement->args[i].bind,
+                                       sql->err, i + 1,
+                                       NULL, 0, SQLT_STR,
+                                       &null_ind, NULL,
+                                       (ub2) 0, (ub4) 0,
+                                       (ub4 *) 0, OCI_DEFAULT);
+            break;
+        }
+
+        if (sql->status != OCI_SUCCESS) {
+            return;
+        }
+    }
+
+    return;
+}
+
+static int dbd_oracle_pbquery(apr_pool_t * pool, apr_dbd_t * sql,
+                              int *nrows, apr_dbd_prepared_t * statement,
+                              const void **values)
+{
+    OCISnapshot *oldsnapshot = NULL;
+    OCISnapshot *newsnapshot = NULL;
+    apr_dbd_transaction_t* trans = sql->trans;
+    int exec_mode;
+    int_errorcode;
+
+    if (trans) {
+        switch (trans->status) {
+        case TRANS_ERROR:
+            return -1;
+        case TRANS_NONE:
+            trans = NULL;
+            break;
+        case TRANS_1:
+            oldsnapshot = trans->snapshot1;
+            newsnapshot = trans->snapshot2;
+            trans->status = TRANS_2;
+            break;
+        case TRANS_2:
+            oldsnapshot = trans->snapshot2;
+            newsnapshot = trans->snapshot1;
+            trans->status = TRANS_1;
+            break;
+        }
+        exec_mode = OCI_DEFAULT;
+    }
+    else {
+        exec_mode = OCI_COMMIT_ON_SUCCESS;
+    }
+
+    dbd_oracle_bbind(statement, values);
+
+    sql->status = OCIStmtExecute(sql->svc, statement->stmt, sql->err, 1, 0,
+                                 oldsnapshot, newsnapshot, exec_mode);
+    switch (sql->status) {
+    case OCI_SUCCESS:
+        break;
+    case OCI_ERROR:
+#ifdef DEBUG
+        OCIErrorGet(sql->err, 1, NULL, &errorcode,
+                    sql->buf, sizeof(sql->buf), OCI_HTYPE_ERROR);
+        printf("Execute error %d: %s\n", sql->status, sql->buf);
+#endif
+        /* fallthrough */
+    default:
+        if (TXN_NOTICE_ERRORS(trans)) {
+            trans->status = TRANS_ERROR;
+        }
+        return 1;
+    }
+
+    sql->status = OCIAttrGet(statement->stmt, OCI_HTYPE_STMT, nrows, 0,
+                             OCI_ATTR_ROW_COUNT, sql->err);
+    return 0;
+}
+
+static int dbd_oracle_pvbquery(apr_pool_t * pool, apr_dbd_t * sql,
+                               int *nrows, apr_dbd_prepared_t * statement,
+                               va_list args)
+{
+    const void **values;
+    int i;
+
+    if (sql->trans && sql->trans->status == TRANS_ERROR) {
+        return -1;
+    }
+
+    values = apr_palloc(pool, sizeof(*values) * statement->nvals);
+
+    for (i = 0; i < statement->nvals; i++) {
+        values[i] = va_arg(args, const void*);
+    }
+
+    return dbd_oracle_pbquery(pool, sql, nrows, statement, values);
+}
+
+static int dbd_oracle_pbselect(apr_pool_t * pool, apr_dbd_t * sql,
+                               apr_dbd_results_t ** results,
+                               apr_dbd_prepared_t * statement,
+                               int seek, const void **values)
+{
+    int exec_mode = seek ? OCI_STMT_SCROLLABLE_READONLY : OCI_DEFAULT;
+    OCISnapshot *oldsnapshot = NULL;
+    OCISnapshot *newsnapshot = NULL;
+    apr_dbd_transaction_t* trans = sql->trans;
+    int_errorcode;
+
+    if (trans) {
+        switch (trans->status) {
+        case TRANS_ERROR:
+            return 1;
+        case TRANS_NONE:
+            trans = NULL;
+            break;
+        case TRANS_1:
+            oldsnapshot = trans->snapshot1;
+            newsnapshot = trans->snapshot2;
+            trans->status = TRANS_2;
+            break;
+        case TRANS_2:
+            oldsnapshot = trans->snapshot2;
+            newsnapshot = trans->snapshot1;
+            trans->status = TRANS_1;
+            break;
+        }
+    }
+
+    dbd_oracle_bbind(statement, values);
+
+    sql->status = OCIStmtExecute(sql->svc, statement->stmt, sql->err, 0, 0,
+                                 oldsnapshot, newsnapshot, exec_mode);
+    switch (sql->status) {
+    case OCI_SUCCESS:
+        break;
+    case OCI_ERROR:
+#ifdef DEBUG
+        OCIErrorGet(sql->err, 1, NULL, &errorcode,
+                    sql->buf, sizeof(sql->buf), OCI_HTYPE_ERROR);
+        printf("Executing prepared statement: %s\n", sql->buf);
+#endif
+        /* fallthrough */
+    default:
+        if (TXN_NOTICE_ERRORS(trans)) {
+            trans->status = TRANS_ERROR;
+        }
+        return 1;
+    }
+
+    if (!*results) {
+        *results = apr_palloc(pool, sizeof(apr_dbd_results_t));
+    }
+    (*results)->handle = sql;
+    (*results)->statement = statement;
+    (*results)->seek = seek;
+    (*results)->rownum = seek ? 0 : -1;
+    (*results)->pool = pool;
+
+    return 0;
+}
+
+static int dbd_oracle_pvbselect(apr_pool_t * pool, apr_dbd_t * sql,
+                                apr_dbd_results_t ** results,
+                                apr_dbd_prepared_t * statement, int seek,
+                                va_list args)
+{
+    const void **values;
+    int i;
+
+    if (sql->trans && sql->trans->status == TRANS_ERROR) {
+        return -1;
+    }
+
+    values = apr_palloc(pool, sizeof(*values) * statement->nvals);
+
+    for (i = 0; i < statement->nvals; i++) {
+        values[i] = va_arg(args, const void*);
+    }
+
+    return dbd_oracle_pbselect(pool, sql, results, statement, seek, values);
+}
+
+static int dbd_oracle_start_transaction(apr_pool_t *pool, apr_dbd_t *sql,
+                                        apr_dbd_transaction_t **trans)
+{
+    int ret = 0;
+    int_errorcode;
+    if (*trans) {
+        dbd_oracle_end_transaction(*trans);
+    }
+    else {
+        *trans = apr_pcalloc(pool, sizeof(apr_dbd_transaction_t));
+        OCIHandleAlloc(dbd_oracle_env, (dvoid**)&(*trans)->trans,
+                       OCI_HTYPE_TRANS, 0, 0);
+        OCIAttrSet(sql->svc, OCI_HTYPE_SVCCTX, (*trans)->trans, 0,
+                   OCI_ATTR_TRANS, sql->err);
+    }
+
+
+    sql->status = OCITransStart(sql->svc, sql->err, TRANS_TIMEOUT,
+                                OCI_TRANS_NEW);
+    switch (sql->status) {
+    case OCI_ERROR:
+#ifdef DEBUG
+        OCIErrorGet(sql->err, 1, NULL, &errorcode, sql->buf,
+                    sizeof(sql->buf), OCI_HTYPE_ERROR);
+        printf("Transaction: %s\n", sql->buf);
+#endif
+        ret = 1;
+        break;
+    case OCI_SUCCESS:
+        (*trans)->handle = sql;
+        (*trans)->status = TRANS_1;
+        sql->trans = *trans;
+        switch (OCIDescriptorAlloc(dbd_oracle_env,
+                                   (dvoid**)&(*trans)->snapshot1,
+                                   OCI_DTYPE_SNAP, 0, NULL)) {
+        case OCI_SUCCESS:
+            apr_pool_cleanup_register(pool, (*trans)->snapshot1,
+                                      dbd_free_snapshot, apr_pool_cleanup_null);
+            break;
+        case OCI_INVALID_HANDLE:
+            ret = 1;
+            break;
+        }
+        switch (OCIDescriptorAlloc(dbd_oracle_env,
+                                   (dvoid**)&(*trans)->snapshot2,
+                                   OCI_DTYPE_SNAP, 0, NULL)) {
+        case OCI_SUCCESS:
+            apr_pool_cleanup_register(pool, (*trans)->snapshot2,
+                                      dbd_free_snapshot, apr_pool_cleanup_null);
+            break;
+        case OCI_INVALID_HANDLE:
+            ret = 1;
+            break;
+        }
+        break;
+    default:
+        ret = 1;
+        break;
+    }
+    return ret;
+}
+
+static int dbd_oracle_end_transaction(apr_dbd_transaction_t *trans)
+{
+    int ret = 1;             /* no transaction is an error cond */
+    sword status;
+    if (trans) {
+        apr_dbd_t *handle = trans->handle;
+        switch (trans->status) {
+        case TRANS_NONE:     /* No trans is an error here */
+            status = OCI_ERROR;
+            break;
+        case TRANS_ERROR:
+            status = OCITransRollback(handle->svc, handle->err, OCI_DEFAULT);
+            break;
+        default:
+            /* rollback on explicit rollback request */
+            if (TXN_DO_ROLLBACK(trans)) {
+                status = OCITransRollback(handle->svc, handle->err, OCI_DEFAULT);
+            } else {
+                status = OCITransCommit(handle->svc, handle->err, OCI_DEFAULT);
+            }
+            break;
+        }
+
+        handle->trans = NULL;
+
+        switch (status) {
+        case OCI_SUCCESS:
+            ret = 0;
+            break;
+        default:
+            ret = 3;
+            break;
+        }
+    }
+    return ret;
+}
+
+static int dbd_oracle_transaction_mode_get(apr_dbd_transaction_t *trans)
+{
+    if (!trans)
+        return APR_DBD_TRANSACTION_COMMIT;
+
+    return trans->mode;
+}
+
+static int dbd_oracle_transaction_mode_set(apr_dbd_transaction_t *trans,
+                                           int mode)
+{
+    if (!trans)
+        return APR_DBD_TRANSACTION_COMMIT;
+
+    return trans->mode = (mode & TXN_MODE_BITS);
+}
+
+/* This doesn't work for BLOB because of NULLs, but it can fake it
+ * if the BLOB is really a string
+ */
+static const char *dbd_oracle_get_entry(const apr_dbd_row_t *row, int n)
+{
+    ub4 len = 0;
+    ub1 csform = 0;
+    ub2 csid = 0;
+    apr_size_t buflen = 0;
+    char *buf = NULL;
+    define_arg *val = &row->res->statement->out[n];
+    apr_dbd_t *sql = row->res->handle;
+    int_errorcode;
+
+    if ((n < 0) || (n >= row->res->statement->nout) || (val->ind == -1)) {
+        return NULL;
+    }
+
+    switch (val->type) {
+    case SQLT_BLOB:
+    case SQLT_CLOB:
+        sql->status = OCILobGetLength(sql->svc, sql->err, val->buf.lobval,
+                                      &len);
+        switch (sql->status) {
+        case OCI_SUCCESS:
+        case OCI_SUCCESS_WITH_INFO:
+            if (len == 0) {
+                buf = "";
+            }
+            break;
+        case OCI_ERROR:
+#ifdef DEBUG
+            OCIErrorGet(sql->err, 1, NULL, &errorcode,
+                        sql->buf, sizeof(sql->buf), OCI_HTYPE_ERROR);
+            printf("Finding LOB length: %s\n", sql->buf);
+            break;
+#endif
+        default:
+            break;
+        }
+
+        if (len == 0) {
+            break;
+        }
+
+        if (val->type == APR_DBD_TYPE_CLOB) {
+#if 1
+            /* Is this necessary, or can it be defaulted? */
+            sql->status = OCILobCharSetForm(dbd_oracle_env, sql->err,
+                                            val->buf.lobval, &csform);
+            if (sql->status == OCI_SUCCESS) {
+                sql->status = OCILobCharSetId(dbd_oracle_env, sql->err,
+                                              val->buf.lobval, &csid);
+            }
+            switch (sql->status) {
+            case OCI_SUCCESS:
+            case OCI_SUCCESS_WITH_INFO:
+                buflen = (len+1) * 4; /* ugh, wasteful UCS-4 handling */
+                /* zeroise all - where the string ends depends on charset */
+                buf = apr_pcalloc(row->pool, buflen);
+                break;
+#ifdef DEBUG
+            case OCI_ERROR:
+                OCIErrorGet(sql->err, 1, NULL, &errorcode,
+                            sql->buf, sizeof(sql->buf), OCI_HTYPE_ERROR);
+                printf("Reading LOB character set: %s\n", sql->buf);
+                break; /*** XXX?? ***/
+#endif
+            default:
+                break; /*** XXX?? ***/
+            }
+#else   /* ignore charset */
+            buflen = (len+1) * 4; /* ugh, wasteful UCS-4 handling */
+            /* zeroise all - where the string ends depends on charset */
+            buf = apr_pcalloc(row->pool, buflen);
+#endif
+        } else {
+            /* BUG: this'll only work if the BLOB looks like a string */
+            buflen = len;
+            buf = apr_palloc(row->pool, buflen+1);
+            buf[buflen] = 0;
+        }
+
+        if (!buf) {
+            break;
+        }
+
+        sql->status = OCILobRead(sql->svc, sql->err, val->buf.lobval,
+                                 &len, 1, (dvoid*) buf, buflen,
+                                 NULL, NULL, csid, csform);
+        switch (sql->status) {
+        case OCI_SUCCESS:
+        case OCI_SUCCESS_WITH_INFO:
+            break;
+#ifdef DEBUG
+        case OCI_ERROR:
+            OCIErrorGet(sql->err, 1, NULL, &errorcode,
+                        sql->buf, sizeof(sql->buf), OCI_HTYPE_ERROR);
+            printf("Reading LOB: %s\n", sql->buf);
+            buf = NULL; /*** XXX?? ***/
+            break;
+#endif
+        default:
+            buf = NULL; /*** XXX?? ***/
+            break;
+        }
+
+        break;
+    case SQLT_LNG:
+    case SQLT_LBI:
+        /* raw is struct { ub4 len; char *buf; } */
+        len = *(ub4*) val->buf.raw;
+        buf = apr_pstrndup(row->pool, val->buf.sval + sizeof(ub4), len);
+        break;
+    default:
+        buf = apr_pstrndup(row->pool, val->buf.sval, val->len);
+        break;
+    }
+    return (const char*) buf;
+}
+
+/* XXX Should this use Oracle proper API instead of calling get_entry()? */
+static apr_status_t dbd_oracle_datum_get(const apr_dbd_row_t *row, int n,
+                                         apr_dbd_type_e type, void *data)
+{
+    define_arg *val = &row->res->statement->out[n];
+    const char *entry;
+
+    if ((n < 0) || (n >= row->res->statement->nout)) {
+        return APR_EGENERAL;
+    }
+
+    if(val->ind == -1) {
+        return APR_ENOENT;
+    }
+
+    switch (type) {
+    case APR_DBD_TYPE_TINY:
+        entry = dbd_oracle_get_entry(row, n);
+        if (entry == NULL) {
+            return APR_ENOENT;
+        }
+        *(char*)data = atoi(entry);
+        break;
+    case APR_DBD_TYPE_UTINY:
+        entry = dbd_oracle_get_entry(row, n);
+        if (entry == NULL) {
+            return APR_ENOENT;
+        }
+        *(unsigned char*)data = atoi(entry);
+        break;
+    case APR_DBD_TYPE_SHORT:
+        entry = dbd_oracle_get_entry(row, n);
+        if (entry == NULL) {
+            return APR_ENOENT;
+        }
+        *(short*)data = atoi(entry);
+        break;
+    case APR_DBD_TYPE_USHORT:
+        entry = dbd_oracle_get_entry(row, n);
+        if (entry == NULL) {
+            return APR_ENOENT;
+        }
+        *(unsigned short*)data = atoi(entry);
+        break;
+    case APR_DBD_TYPE_INT:
+        entry = dbd_oracle_get_entry(row, n);
+        if (entry == NULL) {
+            return APR_ENOENT;
+        }
+        *(int*)data = atoi(entry);
+        break;
+    case APR_DBD_TYPE_UINT:
+        entry = dbd_oracle_get_entry(row, n);
+        if (entry == NULL) {
+            return APR_ENOENT;
+        }
+        *(unsigned int*)data = atoi(entry);
+        break;
+    case APR_DBD_TYPE_LONG:
+        entry = dbd_oracle_get_entry(row, n);
+        if (entry == NULL) {
+            return APR_ENOENT;
+        }
+        *(long*)data = atol(entry);
+        break;
+    case APR_DBD_TYPE_ULONG:
+        entry = dbd_oracle_get_entry(row, n);
+        if (entry == NULL) {
+            return APR_ENOENT;
+        }
+        *(unsigned long*)data = atol(entry);
+        break;
+    case APR_DBD_TYPE_LONGLONG:
+        entry = dbd_oracle_get_entry(row, n);
+        if (entry == NULL) {
+            return APR_ENOENT;
+        }
+        *(apr_int64_t*)data = apr_atoi64(entry);
+        break;
+    case APR_DBD_TYPE_ULONGLONG:
+        entry = dbd_oracle_get_entry(row, n);
+        if (entry == NULL) {
+            return APR_ENOENT;
+        }
+        *(apr_uint64_t*)data = apr_atoi64(entry);
+        break;
+    case APR_DBD_TYPE_FLOAT:
+        entry = dbd_oracle_get_entry(row, n);
+        if (entry == NULL) {
+            return APR_ENOENT;
+        }
+        *(float*)data = (float)atof(entry);
+        break;
+    case APR_DBD_TYPE_DOUBLE:
+        entry = dbd_oracle_get_entry(row, n);
+        if (entry == NULL) {
+            return APR_ENOENT;
+        }
+        *(double*)data = atof(entry);
+        break;
+    case APR_DBD_TYPE_STRING:
+    case APR_DBD_TYPE_TEXT:
+    case APR_DBD_TYPE_TIME:
+    case APR_DBD_TYPE_DATE:
+    case APR_DBD_TYPE_DATETIME:
+    case APR_DBD_TYPE_TIMESTAMP:
+    case APR_DBD_TYPE_ZTIMESTAMP:
+        entry = dbd_oracle_get_entry(row, n);
+        if (entry == NULL) {
+            return APR_ENOENT;
+        }
+        *(char**)data = (char*)entry;
+        break;
+    case APR_DBD_TYPE_BLOB:
+    case APR_DBD_TYPE_CLOB:
+        {
+        apr_bucket *e;
+        apr_bucket_brigade *b = (apr_bucket_brigade*)data;
+        apr_dbd_t *sql = row->res->handle;
+        ub4 len = 0;
+
+        switch (val->type) {
+        case SQLT_BLOB:
+        case SQLT_CLOB:
+            sql->status = OCILobGetLength(sql->svc, sql->err,
+                                          val->buf.lobval, &len);
+            switch(sql->status) {
+            case OCI_SUCCESS:
+            case OCI_SUCCESS_WITH_INFO:
+                if (len == 0) {
+                    e = apr_bucket_eos_create(b->bucket_alloc);
+                }
+                else {
+                    e = apr_bucket_lob_create(row, n, 0, len,
+                                              row->pool, b->bucket_alloc);
+                }
+                break;
+            default:
+                return APR_ENOENT;
+            }
+            break;
+        default:
+            entry = dbd_oracle_get_entry(row, n);
+            if (entry == NULL) {
+                return APR_ENOENT;
+            }
+            e = apr_bucket_pool_create(entry, strlen(entry),
+                                       row->pool, b->bucket_alloc);
+            break;
+        }
+        APR_BRIGADE_INSERT_TAIL(b, e);
+        }
+        break;
+    case APR_DBD_TYPE_NULL:
+        *(void**)data = NULL;
+        break;
+    default:
+        return APR_EGENERAL;
+    }
+
+    return APR_SUCCESS;
+}
+
+static apr_status_t dbd_oracle_close(apr_dbd_t *handle)
+{
+    /* FIXME: none of the oracle docs/examples say anything about
+     * closing/releasing handles.  Which seems unlikely ...
+     */
+
+    /* OK, let's grab from cdemo again.
+     * cdemo81 does nothing; cdemo82 does OCIHandleFree on the handles
+     */
+    switch (OCISessionEnd(handle->svc, handle->err, handle->auth,
+            (ub4)OCI_DEFAULT)) {
+    default:
+        break;
+    }
+    switch (OCIServerDetach(handle->svr, handle->err, (ub4) OCI_DEFAULT )) {
+    default:
+        break;
+    }
+    /* does OCISessionEnd imply this? */
+    switch (OCIHandleFree((dvoid *) handle->auth, (ub4) OCI_HTYPE_SESSION)) {
+    default:
+        break;
+    }
+    switch (OCIHandleFree((dvoid *) handle->svr, (ub4) OCI_HTYPE_SERVER)) {
+    default:
+        break;
+    }
+    switch (OCIHandleFree((dvoid *) handle->svc, (ub4) OCI_HTYPE_SVCCTX)) {
+    default:
+        break;
+    }
+    switch (OCIHandleFree((dvoid *) handle->err, (ub4) OCI_HTYPE_ERROR)) {
+    default:
+        break;
+    }
+    return APR_SUCCESS;
+}
+
+static apr_status_t dbd_oracle_check_conn(apr_pool_t *pool, apr_dbd_t *sql)
+{
+    apr_dbd_results_t *res = NULL;
+    apr_dbd_row_t *row = NULL;
+    
+    if(dbd_oracle_pselect(pool, sql, &res, sql->check_conn_stmt,
+                          0, NULL) != 0) {
+        return APR_EGENERAL;
+    }
+    
+    if(dbd_oracle_get_row(pool, res, &row, -1) != 0) {
+        return APR_EGENERAL;
+    }
+    
+    if(dbd_oracle_get_row(pool, res, &row, -1) != -1) {
+        return APR_EGENERAL;
+    }
+
+    return APR_SUCCESS;
+}
+
+static int dbd_oracle_select_db(apr_pool_t *pool, apr_dbd_t *handle,
+                                const char *name)
+{
+    /* FIXME: need to find this in the docs */
+    return APR_ENOTIMPL;
+}
+
+static void *dbd_oracle_native(apr_dbd_t *handle)
+{
+    /* FIXME: can we do anything better?  Oracle doesn't seem to have
+     * a concept of a handle in the sense we use it.
+     */
+    return dbd_oracle_env;
+}
+
+static int dbd_oracle_num_cols(apr_dbd_results_t* res)
+{
+    return res->statement->nout;
+}
+
+static int dbd_oracle_num_tuples(apr_dbd_results_t* res)
+{
+    if (!res->seek) {
+        return -1;
+    }
+    if (res->nrows >= 0) {
+        return res->nrows;
+    }
+    res->handle->status = OCIAttrGet(res->statement->stmt, OCI_HTYPE_STMT,
+                                     &res->nrows, 0, OCI_ATTR_ROW_COUNT,
+                                     res->handle->err);
+    return res->nrows;
+}
+
+APR_MODULE_DECLARE_DATA const apr_dbd_driver_t apr_dbd_oracle_driver = {
+    "oracle",
+    dbd_oracle_init,
+    dbd_oracle_native,
+    dbd_oracle_open,
+    dbd_oracle_check_conn,
+    dbd_oracle_close,
+    dbd_oracle_select_db,
+    dbd_oracle_start_transaction,
+    dbd_oracle_end_transaction,
+    dbd_oracle_query,
+    dbd_oracle_select,
+    dbd_oracle_num_cols,
+    dbd_oracle_num_tuples,
+    dbd_oracle_get_row,
+    dbd_oracle_get_entry,
+    dbd_oracle_error,
+    dbd_oracle_escape,
+    dbd_oracle_prepare,
+    dbd_oracle_pvquery,
+    dbd_oracle_pvselect,
+    dbd_oracle_pquery,
+    dbd_oracle_pselect,
+    dbd_oracle_get_name,
+    dbd_oracle_transaction_mode_get,
+    dbd_oracle_transaction_mode_set,
+    ":apr%d",
+    dbd_oracle_pvbquery,
+    dbd_oracle_pvbselect,
+    dbd_oracle_pbquery,
+    dbd_oracle_pbselect,
+    dbd_oracle_datum_get
+};
+#endif
diff --git a/dbd/apr_dbd_oracle.dsp b/dbd/apr_dbd_oracle.dsp
new file mode 100644
index 00000000000..91134138807
--- /dev/null
+++ b/dbd/apr_dbd_oracle.dsp
@@ -0,0 +1,207 @@
+# Microsoft Developer Studio Project File - Name="apr_dbd_oracle" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=apr_dbd_oracle - 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 "apr_dbd_oracle.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 "apr_dbd_oracle.mak" CFG="apr_dbd_oracle - Win32 Release"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "apr_dbd_oracle - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_dbd_oracle - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_dbd_oracle - x64 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_dbd_oracle - x64 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)" == "apr_dbd_oracle - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /Zi /O2 /Oy- /I "../include" /I "../include/arch/win32" /I "../include/private" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_ORACLE=1 /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbd_oracle_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /fo"Release/apr_dbd_oracle-1.res" /d DLL_NAME="apr_dbd_oracle" /d "NDEBUG" /d "APU_VERSION_ONLY" /I "../include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib oci.lib /nologo /base:"0x6EF40000" /subsystem:windows /dll /incremental:no /debug /opt:ref
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib oci.lib /nologo /base:"0x6EF40000" /subsystem:windows /dll /incremental:no /debug /out:"Release\apr_dbd_oracle-1.dll" /pdb:"Release\apr_dbd_oracle-1.pdb" /implib:"Release\apr_dbd_oracle-1.lib" /MACHINE:X86 /opt:ref
+# Begin Special Build Tool
+TargetPath=Release\apr_dbd_oracle-1.dll
+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)" == "apr_dbd_oracle - 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 /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /EHsc /c
+# ADD CPP /nologo /MDd /W3 /Zi /Od /I "../include" /I "../include/arch/win32" /I "../include/private" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_ORACLE=1 /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbd_oracle_src" /FD /EHsc /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /fo"Debug/apr_dbd_oracle-1.res" /d DLL_NAME="apr_dbd_oracle" /d "_DEBUG" /d "APU_VERSION_ONLY" /I "../include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib oci.lib /nologo /base:"0x6EF40000" /subsystem:windows /dll /incremental:no /debug
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib oci.lib /nologo /base:"0x6EF40000" /subsystem:windows /dll /incremental:no /debug /out:"Debug\apr_dbd_oracle-1.dll" /pdb:"Debug\apr_dbd_oracle-1.pdb" /implib:"Debug\apr_dbd_oracle-1.lib" /MACHINE:X86
+# Begin Special Build Tool
+TargetPath=Debug\apr_dbd_oracle-1.dll
+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)" == "apr_dbd_oracle - x64 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "x64\Release"
+# PROP BASE Intermediate_Dir "x64\Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "x64\Release"
+# PROP Intermediate_Dir "x64\Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /Zi /O2 /Oy- /I "../include" /I "../include/arch/win32" /I "../include/private" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_ORACLE=1 /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbd_oracle_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /fo"x64/Release/apr_dbd_oracle-1.res" /d DLL_NAME="apr_dbd_oracle" /d "NDEBUG" /d "APU_VERSION_ONLY" /I "../include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib oci.lib /nologo /base:"0x6EF40000" /subsystem:windows /dll /incremental:no /debug /opt:ref
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib oci.lib /nologo /base:"0x6EF40000" /subsystem:windows /dll /incremental:no /debug /out:"x64\Release\apr_dbd_oracle-1.dll" /pdb:"x64\Release\apr_dbd_oracle-1.pdb" /implib:"x64\Release\apr_dbd_oracle-1.lib" /MACHINE:X64 /opt:ref
+# Begin Special Build Tool
+TargetPath=x64\Release\apr_dbd_oracle-1.dll
+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)" == "apr_dbd_oracle - x64 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "x64\Debug"
+# PROP BASE Intermediate_Dir "x64\Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "x64\Debug"
+# PROP Intermediate_Dir "x64\Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /EHsc /c
+# ADD CPP /nologo /MDd /W3 /Zi /Od /I "../include" /I "../include/arch/win32" /I "../include/private" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_ORACLE=1 /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbd_oracle_src" /FD /EHsc /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /fo"x64/Debug/apr_dbd_oracle-1.res" /d DLL_NAME="apr_dbd_oracle" /d "_DEBUG" /d "APU_VERSION_ONLY" /I "../include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib oci.lib /nologo /base:"0x6EF40000" /subsystem:windows /dll /incremental:no /debug
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib oci.lib /nologo /base:"0x6EF40000" /subsystem:windows /dll /incremental:no /debug /out:"x64\Debug\apr_dbd_oracle-1.dll" /pdb:"x64\Debug\apr_dbd_oracle-1.pdb" /implib:"x64\Debug\apr_dbd_oracle-1.lib" /MACHINE:X64
+# Begin Special Build Tool
+TargetPath=x64\Debug\apr_dbd_oracle-1.dll
+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 "apr_dbd_oracle - Win32 Release"
+# Name "apr_dbd_oracle - Win32 Debug"
+# Name "apr_dbd_oracle - x64 Release"
+# Name "apr_dbd_oracle - x64 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\apr_dbd_oracle.c
+# End Source File
+# End Group
+# Begin Group "Public Header Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\include\apr_dbd.h
+# End Source File
+# End Group
+# Begin Group "Internal Header Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\include\private\apu_config.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\private\apu_dbd_internal.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\private\apu_internal.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\libapr.rc
+# End Source File
+# End Target
+# End Project
diff --git a/dbd/apr_dbd_pgsql.c b/dbd/apr_dbd_pgsql.c
new file mode 100644
index 00000000000..af09e0a478f
--- /dev/null
+++ b/dbd/apr_dbd_pgsql.c
@@ -0,0 +1,1314 @@
+/* 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 "apu.h"
+#include "apr_private.h"
+
+#if APU_HAVE_PGSQL
+
+#include <ctype.h>
+#include <stdlib.h>
+
+#ifdef HAVE_LIBPQ_FE_H
+#include <libpq-fe.h>
+#elif defined(HAVE_POSTGRESQL_LIBPQ_FE_H)
+#include <postgresql/libpq-fe.h>
+#endif
+
+#include "apr_strings.h"
+#include "apr_time.h"
+#include "apr_buckets.h"
+
+#include "apr_dbd_internal.h"
+
+struct apr_dbd_transaction_t {
+    int mode;
+    int errnum;
+    apr_dbd_t *handle;
+};
+
+struct apr_dbd_t {
+    PGconn *conn;
+    apr_dbd_transaction_t *trans;
+};
+
+struct apr_dbd_results_t {
+    int random;
+    PGconn *handle;
+    PGresult *res;
+    size_t ntuples;
+    size_t sz;
+    size_t index;
+    apr_pool_t *pool;
+};
+
+struct apr_dbd_row_t {
+    int n;
+    apr_dbd_results_t *res;
+};
+
+struct apr_dbd_prepared_t {
+    const char *name;
+    int prepared;
+    int nargs;
+    int nvals;
+    apr_dbd_type_e *types;
+};
+
+#define dbd_pgsql_is_success(x) (((x) == PGRES_EMPTY_QUERY) \
+                                 || ((x) == PGRES_COMMAND_OK) \
+                                 || ((x) == PGRES_TUPLES_OK))
+
+static apr_status_t clear_result(void *data)
+{
+    PQclear(data);
+    return APR_SUCCESS;
+}
+
+static int dbd_pgsql_select(apr_pool_t *pool, apr_dbd_t *sql,
+                            apr_dbd_results_t **results,
+                            const char *query, int seek)
+{
+    PGresult *res;
+    int ret;
+    if ( sql->trans && sql->trans->errnum ) {
+        return sql->trans->errnum;
+    }
+    if (seek) { /* synchronous query */
+        if (TXN_IGNORE_ERRORS(sql->trans)) {
+            PGresult *res = PQexec(sql->conn, "SAVEPOINT APR_DBD_TXN_SP");
+            if (res) {
+                int ret = PQresultStatus(res);
+                PQclear(res);
+                if (!dbd_pgsql_is_success(ret)) {
+                    sql->trans->errnum = ret;
+                    return PGRES_FATAL_ERROR;
+                }
+            } else {
+                return sql->trans->errnum = PGRES_FATAL_ERROR;
+            }
+        }
+        res = PQexec(sql->conn, query);
+        if (res) {
+            ret = PQresultStatus(res);
+            if (dbd_pgsql_is_success(ret)) {
+                ret = 0;
+            } else {
+                PQclear(res);
+            }
+        } else {
+            ret = PGRES_FATAL_ERROR;
+        }
+        if (ret != 0) {
+            if (TXN_IGNORE_ERRORS(sql->trans)) {
+                PGresult *res = PQexec(sql->conn,
+                                       "ROLLBACK TO SAVEPOINT APR_DBD_TXN_SP");
+                if (res) {
+                    int ret = PQresultStatus(res);
+                    PQclear(res);
+                    if (!dbd_pgsql_is_success(ret)) {
+                        sql->trans->errnum = ret;
+                        return PGRES_FATAL_ERROR;
+                    }
+                } else {
+                    return sql->trans->errnum = PGRES_FATAL_ERROR;
+                }
+            } else if (TXN_NOTICE_ERRORS(sql->trans)){
+                sql->trans->errnum = ret;
+            }
+            return ret;
+        } else {
+            if (TXN_IGNORE_ERRORS(sql->trans)) {
+                PGresult *res = PQexec(sql->conn,
+                                       "RELEASE SAVEPOINT APR_DBD_TXN_SP");
+                if (res) {
+                    int ret = PQresultStatus(res);
+                    PQclear(res);
+                    if (!dbd_pgsql_is_success(ret)) {
+                        sql->trans->errnum = ret;
+                        return PGRES_FATAL_ERROR;
+                    }
+                } else {
+                    return sql->trans->errnum = PGRES_FATAL_ERROR;
+                }
+            }
+        }
+        if (!*results) {
+            *results = apr_pcalloc(pool, sizeof(apr_dbd_results_t));
+        }
+        (*results)->res = res;
+        (*results)->ntuples = PQntuples(res);
+        (*results)->sz = PQnfields(res);
+        (*results)->random = seek;
+        (*results)->pool = pool;
+        apr_pool_cleanup_register(pool, res, clear_result,
+                                  apr_pool_cleanup_null);
+    }
+    else {
+        if (TXN_IGNORE_ERRORS(sql->trans)) {
+            PGresult *res = PQexec(sql->conn, "SAVEPOINT APR_DBD_TXN_SP");
+            if (res) {
+                int ret = PQresultStatus(res);
+                PQclear(res);
+                if (!dbd_pgsql_is_success(ret)) {
+                    sql->trans->errnum = ret;
+                    return PGRES_FATAL_ERROR;
+                }
+            } else {
+                return sql->trans->errnum = PGRES_FATAL_ERROR;
+            }
+        }
+        if (PQsendQuery(sql->conn, query) == 0) {
+            if (TXN_IGNORE_ERRORS(sql->trans)) {
+                PGresult *res = PQexec(sql->conn,
+                                       "ROLLBACK TO SAVEPOINT APR_DBD_TXN_SP");
+                if (res) {
+                    int ret = PQresultStatus(res);
+                    PQclear(res);
+                    if (!dbd_pgsql_is_success(ret)) {
+                        sql->trans->errnum = ret;
+                        return PGRES_FATAL_ERROR;
+                    }
+                } else {
+                    return sql->trans->errnum = PGRES_FATAL_ERROR;
+                }
+            } else if (TXN_NOTICE_ERRORS(sql->trans)){
+                sql->trans->errnum = 1;
+            }
+            return 1;
+        } else {
+            if (TXN_IGNORE_ERRORS(sql->trans)) {
+                PGresult *res = PQexec(sql->conn,
+                                       "RELEASE SAVEPOINT APR_DBD_TXN_SP");
+                if (res) {
+                    int ret = PQresultStatus(res);
+                    PQclear(res);
+                    if (!dbd_pgsql_is_success(ret)) {
+                        sql->trans->errnum = ret;
+                        return PGRES_FATAL_ERROR;
+                    }
+                } else {
+                    return sql->trans->errnum = PGRES_FATAL_ERROR;
+                }
+            }
+        }
+        if (*results == NULL) {
+            *results = apr_pcalloc(pool, sizeof(apr_dbd_results_t));
+        }
+        (*results)->random = seek;
+        (*results)->handle = sql->conn;
+        (*results)->pool = pool;
+    }
+    return 0;
+}
+
+static const char *dbd_pgsql_get_name(const apr_dbd_results_t *res, int n)
+{
+    if (res->res) {
+        if ((n>=0) && (PQnfields(res->res) > n)) {
+            return PQfname(res->res,n);
+        }
+    }
+    return NULL;
+}
+
+static int dbd_pgsql_get_row(apr_pool_t *pool, apr_dbd_results_t *res,
+                             apr_dbd_row_t **rowp, int rownum)
+{
+    apr_dbd_row_t *row = *rowp;
+    int sequential = ((rownum >= 0) && res->random) ? 0 : 1;
+
+    if (row == NULL) {
+        row = apr_palloc(pool, sizeof(apr_dbd_row_t));
+        *rowp = row;
+        row->res = res;
+        if ( sequential ) {
+            row->n = 0;
+        }
+        else {
+            if (rownum > 0) {
+                row->n = --rownum;
+            }
+            else {
+                return -1; /* invalid row */
+            }
+        }
+    }
+    else {
+        if ( sequential ) {
+            ++row->n;
+        }
+        else {
+            if (rownum > 0) {
+                row->n = --rownum;
+            }
+            else {
+                return -1; /* invalid row */
+            }
+        }
+    }
+
+    if (res->random) {
+        if ((row->n >= 0) && (size_t)row->n >= res->ntuples) {
+            *rowp = NULL;
+            apr_pool_cleanup_run(res->pool, res->res, clear_result);
+            res->res = NULL;
+            return -1;
+        }
+    }
+    else {
+        if ((row->n >= 0) && (size_t)row->n >= res->ntuples) {
+            /* no data; we have to fetch some */
+            row->n -= res->ntuples;
+            if (res->res != NULL) {
+                PQclear(res->res);
+            }
+            res->res = PQgetResult(res->handle);
+            if (res->res) {
+                res->ntuples = PQntuples(res->res);
+                while (res->ntuples == 0) {
+                    /* if we got an empty result, clear it, wait a mo, try
+                     * again */
+                    PQclear(res->res);
+                    apr_sleep(100000);        /* 0.1 secs */
+                    res->res = PQgetResult(res->handle);
+                    if (res->res) {
+                        res->ntuples = PQntuples(res->res);
+                    }
+                    else {
+                        return -1;
+                    }
+                }
+                if (res->sz == 0) {
+                    res->sz = PQnfields(res->res);
+                }
+            }
+            else {
+                return -1;
+            }
+        }
+    }
+    return 0;
+}
+
+static const char *dbd_pgsql_get_entry(const apr_dbd_row_t *row, int n)
+{
+    return PQgetvalue(row->res->res, row->n, n);
+}
+
+static apr_status_t dbd_pgsql_datum_get(const apr_dbd_row_t *row, int n,
+                                        apr_dbd_type_e type, void *data)
+{
+    if (PQgetisnull(row->res->res, row->n, n)) {
+        return APR_ENOENT;
+    }
+
+    switch (type) {
+    case APR_DBD_TYPE_TINY:
+        *(char*)data = atoi(PQgetvalue(row->res->res, row->n, n));
+        break;
+    case APR_DBD_TYPE_UTINY:
+        *(unsigned char*)data = atoi(PQgetvalue(row->res->res, row->n, n));
+        break;
+    case APR_DBD_TYPE_SHORT:
+        *(short*)data = atoi(PQgetvalue(row->res->res, row->n, n));
+        break;
+    case APR_DBD_TYPE_USHORT:
+        *(unsigned short*)data = atoi(PQgetvalue(row->res->res, row->n, n));
+        break;
+    case APR_DBD_TYPE_INT:
+        *(int*)data = atoi(PQgetvalue(row->res->res, row->n, n));
+        break;
+    case APR_DBD_TYPE_UINT:
+        *(unsigned int*)data = atoi(PQgetvalue(row->res->res, row->n, n));
+        break;
+    case APR_DBD_TYPE_LONG:
+        *(long*)data = atol(PQgetvalue(row->res->res, row->n, n));
+        break;
+    case APR_DBD_TYPE_ULONG:
+        *(unsigned long*)data = atol(PQgetvalue(row->res->res, row->n, n));
+        break;
+    case APR_DBD_TYPE_LONGLONG:
+        *(apr_int64_t*)data = apr_atoi64(PQgetvalue(row->res->res, row->n, n));
+        break;
+    case APR_DBD_TYPE_ULONGLONG:
+        *(apr_uint64_t*)data = apr_atoi64(PQgetvalue(row->res->res, row->n, n));
+        break;
+    case APR_DBD_TYPE_FLOAT:
+        *(float*)data = (float)atof(PQgetvalue(row->res->res, row->n, n));
+        break;
+    case APR_DBD_TYPE_DOUBLE:
+        *(double*)data = atof(PQgetvalue(row->res->res, row->n, n));
+        break;
+    case APR_DBD_TYPE_STRING:
+    case APR_DBD_TYPE_TEXT:
+    case APR_DBD_TYPE_TIME:
+    case APR_DBD_TYPE_DATE:
+    case APR_DBD_TYPE_DATETIME:
+    case APR_DBD_TYPE_TIMESTAMP:
+    case APR_DBD_TYPE_ZTIMESTAMP:
+        *(char**)data = PQgetvalue(row->res->res, row->n, n);
+        break;
+    case APR_DBD_TYPE_BLOB:
+    case APR_DBD_TYPE_CLOB:
+        {
+        apr_bucket *e;
+        apr_bucket_brigade *b = (apr_bucket_brigade*)data;
+
+        e = apr_bucket_pool_create(PQgetvalue(row->res->res, row->n, n),
+                                   PQgetlength(row->res->res, row->n, n),
+                                   row->res->pool, b->bucket_alloc);
+        APR_BRIGADE_INSERT_TAIL(b, e);
+        }
+        break;
+    case APR_DBD_TYPE_NULL:
+        *(void**)data = NULL;
+        break;
+    default:
+        return APR_EGENERAL;
+    }
+
+    return APR_SUCCESS;
+}
+
+static const char *dbd_pgsql_error(apr_dbd_t *sql, int n)
+{
+    return PQerrorMessage(sql->conn);
+}
+
+static int dbd_pgsql_query(apr_dbd_t *sql, int *nrows, const char *query)
+{
+    PGresult *res;
+    int ret;
+    if (sql->trans && sql->trans->errnum) {
+        return sql->trans->errnum;
+    }
+
+    if (TXN_IGNORE_ERRORS(sql->trans)) {
+        PGresult *res = PQexec(sql->conn, "SAVEPOINT APR_DBD_TXN_SP");
+        if (res) {
+            int ret = PQresultStatus(res);
+            PQclear(res);
+            if (!dbd_pgsql_is_success(ret)) {
+                sql->trans->errnum = ret;
+                return PGRES_FATAL_ERROR;
+            }
+        } else {
+            return sql->trans->errnum = PGRES_FATAL_ERROR;
+        }
+    }
+
+    res = PQexec(sql->conn, query);
+    if (res) {
+        ret = PQresultStatus(res);
+        if (dbd_pgsql_is_success(ret)) {
+            /* ugh, making 0 return-success doesn't fit */
+            ret = 0;
+        }
+        *nrows = atoi(PQcmdTuples(res));
+        PQclear(res);
+    }
+    else {
+        ret = PGRES_FATAL_ERROR;
+    }
+    
+    if (ret != 0){
+        if (TXN_IGNORE_ERRORS(sql->trans)) {
+            PGresult *res = PQexec(sql->conn,
+                                   "ROLLBACK TO SAVEPOINT APR_DBD_TXN_SP");
+            if (res) {
+                int ret = PQresultStatus(res);
+                PQclear(res);
+                if (!dbd_pgsql_is_success(ret)) {
+                    sql->trans->errnum = ret;
+                    return PGRES_FATAL_ERROR;
+                }
+            } else {
+                sql->trans->errnum = ret;
+                return PGRES_FATAL_ERROR;
+            }
+        } else if (TXN_NOTICE_ERRORS(sql->trans)){
+            sql->trans->errnum = ret;
+        }
+    } else {
+        if (TXN_IGNORE_ERRORS(sql->trans)) {
+            PGresult *res = PQexec(sql->conn,
+                                   "RELEASE SAVEPOINT APR_DBD_TXN_SP");
+            if (res) {
+                int ret = PQresultStatus(res);
+                PQclear(res);
+                if (!dbd_pgsql_is_success(ret)) {
+                    sql->trans->errnum = ret;
+                    return PGRES_FATAL_ERROR;
+                }
+            } else {
+                sql->trans->errnum = ret;
+                return PGRES_FATAL_ERROR;
+            }
+        }
+    }
+
+    return ret;
+}
+
+static const char *dbd_pgsql_escape(apr_pool_t *pool, const char *arg,
+                                    apr_dbd_t *sql)
+{
+    size_t len = strlen(arg);
+    char *ret = apr_palloc(pool, 2*len + 2);
+    PQescapeStringConn(sql->conn, ret, arg, len, NULL);
+    return ret;
+}
+
+static int dbd_pgsql_prepare(apr_pool_t *pool, apr_dbd_t *sql,
+                             const char *query, const char *label,
+                             int nargs, int nvals, apr_dbd_type_e *types,
+                             apr_dbd_prepared_t **statement)
+{
+    char *sqlcmd;
+    char *sqlptr;
+    size_t length, qlen;
+    int i = 0;
+    const char **args;
+    size_t alen;
+    int ret;
+    PGresult *res;
+
+    if (!*statement) {
+        *statement = apr_palloc(pool, sizeof(apr_dbd_prepared_t));
+    }
+    (*statement)->nargs = nargs;
+    (*statement)->nvals = nvals;
+    (*statement)->types = types;
+
+    args = apr_palloc(pool, nargs * sizeof(*args));
+
+    qlen = strlen(query);
+    length = qlen + 1;
+
+    for (i = 0; i < nargs; i++) {
+        switch (types[i]) {
+        case APR_DBD_TYPE_TINY: 
+        case APR_DBD_TYPE_UTINY: 
+        case APR_DBD_TYPE_SHORT: 
+        case APR_DBD_TYPE_USHORT:
+            args[i] = "smallint";
+            break;
+        case APR_DBD_TYPE_INT: 
+        case APR_DBD_TYPE_UINT:
+            args[i] = "integer";
+            break;
+        case APR_DBD_TYPE_LONG: 
+        case APR_DBD_TYPE_ULONG:   
+        case APR_DBD_TYPE_LONGLONG: 
+        case APR_DBD_TYPE_ULONGLONG:
+            args[i] = "bigint";
+            break;
+        case APR_DBD_TYPE_FLOAT:
+            args[i] = "real";
+            break;
+        case APR_DBD_TYPE_DOUBLE:
+            args[i] = "double precision";
+            break;
+        case APR_DBD_TYPE_TEXT:
+            args[i] = "text";
+            break;
+        case APR_DBD_TYPE_TIME:
+            args[i] = "time";
+            break;
+        case APR_DBD_TYPE_DATE:
+            args[i] = "date";
+            break;
+        case APR_DBD_TYPE_DATETIME:
+        case APR_DBD_TYPE_TIMESTAMP:
+            args[i] = "timestamp";
+            break;
+        case APR_DBD_TYPE_ZTIMESTAMP:
+            args[i] = "timestamp with time zone";
+            break;
+        case APR_DBD_TYPE_BLOB:
+        case APR_DBD_TYPE_CLOB:
+            args[i] = "bytea";
+            break;
+        case APR_DBD_TYPE_NULL:
+            args[i] = "varchar"; /* XXX Eh? */
+            break;
+        default:
+            args[i] = "varchar";
+            break;
+        }
+        length += 1 + strlen(args[i]);
+    }
+
+    if (!label) {
+        /* don't really prepare; use in execParams instead */
+        (*statement)->prepared = 0;
+        (*statement)->name = apr_pstrdup(pool, query);
+        return 0;
+    }
+    (*statement)->name = apr_pstrdup(pool, label);
+
+    /* length of SQL query that prepares this statement */
+    length = 8 + strlen(label) + 2 + 4 + length + 1;
+    sqlcmd = apr_palloc(pool, length);
+    sqlptr = sqlcmd;
+    memcpy(sqlptr, "PREPARE ", 8);
+    sqlptr += 8;
+    length = strlen(label);
+    memcpy(sqlptr, label, length);
+    sqlptr += length;
+    if (nargs > 0) {
+        memcpy(sqlptr, " (",2);
+        sqlptr += 2;
+        for (i=0; i < nargs; ++i) {
+            alen = strlen(args[i]);
+            memcpy(sqlptr, args[i], alen);
+            sqlptr += alen;
+            *sqlptr++ = ',';
+        }
+        sqlptr[-1] =  ')';
+    }
+    memcpy(sqlptr, " AS ", 4);
+    sqlptr += 4;
+    memcpy(sqlptr, query, qlen);
+    sqlptr += qlen;
+    *sqlptr = 0;
+
+    res = PQexec(sql->conn, sqlcmd);
+    if ( res ) {
+        ret = PQresultStatus(res);
+        if (dbd_pgsql_is_success(ret)) {
+            ret = 0;
+        }
+        /* Hmmm, do we do this here or register it on the pool? */
+        PQclear(res);
+    }
+    else {
+        ret = PGRES_FATAL_ERROR;
+    }
+    (*statement)->prepared = 1;
+
+    return ret;
+}
+
+static int dbd_pgsql_pquery_internal(apr_pool_t *pool, apr_dbd_t *sql,
+                                     int *nrows, apr_dbd_prepared_t *statement,
+                                     const char **values,
+                                     const int *len, const int *fmt)
+{
+    int ret;
+    PGresult *res;
+
+    if (TXN_IGNORE_ERRORS(sql->trans)) {
+        PGresult *res = PQexec(sql->conn, "SAVEPOINT APR_DBD_TXN_SP");
+        if (res) {
+            int ret = PQresultStatus(res);
+            PQclear(res);
+            if (!dbd_pgsql_is_success(ret)) {
+                sql->trans->errnum = ret;
+                return PGRES_FATAL_ERROR;
+            }
+        } else {
+            return sql->trans->errnum = PGRES_FATAL_ERROR;
+        }
+    }
+
+    if (statement->prepared) {
+        res = PQexecPrepared(sql->conn, statement->name, statement->nargs,
+                             values, len, fmt, 0);
+    }
+    else {
+        res = PQexecParams(sql->conn, statement->name, statement->nargs, 0,
+                           values, len, fmt, 0);
+    }
+    if (res) {
+        ret = PQresultStatus(res);
+        if (dbd_pgsql_is_success(ret)) {
+            ret = 0;
+        }
+        *nrows = atoi(PQcmdTuples(res));
+        PQclear(res);
+    }
+    else {
+        ret = PGRES_FATAL_ERROR;
+    }
+
+    if (ret != 0){
+        if (TXN_IGNORE_ERRORS(sql->trans)) {
+            PGresult *res = PQexec(sql->conn,
+                                   "ROLLBACK TO SAVEPOINT APR_DBD_TXN_SP");
+            if (res) {
+                int ret = PQresultStatus(res);
+                PQclear(res);
+                if (!dbd_pgsql_is_success(ret)) {
+                    sql->trans->errnum = ret;
+                    return PGRES_FATAL_ERROR;
+                }
+            } else {
+                sql->trans->errnum = ret;
+                return PGRES_FATAL_ERROR;
+            }
+        } else if (TXN_NOTICE_ERRORS(sql->trans)){
+            sql->trans->errnum = ret;
+        }
+    } else {
+        if (TXN_IGNORE_ERRORS(sql->trans)) {
+            PGresult *res = PQexec(sql->conn,
+                                   "RELEASE SAVEPOINT APR_DBD_TXN_SP");
+            if (res) {
+                int ret = PQresultStatus(res);
+                PQclear(res);
+                if (!dbd_pgsql_is_success(ret)) {
+                    sql->trans->errnum = ret;
+                    return PGRES_FATAL_ERROR;
+                }
+            } else {
+                sql->trans->errnum = ret;
+                return PGRES_FATAL_ERROR;
+            }
+        }
+    }
+
+    return ret;
+}
+
+static void dbd_pgsql_bind(apr_dbd_prepared_t *statement,
+                           const char **values,
+                           const char **val, int *len, int *fmt)
+{
+    int i, j;
+
+    for (i = 0, j = 0; i < statement->nargs; i++, j++) {
+        if (values[j] == NULL) {
+            val[i] = NULL;
+        }
+        else {
+            switch (statement->types[i]) {
+            case APR_DBD_TYPE_BLOB:
+            case APR_DBD_TYPE_CLOB:
+                val[i] = (char *)values[j];
+                len[i] = atoi(values[++j]);
+                fmt[i] = 1;
+
+                /* skip table and column */
+                j += 2;
+                break;
+            default:
+                val[i] = values[j];
+                break;
+            }
+        }
+    }
+
+    return;
+}
+
+static int dbd_pgsql_pquery(apr_pool_t *pool, apr_dbd_t *sql,
+                            int *nrows, apr_dbd_prepared_t *statement,
+                            const char **values)
+{
+    int *len, *fmt;
+    const char **val;
+
+    if (sql->trans && sql->trans->errnum) {
+        return sql->trans->errnum;
+    }
+
+    val = apr_palloc(pool, sizeof(*val) * statement->nargs);
+    len = apr_pcalloc(pool, sizeof(*len) * statement->nargs);
+    fmt = apr_pcalloc(pool, sizeof(*fmt) * statement->nargs);
+
+    dbd_pgsql_bind(statement, values, val, len, fmt);
+
+    return dbd_pgsql_pquery_internal(pool, sql, nrows, statement,
+                                     val, len, fmt);
+}
+
+static int dbd_pgsql_pvquery(apr_pool_t *pool, apr_dbd_t *sql,
+                             int *nrows, apr_dbd_prepared_t *statement,
+                             va_list args)
+{
+    const char **values;
+    int i;
+
+    if (sql->trans && sql->trans->errnum) {
+        return sql->trans->errnum;
+    }
+
+    values = apr_palloc(pool, sizeof(*values) * statement->nvals);
+
+    for (i = 0; i < statement->nvals; i++) {
+        values[i] = va_arg(args, const char*);
+    }
+
+    return dbd_pgsql_pquery(pool, sql, nrows, statement, values);
+}
+
+static int dbd_pgsql_pselect_internal(apr_pool_t *pool, apr_dbd_t *sql,
+                                      apr_dbd_results_t **results,
+                                      apr_dbd_prepared_t *statement,
+                                      int seek, const char **values,
+                                      const int *len, const int *fmt)
+{
+    PGresult *res;
+    int rv;
+    int ret = 0;
+
+    if (seek) { /* synchronous query */
+        if (TXN_IGNORE_ERRORS(sql->trans)) {
+            PGresult *res = PQexec(sql->conn, "SAVEPOINT APR_DBD_TXN_SP");
+            if (res) {
+                int ret = PQresultStatus(res);
+                PQclear(res);
+                if (!dbd_pgsql_is_success(ret)) {
+                    sql->trans->errnum = ret;
+                    return PGRES_FATAL_ERROR;
+                }
+            } else {
+                sql->trans->errnum = ret;
+                return PGRES_FATAL_ERROR;
+            }
+        }
+        if (statement->prepared) {
+            res = PQexecPrepared(sql->conn, statement->name, statement->nargs,
+                                 values, len, fmt, 0);
+        }
+        else {
+            res = PQexecParams(sql->conn, statement->name, statement->nargs, 0,
+                               values, len, fmt, 0);
+        }
+        if (res) {
+            ret = PQresultStatus(res);
+            if (dbd_pgsql_is_success(ret)) {
+                ret = 0;
+            }
+            else {
+                PQclear(res);
+            }
+        }
+        else {
+            ret = PGRES_FATAL_ERROR;
+        }
+        if (ret != 0) {
+            if (TXN_IGNORE_ERRORS(sql->trans)) {
+                PGresult *res = PQexec(sql->conn,
+                                       "ROLLBACK TO SAVEPOINT APR_DBD_TXN_SP");
+                if (res) {
+                    int ret = PQresultStatus(res);
+                    PQclear(res);
+                    if (!dbd_pgsql_is_success(ret)) {
+                        sql->trans->errnum = ret;
+                        return PGRES_FATAL_ERROR;
+                    }
+                } else {
+                    sql->trans->errnum = ret;
+                    return PGRES_FATAL_ERROR;
+                }
+            } else if (TXN_NOTICE_ERRORS(sql->trans)){
+                sql->trans->errnum = ret;
+            }
+            return ret;
+        } else {
+            if (TXN_IGNORE_ERRORS(sql->trans)) {
+                PGresult *res = PQexec(sql->conn,
+                                       "RELEASE SAVEPOINT APR_DBD_TXN_SP");
+                if (res) {
+                    int ret = PQresultStatus(res);
+                    PQclear(res);
+                    if (!dbd_pgsql_is_success(ret)) {
+                        sql->trans->errnum = ret;
+                        return PGRES_FATAL_ERROR;
+                    }
+                } else {
+                    sql->trans->errnum = ret;
+                    return PGRES_FATAL_ERROR;
+                }
+            }
+        }
+        if (!*results) {
+            *results = apr_pcalloc(pool, sizeof(apr_dbd_results_t));
+        }
+        (*results)->res = res;
+        (*results)->ntuples = PQntuples(res);
+        (*results)->sz = PQnfields(res);
+        (*results)->random = seek;
+        (*results)->pool = pool;
+        apr_pool_cleanup_register(pool, res, clear_result,
+                                  apr_pool_cleanup_null);
+    }
+    else {
+        if (TXN_IGNORE_ERRORS(sql->trans)) {
+            PGresult *res = PQexec(sql->conn, "SAVEPOINT APR_DBD_TXN_SP");
+            if (res) {
+                int ret = PQresultStatus(res);
+                PQclear(res);
+                if (!dbd_pgsql_is_success(ret)) {
+                    sql->trans->errnum = ret;
+                    return PGRES_FATAL_ERROR;
+                }
+            } else {
+                sql->trans->errnum = ret;
+                return PGRES_FATAL_ERROR;
+            }
+        }
+        if (statement->prepared) {
+            rv = PQsendQueryPrepared(sql->conn, statement->name,
+                                     statement->nargs, values, len, fmt, 0);
+        }
+        else {
+            rv = PQsendQueryParams(sql->conn, statement->name,
+                                   statement->nargs, 0, values, len, fmt, 0);
+        }
+        if (rv == 0) {
+            if (TXN_IGNORE_ERRORS(sql->trans)) {
+                PGresult *res = PQexec(sql->conn,
+                                       "ROLLBACK TO SAVEPOINT APR_DBD_TXN_SP");
+                if (res) {
+                    int ret = PQresultStatus(res);
+                    PQclear(res);
+                    if (!dbd_pgsql_is_success(ret)) {
+                        sql->trans->errnum = ret;
+                        return PGRES_FATAL_ERROR;
+                    }
+                } else {
+                    sql->trans->errnum = ret;
+                    return PGRES_FATAL_ERROR;
+                }
+            } else if (TXN_NOTICE_ERRORS(sql->trans)){
+                sql->trans->errnum = 1;
+            }
+            return 1;
+        } else {
+            if (TXN_IGNORE_ERRORS(sql->trans)) {
+                PGresult *res = PQexec(sql->conn,
+                                       "RELEASE SAVEPOINT APR_DBD_TXN_SP");
+                if (res) {
+                    int ret = PQresultStatus(res);
+                    PQclear(res);
+                    if (!dbd_pgsql_is_success(ret)) {
+                        sql->trans->errnum = ret;
+                        return PGRES_FATAL_ERROR;
+                    }
+                } else {
+                    sql->trans->errnum = ret;
+                    return PGRES_FATAL_ERROR;
+                }
+            }
+        }
+        if (!*results) {
+            *results = apr_pcalloc(pool, sizeof(apr_dbd_results_t));
+        }
+        (*results)->random = seek;
+        (*results)->handle = sql->conn;
+        (*results)->pool = pool;
+    }
+
+    return ret;
+}
+
+static int dbd_pgsql_pselect(apr_pool_t *pool, apr_dbd_t *sql,
+                             apr_dbd_results_t **results,
+                             apr_dbd_prepared_t *statement,
+                             int seek, const char **values)
+{
+    int *len, *fmt;
+    const char **val;
+
+    if (sql->trans && sql->trans->errnum) {
+        return sql->trans->errnum;
+    }
+
+    val = apr_palloc(pool, sizeof(*val) * statement->nargs);
+    len = apr_pcalloc(pool, sizeof(*len) * statement->nargs);
+    fmt = apr_pcalloc(pool, sizeof(*fmt) * statement->nargs);
+
+    dbd_pgsql_bind(statement, values, val, len, fmt);
+
+    return dbd_pgsql_pselect_internal(pool, sql, results, statement,
+                                      seek, val, len, fmt);
+}
+
+static int dbd_pgsql_pvselect(apr_pool_t *pool, apr_dbd_t *sql,
+                              apr_dbd_results_t **results,
+                              apr_dbd_prepared_t *statement,
+                              int seek, va_list args)
+{
+    const char **values;
+    int i;
+
+    if (sql->trans && sql->trans->errnum) {
+        return sql->trans->errnum;
+    }
+
+    values = apr_palloc(pool, sizeof(*values) * statement->nvals);
+
+    for (i = 0; i < statement->nvals; i++) {
+        values[i] = va_arg(args, const char*);
+    }
+
+    return dbd_pgsql_pselect(pool, sql, results, statement, seek, values);
+}
+
+static void dbd_pgsql_bbind(apr_pool_t *pool, apr_dbd_prepared_t * statement,
+                            const void **values,
+                            const char **val, int *len, int *fmt)
+{
+    int i, j;
+    apr_dbd_type_e type;
+
+    for (i = 0, j = 0; i < statement->nargs; i++, j++) {
+        type = (values[j] == NULL ? APR_DBD_TYPE_NULL : statement->types[i]);
+
+        switch (type) {
+        case APR_DBD_TYPE_TINY:
+            val[i] = apr_itoa(pool, *(char*)values[j]);
+            break;
+        case APR_DBD_TYPE_UTINY:
+            val[i] = apr_itoa(pool, *(unsigned char*)values[j]);
+            break;
+        case APR_DBD_TYPE_SHORT:
+            val[i] = apr_itoa(pool, *(short*)values[j]);
+            break;
+        case APR_DBD_TYPE_USHORT:
+            val[i] = apr_itoa(pool, *(unsigned short*)values[j]);
+            break;
+        case APR_DBD_TYPE_INT:
+            val[i] = apr_itoa(pool, *(int*)values[j]);
+            break;
+        case APR_DBD_TYPE_UINT:
+            val[i] = apr_itoa(pool, *(unsigned int*)values[j]);
+            break;
+        case APR_DBD_TYPE_LONG:
+            val[i] = apr_ltoa(pool, *(long*)values[j]);
+            break;
+        case APR_DBD_TYPE_ULONG:
+            val[i] = apr_ltoa(pool, *(unsigned long*)values[j]);
+            break;
+        case APR_DBD_TYPE_LONGLONG:
+            val[i] = apr_psprintf(pool, "%" APR_INT64_T_FMT,
+                                  *(apr_int64_t*)values[j]);
+            break;
+        case APR_DBD_TYPE_ULONGLONG:
+            val[i] = apr_psprintf(pool, "%" APR_UINT64_T_FMT,
+                                  *(apr_uint64_t*)values[j]);
+            break;
+        case APR_DBD_TYPE_FLOAT:
+            val[i] = apr_psprintf(pool, "%f", *(float*)values[j]);
+            break;
+        case APR_DBD_TYPE_DOUBLE:
+            val[i] = apr_psprintf(pool, "%lf", *(double*)values[j]);
+            break;
+        case APR_DBD_TYPE_STRING:
+        case APR_DBD_TYPE_TEXT:
+        case APR_DBD_TYPE_TIME:
+        case APR_DBD_TYPE_DATE:
+        case APR_DBD_TYPE_DATETIME:
+        case APR_DBD_TYPE_TIMESTAMP:
+        case APR_DBD_TYPE_ZTIMESTAMP:
+            val[i] = values[j];
+            break;
+        case APR_DBD_TYPE_BLOB:
+        case APR_DBD_TYPE_CLOB:
+            val[i] = (char*)values[j];
+            len[i] = *(apr_size_t*)values[++j];
+            fmt[i] = 1;
+
+            /* skip table and column */
+            j += 2;
+            break;
+        case APR_DBD_TYPE_NULL:
+        default:
+            val[i] = NULL;
+            break;
+        }
+    }
+
+    return;
+}
+
+static int dbd_pgsql_pbquery(apr_pool_t * pool, apr_dbd_t * sql,
+                             int *nrows, apr_dbd_prepared_t * statement,
+                             const void **values)
+{
+    int *len, *fmt;
+    const char **val;
+
+    if (sql->trans && sql->trans->errnum) {
+        return sql->trans->errnum;
+    }
+
+    val = apr_palloc(pool, sizeof(*val) * statement->nargs);
+    len = apr_pcalloc(pool, sizeof(*len) * statement->nargs);
+    fmt = apr_pcalloc(pool, sizeof(*fmt) * statement->nargs);
+
+    dbd_pgsql_bbind(pool, statement, values, val, len, fmt);
+
+    return dbd_pgsql_pquery_internal(pool, sql, nrows, statement,
+                                     val, len, fmt);
+}
+
+static int dbd_pgsql_pvbquery(apr_pool_t * pool, apr_dbd_t * sql,
+                              int *nrows, apr_dbd_prepared_t * statement,
+                              va_list args)
+{
+    const void **values;
+    int i;
+
+    if (sql->trans && sql->trans->errnum) {
+        return sql->trans->errnum;
+    }
+
+    values = apr_palloc(pool, sizeof(*values) * statement->nvals);
+
+    for (i = 0; i < statement->nvals; i++) {
+        values[i] = va_arg(args, const void*);
+    }
+
+    return dbd_pgsql_pbquery(pool, sql, nrows, statement, values);
+}
+
+static int dbd_pgsql_pbselect(apr_pool_t * pool, apr_dbd_t * sql,
+                              apr_dbd_results_t ** results,
+                              apr_dbd_prepared_t * statement,
+                              int seek, const void **values)
+{
+    int *len, *fmt;
+    const char **val;
+
+    if (sql->trans && sql->trans->errnum) {
+        return sql->trans->errnum;
+    }
+
+    val = apr_palloc(pool, sizeof(*val) * statement->nargs);
+    len = apr_pcalloc(pool, sizeof(*len) * statement->nargs);
+    fmt = apr_pcalloc(pool, sizeof(*fmt) * statement->nargs);
+
+    dbd_pgsql_bbind(pool, statement, values, val, len, fmt);
+
+    return dbd_pgsql_pselect_internal(pool, sql, results, statement,
+                                      seek, val, len, fmt);
+}
+
+static int dbd_pgsql_pvbselect(apr_pool_t * pool, apr_dbd_t * sql,
+                               apr_dbd_results_t ** results,
+                               apr_dbd_prepared_t * statement, int seek,
+                               va_list args)
+{
+    const void **values;
+    int i;
+
+    if (sql->trans && sql->trans->errnum) {
+        return sql->trans->errnum;
+    }
+
+    values = apr_palloc(pool, sizeof(*values) * statement->nvals);
+
+    for (i = 0; i < statement->nvals; i++) {
+        values[i] = va_arg(args, const void*);
+    }
+
+    return dbd_pgsql_pbselect(pool, sql, results, statement, seek, values);
+}
+
+static int dbd_pgsql_start_transaction(apr_pool_t *pool, apr_dbd_t *handle,
+                                       apr_dbd_transaction_t **trans)
+{
+    int ret = 0;
+    PGresult *res;
+
+    /* XXX handle recursive transactions here */
+
+    res = PQexec(handle->conn, "BEGIN TRANSACTION");
+    if (res) {
+        ret = PQresultStatus(res);
+        if (dbd_pgsql_is_success(ret)) {
+            ret = 0;
+            if (!*trans) {
+                *trans = apr_pcalloc(pool, sizeof(apr_dbd_transaction_t));
+            }
+        }
+        PQclear(res);
+        (*trans)->handle = handle;
+        handle->trans = *trans;
+    }
+    else {
+        ret = PGRES_FATAL_ERROR;
+    }
+    return ret;
+}
+
+static int dbd_pgsql_end_transaction(apr_dbd_transaction_t *trans)
+{
+    PGresult *res;
+    int ret = -1;                /* no transaction is an error cond */
+    if (trans) {
+        /* rollback on error or explicit rollback request */
+        if (trans->errnum || TXN_DO_ROLLBACK(trans)) {
+            trans->errnum = 0;
+            res = PQexec(trans->handle->conn, "ROLLBACK");
+        }
+        else {
+            res = PQexec(trans->handle->conn, "COMMIT");
+        }
+        if (res) {
+            ret = PQresultStatus(res);
+            if (dbd_pgsql_is_success(ret)) {
+                ret = 0;
+            }
+            PQclear(res);
+        }
+        else {
+            ret = PGRES_FATAL_ERROR;
+        }
+        trans->handle->trans = NULL;
+    }
+    return ret;
+}
+
+static int dbd_pgsql_transaction_mode_get(apr_dbd_transaction_t *trans)
+{
+    if (!trans)
+        return APR_DBD_TRANSACTION_COMMIT;
+
+    return trans->mode;
+}
+
+static int dbd_pgsql_transaction_mode_set(apr_dbd_transaction_t *trans,
+                                          int mode)
+{
+    if (!trans)
+        return APR_DBD_TRANSACTION_COMMIT;
+
+    return trans->mode = (mode & TXN_MODE_BITS);
+}
+
+static void null_notice_receiver(void *arg, const PGresult *res)
+{
+    /* nothing */
+}
+
+static void null_notice_processor(void *arg, const char *message)
+{
+    /* nothing */
+}
+
+static apr_dbd_t *dbd_pgsql_open(apr_pool_t *pool, const char *params,
+                                 const char **error)
+{
+    apr_dbd_t *sql;
+    
+    PGconn *conn = PQconnectdb(params);
+
+    /* if there's an error in the connect string or something we get
+     * back a * bogus connection object, and things like PQreset are
+     * liable to segfault, so just close it out now.  it would be nice
+     * if we could give an indication of why we failed to connect... */
+    if (PQstatus(conn) != CONNECTION_OK) {
+        if (error) {
+            *error = apr_pstrdup(pool, PQerrorMessage(conn));
+        }
+        PQfinish(conn);
+        return NULL;
+    }
+
+    PQsetNoticeReceiver(conn, null_notice_receiver, NULL);
+    PQsetNoticeProcessor(conn, null_notice_processor, NULL);
+
+    sql = apr_pcalloc (pool, sizeof (*sql));
+
+    sql->conn = conn;
+
+    return sql;
+}
+
+static apr_status_t dbd_pgsql_close(apr_dbd_t *handle)
+{
+    PQfinish(handle->conn);
+    return APR_SUCCESS;
+}
+
+static apr_status_t dbd_pgsql_check_conn(apr_pool_t *pool,
+                                         apr_dbd_t *handle)
+{
+    if (PQstatus(handle->conn) != CONNECTION_OK) {
+        PQreset(handle->conn);
+        if (PQstatus(handle->conn) != CONNECTION_OK) {
+            return APR_EGENERAL;
+        }
+    }
+    return APR_SUCCESS;
+}
+
+static int dbd_pgsql_select_db(apr_pool_t *pool, apr_dbd_t *handle,
+                               const char *name)
+{
+    return APR_ENOTIMPL;
+}
+
+static void *dbd_pgsql_native(apr_dbd_t *handle)
+{
+    return handle->conn;
+}
+
+static int dbd_pgsql_num_cols(apr_dbd_results_t* res)
+{
+    return res->sz;
+}
+
+static int dbd_pgsql_num_tuples(apr_dbd_results_t* res)
+{
+    if (res->random) {
+        return res->ntuples;
+    }
+    else {
+        return -1;
+    }
+}
+
+APR_MODULE_DECLARE_DATA const apr_dbd_driver_t apr_dbd_pgsql_driver = {
+    "pgsql",
+    NULL,
+    dbd_pgsql_native,
+    dbd_pgsql_open,
+    dbd_pgsql_check_conn,
+    dbd_pgsql_close,
+    dbd_pgsql_select_db,
+    dbd_pgsql_start_transaction,
+    dbd_pgsql_end_transaction,
+    dbd_pgsql_query,
+    dbd_pgsql_select,
+    dbd_pgsql_num_cols,
+    dbd_pgsql_num_tuples,
+    dbd_pgsql_get_row,
+    dbd_pgsql_get_entry,
+    dbd_pgsql_error,
+    dbd_pgsql_escape,
+    dbd_pgsql_prepare,
+    dbd_pgsql_pvquery,
+    dbd_pgsql_pvselect,
+    dbd_pgsql_pquery,
+    dbd_pgsql_pselect,
+    dbd_pgsql_get_name,
+    dbd_pgsql_transaction_mode_get,
+    dbd_pgsql_transaction_mode_set,
+    "$%d",
+    dbd_pgsql_pvbquery,
+    dbd_pgsql_pvbselect,
+    dbd_pgsql_pbquery,
+    dbd_pgsql_pbselect,
+    dbd_pgsql_datum_get
+};
+#endif
diff --git a/dbd/apr_dbd_pgsql.dsp b/dbd/apr_dbd_pgsql.dsp
new file mode 100644
index 00000000000..03526576fd3
--- /dev/null
+++ b/dbd/apr_dbd_pgsql.dsp
@@ -0,0 +1,207 @@
+# Microsoft Developer Studio Project File - Name="apr_dbd_pgsql" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=apr_dbd_pgsql - 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 "apr_dbd_pgsql.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 "apr_dbd_pgsql.mak" CFG="apr_dbd_pgsql - Win32 Release"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "apr_dbd_pgsql - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_dbd_pgsql - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_dbd_pgsql - x64 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_dbd_pgsql - x64 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)" == "apr_dbd_pgsql - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /Zi /O2 /Oy- /I "../include" /I "../include/arch/win32" /I "../include/private" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_PGSQL=1 /D "HAVE_LIBPQ_FE_H" /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbd_pgsql_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /fo"Release/apr_dbd_pgsql-1.res" /d DLL_NAME="apr_dbd_pgsql" /d "NDEBUG" /d "APU_VERSION_ONLY" /I "../include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libpq.lib /nologo /base:"0x6EF30000" /subsystem:windows /dll /incremental:no /debug /opt:ref
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libpq.lib /nologo /base:"0x6EF30000" /subsystem:windows /dll /incremental:no /debug /out:"Release\apr_dbd_pgsql-1.dll" /pdb:"Release\apr_dbd_pgsql-1.pdb" /implib:"Release\apr_dbd_pgsql-1.lib" /MACHINE:X86 /opt:ref
+# Begin Special Build Tool
+TargetPath=Release\apr_dbd_pgsql-1.dll
+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)" == "apr_dbd_pgsql - 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 /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /EHsc /c
+# ADD CPP /nologo /MDd /W3 /Zi /Od /I "../include" /I "../include/arch/win32" /I "../include/private" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_PGSQL=1 /D "HAVE_LIBPQ_FE_H" /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbd_pgsql_src" /FD /EHsc /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /fo"Debug/apr_dbd_pgsql-1.res" /d DLL_NAME="apr_dbd_pgsql" /d "_DEBUG" /d "APU_VERSION_ONLY" /I "../include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libpq.lib /nologo /base:"0x6EF30000" /subsystem:windows /dll /incremental:no /debug
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libpq.lib /nologo /base:"0x6EF30000" /subsystem:windows /dll /incremental:no /debug /out:"Debug\apr_dbd_pgsql-1.dll" /pdb:"Debug\apr_dbd_pgsql-1.pdb" /implib:"Debug\apr_dbd_pgsql-1.lib" /MACHINE:X86
+# Begin Special Build Tool
+TargetPath=Debug\apr_dbd_pgsql-1.dll
+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)" == "apr_dbd_pgsql - x64 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "x64\Release"
+# PROP BASE Intermediate_Dir "x64\Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "x64\Release"
+# PROP Intermediate_Dir "x64\Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /Zi /O2 /Oy- /I "../include" /I "../include/arch/win32" /I "../include/private" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_PGSQL=1 /D "HAVE_LIBPQ_FE_H" /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbd_pgsql_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /fo"x64/Release/apr_dbd_pgsql-1.res" /d DLL_NAME="apr_dbd_pgsql" /d "NDEBUG" /d "APU_VERSION_ONLY" /I "../include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libpq.lib /nologo /base:"0x6EF30000" /subsystem:windows /dll /incremental:no /debug /opt:ref
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libpq.lib /nologo /base:"0x6EF30000" /subsystem:windows /dll /incremental:no /debug /out:"x64\Release\apr_dbd_pgsql-1.dll" /pdb:"x64\Release\apr_dbd_pgsql-1.pdb" /implib:"x64\Release\apr_dbd_pgsql-1.lib" /MACHINE:X64 /opt:ref
+# Begin Special Build Tool
+TargetPath=x64\Release\apr_dbd_pgsql-1.dll
+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)" == "apr_dbd_pgsql - x64 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "x64\Debug"
+# PROP BASE Intermediate_Dir "x64\Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "x64\Debug"
+# PROP Intermediate_Dir "x64\Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /EHsc /c
+# ADD CPP /nologo /MDd /W3 /Zi /Od /I "../include" /I "../include/arch/win32" /I "../include/private" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_PGSQL=1 /D "HAVE_LIBPQ_FE_H" /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbd_pgsql_src" /FD /EHsc /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /fo"x64/Debug/apr_dbd_pgsql-1.res" /d DLL_NAME="apr_dbd_pgsql" /d "_DEBUG" /d "APU_VERSION_ONLY" /I "../include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libpq.lib /nologo /base:"0x6EF30000" /subsystem:windows /dll /incremental:no /debug
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libpq.lib /nologo /base:"0x6EF30000" /subsystem:windows /dll /incremental:no /debug /out:"x64\Debug\apr_dbd_pgsql-1.dll" /pdb:"x64\Debug\apr_dbd_pgsql-1.pdb" /implib:"x64\Debug\apr_dbd_pgsql-1.lib" /MACHINE:X64
+# Begin Special Build Tool
+TargetPath=x64\Debug\apr_dbd_pgsql-1.dll
+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 "apr_dbd_pgsql - Win32 Release"
+# Name "apr_dbd_pgsql - Win32 Debug"
+# Name "apr_dbd_pgsql - x64 Release"
+# Name "apr_dbd_pgsql - x64 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\apr_dbd_pgsql.c
+# End Source File
+# End Group
+# Begin Group "Public Header Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\include\apr_dbd.h
+# End Source File
+# End Group
+# Begin Group "Internal Header Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\include\private\apu_config.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\private\apu_dbd_internal.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\private\apu_internal.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\libapr.rc
+# End Source File
+# End Target
+# End Project
diff --git a/dbd/apr_dbd_sqlite2.c b/dbd/apr_dbd_sqlite2.c
new file mode 100644
index 00000000000..af72b931fbd
--- /dev/null
+++ b/dbd/apr_dbd_sqlite2.c
@@ -0,0 +1,567 @@
+/* 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 "apu.h"
+#include "apr_private.h"
+
+#if APU_HAVE_SQLITE2
+
+#include <ctype.h>
+#include <stdlib.h>
+
+#include <sqlite.h>
+
+#include "apr_strings.h"
+#include "apr_time.h"
+#include "apr_buckets.h"
+
+#include "apr_dbd_internal.h"
+
+struct apr_dbd_transaction_t {
+    int mode;
+    int errnum;
+    apr_dbd_t *handle;
+};
+
+struct apr_dbd_t {
+    sqlite *conn;
+    char *errmsg;
+    apr_dbd_transaction_t *trans;
+};
+
+struct apr_dbd_results_t {
+    int random;
+    sqlite *handle;
+    char **res;
+    size_t ntuples;
+    size_t sz;
+    size_t index;
+    apr_pool_t *pool;
+};
+
+struct apr_dbd_row_t {
+    int n;
+    char **data;
+    apr_dbd_results_t *res;
+};
+
+struct apr_dbd_prepared_t {
+    const char *name;
+    int prepared;
+};
+
+#define FREE_ERROR_MSG(dbd) \
+	do { \
+		if(dbd && dbd->errmsg) { \
+			free(dbd->errmsg); \
+			dbd->errmsg = NULL; \
+		} \
+	} while(0);
+
+static apr_status_t free_table(void *data)
+{
+    sqlite_free_table(data); 
+    return APR_SUCCESS;
+}
+
+static int dbd_sqlite_select(apr_pool_t * pool, apr_dbd_t * sql,
+                             apr_dbd_results_t ** results, const char *query,
+                             int seek)
+{
+    char **result;
+    int ret = 0;
+    int tuples = 0;
+    int fields = 0;
+
+    if (sql->trans && sql->trans->errnum) {
+        return sql->trans->errnum;
+    }
+
+    FREE_ERROR_MSG(sql);
+
+    ret = sqlite_get_table(sql->conn, query, &result, &tuples, &fields,
+                          &sql->errmsg);
+
+    if (ret == SQLITE_OK) {
+        if (!*results) {
+            *results = apr_pcalloc(pool, sizeof(apr_dbd_results_t));
+        }
+
+        (*results)->res = result;
+        (*results)->ntuples = tuples;
+        (*results)->sz = fields;
+        (*results)->random = seek;
+        (*results)->pool = pool;
+
+        if (tuples > 0)
+            apr_pool_cleanup_register(pool, result, free_table,
+                                      apr_pool_cleanup_null);
+
+        ret = 0;
+    }
+    else {
+        if (TXN_NOTICE_ERRORS(sql->trans)) {
+            sql->trans->errnum = ret;
+        }
+    }
+
+    return ret;
+}
+
+static const char *dbd_sqlite_get_name(const apr_dbd_results_t *res, int n)
+{
+    if ((n < 0) || (n >= res->sz)) {
+        return NULL;
+    }
+
+    return res->res[n];
+}
+
+static int dbd_sqlite_get_row(apr_pool_t * pool, apr_dbd_results_t * res,
+                              apr_dbd_row_t ** rowp, int rownum)
+{
+    apr_dbd_row_t *row = *rowp;
+    int sequential = ((rownum >= 0) && res->random) ? 0 : 1;
+
+    if (row == NULL) {
+        row = apr_palloc(pool, sizeof(apr_dbd_row_t));
+        *rowp = row;
+        row->res = res;
+        row->n = sequential ? 0 : rownum - 1;
+    }
+    else {
+        if (sequential) {
+            ++row->n;
+        }
+        else {
+            row->n = rownum - 1;
+        }
+    }
+
+    if (row->n >= res->ntuples) {
+        *rowp = NULL;
+        apr_pool_cleanup_run(res->pool, res->res, free_table);
+        res->res = NULL;
+        return -1;
+    }
+
+    /* Pointer magic explanation:
+     *      The sqlite result is an array such that the first res->sz elements are 
+     *      the column names and each tuple follows afterwards 
+     *      ex: (from the sqlite2 documentation)
+     SELECT employee_name, login, host FROM users WHERE login LIKE *        'd%';
+
+     nrow = 2
+     ncolumn = 3
+     result[0] = "employee_name"
+     result[1] = "login"
+     result[2] = "host"
+     result[3] = "dummy"
+     result[4] = "No such user"
+     result[5] = 0
+     result[6] = "D. Richard Hipp"
+     result[7] = "drh"
+     result[8] = "zadok"
+     */
+
+    row->data = res->res + res->sz + (res->sz * row->n);
+
+    return 0;
+}
+
+static const char *dbd_sqlite_get_entry(const apr_dbd_row_t * row, int n)
+{
+    if ((n < 0) || (n >= row->res->sz)) {
+      return NULL;
+    }
+
+    return row->data[n];
+}
+
+static apr_status_t dbd_sqlite_datum_get(const apr_dbd_row_t *row, int n,
+                                         apr_dbd_type_e type, void *data)
+{
+    if ((n < 0) || (n >= row->res->sz)) {
+      return APR_EGENERAL;
+    }
+
+    if (row->data[n] == NULL) {
+        return APR_ENOENT;
+    }
+
+    switch (type) {
+    case APR_DBD_TYPE_TINY:
+        *(char*)data = atoi(row->data[n]);
+        break;
+    case APR_DBD_TYPE_UTINY:
+        *(unsigned char*)data = atoi(row->data[n]);
+        break;
+    case APR_DBD_TYPE_SHORT:
+        *(short*)data = atoi(row->data[n]);
+        break;
+    case APR_DBD_TYPE_USHORT:
+        *(unsigned short*)data = atoi(row->data[n]);
+        break;
+    case APR_DBD_TYPE_INT:
+        *(int*)data = atoi(row->data[n]);
+        break;
+    case APR_DBD_TYPE_UINT:
+        *(unsigned int*)data = atoi(row->data[n]);
+        break;
+    case APR_DBD_TYPE_LONG:
+        *(long*)data = atol(row->data[n]);
+        break;
+    case APR_DBD_TYPE_ULONG:
+        *(unsigned long*)data = atol(row->data[n]);
+        break;
+    case APR_DBD_TYPE_LONGLONG:
+        *(apr_int64_t*)data = apr_atoi64(row->data[n]);
+        break;
+    case APR_DBD_TYPE_ULONGLONG:
+        *(apr_uint64_t*)data = apr_atoi64(row->data[n]);
+        break;
+    case APR_DBD_TYPE_FLOAT:
+        *(float*)data = atof(row->data[n]);
+        break;
+    case APR_DBD_TYPE_DOUBLE:
+        *(double*)data = atof(row->data[n]);
+        break;
+    case APR_DBD_TYPE_STRING:
+    case APR_DBD_TYPE_TEXT:
+    case APR_DBD_TYPE_TIME:
+    case APR_DBD_TYPE_DATE:
+    case APR_DBD_TYPE_DATETIME:
+    case APR_DBD_TYPE_TIMESTAMP:
+    case APR_DBD_TYPE_ZTIMESTAMP:
+        *(char**)data = row->data[n];
+        break;
+    case APR_DBD_TYPE_BLOB:
+    case APR_DBD_TYPE_CLOB:
+        {
+        apr_bucket *e;
+        apr_bucket_brigade *b = (apr_bucket_brigade*)data;
+
+        e = apr_bucket_pool_create(row->data[n],strlen(row->data[n]),
+                                   row->res->pool, b->bucket_alloc);
+        APR_BRIGADE_INSERT_TAIL(b, e);
+        }
+        break;
+    case APR_DBD_TYPE_NULL:
+        *(void**)data = NULL;
+        break;
+    default:
+        return APR_EGENERAL;
+    }
+
+    return APR_SUCCESS;
+}
+
+static const char *dbd_sqlite_error(apr_dbd_t * sql, int n)
+{
+    return sql->errmsg;
+}
+
+static int dbd_sqlite_query(apr_dbd_t * sql, int *nrows, const char *query)
+{
+    char **result;
+    int ret;
+    int tuples = 0;
+    int fields = 0;
+
+    if (sql->trans && sql->trans->errnum) {
+        return sql->trans->errnum;
+    }
+
+    FREE_ERROR_MSG(sql);
+
+    ret =
+        sqlite_get_table(sql->conn, query, &result, &tuples, &fields,
+                         &sql->errmsg);
+    if (ret == SQLITE_OK) {
+        *nrows = sqlite_changes(sql->conn);
+
+        if (tuples > 0)
+            free(result);
+
+        ret = 0;
+    }
+
+    if (TXN_NOTICE_ERRORS(sql->trans)) {
+        sql->trans->errnum = ret;
+    }
+
+    return ret;
+}
+
+static apr_status_t free_mem(void *data)
+{
+    sqlite_freemem(data);
+    return APR_SUCCESS;
+}
+
+static const char *dbd_sqlite_escape(apr_pool_t * pool, const char *arg,
+                                     apr_dbd_t * sql)
+{
+    char *ret = sqlite_mprintf("%q", arg);
+    apr_pool_cleanup_register(pool, ret, free_mem, apr_pool_cleanup_null);
+    return ret;
+}
+
+static int dbd_sqlite_prepare(apr_pool_t * pool, apr_dbd_t * sql,
+                              const char *query, const char *label,
+                              int nargs, int nvals, apr_dbd_type_e *types,
+                              apr_dbd_prepared_t ** statement)
+{
+    return APR_ENOTIMPL;
+}
+
+static int dbd_sqlite_pquery(apr_pool_t * pool, apr_dbd_t * sql,
+                             int *nrows, apr_dbd_prepared_t * statement,
+                             const char **values)
+{
+    return APR_ENOTIMPL;
+}
+
+static int dbd_sqlite_pvquery(apr_pool_t * pool, apr_dbd_t * sql,
+                              int *nrows, apr_dbd_prepared_t * statement,
+                              va_list args)
+{
+    return APR_ENOTIMPL;
+}
+
+static int dbd_sqlite_pselect(apr_pool_t * pool, apr_dbd_t * sql,
+                              apr_dbd_results_t ** results,
+                              apr_dbd_prepared_t * statement,
+                              int seek, const char **values)
+{
+    return APR_ENOTIMPL;
+}
+
+static int dbd_sqlite_pvselect(apr_pool_t * pool, apr_dbd_t * sql,
+                               apr_dbd_results_t ** results,
+                               apr_dbd_prepared_t * statement, int seek,
+                               va_list args)
+{
+    return APR_ENOTIMPL;
+}
+
+static int dbd_sqlite_pbquery(apr_pool_t * pool, apr_dbd_t * sql,
+                              int *nrows, apr_dbd_prepared_t * statement,
+                              const void **values)
+{
+    return APR_ENOTIMPL;
+}
+
+static int dbd_sqlite_pvbquery(apr_pool_t * pool, apr_dbd_t * sql,
+                               int *nrows, apr_dbd_prepared_t * statement,
+                               va_list args)
+{
+    return APR_ENOTIMPL;
+}
+
+static int dbd_sqlite_pbselect(apr_pool_t * pool, apr_dbd_t * sql,
+                               apr_dbd_results_t ** results,
+                               apr_dbd_prepared_t * statement,
+                               int seek, const void **values)
+{
+    return APR_ENOTIMPL;
+}
+
+static int dbd_sqlite_pvbselect(apr_pool_t * pool, apr_dbd_t * sql,
+                                apr_dbd_results_t ** results,
+                                apr_dbd_prepared_t * statement, int seek,
+                                va_list args)
+{
+    return APR_ENOTIMPL;
+}
+
+static int dbd_sqlite_start_transaction(apr_pool_t * pool, apr_dbd_t * handle,
+                                        apr_dbd_transaction_t ** trans)
+{
+    int ret, rows;
+
+    ret = dbd_sqlite_query(handle, &rows, "BEGIN TRANSACTION");
+    if (ret == 0) {
+        if (!*trans) {
+            *trans = apr_pcalloc(pool, sizeof(apr_dbd_transaction_t));
+        }
+        (*trans)->handle = handle;
+        handle->trans = *trans;
+    }
+    else {
+        ret = -1;
+    }
+    return ret;
+}
+
+static int dbd_sqlite_end_transaction(apr_dbd_transaction_t * trans)
+{
+    int rows;
+    int ret = -1;               /* no transaction is an error cond */
+
+    if (trans) {
+        /* rollback on error or explicit rollback request */
+        if (trans->errnum || TXN_DO_ROLLBACK(trans)) {
+            trans->errnum = 0;
+            ret =
+                dbd_sqlite_query(trans->handle, &rows,
+                                 "ROLLBACK TRANSACTION");
+        }
+        else {
+            ret =
+                dbd_sqlite_query(trans->handle, &rows, "COMMIT TRANSACTION");
+        }
+        trans->handle->trans = NULL;
+    }
+
+    return ret;
+}
+
+static int dbd_sqlite_transaction_mode_get(apr_dbd_transaction_t *trans)
+{
+    if (!trans)
+        return APR_DBD_TRANSACTION_COMMIT;
+
+    return trans->mode;
+}
+
+static int dbd_sqlite_transaction_mode_set(apr_dbd_transaction_t *trans,
+                                           int mode)
+{
+    if (!trans)
+        return APR_DBD_TRANSACTION_COMMIT;
+
+    return trans->mode = (mode & TXN_MODE_BITS);
+}
+
+static apr_status_t error_free(void *data)
+{
+    free(data);
+    return APR_SUCCESS;
+}
+
+static apr_dbd_t *dbd_sqlite_open(apr_pool_t * pool, const char *params_,
+                                  const char **error)
+{
+    apr_dbd_t *sql;
+    sqlite *conn = NULL;
+    char *perm;
+    int iperms = 600;
+    char* params = apr_pstrdup(pool, params_);
+    /* params = "[filename]:[permissions]"
+     *    example: "shopping.db:600"
+     */
+
+    perm = strstr(params, ":");
+    if (perm) {
+        *(perm++) = '\x00';     /* split the filename and permissions */
+
+        if (strlen(perm) > 0)
+            iperms = atoi(perm);
+    }
+
+    if (error) {
+        *error = NULL;
+
+        conn = sqlite_open(params, iperms, (char **)error);
+
+        if (*error) {
+            apr_pool_cleanup_register(pool, *error, error_free,
+                                      apr_pool_cleanup_null);
+        }
+    }
+    else {
+        conn = sqlite_open(params, iperms, NULL);
+    }
+
+    sql = apr_pcalloc(pool, sizeof(*sql));
+    sql->conn = conn;
+
+    return sql;
+}
+
+static apr_status_t dbd_sqlite_close(apr_dbd_t * handle)
+{
+    if (handle->conn) {
+        sqlite_close(handle->conn);
+        handle->conn = NULL;
+    }
+    return APR_SUCCESS;
+}
+
+static apr_status_t dbd_sqlite_check_conn(apr_pool_t * pool,
+                                          apr_dbd_t * handle)
+{
+    if (handle->conn == NULL)
+        return -1;
+    return APR_SUCCESS;
+}
+
+static int dbd_sqlite_select_db(apr_pool_t * pool, apr_dbd_t * handle,
+                                const char *name)
+{
+    return APR_ENOTIMPL;
+}
+
+static void *dbd_sqlite_native(apr_dbd_t * handle)
+{
+    return handle->conn;
+}
+
+static int dbd_sqlite_num_cols(apr_dbd_results_t * res)
+{
+    return res->sz;
+}
+
+static int dbd_sqlite_num_tuples(apr_dbd_results_t * res)
+{
+    return res->ntuples;
+}
+
+APR_MODULE_DECLARE_DATA const apr_dbd_driver_t apr_dbd_sqlite2_driver = {
+    "sqlite2",
+    NULL,
+    dbd_sqlite_native,
+    dbd_sqlite_open,
+    dbd_sqlite_check_conn,
+    dbd_sqlite_close,
+    dbd_sqlite_select_db,
+    dbd_sqlite_start_transaction,
+    dbd_sqlite_end_transaction,
+    dbd_sqlite_query,
+    dbd_sqlite_select,
+    dbd_sqlite_num_cols,
+    dbd_sqlite_num_tuples,
+    dbd_sqlite_get_row,
+    dbd_sqlite_get_entry,
+    dbd_sqlite_error,
+    dbd_sqlite_escape,
+    dbd_sqlite_prepare,
+    dbd_sqlite_pvquery,
+    dbd_sqlite_pvselect,
+    dbd_sqlite_pquery,
+    dbd_sqlite_pselect,
+    dbd_sqlite_get_name,
+    dbd_sqlite_transaction_mode_get,
+    dbd_sqlite_transaction_mode_set,
+    NULL,
+    dbd_sqlite_pvbquery,
+    dbd_sqlite_pvbselect,
+    dbd_sqlite_pbquery,
+    dbd_sqlite_pbselect,
+    dbd_sqlite_datum_get
+};
+#endif
diff --git a/dbd/apr_dbd_sqlite2.dsp b/dbd/apr_dbd_sqlite2.dsp
new file mode 100644
index 00000000000..8a0047e678a
--- /dev/null
+++ b/dbd/apr_dbd_sqlite2.dsp
@@ -0,0 +1,207 @@
+# Microsoft Developer Studio Project File - Name="apr_dbd_sqlite2" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=apr_dbd_sqlite2 - 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 "apr_dbd_sqlite2.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 "apr_dbd_sqlite2.mak" CFG="apr_dbd_sqlite2 - Win32 Release"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "apr_dbd_sqlite2 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_dbd_sqlite2 - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_dbd_sqlite2 - x64 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_dbd_sqlite2 - x64 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)" == "apr_dbd_sqlite2 - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /Zi /O2 /Oy- /I "../include" /I "../include/arch/win32" /I "../include/private" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_SQLITE2=1 /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbd_sqlite2_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /fo"Release/apr_dbd_sqlite2-1.res" /d DLL_NAME="apr_dbd_sqlite2" /d "NDEBUG" /d "APU_VERSION_ONLY" /I "../include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib sqlite2.lib /nologo /base:"0x6EF10000" /subsystem:windows /dll /incremental:no /debug /opt:ref
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib sqlite2.lib /nologo /base:"0x6EF10000" /subsystem:windows /dll /incremental:no /debug /out:"Release\apr_dbd_sqlite2-1.dll" /pdb:"Release\apr_dbd_sqlite2-1.pdb" /implib:"Release\apr_dbd_sqlite2-1.lib" /MACHINE:X86 /opt:ref
+# Begin Special Build Tool
+TargetPath=Release\apr_dbd_sqlite2-1.dll
+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)" == "apr_dbd_sqlite2 - 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 /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /EHsc /c
+# ADD CPP /nologo /MDd /W3 /Zi /Od /I "../include" /I "../include/arch/win32" /I "../include/private" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_SQLITE2=1 /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbd_sqlite2_src" /FD /EHsc /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /fo"Debug/apr_dbd_sqlite2-1.res" /d DLL_NAME="apr_dbd_sqlite2" /d "_DEBUG" /d "APU_VERSION_ONLY" /I "../include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib sqlite2.lib /nologo /base:"0x6EF10000" /subsystem:windows /dll /incremental:no /debug
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib sqlite2.lib /nologo /base:"0x6EF10000" /subsystem:windows /dll /incremental:no /debug /out:"Debug\apr_dbd_sqlite2-1.dll" /pdb:"Debug\apr_dbd_sqlite2-1.pdb" /implib:"Debug\apr_dbd_sqlite2-1.lib" /MACHINE:X86
+# Begin Special Build Tool
+TargetPath=Debug\apr_dbd_sqlite2-1.dll
+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)" == "apr_dbd_sqlite2 - x64 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "x64\Release"
+# PROP BASE Intermediate_Dir "x64\Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "x64\Release"
+# PROP Intermediate_Dir "x64\Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /Zi /O2 /Oy- /I "../include" /I "../include/arch/win32" /I "../include/private" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_SQLITE2=1 /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbd_sqlite2_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /fo"x64/Release/apr_dbd_sqlite2-1.res" /d DLL_NAME="apr_dbd_sqlite2" /d "NDEBUG" /d "APU_VERSION_ONLY" /I "../include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib sqlite2.lib /nologo /base:"0x6EF10000" /subsystem:windows /dll /incremental:no /debug /opt:ref
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib sqlite2.lib /nologo /base:"0x6EF10000" /subsystem:windows /dll /incremental:no /debug /out:"x64\Release\apr_dbd_sqlite2-1.dll" /pdb:"x64\Release\apr_dbd_sqlite2-1.pdb" /implib:"x64\Release\apr_dbd_sqlite2-1.lib" /MACHINE:X64 /opt:ref
+# Begin Special Build Tool
+TargetPath=x64\Release\apr_dbd_sqlite2-1.dll
+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)" == "apr_dbd_sqlite2 - x64 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "x64\Debug"
+# PROP BASE Intermediate_Dir "x64\Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "x64\Debug"
+# PROP Intermediate_Dir "x64\Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /EHsc /c
+# ADD CPP /nologo /MDd /W3 /Zi /Od /I "../include" /I "../include/arch/win32" /I "../include/private" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_SQLITE2=1 /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbd_sqlite2_src" /FD /EHsc /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /fo"x64/Debug/apr_dbd_sqlite2-1.res" /d DLL_NAME="apr_dbd_sqlite2" /d "_DEBUG" /d "APU_VERSION_ONLY" /I "../include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib sqlite2.lib /nologo /base:"0x6EF10000" /subsystem:windows /dll /incremental:no /debug
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib sqlite2.lib /nologo /base:"0x6EF10000" /subsystem:windows /dll /incremental:no /debug /out:"x64\Debug\apr_dbd_sqlite2-1.dll" /pdb:"x64\Debug\apr_dbd_sqlite2-1.pdb" /implib:"x64\Debug\apr_dbd_sqlite2-1.lib" /MACHINE:X64
+# Begin Special Build Tool
+TargetPath=x64\Debug\apr_dbd_sqlite2-1.dll
+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 "apr_dbd_sqlite2 - Win32 Release"
+# Name "apr_dbd_sqlite2 - Win32 Debug"
+# Name "apr_dbd_sqlite2 - x64 Release"
+# Name "apr_dbd_sqlite2 - x64 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\apr_dbd_sqlite2.c
+# End Source File
+# End Group
+# Begin Group "Public Header Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\include\apr_dbd.h
+# End Source File
+# End Group
+# Begin Group "Internal Header Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\include\private\apu_config.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\private\apu_dbd_internal.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\private\apu_internal.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\libapr.rc
+# End Source File
+# End Target
+# End Project
diff --git a/dbd/apr_dbd_sqlite3.c b/dbd/apr_dbd_sqlite3.c
new file mode 100644
index 00000000000..33f3034f787
--- /dev/null
+++ b/dbd/apr_dbd_sqlite3.c
@@ -0,0 +1,915 @@
+/* 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 "apu.h"
+#include "apr_private.h"
+
+#if APU_HAVE_SQLITE3
+
+#include <ctype.h>
+#include <stdlib.h>
+
+#include <sqlite3.h>
+
+#include "apr_strings.h"
+#include "apr_time.h"
+#include "apr_buckets.h"
+
+#include "apr_dbd_internal.h"
+
+#define MAX_RETRY_COUNT 15
+#define MAX_RETRY_SLEEP 100000
+
+struct apr_dbd_transaction_t {
+    int mode;
+    int errnum;
+    apr_dbd_t *handle;
+};
+
+struct apr_dbd_t {
+    sqlite3 *conn;
+    apr_dbd_transaction_t *trans;
+    apr_pool_t *pool;
+    apr_dbd_prepared_t *prep;
+};
+
+typedef struct {
+    char *name;
+    char *value;
+    int size;
+    int type;
+} apr_dbd_column_t;
+
+struct apr_dbd_row_t {
+    apr_dbd_results_t *res;
+    apr_dbd_column_t **columns;
+    apr_dbd_row_t *next_row;
+    int columnCount;
+    int rownum;
+};
+
+struct apr_dbd_results_t {
+    int random;
+    sqlite3 *handle;
+    sqlite3_stmt *stmt;
+    apr_dbd_row_t *next_row;
+    size_t sz;
+    int tuples;
+    char **col_names;
+    apr_pool_t *pool;
+};
+
+struct apr_dbd_prepared_t {
+    sqlite3_stmt *stmt;
+    apr_dbd_prepared_t *next;
+    int nargs;
+    int nvals;
+    apr_dbd_type_e *types;
+};
+
+#define dbd_sqlite3_is_success(x) (((x) == SQLITE_DONE) || ((x) == SQLITE_OK))
+
+static int dbd_sqlite3_select_internal(apr_pool_t *pool,
+                                       apr_dbd_t *sql,
+                                       apr_dbd_results_t **results,
+                                       sqlite3_stmt *stmt, int seek)
+{
+    int ret, retry_count = 0, column_count;
+    size_t i, num_tuples = 0;
+    int increment = 0;
+    apr_dbd_row_t *row = NULL;
+    apr_dbd_row_t *lastrow = NULL;
+    apr_dbd_column_t *column;
+    char *hold = NULL;
+
+    column_count = sqlite3_column_count(stmt);
+    if (!*results) {
+        *results = apr_pcalloc(pool, sizeof(apr_dbd_results_t));
+    }
+    (*results)->stmt = stmt;
+    (*results)->sz = column_count;
+    (*results)->random = seek;
+    (*results)->next_row = 0;
+    (*results)->tuples = 0;
+    (*results)->col_names = apr_pcalloc(pool, column_count * sizeof(char *));
+    (*results)->pool = pool;
+    do {
+        ret = sqlite3_step(stmt);
+        if (ret == SQLITE_BUSY) {
+            if (retry_count++ > MAX_RETRY_COUNT) {
+                ret = SQLITE_ERROR;
+            } else {
+                apr_dbd_mutex_unlock();
+                apr_sleep(MAX_RETRY_SLEEP);
+                apr_dbd_mutex_lock();
+            }
+        } else if (ret == SQLITE_ROW) {
+            int length;
+            row = apr_palloc(pool, sizeof(apr_dbd_row_t));
+            row->res = *results;
+            increment = sizeof(apr_dbd_column_t *);
+            length = increment * (*results)->sz;
+            row->columns = apr_palloc(pool, length);
+            row->columnCount = column_count;
+            for (i = 0; i < (*results)->sz; i++) {
+                column = apr_palloc(pool, sizeof(apr_dbd_column_t));
+                row->columns[i] = column;
+                /* copy column name once only */
+                if ((*results)->col_names[i] == NULL) {
+                    (*results)->col_names[i] =
+                        apr_pstrdup(pool, sqlite3_column_name(stmt, i));
+                }
+                column->name = (*results)->col_names[i];
+                column->size = sqlite3_column_bytes(stmt, i);
+                column->type = sqlite3_column_type(stmt, i);
+                column->value = NULL;
+                switch (column->type) {
+                case SQLITE_FLOAT:
+                case SQLITE_INTEGER:
+                case SQLITE_TEXT:
+                    hold = (char *) sqlite3_column_text(stmt, i);
+                    if (hold) {
+                        column->value = apr_pstrmemdup(pool, hold,
+                                                       column->size);
+                    }
+                    break;
+                case SQLITE_BLOB:
+                    hold = (char *) sqlite3_column_blob(stmt, i);
+                    if (hold) {
+                        column->value = apr_pstrmemdup(pool, hold,
+                                                       column->size);
+                    }
+                    break;
+                case SQLITE_NULL:
+                    break;
+                }
+            }
+            row->rownum = num_tuples++;
+            row->next_row = 0;
+            (*results)->tuples = num_tuples;
+            if ((*results)->next_row == 0) {
+                (*results)->next_row = row;
+            }
+            if (lastrow != 0) {
+                lastrow->next_row = row;
+            }
+            lastrow = row;
+        }
+    } while (ret == SQLITE_ROW || ret == SQLITE_BUSY);
+
+    if (dbd_sqlite3_is_success(ret)) {
+        ret = 0;
+    }
+    return ret;
+}
+
+static int dbd_sqlite3_select(apr_pool_t *pool, apr_dbd_t *sql,
+                              apr_dbd_results_t **results, const char *query,
+                              int seek)
+{
+    sqlite3_stmt *stmt = NULL;
+    const char *tail = NULL;
+    int ret;
+
+    if (sql->trans && sql->trans->errnum) {
+        return sql->trans->errnum;
+    }
+
+    apr_dbd_mutex_lock();
+
+    ret = sqlite3_prepare(sql->conn, query, strlen(query), &stmt, &tail);
+    if (dbd_sqlite3_is_success(ret)) {
+        ret = dbd_sqlite3_select_internal(pool, sql, results, stmt, seek);
+    }
+    sqlite3_finalize(stmt);
+
+    apr_dbd_mutex_unlock();
+
+    if (TXN_NOTICE_ERRORS(sql->trans)) {
+        sql->trans->errnum = ret;
+    }
+    return ret;
+}
+
+static const char *dbd_sqlite3_get_name(const apr_dbd_results_t *res, int n)
+{
+    if ((n < 0) || ((size_t)n >= res->sz)) {
+        return NULL;
+    }
+
+    return res->col_names[n];
+}
+
+static int dbd_sqlite3_get_row(apr_pool_t *pool, apr_dbd_results_t *res,
+                               apr_dbd_row_t **rowp, int rownum)
+{
+    int i = 0;
+
+    if (rownum == -1) {
+        *rowp = res->next_row;
+        if (*rowp == 0)
+            return -1;
+        res->next_row = (*rowp)->next_row;
+        return 0;
+    }
+    if (rownum > res->tuples) {
+        return -1;
+    }
+    rownum--;
+    *rowp = res->next_row;
+    for (; *rowp != 0; i++, *rowp = (*rowp)->next_row) {
+        if (i == rownum) {
+            return 0;
+        }
+    }
+
+    return -1;
+
+}
+
+static const char *dbd_sqlite3_get_entry(const apr_dbd_row_t *row, int n)
+{
+    apr_dbd_column_t *column;
+    const char *value;
+    if ((n < 0) || (n >= row->columnCount)) {
+        return NULL;
+    }
+    column = row->columns[n];
+    value = column->value;
+    return value;
+}
+
+static apr_status_t dbd_sqlite3_datum_get(const apr_dbd_row_t *row, int n,
+                                          apr_dbd_type_e type, void *data)
+{
+    if ((n < 0) || ((size_t)n >= row->res->sz)) {
+      return APR_EGENERAL;
+    }
+
+    if (row->columns[n]->type == SQLITE_NULL) {
+        return APR_ENOENT;
+    }
+
+    switch (type) {
+    case APR_DBD_TYPE_TINY:
+        *(char*)data = atoi(row->columns[n]->value);
+        break;
+    case APR_DBD_TYPE_UTINY:
+        *(unsigned char*)data = atoi(row->columns[n]->value);
+        break;
+    case APR_DBD_TYPE_SHORT:
+        *(short*)data = atoi(row->columns[n]->value);
+        break;
+    case APR_DBD_TYPE_USHORT:
+        *(unsigned short*)data = atoi(row->columns[n]->value);
+        break;
+    case APR_DBD_TYPE_INT:
+        *(int*)data = atoi(row->columns[n]->value);
+        break;
+    case APR_DBD_TYPE_UINT:
+        *(unsigned int*)data = atoi(row->columns[n]->value);
+        break;
+    case APR_DBD_TYPE_LONG:
+        *(long*)data = atol(row->columns[n]->value);
+        break;
+    case APR_DBD_TYPE_ULONG:
+        *(unsigned long*)data = atol(row->columns[n]->value);
+        break;
+    case APR_DBD_TYPE_LONGLONG:
+        *(apr_int64_t*)data = apr_atoi64(row->columns[n]->value);
+        break;
+    case APR_DBD_TYPE_ULONGLONG:
+        *(apr_uint64_t*)data = apr_atoi64(row->columns[n]->value);
+        break;
+    case APR_DBD_TYPE_FLOAT:
+        *(float*)data = (float)atof(row->columns[n]->value);
+        break;
+    case APR_DBD_TYPE_DOUBLE:
+        *(double*)data = atof(row->columns[n]->value);
+        break;
+    case APR_DBD_TYPE_STRING:
+    case APR_DBD_TYPE_TEXT:
+    case APR_DBD_TYPE_TIME:
+    case APR_DBD_TYPE_DATE:
+    case APR_DBD_TYPE_DATETIME:
+    case APR_DBD_TYPE_TIMESTAMP:
+    case APR_DBD_TYPE_ZTIMESTAMP:
+        *(char**)data = row->columns[n]->value;
+        break;
+    case APR_DBD_TYPE_BLOB:
+    case APR_DBD_TYPE_CLOB:
+        {
+        apr_bucket *e;
+        apr_bucket_brigade *b = (apr_bucket_brigade*)data;
+
+        e = apr_bucket_pool_create(row->columns[n]->value,
+                                   row->columns[n]->size,
+                                   row->res->pool, b->bucket_alloc);
+        APR_BRIGADE_INSERT_TAIL(b, e);
+        }
+        break;
+    case APR_DBD_TYPE_NULL:
+        *(void**)data = NULL;
+        break;
+    default:
+        return APR_EGENERAL;
+    }
+
+    return APR_SUCCESS;
+}
+
+static const char *dbd_sqlite3_error(apr_dbd_t *sql, int n)
+{
+    return sqlite3_errmsg(sql->conn);
+}
+
+static int dbd_sqlite3_query_internal(apr_dbd_t *sql, sqlite3_stmt *stmt,
+                                      int *nrows)
+{
+    int ret = -1, retry_count = 0;
+
+    while(retry_count++ <= MAX_RETRY_COUNT) {
+        ret = sqlite3_step(stmt);
+        if (ret != SQLITE_BUSY)
+            break;
+
+        apr_dbd_mutex_unlock();
+        apr_sleep(MAX_RETRY_SLEEP);
+        apr_dbd_mutex_lock();
+    }
+
+    *nrows = sqlite3_changes(sql->conn);
+
+    if (dbd_sqlite3_is_success(ret)) {
+        ret = 0;
+    }
+    return ret;
+}
+
+static int dbd_sqlite3_query(apr_dbd_t *sql, int *nrows, const char *query)
+{
+    sqlite3_stmt *stmt = NULL;
+    const char *tail = NULL;
+    int ret = -1, length = 0;
+
+    if (sql->trans && sql->trans->errnum) {
+        return sql->trans->errnum;
+    }
+
+    length = strlen(query);
+    apr_dbd_mutex_lock();
+
+    do {
+        ret = sqlite3_prepare(sql->conn, query, length, &stmt, &tail);
+        if (ret != SQLITE_OK) {
+            sqlite3_finalize(stmt);
+            break;
+        }
+
+        ret = dbd_sqlite3_query_internal(sql, stmt, nrows);
+
+        sqlite3_finalize(stmt);
+        length -= (tail - query);
+        query = tail;
+    } while (length > 0);
+
+    apr_dbd_mutex_unlock();
+
+    if (TXN_NOTICE_ERRORS(sql->trans)) {
+        sql->trans->errnum = ret;
+    }
+    return ret;
+}
+
+static apr_status_t free_mem(void *data)
+{
+    sqlite3_free(data);
+    return APR_SUCCESS;
+}
+
+static const char *dbd_sqlite3_escape(apr_pool_t *pool, const char *arg,
+                                      apr_dbd_t *sql)
+{
+    char *ret = sqlite3_mprintf("%q", arg);
+    apr_pool_cleanup_register(pool, ret, free_mem,
+                              apr_pool_cleanup_null);
+    return ret;
+}
+
+static int dbd_sqlite3_prepare(apr_pool_t *pool, apr_dbd_t *sql,
+                               const char *query, const char *label,
+                               int nargs, int nvals, apr_dbd_type_e *types,
+                               apr_dbd_prepared_t **statement)
+{
+    sqlite3_stmt *stmt;
+    const char *tail = NULL;
+    int ret;
+
+    apr_dbd_mutex_lock();
+
+    ret = sqlite3_prepare(sql->conn, query, strlen(query), &stmt, &tail);
+    if (ret == SQLITE_OK) {
+        apr_dbd_prepared_t *prep; 
+
+        prep = apr_pcalloc(sql->pool, sizeof(*prep));
+        prep->stmt = stmt;
+        prep->next = sql->prep;
+        prep->nargs = nargs;
+        prep->nvals = nvals;
+        prep->types = types;
+
+        /* link new statement to the handle */
+        sql->prep = prep;
+
+        *statement = prep;
+    } else {
+        sqlite3_finalize(stmt);
+    }
+   
+    apr_dbd_mutex_unlock();
+
+    return ret;
+}
+
+static void dbd_sqlite3_bind(apr_dbd_prepared_t *statement, const char **values)
+{
+    sqlite3_stmt *stmt = statement->stmt;
+    int i, j;
+
+    for (i = 0, j = 0; i < statement->nargs; i++, j++) {
+        if (values[j] == NULL) {
+            sqlite3_bind_null(stmt, i + 1);
+        }
+        else {
+            switch (statement->types[i]) {
+            case APR_DBD_TYPE_BLOB:
+            case APR_DBD_TYPE_CLOB:
+                {
+                char *data = (char *)values[j];
+                int size = atoi((char*)values[++j]);
+
+                /* skip table and column */
+                j += 2;
+
+                sqlite3_bind_blob(stmt, i + 1, data, size, SQLITE_STATIC);
+                }
+                break;
+            default:
+                sqlite3_bind_text(stmt, i + 1, values[j],
+                                  strlen(values[j]), SQLITE_STATIC);
+                break;
+            }
+        }
+    }
+
+    return;
+}
+
+static int dbd_sqlite3_pquery(apr_pool_t *pool, apr_dbd_t *sql,
+                              int *nrows, apr_dbd_prepared_t *statement,
+                              const char **values)
+{
+    sqlite3_stmt *stmt = statement->stmt;
+    int ret = -1;
+
+    if (sql->trans && sql->trans->errnum) {
+        return sql->trans->errnum;
+    }
+
+    apr_dbd_mutex_lock();
+
+    ret = sqlite3_reset(stmt);
+    if (ret == SQLITE_OK) {
+        dbd_sqlite3_bind(statement, values);
+
+        ret = dbd_sqlite3_query_internal(sql, stmt, nrows);
+
+        sqlite3_reset(stmt);
+    }
+
+    apr_dbd_mutex_unlock();
+
+    if (TXN_NOTICE_ERRORS(sql->trans)) {
+        sql->trans->errnum = ret;
+    }
+    return ret;
+}
+
+static int dbd_sqlite3_pvquery(apr_pool_t *pool, apr_dbd_t *sql, int *nrows,
+                               apr_dbd_prepared_t *statement, va_list args)
+{
+    const char **values;
+    int i;
+
+    if (sql->trans && sql->trans->errnum) {
+        return sql->trans->errnum;
+    }
+
+    values = apr_palloc(pool, sizeof(*values) * statement->nvals);
+
+    for (i = 0; i < statement->nvals; i++) {
+        values[i] = va_arg(args, const char*);
+    }
+
+    return dbd_sqlite3_pquery(pool, sql, nrows, statement, values);
+}
+
+static int dbd_sqlite3_pselect(apr_pool_t *pool, apr_dbd_t *sql,
+                               apr_dbd_results_t **results,
+                               apr_dbd_prepared_t *statement, int seek,
+                               const char **values)
+{
+    sqlite3_stmt *stmt = statement->stmt;
+    int ret;
+
+    if (sql->trans && sql->trans->errnum) {
+        return sql->trans->errnum;
+    }
+
+    apr_dbd_mutex_lock();
+
+    ret = sqlite3_reset(stmt);
+    if (ret == SQLITE_OK) {
+        dbd_sqlite3_bind(statement, values);
+
+        ret = dbd_sqlite3_select_internal(pool, sql, results, stmt, seek);
+
+        sqlite3_reset(stmt);
+    }
+
+    apr_dbd_mutex_unlock();
+
+    if (TXN_NOTICE_ERRORS(sql->trans)) {
+        sql->trans->errnum = ret;
+    }
+    return ret;
+}
+
+static int dbd_sqlite3_pvselect(apr_pool_t *pool, apr_dbd_t *sql,
+                                apr_dbd_results_t **results,
+                                apr_dbd_prepared_t *statement, int seek,
+                                va_list args)
+{
+    const char **values;
+    int i;
+
+    if (sql->trans && sql->trans->errnum) {
+        return sql->trans->errnum;
+    }
+
+    values = apr_palloc(pool, sizeof(*values) * statement->nvals);
+
+    for (i = 0; i < statement->nvals; i++) {
+        values[i] = va_arg(args, const char*);
+    }
+
+    return dbd_sqlite3_pselect(pool, sql, results, statement, seek, values);
+}
+
+static void dbd_sqlite3_bbind(apr_dbd_prepared_t * statement,
+                              const void **values)
+{
+    sqlite3_stmt *stmt = statement->stmt;
+    int i, j;
+    apr_dbd_type_e type;
+
+    for (i = 0, j = 0; i < statement->nargs; i++, j++) {
+        type = (values[j] == NULL ? APR_DBD_TYPE_NULL : statement->types[i]);
+
+        switch (type) {
+        case APR_DBD_TYPE_TINY:
+            sqlite3_bind_int(stmt, i + 1, *(char*)values[j]);
+            break;
+        case APR_DBD_TYPE_UTINY:
+            sqlite3_bind_int(stmt, i + 1, *(unsigned char*)values[j]);
+            break;
+        case APR_DBD_TYPE_SHORT:
+            sqlite3_bind_int(stmt, i + 1, *(short*)values[j]);
+            break;
+        case APR_DBD_TYPE_USHORT:
+            sqlite3_bind_int(stmt, i + 1, *(unsigned short*)values[j]);
+            break;
+        case APR_DBD_TYPE_INT:
+            sqlite3_bind_int(stmt, i + 1, *(int*)values[j]);
+            break;
+        case APR_DBD_TYPE_UINT:
+            sqlite3_bind_int(stmt, i + 1, *(unsigned int*)values[j]);
+            break;
+        case APR_DBD_TYPE_LONG:
+            sqlite3_bind_int64(stmt, i + 1, *(long*)values[j]);
+            break;
+        case APR_DBD_TYPE_ULONG:
+            sqlite3_bind_int64(stmt, i + 1, *(unsigned long*)values[j]);
+            break;
+        case APR_DBD_TYPE_LONGLONG:
+            sqlite3_bind_int64(stmt, i + 1, *(apr_int64_t*)values[j]);
+            break;
+        case APR_DBD_TYPE_ULONGLONG:
+            sqlite3_bind_int64(stmt, i + 1, *(apr_uint64_t*)values[j]);
+            break;
+        case APR_DBD_TYPE_FLOAT:
+            sqlite3_bind_double(stmt, i + 1, *(float*)values[j]);
+            break;
+        case APR_DBD_TYPE_DOUBLE:
+            sqlite3_bind_double(stmt, i + 1, *(double*)values[j]);
+            break;
+        case APR_DBD_TYPE_STRING:
+        case APR_DBD_TYPE_TEXT:
+        case APR_DBD_TYPE_TIME:
+        case APR_DBD_TYPE_DATE:
+        case APR_DBD_TYPE_DATETIME:
+        case APR_DBD_TYPE_TIMESTAMP:
+        case APR_DBD_TYPE_ZTIMESTAMP:
+            sqlite3_bind_text(stmt, i + 1, values[j], strlen(values[j]),
+                              SQLITE_STATIC);
+            break;
+        case APR_DBD_TYPE_BLOB:
+        case APR_DBD_TYPE_CLOB:
+            {
+            char *data = (char*)values[j];
+            apr_size_t size = *(apr_size_t*)values[++j];
+
+            sqlite3_bind_blob(stmt, i + 1, data, size, SQLITE_STATIC);
+
+            /* skip table and column */
+            j += 2;
+            }
+            break;
+        case APR_DBD_TYPE_NULL:
+        default:
+            sqlite3_bind_null(stmt, i + 1);
+            break;
+        }
+    }
+
+    return;
+}
+
+static int dbd_sqlite3_pbquery(apr_pool_t * pool, apr_dbd_t * sql,
+                               int *nrows, apr_dbd_prepared_t * statement,
+                               const void **values)
+{
+    sqlite3_stmt *stmt = statement->stmt;
+    int ret = -1;
+
+    if (sql->trans && sql->trans->errnum) {
+        return sql->trans->errnum;
+    }
+
+    apr_dbd_mutex_lock();
+
+    ret = sqlite3_reset(stmt);
+    if (ret == SQLITE_OK) {
+        dbd_sqlite3_bbind(statement, values);
+
+        ret = dbd_sqlite3_query_internal(sql, stmt, nrows);
+
+        sqlite3_reset(stmt);
+    }
+
+    apr_dbd_mutex_unlock();
+
+    if (TXN_NOTICE_ERRORS(sql->trans)) {
+        sql->trans->errnum = ret;
+    }
+    return ret;
+}
+
+static int dbd_sqlite3_pvbquery(apr_pool_t * pool, apr_dbd_t * sql,
+                                int *nrows, apr_dbd_prepared_t * statement,
+                                va_list args)
+{
+    const void **values;
+    int i;
+
+    if (sql->trans && sql->trans->errnum) {
+        return sql->trans->errnum;
+    }
+
+    values = apr_palloc(pool, sizeof(*values) * statement->nvals);
+
+    for (i = 0; i < statement->nvals; i++) {
+        values[i] = va_arg(args, const void*);
+    }
+
+    return dbd_sqlite3_pbquery(pool, sql, nrows, statement, values);
+}
+
+static int dbd_sqlite3_pbselect(apr_pool_t * pool, apr_dbd_t * sql,
+                                apr_dbd_results_t ** results,
+                                apr_dbd_prepared_t * statement,
+                                int seek, const void **values)
+{
+    sqlite3_stmt *stmt = statement->stmt;
+    int ret;
+
+    if (sql->trans && sql->trans->errnum) {
+        return sql->trans->errnum;
+    }
+
+    apr_dbd_mutex_lock();
+
+    ret = sqlite3_reset(stmt);
+    if (ret == SQLITE_OK) {
+        dbd_sqlite3_bbind(statement, values);
+
+        ret = dbd_sqlite3_select_internal(pool, sql, results, stmt, seek);
+
+        sqlite3_reset(stmt);
+    }
+
+    apr_dbd_mutex_unlock();
+
+    if (TXN_NOTICE_ERRORS(sql->trans)) {
+        sql->trans->errnum = ret;
+    }
+    return ret;
+}
+
+static int dbd_sqlite3_pvbselect(apr_pool_t * pool, apr_dbd_t * sql,
+                                 apr_dbd_results_t ** results,
+                                 apr_dbd_prepared_t * statement, int seek,
+                                 va_list args)
+{
+    const void **values;
+    int i;
+
+    if (sql->trans && sql->trans->errnum) {
+        return sql->trans->errnum;
+    }
+
+    values = apr_palloc(pool, sizeof(*values) * statement->nvals);
+
+    for (i = 0; i < statement->nvals; i++) {
+        values[i] = va_arg(args, const void*);
+    }
+
+    return dbd_sqlite3_pbselect(pool, sql, results, statement, seek, values);
+}
+
+static int dbd_sqlite3_start_transaction(apr_pool_t *pool,
+                                         apr_dbd_t *handle,
+                                         apr_dbd_transaction_t **trans)
+{
+    int ret = 0;
+    int nrows = 0;
+
+    ret = dbd_sqlite3_query(handle, &nrows, "BEGIN IMMEDIATE");
+    if (!*trans) {
+        *trans = apr_pcalloc(pool, sizeof(apr_dbd_transaction_t));
+        (*trans)->handle = handle;
+        handle->trans = *trans;
+    }
+
+    return ret;
+}
+
+static int dbd_sqlite3_end_transaction(apr_dbd_transaction_t *trans)
+{
+    int ret = -1; /* ending transaction that was never started is an error */
+    int nrows = 0;
+
+    if (trans) {
+        /* rollback on error or explicit rollback request */
+        if (trans->errnum || TXN_DO_ROLLBACK(trans)) {
+            trans->errnum = 0;
+            ret = dbd_sqlite3_query(trans->handle, &nrows, "ROLLBACK");
+        } else {
+            ret = dbd_sqlite3_query(trans->handle, &nrows, "COMMIT");
+        }
+        trans->handle->trans = NULL;
+    }
+
+    return ret;
+}
+
+static int dbd_sqlite3_transaction_mode_get(apr_dbd_transaction_t *trans)
+{
+    if (!trans)
+        return APR_DBD_TRANSACTION_COMMIT;
+
+    return trans->mode;
+}
+
+static int dbd_sqlite3_transaction_mode_set(apr_dbd_transaction_t *trans,
+                                            int mode)
+{
+    if (!trans)
+        return APR_DBD_TRANSACTION_COMMIT;
+
+    return trans->mode = (mode & TXN_MODE_BITS);
+}
+
+static apr_dbd_t *dbd_sqlite3_open(apr_pool_t *pool, const char *params,
+                                   const char **error)
+{
+    apr_dbd_t *sql = NULL;
+    sqlite3 *conn = NULL;
+    int sqlres;
+    if (!params)
+        return NULL;
+    sqlres = sqlite3_open(params, &conn);
+    if (sqlres != SQLITE_OK) {
+        if (error) {
+            *error = apr_pstrdup(pool, sqlite3_errmsg(conn));
+        }
+        sqlite3_close(conn);
+        return NULL;
+    }
+    /* should we register rand or power functions to the sqlite VM? */
+    sql = apr_pcalloc(pool, sizeof(*sql));
+    sql->conn = conn;
+    sql->pool = pool;
+    sql->trans = NULL;
+
+    return sql;
+}
+
+static apr_status_t dbd_sqlite3_close(apr_dbd_t *handle)
+{
+    apr_dbd_prepared_t *prep = handle->prep;
+
+    /* finalize all prepared statements, or we'll get SQLITE_BUSY on close */
+    while (prep) {
+        sqlite3_finalize(prep->stmt);
+        prep = prep->next;
+    }
+
+    sqlite3_close(handle->conn);
+    return APR_SUCCESS;
+}
+
+static apr_status_t dbd_sqlite3_check_conn(apr_pool_t *pool,
+                                           apr_dbd_t *handle)
+{
+    return (handle->conn != NULL) ? APR_SUCCESS : APR_EGENERAL;
+}
+
+static int dbd_sqlite3_select_db(apr_pool_t *pool, apr_dbd_t *handle,
+                                 const char *name)
+{
+    return APR_ENOTIMPL;
+}
+
+static void *dbd_sqlite3_native(apr_dbd_t *handle)
+{
+    return handle->conn;
+}
+
+static int dbd_sqlite3_num_cols(apr_dbd_results_t *res)
+{
+    return res->sz;
+}
+
+static int dbd_sqlite3_num_tuples(apr_dbd_results_t *res)
+{
+    return res->tuples;
+}
+
+APR_MODULE_DECLARE_DATA const apr_dbd_driver_t apr_dbd_sqlite3_driver = {
+    "sqlite3",
+    NULL,
+    dbd_sqlite3_native,
+    dbd_sqlite3_open,
+    dbd_sqlite3_check_conn,
+    dbd_sqlite3_close,
+    dbd_sqlite3_select_db,
+    dbd_sqlite3_start_transaction,
+    dbd_sqlite3_end_transaction,
+    dbd_sqlite3_query,
+    dbd_sqlite3_select,
+    dbd_sqlite3_num_cols,
+    dbd_sqlite3_num_tuples,
+    dbd_sqlite3_get_row,
+    dbd_sqlite3_get_entry,
+    dbd_sqlite3_error,
+    dbd_sqlite3_escape,
+    dbd_sqlite3_prepare,
+    dbd_sqlite3_pvquery,
+    dbd_sqlite3_pvselect,
+    dbd_sqlite3_pquery,
+    dbd_sqlite3_pselect,
+    dbd_sqlite3_get_name,
+    dbd_sqlite3_transaction_mode_get,
+    dbd_sqlite3_transaction_mode_set,
+    "?",
+    dbd_sqlite3_pvbquery,
+    dbd_sqlite3_pvbselect,
+    dbd_sqlite3_pbquery,
+    dbd_sqlite3_pbselect,
+    dbd_sqlite3_datum_get
+};
+#endif
diff --git a/dbd/apr_dbd_sqlite3.dsp b/dbd/apr_dbd_sqlite3.dsp
new file mode 100644
index 00000000000..961461de8c7
--- /dev/null
+++ b/dbd/apr_dbd_sqlite3.dsp
@@ -0,0 +1,207 @@
+# Microsoft Developer Studio Project File - Name="apr_dbd_sqlite3" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=apr_dbd_sqlite3 - 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 "apr_dbd_sqlite3.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 "apr_dbd_sqlite3.mak" CFG="apr_dbd_sqlite3 - Win32 Release"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "apr_dbd_sqlite3 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_dbd_sqlite3 - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_dbd_sqlite3 - x64 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_dbd_sqlite3 - x64 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)" == "apr_dbd_sqlite3 - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /Zi /O2 /Oy- /I "../include" /I "../include/arch/win32" /I "../include/private" /I "../../sqlite3" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_SQLITE3=1 /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbd_sqlite3_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /fo"Release/apr_dbd_sqlite3-1.res" /d DLL_NAME="apr_dbd_sqlite3" /d "NDEBUG" /d "APU_VERSION_ONLY" /I "../include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib sqlite3.lib /nologo /base:"0x6EF20000" /subsystem:windows /dll /incremental:no /debug /opt:ref
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib sqlite3.lib /nologo /base:"0x6EF20000" /subsystem:windows /dll /incremental:no /debug /libpath:"..\..\sqlite3" /out:"Release\apr_dbd_sqlite3-1.dll" /pdb:"Release\apr_dbd_sqlite3-1.pdb" /implib:"Release\apr_dbd_sqlite3-1.lib" /MACHINE:X86 /opt:ref
+# Begin Special Build Tool
+TargetPath=Release\apr_dbd_sqlite3-1.dll
+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)" == "apr_dbd_sqlite3 - 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 /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /EHsc /c
+# ADD CPP /nologo /MDd /W3 /Zi /Od /I "../include" /I "../include/arch/win32" /I "../include/private" /I "../../sqlite3" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_SQLITE3=1 /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbd_sqlite3_src" /FD /EHsc /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /fo"Debug/apr_dbd_sqlite3-1.res" /d DLL_NAME="apr_dbd_sqlite3" /d "_DEBUG" /d "APU_VERSION_ONLY" /I "../include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib sqlite3.lib /nologo /base:"0x6EF20000" /subsystem:windows /dll /incremental:no /debug
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib sqlite3.lib /nologo /base:"0x6EF20000" /subsystem:windows /dll /incremental:no /debug /libpath:"..\..\sqlite3" /out:"Debug\apr_dbd_sqlite3-1.dll" /pdb:"Debug\apr_dbd_sqlite3-1.pdb" /implib:"Debug\apr_dbd_sqlite3-1.lib" /MACHINE:X86
+# Begin Special Build Tool
+TargetPath=Debug\apr_dbd_sqlite3-1.dll
+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)" == "apr_dbd_sqlite3 - x64 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "x64\Release"
+# PROP BASE Intermediate_Dir "x64\Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "x64\Release"
+# PROP Intermediate_Dir "x64\Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /Zi /O2 /Oy- /I "../include" /I "../include/arch/win32" /I "../include/private" /I "../../sqlite3" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_SQLITE3=1 /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbd_sqlite3_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /fo"x64/Release/apr_dbd_sqlite3-1.res" /d DLL_NAME="apr_dbd_sqlite3" /d "NDEBUG" /d "APU_VERSION_ONLY" /I "../include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib sqlite3.lib /nologo /base:"0x6EF20000" /subsystem:windows /dll /incremental:no /debug /opt:ref
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib sqlite3.lib /nologo /base:"0x6EF20000" /subsystem:windows /dll /incremental:no /libpath:"..\..\sqlite3" /debug /out:"x64\Release\apr_dbd_sqlite3-1.dll" /pdb:"x64\Release\apr_dbd_sqlite3-1.pdb" /implib:"x64\Release\apr_dbd_sqlite3-1.lib" /MACHINE:X64 /opt:ref
+# Begin Special Build Tool
+TargetPath=x64\Release\apr_dbd_sqlite3-1.dll
+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)" == "apr_dbd_sqlite3 - x64 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "x64\Debug"
+# PROP BASE Intermediate_Dir "x64\Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "x64\Debug"
+# PROP Intermediate_Dir "x64\Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /EHsc /c
+# ADD CPP /nologo /MDd /W3 /Zi /Od /I "../include" /I "../include/arch/win32" /I "../include/private" /I "../../sqlite3" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_SQLITE3=1 /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbd_sqlite3_src" /FD /EHsc /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /fo"x64/Debug/apr_dbd_sqlite3-1.res" /d DLL_NAME="apr_dbd_sqlite3" /d "_DEBUG" /d "APU_VERSION_ONLY" /I "../include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib sqlite3.lib /nologo /base:"0x6EF20000" /subsystem:windows /dll /incremental:no /debug
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib sqlite3.lib /nologo /base:"0x6EF20000" /subsystem:windows /dll /incremental:no /libpath:"..\..\sqlite3" /debug /out:"x64\Debug\apr_dbd_sqlite3-1.dll" /pdb:"x64\Debug\apr_dbd_sqlite3-1.pdb" /implib:"x64\Debug\apr_dbd_sqlite3-1.lib" /MACHINE:X64
+# Begin Special Build Tool
+TargetPath=x64\Debug\apr_dbd_sqlite3-1.dll
+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 "apr_dbd_sqlite3 - Win32 Release"
+# Name "apr_dbd_sqlite3 - Win32 Debug"
+# Name "apr_dbd_sqlite3 - x64 Release"
+# Name "apr_dbd_sqlite3 - x64 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\apr_dbd_sqlite3.c
+# End Source File
+# End Group
+# Begin Group "Public Header Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\include\apr_dbd.h
+# End Source File
+# End Group
+# Begin Group "Internal Header Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\include\private\apu_config.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\private\apu_dbd_internal.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\private\apu_internal.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\libapr.rc
+# End Source File
+# End Target
+# End Project
diff --git a/dbd/unsupported/NWGNUdbdfreetds b/dbd/unsupported/NWGNUdbdfreetds
new file mode 100644
index 00000000000..71af8d15159
--- /dev/null
+++ b/dbd/unsupported/NWGNUdbdfreetds
@@ -0,0 +1,288 @@
+#
+# 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
+#
+
+ifndef EnvironmentDefined
+include $(APR_WORK)/build/NWGNUhead.inc
+endif
+
+#
+# build this level's files
+
+#
+# Make sure all needed macro's are defined
+#
+
+# LINK_STATIC = 1
+
+# for now defined here - should finally go into build/NWGNUenvironment.inc
+FREETDS_INC = $(FREETDSSDK)/include
+FREETDS_IMP = $(FREETDSSDK)/lib/libfreetds.imp
+FREETDS_LIB = $(FREETDSSDK)/lib/libfreetds.lib
+FREETDS_NLM = libfreetds
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS	+= \
+			$(APR)/include \
+			$(APR)/include/private \
+			$(APR)/include/arch/netware \
+			$(FREETDS_INC) \
+			$(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS		+= \
+			$(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES	+= \
+			-DAPU_HAVE_FREETDS=1 \
+			-DAPU_DSO_MODULE_BUILD \
+			-DHAVE_SYBDB_H=1 \
+			-DSYBDBLIB \
+			$(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS		+= \
+			$(EOLIST)
+
+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	= dbdfreetds
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION	= Apache Portability Runtime Library $(VERSION_STR) DBD FreeTDS Driver Module
+
+#
+# This is used by the '-threadname' directive.  If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME	= dbdfreetds
+
+#
+# If this is specified, it will override VERSION value in
+# $(APR_WORK)/build/NWGNUenvironment.inc
+#
+NLM_VERSION	=
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE	=
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM	=
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM	=
+
+#
+# If this is specified it will be used by the link '-check' directive
+#
+NLM_CHECK_SYM	=
+
+#
+# If these are specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS	=
+
+#
+# If this is specified it will be linked in with the XDCData option in the def
+# file instead of the default of $(NWOS)/apache.xdc.  XDCData can be disabled
+# by setting APACHE_UNIPROC in the environment
+#
+XDCDATA		=
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+	$(OBJDIR)/$(NLM_NAME).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)/apr_dbd_freetds.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)
+
+ifeq ($(LINK_STATIC),1)
+FILES_nlm_libs += \
+	$(FREETDS_LIB) \
+	$(EOLIST)
+endif
+
+#
+# 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)
+
+ifneq ($(LINK_STATIC),1)
+FILES_nlm_modules += \
+	$(FREETDS_NLM) \
+	$(EOLIST)
+endif
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+	@$(APR)/aprlib.imp \
+	@$(NOVI)/libc.imp \
+	$(EOLIST)
+
+ifneq ($(LINK_STATIC),1)
+FILES_nlm_Ximports += \
+	@$(FREETDS_IMP) \
+	$(EOLIST)
+endif
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+	apr_dbd_freetds_driver \
+	$(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 $(APR_WORK)/build/NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(APRBUILD)/NWGNUtail.inc
+
diff --git a/dbd/unsupported/apr_dbd_freetds.c b/dbd/unsupported/apr_dbd_freetds.c
new file mode 100644
index 00000000000..ba952e95b49
--- /dev/null
+++ b/dbd/unsupported/apr_dbd_freetds.c
@@ -0,0 +1,809 @@
+/* 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.
+ */
+
+#ifdef I_CAN_DEAL_WITH_THIS_PARTIAL_DRIVER_AND_UNMAINTAINED_CODE_FOR_FREETDS
+
+#include "apu.h"
+#include "apr_private.h"
+
+/* COMPILE_STUBS: compile stubs for unimplemented functions.
+ *
+ * This is required to compile in /trunk/, but can be
+ * undefined to compile a driver for httpd-2.2 and other
+ * APR-1.2 applications
+ */
+#define COMPILE_STUBS
+
+#if APU_HAVE_FREETDS
+
+#include <ctype.h>
+#include <stdlib.h>
+
+#include "apr_strings.h"
+#include "apr_lib.h"
+
+#include "apr_pools.h"
+#include "apr_dbd_internal.h"
+
+#ifdef HAVE_FREETDS_SYBDB_H
+#include <freetds/sybdb.h>
+#endif
+#ifdef HAVE_SYBDB_H
+#include <sybdb.h>
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <regex.h>
+
+/* This probably needs to change for different applications */
+#define MAX_COL_LEN 256
+
+typedef struct freetds_cell_t {
+    int type;
+    DBINT len;
+    BYTE *data;
+} freetds_cell_t;
+
+struct apr_dbd_transaction_t {
+    int mode;
+    int errnum;
+    apr_dbd_t *handle;
+};
+
+struct apr_dbd_t {
+    DBPROCESS *proc;
+    apr_dbd_transaction_t *trans;
+    apr_pool_t *pool;
+    const char *params;
+    RETCODE err;
+};
+
+struct apr_dbd_results_t {
+    int random;
+    size_t ntuples;
+    size_t sz;
+    apr_pool_t *pool;
+    DBPROCESS *proc;
+};
+
+struct apr_dbd_row_t {
+    apr_dbd_results_t *res;
+    BYTE buf[MAX_COL_LEN];
+};
+
+struct apr_dbd_prepared_t {
+    int nargs;
+    regex_t **taint;
+    int *sz;
+    char *fmt;
+};
+
+#define dbd_freetds_is_success(x) (x == SUCCEED)
+
+static int labelnum = 0; /* FIXME */
+static regex_t dbd_freetds_find_arg;
+
+/* execute a query that doesn't return a result set, mop up,
+ * and return and APR-flavoured status
+ */
+static RETCODE freetds_exec(DBPROCESS *proc, const char *query,
+                            int want_results, int *nrows)
+{
+    /* TBD */
+    RETCODE rv = dbcmd(proc, query);
+    if (rv != SUCCEED) {
+        return rv;
+    }
+    rv = dbsqlexec(proc);
+    if (rv != SUCCEED) {
+        return rv;
+    }
+    if (!want_results) {
+        while (dbresults(proc) != NO_MORE_RESULTS) {
+            ++*nrows;
+        }
+    }
+    return SUCCEED;
+}
+static apr_status_t clear_result(void *data)
+{
+    /* clear cursor */
+    return (dbcanquery((DBPROCESS*)data) == SUCCEED)
+            ? APR_SUCCESS
+            : APR_EGENERAL;
+}
+
+static int dbd_freetds_select(apr_pool_t *pool, apr_dbd_t *sql,
+                              apr_dbd_results_t **results,
+                              const char *query, int seek)
+{
+    apr_dbd_results_t *res;
+    if (sql->trans && (sql->trans->errnum != SUCCEED)) {
+        return 1;
+    }
+    /* the core of this is
+     * dbcmd(proc, query);
+     * dbsqlexec(proc);
+     * while (dbnextrow(dbproc) != NO_MORE_ROWS) {
+     *     do things
+     * }
+     *
+     * Ignore seek
+     */
+
+    sql->err = freetds_exec(sql->proc, query, 1, NULL);
+    if (!dbd_freetds_is_success(sql->err)) {
+        if (sql->trans) {
+            sql->trans->errnum = sql->err;
+        }
+        return 1;
+    }
+
+    sql->err = dbresults(sql->proc);
+    if (sql->err != SUCCEED) {
+        if (sql->trans) {
+            sql->trans->errnum = sql->err;
+        }
+        return 1;
+    }
+
+    if (!*results) {
+        *results = apr_pcalloc(pool, sizeof(apr_dbd_results_t));
+    }
+    res = *results;
+    res->proc = sql->proc;
+    res->random = seek;
+    res->pool = pool;
+    res->ntuples = dblastrow(sql->proc);
+    res->sz = dbnumcols(sql->proc);
+    apr_pool_cleanup_register(pool, sql->proc, clear_result,
+                              apr_pool_cleanup_null);
+
+#if 0
+    /* Now we have a result set.  We need to bind to its vars */
+    res->vars = apr_palloc(pool, res->sz * sizeof(freetds_cell_t*));
+    for (i=1; i <= res->sz; ++i) {
+        freetds_cell_t *cell = &res->vars[i-1];
+        cell->type = dbcoltype(sql->proc, i);
+        cell->len = dbcollen(sql->proc, i);
+        cell->data = apr_palloc(pool, cell->len);
+        sql->err = dbbind(sql->proc, i, /*cell->type */ STRINGBIND, cell->len, cell->data);
+        if (sql->err != SUCCEED) {
+            fprintf(stderr, "dbbind error: %d, %d, %d", i, cell->type, cell->len);
+        }
+        if ((sql->err != SUCCEED) && (sql->trans != NULL)) {
+            sql->trans->errnum = sql->err;
+        }
+    }
+#endif
+    return (sql->err == SUCCEED) ? 0 : 1;
+}
+static const char *dbd_untaint(apr_pool_t *pool, regex_t *rx, const char *val)
+{
+    regmatch_t match[1];
+    if (rx == NULL) {
+        /* no untaint expression */
+        return val;
+    }
+    if (regexec(rx, val, 1, match, 0) == 0) {
+        return apr_pstrndup(pool, val+match[0].rm_so,
+                            match[0].rm_eo - match[0].rm_so);
+    }
+    return "";
+}
+static const char *dbd_statement(apr_pool_t *pool,
+                                 apr_dbd_prepared_t *stmt,
+                                 int nargs, const char **args)
+{
+    int i;
+    int len;
+    const char *var;
+    char *ret;
+    const char *p_in;
+    char *p_out;
+    char *q;
+   
+    /* compute upper bound on length (since untaint shrinks) */
+    len  = strlen(stmt->fmt) +1;
+    for (i=0; i<nargs; ++i) {
+        len += strlen(args[i]) - 2;
+    }
+    i = 0;
+    p_in = stmt->fmt;
+    p_out = ret = apr_palloc(pool, len);
+    /* FIXME silly bug - this'll catch %%s */
+    while (q = strstr(p_in, "%s"), q != NULL) {
+        len = q-p_in;
+        strncpy(p_out, p_in, len);
+        p_in += len;
+        p_out += len;
+        var = dbd_untaint(pool, stmt->taint[i], args[i]);
+        len = strlen(var);
+        strncpy(p_out, var, len);
+        p_in += 2;
+        p_out += len;
+        ++i;
+    }
+    strcpy(p_out, p_in);
+    return ret;
+}
+static int dbd_freetds_pselect(apr_pool_t *pool, apr_dbd_t *sql,
+                               apr_dbd_results_t **results,
+                               apr_dbd_prepared_t *statement,
+                               int seek, const char **values)
+{
+    const char *query = dbd_statement(pool, statement,
+                                      statement->nargs, values);
+    return dbd_freetds_select(pool, sql, results, query, seek);
+}
+static int dbd_freetds_pvselect(apr_pool_t *pool, apr_dbd_t *sql,
+                                apr_dbd_results_t **results,
+                                apr_dbd_prepared_t *statement,
+                                int seek, va_list args)
+{
+    const char **values;
+    int i;
+
+    if (sql->trans && sql->trans->errnum) {
+        return sql->trans->errnum;
+    }
+
+    values = apr_palloc(pool, sizeof(*values) * statement->nargs);
+
+    for (i = 0; i < statement->nargs; i++) {
+        values[i] = va_arg(args, const char*);
+    }
+
+    return dbd_freetds_pselect(pool, sql, results, statement, seek, values);
+}
+static int dbd_freetds_query(apr_dbd_t *sql, int *nrows, const char *query);
+static int dbd_freetds_pquery(apr_pool_t *pool, apr_dbd_t *sql,
+                              int *nrows, apr_dbd_prepared_t *statement,
+                              const char **values)
+{
+    const char *query = dbd_statement(pool, statement,
+                                      statement->nargs, values);
+    return dbd_freetds_query(sql, nrows, query);
+}
+static int dbd_freetds_pvquery(apr_pool_t *pool, apr_dbd_t *sql, int *nrows,
+                               apr_dbd_prepared_t *statement, va_list args)
+{
+    const char **values;
+    int i;
+
+    if (sql->trans && sql->trans->errnum) {
+        return sql->trans->errnum;
+    }
+
+    values = apr_palloc(pool, sizeof(*values) * statement->nargs);
+
+    for (i = 0; i < statement->nargs; i++) {
+        values[i] = va_arg(args, const char*);
+    }
+    return dbd_freetds_pquery(pool, sql, nrows, statement, values);
+}
+
+static int dbd_freetds_get_row(apr_pool_t *pool, apr_dbd_results_t *res,
+                               apr_dbd_row_t **rowp, int rownum)
+{
+    RETCODE rv = 0;
+    apr_dbd_row_t *row = *rowp;
+    int sequential = ((rownum >= 0) && res->random) ? 0 : 1;
+
+    if (row == NULL) {
+        row = apr_palloc(pool, sizeof(apr_dbd_row_t));
+        *rowp = row;
+        row->res = res;
+    }
+    /*
+    else {
+        if ( sequential ) {
+            ++row->n;
+        }
+        else {
+            row->n = rownum;
+        }
+    }
+    */
+    if (sequential) {
+        rv = dbnextrow(res->proc);
+    }
+    else {
+        rv = (rownum >= 0) ? dbgetrow(res->proc, rownum) : NO_MORE_ROWS;
+    }
+    switch (rv) {
+    case SUCCEED: return 0;
+    case REG_ROW: return 0;
+    case NO_MORE_ROWS:
+        apr_pool_cleanup_run(res->pool, res->proc, clear_result);
+        *rowp = NULL;
+        return -1;
+    case FAIL: return 1;
+    case BUF_FULL: return 2; /* FIXME */
+    default: return 3;
+    }
+
+    return 0;
+}
+
+static const char *dbd_freetds_get_entry(const apr_dbd_row_t *row, int n)
+{
+    /* FIXME: support different data types */
+    /* this fails - bind gets some vars but not others
+    return (const char*)row->res->vars[n].data;
+     */
+    DBPROCESS* proc = row->res->proc;
+    BYTE *ptr = dbdata(proc, n+1);
+    int t = dbcoltype(proc, n+1);
+    int l = dbcollen(proc, n+1);
+    if (dbwillconvert(t, SYBCHAR)) {
+      dbconvert(proc, t, ptr, l, SYBCHAR, (BYTE *)row->buf, -1);
+      return (const char*)row->buf;
+    }
+    return (char*)ptr;
+}
+
+static const char *dbd_freetds_error(apr_dbd_t *sql, int n)
+{
+    /* XXX this doesn't seem to exist in the API ??? */
+    return apr_psprintf(sql->pool, "Error %d", sql->err);
+}
+
+static int dbd_freetds_query(apr_dbd_t *sql, int *nrows, const char *query)
+{
+    if (sql->trans && sql->trans->errnum) {
+        return sql->trans->errnum;
+    }
+    *nrows = 0;
+    sql->err = freetds_exec(sql->proc, query, 0, nrows);
+
+    if (sql->err != SUCCEED) {
+        if (sql->trans) {
+            sql->trans->errnum = sql->err;
+        }
+        return 1;
+    }
+    return 0;
+}
+
+static const char *dbd_freetds_escape(apr_pool_t *pool, const char *arg,
+                                      apr_dbd_t *sql)
+{
+    return arg;
+}
+
+static apr_status_t freetds_regfree(void *rx)
+{
+    regfree((regex_t*)rx);
+    return APR_SUCCESS;
+}
+static int recurse_args(apr_pool_t *pool, int n, const char *query,
+                        apr_dbd_prepared_t *stmt, int offs)
+{
+
+    /* we only support %s arguments for now */
+    int ret;
+    char arg[256];
+    regmatch_t matches[3];
+    if (regexec(&dbd_freetds_find_arg, query, 3, matches, 0) != 0) {
+        /* No more args */
+        stmt->nargs = n;
+        stmt->taint = apr_palloc(pool, n*sizeof(regex_t*));
+        stmt->sz = apr_palloc(pool, n*sizeof(int));
+        ret = 0;
+    }
+    else {
+        int i;
+        int sz = 0;
+        int len = matches[1].rm_eo - matches[1].rm_so - 2;
+        if (len > 255) {
+            return 9999;
+        }
+
+        ret = recurse_args(pool, n+1, query+matches[0].rm_eo,
+                           stmt, offs+matches[0].rm_eo);
+
+        memmove(stmt->fmt + offs + matches[1].rm_so,
+                stmt->fmt + offs + matches[0].rm_eo-1,
+                strlen(stmt->fmt+offs+matches[0].rm_eo)+2);
+
+        /* compile untaint to a regex if found */
+        if (matches[1].rm_so == -1) {
+            stmt->taint[n] = NULL;
+        }
+        else {
+            strncpy(arg, query+matches[1].rm_so+1,
+                    matches[1].rm_eo - matches[1].rm_so - 2);
+            arg[matches[1].rm_eo - matches[1].rm_so - 2] = '\0';
+            stmt->taint[n] = apr_palloc(pool, sizeof(regex_t));
+            if (regcomp(stmt->taint[n], arg, REG_ICASE|REG_EXTENDED) != 0) {
+                ++ret;
+            }
+            else {
+                apr_pool_cleanup_register(pool, stmt->taint[n], freetds_regfree,
+                                          apr_pool_cleanup_null);
+            }
+        }
+
+        /* record length if specified */
+        for (i=matches[2].rm_so; i<matches[2].rm_eo; ++i) {
+            sz = 10*sz + (query[i]-'\0');
+        }
+    }
+    return ret;
+}
+
+static int dbd_freetds_prepare(apr_pool_t *pool, apr_dbd_t *sql,
+                             const char *query, const char *label,
+                             int nargs, int nvals, apr_dbd_type_e *types,
+                             apr_dbd_prepared_t **statement)
+{
+    apr_dbd_prepared_t *stmt;
+
+    if (label == NULL) {
+        label = apr_psprintf(pool, "%d", labelnum++);
+    }
+
+    if (!*statement) {
+        *statement = apr_palloc(pool, sizeof(apr_dbd_prepared_t));
+    }
+    stmt = *statement;
+
+#if 0
+    /* count args */
+    stmt->fmt = apr_pstrdup(pool, query);
+    stmt->fmt = recurse_args(pool, 0, query, stmt, stmt->fmt);
+
+    /* overestimate by a byte or two to simplify */
+    len = strlen("CREATE PROC apr.")
+            + strlen(label)
+            + stmt->nargs * strlen(" @arg1 varchar(len1),")
+            + strlen(" AS begin ")
+            + strlen(stmt->fmt)
+            + strlen(" end "); /* extra byte for terminator */
+
+    pquery = apr_pcalloc(pool, len);
+    sprintf(pquery, "CREATE PROC apr.%s", label);
+    for (i=0; i<stmt->nargs; ++i) {
+        sprintf(pquery+strlen(pquery), " @arg%d varchar(%d)", i, stmt->sz[i]);
+        if (i < stmt->nargs-1) {
+            pquery[strlen(pquery)] = ',';
+        }
+    }
+    strcat(pquery, " AS BEGIN ");
+    strcat(pquery, stmt->fmt);
+    strcat(pquery, " END");
+
+    return (freetds_exec(sql->proc, pquery, 0, &i) == SUCCEED) ? 0 : 1;
+#else
+    stmt->fmt = apr_pstrdup(pool, query);
+    return recurse_args(pool, 0, query, stmt, 0);
+#endif
+
+}
+
+static int dbd_freetds_start_transaction(apr_pool_t *pool, apr_dbd_t *handle,
+                                         apr_dbd_transaction_t **trans)
+{
+    int dummy;
+
+    /* XXX handle recursive transactions here */
+
+    handle->err = freetds_exec(handle->proc, "BEGIN TRANSACTION", 0, &dummy);
+
+    if (dbd_freetds_is_success(handle->err)) {
+        if (!*trans) {
+            *trans = apr_pcalloc(pool, sizeof(apr_dbd_transaction_t));
+        }
+        (*trans)->handle = handle;
+        handle->trans = *trans;
+        return 0;
+    }
+
+    return 1;
+}
+
+static int dbd_freetds_end_transaction(apr_dbd_transaction_t *trans)
+{
+    int dummy;
+    if (trans) {
+        /* rollback on error or explicit rollback request */
+        if (trans->errnum) {
+            trans->errnum = 0;
+            trans->handle->err = freetds_exec(trans->handle->proc,
+                                              "ROLLBACK", 0, &dummy);
+        }
+        else {
+            trans->handle->err = freetds_exec(trans->handle->proc,
+                                              "COMMIT", 0, &dummy);
+        }
+        trans->handle->trans = NULL;
+    }
+    return (trans->handle->err == SUCCEED) ? 0 : 1;
+}
+
+static DBPROCESS *freetds_open(apr_pool_t *pool, const char *params,
+                               const char **error)
+{
+    char *server = NULL;
+    DBPROCESS *process;
+    LOGINREC *login;
+    static const char *delims = " \r\n\t;|,";
+    char *ptr;
+    char *key;
+    char *value;
+    int vlen;
+    int klen;
+    char *buf;
+    char *databaseName = NULL;
+
+    /* FIXME - this uses malloc */
+    /* FIXME - pass error message back to the caller in case of failure */
+    login = dblogin();
+    if (login == NULL) {
+        return NULL;
+    }
+    /* now set login properties */
+    for (ptr = strchr(params, '='); ptr; ptr = strchr(ptr, '=')) {
+        /* don't dereference memory that may not belong to us */
+        if (ptr == params) {
+            ++ptr;
+            continue;
+        }
+        for (key = ptr-1; apr_isspace(*key); --key);
+        klen = 0;
+        while (apr_isalpha(*key)) {
+            --key;
+            ++klen;
+        }
+        ++key;
+        for (value = ptr+1; apr_isspace(*value); ++value);
+
+        vlen = strcspn(value, delims);
+        buf = apr_pstrndup(pool, value, vlen);        /* NULL-terminated copy */
+
+        if (!strncasecmp(key, "username", klen)) {
+            DBSETLUSER(login, buf);
+        }
+        else if (!strncasecmp(key, "password", klen)) {
+            DBSETLPWD(login, buf);
+        }
+        else if (!strncasecmp(key, "appname", klen)) {
+            DBSETLAPP(login, buf);
+        }
+        else if (!strncasecmp(key, "dbname", klen)) {
+            databaseName = buf;
+        }
+        else if (!strncasecmp(key, "host", klen)) {
+            DBSETLHOST(login, buf);
+        }
+        else if (!strncasecmp(key, "charset", klen)) {
+            DBSETLCHARSET(login, buf);
+        }
+        else if (!strncasecmp(key, "lang", klen)) {
+            DBSETLNATLANG(login, buf);
+        }
+        else if (!strncasecmp(key, "server", klen)) {
+            server = buf;
+        }
+        else {
+            /* unknown param */
+        }
+        ptr = value+vlen;
+    }
+
+    process = dbopen(login, server);
+
+    if (process != NULL && databaseName != NULL)
+    {
+        dbuse(process, databaseName);
+    }
+ 
+    dbloginfree(login);
+    if (process == NULL) {
+        return NULL;
+    }
+
+    return process;
+}
+static apr_dbd_t *dbd_freetds_open(apr_pool_t *pool, const char *params,
+                                   const char **error)
+{
+    apr_dbd_t *sql;
+    /* FIXME - pass error message back to the caller in case of failure */
+    DBPROCESS *process = freetds_open(pool, params, error);
+    if (process == NULL) {
+        return NULL;
+    }
+    sql = apr_pcalloc(pool, sizeof (apr_dbd_t));
+    sql->pool = pool;
+    sql->proc = process;
+    sql->params = params;
+    return sql;
+}
+
+static apr_status_t dbd_freetds_close(apr_dbd_t *handle)
+{
+    dbclose(handle->proc);
+    return APR_SUCCESS;
+}
+
+static apr_status_t dbd_freetds_check_conn(apr_pool_t *pool,
+                                           apr_dbd_t *handle)
+{
+    if (dbdead(handle->proc)) {
+        /* try again */
+        dbclose(handle->proc);
+        handle->proc = freetds_open(handle->pool, handle->params, NULL);
+        if (!handle->proc || dbdead(handle->proc)) {
+            return APR_EGENERAL;
+        }
+    }
+    /* clear it, in case this is called in error handling */
+    dbcancel(handle->proc);
+    return APR_SUCCESS;
+}
+
+static int dbd_freetds_select_db(apr_pool_t *pool, apr_dbd_t *handle,
+                               const char *name)
+{
+    /* ouch, it's declared int.  But we can use APR 0/nonzero */
+    return (dbuse(handle->proc, (char*)name) == SUCCEED) ? APR_SUCCESS : APR_EGENERAL;
+}
+
+static void *dbd_freetds_native(apr_dbd_t *handle)
+{
+    return handle->proc;
+}
+
+static int dbd_freetds_num_cols(apr_dbd_results_t* res)
+{
+    return res->sz;
+}
+
+static int dbd_freetds_num_tuples(apr_dbd_results_t* res)
+{
+    if (res->random) {
+        return res->ntuples;
+    }
+    else {
+        return -1;
+    }
+}
+
+static apr_status_t freetds_term(void *dummy)
+{
+    dbexit();
+    regfree(&dbd_freetds_find_arg);
+    return APR_SUCCESS;
+}
+static int freetds_err_handler(DBPROCESS *dbproc, int severity, int dberr,
+                               int oserr, char *dberrstr, char *oserrstr)
+{
+    return INT_CANCEL; /* never exit */
+}
+static void dbd_freetds_init(apr_pool_t *pool)
+{
+    int rv = regcomp(&dbd_freetds_find_arg,
+                     "%(\\{[^}]*\\})?([0-9]*)[A-Za-z]", REG_EXTENDED);
+    if (rv != 0) {
+        char errmsg[256];
+        regerror(rv, &dbd_freetds_find_arg, errmsg, 256);
+        fprintf(stderr, "regcomp failed: %s\n", errmsg);
+    }
+    dbinit();
+    dberrhandle(freetds_err_handler);
+    apr_pool_cleanup_register(pool, NULL, freetds_term, apr_pool_cleanup_null);
+}
+
+#ifdef COMPILE_STUBS
+/* get_name is the only one of these that is implemented */
+static const char *dbd_freetds_get_name(const apr_dbd_results_t *res, int n)
+{
+    return (const char*) dbcolname(res->proc, n+1); /* numbering starts at 1 */
+}
+
+/* These are stubs: transaction modes not implemented here */
+#define DBD_NOTIMPL APR_ENOTIMPL;
+static int dbd_freetds_transaction_mode_get(apr_dbd_transaction_t *trans)
+{
+    return trans ? trans->mode : APR_DBD_TRANSACTION_COMMIT;
+}
+
+static int dbd_freetds_transaction_mode_set(apr_dbd_transaction_t *trans,
+                                            int mode)
+{
+    if (trans) {
+        trans->mode = mode & TXN_MODE_BITS;
+        return trans->mode;
+    }
+    return APR_DBD_TRANSACTION_COMMIT;
+}
+static int dbd_freetds_pvbquery(apr_pool_t *pool, apr_dbd_t *sql, int *nrows,
+                                apr_dbd_prepared_t *statement, va_list args)
+{
+    return DBD_NOTIMPL;
+}
+static int dbd_freetds_pbquery(apr_pool_t *pool, apr_dbd_t *sql, int *nrows,
+                               apr_dbd_prepared_t * statement,
+                               const void **values)
+{
+    return DBD_NOTIMPL;
+}
+
+static int dbd_freetds_pvbselect(apr_pool_t *pool, apr_dbd_t *sql,
+                                 apr_dbd_results_t **results,
+                                 apr_dbd_prepared_t *statement,
+                                 int seek, va_list args)
+{
+    return DBD_NOTIMPL;
+}
+static int dbd_freetds_pbselect(apr_pool_t *pool, apr_dbd_t *sql,
+                                apr_dbd_results_t **results,
+                                apr_dbd_prepared_t *statement,
+                                int seek, const void **values)
+{
+    return DBD_NOTIMPL;
+}
+static apr_status_t dbd_freetds_datum_get(const apr_dbd_row_t *row, int n,
+                                          apr_dbd_type_e type, void *data)
+{
+    return APR_ENOTIMPL;
+}
+#endif
+
+APR_MODULE_DECLARE_DATA const apr_dbd_driver_t apr_dbd_freetds_driver = {
+    "freetds",
+    dbd_freetds_init,
+    dbd_freetds_native,
+    dbd_freetds_open,
+    dbd_freetds_check_conn,
+    dbd_freetds_close,
+    dbd_freetds_select_db,
+    dbd_freetds_start_transaction,
+    dbd_freetds_end_transaction,
+    dbd_freetds_query,
+    dbd_freetds_select,
+    dbd_freetds_num_cols,
+    dbd_freetds_num_tuples,
+    dbd_freetds_get_row,
+    dbd_freetds_get_entry,
+    dbd_freetds_error,
+    dbd_freetds_escape,
+    dbd_freetds_prepare,
+    dbd_freetds_pvquery,
+    dbd_freetds_pvselect,
+    dbd_freetds_pquery,
+    dbd_freetds_pselect,
+    /* this is only implemented to support httpd/2.2 standard usage,
+     * as in the original DBD implementation.  Everything else is NOTIMPL.
+     */
+#ifdef COMPILE_STUBS
+    dbd_freetds_get_name,
+    dbd_freetds_transaction_mode_get,
+    dbd_freetds_transaction_mode_set,
+    "",
+    dbd_freetds_pvbquery,
+    dbd_freetds_pvbselect,
+    dbd_freetds_pbquery,
+    dbd_freetds_pbselect,
+    dbd_freetds_datum_get
+#endif
+};
+#endif
+
+#endif
diff --git a/dbd/unsupported/apr_dbd_freetds.dsp b/dbd/unsupported/apr_dbd_freetds.dsp
new file mode 100644
index 00000000000..f69ffac4bba
--- /dev/null
+++ b/dbd/unsupported/apr_dbd_freetds.dsp
@@ -0,0 +1,207 @@
+# Microsoft Developer Studio Project File - Name="apr_dbd_freetds" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=apr_dbd_freetds - 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 "apr_dbd_freetds.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 "apr_dbd_freetds.mak" CFG="apr_dbd_freetds - Win32 Release"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "apr_dbd_freetds - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_dbd_freetds - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_dbd_freetds - x64 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_dbd_freetds - x64 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)" == "apr_dbd_freetds - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /Zi /O2 /Oy- /I "../include" /I "../include/arch/win32" /I "../include/private" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_FREETDS=1 /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbd_freetds_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /fo"Release/apr_dbd_freetds-1.res" /d DLL_NAME="apr_dbd_freetds" /d "NDEBUG" /d "APU_VERSION_ONLY" /I "../include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libTDS.lib /nologo /base:"0x6EF60000" /subsystem:windows /dll /incremental:no /debug /opt:ref
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libTDS.lib /nologo /base:"0x6EF60000" /subsystem:windows /dll /incremental:no /debug /out:"Release\apr_dbd_freetds-1.dll" /pdb:"Release\apr_dbd_freetds-1.pdb" /implib:"Release\apr_dbd_freetds-1.lib" /MACHINE:X86 /opt:ref
+# Begin Special Build Tool
+TargetPath=Release\apr_dbd_freetds-1.dll
+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)" == "apr_dbd_freetds - 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 /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /EHsc /c
+# ADD CPP /nologo /MDd /W3 /Zi /Od /I "../include" /I "../include/arch/win32" /I "../include/private" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_FREETDS=1 /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbd_freetds_src" /FD /EHsc /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /fo"Debug/apr_dbd_freetds-1.res" /d DLL_NAME="apr_dbd_freetds" /d "_DEBUG" /d "APU_VERSION_ONLY" /I "../include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libTDS.lib /nologo /base:"0x6EF60000" /subsystem:windows /dll /incremental:no /debug
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libTDS.lib /nologo /base:"0x6EF60000" /subsystem:windows /dll /incremental:no /debug /out:"Debug\apr_dbd_freetds-1.dll" /pdb:"Debug\apr_dbd_freetds-1.pdb" /implib:"Debug\apr_dbd_freetds-1.lib" /MACHINE:X86
+# Begin Special Build Tool
+TargetPath=Debug\apr_dbd_freetds-1.dll
+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)" == "apr_dbd_freetds - x64 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "x64\Release"
+# PROP BASE Intermediate_Dir "x64\Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "x64\Release"
+# PROP Intermediate_Dir "x64\Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /Zi /O2 /Oy- /I "../include" /I "../include/arch/win32" /I "../include/private" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_FREETDS=1 /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbd_freetds_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /fo"x64/Release/apr_dbd_freetds-1.res" /d DLL_NAME="apr_dbd_freetds" /d "NDEBUG" /d "APU_VERSION_ONLY" /I "../include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libTDS.lib /nologo /base:"0x6EF60000" /subsystem:windows /dll /incremental:no /debug /opt:ref
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libTDS.lib /nologo /base:"0x6EF60000" /subsystem:windows /dll /incremental:no /debug /out:"x64\Release\apr_dbd_freetds-1.dll" /pdb:"x64\Release\apr_dbd_freetds-1.pdb" /implib:"x64\Release\apr_dbd_freetds-1.lib" /MACHINE:X64 /opt:ref
+# Begin Special Build Tool
+TargetPath=x64\Release\apr_dbd_freetds-1.dll
+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)" == "apr_dbd_freetds - x64 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "x64\Debug"
+# PROP BASE Intermediate_Dir "x64\Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "x64\Debug"
+# PROP Intermediate_Dir "x64\Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /EHsc /c
+# ADD CPP /nologo /MDd /W3 /Zi /Od /I "../include" /I "../include/arch/win32" /I "../include/private" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_FREETDS=1 /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbd_freetds_src" /FD /EHsc /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /fo"x64/Debug/apr_dbd_freetds-1.res" /d DLL_NAME="apr_dbd_freetds" /d "_DEBUG" /d "APU_VERSION_ONLY" /I "../include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libTDS.lib /nologo /base:"0x6EF60000" /subsystem:windows /dll /incremental:no /debug
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libTDS.lib /nologo /base:"0x6EF60000" /subsystem:windows /dll /incremental:no /debug /out:"x64\Debug\apr_dbd_freetds-1.dll" /pdb:"x64\Debug\apr_dbd_freetds-1.pdb" /implib:"x64\Debug\apr_dbd_freetds-1.lib" /MACHINE:X64
+# Begin Special Build Tool
+TargetPath=x64\Debug\apr_dbd_freetds-1.dll
+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 "apr_dbd_freetds - Win32 Release"
+# Name "apr_dbd_freetds - Win32 Debug"
+# Name "apr_dbd_freetds - x64 Release"
+# Name "apr_dbd_freetds - x64 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\apr_dbd_freetds.c
+# End Source File
+# End Group
+# Begin Group "Public Header Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\include\apr_dbd.h
+# End Source File
+# End Group
+# Begin Group "Internal Header Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\include\private\apu_config.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\private\apu_dbd_internal.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\private\apu_internal.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\libapr.rc
+# End Source File
+# End Target
+# End Project
diff --git a/dbm/NWGNUdbmdb b/dbm/NWGNUdbmdb
new file mode 100644
index 00000000000..266d0d06730
--- /dev/null
+++ b/dbm/NWGNUdbmdb
@@ -0,0 +1,293 @@
+#
+# 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
+#
+
+ifndef EnvironmentDefined
+include $(APR_WORK)/build/NWGNUhead.inc
+endif
+
+#
+# build this level's files
+
+#
+# Make sure all needed macro's are defined
+#
+
+# LINK_STATIC = 1
+
+# for now defined here - should finally go into build/NWGNUenvironment.inc
+DB_INC = $(DBSDK)/inc
+DB_IMP = $(DBSDK)/imp/libdb47.imp
+DB_LIB = $(DBSDK)/lib/libdb47.lib
+DB_NLM = libdb47
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS	+= \
+			$(APR)/include/arch/netware \
+			$(APR)/include \
+			$(APR)/include/private \
+			$(APR) \
+			$(DB_INC) \
+			$(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS		+= \
+			$(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES	+= \
+			-DAPU_DSO_MODULE_BUILD \
+			-DAPU_HAVE_DB=1 \
+			-DAPU_HAVE_DB_VERSION=4 \
+			$(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS		+= \
+			$(EOLIST)
+
+ifdef LINK_STATIC
+XLFLAGS		+= \
+			$(EOLIST)
+else
+XLFLAGS		+= \
+			$(EOLIST)
+endif
+
+#
+# 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	= dbmdb
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION	= Apache Portability Runtime Library $(VERSION_STR) DBM Berkeley DB Driver Module
+
+#
+# This is used by the '-threadname' directive.  If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME	= dbmdb
+
+#
+# If this is specified, it will override VERSION value in
+# $(APR_WORK)/build/NWGNUenvironment.inc
+#
+NLM_VERSION	=
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE	=
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM	=
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM	=
+
+#
+# If this is specified it will be used by the link '-check' directive
+#
+NLM_CHECK_SYM	=
+
+#
+# If these are specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS	=
+
+#
+# If this is specified it will be linked in with the XDCData option in the def
+# file instead of the default of $(NWOS)/apache.xdc.  XDCData can be disabled
+# by setting APACHE_UNIPROC in the environment
+#
+XDCDATA		=
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+	$(OBJDIR)\$(NLM_NAME).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)/apr_dbm_berkeleydb.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)
+
+ifeq ($(LINK_STATIC),1)
+FILES_nlm_libs += \
+	$(DB_LIB) \
+	$(EOLIST)
+endif
+
+#
+# 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)
+
+ifneq ($(LINK_STATIC),1)
+FILES_nlm_modules += \
+	$(DB_NLM) \
+	$(EOLIST)
+endif
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+	@$(APR)/aprlib.imp \
+	@$(NOVI)/libc.imp \
+	$(EOLIST)
+
+ifneq ($(LINK_STATIC),1)
+FILES_nlm_Ximports += \
+	@$(DB_IMP) \
+	$(EOLIST)
+endif
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+	apr_dbm_type_db \
+	$(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 $(APR_WORK)/build/NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(APRBUILD)/NWGNUtail.inc
+
diff --git a/dbm/NWGNUdbmgdbm b/dbm/NWGNUdbmgdbm
new file mode 100644
index 00000000000..f72ce53e634
--- /dev/null
+++ b/dbm/NWGNUdbmgdbm
@@ -0,0 +1,292 @@
+#
+# 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
+#
+
+ifndef EnvironmentDefined
+include $(APR_WORK)/build/NWGNUhead.inc
+endif
+
+#
+# build this level's files
+
+#
+# Make sure all needed macro's are defined
+#
+
+# LINK_STATIC = 1
+
+# for now defined here - should finally go into build/NWGNUenvironment.inc
+GDBM_INC = $(GDBMSDK)/inc
+GDBM_IMP = $(GDBMSDK)/imp/libgdbm.imp
+GDBM_LIB = $(GDBMSDK)/lib/libgdbm.lib
+GDBM_NLM = libgdbm
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS	+= \
+			$(APR)/include/arch/netware \
+			$(APR)/include \
+			$(APR)/include/private \
+			$(APR) \
+			$(GDBM_INC) \
+			$(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS		+= \
+			$(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES	+= \
+			-DAPU_DSO_MODULE_BUILD \
+			-DAPU_HAVE_GDBM=1 \
+			$(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS		+= \
+			$(EOLIST)
+
+ifdef LINK_STATIC
+XLFLAGS		+= \
+			$(EOLIST)
+else
+XLFLAGS		+= \
+			$(EOLIST)
+endif
+
+#
+# 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	= dbmgdbm
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION	= Apache Portability Runtime Library $(VERSION_STR) GDBM Driver Module
+
+#
+# This is used by the '-threadname' directive.  If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME	= dbmgdbm
+
+#
+# If this is specified, it will override VERSION value in
+# $(APR_WORK)/build/NWGNUenvironment.inc
+#
+NLM_VERSION	=
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE	=
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM	=
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM	=
+
+#
+# If this is specified it will be used by the link '-check' directive
+#
+NLM_CHECK_SYM	=
+
+#
+# If these are specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS	=
+
+#
+# If this is specified it will be linked in with the XDCData option in the def
+# file instead of the default of $(NWOS)/apache.xdc.  XDCData can be disabled
+# by setting APACHE_UNIPROC in the environment
+#
+XDCDATA		=
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+	$(OBJDIR)\$(NLM_NAME).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)/apr_dbm_gdbm.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)
+
+ifeq ($(LINK_STATIC),1)
+FILES_nlm_libs += \
+	$(GDBM_LIB) \
+	$(EOLIST)
+endif
+
+#
+# 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)
+
+ifneq ($(LINK_STATIC),1)
+FILES_nlm_modules += \
+	$(GDBM_NLM) \
+	$(EOLIST)
+endif
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+	@$(APR)/aprlib.imp \
+	@$(NOVI)/libc.imp \
+	$(EOLIST)
+
+ifneq ($(LINK_STATIC),1)
+FILES_nlm_Ximports += \
+	@$(GDBM_IMP) \
+	$(EOLIST)
+endif
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+	apr_dbm_type_gdbm \
+	$(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 $(APR_WORK)/build/NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(APRBUILD)/NWGNUtail.inc
+
diff --git a/dbm/NWGNUmakefile b/dbm/NWGNUmakefile
new file mode 100644
index 00000000000..228a45d11d2
--- /dev/null
+++ b/dbm/NWGNUmakefile
@@ -0,0 +1,251 @@
+#
+# 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 $(APR_WORK)/build/NWGNUhead.inc
+
+#
+# build this level's files
+
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS	+= \
+			$(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS		+= \
+			$(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES	+= \
+			$(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS		+= \
+			$(EOLIST)
+
+#
+# These values will be appended to the correct variables based on the value of
+# RELEASE
+#
+ifeq "$(RELEASE)" "debug"
+XINCDIRS	+= \
+			$(EOLIST)
+
+XCFLAGS		+= \
+			$(EOLIST)
+
+XDEFINES	+= \
+			$(EOLIST)
+
+XLFLAGS		+= \
+			$(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "noopt"
+XINCDIRS	+= \
+			$(EOLIST)
+
+XCFLAGS		+= \
+			$(EOLIST)
+
+XDEFINES	+= \
+			$(EOLIST)
+
+XLFLAGS		+= \
+			$(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "release"
+XINCDIRS	+= \
+			$(EOLIST)
+
+XCFLAGS		+= \
+			$(EOLIST)
+
+XDEFINES	+= \
+			$(EOLIST)
+
+XLFLAGS		+= \
+			$(EOLIST)
+endif
+
+#
+# These are used by the link target if an NLM is being generated
+# This is used by the link 'name' directive to name the nlm.  If left blank
+# TARGET_nlm (see below) will be used.
+#
+NLM_NAME	=
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION	=
+
+#
+# This is used by the '-threadname' directive.  If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME	=
+
+#
+# If this is specified, it will override VERSION value in
+# $(APR_WORK)/build/NWGNUenvironment.inc
+#
+NLM_VERSION	=
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE	=
+
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM	=
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM	=
+
+#
+# If this is specified it will be used by the link '-check' directive
+#
+NLM_CHECK_SYM	=
+
+#
+# If these are specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS	=
+
+#
+# If this is specified it will be linked in with the XDCData option in the def
+# file instead of the default of $(NWOS)/apache.xdc.  XDCData can be disabled
+# by setting APACHE_UNIPROC in the environment
+#
+XDCDATA		=
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+	$(EOLIST)
+
+ifeq "$(APU_HAVE_DB)" "1"
+TARGET_nlm += $(OBJDIR)/dbmdb.nlm $(OBJDIR)/dbmdb.nlm $(EOLIST)
+endif
+ifeq "$(APU_HAVE_GDBM)" "1"
+TARGET_nlm += $(OBJDIR)/dbmgdbm.nlm $(OBJDIR)/dbmgdbm.nlm $(EOLIST)
+endif
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+	$(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+	$(EOLIST)
+
+#
+# These are the LIB files needed to create the NLM target above.
+# These will be added as a library command in the link.opt file.
+#
+FILES_nlm_libs = \
+	$(EOLIST)
+
+#
+# These are the modules that the above NLM target depends on to load.
+# These will be added as a module command in the link.opt file.
+#
+FILES_nlm_modules = \
+	$(EOLIST)
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+	$(EOLIST)
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+	$(EOLIST)
+
+#
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+	$(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the
+# correct place.  (See $(APR_WORK)/build/NWGNUhead.inc for examples)
+#
+install :: nlms $(INSTDIRS) FORCE
+	$(call COPY,$(OBJDIR)/*.nlm,$(INSTALLBASE)/)
+
+#
+# Any specialized rules here
+#
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(APRBUILD)/NWGNUtail.inc
+
+
diff --git a/dbm/apr_dbm.c b/dbm/apr_dbm.c
new file mode 100644
index 00000000000..71ba113ec47
--- /dev/null
+++ b/dbm/apr_dbm.c
@@ -0,0 +1,307 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_dso.h"
+#include "apr_hash.h"
+#include "apr_errno.h"
+#include "apr_pools.h"
+#include "apr_strings.h"
+#define APR_WANT_MEMFUNC
+#define APR_WANT_STRFUNC
+#include "apr_want.h"
+#include "apr_general.h"
+#include "apr_atomic.h"
+
+#include "apu.h"
+#include "apr_private.h"
+#include "apu_internal.h"
+#include "apr_version.h"
+#include "apr_dbm_private.h"
+#include "apu_select_dbm.h"
+#include "apr_dbm.h"
+#include "apr_dbm_private.h"
+
+/* ### note: the setting of DBM_VTABLE will go away once we have multiple
+   ### DBMs in here. 
+   ### Well, that day is here.  So, do we remove DBM_VTABLE and the old
+   ### API entirely?  Oh, what to do.  We need an APU_DEFAULT_DBM #define.
+   ### Sounds like a job for autoconf. */
+
+#if APU_USE_DB
+#define DBM_VTABLE apr_dbm_type_db
+#define DBM_NAME   "db"
+#elif APU_USE_GDBM
+#define DBM_VTABLE apr_dbm_type_gdbm
+#define DBM_NAME   "gdbm"
+#elif APU_USE_NDBM
+#define DBM_VTABLE apr_dbm_type_ndbm
+#define DBM_NAME   "ndbm"
+#elif APU_USE_SDBM
+#define DBM_VTABLE apr_dbm_type_sdbm
+#define DBM_NAME   "sdbm"
+#else /* Not in the USE_xDBM list above */
+#error a DBM implementation was not specified
+#endif
+
+#if APR_HAVE_MODULAR_DSO
+
+static apr_hash_t *drivers = NULL;
+static apr_uint32_t initialised = 0, in_init = 1;
+
+static apr_status_t dbm_term(void *ptr)
+{
+    /* set drivers to NULL so init can work again */
+    drivers = NULL;
+
+    /* Everything else we need is handled by cleanups registered
+     * when we created mutexes and loaded DSOs
+     */
+    return APR_SUCCESS;
+}
+
+#endif /* APR_HAVE_MODULAR_DSO */
+
+static apr_status_t dbm_open_type(apr_dbm_type_t const* * vtable,
+                                  const char *type, 
+                                  apr_pool_t *pool)
+{
+#if !APR_HAVE_MODULAR_DSO
+
+    *vtable = NULL;
+    if (!strcasecmp(type, "default"))     *vtable = &DBM_VTABLE;
+#if APU_HAVE_DB
+    else if (!strcasecmp(type, "db"))     *vtable = &apr_dbm_type_db;
+#endif
+    else if (*type && !strcasecmp(type + 1, "dbm")) {
+#if APU_HAVE_GDBM
+        if (*type == 'G' || *type == 'g') *vtable = &apr_dbm_type_gdbm;
+#endif
+#if APU_HAVE_NDBM
+        if (*type == 'N' || *type == 'n') *vtable = &apr_dbm_type_ndbm;
+#endif
+#if APU_HAVE_SDBM
+        if (*type == 'S' || *type == 's') *vtable = &apr_dbm_type_sdbm;
+#endif
+        /* avoid empty block */ ;
+    }
+    if (*vtable)
+        return APR_SUCCESS;
+    return APR_ENOTIMPL;
+
+#else /* APR_HAVE_MODULAR_DSO */
+
+    char modname[32];
+    char symname[34];
+    apr_dso_handle_sym_t symbol;
+    apr_status_t rv;
+    int usertype = 0;
+
+    if (!strcasecmp(type, "default"))        type = DBM_NAME;
+    else if (!strcasecmp(type, "db"))        type = "db";
+    else if (*type && !strcasecmp(type + 1, "dbm")) {
+        if      (*type == 'G' || *type == 'g') type = "gdbm"; 
+        else if (*type == 'N' || *type == 'n') type = "ndbm"; 
+        else if (*type == 'S' || *type == 's') type = "sdbm"; 
+    }
+    else usertype = 1;
+
+    if (apr_atomic_inc32(&initialised)) {
+        apr_atomic_set32(&initialised, 1); /* prevent wrap-around */
+
+        while (apr_atomic_read32(&in_init)) /* wait until we get fully inited */
+            ;
+    }
+    else {
+        apr_pool_t *parent;
+
+        /* Top level pool scope, need process-scope lifetime */
+        for (parent = apr_pool_parent_get(pool);
+             parent && parent != pool;
+             parent = apr_pool_parent_get(pool))
+            pool = parent;
+
+        /* deprecate in 2.0 - permit implicit initialization */
+        apu_dso_init(pool);
+
+        drivers = apr_hash_make(pool);
+        apr_hash_set(drivers, "sdbm", APR_HASH_KEY_STRING, &apr_dbm_type_sdbm);
+
+        apr_pool_cleanup_register(pool, NULL, dbm_term,
+                                  apr_pool_cleanup_null);
+
+        apr_atomic_dec32(&in_init);
+    }
+
+    rv = apu_dso_mutex_lock();
+    if (rv) {
+        *vtable = NULL;
+        return rv;
+    }
+
+    *vtable = apr_hash_get(drivers, type, APR_HASH_KEY_STRING);
+    if (*vtable) {
+        apu_dso_mutex_unlock();
+        return APR_SUCCESS;
+    }
+
+    /* The driver DSO must have exactly the same lifetime as the
+     * drivers hash table; ignore the passed-in pool */
+    pool = apr_hash_pool_get(drivers);
+
+#if defined(NETWARE)
+    apr_snprintf(modname, sizeof(modname), "dbm%s.nlm", type);
+#elif defined(WIN32) || defined (__CYGWIN__)
+    apr_snprintf(modname, sizeof(modname),
+                 "apr_dbm_%s-" APR_STRINGIFY(APR_MAJOR_VERSION) ".dll", type);
+#else
+    apr_snprintf(modname, sizeof(modname),
+                 "apr_dbm_%s-" APR_STRINGIFY(APR_MAJOR_VERSION) ".so", type);
+#endif
+    apr_snprintf(symname, sizeof(symname), "apr_dbm_type_%s", type);
+
+    rv = apu_dso_load(NULL, &symbol, modname, symname, pool);
+    if (rv == APR_SUCCESS || rv == APR_EINIT) { /* previously loaded?!? */
+        *vtable = symbol;
+        if (usertype)
+            type = apr_pstrdup(pool, type);
+        apr_hash_set(drivers, type, APR_HASH_KEY_STRING, *vtable);
+        rv = APR_SUCCESS;
+    }
+    else
+        *vtable = NULL;
+
+    apu_dso_mutex_unlock();
+    return rv;
+
+#endif /* APR_HAVE_MODULAR_DSO */
+}
+
+APR_DECLARE(apr_status_t) apr_dbm_open_ex(apr_dbm_t **pdb, const char *type, 
+                                          const char *pathname, 
+                                          apr_int32_t mode,
+                                          apr_fileperms_t perm,
+                                          apr_pool_t *pool)
+{
+    apr_dbm_type_t const* vtable = NULL;
+    apr_status_t rv = dbm_open_type(&vtable, type, pool);
+
+    if (rv == APR_SUCCESS) {
+        rv = (vtable->open)(pdb, pathname, mode, perm, pool);
+    }
+    return rv;
+} 
+
+APR_DECLARE(apr_status_t) apr_dbm_open(apr_dbm_t **pdb, const char *pathname, 
+                                       apr_int32_t mode, apr_fileperms_t perm,
+                                       apr_pool_t *pool)
+{
+    return apr_dbm_open_ex(pdb, DBM_NAME, pathname, mode, perm, pool);
+}
+
+APR_DECLARE(void) apr_dbm_close(apr_dbm_t *dbm)
+{
+    (*dbm->type->close)(dbm);
+}
+
+APR_DECLARE(apr_status_t) apr_dbm_fetch(apr_dbm_t *dbm, apr_datum_t key,
+                                        apr_datum_t *pvalue)
+{
+    return (*dbm->type->fetch)(dbm, key, pvalue);
+}
+
+APR_DECLARE(apr_status_t) apr_dbm_store(apr_dbm_t *dbm, apr_datum_t key,
+                                        apr_datum_t value)
+{
+    return (*dbm->type->store)(dbm, key, value);
+}
+
+APR_DECLARE(apr_status_t) apr_dbm_delete(apr_dbm_t *dbm, apr_datum_t key)
+{
+    return (*dbm->type->del)(dbm, key);
+}
+
+APR_DECLARE(int) apr_dbm_exists(apr_dbm_t *dbm, apr_datum_t key)
+{
+    return (*dbm->type->exists)(dbm, key);
+}
+
+APR_DECLARE(apr_status_t) apr_dbm_firstkey(apr_dbm_t *dbm, apr_datum_t *pkey)
+{
+    return (*dbm->type->firstkey)(dbm, pkey);
+}
+
+APR_DECLARE(apr_status_t) apr_dbm_nextkey(apr_dbm_t *dbm, apr_datum_t *pkey)
+{
+    return (*dbm->type->nextkey)(dbm, pkey);
+}
+
+APR_DECLARE(void) apr_dbm_freedatum(apr_dbm_t *dbm, apr_datum_t data)
+{
+    (*dbm->type->freedatum)(dbm, data);
+}
+
+APR_DECLARE(char *) apr_dbm_geterror(apr_dbm_t *dbm, int *errcode,
+                                     char *errbuf, apr_size_t errbufsize)
+{
+    if (errcode != NULL)
+        *errcode = dbm->errcode;
+
+    /* assert: errbufsize > 0 */
+
+    if (dbm->errmsg == NULL)
+        *errbuf = '\0';
+    else
+        (void) apr_cpystrn(errbuf, dbm->errmsg, errbufsize);
+    return errbuf;
+}
+
+APR_DECLARE(apr_status_t) apr_dbm_get_usednames_ex(apr_pool_t *p, 
+                                                   const char *type, 
+                                                   const char *pathname,
+                                                   const char **used1,
+                                                   const char **used2)
+{
+    apr_dbm_type_t const* vtable;
+    apr_status_t rv = dbm_open_type(&vtable, type, p);
+
+    if (rv == APR_SUCCESS) {
+        (vtable->getusednames)(p, pathname, used1, used2);
+        return APR_SUCCESS;
+    }
+    return rv;
+} 
+
+APR_DECLARE(void) apr_dbm_get_usednames(apr_pool_t *p,
+                                        const char *pathname,
+                                        const char **used1,
+                                        const char **used2)
+{
+    apr_dbm_get_usednames_ex(p, DBM_NAME, pathname, used1, used2); 
+}
+
+/* Most DBM libraries take a POSIX mode for creating files.  Don't trust
+ * the mode_t type, some platforms may not support it, int is safe.
+ */
+APR_DECLARE(int) apr_posix_perms2mode(apr_fileperms_t perm)
+{
+    int mode = 0;
+
+    mode |= 0700 & (perm >> 2); /* User  is off-by-2 bits */
+    mode |= 0070 & (perm >> 1); /* Group is off-by-1 bit */
+    mode |= 0007 & (perm);      /* World maps 1 for 1 */
+    return mode;
+}
diff --git a/dbm/apr_dbm_berkeleydb.c b/dbm/apr_dbm_berkeleydb.c
new file mode 100644
index 00000000000..37e36bd22e0
--- /dev/null
+++ b/dbm/apr_dbm_berkeleydb.c
@@ -0,0 +1,404 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_strings.h"
+#define APR_WANT_MEMFUNC
+#include "apr_want.h"
+
+#define APU_WANT_DB
+#include "apu_want.h"
+
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h> /* for abort() */
+#endif
+
+#include "apu.h"
+#include "apr_private.h"
+
+#if APU_HAVE_DB 
+#include "apr_dbm_private.h"
+
+/*
+ * We pick up all varieties of Berkeley DB through db.h (included through
+ * apu_select_dbm.h). This code has been compiled/tested against DB1,
+ * DB_185, DB2, DB3, and DB4.
+ */
+
+#if   defined(DB_VERSION_MAJOR) && (DB_VERSION_MAJOR >= 4)
+/* We will treat anything greater than 4.1 as DB4.
+ * We can treat 4.0 as DB3.
+ */
+#if   DB_VERSION_MAJOR > 4 || (defined(DB_VERSION_MINOR) && (DB_VERSION_MINOR >= 1))
+#define DB_VER 4
+#elif DB_VERSION_MAJOR == 4
+#define DB_VER 3
+#endif
+#elif defined(DB_VERSION_MAJOR) && (DB_VERSION_MAJOR == 3)
+#define DB_VER 3
+#elif defined(DB_VERSION_MAJOR) && (DB_VERSION_MAJOR == 2)
+#define DB_VER 2
+#else
+#define DB_VER 1
+#endif
+
+typedef struct {
+    DB *bdb;
+#if DB_VER != 1
+    DBC *curs;
+#endif
+} real_file_t;
+
+
+#if DB_VER == 1
+#define TXN_ARG
+#else
+#define TXN_ARG NULL,
+#endif
+
+#define GET_BDB(f)      (((real_file_t *)(f))->bdb)
+
+#define do_fetch(bdb, k, v)     ((*(bdb)->get)(bdb, TXN_ARG &(k), &(v), 0))
+
+#if DB_VER == 1
+#include <sys/fcntl.h>
+#define APR_DBM_DBMODE_RO       O_RDONLY
+#define APR_DBM_DBMODE_RW       O_RDWR
+#define APR_DBM_DBMODE_RWCREATE (O_CREAT | O_RDWR)
+#define APR_DBM_DBMODE_RWTRUNC  (O_CREAT | O_RDWR | O_TRUNC)
+#else
+#define APR_DBM_DBMODE_RO       DB_RDONLY
+#define APR_DBM_DBMODE_RW       0
+#define APR_DBM_DBMODE_RWCREATE DB_CREATE
+#define APR_DBM_DBMODE_RWTRUNC  DB_TRUNCATE
+#endif /* DBVER == 1 */
+
+/* --------------------------------------------------------------------------
+**
+** UTILITY FUNCTIONS
+*/
+
+/* map a DB error to an apr_status_t */
+static apr_status_t db2s(int dberr)
+{
+    if (dberr != 0) {
+        /* ### need to fix this */
+        return APR_OS_START_USEERR + dberr;
+    }
+
+    return APR_SUCCESS;
+}
+
+
+static apr_status_t set_error(apr_dbm_t *dbm, apr_status_t dbm_said)
+{
+    apr_status_t rv = APR_SUCCESS;
+
+    /* ### ignore whatever the DBM said (dbm_said); ask it explicitly */
+
+    if (dbm_said == APR_SUCCESS) {
+        dbm->errcode = 0;
+        dbm->errmsg = NULL;
+    }
+    else {
+        /* ### need to fix. dberr was tossed in db2s(). */
+        /* ### use db_strerror() */
+        dbm->errcode = dbm_said;
+#if DB_VER == 1 || DB_VER == 2
+        dbm->errmsg = NULL;
+#else
+        dbm->errmsg = db_strerror(dbm_said - APR_OS_START_USEERR);
+#endif
+        rv = dbm_said;
+    }
+
+    return rv;
+}
+
+/* --------------------------------------------------------------------------
+**
+** DEFINE THE VTABLE FUNCTIONS FOR BERKELEY DB
+**
+** ### we may need three sets of these: db1, db2, db3
+*/
+
+static apr_status_t vt_db_open(apr_dbm_t **pdb, const char *pathname,
+                               apr_int32_t mode, apr_fileperms_t perm,
+                               apr_pool_t *pool)
+{
+    real_file_t file;
+    int dbmode;
+
+    *pdb = NULL;
+
+    switch (mode) {
+    case APR_DBM_READONLY:
+        dbmode = APR_DBM_DBMODE_RO;
+        break;
+    case APR_DBM_READWRITE:
+        dbmode = APR_DBM_DBMODE_RW;
+        break;
+    case APR_DBM_RWCREATE:
+        dbmode = APR_DBM_DBMODE_RWCREATE;
+        break;
+    case APR_DBM_RWTRUNC:
+        dbmode = APR_DBM_DBMODE_RWTRUNC;
+        break;
+    default:
+        return APR_EINVAL;
+    }
+
+    {
+        int dberr;
+
+#if DB_VER >= 3
+        if ((dberr = db_create(&file.bdb, NULL, 0)) == 0) {
+            if ((dberr = (*file.bdb->open)(file.bdb,
+#if DB_VER == 4
+                                           NULL,
+#endif
+                                           pathname, NULL, 
+                                           DB_HASH, dbmode, 
+                                           apr_posix_perms2mode(perm))) != 0) {
+                /* close the DB handler */
+                (void) (*file.bdb->close)(file.bdb, 0);
+            }
+        }
+        file.curs = NULL;
+#elif DB_VER == 2
+        dberr = db_open(pathname, DB_HASH, dbmode, apr_posix_perms2mode(perm),
+                        NULL, NULL, &file.bdb);
+        file.curs = NULL;
+#else
+        file.bdb = dbopen(pathname, dbmode, apr_posix_perms2mode(perm),
+                          DB_HASH, NULL);
+        if (file.bdb == NULL)
+            return APR_EGENERAL;      /* ### need a better error */
+        dberr = 0;
+#endif
+        if (dberr != 0)
+            return db2s(dberr);
+    }
+
+    /* we have an open database... return it */
+    *pdb = apr_pcalloc(pool, sizeof(**pdb));
+    (*pdb)->pool = pool;
+    (*pdb)->type = &apr_dbm_type_db;
+    (*pdb)->file = apr_pmemdup(pool, &file, sizeof(file));
+
+    /* ### register a cleanup to close the DBM? */
+
+    return APR_SUCCESS;
+}
+
+static void vt_db_close(apr_dbm_t *dbm)
+{
+    (*GET_BDB(dbm->file)->close)(GET_BDB(dbm->file)
+#if DB_VER != 1
+                                 , 0
+#endif
+        );
+}
+
+static apr_status_t vt_db_fetch(apr_dbm_t *dbm, apr_datum_t key,
+                                apr_datum_t * pvalue)
+{
+    DBT ckey = { 0 };
+    DBT rd = { 0 };
+    int dberr;
+
+    ckey.data = key.dptr;
+    ckey.size = key.dsize;
+
+    dberr = do_fetch(GET_BDB(dbm->file), ckey, rd);
+
+    /* "not found" is not an error. return zero'd value. */
+    if (dberr ==
+#if DB_VER == 1
+        RET_SPECIAL
+#else
+        DB_NOTFOUND
+#endif
+        ) {
+        memset(&rd, 0, sizeof(rd));
+        dberr = 0;
+    }
+
+    pvalue->dptr = rd.data;
+    pvalue->dsize = rd.size;
+
+    /* store the error info into DBM, and return a status code. Also, note
+       that *pvalue should have been cleared on error. */
+    return set_error(dbm, db2s(dberr));
+}
+
+static apr_status_t vt_db_store(apr_dbm_t *dbm, apr_datum_t key,
+                                apr_datum_t value)
+{
+    apr_status_t rv;
+    DBT ckey = { 0 };
+    DBT cvalue = { 0 };
+
+    ckey.data = key.dptr;
+    ckey.size = key.dsize;
+
+    cvalue.data = value.dptr;
+    cvalue.size = value.dsize;
+
+    rv = db2s((*GET_BDB(dbm->file)->put)(GET_BDB(dbm->file),
+                                         TXN_ARG
+                                         &ckey,
+                                         &cvalue,
+                                         0));
+
+    /* store any error info into DBM, and return a status code. */
+    return set_error(dbm, rv);
+}
+
+static apr_status_t vt_db_del(apr_dbm_t *dbm, apr_datum_t key)
+{
+    apr_status_t rv;
+    DBT ckey = { 0 };
+
+    ckey.data = key.dptr;
+    ckey.size = key.dsize;
+
+    rv = db2s((*GET_BDB(dbm->file)->del)(GET_BDB(dbm->file),
+                                         TXN_ARG
+                                         &ckey,
+                                         0));
+
+    /* store any error info into DBM, and return a status code. */
+    return set_error(dbm, rv);
+}
+
+static int vt_db_exists(apr_dbm_t *dbm, apr_datum_t key)
+{
+    DBT ckey = { 0 };   /* converted key */
+    DBT data = { 0 };
+    int dberr;
+
+    ckey.data = key.dptr;
+    ckey.size = key.dsize;
+
+    dberr = do_fetch(GET_BDB(dbm->file), ckey, data);
+
+    /* note: the result data is "loaned" to us; we don't need to free it */
+
+    /* DB returns DB_NOTFOUND if it doesn't exist. but we want to say
+       that *any* error means it doesn't exist. */
+    return dberr == 0;
+}
+
+static apr_status_t vt_db_firstkey(apr_dbm_t *dbm, apr_datum_t * pkey)
+{
+    real_file_t *f = dbm->file;
+    DBT first = { 0 };
+    DBT data = { 0 };
+    int dberr;
+
+#if DB_VER == 1
+    dberr = (*f->bdb->seq)(f->bdb, &first, &data, R_FIRST);
+#else
+    if ((dberr = (*f->bdb->cursor)(f->bdb, NULL, &f->curs
+#if DB_VER >= 3 || ((DB_VERSION_MAJOR == 2) && (DB_VERSION_MINOR > 5))
+                                   , 0
+#endif
+             )) == 0) {
+        dberr = (*f->curs->c_get)(f->curs, &first, &data, DB_FIRST);
+        if (dberr == DB_NOTFOUND) {
+            memset(&first, 0, sizeof(first));
+            (*f->curs->c_close)(f->curs);
+            f->curs = NULL;
+            dberr = 0;
+        }
+    }
+#endif
+
+    pkey->dptr = first.data;
+    pkey->dsize = first.size;
+
+    /* store any error info into DBM, and return a status code. */
+    return set_error(dbm, db2s(dberr));
+}
+
+static apr_status_t vt_db_nextkey(apr_dbm_t *dbm, apr_datum_t * pkey)
+{
+    real_file_t *f = dbm->file;
+    DBT ckey = { 0 };
+    DBT data = { 0 };
+    int dberr;
+
+    ckey.data = pkey->dptr;
+    ckey.size = pkey->dsize;
+
+#if DB_VER == 1
+    dberr = (*f->bdb->seq)(f->bdb, &ckey, &data, R_NEXT);
+    if (dberr == RET_SPECIAL) {
+        dberr = 0;
+        ckey.data = NULL;
+        ckey.size = 0;
+    }
+#else
+    if (f->curs == NULL)
+        return APR_EINVAL;
+
+    dberr = (*f->curs->c_get)(f->curs, &ckey, &data, DB_NEXT);
+    if (dberr == DB_NOTFOUND) {
+        (*f->curs->c_close)(f->curs);
+        f->curs = NULL;
+        dberr = 0;
+        ckey.data = NULL;
+        ckey.size = 0;
+    }
+#endif
+
+    pkey->dptr = ckey.data;
+    pkey->dsize = ckey.size;
+
+    /* store any error info into DBM, and return a status code. */
+    /* ### or use db2s(dberr) instead of APR_SUCCESS? */
+    return set_error(dbm, APR_SUCCESS);
+}
+
+static void vt_db_freedatum(apr_dbm_t *dbm, apr_datum_t data)
+{
+    /* nothing to do */
+}
+
+static void vt_db_usednames(apr_pool_t *pool, const char *pathname,
+                            const char **used1, const char **used2)
+{
+    *used1 = apr_pstrdup(pool, pathname);
+    *used2 = NULL;
+}
+
+
+APR_MODULE_DECLARE_DATA const apr_dbm_type_t apr_dbm_type_db = {
+    "db",
+
+    vt_db_open,
+    vt_db_close,
+    vt_db_fetch,
+    vt_db_store,
+    vt_db_del,
+    vt_db_exists,
+    vt_db_firstkey,
+    vt_db_nextkey,
+    vt_db_freedatum,
+    vt_db_usednames
+};
+
+#endif /* APU_HAVE_DB */
diff --git a/dbm/apr_dbm_db.dsp b/dbm/apr_dbm_db.dsp
new file mode 100644
index 00000000000..78d7fde7e6e
--- /dev/null
+++ b/dbm/apr_dbm_db.dsp
@@ -0,0 +1,215 @@
+# Microsoft Developer Studio Project File - Name="apr_dbm_db" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=apr_dbm_db - 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 "apr_dbm_db.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 "apr_dbm_db.mak" CFG="apr_dbm_db - Win32 Release"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "apr_dbm_db - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_dbm_db - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_dbm_db - x64 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_dbm_db - x64 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)" == "apr_dbm_db - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /Zi /O2 /Oy- /I "../include" /I "../include/arch/win32" /I "../include/private" /I "../../db" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_DB=1 /D APU_HAVE_DB_VERSION=4 /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbm_db_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /fo"Release/apr_dbm_db-1.res" /d DLL_NAME="apr_dbm_db" /d "NDEBUG" /d "APU_VERSION_ONLY" /I "../include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libdb47.lib /nologo /base:"0x6F000000" /subsystem:windows /dll /incremental:no /debug /opt:ref
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libdb47.lib /nologo /base:"0x6F000000" /subsystem:windows /dll /incremental:no /libpath:"..\..\db" /debug /out:"Release\apr_dbm_db-1.dll" /pdb:"Release\apr_dbm_db-1.pdb" /implib:"Release\apr_dbm_db-1.lib" /MACHINE:X86 /opt:ref
+# Begin Special Build Tool
+TargetPath=Release\apr_dbm_db-1.dll
+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)" == "apr_dbm_db - 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 /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /EHsc /c
+# ADD CPP /nologo /MDd /W3 /Zi /Od /I "../include" /I "../include/arch/win32" /I "../include/private" /I "../../db" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_DB=1 /D APU_HAVE_DB_VERSION=4 /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbm_db_src" /FD /EHsc /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /fo"Debug/apr_dbm_db-1.res" /d DLL_NAME="apr_dbm_db" /d "_DEBUG" /d "APU_VERSION_ONLY" /I "../include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libdb47.lib /nologo /base:"0x6F000000" /subsystem:windows /dll /incremental:no /debug
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libdb47.lib /nologo /base:"0x6F000000" /subsystem:windows /dll /incremental:no /libpath:"..\..\db" /debug /out:"Debug\apr_dbm_db-1.dll" /pdb:"Debug\apr_dbm_db-1.pdb" /implib:"Debug\apr_dbm_db-1.lib" /MACHINE:X86
+# Begin Special Build Tool
+TargetPath=Debug\apr_dbm_db-1.dll
+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)" == "apr_dbm_db - x64 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "x64\Release"
+# PROP BASE Intermediate_Dir "x64\Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "x64\Release"
+# PROP Intermediate_Dir "x64\Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /Zi /O2 /Oy- /I "../include" /I "../include/arch/win32" /I "../include/private" /I "../../db" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_DB=1 /D APU_HAVE_DB_VERSION=4 /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbm_db_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /fo"x64/Release/apr_dbm_db-1.res" /d DLL_NAME="apr_dbm_db" /d "NDEBUG" /d "APU_VERSION_ONLY" /I "../include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libdb47.lib /nologo /base:"0x6F000000" /subsystem:windows /dll /incremental:no /debug /opt:ref
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libdb47.lib /nologo /base:"0x6F000000" /subsystem:windows /dll /incremental:no /libpath:"..\..\db" /debug /out:"x64\Release\apr_dbm_db-1.dll" /pdb:"x64\Release\apr_dbm_db-1.pdb" /implib:"x64\Release\apr_dbm_db-1.lib" /MACHINE:X64 /opt:ref
+# Begin Special Build Tool
+TargetPath=x64\Release\apr_dbm_db-1.dll
+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)" == "apr_dbm_db - x64 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "x64\Debug"
+# PROP BASE Intermediate_Dir "x64\Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "x64\Debug"
+# PROP Intermediate_Dir "x64\Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /EHsc /c
+# ADD CPP /nologo /MDd /W3 /Zi /Od /I "../include" /I "../include/arch/win32" /I "../include/private" /I "../../db" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_DB=1 /D APU_HAVE_DB_VERSION=4 /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbm_db_src" /FD /EHsc /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /fo"x64/Debug/apr_dbm_db-1.res" /d DLL_NAME="apr_dbm_db" /d "_DEBUG" /d "APU_VERSION_ONLY" /I "../include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libdb47.lib /nologo /base:"0x6F000000" /subsystem:windows /dll /incremental:no /debug
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libdb47.lib /nologo /base:"0x6F000000" /subsystem:windows /dll /incremental:no /libpath:"..\..\db" /debug /out:"x64\Debug\apr_dbm_db-1.dll" /pdb:"x64\Debug\apr_dbm_db-1.pdb" /implib:"x64\Debug\apr_dbm_db-1.lib" /MACHINE:X64
+# Begin Special Build Tool
+TargetPath=x64\Debug\apr_dbm_db-1.dll
+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 "apr_dbm_db - Win32 Release"
+# Name "apr_dbm_db - Win32 Debug"
+# Name "apr_dbm_db - x64 Release"
+# Name "apr_dbm_db - x64 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\apr_dbm_berkeleydb.c
+# End Source File
+# End Group
+# Begin Group "Public Header Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\include\apr_dbm.h
+# End Source File
+# End Group
+# Begin Group "Internal Header Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\include\private\apu_dbm_private.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\private\apu_config.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\private\apu_dbd_internal.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\private\apu_internal.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\private\apu_select_dbm.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\libapr.rc
+# End Source File
+# End Target
+# End Project
diff --git a/dbm/apr_dbm_gdbm.c b/dbm/apr_dbm_gdbm.c
new file mode 100644
index 00000000000..1d8c96a6398
--- /dev/null
+++ b/dbm/apr_dbm_gdbm.c
@@ -0,0 +1,255 @@
+/* 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 "apu.h"
+#include "apr_private.h"
+#include "apr_strings.h"
+
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h>     /* for free() */
+#endif
+
+#if APU_HAVE_GDBM
+#include "apr_dbm_private.h"
+
+#include <gdbm.h>
+
+#define APR_DBM_DBMODE_RO       GDBM_READER
+#define APR_DBM_DBMODE_RW       GDBM_WRITER
+#define APR_DBM_DBMODE_RWCREATE GDBM_WRCREAT
+#define APR_DBM_DBMODE_RWTRUNC  GDBM_NEWDB
+
+/* map a GDBM error to an apr_status_t */
+static apr_status_t g2s(int gerr)
+{
+    if (gerr == -1) {
+        /* ### need to fix this */
+        return APR_EGENERAL;
+    }
+
+    return APR_SUCCESS;
+}
+
+static apr_status_t datum_cleanup(void *dptr)
+{
+    if (dptr)
+        free(dptr);
+
+    return APR_SUCCESS;
+}
+
+static apr_status_t set_error(apr_dbm_t *dbm, apr_status_t dbm_said)
+{
+    apr_status_t rv = APR_SUCCESS;
+
+    /* ### ignore whatever the DBM said (dbm_said); ask it explicitly */
+
+    if ((dbm->errcode = gdbm_errno) == GDBM_NO_ERROR) {
+        dbm->errmsg = NULL;
+    }
+    else {
+        dbm->errmsg = gdbm_strerror(gdbm_errno);
+        rv = APR_EGENERAL;        /* ### need something better */
+    }
+
+    /* captured it. clear it now. */
+    gdbm_errno = GDBM_NO_ERROR;
+
+    return rv;
+}
+
+/* --------------------------------------------------------------------------
+**
+** DEFINE THE VTABLE FUNCTIONS FOR GDBM
+*/
+
+static apr_status_t vt_gdbm_open(apr_dbm_t **pdb, const char *pathname,
+                                 apr_int32_t mode, apr_fileperms_t perm,
+                                 apr_pool_t *pool)
+{
+    GDBM_FILE file;
+    int dbmode;
+
+    *pdb = NULL;
+
+    switch (mode) {
+    case APR_DBM_READONLY:
+        dbmode = APR_DBM_DBMODE_RO;
+        break;
+    case APR_DBM_READWRITE:
+        dbmode = APR_DBM_DBMODE_RW;
+        break;
+    case APR_DBM_RWCREATE:
+        dbmode = APR_DBM_DBMODE_RWCREATE;
+        break;
+    case APR_DBM_RWTRUNC:
+        dbmode = APR_DBM_DBMODE_RWTRUNC;
+        break;
+    default:
+        return APR_EINVAL;
+    }
+
+    /* Note: stupid cast to get rid of "const" on the pathname */
+    file = gdbm_open((char *) pathname, 0, dbmode, apr_posix_perms2mode(perm),
+                     NULL);
+
+    if (file == NULL)
+        return APR_EGENERAL;      /* ### need a better error */
+
+    /* we have an open database... return it */
+    *pdb = apr_pcalloc(pool, sizeof(**pdb));
+    (*pdb)->pool = pool;
+    (*pdb)->type = &apr_dbm_type_gdbm;
+    (*pdb)->file = file;
+
+    /* ### register a cleanup to close the DBM? */
+
+    return APR_SUCCESS;
+}
+
+static void vt_gdbm_close(apr_dbm_t *dbm)
+{
+    gdbm_close(dbm->file);
+}
+
+static apr_status_t vt_gdbm_fetch(apr_dbm_t *dbm, apr_datum_t key,
+                                  apr_datum_t *pvalue)
+{
+    datum kd, rd;
+
+    kd.dptr = key.dptr;
+    kd.dsize = key.dsize;
+
+    rd = gdbm_fetch(dbm->file, kd);
+
+    pvalue->dptr = rd.dptr;
+    pvalue->dsize = rd.dsize;
+
+    if (pvalue->dptr)
+        apr_pool_cleanup_register(dbm->pool, pvalue->dptr, datum_cleanup,
+                                  apr_pool_cleanup_null);
+
+    /* store the error info into DBM, and return a status code. Also, note
+       that *pvalue should have been cleared on error. */
+    return set_error(dbm, APR_SUCCESS);
+}
+
+static apr_status_t vt_gdbm_store(apr_dbm_t *dbm, apr_datum_t key,
+                                  apr_datum_t value)
+{
+    int rc;
+    datum kd, vd;
+
+    kd.dptr = key.dptr;
+    kd.dsize = key.dsize;
+
+    vd.dptr = value.dptr;
+    vd.dsize = value.dsize;
+
+    rc = gdbm_store(dbm->file, kd, vd, GDBM_REPLACE);
+
+    /* store any error info into DBM, and return a status code. */
+    return set_error(dbm, g2s(rc));
+}
+
+static apr_status_t vt_gdbm_del(apr_dbm_t *dbm, apr_datum_t key)
+{
+    int rc;
+    datum kd;
+
+    kd.dptr = key.dptr;
+    kd.dsize = key.dsize;
+
+    rc = gdbm_delete(dbm->file, kd);
+
+    /* store any error info into DBM, and return a status code. */
+    return set_error(dbm, g2s(rc));
+}
+
+static int vt_gdbm_exists(apr_dbm_t *dbm, apr_datum_t key)
+{
+    datum kd;
+
+    kd.dptr = key.dptr;
+    kd.dsize = key.dsize;
+
+    return gdbm_exists(dbm->file, kd) != 0;
+}
+
+static apr_status_t vt_gdbm_firstkey(apr_dbm_t *dbm, apr_datum_t *pkey)
+{
+    datum rd;
+
+    rd = gdbm_firstkey(dbm->file);
+
+    pkey->dptr = rd.dptr;
+    pkey->dsize = rd.dsize;
+
+    if (pkey->dptr)
+        apr_pool_cleanup_register(dbm->pool, pkey->dptr, datum_cleanup,
+                                  apr_pool_cleanup_null);
+
+    /* store any error info into DBM, and return a status code. */
+    return set_error(dbm, APR_SUCCESS);
+}
+
+static apr_status_t vt_gdbm_nextkey(apr_dbm_t *dbm, apr_datum_t *pkey)
+{
+    datum kd, rd;
+
+    kd.dptr = pkey->dptr;
+    kd.dsize = pkey->dsize;
+
+    rd = gdbm_nextkey(dbm->file, kd);
+
+    pkey->dptr = rd.dptr;
+    pkey->dsize = rd.dsize;
+
+    if (pkey->dptr)
+        apr_pool_cleanup_register(dbm->pool, pkey->dptr, datum_cleanup,
+                                  apr_pool_cleanup_null);
+
+    /* store any error info into DBM, and return a status code. */
+    return set_error(dbm, APR_SUCCESS);
+}
+
+static void vt_gdbm_freedatum(apr_dbm_t *dbm, apr_datum_t data)
+{
+    (void) apr_pool_cleanup_run(dbm->pool, data.dptr, datum_cleanup);
+}
+
+static void vt_gdbm_usednames(apr_pool_t *pool, const char *pathname,
+                              const char **used1, const char **used2)
+{
+    *used1 = apr_pstrdup(pool, pathname);
+    *used2 = NULL;
+}
+
+APR_MODULE_DECLARE_DATA const apr_dbm_type_t apr_dbm_type_gdbm = {
+    "gdbm",
+    vt_gdbm_open,
+    vt_gdbm_close,
+    vt_gdbm_fetch,
+    vt_gdbm_store,
+    vt_gdbm_del,
+    vt_gdbm_exists,
+    vt_gdbm_firstkey,
+    vt_gdbm_nextkey,
+    vt_gdbm_freedatum,
+    vt_gdbm_usednames
+};
+
+#endif /* APU_HAVE_GDBM */
diff --git a/dbm/apr_dbm_gdbm.dsp b/dbm/apr_dbm_gdbm.dsp
new file mode 100644
index 00000000000..eaa51ca515b
--- /dev/null
+++ b/dbm/apr_dbm_gdbm.dsp
@@ -0,0 +1,215 @@
+# Microsoft Developer Studio Project File - Name="apr_dbm_gdbm" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=apr_dbm_gdbm - 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 "apr_dbm_gdbm.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 "apr_dbm_gdbm.mak" CFG="apr_dbm_gdbm - Win32 Release"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "apr_dbm_gdbm - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_dbm_gdbm - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_dbm_gdbm - x64 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_dbm_gdbm - x64 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)" == "apr_dbm_gdbm - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /Zi /O2 /Oy- /I "../include" /I "../include/arch/win32" /I "../include/private" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_GDBM=1 /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbm_gdbm_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /fo"Release/apr_dbm_gdbm-1.res" /d DLL_NAME="apr_dbm_gdbm" /d "NDEBUG" /d "APU_VERSION_ONLY" /I "../include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libgdbm.lib /nologo /base:"0x6F010000" /subsystem:windows /dll /incremental:no /debug /opt:ref
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libgdbm.lib /nologo /base:"0x6F010000" /subsystem:windows /dll /incremental:no /debug /out:"Release\apr_dbm_gdbm-1.dll" /pdb:"Release\apr_dbm_gdbm-1.pdb" /implib:"Release\apr_dbm_gdbm-1.lib" /MACHINE:X86 /opt:ref
+# Begin Special Build Tool
+TargetPath=Release\apr_dbm_gdbm-1.dll
+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)" == "apr_dbm_gdbm - 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 /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /EHsc /c
+# ADD CPP /nologo /MDd /W3 /Zi /Od /I "../include" /I "../include/arch/win32" /I "../include/private" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_GDBM=1 /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbm_gdbm_src" /FD /EHsc /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /fo"Debug/apr_dbm_gdbm-1.res" /d DLL_NAME="apr_dbm_gdbm" /d "_DEBUG" /d "APU_VERSION_ONLY" /I "../include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libgdbm.lib /nologo /base:"0x6F010000" /subsystem:windows /dll /incremental:no /debug
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libgdbm.lib /nologo /base:"0x6F010000" /subsystem:windows /dll /incremental:no /debug /out:"Debug\apr_dbm_gdbm-1.dll" /pdb:"Debug\apr_dbm_gdbm-1.pdb" /implib:"Debug\apr_dbm_gdbm-1.lib" /MACHINE:X86
+# Begin Special Build Tool
+TargetPath=Debug\apr_dbm_gdbm-1.dll
+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)" == "apr_dbm_gdbm - x64 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "x64\Release"
+# PROP BASE Intermediate_Dir "x64\Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "x64\Release"
+# PROP Intermediate_Dir "x64\Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /Zi /O2 /Oy- /I "../include" /I "../include/arch/win32" /I "../include/private" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_GDBM=1 /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbm_gdbm_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /fo"x64/Release/apr_dbm_gdbm-1.res" /d DLL_NAME="apr_dbm_gdbm" /d "NDEBUG" /d "APU_VERSION_ONLY" /I "../include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libgdbm.lib /nologo /base:"0x6F010000" /subsystem:windows /dll /incremental:no /debug /opt:ref
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libgdbm.lib /nologo /base:"0x6F010000" /subsystem:windows /dll /incremental:no /debug /out:"x64\Release\apr_dbm_gdbm-1.dll" /pdb:"x64\Release\apr_dbm_gdbm-1.pdb" /implib:"x64\Release\apr_dbm_gdbm-1.lib" /MACHINE:X64 /opt:ref
+# Begin Special Build Tool
+TargetPath=x64\Release\apr_dbm_gdbm-1.dll
+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)" == "apr_dbm_gdbm - x64 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "x64\Debug"
+# PROP BASE Intermediate_Dir "x64\Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "x64\Debug"
+# PROP Intermediate_Dir "x64\Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /EHsc /c
+# ADD CPP /nologo /MDd /W3 /Zi /Od /I "../include" /I "../include/arch/win32" /I "../include/private" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_GDBM=1 /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbm_gdbm_src" /FD /EHsc /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /fo"x64/Debug/apr_dbm_gdbm-1.res" /d DLL_NAME="apr_dbm_gdbm" /d "_DEBUG" /d "APU_VERSION_ONLY" /I "../include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libgdbm.lib /nologo /base:"0x6F010000" /subsystem:windows /dll /incremental:no /debug
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libgdbm.lib /nologo /base:"0x6F010000" /subsystem:windows /dll /incremental:no /debug /out:"x64\Debug\apr_dbm_gdbm-1.dll" /pdb:"x64\Debug\apr_dbm_gdbm-1.pdb" /implib:"x64\Debug\apr_dbm_gdbm-1.lib" /MACHINE:X64
+# Begin Special Build Tool
+TargetPath=x64\Debug\apr_dbm_gdbm-1.dll
+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 "apr_dbm_gdbm - Win32 Release"
+# Name "apr_dbm_gdbm - Win32 Debug"
+# Name "apr_dbm_gdbm - x64 Release"
+# Name "apr_dbm_gdbm - x64 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\apr_dbm_gdbm.c
+# End Source File
+# End Group
+# Begin Group "Public Header Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\include\apr_dbm.h
+# End Source File
+# End Group
+# Begin Group "Internal Header Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\include\private\apu_dbm_private.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\private\apu_config.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\private\apu_dbd_internal.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\private\apu_internal.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\private\apu_select_dbm.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\libapr.rc
+# End Source File
+# End Target
+# End Project
diff --git a/dbm/apr_dbm_ndbm.c b/dbm/apr_dbm_ndbm.c
new file mode 100644
index 00000000000..a69ac526255
--- /dev/null
+++ b/dbm/apr_dbm_ndbm.c
@@ -0,0 +1,238 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_strings.h"
+
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h>     /* for free() */
+#endif
+
+#include "apu.h"
+#include "apr_private.h"
+
+#if APU_HAVE_NDBM
+#include "apr_dbm_private.h"
+
+#include <ndbm.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#define APR_DBM_DBMODE_RO       O_RDONLY
+#define APR_DBM_DBMODE_RW       O_RDWR
+#define APR_DBM_DBMODE_RWCREATE (O_RDWR|O_CREAT)
+#define APR_DBM_DBMODE_RWTRUNC  (O_RDWR|O_CREAT|O_TRUNC)
+
+/* map a NDBM error to an apr_status_t */
+static apr_status_t ndbm2s(int ndbmerr)
+{
+    if (ndbmerr == -1) {
+        /* ### need to fix this */
+        return APR_EGENERAL;
+    }
+
+    return APR_SUCCESS;
+}
+
+static apr_status_t set_error(apr_dbm_t *dbm, apr_status_t dbm_said)
+{
+    apr_status_t rv = APR_SUCCESS;
+
+    /* ### ignore whatever the DBM said (dbm_said); ask it explicitly */
+
+    dbm->errmsg = NULL;
+    if (dbm_error((DBM*)dbm->file)) {
+        dbm->errmsg = NULL;
+        rv = APR_EGENERAL;        /* ### need something better */
+    }
+
+    /* captured it. clear it now. */
+    dbm_clearerr((DBM*)dbm->file);
+
+    return rv;
+}
+
+/* --------------------------------------------------------------------------
+**
+** DEFINE THE VTABLE FUNCTIONS FOR NDBM
+*/
+
+static apr_status_t vt_ndbm_open(apr_dbm_t **pdb, const char *pathname,
+                                 apr_int32_t mode, apr_fileperms_t perm,
+                                 apr_pool_t *pool)
+{
+    DBM *file;
+    int dbmode;
+
+    *pdb = NULL;
+
+    switch (mode) {
+    case APR_DBM_READONLY:
+        dbmode = APR_DBM_DBMODE_RO;
+        break;
+    case APR_DBM_READWRITE:
+        dbmode = APR_DBM_DBMODE_RW;
+        break;
+    case APR_DBM_RWCREATE:
+        dbmode = APR_DBM_DBMODE_RWCREATE;
+        break;
+    case APR_DBM_RWTRUNC:
+        dbmode = APR_DBM_DBMODE_RWTRUNC;
+        break;
+    default:
+        return APR_EINVAL;
+    }
+
+    {
+        file = dbm_open(pathname, dbmode, apr_posix_perms2mode(perm));
+        if (file == NULL)
+            return APR_EGENERAL;      /* ### need a better error */
+    }
+
+    /* we have an open database... return it */
+    *pdb = apr_pcalloc(pool, sizeof(**pdb));
+    (*pdb)->pool = pool;
+    (*pdb)->type = &apr_dbm_type_ndbm;
+    (*pdb)->file = file;
+
+    /* ### register a cleanup to close the DBM? */
+
+    return APR_SUCCESS;
+}
+
+static void vt_ndbm_close(apr_dbm_t *dbm)
+{
+    dbm_close(dbm->file);
+}
+
+static apr_status_t vt_ndbm_fetch(apr_dbm_t *dbm, apr_datum_t key,
+                                  apr_datum_t *pvalue)
+{
+    datum kd, rd;
+
+    kd.dptr = key.dptr;
+    kd.dsize = key.dsize;
+
+    rd = dbm_fetch(dbm->file, kd);
+
+    pvalue->dptr = rd.dptr;
+    pvalue->dsize = rd.dsize;
+
+    /* store the error info into DBM, and return a status code. Also, note
+       that *pvalue should have been cleared on error. */
+    return set_error(dbm, APR_SUCCESS);
+}
+
+static apr_status_t vt_ndbm_store(apr_dbm_t *dbm, apr_datum_t key,
+                                  apr_datum_t value)
+{
+    int rc;
+    datum kd, vd;
+
+    kd.dptr = key.dptr;
+    kd.dsize = key.dsize;
+
+    vd.dptr = value.dptr;
+    vd.dsize = value.dsize;
+
+    rc = dbm_store(dbm->file, kd, vd, DBM_REPLACE);
+
+    /* store any error info into DBM, and return a status code. */
+    return set_error(dbm, ndbm2s(rc));
+}
+
+static apr_status_t vt_ndbm_del(apr_dbm_t *dbm, apr_datum_t key)
+{
+    int rc;
+    datum kd;
+
+    kd.dptr = key.dptr;
+    kd.dsize = key.dsize;
+
+    rc = dbm_delete(dbm->file, kd);
+
+    /* store any error info into DBM, and return a status code. */
+    return set_error(dbm, ndbm2s(rc));
+}
+
+static int vt_ndbm_exists(apr_dbm_t *dbm, apr_datum_t key)
+{
+    datum kd, rd;
+
+    kd.dptr = key.dptr;
+    kd.dsize = key.dsize;
+
+    rd = dbm_fetch(dbm->file, kd);
+
+    return rd.dptr != NULL;
+}
+
+static apr_status_t vt_ndbm_firstkey(apr_dbm_t *dbm, apr_datum_t *pkey)
+{
+    datum rd;
+
+    rd = dbm_firstkey(dbm->file);
+
+    pkey->dptr = rd.dptr;
+    pkey->dsize = rd.dsize;
+
+    /* store any error info into DBM, and return a status code. */
+    return set_error(dbm, APR_SUCCESS);
+}
+
+static apr_status_t vt_ndbm_nextkey(apr_dbm_t *dbm, apr_datum_t *pkey)
+{
+    datum kd, rd;
+
+    kd.dptr = pkey->dptr;
+    kd.dsize = pkey->dsize;
+
+    rd = dbm_nextkey(dbm->file);
+
+    pkey->dptr = rd.dptr;
+    pkey->dsize = rd.dsize;
+
+    /* store any error info into DBM, and return a status code. */
+    return set_error(dbm, APR_SUCCESS);
+}
+
+static void vt_ndbm_freedatum(apr_dbm_t *dbm, apr_datum_t data)
+{
+  /* nothing to do */
+}
+
+static void vt_ndbm_usednames(apr_pool_t *pool, const char *pathname,
+                              const char **used1, const char **used2)
+{
+    *used1 = apr_pstrdup(pool, pathname);
+    *used2 = NULL;
+}
+
+APR_MODULE_DECLARE_DATA const apr_dbm_type_t apr_dbm_type_ndbm = {
+    "ndbm",
+    vt_ndbm_open,
+    vt_ndbm_close,
+    vt_ndbm_fetch,
+    vt_ndbm_store,
+    vt_ndbm_del,
+    vt_ndbm_exists,
+    vt_ndbm_firstkey,
+    vt_ndbm_nextkey,
+    vt_ndbm_freedatum,
+    vt_ndbm_usednames
+};
+
+#endif /* APU_HAVE_NDBM  */
diff --git a/dbm/apr_dbm_sdbm.c b/dbm/apr_dbm_sdbm.c
new file mode 100644
index 00000000000..ac3192e632c
--- /dev/null
+++ b/dbm/apr_dbm_sdbm.c
@@ -0,0 +1,226 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_strings.h"
+#define APR_WANT_MEMFUNC
+#define APR_WANT_STRFUNC
+#include "apr_want.h"
+
+#include "apu.h"
+#include "apr_private.h"
+
+#if APU_HAVE_SDBM
+
+#include "apr_dbm_private.h"
+#include "apr_sdbm.h"
+
+#define APR_DBM_DBMODE_RO       (APR_FOPEN_READ | APR_FOPEN_BUFFERED)
+#define APR_DBM_DBMODE_RW       (APR_FOPEN_READ | APR_FOPEN_WRITE)
+#define APR_DBM_DBMODE_RWCREATE (APR_FOPEN_READ | APR_FOPEN_WRITE | APR_FOPEN_CREATE)
+#define APR_DBM_DBMODE_RWTRUNC  (APR_FOPEN_READ | APR_FOPEN_WRITE | APR_FOPEN_CREATE | \
+                                 APR_FOPEN_TRUNCATE)
+
+static apr_status_t set_error(apr_dbm_t *dbm, apr_status_t dbm_said)
+{
+    dbm->errcode = dbm_said;
+
+    if (dbm_said != APR_SUCCESS) {
+        dbm->errmsg = apr_psprintf(dbm->pool, "%pm", &dbm_said);
+    } else {
+        dbm->errmsg = NULL;
+    }
+
+    return dbm_said;
+}
+
+/* --------------------------------------------------------------------------
+**
+** DEFINE THE VTABLE FUNCTIONS FOR SDBM
+*/
+
+static apr_status_t vt_sdbm_open(apr_dbm_t **pdb, const char *pathname,
+                                 apr_int32_t mode, apr_fileperms_t perm,
+                                 apr_pool_t *pool)
+{
+    apr_sdbm_t *file;
+    int dbmode;
+
+    *pdb = NULL;
+
+    switch (mode) {
+    case APR_DBM_READONLY:
+        dbmode = APR_DBM_DBMODE_RO;
+        break;
+    case APR_DBM_READWRITE:
+        dbmode = APR_DBM_DBMODE_RW;
+        break;
+    case APR_DBM_RWCREATE:
+        dbmode = APR_DBM_DBMODE_RWCREATE;
+        break;
+    case APR_DBM_RWTRUNC:
+        dbmode = APR_DBM_DBMODE_RWTRUNC;
+        break;
+    default:
+        return APR_EINVAL;
+    }
+
+    {
+        apr_status_t rv;
+
+        rv = apr_sdbm_open(&file, pathname, dbmode, perm, pool);
+        if (rv != APR_SUCCESS)
+            return rv;
+    }
+
+    /* we have an open database... return it */
+    *pdb = apr_pcalloc(pool, sizeof(**pdb));
+    (*pdb)->pool = pool;
+    (*pdb)->type = &apr_dbm_type_sdbm;
+    (*pdb)->file = file;
+
+    /* ### register a cleanup to close the DBM? */
+
+    return APR_SUCCESS;
+}
+
+static void vt_sdbm_close(apr_dbm_t *dbm)
+{
+    apr_sdbm_close(dbm->file);
+}
+
+static apr_status_t vt_sdbm_fetch(apr_dbm_t *dbm, apr_datum_t key,
+                                  apr_datum_t *pvalue)
+{
+    apr_status_t rv;
+    apr_sdbm_datum_t kd, rd;
+
+    kd.dptr = key.dptr;
+    kd.dsize = (int)key.dsize;
+
+    rv = apr_sdbm_fetch(dbm->file, &rd, kd);
+
+    pvalue->dptr = rd.dptr;
+    pvalue->dsize = rd.dsize;
+
+    /* store the error info into DBM, and return a status code. Also, note
+       that *pvalue should have been cleared on error. */
+    return set_error(dbm, rv);
+}
+
+static apr_status_t vt_sdbm_store(apr_dbm_t *dbm, apr_datum_t key,
+                                  apr_datum_t value)
+{
+    apr_status_t rv;
+    apr_sdbm_datum_t kd, vd;
+
+    kd.dptr = key.dptr;
+    kd.dsize = (int)key.dsize;
+
+    vd.dptr = value.dptr;
+    vd.dsize = (int)value.dsize;
+
+    rv = apr_sdbm_store(dbm->file, kd, vd, APR_SDBM_REPLACE);
+
+    /* store any error info into DBM, and return a status code. */
+    return set_error(dbm, rv);
+}
+
+static apr_status_t vt_sdbm_del(apr_dbm_t *dbm, apr_datum_t key)
+{
+    apr_status_t rv;
+    apr_sdbm_datum_t kd;
+
+    kd.dptr = key.dptr;
+    kd.dsize = (int)key.dsize;
+
+    rv = apr_sdbm_delete(dbm->file, kd);
+
+    /* store any error info into DBM, and return a status code. */
+    return set_error(dbm, rv);
+}
+
+static int vt_sdbm_exists(apr_dbm_t *dbm, apr_datum_t key)
+{
+    int exists;
+    apr_sdbm_datum_t vd, kd;
+
+    kd.dptr = key.dptr;
+    kd.dsize = (int)key.dsize;
+
+    if (apr_sdbm_fetch(dbm->file, &vd, kd) != APR_SUCCESS)
+        exists = 0;
+    else
+        exists = vd.dptr != NULL;
+
+    return exists;
+}
+
+static apr_status_t vt_sdbm_firstkey(apr_dbm_t *dbm, apr_datum_t *pkey)
+{
+    apr_status_t rv;
+    apr_sdbm_datum_t rd;
+
+    rv = apr_sdbm_firstkey(dbm->file, &rd);
+
+    pkey->dptr = rd.dptr;
+    pkey->dsize = rd.dsize;
+
+    /* store any error info into DBM, and return a status code. */
+    return set_error(dbm, rv);
+}
+
+static apr_status_t vt_sdbm_nextkey(apr_dbm_t *dbm, apr_datum_t *pkey)
+{
+    apr_sdbm_datum_t rd;
+
+    (void)apr_sdbm_nextkey(dbm->file, &rd);
+
+    pkey->dptr = rd.dptr;
+    pkey->dsize = rd.dsize;
+
+    /*
+     * XXX: This discards any error but apr_sdbm_nextkey currently returns
+     * XXX: an error for the last key
+     */
+    return set_error(dbm, APR_SUCCESS);
+}
+
+static void vt_sdbm_freedatum(apr_dbm_t *dbm, apr_datum_t data)
+{
+}
+
+static void vt_sdbm_usednames(apr_pool_t *pool, const char *pathname,
+                              const char **used1, const char **used2)
+{
+    *used1 = apr_pstrcat(pool, pathname, APR_SDBM_DIRFEXT, NULL);
+    *used2 = apr_pstrcat(pool, pathname, APR_SDBM_PAGFEXT, NULL);
+}
+
+APR_MODULE_DECLARE_DATA const apr_dbm_type_t apr_dbm_type_sdbm = {
+    "sdbm",
+    vt_sdbm_open,
+    vt_sdbm_close,
+    vt_sdbm_fetch,
+    vt_sdbm_store,
+    vt_sdbm_del,
+    vt_sdbm_exists,
+    vt_sdbm_firstkey,
+    vt_sdbm_nextkey,
+    vt_sdbm_freedatum,
+    vt_sdbm_usednames
+};
+
+#endif /* APU_HAVE_SDBM */
diff --git a/dbm/sdbm/sdbm.c b/dbm/sdbm/sdbm.c
new file mode 100644
index 00000000000..9ad9d20ff5f
--- /dev/null
+++ b/dbm/sdbm/sdbm.c
@@ -0,0 +1,584 @@
+/* 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.
+ */
+
+/*
+ * sdbm - ndbm work-alike hashed database library
+ * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
+ * author: oz@nexus.yorku.ca
+ * ex-public domain, ported to APR for Apache 2
+ * core routines
+ */
+
+#include "apr.h"
+#include "apr_file_io.h"
+#include "apr_strings.h"
+#include "apr_errno.h"
+#include "apr_sdbm.h"
+
+#include "sdbm_tune.h"
+#include "sdbm_pair.h"
+#include "sdbm_private.h"
+
+#include <string.h>     /* for memset() */
+#include <stdlib.h>     /* for malloc() and free() */
+
+/*
+ * forward
+ */
+static int getdbit (apr_sdbm_t *, long);
+static apr_status_t setdbit(apr_sdbm_t *, long);
+static apr_status_t getpage(apr_sdbm_t *db, long, int, int);
+static apr_status_t getnext(apr_sdbm_datum_t *key, apr_sdbm_t *db);
+static apr_status_t makroom(apr_sdbm_t *, long, int);
+
+/*
+ * useful macros
+ */
+#define bad(x)		((x).dptr == NULL || (x).dsize <= 0)
+#define exhash(item)	sdbm_hash((item).dptr, (item).dsize)
+
+#define OFF_PAG(off)	(apr_off_t) (off) * PBLKSIZ
+#define OFF_DIR(off)	(apr_off_t) (off) * DBLKSIZ
+
+static const long masks[] = {
+        000000000000, 000000000001, 000000000003, 000000000007,
+        000000000017, 000000000037, 000000000077, 000000000177,
+        000000000377, 000000000777, 000000001777, 000000003777,
+        000000007777, 000000017777, 000000037777, 000000077777,
+        000000177777, 000000377777, 000000777777, 000001777777,
+        000003777777, 000007777777, 000017777777, 000037777777,
+        000077777777, 000177777777, 000377777777, 000777777777,
+        001777777777, 003777777777, 007777777777, 017777777777
+};
+
+const apr_sdbm_datum_t sdbm_nullitem = { NULL, 0 };
+
+static apr_status_t database_cleanup(void *data)
+{
+    apr_sdbm_t *db = data;
+
+    /*
+     * Can't rely on apr_sdbm_unlock, since it will merely
+     * decrement the refcnt if several locks are held.
+     */
+    if (db->flags & (SDBM_SHARED_LOCK | SDBM_EXCLUSIVE_LOCK))
+        (void) apr_file_unlock(db->dirf);
+    (void) apr_file_close(db->dirf);
+    (void) apr_file_close(db->pagf);
+    free(db);
+
+    return APR_SUCCESS;
+}
+
+static apr_status_t prep(apr_sdbm_t **pdb, const char *dirname, const char *pagname,
+                         apr_int32_t flags, apr_fileperms_t perms, apr_pool_t *p)
+{
+    apr_sdbm_t *db;
+    apr_status_t status;
+
+    *pdb = NULL;
+
+    db = malloc(sizeof(*db));
+    memset(db, 0, sizeof(*db));
+    db->pagbno = -1L;
+
+    db->pool = p;
+
+    /*
+     * adjust user flags so that WRONLY becomes RDWR, 
+     * as required by this package. Also set our internal
+     * flag for RDONLY if needed.
+     */
+    if (!(flags & APR_FOPEN_WRITE)) {
+        db->flags |= SDBM_RDONLY;
+    }
+
+    /*
+     * adjust the file open flags so that we handle locking
+     * on our own (don't rely on any locking behavior within
+     * an apr_file_t, in case it's ever introduced, and set
+     * our own flag.
+     */
+    if (flags & APR_FOPEN_SHARELOCK) {
+        db->flags |= SDBM_SHARED;
+        flags &= ~APR_FOPEN_SHARELOCK;
+    }
+
+    flags |= APR_FOPEN_BINARY | APR_FOPEN_READ;
+
+    /*
+     * open the files in sequence, and stat the dirfile.
+     * If we fail anywhere, undo everything, return NULL.
+     */
+
+    if ((status = apr_file_open(&db->dirf, dirname, flags, perms, p))
+                != APR_SUCCESS)
+        goto error;
+
+    if ((status = apr_file_open(&db->pagf, pagname, flags, perms, p))
+                != APR_SUCCESS)
+        goto error;
+
+    if ((status = apr_sdbm_lock(db, (db->flags & SDBM_RDONLY) 
+                                        ? APR_FLOCK_SHARED
+                                        : APR_FLOCK_EXCLUSIVE))
+                != APR_SUCCESS)
+        goto error;
+
+    /* apr_pcalloc zeroed the buffers
+     * apr_sdbm_lock stated the dirf->size and invalidated the cache
+     */
+
+    /*
+     * if we are opened in SHARED mode, unlock ourself 
+     */
+    if (db->flags & SDBM_SHARED)
+        if ((status = apr_sdbm_unlock(db)) != APR_SUCCESS)
+            goto error;
+
+    /* make sure that we close the database at some point */
+    apr_pool_cleanup_register(p, db, database_cleanup, apr_pool_cleanup_null);
+
+    /* Done! */
+    *pdb = db;
+    return APR_SUCCESS;
+
+error:
+    if (db->dirf && db->pagf)
+        (void) apr_sdbm_unlock(db);
+    if (db->dirf != NULL)
+        (void) apr_file_close(db->dirf);
+    if (db->pagf != NULL) {
+        (void) apr_file_close(db->pagf);
+    }
+    free(db);
+    return status;
+}
+
+APR_DECLARE(apr_status_t) apr_sdbm_open(apr_sdbm_t **db, const char *file, 
+                                        apr_int32_t flags, 
+                                        apr_fileperms_t perms, apr_pool_t *p)
+{
+    char *dirname = apr_pstrcat(p, file, APR_SDBM_DIRFEXT, NULL);
+    char *pagname = apr_pstrcat(p, file, APR_SDBM_PAGFEXT, NULL);
+    
+    return prep(db, dirname, pagname, flags, perms, p);
+}
+
+APR_DECLARE(apr_status_t) apr_sdbm_close(apr_sdbm_t *db)
+{
+    return apr_pool_cleanup_run(db->pool, db, database_cleanup);
+}
+
+APR_DECLARE(apr_status_t) apr_sdbm_fetch(apr_sdbm_t *db, apr_sdbm_datum_t *val,
+                                         apr_sdbm_datum_t key)
+{
+    apr_status_t status;
+    
+    if (db == NULL || bad(key))
+        return APR_EINVAL;
+
+    if ((status = apr_sdbm_lock(db, APR_FLOCK_SHARED)) != APR_SUCCESS)
+        return status;
+
+    if ((status = getpage(db, exhash(key), 0, 1)) == APR_SUCCESS) {
+        *val = getpair(db->pagbuf, key);
+        /* ### do we want a not-found result? */
+    }
+
+    (void) apr_sdbm_unlock(db);
+
+    return status;
+}
+
+static apr_status_t write_page(apr_sdbm_t *db, const char *buf, long pagno)
+{
+    apr_status_t status;
+    apr_off_t off = OFF_PAG(pagno);
+    
+    if ((status = apr_file_seek(db->pagf, APR_SET, &off)) == APR_SUCCESS)
+        status = apr_file_write_full(db->pagf, buf, PBLKSIZ, NULL);
+
+    return status;
+}
+
+APR_DECLARE(apr_status_t) apr_sdbm_delete(apr_sdbm_t *db, 
+                                          const apr_sdbm_datum_t key)
+{
+    apr_status_t status;
+    
+    if (db == NULL || bad(key))
+        return APR_EINVAL;
+    if (apr_sdbm_rdonly(db))
+        return APR_EINVAL;
+    
+    if ((status = apr_sdbm_lock(db, APR_FLOCK_EXCLUSIVE)) != APR_SUCCESS)
+        return status;
+
+    if ((status = getpage(db, exhash(key), 0, 1)) == APR_SUCCESS) {
+        if (!delpair(db->pagbuf, key))
+            /* ### should we define some APRUTIL codes? */
+            status = APR_EGENERAL;
+        else
+            status = write_page(db, db->pagbuf, db->pagbno);
+    }
+
+    (void) apr_sdbm_unlock(db);
+
+    return status;
+}
+
+APR_DECLARE(apr_status_t) apr_sdbm_store(apr_sdbm_t *db, apr_sdbm_datum_t key,
+                                         apr_sdbm_datum_t val, int flags)
+{
+    int need;
+    register long hash;
+    apr_status_t status;
+    
+    if (db == NULL || bad(key))
+        return APR_EINVAL;
+    if (apr_sdbm_rdonly(db))
+        return APR_EINVAL;
+    need = key.dsize + val.dsize;
+    /*
+     * is the pair too big (or too small) for this database ??
+     */
+    if (need < 0 || need > PAIRMAX)
+        return APR_EINVAL;
+
+    if ((status = apr_sdbm_lock(db, APR_FLOCK_EXCLUSIVE)) != APR_SUCCESS)
+        return status;
+
+    if ((status = getpage(db, (hash = exhash(key)), 0, 1)) == APR_SUCCESS) {
+
+        /*
+         * if we need to replace, delete the key/data pair
+         * first. If it is not there, ignore.
+         */
+        if (flags == APR_SDBM_REPLACE)
+            (void) delpair(db->pagbuf, key);
+        else if (!(flags & APR_SDBM_INSERTDUP) && duppair(db->pagbuf, key)) {
+            status = APR_EEXIST;
+            goto error;
+        }
+        /*
+         * if we do not have enough room, we have to split.
+         */
+        if (!fitpair(db->pagbuf, need))
+            if ((status = makroom(db, hash, need)) != APR_SUCCESS)
+                goto error;
+        /*
+         * we have enough room or split is successful. insert the key,
+         * and update the page file.
+         */
+        (void) putpair(db->pagbuf, key, val);
+
+        status = write_page(db, db->pagbuf, db->pagbno);
+    }
+
+error:
+    (void) apr_sdbm_unlock(db);    
+
+    return status;
+}
+
+/*
+ * makroom - make room by splitting the overfull page
+ * this routine will attempt to make room for SPLTMAX times before
+ * giving up.
+ */
+static apr_status_t makroom(apr_sdbm_t *db, long hash, int need)
+{
+    long newp;
+    char twin[PBLKSIZ];
+    char *pag = db->pagbuf;
+    char *new = twin;
+    register int smax = SPLTMAX;
+    apr_status_t status;
+
+    do {
+        /*
+         * split the current page
+         */
+        (void) splpage(pag, new, db->hmask + 1);
+        /*
+         * address of the new page
+         */
+        newp = (hash & db->hmask) | (db->hmask + 1);
+
+        /*
+         * write delay, read avoidence/cache shuffle:
+         * select the page for incoming pair: if key is to go to the new page,
+         * write out the previous one, and copy the new one over, thus making
+         * it the current page. If not, simply write the new page, and we are
+         * still looking at the page of interest. current page is not updated
+         * here, as sdbm_store will do so, after it inserts the incoming pair.
+         */
+        if (hash & (db->hmask + 1)) {
+            if ((status = write_page(db, db->pagbuf, db->pagbno)) 
+                        != APR_SUCCESS)
+                return status;
+                    
+            db->pagbno = newp;
+            (void) memcpy(pag, new, PBLKSIZ);
+        }
+        else {
+            if ((status = write_page(db, new, newp)) != APR_SUCCESS)
+                return status;
+        }
+
+        if ((status = setdbit(db, db->curbit)) != APR_SUCCESS)
+            return status;
+        /*
+         * see if we have enough room now
+         */
+        if (fitpair(pag, need))
+            return APR_SUCCESS;
+        /*
+         * try again... update curbit and hmask as getpage would have
+         * done. because of our update of the current page, we do not
+         * need to read in anything. BUT we have to write the current
+         * [deferred] page out, as the window of failure is too great.
+         */
+        db->curbit = 2 * db->curbit
+                   + ((hash & (db->hmask + 1)) ? 2 : 1);
+        db->hmask |= db->hmask + 1;
+            
+        if ((status = write_page(db, db->pagbuf, db->pagbno))
+                    != APR_SUCCESS)
+            return status;
+            
+    } while (--smax);
+
+    /*
+     * if we are here, this is real bad news. After SPLTMAX splits,
+     * we still cannot fit the key. say goodnight.
+     */
+#if 0
+    (void) write(2, "sdbm: cannot insert after SPLTMAX attempts.\n", 44);
+#endif
+    /* ### ENOSPC not really appropriate but better than nothing */
+    return APR_ENOSPC;
+
+}
+
+/* Reads 'len' bytes from file 'f' at offset 'off' into buf.
+ * 'off' is given relative to the start of the file.
+ * If 'create' is asked and EOF is returned while reading, this is taken
+ * as success (i.e. a cleared buffer is returned).
+ */
+static apr_status_t read_from(apr_file_t *f, void *buf, 
+                              apr_off_t off, apr_size_t len,
+                              int create)
+{
+    apr_status_t status;
+
+    if ((status = apr_file_seek(f, APR_SET, &off)) != APR_SUCCESS ||
+        ((status = apr_file_read_full(f, buf, len, NULL)) != APR_SUCCESS)) {
+        /* if EOF is reached, pretend we read all zero's */
+        if (status == APR_EOF && create) {
+            memset(buf, 0, len);
+            status = APR_SUCCESS;
+        }
+    }
+
+    return status;
+}
+
+/*
+ * the following two routines will break if
+ * deletions aren't taken into account. (ndbm bug)
+ */
+APR_DECLARE(apr_status_t) apr_sdbm_firstkey(apr_sdbm_t *db, 
+                                            apr_sdbm_datum_t *key)
+{
+    apr_status_t status;
+    
+    if ((status = apr_sdbm_lock(db, APR_FLOCK_SHARED)) != APR_SUCCESS)
+        return status;
+
+    /*
+     * start at page 0
+     */
+    if ((status = getpage(db, 0, 1, 1)) == APR_SUCCESS) {
+        db->blkptr = 0;
+        db->keyptr = 0;
+        status = getnext(key, db);
+    }
+
+    (void) apr_sdbm_unlock(db);
+
+    return status;
+}
+
+APR_DECLARE(apr_status_t) apr_sdbm_nextkey(apr_sdbm_t *db, 
+                                           apr_sdbm_datum_t *key)
+{
+    apr_status_t status;
+    
+    if ((status = apr_sdbm_lock(db, APR_FLOCK_SHARED)) != APR_SUCCESS)
+        return status;
+
+    status = getnext(key, db);
+
+    (void) apr_sdbm_unlock(db);
+
+    return status;
+}
+
+/*
+ * all important binary tree traversal
+ */
+static apr_status_t getpage(apr_sdbm_t *db, long hash, int by_num, int create)
+{
+    apr_status_t status;
+    register long pagb;
+
+    if (by_num) {
+        pagb = hash;
+    }
+    else {
+        register int hbit = 0;
+        register long dbit = 0;
+
+        while (dbit < db->maxbno && getdbit(db, dbit))
+            dbit = 2 * dbit + ((hash & (1 << hbit++)) ? 2 : 1);
+        debug(("dbit: %d...", dbit));
+
+        db->curbit = dbit;
+        db->hmask = masks[hbit];
+
+        pagb = hash & db->hmask;
+    }
+
+    /*
+     * see if the block we need is already in memory.
+     * note: this lookaside cache has about 10% hit rate.
+     */
+    if (pagb != db->pagbno) { 
+        /*
+         * note: here, we assume a "hole" is read as 0s.
+         * if not, must zero pagbuf first.
+         * ### joe: this assumption was surely never correct? but
+         * ### we make it so in read_from anyway.
+         */
+        if ((status = read_from(db->pagf, db->pagbuf,
+                                OFF_PAG(pagb), PBLKSIZ,
+                                create)) != APR_SUCCESS)
+            return status;
+
+        if (!chkpage(db->pagbuf))
+            return APR_ENOSPC; /* ### better error? */
+
+        db->pagbno = pagb;
+
+        debug(("pag read: %d\n", pagb));
+    }
+    return APR_SUCCESS;
+}
+
+static int getdbit(apr_sdbm_t *db, long dbit)
+{
+    register long c;
+    register long dirb;
+
+    c = dbit / BYTESIZ;
+    dirb = c / DBLKSIZ;
+
+    if (dirb != db->dirbno) {
+        if (read_from(db->dirf, db->dirbuf,
+                      OFF_DIR(dirb), DBLKSIZ,
+                      1) != APR_SUCCESS)
+            return 0;
+
+        db->dirbno = dirb;
+
+        debug(("dir read: %d\n", dirb));
+    }
+
+    return db->dirbuf[c % DBLKSIZ] & (1 << dbit % BYTESIZ);
+}
+
+static apr_status_t setdbit(apr_sdbm_t *db, long dbit)
+{
+    register long c;
+    register long dirb;
+    apr_status_t status;
+    apr_off_t off;
+
+    c = dbit / BYTESIZ;
+    dirb = c / DBLKSIZ;
+
+    if (dirb != db->dirbno) {
+        if ((status = read_from(db->dirf, db->dirbuf,
+                                OFF_DIR(dirb), DBLKSIZ,
+                                1)) != APR_SUCCESS)
+            return status;
+
+        db->dirbno = dirb;
+        
+        debug(("dir read: %d\n", dirb));
+    }
+
+    db->dirbuf[c % DBLKSIZ] |= (1 << dbit % BYTESIZ);
+
+    if (dbit >= db->maxbno)
+        db->maxbno += DBLKSIZ * BYTESIZ;
+
+    off = OFF_DIR(dirb);
+    if ((status = apr_file_seek(db->dirf, APR_SET, &off)) == APR_SUCCESS)
+        status = apr_file_write_full(db->dirf, db->dirbuf, DBLKSIZ, NULL);
+
+    return status;
+}
+
+/*
+* getnext - get the next key in the page, and if done with
+* the page, try the next page in sequence
+*/
+static apr_status_t getnext(apr_sdbm_datum_t *key, apr_sdbm_t *db)
+{
+    apr_status_t status;
+    for (;;) {
+        db->keyptr++;
+        *key = getnkey(db->pagbuf, db->keyptr);
+        if (key->dptr != NULL)
+            return APR_SUCCESS;
+        /*
+         * we either run out, or there is nothing on this page..
+         * try the next one... If we lost our position on the
+         * file, we will have to seek.
+         */
+        db->blkptr++;
+        db->keyptr = 0;
+
+        /* ### EOF acceptable here too? */
+        if ((status = getpage(db, db->blkptr, 1, 0)) != APR_SUCCESS)
+            return status;
+    }
+
+    /* NOTREACHED */
+}
+
+
+APR_DECLARE(int) apr_sdbm_rdonly(apr_sdbm_t *db)
+{
+    /* ### Should we return true if the first lock is a share lock,
+     *     to reflect that apr_sdbm_store and apr_sdbm_delete will fail?
+     */
+    return (db->flags & SDBM_RDONLY) != 0;
+}
+
diff --git a/dbm/sdbm/sdbm_hash.c b/dbm/sdbm/sdbm_hash.c
new file mode 100644
index 00000000000..e4d75179451
--- /dev/null
+++ b/dbm/sdbm/sdbm_hash.c
@@ -0,0 +1,63 @@
+/* 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.
+ */
+
+/*
+ * sdbm - ndbm work-alike hashed database library
+ * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
+ * author: oz@nexus.yorku.ca
+ * status: ex-public domain. keep it that way.
+ *
+ * hashing routine
+ */
+
+#include "apr_sdbm.h"
+#include "sdbm_private.h"
+
+/*
+ * polynomial conversion ignoring overflows
+ * [this seems to work remarkably well, in fact better
+ * then the ndbm hash function. Replace at your own risk]
+ * use: 65599	nice.
+ *      65587   even better. 
+ */
+long sdbm_hash(const char *str, int len)
+{
+	register unsigned long n = 0;
+
+#define DUFF	/* go ahead and use the loop-unrolled version */
+#ifdef DUFF
+
+#define HASHC	n = *str++ + 65599 * n
+
+	if (len > 0) {
+		register int loop = (len + 8 - 1) >> 3;
+
+		switch(len & (8 - 1)) {
+		case 0:	do {
+			HASHC;	case 7:	HASHC;
+		case 6:	HASHC;	case 5:	HASHC;
+		case 4:	HASHC;	case 3:	HASHC;
+		case 2:	HASHC;	case 1:	HASHC;
+			} while (--loop);
+		}
+
+	}
+#else
+	while (len--)
+		n = *str++ + 65599 * n;
+#endif
+	return n;
+}
diff --git a/dbm/sdbm/sdbm_lock.c b/dbm/sdbm/sdbm_lock.c
new file mode 100644
index 00000000000..9241c1fb647
--- /dev/null
+++ b/dbm/sdbm/sdbm_lock.c
@@ -0,0 +1,79 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_file_info.h"
+#include "apr_file_io.h"
+#include "apr_sdbm.h"
+
+#include "sdbm_private.h"
+#include "sdbm_tune.h"
+
+/* NOTE: this function may block until it acquires the lock */
+APR_DECLARE(apr_status_t) apr_sdbm_lock(apr_sdbm_t *db, int type)
+{
+    apr_status_t status;
+    int lock_type = type & APR_FLOCK_TYPEMASK;
+
+    if (!(lock_type == APR_FLOCK_SHARED || lock_type == APR_FLOCK_EXCLUSIVE))
+        return APR_EINVAL;
+
+    if (db->flags & SDBM_EXCLUSIVE_LOCK) {
+        ++db->lckcnt;
+        return APR_SUCCESS;
+    }
+    else if (db->flags & SDBM_SHARED_LOCK) {
+        /*
+         * Cannot promote a shared lock to an exlusive lock
+         * in a cross-platform compatibile manner.
+         */
+        if (type == APR_FLOCK_EXCLUSIVE)
+            return APR_EINVAL;
+        ++db->lckcnt;
+        return APR_SUCCESS;
+    }
+    /*
+     * zero size: either a fresh database, or one with a single,
+     * unsplit data page: dirpage is all zeros.
+     */
+    if ((status = apr_file_lock(db->dirf, type)) == APR_SUCCESS) 
+    {
+        apr_finfo_t finfo;
+        if ((status = apr_file_info_get(&finfo, APR_FINFO_SIZE, db->dirf))
+                != APR_SUCCESS) {
+            (void) apr_file_unlock(db->dirf);
+            return status;
+        }
+
+        SDBM_INVALIDATE_CACHE(db, finfo);
+
+        ++db->lckcnt;
+        if (type == APR_FLOCK_SHARED)
+            db->flags |= SDBM_SHARED_LOCK;
+        else if (type == APR_FLOCK_EXCLUSIVE)
+            db->flags |= SDBM_EXCLUSIVE_LOCK;
+    }
+    return status;
+}
+
+APR_DECLARE(apr_status_t) apr_sdbm_unlock(apr_sdbm_t *db)
+{
+    if (!(db->flags & (SDBM_SHARED_LOCK | SDBM_EXCLUSIVE_LOCK)))
+        return APR_EINVAL;
+    if (--db->lckcnt > 0)
+        return APR_SUCCESS;
+    db->flags &= ~(SDBM_SHARED_LOCK | SDBM_EXCLUSIVE_LOCK);
+    return apr_file_unlock(db->dirf);
+}
diff --git a/dbm/sdbm/sdbm_pair.c b/dbm/sdbm/sdbm_pair.c
new file mode 100644
index 00000000000..50d7965b141
--- /dev/null
+++ b/dbm/sdbm/sdbm_pair.c
@@ -0,0 +1,320 @@
+/* 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.
+ */
+
+/*
+ * sdbm - ndbm work-alike hashed database library
+ * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
+ * author: oz@nexus.yorku.ca
+ * status: ex-public domain.
+ *
+ * page-level routines
+ */
+
+#include "apr_sdbm.h"
+
+#include "sdbm_tune.h"
+#include "sdbm_pair.h"
+#include "sdbm_private.h"
+
+#include <string.h>	/* for memset() */
+
+
+#define exhash(item)	sdbm_hash((item).dptr, (item).dsize)
+
+/* 
+ * forward 
+ */
+static int seepair(char *, int, char *, int);
+
+/*
+ * page format:
+ *	+------------------------------+
+ * ino	| n | keyoff | datoff | keyoff |
+ * 	+------------+--------+--------+
+ *	| datoff | - - - ---->	       |
+ *	+--------+---------------------+
+ *	|	 F R E E A R E A       |
+ *	+--------------+---------------+
+ *	|  <---- - - - | data          |
+ *	+--------+-----+----+----------+
+ *	|  key   | data     | key      |
+ *	+--------+----------+----------+
+ *
+ * calculating the offsets for free area:  if the number
+ * of entries (ino[0]) is zero, the offset to the END of
+ * the free area is the block size. Otherwise, it is the
+ * nth (ino[ino[0]]) entry's offset.
+ */
+
+int
+fitpair(pag, need)
+char *pag;
+int need;
+{
+	register int n;
+	register int off;
+	register int avail;
+	register short *ino = (short *) pag;
+
+	off = ((n = ino[0]) > 0) ? ino[n] : PBLKSIZ;
+	avail = off - (n + 1) * sizeof(short);
+	need += 2 * sizeof(short);
+
+	debug(("avail %d need %d\n", avail, need));
+
+	return need <= avail;
+}
+
+void
+putpair(pag, key, val)
+char *pag;
+apr_sdbm_datum_t key;
+apr_sdbm_datum_t val;
+{
+	register int n;
+	register int off;
+	register short *ino = (short *) pag;
+
+	off = ((n = ino[0]) > 0) ? ino[n] : PBLKSIZ;
+/*
+ * enter the key first
+ */
+	off -= key.dsize;
+	(void) memcpy(pag + off, key.dptr, key.dsize);
+	ino[n + 1] = off;
+/*
+ * now the data
+ */
+	off -= val.dsize;
+	(void) memcpy(pag + off, val.dptr, val.dsize);
+	ino[n + 2] = off;
+/*
+ * adjust item count
+ */
+	ino[0] += 2;
+}
+
+apr_sdbm_datum_t
+getpair(pag, key)
+char *pag;
+apr_sdbm_datum_t key;
+{
+	register int i;
+	register int n;
+	apr_sdbm_datum_t val;
+	register short *ino = (short *) pag;
+
+	if ((n = ino[0]) == 0)
+		return sdbm_nullitem;
+
+	if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
+		return sdbm_nullitem;
+
+	val.dptr = pag + ino[i + 1];
+	val.dsize = ino[i] - ino[i + 1];
+	return val;
+}
+
+int
+duppair(pag, key)
+char *pag;
+apr_sdbm_datum_t key;
+{
+	register short *ino = (short *) pag;
+	return ino[0] > 0 && seepair(pag, ino[0], key.dptr, key.dsize) > 0;
+}
+
+apr_sdbm_datum_t
+getnkey(pag, num)
+char *pag;
+int num;
+{
+	apr_sdbm_datum_t key;
+	register int off;
+	register short *ino = (short *) pag;
+
+	num = num * 2 - 1;
+	if (ino[0] == 0 || num > ino[0])
+		return sdbm_nullitem;
+
+	off = (num > 1) ? ino[num - 1] : PBLKSIZ;
+
+	key.dptr = pag + ino[num];
+	key.dsize = off - ino[num];
+
+	return key;
+}
+
+int
+delpair(pag, key)
+char *pag;
+apr_sdbm_datum_t key;
+{
+	register int n;
+	register int i;
+	register short *ino = (short *) pag;
+
+	if ((n = ino[0]) == 0)
+		return 0;
+
+	if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
+		return 0;
+/*
+ * found the key. if it is the last entry
+ * [i.e. i == n - 1] we just adjust the entry count.
+ * hard case: move all data down onto the deleted pair,
+ * shift offsets onto deleted offsets, and adjust them.
+ * [note: 0 < i < n]
+ */
+	if (i < n - 1) {
+		register int m;
+		register char *dst = pag + (i == 1 ? PBLKSIZ : ino[i - 1]);
+		register char *src = pag + ino[i + 1];
+		register short zoo = (short) (dst - src);
+
+		debug(("free-up %d ", zoo));
+/*
+ * shift data/keys down
+ */
+		m = ino[i + 1] - ino[n];
+
+#undef DUFF	/* just use memmove. it should be plenty fast. */
+#ifdef DUFF
+#define MOVB 	*--dst = *--src
+
+		if (m > 0) {
+			register int loop = (m + 8 - 1) >> 3;
+
+			switch (m & (8 - 1)) {
+			case 0:	do {
+				MOVB;	case 7:	MOVB;
+			case 6:	MOVB;	case 5:	MOVB;
+			case 4:	MOVB;	case 3:	MOVB;
+			case 2:	MOVB;	case 1:	MOVB;
+				} while (--loop);
+			}
+		}
+#else
+		dst -= m;
+		src -= m;
+		memmove(dst, src, m);
+#endif
+
+/*
+ * adjust offset index up
+ */
+		while (i < n - 1) {
+			ino[i] = ino[i + 2] + zoo;
+			i++;
+		}
+	}
+	ino[0] -= 2;
+	return 1;
+}
+
+/*
+ * search for the key in the page.
+ * return offset index in the range 0 < i < n.
+ * return 0 if not found.
+ */
+static int
+seepair(pag, n, key, siz)
+char *pag;
+register int n;
+register char *key;
+register int siz;
+{
+	register int i;
+	register int off = PBLKSIZ;
+	register short *ino = (short *) pag;
+
+	for (i = 1; i < n; i += 2) {
+		if (siz == off - ino[i] &&
+		    memcmp(key, pag + ino[i], siz) == 0)
+			return i;
+		off = ino[i + 1];
+	}
+	return 0;
+}
+
+void
+splpage(pag, new, sbit)
+char *pag;
+char *new;
+long sbit;
+{
+	apr_sdbm_datum_t key;
+	apr_sdbm_datum_t val;
+
+	register int n;
+	register int off = PBLKSIZ;
+	char cur[PBLKSIZ];
+	register short *ino = (short *) cur;
+
+	(void) memcpy(cur, pag, PBLKSIZ);
+	(void) memset(pag, 0, PBLKSIZ);
+	(void) memset(new, 0, PBLKSIZ);
+
+	n = ino[0];
+	for (ino++; n > 0; ino += 2) {
+		key.dptr = cur + ino[0]; 
+		key.dsize = off - ino[0];
+		val.dptr = cur + ino[1];
+		val.dsize = ino[0] - ino[1];
+/*
+ * select the page pointer (by looking at sbit) and insert
+ */
+		(void) putpair((exhash(key) & sbit) ? new : pag, key, val);
+
+		off = ino[1];
+		n -= 2;
+	}
+
+	debug(("%d split %d/%d\n", ((short *) cur)[0] / 2, 
+	       ((short *) new)[0] / 2,
+	       ((short *) pag)[0] / 2));
+}
+
+/*
+ * check page sanity: 
+ * number of entries should be something
+ * reasonable, and all offsets in the index should be in order.
+ * this could be made more rigorous.
+ */
+int
+chkpage(pag)
+char *pag;
+{
+	register int n;
+	register int off;
+	register short *ino = (short *) pag;
+
+	if ((n = ino[0]) < 0 || n > PBLKSIZ / sizeof(short))
+		return 0;
+
+	if (n > 0) {
+		off = PBLKSIZ;
+		for (ino++; n > 0; ino += 2) {
+			if (ino[0] < 0 || ino[0] > off ||
+			    ino[1] < 0 || ino[1] > off ||
+			    ino[1] > ino[0])
+				return 0;
+			off = ino[1];
+			n -= 2;
+		}
+	}
+	return 1;
+}
diff --git a/dbm/sdbm/sdbm_pair.h b/dbm/sdbm/sdbm_pair.h
new file mode 100644
index 00000000000..222c5e17f4b
--- /dev/null
+++ b/dbm/sdbm/sdbm_pair.h
@@ -0,0 +1,40 @@
+/* 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 SDBM_PAIR_H
+#define SDBM_PAIR_H
+
+/* Mini EMBED (pair.c) */
+#define chkpage apu__sdbm_chkpage
+#define delpair apu__sdbm_delpair
+#define duppair apu__sdbm_duppair
+#define fitpair apu__sdbm_fitpair
+#define getnkey apu__sdbm_getnkey
+#define getpair apu__sdbm_getpair
+#define putpair apu__sdbm_putpair
+#define splpage apu__sdbm_splpage
+
+int fitpair(char *, int);
+void  putpair(char *, apr_sdbm_datum_t, apr_sdbm_datum_t);
+apr_sdbm_datum_t getpair(char *, apr_sdbm_datum_t);
+int  delpair(char *, apr_sdbm_datum_t);
+int  chkpage (char *);
+apr_sdbm_datum_t getnkey(char *, int);
+void splpage(char *, char *, long);
+int duppair(char *, apr_sdbm_datum_t);
+
+#endif /* SDBM_PAIR_H */
+
diff --git a/dbm/sdbm/sdbm_private.h b/dbm/sdbm/sdbm_private.h
new file mode 100644
index 00000000000..f5d1ae06b56
--- /dev/null
+++ b/dbm/sdbm/sdbm_private.h
@@ -0,0 +1,84 @@
+/* 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.
+ */
+
+/*
+ * sdbm - ndbm work-alike hashed database library
+ * based on Per-Ake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
+ * author: oz@nexus.yorku.ca
+ */
+
+#ifndef SDBM_PRIVATE_H
+#define SDBM_PRIVATE_H
+
+#include "apr.h"
+#include "apr_pools.h"
+#include "apr_file_io.h"
+#include "apr_errno.h" /* for apr_status_t */
+
+#if 0
+/* if the block/page size is increased, it breaks perl apr_sdbm_t compatibility */
+#define DBLKSIZ 16384
+#define PBLKSIZ 8192
+#define PAIRMAX 8008			/* arbitrary on PBLKSIZ-N */
+#else
+#define DBLKSIZ 4096
+#define PBLKSIZ 1024
+#define PAIRMAX 1008			/* arbitrary on PBLKSIZ-N */
+#endif
+#define SPLTMAX	10			/* maximum allowed splits */
+
+/* for apr_sdbm_t.flags */
+#define SDBM_RDONLY	        0x1    /* data base open read-only */
+#define SDBM_SHARED	        0x2    /* data base open for sharing */
+#define SDBM_SHARED_LOCK	0x4    /* data base locked for shared read */
+#define SDBM_EXCLUSIVE_LOCK	0x8    /* data base locked for write */
+
+struct apr_sdbm_t {
+    apr_pool_t *pool;
+    apr_file_t *dirf;		       /* directory file descriptor */
+    apr_file_t *pagf;		       /* page file descriptor */
+    apr_int32_t flags;		       /* status/error flags, see below */
+    long maxbno;		       /* size of dirfile in bits */
+    long curbit;		       /* current bit number */
+    long hmask;			       /* current hash mask */
+    long blkptr;		       /* current block for nextkey */
+    int  keyptr;		       /* current key for nextkey */
+    long blkno;			       /* current page to read/write */
+    long pagbno;		       /* current page in pagbuf */
+    char pagbuf[PBLKSIZ];	       /* page file block buffer */
+    long dirbno;		       /* current block in dirbuf */
+    char dirbuf[DBLKSIZ];	       /* directory file block buffer */
+    int  lckcnt;                       /* number of calls to sdbm_lock */
+};
+
+
+#define sdbm_hash apu__sdbm_hash
+#define sdbm_nullitem apu__sdbm_nullitem
+
+extern const apr_sdbm_datum_t sdbm_nullitem;
+
+long sdbm_hash(const char *str, int len);
+
+/*
+ * zero the cache
+ */
+#define SDBM_INVALIDATE_CACHE(db, finfo) \
+    do { db->dirbno = (!finfo.size) ? 0 : -1; \
+         db->pagbno = -1; \
+         db->maxbno = (long)(finfo.size * BYTESIZ); \
+    } while (0);
+
+#endif /* SDBM_PRIVATE_H */
diff --git a/dbm/sdbm/sdbm_tune.h b/dbm/sdbm/sdbm_tune.h
new file mode 100644
index 00000000000..9bf3d09f288
--- /dev/null
+++ b/dbm/sdbm/sdbm_tune.h
@@ -0,0 +1,40 @@
+/* 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.
+ */
+
+/*
+ * sdbm - ndbm work-alike hashed database library
+ * tuning and portability constructs [not nearly enough]
+ * author: oz@nexus.yorku.ca
+ */
+
+#ifndef SDBM_TUNE_H
+#define SDBM_TUNE_H
+
+#include "apr_errno.h"
+
+/* ### this might be better off as sizeof(char *) */
+#define BYTESIZ		8
+
+/*
+ * misc
+ */
+#ifdef DEBUG
+#define debug(x)	printf x
+#else
+#define debug(x)
+#endif
+
+#endif /* SDBM_TUNE_H */
diff --git a/docs/APRDesign.html b/docs/APRDesign.html
new file mode 100644
index 00000000000..7d1caeb8d4e
--- /dev/null
+++ b/docs/APRDesign.html
@@ -0,0 +1,399 @@
+<HTML>
+<HEAD><TITLE>APR Design Document</TITLE></HEAD>
+<BODY>
+<h1>Design of APR</h1>
+
+<p>The Apache Portable Run-time libraries have been designed to provide a common
+interface to low level routines across any platform.  The original goal of APR
+was to combine all code in Apache to one common code base.  This is not the
+correct approach however, so the goal of APR has changed.  There are places 
+where common code is not a good thing.  For example, how to map requests 
+to either threads or processes should be platform specific.  APR's place 
+is now to combine any code that can be safely combined without sacrificing 
+performance.</p>
+
+<p>To this end we have created a set of operations that are required for cross
+platform development.  There may be other types that are desired and those
+will be implemented in the future.</p>
+
+<p>This document will discuss the structure of APR, and how best to contribute
+code to the effort.</p>
+
+<h2>APR On Windows and Netware</h2>
+
+<p>APR on Windows and Netware is different from APR on all other systems, 
+because those platforms don't use autoconf. On Unix, apr_private.h (private to 
+APR) and apr.h (public, used by applications that use APR) are generated by 
+autoconf from acconfig.h and apr.h.in respectively. On Windows (and Netware), 
+apr_private.h and apr.h are created from apr_private.hw (apr_private.hwn) 
+and apr.hw (apr.hwn) respectively.</p>
+
+<p> <strong>
+        If you add code to acconfig.h or tests to configure.in or aclocal.m4,
+        please give some thought to whether or not Windows and Netware need 
+	these additions as well.  A general rule of thumb, is that if it is 
+	a feature macro, such as APR_HAS_THREADS, Windows and Netware need it.
+	In other words, if the definition is going to be used in a public APR 
+	header file, such as apr_general.h, Windows needs it.
+        
+        The only time it is safe to add a macro or test without also adding 
+        the macro to apr*.h[n]w, is if the macro tells APR how to build.  For
+        example, a test for a header file does not need to be added to Windows.
+</strong></p>
+
+<h2>APR Features</h2>
+
+<p>One of the goals of APR is to provide a common set of features across all 
+platforms.  This is an admirable goal, it is also not realistic.  We cannot
+expect to be able to implement ALL features on ALL platforms.  So we are
+going to do the next best thing.  Provide a common interface to ALL APR 
+features on MOST platforms.</p>
+
+<p>APR developers should create FEATURE MACROS for any feature that is not
+available on ALL platforms.  This should be a simple definition which has
+the form:</p>
+
+<code>APR_HAS_FEATURE</code>
+
+<p>This macro should evaluate to true if APR has this feature on this platform.
+For example, Linux and Windows have mmap'ed files, and APR is providing an
+interface for mmapp'ing a file.  On both Linux and Windows, APR_HAS_MMAP
+should evaluate to one, and the ap_mmap_* functions should map files into
+memory and return the appropriate status codes.</p>
+
+<p>If your OS of choice does not have mmap'ed files, APR_HAS_MMAP should 
+evaluate to zero, and all ap_mmap_* functions should not be defined.  The 
+second step is a precaution that will allow us to break at compile time if a 
+programmer tries to use unsupported functions.</p>
+
+<h2>APR types</h2>
+
+<p>The base types in APR</p>
+
+<ul>
+<li>dso<br>
+	Shared library routines
+<li>mmap<br>
+	Memory-mapped files
+<li>poll<br>
+	Polling I/O
+<li>time<br>
+	Time
+<li>user<br>
+	Users and groups
+<li>locks<br>
+	Process and thread locks (critical sections)
+<li>shmem<br>
+	Shared memory
+<li>file_io<br>
+	File I/O, including pipes
+<li>atomic<br>
+	Atomic integer operations
+<li>strings<br>
+	String handling routines
+<li>memory<br>
+	Pool-based memory allocation
+<li>passwd<br>
+	Reading passwords from the terminal
+<li>tables<br>
+	Tables and hashes
+<li>network_io<br>
+	Network I/O
+<li>threadproc<br>
+	Threads and processes
+<li>misc<br>
+	Any APR type which doesn't have any other place to belong.  This
+	should be used sparingly.
+<li>support<br>
+	Functions meant to be used across multiple APR types.  This area
+	is for internal functions only.  If a function is exposed, it should
+	not be put here.
+</ul>
+
+<h2>Directory Structure</h2>
+
+<p>Each type has a base directory.  Inside this base directory, are
+subdirectories, which contain the actual code.  These subdirectories are named
+after the platforms the are compiled on.  Unix is also used as a common
+directory.  If the code you are writing is POSIX based, you should look at the
+code in the unix directory.  A good rule of thumb, is that if more than half
+your code needs to be ifdef'ed out, and the structures required for your code
+are substantively different from the POSIX code, you should create a new
+directory.</p>
+
+<p>Currently, the APR code is written for Unix, BeOS, Windows, and OS/2.  An
+example of the directory structure is the file I/O directory:</p>
+
+<pre>
+apr
+  |
+   ->  file_io
+          |
+           -> unix            The Unix and common base code
+          |
+           -> win32           The Windows code
+          | 
+           -> os2             The OS/2 code
+</pre>
+
+<p>Obviously, BeOS does not have a directory.  This is because BeOS is currently
+using the Unix directory for it's file_io.</p>
+
+<p>There are a few special top level directories.  These are test and include.
+Test is a directory which stores all test programs.  It is expected
+that if a new type is developed, there will also be a new test program, to
+help people port this new type to different platforms.  A small document
+describing how to create new tests that integrate with the test suite can be
+found in the test/ directory.  Include is a directory which stores all 
+required APR header files for external use.</p>
+
+<h2>Creating an APR Type</h2>
+
+<p>The current design of APR requires that most APR types be incomplete.  
+It is not possible to write flexible portable code if programs can access 
+the internals of APR types.  This is because different platforms are 
+likely to define different native types.  There are only two execptions to
+this rule:</p>
+
+<ul>
+<li>The first exception to this rule is if the type can only reasonably be 
+implemented one way.  For example, time is a complete type because there 
+is only one reasonable time implementation.
+
+<li>The second exception to the incomplete type rule can be found in 
+apr_portable.h.  This file defines the native types for each platform.  
+Using these types, it is possible to extract native types for any APR type.</p>
+</ul>
+
+<p>For this reason, each platform defines a structure in their own directories. 
+Those structures are then typedef'ed in an external header file.  For example
+in file_io/unix/fileio.h:</p>
+
+<pre>
+    struct ap_file_t {
+        apr_pool_t *cntxt;
+        int filedes;
+        FILE *filehand;
+        ...
+    }
+</pre>
+
+<p>In include/apr_file_io.h:</p>
+    </pre>
+    typedef struct ap_file_t    ap_file_t;
+    </pre>
+
+<p> This will cause a compiler error if somebody tries to access the filedes 
+field in this structure.  Windows does not have a filedes field, so obviously, 
+it is important that programs not be able to access these.</p>
+
+<p>You may notice the apr_pool_t field.  Most APR types have this field.  This
+type is used to allocate memory within APR.  Because every APR type has a pool,
+any APR function can allocate memory if it needs to.  This is very important
+and it is one of the reasons that APR works.  If you create a new type, you
+must add a pool to it.  If you do not, then all functions that operate on that
+type will need a pool argument.</p>
+
+<h2>New Function</h2>
+
+<p>When creating a new function, please try to adhere to these rules.</p>
+
+<ul>
+<li>  Result arguments should be the first arguments.
+<li>  If a function needs a pool, it should be the last argument.
+<li>  These rules are flexible, especially if it makes the code easier
+      to understand because it mimics a standard function.
+</ul>
+
+<h2>Documentation</h2>
+
+<p>Whenever a new function is added to APR, it MUST be documented.  New 
+functions will not be committed unless there are docs to go along with them.
+The documentation should be a comment block above the function in the header
+file.</p>
+
+<p>The format for the comment block is:</p>
+
+<pre>
+    /**
+     * Brief description of the function
+     * @param parma_1_name explanation
+     * @param parma_2_name explanation
+     * @param parma_n_name explanation
+     * @tip Any extra information people should know.
+     * @deffunc function prototype if required
+     */ 
+</pre>
+
+<p>For an actual example, look at any file in the include directory.  The 
+reason the docs are in the header files is to ensure that the docs always
+reflect the current code.  If you change paramters or return values for a 
+function, please be sure to update the documentation.</p>
+
+<h2>APR Error reporting</h2>
+
+<p>Most APR functions should return an ap_status_t type.  The only time an
+APR function does not return an ap_status_t is if it absolutely CAN NOT
+fail.  Examples of this would be filling out an array when you know you are
+not beyond the array's range.  If it cannot fail on your platform, but it
+could conceivably fail on another platform, it should return an ap_status_t.
+Unless you are sure, return an ap_status_t.</p>
+
+<strong>
+        This includes functions that return TRUE/FALSE values.  How that 
+        is handled is discussed below
+</strong>
+
+<p>All platforms return errno values unchanged.  Each platform can also have
+one system error type, which can be returned after an offset is added.  
+There are five types of error values in APR, each with it's own offset.</p>
+
+<!--  This should be turned into a table, but I am lazy today -->
+<pre>
+    Name			Purpose
+0) 			This is 0 for all platforms and isn't really defined
+ 			anywhere, but it is the offset for errno values.
+			(This has no name because it isn't actually defined, 
+                        but for completeness we are discussing it here).
+
+1) APR_OS_START_ERROR	This is platform dependent, and is the offset at which
+			APR errors start to be defined.  Error values are 
+			defined as anything which caused the APR function to 
+			fail.  APR errors in this range should be named 
+			APR_E* (i.e. APR_ENOSOCKET)
+
+2) APR_OS_START_STATUS	This is platform dependent, and is the offset at which
+			APR status values start.  Status values do not indicate
+			success or failure, and should be returned if 
+			APR_SUCCESS does not make sense.  APR status codes in 
+			this range should be name APR_* (i.e. APR_DETACH)
+
+4) APR_OS_START_USEERR	This is platform dependent, and is the offset at which
+			APR apps can begin to add their own error codes.
+
+3) APR_OS_START_SYSERR	This is platform dependent, and is the offset at which
+			system error values begin.
+</pre>
+
+<strong>The difference in naming between APR_OS_START_ERROR and 
+APR_OS_START_STATUS mentioned above allows programmers to easily determine if
+the error code indicates an error condition or a status codition.</strong>
+
+<p>If your function has multiple return codes that all indicate success, but
+with different results, or if your function can only return PASS/FAIL, you 
+should still return an apr_status_t.  In the first case, define one
+APR status code for each return value, an example of this is
+<code>apr_proc_wait</code>, which can only return APR_CHILDDONE, 
+APR_CHILDNOTDONE, or an error code.  In the second case, please return 
+APR_SUCCESS for PASS, and define a new APR status code for failure, an 
+example of this is <code>apr_compare_users</code>, which can only return
+APR_SUCCESS, APR_EMISMATCH, or an error code.</p>
+
+<p>All of these definitions can be found in apr_errno.h for all platforms.  When
+an error occurs in an APR function, the function must return an error code.
+If the error occurred in a system call and that system call uses errno to
+report an error, then the code is returned unchanged.  For example: </p>
+
+<pre>
+    if (open(fname, oflags, 0777) < 0)
+        return errno;
+</pre>
+
+<p>The next place an error can occur is a system call that uses some error value
+other than the primary error value on a platform.  This can also be handled
+by APR applications.  For example:</p>
+
+<pre>
+    if (CreateFile(fname, oflags, sharemod, NULL, 
+                   createflags, attributes, 0) == INVALID_HANDLE_VALUE
+        return (GetLAstError() + APR_OS_START_SYSERR);
+</pre>
+
+<p>These two examples implement the same function for two different platforms.
+Obviously even if the underlying problem is the same on both platforms, this
+will result in two different error codes being returned.  This is OKAY, and
+is correct for APR.  APR relies on the fact that most of the time an error
+occurs, the program logs the error and continues, it does not try to
+programatically solve the problem.  This does not mean we have not provided
+support for programmatically solving the problem, it just isn't the default
+case.  We'll get to how this problem is solved in a little while.</p>
+
+<p>If the error occurs in an APR function but it is not due to a system call,
+but it is actually an APR error or just a status code from APR, then the
+appropriate code should be returned.  These codes are defined in apr_errno.h
+and should be self explanatory.</p>
+
+<p>No APR code should ever return a code between APR_OS_START_USEERR and 
+APR_OS_START_SYSERR, those codes are reserved for APR applications.</p>
+
+<p>To programmatically correct an error in a running application, the error 
+codes need to be consistent across platforms.  This should make sense.  APR
+has provided macros to test for status code equivalency.  For example, to
+determine if the code that you received from the APR function means EOF, you
+would use the macro APR_STATUS_IS_EOF().</p>
+
+<p>Why did APR take this approach?  There are two ways to deal with error 
+codes portably.</p>
+
+<ol type=1>
+<li>  Return the same error code across all platforms.
+<li>  Return platform specific error codes and convert them when necessary.  
+</ol>
+
+<p>The problem with option number one is that it takes time to convert error 
+codes to a common code, and most of the time programs want to just output 
+an error string.  If we convert all errors to a common subset, we have four 
+steps to output an error string:</p>
+
+<p>The seocnd problem with option 1, is that it is a lossy conversion.  For
+example, Windows and OS/2 have a couple hundred error codes, but POSIX errno
+only defines about 50 errno values.  This means that if we convert to a
+canonical error value immediately, there is no way for the programmer to
+get the actual system error.</p>
+
+<pre>
+    make syscall that fails
+        convert to common error code                 step 1
+        return common error code
+            check for success
+            call error output function               step 2
+                convert back to system error         step 3
+                output error string                  step 4
+</pre>
+
+<p>By keeping the errors platform specific, we can output error strings in two
+steps.</p>
+
+<pre>
+    make syscall that fails
+        return error code
+            check for success
+            call error output function               step 1
+                output error string                  step 2
+</pre>
+
+<p>Less often, programs change their execution based on what error was returned.
+This is no more expensive using option 2 than it is using option 1, but we
+put the onus of converting the error code on the programmer themselves.
+For example, using option 1:</p>
+
+<pre>
+    make syscall that fails
+        convert to common error code
+        return common error code
+            decide execution based on common error code
+</pre>
+
+<p>Using option 2:</p>
+    
+<pre>
+    make syscall that fails
+        return error code
+            convert to common error code (using ap_canonical_error)
+            decide execution based on common error code
+</pre>
+
+<p>Finally, there is one more operation on error codes.  You can get a string
+that explains in human readable form what has happened.  To do this using 
+APR, call ap_strerror().</p>
+
diff --git a/docs/canonical_filenames.html b/docs/canonical_filenames.html
new file mode 100644
index 00000000000..2bd9bdba822
--- /dev/null
+++ b/docs/canonical_filenames.html
@@ -0,0 +1,156 @@
+<HTML>
+<HEAD><TITLE>APR Canonical Filenames</TITLE></HEAD>
+<BODY>
+<h1>APR Canonical Filename</h1>
+
+<h2>Requirements</h2>
+
+<p>APR porters need to address the underlying discrepancies between
+file systems.  To achieve a reasonable degree of security, the
+program depending upon APR needs to know that two paths may be
+compared, and that a mismatch is guarenteed to reflect that the
+two paths do not return the same resource</p>.
+
+<p>The first discrepancy is in volume roots.  Unix and pure deriviates
+have only one root path, "/".  Win32 and OS2 share root paths of
+the form "D:/", D: is the volume designation.  However, this can
+be specified as "//./D:/" as well, indicating D: volume of the 
+'this' machine.  Win32 and OS2 also may employ a UNC root path,
+of the form "//server/share/" where share is a share-point of the
+specified network server.  Finally, NetWare root paths are of the
+form "server/volume:/", or the simpler "volume:/" syntax for 'this'
+machine.  All these non-Unix file systems accept volume:path,
+without a slash following the colon, as a path relative to the
+current working directory, which APR will treat as ambigious, that
+is, neither an absolute nor a relative path per se.</p>
+
+<p>The second discrepancy is in the meaning of the 'this' directory.
+In general, 'this' must be eliminated from the path where it occurs.
+The syntax "path/./" and "path/" are both aliases to path.  However,
+this isn't file system independent, since the double slash "//" has
+a special meaning on OS2 and Win32 at the start of the path name,
+and is invalid on those platforms before the "//server/share/" UNC
+root path is completed.  Finally, as noted above, "//./volume/" is
+legal root syntax on WinNT, and perhaps others.</p>
+
+<p>The third discrepancy is in the context of the 'parent' directory.
+When "parent/path/.." occurs, the path must be unwound to "parent".
+It's also critical to simply truncate leading "/../" paths to "/",
+since the parent of the root is root.  This gets tricky on the
+Win32 and OS2 platforms, since the ".." element is invalid before
+the "//server/share/" is complete, and the "//server/share/../"
+seqence is the complete UNC root "//server/share/".  In relative
+paths, leading ".." elements are significant, until they are merged
+with an absolute path.  The relative form must only retain the ".."
+segments as leading segments, to be resolved once merged to another
+relative or an absolute path.</p>
+
+<p>The fourth discrepancy occurs with acceptance of alternate character
+codes for the same element.  Path seperators are not retained within
+the APR canonical forms.  The OS filesystem and APR (slashed) forms
+can both be returned as strings, to be used in the proper context.
+Unix, Win32 and Netware all accept slashes and backslashes as the
+same path seperator symbol, although unix strictly accepts slashes.
+While the APR form of the name strictly uses slashes, always consider
+that there could be a platform that actually accepts slashes as a
+character within a segment name.</p>
+
+<p>The fifth and worst discrepancy plauges Win32, OS2, Netware, and some
+filesystems mounted in Unix.  Case insensitivity can permit the same
+file to slip through in both it's proper case and alternate cases.
+Simply changing the case is insufficient for any character set beyond
+ASCII, since various dilectic forms of characters suffer from one to
+many or many to one translations.  An example would be u-umlaut, which
+might be accepted as a single character u-umlaut, a two character
+sequence u and the zero-width umlaut, the upper case form of the same,
+or perhaps even a captial U alone.  This can be handled in different
+ways depending on the purposes of the APR based program, but the one
+requirement is that the path must be absolute in order to resolve these
+ambiguities.  Methods employed include comparison of device and inode
+file uniqifiers, which is a fairly fast operation, or quering the OS
+for the true form of the name, which can be much slower.  Only the
+acknowledgement of the file names by the OS can validate the equality
+of two different cases of the same filename.</p>
+
+<p>The sixth discrepancy, illegal or insignificant characters, is especially 
+significant in non-unix file systems.  Trailing periods are accepted
+but never stored, therefore trailing periods must be ignored for any
+form of comparison.  And all OS's have certain expectations of what
+characters are illegal (or undesireable due to confusion.)</p>
+
+<p>A final warning, canonical functions don't transform or resolve case
+or character ambiguity issues until they are resolved into an absolute
+path.  The relative canonical path, while useful, while useful for URL
+or similar identifiers, cannot be used for testing or comparison of file 
+system objects.</p>
+
+<hr>
+
+<h2>Canonical API</h2>
+
+Functions to manipulate the apr_canon_file_t (an opaque type) include:
+
+<ul>
+<li>Create canon_file_t (from char* path and canon_file_t parent path)
+<li>Merged canon_file_t (from path and parent, both canon_file_t)
+<li>Get char* path of all or some segments
+<li>Get path flags of IsRelative, IsVirtualRoot, and IsAbsolute
+<li>Compare two canon_file_t structures for file equality
+</ul>
+
+<p>The path is corrected to the file system case only if is in absolute 
+form.  The apr_canon_file_t should be preserved as long as possible and 
+used as the parent to create child entries to reduce the number of expensive 
+stat and case canonicalization calls to the OS.</p>
+
+<p>The comparison operation provides that the APR can postpone correction
+of case by simply relying upon the device and inode for equivalence.  The
+stat implementation provides that two files are the same, while their
+strings are not equivalent, and eliminates the need for the operating
+system to return the proper form of the name.</p>
+
+<p>In any case, returning the char* path, with a flag to request the proper
+case, forces the OS calls to resolve the true names of each segment.  Where
+there is a penality for this operation and the stat device and inode test
+is faster, case correction is postponed until the char* result is requested.
+On platforms that identify the inode, device, or proper name interchangably
+with no penalities, this may occur when the name is initially processed.</p>
+
+<hr>
+
+<h2>Unix Example</h2>
+
+<p>First the simplest case:</p>
+
+<pre>
+Parse Canonical Name 
+accepts parent path as canonical_t
+        this path as string
+
+Split this path Segments on '/'
+
+For each of this path Segments
+  If first Segment
+    If this Segment is Empty ([nothing]/)
+      Append this Root Segment (don't merge)
+      Continue to next Segment
+    Else is relative
+      Append parent Segments (to merge)
+      Continue with this Segment
+  If Segment is '.' or empty (2 slashes)
+    Discard this Segment
+    Continue with next Segment
+  If Segment is '..'
+    If no previous Segment or previous Segment is '..'
+      Append this Segment
+      Continue with next Segment
+    If previous Segment and previous is not Root Segment
+      Discard previous Segment
+    Discard this Segment
+    Continue with next Segment
+  Append this Relative Segment
+  Continue with next Segment        
+</pre>
+
+</BODY>
+</HTML>
diff --git a/docs/doxygen.conf b/docs/doxygen.conf
new file mode 100644
index 00000000000..86145a4d061
--- /dev/null
+++ b/docs/doxygen.conf
@@ -0,0 +1,42 @@
+PROJECT_NAME="Apache Portable Runtime"
+
+INPUT=.
+QUIET=YES
+RECURSIVE=YES
+FILE_PATTERNS=*.h
+
+OUTPUT_DIRECTORY=docs/dox
+
+MACRO_EXPANSION=YES
+EXPAND_ONLY_PREDEF=YES
+#EXPAND_AS_DEFINED=
+# not sure why this doesn't work as EXPAND_AS_DEFINED, it should!
+PREDEFINED="APR_DECLARE(x)=x" \
+           "APR_DECLARE_NONSTD(x)=x" \
+           "APR_DECLARE_LDAP(x)=x" \
+           "APR_DECLARE_DATA" \
+           "APR_POOL_DECLARE_ACCESSOR(x)=apr_pool_t* apr_##x##_pool_get (const apr_##x##_t *the##x)" \
+           "APR_DECLARE_INHERIT_SET(x)=apr_status_t apr_##x##_inherit_set(apr_##x##_t *the##x)" \
+           "APR_DECLARE_INHERIT_UNSET(x)=apr_status_t apr_##x##_inherit_unset(apr_##x##_t *the##x)" \
+           "APR_HAS_THREADS" \
+           "APR_HAS_MMAP" \
+           "APR_HAS_XLATE" \
+           "APR_MODULE_DECLARE_DATA" \
+           "__attribute__(x)=" \
+           DOXYGEN=
+
+OPTIMIZE_OUTPUT_FOR_C=YES
+STRIP_CODE_COMMENTS=NO
+
+FULL_PATH_NAMES=NO
+CASE_SENSE_NAMES=NO
+# some autoconf guru needs to make configure set this correctly...
+# in the meantime, simply listing the headers should be alright
+#STRIP_FROM_PATH=/buildpath/apr
+
+EXCLUDE_PATTERNS="*/acconfig.h" \
+                 "*/test/*" \
+                 "*/arch/*"
+
+GENERATE_TAGFILE=docs/dox/apr.tag
+
diff --git a/docs/incomplete_types b/docs/incomplete_types
new file mode 100644
index 00000000000..cbed7774232
--- /dev/null
+++ b/docs/incomplete_types
@@ -0,0 +1,84 @@
+The question has been asked multiple times, "Why is APR using Incomplete
+types?"  This document will try to explain that.
+
+Incomplete types are used in APR because they can enforce portability, and
+they make the APR developers job easier, as well as allowing APR to use native
+types on all platforms.  Imagine a scenario where APR wasn't using incomplete
+types.  The ap_file_t type would have to be defined as:
+
+typedef struct ap_file_t {
+    ap_pool_t *pool
+    char *fname;
+    int eof_hit;
+    int pipe;
+    ap_interval_time_t timeout;
+#ifdef WIN32
+    HANDLE file_handle;
+    DWORD dwFileAttributes;
+#elif defined(OS2)
+    HFILE filedes;
+    HEV PipeSem
+#else
+    int filedes;
+    int ungetchar;
+#endif
+
+#ifndef WIN32
+    int buffered;
+    ap_int32_flags
+    int isopen;
+   
+    /* Stuff for buffered mode */
+    char *buffer;
+    int bufpos;
+    unsigned long dataRead;
+    int direction;
+    unsigned long filePtr;
+    ap_lock_t *mutex; 
+#endif
+} ap_file_t;
+
+This captures the essense of what is currently being defined for ap_file_t
+using incomplete types.  However, using this structure leads developers to
+believe that they are safe accessing any of the fields in this structure.
+This is not true.  On some platforms, such as Windows, about half of the
+structure disappears.  We could combine some of these definitions with
+macros, for example:
+
+#ifdef WIN32
+#define filetype HANDLE
+#elif OS2
+#define filetype HFILE
+#else
+#define filetype int
+#endif
+
+And then in the defintion for ap_file_t, we could say:
+    filetype filedes;
+
+This gets rid of some of the complexity, by moving it off to the side, but
+it is still not safe for a programmers to access the filedes field directly 
+outside of APR, because the programmer has no way of knowing what the actual 
+type is.  So for example printing the filedes using printf would yield wildly 
+varying results on Windows and OS2 when compared to Unix.
+
+Another option also presents itself.  Stick strictly to POSIX.  This means
+that all code can be shared on any POSIX compliant platform.  The problem
+with this is performance.  One of the benefits to APR, is that it allows
+developers to easily use native types on all platforms with the same code.
+This has proven to provide a substantial performance boost on most non-Unix
+platforms.
+
+Having said all of that, sometimes incomplete types just don't make sense.
+For example, the first implementation of time functions used incomplete types,
+which added a layer of complexity that turned out to be unnecessary.  If
+a platform cannot provide a simple number that represents the number of seconds
+elapsed since a specifed date and time, then APR doesn't really want to 
+provide support for that platform.
+
+APR is trying hard to provide a balance of incomplete and complete types, 
+but like all things, sometimes the developers make mistakes.  If you are
+using APR and find that there is an incomplete type that doesn't need to be
+an incomplete type, please let us know, we are more than willing to listen
+and design parts of APR that do not use incomplete types.
+
diff --git a/docs/non_apr_programs b/docs/non_apr_programs
new file mode 100644
index 00000000000..5003a8bd550
--- /dev/null
+++ b/docs/non_apr_programs
@@ -0,0 +1,47 @@
+How do I use APR'ized programs in connection with programs that don't
+use APR?  These darn incomplete types don't let me fill out the APR types.
+
+The APR developers acknowledge that most programs are not using APR, and
+we don't expect them to migrate to using APR just because APR has been
+released.  So, we have provided a way for non-APR'ized programs to interact
+very cleanly with APR.
+
+There are a set of functions, all documented in apr_portable.h, which allow
+a programmer to either get a native type from an APR type, or to setup an
+APR type from a native type.
+
+For example, if you are writing an add-on to another program that does not use
+APR for file I/O, but you (in your infinite wisdom) want to use APR to make
+sure your section is portable.  Assume the program provides a type foo_t with
+a file descriptor in it (fd).
+
+void function_using_apr(foo_t non_apr_struct, ap_pool_t *p)
+{
+    ap_file_t *apr_file = NULL;
+
+    ap_put_os_file(&apr_file, &non_apr_struct->fd, p);
+
+    ...
+}
+
+There are portable functions for each APR incomplete type.  They are all 
+called ap_put_os_foobar(), and they each take the same basic arguments, a
+pointer to a pointer to the incomplete type (the last pointer in that list 
+should be NULL), a pointer to the native type, and a pool.  Each of these can
+be found in apr_portable.h.
+
+If you have to do the exact opposite (take an APR type and convert it to a 
+native type, there are functions for that too.  For example:
+
+void function_not_using_apr(apr_file_t *apr_file)
+{
+    int unix_file_desc;
+
+    ap_get_os_file(&unix_file_desc, apr_file);
+   
+    ...
+}
+
+For each ap_put_os_foobar, there is a corresponding ap_get_os_file.  These are
+also documented in apr_portable.h.
+
diff --git a/docs/pool-design.html b/docs/pool-design.html
new file mode 100644
index 00000000000..46b63d62b2b
--- /dev/null
+++ b/docs/pool-design.html
@@ -0,0 +1,96 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head>
+    <title>Using APR Pools</title>
+  </head>
+  <body>
+    <h1>Using APR Pools</h1>
+
+    <p>
+      From <a href="http://subversion.tigris.org/">Subversion</a>, we
+      have learned a <em>lot</em> about how to use pools in a heavily
+      structured/object-based environment.
+      <a href="http://httpd.apache.org/">Apache httpd</a> is a
+      completely different beast: "allocate a request pool. use
+      it. destroy it."
+    </p>
+
+    <p>
+      In a complex app, that request-style of behavior is not
+      present. Luckily, the "proper" use of pools can be described in
+      just a few rules:
+    </p>
+
+    <ul>
+      <li>
+        Objects should not have their own pools. An object is
+        allocated into a pool defined by the constructor's caller. The
+        <strong>caller</strong> knows the lifetime of the object and
+        will manage it via the pool. Generally, this also means that
+        objects will not have a "close" or a "free" since those
+        operations will happen implicitly as part of the destruction
+        of the pool the objects live within.
+      </li>
+
+      <li>
+        <p>
+          Functions should not create/destroy pools for their
+          operation; they should use a pool provided by the
+          caller. Again, the <strong>caller</strong> knows more about
+          how the function will be used, how often, how many times,
+          etc. Thus, it should be in charge of the function's memory
+          usage.
+        </p>
+        <p>
+          As an example, the caller might know that the app will exit
+          upon the function's return. Thus, the function would be
+          creating extra work if it built and destroyed a
+          pool. Instead, it should use the passed-in pool, which the
+          caller is going to be tossing as part of app-exit anyways.
+        </p>
+      </li>
+
+      <li>
+        <p>
+          Whenever an unbounded iteration occurs, a subpool should be
+          used. The general pattern is:
+        </p>
+        <blockquote>
+          <pre>
+subpool = apr_create_subpool(pool);
+for (i = 0; i < n; ++i) {
+  apr_pool_clear(subpool);
+
+  do_operation(..., subpool);
+}
+apr_pool_destroy(subpool);</pre>
+        </blockquote>
+        <p>
+          This pattern prevents the 'pool' from growing unbounded and
+          consuming all of memory. Note that it is slightly more
+          optimal to clear the pool on loop-entry. This pattern also
+          allows for a '<tt>continue</tt>' to occur within the loop,
+          yet still ensure the pool will be cleared.
+        </p>
+      </li>
+
+      <li>
+        Given all of the above, it is pretty well mandatory to pass a
+        pool to <em>every</em> function. Since objects are not
+        recording pools for themselves, and the caller is always
+        supposed to be managing memory, then each function needs a
+        pool, rather than relying on some hidden magic pool. In
+        limited cases, objects may record the pool used for their
+        construction so that they can construct sub-parts, but these
+        cases should be examined carefully. Internal pools can lead to
+        unbounded pool usage if the object is not careful.
+      </li>
+    </ul>
+
+    <hr>
+    <address>Greg Stein</address>
+    <!-- Created: Wed Jun 25 14:39:57 PDT 2003 -->
+    <!-- hhmts start -->
+Last modified: Wed Jun 25 14:50:19 PDT 2003
+<!-- hhmts end -->
+
+</body></html>
diff --git a/docs/win32_builds.html b/docs/win32_builds.html
new file mode 100644
index 00000000000..c835829824b
--- /dev/null
+++ b/docs/win32_builds.html
@@ -0,0 +1,57 @@
+<HTML>
+<HEAD><TITLE>APR Win32 Builds and Debugging</TITLE></HEAD>
+<BODY>
+<h1>APR Win32 Builds and Debugging</h1>
+
+<h2>Configuration and Flavors</h2>
+
+<p>The Win32 APR Developer Studio projects consist of</p>
+
+<dl>
+  <dt>apr/apr.dsp</dt>
+    <dd>Builds the static apr.lib library (-D APR_DECLARE_STATIC)</dd>
+  <dt>apr/libapr.dsp</dt>
+    <dd>Builds the dynamic libapr.dll library (no define required)</dd>
+  <dt>apr-util/aprutil.dsp</dt>
+    <dd>Builds the static aprutil.lib library (-D APR_DECLARE_STATIC)</dd>
+  <dt>apr-util/libaprutil.dsp</dt>
+    <dd>Builds the dynamic libaprutil.dll library (no define required)</dd>
+  <dt>apr-iconv/apriconv.dsp</dt>
+    <dd>Builds the static apriconv.lib library (-D API_DECLARE_STATIC)</dd>
+  <dt>apr-iconv/libapriconv.dsp</dt>
+    <dd>Builds the dynamic libapriconv.dll library (no define required)</dd>
+</dl>
+
+<p>In order to prepare to use one of the <em>static</em> libraries above, 
+   your application must be compiled with the define shown above, so that the
+   correct linkage is created.  The APR authors intended the use of dynamic
+   libraries by default, so application authors do not need any special
+   defines in order to link to the dynamic library flavors.</p>
+
+<p>In order to build APR, you must use the proper dependencies.  A good
+   example of those dependencies is given in the apr-util/aprutil.dsw
+   Developer Studio workspace.  You can borrow the parts of that structure
+   your application needs, that workspace defines both the dynamic and static
+   library dependencies.</p>
+
+<p>The APR libraries (dynamic and static) are compiled with debugging symbols,
+   even in Release builds.  The dynamic library symbols are always usable,
+   simply keep the correspond .pdb file in the same path as the library .dll.
+   (E.g. both libapr.dll and libapr.pdb should be copied to the same path.)</p>
+
+<p>The static symbols will only be fully usable if your application does <em>not<em>
+   link with the /pdbtype:sept flag!  At the time your application links to
+   an APR library, the corresponding _src.pdb file should exist in the original
+   path the library was built, or it may be sufficient to keep the _src.pdb file
+   in the same path as the library file.  (E.g. apr.lib and apr_src.pdb should
+   reside together in your lib directory.)  The later option is unconfirmed.</p>
+
+<p>In order to keep the symbols compiled into the static library, your application
+   must use the linker's /debug flag.  If you do not want the application to be
+   debuggable with its corresponding .pdb file, omit the /debug flag and all debug
+   symbolic information is discarded.  Note that your application can only be
+   debugged with the corresponding .pdb file created by the linker, unless you use
+   /debugtype:coff or /debugtype:both in your link options.</p>
+
+</BODY>
+</HTML>
diff --git a/dso/aix/Makefile.in b/dso/aix/Makefile.in
deleted file mode 100644
index 56714ed3aa5..00000000000
--- a/dso/aix/Makefile.in
+++ /dev/null
@@ -1,61 +0,0 @@
-#CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
-#LIBS=$(EXTRA_LIBS) $(LIBS1)
-#INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
-#LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
-
-RM=@RM@
-CC=@CC@
-RANLIB=@RANLIB@
-CFLAGS=@CFLAGS@ @OPTIM@
-LIBS=@LIBS@
-LDFLAGS=@LDFLAGS@ $(LIBS)
-INCDIR=../../include
-INCLUDES=-I$(INCDIR) -I$(INCDIR1) -I.
-
-LIB=libdso.a
-
-OBJS=dso.o
-
-.c.o:
-	$(CC) $(CFLAGS) -c $(INCLUDES) $<
-
-all: $(LIB)
-
-clean:
-	$(RM) -f *.o *.a *.so
-
-distclean: clean
-	-$(RM) -f Makefile
-
-$(OBJS): Makefile
-
-$(LIB): $(OBJS)
-	$(RM) -f $@
-	$(AR) cr $@ $(OBJS)
-	$(RANLIB) $@
-
-#
-# We really don't expect end users to use this rule.  It works only with
-# gcc, and rebuilds Makefile.tmpl.  You have to re-run Configure after
-# using it.
-#
-depend:
-	cp Makefile.in Makefile.in.bak \
-	    && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.in > Makefile.new \
-	    && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \
-	    && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
-	           -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
-		> Makefile.in \
-	    && rm Makefile.new
-
-# DO NOT REMOVE
-getopt.o: getopt.c misc.h ../../include/apr_private.h \
- ../../include/apr_general.h ../../include/apr.h \
- ../../include/apr_errno.h ../../include/apr_pools.h \
- ../../include/apr_lib.h ../../include/apr_file_io.h \
- ../../include/apr_getopt.h
-start.o: start.c misc.h ../../include/apr_private.h \
- ../../include/apr_general.h ../../include/apr.h \
- ../../include/apr_errno.h ../../include/apr_pools.h \
- ../../include/apr_lib.h ../../include/apr_file_io.h \
- ../../include/apr_getopt.h
diff --git a/dso/aix/dso.c b/dso/aix/dso.c
index d43c8fdd99d..25f6262af86 100644
--- a/dso/aix/dso.c
+++ b/dso/aix/dso.c
@@ -1,59 +1,23 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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.
  */
 
 /*
  *  dso.c -- DSO system function emulation for AIX
+ *
+ *  This is *only* intended for AIX < 4.3.
  */
 
 /*
@@ -85,7 +49,10 @@
 #include <sys/types.h>
 #include <sys/ldr.h>
 #include <a.out.h>
-#include "dso.h"
+#include "apr_arch_dso.h"
+#include "apr_portable.h"
+
+#if APR_HAS_DSO
 
 #undef FREAD
 #undef FWRITE
@@ -116,7 +83,7 @@
 #define RTLD_GLOBAL	0x100	/* allow symbols to be global */
 
 /*
- * To be able to intialize, a library may provide a dl_info structure
+ * To be able to initialize, a library may provide a dl_info structure
  * that contains functions to be called to initialize and terminate.
  */
 struct dl_info {
@@ -130,45 +97,84 @@ struct dl_info {
  * add the basic "wrappers" here.
  */
 
-ap_status_t ap_dso_init(void){
+APR_DECLARE(apr_status_t) apr_os_dso_handle_put(apr_dso_handle_t **aprdso,
+                                                apr_os_dso_handle_t osdso,
+                                                apr_pool_t *pool)
+{
+    *aprdso = apr_pcalloc(pool, sizeof **aprdso);
+    (*aprdso)->handle = osdso;
+    (*aprdso)->pool = pool;
     return APR_SUCCESS;
 }
 
-ap_status_t ap_dso_load(ap_dso_handle_t **res_handle, const char *path, 
-                        ap_pool_t *ctx)
+APR_DECLARE(apr_status_t) apr_os_dso_handle_get(apr_os_dso_handle_t *osdso,
+                                                apr_dso_handle_t *aprdso)
+{
+    *osdso = aprdso->handle;
+    return APR_SUCCESS;
+}
+
+static apr_status_t dso_cleanup(void *thedso)
+{
+    apr_dso_handle_t *dso = thedso;
+
+    if (dso->handle != NULL && dlclose(dso->handle) != 0)
+        return APR_EINIT;
+    dso->handle = NULL;
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_dso_load(apr_dso_handle_t **res_handle, 
+                                       const char *path, apr_pool_t *ctx)
 {
     void *os_handle = dlopen((char *)path, RTLD_NOW | RTLD_GLOBAL);
 
-    if(os_handle == NULL)
+    *res_handle = apr_pcalloc(ctx, sizeof(*res_handle));
+
+    if(os_handle == NULL) {
+        (*res_handle)->errormsg = dlerror();       
         return APR_EDSOOPEN;
+    }
 
-    *res_handle = ap_pcalloc(ctx, sizeof(*res_handle));
     (*res_handle)->handle = (void*)os_handle;
-    (*res_handle)->cont = ctx;
+    (*res_handle)->pool = ctx;
+    (*res_handle)->errormsg = NULL;
+
+    apr_pool_cleanup_register(ctx, *res_handle, dso_cleanup, apr_pool_cleanup_null);
+
     return APR_SUCCESS;
 }
 
-ap_status_t ap_dso_unload(ap_dso_handle_t *handle)
+APR_DECLARE(apr_status_t) apr_dso_unload(apr_dso_handle_t *handle)
 {
-    if (dlclose(handle->handle) != 0)
-        return APR_EINIT;
-
-    return APR_SUCCESS;
+    return apr_pool_cleanup_run(handle->pool, handle, dso_cleanup);
 }
 
-ap_status_t ap_dso_sym(ap_dso_handle_sym_t *ressym, 
-                       ap_dso_handle_t *handle, 
-                       const char *symname)
+APR_DECLARE(apr_status_t) apr_dso_sym(apr_dso_handle_sym_t *ressym, 
+                                      apr_dso_handle_t *handle, 
+                                      const char *symname)
 {
     void *retval = dlsym(handle->handle, symname);
 
-    if (retval == NULL)
-        return APR_EINIT;
-    
-    ressym = retval;   
+    if (retval == NULL) {
+        handle->errormsg = dlerror();
+        return APR_ESYMNOTFOUND;
+    }
+
+    *ressym = retval;
     return APR_SUCCESS;
 }
 
+APR_DECLARE(const char *) apr_dso_error(apr_dso_handle_t *dso, char *buffer, apr_size_t buflen)
+{
+    if (dso->errormsg) {
+        apr_cpystrn(buffer, dso->errormsg, buflen);
+        return dso->errormsg;
+    }
+    return "No Error";
+}
+
 
 
 /*
@@ -273,7 +279,7 @@ void *dlopen(const char *path, int mode)
      * load should be declared load(const char *...). Thus we
      * cast the path to a normal char *. Ugly.
      */
-    if ((mp->entry = (void *) load((char *) path, L_NOAUTODEFER, NULL)) == NULL) {
+    if ((mp->entry = (void *) loadAndInit((char *) path, L_NOAUTODEFER, NULL)) == NULL) {
 	free(mp->name);
 	free(mp);
 	errvalid++;
@@ -704,3 +710,5 @@ static void *findMain(void)
     free(buf);
     return ret;
 }
+
+#endif
diff --git a/dso/aix/dso.h b/dso/aix/dso.h
deleted file mode 100644
index 392a92015ab..00000000000
--- a/dso/aix/dso.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef DSO_H
-#define DSO_H
-
-#include "apr_private.h"
-#include "apr_general.h"
-#include "apr_pools.h"
-#include "apr_dso.h"
-
-void *dlopen(const char *path, int mode);
-void *dlsym(void *handle, const char *symbol);
-const char *dlerror(void);
-int dlclose(void *handle);
-
-struct ap_dso_handle_t {
-    ap_pool_t  *cont;
-    void          *handle;
-};
-
-#endif
diff --git a/dso/beos/Makefile.in b/dso/beos/Makefile.in
deleted file mode 100644
index 6c5788d86f1..00000000000
--- a/dso/beos/Makefile.in
+++ /dev/null
@@ -1,60 +0,0 @@
-#CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
-#LIBS=$(EXTRA_LIBS) $(LIBS1)
-#INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
-#LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
-
-CC=@CC@
-RANLIB=@RANLIB@
-CFLAGS=@CFLAGS@ @OPTIM@
-LIBS=@LIBS@
-LDFLAGS=@LDFLAGS@ $(LIBS)
-INCDIR=../../include
-INCLUDES=-I$(INCDIR) -I$(INCDIR1) -I.
-
-LIB=libdso.a
-
-OBJS=dso.o
-
-.c.o:
-	$(CC) $(CFLAGS) -c $(INCLUDES) $<
-
-all: $(LIB)
-
-clean:
-	$(RM) -f *.o *.a *.so
-
-distclean: clean
-	-$(RM) -f Makefile
-
-$(OBJS): Makefile
-
-$(LIB): $(OBJS)
-	$(RM) -f $@
-	$(AR) cr $@ $(OBJS)
-	$(RANLIB) $@
-
-#
-# We really don't expect end users to use this rule.  It works only with
-# gcc, and rebuilds Makefile.tmpl.  You have to re-run Configure after
-# using it.
-#
-depend:
-	cp Makefile.in Makefile.in.bak \
-	    && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.in > Makefile.new \
-	    && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \
-	    && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
-	           -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
-		> Makefile.in \
-	    && rm Makefile.new
-
-# DO NOT REMOVE
-getopt.o: getopt.c misc.h ../../include/apr_private.h \
- ../../include/apr_general.h ../../include/apr.h \
- ../../include/apr_errno.h ../../include/apr_pools.h \
- ../../include/apr_lib.h ../../include/apr_file_io.h \
- ../../include/apr_getopt.h
-start.o: start.c misc.h ../../include/apr_private.h \
- ../../include/apr_general.h ../../include/apr.h \
- ../../include/apr_errno.h ../../include/apr_pools.h \
- ../../include/apr_lib.h ../../include/apr_file_io.h \
- ../../include/apr_getopt.h
diff --git a/dso/beos/dso.c b/dso/beos/dso.c
index c63102739b5..91dd1b4e81c 100644
--- a/dso/beos/dso.c
+++ b/dso/beos/dso.c
@@ -1,99 +1,98 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "dso.h"
+#include "apr_arch_dso.h"
+#include "apr_portable.h"
 
+#if APR_HAS_DSO
+
+static apr_status_t dso_cleanup(void *thedso)
+{
+    apr_dso_handle_t *dso = thedso;
+
+    if (dso->handle > 0 && unload_add_on(dso->handle) < B_NO_ERROR)
+        return APR_EINIT;
+    dso->handle = -1;
 
-ap_status_t ap_dso_init(void){
     return APR_SUCCESS;
 }
 
-ap_status_t ap_dso_load(ap_dso_handle_t **res_handle, const char *path,
-              ap_pool_t *ctx)
+APR_DECLARE(apr_status_t) apr_dso_load(apr_dso_handle_t **res_handle, 
+                                       const char *path, apr_pool_t *pool)
 {
-    image_id newid;
+    image_id newid = -1;
 
-    if((newid = load_add_on(path)) < B_NO_ERROR)
-        return APR_EINIT;
+    *res_handle = apr_pcalloc(pool, sizeof(*res_handle));
 
-    *res_handle = ap_pcalloc(ctx, sizeof(*res_handle));
+    if((newid = load_add_on(path)) < B_NO_ERROR) {
+        (*res_handle)->errormsg = strerror(newid);
+        return APR_EDSOOPEN;
+	}
+	
+    (*res_handle)->pool = pool;
     (*res_handle)->handle = newid;
-    (*res_handle)->cont = ctx;
+
+    apr_pool_cleanup_register(pool, *res_handle, dso_cleanup, apr_pool_cleanup_null);
+
     return APR_SUCCESS;
 }
 
-ap_status_t ap_dso_unload(ap_dso_handle_t *handle)
+APR_DECLARE(apr_status_t) apr_dso_unload(apr_dso_handle_t *handle)
 {
-    if(unload_add_on(handle->handle) < B_NO_ERROR)
-      return APR_EINIT;
-
-    return APR_SUCCESS;
+    return apr_pool_cleanup_run(handle->pool, handle, dso_cleanup);
 }
 
-ap_status_t ap_dso_sym(ap_dso_handle_sym_t *ressym, ap_dso_handle_t *handle,
+APR_DECLARE(apr_status_t) apr_dso_sym(apr_dso_handle_sym_t *ressym, apr_dso_handle_t *handle,
                const char *symname)
 {
     int err;
 
     if (symname == NULL)
-        return APR_EINIT;
+        return APR_ESYMNOTFOUND;
 
     err = get_image_symbol(handle->handle, symname, B_SYMBOL_TYPE_ANY, 
 			 ressym);
 
     if(err != B_OK)
-        return APR_EINIT;
+        return APR_ESYMNOTFOUND;
 
     return APR_SUCCESS;
 }
+
+APR_DECLARE(const char *) apr_dso_error(apr_dso_handle_t *dso, char *buffer, apr_size_t buflen)
+{
+    strncpy(buffer, strerror(errno), buflen);
+    return buffer;
+}
+
+APR_DECLARE(apr_status_t) apr_os_dso_handle_put(apr_dso_handle_t **aprdso,
+                                                apr_os_dso_handle_t osdso,
+                                                apr_pool_t *pool)
+{
+    *aprdso = apr_pcalloc(pool, sizeof **aprdso);
+    (*aprdso)->handle = osdso;
+    (*aprdso)->pool = pool;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_os_dso_handle_get(apr_os_dso_handle_t *osdso,
+                                                apr_dso_handle_t *aprdso)
+{
+    *osdso = aprdso->handle;
+    return APR_SUCCESS;
+}
+
+#endif
diff --git a/dso/beos/dso.h b/dso/beos/dso.h
deleted file mode 100644
index 2666d779ad2..00000000000
--- a/dso/beos/dso.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef DSO_H
-#define DSO_H
-
-#include "apr_private.h"
-#include "apr_general.h"
-#include "apr_pools.h"
-#include "apr_errno.h"
-#include "apr_dso.h"
-#include <kernel/image.h>
-
-struct ap_dso_handle_t {
-    image_id       handle;    /* Handle to the DSO loaded */
-    ap_pool_t   *cont;
-};
-
-#endif
diff --git a/dso/netware/dso.c b/dso/netware/dso.c
new file mode 100644
index 00000000000..4cd2ad611ed
--- /dev/null
+++ b/dso/netware/dso.c
@@ -0,0 +1,137 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_arch_dso.h"
+#include "apr_strings.h"
+#include "apr_portable.h"
+
+#include <library.h>
+#include <unistd.h>
+
+APR_DECLARE(apr_status_t) apr_os_dso_handle_put(apr_dso_handle_t **aprdso,
+                                                apr_os_dso_handle_t osdso,
+                                                apr_pool_t *pool)
+{
+    *aprdso = apr_pcalloc(pool, sizeof **aprdso);
+    (*aprdso)->handle = osdso;
+    (*aprdso)->pool = pool;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_os_dso_handle_get(apr_os_dso_handle_t *osdso,
+                                                apr_dso_handle_t *aprdso)
+{
+    *osdso = aprdso->handle;
+    return APR_SUCCESS;
+}
+
+static apr_status_t dso_cleanup(void *thedso)
+{
+    apr_dso_handle_t *dso = thedso;
+    sym_list *symbol = NULL;
+    void *NLMHandle = getnlmhandle();
+
+    if (dso->handle == NULL)
+        return APR_SUCCESS;
+
+    if (dso->symbols != NULL) {
+        symbol = dso->symbols;
+        while (symbol) {
+            UnImportPublicObject(NLMHandle, symbol->symbol);
+            symbol = symbol->next;
+        }
+    }
+
+    if (dlclose(dso->handle) != 0)
+        return APR_EINIT;
+
+    dso->handle = NULL;
+    dso->symbols = NULL;
+    dso->path = NULL;
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_dso_load(apr_dso_handle_t **res_handle, 
+                                       const char *path, apr_pool_t *pool)
+{
+
+    void *os_handle = NULL;
+    char *fullpath = NULL;
+    apr_status_t rv;
+
+    if ((rv = apr_filepath_merge(&fullpath, NULL, path, 
+                                 APR_FILEPATH_NATIVE, pool)) != APR_SUCCESS) {
+        return rv;
+    }
+
+    os_handle = dlopen(fullpath, RTLD_NOW | RTLD_LOCAL);
+
+    *res_handle = apr_pcalloc(pool, sizeof(**res_handle));
+
+    if(os_handle == NULL) {
+        (*res_handle)->errormsg = dlerror();
+        return APR_EDSOOPEN;
+    }
+
+    (*res_handle)->handle = (void*)os_handle;
+    (*res_handle)->pool = pool;
+    (*res_handle)->errormsg = NULL;
+    (*res_handle)->symbols = NULL;
+    (*res_handle)->path = apr_pstrdup(pool, fullpath);
+
+    apr_pool_cleanup_register(pool, *res_handle, dso_cleanup, apr_pool_cleanup_null);
+
+    return APR_SUCCESS;
+}
+    
+APR_DECLARE(apr_status_t) apr_dso_unload(apr_dso_handle_t *handle)
+{
+    return apr_pool_cleanup_run(handle->pool, handle, dso_cleanup);
+}
+
+APR_DECLARE(apr_status_t) apr_dso_sym(apr_dso_handle_sym_t *ressym, 
+                                      apr_dso_handle_t *handle, 
+                                      const char *symname)
+{
+    sym_list *symbol = NULL;
+    void *retval = dlsym(handle->handle, symname);
+
+    if (retval == NULL) {
+        handle->errormsg = dlerror();
+        return APR_ESYMNOTFOUND;
+    }
+
+    symbol = apr_pcalloc(handle->pool, sizeof(sym_list));
+    symbol->next = handle->symbols;
+    handle->symbols = symbol;
+    symbol->symbol = apr_pstrdup(handle->pool, symname);
+
+    *ressym = retval;
+    
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(const char *) apr_dso_error(apr_dso_handle_t *dso, char *buffer, 
+                                        apr_size_t buflen)
+{
+    if (dso->errormsg) {
+        apr_cpystrn(buffer, dso->errormsg, buflen);
+        return dso->errormsg;
+    }
+    return "No Error";
+}
+
diff --git a/dso/os2/Makefile.in b/dso/os2/Makefile.in
deleted file mode 100644
index 8fadaff4bb5..00000000000
--- a/dso/os2/Makefile.in
+++ /dev/null
@@ -1,57 +0,0 @@
-#CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
-#LIBS=$(EXTRA_LIBS) $(LIBS1)
-#INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
-#LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
-
-SHELL=@SH@
-CC=@CC@
-RANLIB=@RANLIB@
-CFLAGS=@CFLAGS@ @OPTIM@
-LIBS=@LIBS@
-LDFLAGS=@LDFLAGS@ $(LIBS)
-INCDIR=../../include
-INCLUDES=-I$(INCDIR) -I$(INCDIR1) -I.
-
-LIB=libdso.a
-
-OBJS=dso.o
-
-.c.o:
-	$(CC) $(CFLAGS) -c $(INCLUDES) $<
-
-all: $(LIB)
-
-clean:
-	$(RM) -f *.o *.a *.so
-
-distclean: clean
-	-$(RM) -f Makefile
-
-$(OBJS): Makefile
-
-$(LIB): $(OBJS)
-	$(RM) -f $@
-	$(AR) cr $@ $(OBJS)
-	$(RANLIB) $@
-
-#
-# We really don't expect end users to use this rule.  It works only with
-# gcc, and rebuilds Makefile.tmpl.  You have to re-run Configure after
-# using it.
-#
-depend:
-	cp Makefile.in Makefile.in.bak \
-	    && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.in > Makefile.new \
-	    && gcc -MM $(INCLUDES) $(CFLAGS) *.c | sed -e "s%\\\\\(.\)%/\\1%g" >> Makefile.new \
-	    && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
-	           -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
-		> Makefile.in \
-	    && rm Makefile.new
-
-# DO NOT REMOVE
-dso.o: dso.c dso.h $(INCDIR)/apr_private.h \
- $(INCDIR)/apr_general.h $(INCDIR)/apr.h \
- $(INCDIR)/apr_errno.h $(INCDIR)/apr_pools.h \
- $(INCDIR)/apr_lib.h $(INCDIR)/apr_file_io.h \
- $(INCDIR)/apr_time.h $(INCDIR)/apr_thread_proc.h \
- $(INCDIR)/apr_dso.h
diff --git a/dso/os2/dso.c b/dso/os2/dso.c
index 25043c130d5..1a7f7de838a 100644
--- a/dso/os2/dso.c
+++ b/dso/os2/dso.c
@@ -1,128 +1,132 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "dso.h"
-#define INCL_DOS
-#include <os2.h>
+#include "apr_arch_dso.h"
+#include "apr_strings.h"
+#include "apr_portable.h"
 #include <stdio.h>
 #include <string.h>
 
-ap_status_t ap_dso_init() 
+#if APR_HAS_DSO
+
+static apr_status_t dso_cleanup(void *thedso)
 {
-    return APR_SUCCESS;
-}
+    apr_dso_handle_t *dso = thedso;
+    int rc;
+
+    if (dso->handle == 0)
+        return APR_SUCCESS;
+       
+    rc = DosFreeModule(dso->handle);
 
+    if (rc == 0)
+        dso->handle = 0;
 
-static ap_status_t dso_cleanup(void *thedso)
-{
-    ap_dso_handle_t *dso = thedso;
-    return ap_dso_unload(dso);
+    return APR_FROM_OS_ERROR(rc);
 }
 
 
-ap_status_t ap_dso_load(ap_dso_handle_t **res_handle, const char *path, ap_pool_t *ctx)
+APR_DECLARE(apr_status_t) apr_dso_load(apr_dso_handle_t **res_handle, const char *path, apr_pool_t *ctx)
 {
-    char failed_module[1024];
+    char failed_module[200];
     HMODULE handle;
     int rc;
 
-    *res_handle = ap_pcalloc(ctx, sizeof(*res_handle));
+    *res_handle = apr_pcalloc(ctx, sizeof(**res_handle));
+    (*res_handle)->cont = ctx;
+    (*res_handle)->load_error = APR_SUCCESS;
+    (*res_handle)->failed_module = NULL;
 
     if ((rc = DosLoadModule(failed_module, sizeof(failed_module), path, &handle)) != 0) {
-        (*res_handle)->failed_module = ap_pstrdup(ctx, failed_module);
-        return APR_OS2_STATUS(rc);
+        (*res_handle)->load_error = APR_FROM_OS_ERROR(rc);
+        (*res_handle)->failed_module = apr_pstrdup(ctx, failed_module);
+        return APR_FROM_OS_ERROR(rc);
     }
 
     (*res_handle)->handle  = handle;
-    (*res_handle)->cont    = ctx;
-    (*res_handle)->failed_module = NULL;
-    ap_register_cleanup(ctx, *res_handle, dso_cleanup, ap_null_cleanup);
+    apr_pool_cleanup_register(ctx, *res_handle, dso_cleanup, apr_pool_cleanup_null);
     return APR_SUCCESS;
 }
 
 
 
-ap_status_t ap_dso_unload(ap_dso_handle_t *handle)
+APR_DECLARE(apr_status_t) apr_dso_unload(apr_dso_handle_t *handle)
 {
-    int rc;
-
-    if (handle->handle == 0)
-        return APR_SUCCESS;
-       
-    rc = DosFreeModule(handle->handle);
-
-    if (rc == 0)
-        handle->handle = 0;
-
-    return APR_OS2_STATUS(rc);
+    return apr_pool_cleanup_run(handle->cont, handle, dso_cleanup);
 }
 
 
 
-ap_status_t ap_dso_sym(ap_dso_handle_sym_t *ressym, 
-                       ap_dso_handle_t *handle, 
-                       const char *symname)
+APR_DECLARE(apr_status_t) apr_dso_sym(apr_dso_handle_sym_t *ressym, 
+                                      apr_dso_handle_t *handle, 
+                                      const char *symname)
 {
     PFN func;
     int rc;
 
     if (symname == NULL || ressym == NULL)
-        return APR_EINIT;
+        return APR_ESYMNOTFOUND;
 
-    if ((rc = DosQueryProcAddr(handle->handle, 0, symname, &func)) != 0)
-        return APR_EINIT;
+    if ((rc = DosQueryProcAddr(handle->handle, 0, symname, &func)) != 0) {
+        handle->load_error = APR_FROM_OS_ERROR(rc);
+        return handle->load_error;
+    }
 
     *ressym = func;
     return APR_SUCCESS;
 }
+
+
+
+APR_DECLARE(const char *) apr_dso_error(apr_dso_handle_t *dso, char *buffer, apr_size_t buflen)
+{
+    char message[200];
+    apr_strerror(dso->load_error, message, sizeof(message));
+
+    if (dso->failed_module != NULL) {
+        strcat(message, " (");
+        strcat(message, dso->failed_module);
+        strcat(message, ")");
+    }
+
+    apr_cpystrn(buffer, message, buflen);
+    return buffer;
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_os_dso_handle_put(apr_dso_handle_t **aprdso,
+                                                apr_os_dso_handle_t osdso,
+                                                apr_pool_t *pool)
+{
+    *aprdso = apr_pcalloc(pool, sizeof **aprdso);
+    (*aprdso)->handle = osdso;
+    (*aprdso)->cont = pool;
+    (*aprdso)->load_error = APR_SUCCESS;
+    (*aprdso)->failed_module = NULL;
+    return APR_SUCCESS;
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_os_dso_handle_get(apr_os_dso_handle_t *osdso,
+                                                apr_dso_handle_t *aprdso)
+{
+    *osdso = aprdso->handle;
+    return APR_SUCCESS;
+}
+
+#endif
diff --git a/dso/os2/dso.h b/dso/os2/dso.h
deleted file mode 100644
index 02855bb0c7b..00000000000
--- a/dso/os2/dso.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef DSO_H
-#define DSO_H
-
-#define INCL_DOS
-#include <os2.h>
-
-#include "apr_private.h"
-#include "apr_general.h"
-#include "apr_pools.h"
-#include "apr_dso.h"
-
-struct ap_dso_handle_t {
-    ap_pool_t  *cont;       /* Context for returning error strings */
-    HMODULE       handle;     /* Handle to the DSO loaded            */
-    char          *failed_module;
-};
-
-#endif
diff --git a/dso/os390/dso.c b/dso/os390/dso.c
new file mode 100644
index 00000000000..9344c71a154
--- /dev/null
+++ b/dso/os390/dso.c
@@ -0,0 +1,109 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_portable.h"
+#include "apr_strings.h"
+#include "apr_arch_dso.h"
+#include <errno.h>
+#include <string.h>
+
+#if APR_HAS_DSO
+
+APR_DECLARE(apr_status_t) apr_os_dso_handle_put(apr_dso_handle_t **aprdso,
+                                                apr_os_dso_handle_t osdso,
+                                                apr_pool_t *pool)
+{   
+    *aprdso = apr_pcalloc(pool, sizeof **aprdso);
+    (*aprdso)->handle = osdso;
+    (*aprdso)->pool = pool;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_os_dso_handle_get(apr_os_dso_handle_t *osdso,
+                                                apr_dso_handle_t *aprdso)
+{
+    *osdso = aprdso->handle;
+    return APR_SUCCESS;
+}
+
+static apr_status_t dso_cleanup(void *thedso)
+{
+    apr_dso_handle_t *dso = thedso;
+    int rc;
+
+    if (dso->handle == 0)
+        return APR_SUCCESS;
+       
+    rc = dllfree(dso->handle);
+
+    if (rc == 0) {
+        dso->handle = 0;
+        return APR_SUCCESS;
+    }
+    dso->failing_errno = errno;
+    return errno;
+}
+
+APR_DECLARE(apr_status_t) apr_dso_load(apr_dso_handle_t **res_handle, 
+                                       const char *path, apr_pool_t *ctx)
+{
+    dllhandle *handle;
+    int rc;
+
+    *res_handle = apr_pcalloc(ctx, sizeof(**res_handle));
+    (*res_handle)->pool = ctx;
+    if ((handle = dllload(path)) != NULL) {
+        (*res_handle)->handle  = handle;
+        apr_pool_cleanup_register(ctx, *res_handle, dso_cleanup, apr_pool_cleanup_null);
+        return APR_SUCCESS;
+    }
+
+    (*res_handle)->failing_errno = errno;
+    return APR_EDSOOPEN;
+}
+
+APR_DECLARE(apr_status_t) apr_dso_unload(apr_dso_handle_t *handle)
+{
+    return apr_pool_cleanup_run(handle->pool, handle, dso_cleanup);
+}
+
+APR_DECLARE(apr_status_t) apr_dso_sym(apr_dso_handle_sym_t *ressym, 
+                                      apr_dso_handle_t *handle, 
+                                      const char *symname)
+{
+    void *func_ptr;
+    void *var_ptr; 
+
+    if ((var_ptr = dllqueryvar(handle->handle, symname)) != NULL) {
+        *ressym = var_ptr;
+        return APR_SUCCESS;
+    }
+    if ((func_ptr = (void *)dllqueryfn(handle->handle, symname)) != NULL) {
+        *ressym = func_ptr;
+        return APR_SUCCESS;
+    }
+    handle->failing_errno = errno;
+    return APR_ESYMNOTFOUND;
+}
+
+APR_DECLARE(const char *) apr_dso_error(apr_dso_handle_t *handle, char *buffer, 
+                          apr_size_t buflen)
+{
+    apr_cpystrn(buffer, strerror(handle->failing_errno), buflen);
+    return buffer;
+}
+
+#endif
diff --git a/dso/unix/.cvsignore b/dso/unix/.cvsignore
deleted file mode 100644
index f3c7a7c5da6..00000000000
--- a/dso/unix/.cvsignore
+++ /dev/null
@@ -1 +0,0 @@
-Makefile
diff --git a/dso/unix/Makefile.in b/dso/unix/Makefile.in
deleted file mode 100644
index 0be9515cc43..00000000000
--- a/dso/unix/Makefile.in
+++ /dev/null
@@ -1,57 +0,0 @@
-#CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
-#LIBS=$(EXTRA_LIBS) $(LIBS1)
-#INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
-#LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
-
-RM=@RM@
-CC=@CC@
-RANLIB=@RANLIB@
-CFLAGS=@CFLAGS@ @OPTIM@
-LIBS=@LIBS@
-LDFLAGS=@LDFLAGS@ $(LIBS)
-INCDIR=../../include
-INCLUDES=-I$(INCDIR) -I$(INCDIR1) -I.
-
-LIB=libdso.a
-
-OBJS=dso.o
-
-.c.o:
-	$(CC) $(CFLAGS) -c $(INCLUDES) $<
-
-all: $(LIB)
-
-clean:
-	$(RM) -f *.o *.a *.so
-
-distclean: clean
-	-$(RM) -f Makefile
-
-$(OBJS): Makefile
-
-$(LIB): $(OBJS)
-	$(RM) -f $@
-	$(AR) cr $@ $(OBJS)
-	$(RANLIB) $@
-
-#
-# We really don't expect end users to use this rule.  It works only with
-# gcc, and rebuilds Makefile.tmpl.  You have to re-run Configure after
-# using it.
-#
-depend:
-	cp Makefile.in Makefile.in.bak \
-	    && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.in > Makefile.new \
-	    && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \
-	    && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
-	           -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
-		> Makefile.in \
-	    && rm Makefile.new
-
-# DO NOT REMOVE
-dso.o: dso.c dso.h $(INCDIR)/apr_private.h \
- $(INCDIR)/apr_general.h $(INCDIR)/apr.h \
- $(INCDIR)/apr_errno.h $(INCDIR)/apr_pools.h \
- $(INCDIR)/apr_lib.h $(INCDIR)/apr_file_io.h \
- $(INCDIR)/apr_time.h $(INCDIR)/apr_thread_proc.h \
- $(INCDIR)/apr_dso.h
diff --git a/dso/unix/dso.c b/dso/unix/dso.c
index c25986b85e3..fdd56f1d338 100644
--- a/dso/unix/dso.c
+++ b/dso/unix/dso.c
@@ -1,131 +1,251 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "dso.h"
+#include "apr_arch_dso.h"
+#include "apr_strings.h"
+#include "apr_portable.h"
+
+#if APR_HAS_DSO
+
+#if !defined(DSO_USE_DLFCN) && !defined(DSO_USE_SHL) && !defined(DSO_USE_DYLD)
+#error No DSO implementation specified.
+#endif
+
+#ifdef HAVE_STDDEF_H
+#include <stddef.h>
+#endif
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h> /* malloc(), free() */
+#endif
+#if APR_HAVE_STRING_H
+#include <string.h> /* for strerror() on HP-UX */
+#endif
+
+#if defined(DSO_USE_DYLD)
+#define DYLD_LIBRARY_HANDLE (void *)-1
+#endif
 
-ap_status_t ap_dso_init(void){
+APR_DECLARE(apr_status_t) apr_os_dso_handle_put(apr_dso_handle_t **aprdso,
+                                                apr_os_dso_handle_t osdso,
+                                                apr_pool_t *pool)
+{
+    *aprdso = apr_pcalloc(pool, sizeof **aprdso);
+    (*aprdso)->handle = osdso;
+    (*aprdso)->pool = pool;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_os_dso_handle_get(apr_os_dso_handle_t *osdso,
+                                                apr_dso_handle_t *aprdso)
+{
+    *osdso = aprdso->handle;
     return APR_SUCCESS;
 }
 
-ap_status_t ap_dso_load(ap_dso_handle_t **res_handle, const char *path, 
-                        ap_pool_t *ctx)
+static apr_status_t dso_cleanup(void *thedso)
 {
-#if defined(HPUX) || defined(HPUX10) || defined(HPUX11)
-    shl_t os_handle = shl_load(path, BIND_IMMEDIATE|BIND_VERBOSE|BIND_NOSTART, 0L);
-#elif defined(OSF1) || defined(SEQUENT) || defined(SNI) ||\
-    (defined(__FreeBSD_version) && (__FreeBSD_version >= 220000))
+    apr_dso_handle_t *dso = thedso;
+
+    if (dso->handle == NULL)
+        return APR_SUCCESS;
+
+#if defined(DSO_USE_SHL)
+    shl_unload((shl_t)dso->handle);
+#elif defined(DSO_USE_DYLD)
+    if (dso->handle != DYLD_LIBRARY_HANDLE) {
+        NSUnLinkModule(dso->handle, FALSE);
+    }
+#elif defined(DSO_USE_DLFCN)
+    if (dlclose(dso->handle) != 0)
+        return APR_EINIT;
+#endif
+    dso->handle = NULL;
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_dso_load(apr_dso_handle_t **res_handle, 
+                                       const char *path, apr_pool_t *pool)
+{
+#if defined(DSO_USE_SHL)
+    shl_t os_handle = shl_load(path, BIND_IMMEDIATE, 0L);
+
+#elif defined(DSO_USE_DYLD)
+    NSObjectFileImage image;
+    NSModule os_handle = NULL;
+    NSObjectFileImageReturnCode dsoerr;
+    const char* err_msg = NULL;
+    dsoerr = NSCreateObjectFileImageFromFile(path, &image);
+
+    if (dsoerr == NSObjectFileImageSuccess) {
+#if defined(NSLINKMODULE_OPTION_RETURN_ON_ERROR) && defined(NSLINKMODULE_OPTION_NONE)
+        os_handle = NSLinkModule(image, path,
+                                 NSLINKMODULE_OPTION_RETURN_ON_ERROR |
+                                 NSLINKMODULE_OPTION_NONE);
+        /* If something went wrong, get the errors... */
+        if (!os_handle) {
+            NSLinkEditErrors errors;
+            int errorNumber;
+            const char *fileName;
+            NSLinkEditError(&errors, &errorNumber, &fileName, &err_msg);
+        }
+#else
+        os_handle = NSLinkModule(image, path, FALSE);
+#endif
+        NSDestroyObjectFileImage(image);
+    }
+    else if ((dsoerr == NSObjectFileImageFormat ||
+             dsoerr == NSObjectFileImageInappropriateFile) &&
+             NSAddLibrary(path) == TRUE) {
+        os_handle = (NSModule)DYLD_LIBRARY_HANDLE;
+    }
+    else {
+        err_msg = "cannot create object file image or add library";
+    }
+
+#elif defined(DSO_USE_DLFCN)
+#if defined(OSF1) || defined(SEQUENT) || defined(SNI) ||\
+    (defined(__FreeBSD_version) && (__FreeBSD_version >= 220000)) ||\
+    defined(__DragonFly__)
     void *os_handle = dlopen((char *)path, RTLD_NOW | RTLD_GLOBAL);
+
 #else
-    void *os_handle = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
+    int flags = RTLD_NOW | RTLD_GLOBAL;
+    void *os_handle;
+#ifdef _AIX
+    if (strchr(path + 1, '(') && path[strlen(path) - 1] == ')')
+    {
+        /* This special archive.a(dso.so) syntax is required for
+         * the way libtool likes to build shared libraries on AIX.
+         * dlopen() support for such a library requires that the
+         * RTLD_MEMBER flag be enabled.
+         */
+        flags |= RTLD_MEMBER;
+    }
+#endif
+    os_handle = dlopen(path, flags);
 #endif    
+#endif /* DSO_USE_x */
 
-    if(os_handle == NULL)
+    *res_handle = apr_pcalloc(pool, sizeof(**res_handle));
+
+    if(os_handle == NULL) {
+#if defined(DSO_USE_SHL)
+        (*res_handle)->errormsg = strerror(errno);
+        return APR_EDSOOPEN;
+#elif defined(DSO_USE_DYLD)
+        (*res_handle)->errormsg = (err_msg) ? err_msg : "link failed";
         return APR_EDSOOPEN;
+#elif defined(DSO_USE_DLFCN)
+        (*res_handle)->errormsg = dlerror();
+        return APR_EDSOOPEN;
+#endif
+    }
 
-    *res_handle = ap_pcalloc(ctx, sizeof(*res_handle));
     (*res_handle)->handle = (void*)os_handle;
-    (*res_handle)->cont = ctx;
+    (*res_handle)->pool = pool;
+    (*res_handle)->errormsg = NULL;
+
+    apr_pool_cleanup_register(pool, *res_handle, dso_cleanup, apr_pool_cleanup_null);
+
     return APR_SUCCESS;
 }
     
-ap_status_t ap_dso_unload(ap_dso_handle_t *handle)
+APR_DECLARE(apr_status_t) apr_dso_unload(apr_dso_handle_t *handle)
 {
-#if defined(HPUX) || defined(HPUX10) || defined(HPUX11)
-    shl_unload((shl_t)handle->handle);
-#else
-    if (dlclose(handle->handle) != 0)
-        return APR_EINIT;
-#endif
-    handle->handle = NULL;
-
-    return APR_SUCCESS;
+    return apr_pool_cleanup_run(handle->pool, handle, dso_cleanup);
 }
 
-ap_status_t ap_dso_sym(ap_dso_handle_sym_t *ressym, 
-                       ap_dso_handle_t *handle, 
-                       const char *symname)
+APR_DECLARE(apr_status_t) apr_dso_sym(apr_dso_handle_sym_t *ressym, 
+                                      apr_dso_handle_t *handle, 
+                                      const char *symname)
 {
-#if defined(HPUX) || defined(HPUX10) || defined(HPUX11)
+#if defined(DSO_USE_SHL)
     void *symaddr = NULL;
     int status;
 
     errno = 0;
-    status = shl_findsym((shl_t *)&handle->handle, symname, TYPE_PROCEDURE, &symaddr);
+    status = shl_findsym((void *)&handle->handle, symname, TYPE_PROCEDURE, &symaddr);
     if (status == -1 && errno == 0) /* try TYPE_DATA instead */
-        status = shl_findsym((shl_t *)&handle->handle, symname, TYPE_DATA, &symaddr);
-    if (status = -1)
-        return APR_EINIT;
-    ressym = symaddr;
+        status = shl_findsym((void *)&handle->handle, symname, TYPE_DATA, &symaddr);
+    if (status == -1)
+        return APR_ESYMNOTFOUND;
+    *ressym = symaddr;
+    return APR_SUCCESS;
 
+#elif defined(DSO_USE_DYLD)
+    void *retval = NULL;
+    NSSymbol symbol;
+    char *symname2 = (char*)malloc(sizeof(char)*(strlen(symname)+2));
+    sprintf(symname2, "_%s", symname);
+#ifdef NSLINKMODULE_OPTION_PRIVATE
+    if (handle->handle == DYLD_LIBRARY_HANDLE) {
+        symbol = NSLookupAndBindSymbol(symname2);
+    }
+    else {
+        symbol = NSLookupSymbolInModule((NSModule)handle->handle, symname2);
+    }
+#else
+    symbol = NSLookupAndBindSymbol(symname2);
+#endif
+    free(symname2);
+    if (symbol == NULL) {
+        handle->errormsg = "undefined symbol";
+	return APR_ESYMNOTFOUND;
+    }
+    retval = NSAddressOfSymbol(symbol);
+    if (retval == NULL) {
+        handle->errormsg = "cannot resolve symbol";
+	return APR_ESYMNOTFOUND;
+    }
+    *ressym = retval;
+    return APR_SUCCESS;
+#elif defined(DSO_USE_DLFCN)
 
-#elif defined(DLSYM_NEEDS_UNDERSCORE)
+#if defined(DLSYM_NEEDS_UNDERSCORE)
     void *retval;
     char *symbol = (char*)malloc(sizeof(char)*(strlen(symname)+2));
     sprintf(symbol, "_%s", symname);
     retval = dlsym(handle->handle, symbol);
     free(symbol);
-
 #elif defined(SEQUENT) || defined(SNI)
     void *retval = dlsym(handle->handle, (char *)symname);
 #else
     void *retval = dlsym(handle->handle, symname);
-#endif
+#endif /* DLSYM_NEEDS_UNDERSCORE */
 
-    if (retval == NULL)
-        return APR_EINIT;
+    if (retval == NULL) {
+        handle->errormsg = dlerror();
+        return APR_ESYMNOTFOUND;
+    }
 
     *ressym = retval;
     
     return APR_SUCCESS;
+#endif /* DSO_USE_x */
 }
+
+APR_DECLARE(const char *) apr_dso_error(apr_dso_handle_t *dso, char *buffer, 
+                                        apr_size_t buflen)
+{
+    if (dso->errormsg) {
+        apr_cpystrn(buffer, dso->errormsg, buflen);
+        return dso->errormsg;
+    }
+    return "No Error";
+}
+
+#endif
diff --git a/dso/unix/dso.h b/dso/unix/dso.h
deleted file mode 100644
index 67bf85104d2..00000000000
--- a/dso/unix/dso.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef DSO_H
-#define DSO_H
-
-#include "apr_private.h"
-#include "apr_general.h"
-#include "apr_pools.h"
-#include "apr_dso.h"
-
-#ifdef HAVE_DLFCN_H
-#include <dlfcn.h>
-#endif
-
-#ifdef HAVE_DL_H
-#include <dl.h>
-#endif
-
-#ifndef RTLD_NOW
-#define RTLD_NOW 1
-#endif
-
-#ifndef RTLD_GLOBAL
-#define RTLD_GLOBAL 0
-#endif
-
-#if (defined(__FreeBSD__) ||\
-     defined(__OpenBSD__) ||\
-     defined(__NetBSD__)     ) && !defined(__ELF__)
-#define DLSYM_NEEDS_UNDERSCORE
-#endif
-
-struct ap_dso_handle_t {
-    ap_pool_t  *cont;
-    void          *handle;
-};
-
-#endif
diff --git a/dso/win32/dso.c b/dso/win32/dso.c
index b8dde20e4a3..89885e5fa0f 100644
--- a/dso/win32/dso.c
+++ b/dso/win32/dso.c
@@ -1,95 +1,183 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "dso.h"
+#include "apr_arch_dso.h"
+#include "apr_strings.h"
+#include "apr_private.h"
+#include "apr_arch_file_io.h"
+#include "apr_arch_utf8.h"
+
+#if APR_HAS_DSO
 
-ap_status_t ap_dso_init(void){
+APR_DECLARE(apr_status_t) apr_os_dso_handle_put(apr_dso_handle_t **aprdso,
+                                                apr_os_dso_handle_t osdso,
+                                                apr_pool_t *pool)
+{
+    *aprdso = apr_pcalloc(pool, sizeof **aprdso);
+    (*aprdso)->handle = osdso;
+    (*aprdso)->cont = pool;
     return APR_SUCCESS;
 }
 
-ap_status_t ap_dso_load(struct ap_dso_handle_t **res_handle, const char *path, 
-                        ap_pool_t *ctx)
+APR_DECLARE(apr_status_t) apr_os_dso_handle_get(apr_os_dso_handle_t *osdso,
+                                                apr_dso_handle_t *aprdso)
 {
-    HINSTANCE os_handle = LoadLibraryEx(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
-    if(os_handle == NULL) {
-        return GetLastError();
+    *osdso = aprdso->handle;
+    return APR_SUCCESS;
+}
+
+static apr_status_t dso_cleanup(void *thedso)
+{
+    apr_dso_handle_t *dso = thedso;
+
+    if (dso->handle != NULL && !FreeLibrary(dso->handle)) {
+        return apr_get_os_error();
     }
+    dso->handle = NULL;
 
-    *res_handle = ap_pcalloc(ctx, sizeof(*res_handle));
-    (*res_handle)->handle = (void*)os_handle;
-    (*res_handle)->cont = ctx;
     return APR_SUCCESS;
 }
-    
-ap_status_t ap_dso_unload(struct ap_dso_handle_t *handle)
+
+APR_DECLARE(apr_status_t) apr_dso_load(struct apr_dso_handle_t **res_handle, 
+                                       const char *path, apr_pool_t *ctx)
 {
-    if (!FreeLibrary(handle->handle)) {
-        return GetLastError();
+    HINSTANCE os_handle;
+    apr_status_t rv;
+#ifndef _WIN32_WCE
+    UINT em;
+#endif
+
+#if APR_HAS_UNICODE_FS
+    IF_WIN_OS_IS_UNICODE 
+    {
+        apr_wchar_t wpath[APR_PATH_MAX];
+        if ((rv = utf8_to_unicode_path(wpath, sizeof(wpath) 
+                                            / sizeof(apr_wchar_t), path))
+                != APR_SUCCESS) {
+            *res_handle = apr_pcalloc(ctx, sizeof(**res_handle));
+            return ((*res_handle)->load_error = rv);
+        }
+        /* Prevent ugly popups from killing our app */
+#ifndef _WIN32_WCE
+        em = SetErrorMode(SEM_FAILCRITICALERRORS);
+#endif
+        os_handle = LoadLibraryExW(wpath, NULL, 0);
+        if (!os_handle)
+            os_handle = LoadLibraryExW(wpath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
+        if (!os_handle) {
+#ifndef _WIN32_WCE
+            apr_wchar_t *ignored;
+            apr_wchar_t fpath[APR_PATH_MAX];
+            rv = apr_get_os_error();
+            if (GetFullPathNameW(wpath, sizeof(fpath) / sizeof(apr_wchar_t), fpath, &ignored)) {
+                if (SetDllDirectoryW(fpath)) {
+                    os_handle = LoadLibraryExW(wpath, NULL, 0);
+                    if (!os_handle)
+                        os_handle = LoadLibraryExW(wpath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
+                    if (os_handle)
+                        rv = APR_SUCCESS;
+                 }
+            }
+#else            
+            rv = apr_get_os_error();
+#endif
+        }
+#ifndef _WIN32_WCE
+        SetErrorMode(em);
+#endif
     }
+#endif /* APR_HAS_UNICODE_FS */
+#if APR_HAS_ANSI_FS
+    ELSE_WIN_OS_IS_ANSI
+    {
+        char fspec[APR_PATH_MAX], *p = fspec;
+        /* Must convert path from / to \ notation.
+         * Per PR2555, the LoadLibraryEx function is very picky about slashes.
+         * Debugging on NT 4 SP 6a reveals First Chance Exception within NTDLL.
+         * LoadLibrary in the MS PSDK also reveals that it -explicitly- states
+         * that backslashes must be used for the LoadLibrary family of calls.
+         */
+        apr_cpystrn(fspec, path, sizeof(fspec));
+        while ((p = strchr(p, '/')) != NULL)
+            *p = '\\';
+        
+        /* Prevent ugly popups from killing our app */
+        em = SetErrorMode(SEM_FAILCRITICALERRORS);
+        os_handle = LoadLibraryEx(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
+        if (!os_handle)
+            os_handle = LoadLibraryEx(path, NULL, 0);
+        if (!os_handle)
+            rv = apr_get_os_error();
+        else
+            rv = APR_SUCCESS;
+        SetErrorMode(em);
+    }
+#endif
+
+    *res_handle = apr_pcalloc(ctx, sizeof(**res_handle));
+    (*res_handle)->cont = ctx;
+
+    if (rv) {
+        return ((*res_handle)->load_error = rv);
+    }
+
+    (*res_handle)->handle = (void*)os_handle;
+    (*res_handle)->load_error = APR_SUCCESS;
+
+    apr_pool_cleanup_register(ctx, *res_handle, dso_cleanup, apr_pool_cleanup_null);
+
     return APR_SUCCESS;
 }
+    
+APR_DECLARE(apr_status_t) apr_dso_unload(struct apr_dso_handle_t *handle)
+{
+    return apr_pool_cleanup_run(handle->cont, handle, dso_cleanup);
+}
 
-ap_status_t ap_dso_sym(ap_dso_handle_sym_t *ressym, 
-                       struct ap_dso_handle_t *handle, 
-                       const char *symname)
+APR_DECLARE(apr_status_t) apr_dso_sym(apr_dso_handle_sym_t *ressym, 
+                         struct apr_dso_handle_t *handle, 
+                         const char *symname)
 {
-    FARPROC retval = GetProcAddress(handle->handle, symname);
-    if (!retval) {
-        return GetLastError();
+#ifdef _WIN32_WCE
+    apr_size_t symlen = strlen(symname) + 1;
+    apr_size_t wsymlen = 256;
+    apr_wchar_t wsymname[256];
+    apr_status_t rv;
+
+    rv = apr_conv_utf8_to_ucs2(wsymname, &wsymlen, symname, &symlen);
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+    else if (symlen) {
+        return APR_ENAMETOOLONG;
+    }
+
+    *ressym = (apr_dso_handle_sym_t)GetProcAddressW(handle->handle, wsymname);
+#else
+    *ressym = (apr_dso_handle_sym_t)GetProcAddress(handle->handle, symname);
+#endif
+    if (!*ressym) {
+        return apr_get_os_error();
     }
-    
-    *ressym = retval;
-    
     return APR_SUCCESS;
 }
+
+APR_DECLARE(const char *) apr_dso_error(apr_dso_handle_t *dso, char *buf, apr_size_t bufsize)
+{
+    return apr_strerror(dso->load_error, buf, bufsize);
+}
+
+#endif
diff --git a/dso/win32/dso.h b/dso/win32/dso.h
deleted file mode 100644
index 745db192dce..00000000000
--- a/dso/win32/dso.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef DSO_H
-#define DSO_H
-
-#include "apr_private.h"
-#include "apr_general.h"
-#include "apr_pools.h"
-#include "apr_dso.h"
-
-struct ap_dso_handle_t {
-    ap_pool_t  *cont;
-    void          *handle;
-};
-
-#endif
diff --git a/emacs-mode b/emacs-mode
new file mode 100644
index 00000000000..2c7abe98356
--- /dev/null
+++ b/emacs-mode
@@ -0,0 +1,15 @@
+;; M-x load-file <this file>
+;; or emacs -l <this file>
+;; to use this style: C-c . apache
+(c-add-style "apache"
+	     '((inclass . ++)
+	       (defun-block-intro . ++)
+	       (statement-block-intro . ++)
+	       (substatement . ++)
+	       (brace-list-intro . ++)
+	       (statement-case-intro . ++)
+	       (inextern-lang . 0)
+	       ))
+(setq-default indent-tabs-mode nil)
+;; if you forgot to do this at startup, then M-x eval-expression
+;; (setq indent-tabs-mode nil) on each buffer
diff --git a/encoding/apr_base64.c b/encoding/apr_base64.c
new file mode 100644
index 00000000000..b07aede010b
--- /dev/null
+++ b/encoding/apr_base64.c
@@ -0,0 +1,293 @@
+/* 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.
+ */
+
+/* base64 encoder/decoder. Originally part of main/util.c
+ * but moved here so that support/ab and apr_sha1.c could
+ * use it. This meant removing the apr_palloc()s and adding
+ * ugly 'len' functions, which is quite a nasty cost.
+ */
+
+#include "apr_base64.h"
+#if APR_CHARSET_EBCDIC
+#include "apr_xlate.h"
+#endif				/* APR_CHARSET_EBCDIC */
+
+/* aaaack but it's fast and const should make it shared text page. */
+static const unsigned char pr2six[256] =
+{
+#if !APR_CHARSET_EBCDIC
+    /* ASCII table */
+    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
+    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
+    64,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
+    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
+    64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
+    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
+#else /*APR_CHARSET_EBCDIC*/
+    /* EBCDIC table */
+    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64,
+    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+    64, 63, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+    64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 64, 64, 64, 64, 64, 64,
+    64, 35, 36, 37, 38, 39, 40, 41, 42, 43, 64, 64, 64, 64, 64, 64,
+    64, 64, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, 64,
+    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+    64,  0,  1,  2,  3,  4,  5,  6,  7,  8, 64, 64, 64, 64, 64, 64,
+    64,  9, 10, 11, 12, 13, 14, 15, 16, 17, 64, 64, 64, 64, 64, 64,
+    64, 64, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64, 64,
+    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64
+#endif /*APR_CHARSET_EBCDIC*/
+};
+
+#if APR_CHARSET_EBCDIC
+static apr_xlate_t *xlate_to_ebcdic;
+static unsigned char os_toascii[256];
+
+APR_DECLARE(apr_status_t) apr_base64init_ebcdic(apr_xlate_t *to_ascii,
+                                             apr_xlate_t *to_ebcdic)
+{
+    int i;
+    apr_size_t inbytes_left, outbytes_left;
+    apr_status_t rv;
+    int onoff;
+    
+    /* Only single-byte conversion is supported.
+     */
+    rv = apr_xlate_sb_get(to_ascii, &onoff);
+    if (rv) {
+        return rv;
+    }
+    if (!onoff) { /* If conversion is not single-byte-only */
+        return APR_EINVAL;
+    }
+    rv = apr_xlate_sb_get(to_ebcdic, &onoff);
+    if (rv) {
+        return rv;
+    }
+    if (!onoff) { /* If conversion is not single-byte-only */
+        return APR_EINVAL;
+    }
+    xlate_to_ebcdic = to_ebcdic;
+    for (i = 0; i < sizeof(os_toascii); i++) {
+        os_toascii[i] = i;
+    }
+    inbytes_left = outbytes_left = sizeof(os_toascii);
+    apr_xlate_conv_buffer(to_ascii, os_toascii, &inbytes_left,
+                          os_toascii, &outbytes_left);
+
+    return APR_SUCCESS;
+}
+#endif /*APR_CHARSET_EBCDIC*/
+
+APR_DECLARE(int) apr_base64_decode_len(const char *bufcoded)
+{
+    int nbytesdecoded;
+    register const unsigned char *bufin;
+    register apr_size_t nprbytes;
+
+    bufin = (const unsigned char *) bufcoded;
+    while (pr2six[*(bufin++)] <= 63);
+
+    nprbytes = (bufin - (const unsigned char *) bufcoded) - 1;
+    nbytesdecoded = (((int)nprbytes + 3) / 4) * 3;
+
+    return nbytesdecoded + 1;
+}
+
+APR_DECLARE(int) apr_base64_decode(char *bufplain, const char *bufcoded)
+{
+#if APR_CHARSET_EBCDIC
+    apr_size_t inbytes_left, outbytes_left;
+#endif				/* APR_CHARSET_EBCDIC */
+    int len;
+    
+    len = apr_base64_decode_binary((unsigned char *) bufplain, bufcoded);
+#if APR_CHARSET_EBCDIC
+    inbytes_left = outbytes_left = len;
+    apr_xlate_conv_buffer(xlate_to_ebcdic, bufplain, &inbytes_left,
+                          bufplain, &outbytes_left);
+#endif				/* APR_CHARSET_EBCDIC */
+    bufplain[len] = '\0';
+    return len;
+}
+
+/* This is the same as apr_base64_decode() except:
+ * - no \0 is appended
+ * - on EBCDIC machines, the conversion of the output to ebcdic is left out
+ */
+APR_DECLARE(int) apr_base64_decode_binary(unsigned char *bufplain,
+				   const char *bufcoded)
+{
+    int nbytesdecoded;
+    register const unsigned char *bufin;
+    register unsigned char *bufout;
+    register apr_size_t nprbytes;
+
+    bufin = (const unsigned char *) bufcoded;
+    while (pr2six[*(bufin++)] <= 63);
+    nprbytes = (bufin - (const unsigned char *) bufcoded) - 1;
+    nbytesdecoded = (((int)nprbytes + 3) / 4) * 3;
+
+    bufout = (unsigned char *) bufplain;
+    bufin = (const unsigned char *) bufcoded;
+
+    while (nprbytes > 4) {
+	*(bufout++) =
+	    (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
+	*(bufout++) =
+	    (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
+	*(bufout++) =
+	    (unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
+	bufin += 4;
+	nprbytes -= 4;
+    }
+
+    /* Note: (nprbytes == 1) would be an error, so just ingore that case */
+    if (nprbytes > 1) {
+	*(bufout++) =
+	    (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
+    }
+    if (nprbytes > 2) {
+	*(bufout++) =
+	    (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
+    }
+    if (nprbytes > 3) {
+	*(bufout++) =
+	    (unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
+    }
+
+    nbytesdecoded -= (4 - (int)nprbytes) & 3;
+    return nbytesdecoded;
+}
+
+APR_DECLARE(char *) apr_pbase64_decode(apr_pool_t *p, const char *bufcoded)
+{
+    char *decoded;
+    int l;
+
+    decoded = (char *) apr_palloc(p, 1 + apr_base64_decode_len(bufcoded));
+    l = apr_base64_decode(decoded, bufcoded);
+    decoded[l] = '\0'; /* make binary sequence into string */
+
+    return decoded;
+}
+
+static const char basis_64[] =
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+APR_DECLARE(int) apr_base64_encode_len(int len)
+{
+    return ((len + 2) / 3 * 4) + 1;
+}
+
+APR_DECLARE(int) apr_base64_encode(char *encoded, const char *string, int len)
+{
+#if !APR_CHARSET_EBCDIC
+    return apr_base64_encode_binary(encoded, (const unsigned char *) string, len);
+#else /* APR_CHARSET_EBCDIC */
+    int i;
+    char *p;
+
+    p = encoded;
+    for (i = 0; i < len - 2; i += 3) {
+	*p++ = basis_64[(os_toascii[string[i]] >> 2) & 0x3F];
+	*p++ = basis_64[((os_toascii[string[i]] & 0x3) << 4) |
+	                ((int) (os_toascii[string[i + 1]] & 0xF0) >> 4)];
+	*p++ = basis_64[((os_toascii[string[i + 1]] & 0xF) << 2) |
+	                ((int) (os_toascii[string[i + 2]] & 0xC0) >> 6)];
+	*p++ = basis_64[os_toascii[string[i + 2]] & 0x3F];
+    }
+    if (i < len) {
+	*p++ = basis_64[(os_toascii[string[i]] >> 2) & 0x3F];
+	if (i == (len - 1)) {
+	    *p++ = basis_64[((os_toascii[string[i]] & 0x3) << 4)];
+	    *p++ = '=';
+	}
+	else {
+	    *p++ = basis_64[((os_toascii[string[i]] & 0x3) << 4) |
+	                    ((int) (os_toascii[string[i + 1]] & 0xF0) >> 4)];
+	    *p++ = basis_64[((os_toascii[string[i + 1]] & 0xF) << 2)];
+	}
+	*p++ = '=';
+    }
+
+    *p++ = '\0';
+    return p - encoded;
+#endif				/* APR_CHARSET_EBCDIC */
+}
+
+/* This is the same as apr_base64_encode() except on EBCDIC machines, where
+ * the conversion of the input to ascii is left out.
+ */
+APR_DECLARE(int) apr_base64_encode_binary(char *encoded,
+                                      const unsigned char *string, int len)
+{
+    int i;
+    char *p;
+
+    p = encoded;
+    for (i = 0; i < len - 2; i += 3) {
+	*p++ = basis_64[(string[i] >> 2) & 0x3F];
+	*p++ = basis_64[((string[i] & 0x3) << 4) |
+	                ((int) (string[i + 1] & 0xF0) >> 4)];
+	*p++ = basis_64[((string[i + 1] & 0xF) << 2) |
+	                ((int) (string[i + 2] & 0xC0) >> 6)];
+	*p++ = basis_64[string[i + 2] & 0x3F];
+    }
+    if (i < len) {
+	*p++ = basis_64[(string[i] >> 2) & 0x3F];
+	if (i == (len - 1)) {
+	    *p++ = basis_64[((string[i] & 0x3) << 4)];
+	    *p++ = '=';
+	}
+	else {
+	    *p++ = basis_64[((string[i] & 0x3) << 4) |
+	                    ((int) (string[i + 1] & 0xF0) >> 4)];
+	    *p++ = basis_64[((string[i + 1] & 0xF) << 2)];
+	}
+	*p++ = '=';
+    }
+
+    *p++ = '\0';
+    return (int)(p - encoded);
+}
+
+APR_DECLARE(char *) apr_pbase64_encode(apr_pool_t *p, const char *string)
+{
+    char *encoded;
+    int l = strlen(string);
+
+    encoded = (char *) apr_palloc(p, apr_base64_encode_len(l));
+    l = apr_base64_encode(encoded, string, l);
+    encoded[l] = '\0'; /* make binary sequence into string */
+
+    return encoded;
+}
diff --git a/encoding/apr_escape.c b/encoding/apr_escape.c
new file mode 100644
index 00000000000..3be9eb99ec1
--- /dev/null
+++ b/encoding/apr_escape.c
@@ -0,0 +1,1254 @@
+/* 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.
+ */
+
+/* escape/unescape functions.
+ *
+ * These functions perform various escaping operations, and are provided in
+ * pairs, a function to query the length of and escape existing buffers, as
+ * well as companion functions to perform the same process to memory
+ * allocated from a pool.
+ *
+ * The API is designed to have the smallest possible RAM footprint, and so
+ * will only allocate the exact amount of RAM needed for each conversion.
+ */
+
+#include "apr_escape.h"
+#include "apr_escape_test_char.h"
+#include "apr_lib.h"
+#include "apr_strings.h"
+
+#if APR_CHARSET_EBCDIC
+static int convert_a2e[256] = {
+  0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F, 0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+  0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26, 0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F,
+  0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D, 0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,
+  0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,
+  0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
+  0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D,
+  0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
+  0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07,
+  0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x06, 0x17, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x09, 0x0A, 0x1B,
+  0x30, 0x31, 0x1A, 0x33, 0x34, 0x35, 0x36, 0x08, 0x38, 0x39, 0x3A, 0x3B, 0x04, 0x14, 0x3E, 0xFF,
+  0x41, 0xAA, 0x4A, 0xB1, 0x9F, 0xB2, 0x6A, 0xB5, 0xBB, 0xB4, 0x9A, 0x8A, 0xB0, 0xCA, 0xAF, 0xBC,
+  0x90, 0x8F, 0xEA, 0xFA, 0xBE, 0xA0, 0xB6, 0xB3, 0x9D, 0xDA, 0x9B, 0x8B, 0xB7, 0xB8, 0xB9, 0xAB,
+  0x64, 0x65, 0x62, 0x66, 0x63, 0x67, 0x9E, 0x68, 0x74, 0x71, 0x72, 0x73, 0x78, 0x75, 0x76, 0x77,
+  0xAC, 0x69, 0xED, 0xEE, 0xEB, 0xEF, 0xEC, 0xBF, 0x80, 0xFD, 0xFE, 0xFB, 0xFC, 0xBA, 0xAE, 0x59,
+  0x44, 0x45, 0x42, 0x46, 0x43, 0x47, 0x9C, 0x48, 0x54, 0x51, 0x52, 0x53, 0x58, 0x55, 0x56, 0x57,
+  0x8C, 0x49, 0xCD, 0xCE, 0xCB, 0xCF, 0xCC, 0xE1, 0x70, 0xDD, 0xDE, 0xDB, 0xDC, 0x8D, 0x8E, 0xDF };
+
+static int convert_e2a[256] = {
+  0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F, 0x97, 0x8D, 0x8E, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+  0x10, 0x11, 0x12, 0x13, 0x9D, 0x0A, 0x08, 0x87, 0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F,
+  0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x17, 0x1B, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07,
+  0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04, 0x98, 0x99, 0x9A, 0x9B, 0x14, 0x15, 0x9E, 0x1A,
+  0x20, 0xA0, 0xE2, 0xE4, 0xE0, 0xE1, 0xE3, 0xE5, 0xE7, 0xF1, 0xA2, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
+  0x26, 0xE9, 0xEA, 0xEB, 0xE8, 0xED, 0xEE, 0xEF, 0xEC, 0xDF, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0x5E,
+  0x2D, 0x2F, 0xC2, 0xC4, 0xC0, 0xC1, 0xC3, 0xC5, 0xC7, 0xD1, 0xA6, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
+  0xF8, 0xC9, 0xCA, 0xCB, 0xC8, 0xCD, 0xCE, 0xCF, 0xCC, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
+  0xD8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0xAB, 0xBB, 0xF0, 0xFD, 0xFE, 0xB1,
+  0xB0, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0xAA, 0xBA, 0xE6, 0xB8, 0xC6, 0xA4,
+  0xB5, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0xA1, 0xBF, 0xD0, 0x5B, 0xDE, 0xAE,
+  0xAC, 0xA3, 0xA5, 0xB7, 0xA9, 0xA7, 0xB6, 0xBC, 0xBD, 0xBE, 0xDD, 0xA8, 0xAF, 0x5D, 0xB4, 0xD7,
+  0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0xAD, 0xF4, 0xF6, 0xF2, 0xF3, 0xF5,
+  0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0xB9, 0xFB, 0xFC, 0xF9, 0xFA, 0xFF,
+  0x5C, 0xF7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0xB2, 0xD4, 0xD6, 0xD2, 0xD3, 0xD5,
+  0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0xB3, 0xDB, 0xDC, 0xD9, 0xDA, 0x9F };
+#define RAW_ASCII_CHAR(ch)  convert_e2a[(unsigned char)ch]
+#else /* APR_CHARSET_EBCDIC */
+#define RAW_ASCII_CHAR(ch)  (ch)
+#endif /* !APR_CHARSET_EBCDIC */
+
+/* we assume the folks using this ensure 0 <= c < 256... which means
+ * you need a cast to (unsigned char) first, you can't just plug a
+ * char in here and get it to work, because if char is signed then it
+ * will first be sign extended.
+ */
+#define TEST_CHAR(c, f)        (test_char_table[(unsigned)(c)] & (f))
+
+APR_DECLARE(apr_status_t) apr_escape_shell(char *escaped, const char *str,
+        apr_ssize_t slen, apr_size_t *len)
+{
+    unsigned char *d;
+    const unsigned char *s;
+    apr_size_t size = 1;
+    int found = 0;
+
+    d = (unsigned char *) escaped;
+    s = (const unsigned char *) str;
+
+    if (s) {
+        if (d) {
+            for (; *s && slen; ++s, slen--) {
+#if defined(OS2) || defined(WIN32)
+                /*
+                 * Newlines to Win32/OS2 CreateProcess() are ill advised.
+                 * Convert them to spaces since they are effectively white
+                 * space to most applications
+                 */
+                if (*s == '\r' || *s == '\n') {
+                    if (d) {
+                        *d++ = ' ';
+                        found = 1;
+                    }
+                    continue;
+                }
+#endif
+                if (TEST_CHAR(*s, T_ESCAPE_SHELL_CMD)) {
+                    *d++ = '\\';
+                    size++;
+                    found = 1;
+                }
+                *d++ = *s;
+                size++;
+            }
+            *d = '\0';
+        }
+        else {
+            for (; *s && slen; ++s, slen--) {
+                if (TEST_CHAR(*s, T_ESCAPE_SHELL_CMD)) {
+                    size++;
+                    found = 1;
+                }
+                size++;
+            }
+        }
+    }
+
+    if (len) {
+        *len = size;
+    }
+    if (!found) {
+        return APR_NOTFOUND;
+    }
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(const char *) apr_pescape_shell(apr_pool_t *p, const char *str)
+{
+    apr_size_t len;
+
+    switch (apr_escape_shell(NULL, str, APR_ESCAPE_STRING, &len)) {
+    case APR_SUCCESS: {
+        char *cmd = apr_palloc(p, len);
+        apr_escape_shell(cmd, str, APR_ESCAPE_STRING, NULL);
+        return cmd;
+    }
+    case APR_NOTFOUND: {
+        break;
+    }
+    }
+
+    return str;
+}
+
+static char x2c(const char *what)
+{
+    register char digit;
+
+#if !APR_CHARSET_EBCDIC
+    digit =
+            ((what[0] >= 'A') ? ((what[0] & 0xdf) - 'A') + 10 : (what[0] - '0'));
+    digit *= 16;
+    digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A') + 10 : (what[1] - '0'));
+#else /*APR_CHARSET_EBCDIC*/
+    char xstr[5];
+    xstr[0]='0';
+    xstr[1]='x';
+    xstr[2]=what[0];
+    xstr[3]=what[1];
+    xstr[4]='\0';
+    digit = convert_a2e[0xFF & strtol(xstr, NULL, 16)];
+#endif /*APR_CHARSET_EBCDIC*/
+    return (digit);
+}
+
+APR_DECLARE(apr_status_t) apr_unescape_url(char *escaped, const char *url,
+        apr_ssize_t slen, const char *forbid, const char *reserved, int plus,
+        apr_size_t *len)
+{
+    apr_size_t size = 1;
+    int found = 0;
+    const char *s = (const char *) url;
+    char *d = (char *) escaped;
+    register int badesc, badpath;
+
+    if (!url) {
+        return APR_NOTFOUND;
+    }
+
+    badesc = 0;
+    badpath = 0;
+    if (s) {
+        if (d) {
+            for (; *s && slen; ++s, d++, slen--) {
+                if (plus && *s == '+') {
+                    *d = ' ';
+                    found = 1;
+                }
+                else if (*s != '%') {
+                    *d = *s;
+                }
+                else {
+                    if (!apr_isxdigit(*(s + 1)) || !apr_isxdigit(*(s + 2))) {
+                        badesc = 1;
+                        *d = '%';
+                    }
+                    else {
+                        char decoded;
+                        decoded = x2c(s + 1);
+                        if ((decoded == '\0')
+                                || (forbid && strchr(forbid, decoded))) {
+                            badpath = 1;
+                            *d = decoded;
+                            s += 2;
+                            slen -= 2;
+                        }
+                        else if (reserved && strchr(reserved, decoded)) {
+                            *d++ = *s++;
+                            *d++ = *s++;
+                            *d = *s;
+                            size += 2;
+                        }
+                        else {
+                            *d = decoded;
+                            s += 2;
+                            slen -= 2;
+                            found = 1;
+                        }
+                    }
+                }
+                size++;
+            }
+            *d = '\0';
+        }
+        else {
+            for (; *s && slen; ++s, slen--) {
+                if (plus && *s == '+') {
+                    found = 1;
+                }
+                else if (*s != '%') {
+                    /* character unchanged */
+                }
+                else {
+                    if (!apr_isxdigit(*(s + 1)) || !apr_isxdigit(*(s + 2))) {
+                        badesc = 1;
+                    }
+                    else {
+                        char decoded;
+                        decoded = x2c(s + 1);
+                        if ((decoded == '\0')
+                                || (forbid && strchr(forbid, decoded))) {
+                            badpath = 1;
+                            s += 2;
+                            slen -= 2;
+                        }
+                        else if (reserved && strchr(reserved, decoded)) {
+                            s += 2;
+                            slen -= 2;
+                            size += 2;
+                        }
+                        else {
+                            s += 2;
+                            slen -= 2;
+                            found = 1;
+                        }
+                    }
+                }
+                size++;
+            }
+        }
+    }
+
+    if (len) {
+        *len = size;
+    }
+    if (badesc) {
+        return APR_EINVAL;
+    }
+    else if (badpath) {
+        return APR_BADCH;
+    }
+    else if (!found) {
+        return APR_NOTFOUND;
+    }
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(const char *) apr_punescape_url(apr_pool_t *p, const char *url,
+        const char *forbid, const char *reserved, int plus)
+{
+    apr_size_t len;
+
+    switch (apr_unescape_url(NULL, url, APR_ESCAPE_STRING, forbid, reserved,
+            plus, &len)) {
+    case APR_SUCCESS: {
+        char *buf = apr_palloc(p, len);
+        apr_unescape_url(buf, url, APR_ESCAPE_STRING, forbid, reserved, plus,
+                NULL);
+        return buf;
+    }
+    case APR_EINVAL:
+    case APR_BADCH: {
+        return NULL;
+    }
+    case APR_NOTFOUND: {
+        break;
+    }
+    }
+
+    return url;
+}
+
+/* c2x takes an unsigned, and expects the caller has guaranteed that
+ * 0 <= what < 256... which usually means that you have to cast to
+ * unsigned char first, because (unsigned)(char)(x) first goes through
+ * signed extension to an int before the unsigned cast.
+ *
+ * The reason for this assumption is to assist gcc code generation --
+ * the unsigned char -> unsigned extension is already done earlier in
+ * both uses of this code, so there's no need to waste time doing it
+ * again.
+ */
+static const char c2x_table[] = "0123456789abcdef";
+
+static APR_INLINE unsigned char *c2x(unsigned what, unsigned char prefix,
+        unsigned char *where)
+{
+#if APR_CHARSET_EBCDIC
+    what = convert_e2a[(unsigned char)what];
+#endif /*APR_CHARSET_EBCDIC*/
+    *where++ = prefix;
+    *where++ = c2x_table[what >> 4];
+    *where++ = c2x_table[what & 0xf];
+    return where;
+}
+
+APR_DECLARE(apr_status_t) apr_escape_path_segment(char *escaped,
+        const char *str, apr_ssize_t slen, apr_size_t *len)
+{
+    apr_size_t size = 1;
+    int found = 0;
+    const unsigned char *s = (const unsigned char *) str;
+    unsigned char *d = (unsigned char *) escaped;
+    unsigned c;
+
+    if (s) {
+        if (d) {
+            while ((c = *s) && slen) {
+                if (TEST_CHAR(c, T_ESCAPE_PATH_SEGMENT)) {
+                    d = c2x(c, '%', d);
+                    size += 2;
+                    found = 1;
+                }
+                else {
+                    *d++ = c;
+                }
+                ++s;
+                size++;
+                slen--;
+            }
+            *d = '\0';
+        }
+        else {
+            while ((c = *s) && slen) {
+                if (TEST_CHAR(c, T_ESCAPE_PATH_SEGMENT)) {
+                    size += 2;
+                    found = 1;
+                }
+                ++s;
+                size++;
+                slen--;
+            }
+        }
+    }
+
+    if (len) {
+        *len = size;
+    }
+    if (!found) {
+        return APR_NOTFOUND;
+    }
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(const char *) apr_pescape_path_segment(apr_pool_t *p,
+        const char *str)
+{
+    apr_size_t len;
+
+    switch (apr_escape_path_segment(NULL, str, APR_ESCAPE_STRING, &len)) {
+    case APR_SUCCESS: {
+        char *cmd = apr_palloc(p, len);
+        apr_escape_path_segment(cmd, str, APR_ESCAPE_STRING, NULL);
+        return cmd;
+    }
+    case APR_NOTFOUND: {
+        break;
+    }
+    }
+
+    return str;
+}
+
+APR_DECLARE(apr_status_t) apr_escape_path(char *escaped, const char *path,
+        apr_ssize_t slen, int partial, apr_size_t *len)
+{
+    apr_size_t size = 1;
+    int found = 0;
+    const unsigned char *s = (const unsigned char *) path;
+    unsigned char *d = (unsigned char *) escaped;
+    unsigned c;
+
+    if (!path) {
+        return APR_NOTFOUND;
+    }
+
+    if (!partial) {
+        const char *colon = strchr(path, ':');
+        const char *slash = strchr(path, '/');
+
+        if (colon && (!slash || colon < slash)) {
+            if (d) {
+                *d++ = '.';
+                *d++ = '/';
+            }
+            size += 2;
+            found = 1;
+        }
+    }
+    if (d) {
+        while ((c = *s) && slen) {
+            if (TEST_CHAR(c, T_OS_ESCAPE_PATH)) {
+                d = c2x(c, '%', d);
+                size += 2;
+                found = 1;
+            }
+            else {
+                *d++ = c;
+            }
+            ++s;
+            size++;
+            slen--;
+        }
+        *d = '\0';
+    }
+    else {
+        while ((c = *s) && slen) {
+            if (TEST_CHAR(c, T_OS_ESCAPE_PATH)) {
+                size += 2;
+                found = 1;
+            }
+            ++s;
+            size++;
+            slen--;
+        }
+    }
+
+    if (len) {
+        *len = size;
+    }
+    if (!found) {
+        return APR_NOTFOUND;
+    }
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(const char *) apr_pescape_path(apr_pool_t *p, const char *str,
+        int partial)
+{
+    apr_size_t len;
+
+    switch (apr_escape_path(NULL, str, APR_ESCAPE_STRING, partial, &len)) {
+    case APR_SUCCESS: {
+        char *path = apr_palloc(p, len);
+        apr_escape_path(path, str, APR_ESCAPE_STRING, partial, NULL);
+        return path;
+    }
+    case APR_NOTFOUND: {
+        break;
+    }
+    }
+
+    return str;
+}
+
+APR_DECLARE(apr_status_t) apr_escape_urlencoded(char *escaped, const char *str,
+        apr_ssize_t slen, apr_size_t *len)
+{
+    apr_size_t size = 1;
+    int found = 0;
+    const unsigned char *s = (const unsigned char *) str;
+    unsigned char *d = (unsigned char *) escaped;
+    unsigned c;
+
+    if (s) {
+        if (d) {
+            while ((c = *s) && slen) {
+                if (TEST_CHAR(c, T_ESCAPE_URLENCODED)) {
+                    d = c2x(c, '%', d);
+                    size += 2;
+                    found = 1;
+                }
+                else if (c == ' ') {
+                    *d++ = '+';
+                    found = 1;
+                }
+                else {
+                    *d++ = c;
+                }
+                ++s;
+                size++;
+                slen--;
+            }
+            *d = '\0';
+        }
+        else {
+            while ((c = *s) && slen) {
+                if (TEST_CHAR(c, T_ESCAPE_URLENCODED)) {
+                    size += 2;
+                    found = 1;
+                }
+                else if (c == ' ') {
+                    found = 1;
+                }
+                ++s;
+                size++;
+                slen--;
+            }
+        }
+    }
+
+    if (len) {
+        *len = size;
+    }
+    if (!found) {
+        return APR_NOTFOUND;
+    }
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(const char *) apr_pescape_urlencoded(apr_pool_t *p, const char *str)
+{
+    apr_size_t len;
+
+    switch (apr_escape_urlencoded(NULL, str, APR_ESCAPE_STRING, &len)) {
+    case APR_SUCCESS: {
+        char *encoded = apr_palloc(p, len);
+        apr_escape_urlencoded(encoded, str, APR_ESCAPE_STRING, NULL);
+        return encoded;
+    }
+    case APR_NOTFOUND: {
+        break;
+    }
+    }
+
+    return str;
+}
+
+APR_DECLARE(apr_status_t) apr_escape_entity(char *escaped, const char *str,
+        apr_ssize_t slen, int toasc, apr_size_t *len)
+{
+    apr_size_t size = 1;
+    int found = 0;
+    const unsigned char *s = (const unsigned char *) str;
+    unsigned char *d = (unsigned char *) escaped;
+    unsigned c;
+
+    if (s) {
+        if (d) {
+            while ((c = *s) && slen) {
+                if (TEST_CHAR(c, T_ESCAPE_XML)) {
+                    switch (c) {
+                    case '>': {
+                        memcpy(d, "&gt;", 4);
+                        size += 4;
+                        d += 4;
+                        break;
+                    }
+                    case '<': {
+                        memcpy(d, "&lt;", 4);
+                        size += 4;
+                        d += 4;
+                        break;
+                    }
+                    case '&': {
+                        memcpy(d, "&amp;", 5);
+                        size += 5;
+                        d += 5;
+                        break;
+                    }
+                    case '\"': {
+                        memcpy(d, "&quot;", 6);
+                        size += 6;
+                        d += 6;
+                        break;
+                    }
+                    case '\'': {
+                        memcpy(d, "&apos;", 6);
+                        size += 6;
+                        d += 6;
+                        break;
+                    }
+                    }
+                    found = 1;
+                }
+                else if (toasc && !apr_isascii(c)) {
+                    int offset = apr_snprintf((char *) d, 6, "&#%3.3d;", c);
+                    size += offset;
+                    d += offset;
+                    found = 1;
+                }
+                else {
+                    *d++ = c;
+                    size++;
+                }
+                ++s;
+                slen--;
+            }
+            *d = '\0';
+        }
+        else {
+            while ((c = *s) && slen) {
+                if (TEST_CHAR(c, T_ESCAPE_XML)) {
+                    switch (c) {
+                    case '>': {
+                        size += 4;
+                        break;
+                    }
+                    case '<': {
+                        size += 4;
+                        break;
+                    }
+                    case '&': {
+                        size += 5;
+                        break;
+                    }
+                    case '\"': {
+                        size += 6;
+                        break;
+                    }
+                    case '\'': {
+                        size += 6;
+                        break;
+                    }
+                    }
+                    found = 1;
+                }
+                else if (toasc && !apr_isascii(c)) {
+                    char buf[8];
+                    size += apr_snprintf(buf, 6, "&#%3.3d;", c);
+                    found = 1;
+                }
+                else {
+                    size++;
+                }
+                ++s;
+                slen--;
+            }
+        }
+    }
+
+    if (len) {
+        *len = size;
+    }
+    if (!found) {
+        return APR_NOTFOUND;
+    }
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(const char *) apr_pescape_entity(apr_pool_t *p, const char *str,
+        int toasc)
+{
+    apr_size_t len;
+
+    switch (apr_escape_entity(NULL, str, APR_ESCAPE_STRING, toasc, &len)) {
+    case APR_SUCCESS: {
+        char *cmd = apr_palloc(p, len);
+        apr_escape_entity(cmd, str, APR_ESCAPE_STRING, toasc, NULL);
+        return cmd;
+    }
+    case APR_NOTFOUND: {
+        break;
+    }
+    }
+
+    return str;
+}
+
+/* maximum length of any ISO-LATIN-1 HTML entity name. */
+#define MAXENTLEN (6)
+
+APR_DECLARE(apr_status_t) apr_unescape_entity(char *unescaped, const char *str,
+        apr_ssize_t slen, apr_size_t *len)
+{
+    int found = 0;
+    apr_size_t size = 1;
+    int val, i, j;
+    char *d = unescaped;
+    const char *s = str;
+    const char *ents;
+    static const char * const entlist[MAXENTLEN + 1] =
+    {
+            NULL, /* 0 */
+            NULL, /* 1 */
+            "lt\074gt\076", /* 2 */
+            "amp\046ETH\320eth\360", /* 3 */
+            "quot\042Auml\304Euml\313Iuml\317Ouml\326Uuml\334auml\344euml"
+            "\353iuml\357ouml\366uuml\374yuml\377", /* 4 */
+            "Acirc\302Aring\305AElig\306Ecirc\312Icirc\316Ocirc\324Ucirc"
+            "\333THORN\336szlig\337acirc\342aring\345aelig\346ecirc\352"
+            "icirc\356ocirc\364ucirc\373thorn\376", /* 5 */
+            "Agrave\300Aacute\301Atilde\303Ccedil\307Egrave\310Eacute\311"
+            "Igrave\314Iacute\315Ntilde\321Ograve\322Oacute\323Otilde"
+            "\325Oslash\330Ugrave\331Uacute\332Yacute\335agrave\340"
+            "aacute\341atilde\343ccedil\347egrave\350eacute\351igrave"
+            "\354iacute\355ntilde\361ograve\362oacute\363otilde\365"
+            "oslash\370ugrave\371uacute\372yacute\375" /* 6 */
+    };
+
+    if (s) {
+        if (d) {
+            for (; *s != '\0' && slen; s++, d++, size++, slen--) {
+                if (*s != '&') {
+                    *d = *s;
+                    continue;
+                }
+                /* find end of entity */
+                for (i = 1; s[i] != ';' && s[i] != '\0' && (slen - i) != 0;
+                        i++) {
+                    continue;
+                }
+
+                if (s[i] == '\0' || (slen - i) == 0) { /* treat as normal data */
+                    *d = *s;
+                    continue;
+                }
+
+                /* is it numeric ? */
+                if (s[1] == '#') {
+                    for (j = 2, val = 0; j < i && apr_isdigit(s[j]); j++) {
+                        val = val * 10 + s[j] - '0';
+                    }
+                    s += i;
+                    if (j < i || val <= 8 || (val >= 11 && val <= 31)
+                            || (val >= 127 && val <= 160) || val >= 256) {
+                        d--; /* no data to output */
+                        size--;
+                    }
+                    else {
+                        *d = RAW_ASCII_CHAR(val);
+                        found = 1;
+                    }
+                }
+                else {
+                    j = i - 1;
+                    if (j > MAXENTLEN || entlist[j] == NULL) {
+                        /* wrong length */
+                        *d = '&';
+                        continue; /* skip it */
+                    }
+                    for (ents = entlist[j]; *ents != '\0'; ents += i) {
+                        if (strncmp(s + 1, ents, j) == 0) {
+                            break;
+                        }
+                    }
+
+                    if (*ents == '\0') {
+                        *d = '&'; /* unknown */
+                    }
+                    else {
+                        *d = RAW_ASCII_CHAR(((const unsigned char *) ents)[j]);
+                        s += i;
+                        slen -= i;
+                        found = 1;
+                    }
+                }
+            }
+            *d = '\0';
+        }
+        else {
+            for (; *s != '\0' && slen; s++, size++, slen--) {
+                if (*s != '&') {
+                    continue;
+                }
+                /* find end of entity */
+                for (i = 1; s[i] != ';' && s[i] != '\0' && (slen - i) != 0;
+                        i++) {
+                    continue;
+                }
+
+                if (s[i] == '\0' || (slen - i) == 0) { /* treat as normal data */
+                    continue;
+                }
+
+                /* is it numeric ? */
+                if (s[1] == '#') {
+                    for (j = 2, val = 0; j < i && apr_isdigit(s[j]); j++) {
+                        val = val * 10 + s[j] - '0';
+                    }
+                    s += i;
+                    if (j < i || val <= 8 || (val >= 11 && val <= 31)
+                            || (val >= 127 && val <= 160) || val >= 256) {
+                        /* no data to output */
+                        size--;
+                    }
+                    else {
+                        found = 1;
+                    }
+                }
+                else {
+                    j = i - 1;
+                    if (j > MAXENTLEN || entlist[j] == NULL) {
+                        /* wrong length */
+                        continue; /* skip it */
+                    }
+                    for (ents = entlist[j]; *ents != '\0'; ents += i) {
+                        if (strncmp(s + 1, ents, j) == 0) {
+                            break;
+                        }
+                    }
+
+                    if (*ents == '\0') {
+                        /* unknown */
+                    }
+                    else {
+                        s += i;
+                        slen -= i;
+                        found = 1;
+                    }
+                }
+            }
+        }
+    }
+
+    if (len) {
+        *len = size;
+    }
+    if (!found) {
+        return APR_NOTFOUND;
+    }
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(const char *) apr_punescape_entity(apr_pool_t *p, const char *str)
+{
+    apr_size_t len;
+
+    switch (apr_unescape_entity(NULL, str, APR_ESCAPE_STRING, &len)) {
+    case APR_SUCCESS: {
+        char *cmd = apr_palloc(p, len);
+        apr_unescape_entity(cmd, str, APR_ESCAPE_STRING, NULL);
+        return cmd;
+    }
+    case APR_NOTFOUND: {
+        break;
+    }
+    }
+
+    return str;
+}
+
+APR_DECLARE(apr_status_t) apr_escape_echo(char *escaped, const char *str,
+        apr_ssize_t slen, int quote, apr_size_t *len)
+{
+    apr_size_t size = 1;
+    int found = 0;
+    const unsigned char *s = (const unsigned char *) str;
+    unsigned char *d = (unsigned char *) escaped;
+    unsigned c;
+
+    if (s) {
+        if (d) {
+            while ((c = *s) && slen) {
+                if (TEST_CHAR(c, T_ESCAPE_ECHO)) {
+                    *d++ = '\\';
+                    size++;
+                    switch (c) {
+                    case '\a':
+                        *d++ = 'a';
+                        size++;
+                        found = 1;
+                        break;
+                    case '\b':
+                        *d++ = 'b';
+                        size++;
+                        found = 1;
+                        break;
+                    case '\f':
+                        *d++ = 'f';
+                        size++;
+                        found = 1;
+                        break;
+                    case '\n':
+                        *d++ = 'n';
+                        size++;
+                        found = 1;
+                        break;
+                    case '\r':
+                        *d++ = 'r';
+                        size++;
+                        found = 1;
+                        break;
+                    case '\t':
+                        *d++ = 't';
+                        size++;
+                        found = 1;
+                        break;
+                    case '\v':
+                        *d++ = 'v';
+                        size++;
+                        found = 1;
+                        break;
+                    case '\\':
+                        *d++ = '\\';
+                        size++;
+                        found = 1;
+                        break;
+                    case '"':
+                        if (quote) {
+                            *d++ = c;
+                            size++;
+                            found = 1;
+                        }
+                        else {
+                            d[-1] = c;
+                        }
+                        break;
+                    default:
+                        c2x(c, 'x', d);
+                        d += 3;
+                        size += 3;
+                        found = 1;
+                        break;
+                    }
+                }
+                else {
+                    *d++ = c;
+                    size++;
+                }
+                ++s;
+                slen--;
+            }
+            *d = '\0';
+        }
+        else {
+            while ((c = *s) && slen) {
+                if (TEST_CHAR(c, T_ESCAPE_ECHO)) {
+                    size++;
+                    switch (c) {
+                    case '\a':
+                    case '\b':
+                    case '\f':
+                    case '\n':
+                    case '\r':
+                    case '\t':
+                    case '\v':
+                    case '\\':
+                        size++;
+                        found = 1;
+                        break;
+                    case '"':
+                        if (quote) {
+                            size++;
+                            found = 1;
+                        }
+                        break;
+                    default:
+                        size += 3;
+                        found = 1;
+                        break;
+                    }
+                }
+                else {
+                    size++;
+                }
+                ++s;
+                slen--;
+            }
+        }
+    }
+
+    if (len) {
+        *len = size;
+    }
+    if (!found) {
+        return APR_NOTFOUND;
+    }
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(const char *) apr_pescape_echo(apr_pool_t *p, const char *str,
+        int quote)
+{
+    apr_size_t len;
+
+    switch (apr_escape_echo(NULL, str, APR_ESCAPE_STRING, quote, &len)) {
+    case APR_SUCCESS: {
+        char *cmd = apr_palloc(p, len);
+        apr_escape_echo(cmd, str, APR_ESCAPE_STRING, quote, NULL);
+        return cmd;
+    }
+    case APR_NOTFOUND: {
+        break;
+    }
+    }
+
+    return str;
+}
+
+APR_DECLARE(apr_status_t) apr_escape_hex(char *dest, const void *src,
+        apr_size_t srclen, int colon, apr_size_t *len)
+{
+    const unsigned char *in = src;
+    apr_size_t size;
+
+    if (!src) {
+        return APR_NOTFOUND;
+    }
+
+    if (dest) {
+        for (size = 0; size < srclen; size++) {
+            if (colon && size) {
+                *dest++ = ':';
+            }
+            *dest++ = c2x_table[in[size] >> 4];
+            *dest++ = c2x_table[in[size] & 0xf];
+        }
+        *dest = '\0';
+    }
+
+    if (len) {
+        if (colon && srclen) {
+            *len = srclen * 3;
+        }
+        else {
+            *len = srclen * 2 + 1;
+        }
+    }
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(const char *) apr_pescape_hex(apr_pool_t *p, const void *src,
+        apr_size_t srclen, int colon)
+{
+    apr_size_t len;
+
+    switch (apr_escape_hex(NULL, src, srclen, colon, &len)) {
+    case APR_SUCCESS: {
+        char *cmd = apr_palloc(p, len);
+        apr_escape_hex(cmd, src, srclen, colon, NULL);
+        return cmd;
+    }
+    case APR_NOTFOUND: {
+        break;
+    }
+    }
+
+    return src;
+}
+
+APR_DECLARE(apr_status_t) apr_unescape_hex(void *dest, const char *str,
+        apr_ssize_t slen, int colon, apr_size_t *len)
+{
+    apr_size_t size = 0;
+    int flip = 0;
+    const unsigned char *s = (const unsigned char *) str;
+    unsigned char *d = (unsigned char *) dest;
+    unsigned c;
+    unsigned char u = 0;
+
+    if (s) {
+        if (d) {
+            while ((c = *s) && slen) {
+
+                if (!flip) {
+                    u = 0;
+                }
+
+                if (colon && c == ':' && !flip) {
+                    ++s;
+                    slen--;
+                    continue;
+                }
+                else if (apr_isdigit(c)) {
+                    u |= c - '0';
+                }
+                else if (apr_isupper(c) && c <= 'F') {
+                    u |= c - ('A' - 10);
+                }
+                else if (apr_islower(c) && c <= 'f') {
+                    u |= c - ('a' - 10);
+                }
+                else {
+                    return APR_BADCH;
+                }
+
+                if (flip) {
+                    *d++ = u;
+                    size++;
+                }
+                else {
+                    u <<= 4;
+                    *d = u;
+                }
+                flip = !flip;
+
+                ++s;
+                slen--;
+            }
+        }
+        else {
+            while ((c = *s) && slen) {
+
+                if (colon && c == ':' && !flip) {
+                    ++s;
+                    slen--;
+                    continue;
+                }
+                else if (apr_isdigit(c)) {
+                    /* valid */
+                }
+                else if (apr_isupper(c) && c <= 'F') {
+                    /* valid */
+                }
+                else if (apr_islower(c) && c <= 'f') {
+                    /* valid */
+                }
+                else {
+                    return APR_BADCH;
+                }
+
+                if (flip) {
+                    size++;
+                }
+                flip = !flip;
+
+                ++s;
+                slen--;
+            }
+        }
+    }
+
+    if (len) {
+        *len = size;
+    }
+    if (!s) {
+        return APR_NOTFOUND;
+    }
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(const void *) apr_punescape_hex(apr_pool_t *p, const char *str,
+        int colon, apr_size_t *len)
+{
+    apr_size_t size;
+
+    switch (apr_unescape_hex(NULL, str, APR_ESCAPE_STRING, colon, &size)) {
+    case APR_SUCCESS: {
+        void *cmd = apr_palloc(p, size);
+        apr_unescape_hex(cmd, str, APR_ESCAPE_STRING, colon, len);
+        return cmd;
+    }
+    case APR_BADCH:
+    case APR_NOTFOUND: {
+        break;
+    }
+    }
+
+    return NULL;
+}
+
+APR_DECLARE(apr_status_t) apr_escape_ldap(char *escaped, const void *str,
+        apr_ssize_t slen, int flags, apr_size_t *len)
+{
+    apr_size_t size = 1;
+    int found = 0;
+    const unsigned char *s = (const unsigned char *) str;
+    unsigned char *d = (unsigned char *) escaped;
+    unsigned c;
+
+    if (s) {
+        if (d) {
+            while (((c = *s) && slen) || (slen > 0)) {
+                if (((flags & APR_ESCAPE_LDAP_DN) && TEST_CHAR(c, T_ESCAPE_LDAP_DN))
+                     || ((flags & APR_ESCAPE_LDAP_FILTER) && TEST_CHAR(c, T_ESCAPE_LDAP_FILTER))) {
+                    d = c2x(c, '\\', d);
+                    size += 2;
+                    found = 1;
+                }
+                else {
+                    *d++ = c;
+                }
+                ++s;
+                size++;
+                slen--;
+            }
+            *d = '\0';
+        }
+        else {
+            while (((c = *s) && slen) || (slen > 0)) {
+                if (((flags & APR_ESCAPE_LDAP_DN) && TEST_CHAR(c, T_ESCAPE_LDAP_DN)) 
+                     || ((flags & APR_ESCAPE_LDAP_FILTER) && TEST_CHAR(c, T_ESCAPE_LDAP_FILTER))) {
+                    size += 2;
+                    found = 1;
+                }
+                ++s;
+                size++;
+                slen--;
+            }
+        }
+    }
+
+    if (len) {
+        *len = size;
+    }
+    if (!found) {
+        return APR_NOTFOUND;
+    }
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(const char *) apr_pescape_ldap(apr_pool_t *p, const void *src,
+        apr_ssize_t srclen, int flags)
+{
+    apr_size_t len;
+
+    switch (apr_escape_ldap(NULL, src, srclen, flags, &len)) {
+    case APR_SUCCESS: {
+        char *encoded = apr_palloc(p, len);
+        apr_escape_ldap(encoded, src, srclen, flags, NULL);
+        return encoded;
+    }
+    case APR_NOTFOUND: {
+        break;
+    }
+    }
+
+    return src;
+}
+
diff --git a/file_io/beos/Makefile.in b/file_io/beos/Makefile.in
deleted file mode 100644
index c06254b2da1..00000000000
--- a/file_io/beos/Makefile.in
+++ /dev/null
@@ -1,63 +0,0 @@
-#CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
-#LIBS=$(EXTRA_LIBS) $(LIBS1)
-#INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
-#LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
-
-RM=@RM@
-CC=@CC@
-RANLIB=@RANLIB@
-CFLAGS=@CFLAGS@ @OPTIM@
-LIBS=@LIBS@
-LDFLAGS=@LDFLAGS@ $(LIBS)
-INCDIR=../../include -I../unix
-INCLUDES=-I$(INCDIR) -I.
-
-LIB=libfile.a
-
-OBJS=file_io_common.o 	readwrite.o
-
-.c.o:
-	$(CC) $(CFLAGS) -c $(INCLUDES) $<
-
-all: $(LIB)
-
-clean:
-	$(RM) -f *.o *.a *.so
-
-distclean: clean
-	-$(RM) -f Makefile
-
-$(OBJS): Makefile
-
-$(LIB): $(OBJS)
-	$(RM) -f $@
-	$(AR) cr $@ $(OBJS)
-	$(RANLIB) $@
-
-#
-# We really don't expect end users to use this rule.  It works only with
-# gcc, and rebuilds Makefile.tmpl.  You have to re-run Configure after
-# using it.
-#
-depend:
-	cp Makefile.in Makefile.in.bak \
-	    && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.in > Makefile.new \
-	    && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \
-	    && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
-	           -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
-		> Makefile.in \
-	    && rm Makefile.new
-
-# DO NOT REMOVE
-file_io_common.o: file_io_common.c ../unix/dir.c ../unix/fileio.h \
- ../../include/apr_private.h ../../include/apr_general.h \
- ../../include/apr.h ../../include/apr_errno.h \
- ../../include/apr_file_io.h ../../include/apr_lib.h \
- ../../include/apr_portable.h ../../include/apr_thread_proc.h \
- ../../include/apr_network_io.h ../../include/apr_lock.h \
- ../../include/apr_time.h ../unix/fileacc.c ../unix/filedup.c \
- ../unix/filestat.c ../unix/open.c ../unix/pipe.c ../unix/seek.c
-readwrite.o: readwrite.c ../unix/fileio.h ../../include/apr_private.h \
- ../../include/apr_general.h ../../include/apr.h \
- ../../include/apr_errno.h ../../include/apr_file_io.h \
- ../../include/apr_lib.h
diff --git a/file_io/beos/file_io_common.c b/file_io/beos/file_io_common.c
deleted file mode 100644
index 63ffac03e9d..00000000000
--- a/file_io/beos/file_io_common.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-/* common.c */
-
-/* The code used in readwrite.c in the Unix directory won't work on
-   BeOS so I've moved to using a common.c file for all the common
-   code. */
-   
-#include "../unix/dir.c"
-
-#include "../unix/fileacc.c"
-
-#include "../unix/filedup.c"
-
-#include "../unix/filestat.c"
-
-#include "../unix/open.c"
-
-#include "../unix/pipe.c"
-
-#include "../unix/seek.c"
diff --git a/file_io/beos/readwrite.c b/file_io/beos/readwrite.c
deleted file mode 100644
index 96aaf5247db..00000000000
--- a/file_io/beos/readwrite.c
+++ /dev/null
@@ -1,334 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "../unix/fileio.h"
-
-ap_status_t ap_read(ap_file_t *thefile, void *buf, ap_ssize_t *nbytes)
-{
-    ap_ssize_t rv;
-    ap_ssize_t bytes_read;
-
-    if(*nbytes <= 0) {
-        *nbytes = 0;
-        return APR_SUCCESS;
-    }
-
-    if (thefile->buffered) {
-        char *pos = (char *)buf;
-        ap_uint64_t blocksize;
-        ap_uint64_t size = *nbytes;
-
-        ap_lock(thefile->thlock);
-
-        if (thefile->direction == 1) {
-            ap_flush(thefile);
-            thefile->bufpos = 0;
-            thefile->direction = 0;
-            thefile->dataRead = 0;
-        }
-
-        rv = 0;
-        while (rv == 0 && size > 0) {
-            if (thefile->bufpos >= thefile->dataRead) {
-                thefile->dataRead = read(thefile->filedes, thefile->buffer, APR_FILE_BUFSIZE);
-                if (thefile->dataRead == 0) {
-                    thefile->eof_hit = TRUE;
-                    break;
-                }
-                thefile->filePtr += thefile->dataRead;
-                thefile->bufpos = 0;
-            }
-
-            blocksize = size > thefile->dataRead - thefile->bufpos ? thefile->dataRead - thefile->bufpos : size;                                                            memcpy(pos, thefile->buffer + thefile->bufpos, blocksize);
-            thefile->bufpos += blocksize;
-            pos += blocksize;
-            size -= blocksize;
-        }
-
-        *nbytes = rv == 0 ? pos - (char *)buf : 0;
-        ap_unlock(thefile->thlock);
-        return rv;
-    }
-    else {
-        bytes_read = 0;
-        if (thefile->ungetchar != -1) {
-            bytes_read = 1;
-            *(char *)buf = (char)thefile->ungetchar;
-            buf = (char *)buf + 1;
-            (*nbytes)--;
-            thefile->ungetchar = -1;
-            if (*nbytes == 0) {
-	            *nbytes = bytes_read;
-	            return APR_SUCCESS;
-            }
-        }
-        do {
-            rv = read(thefile->filedes, buf, *nbytes);
-        } while (rv == -1 && errno == EINTR);
-        *nbytes = bytes_read;
-        if (rv == 0) {
-            return APR_EOF;
-        }
-        if (rv > 0) {
-            *nbytes += rv;
-            return APR_SUCCESS;
-        }
-        return errno;
-    }
-}
-
-ap_status_t ap_write(ap_file_t *thefile, void *buf, ap_ssize_t *nbytes)
-{
-    ap_size_t rv;
-    
-    if (thefile->buffered) {
-        char *pos = (char *)buf;
-        int blocksize;
-        int size = *nbytes;
-
-        ap_lock(thefile->thlock);
-
-        if ( thefile->direction == 0 ) {
-            /* Position file pointer for writing at the offset we are 
-             * logically reading from
-             */
-            ap_int64_t offset = thefile->filePtr - thefile->dataRead + thefile->bufpos;
-            if (offset != thefile->filePtr)
-                lseek(thefile->filedes, offset, SEEK_SET);
-            thefile->bufpos = thefile->dataRead = 0;
-            thefile->direction = 1;
-        }
-
-        rv = 0;
-        while (rv == 0 && size > 0) {
-            if (thefile->bufpos == APR_FILE_BUFSIZE)   /* write buffer is full*/
-                ap_flush(thefile);
-
-            blocksize = size > APR_FILE_BUFSIZE - thefile->bufpos ? 
-                        APR_FILE_BUFSIZE - thefile->bufpos : size;
-            memcpy(thefile->buffer + thefile->bufpos, pos, blocksize);                      thefile->bufpos += blocksize;
-            pos += blocksize;
-            size -= blocksize;
-        }
-
-        ap_unlock(thefile->thlock);
-        return rv;
-    }
-    else {
-        do {
-            rv = write(thefile->filedes, buf, *nbytes);
-        } while (rv == (ap_size_t)-1 && errno == EINTR);
-
-        if (rv == (ap_size_t)-1) {
-            (*nbytes) = 0;
-            return errno;
-        }
-        *nbytes = rv;
-        return APR_SUCCESS;
-    }
-}
-
-ap_status_t ap_writev(ap_file_t *thefile, const struct iovec *vec, 
-                      ap_size_t nvec, ap_ssize_t *nbytes)
-{
-    int bytes;
-
-    if ((bytes = writev(thefile->filedes, vec, nvec)) < 0) {
-        *nbytes = 0;
-        return errno;
-    }
-    else {
-        *nbytes = bytes;
-        return APR_SUCCESS;
-    }
-}
-
-ap_status_t ap_putc(char ch, ap_file_t *thefile)
-{
-    if (write(thefile->filedes, &ch, 1) != 1) {
-        return errno;
-    }
-    return APR_SUCCESS; 
-}
-
-ap_status_t ap_ungetc(char ch, ap_file_t *thefile)
-{
-    thefile->ungetchar = (unsigned char)ch;
-    return APR_SUCCESS; 
-}
-
-ap_status_t ap_getc(char *ch, ap_file_t *thefile)
-{
-    ssize_t rv;
-    
-    if (thefile->ungetchar != -1) {
-        *ch = (char) thefile->ungetchar;
-        thefile->ungetchar = -1;
-        return APR_SUCCESS;
-    }
-    rv = read(thefile->filedes, ch, 1); 
-    if (rv == 0) {
-        thefile->eof_hit = TRUE;
-        return APR_EOF;
-    }
-    else if (rv != 1) {
-        return errno;
-    }
-    return APR_SUCCESS; 
-}
-
-ap_status_t ap_puts(char *str, ap_file_t *thefile)
-{
-    ssize_t rv;
-    int len;
-
-    len = strlen(str);
-    rv = write(thefile->filedes, str, len); 
-    if (rv != len) {
-        return errno;
-    }
-    return APR_SUCCESS; 
-}
-
-ap_status_t ap_flush(ap_file_t *thefile)
-{
-    if (thefile->buffered) {
-        ap_int64_t written = 0;
-        int rc = 0;
-
-        if (thefile->direction == 1 && thefile->bufpos) {
-            written= write(thefile->filedes, thefile->buffer, thefile->bufpos);
-            thefile->filePtr += written;
-
-            if (rc == 0)
-                thefile->bufpos = 0;
-        }
-
-        return rc;
-    }
-    /* There isn't anything to do if we aren't buffering the output
-     * so just return success.
-     */
-    return APR_SUCCESS; 
-}
-
-ap_status_t ap_fgets(char *str, int len, ap_file_t *thefile)
-{
-    ssize_t rv;
-    int i, used_unget = FALSE, beg_idx;
-
-    if(len <= 1)  /* as per fgets() */
-        return APR_SUCCESS;
-
-    if(thefile->ungetchar != -1){
-        str[0] = thefile->ungetchar;
-	used_unget = TRUE;
-	beg_idx = 1;
-	if(str[0] == '\n' || str[0] == '\r'){
-	    thefile->ungetchar = -1;
-	    str[1] = '\0';
-	    return APR_SUCCESS;
-	}
-    } else
-        beg_idx = 0;
-    
-    for (i = beg_idx; i < len; i++) {
-        rv = read(thefile->filedes, &str[i], 1); 
-        if (rv == 0) {
-            thefile->eof_hit = TRUE;
-	    if(used_unget) thefile->filedes = -1;
-	    str[i] = '\0';
-            return APR_EOF;
-        }
-        else if (rv != 1) {
-            return errno;
-        }
-        if (str[i] == '\n' || str[i] == '\r')
-            break;
-    }
-    if (i < len-1)
-        str[i+1] = '\0';
-    return APR_SUCCESS; 
-}
-
-#if 0 /* not currently used */
-static int printf_flush(ap_vformatter_buff_t *vbuff)
-{
-    /* I would love to print this stuff out to the file, but I will
-     * get that working later.  :)  For now, just return.
-     */
-    return -1;
-}
-#endif
-
-API_EXPORT(int) ap_fprintf(ap_file_t *fptr, const char *format, ...)
-{
-    int cc;
-    va_list ap;
-    char *buf;
-    int len;
-
-    buf = malloc(HUGE_STRING_LEN);
-    if (buf == NULL) {
-        return 0;
-    }
-    va_start(ap, format);
-    len = ap_vsnprintf(buf, HUGE_STRING_LEN, format, ap);
-    cc = ap_puts(buf, fptr);
-    va_end(ap);
-    free(buf);
-    return (cc == APR_SUCCESS) ? len : -1;
-}
-
-
diff --git a/file_io/netware/filestat.c b/file_io/netware/filestat.c
new file mode 100644
index 00000000000..85d73c30d13
--- /dev/null
+++ b/file_io/netware/filestat.c
@@ -0,0 +1,417 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_arch_file_io.h"
+#include "fsio.h"
+#include "nks/dirio.h"
+#include "apr_file_io.h"
+#include "apr_general.h"
+#include "apr_strings.h"
+#include "apr_errno.h"
+#include "apr_hash.h"
+#include "apr_thread_rwlock.h"
+
+#ifdef HAVE_UTIME_H
+#include <utime.h>
+#endif
+
+#define APR_HAS_PSA
+
+static apr_filetype_e filetype_from_mode(mode_t mode)
+{
+    apr_filetype_e type = APR_NOFILE;
+
+    if (S_ISREG(mode))
+        type = APR_REG;
+    else if (S_ISDIR(mode))
+        type = APR_DIR;
+    else if (S_ISCHR(mode))
+        type = APR_CHR;
+    else if (S_ISBLK(mode))
+        type = APR_BLK;
+    else if (S_ISFIFO(mode))
+        type = APR_PIPE;
+    else if (S_ISLNK(mode))
+        type = APR_LNK;
+    else if (S_ISSOCK(mode))
+        type = APR_SOCK;
+    else
+        type = APR_UNKFILE;
+    return type;
+}
+
+static void fill_out_finfo(apr_finfo_t *finfo, struct stat *info,
+                           apr_int32_t wanted)
+{ 
+    finfo->valid = APR_FINFO_MIN | APR_FINFO_IDENT | APR_FINFO_NLINK 
+                    | APR_FINFO_OWNER | APR_FINFO_PROT;
+
+    finfo->protection = apr_unix_mode2perms(info->st_mode);
+    finfo->filetype = filetype_from_mode(info->st_mode);
+    finfo->user = info->st_uid;
+    finfo->group = info->st_gid;
+    finfo->size = info->st_size;
+    finfo->inode = info->st_ino;
+    finfo->device = info->st_dev;
+    finfo->nlink = info->st_nlink;
+
+    apr_time_ansi_put(&finfo->atime, info->st_atime.tv_sec);
+    apr_time_ansi_put(&finfo->mtime, info->st_mtime.tv_sec);
+    apr_time_ansi_put(&finfo->ctime, info->st_ctime.tv_sec);
+
+#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
+#ifdef DEV_BSIZE
+    finfo->csize = (apr_off_t)info->st_blocks * (apr_off_t)DEV_BSIZE;
+#else
+    finfo->csize = (apr_off_t)info->st_blocks * (apr_off_t)512;
+#endif
+    finfo->valid |= APR_FINFO_CSIZE;
+#endif
+}
+
+apr_status_t apr_file_info_get_locked(apr_finfo_t *finfo, apr_int32_t wanted,
+                                      apr_file_t *thefile)
+{
+    struct_stat info;
+
+    if (thefile->buffered) {
+        apr_status_t rv = apr_file_flush_locked(thefile);
+        if (rv != APR_SUCCESS)
+            return rv;
+    }
+
+    if (fstat(thefile->filedes, &info) == 0) {
+        finfo->pool = thefile->pool;
+        finfo->fname = thefile->fname;
+        fill_out_finfo(finfo, &info, wanted);
+        return (wanted & ~finfo->valid) ? APR_INCOMPLETE : APR_SUCCESS;
+    }
+    else {
+        return errno;
+    }
+}
+
+APR_DECLARE(apr_status_t) apr_file_info_get(apr_finfo_t *finfo, 
+                                            apr_int32_t wanted,
+                                            apr_file_t *thefile)
+{
+    struct stat info;
+
+    if (thefile->buffered) {
+        /* XXX: flush here is not mutex protected */
+        apr_status_t rv = apr_file_flush(thefile);
+        if (rv != APR_SUCCESS)
+            return rv;
+    }
+
+    if (fstat(thefile->filedes, &info) == 0) {
+        finfo->pool = thefile->pool;
+        finfo->fname = thefile->fname;
+        fill_out_finfo(finfo, &info, wanted);
+        return (wanted & ~finfo->valid) ? APR_INCOMPLETE : APR_SUCCESS;
+    }
+    else {
+        return errno;
+    }
+}
+
+APR_DECLARE(apr_status_t) apr_file_perms_set(const char *fname, 
+                                             apr_fileperms_t perms)
+{
+    mode_t mode = apr_unix_perms2mode(perms);
+
+    if (chmod(fname, mode) == -1)
+        return errno;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_file_attrs_set(const char *fname,
+                                             apr_fileattrs_t attributes,
+                                             apr_fileattrs_t attr_mask,
+                                             apr_pool_t *pool)
+{
+    apr_status_t status;
+    apr_finfo_t finfo;
+
+    /* Don't do anything if we can't handle the requested attributes */
+    if (!(attr_mask & (APR_FILE_ATTR_READONLY
+                       | APR_FILE_ATTR_EXECUTABLE)))
+        return APR_SUCCESS;
+
+    status = apr_stat(&finfo, fname, APR_FINFO_PROT, pool);
+    if (status)
+        return status;
+
+    /* ### TODO: should added bits be umask'd? */
+    if (attr_mask & APR_FILE_ATTR_READONLY)
+    {
+        if (attributes & APR_FILE_ATTR_READONLY)
+        {
+            finfo.protection &= ~APR_FPROT_UWRITE;
+            finfo.protection &= ~APR_FPROT_GWRITE;
+            finfo.protection &= ~APR_FPROT_WWRITE;
+        }
+        else
+        {
+            /* ### umask this! */
+            finfo.protection |= APR_FPROT_UWRITE;
+            finfo.protection |= APR_FPROT_GWRITE;
+            finfo.protection |= APR_FPROT_WWRITE;
+        }
+    }
+
+    if (attr_mask & APR_FILE_ATTR_EXECUTABLE)
+    {
+        if (attributes & APR_FILE_ATTR_EXECUTABLE)
+        {
+            /* ### umask this! */
+            finfo.protection |= APR_FPROT_UEXECUTE;
+            finfo.protection |= APR_FPROT_GEXECUTE;
+            finfo.protection |= APR_FPROT_WEXECUTE;
+        }
+        else
+        {
+            finfo.protection &= ~APR_FPROT_UEXECUTE;
+            finfo.protection &= ~APR_FPROT_GEXECUTE;
+            finfo.protection &= ~APR_FPROT_WEXECUTE;
+        }
+    }
+
+    return apr_file_perms_set(fname, finfo.protection);
+}
+
+#ifndef APR_HAS_PSA
+static apr_status_t stat_cache_cleanup(void *data)
+{
+    apr_pool_t *p = (apr_pool_t *)getGlobalPool();
+    apr_hash_index_t *hi;
+    apr_hash_t *statCache = (apr_hash_t*)data;
+	char *key;
+    apr_ssize_t keylen;
+    NXPathCtx_t pathctx;
+
+    for (hi = apr_hash_first(p, statCache); hi; hi = apr_hash_next(hi)) {
+        apr_hash_this(hi, (const void**)&key, &keylen, (void**)&pathctx);
+
+        if (pathctx) {
+            NXFreePathContext(pathctx);
+        }
+    }
+
+    return APR_SUCCESS;
+}
+
+int cstat (NXPathCtx_t ctx, char *path, struct stat *buf, unsigned long requestmap, apr_pool_t *p)
+{
+    apr_pool_t *gPool = (apr_pool_t *)getGlobalPool();
+    apr_hash_t *statCache = NULL;
+    apr_thread_rwlock_t *rwlock = NULL;
+
+    NXPathCtx_t pathctx = 0;
+    char *ptr = NULL, *tr;
+    int len = 0, x;
+    char *ppath;
+    char *pinfo;
+
+    if (ctx == 1) {
+
+        /* If there isn't a global pool then just stat the file
+           and return */
+        if (!gPool) {
+            char poolname[50];
+    
+            if (apr_pool_create(&gPool, NULL) != APR_SUCCESS) {
+                return getstat(ctx, path, buf, requestmap);
+            }
+    
+            setGlobalPool(gPool);
+            apr_pool_tag(gPool, apr_pstrdup(gPool, "cstat_mem_pool"));
+    
+            statCache = apr_hash_make(gPool);
+            apr_pool_userdata_set ((void*)statCache, "STAT_CACHE", stat_cache_cleanup, gPool);
+
+            apr_thread_rwlock_create(&rwlock, gPool);
+            apr_pool_userdata_set ((void*)rwlock, "STAT_CACHE_LOCK", apr_pool_cleanup_null, gPool);
+        }
+        else {
+            apr_pool_userdata_get((void**)&statCache, "STAT_CACHE", gPool);
+            apr_pool_userdata_get((void**)&rwlock, "STAT_CACHE_LOCK", gPool);
+        }
+
+        if (!gPool || !statCache || !rwlock) {
+            return getstat(ctx, path, buf, requestmap);
+        }
+    
+        for (x = 0,tr = path;*tr != '\0';tr++,x++) {
+            if (*tr == '\\' || *tr == '/') {
+                ptr = tr;
+                len = x;
+            }
+            if (*tr == ':') {
+                ptr = "\\";
+                len = x;
+            }
+        }
+    
+        if (ptr) {
+            ppath = apr_pstrndup (p, path, len);
+            strlwr(ppath);
+            if (ptr[1] != '\0') {
+                ptr++;
+            }
+            /* If the path ended in a trailing slash then our result path
+               will be a single slash. To avoid stat'ing the root with a
+               slash, we need to make sure we stat the current directory
+               with a dot */
+            if (((*ptr == '/') || (*ptr == '\\')) && (*(ptr+1) == '\0')) {
+                pinfo = apr_pstrdup (p, ".");
+            }
+            else {
+                pinfo = apr_pstrdup (p, ptr);
+            }
+        }
+    
+        /* If we have a statCache then try to pull the information
+           from the cache.  Otherwise just stat the file and return.*/
+        if (statCache) {
+            apr_thread_rwlock_rdlock(rwlock);
+            pathctx = (NXPathCtx_t) apr_hash_get(statCache, ppath, APR_HASH_KEY_STRING);
+            apr_thread_rwlock_unlock(rwlock);
+            if (pathctx) {
+                return getstat(pathctx, pinfo, buf, requestmap);
+            }
+            else {
+                int err;
+
+                err = NXCreatePathContext(0, ppath, 0, NULL, &pathctx);
+                if (!err) {
+                    apr_thread_rwlock_wrlock(rwlock);
+                    apr_hash_set(statCache, apr_pstrdup(gPool,ppath) , APR_HASH_KEY_STRING, (void*)pathctx);
+                    apr_thread_rwlock_unlock(rwlock);
+                    return getstat(pathctx, pinfo, buf, requestmap);
+                }
+            }
+        }
+    }
+    return getstat(ctx, path, buf, requestmap);
+}
+#endif
+
+APR_DECLARE(apr_status_t) apr_stat(apr_finfo_t *finfo, 
+                                   const char *fname, 
+                                   apr_int32_t wanted, apr_pool_t *pool)
+{
+    struct stat info;
+    int srv;
+    NXPathCtx_t pathCtx = 0;
+
+    getcwdpath(NULL, &pathCtx, CTX_ACTUAL_CWD);
+#ifdef APR_HAS_PSA
+	srv = getstat(pathCtx, (char*)fname, &info, ST_STAT_BITS|ST_NAME_BIT);
+#else
+    srv = cstat(pathCtx, (char*)fname, &info, ST_STAT_BITS|ST_NAME_BIT, pool);
+#endif
+    errno = srv;
+
+    if (srv == 0) {
+        finfo->pool = pool;
+        finfo->fname = fname;
+        fill_out_finfo(finfo, &info, wanted);
+        if (wanted & APR_FINFO_LINK)
+            wanted &= ~APR_FINFO_LINK;
+        if (wanted & APR_FINFO_NAME) {
+            finfo->name = apr_pstrdup(pool, info.st_name);
+            finfo->valid |= APR_FINFO_NAME;
+        }
+        return (wanted & ~finfo->valid) ? APR_INCOMPLETE : APR_SUCCESS;
+    }
+    else {
+#if !defined(ENOENT) || !defined(ENOTDIR)
+#error ENOENT || ENOTDIR not defined; please see the
+#error comments at this line in the source for a workaround.
+        /*
+         * If ENOENT || ENOTDIR is not defined in one of the your OS's
+         * include files, APR cannot report a good reason why the stat()
+         * of the file failed; there are cases where it can fail even though
+         * the file exists.  This opens holes in Apache, for example, because
+         * it becomes possible for someone to get a directory listing of a 
+         * directory even though there is an index (eg. index.html) file in 
+         * it.  If you do not have a problem with this, delete the above 
+         * #error lines and start the compile again.  If you need to do this,
+         * please submit a bug report to http://www.apache.org/bug_report.html
+         * letting us know that you needed to do this.  Please be sure to 
+         * include the operating system you are using.
+         */
+        /* WARNING: All errors will be handled as not found
+         */
+#if !defined(ENOENT) 
+        return APR_ENOENT;
+#else
+        /* WARNING: All errors but not found will be handled as not directory
+         */
+        if (errno != ENOENT)
+            return APR_ENOENT;
+        else
+            return errno;
+#endif
+#else /* All was defined well, report the usual: */
+        return errno;
+#endif
+    }
+}
+
+APR_DECLARE(apr_status_t) apr_file_mtime_set(const char *fname,
+                                              apr_time_t mtime,
+                                              apr_pool_t *pool)
+{
+    apr_status_t status;
+    apr_finfo_t finfo;
+
+    status = apr_stat(&finfo, fname, APR_FINFO_ATIME, pool);
+    if (status) {
+        return status;
+    }
+
+#ifdef HAVE_UTIMES
+    {
+      struct timeval tvp[2];
+    
+      tvp[0].tv_sec = apr_time_sec(finfo.atime);
+      tvp[0].tv_usec = apr_time_usec(finfo.atime);
+      tvp[1].tv_sec = apr_time_sec(mtime);
+      tvp[1].tv_usec = apr_time_usec(mtime);
+      
+      if (utimes(fname, tvp) == -1) {
+        return errno;
+      }
+    }
+#elif defined(HAVE_UTIME)
+    {
+      struct utimbuf buf;
+      
+      buf.actime = (time_t) (finfo.atime / APR_USEC_PER_SEC);
+      buf.modtime = (time_t) (mtime / APR_USEC_PER_SEC);
+      
+      if (utime(fname, &buf) == -1) {
+        return errno;
+      }
+    }
+#else
+    return APR_ENOTIMPL;
+#endif
+
+    return APR_SUCCESS;
+}
diff --git a/file_io/netware/filesys.c b/file_io/netware/filesys.c
new file mode 100644
index 00000000000..05c44cecd57
--- /dev/null
+++ b/file_io/netware/filesys.c
@@ -0,0 +1,106 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_arch_file_io.h"
+#include "apr_strings.h"
+
+apr_status_t filepath_root_case(char **rootpath, char *root, apr_pool_t *p)
+{
+/* See the Windows code to figure out what to do here.
+    It probably checks to make sure that the root exists 
+    and case it correctly according to the file system.
+*/
+    *rootpath = apr_pstrdup(p, root);
+    return APR_SUCCESS;
+}
+
+apr_status_t filepath_has_drive(const char *rootpath, int only, apr_pool_t *p)
+{
+    char *s;
+
+    if (rootpath) {
+        s = strchr (rootpath, ':');
+        if (only)
+            /* Test if the path only has a drive/volume and nothing else
+            */
+            return (s && (s != rootpath) && !s[1]);
+        else
+            /* Test if the path includes a drive/volume
+            */
+            return (s && (s != rootpath));
+    }
+    return 0;
+}
+
+apr_status_t filepath_compare_drive(const char *path1, const char *path2, apr_pool_t *p)
+{
+    char *s1, *s2;
+
+    if (path1 && path2) {
+        s1 = strchr (path1, ':');
+        s2 = strchr (path2, ':');
+
+        /* Make sure that they both have a drive/volume delimiter
+            and are the same size.  Then see if they match.
+        */
+        if (s1 && s2 && ((s1-path1) == (s2-path2))) {
+            return strnicmp (s1, s2, s1-path1);
+        }
+    }
+    return -1;
+}
+
+APR_DECLARE(apr_status_t) apr_filepath_get(char **rootpath, apr_int32_t flags,
+                                           apr_pool_t *p)
+{
+    char path[APR_PATH_MAX];
+    char *ptr;
+
+    /* use getcwdpath to make sure that we get the volume name*/
+    if (!getcwdpath(path, NULL, 0)) {
+        if (errno == ERANGE)
+            return APR_ENAMETOOLONG;
+        else
+            return errno;
+    }
+    /* Strip off the server name if there is one*/
+    ptr = strpbrk(path, "\\/:");
+    if (!ptr) {
+        return APR_ENOENT;
+    }
+    if (*ptr == ':') {
+        ptr = path;
+    }
+    *rootpath = apr_pstrdup(p, ptr);
+    if (!(flags & APR_FILEPATH_NATIVE)) {
+        for (ptr = *rootpath; *ptr; ++ptr) {
+            if (*ptr == '\\')
+                *ptr = '/';
+        }
+    }
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_filepath_set(const char *rootpath,
+                                           apr_pool_t *p)
+{
+    if (chdir2(rootpath) != 0)
+        return errno;
+    return APR_SUCCESS;
+}
+
+
diff --git a/file_io/netware/flock.c b/file_io/netware/flock.c
new file mode 100644
index 00000000000..c083a0ed401
--- /dev/null
+++ b/file_io/netware/flock.c
@@ -0,0 +1,39 @@
+/* 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 <nks/fsio.h>
+#include "apr_arch_file_io.h"
+
+
+apr_status_t apr_file_lock(apr_file_t *thefile, int type)
+{
+	int fc;
+
+	fc = (type & APR_FLOCK_NONBLOCK) ? NX_RANGE_LOCK_TRYLOCK : NX_RANGE_LOCK_CHECK;
+
+    if(NXFileRangeLock(thefile->filedes,fc, 0, 0) == -1)
+		return errno;
+            
+    return APR_SUCCESS;
+}
+
+apr_status_t apr_file_unlock(apr_file_t *thefile)
+{
+    if(NXFileRangeUnlock(thefile->filedes,NX_RANGE_LOCK_CANCEL,0 , 0) == -1)
+		return errno;
+   
+    return APR_SUCCESS;
+}
diff --git a/file_io/netware/mktemp.c b/file_io/netware/mktemp.c
new file mode 100644
index 00000000000..f37cab85bdc
--- /dev/null
+++ b/file_io/netware/mktemp.c
@@ -0,0 +1,64 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_private.h"
+#include "apr_file_io.h" /* prototype of apr_mkstemp() */
+#include "apr_strings.h" /* prototype of apr_mkstemp() */
+#include "apr_arch_file_io.h" /* prototype of apr_mkstemp() */
+#include "apr_portable.h" /* for apr_os_file_put() */
+#include "apr_arch_inherit.h"
+
+#include <stdlib.h> /* for mkstemp() - Single Unix */
+
+APR_DECLARE(apr_status_t) apr_file_mktemp(apr_file_t **fp, char *template, apr_int32_t flags, apr_pool_t *p)
+{
+    int fd;
+    apr_status_t rv;
+
+    flags = (!flags) ? APR_FOPEN_CREATE | APR_FOPEN_READ | APR_FOPEN_WRITE |
+                       APR_FOPEN_DELONCLOSE : flags & ~APR_FOPEN_EXCL;
+
+    fd = mkstemp(template);
+    if (fd == -1) {
+        return errno;
+    }
+    /* We need to reopen the file to get rid of the o_excl flag.
+     * Otherwise file locking will not allow the file to be shared.
+     */
+    close(fd);
+    if ((rv = apr_file_open(fp, template, flags|APR_FOPEN_NOCLEANUP,
+                            APR_FPROT_UREAD | APR_FPROT_UWRITE, p)) == APR_SUCCESS) {
+
+
+	if (!(flags & APR_FOPEN_NOCLEANUP)) {
+            int flags;
+
+            if ((flags = fcntl((*fp)->filedes, F_GETFD)) == -1)
+                return errno;
+
+            flags |= FD_CLOEXEC;
+            if (fcntl((*fp)->filedes, F_SETFD, flags) == -1)
+                return errno;
+
+	    apr_pool_cleanup_register((*fp)->pool, (void *)(*fp),
+				      apr_unix_file_cleanup,
+				      apr_unix_child_file_cleanup);
+	}
+    }
+
+    return rv;
+}
+
diff --git a/file_io/netware/pipe.c b/file_io/netware/pipe.c
new file mode 100644
index 00000000000..1a3a5e87932
--- /dev/null
+++ b/file_io/netware/pipe.c
@@ -0,0 +1,227 @@
+/* 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 <stdio.h>
+#include <nks/fsio.h>
+#include <nks/errno.h>
+
+#include "apr_arch_file_io.h"
+#include "apr_strings.h"
+#include "apr_portable.h"
+#include "apr_arch_inherit.h"
+
+static apr_status_t pipeblock(apr_file_t *thepipe)
+{
+#ifdef USE_FLAGS
+    unsigned long   flags;
+
+    if (fcntl(thepipe->filedes, F_GETFL, &flags) != -1)
+    {
+        flags &= ~FNDELAY;
+        fcntl(thepipe->filedes, F_SETFL, flags);
+    }
+#else
+        errno = 0;
+        fcntl(thepipe->filedes, F_SETFL, 0);
+#endif
+
+    if (errno)
+        return errno;
+
+    thepipe->blocking = BLK_ON;
+    return APR_SUCCESS;
+}
+
+static apr_status_t pipenonblock(apr_file_t *thepipe)
+{
+#ifdef USE_FLAGS
+    unsigned long   flags;
+
+    errno = 0;
+    if (fcntl(thepipe->filedes, F_GETFL, &flags) != -1)
+    {
+        flags |= FNDELAY;
+        fcntl(thepipe->filedes, F_SETFL, flags);
+    }
+#else
+        errno = 0;
+        fcntl(thepipe->filedes, F_SETFL, FNDELAY);
+#endif
+
+    if (errno)
+        return errno;
+
+    thepipe->blocking = BLK_OFF;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_file_pipe_timeout_set(apr_file_t *thepipe, apr_interval_time_t timeout)
+{
+    if (thepipe->is_pipe == 1) {
+        thepipe->timeout = timeout;
+        if (timeout >= 0) {
+            if (thepipe->blocking != BLK_OFF) { /* blocking or unknown state */
+                return pipenonblock(thepipe);
+            }
+        }
+        else {
+            if (thepipe->blocking != BLK_ON) { /* non-blocking or unknown state */
+                return pipeblock(thepipe);
+            }
+        }
+        return APR_SUCCESS;
+    }
+    return APR_EINVAL;
+}
+
+APR_DECLARE(apr_status_t) apr_file_pipe_timeout_get(apr_file_t *thepipe, apr_interval_time_t *timeout)
+{
+    if (thepipe->is_pipe == 1) {
+        *timeout = thepipe->timeout;
+        return APR_SUCCESS;
+    }
+    return APR_EINVAL;
+}
+
+APR_DECLARE(apr_status_t) apr_os_pipe_put_ex(apr_file_t **file,
+                                             apr_os_file_t *thefile,
+                                             int register_cleanup,
+                                             apr_pool_t *pool)
+{
+    int *dafile = thefile;
+    
+    (*file) = apr_pcalloc(pool, sizeof(apr_file_t));
+    (*file)->pool = pool;
+    (*file)->eof_hit = 0;
+    (*file)->is_pipe = 1;
+    (*file)->blocking = BLK_UNKNOWN; /* app needs to make a timeout call */
+    (*file)->timeout = -1;
+    (*file)->ungetchar = -1; /* no char avail */
+    (*file)->filedes = *dafile;
+    if (!register_cleanup) {
+        (*file)->flags = APR_FOPEN_NOCLEANUP;
+    }
+    (*file)->buffered = 0;
+#if APR_HAS_THREADS
+    (*file)->thlock = NULL;
+#endif
+    if (register_cleanup) {
+        apr_pool_cleanup_register((*file)->pool, (void *)(*file),
+                                  apr_unix_file_cleanup,
+                                  apr_pool_cleanup_null);
+    }
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_os_pipe_put(apr_file_t **file,
+                                          apr_os_file_t *thefile,
+                                          apr_pool_t *pool)
+{
+    return apr_os_pipe_put_ex(file, thefile, 0, pool);
+}
+
+static apr_status_t file_pipe_create(apr_file_t **in,
+                                     apr_file_t **out,
+                                     apr_int32_t blocking,
+                                     apr_pool_t *pool_in,
+                                     apr_pool_t *pool_out)
+{
+    int filedes[2];
+
+    if (pipe(filedes) == -1) {
+        return errno;
+    }
+
+    (*in) = (apr_file_t *)apr_pcalloc(pool_in, sizeof(apr_file_t));
+    (*out) = (apr_file_t *)apr_pcalloc(pool_out, sizeof(apr_file_t));
+
+    (*in)->pool     = pool_in;
+    (*out)->pool    = pool_out;
+    (*in)->filedes   = filedes[0];
+    (*out)->filedes  = filedes[1];
+    (*in)->flags     = APR_INHERIT;
+    (*out)->flags    = APR_INHERIT;
+    (*in)->is_pipe      =
+    (*out)->is_pipe     = 1;
+    (*out)->fname    = 
+    (*in)->fname     = NULL;
+    (*in)->buffered  =
+    (*out)->buffered = 0;
+    (*in)->blocking  =
+    (*out)->blocking = BLK_ON;
+    (*in)->timeout   =
+    (*out)->timeout  = -1;
+    (*in)->ungetchar = -1;
+    (*in)->thlock    =
+    (*out)->thlock   = NULL;
+    (void) apr_pollset_create(&(*in)->pollset, 1, pool_in, 0);
+    (void) apr_pollset_create(&(*out)->pollset, 1, pool_out, 0);
+
+    apr_pool_cleanup_register((*in)->pool, (void *)(*in), apr_unix_file_cleanup,
+                         apr_pool_cleanup_null);
+    apr_pool_cleanup_register((*out)->pool, (void *)(*out), apr_unix_file_cleanup,
+                         apr_pool_cleanup_null);
+
+    switch (blocking) {
+    case APR_FULL_BLOCK:
+        break;
+    case APR_READ_BLOCK:
+        apr_file_pipe_timeout_set(*out, 0);
+        break;
+    case APR_WRITE_BLOCK:
+        apr_file_pipe_timeout_set(*in, 0);
+        break;
+    default:
+        apr_file_pipe_timeout_set(*out, 0);
+        apr_file_pipe_timeout_set(*in, 0);
+        break;
+    }
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_file_pipe_create(apr_file_t **in,
+                                               apr_file_t **out,
+                                               apr_pool_t *pool)
+{
+    /* Default is full blocking pipes. */
+    return file_pipe_create(in, out, APR_FULL_BLOCK, pool, pool);
+}
+
+APR_DECLARE(apr_status_t) apr_file_pipe_create_ex(apr_file_t **in, 
+                                                  apr_file_t **out, 
+                                                  apr_int32_t blocking,
+                                                  apr_pool_t *pool)
+{
+    return file_pipe_create(in, out, blocking, pool, pool);
+}
+
+APR_DECLARE(apr_status_t) apr_file_pipe_create_pools(apr_file_t **in,
+                                                     apr_file_t **out,
+                                                     apr_int32_t blocking,
+                                                     apr_pool_t *pool_in,
+                                                     apr_pool_t *pool_out)
+{
+    return file_pipe_create(in, out, blocking, pool_in, pool_out);
+}
+
+APR_DECLARE(apr_status_t) apr_file_namedpipe_create(const char *filename, 
+                                                    apr_fileperms_t perm, apr_pool_t *pool)
+{
+    return APR_ENOTIMPL;
+} 
+
+    
+
diff --git a/file_io/os2/.cvsignore b/file_io/os2/.cvsignore
deleted file mode 100644
index f3c7a7c5da6..00000000000
--- a/file_io/os2/.cvsignore
+++ /dev/null
@@ -1 +0,0 @@
-Makefile
diff --git a/file_io/os2/Makefile.in b/file_io/os2/Makefile.in
deleted file mode 100644
index 934134b5ee5..00000000000
--- a/file_io/os2/Makefile.in
+++ /dev/null
@@ -1,105 +0,0 @@
-#CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
-#LIBS=$(EXTRA_LIBS) $(LIBS1)
-#INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
-#LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
-
-CC=@CC@
-RANLIB=@RANLIB@
-CFLAGS=@CFLAGS@ @OPTIM@
-LIBS=@LIBS@
-LDFLAGS=@LDFLAGS@ $(LIBS)
-INCDIR=../../inc
-INCDIR1=../../include
-INCLUDES=-I$(INCDIR) -I$(INCDIR1) -I.
-
-LIB=file.a
-
-OBJS=dir.o \
-	fileacc.o \
-	filedup.o \
-	filestat.o \
-	open.o \
-	pipe.o \
-	readwrite.o \
-	seek.o \
-	maperrorcode.o
-
-.c.o:
-	$(CC) $(CFLAGS) -c $(INCLUDES) $<
-
-all: $(LIB)
-
-clean:
-	$(RM) -f *.o *.a *.so
-
-distclean: clean
-	-$(RM) -f Makefile
-
-$(OBJS): Makefile
-
-$(LIB): $(OBJS)
-	$(RM) -f $@
-	$(AR) cr $@ $(OBJS)
-	$(RANLIB) $@
-
-#
-# We really don't expect end users to use this rule.  It works only with
-# gcc, and rebuilds Makefile.tmpl.  You have to re-run Configure after
-# using it.
-#
-depend:
-	cp Makefile.in Makefile.in.bak \
-	    && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.in > Makefile.new \
-	    && gcc -MM $(INCLUDES) $(CFLAGS) *.c | sed -e "s%\\\\\(.\)%/\\1%g" >> Makefile.new \
-	    && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
-	           -e '1,$$s: $(INCDIR1)/: $$(INCDIR1)/:g' \
-	           -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
-		> Makefile.in \
-	    && rm Makefile.new
-
-# DO NOT REMOVE
-dir.o: dir.c fileio.h $(INCDIR1)/apr_private.h \
- $(INCDIR1)/apr_general.h $(INCDIR1)/apr.h \
- $(INCDIR1)/apr_errno.h $(INCDIR1)/apr_file_io.h \
- $(INCDIR1)/apr_time.h $(INCDIR1)/apr_lib.h \
- $(INCDIR1)/apr_thread_proc.h
-fileacc.o: fileacc.c fileio.h $(INCDIR1)/apr_private.h \
- $(INCDIR1)/apr_general.h $(INCDIR1)/apr.h \
- $(INCDIR1)/apr_errno.h $(INCDIR1)/apr_file_io.h \
- $(INCDIR1)/apr_time.h $(INCDIR1)/apr_lib.h \
- $(INCDIR1)/apr_thread_proc.h
-filedup.o: filedup.c fileio.h $(INCDIR1)/apr_private.h \
- $(INCDIR1)/apr_general.h $(INCDIR1)/apr.h \
- $(INCDIR1)/apr_errno.h $(INCDIR1)/apr_file_io.h \
- $(INCDIR1)/apr_time.h $(INCDIR1)/apr_lib.h \
- $(INCDIR1)/apr_thread_proc.h
-filestat.o: filestat.c fileio.h $(INCDIR1)/apr_private.h \
- $(INCDIR1)/apr_general.h $(INCDIR1)/apr.h \
- $(INCDIR1)/apr_errno.h $(INCDIR1)/apr_file_io.h \
- $(INCDIR1)/apr_time.h $(INCDIR1)/apr_lib.h \
- $(INCDIR1)/apr_thread_proc.h
-maperrorcode.o: maperrorcode.c fileio.h $(INCDIR1)/apr_private.h \
- $(INCDIR1)/apr_general.h $(INCDIR1)/apr.h \
- $(INCDIR1)/apr_errno.h $(INCDIR1)/apr_file_io.h \
- $(INCDIR1)/apr_time.h ../../network_io/os2/os2calls.h
-open.o: open.c fileio.h $(INCDIR1)/apr_private.h \
- $(INCDIR1)/apr_general.h $(INCDIR1)/apr.h \
- $(INCDIR1)/apr_errno.h $(INCDIR1)/apr_file_io.h \
- $(INCDIR1)/apr_time.h $(INCDIR1)/apr_lib.h \
- $(INCDIR1)/apr_thread_proc.h $(INCDIR1)/apr_portable.h \
- $(INCDIR1)/apr_network_io.h $(INCDIR1)/apr_lock.h
-pipe.o: pipe.c fileio.h $(INCDIR1)/apr_private.h \
- $(INCDIR1)/apr_general.h $(INCDIR1)/apr.h \
- $(INCDIR1)/apr_errno.h $(INCDIR1)/apr_file_io.h \
- $(INCDIR1)/apr_time.h $(INCDIR1)/apr_lib.h \
- $(INCDIR1)/apr_thread_proc.h
-readwrite.o: readwrite.c fileio.h $(INCDIR1)/apr_private.h \
- $(INCDIR1)/apr_general.h $(INCDIR1)/apr.h \
- $(INCDIR1)/apr_errno.h $(INCDIR1)/apr_file_io.h \
- $(INCDIR1)/apr_time.h $(INCDIR1)/apr_lib.h \
- $(INCDIR1)/apr_thread_proc.h
-seek.o: seek.c fileio.h $(INCDIR1)/apr_private.h \
- $(INCDIR1)/apr_general.h $(INCDIR1)/apr.h \
- $(INCDIR1)/apr_errno.h $(INCDIR1)/apr_file_io.h \
- $(INCDIR1)/apr_time.h $(INCDIR1)/apr_lib.h \
- $(INCDIR1)/apr_thread_proc.h
diff --git a/file_io/os2/buffer.c b/file_io/os2/buffer.c
new file mode 100644
index 00000000000..8edc606187b
--- /dev/null
+++ b/file_io/os2/buffer.c
@@ -0,0 +1,69 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_arch_file_io.h"
+#include "apr_thread_mutex.h"
+
+APR_DECLARE(apr_status_t) apr_file_buffer_set(apr_file_t *file, 
+                                              char * buffer,
+                                              apr_size_t bufsize)
+{
+    apr_status_t rv = APR_SUCCESS;
+    int do_locking = file->mutex != NULL && file->buffered;
+
+    if (do_locking) {
+        apr_thread_mutex_lock(file->mutex);
+    }
+ 
+    if (file->buffered) {
+        /* Flush the existing buffer */
+        rv = apr_file_flush(file);
+        if (rv != APR_SUCCESS) {
+            if (do_locking) {
+                apr_thread_mutex_unlock(file->mutex);
+            }
+
+            return rv;
+        }
+    }
+        
+    file->buffer = buffer;
+    file->bufsize = bufsize;
+    file->bufpos = 0;
+    file->direction = 0;
+    file->dataRead = 0;
+
+    if (bufsize > 0 && file->mutex == NULL && (file->flags & APR_FOPEN_XTHREAD)) {
+        /* buffering is being turned on but we have no mutex, make one */
+        rv = apr_thread_mutex_create(&file->mutex, 0, file->pool);
+    }
+
+    /* Setting the buffer size to zero is equivalent to turning 
+     * buffering off. 
+     */
+    file->buffered = file->bufsize > 0;
+    
+    if (do_locking) {
+        apr_thread_mutex_unlock(file->mutex);
+    }
+
+    return rv;
+}
+
+APR_DECLARE(apr_size_t) apr_file_buffer_size_get(apr_file_t *file)
+{
+    return file->bufsize;
+}
diff --git a/file_io/os2/copy.c b/file_io/os2/copy.c
new file mode 100644
index 00000000000..f4ce010f8f7
--- /dev/null
+++ b/file_io/os2/copy.c
@@ -0,0 +1 @@
+#include "../unix/copy.c"
diff --git a/file_io/os2/dir.c b/file_io/os2/dir.c
index 34f973ec63c..f1554b6f35c 100644
--- a/file_io/os2/dir.c
+++ b/file_io/os2/dir.c
@@ -1,82 +1,45 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "fileio.h"
+#include "apr_arch_file_io.h"
 #include "apr_file_io.h"
 #include "apr_lib.h"
+#include "apr_strings.h"
+#include "apr_portable.h"
 #include <string.h>
 
-#define INCL_DOS
-#include <os2.h>
-
-static ap_status_t dir_cleanup(void *thedir)
+static apr_status_t dir_cleanup(void *thedir)
 {
-    ap_dir_t *dir = thedir;
-    return ap_closedir(dir);
+    apr_dir_t *dir = thedir;
+    return apr_dir_close(dir);
 }
 
 
 
-ap_status_t ap_opendir(ap_dir_t **new, const char *dirname, ap_pool_t *cntxt)
+APR_DECLARE(apr_status_t) apr_dir_open(apr_dir_t **new, const char *dirname, apr_pool_t *pool)
 {
-    ap_dir_t *thedir = (ap_dir_t *)ap_palloc(cntxt, sizeof(ap_dir_t));
+    FILESTATUS3 filestatus;
+    int rv;
+    apr_dir_t *thedir = (apr_dir_t *)apr_palloc(pool, sizeof(apr_dir_t));
     
     if (thedir == NULL)
         return APR_ENOMEM;
     
-    thedir->cntxt = cntxt;
-    thedir->dirname = ap_pstrdup(cntxt, dirname);
+    thedir->pool = pool;
+    thedir->dirname = apr_pstrdup(pool, dirname);
 
     if (thedir->dirname == NULL)
         return APR_ENOMEM;
@@ -84,13 +47,24 @@ ap_status_t ap_opendir(ap_dir_t **new, const char *dirname, ap_pool_t *cntxt)
     thedir->handle = 0;
     thedir->validentry = FALSE;
     *new = thedir;
-    ap_register_cleanup(cntxt, thedir, dir_cleanup, ap_null_cleanup);
+    apr_pool_cleanup_register(pool, thedir, dir_cleanup, apr_pool_cleanup_null);
+
+    rv = DosQueryPathInfo(dirname, FIL_STANDARD, &filestatus, sizeof(filestatus));
+
+    if (rv != 0) {
+        return APR_FROM_OS_ERROR(rv);
+    }
+
+    if ((filestatus.attrFile & FILE_DIRECTORY) == 0) {
+        return APR_ENOTDIR;
+    }
+
     return APR_SUCCESS;
 }
 
 
 
-ap_status_t ap_closedir(ap_dir_t *thedir)
+APR_DECLARE(apr_status_t) apr_dir_close(apr_dir_t *thedir)
 {
     int rv = 0;
     
@@ -102,126 +76,105 @@ ap_status_t ap_closedir(ap_dir_t *thedir)
         }
     }
 
-    return APR_OS2_STATUS(rv);
+    return APR_FROM_OS_ERROR(rv);
 } 
 
 
 
-ap_status_t ap_readdir(ap_dir_t *thedir)
+APR_DECLARE(apr_status_t) apr_dir_read(apr_finfo_t *finfo, apr_int32_t wanted,
+                                       apr_dir_t *thedir)
 {
     int rv;
     ULONG entries = 1;
     
     if (thedir->handle == 0) {
         thedir->handle = HDIR_CREATE;
-        rv = DosFindFirst(ap_pstrcat(thedir->cntxt, thedir->dirname, "/*", NULL), &thedir->handle, 
+        rv = DosFindFirst(apr_pstrcat(thedir->pool, thedir->dirname, "/*", NULL), &thedir->handle, 
                           FILE_ARCHIVED|FILE_DIRECTORY|FILE_SYSTEM|FILE_HIDDEN|FILE_READONLY, 
                           &thedir->entry, sizeof(thedir->entry), &entries, FIL_STANDARD);
     } else {
         rv = DosFindNext(thedir->handle, &thedir->entry, sizeof(thedir->entry), &entries);
     }
 
+    finfo->pool = thedir->pool;
+    finfo->fname = NULL;
+    finfo->valid = 0;
+
     if (rv == 0 && entries == 1) {
         thedir->validentry = TRUE;
-        return APR_SUCCESS;
-    }
-        
-    thedir->validentry = FALSE;
-    
-    if (rv)
-        return APR_OS2_STATUS(rv);
-    
-    return APR_ENOENT;
-}
 
+        /* We passed a name off the stack that has popped */
+        finfo->fname = NULL;
+        finfo->size = thedir->entry.cbFile;
+        finfo->csize = thedir->entry.cbFileAlloc;
 
+        /* Only directories & regular files show up in directory listings */
+        finfo->filetype = (thedir->entry.attrFile & FILE_DIRECTORY) ? APR_DIR : APR_REG;
 
-ap_status_t ap_rewinddir(ap_dir_t *thedir)
-{
-    return ap_closedir(thedir);
-}
+        apr_os2_time_to_apr_time(&finfo->mtime, thedir->entry.fdateLastWrite,
+                                 thedir->entry.ftimeLastWrite);
+        apr_os2_time_to_apr_time(&finfo->atime, thedir->entry.fdateLastAccess,
+                                 thedir->entry.ftimeLastAccess);
+        apr_os2_time_to_apr_time(&finfo->ctime, thedir->entry.fdateCreation,
+                                 thedir->entry.ftimeCreation);
 
+        finfo->name = thedir->entry.achName;
+        finfo->valid = APR_FINFO_NAME | APR_FINFO_MTIME | APR_FINFO_ATIME |
+            APR_FINFO_CTIME | APR_FINFO_TYPE | APR_FINFO_SIZE |
+            APR_FINFO_CSIZE;
 
+        return APR_SUCCESS;
+    }
 
-ap_status_t ap_make_dir(const char *path, ap_fileperms_t perm, ap_pool_t *cont)
-{
-    return APR_OS2_STATUS(DosCreateDir(path, NULL));
+    thedir->validentry = FALSE;
+
+    if (rv)
+        return APR_FROM_OS_ERROR(rv);
+
+    return APR_ENOENT;
 }
 
 
 
-ap_status_t ap_remove_dir(const char *path, ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_dir_rewind(apr_dir_t *thedir)
 {
-    return APR_OS2_STATUS(DosDeleteDir(path));
+    return apr_dir_close(thedir);
 }
 
 
 
-ap_status_t ap_dir_entry_size(ap_ssize_t *size, ap_dir_t *thedir)
+APR_DECLARE(apr_status_t) apr_dir_make(const char *path, apr_fileperms_t perm, apr_pool_t *pool)
 {
-    if (thedir->validentry) {
-        *size = thedir->entry.cbFile;
-        return APR_SUCCESS;
-    }
-    
-    return APR_ENOFILE;
+    return APR_FROM_OS_ERROR(DosCreateDir(path, NULL));
 }
 
 
 
-ap_status_t ap_dir_entry_mtime(ap_time_t *time, ap_dir_t *thedir)
+APR_DECLARE(apr_status_t) apr_dir_remove(const char *path, apr_pool_t *pool)
 {
-    if (thedir->validentry) {
-        ap_os2_time_to_ap_time(time, thedir->entry.fdateLastWrite, thedir->entry.ftimeLastWrite);
-        return APR_SUCCESS;
-    }
-
-    return APR_ENOFILE;
+    return APR_FROM_OS_ERROR(DosDeleteDir(path));
 }
 
 
 
-ap_status_t ap_dir_entry_ftype(ap_filetype_e *type, ap_dir_t *thedir)
+APR_DECLARE(apr_status_t) apr_os_dir_get(apr_os_dir_t **thedir, apr_dir_t *dir)
 {
-    int rc;
-    HFILE hFile;
-    ULONG action, Type, Attr;
-    ap_filetype_e typemap[8] = { APR_REG, APR_CHR, APR_PIPE };
-
-    if (thedir->validentry) {
-        if (thedir->entry.attrFile & FILE_DIRECTORY) {
-            *type = APR_DIR;
-            return APR_SUCCESS;
-        } else {
-            rc = DosOpen(ap_pstrcat(thedir->cntxt, thedir->dirname, "/", thedir->entry.achName, NULL) ,
-                         &hFile, &action, 0, 0,
-                         OPEN_ACTION_FAIL_IF_NEW|OPEN_ACTION_OPEN_IF_EXISTS, OPEN_SHARE_DENYNONE|OPEN_ACCESS_READONLY,
-                         NULL);
-
-            if ( rc == 0 ) {
-                rc = DosQueryHType( hFile, &Type, &Attr );
-
-                if ( rc == 0 ) {
-            *type = typemap[(Type & 0x0007)];
-                }
-                DosClose( hFile );
-            }
-
-            return APR_OS2_STATUS(rc);
-        }
+    if (dir == NULL) {
+        return APR_ENODIR;
     }
-
-    return APR_ENOFILE;
+    *thedir = &dir->handle;
+    return APR_SUCCESS;
 }
 
 
 
-ap_status_t ap_get_dir_filename(char **new, ap_dir_t *thedir)
+APR_DECLARE(apr_status_t) apr_os_dir_put(apr_dir_t **dir, apr_os_dir_t *thedir,
+                                         apr_pool_t *pool)
 {
-    if (thedir->validentry) {
-        *new = thedir->entry.achName;
-        return APR_SUCCESS;
+    if ((*dir) == NULL) {
+        (*dir) = (apr_dir_t *)apr_pcalloc(pool, sizeof(apr_dir_t));
+        (*dir)->pool = pool;
     }
-
-    return APR_ENOFILE;
+    (*dir)->handle = *thedir;
+    return APR_SUCCESS;
 }
diff --git a/file_io/os2/dir_make_recurse.c b/file_io/os2/dir_make_recurse.c
new file mode 100644
index 00000000000..602a621ae7e
--- /dev/null
+++ b/file_io/os2/dir_make_recurse.c
@@ -0,0 +1,90 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_file_io.h"
+#include "apr_lib.h"
+#include "apr_strings.h"
+#include <string.h>
+
+#define IS_SEP(c) (c == '/' || c == '\\')
+
+/* Remove trailing separators that don't affect the meaning of PATH. */
+static const char *path_canonicalize(const char *path, apr_pool_t *pool)
+{
+    /* At some point this could eliminate redundant components.  For
+     * now, it just makes sure there is no trailing slash. */
+    apr_size_t len = strlen(path);
+    apr_size_t orig_len = len;
+
+    while ((len > 0) && IS_SEP(path[len - 1])) {
+        len--;
+    }
+
+    if (len != orig_len) {
+        return apr_pstrndup(pool, path, len);
+    }
+    else {
+        return path;
+    }
+}
+
+
+
+/* Remove one component off the end of PATH. */
+static char *path_remove_last_component(const char *path, apr_pool_t *pool)
+{
+    const char *newpath = path_canonicalize(path, pool);
+    int i;
+
+    for (i = strlen(newpath) - 1; i >= 0; i--) {
+        if (IS_SEP(path[i])) {
+            break;
+        }
+    }
+
+    return apr_pstrndup(pool, path, (i < 0) ? 0 : i);
+}
+
+
+
+apr_status_t apr_dir_make_recursive(const char *path, apr_fileperms_t perm,
+                                    apr_pool_t *pool)
+{
+    apr_status_t apr_err = APR_SUCCESS;
+    
+    apr_err = apr_dir_make(path, perm, pool); /* Try to make PATH right out */
+
+    if (APR_STATUS_IS_ENOENT(apr_err)) { /* Missing an intermediate dir */
+        char *dir;
+
+        dir = path_remove_last_component(path, pool);
+        apr_err = apr_dir_make_recursive(dir, perm, pool);
+
+        if (!apr_err) {
+            apr_err = apr_dir_make(path, perm, pool);
+        }
+    }
+
+    /*
+     * It's OK if PATH exists. Timing issues can lead to the second
+     * apr_dir_make being called on existing dir, therefore this check
+     * has to come last.
+     */
+    if (APR_STATUS_IS_EEXIST(apr_err))
+        return APR_SUCCESS;
+
+    return apr_err;
+}
diff --git a/file_io/os2/fileacc.c b/file_io/os2/fileacc.c
index 0dfee57f02b..b5c1afd5031 100644
--- a/file_io/os2/fileacc.c
+++ b/file_io/os2/fileacc.c
@@ -1,102 +1,18 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+/* 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 "fileio.h"
-#include "apr_file_io.h"
-#include "apr_general.h"
-#include "apr_lib.h"
-#include <errno.h>
-#include <string.h>
-#include <sys/types.h>
-
-/* A file to put ALL of the accessor functions for ap_file_t types. */
-
-ap_status_t ap_get_filename(char **new, ap_file_t *thefile)
-{
-    if (thefile != NULL) {
-        *new = ap_pstrdup(thefile->cntxt, thefile->fname);
-        return APR_SUCCESS;
-    } else {
-        *new = NULL;
-        return APR_ENOFILE;
-    }
-}
-
-
-
-ap_status_t ap_get_filedata(void **data, char *key, ap_file_t *file)
-{    
-    if (file != NULL) {
-        return ap_get_userdata(data, key, file->cntxt);
-    }
-    else {
-        data = NULL;
-        return APR_ENOFILE;
-    }
-}
-
-
-
-ap_status_t ap_set_filedata(ap_file_t *file, void *data, char *key,
-                            ap_status_t (*cleanup) (void *))
-{    
-    if (file != NULL) {
-        return ap_set_userdata(data, key, cleanup, file->cntxt);
-    }
-    else {
-        data = NULL;
-        return APR_ENOFILE;
-    }
-}
+#include "../unix/fileacc.c"
 
diff --git a/file_io/os2/filedup.c b/file_io/os2/filedup.c
index d3cedd6a70f..ff937eb686c 100644
--- a/file_io/os2/filedup.c
+++ b/file_io/os2/filedup.c
@@ -1,72 +1,33 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "fileio.h"
+#include "apr_arch_file_io.h"
 #include "apr_file_io.h"
 #include "apr_lib.h"
+#include "apr_strings.h"
 #include <string.h>
+#include "apr_arch_inherit.h"
 
-#define INCL_DOS
-#include <os2.h>
-
-ap_status_t ap_dupfile(ap_file_t **new_file, ap_file_t *old_file, ap_pool_t *p)
+static apr_status_t file_dup(apr_file_t **new_file, apr_file_t *old_file, apr_pool_t *p)
 {
     int rv;
-    ap_file_t *dup_file;
+    apr_file_t *dup_file;
 
     if (*new_file == NULL) {
-        dup_file = (ap_file_t *)ap_palloc(p, sizeof(ap_file_t));
+        dup_file = (apr_file_t *)apr_palloc(p, sizeof(apr_file_t));
 
         if (dup_file == NULL) {
             return APR_ENOMEM;
@@ -77,25 +38,89 @@ ap_status_t ap_dupfile(ap_file_t **new_file, ap_file_t *old_file, ap_pool_t *p)
       dup_file = *new_file;
     }
 
-    dup_file->cntxt = p;
+    dup_file->pool = p;
     rv = DosDupHandle(old_file->filedes, &dup_file->filedes);
 
     if (rv) {
-        return APR_OS2_STATUS(rv);
+        return APR_FROM_OS_ERROR(rv);
     }
 
-    dup_file->fname = ap_pstrdup(dup_file->cntxt, old_file->fname);
+    dup_file->fname = apr_pstrdup(dup_file->pool, old_file->fname);
     dup_file->buffered = old_file->buffered;
     dup_file->isopen = old_file->isopen;
-    dup_file->flags = old_file->flags;
+    dup_file->flags = old_file->flags & ~APR_INHERIT;
+    dup_file->ungetchar = old_file->ungetchar;
     /* TODO - dup pipes correctly */
     dup_file->pipe = old_file->pipe;
 
     if (*new_file == NULL) {
-        ap_register_cleanup(dup_file->cntxt, dup_file, apr_file_cleanup,
-                            ap_null_cleanup);
+        apr_pool_cleanup_register(dup_file->pool, dup_file, apr_file_cleanup,
+                            apr_pool_cleanup_null);
         *new_file = dup_file;
     }
 
     return APR_SUCCESS;
 }
+
+
+
+APR_DECLARE(apr_status_t) apr_file_dup(apr_file_t **new_file, apr_file_t *old_file, apr_pool_t *p)
+{
+  if (*new_file) {
+      apr_file_close(*new_file);
+      (*new_file)->filedes = -1;
+  }
+
+  return file_dup(new_file, old_file, p);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_file_dup2(apr_file_t *new_file, apr_file_t *old_file, apr_pool_t *p)
+{
+  return file_dup(&new_file, old_file, p);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_file_setaside(apr_file_t **new_file,
+                                            apr_file_t *old_file,
+                                            apr_pool_t *p)
+{
+    *new_file = (apr_file_t *)apr_pmemdup(p, old_file, sizeof(apr_file_t));
+    (*new_file)->pool = p;
+
+    if (old_file->buffered) {
+        (*new_file)->buffer = apr_palloc(p, old_file->bufsize);
+        (*new_file)->bufsize = old_file->bufsize;
+
+        if (old_file->direction == 1) {
+            memcpy((*new_file)->buffer, old_file->buffer, old_file->bufpos);
+        }
+        else {
+            memcpy((*new_file)->buffer, old_file->buffer, old_file->dataRead);
+        }
+
+        if (old_file->mutex) {
+            apr_thread_mutex_create(&((*new_file)->mutex),
+                                    APR_THREAD_MUTEX_DEFAULT, p);
+            apr_thread_mutex_destroy(old_file->mutex);
+        }
+    }
+
+    if (old_file->fname) {
+        (*new_file)->fname = apr_pstrdup(p, old_file->fname);
+    }
+
+    if (!(old_file->flags & APR_FOPEN_NOCLEANUP)) {
+        apr_pool_cleanup_register(p, (void *)(*new_file), 
+                                  apr_file_cleanup,
+                                  apr_file_cleanup);
+    }
+
+    old_file->filedes = -1;
+    apr_pool_cleanup_kill(old_file->pool, (void *)old_file,
+                          apr_file_cleanup);
+
+    return APR_SUCCESS;
+}
diff --git a/file_io/os2/fileio.h b/file_io/os2/fileio.h
deleted file mode 100644
index b2d6d6d2ef0..00000000000
--- a/file_io/os2/fileio.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef FILE_IO_H
-#define FILE_IO_H
-
-#define INCL_DOS
-#include <os2.h>
-
-#include "apr_private.h"
-#include "apr_general.h"
-#include "apr_lock.h"
-#include "apr_file_io.h"
-#include "apr_errno.h"
-
-#define APR_FILE_BUFSIZE 4096
-
-struct ap_file_t {
-    ap_pool_t *cntxt;
-    HFILE filedes;
-    char * fname;
-    int isopen;
-    int buffered;
-    int eof_hit;
-    ap_int32_t flags;
-    int timeout;
-    int pipe;
-    HEV pipeSem;
-
-    /* Stuff for buffered mode */
-    char *buffer;
-    int bufpos;               // Read/Write position in buffer
-    unsigned long dataRead;   // amount of valid data read into buffer
-    int direction;            // buffer being used for 0 = read, 1 = write
-    unsigned long filePtr;    // position in file of handle
-    ap_lock_t *mutex;         // mutex semaphore, must be owned to access the above fields
-};
-
-struct ap_dir_t {
-    ap_pool_t *cntxt;
-    char *dirname;
-    ULONG handle;
-    FILEFINDBUF3 entry;
-    int validentry;
-};
-
-ap_status_t apr_file_cleanup(void *);
-ap_status_t ap_os2_time_to_ap_time(ap_time_t *result, FDATE os2date, FTIME os2time);
-
-#endif  /* ! FILE_IO_H */
-
diff --git a/file_io/os2/filepath.c b/file_io/os2/filepath.c
new file mode 100644
index 00000000000..9422faa957c
--- /dev/null
+++ b/file_io/os2/filepath.c
@@ -0,0 +1,16 @@
+/* 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 "../win32/filepath.c"
diff --git a/file_io/os2/filepath_util.c b/file_io/os2/filepath_util.c
new file mode 100644
index 00000000000..a89c173e54e
--- /dev/null
+++ b/file_io/os2/filepath_util.c
@@ -0,0 +1 @@
+#include "../unix/filepath_util.c"
diff --git a/file_io/os2/filestat.c b/file_io/os2/filestat.c
index 429686c2822..8208eb4b7f3 100644
--- a/file_io/os2/filestat.c
+++ b/file_io/os2/filestat.c
@@ -1,69 +1,31 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
 #define INCL_DOS
 #define INCL_DOSERRORS
-#include "fileio.h"
+#include "apr_arch_file_io.h"
 #include "apr_file_io.h"
 #include "apr_lib.h"
 #include <sys/time.h>
-#include <os2.h>
+#include "apr_strings.h"
 
 
-static void FS3_to_finfo(ap_finfo_t *finfo, FILESTATUS3 *fstatus)
+static void FS3_to_finfo(apr_finfo_t *finfo, FILESTATUS3 *fstatus)
 {
-    finfo->protection = (fstatus->attrFile & FILE_READONLY) ? 0555 : 0777;
+    finfo->protection = (fstatus->attrFile & FILE_READONLY) ? 0x555 : 0x777;
 
     if (fstatus->attrFile & FILE_DIRECTORY)
         finfo->filetype = APR_DIR;
@@ -73,15 +35,23 @@ static void FS3_to_finfo(ap_finfo_t *finfo, FILESTATUS3 *fstatus)
     finfo->user = 0;
     finfo->group = 0;
     finfo->inode = 0;
+    finfo->device = 0;
     finfo->size = fstatus->cbFile;
-    ap_os2_time_to_ap_time(&finfo->atime, fstatus->fdateLastAccess, fstatus->ftimeLastAccess );
-    ap_os2_time_to_ap_time(&finfo->mtime, fstatus->fdateLastWrite,  fstatus->ftimeLastWrite );
-    ap_os2_time_to_ap_time(&finfo->ctime, fstatus->fdateCreation,   fstatus->ftimeCreation );
+    finfo->csize = fstatus->cbFileAlloc;
+    apr_os2_time_to_apr_time(&finfo->atime, fstatus->fdateLastAccess, 
+                             fstatus->ftimeLastAccess );
+    apr_os2_time_to_apr_time(&finfo->mtime, fstatus->fdateLastWrite,  
+                             fstatus->ftimeLastWrite );
+    apr_os2_time_to_apr_time(&finfo->ctime, fstatus->fdateCreation,   
+                             fstatus->ftimeCreation );
+    finfo->valid = APR_FINFO_TYPE | APR_FINFO_PROT | APR_FINFO_SIZE
+                 | APR_FINFO_CSIZE | APR_FINFO_MTIME 
+                 | APR_FINFO_CTIME | APR_FINFO_ATIME | APR_FINFO_LINK;
 }
 
 
 
-static ap_status_t handle_type(ap_filetype_e *ftype, HFILE file)
+static apr_status_t handle_type(apr_filetype_e *ftype, HFILE file)
 {
     ULONG filetype, fileattr, rc;
 
@@ -100,27 +70,43 @@ static ap_status_t handle_type(ap_filetype_e *ftype, HFILE file)
         case 2:
             *ftype = APR_PIPE;
             break;
+
+        default:
+            /* Values greater than 2 are reserved, this should never happen */
+            *ftype = APR_UNKFILE;
+            break;
         }
 
         return APR_SUCCESS;
     }
-    return APR_OS2_STATUS(rc);
+    return APR_FROM_OS_ERROR(rc);
 }
 
 
 
-ap_status_t ap_getfileinfo(ap_finfo_t *finfo, ap_file_t *thefile)
+APR_DECLARE(apr_status_t) apr_file_info_get(apr_finfo_t *finfo, apr_int32_t wanted, 
+                                   apr_file_t *thefile)
 {
     ULONG rc;
     FILESTATUS3 fstatus;
 
-    if (thefile->isopen)
+    if (thefile->isopen) {
+        if (thefile->buffered) {
+            apr_status_t rv = apr_file_flush(thefile);
+
+            if (rv != APR_SUCCESS) {
+                return rv;
+            }
+        }
+
         rc = DosQueryFileInfo(thefile->filedes, FIL_STANDARD, &fstatus, sizeof(fstatus));
+    }
     else
         rc = DosQueryPathInfo(thefile->fname, FIL_STANDARD, &fstatus, sizeof(fstatus));
 
     if (rc == 0) {
         FS3_to_finfo(finfo, &fstatus);
+        finfo->fname = thefile->fname;
 
         if (finfo->filetype == APR_REG) {
             if (thefile->isopen) {
@@ -133,29 +119,120 @@ ap_status_t ap_getfileinfo(ap_finfo_t *finfo, ap_file_t *thefile)
 
     finfo->protection = 0;
     finfo->filetype = APR_NOFILE;
-    return APR_OS2_STATUS(rc);
+    return APR_FROM_OS_ERROR(rc);
 }
 
+APR_DECLARE(apr_status_t) apr_file_perms_set(const char *fname, apr_fileperms_t perms)
+{
+    return APR_ENOTIMPL;
+}
 
 
-ap_status_t ap_stat(ap_finfo_t *finfo, const char *fname, ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_stat(apr_finfo_t *finfo, const char *fname,
+                              apr_int32_t wanted, apr_pool_t *cont)
 {
     ULONG rc;
     FILESTATUS3 fstatus;
     
     finfo->protection = 0;
     finfo->filetype = APR_NOFILE;
+    finfo->name = NULL;
     rc = DosQueryPathInfo(fname, FIL_STANDARD, &fstatus, sizeof(fstatus));
     
     if (rc == 0) {
         FS3_to_finfo(finfo, &fstatus);
-        return APR_SUCCESS;
+        finfo->fname = fname;
+
+        if (wanted & APR_FINFO_NAME) {
+            ULONG count = 1;
+            HDIR hDir = HDIR_SYSTEM;
+            FILEFINDBUF3 ffb;
+            rc = DosFindFirst(fname, &hDir,
+                              FILE_DIRECTORY|FILE_HIDDEN|FILE_SYSTEM|FILE_ARCHIVED,
+                              &ffb, sizeof(ffb), &count, FIL_STANDARD);
+            if (rc == 0 && count == 1) {
+                finfo->name = apr_pstrdup(cont, ffb.achName);
+                finfo->valid |= APR_FINFO_NAME;
+            }
+        }
     } else if (rc == ERROR_INVALID_ACCESS) {
-        memset(finfo, 0, sizeof(ap_finfo_t));
-        finfo->protection = 0444;
+        memset(finfo, 0, sizeof(apr_finfo_t));
+        finfo->valid = APR_FINFO_TYPE | APR_FINFO_PROT;
+        finfo->protection = 0666;
         finfo->filetype = APR_CHR;
+
+        if (wanted & APR_FINFO_NAME) {
+            finfo->name = apr_pstrdup(cont, fname);
+            finfo->valid |= APR_FINFO_NAME;
+        }
+    } else {
+        return APR_FROM_OS_ERROR(rc);
+    }
+
+    return (wanted & ~finfo->valid) ? APR_INCOMPLETE : APR_SUCCESS;
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_file_attrs_set(const char *fname,
+                                             apr_fileattrs_t attributes,
+                                             apr_fileattrs_t attr_mask,
+                                             apr_pool_t *cont)
+{
+    FILESTATUS3 fs3;
+    ULONG rc;
+
+    /* Don't do anything if we can't handle the requested attributes */
+    if (!(attr_mask & (APR_FILE_ATTR_READONLY
+                       | APR_FILE_ATTR_HIDDEN)))
         return APR_SUCCESS;
+
+    rc = DosQueryPathInfo(fname, FIL_STANDARD, &fs3, sizeof(fs3));
+    if (rc == 0) {
+        ULONG old_attr = fs3.attrFile;
+
+        if (attr_mask & APR_FILE_ATTR_READONLY)
+        {
+            if (attributes & APR_FILE_ATTR_READONLY) {
+                fs3.attrFile |= FILE_READONLY;
+            } else {
+                fs3.attrFile &= ~FILE_READONLY;
+            }
+        }
+
+        if (attr_mask & APR_FILE_ATTR_HIDDEN)
+        {
+            if (attributes & APR_FILE_ATTR_HIDDEN) {
+                fs3.attrFile |= FILE_HIDDEN;
+            } else {
+                fs3.attrFile &= ~FILE_HIDDEN;
+            }
+        }
+
+        if (fs3.attrFile != old_attr) {
+            rc = DosSetPathInfo(fname, FIL_STANDARD, &fs3, sizeof(fs3), 0);
+        }
     }
-    
-    return APR_OS2_STATUS(rc);
+
+    return APR_FROM_OS_ERROR(rc);
+}
+
+
+/* ### Somebody please write this! */
+APR_DECLARE(apr_status_t) apr_file_mtime_set(const char *fname,
+                                              apr_time_t mtime,
+                                              apr_pool_t *pool)
+{
+    FILESTATUS3 fs3;
+    ULONG rc;
+    rc = DosQueryPathInfo(fname, FIL_STANDARD, &fs3, sizeof(fs3));
+
+    if (rc) {
+        return APR_FROM_OS_ERROR(rc);
+    }
+
+    apr_apr_time_to_os2_time(&fs3.fdateLastWrite, &fs3.ftimeLastWrite, mtime);
+
+    rc = DosSetPathInfo(fname, FIL_STANDARD, &fs3, sizeof(fs3), 0);
+    return APR_FROM_OS_ERROR(rc);
 }
diff --git a/file_io/os2/filesys.c b/file_io/os2/filesys.c
new file mode 100644
index 00000000000..ae43bc0a0fc
--- /dev/null
+++ b/file_io/os2/filesys.c
@@ -0,0 +1,148 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_arch_file_io.h"
+#include "apr_strings.h"
+#include "apr_lib.h"
+#include <ctype.h>
+
+/* OS/2 Exceptions:
+ *
+ * Note that trailing spaces and trailing periods are never recorded
+ * in the file system.
+ *
+ * Leading spaces and periods are accepted, however.
+ * The * ? < > codes all have wildcard side effects
+ * The " / \ : are exclusively component separator tokens 
+ * The system doesn't accept | for any (known) purpose 
+ * Oddly, \x7f _is_ acceptable ;)
+ */
+
+const char c_is_fnchar[256] =
+{/* Reject all ctrl codes...                                         */
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ /*     "               *         /                      :   <   > ? */
+    1,1,0,1,1,1,1,1,1,1,0,1,1,1,1,0, 1,1,1,1,1,1,1,1,1,1,0,1,0,1,0,0,
+ /*                                                          \       */
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,
+ /*                                                          |       */
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,
+ /* High bit codes are accepted                                      */
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
+};
+
+
+#define IS_SLASH(c) (c == '/' || c == '\\')
+
+
+apr_status_t filepath_root_test(char *path, apr_pool_t *p)
+{
+    char drive = apr_toupper(path[0]);
+
+    if (drive >= 'A' && drive <= 'Z' && path[1] == ':' && IS_SLASH(path[2]))
+        return APR_SUCCESS;
+
+    return APR_EBADPATH;
+}
+
+
+apr_status_t filepath_drive_get(char **rootpath, char drive, 
+                                apr_int32_t flags, apr_pool_t *p)
+{
+    char path[APR_PATH_MAX];
+    char *pos;
+    ULONG rc;
+    ULONG bufsize = sizeof(path) - 3;
+
+    path[0] = drive;
+    path[1] = ':';
+    path[2] = '/';
+
+    rc = DosQueryCurrentDir(apr_toupper(drive) - 'A', path+3, &bufsize);
+
+    if (rc) {
+        return APR_FROM_OS_ERROR(rc);
+    }
+
+    if (!(flags & APR_FILEPATH_NATIVE)) {
+        for (pos=path; *pos; pos++) {
+            if (*pos == '\\')
+                *pos = '/';
+        }
+    }
+
+    *rootpath = apr_pstrdup(p, path);
+    return APR_SUCCESS;
+}
+
+
+apr_status_t filepath_root_case(char **rootpath, char *root, apr_pool_t *p)
+{
+    if (root[0] && apr_islower(root[0]) && root[1] == ':') {
+        *rootpath = apr_pstrdup(p, root);
+        (*rootpath)[0] = apr_toupper((*rootpath)[0]);
+    }
+    else {
+       *rootpath = root;
+    }
+    return APR_SUCCESS;
+}
+
+
+APR_DECLARE(apr_status_t) apr_filepath_get(char **defpath, apr_int32_t flags,
+                                           apr_pool_t *p)
+{
+    char path[APR_PATH_MAX];
+    ULONG drive;
+    ULONG drivemap;
+    ULONG rv, pathlen = sizeof(path) - 3;
+    char *pos;
+
+    DosQueryCurrentDisk(&drive, &drivemap);
+    path[0] = '@' + drive;
+    strcpy(path+1, ":\\");
+    rv = DosQueryCurrentDir(drive, path+3, &pathlen);
+
+    *defpath = apr_pstrdup(p, path);
+
+    if (!(flags & APR_FILEPATH_NATIVE)) {
+        for (pos=*defpath; *pos; pos++) {
+            if (*pos == '\\')
+                *pos = '/';
+        }
+    }
+
+    return APR_SUCCESS;
+}    
+
+
+
+APR_DECLARE(apr_status_t) apr_filepath_set(const char *path, apr_pool_t *p)
+{
+    ULONG rv = 0;
+
+    if (path[1] == ':')
+        rv = DosSetDefaultDisk(apr_toupper(path[0]) - '@');
+
+    if (rv == 0)
+        rv = DosSetCurrentDir(path);
+
+    return APR_FROM_OS_ERROR(rv);
+}
diff --git a/file_io/os2/flock.c b/file_io/os2/flock.c
new file mode 100644
index 00000000000..ec94022081a
--- /dev/null
+++ b/file_io/os2/flock.c
@@ -0,0 +1,37 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_arch_file_io.h"
+
+APR_DECLARE(apr_status_t) apr_file_lock(apr_file_t *thefile, int type)
+{
+    FILELOCK lockrange = { 0, 0x7fffffff };
+    ULONG rc;
+
+    rc = DosSetFileLocks(thefile->filedes, NULL, &lockrange,
+                         (type & APR_FLOCK_NONBLOCK) ? 0 : (ULONG)-1,
+                         (type & APR_FLOCK_TYPEMASK) == APR_FLOCK_SHARED);
+    return APR_FROM_OS_ERROR(rc);
+}
+
+APR_DECLARE(apr_status_t) apr_file_unlock(apr_file_t *thefile)
+{
+    FILELOCK unlockrange = { 0, 0x7fffffff };
+    ULONG rc;
+
+    rc = DosSetFileLocks(thefile->filedes, &unlockrange, NULL, 0, 0);
+    return APR_FROM_OS_ERROR(rc);
+}
diff --git a/file_io/os2/fullrw.c b/file_io/os2/fullrw.c
new file mode 100644
index 00000000000..cf6294882b4
--- /dev/null
+++ b/file_io/os2/fullrw.c
@@ -0,0 +1 @@
+#include "../unix/fullrw.c"
diff --git a/file_io/os2/link.c b/file_io/os2/link.c
new file mode 100644
index 00000000000..5487df17c45
--- /dev/null
+++ b/file_io/os2/link.c
@@ -0,0 +1,23 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_arch_file_io.h"
+
+APR_DECLARE(apr_status_t) apr_file_link(const char *from_path, const char *to_path)
+{
+    /* OS/2 doesn't support links */
+    return APR_ENOTIMPL;
+}
diff --git a/file_io/os2/maperrorcode.c b/file_io/os2/maperrorcode.c
index 209eec026bc..282338bba03 100644
--- a/file_io/os2/maperrorcode.c
+++ b/file_io/os2/maperrorcode.c
@@ -1,65 +1,25 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
 #define INCL_DOSERRORS
-#include "fileio.h"
+#include "apr_arch_file_io.h"
 #include "apr_file_io.h"
 #include <errno.h>
 #include <string.h>
-#include <os2.h>
-#include "../../network_io/os2/os2calls.h"
-
+#include "apr_errno.h"
 
 static int errormap[][2] = {
     { NO_ERROR,                   APR_SUCCESS      },
@@ -115,7 +75,7 @@ static int errormap[][2] = {
 
 #define MAPSIZE (sizeof(errormap)/sizeof(errormap[0]))
 
-int ap_canonical_error(ap_status_t err)
+int apr_canonical_error(apr_status_t err)
 {
     int rv = -1, index;
 
@@ -129,7 +89,7 @@ int ap_canonical_error(ap_status_t err)
     if (index<MAPSIZE)
         rv = errormap[index][1];
     else
-        fprintf(stderr, "ap_canonical_error: Unknown OS/2 error code %d\n", err );
+        fprintf(stderr, "apr_canonical_error: Unknown OS/2 error code %d\n", err );
         
     return rv;
 }
diff --git a/file_io/os2/mktemp.c b/file_io/os2/mktemp.c
new file mode 100644
index 00000000000..9e8523607f1
--- /dev/null
+++ b/file_io/os2/mktemp.c
@@ -0,0 +1 @@
+#include "../unix/mktemp.c"
diff --git a/file_io/os2/open.c b/file_io/os2/open.c
index b65805c546b..996e68bb994 100644
--- a/file_io/os2/open.c
+++ b/file_io/os2/open.c
@@ -1,132 +1,101 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "fileio.h"
+#include "apr_arch_file_io.h"
 #include "apr_file_io.h"
 #include "apr_lib.h"
 #include "apr_portable.h"
+#include "apr_strings.h"
+#include "apr_arch_inherit.h"
 #include <string.h>
 
-#define INCL_DOS
-#include <os2.h>
-
-ap_status_t apr_file_cleanup(void *thefile)
+apr_status_t apr_file_cleanup(void *thefile)
 {
-    ap_file_t *file = thefile;
-    return ap_close(file);
+    apr_file_t *file = thefile;
+    return apr_file_close(file);
 }
 
 
 
-ap_status_t ap_open(ap_file_t **new, const char *fname, ap_int32_t flag,  ap_fileperms_t perm, ap_pool_t *cntxt)
+APR_DECLARE(apr_status_t) apr_file_open(apr_file_t **new, const char *fname, apr_int32_t flag,  apr_fileperms_t perm, apr_pool_t *pool)
 {
     int oflags = 0;
-    int mflags = OPEN_FLAGS_FAIL_ON_ERROR|OPEN_SHARE_DENYNONE;
+    int mflags = OPEN_FLAGS_FAIL_ON_ERROR|OPEN_SHARE_DENYNONE|OPEN_FLAGS_NOINHERIT;
     int rv;
     ULONG action;
-    ap_file_t *dafile = (ap_file_t *)ap_palloc(cntxt, sizeof(ap_file_t));
+    apr_file_t *dafile = (apr_file_t *)apr_pcalloc(pool, sizeof(apr_file_t));
 
-    *new = dafile;
-    dafile->cntxt = cntxt;
+    if (flag & APR_FOPEN_NONBLOCK) {
+        return APR_ENOTIMPL;
+    }
+
+    dafile->pool = pool;
     dafile->isopen = FALSE;
     dafile->eof_hit = FALSE;
     dafile->buffer = NULL;
     dafile->flags = flag;
+    dafile->blocking = BLK_ON;
+    dafile->ungetchar = -1;
     
-    if ((flag & APR_READ) && (flag & APR_WRITE)) {
+    if ((flag & APR_FOPEN_READ) && (flag & APR_FOPEN_WRITE)) {
         mflags |= OPEN_ACCESS_READWRITE;
-    } else if (flag & APR_READ) {
+    } else if (flag & APR_FOPEN_READ) {
         mflags |= OPEN_ACCESS_READONLY;
-    } else if (flag & APR_WRITE) {
+    } else if (flag & APR_FOPEN_WRITE) {
         mflags |= OPEN_ACCESS_WRITEONLY;
     } else {
         dafile->filedes = -1;
         return APR_EACCES;
     }
 
-    dafile->buffered = (flag & APR_BUFFERED) > 0;
+    dafile->buffered = (flag & APR_FOPEN_BUFFERED) > 0;
 
     if (dafile->buffered) {
-        dafile->buffer = ap_palloc(cntxt, APR_FILE_BUFSIZE);
-        rv = ap_create_lock(&dafile->mutex, APR_MUTEX, APR_INTRAPROCESS, NULL, cntxt);
+        dafile->buffer = apr_palloc(pool, APR_FILE_DEFAULT_BUFSIZE);
+        dafile->bufsize = APR_FILE_DEFAULT_BUFSIZE;
 
-        if (rv)
-            return APR_OS2_STATUS(rv);
+        if (flag & APR_FOPEN_XTHREAD) {
+            rv = apr_thread_mutex_create(&dafile->mutex, 0, pool);
+
+            if (rv) {
+                return rv;
+            }
+        }
     }
 
-    if (flag & APR_CREATE) {
-        oflags |= OPEN_ACTION_CREATE_IF_NEW; 
-        if (!(flag & APR_EXCL)) {
-            if (flag & APR_APPEND)
-                oflags |= OPEN_ACTION_OPEN_IF_EXISTS;
-            else
-                oflags |= OPEN_ACTION_REPLACE_IF_EXISTS;
+    if (flag & APR_FOPEN_CREATE) {
+        oflags |= OPEN_ACTION_CREATE_IF_NEW;
+
+        if (!(flag & APR_FOPEN_EXCL) && !(flag & APR_FOPEN_TRUNCATE)) {
+            oflags |= OPEN_ACTION_OPEN_IF_EXISTS;
         }
     }
     
-    if ((flag & APR_EXCL) && !(flag & APR_CREATE))
+    if ((flag & APR_FOPEN_EXCL) && !(flag & APR_FOPEN_CREATE))
         return APR_EACCES;
 
-    if (flag & APR_TRUNCATE) {
+    if (flag & APR_FOPEN_TRUNCATE) {
         oflags |= OPEN_ACTION_REPLACE_IF_EXISTS;
-    } else if ((oflags & 0xF) == 0) {
+    } else if ((oflags & 0xFF) == 0) {
         oflags |= OPEN_ACTION_OPEN_IF_EXISTS;
     }
     
     rv = DosOpen(fname, &(dafile->filedes), &action, 0, 0, oflags, mflags, NULL);
     
-    if (rv == 0 && (flag & APR_APPEND)) {
+    if (rv == 0 && (flag & APR_FOPEN_APPEND)) {
         ULONG newptr;
         rv = DosSetFilePtr(dafile->filedes, 0, FILE_END, &newptr );
         
@@ -135,90 +104,123 @@ ap_status_t ap_open(ap_file_t **new, const char *fname, ap_int32_t flag,  ap_fil
     }
     
     if (rv != 0)
-        return APR_OS2_STATUS(rv);
+        return APR_FROM_OS_ERROR(rv);
     
     dafile->isopen = TRUE;
-    dafile->fname = ap_pstrdup(cntxt, fname);
+    dafile->fname = apr_pstrdup(pool, fname);
     dafile->filePtr = 0;
     dafile->bufpos = 0;
     dafile->dataRead = 0;
     dafile->direction = 0;
     dafile->pipe = FALSE;
 
-    ap_register_cleanup(dafile->cntxt, dafile, apr_file_cleanup, ap_null_cleanup);
+    if (!(flag & APR_FOPEN_NOCLEANUP)) {
+        apr_pool_cleanup_register(dafile->pool, dafile, apr_file_cleanup, apr_file_cleanup);
+    }
+
+    *new = dafile;
     return APR_SUCCESS;
 }
 
 
 
-ap_status_t ap_close(ap_file_t *file)
+APR_DECLARE(apr_status_t) apr_file_close(apr_file_t *file)
 {
     ULONG rc;
-    ap_status_t status;
+    apr_status_t status;
     
     if (file && file->isopen) {
-        ap_flush(file);
+        status = apr_file_flush(file);
         rc = DosClose(file->filedes);
     
         if (rc == 0) {
             file->isopen = FALSE;
-            status = APR_SUCCESS;
 
-            if (file->flags & APR_DELONCLOSE) {
-                status = APR_OS2_STATUS(DosDelete(file->fname));
+            if (file->flags & APR_FOPEN_DELONCLOSE) {
+                status = APR_FROM_OS_ERROR(DosDelete(file->fname));
             }
+            /* else we return the status of the flush attempt 
+             * when all else succeeds
+             */
         } else {
-            return APR_OS2_STATUS(rc);
+            return APR_FROM_OS_ERROR(rc);
         }
     }
 
-    if (file->buffered)
-        ap_destroy_lock(file->mutex);
+    if (file->mutex) {
+        apr_thread_mutex_destroy(file->mutex);
+        file->mutex = NULL;
+    }
 
-    return APR_SUCCESS;
+    return status;
 }
 
 
 
-ap_status_t ap_remove_file(char *path, ap_pool_t *cntxt)
+APR_DECLARE(apr_status_t) apr_file_remove(const char *path, apr_pool_t *pool)
 {
     ULONG rc = DosDelete(path);
-    return APR_OS2_STATUS(rc);
+    return APR_FROM_OS_ERROR(rc);
 }
 
 
 
-ap_status_t ap_get_os_file(ap_os_file_t *thefile, ap_file_t *file)
+APR_DECLARE(apr_status_t) apr_file_rename(const char *from_path, const char *to_path,
+                                   apr_pool_t *p)
 {
-    if (file == NULL) {
-        return APR_ENOFILE;
+    ULONG rc = DosMove(from_path, to_path);
+
+    if (rc == ERROR_ACCESS_DENIED || rc == ERROR_ALREADY_EXISTS) {
+        rc = DosDelete(to_path);
+
+        if (rc == 0 || rc == ERROR_FILE_NOT_FOUND) {
+            rc = DosMove(from_path, to_path);
+        }
     }
 
+    return APR_FROM_OS_ERROR(rc);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_os_file_get(apr_os_file_t *thefile, apr_file_t *file)
+{
     *thefile = file->filedes;
     return APR_SUCCESS;
 }
 
 
 
-ap_status_t ap_put_os_file(ap_file_t **file, ap_os_file_t *thefile, ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_os_file_put(apr_file_t **file, apr_os_file_t *thefile, apr_int32_t flags, apr_pool_t *pool)
 {
-    ap_os_file_t *dafile = thefile;
-    if ((*file) == NULL) {
-        (*file) = (ap_file_t *)ap_palloc(cont, sizeof(ap_file_t));
-        (*file)->cntxt = cont;
-    }
+    apr_os_file_t *dafile = thefile;
+
+    (*file) = apr_palloc(pool, sizeof(apr_file_t));
+    (*file)->pool = pool;
     (*file)->filedes = *dafile;
     (*file)->isopen = TRUE;
-    (*file)->buffered = FALSE;
     (*file)->eof_hit = FALSE;
-    (*file)->flags = 0;
+    (*file)->flags = flags;
     (*file)->pipe = FALSE;
+    (*file)->buffered = (flags & APR_FOPEN_BUFFERED) > 0;
+    (*file)->ungetchar = -1;
+
+    if ((*file)->buffered) {
+        apr_status_t rv;
+
+        (*file)->buffer = apr_palloc(pool, APR_FILE_DEFAULT_BUFSIZE);
+        (*file)->bufsize = APR_FILE_DEFAULT_BUFSIZE;
+        rv = apr_thread_mutex_create(&(*file)->mutex, 0, pool);
+
+        if (rv)
+            return rv;
+    }
+
     return APR_SUCCESS;
 }    
 
 
-
-ap_status_t ap_eof(ap_file_t *fptr)
+APR_DECLARE(apr_status_t) apr_file_eof(apr_file_t *fptr)
 {
     if (!fptr->isopen || fptr->eof_hit == 1) {
         return APR_EOF;
@@ -227,21 +229,85 @@ ap_status_t ap_eof(ap_file_t *fptr)
 }   
 
 
+APR_DECLARE(apr_status_t) apr_file_open_flags_stderr(apr_file_t **thefile, 
+                                                     apr_int32_t flags,
+                                                     apr_pool_t *pool)
+{
+    apr_os_file_t fd = 2;
+
+    return apr_os_file_put(thefile, &fd, flags | APR_FOPEN_WRITE, pool);
+}
+
+
+APR_DECLARE(apr_status_t) apr_file_open_flags_stdout(apr_file_t **thefile, 
+                                                     apr_int32_t flags,
+                                                     apr_pool_t *pool)
+{
+    apr_os_file_t fd = 1;
+
+    return apr_os_file_put(thefile, &fd, flags | APR_FOPEN_WRITE, pool);
+}
+
+
+APR_DECLARE(apr_status_t) apr_file_open_flags_stdin(apr_file_t **thefile, 
+                                                    apr_int32_t flags,
+                                                    apr_pool_t *pool)
+{
+    apr_os_file_t fd = 0;
+
+    return apr_os_file_put(thefile, &fd, flags | APR_FOPEN_READ, pool);
+}
+
+
+APR_DECLARE(apr_status_t) apr_file_open_stderr(apr_file_t **thefile, apr_pool_t *pool)
+{
+    return apr_file_open_flags_stderr(thefile, 0, pool);
+}
+
+
+APR_DECLARE(apr_status_t) apr_file_open_stdout(apr_file_t **thefile, apr_pool_t *pool)
+{
+    return apr_file_open_flags_stdout(thefile, 0, pool);
+}
+
+
+APR_DECLARE(apr_status_t) apr_file_open_stdin(apr_file_t **thefile, apr_pool_t *pool)
+{
+    return apr_file_open_flags_stdin(thefile, 0, pool);
+}
+
+APR_POOL_IMPLEMENT_ACCESSOR(file);
+
 
-ap_status_t ap_open_stderr(ap_file_t **thefile, ap_pool_t *cont)
+
+APR_DECLARE(apr_status_t) apr_file_inherit_set(apr_file_t *thefile)
 {
-    (*thefile) = ap_palloc(cont, sizeof(ap_file_t));
-    if ((*thefile) == NULL) {
-        return APR_ENOMEM;
+    int rv;
+    ULONG state;
+
+    rv = DosQueryFHState(thefile->filedes, &state);
+
+    if (rv == 0 && (state & OPEN_FLAGS_NOINHERIT) != 0) {
+        state &= OPEN_FLAGS_WRITE_THROUGH|OPEN_FLAGS_FAIL_ON_ERROR|OPEN_FLAGS_NO_CACHE;
+        rv = DosSetFHState(thefile->filedes, state);
     }
-    (*thefile)->cntxt = cont;
-    (*thefile)->filedes = 2;
-    (*thefile)->fname = NULL;
-    (*thefile)->isopen = TRUE;
-    (*thefile)->buffered = FALSE;
-    (*thefile)->eof_hit = FALSE;
-    (*thefile)->flags = 0;
-    (*thefile)->pipe = FALSE;
 
-    return APR_SUCCESS;
+    return APR_FROM_OS_ERROR(rv);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_file_inherit_unset(apr_file_t *thefile)
+{
+    int rv;
+    ULONG state;
+
+    rv = DosQueryFHState(thefile->filedes, &state);
+
+    if (rv == 0 && (state & OPEN_FLAGS_NOINHERIT) == 0) {
+        state &= OPEN_FLAGS_WRITE_THROUGH|OPEN_FLAGS_FAIL_ON_ERROR|OPEN_FLAGS_NO_CACHE;
+        rv = DosSetFHState(thefile->filedes, state | OPEN_FLAGS_NOINHERIT);
+    }
+
+    return APR_FROM_OS_ERROR(rv);
 }
diff --git a/file_io/os2/pipe.c b/file_io/os2/pipe.c
index 4ec94a889d8..4dbe30dbf33 100644
--- a/file_io/os2/pipe.c
+++ b/file_io/os2/pipe.c
@@ -1,66 +1,31 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
 #define INCL_DOSERRORS
-#include "fileio.h"
+#include "apr_arch_file_io.h"
 #include "apr_file_io.h"
 #include "apr_general.h"
 #include "apr_lib.h"
+#include "apr_strings.h"
+#include "apr_portable.h"
 #include <string.h>
 #include <process.h>
 
-ap_status_t ap_create_pipe(ap_file_t **in, ap_file_t **out, ap_pool_t *cont)
+static apr_status_t file_pipe_create(apr_file_t **in, apr_file_t **out,
+        apr_pool_t *pool_in, apr_pool_t *pool_out)
 {
     ULONG filedes[2];
     ULONG rc, action;
@@ -71,13 +36,13 @@ ap_status_t ap_create_pipe(ap_file_t **in, ap_file_t **out, ap_pool_t *cont)
     rc = DosCreateNPipe(pipename, filedes, NP_ACCESS_INBOUND, NP_NOWAIT|1, 4096, 4096, 0);
 
     if (rc)
-        return APR_OS2_STATUS(rc);
+        return APR_FROM_OS_ERROR(rc);
 
     rc = DosConnectNPipe(filedes[0]);
 
     if (rc && rc != ERROR_PIPE_NOT_CONNECTED) {
         DosClose(filedes[0]);
-        return APR_OS2_STATUS(rc);
+        return APR_FROM_OS_ERROR(rc);
     }
 
     rc = DosOpen (pipename, filedes+1, &action, 0, FILE_NORMAL,
@@ -87,54 +52,121 @@ ap_status_t ap_create_pipe(ap_file_t **in, ap_file_t **out, ap_pool_t *cont)
 
     if (rc) {
         DosClose(filedes[0]);
-        return APR_OS2_STATUS(rc);
+        return APR_FROM_OS_ERROR(rc);
     }
 
-    (*in) = (ap_file_t *)ap_palloc(cont, sizeof(ap_file_t));
+    (*in) = (apr_file_t *)apr_palloc(pool_in, sizeof(apr_file_t));
     rc = DosCreateEventSem(NULL, &(*in)->pipeSem, DC_SEM_SHARED, FALSE);
 
     if (rc) {
         DosClose(filedes[0]);
         DosClose(filedes[1]);
-        return APR_OS2_STATUS(rc);
+        return APR_FROM_OS_ERROR(rc);
     }
 
     rc = DosSetNPipeSem(filedes[0], (HSEM)(*in)->pipeSem, 1);
 
+    if (!rc) {
+        rc = DosSetNPHState(filedes[0], NP_WAIT);
+    }
+
     if (rc) {
         DosClose(filedes[0]);
         DosClose(filedes[1]);
         DosCloseEventSem((*in)->pipeSem);
-        return APR_OS2_STATUS(rc);
+        return APR_FROM_OS_ERROR(rc);
     }
 
-    (*in)->cntxt = cont;
+    (*in)->pool = pool_in;
     (*in)->filedes = filedes[0];
-    (*in)->fname = ap_pstrdup(cont, pipename);
+    (*in)->fname = apr_pstrdup(pool_in, pipename);
     (*in)->isopen = TRUE;
     (*in)->buffered = FALSE;
-    (*in)->flags = 0;
+    (*in)->flags = APR_FOPEN_READ;
     (*in)->pipe = 1;
     (*in)->timeout = -1;
-    ap_register_cleanup(cont, *in, apr_file_cleanup, ap_null_cleanup);
+    (*in)->blocking = BLK_ON;
+    (*in)->ungetchar = -1;
+    apr_pool_cleanup_register(pool_in, *in, apr_file_cleanup,
+            apr_pool_cleanup_null);
+
+    (*out) = (apr_file_t *)apr_palloc(pool_out, sizeof(apr_file_t));
+    rc = DosCreateEventSem(NULL, &(*out)->pipeSem, DC_SEM_SHARED, FALSE);
+
+    if (rc) {
+        DosClose(filedes[0]);
+        DosClose(filedes[1]);
+        DosCloseEventSem((*in)->pipeSem);
+        return APR_FROM_OS_ERROR(rc);
+    }
+
+    rc = DosSetNPipeSem(filedes[1], (HSEM)(*out)->pipeSem, 1);
 
-    (*out) = (ap_file_t *)ap_palloc(cont, sizeof(ap_file_t));
-    (*out)->cntxt = cont;
+    if (rc) {
+        DosClose(filedes[0]);
+        DosClose(filedes[1]);
+        DosCloseEventSem((*in)->pipeSem);
+        DosCloseEventSem((*out)->pipeSem);
+        return APR_FROM_OS_ERROR(rc);
+    }
+
+    (*out)->pool = pool_out;
     (*out)->filedes = filedes[1];
-    (*out)->fname = ap_pstrdup(cont, pipename);
+    (*out)->fname = apr_pstrdup(pool_out, pipename);
     (*out)->isopen = TRUE;
     (*out)->buffered = FALSE;
-    (*out)->flags = 0;
+    (*out)->flags = APR_FOPEN_WRITE;
     (*out)->pipe = 1;
     (*out)->timeout = -1;
-    ap_register_cleanup(cont, *out, apr_file_cleanup, ap_null_cleanup);
-
+    (*out)->blocking = BLK_ON;
+    (*out)->ungetchar = -1;
+    apr_pool_cleanup_register(pool_out, *out, apr_file_cleanup,
+            apr_pool_cleanup_null);
+
+    switch (blocking) {
+    case APR_FULL_BLOCK:
+        break;
+    case APR_READ_BLOCK:
+        apr_file_pipe_timeout_set(*out, 0);
+        break;
+    case APR_WRITE_BLOCK:
+        apr_file_pipe_timeout_set(*in, 0);
+        break;
+    default:
+        apr_file_pipe_timeout_set(*out, 0);
+        apr_file_pipe_timeout_set(*in, 0);
+        break;
+    }
     return APR_SUCCESS;
 }
 
+APR_DECLARE(apr_status_t) apr_file_pipe_create(apr_file_t **in,
+                                               apr_file_t **out,
+                                               apr_pool_t *pool)
+{
+    /* Default is full blocking pipes. */
+    return file_pipe_create(in, out, APR_FULL_BLOCK, pool, pool);
+}
 
+APR_DECLARE(apr_status_t) apr_file_pipe_create_ex(apr_file_t **in, 
+                                                  apr_file_t **out, 
+                                                  apr_int32_t blocking,
+                                                  apr_pool_t *pool)
+{
+    return file_pipe_create(in, out, blocking, pool, pool);
+}
 
-ap_status_t ap_create_namedpipe(char *filename, ap_fileperms_t perm, ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_file_pipe_create_pools(apr_file_t **in,
+                                                     apr_file_t **out,
+                                                     apr_int32_t blocking,
+                                                     apr_pool_t *pool_in,
+                                                     apr_pool_t *pool_out)
+{
+    return file_pipe_create(in, out, blocking, pool_in, pool_out);
+}
+    
+    
+APR_DECLARE(apr_status_t) apr_file_namedpipe_create(const char *filename, apr_fileperms_t perm, apr_pool_t *pool)
 {
     /* Not yet implemented, interface not suitable */
     return APR_ENOTIMPL;
@@ -142,17 +174,73 @@ ap_status_t ap_create_namedpipe(char *filename, ap_fileperms_t perm, ap_pool_t *
 
  
 
-ap_status_t ap_set_pipe_timeout(ap_file_t *thepipe, ap_interval_time_t timeout)
+APR_DECLARE(apr_status_t) apr_file_pipe_timeout_set(apr_file_t *thepipe, apr_interval_time_t timeout)
 {
+    apr_status_t rv = APR_SUCCESS;
+
     if (thepipe->pipe == 1) {
         thepipe->timeout = timeout;
+
+        if (thepipe->timeout >= 0) {
+            if (thepipe->blocking != BLK_OFF) {
+                thepipe->blocking = BLK_OFF;
+                return APR_FROM_OS_ERROR(DosSetNPHState(thepipe->filedes, NP_NOWAIT));
+            }
+        }
+        else if (thepipe->timeout == -1) {
+            if (thepipe->blocking != BLK_ON) {
+                thepipe->blocking = BLK_ON;
+                return APR_FROM_OS_ERROR(DosSetNPHState(thepipe->filedes, NP_WAIT));
+            }
+        }
+    }
+    else {
+        rv = APR_EINVAL;
+    }
+
+    return rv;
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_file_pipe_timeout_get(apr_file_t *thepipe, apr_interval_time_t *timeout)
+{
+    if (thepipe->pipe == 1) {
+        *timeout = thepipe->timeout;
         return APR_SUCCESS;
     }
     return APR_EINVAL;
 }
 
 
-ap_status_t ap_block_pipe(ap_file_t *thepipe)
+
+APR_DECLARE(apr_status_t) apr_os_pipe_put_ex(apr_file_t **file,
+                                             apr_os_file_t *thefile,
+                                             int register_cleanup,
+                                             apr_pool_t *pool)
+{
+    (*file) = apr_pcalloc(pool, sizeof(apr_file_t));
+    (*file)->pool = pool;
+    (*file)->isopen = TRUE;
+    (*file)->pipe = 1;
+    (*file)->blocking = BLK_UNKNOWN; /* app needs to make a timeout call */
+    (*file)->timeout = -1;
+    (*file)->ungetchar = -1;
+    (*file)->filedes = *thefile;
+
+    if (register_cleanup) {
+        apr_pool_cleanup_register(pool, *file, apr_file_cleanup,
+                                  apr_pool_cleanup_null);
+    }
+
+    return APR_SUCCESS;
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_os_pipe_put(apr_file_t **file,
+                                          apr_os_file_t *thefile,
+                                          apr_pool_t *pool)
 {
-    return APR_OS2_STATUS(DosSetNPHState (thepipe->filedes, NP_WAIT));
+    return apr_os_pipe_put_ex(file, thefile, 0, pool);
 }
diff --git a/file_io/os2/printf.c b/file_io/os2/printf.c
new file mode 100644
index 00000000000..a77d258905d
--- /dev/null
+++ b/file_io/os2/printf.c
@@ -0,0 +1 @@
+#include "../unix/printf.c"
diff --git a/file_io/os2/readwrite.c b/file_io/os2/readwrite.c
index d63ae181353..d567ef3a5c0 100644
--- a/file_io/os2/readwrite.c
+++ b/file_io/os2/readwrite.c
@@ -1,86 +1,80 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
 #define INCL_DOS
 #define INCL_DOSERRORS
 
-#include "fileio.h"
+#include "apr_arch_file_io.h"
 #include "apr_file_io.h"
 #include "apr_lib.h"
+#include "apr_strings.h"
 
-#include <os2.h>
 #include <malloc.h>
 
-ap_status_t ap_read(ap_file_t *thefile, void *buf, ap_ssize_t *nbytes)
+static void file_lock(apr_file_t *thefile)
+{
+    if (thefile->mutex && thefile->buffered) {
+        apr_thread_mutex_lock(thefile->mutex);
+    }
+}
+
+
+
+static void file_unlock(apr_file_t *thefile)
+{
+    if (thefile->mutex && thefile->buffered) {
+        apr_thread_mutex_unlock(thefile->mutex);
+    }
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_file_read(apr_file_t *thefile, void *buf, apr_size_t *nbytes)
 {
     ULONG rc = 0;
     ULONG bytesread;
+    apr_size_t req_nbytes = *nbytes;
 
     if (!thefile->isopen) {
         *nbytes = 0;
         return APR_EBADF;
     }
 
+    if (thefile->ungetchar != -1 && req_nbytes >= 1) {
+        *(char *)buf = (char)thefile->ungetchar;
+        thefile->ungetchar = -1;
+        (*nbytes) = 1;
+        return APR_SUCCESS;
+    }
+
     if (thefile->buffered) {
         char *pos = (char *)buf;
         ULONG blocksize;
         ULONG size = *nbytes;
 
-        ap_lock(thefile->mutex);
+        file_lock(thefile);
 
         if (thefile->direction == 1) {
-            ap_flush(thefile);
+            int rv = apr_file_flush(thefile);
+
+            if (rv != APR_SUCCESS) {
+                file_unlock(thefile);
+                return rv;
+            }
+
             thefile->bufpos = 0;
             thefile->direction = 0;
             thefile->dataRead = 0;
@@ -88,12 +82,17 @@ ap_status_t ap_read(ap_file_t *thefile, void *buf, ap_ssize_t *nbytes)
 
         while (rc == 0 && size > 0) {
             if (thefile->bufpos >= thefile->dataRead) {
-                rc = DosRead(thefile->filedes, thefile->buffer, APR_FILE_BUFSIZE, &thefile->dataRead );
-                if (thefile->dataRead == 0) {
+                ULONG bytesread;
+                rc = DosRead(thefile->filedes, thefile->buffer,
+                             thefile->bufsize, &bytesread);
+
+                if (bytesread == 0) {
                     if (rc == 0)
                         thefile->eof_hit = TRUE;
                     break;
                 }
+
+                thefile->dataRead = bytesread;
                 thefile->filePtr += thefile->dataRead;
                 thefile->bufpos = 0;
             }
@@ -106,8 +105,13 @@ ap_status_t ap_read(ap_file_t *thefile, void *buf, ap_ssize_t *nbytes)
         }
 
         *nbytes = rc == 0 ? pos - (char *)buf : 0;
-        ap_unlock(thefile->mutex);
-        return APR_OS2_STATUS(rc);
+        file_unlock(thefile);
+
+        if (*nbytes == 0 && rc == 0 && thefile->eof_hit) {
+            return APR_EOF;
+        }
+
+        return APR_FROM_OS_ERROR(rc);
     } else {
         if (thefile->pipe)
             DosResetEventSem(thefile->pipeSem, &rc);
@@ -117,19 +121,25 @@ ap_status_t ap_read(ap_file_t *thefile, void *buf, ap_ssize_t *nbytes)
         if (rc == ERROR_NO_DATA && thefile->timeout != 0) {
             int rcwait = DosWaitEventSem(thefile->pipeSem, thefile->timeout >= 0 ? thefile->timeout / 1000 : SEM_INDEFINITE_WAIT);
 
-            if (rcwait == 0)
+            if (rcwait == 0) {
                 rc = DosRead(thefile->filedes, buf, *nbytes, &bytesread);
+            }
+            else if (rcwait == ERROR_TIMEOUT) {
+                *nbytes = 0;
+                return APR_TIMEUP;
+            }
         }
 
         if (rc) {
             *nbytes = 0;
-            return APR_OS2_STATUS(rc);
+            return APR_FROM_OS_ERROR(rc);
         }
 
         *nbytes = bytesread;
         
-        if (bytesread == 0) {
+        if (bytesread == 0 && req_nbytes > 0) {
             thefile->eof_hit = TRUE;
+            return APR_EOF;
         }
 
         return APR_SUCCESS;
@@ -138,7 +148,7 @@ ap_status_t ap_read(ap_file_t *thefile, void *buf, ap_ssize_t *nbytes)
 
 
 
-ap_status_t ap_write(ap_file_t *thefile, void *buf, ap_ssize_t *nbytes)
+APR_DECLARE(apr_status_t) apr_file_write(apr_file_t *thefile, const void *buf, apr_size_t *nbytes)
 {
     ULONG rc = 0;
     ULONG byteswritten;
@@ -152,11 +162,12 @@ ap_status_t ap_write(ap_file_t *thefile, void *buf, ap_ssize_t *nbytes)
         char *pos = (char *)buf;
         int blocksize;
         int size = *nbytes;
+        apr_status_t rv = APR_SUCCESS;
 
-        DosEnterCritSec();
+        file_lock(thefile);
 
         if ( thefile->direction == 0 ) {
-            // Position file pointer for writing at the offset we are logically reading from
+            /* Position file pointer for writing at the offset we are logically reading from */
             ULONG offset = thefile->filePtr - thefile->dataRead + thefile->bufpos;
             if (offset != thefile->filePtr)
                 DosSetFilePtr(thefile->filedes, offset, FILE_BEGIN, &thefile->filePtr );
@@ -164,25 +175,62 @@ ap_status_t ap_write(ap_file_t *thefile, void *buf, ap_ssize_t *nbytes)
             thefile->direction = 1;
         }
 
-        while (rc == 0 && size > 0) {
-            if (thefile->bufpos == APR_FILE_BUFSIZE)   // write buffer is full
-                ap_flush(thefile);
+        while (rv == APR_SUCCESS && size > 0) {
+            if (thefile->bufpos == thefile->bufsize) {
+                /* write buffer is full */
+                rv = apr_file_flush(thefile);
+            }
 
-            blocksize = size > APR_FILE_BUFSIZE - thefile->bufpos ? APR_FILE_BUFSIZE - thefile->bufpos : size;
+            blocksize = size > thefile->bufsize - thefile->bufpos ? thefile->bufsize - thefile->bufpos : size;
             memcpy(thefile->buffer + thefile->bufpos, pos, blocksize);
             thefile->bufpos += blocksize;
             pos += blocksize;
             size -= blocksize;
         }
 
-        DosExitCritSec();
-        return APR_OS2_STATUS(rc);
+        file_unlock(thefile);
+        return rv;
     } else {
-        rc = DosWrite(thefile->filedes, buf, *nbytes, &byteswritten);
+        if (thefile->pipe) {
+            DosResetEventSem(thefile->pipeSem, &rc);
+        }
+
+        if (thefile->flags & APR_FOPEN_APPEND) {
+            FILELOCK all = { 0, 0x7fffffff };
+            ULONG newpos;
+            rc = DosSetFileLocks(thefile->filedes, NULL, &all, -1, 0);
+
+            if (rc == 0) {
+                rc = DosSetFilePtr(thefile->filedes, 0, FILE_END, &newpos);
+
+                if (rc == 0) {
+                    rc = DosWrite(thefile->filedes, buf, *nbytes, &byteswritten);
+                }
+
+                DosSetFileLocks(thefile->filedes, &all, NULL, -1, 0);
+            }
+        } else {
+            rc = DosWrite(thefile->filedes, buf, *nbytes, &byteswritten);
+
+            if (thefile->pipe && rc == 0 && *nbytes > 0 && byteswritten == 0) {
+                /* Pipe is full, wait or timeout */
+                int rcwait = DosWaitEventSem(thefile->pipeSem, thefile->timeout >= 0 ? thefile->timeout / 1000 : SEM_INDEFINITE_WAIT);
+
+                if (rcwait == 0) {
+                    rc = DosWrite(thefile->filedes, buf, *nbytes, &byteswritten);
+                }
+                else if (rcwait == ERROR_TIMEOUT) {
+                    return APR_TIMEUP;
+                }
+                else {
+                    rc = rcwait;
+                }
+            }
+        }
 
         if (rc) {
             *nbytes = 0;
-            return APR_OS2_STATUS(rc);
+            return APR_FROM_OS_ERROR(rc);
         }
 
         *nbytes = byteswritten;
@@ -192,63 +240,51 @@ ap_status_t ap_write(ap_file_t *thefile, void *buf, ap_ssize_t *nbytes)
 
 
 
-#ifdef HAVE_WRITEV
-
-ap_status_t ap_writev(ap_file_t *thefile, const struct iovec *vec, ap_size_t nvec, ap_ssize_t *nbytes)
+APR_DECLARE(apr_status_t) apr_file_writev(apr_file_t *thefile, const struct iovec *vec, apr_size_t nvec, apr_size_t *nbytes)
 {
-    int bytes;
-    if ((bytes = writev(thefile->filedes, vec, nvec)) < 0) {
-        *nbytes = 0;
-        return errno;
-    }
-    else {
-        *nbytes = bytes;
-        return APR_SUCCESS;
-    }
+  int c;
+  apr_status_t rv = APR_SUCCESS;
+  apr_size_t written = 0;
+
+  for (c = 0; c < nvec && rv == APR_SUCCESS; c++) {
+      apr_size_t nbytes = vec[c].iov_len;
+      rv = apr_file_write(thefile, vec[c].iov_base, &nbytes);
+      written += nbytes;
+  }
+
+  *nbytes = written;
+  return rv;
 }
-#endif
 
 
 
-ap_status_t ap_putc(char ch, ap_file_t *thefile)
+APR_DECLARE(apr_status_t) apr_file_putc(char ch, apr_file_t *thefile)
 {
-    ULONG rc;
-    ULONG byteswritten;
+    apr_size_t nbytes = 1;
 
-    if (!thefile->isopen) {
-        return APR_EBADF;
-    }
-
-    rc = DosWrite(thefile->filedes, &ch, 1, &byteswritten);
-
-    if (rc) {
-        return APR_OS2_STATUS(rc);
-    }
-    
-    return APR_SUCCESS;
+    return apr_file_write(thefile, &ch, &nbytes);
 }
 
 
 
-ap_status_t ap_ungetc(char ch, ap_file_t *thefile)
+APR_DECLARE(apr_status_t) apr_file_ungetc(char ch, apr_file_t *thefile)
 {
-    ap_off_t offset = -1;
-    return ap_seek(thefile, APR_CUR, &offset);
+    thefile->ungetchar = (unsigned char)ch;
+    return APR_SUCCESS;
 }
 
 
-
-ap_status_t ap_getc(char *ch, ap_file_t *thefile)
+APR_DECLARE(apr_status_t) apr_file_getc(char *ch, apr_file_t *thefile)
 {
     ULONG rc;
-    int bytesread;
+    apr_size_t bytesread;
 
     if (!thefile->isopen) {
         return APR_EBADF;
     }
 
     bytesread = 1;
-    rc = ap_read(thefile, ch, &bytesread);
+    rc = apr_file_read(thefile, ch, &bytesread);
 
     if (rc) {
         return rc;
@@ -264,31 +300,34 @@ ap_status_t ap_getc(char *ch, ap_file_t *thefile)
 
 
 
-ap_status_t ap_puts(char *str, ap_file_t *thefile)
+APR_DECLARE(apr_status_t) apr_file_puts(const char *str, apr_file_t *thefile)
 {
-    ap_ssize_t len;
+    apr_size_t len;
 
     len = strlen(str);
-    return ap_write(thefile, str, &len); 
+    return apr_file_write(thefile, str, &len); 
 }
 
 
-
-ap_status_t ap_flush(ap_file_t *thefile)
+APR_DECLARE(apr_status_t) apr_file_flush(apr_file_t *thefile)
 {
     if (thefile->buffered) {
         ULONG written = 0;
         int rc = 0;
 
         if (thefile->direction == 1 && thefile->bufpos) {
+            file_lock(thefile);
+
             rc = DosWrite(thefile->filedes, thefile->buffer, thefile->bufpos, &written);
             thefile->filePtr += written;
 
             if (rc == 0)
                 thefile->bufpos = 0;
+
+            file_unlock(thefile);
         }
 
-        return APR_OS2_STATUS(rc);
+        return APR_FROM_OS_ERROR(rc);
     } else {
         /* There isn't anything to do if we aren't buffering the output
          * so just return success.
@@ -297,51 +336,112 @@ ap_status_t ap_flush(ap_file_t *thefile)
     }
 }
 
+APR_DECLARE(apr_status_t) apr_file_sync(apr_file_t *thefile)
+{
+    apr_status_t rv;
+    int rc;
+
+    rv = apr_file_flush(thefile);
 
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
 
-ap_status_t ap_fgets(char *str, int len, ap_file_t *thefile)
+    rc = DosResetBuffer(thefile->filedes);
+    return APR_FROM_OS_ERROR(rc);
+}
+
+APR_DECLARE(apr_status_t) apr_file_datasync(apr_file_t *thefile)
 {
-    ssize_t readlen;
-    ap_status_t rv = APR_SUCCESS;
+    return apr_file_sync(thefile);
+}
+
+APR_DECLARE(apr_status_t) apr_file_gets(char *str, int len, apr_file_t *thefile)
+{
+    apr_size_t readlen;
+    apr_status_t rv = APR_SUCCESS;
     int i;    
 
     for (i = 0; i < len-1; i++) {
         readlen = 1;
-        rv = ap_read(thefile, str+i, &readlen);
+        rv = apr_file_read(thefile, str+i, &readlen);
+
+        if (rv != APR_SUCCESS) {
+            break;
+        }
 
         if (readlen != 1) {
             rv = APR_EOF;
             break;
         }
         
-        if (str[i] == '\r' || str[i] == '\x1A')
-            i--;
-        else if (str[i] == '\n')
+        if (str[i] == '\n') {
+            i++;
             break;
+        }
     }
     str[i] = 0;
+    if (i > 0) {
+        /* we stored chars; don't report EOF or any other errors;
+         * the app will find out about that on the next call
+         */
+        return APR_SUCCESS;
+    }
     return rv;
 }
 
 
 
-API_EXPORT(int) ap_fprintf(ap_file_t *fptr, const char *format, ...)
+apr_status_t apr_file_check_read(apr_file_t *fd)
+{
+    int rc;
+
+    if (!fd->pipe)
+        return APR_SUCCESS; /* Not a pipe, assume no waiting */
+
+    rc = DosWaitEventSem(fd->pipeSem, SEM_IMMEDIATE_RETURN);
+
+    if (rc == ERROR_TIMEOUT)
+        return APR_TIMEUP;
+
+    return APR_FROM_OS_ERROR(rc);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_file_pipe_wait(apr_file_t *pipe, apr_wait_type_t direction)
 {
-    int cc;
-    va_list ap;
-    char *buf;
-    int len;
-
-    buf = malloc(HUGE_STRING_LEN);
-    if (buf == NULL) {
-        return 0;
+    int rc;
+
+    if (!pipe->pipe) {
+        /* No support for waiting on a regular file */
+        return APR_ENOTIMPL;
     }
-    va_start(ap, format);
-    len = ap_vsnprintf(buf, HUGE_STRING_LEN, format, ap);
-    cc = ap_puts(buf, fptr);
-    va_end(ap);
-    free(buf);
-    return (cc == APR_SUCCESS) ? len : -1;
+
+    if (((pipe->flags & APR_FOPEN_READ) > 0) != (direction == APR_WAIT_READ)) {
+        /* Attempt to wait for read from the write end of the pipe or vica versa */
+        return APR_EINVAL;
+    }
+
+    rc = DosWaitEventSem(pipe->pipeSem, pipe->timeout >= 0 ? pipe->timeout / 1000 : SEM_INDEFINITE_WAIT);
+
+    if (rc == ERROR_TIMEOUT) {
+        return APR_TIMEUP;
+    }
+
+    return APR_FROM_OS_ERROR(rc);
 }
 
 
+
+APR_DECLARE(apr_status_t) apr_file_rotating_check(apr_file_t *thefile)
+{
+    return APR_ENOTIMPL;
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_file_rotating_manual_check(apr_file_t *thefile, apr_time_t n)
+{
+    return APR_ENOTIMPL;
+}
diff --git a/file_io/os2/seek.c b/file_io/os2/seek.c
index e303cf41cdb..7afba30773b 100644
--- a/file_io/os2/seek.c
+++ b/file_io/os2/seek.c
@@ -1,75 +1,38 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "fileio.h"
+#include "apr_arch_file_io.h"
 #include "apr_file_io.h"
 #include "apr_lib.h"
 #include <string.h>
 #include <io.h>
 
-#define INCL_DOS
-#include <os2.h>
 
-
-
-static ap_status_t setptr(ap_file_t *thefile, unsigned long pos )
+static apr_status_t setptr(apr_file_t *thefile, unsigned long pos )
 {
     long newbufpos;
     ULONG rc;
 
     if (thefile->direction == 1) {
-        ap_flush(thefile);
+        apr_status_t rv = apr_file_flush(thefile);
+
+        if (rv != APR_SUCCESS) {
+            return rv;
+        }
+
         thefile->bufpos = thefile->direction = thefile->dataRead = 0;
     }
 
@@ -84,20 +47,26 @@ static ap_status_t setptr(ap_file_t *thefile, unsigned long pos )
             thefile->bufpos = thefile->dataRead = 0;
     }
 
-    return APR_OS2_STATUS(rc);
+    return APR_FROM_OS_ERROR(rc);
 }
 
 
 
-ap_status_t ap_seek(ap_file_t *thefile, ap_seek_where_t where, ap_off_t *offset)
+APR_DECLARE(apr_status_t) apr_file_seek(apr_file_t *thefile, apr_seek_where_t where, apr_off_t *offset)
 {
     if (!thefile->isopen) {
         return APR_EBADF;
     }
 
+    thefile->eof_hit = 0;
+
     if (thefile->buffered) {
         int rc = EINVAL;
-        ap_finfo_t finfo;
+        apr_finfo_t finfo;
+
+        if (thefile->mutex) {
+            apr_thread_mutex_lock(thefile->mutex);
+        }
 
         switch (where) {
         case APR_SET:
@@ -109,13 +78,18 @@ ap_status_t ap_seek(ap_file_t *thefile, ap_seek_where_t where, ap_off_t *offset)
             break;
 
         case APR_END:
-            rc = ap_getfileinfo(&finfo, thefile);
+            rc = apr_file_info_get(&finfo, APR_FINFO_NORM, thefile);
             if (rc == APR_SUCCESS)
-                rc = setptr(thefile, finfo.size - *offset);
+                rc = setptr(thefile, finfo.size + *offset);
             break;
         }
 
-        *offset = thefile->filePtr + thefile->bufpos;
+        *offset = thefile->filePtr - thefile->dataRead + thefile->bufpos;
+
+        if (thefile->mutex) {
+            apr_thread_mutex_unlock(thefile->mutex);
+        }
+
         return rc;
     } else {
         switch (where) {
@@ -132,6 +106,23 @@ ap_status_t ap_seek(ap_file_t *thefile, ap_seek_where_t where, ap_off_t *offset)
             break;
         }
 
-        return APR_OS2_STATUS(DosSetFilePtr(thefile->filedes, *offset, where, (ULONG *)&offset));
+        return APR_FROM_OS_ERROR(DosSetFilePtr(thefile->filedes, *offset, where, (ULONG *)offset));
+    }
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_file_trunc(apr_file_t *fp, apr_off_t offset)
+{
+    int rc = DosSetFileSize(fp->filedes, offset);
+
+    if (rc != 0) {
+        return APR_FROM_OS_ERROR(rc);
     }
+
+    if (fp->buffered) {
+        return setptr(fp, offset);
+    }
+
+    return APR_SUCCESS;
 }
diff --git a/file_io/os2/tempdir.c b/file_io/os2/tempdir.c
new file mode 100644
index 00000000000..6823569f296
--- /dev/null
+++ b/file_io/os2/tempdir.c
@@ -0,0 +1 @@
+#include "../unix/tempdir.c"
diff --git a/file_io/unix/.cvsignore b/file_io/unix/.cvsignore
deleted file mode 100644
index f3c7a7c5da6..00000000000
--- a/file_io/unix/.cvsignore
+++ /dev/null
@@ -1 +0,0 @@
-Makefile
diff --git a/file_io/unix/Makefile.in b/file_io/unix/Makefile.in
deleted file mode 100644
index 084572d4069..00000000000
--- a/file_io/unix/Makefile.in
+++ /dev/null
@@ -1,101 +0,0 @@
-#CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
-#LIBS=$(EXTRA_LIBS) $(LIBS1)
-#INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
-#LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
-
-RM=@RM@
-CC=@CC@
-RANLIB=@RANLIB@
-CFLAGS=@CFLAGS@ @OPTIM@
-LIBS=@LIBS@
-LDFLAGS=@LDFLAGS@ $(LIBS)
-INCDIR=../../include
-INCLUDES=-I$(INCDIR) -I.
-
-#LIB=libfile.a
-
-OBJS=dir.o \
-	fileacc.o \
-	filedup.o \
-	filestat.o \
-	open.o \
-	pipe.o \
-	readwrite.o \
-	seek.o
-
-.c.o:
-	$(CC) $(CFLAGS) -c $(INCLUDES) $<
-
-all: $(OBJS)
-
-clean:
-	$(RM) -f *.o *.a *.so
-
-distclean: clean
-	-$(RM) -f Makefile
-
-$(OBJS): Makefile
-
-#$(LIB): $(OBJS)
-#	$(RM) -f $@
-#	$(AR) cr $@ $(OBJS)
-#	$(RANLIB) $@
-
-#
-# We really don't expect end users to use this rule.  It works only with
-# gcc, and rebuilds Makefile.tmpl.  You have to re-run Configure after
-# using it.
-#
-depend:
-	cp Makefile.in Makefile.in.bak \
-	    && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.in > Makefile.new \
-	    && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \
-	    && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
-	           -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
-		> Makefile.in \
-	    && rm Makefile.new
-
-# DO NOT REMOVE
-dir.o: dir.c fileio.h $(INCDIR)/apr_private.h \
- $(INCDIR)/apr_general.h $(INCDIR)/apr.h \
- $(INCDIR)/apr_errno.h $(INCDIR)/apr_file_io.h \
- $(INCDIR)/apr_time.h $(INCDIR)/apr_lib.h \
- $(INCDIR)/apr_thread_proc.h $(INCDIR)/apr_portable.h \
- $(INCDIR)/apr_network_io.h $(INCDIR)/apr_lock.h
-fileacc.o: fileacc.c fileio.h $(INCDIR)/apr_private.h \
- $(INCDIR)/apr_general.h $(INCDIR)/apr.h \
- $(INCDIR)/apr_errno.h $(INCDIR)/apr_file_io.h \
- $(INCDIR)/apr_time.h $(INCDIR)/apr_lib.h \
- $(INCDIR)/apr_thread_proc.h
-filedup.o: filedup.c fileio.h $(INCDIR)/apr_private.h \
- $(INCDIR)/apr_general.h $(INCDIR)/apr.h \
- $(INCDIR)/apr_errno.h $(INCDIR)/apr_file_io.h \
- $(INCDIR)/apr_time.h $(INCDIR)/apr_lib.h \
- $(INCDIR)/apr_thread_proc.h $(INCDIR)/apr_portable.h \
- $(INCDIR)/apr_network_io.h $(INCDIR)/apr_lock.h
-filestat.o: filestat.c fileio.h $(INCDIR)/apr_private.h \
- $(INCDIR)/apr_general.h $(INCDIR)/apr.h \
- $(INCDIR)/apr_errno.h $(INCDIR)/apr_file_io.h \
- $(INCDIR)/apr_time.h $(INCDIR)/apr_lib.h \
- $(INCDIR)/apr_thread_proc.h
-open.o: open.c fileio.h $(INCDIR)/apr_private.h \
- $(INCDIR)/apr_general.h $(INCDIR)/apr.h \
- $(INCDIR)/apr_errno.h $(INCDIR)/apr_file_io.h \
- $(INCDIR)/apr_time.h $(INCDIR)/apr_lib.h \
- $(INCDIR)/apr_thread_proc.h $(INCDIR)/apr_portable.h \
- $(INCDIR)/apr_network_io.h $(INCDIR)/apr_lock.h
-pipe.o: pipe.c fileio.h $(INCDIR)/apr_private.h \
- $(INCDIR)/apr_general.h $(INCDIR)/apr.h \
- $(INCDIR)/apr_errno.h $(INCDIR)/apr_file_io.h \
- $(INCDIR)/apr_time.h $(INCDIR)/apr_lib.h \
- $(INCDIR)/apr_thread_proc.h
-readwrite.o: readwrite.c fileio.h $(INCDIR)/apr_private.h \
- $(INCDIR)/apr_general.h $(INCDIR)/apr.h \
- $(INCDIR)/apr_errno.h $(INCDIR)/apr_file_io.h \
- $(INCDIR)/apr_time.h $(INCDIR)/apr_lib.h \
- $(INCDIR)/apr_thread_proc.h $(INCDIR)/apr_lock.h
-seek.o: seek.c fileio.h $(INCDIR)/apr_private.h \
- $(INCDIR)/apr_general.h $(INCDIR)/apr.h \
- $(INCDIR)/apr_errno.h $(INCDIR)/apr_file_io.h \
- $(INCDIR)/apr_time.h $(INCDIR)/apr_lib.h \
- $(INCDIR)/apr_thread_proc.h
diff --git a/file_io/unix/buffer.c b/file_io/unix/buffer.c
new file mode 100644
index 00000000000..ba2a8a7c636
--- /dev/null
+++ b/file_io/unix/buffer.c
@@ -0,0 +1,60 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_arch_file_io.h"
+#include "apr_pools.h"
+#include "apr_thread_mutex.h"
+
+APR_DECLARE(apr_status_t) apr_file_buffer_set(apr_file_t *file, 
+                                              char * buffer,
+                                              apr_size_t bufsize)
+{
+    apr_status_t rv;
+
+    file_lock(file);
+
+    if(file->buffered) {
+        /* Flush the existing buffer */
+        rv = apr_file_flush_locked(file);
+        if (rv != APR_SUCCESS) {
+            file_unlock(file);
+            return rv;
+        }
+    }
+        
+    file->buffer = buffer;
+    file->bufsize = bufsize;
+    file->buffered = 1;
+    file->bufpos = 0;
+    file->direction = 0;
+    file->dataRead = 0;
+ 
+    if (file->bufsize == 0) {
+            /* Setting the buffer size to zero is equivalent to turning 
+             * buffering off. 
+             */
+            file->buffered = 0;
+    }
+
+    file_unlock(file);
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_size_t) apr_file_buffer_size_get(apr_file_t *file)
+{
+    return file->bufsize;
+}
diff --git a/file_io/unix/copy.c b/file_io/unix/copy.c
new file mode 100644
index 00000000000..bf844aa46e0
--- /dev/null
+++ b/file_io/unix/copy.c
@@ -0,0 +1,119 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_arch_file_io.h"
+#include "apr_file_io.h"
+
+static apr_status_t apr_file_transfer_contents(const char *from_path,
+                                               const char *to_path,
+                                               apr_int32_t flags,
+                                               apr_fileperms_t to_perms,
+                                               apr_pool_t *pool)
+{
+    apr_file_t *s, *d;
+    apr_status_t status;
+    apr_finfo_t finfo;
+    apr_fileperms_t perms;
+
+    /* Open source file. */
+    status = apr_file_open(&s, from_path, APR_FOPEN_READ, APR_FPROT_OS_DEFAULT, pool);
+    if (status)
+        return status;
+
+    /* Maybe get its permissions. */
+    if (to_perms == APR_FPROT_FILE_SOURCE_PERMS) {
+        status = apr_file_info_get(&finfo, APR_FINFO_PROT, s);
+        if (status != APR_SUCCESS && status != APR_INCOMPLETE) {
+            apr_file_close(s);  /* toss any error */
+            return status;
+        }
+        perms = finfo.protection;
+        apr_file_perms_set(to_path, perms);  /* ignore any failure */
+    }
+    else
+        perms = to_perms;
+
+    /* Open dest file. */
+    status = apr_file_open(&d, to_path, flags, perms, pool);
+    if (status) {
+        apr_file_close(s);  /* toss any error */
+        return status;
+    }
+
+#if BUFSIZ > APR_FILE_DEFAULT_BUFSIZE
+#define COPY_BUFSIZ BUFSIZ
+#else
+#define COPY_BUFSIZ APR_FILE_DEFAULT_BUFSIZE
+#endif
+
+    /* Copy bytes till the cows come home. */
+    while (1) {
+        char buf[COPY_BUFSIZ];
+        apr_size_t bytes_this_time = sizeof(buf);
+        apr_status_t read_err;
+        apr_status_t write_err;
+
+        /* Read 'em. */
+        read_err = apr_file_read(s, buf, &bytes_this_time);
+        if (read_err && !APR_STATUS_IS_EOF(read_err)) {
+            apr_file_close(s);  /* toss any error */
+            apr_file_close(d);  /* toss any error */
+            return read_err;
+        }
+
+        /* Write 'em. */
+        write_err = apr_file_write_full(d, buf, bytes_this_time, NULL);
+        if (write_err) {
+            apr_file_close(s);  /* toss any error */
+            apr_file_close(d);  /* toss any error */
+            return write_err;
+        }
+
+        if (read_err && APR_STATUS_IS_EOF(read_err)) {
+            status = apr_file_close(s);
+            if (status) {
+                apr_file_close(d);  /* toss any error */
+                return status;
+            }
+
+            /* return the results of this close: an error, or success */
+            return apr_file_close(d);
+        }
+    }
+    /* NOTREACHED */
+}
+
+APR_DECLARE(apr_status_t) apr_file_copy(const char *from_path,
+                                        const char *to_path,
+                                        apr_fileperms_t perms,
+                                        apr_pool_t *pool)
+{
+    return apr_file_transfer_contents(from_path, to_path,
+                                      (APR_FOPEN_WRITE | APR_FOPEN_CREATE | APR_FOPEN_TRUNCATE),
+                                      perms,
+                                      pool);
+}
+
+APR_DECLARE(apr_status_t) apr_file_append(const char *from_path,
+                                          const char *to_path,
+                                          apr_fileperms_t perms,
+                                          apr_pool_t *pool)
+{
+    return apr_file_transfer_contents(from_path, to_path,
+                                      (APR_FOPEN_WRITE | APR_FOPEN_CREATE | APR_FOPEN_APPEND),
+                                      perms,
+                                      pool);
+}
diff --git a/file_io/unix/dir.c b/file_io/unix/dir.c
index d8312408516..a94eb8e7fb8 100644
--- a/file_io/unix/dir.c
+++ b/file_io/unix/dir.c
@@ -1,63 +1,32 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "fileio.h"
+#include "apr_arch_file_io.h"
+#include "apr_strings.h"
 #include "apr_portable.h"
+#if APR_HAVE_SYS_SYSLIMITS_H
+#include <sys/syslimits.h>
+#endif
+#if APR_HAVE_LIMITS_H
+#include <limits.h>
+#endif
 
-static ap_status_t dir_cleanup(void *thedir)
+static apr_status_t dir_cleanup(void *thedir)
 {
-    ap_dir_t *dir = thedir;
+    apr_dir_t *dir = thedir;
     if (closedir(dir->dirstruct) == 0) {
         return APR_SUCCESS;
     }
@@ -66,182 +35,316 @@ static ap_status_t dir_cleanup(void *thedir)
     }
 } 
 
-ap_status_t ap_opendir(ap_dir_t **new, const char *dirname, ap_pool_t *cont)
+#define PATH_SEPARATOR '/'
+
+/* Remove trailing separators that don't affect the meaning of PATH. */
+static const char *path_canonicalize (const char *path, apr_pool_t *pool)
+{
+    /* At some point this could eliminate redundant components.  For
+     * now, it just makes sure there is no trailing slash. */
+    apr_size_t len = strlen (path);
+    apr_size_t orig_len = len;
+    
+    while ((len > 0) && (path[len - 1] == PATH_SEPARATOR))
+        len--;
+    
+    if (len != orig_len)
+        return apr_pstrndup (pool, path, len);
+    else
+        return path;
+}
+
+/* Remove one component off the end of PATH. */
+static char *path_remove_last_component (const char *path, apr_pool_t *pool)
 {
-    (*new) = (ap_dir_t *)ap_palloc(cont, sizeof(ap_dir_t));
+    const char *newpath = path_canonicalize (path, pool);
+    int i;
+    
+    for (i = (strlen(newpath) - 1); i >= 0; i--) {
+        if (path[i] == PATH_SEPARATOR)
+            break;
+    }
 
-    (*new)->cntxt = cont;
-    (*new)->dirname = ap_pstrdup(cont, dirname);
-    (*new)->dirstruct = opendir(dirname);
-    (*new)->entry = ap_pcalloc(cont, sizeof(struct dirent));
+    return apr_pstrndup (pool, path, (i < 0) ? 0 : i);
+}
+
+apr_status_t apr_dir_open(apr_dir_t **new, const char *dirname, 
+                          apr_pool_t *pool)
+{
+    /* On some platforms (e.g., Linux+GNU libc), d_name[] in struct 
+     * dirent is declared with enough storage for the name.  On other
+     * platforms (e.g., Solaris 8 for Intel), d_name is declared as a
+     * one-byte array.  Note: gcc evaluates this at compile time.
+     */
+    apr_size_t dirent_size = 
+        sizeof(*(*new)->entry) +
+        (sizeof((*new)->entry->d_name) > 1 ? 0 : 255);
+    DIR *dir = opendir(dirname);
 
-    if ((*new)->dirstruct == NULL) {
+    if (!dir) {
         return errno;
-    }    
-    else {
-        ap_register_cleanup((*new)->cntxt, (void *)(*new), dir_cleanup,
-	                    ap_null_cleanup);
-        return APR_SUCCESS;
     }
+
+    (*new) = (apr_dir_t *)apr_palloc(pool, sizeof(apr_dir_t));
+
+    (*new)->pool = pool;
+    (*new)->dirname = apr_pstrdup(pool, dirname);
+    (*new)->dirstruct = dir;
+    (*new)->entry = apr_pcalloc(pool, dirent_size);
+
+    apr_pool_cleanup_register((*new)->pool, *new, dir_cleanup,
+                              apr_pool_cleanup_null);
+    return APR_SUCCESS;
 }
 
-ap_status_t ap_closedir(ap_dir_t *thedir)
+apr_status_t apr_dir_close(apr_dir_t *thedir)
 {
-    ap_status_t rv;
+    return apr_pool_cleanup_run(thedir->pool, thedir, dir_cleanup);
+}
 
-    if ((rv = dir_cleanup(thedir)) == APR_SUCCESS) {
-        ap_kill_cleanup(thedir->cntxt, thedir, dir_cleanup);
-        return APR_SUCCESS;
+#ifdef DIRENT_TYPE
+static apr_filetype_e filetype_from_dirent_type(int type)
+{
+    switch (type) {
+    case DT_REG:
+        return APR_REG;
+    case DT_DIR:
+        return APR_DIR;
+    case DT_LNK:
+        return APR_LNK;
+    case DT_CHR:
+        return APR_CHR;
+    case DT_BLK:
+        return APR_BLK;
+#if defined(DT_FIFO)
+    case DT_FIFO:
+        return APR_PIPE;
+#endif
+#if !defined(BEOS) && defined(DT_SOCK)
+    case DT_SOCK:
+        return APR_SOCK;
+#endif
+    default:
+        return APR_UNKFILE;
     }
-    return rv;
 }
+#endif
 
-ap_status_t ap_readdir(ap_dir_t *thedir)
+apr_status_t apr_dir_read(apr_finfo_t *finfo, apr_int32_t wanted,
+                          apr_dir_t *thedir)
 {
+    apr_status_t ret = 0;
+#ifdef DIRENT_TYPE
+    apr_filetype_e type;
+#endif
 #if APR_HAS_THREADS && defined(_POSIX_THREAD_SAFE_FUNCTIONS) \
-    && !defined(READDIR_IS_THREAD_SAFE)
-    ap_status_t ret;
+                    && !defined(READDIR_IS_THREAD_SAFE) \
+                    && (defined(APR_USE_READDIR64_R) \
+                        || defined(APR_USE_READDIR_R))
+#ifdef APR_USE_READDIR64_R
+    struct dirent64 *retent;
+
+    /* If LFS is enabled and readdir64_r is available, readdir64_r is
+     * used in preference to readdir_r.  This allows directories to be
+     * read which contain a (64-bit) inode number which doesn't fit
+     * into the 32-bit apr_ino_t, iff the caller doesn't actually care
+     * about the inode number (i.e. wanted & APR_FINFO_INODE == 0).
+     * (such inodes may be seen in some wonky NFS environments)
+     *
+     * Similarly, if the d_off field cannot be reprented in a 32-bit
+     * offset, the libc readdir_r() would barf; using readdir64_r
+     * bypasses that case entirely since APR does not care about
+     * d_off. */
+
+    ret = readdir64_r(thedir->dirstruct, thedir->entry, &retent);
+#else
+
+    struct dirent *retent;
+
+    ret = readdir_r(thedir->dirstruct, thedir->entry, &retent);
 #endif
 
-#if APR_HAS_THREADS && defined(_POSIX_THREAD_SAFE_FUNCTIONS) \
-    && !defined(READDIR_IS_THREAD_SAFE)
+    /* POSIX treats "end of directory" as a non-error case, so ret
+     * will be zero and retent will be set to NULL in that case. */
+    if (!ret && retent == NULL) {
+        ret = APR_ENOENT;
+    }
 
-    ret = readdir_r(thedir->dirstruct, thedir->entry, &thedir->entry);
-    /* Avoid the Linux problem where at end-of-directory thedir->entry
-     * is set to NULL, but ret = APR_SUCCESS.
+    /* Solaris is a bit strange, if there are no more entries in the
+     * directory, it returns EINVAL.  Since this is against POSIX, we
+     * hack around the problem here.  EINVAL is possible from other
+     * readdir implementations, but only if the result buffer is too small.
+     * since we control the size of that buffer, we should never have
+     * that problem.
      */
-    return (ret == APR_SUCCESS && thedir->entry == NULL) ? APR_ENOENT : ret;
+    if (ret == EINVAL) {
+        ret = APR_ENOENT;
+    }
 #else
-
+    /* We're about to call readdir() that may possibly set errno, and the
+     * logic below actually cares about errno after the call.  Therefore
+     * we need to clear errno first.
+     */
+    errno = 0;
     thedir->entry = readdir(thedir->dirstruct);
     if (thedir->entry == NULL) {
         /* If NULL was returned, this can NEVER be a success. Can it?! */
         if (errno == APR_SUCCESS) {
-            return APR_ENOENT;
+            ret = APR_ENOENT;
         }
-        return errno;
+        else
+            ret = errno;
     }
-    return APR_SUCCESS;
 #endif
-}
 
-ap_status_t ap_rewinddir(ap_dir_t *thedir)
-{
-    rewinddir(thedir->dirstruct);
-    return APR_SUCCESS;
-}
+    /* No valid bit flag to test here - do we want one? */
+    finfo->fname = NULL;
 
-ap_status_t ap_make_dir(const char *path, ap_fileperms_t perm, ap_pool_t *cont)
-{
-    mode_t mode = ap_unix_get_fileperms(perm);
+    if (ret) {
+        finfo->valid = 0;
+        return ret;
+    }
 
-    if (mkdir(path, mode) == 0) {
-        return APR_SUCCESS;
+#ifdef DIRENT_TYPE
+    type = filetype_from_dirent_type(thedir->entry->DIRENT_TYPE);
+    if (type != APR_UNKFILE) {
+        wanted &= ~APR_FINFO_TYPE;
     }
-    else {
-        return errno;
+#endif
+#ifdef DIRENT_INODE
+    if (thedir->entry->DIRENT_INODE && thedir->entry->DIRENT_INODE != -1) {
+#ifdef APR_USE_READDIR64_R
+        /* If readdir64_r is used, check for the overflow case of trying
+         * to fit a 64-bit integer into a 32-bit integer. */
+        if (sizeof(apr_ino_t) >= sizeof(retent->DIRENT_INODE)
+            || (apr_ino_t)retent->DIRENT_INODE == retent->DIRENT_INODE) {
+            wanted &= ~APR_FINFO_INODE;
+        } else {
+            /* Prevent the fallback code below from filling in the
+             * inode if the stat call fails. */
+            retent->DIRENT_INODE = 0;
+        }
+#else
+        wanted &= ~APR_FINFO_INODE;
+#endif /* APR_USE_READDIR64_R */
     }
-}
+#endif /* DIRENT_INODE */
 
-ap_status_t ap_remove_dir(const char *path, ap_pool_t *cont)
-{
-    if (rmdir(path) == 0) {
-        return APR_SUCCESS;
+    wanted &= ~APR_FINFO_NAME;
+
+    if (wanted)
+    {
+        char fspec[APR_PATH_MAX];
+        char *end;
+
+        end = apr_cpystrn(fspec, thedir->dirname, sizeof fspec);
+
+        if (end > fspec && end[-1] != '/' && (end < fspec + APR_PATH_MAX))
+            *end++ = '/';
+
+        apr_cpystrn(end, thedir->entry->d_name, 
+                    sizeof fspec - (end - fspec));
+
+        ret = apr_stat(finfo, fspec, APR_FINFO_LINK | wanted, thedir->pool);
+        /* We passed a stack name that will disappear */
+        finfo->fname = NULL;
+    }
+
+    if (wanted && (ret == APR_SUCCESS || ret == APR_INCOMPLETE)) {
+        wanted &= ~finfo->valid;
     }
     else {
-        return errno;
+        /* We don't bail because we fail to stat, when we are only -required-
+         * to readdir... but the result will be APR_INCOMPLETE
+         */
+        finfo->pool = thedir->pool;
+        finfo->valid = 0;
+#ifdef DIRENT_TYPE
+        if (type != APR_UNKFILE) {
+            finfo->filetype = type;
+            finfo->valid |= APR_FINFO_TYPE;
+        }
+#endif
+#ifdef DIRENT_INODE
+        if (thedir->entry->DIRENT_INODE && thedir->entry->DIRENT_INODE != -1) {
+            finfo->inode = thedir->entry->DIRENT_INODE;
+            finfo->valid |= APR_FINFO_INODE;
+        }
+#endif
     }
+
+    finfo->name = apr_pstrdup(thedir->pool, thedir->entry->d_name);
+    finfo->valid |= APR_FINFO_NAME;
+
+    if (wanted)
+        return APR_INCOMPLETE;
+
+    return APR_SUCCESS;
 }
 
-ap_status_t ap_dir_entry_size(ap_ssize_t *size, ap_dir_t *thedir)
+apr_status_t apr_dir_rewind(apr_dir_t *thedir)
 {
-    struct stat filestat;
-    char *fname = NULL;    
-
-    if (thedir->entry == NULL) {
-        *size = -1;
-        return APR_ENOFILE;
-    }
-    fname = ap_pstrcat(thedir->cntxt, thedir->dirname, "/", 
-                       thedir->entry->d_name, NULL);
-    if (stat(fname, &filestat) == -1) {
-        *size = -1;
-        return errno;
-    }
-    
-    *size = filestat.st_size;
+    rewinddir(thedir->dirstruct);
     return APR_SUCCESS;
 }
 
-ap_status_t ap_dir_entry_mtime(ap_time_t *mtime, ap_dir_t *thedir)
+apr_status_t apr_dir_make(const char *path, apr_fileperms_t perm, 
+                          apr_pool_t *pool)
 {
-    struct stat filestat;
-    char *fname = NULL;
+    mode_t mode = apr_unix_perms2mode(perm);
 
-    if (thedir->entry == NULL) {
-        *mtime = -1;
-        return APR_ENOFILE;
+    if (mkdir(path, mode) == 0) {
+        return APR_SUCCESS;
     }
-
-    fname = ap_pstrcat(thedir->cntxt, thedir->dirname, "/", 
-                       thedir->entry->d_name, NULL);
-    if (stat(fname, &filestat) == -1) {
-        *mtime = -1;
+    else {
         return errno;
     }
-    
-    ap_ansi_time_to_ap_time(mtime, filestat.st_mtime);
-    return APR_SUCCESS;
 }
- 
-ap_status_t ap_dir_entry_ftype(ap_filetype_e *type, ap_dir_t *thedir)
+
+apr_status_t apr_dir_make_recursive(const char *path, apr_fileperms_t perm,
+                                           apr_pool_t *pool) 
 {
-    struct stat filestat;
-    char *fname = NULL;
+    apr_status_t apr_err = 0;
+    
+    apr_err = apr_dir_make (path, perm, pool); /* Try to make PATH right out */
+    
+    if (apr_err == ENOENT) { /* Missing an intermediate dir */
+        char *dir;
+        
+        dir = path_remove_last_component(path, pool);
+        /* If there is no path left, give up. */
+        if (dir[0] == '\0') {
+            return apr_err;
+        }
 
-    if (thedir->entry == NULL) {
-        *type = APR_REG;
-        return APR_ENOFILE;
+        apr_err = apr_dir_make_recursive(dir, perm, pool);
+        
+        if (!apr_err) 
+            apr_err = apr_dir_make (path, perm, pool);
     }
 
-    fname = ap_pstrcat(thedir->cntxt, thedir->dirname, "/", 
-                       thedir->entry->d_name, NULL);
-    if (stat(fname, &filestat) == -1) {
-        *type = APR_REG;
-        return errno;
-    }
+    /*
+     * It's OK if PATH exists. Timing issues can lead to the second
+     * apr_dir_make being called on existing dir, therefore this check
+     * has to come last.
+     */
+    if (APR_STATUS_IS_EEXIST(apr_err))
+        return APR_SUCCESS;
 
-    if (S_ISREG(filestat.st_mode))
-        *type = APR_REG;    
-    if (S_ISDIR(filestat.st_mode))
-        *type = APR_DIR;    
-    if (S_ISCHR(filestat.st_mode))
-        *type = APR_CHR;    
-    if (S_ISBLK(filestat.st_mode))
-        *type = APR_BLK;    
-    if (S_ISFIFO(filestat.st_mode))
-        *type = APR_PIPE;    
-    if (S_ISLNK(filestat.st_mode))
-        *type = APR_LNK;    
-#ifndef BEOS
-    if (S_ISSOCK(filestat.st_mode))
-        *type = APR_SOCK;    
-#endif
-    return APR_SUCCESS;
+    return apr_err;
 }
 
-ap_status_t ap_get_dir_filename(char **new, ap_dir_t *thedir)
+apr_status_t apr_dir_remove(const char *path, apr_pool_t *pool)
 {
-    /* Detect End-Of-File */
-    if (thedir == NULL || thedir->entry == NULL) {
-        *new = NULL;
-        return APR_ENOENT;
+    if (rmdir(path) == 0) {
+        return APR_SUCCESS;
+    }
+    else {
+        return errno;
     }
-    (*new) = ap_pstrdup(thedir->cntxt, thedir->entry->d_name);
-    return APR_SUCCESS;
 }
 
-ap_status_t ap_get_os_dir(ap_os_dir_t **thedir, ap_dir_t *dir)
+apr_status_t apr_os_dir_get(apr_os_dir_t **thedir, apr_dir_t *dir)
 {
     if (dir == NULL) {
         return APR_ENODIR;
@@ -250,12 +353,12 @@ ap_status_t ap_get_os_dir(ap_os_dir_t **thedir, ap_dir_t *dir)
     return APR_SUCCESS;
 }
 
-ap_status_t ap_put_os_dir(ap_dir_t **dir, ap_os_dir_t *thedir,
-                          ap_pool_t *cont)
+apr_status_t apr_os_dir_put(apr_dir_t **dir, apr_os_dir_t *thedir,
+                          apr_pool_t *pool)
 {
     if ((*dir) == NULL) {
-        (*dir) = (ap_dir_t *)ap_palloc(cont, sizeof(ap_dir_t));
-        (*dir)->cntxt = cont;
+        (*dir) = (apr_dir_t *)apr_pcalloc(pool, sizeof(apr_dir_t));
+        (*dir)->pool = pool;
     }
     (*dir)->dirstruct = thedir;
     return APR_SUCCESS;
diff --git a/file_io/unix/fileacc.c b/file_io/unix/fileacc.c
index 76041a3600a..d44e4e17b3b 100644
--- a/file_io/unix/fileacc.c
+++ b/file_io/unix/fileacc.c
@@ -1,120 +1,119 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "fileio.h"
+#include "apr_strings.h"
+#include "apr_arch_file_io.h"
 
-/* A file to put ALL of the accessor functions for ap_file_t types. */
+/* A file to put ALL of the accessor functions for apr_file_t types. */
 
-ap_status_t ap_get_filename(char **new, ap_file_t *thefile)
+APR_DECLARE(apr_status_t) apr_file_name_get(const char **fname,
+                                           apr_file_t *thefile)
 {
-    if (thefile != NULL) {
-        *new = ap_pstrdup(thefile->cntxt, thefile->fname);
-        return APR_SUCCESS;
-    }
-    else {
-        *new = NULL;
-        return APR_ENOFILE;
-    }
+    *fname = thefile->fname;
+    return APR_SUCCESS;
 }
 
-mode_t ap_unix_get_fileperms(ap_fileperms_t mode)
+APR_DECLARE(apr_int32_t) apr_file_flags_get(apr_file_t *f)
 {
-    mode_t rv = 0;
-
-    if (mode & APR_UREAD)
-        rv |= S_IRUSR;
-    if (mode & APR_UWRITE)
-        rv |= S_IWUSR;
-    if (mode & APR_UEXECUTE)
-        rv |= S_IXUSR;
-
-    if (mode & APR_GREAD)
-        rv |= S_IRGRP;
-    if (mode & APR_GWRITE)
-        rv |= S_IWGRP;
-    if (mode & APR_GEXECUTE)
-        rv |= S_IXGRP;
-
-    if (mode & APR_WREAD)
-        rv |= S_IROTH;
-    if (mode & APR_WWRITE)
-        rv |= S_IWOTH;
-    if (mode & APR_WEXECUTE)
-        rv |= S_IXOTH;
-
-    return rv;
+    return f->flags;
 }
 
-ap_status_t ap_get_filedata(void **data, char *key, ap_file_t *file)
-{    
-    if (file != NULL) {
-        return ap_get_userdata(data, key, file->cntxt);
-    }
-    else {
-        *data = NULL;
-        return APR_ENOFILE;
-    }
+#if !defined(OS2) && !defined(WIN32)
+mode_t apr_unix_perms2mode(apr_fileperms_t perms)
+{
+    mode_t mode = 0;
+
+    if (perms & APR_FPROT_USETID)
+        mode |= S_ISUID;
+    if (perms & APR_FPROT_UREAD)
+        mode |= S_IRUSR;
+    if (perms & APR_FPROT_UWRITE)
+        mode |= S_IWUSR;
+    if (perms & APR_FPROT_UEXECUTE)
+        mode |= S_IXUSR;
+
+    if (perms & APR_FPROT_GSETID)
+        mode |= S_ISGID;
+    if (perms & APR_FPROT_GREAD)
+        mode |= S_IRGRP;
+    if (perms & APR_FPROT_GWRITE)
+        mode |= S_IWGRP;
+    if (perms & APR_FPROT_GEXECUTE)
+        mode |= S_IXGRP;
+
+#ifdef S_ISVTX
+    if (perms & APR_FPROT_WSTICKY)
+        mode |= S_ISVTX;
+#endif
+    if (perms & APR_FPROT_WREAD)
+        mode |= S_IROTH;
+    if (perms & APR_FPROT_WWRITE)
+        mode |= S_IWOTH;
+    if (perms & APR_FPROT_WEXECUTE)
+        mode |= S_IXOTH;
+
+    return mode;
 }
 
-ap_status_t ap_set_filedata(ap_file_t *file, void *data, char *key,
-                            ap_status_t (*cleanup) (void *))
+apr_fileperms_t apr_unix_mode2perms(mode_t mode)
+{
+    apr_fileperms_t perms = 0;
+
+    if (mode & S_ISUID)
+        perms |= APR_FPROT_USETID;
+    if (mode & S_IRUSR)
+        perms |= APR_FPROT_UREAD;
+    if (mode & S_IWUSR)
+        perms |= APR_FPROT_UWRITE;
+    if (mode & S_IXUSR)
+        perms |= APR_FPROT_UEXECUTE;
+
+    if (mode & S_ISGID)
+        perms |= APR_FPROT_GSETID;
+    if (mode & S_IRGRP)
+        perms |= APR_FPROT_GREAD;
+    if (mode & S_IWGRP)
+        perms |= APR_FPROT_GWRITE;
+    if (mode & S_IXGRP)
+        perms |= APR_FPROT_GEXECUTE;
+
+#ifdef S_ISVTX
+    if (mode & S_ISVTX)
+        perms |= APR_FPROT_WSTICKY;
+#endif
+    if (mode & S_IROTH)
+        perms |= APR_FPROT_WREAD;
+    if (mode & S_IWOTH)
+        perms |= APR_FPROT_WWRITE;
+    if (mode & S_IXOTH)
+        perms |= APR_FPROT_WEXECUTE;
+
+    return perms;
+}
+#endif
+
+APR_DECLARE(apr_status_t) apr_file_data_get(void **data, const char *key,
+                                           apr_file_t *file)
 {    
-    if (file != NULL) {
-        return ap_set_userdata(data, key, cleanup, file->cntxt);
-    }
-    else {
-        return APR_ENOFILE;
-    }
+    return apr_pool_userdata_get(data, key, file->pool);
 }
 
+APR_DECLARE(apr_status_t) apr_file_data_set(apr_file_t *file, void *data,
+                                           const char *key,
+                                           apr_status_t (*cleanup)(void *))
+{    
+    return apr_pool_userdata_set(data, key, cleanup, file->pool);
+}
diff --git a/file_io/unix/filedup.c b/file_io/unix/filedup.c
index f7c19ac9e38..797f8045f6b 100644
--- a/file_io/unix/filedup.c
+++ b/file_io/unix/filedup.c
@@ -1,88 +1,192 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "fileio.h"
+#include "apr_arch_file_io.h"
+#include "apr_strings.h"
 #include "apr_portable.h"
+#include "apr_thread_mutex.h"
+#include "apr_arch_inherit.h"
 
-ap_status_t ap_dupfile(ap_file_t **new_file, ap_file_t *old_file, ap_pool_t *p)
+static apr_status_t file_dup(apr_file_t **new_file, 
+                             apr_file_t *old_file, apr_pool_t *p,
+                             int which_dup)
 {
-    int have_file = 0;
+    int rv;
+#ifdef HAVE_DUP3
+    int flags = 0;
+#endif
 
-    if ((*new_file) == NULL) {
-        (*new_file) = (ap_file_t *)ap_pcalloc(p, sizeof(ap_file_t));
+    if (which_dup == 2) {
         if ((*new_file) == NULL) {
-            return APR_ENOMEM;
+            /* We can't dup2 unless we have a valid new_file */
+            return APR_EINVAL;
+        }
+#ifdef HAVE_DUP3
+        if (!((*new_file)->flags & (APR_FOPEN_NOCLEANUP|APR_INHERIT)))
+            flags |= O_CLOEXEC;
+        rv = dup3(old_file->filedes, (*new_file)->filedes, flags);
+#else
+        rv = dup2(old_file->filedes, (*new_file)->filedes);
+        if (!((*new_file)->flags & (APR_FOPEN_NOCLEANUP|APR_INHERIT))) {
+            int flags;
+
+            if (rv == -1)
+                return errno;
+
+            if ((flags = fcntl((*new_file)->filedes, F_GETFD)) == -1)
+                return errno;
+
+            flags |= FD_CLOEXEC;
+            if (fcntl((*new_file)->filedes, F_SETFD, flags) == -1)
+                return errno;
+
         }
+#endif
     } else {
-        have_file = 1;
+        rv = dup(old_file->filedes);
     }
+
+    if (rv == -1)
+        return errno;
     
-    (*new_file)->cntxt = p; 
-    if (have_file) {
-        dup2(old_file->filedes, (*new_file)->filedes);
-    }
-    else {
-        (*new_file)->filedes = dup(old_file->filedes); 
+    if (which_dup == 1) {
+        (*new_file) = (apr_file_t *)apr_pcalloc(p, sizeof(apr_file_t));
+        (*new_file)->pool = p;
+        (*new_file)->filedes = rv;
     }
+
+    (*new_file)->fname = apr_pstrdup(p, old_file->fname);
+    (*new_file)->buffered = old_file->buffered;
+
+    /* If the existing socket in a dup2 is already buffered, we
+     * have an existing and valid (hopefully) mutex, so we don't
+     * want to create it again as we could leak!
+     */
 #if APR_HAS_THREADS
-    ap_create_lock(&((*new_file)->thlock), APR_MUTEX, APR_INTRAPROCESS, NULL, 
-                   p);
+    if ((*new_file)->buffered && !(*new_file)->thlock && old_file->thlock) {
+        apr_thread_mutex_create(&((*new_file)->thlock),
+                                APR_THREAD_MUTEX_DEFAULT, p);
+    }
+#endif
+    /* As above, only create the buffer if we haven't already
+     * got one.
+     */
+    if ((*new_file)->buffered && !(*new_file)->buffer) {
+        (*new_file)->buffer = apr_palloc(p, old_file->bufsize);
+        (*new_file)->bufsize = old_file->bufsize;
+    }
+
+    /* this is the way dup() works */
+    (*new_file)->blocking = old_file->blocking; 
+
+    /* make sure unget behavior is consistent */
+    (*new_file)->ungetchar = old_file->ungetchar;
+
+    if (old_file->rotating != NULL) {
+        (*new_file)->rotating = (apr_rotating_info_t *)apr_pcalloc(p, sizeof(apr_rotating_info_t));
+
+        memcpy(&((*new_file)->rotating->finfo), &(old_file->rotating->finfo), sizeof(apr_finfo_t));
+        (*new_file)->rotating->timeout = old_file->rotating->timeout;
+        (*new_file)->rotating->lastcheck = old_file->rotating->lastcheck;
+        (*new_file)->rotating->oflags = old_file->rotating->oflags;
+        (*new_file)->rotating->perm = old_file->rotating->perm;
+        (*new_file)->rotating->manual = old_file->rotating->manual;
+    }
+
+    /* apr_file_dup2() retains the original cleanup, reflecting 
+     * the existing inherit and nocleanup flags.  This means, 
+     * that apr_file_dup2() cannot be called against an apr_file_t
+     * already closed with apr_file_close, because the expected
+     * cleanup was already killed.
+     */
+    if (which_dup == 2) {
+        return APR_SUCCESS;
+    }
+
+    /* apr_file_dup() retains all old_file flags with the exceptions
+     * of APR_INHERIT and APR_FOPEN_NOCLEANUP.
+     * The user must call apr_file_inherit_set() on the dupped 
+     * apr_file_t when desired.
+     */
+    (*new_file)->flags = old_file->flags
+                       & ~(APR_INHERIT | APR_FOPEN_NOCLEANUP);
+
+    apr_pool_cleanup_register((*new_file)->pool, (void *)(*new_file),
+                              apr_unix_file_cleanup, 
+                              apr_unix_child_file_cleanup);
+#ifndef WAITIO_USES_POLL
+    /* Start out with no pollset.  apr_wait_for_io_or_timeout() will
+     * initialize the pollset if needed.
+     */
+    (*new_file)->pollset = NULL;
 #endif
-    (*new_file)->fname = ap_pstrdup(p, old_file->fname);
-    (*new_file)->buffered = old_file->buffered;
-    ap_register_cleanup((*new_file)->cntxt, (void *)(*new_file), ap_unix_file_cleanup,
-                        ap_null_cleanup);
     return APR_SUCCESS;
 }
 
+APR_DECLARE(apr_status_t) apr_file_dup(apr_file_t **new_file,
+                                       apr_file_t *old_file, apr_pool_t *p)
+{
+    return file_dup(new_file, old_file, p, 1);
+}
+
+APR_DECLARE(apr_status_t) apr_file_dup2(apr_file_t *new_file,
+                                        apr_file_t *old_file, apr_pool_t *p)
+{
+    return file_dup(&new_file, old_file, p, 2);
+}
+
+APR_DECLARE(apr_status_t) apr_file_setaside(apr_file_t **new_file,
+                                            apr_file_t *old_file,
+                                            apr_pool_t *p)
+{
+    *new_file = (apr_file_t *)apr_pmemdup(p, old_file, sizeof(apr_file_t));
+    (*new_file)->pool = p;
+    if (old_file->buffered) {
+        (*new_file)->buffer = apr_palloc(p, old_file->bufsize);
+        (*new_file)->bufsize = old_file->bufsize;
+        if (old_file->direction == 1) {
+            memcpy((*new_file)->buffer, old_file->buffer, old_file->bufpos);
+        }
+        else {
+            memcpy((*new_file)->buffer, old_file->buffer, old_file->dataRead);
+        }
+#if APR_HAS_THREADS
+        if (old_file->thlock) {
+            apr_thread_mutex_create(&((*new_file)->thlock),
+                                    APR_THREAD_MUTEX_DEFAULT, p);
+            apr_thread_mutex_destroy(old_file->thlock);
+        }
+#endif /* APR_HAS_THREADS */
+    }
+    if (old_file->fname) {
+        (*new_file)->fname = apr_pstrdup(p, old_file->fname);
+    }
+    if (!(old_file->flags & APR_FOPEN_NOCLEANUP)) {
+        apr_pool_cleanup_register(p, (void *)(*new_file), 
+                                  apr_unix_file_cleanup,
+                                  ((*new_file)->flags & APR_INHERIT)
+                                     ? apr_pool_cleanup_null
+                                     : apr_unix_child_file_cleanup);
+    }
+
+    old_file->filedes = -1;
+    apr_pool_cleanup_kill(old_file->pool, (void *)old_file,
+                          apr_unix_file_cleanup);
+#ifndef WAITIO_USES_POLL
+    (*new_file)->pollset = NULL;
+#endif
+    return APR_SUCCESS;
+}
diff --git a/file_io/unix/fileio.h b/file_io/unix/fileio.h
deleted file mode 100644
index 1ef43ba0922..00000000000
--- a/file_io/unix/fileio.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef FILE_IO_H
-#define FILE_IO_H
-
-#include "apr_private.h"
-#include "apr_general.h"
-#include "apr_file_io.h"
-#include "apr_errno.h"
-#include "apr_lib.h"
-
-/* System headers the file I/O library needs */
-#if HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#if HAVE_STRING_H
-#include <string.h>
-#endif
-#if HAVE_DIRENT_H
-#include <dirent.h>
-#endif
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_STDIO_H
-#include <stdio.h>
-#endif
-#if HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#if HAVE_SYS_UIO_H
-#include <sys/uio.h>
-#endif
-#if HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#ifdef BEOS
-#include <kernel/OS.h>
-#endif
-/* End System headers */
-
-#define APR_FILE_BUFSIZE 4096
-
-struct ap_file_t {
-    ap_pool_t *cntxt;
-    int filedes;
-    char * fname;
-    int oflags;
-    int eof_hit;
-    int pipe;
-    ap_interval_time_t timeout;
-    int buffered;
-    int ungetchar;    /* Last char provided by an unget op. (-1 = no char)*/
-
-    /* Stuff for buffered mode */
-    char *buffer;
-    int bufpos;               /* Read/Write position in buffer */
-    unsigned long dataRead;   /* amount of valid data read into buffer */
-    int direction;            /* buffer being used for 0 = read, 1 = write */
-    unsigned long filePtr;    /* position in file of handle */
-#if APR_HAS_THREADS
-    struct ap_lock_t *thlock;
-#endif
-};
-
-struct ap_dir_t {
-    ap_pool_t *cntxt;
-    char *dirname;
-    DIR *dirstruct;
-    struct dirent *entry;
-};
-
-ap_status_t ap_unix_file_cleanup(void *);
-mode_t ap_unix_get_fileperms(ap_fileperms_t);
-
-#endif  /* ! FILE_IO_H */
-
diff --git a/file_io/unix/filepath.c b/file_io/unix/filepath.c
new file mode 100644
index 00000000000..b3dd2cac926
--- /dev/null
+++ b/file_io/unix/filepath.c
@@ -0,0 +1,300 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_private.h"
+#include "apr_arch_file_io.h"
+#include "apr_file_io.h"
+#include "apr_strings.h"
+#define APR_WANT_STRFUNC
+#include "apr_want.h"
+#if APR_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+/* Win32 malpropism that can go away once everyone believes this
+ * code is golden, and I'm not testing it anymore :-)
+ */
+#if APR_HAVE_DIRENT_H
+#include <dirent.h>
+#endif
+
+/* Any OS that requires/refuses trailing slashes should be dealt with here.
+ */
+APR_DECLARE(apr_status_t) apr_filepath_get(char **defpath, apr_int32_t flags,
+                                           apr_pool_t *p)
+{
+    char path[APR_PATH_MAX];
+
+    if (!getcwd(path, sizeof(path))) {
+        if (errno == ERANGE)
+            return APR_ENAMETOOLONG;
+        else
+            return errno;
+    }
+    *defpath = apr_pstrdup(p, path);
+
+    return APR_SUCCESS;
+}
+
+
+/* Any OS that requires/refuses trailing slashes should be dealt with here
+ */
+APR_DECLARE(apr_status_t) apr_filepath_set(const char *path, apr_pool_t *p)
+{
+    if (chdir(path) != 0)
+        return errno;
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_filepath_root(const char **rootpath,
+                                            const char **inpath,
+                                            apr_int32_t flags,
+                                            apr_pool_t *p)
+{
+    if (**inpath == '/') {
+        *rootpath = apr_pstrdup(p, "/");
+        do {
+            ++(*inpath);
+        } while (**inpath == '/');
+
+        return APR_SUCCESS;
+    }
+
+    return APR_ERELATIVE;
+}
+
+APR_DECLARE(apr_status_t) apr_filepath_merge(char **newpath,
+                                             const char *rootpath,
+                                             const char *addpath,
+                                             apr_int32_t flags,
+                                             apr_pool_t *p)
+{
+    char *path;
+    apr_size_t rootlen; /* is the length of the src rootpath */
+    apr_size_t maxlen;  /* maximum total path length */
+    apr_size_t keptlen; /* is the length of the retained rootpath */
+    apr_size_t pathlen; /* is the length of the result path */
+    apr_size_t seglen;  /* is the end of the current segment */
+    apr_status_t rv;
+
+    /* Treat null as an empty path.
+     */
+    if (!addpath)
+        addpath = "";
+
+    if (addpath[0] == '/') {
+        /* If addpath is rooted, then rootpath is unused.
+         * Ths violates any APR_FILEPATH_SECUREROOTTEST and
+         * APR_FILEPATH_NOTABSOLUTE flags specified.
+         */
+        if (flags & APR_FILEPATH_SECUREROOTTEST)
+            return APR_EABOVEROOT;
+        if (flags & APR_FILEPATH_NOTABSOLUTE)
+            return APR_EABSOLUTE;
+
+        /* If APR_FILEPATH_NOTABOVEROOT wasn't specified,
+         * we won't test the root again, it's ignored.
+         * Waste no CPU retrieving the working path.
+         */
+        if (!rootpath && !(flags & APR_FILEPATH_NOTABOVEROOT))
+            rootpath = "";
+    }
+    else {
+        /* If APR_FILEPATH_NOTABSOLUTE is specified, the caller
+         * requires a relative result.  If the rootpath is
+         * ommitted, we do not retrieve the working path,
+         * if rootpath was supplied as absolute then fail.
+         */
+        if (flags & APR_FILEPATH_NOTABSOLUTE) {
+            if (!rootpath)
+                rootpath = "";
+            else if (rootpath[0] == '/')
+                return APR_EABSOLUTE;
+        }
+    }
+
+    if (!rootpath) {
+        /* Start with the current working path.  This is bass akwards,
+         * but required since the compiler (at least vc) doesn't like
+         * passing the address of a char const* for a char** arg.
+         */
+        char *getpath;
+        rv = apr_filepath_get(&getpath, flags, p);
+        rootpath = getpath;
+        if (rv != APR_SUCCESS)
+            return errno;
+
+        /* XXX: Any kernel subject to goofy, uncanonical results
+         * must run the rootpath against the user's given flags.
+         * Simplest would be a recursive call to apr_filepath_merge
+         * with an empty (not null) rootpath and addpath of the cwd.
+         */
+    }
+
+    rootlen = strlen(rootpath);
+    maxlen = rootlen + strlen(addpath) + 4; /* 4 for slashes at start, after
+                                             * root, and at end, plus trailing
+                                             * null */
+    if (maxlen > APR_PATH_MAX) {
+        return APR_ENAMETOOLONG;
+    }
+    path = (char *)apr_palloc(p, maxlen);
+
+    if (addpath[0] == '/') {
+        /* Ignore the given root path, strip off leading
+         * '/'s to a single leading '/' from the addpath,
+         * and leave addpath at the first non-'/' character.
+         */
+        keptlen = 0;
+        while (addpath[0] == '/')
+            ++addpath;
+        path[0] = '/';
+        pathlen = 1;
+    }
+    else {
+        /* If both paths are relative, fail early
+         */
+        if (rootpath[0] != '/' && (flags & APR_FILEPATH_NOTRELATIVE))
+            return APR_ERELATIVE;
+
+        /* Base the result path on the rootpath
+         */
+        keptlen = rootlen;
+        memcpy(path, rootpath, rootlen);
+
+        /* Always '/' terminate the given root path
+         */
+        if (keptlen && path[keptlen - 1] != '/') {
+            path[keptlen++] = '/';
+        }
+        pathlen = keptlen;
+    }
+
+    while (*addpath) {
+        /* Parse each segment, find the closing '/'
+         */
+        const char *next = addpath;
+        while (*next && (*next != '/')) {
+            ++next;
+        }
+        seglen = next - addpath;
+
+        if (seglen == 0 || (seglen == 1 && addpath[0] == '.')) {
+            /* noop segment (/ or ./) so skip it
+             */
+        }
+        else if (seglen == 2 && addpath[0] == '.' && addpath[1] == '.') {
+            /* backpath (../) */
+            if (pathlen == 1 && path[0] == '/') {
+                /* Attempt to move above root.  Always die if the
+                 * APR_FILEPATH_SECUREROOTTEST flag is specified.
+                 */
+                if (flags & APR_FILEPATH_SECUREROOTTEST) {
+                    return APR_EABOVEROOT;
+                }
+
+                /* Otherwise this is simply a noop, above root is root.
+                 * Flag that rootpath was entirely replaced.
+                 */
+                keptlen = 0;
+            }
+            else if (pathlen == 0
+                     || (pathlen == 3
+                         && !memcmp(path + pathlen - 3, "../", 3))
+                     || (pathlen  > 3
+                         && !memcmp(path + pathlen - 4, "/../", 4))) {
+                /* Path is already backpathed or empty, if the
+                 * APR_FILEPATH_SECUREROOTTEST.was given die now.
+                 */
+                if (flags & APR_FILEPATH_SECUREROOTTEST) {
+                    return APR_EABOVEROOT;
+                }
+
+                /* Otherwise append another backpath, including
+                 * trailing slash if present.
+                 */
+                memcpy(path + pathlen, "../", *next ? 3 : 2);
+                pathlen += *next ? 3 : 2;
+            }
+            else {
+                /* otherwise crop the prior segment
+                 */
+                do {
+                    --pathlen;
+                } while (pathlen && path[pathlen - 1] != '/');
+            }
+
+            /* Now test if we are above where we started and back up
+             * the keptlen offset to reflect the added/altered path.
+             */
+            if (pathlen < keptlen) {
+                if (flags & APR_FILEPATH_SECUREROOTTEST) {
+                    return APR_EABOVEROOT;
+                }
+                keptlen = pathlen;
+            }
+        }
+        else {
+            /* An actual segment, append it to the destination path
+             */
+            if (*next) {
+                seglen++;
+            }
+            memcpy(path + pathlen, addpath, seglen);
+            pathlen += seglen;
+        }
+
+        /* Skip over trailing slash to the next segment
+         */
+        if (*next) {
+            ++next;
+        }
+
+        addpath = next;
+    }
+    path[pathlen] = '\0';
+
+    /* keptlen will be the rootlen unless the addpath contained
+     * backpath elements.  If so, and APR_FILEPATH_NOTABOVEROOT
+     * is specified (APR_FILEPATH_SECUREROOTTEST was caught above),
+     * compare the original root to assure the result path is
+     * still within given root path.
+     */
+    if ((flags & APR_FILEPATH_NOTABOVEROOT) && keptlen < rootlen) {
+        if (strncmp(rootpath, path, rootlen)) {
+            return APR_EABOVEROOT;
+        }
+        if (rootpath[rootlen - 1] != '/'
+            && path[rootlen] && path[rootlen] != '/') {
+            return APR_EABOVEROOT;
+        }
+    }
+
+    *newpath = path;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_filepath_encoding(int *style, apr_pool_t *p)
+{
+#if defined(DARWIN)
+    *style = APR_FILEPATH_ENCODING_UTF8;
+#else
+    *style = APR_FILEPATH_ENCODING_LOCALE;
+#endif
+    return APR_SUCCESS;
+}
diff --git a/file_io/unix/filepath_util.c b/file_io/unix/filepath_util.c
new file mode 100644
index 00000000000..82d97e48144
--- /dev/null
+++ b/file_io/unix/filepath_util.c
@@ -0,0 +1,115 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#define APR_WANT_STRFUNC
+#define APR_WANT_MEMFUNC
+#include "apr_want.h"
+#include "apr_file_info.h"
+#include "apr_errno.h"
+#include "apr_pools.h"
+#include "apr_strings.h"
+#include "apr_tables.h"
+
+#include "apr_private.h"
+
+#if defined(WIN32) || defined(OS2) || defined(NETWARE)
+#define PATH_SEPARATOR ';'
+#define PATH_SEPARATOR_STRING ";"
+#else
+#define PATH_SEPARATOR ':'
+#define PATH_SEPARATOR_STRING ":"
+#endif
+
+APR_DECLARE(apr_status_t) apr_filepath_list_split(apr_array_header_t **pathelts,
+                                                  const char *liststr,
+                                                  apr_pool_t *p)
+{
+    char *path, *part, *ptr;
+    apr_array_header_t *elts;
+    int nelts;
+
+    /* Count the number of path elements. We know there'll be at least
+       one even if path is an empty string. */
+    path = apr_pstrdup(p, liststr);
+    for (nelts = 0, ptr = path; ptr != NULL; ++nelts)
+    {
+        ptr = strchr(ptr, PATH_SEPARATOR);
+        if (ptr)
+            ++ptr;
+    }
+
+    /* Split the path into the array. */
+    elts = apr_array_make(p, nelts, sizeof(char*));
+    while ((part = apr_strtok(path, PATH_SEPARATOR_STRING, &ptr)) != NULL)
+    {
+        if (*part == '\0')      /* Ignore empty path components. */
+            continue;
+
+        *(char**)apr_array_push(elts) = part;
+        path = NULL;            /* For the next call to apr_strtok */
+    }
+
+    *pathelts = elts;
+    return APR_SUCCESS;
+}
+
+
+APR_DECLARE(apr_status_t) apr_filepath_list_merge(char **liststr,
+                                                  apr_array_header_t *pathelts,
+                                                  apr_pool_t *p)
+{
+    apr_size_t path_size = 0;
+    char *path;
+    int i;
+
+    /* This test isn't 100% certain, but it'll catch at least some
+       invalid uses... */
+    if (pathelts->elt_size != sizeof(char*))
+        return APR_EINVAL;
+
+    /* Calculate the size of the merged path */
+    for (i = 0; i < pathelts->nelts; ++i)
+        path_size += strlen(((char**)pathelts->elts)[i]);
+
+    if (path_size == 0)
+    {
+        *liststr = NULL;
+        return APR_SUCCESS;
+    }
+
+    if (i > 0)                  /* Add space for the separators */
+        path_size += (i - 1);
+
+    /* Merge the path components */
+    path = *liststr = apr_palloc(p, path_size + 1);
+    for (i = 0; i < pathelts->nelts; ++i)
+    {
+        /* ### Hmmmm. Calling strlen twice on the same string. Yuck.
+               But is is better than reallocation in apr_pstrcat? */
+        const char *part = ((char**)pathelts->elts)[i];
+        apr_size_t part_size = strlen(part);
+        if (part_size == 0)     /* Ignore empty path components. */
+            continue;
+
+        if (i > 0)
+            *path++ = PATH_SEPARATOR;
+        memcpy(path, part, part_size);
+        path += part_size;
+    }
+    *path = '\0';
+    return APR_SUCCESS;
+}
diff --git a/file_io/unix/filestat.c b/file_io/unix/filestat.c
index e6baf7191ca..65918c2127e 100644
--- a/file_io/unix/filestat.c
+++ b/file_io/unix/filestat.c
@@ -1,123 +1,339 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "fileio.h"
+#include "apr_arch_file_io.h"
 #include "apr_file_io.h"
 #include "apr_general.h"
+#include "apr_strings.h"
 #include "apr_errno.h"
 
-static ap_filetype_e filetype_from_mode(int mode)
+#ifdef HAVE_UTIME
+#include <utime.h>
+#endif
+
+static apr_filetype_e filetype_from_mode(mode_t mode)
 {
-    ap_filetype_e type = APR_NOFILE;
-
-    if (S_ISREG(mode))
-        type = APR_REG;
-    if (S_ISDIR(mode))
-        type = APR_DIR;
-    if (S_ISCHR(mode))
-        type = APR_CHR;
-    if (S_ISBLK(mode))
-        type = APR_BLK;
-    if (S_ISFIFO(mode))
-        type = APR_PIPE;
-    if (S_ISLNK(mode))
-        type = APR_LNK;
-#ifndef BEOS
-    if (S_ISSOCK(mode))
-        type = APR_SOCK;
+    apr_filetype_e type;
+
+    switch (mode & S_IFMT) {
+    case S_IFREG:
+        type = APR_REG;  break;
+    case S_IFDIR:
+        type = APR_DIR;  break;
+    case S_IFLNK:
+        type = APR_LNK;  break;
+    case S_IFCHR:
+        type = APR_CHR;  break;
+    case S_IFBLK:
+        type = APR_BLK;  break;
+#if defined(S_IFFIFO)
+    case S_IFFIFO:
+        type = APR_PIPE; break;
 #endif
+#if !defined(BEOS) && defined(S_IFSOCK)
+    case S_IFSOCK:
+        type = APR_SOCK; break;
+#endif
+
+    default:
+	/* Work around missing S_IFxxx values above
+         * for Linux et al.
+         */
+#if !defined(S_IFFIFO) && defined(S_ISFIFO)
+    	if (S_ISFIFO(mode)) {
+            type = APR_PIPE;
+	} else
+#endif
+#if !defined(BEOS) && !defined(S_IFSOCK) && defined(S_ISSOCK)
+    	if (S_ISSOCK(mode)) {
+            type = APR_SOCK;
+	} else
+#endif
+        type = APR_UNKFILE;
+    }
     return type;
 }
 
-ap_status_t ap_getfileinfo(ap_finfo_t *finfo, ap_file_t *thefile)
+static void fill_out_finfo(apr_finfo_t *finfo, struct_stat *info,
+                           apr_int32_t wanted)
+{ 
+    finfo->valid = APR_FINFO_MIN | APR_FINFO_IDENT | APR_FINFO_NLINK
+                 | APR_FINFO_OWNER | APR_FINFO_PROT;
+    finfo->protection = apr_unix_mode2perms(info->st_mode);
+    finfo->filetype = filetype_from_mode(info->st_mode);
+    finfo->user = info->st_uid;
+    finfo->group = info->st_gid;
+    finfo->size = info->st_size;
+    finfo->device = info->st_dev;
+    finfo->nlink = info->st_nlink;
+
+    /* Check for overflow if storing a 64-bit st_ino in a 32-bit
+     * apr_ino_t for LFS builds: */
+    if (sizeof(apr_ino_t) >= sizeof(info->st_ino)
+        || (apr_ino_t)info->st_ino == info->st_ino) {
+        finfo->inode = info->st_ino;
+    } else {
+        finfo->valid &= ~APR_FINFO_INODE;
+    }
+
+    apr_time_ansi_put(&finfo->atime, info->st_atime);
+#ifdef HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC
+    finfo->atime += info->st_atim.tv_nsec / APR_TIME_C(1000);
+#elif defined(HAVE_STRUCT_STAT_ST_ATIMENSEC)
+    finfo->atime += info->st_atimensec / APR_TIME_C(1000);
+#elif defined(HAVE_STRUCT_STAT_ST_ATIME_N)
+    finfo->atime += info->st_atime_n / APR_TIME_C(1000);
+#endif
+
+    apr_time_ansi_put(&finfo->mtime, info->st_mtime);
+#ifdef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
+    finfo->mtime += info->st_mtim.tv_nsec / APR_TIME_C(1000);
+#elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
+    finfo->mtime += info->st_mtimensec / APR_TIME_C(1000);
+#elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
+    finfo->mtime += info->st_mtime_n / APR_TIME_C(1000);
+#endif
+
+    apr_time_ansi_put(&finfo->ctime, info->st_ctime);
+#ifdef HAVE_STRUCT_STAT_ST_CTIM_TV_NSEC
+    finfo->ctime += info->st_ctim.tv_nsec / APR_TIME_C(1000);
+#elif defined(HAVE_STRUCT_STAT_ST_CTIMENSEC)
+    finfo->ctime += info->st_ctimensec / APR_TIME_C(1000);
+#elif defined(HAVE_STRUCT_STAT_ST_CTIME_N)
+    finfo->ctime += info->st_ctime_n / APR_TIME_C(1000);
+#endif
+
+#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
+#ifdef DEV_BSIZE
+    finfo->csize = (apr_off_t)info->st_blocks * (apr_off_t)DEV_BSIZE;
+#else
+    finfo->csize = (apr_off_t)info->st_blocks * (apr_off_t)512;
+#endif
+    finfo->valid |= APR_FINFO_CSIZE;
+#endif
+}
+
+apr_status_t apr_file_info_get_locked(apr_finfo_t *finfo, apr_int32_t wanted,
+                                      apr_file_t *thefile)
 {
-    struct stat info;
+    struct_stat info;
+
+    if (thefile->buffered) {
+        apr_status_t rv = apr_file_flush_locked(thefile);
+        if (rv != APR_SUCCESS)
+            return rv;
+    }
 
     if (fstat(thefile->filedes, &info) == 0) {
-        finfo->protection = info.st_mode;
-        finfo->filetype = filetype_from_mode(info.st_mode);
-        finfo->user = info.st_uid;
-        finfo->group = info.st_gid;
-        finfo->size = info.st_size;
-        finfo->inode = info.st_ino;
-        ap_ansi_time_to_ap_time(&finfo->atime, info.st_atime);
-        ap_ansi_time_to_ap_time(&finfo->mtime, info.st_mtime);
-        ap_ansi_time_to_ap_time(&finfo->ctime, info.st_ctime);
-        return APR_SUCCESS;
+        finfo->pool = thefile->pool;
+        finfo->fname = thefile->fname;
+        fill_out_finfo(finfo, &info, wanted);
+        return (wanted & ~finfo->valid) ? APR_INCOMPLETE : APR_SUCCESS;
     }
     else {
         return errno;
     }
 }
 
-ap_status_t ap_stat(ap_finfo_t *finfo, const char *fname, ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_file_info_get(apr_finfo_t *finfo, 
+                                            apr_int32_t wanted,
+                                            apr_file_t *thefile)
 {
-    struct stat info;
-
-    if (stat(fname, &info) == 0) {
-        finfo->protection = info.st_mode;
-        finfo->filetype = filetype_from_mode(info.st_mode);
-        finfo->user = info.st_uid;
-        finfo->group = info.st_gid;
-        finfo->size = info.st_size;
-        finfo->inode = info.st_ino;
-        ap_ansi_time_to_ap_time(&finfo->atime, info.st_atime);
-        ap_ansi_time_to_ap_time(&finfo->mtime, info.st_mtime);
-        ap_ansi_time_to_ap_time(&finfo->ctime, info.st_ctime);
+    struct_stat info;
+
+    if (thefile->buffered) {
+        apr_status_t rv = apr_file_flush(thefile);
+        if (rv != APR_SUCCESS)
+            return rv;
+    }
+
+    if (fstat(thefile->filedes, &info) == 0) {
+        finfo->pool = thefile->pool;
+        finfo->fname = thefile->fname;
+        fill_out_finfo(finfo, &info, wanted);
+        return (wanted & ~finfo->valid) ? APR_INCOMPLETE : APR_SUCCESS;
+    }
+    else {
+        return errno;
+    }
+}
+
+APR_DECLARE(apr_status_t) apr_file_perms_set(const char *fname, 
+                                             apr_fileperms_t perms)
+{
+    mode_t mode = apr_unix_perms2mode(perms);
+
+    if (chmod(fname, mode) == -1)
+        return errno;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_file_attrs_set(const char *fname,
+                                             apr_fileattrs_t attributes,
+                                             apr_fileattrs_t attr_mask,
+                                             apr_pool_t *pool)
+{
+    apr_status_t status;
+    apr_finfo_t finfo;
+
+    /* Don't do anything if we can't handle the requested attributes */
+    if (!(attr_mask & (APR_FILE_ATTR_READONLY
+                       | APR_FILE_ATTR_EXECUTABLE)))
         return APR_SUCCESS;
+
+    status = apr_stat(&finfo, fname, APR_FINFO_PROT, pool);
+    if (status)
+        return status;
+
+    /* ### TODO: should added bits be umask'd? */
+    if (attr_mask & APR_FILE_ATTR_READONLY)
+    {
+        if (attributes & APR_FILE_ATTR_READONLY)
+        {
+            finfo.protection &= ~APR_FPROT_UWRITE;
+            finfo.protection &= ~APR_FPROT_GWRITE;
+            finfo.protection &= ~APR_FPROT_WWRITE;
+        }
+        else
+        {
+            /* ### umask this! */
+            finfo.protection |= APR_FPROT_UWRITE;
+            finfo.protection |= APR_FPROT_GWRITE;
+            finfo.protection |= APR_FPROT_WWRITE;
+        }
+    }
+
+    if (attr_mask & APR_FILE_ATTR_EXECUTABLE)
+    {
+        if (attributes & APR_FILE_ATTR_EXECUTABLE)
+        {
+            /* ### umask this! */
+            finfo.protection |= APR_FPROT_UEXECUTE;
+            finfo.protection |= APR_FPROT_GEXECUTE;
+            finfo.protection |= APR_FPROT_WEXECUTE;
+        }
+        else
+        {
+            finfo.protection &= ~APR_FPROT_UEXECUTE;
+            finfo.protection &= ~APR_FPROT_GEXECUTE;
+            finfo.protection &= ~APR_FPROT_WEXECUTE;
+        }
+    }
+
+    return apr_file_perms_set(fname, finfo.protection);
+}
+
+
+APR_DECLARE(apr_status_t) apr_file_mtime_set(const char *fname,
+                                              apr_time_t mtime,
+                                              apr_pool_t *pool)
+{
+    apr_status_t status;
+    apr_finfo_t finfo;
+
+    status = apr_stat(&finfo, fname, APR_FINFO_ATIME, pool);
+    if (status) {
+        return status;
+    }
+
+#ifdef HAVE_UTIMES
+    {
+      struct timeval tvp[2];
+    
+      tvp[0].tv_sec = apr_time_sec(finfo.atime);
+      tvp[0].tv_usec = apr_time_usec(finfo.atime);
+      tvp[1].tv_sec = apr_time_sec(mtime);
+      tvp[1].tv_usec = apr_time_usec(mtime);
+      
+      if (utimes(fname, tvp) == -1) {
+        return errno;
+      }
+    }
+#elif defined(HAVE_UTIME)
+    {
+      struct utimbuf buf;
+      
+      buf.actime = (time_t) (finfo.atime / APR_USEC_PER_SEC);
+      buf.modtime = (time_t) (mtime / APR_USEC_PER_SEC);
+      
+      if (utime(fname, &buf) == -1) {
+        return errno;
+      }
+    }
+#else
+    return APR_ENOTIMPL;
+#endif
+
+    return APR_SUCCESS;
+}
+
+
+APR_DECLARE(apr_status_t) apr_stat(apr_finfo_t *finfo, 
+                                   const char *fname, 
+                                   apr_int32_t wanted, apr_pool_t *pool)
+{
+    struct_stat info;
+    int srv;
+
+    if (wanted & APR_FINFO_LINK)
+        srv = lstat(fname, &info);
+    else
+        srv = stat(fname, &info);
+
+    if (srv == 0) {
+        finfo->pool = pool;
+        finfo->fname = fname;
+        fill_out_finfo(finfo, &info, wanted);
+        if (wanted & APR_FINFO_LINK)
+            wanted &= ~APR_FINFO_LINK;
+        return (wanted & ~finfo->valid) ? APR_INCOMPLETE : APR_SUCCESS;
     }
     else {
+#if !defined(ENOENT) || !defined(ENOTDIR)
+#error ENOENT || ENOTDIR not defined; please see the
+#error comments at this line in the source for a workaround.
+        /*
+         * If ENOENT || ENOTDIR is not defined in one of the your OS's
+         * include files, APR cannot report a good reason why the stat()
+         * of the file failed; there are cases where it can fail even though
+         * the file exists.  This opens holes in Apache, for example, because
+         * it becomes possible for someone to get a directory listing of a 
+         * directory even though there is an index (eg. index.html) file in 
+         * it.  If you do not have a problem with this, delete the above 
+         * #error lines and start the compile again.  If you need to do this,
+         * please submit a bug report to http://www.apache.org/bug_report.html
+         * letting us know that you needed to do this.  Please be sure to 
+         * include the operating system you are using.
+         */
+        /* WARNING: All errors will be handled as not found
+         */
+#if !defined(ENOENT) 
+        return APR_ENOENT;
+#else
+        /* WARNING: All errors but not found will be handled as not directory
+         */
+        if (errno != ENOENT)
+            return APR_ENOENT;
+        else
+            return errno;
+#endif
+#else /* All was defined well, report the usual: */
         return errno;
+#endif
     }
 }
+
+
diff --git a/file_io/unix/flock.c b/file_io/unix/flock.c
new file mode 100644
index 00000000000..01e8a639ba9
--- /dev/null
+++ b/file_io/unix/flock.c
@@ -0,0 +1,120 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_arch_file_io.h"
+
+#if APR_HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_SYS_FILE_H
+#include <sys/file.h>
+#endif
+
+APR_DECLARE(apr_status_t) apr_file_lock(apr_file_t *thefile, int type)
+{
+    int rc;
+
+#if defined(HAVE_FCNTL_H)
+    {
+        struct flock l = { 0 };
+        int fc;
+
+        l.l_whence = SEEK_SET;  /* count l_start from start of file */
+        l.l_start = 0;          /* lock from start of file */
+        l.l_len = 0;            /* lock to end of file */
+        if ((type & APR_FLOCK_TYPEMASK) == APR_FLOCK_SHARED)
+            l.l_type = F_RDLCK;
+        else
+            l.l_type = F_WRLCK;
+
+        fc = (type & APR_FLOCK_NONBLOCK) ? F_SETLK : F_SETLKW;
+
+        /* keep trying if fcntl() gets interrupted (by a signal) */
+        while ((rc = fcntl(thefile->filedes, fc, &l)) < 0 && errno == EINTR)
+            continue;
+
+        if (rc == -1) {
+            /* on some Unix boxes (e.g., Tru64), we get EACCES instead
+             * of EAGAIN; we don't want APR_STATUS_IS_EAGAIN() matching EACCES
+             * since that breaks other things, so fix up the retcode here
+             */
+            if (errno == EACCES) {
+                return EAGAIN;
+            }
+            return errno;
+        }
+    }
+#elif defined(HAVE_SYS_FILE_H)
+    {
+        int ltype;
+
+        if ((type & APR_FLOCK_TYPEMASK) == APR_FLOCK_SHARED)
+            ltype = LOCK_SH;
+        else
+            ltype = LOCK_EX;
+        if ((type & APR_FLOCK_NONBLOCK) != 0)
+            ltype |= LOCK_NB;
+
+        /* keep trying if flock() gets interrupted (by a signal) */
+        while ((rc = flock(thefile->filedes, ltype)) < 0 && errno == EINTR)
+            continue;
+
+        if (rc == -1)
+            return errno;
+    }
+#else
+#error No file locking mechanism is available.
+#endif
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_file_unlock(apr_file_t *thefile)
+{
+    int rc;
+
+#if defined(HAVE_FCNTL_H)
+    {
+        struct flock l = { 0 };
+
+        l.l_whence = SEEK_SET;  /* count l_start from start of file */
+        l.l_start = 0;          /* lock from start of file */
+        l.l_len = 0;            /* lock to end of file */
+        l.l_type = F_UNLCK;
+
+        /* keep trying if fcntl() gets interrupted (by a signal) */
+        while ((rc = fcntl(thefile->filedes, F_SETLKW, &l)) < 0
+               && errno == EINTR)
+            continue;
+
+        if (rc == -1)
+            return errno;
+    }
+#elif defined(HAVE_SYS_FILE_H)
+    {
+        /* keep trying if flock() gets interrupted (by a signal) */
+        while ((rc = flock(thefile->filedes, LOCK_UN)) < 0 && errno == EINTR)
+            continue;
+
+        if (rc == -1)
+            return errno;
+    }
+#else
+#error No file locking mechanism is available.
+#endif
+
+    return APR_SUCCESS;
+}
diff --git a/file_io/unix/fullrw.c b/file_io/unix/fullrw.c
new file mode 100644
index 00000000000..3c67f65904d
--- /dev/null
+++ b/file_io/unix/fullrw.c
@@ -0,0 +1,111 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_file_io.h"
+
+
+APR_DECLARE(apr_status_t) apr_file_read_full(apr_file_t *thefile, void *buf,
+                                             apr_size_t nbytes,
+                                             apr_size_t *bytes_read)
+{
+    apr_status_t status;
+    apr_size_t total_read = 0;
+
+    do {
+	apr_size_t amt = nbytes;
+
+	status = apr_file_read(thefile, buf, &amt);
+	buf = (char *)buf + amt;
+        nbytes -= amt;
+        total_read += amt;
+    } while (status == APR_SUCCESS && nbytes > 0);
+
+    if (bytes_read != NULL)
+        *bytes_read = total_read;
+
+    return status;
+}
+
+APR_DECLARE(apr_status_t) apr_file_write_full(apr_file_t *thefile,
+                                              const void *buf,
+                                              apr_size_t nbytes,
+                                              apr_size_t *bytes_written)
+{
+    apr_status_t status;
+    apr_size_t total_written = 0;
+
+    do {
+	apr_size_t amt = nbytes;
+
+	status = apr_file_write(thefile, buf, &amt);
+	buf = (char *)buf + amt;
+        nbytes -= amt;
+        total_written += amt;
+    } while (status == APR_SUCCESS && nbytes > 0);
+
+    if (bytes_written != NULL)
+        *bytes_written = total_written;
+
+    return status;
+}
+
+APR_DECLARE(apr_status_t) apr_file_writev_full(apr_file_t *thefile,
+                                               const struct iovec *vec,
+                                               apr_size_t nvec,
+                                               apr_size_t *bytes_written)
+{
+    apr_status_t rv = APR_SUCCESS;
+    apr_size_t i;
+    apr_size_t amt = 0;
+    apr_size_t total = 0;
+
+    for (i = 0; i < nvec; i++) {
+        total += vec[i].iov_len;
+    }
+
+    rv = apr_file_writev(thefile, vec, nvec, &amt);
+
+    if (bytes_written != NULL)
+        *bytes_written = amt;
+
+    if (rv != APR_SUCCESS || (amt == total)) {
+        return rv;
+    }
+
+    for (i = 0; i < nvec && amt; i++) {
+        if (amt >= vec[i].iov_len) {
+            amt -= vec[i].iov_len;
+        }
+        else {
+            break;
+        }
+    }
+
+    if (amt) {
+        rv = apr_file_write_full(thefile, (const char *)vec[i].iov_base + amt,
+                                 vec[i].iov_len - amt, NULL);
+    }
+
+    for (; i < nvec && rv == APR_SUCCESS; i++) {
+        rv = apr_file_write_full(thefile, vec[i].iov_base,
+                                 vec[i].iov_len, &amt);
+    }
+
+    if (bytes_written != NULL)
+        *bytes_written = total;
+
+    return rv;
+}
diff --git a/file_io/unix/mktemp.c b/file_io/unix/mktemp.c
new file mode 100644
index 00000000000..4ba28a7b44c
--- /dev/null
+++ b/file_io/unix/mktemp.c
@@ -0,0 +1,231 @@
+/* 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.
+ */
+/*
+ * Copyright (c) 1987, 1993
+ * The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    This product includes software developed by the University of
+ *    California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "apr_private.h"
+#include "apr_file_io.h" /* prototype of apr_mkstemp() */
+#include "apr_strings.h" /* prototype of apr_mkstemp() */
+#include "apr_arch_file_io.h" /* prototype of apr_mkstemp() */
+#include "apr_portable.h" /* for apr_os_file_put() */
+#include "apr_arch_inherit.h"
+
+#ifndef HAVE_MKSTEMP
+
+#if defined(SVR4) || defined(WIN32) || defined(NETWARE)
+#ifdef SVR4
+#if HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+#endif
+#define arc4random() rand()
+#define seedrandom(a) srand(a)
+#else
+#if APR_HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#define arc4random() random()
+#define seedrandom(a) srandom(a)
+#endif
+
+#if APR_HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if APR_HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+
+static const unsigned char padchar[] =
+"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+static apr_uint32_t randseed=0;
+
+static int gettemp(char *path, apr_file_t **doopen, apr_int32_t flags, apr_pool_t *p)
+{
+    register char *start, *trv, *suffp;
+    char *pad;
+    apr_finfo_t sbuf;
+    apr_status_t rv;
+    apr_uint32_t randnum;
+
+    if (randseed==0) {
+        randseed = (int)apr_time_now();
+        seedrandom(randseed);
+    }
+
+    for (trv = path; *trv; ++trv)
+        ;
+    suffp = trv;
+    --trv;
+    if (trv < path) {
+        return APR_EINVAL;
+    }
+
+    /* Fill space with random characters */
+    while (*trv == 'X') {
+        randnum = arc4random() % (sizeof(padchar) - 1);
+        *trv-- = padchar[randnum];
+    }
+    start = trv + 1;
+
+    /*
+     * check the target directory.
+     */
+    for (;; --trv) {
+        if (trv <= path)
+            break;
+        if (*trv == '/') {
+            *trv = '\0';
+            rv = apr_stat(&sbuf, path, APR_FINFO_TYPE, p);
+            *trv = '/';
+            if (rv != APR_SUCCESS)
+                return rv;
+            if (sbuf.filetype != APR_DIR) {
+                return APR_ENOTDIR;
+            }
+            break;
+        }
+    }
+
+    for (;;) {
+        if ((rv = apr_file_open(doopen, path, flags,
+                                APR_FPROT_UREAD | APR_FPROT_UWRITE, p)) == APR_SUCCESS)
+            return APR_SUCCESS;
+        if (!APR_STATUS_IS_EEXIST(rv))
+            return rv;
+
+        /* If we have a collision, cycle through the space of filenames */
+        for (trv = start;;) {
+            if (*trv == '\0' || trv == suffp)
+                return APR_EINVAL; /* XXX: is this the correct return code? */
+            pad = strchr((char *)padchar, *trv);
+            if (pad == NULL || !*++pad) {
+                *trv++ = padchar[0];
+            }
+            else {
+                *trv++ = *pad;
+                break;
+            }
+        }
+    }
+    /*NOTREACHED*/
+}
+
+#else
+
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h> /* for mkstemp() - Single Unix */
+#endif
+#if APR_HAVE_UNISTD_H
+#include <unistd.h> /* for mkstemp() - FreeBSD */
+#endif
+#endif /* !defined(HAVE_MKSTEMP) */
+
+#if defined(HAVE_MKOSTEMP64)
+#define wrap_mkostemp(t, f) mkostemp64(t, (f))
+#elif defined(HAVE_MKOSTEMP)
+#define wrap_mkostemp(t, f) mkostemp(t, (f))
+#elif defined(HAVE_MKSTEMP64)
+#define wrap_mkostemp(t, f) mkstemp64(t)
+#else
+#define wrap_mkostemp(t, f) mkstemp(t)
+#endif
+
+APR_DECLARE(apr_status_t) apr_file_mktemp(apr_file_t **fp, char *template, apr_int32_t flags, apr_pool_t *p)
+{
+#ifdef HAVE_MKSTEMP
+    int fd;
+#endif
+    flags = (!flags) ? APR_FOPEN_CREATE | APR_FOPEN_READ | APR_FOPEN_WRITE | APR_FOPEN_EXCL |
+                       APR_FOPEN_DELONCLOSE : flags;
+#ifndef HAVE_MKSTEMP
+    return gettemp(template, fp, flags, p);
+#else
+
+    fd = wrap_mkostemp(template,
+                       (flags & APR_FOPEN_NOCLEANUP) ? 0 : O_CLOEXEC);
+    if (fd == -1) {
+        return errno;
+    }
+    /* XXX: We must reset several flags values as passed-in, since
+     * mkstemp didn't subscribe to our preference flags.
+     *
+     * We either have to unset the flags, or fix up the fd and other
+     * xthread and inherit bits appropriately.  Since gettemp() above
+     * calls apr_file_open, our flags are respected in that code path.
+     */
+    apr_os_file_put(fp, &fd, flags, p);
+    (*fp)->fname = apr_pstrdup(p, template);
+
+    if (!(flags & APR_FOPEN_NOCLEANUP)) {
+#if !defined(HAVE_MKOSTEMP64) && !defined(HAVE_MKOSTEMP)
+        int flags;
+
+        if ((flags = fcntl(fd, F_GETFD)) == -1)
+            return errno;
+
+        flags |= FD_CLOEXEC;
+        if (fcntl(fd, F_SETFD, flags) == -1)
+            return errno;
+#endif
+
+        apr_pool_cleanup_register((*fp)->pool, (void *)(*fp),
+                                  apr_unix_file_cleanup,
+                                  apr_unix_child_file_cleanup);
+    }
+#endif
+    return APR_SUCCESS;
+}
+
diff --git a/file_io/unix/open.c b/file_io/unix/open.c
index 6e0039ac73c..770d438ae34 100644
--- a/file_io/unix/open.c
+++ b/file_io/unix/open.c
@@ -1,151 +1,234 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "fileio.h"
+#include "apr_arch_file_io.h"
+#include "apr_strings.h"
 #include "apr_portable.h"
+#include "apr_thread_mutex.h"
+#include "apr_arch_inherit.h"
+#include "apr_time.h"
 
-ap_status_t ap_unix_file_cleanup(void *thefile)
+#ifdef NETWARE
+#include "nks/dirio.h"
+#include "apr_hash.h"
+#include "fsio.h"
+#endif
+
+static apr_status_t file_cleanup(apr_file_t *file, int is_child)
 {
-    ap_file_t *file = thefile;
-    int rv;
+    apr_status_t rv = APR_SUCCESS;
+    int fd = file->filedes;
 
-    rv = close(file->filedes);
+    /* Set file descriptor to -1 before close(), so that there is no
+     * chance of returning an already closed FD from apr_os_file_get().
+     */
+    file->filedes = -1;
 
-    if (rv == 0) {
-        file->filedes = -1;
+    if (close(fd) == 0) {
+        /* Only the parent process should delete the file! */
+        if (!is_child && (file->flags & APR_FOPEN_DELONCLOSE)) {
+            unlink(file->fname);
+        }
 #if APR_HAS_THREADS
         if (file->thlock) {
-            return ap_destroy_lock(file->thlock);
+            rv = apr_thread_mutex_destroy(file->thlock);
         }
-        return APR_SUCCESS;
-#else
-        return APR_SUCCESS;
 #endif
     }
     else {
-        return errno;
-	/* Are there any error conditions other than EINTR or EBADF? */
+        /* Restore, close() was not successful. */
+        file->filedes = fd;
+
+        /* Are there any error conditions other than EINTR or EBADF? */
+        rv = errno;
     }
+#ifndef WAITIO_USES_POLL
+    if (file->pollset != NULL) {
+        apr_status_t pollset_rv = apr_pollset_destroy(file->pollset);
+        /* If the file close failed, return its error value,
+         * not apr_pollset_destroy()'s.
+         */
+        if (rv == APR_SUCCESS) {
+            rv = pollset_rv;
+        }
+    }
+#endif /* !WAITIO_USES_POLL */
+    return rv;
 }
 
-ap_status_t ap_open(ap_file_t **new, const char *fname, ap_int32_t flag,  ap_fileperms_t perm, ap_pool_t *cont)
+apr_status_t apr_unix_file_cleanup(void *thefile)
 {
-    int oflags = 0;
+    apr_file_t *file = thefile;
+    apr_status_t flush_rv = APR_SUCCESS, rv = APR_SUCCESS;
 
-    if ((*new) == NULL) {
-        (*new) = (ap_file_t *)ap_pcalloc(cont, sizeof(ap_file_t));
+    if (file->buffered) {
+        flush_rv = apr_file_flush(file);
     }
 
-    (*new)->cntxt = cont;
-    (*new)->oflags = oflags;
-    (*new)->filedes = -1;
-    (*new)->buffer = NULL;
+    rv = file_cleanup(file, 0);
+
+    return rv != APR_SUCCESS ? rv : flush_rv;
+}
+
+apr_status_t apr_unix_child_file_cleanup(void *thefile)
+{
+    return file_cleanup(thefile, 1);
+}
+
+APR_DECLARE(apr_status_t) apr_file_open(apr_file_t **new, 
+                                        const char *fname, 
+                                        apr_int32_t flag, 
+                                        apr_fileperms_t perm, 
+                                        apr_pool_t *pool)
+{
+    apr_os_file_t fd;
+    int oflags = 0;
 #if APR_HAS_THREADS
-    ap_create_lock(&((*new)->thlock), APR_MUTEX, APR_INTRAPROCESS, NULL, cont);
+    apr_thread_mutex_t *thlock = NULL;
 #endif
+    apr_status_t rv;
 
-    if ((flag & APR_READ) && (flag & APR_WRITE)) {
+    if ((flag & APR_FOPEN_READ) && (flag & APR_FOPEN_WRITE)) {
         oflags = O_RDWR;
     }
-    else if (flag & APR_READ) {
+    else if (flag & APR_FOPEN_READ) {
         oflags = O_RDONLY;
     }
-    else if (flag & APR_WRITE) {
+    else if (flag & APR_FOPEN_WRITE) {
         oflags = O_WRONLY;
     }
     else {
         return APR_EACCES; 
     }
 
-    (*new)->fname = ap_pstrdup(cont, fname);
-
-    (*new)->buffered = (flag & APR_BUFFERED) > 0;
-
-    if (flag & APR_CREATE) {
-        oflags |= O_CREAT; 
-	if (flag & APR_EXCL) {
-	    oflags |= O_EXCL;
-	}
+    if (flag & APR_FOPEN_CREATE) {
+        oflags |= O_CREAT;
+        if (flag & APR_FOPEN_EXCL) {
+            oflags |= O_EXCL;
+        }
     }
-    if ((flag & APR_EXCL) && !(flag & APR_CREATE)) {
+    if ((flag & APR_FOPEN_EXCL) && !(flag & APR_FOPEN_CREATE)) {
         return APR_EACCES;
     }   
 
-    if (flag & APR_APPEND) {
+    if (flag & APR_FOPEN_APPEND) {
         oflags |= O_APPEND;
     }
-    if (flag & APR_TRUNCATE) {
+    if (flag & APR_FOPEN_TRUNCATE) {
         oflags |= O_TRUNC;
     }
-    
-    if (perm == APR_OS_DEFAULT) {
-        (*new)->filedes = open(fname, oflags, 0666);
+#ifdef O_BINARY
+    if (flag & APR_FOPEN_BINARY) {
+        oflags |= O_BINARY;
     }
-    else {
-        (*new)->filedes = open(fname, oflags, ap_unix_get_fileperms(perm));
-    }    
+#endif
+
+    if (flag & APR_FOPEN_NONBLOCK) {
+#ifdef O_NONBLOCK
+        oflags |= O_NONBLOCK;
+#else
+        return APR_ENOTIMPL;
+#endif
+    }
+
+#ifdef O_CLOEXEC
+    /* Introduced in Linux 2.6.23. Silently ignored on earlier Linux kernels.
+     */
+    if (!(flag & APR_FOPEN_NOCLEANUP)) {
+        oflags |= O_CLOEXEC;
+}
+#endif
+ 
+#if APR_HAS_LARGE_FILES && defined(_LARGEFILE64_SOURCE)
+    oflags |= O_LARGEFILE;
+#elif defined(O_LARGEFILE)
+    if (flag & APR_FOPEN_LARGEFILE) {
+        oflags |= O_LARGEFILE;
+    }
+#endif
+
+#if APR_HAS_THREADS
+    if ((flag & APR_FOPEN_BUFFERED) && (flag & APR_FOPEN_XTHREAD)) {
+        rv = apr_thread_mutex_create(&thlock,
+                                     APR_THREAD_MUTEX_DEFAULT, pool);
+        if (rv) {
+            return rv;
+        }
+    }
+#endif
 
-    if ((*new)->filedes < 0) {
-       (*new)->filedes = -1;
-       (*new)->eof_hit = 1;
+    if (perm == APR_FPROT_OS_DEFAULT) {
+        fd = open(fname, oflags, 0666);
+    }
+    else {
+        fd = open(fname, oflags, apr_unix_perms2mode(perm));
+    } 
+    if (fd < 0) {
        return errno;
     }
+    if (!(flag & APR_FOPEN_NOCLEANUP)) {
+#ifdef O_CLOEXEC
+        static int has_o_cloexec = 0;
+        if (!has_o_cloexec)
+#endif
+        {
+            int flags;
 
-    if (flag & APR_DELONCLOSE) {
-        unlink(fname);
+            if ((flags = fcntl(fd, F_GETFD)) == -1) {
+                close(fd);
+                return errno;
+            }
+            if ((flags & FD_CLOEXEC) == 0) {
+                flags |= FD_CLOEXEC;
+                if (fcntl(fd, F_SETFD, flags) == -1) {
+                    close(fd);
+                    return errno;
+                }
+            }
+#ifdef O_CLOEXEC
+            else {
+                has_o_cloexec = 1;
+            }
+#endif
+        }
     }
-    (*new)->pipe = 0;
+
+    (*new) = (apr_file_t *)apr_pcalloc(pool, sizeof(apr_file_t));
+    (*new)->pool = pool;
+    (*new)->flags = flag;
+    (*new)->filedes = fd;
+
+    (*new)->fname = apr_pstrdup(pool, fname);
+
+    (*new)->blocking = BLK_ON;
+    (*new)->buffered = (flag & APR_FOPEN_BUFFERED) > 0;
+
+    if ((*new)->buffered) {
+        (*new)->buffer = apr_palloc(pool, APR_FILE_DEFAULT_BUFSIZE);
+        (*new)->bufsize = APR_FILE_DEFAULT_BUFSIZE;
+    }
+    else {
+        (*new)->buffer = NULL;
+    }
+
+#if APR_HAS_THREADS
+    (*new)->thlock = thlock;
+#endif
+
+    (*new)->is_pipe = 0;
     (*new)->timeout = -1;
     (*new)->ungetchar = -1;
     (*new)->eof_hit = 0;
@@ -153,23 +236,52 @@ ap_status_t ap_open(ap_file_t **new, const char *fname, ap_int32_t flag,  ap_fil
     (*new)->bufpos = 0;
     (*new)->dataRead = 0;
     (*new)->direction = 0;
-    ap_register_cleanup((*new)->cntxt, (void *)(*new), ap_unix_file_cleanup,
-                        ap_null_cleanup);
+#ifndef WAITIO_USES_POLL
+    /* Start out with no pollset.  apr_wait_for_io_or_timeout() will
+     * initialize the pollset if needed.
+     */
+    (*new)->pollset = NULL;
+#endif
+    if (!(flag & APR_FOPEN_NOCLEANUP)) {
+        apr_pool_cleanup_register((*new)->pool, (void *)(*new), 
+                                  apr_unix_file_cleanup, 
+                                  apr_unix_child_file_cleanup);
+    }
+
+    if ((flag & APR_FOPEN_ROTATING) || (flag & APR_FOPEN_MANUAL_ROTATE)) {
+        (*new)->rotating = (apr_rotating_info_t *)apr_pcalloc(pool,
+                                                              sizeof(apr_rotating_info_t));
+
+        rv =  apr_file_info_get(&(*new)->rotating->finfo,
+                                APR_FINFO_DEV|APR_FINFO_INODE, *new);
+        if (rv != APR_SUCCESS) {
+            return rv;
+        }
+
+        if (flag & APR_FOPEN_MANUAL_ROTATE) {
+            (*new)->rotating->manual = 1;
+        }
+        else {
+            (*new)->rotating->manual = 0;
+        }
+        (*new)->rotating->timeout = 60;
+        (*new)->rotating->lastcheck = apr_time_sec(apr_time_now());
+        (*new)->rotating->oflags = oflags;
+        (*new)->rotating->perm = perm;
+    }
+    else {
+        (*new)->rotating = NULL;
+    }
+
     return APR_SUCCESS;
 }
 
-ap_status_t ap_close(ap_file_t *file)
+APR_DECLARE(apr_status_t) apr_file_close(apr_file_t *file)
 {
-    ap_status_t rv;
-  
-    if ((rv = ap_unix_file_cleanup(file)) == APR_SUCCESS) {
-        ap_kill_cleanup(file->cntxt, file, ap_unix_file_cleanup);
-        return APR_SUCCESS;
-    }
-    return rv;
+    return apr_pool_cleanup_run(file->pool, file, apr_unix_file_cleanup);
 }
 
-ap_status_t ap_remove_file(char *path, ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_file_remove(const char *path, apr_pool_t *pool)
 {
     if (unlink(path) == 0) {
         return APR_SUCCESS;
@@ -179,37 +291,64 @@ ap_status_t ap_remove_file(char *path, ap_pool_t *cont)
     }
 }
 
-ap_status_t ap_get_os_file(ap_os_file_t *thefile, ap_file_t *file)
+APR_DECLARE(apr_status_t) apr_file_rename(const char *from_path, 
+                                          const char *to_path,
+                                          apr_pool_t *p)
 {
-    if (file == NULL) {
-        return APR_ENOFILE;
+    if (rename(from_path, to_path) != 0) {
+        return errno;
     }
+    return APR_SUCCESS;
+}
 
+APR_DECLARE(apr_status_t) apr_os_file_get(apr_os_file_t *thefile, 
+                                          apr_file_t *file)
+{
     *thefile = file->filedes;
     return APR_SUCCESS;
 }
 
-ap_status_t ap_put_os_file(ap_file_t **file, ap_os_file_t *thefile,
-                           ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_os_file_put(apr_file_t **file, 
+                                          apr_os_file_t *thefile,
+                                          apr_int32_t flags, apr_pool_t *pool)
 {
     int *dafile = thefile;
     
-    if ((*file) == NULL) {
-        (*file) = ap_pcalloc(cont, sizeof(ap_file_t));
-        (*file)->cntxt = cont;
-    }
+    (*file) = apr_pcalloc(pool, sizeof(apr_file_t));
+    (*file)->pool = pool;
     (*file)->eof_hit = 0;
-    (*file)->buffered = 0;
+    (*file)->blocking = BLK_UNKNOWN; /* in case it is a pipe */
     (*file)->timeout = -1;
+    (*file)->ungetchar = -1; /* no char avail */
     (*file)->filedes = *dafile;
-    /* buffer already NULL */
+    (*file)->flags = flags | APR_FOPEN_NOCLEANUP;
+    (*file)->buffered = (flags & APR_FOPEN_BUFFERED) > 0;
+
+#ifndef WAITIO_USES_POLL
+    /* Start out with no pollset.  apr_wait_for_io_or_timeout() will
+     * initialize the pollset if needed.
+     */
+    (*file)->pollset = NULL;
+#endif
+
+    if ((*file)->buffered) {
+        (*file)->buffer = apr_palloc(pool, APR_FILE_DEFAULT_BUFSIZE);
+        (*file)->bufsize = APR_FILE_DEFAULT_BUFSIZE;
 #if APR_HAS_THREADS
-    ap_create_lock(&((*file)->thlock), APR_MUTEX, APR_INTRAPROCESS, NULL, cont);
+        if ((*file)->flags & APR_FOPEN_XTHREAD) {
+            apr_status_t rv;
+            rv = apr_thread_mutex_create(&((*file)->thlock),
+                                         APR_THREAD_MUTEX_DEFAULT, pool);
+            if (rv) {
+                return rv;
+            }
+        }
 #endif
+    }
     return APR_SUCCESS;
 }    
 
-ap_status_t ap_eof(ap_file_t *fptr)
+APR_DECLARE(apr_status_t) apr_file_eof(apr_file_t *fptr)
 {
     if (fptr->eof_hit == 1) {
         return APR_EOF;
@@ -217,25 +356,88 @@ ap_status_t ap_eof(ap_file_t *fptr)
     return APR_SUCCESS;
 }   
 
-ap_status_t ap_ferror(ap_file_t *fptr)
+APR_DECLARE(apr_status_t) apr_file_open_flags_stderr(apr_file_t **thefile, 
+                                                     apr_int32_t flags,
+                                                     apr_pool_t *pool)
 {
-/* This function should be removed ASAP.  It is next on my list once
- * I am sure nobody is using it.
- */
+    int fd = STDERR_FILENO;
+
+    return apr_os_file_put(thefile, &fd, flags | APR_FOPEN_WRITE, pool);
+}
+
+APR_DECLARE(apr_status_t) apr_file_open_flags_stdout(apr_file_t **thefile, 
+                                                     apr_int32_t flags,
+                                                     apr_pool_t *pool)
+{
+    int fd = STDOUT_FILENO;
+
+    return apr_os_file_put(thefile, &fd, flags | APR_FOPEN_WRITE, pool);
+}
+
+APR_DECLARE(apr_status_t) apr_file_open_flags_stdin(apr_file_t **thefile, 
+                                                    apr_int32_t flags,
+                                                    apr_pool_t *pool)
+{
+    int fd = STDIN_FILENO;
+
+    return apr_os_file_put(thefile, &fd, flags | APR_FOPEN_READ, pool);
+}
+
+APR_DECLARE(apr_status_t) apr_file_open_stderr(apr_file_t **thefile, 
+                                               apr_pool_t *pool)
+{
+    return apr_file_open_flags_stderr(thefile, 0, pool);
+}
+
+APR_DECLARE(apr_status_t) apr_file_open_stdout(apr_file_t **thefile, 
+                                               apr_pool_t *pool)
+{
+    return apr_file_open_flags_stdout(thefile, 0, pool);
+}
+
+APR_DECLARE(apr_status_t) apr_file_open_stdin(apr_file_t **thefile, 
+                                              apr_pool_t *pool)
+{
+    return apr_file_open_flags_stdin(thefile, 0, pool);
+}
+
+APR_IMPLEMENT_INHERIT_SET(file, flags, pool, apr_unix_file_cleanup)
+
+/* We need to do this by hand instead of using APR_IMPLEMENT_INHERIT_UNSET
+ * because the macro sets both cleanups to the same function, which is not
+ * suitable on Unix (see PR 41119). */
+APR_DECLARE(apr_status_t) apr_file_inherit_unset(apr_file_t *thefile)
+{
+    if (thefile->flags & APR_FOPEN_NOCLEANUP) {
+        return APR_EINVAL;
+    }
+    if (thefile->flags & APR_INHERIT) {
+        int flags;
+
+        if ((flags = fcntl(thefile->filedes, F_GETFD)) == -1)
+            return errno;
+
+        flags |= FD_CLOEXEC;
+        if (fcntl(thefile->filedes, F_SETFD, flags) == -1)
+            return errno;
+
+        thefile->flags &= ~APR_INHERIT;
+        apr_pool_child_cleanup_set(thefile->pool,
+                                   (void *)thefile,
+                                   apr_unix_file_cleanup,
+                                   apr_unix_child_file_cleanup);
+    }
     return APR_SUCCESS;
-}   
+}
+
+APR_POOL_IMPLEMENT_ACCESSOR(file)
 
-ap_status_t ap_open_stderr(ap_file_t **thefile, ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_file_link(const char *from_path, 
+                                          const char *to_path)
 {
-    (*thefile) = ap_pcalloc(cont, sizeof(ap_file_t));
-    if ((*thefile) == NULL) {
-        return APR_ENOMEM;
+    if (link(from_path, to_path) == -1) {
+        return errno;
     }
-    (*thefile)->filedes = STDERR_FILENO;
-    (*thefile)->cntxt = cont;
-    (*thefile)->buffered = 0;
-    (*thefile)->fname = NULL;
-    (*thefile)->eof_hit = 0;
 
     return APR_SUCCESS;
 }
diff --git a/file_io/unix/pipe.c b/file_io/unix/pipe.c
index 2f2091bd821..b68ac65423e 100644
--- a/file_io/unix/pipe.c
+++ b/file_io/unix/pipe.c
@@ -1,91 +1,186 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "fileio.h"
+#include "apr_arch_file_io.h"
+#include "apr_strings.h"
+#include "apr_portable.h"
 
-static ap_status_t pipenonblock(ap_file_t *thefile)
-{
-#ifndef BEOS /* this code won't work on BeOS */
-    int fd_flags = fcntl(thefile->filedes, F_GETFL, 0);
-
-#if defined(O_NONBLOCK)
-    fd_flags |= O_NONBLOCK;
-#elif defined(O_NDELAY)
-    fd_flags |= O_NDELAY;
-#elif defined(FNDELAY)
-    fd_flags |= O_FNDELAY;
+#include "apr_arch_inherit.h"
+
+/* Figure out how to get pipe block/nonblock on BeOS...
+ * Basically, BONE7 changed things again so that ioctl didn't work,
+ * but now fcntl does, hence we need to do this extra checking.
+ * The joys of beta programs. :-)
+ */
+#if defined(BEOS)
+#if !defined(BONE7)
+# define BEOS_BLOCKING 1
 #else
-    /* XXXX: this breaks things, but an alternative isn't obvious...*/
-    return -1;
+# define BEOS_BLOCKING 0
 #endif
-    if (fcntl(thefile->filedes, F_SETFL, fd_flags) == -1) {
-        return errno;
-    }
-#endif /* !BeOS */
+#endif
+
+static apr_status_t pipeblock(apr_file_t *thepipe)
+{
+#if !defined(BEOS) || !BEOS_BLOCKING
+      int fd_flags;
+
+      fd_flags = fcntl(thepipe->filedes, F_GETFL, 0);
+#  if defined(O_NONBLOCK)
+      fd_flags &= ~O_NONBLOCK;
+#  elif defined(O_NDELAY)
+      fd_flags &= ~O_NDELAY;
+#  elif defined(O_FNDELAY)
+      fd_flags &= ~O_FNDELAY;
+#  else 
+      /* XXXX: this breaks things, but an alternative isn't obvious...*/
+      return APR_ENOTIMPL;
+#  endif
+      if (fcntl(thepipe->filedes, F_SETFL, fd_flags) == -1) {
+          return errno;
+      }
+#else /* BEOS_BLOCKING */
+
+#  if BEOS_BONE /* This only works on BONE 0-6 */
+      int on = 0;
+      if (ioctl(thepipe->filedes, FIONBIO, &on, sizeof(on)) < 0) {
+          return errno;
+      }
+#  else /* "classic" BeOS doesn't support this at all */
+      return APR_ENOTIMPL;
+#  endif 
+ 
+#endif /* !BEOS_BLOCKING */
+
+    thepipe->blocking = BLK_ON;
     return APR_SUCCESS;
 }
 
-ap_status_t ap_set_pipe_timeout(ap_file_t *thepipe, ap_interval_time_t timeout)
+static apr_status_t pipenonblock(apr_file_t *thepipe)
 {
-    if (thepipe->pipe == 1) {
+#if !defined(BEOS) || !BEOS_BLOCKING
+      int fd_flags = fcntl(thepipe->filedes, F_GETFL, 0);
+
+#  if defined(O_NONBLOCK)
+      fd_flags |= O_NONBLOCK;
+#  elif defined(O_NDELAY)
+      fd_flags |= O_NDELAY;
+#  elif defined(O_FNDELAY)
+      fd_flags |= O_FNDELAY;
+#  else
+      /* XXXX: this breaks things, but an alternative isn't obvious...*/
+      return APR_ENOTIMPL;
+#  endif
+      if (fcntl(thepipe->filedes, F_SETFL, fd_flags) == -1) {
+          return errno;
+      }
+    
+#else /* BEOS_BLOCKING */
+
+#  if BEOS_BONE /* This only works on BONE 0-6 */
+      int on = 1;
+      if (ioctl(thepipe->filedes, FIONBIO, &on, sizeof(on)) < 0) {
+          return errno;
+      }
+#  else /* "classic" BeOS doesn't support this at all */
+      return APR_ENOTIMPL;
+#  endif
+
+#endif /* !BEOS_BLOCKING */
+
+    thepipe->blocking = BLK_OFF;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_file_pipe_timeout_set(apr_file_t *thepipe, apr_interval_time_t timeout)
+{
+    if (thepipe->is_pipe == 1) {
         thepipe->timeout = timeout;
+        if (timeout >= 0) {
+            if (thepipe->blocking != BLK_OFF) { /* blocking or unknown state */
+                return pipenonblock(thepipe);
+            }
+        }
+        else {
+            if (thepipe->blocking != BLK_ON) { /* non-blocking or unknown state */
+                return pipeblock(thepipe);
+            }
+        }
+        return APR_SUCCESS;
+    }
+    return APR_EINVAL;
+}
+
+APR_DECLARE(apr_status_t) apr_file_pipe_timeout_get(apr_file_t *thepipe, apr_interval_time_t *timeout)
+{
+    if (thepipe->is_pipe == 1) {
+        *timeout = thepipe->timeout;
         return APR_SUCCESS;
     }
     return APR_EINVAL;
 }
 
-ap_status_t ap_create_pipe(ap_file_t **in, ap_file_t **out, ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_os_pipe_put_ex(apr_file_t **file,
+                                             apr_os_file_t *thefile,
+                                             int register_cleanup,
+                                             apr_pool_t *pool)
+{
+    int *dafile = thefile;
+    
+    (*file) = apr_pcalloc(pool, sizeof(apr_file_t));
+    (*file)->pool = pool;
+    (*file)->eof_hit = 0;
+    (*file)->is_pipe = 1;
+    (*file)->blocking = BLK_UNKNOWN; /* app needs to make a timeout call */
+    (*file)->timeout = -1;
+    (*file)->ungetchar = -1; /* no char avail */
+    (*file)->filedes = *dafile;
+    if (!register_cleanup) {
+        (*file)->flags = APR_FOPEN_NOCLEANUP;
+    }
+    (*file)->buffered = 0;
+#if APR_HAS_THREADS
+    (*file)->thlock = NULL;
+#endif
+    if (register_cleanup) {
+        apr_pool_cleanup_register((*file)->pool, (void *)(*file),
+                                  apr_unix_file_cleanup,
+                                  apr_pool_cleanup_null);
+    }
+#ifndef WAITIO_USES_POLL
+    /* Start out with no pollset.  apr_wait_for_io_or_timeout() will
+     * initialize the pollset if needed.
+     */
+    (*file)->pollset = NULL;
+#endif
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_os_pipe_put(apr_file_t **file,
+                                          apr_os_file_t *thefile,
+                                          apr_pool_t *pool)
+{
+    return apr_os_pipe_put_ex(file, thefile, 0, pool);
+}
+
+static apr_status_t file_pipe_create(apr_file_t **in,
+                                     apr_file_t **out,
+                                     apr_int32_t blocking,
+                                     apr_pool_t *pool_in,
+                                     apr_pool_t *pool_out)
 {
     int filedes[2];
 
@@ -93,39 +188,88 @@ ap_status_t ap_create_pipe(ap_file_t **in, ap_file_t **out, ap_pool_t *cont)
         return errno;
     }
     
-    (*in) = (ap_file_t *)ap_palloc(cont, sizeof(ap_file_t));
-    (*in)->cntxt = cont;
+    (*in) = (apr_file_t *)apr_pcalloc(pool_in, sizeof(apr_file_t));
+    (*in)->pool = pool_in;
     (*in)->filedes = filedes[0];
-    (*in)->pipe = 1;
-    (*in)->fname = ap_pstrdup(cont, "PIPE");
+    (*in)->is_pipe = 1;
+    (*in)->fname = NULL;
     (*in)->buffered = 0;
+    (*in)->blocking = BLK_ON;
     (*in)->timeout = -1;
     (*in)->ungetchar = -1;
+    (*in)->flags = APR_INHERIT;
 #if APR_HAS_THREADS
     (*in)->thlock = NULL;
 #endif
-
-    (*out) = (ap_file_t *)ap_palloc(cont, sizeof(ap_file_t));
-    (*out)->cntxt = cont;
+#ifndef WAITIO_USES_POLL
+    (*in)->pollset = NULL;
+#endif
+    (*out) = (apr_file_t *)apr_pcalloc(pool_out, sizeof(apr_file_t));
+    (*out)->pool = pool_out;
     (*out)->filedes = filedes[1];
-    (*out)->pipe = 1;
-    (*out)->fname = ap_pstrdup(cont, "PIPE");
+    (*out)->is_pipe = 1;
+    (*out)->fname = NULL;
     (*out)->buffered = 0;
+    (*out)->blocking = BLK_ON;
+    (*out)->flags = APR_INHERIT;
     (*out)->timeout = -1;
 #if APR_HAS_THREADS
-    (*in)->thlock = NULL;
+    (*out)->thlock = NULL;
 #endif
+#ifndef WAITIO_USES_POLL
+    (*out)->pollset = NULL;
+#endif
+    apr_pool_cleanup_register((*in)->pool, (void *)(*in), apr_unix_file_cleanup,
+                         apr_pool_cleanup_null);
+    apr_pool_cleanup_register((*out)->pool, (void *)(*out), apr_unix_file_cleanup,
+                         apr_pool_cleanup_null);
 
-    pipenonblock(*in);
-    pipenonblock(*out);
-
+    switch (blocking) {
+    case APR_FULL_BLOCK:
+        break;
+    case APR_READ_BLOCK:
+        apr_file_pipe_timeout_set(*out, 0);
+        break;
+    case APR_WRITE_BLOCK:
+        apr_file_pipe_timeout_set(*in, 0);
+        break;
+    default:
+        apr_file_pipe_timeout_set(*out, 0);
+        apr_file_pipe_timeout_set(*in, 0);
+        break;
+    }
     return APR_SUCCESS;
 }
 
-ap_status_t ap_create_namedpipe(char *filename, 
-                                ap_fileperms_t perm, ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_file_pipe_create(apr_file_t **in,
+                                               apr_file_t **out,
+                                               apr_pool_t *pool)
+{
+    /* Default is full blocking pipes. */
+    return file_pipe_create(in, out, APR_FULL_BLOCK, pool, pool);
+}
+
+APR_DECLARE(apr_status_t) apr_file_pipe_create_ex(apr_file_t **in, 
+                                                  apr_file_t **out, 
+                                                  apr_int32_t blocking,
+                                                  apr_pool_t *pool)
+{
+    return file_pipe_create(in, out, blocking, pool, pool);
+}
+
+APR_DECLARE(apr_status_t) apr_file_pipe_create_pools(apr_file_t **in,
+                                                     apr_file_t **out,
+                                                     apr_int32_t blocking,
+                                                     apr_pool_t *pool_in,
+                                                     apr_pool_t *pool_out)
+{
+    return file_pipe_create(in, out, blocking, pool_in, pool_out);
+}
+
+APR_DECLARE(apr_status_t) apr_file_namedpipe_create(const char *filename, 
+                                                    apr_fileperms_t perm, apr_pool_t *pool)
 {
-    mode_t mode = ap_unix_get_fileperms(perm);
+    mode_t mode = apr_unix_perms2mode(perm);
 
     if (mkfifo(filename, mode) == -1) {
         return errno;
@@ -133,27 +277,5 @@ ap_status_t ap_create_namedpipe(char *filename,
     return APR_SUCCESS;
 } 
 
-ap_status_t ap_block_pipe(ap_file_t *thepipe)
-{
-#ifndef BEOS /* this code won't work on BeOS */
-    int fd_flags;
-
-    fd_flags = fcntl(thepipe->filedes, F_GETFL, 0);
-#if defined(O_NONBLOCK)
-    fd_flags &= ~O_NONBLOCK;
-#elif defined(~O_NDELAY)
-    fd_flags &= ~O_NDELAY;
-#elif defined(FNDELAY)
-    fd_flags &= ~O_FNDELAY;
-#else 
-    /* XXXX: this breaks things, but an alternative isn't obvious...*/
-    return -1;
-#endif
-    if (fcntl(thepipe->filedes, F_SETFL, fd_flags) == -1) {
-        return errno;
-    }
-#endif /* !BeOS */
-    return APR_SUCCESS;
-}
     
 
diff --git a/file_io/unix/printf.c b/file_io/unix/printf.c
new file mode 100644
index 00000000000..03c23b22256
--- /dev/null
+++ b/file_io/unix/printf.c
@@ -0,0 +1,70 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_file_io.h"
+#include "apr_strings.h"
+#include "apr_lib.h"
+
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+struct apr_file_printf_data {
+    apr_vformatter_buff_t vbuff;
+    apr_file_t *fptr;
+    char *buf;
+};
+
+static int file_printf_flush(apr_vformatter_buff_t *buff)
+{
+    struct apr_file_printf_data *data = (struct apr_file_printf_data *)buff;
+
+    if (apr_file_write_full(data->fptr, data->buf, 
+                            data->vbuff.curpos - data->buf, NULL)) {
+        return -1;
+    }
+
+    data->vbuff.curpos = data->buf;
+    return 0;
+}
+
+APR_DECLARE_NONSTD(int) apr_file_printf(apr_file_t *fptr, 
+                                        const char *format, ...)
+{
+    struct apr_file_printf_data data;
+    va_list ap;
+    int count;
+
+    /* don't really need a HUGE_STRING_LEN anymore */
+    data.buf = malloc(HUGE_STRING_LEN);
+    if (data.buf == NULL) {
+        return -1;
+    }
+    data.vbuff.curpos = data.buf;
+    data.vbuff.endpos = data.buf + HUGE_STRING_LEN;
+    data.fptr = fptr;
+    va_start(ap, format);
+    count = apr_vformatter(file_printf_flush,
+                           (apr_vformatter_buff_t *)&data, format, ap);
+    /* apr_vformatter does not call flush for the last bits */
+    if (count >= 0) file_printf_flush((apr_vformatter_buff_t *)&data);
+
+    va_end(ap);
+
+    free(data.buf);
+
+    return count;
+}
diff --git a/file_io/unix/readwrite.c b/file_io/unix/readwrite.c
index 5b0d1d6a6cd..f9c7b06bdb4 100644
--- a/file_io/unix/readwrite.c
+++ b/file_io/unix/readwrite.c
@@ -1,143 +1,103 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "fileio.h"
-#include "apr_lock.h"
+#include "apr_arch_file_io.h"
+#include "apr_strings.h"
+#include "apr_thread_mutex.h"
+#include "apr_support.h"
+#include "apr_time.h"
+#include "apr_file_info.h"
+
+/* The only case where we don't use wait_for_io_or_timeout is on
+ * pre-BONE BeOS, so this check should be sufficient and simpler */
+#if !defined(BEOS_R5)
+#define USE_WAIT_FOR_IO
+#endif
 
-static ap_status_t wait_for_io_or_timeout(ap_file_t *file, int for_read)
+static apr_status_t file_read_buffered(apr_file_t *thefile, void *buf,
+                                       apr_size_t *nbytes)
 {
-    struct timeval tv, *tvptr;
-    fd_set fdset;
-    int srv;
-
-    /* TODO - timeout should be less each time through this loop */
-
-    do {
-        FD_ZERO(&fdset);
-        FD_SET(file->filedes, &fdset);
-        if (file->timeout >= 0) {
-            tv.tv_sec = file->timeout / AP_USEC_PER_SEC;
-            tv.tv_usec = file->timeout % AP_USEC_PER_SEC;
-            tvptr = &tv;
+    apr_ssize_t rv;
+    char *pos = (char *)buf;
+    apr_uint64_t blocksize;
+    apr_uint64_t size = *nbytes;
+
+    if (thefile->direction == 1) {
+        rv = apr_file_flush_locked(thefile);
+        if (rv) {
+            return rv;
         }
-        else {
-            tvptr = NULL;
+        thefile->bufpos = 0;
+        thefile->direction = 0;
+        thefile->dataRead = 0;
+    }
+
+    rv = 0;
+    if (thefile->ungetchar != -1) {
+        *pos = (char)thefile->ungetchar;
+        ++pos;
+        --size;
+        thefile->ungetchar = -1;
+    }
+    while (rv == 0 && size > 0) {
+        if (thefile->bufpos >= thefile->dataRead) {
+            int bytesread = read(thefile->filedes, thefile->buffer, 
+                                 thefile->bufsize);
+            if (bytesread == 0) {
+                thefile->eof_hit = TRUE;
+                rv = APR_EOF;
+                break;
+            }
+            else if (bytesread == -1) {
+                rv = errno;
+                break;
+            }
+            thefile->dataRead = bytesread;
+            thefile->filePtr += thefile->dataRead;
+            thefile->bufpos = 0;
         }
-        srv = select(FD_SETSIZE,
-            for_read ? &fdset : NULL,
-            for_read ? NULL : &fdset,
-            NULL,
-            tvptr);
-    } while (srv == -1 && errno == EINTR);
-
-    if (srv == 0) {
-        return APR_TIMEUP;
+
+        blocksize = size > thefile->dataRead - thefile->bufpos ? thefile->dataRead - thefile->bufpos : size;
+        memcpy(pos, thefile->buffer + thefile->bufpos, blocksize);
+        thefile->bufpos += blocksize;
+        pos += blocksize;
+        size -= blocksize;
     }
-    else if (srv < 0) {
-        return errno;
+
+    *nbytes = pos - (char *)buf;
+    if (*nbytes) {
+        rv = 0;
     }
-    return APR_SUCCESS;
+    return rv;
 }
 
-ap_status_t ap_read(ap_file_t *thefile, void *buf, ap_ssize_t *nbytes)
+APR_DECLARE(apr_status_t) apr_file_read(apr_file_t *thefile, void *buf, apr_size_t *nbytes)
 {
-    ap_ssize_t rv;
-    ap_ssize_t bytes_read;
+    apr_ssize_t rv;
+    apr_size_t bytes_read;
 
-    if(*nbytes <= 0) {
+    if (*nbytes <= 0) {
         *nbytes = 0;
-	return APR_SUCCESS;
+        return APR_SUCCESS;
     }
 
     if (thefile->buffered) {
-        char *pos = (char *)buf;
-        ap_uint64_t blocksize;
-        ap_uint64_t size = *nbytes;
-
-#if APR_HAS_THREADS
-        ap_lock(thefile->thlock);
-#endif
-
-        if (thefile->direction == 1) {
-            ap_flush(thefile);
-            thefile->bufpos = 0;
-            thefile->direction = 0;
-            thefile->dataRead = 0;
-        }
-
-	rv = 0;
-        while (rv == 0 && size > 0) {
-            if (thefile->bufpos >= thefile->dataRead) {
-                thefile->dataRead = read(thefile->filedes, thefile->buffer, APR_FILE_BUFSIZE);
-                if (thefile->dataRead == 0) {
-                    thefile->eof_hit = TRUE;
-                    break;
-                }
-                thefile->filePtr += thefile->dataRead;
-                thefile->bufpos = 0;
-            }
-
-            blocksize = size > thefile->dataRead - thefile->bufpos ? thefile->dataRead - thefile->bufpos : size;                                                            memcpy(pos, thefile->buffer + thefile->bufpos, blocksize);
-            thefile->bufpos += blocksize;
-            pos += blocksize;
-            size -= blocksize;
-        }
-
-        *nbytes = rv == 0 ? pos - (char *)buf : 0;
-#if APR_HAS_THREADS
-        ap_unlock(thefile->thlock);
-#endif
+        file_lock(thefile);
+        rv = file_read_buffered(thefile, buf, nbytes);
+        file_unlock(thefile);
         return rv;
     }
     else {
@@ -148,20 +108,20 @@ ap_status_t ap_read(ap_file_t *thefile, void *buf, ap_ssize_t *nbytes)
             buf = (char *)buf + 1;
             (*nbytes)--;
             thefile->ungetchar = -1;
-	if     (*nbytes == 0) {
-	        *nbytes = bytes_read;
-	        return APR_SUCCESS;
-	}
+            if (*nbytes == 0) {
+                *nbytes = bytes_read;
+                return APR_SUCCESS;
+            }
         }
 
         do {
             rv = read(thefile->filedes, buf, *nbytes);
         } while (rv == -1 && errno == EINTR);
-
+#ifdef USE_WAIT_FOR_IO
         if (rv == -1 && 
             (errno == EAGAIN || errno == EWOULDBLOCK) && 
             thefile->timeout != 0) {
-            ap_status_t arv = wait_for_io_or_timeout(thefile, 1);
+            apr_status_t arv = apr_wait_for_io_or_timeout(thefile, NULL, 1);
             if (arv != APR_SUCCESS) {
                 *nbytes = bytes_read;
                 return arv;
@@ -172,81 +132,173 @@ ap_status_t ap_read(ap_file_t *thefile, void *buf, ap_ssize_t *nbytes)
                 } while (rv == -1 && errno == EINTR);
             }
         }  
-
+#endif
         *nbytes = bytes_read;
         if (rv == 0) {
-	return     APR_EOF;
+            thefile->eof_hit = TRUE;
+            return APR_EOF;
         }
         if (rv > 0) {
-	*nbytes     += rv;
-	return     APR_SUCCESS;
+            *nbytes += rv;
+            return APR_SUCCESS;
         }
         return errno;
     }
 }
 
-ap_status_t ap_write(ap_file_t *thefile, void *buf, ap_ssize_t *nbytes)
+static apr_status_t do_rotating_check(apr_file_t *thefile, apr_time_t now)
+{
+    apr_size_t rv = APR_SUCCESS;
+
+    if ((now - thefile->rotating->lastcheck) >= thefile->rotating->timeout) {
+        apr_finfo_t new_finfo;
+        apr_pool_t *tmp_pool;
+
+        apr_pool_create(&tmp_pool, thefile->pool);
+
+        rv = apr_stat(&new_finfo, thefile->fname,
+                      APR_FINFO_DEV|APR_FINFO_INODE, tmp_pool);
+
+        if (rv != APR_SUCCESS || 
+            new_finfo.inode != thefile->rotating->finfo.inode ||
+            new_finfo.device != thefile->rotating->finfo.device)  {
+
+            if (thefile->buffered) {
+                apr_file_flush(thefile);
+            }
+
+            close(thefile->filedes);
+            thefile->filedes = -1;
+
+            if (thefile->rotating->perm == APR_FPROT_OS_DEFAULT) {
+                thefile->filedes = open(thefile->fname,
+                                        thefile->rotating->oflags,
+                                        0666);
+            }
+            else {
+                thefile->filedes = open(thefile->fname,
+                                        thefile->rotating->oflags,
+                                        apr_unix_perms2mode(thefile->rotating->perm));
+            }
+
+            if (thefile->filedes < 0) {
+                rv = errno;
+            }
+            else {
+                rv = apr_file_info_get(&thefile->rotating->finfo,
+                                       APR_FINFO_DEV|APR_FINFO_INODE,
+                                       thefile);
+            }
+        }
+
+        apr_pool_destroy(tmp_pool);
+        thefile->rotating->lastcheck = now;
+    }
+    return rv;
+}
+
+static apr_status_t file_rotating_check(apr_file_t *thefile)
 {
-    ap_size_t rv;
+    if (thefile->rotating && thefile->rotating->manual == 0) {
+        apr_time_t now = apr_time_sec(apr_time_now());
+        return do_rotating_check(thefile, now);
+    }
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_file_rotating_check(apr_file_t *thefile)
+{
+    if (thefile->rotating) {
+        apr_time_t now = apr_time_sec(apr_time_now());
+        return do_rotating_check(thefile, now);
+    }
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_file_rotating_manual_check(apr_file_t *thefile, apr_time_t n)
+{
+    if (thefile->rotating) {
+        return do_rotating_check(thefile, n);
+    }
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_file_write(apr_file_t *thefile, const void *buf, apr_size_t *nbytes)
+{
+    apr_size_t rv;
+
+    rv = file_rotating_check(thefile);
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
 
     if (thefile->buffered) {
         char *pos = (char *)buf;
         int blocksize;
         int size = *nbytes;
 
-#if APR_HAS_THREADS
-        ap_lock(thefile->thlock);
-#endif
+        file_lock(thefile);
 
         if ( thefile->direction == 0 ) {
             /* Position file pointer for writing at the offset we are 
              * logically reading from
              */
-            ap_int64_t offset = thefile->filePtr - thefile->dataRead + thefile->bufpos;
+            apr_int64_t offset = thefile->filePtr - thefile->dataRead + thefile->bufpos;
             if (offset != thefile->filePtr)
                 lseek(thefile->filedes, offset, SEEK_SET);
             thefile->bufpos = thefile->dataRead = 0;
             thefile->direction = 1;
         }
 
-	rv = 0;
+        rv = 0;
         while (rv == 0 && size > 0) {
-            if (thefile->bufpos == APR_FILE_BUFSIZE)   /* write buffer is full*/
-                ap_flush(thefile);
+            if (thefile->bufpos == thefile->bufsize)   /* write buffer is full*/
+                rv = apr_file_flush_locked(thefile);
 
-            blocksize = size > APR_FILE_BUFSIZE - thefile->bufpos ? 
-                        APR_FILE_BUFSIZE - thefile->bufpos : size;
-            memcpy(thefile->buffer + thefile->bufpos, pos, blocksize);                      thefile->bufpos += blocksize;
+            blocksize = size > thefile->bufsize - thefile->bufpos ? 
+                        thefile->bufsize - thefile->bufpos : size;
+            memcpy(thefile->buffer + thefile->bufpos, pos, blocksize);                      
+            thefile->bufpos += blocksize;
             pos += blocksize;
             size -= blocksize;
         }
 
-#if APR_HAS_THREADS
-        ap_unlock(thefile->thlock);
-#endif
+        file_unlock(thefile);
+
         return rv;
     }
     else {
         do {
             rv = write(thefile->filedes, buf, *nbytes);
-        } while (rv == (ap_size_t)-1 && errno == EINTR);
-
-        if (rv == (ap_size_t)-1 &&
+        } while (rv == (apr_size_t)-1 && errno == EINTR);
+#ifdef USE_WAIT_FOR_IO
+        if (rv == (apr_size_t)-1 &&
             (errno == EAGAIN || errno == EWOULDBLOCK) && 
             thefile->timeout != 0) {
-            ap_status_t arv = wait_for_io_or_timeout(thefile, 0);
+            apr_status_t arv = apr_wait_for_io_or_timeout(thefile, NULL, 0);
             if (arv != APR_SUCCESS) {
                 *nbytes = 0;
                 return arv;
             }
             else {
                 do {
-                    rv = write(thefile->filedes, buf, *nbytes);
-	        } while (rv == (ap_size_t)-1 && errno == EINTR);
+                    do {
+                        rv = write(thefile->filedes, buf, *nbytes);
+                    } while (rv == (apr_size_t)-1 && errno == EINTR);
+                    if (rv == (apr_size_t)-1 &&
+                        (errno == EAGAIN || errno == EWOULDBLOCK)) {
+                        *nbytes /= 2; /* yes, we'll loop if kernel lied
+                                       * and we can't even write 1 byte
+                                       */
+                    }
+                    else {
+                        break;
+                    }
+                } while (1);
             }
         }  
-
-        if (rv == (ap_size_t)-1) {
+#endif
+        if (rv == (apr_size_t)-1) {
             (*nbytes) = 0;
             return errno;
         }
@@ -255,160 +307,271 @@ ap_status_t ap_write(ap_file_t *thefile, void *buf, ap_ssize_t *nbytes)
     }
 }
 
-ap_status_t ap_writev(ap_file_t *thefile, const struct iovec *vec,
-                      ap_size_t nvec, ap_ssize_t *nbytes)
+APR_DECLARE(apr_status_t) apr_file_writev(apr_file_t *thefile, const struct iovec *vec,
+                                          apr_size_t nvec, apr_size_t *nbytes)
 {
 #ifdef HAVE_WRITEV
-    int bytes;
+    apr_status_t rv;
+    apr_ssize_t bytes;
+
+    if (thefile->buffered) {
+        file_lock(thefile);
+
+        rv = apr_file_flush_locked(thefile);
+        if (rv != APR_SUCCESS) {
+            file_unlock(thefile);
+            return rv;
+        }
+        if (thefile->direction == 0) {
+            /* Position file pointer for writing at the offset we are
+             * logically reading from
+             */
+            apr_int64_t offset = thefile->filePtr - thefile->dataRead +
+                                 thefile->bufpos;
+            if (offset != thefile->filePtr)
+                lseek(thefile->filedes, offset, SEEK_SET);
+            thefile->bufpos = thefile->dataRead = 0;
+        }
+
+        file_unlock(thefile);
+    }
+
+    rv = file_rotating_check(thefile);
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
 
     if ((bytes = writev(thefile->filedes, vec, nvec)) < 0) {
         *nbytes = 0;
-        return errno;
+        rv = errno;
     }
     else {
         *nbytes = bytes;
-        return APR_SUCCESS;
+        rv = APR_SUCCESS;
     }
+    return rv;
 #else
+    /**
+     * The problem with trying to output the entire iovec is that we cannot
+     * maintain the behaviour that a real writev would have.  If we iterate
+     * over the iovec one at a time, we lose the atomic properties of 
+     * writev().  The other option is to combine the entire iovec into one
+     * buffer that we could then send in one call to write().  This is not 
+     * reasonable since we do not know how much data an iovec could contain.
+     *
+     * The only reasonable option, that maintains the semantics of a real 
+     * writev(), is to only write the first iovec.  Callers of file_writev()
+     * must deal with partial writes as they normally would. If you want to 
+     * ensure an entire iovec is written, use apr_file_writev_full().
+     */
+
     *nbytes = vec[0].iov_len;
-    return ap_write(thefile, vec[0].iov_base, nbytes);
+    return apr_file_write(thefile, vec[0].iov_base, nbytes);
 #endif
 }
 
-ap_status_t ap_putc(char ch, ap_file_t *thefile)
+APR_DECLARE(apr_status_t) apr_file_putc(char ch, apr_file_t *thefile)
 {
-    if (write(thefile->filedes, &ch, 1) != 1) {
-        return errno;
-    }
-    return APR_SUCCESS; 
+    apr_size_t nbytes = 1;
+
+    return apr_file_write(thefile, &ch, &nbytes);
 }
 
-ap_status_t ap_ungetc(char ch, ap_file_t *thefile)
+APR_DECLARE(apr_status_t) apr_file_ungetc(char ch, apr_file_t *thefile)
 {
     thefile->ungetchar = (unsigned char)ch;
     return APR_SUCCESS; 
 }
 
-ap_status_t ap_getc(char *ch, ap_file_t *thefile)
+APR_DECLARE(apr_status_t) apr_file_getc(char *ch, apr_file_t *thefile)
 {
-    ssize_t rv;
-    
-    if (thefile->ungetchar != -1) {
-        *ch = (char) thefile->ungetchar;
-        thefile->ungetchar = -1;
-        return APR_SUCCESS;
-    }
-    rv = read(thefile->filedes, ch, 1); 
-    if (rv == 0) {
-        thefile->eof_hit = TRUE;
-        return APR_EOF;
-    }
-    else if (rv != 1) {
-        return errno;
-    }
-    return APR_SUCCESS; 
+    apr_size_t nbytes = 1;
+
+    return apr_file_read(thefile, ch, &nbytes);
 }
 
-ap_status_t ap_puts(char *str, ap_file_t *thefile)
+APR_DECLARE(apr_status_t) apr_file_puts(const char *str, apr_file_t *thefile)
 {
-    ssize_t rv;
-    int len;
-
-    len = strlen(str);
-    rv = write(thefile->filedes, str, len); 
-    if (rv != len) {
-        return errno;
-    }
-    return APR_SUCCESS; 
+    return apr_file_write_full(thefile, str, strlen(str), NULL);
 }
 
-ap_status_t ap_flush(ap_file_t *thefile)
+apr_status_t apr_file_flush_locked(apr_file_t *thefile)
 {
-    if (thefile->buffered) {
-        ap_int64_t written = 0;
-        int rc = 0;
+    apr_status_t rv = APR_SUCCESS;
 
-        if (thefile->direction == 1 && thefile->bufpos) {
-            written= write(thefile->filedes, thefile->buffer, thefile->bufpos);
-            thefile->filePtr += written;
+    if (thefile->direction == 1 && thefile->bufpos) {
+        apr_ssize_t written = 0, ret;
 
-            if (rc == 0)
-                thefile->bufpos = 0;
+        do {
+            ret = write(thefile->filedes, thefile->buffer + written,
+                        thefile->bufpos - written);
+            if (ret > 0)
+                written += ret;
+        } while (written < thefile->bufpos &&
+                 (ret > 0 || (ret == -1 && errno == EINTR)));
+        if (ret == -1) {
+            rv = errno;
+        } else {
+            thefile->filePtr += written;
+            thefile->bufpos = 0;
         }
+    }
+
+    return rv;
+}
+
+APR_DECLARE(apr_status_t) apr_file_flush(apr_file_t *thefile)
+{
+    apr_status_t rv = APR_SUCCESS;
 
-        return rc;
+    if (thefile->buffered) {
+        file_lock(thefile);
+        rv = apr_file_flush_locked(thefile);
+        file_unlock(thefile);
     }
     /* There isn't anything to do if we aren't buffering the output
      * so just return success.
      */
-    return APR_SUCCESS; 
+    return rv;
 }
 
-ap_status_t ap_fgets(char *str, int len, ap_file_t *thefile)
+APR_DECLARE(apr_status_t) apr_file_sync(apr_file_t *thefile)
 {
-    ssize_t rv;
-    int i, used_unget = FALSE, beg_idx;
+    apr_status_t rv = APR_SUCCESS;
 
-    if(len <= 1)  /* as per fgets() */
-        return APR_SUCCESS;
+    file_lock(thefile);
 
-    if(thefile->ungetchar != -1){
-        str[0] = thefile->ungetchar;
-	used_unget = TRUE;
-	beg_idx = 1;
-	if(str[0] == '\n' || str[0] == '\r'){
-	    thefile->ungetchar = -1;
-	    str[1] = '\0';
-	    return APR_SUCCESS;
-	}
-    } else
-        beg_idx = 0;
-    
-    for (i = beg_idx; i < len; i++) {
-        rv = read(thefile->filedes, &str[i], 1); 
-        if (rv == 0) {
-            thefile->eof_hit = TRUE;
-	    if(used_unget) thefile->filedes = -1;
-	    str[i] = '\0';
-            return APR_EOF;
-        }
-        else if (rv != 1) {
-            return errno;
+    if (thefile->buffered) {
+        rv = apr_file_flush_locked(thefile);
+
+        if (rv != APR_SUCCESS) {
+            file_unlock(thefile);
+            return rv;
         }
-        if (str[i] == '\n' || str[i] == '\r')
-            break;
     }
-    if (i < len-1)
-        str[i+1] = '\0';
-    return APR_SUCCESS; 
+
+    if (fsync(thefile->filedes)) {
+        rv = apr_get_os_error();
+    }
+
+    file_unlock(thefile);
+
+    return rv;
 }
 
-#if 0 /* not currently used */
-static int printf_flush(ap_vformatter_buff_t *vbuff)
+APR_DECLARE(apr_status_t) apr_file_datasync(apr_file_t *thefile)
 {
-    /* I would love to print this stuff out to the file, but I will
-     * get that working later.  :)  For now, just return.
-     */
-    return -1;
-}
+    apr_status_t rv = APR_SUCCESS;
+
+    file_lock(thefile);
+
+    if (thefile->buffered) {
+        rv = apr_file_flush_locked(thefile);
+
+        if (rv != APR_SUCCESS) {
+            file_unlock(thefile);
+            return rv;
+        }
+    }
+
+#ifdef HAVE_FDATASYNC
+    if (fdatasync(thefile->filedes)) {
+#elif defined(F_FULLFSYNC)
+    if (fcntl(thefile->filedes, F_FULLFSYNC)) {
+#else
+    if (fsync(thefile->filedes)) {
 #endif
+        rv = apr_get_os_error();
+    }
+
+    file_unlock(thefile);
+
+    return rv;
+}
 
-API_EXPORT(int) ap_fprintf(ap_file_t *fptr, const char *format, ...)
+APR_DECLARE(apr_status_t) apr_file_gets(char *str, int len, apr_file_t *thefile)
 {
-    int cc;
-    va_list ap;
-    char *buf;
-    int len;
-
-    buf = malloc(HUGE_STRING_LEN);
-    if (buf == NULL) {
-        return 0;
+    apr_status_t rv = APR_SUCCESS; /* get rid of gcc warning */
+    apr_size_t nbytes;
+    const char *str_start = str;
+    char *final = str + len - 1;
+
+    if (len <= 1) {  
+        /* sort of like fgets(), which returns NULL and stores no bytes 
+         */
+        return APR_SUCCESS;
     }
-    va_start(ap, format);
-    len = ap_vsnprintf(buf, HUGE_STRING_LEN, format, ap);
-    cc = ap_puts(buf, fptr);
-    va_end(ap);
-    free(buf);
-    return (cc == APR_SUCCESS) ? len : -1;
+
+    /* If we have an underlying buffer, we can be *much* more efficient
+     * and skip over the apr_file_read calls.
+     */
+    if (thefile->buffered) {
+        file_lock(thefile);
+
+        if (thefile->direction == 1) {
+            rv = apr_file_flush_locked(thefile);
+            if (rv) {
+                file_unlock(thefile);
+                return rv;
+            }
+
+            thefile->direction = 0;
+            thefile->bufpos = 0;
+            thefile->dataRead = 0;
+        }
+
+        while (str < final) { /* leave room for trailing '\0' */
+            /* Force ungetc leftover to call apr_file_read. */
+            if (thefile->bufpos < thefile->dataRead &&
+                thefile->ungetchar == -1) {
+                *str = thefile->buffer[thefile->bufpos++];
+            }
+            else {
+                nbytes = 1;
+                rv = file_read_buffered(thefile, str, &nbytes);
+                if (rv != APR_SUCCESS) {
+                    break;
+                }
+            }
+            if (*str == '\n') {
+                ++str;
+                break;
+            }
+            ++str;
+        }
+        file_unlock(thefile);
+    }
+    else {
+        while (str < final) { /* leave room for trailing '\0' */
+            nbytes = 1;
+            rv = apr_file_read(thefile, str, &nbytes);
+            if (rv != APR_SUCCESS) {
+                break;
+            }
+            if (*str == '\n') {
+                ++str;
+                break;
+            }
+            ++str;
+        }
+    }
+
+    /* We must store a terminating '\0' if we've stored any chars. We can
+     * get away with storing it if we hit an error first. 
+     */
+    *str = '\0';
+    if (str > str_start) {
+        /* we stored chars; don't report EOF or any other errors;
+         * the app will find out about that on the next call
+         */
+        return APR_SUCCESS;
+    }
+    return rv;
 }
 
+
+
+APR_DECLARE(apr_status_t) apr_file_pipe_wait(apr_file_t *thepipe, apr_wait_type_t direction)
+{
+    return apr_wait_for_io_or_timeout(thepipe, NULL, direction == APR_WAIT_READ);
+}
diff --git a/file_io/unix/seek.c b/file_io/unix/seek.c
index 1fcb0cbab90..2e973377bf8 100644
--- a/file_io/unix/seek.c
+++ b/file_io/unix/seek.c
@@ -1,98 +1,65 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "fileio.h"
+#include "apr_arch_file_io.h"
 
-static ap_status_t setptr(ap_file_t *thefile, unsigned long pos )
+static apr_status_t setptr(apr_file_t *thefile, apr_off_t pos )
 {
-    long newbufpos;
-    int rc;
+    apr_off_t newbufpos;
+    apr_status_t rv;
 
     if (thefile->direction == 1) {
-        ap_flush(thefile);
+        rv = apr_file_flush_locked(thefile);
+        if (rv) {
+            return rv;
+        }
         thefile->bufpos = thefile->direction = thefile->dataRead = 0;
     }
 
     newbufpos = pos - (thefile->filePtr - thefile->dataRead);
     if (newbufpos >= 0 && newbufpos <= thefile->dataRead) {
         thefile->bufpos = newbufpos;
-        rc = 0;
-    } 
+        rv = APR_SUCCESS;
+    }
     else {
-        rc = lseek(thefile->filedes, pos, SEEK_SET);
-
-        if (rc != -1 ) {
+        if (lseek(thefile->filedes, pos, SEEK_SET) != -1) {
             thefile->bufpos = thefile->dataRead = 0;
-            rc = 0;
+            thefile->filePtr = pos;
+            rv = APR_SUCCESS;
         }
         else {
-            rc = errno;
+            rv = errno;
         }
     }
 
-    return rc;
+    return rv;
 }
 
 
-ap_status_t ap_seek(ap_file_t *thefile, ap_seek_where_t where, ap_off_t *offset)
+APR_DECLARE(apr_status_t) apr_file_seek(apr_file_t *thefile, apr_seek_where_t where, apr_off_t *offset)
 {
-    ap_off_t rv;
+    apr_off_t rv;
 
+    thefile->eof_hit = 0;
 
     if (thefile->buffered) {
         int rc = EINVAL;
-        ap_finfo_t finfo;
+        apr_finfo_t finfo;
+
+        file_lock(thefile);
 
         switch (where) {
         case APR_SET:
@@ -104,16 +71,19 @@ ap_status_t ap_seek(ap_file_t *thefile, ap_seek_where_t where, ap_off_t *offset)
             break;
 
         case APR_END:
-            rc = ap_getfileinfo(&finfo, thefile);
+            rc = apr_file_info_get_locked(&finfo, APR_FINFO_SIZE, thefile);
             if (rc == APR_SUCCESS)
-                rc = setptr(thefile, finfo.size - *offset);
+                rc = setptr(thefile, finfo.size + *offset);
             break;
         }
 
-        *offset = thefile->filePtr + thefile->bufpos;
-        return rc;
-    } else {
+        *offset = thefile->filePtr - thefile->dataRead + thefile->bufpos;
 
+        file_unlock(thefile);
+
+        return rc;
+    }
+    else {
         rv = lseek(thefile->filedes, *offset, where);
         if (rv == -1) {
             *offset = -1;
@@ -125,3 +95,42 @@ ap_status_t ap_seek(ap_file_t *thefile, ap_seek_where_t where, ap_off_t *offset)
         }
     }
 }
+
+apr_status_t apr_file_trunc(apr_file_t *fp, apr_off_t offset)
+{
+    if (fp->buffered) {
+        int rc = 0;
+        file_lock(fp);
+        if (fp->direction == 1 && fp->bufpos != 0) {
+            apr_off_t len = fp->filePtr + fp->bufpos;
+            if (offset < len) {
+                /* New file end fall below our write buffer limit.
+                 * Figure out if and what needs to be flushed.
+                 */
+                apr_off_t off = len - offset;
+                if (off >= 0 && off <= fp->bufpos)
+                    fp->bufpos = fp->bufpos - (size_t)off;
+                else
+                    fp->bufpos = 0;
+            }
+            rc = apr_file_flush_locked(fp);
+            /* Reset buffer positions for write mode */
+            fp->bufpos = fp->direction = fp->dataRead = 0;
+        }
+        else if (fp->direction == 0) {
+            /* Discard the read buffer, as we are about to reposition
+             * ourselves to the end of file.
+             */
+            fp->bufpos = 0;
+            fp->dataRead = 0;
+        }
+        file_unlock(fp);
+        if (rc) {
+            return rc;
+        }
+    }
+    if (ftruncate(fp->filedes, offset) == -1) {
+        return errno;
+    }
+    return apr_file_seek(fp, APR_SET, &offset);
+}
diff --git a/file_io/unix/tempdir.c b/file_io/unix/tempdir.c
new file mode 100644
index 00000000000..22325eff1c1
--- /dev/null
+++ b/file_io/unix/tempdir.c
@@ -0,0 +1,129 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "apr_private.h"
+#include "apr_file_io.h"
+#include "apr_strings.h"
+#include "apr_env.h"
+
+
+/* Try to open a temporary file in the temporary dir, write to it,
+   and then close it. */
+static int test_tempdir(const char *temp_dir, apr_pool_t *p)
+{
+    apr_file_t *dummy_file;
+    char *path = apr_pstrcat(p, temp_dir, "/apr-tmp.XXXXXX", NULL);
+
+    if (apr_file_mktemp(&dummy_file, path, 0, p) == APR_SUCCESS) {
+        if (apr_file_putc('!', dummy_file) == APR_SUCCESS) {
+            if (apr_file_close(dummy_file) == APR_SUCCESS) {
+                return 1;
+            }
+        }
+    }
+    return 0;
+}
+
+
+APR_DECLARE(apr_status_t) apr_temp_dir_get(const char **temp_dir, 
+                                           apr_pool_t *p)
+{
+    apr_status_t apr_err;
+    const char *try_dirs[] = { "/tmp", "/usr/tmp", "/var/tmp" };
+    const char *try_envs[] = { "TMPDIR", "TMP", "TEMP"};
+    const char *dir;
+    char *cwd;
+    int i;
+
+    /* Our goal is to find a temporary directory suitable for writing
+       into.
+       Here's the order in which we'll try various paths:
+
+          $TMPDIR
+          $TMP
+          $TEMP
+          "C:\TEMP"     (windows only)
+          "SYS:\TMP"    (netware only)
+          "/tmp"
+          "/var/tmp"
+          "/usr/tmp"
+          P_tmpdir      (POSIX define)
+          `pwd` 
+
+       NOTE: This algorithm is basically the same one used by Python
+       2.2's tempfile.py module.  */
+
+    /* Try the environment first. */
+    for (i = 0; i < (sizeof(try_envs) / sizeof(const char *)); i++) {
+        char *value;
+        apr_err = apr_env_get(&value, try_envs[i], p);
+        if ((apr_err == APR_SUCCESS) && value) {
+            apr_size_t len = strlen(value);
+            if (len && (len < APR_PATH_MAX) && test_tempdir(value, p)) {
+                dir = value;
+                goto end;
+            }
+        }
+    }
+
+#ifdef WIN32
+    /* Next, on Win32, try the C:\TEMP directory. */
+    if (test_tempdir("C:\\TEMP", p)) {
+        dir = "C:\\TEMP";
+        goto end;
+    }
+#endif
+#ifdef NETWARE
+    /* Next, on NetWare, try the SYS:/TMP directory. */
+    if (test_tempdir("SYS:/TMP", p)) {
+        dir = "SYS:/TMP";
+        goto end;
+    }
+#endif
+
+    /* Next, try a set of hard-coded paths. */
+    for (i = 0; i < (sizeof(try_dirs) / sizeof(const char *)); i++) {
+        if (test_tempdir(try_dirs[i], p)) {
+            dir = try_dirs[i];
+            goto end;
+        }
+    }
+
+#ifdef P_tmpdir
+    /* 
+     * If we have it, use the POSIX definition of where 
+     * the tmpdir should be 
+     */
+    if (test_tempdir(P_tmpdir, p)) {
+        dir = P_tmpdir;
+        goto end;
+    }
+#endif
+    
+    /* Finally, try the current working directory. */
+    if (APR_SUCCESS == apr_filepath_get(&cwd, APR_FILEPATH_NATIVE, p)) {
+        if (test_tempdir(cwd, p)) {
+            dir = cwd;
+	    goto end;
+        }
+    }
+
+    /* We didn't find a suitable temp dir anywhere */
+    return APR_EGENERAL;
+
+end:
+    *temp_dir = apr_pstrdup(p, dir);
+    return APR_SUCCESS;
+}
diff --git a/file_io/win32/buffer.c b/file_io/win32/buffer.c
new file mode 100644
index 00000000000..1b7d857ca39
--- /dev/null
+++ b/file_io/win32/buffer.c
@@ -0,0 +1,63 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_arch_file_io.h"
+#include "apr_thread_mutex.h"
+
+APR_DECLARE(apr_status_t) apr_file_buffer_set(apr_file_t *file, 
+                                              char * buffer,
+                                              apr_size_t bufsize)
+{
+    apr_status_t rv;
+
+    if (file->flags & APR_FOPEN_XTHREAD) {
+        apr_thread_mutex_lock(file->mutex);
+    }
+ 
+    if(file->buffered) {
+        /* Flush the existing buffer */
+        rv = apr_file_flush(file);
+        if (rv != APR_SUCCESS) {
+            apr_thread_mutex_unlock(file->mutex);
+            return rv;
+        }
+    }
+        
+    file->buffer = buffer;
+    file->bufsize = bufsize;
+    file->buffered = 1;
+    file->bufpos = 0;
+    file->direction = 0;
+    file->dataRead = 0;
+ 
+    if (file->bufsize == 0) {
+            /* Setting the buffer size to zero is equivalent to turning 
+             * buffering off. 
+             */
+            file->buffered = 0;
+    }
+    
+    if (file->flags & APR_FOPEN_XTHREAD) {
+        apr_thread_mutex_unlock(file->mutex);
+    }
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_size_t) apr_file_buffer_size_get(apr_file_t *file)
+{
+    return file->bufsize;
+}
diff --git a/file_io/win32/dir.c b/file_io/win32/dir.c
index a74a5aa90fb..5c30af8fdc3 100644
--- a/file_io/win32/dir.c
+++ b/file_io/win32/dir.c
@@ -1,207 +1,397 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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.
  */
 
-#ifdef HAVE_ERRNO_H
+#include "apr.h"
+#include "apr_arch_file_io.h"
+#include "apr_file_io.h"
+#include "apr_strings.h"
+#include "apr_portable.h"
+#include "apr_arch_atime.h"
+
+#if APR_HAVE_ERRNO_H
 #include <errno.h>
 #endif
-#ifdef HAVE_STRING_H
+#if APR_HAVE_STRING_H
 #include <string.h>
 #endif
-#ifdef HAVE_DIRENT_H
+#if APR_HAVE_DIRENT_H
 #include <dirent.h>
 #endif
 #ifdef HAVE_SYS_STAT_H
 #include <sys/stat.h>
 #endif
-#include "fileio.h"
-#include "apr_file_io.h"
-#include "apr_lib.h"
-#include "apr_portable.h"
-#include "atime.h"
 
-ap_status_t dir_cleanup(void *thedir)
+
+static apr_status_t dir_cleanup(void *thedir)
 {
-    ap_dir_t *dir = thedir;
-    if (!CloseHandle(dir->dirhand)) {
-        return GetLastError();
+    apr_dir_t *dir = thedir;
+    if (dir->dirhand != INVALID_HANDLE_VALUE && !FindClose(dir->dirhand)) {
+        return apr_get_os_error();
     }
+    dir->dirhand = INVALID_HANDLE_VALUE;
     return APR_SUCCESS;
 } 
 
-ap_status_t ap_opendir(ap_dir_t **new, const char *dirname, ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_dir_open(apr_dir_t **new, const char *dirname,
+                                       apr_pool_t *pool)
 {
-    char * temp;
-    (*new) = ap_pcalloc(cont, sizeof(ap_dir_t));
-    (*new)->cntxt = cont;
-    (*new)->entry = NULL;
-    temp = canonical_filename((*new)->cntxt, dirname);
-    if (temp[strlen(temp)] == '/') {
-    	(*new)->dirname = ap_pstrcat(cont, dirname, "*", NULL);
+    apr_status_t rv;
+
+    apr_size_t len = strlen(dirname);
+    (*new) = apr_pcalloc(pool, sizeof(apr_dir_t));
+    /* Leave room here to add and pop the '*' wildcard for FindFirstFile 
+     * and double-null terminate so we have one character to change.
+     */
+    (*new)->dirname = apr_palloc(pool, len + 3);
+    memcpy((*new)->dirname, dirname, len);
+    if (len && (*new)->dirname[len - 1] != '/') {
+    	(*new)->dirname[len++] = '/';
+    }
+    (*new)->dirname[len++] = '\0';
+    (*new)->dirname[len] = '\0';
+
+#if APR_HAS_UNICODE_FS
+    IF_WIN_OS_IS_UNICODE
+    {
+        /* Create a buffer for the longest file name we will ever see 
+         */
+        (*new)->w.entry = apr_pcalloc(pool, sizeof(WIN32_FIND_DATAW));
+        (*new)->name = apr_pcalloc(pool, APR_FILE_MAX * 3 + 1);        
     }
-    else {
-        (*new)->dirname = ap_pstrcat(cont, dirname, "/*", NULL);
+#endif
+#if APR_HAS_ANSI_FS
+    ELSE_WIN_OS_IS_ANSI
+    {
+        /* Note that we won't open a directory that is greater than MAX_PATH,
+         * counting the additional '/' '*' wildcard suffix.  If a * won't fit
+         * then neither will any other file name within the directory.
+         * The length not including the trailing '*' is stored as rootlen, to
+         * skip over all paths which are too long.
+         */
+        if (len >= APR_PATH_MAX) {
+            (*new) = NULL;
+            return APR_ENAMETOOLONG;
+        }
+        (*new)->n.entry = apr_pcalloc(pool, sizeof(WIN32_FIND_DATAW));
     }
+#endif
+    (*new)->rootlen = len - 1;
+    (*new)->pool = pool;
     (*new)->dirhand = INVALID_HANDLE_VALUE;
-    ap_register_cleanup((*new)->cntxt, (void *)(*new), dir_cleanup,
-                        ap_null_cleanup);
-    return APR_SUCCESS;
-}
+    apr_pool_cleanup_register((*new)->pool, (void *)(*new), dir_cleanup,
+                        apr_pool_cleanup_null);
 
-ap_status_t ap_closedir(ap_dir_t *thedir)
-{
-    if (!FindClose(thedir->dirhand)) {
-        return GetLastError();   
+    rv = apr_dir_read(NULL, 0, *new);
+    if (rv != APR_SUCCESS) {
+        dir_cleanup(*new);
+        *new = NULL;
     }
-    ap_kill_cleanup(thedir->cntxt, thedir, dir_cleanup);
-    return APR_SUCCESS;
+
+    return rv;
 }
 
-ap_status_t ap_readdir(ap_dir_t *thedir)
+APR_DECLARE(apr_status_t) apr_dir_close(apr_dir_t *dir)
 {
-    if (thedir->dirhand == INVALID_HANDLE_VALUE) {
-        thedir->entry = ap_pcalloc(thedir->cntxt, sizeof(WIN32_FIND_DATA));
-        thedir->dirhand = FindFirstFile(thedir->dirname, thedir->entry);
-        if (thedir->dirhand == INVALID_HANDLE_VALUE) {
-            return GetLastError();
-        }
-        return APR_SUCCESS;
-    }
-    if (!FindNextFile(thedir->dirhand, thedir->entry)) {
-        return GetLastError();
-    }
-    return APR_SUCCESS;
+    apr_pool_cleanup_kill(dir->pool, dir, dir_cleanup);
+    return dir_cleanup(dir);
 }
 
-ap_status_t ap_rewinddir(ap_dir_t *thedir)
+APR_DECLARE(apr_status_t) apr_dir_read(apr_finfo_t *finfo, apr_int32_t wanted,
+                                       apr_dir_t *thedir)
 {
-    ap_status_t stat;
-    ap_pool_t *cont = thedir->cntxt;
-    char *temp = ap_pstrdup(cont, thedir->dirname);
-    temp[strlen(temp) - 2] = '\0';   /*remove the \* at the end */
-    if (thedir->dirhand == INVALID_HANDLE_VALUE) {
-        return APR_SUCCESS;
+    apr_status_t rv;
+    char *fname;
+    /* The while loops below allow us to skip all invalid file names, so that
+     * we aren't reporting any files where their absolute paths are too long.
+     */
+#if APR_HAS_UNICODE_FS
+    apr_wchar_t wdirname[APR_PATH_MAX];
+    apr_wchar_t *eos = NULL;
+    IF_WIN_OS_IS_UNICODE
+    {
+        /* This code path is always be invoked by apr_dir_open or
+         * apr_dir_rewind, so return without filling out the finfo.
+         */
+        if (thedir->dirhand == INVALID_HANDLE_VALUE) 
+        {
+            apr_status_t rv;
+            if ((rv = utf8_to_unicode_path(wdirname, sizeof(wdirname) 
+                                                   / sizeof(apr_wchar_t), 
+                                           thedir->dirname))) {
+                return rv;
+            }
+            eos = wcschr(wdirname, '\0');
+            eos[0] = '*';
+            eos[1] = '\0';
+            thedir->dirhand = FindFirstFileW(wdirname, thedir->w.entry);
+            eos[0] = '\0';
+            if (thedir->dirhand == INVALID_HANDLE_VALUE) {
+                return apr_get_os_error();
+            }
+            thedir->bof = 1;
+            return APR_SUCCESS;
+        }
+        else if (thedir->bof) {
+            /* Noop - we already called FindFirstFileW from
+             * either apr_dir_open or apr_dir_rewind ... use
+             * that first record.
+             */
+            thedir->bof = 0; 
+        }
+        else if (!FindNextFileW(thedir->dirhand, thedir->w.entry)) {
+            return apr_get_os_error();
+        }
+
+        while (thedir->rootlen &&
+               thedir->rootlen + wcslen(thedir->w.entry->cFileName) >= APR_PATH_MAX)
+        {
+            if (!FindNextFileW(thedir->dirhand, thedir->w.entry)) {
+                return apr_get_os_error();
+            }
+        }
+        if ((rv = unicode_to_utf8_path(thedir->name, APR_FILE_MAX * 3 + 1, 
+                                       thedir->w.entry->cFileName)))
+            return rv;
+        fname = thedir->name;
     }
-    if ((stat = ap_closedir(thedir)) == APR_SUCCESS) {
-        if ((stat = ap_opendir(&thedir, temp, cont)) == APR_SUCCESS) {
-            ap_readdir(thedir);
+#endif
+#if APR_HAS_ANSI_FS
+    ELSE_WIN_OS_IS_ANSI
+    {
+        /* This code path is always be invoked by apr_dir_open or 
+         * apr_dir_rewind, so return without filling out the finfo.
+         */
+        if (thedir->dirhand == INVALID_HANDLE_VALUE) {
+            /* '/' terminated, so add the '*' and pop it when we finish */
+            char *eop = strchr(thedir->dirname, '\0');
+            eop[0] = '*';
+            eop[1] = '\0';
+            thedir->dirhand = FindFirstFileA(thedir->dirname, 
+                                             thedir->n.entry);
+            eop[0] = '\0';
+            if (thedir->dirhand == INVALID_HANDLE_VALUE) {
+                return apr_get_os_error();
+            }
+            thedir->bof = 1;
             return APR_SUCCESS;
         }
+        else if (thedir->bof) {
+            /* Noop - we already called FindFirstFileW from
+             * either apr_dir_open or apr_dir_rewind ... use
+             * that first record.
+             */
+            thedir->bof = 0; 
+        }
+        else if (!FindNextFileA(thedir->dirhand, thedir->n.entry)) {
+            return apr_get_os_error();
+        }
+        while (thedir->rootlen &&
+               thedir->rootlen + strlen(thedir->n.entry->cFileName) >= MAX_PATH)
+        {
+            if (!FindNextFileA(thedir->dirhand, thedir->n.entry)) {
+                return apr_get_os_error();
+            }
+        }
+        fname = thedir->n.entry->cFileName;
     }
-    return stat;	
-}
+#endif
 
-ap_status_t ap_make_dir(const char *path, ap_fileperms_t perm, ap_pool_t *cont)
-{
-    if (!CreateDirectory(path, NULL)) {
-        return GetLastError();
+    fillin_fileinfo(finfo, (WIN32_FILE_ATTRIBUTE_DATA *) thedir->w.entry, 
+                    0, wanted);
+    finfo->pool = thedir->pool;
+
+    finfo->valid |= APR_FINFO_NAME;
+    finfo->name = fname;
+
+    if (wanted &= ~finfo->valid) {
+        /* Go back and get more_info if we can't answer the whole inquiry
+         */
+#if APR_HAS_UNICODE_FS
+        IF_WIN_OS_IS_UNICODE
+        {
+            /* Almost all our work is done.  Tack on the wide file name
+             * to the end of the wdirname (already / delimited)
+             */
+            if (!eos)
+                eos = wcschr(wdirname, '\0');
+            wcscpy(eos, thedir->w.entry->cFileName);
+            rv = more_finfo(finfo, wdirname, wanted, MORE_OF_WFSPEC);
+            eos[0] = '\0';
+            return rv;
+        }
+#endif
+#if APR_HAS_ANSI_FS
+        ELSE_WIN_OS_IS_ANSI
+        {
+#if APR_HAS_UNICODE_FS
+            /* Don't waste stack space on a second buffer, the one we set
+             * aside for the wide directory name is twice what we need.
+             */
+            char *fspec = (char*)wdirname;
+#else
+            char fspec[APR_PATH_MAX];
+#endif
+            apr_size_t dirlen = strlen(thedir->dirname);
+            if (dirlen >= sizeof(fspec))
+                dirlen = sizeof(fspec) - 1;
+            apr_cpystrn(fspec, thedir->dirname, sizeof(fspec));
+            apr_cpystrn(fspec + dirlen, fname, sizeof(fspec) - dirlen);
+            return more_finfo(finfo, fspec, wanted, MORE_OF_FSPEC);
+        }
+#endif
     }
+
     return APR_SUCCESS;
 }
 
-ap_status_t ap_remove_dir(const char *path, ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_dir_rewind(apr_dir_t *dir)
 {
-    char *temp = canonical_filename(cont, path);
-    if (!RemoveDirectory(temp)) {
-        return GetLastError();
-    }
-    return APR_SUCCESS;
+    apr_status_t rv;
+
+    /* this will mark the handle as invalid and we'll open it
+     * again if apr_dir_read() is subsequently called
+     */
+    rv = dir_cleanup(dir);
+
+    if (rv == APR_SUCCESS)
+        rv = apr_dir_read(NULL, 0, dir);
+
+    return rv;
 }
 
-ap_status_t ap_dir_entry_size(ap_ssize_t *size, ap_dir_t *thedir)
+APR_DECLARE(apr_status_t) apr_dir_make(const char *path, apr_fileperms_t perm,
+                                       apr_pool_t *pool)
 {
-    if (thedir == NULL || thedir->entry == NULL) {
-        return APR_ENODIR;
+#if APR_HAS_UNICODE_FS
+    IF_WIN_OS_IS_UNICODE
+    {
+        apr_wchar_t wpath[APR_PATH_MAX];
+        apr_status_t rv;
+        if ((rv = utf8_to_unicode_path(wpath,
+                                       sizeof(wpath) / sizeof(apr_wchar_t),
+                                       path))) {
+            return rv;
+        }
+        if (!CreateDirectoryW(wpath, NULL)) {
+            return apr_get_os_error();
+        }
     }
-    (*size) = (thedir->entry->nFileSizeHigh * MAXDWORD) + 
-        thedir->entry->nFileSizeLow;
+#endif
+#if APR_HAS_ANSI_FS
+    ELSE_WIN_OS_IS_ANSI
+        if (!CreateDirectory(path, NULL)) {
+            return apr_get_os_error();
+        }
+#endif
     return APR_SUCCESS;
 }
 
-ap_status_t ap_dir_entry_mtime(ap_time_t *time, ap_dir_t *thedir)
+
+static apr_status_t dir_make_parent(char *path,
+                                    apr_fileperms_t perm,
+                                    apr_pool_t *pool)
 {
-    if (thedir == NULL || thedir->entry == NULL) {
-        return APR_ENODIR;
+    apr_status_t rv;
+    char *ch = strrchr(path, '\\');
+    if (!ch) {
+        return APR_ENOENT;
     }
-    FileTimeToAprTime(time, &thedir->entry->ftLastWriteTime);
-    return APR_SUCCESS;
+
+    *ch = '\0';
+    rv = apr_dir_make (path, perm, pool); /* Try to make straight off */
+    
+    if (APR_STATUS_IS_ENOENT(rv)) { /* Missing an intermediate dir */
+        rv = dir_make_parent(path, perm, pool);
+
+        if (rv == APR_SUCCESS || APR_STATUS_IS_EEXIST(rv)) {
+            rv = apr_dir_make(path, perm, pool); /* And complete the path */
+        }
+    }
+
+    *ch = '\\'; /* Always replace the slash before returning */
+    return rv;
 }
- 
-ap_status_t ap_dir_entry_ftype(ap_filetype_e *type, ap_dir_t *thedir)
+
+APR_DECLARE(apr_status_t) apr_dir_make_recursive(const char *path,
+                                                 apr_fileperms_t perm,
+                                                 apr_pool_t *pool)
 {
-    switch(thedir->entry->dwFileAttributes) {
-    case FILE_ATTRIBUTE_DIRECTORY: {
-        (*type) = APR_DIR;
-        return APR_SUCCESS;
-    }
-    case FILE_ATTRIBUTE_NORMAL: {
-        (*type) = APR_REG;
-        return APR_SUCCESS;
-    }
-    default: {
-        (*type) = APR_REG;     /* As valid as anything else.*/
-        return APR_SUCCESS;
+    apr_status_t rv = 0;
+
+    rv = apr_dir_make (path, perm, pool); /* Try to make PATH right out */
+
+    if (APR_STATUS_IS_ENOENT(rv)) { /* Missing an intermediate dir */
+        char *dir;
+
+        rv = apr_filepath_merge(&dir, "", path, APR_FILEPATH_NATIVE, pool);
+
+        if (rv != APR_SUCCESS)
+            return rv;
+
+        rv = dir_make_parent(dir, perm, pool); /* Make intermediate dirs */
+
+        if (rv == APR_SUCCESS || APR_STATUS_IS_EEXIST(rv)) {
+            rv = apr_dir_make (dir, perm, pool);   /* And complete the path */
+
+            if (APR_STATUS_IS_EEXIST(rv)) {
+                rv = APR_SUCCESS; /* Timing issue; see comment below */
+            }
+        }
     }
+    else if (APR_STATUS_IS_EEXIST(rv)) {
+        /*
+         * It's OK if PATH exists. Timing issues can lead to the
+         * second apr_dir_make being called on existing dir, therefore
+         * this check has to come last.
+         */
+        rv = APR_SUCCESS;
     }
+
+    return rv;
 }
 
-ap_status_t ap_get_dir_filename(char **new, ap_dir_t *thedir)
+
+APR_DECLARE(apr_status_t) apr_dir_remove(const char *path, apr_pool_t *pool)
 {
-    (*new) = ap_pstrdup(thedir->cntxt, thedir->entry->cFileName);
+#if APR_HAS_UNICODE_FS
+    IF_WIN_OS_IS_UNICODE
+    {
+        apr_wchar_t wpath[APR_PATH_MAX];
+        apr_status_t rv;
+        if ((rv = utf8_to_unicode_path(wpath,
+                                       sizeof(wpath) / sizeof(apr_wchar_t),
+                                       path))) {
+            return rv;
+        }
+        if (!RemoveDirectoryW(wpath)) {
+            return apr_get_os_error();
+        }
+    }
+#endif
+#if APR_HAS_ANSI_FS
+    ELSE_WIN_OS_IS_ANSI
+        if (!RemoveDirectory(path)) {
+            return apr_get_os_error();
+        }
+#endif
     return APR_SUCCESS;
 }
 
-ap_status_t ap_get_os_dir(ap_os_dir_t **thedir, ap_dir_t *dir)
+APR_DECLARE(apr_status_t) apr_os_dir_get(apr_os_dir_t **thedir,
+                                         apr_dir_t *dir)
 {
     if (dir == NULL) {
         return APR_ENODIR;
@@ -210,15 +400,9 @@ ap_status_t ap_get_os_dir(ap_os_dir_t **thedir, ap_dir_t *dir)
     return APR_SUCCESS;
 }
 
-ap_status_t ap_put_os_dir(ap_dir_t **dir, ap_os_dir_t *thedir, ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_os_dir_put(apr_dir_t **dir,
+                                         apr_os_dir_t *thedir,
+                                         apr_pool_t *pool)
 {
-    if (cont == NULL) {
-        return APR_ENOPOOL;
-    }
-    if ((*dir) == NULL) {
-        (*dir) = (ap_dir_t *)ap_pcalloc(cont, sizeof(ap_dir_t));
-        (*dir)->cntxt = cont;
-    }
-    (*dir)->dirhand = thedir;
-    return APR_SUCCESS;
+    return APR_ENOTIMPL;
 }
diff --git a/file_io/win32/fileacc.c b/file_io/win32/fileacc.c
deleted file mode 100644
index 7edb8e3edf5..00000000000
--- a/file_io/win32/fileacc.c
+++ /dev/null
@@ -1,141 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "fileio.h"
-#include "apr_file_io.h"
-#include "apr_general.h"
-#include "apr_lib.h"
-#include <errno.h>
-#include <string.h>
-#include <sys/types.h>
-
-/* A file to put ALL of the accessor functions for ap_file_t types. */
-
-ap_status_t ap_get_filename(char **new, ap_file_t *thefile)
-{
-    if (thefile != NULL) {
-        *new = ap_pstrdup(thefile->cntxt, thefile->fname);
-        return APR_SUCCESS;
-    }
-    else {
-        *new = NULL;
-        return APR_ENOFILE;
-    }
-}
-
-/*mode_t get_fileperms(ap_fileperms_t mode)
-{
-    mode_t rv = 0;
-
-    if (mode & APR_UREAD)
-        rv |= S_IRUSR;
-    if (mode & APR_UWRITE)
-        rv |= S_IWUSR;
-    if (mode & APR_UEXECUTE)
-        rv |= S_IXUSR;
-
-    if (mode & APR_GREAD)
-        rv |= S_IRGRP;
-    if (mode & APR_GWRITE)
-        rv |= S_IWGRP;
-    if (mode & APR_GEXECUTE)
-        rv |= S_IXGRP;
-
-    if (mode & APR_WREAD)
-        rv |= S_IROTH;
-    if (mode & APR_WWRITE)
-        rv |= S_IWOTH;
-    if (mode & APR_WEXECUTE)
-        rv |= S_IXOTH;
-
-    return rv;
-}*/
-
-
-/*
-ap_status_t ap_get_fileperms(ap_fileperms_t *perm, ap_file_t *file)
-{
-    if (file != NULL) {
-        *perm = file->protection;
-        return APR_SUCCESS;
-    }
-    else {
-        *perm = -1;
-        return APR_ENOFILE;
-    }
-}
-*/
-
-ap_status_t ap_get_filedata(void **data, char *key, ap_file_t *file)
-{    
-    if (file != NULL) {
-        return ap_get_userdata(data, key, file->cntxt);
-    }
-    else {
-        data = NULL;
-        return APR_ENOFILE;
-    }
-}
-                   
-ap_status_t ap_set_filedata(ap_file_t *file, void *data, char *key,
-                            ap_status_t (*cleanup) (void *))
-{    
-    if (file != NULL) {
-        return ap_set_userdata(data, key, cleanup, file->cntxt);
-    }
-    else {
-        data = NULL;
-        return APR_ENOFILE;
-    }
-}
diff --git a/file_io/win32/filedup.c b/file_io/win32/filedup.c
index 012a523dc77..eaafaff4290 100644
--- a/file_io/win32/filedup.c
+++ b/file_io/win32/filedup.c
@@ -1,120 +1,229 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "fileio.h"
+#include "apr_arch_file_io.h"
 #include "apr_file_io.h"
 #include "apr_general.h"
-#include "apr_lib.h"
+#include "apr_strings.h"
 #include <string.h>
+#include "apr_arch_inherit.h"
+#include <io.h> /* for [_open/_get]_osfhandle */
+
 
-ap_status_t ap_dupfile(ap_file_t **new_file, ap_file_t *old_file, ap_pool_t *p)
+APR_DECLARE(apr_status_t) apr_file_dup(apr_file_t **new_file,
+                                       apr_file_t *old_file, apr_pool_t *p)
 {
-    HANDLE hCurrentProcess = GetCurrentProcess();
+#ifdef _WIN32_WCE
+    return APR_ENOTIMPL;
+#else
+    HANDLE hproc = GetCurrentProcess();
+    HANDLE newhand = NULL;
 
-    if ((*new_file) == NULL) {
-        if (p == NULL) {
-            p = old_file->cntxt;
-        }
-            
-        (*new_file) = (ap_file_t *) ap_pcalloc(p,
-                                               sizeof(ap_file_t));
-        if ((*new_file) == NULL) {
-            return APR_ENOMEM;
+    if (!DuplicateHandle(hproc, old_file->filehand, 
+                         hproc, &newhand, 0, FALSE, 
+                         DUPLICATE_SAME_ACCESS)) {
+        return apr_get_os_error();
+    }
+
+    (*new_file) = (apr_file_t *) apr_pcalloc(p, sizeof(apr_file_t));
+    (*new_file)->filehand = newhand;
+    (*new_file)->flags = old_file->flags & ~(APR_STD_FLAGS | APR_INHERIT);
+    (*new_file)->pool = p;
+    (*new_file)->fname = apr_pstrdup(p, old_file->fname);
+    (*new_file)->append = old_file->append;
+    (*new_file)->buffered = FALSE;
+    (*new_file)->ungetchar = old_file->ungetchar;
+
+#if APR_HAS_THREADS
+    if (old_file->mutex) {
+        apr_thread_mutex_create(&((*new_file)->mutex),
+                                APR_THREAD_MUTEX_DEFAULT, p);
+    }
+#endif
+
+    apr_pool_cleanup_register((*new_file)->pool, (void *)(*new_file), file_cleanup,
+                        apr_pool_cleanup_null);
+
+#if APR_FILES_AS_SOCKETS
+    /* Create a pollset with room for one descriptor. */
+    /* ### check return codes */
+    (void) apr_pollset_create(&(*new_file)->pollset, 1, p, 0);
+#endif
+    return APR_SUCCESS;
+#endif /* !defined(_WIN32_WCE) */
+}
+
+APR_DECLARE(apr_status_t) apr_file_dup2(apr_file_t *new_file,
+                                        apr_file_t *old_file, apr_pool_t *p)
+{
+#ifdef _WIN32_WCE
+    return APR_ENOTIMPL;
+#else
+    HANDLE hproc = GetCurrentProcess();
+    HANDLE newhand = NULL;
+    apr_int32_t newflags;
+    int fd;
+
+    if (new_file->flags & APR_STD_FLAGS)
+    {
+        if ((new_file->flags & APR_STD_FLAGS) == APR_STDERR_FLAG)
+        {
+            /* Flush stderr and unset its buffer, then commit the fd-based buffer.
+             * This is typically a noop for Win2K/XP since services with NULL std
+             * handles [but valid FILE *'s, oddly enough], but is required
+             * for NT 4.0 and to use this code outside of services.
+             */
+            fflush(stderr);
+            setvbuf(stderr, NULL, _IONBF, 0);
+            if (!_isatty(2)) {
+                _commit(2 /* stderr */);
+            }
+
+            /* Clone a handle can _close() without harming the source handle,
+             * open an MSVCRT-based pseudo-fd for the file handle, then dup2
+             * and close our temporary pseudo-fd once it's been duplicated.
+             * This will incidently keep the FILE-based stderr in sync.
+             * Note the apparently redundant _O_BINARY coersions are required.
+             * Note the _dup2 will close the previous std Win32 handle.
+             */
+            if (!DuplicateHandle(hproc, old_file->filehand, hproc, &newhand,
+                                 0, FALSE, DUPLICATE_SAME_ACCESS)) {
+                return apr_get_os_error();
+            }
+            fd = _open_osfhandle((INT_PTR)newhand, _O_WRONLY | _O_BINARY);
+            _dup2(fd, 2);
+            _close(fd);
+            _setmode(2, _O_BINARY);
+
+            /* hPipeWrite was _close()'ed above, and _dup2()'ed
+             * to fd 2 creating a new, inherited Win32 handle.
+             * Recover that real handle from fd 2.  Note that
+             * SetStdHandle(STD_ERROR_HANDLE, _get_osfhandle(2))
+             * is implicit in the dup2() call above
+             */
+            newhand = (HANDLE)_get_osfhandle(2);
         }
-        if (!DuplicateHandle(hCurrentProcess, old_file->filehand, 
-                             hCurrentProcess,
-                             &(*new_file)->filehand, 0, FALSE, 
-                             DUPLICATE_SAME_ACCESS)) {
-            return GetLastError();
+        else if ((new_file->flags & APR_STD_FLAGS) == APR_STDOUT_FLAG) {
+            /* For the process flow see the stderr case above */
+            fflush(stdout);
+            setvbuf(stdout, NULL, _IONBF, 0);
+            if (!_isatty(1)) {
+                _commit(1 /* stdout */);
+            }
+
+            if (!DuplicateHandle(hproc, old_file->filehand, hproc, &newhand,
+                                 0, FALSE, DUPLICATE_SAME_ACCESS)) {
+                return apr_get_os_error();
+            }
+            fd = _open_osfhandle((INT_PTR)newhand, _O_WRONLY | _O_BINARY);
+            _dup2(fd, 1);
+            _close(fd);
+            _setmode(1, _O_BINARY);
+            newhand = (HANDLE)_get_osfhandle(1);
         }
-    } else {
-        HANDLE hFile = (*new_file)->filehand;
-        /* dup2 is not supported with native Windows handles. We 
-         * can, however, emulate dup2 for the standard i/o handles.
-         */
-        if (hFile == GetStdHandle(STD_ERROR_HANDLE)) {
-            if (!SetStdHandle(STD_ERROR_HANDLE, old_file->filehand))
-                return GetLastError();
+        else if ((new_file->flags & APR_STD_FLAGS) == APR_STDIN_FLAG) {
+            /* For the process flow see the stderr case above */
+            fflush(stdin);
+            setvbuf(stdin, NULL, _IONBF, 0);
+
+            if (!DuplicateHandle(hproc, old_file->filehand, hproc, &newhand,
+                                 0, FALSE, DUPLICATE_SAME_ACCESS)) {
+                return apr_get_os_error();
+            }
+            fd = _open_osfhandle((INT_PTR)newhand, _O_RDONLY | _O_BINARY);
+            _dup2(fd, 0);
+            _close(fd);
+            _setmode(0, _O_BINARY);
+            newhand = (HANDLE)_get_osfhandle(0);
         }
-        else if (hFile == GetStdHandle(STD_OUTPUT_HANDLE)) {
-            if (!SetStdHandle(STD_OUTPUT_HANDLE, old_file->filehand))
-                return GetLastError();
+        newflags = (new_file->flags & APR_STD_FLAGS) 
+                 | (old_file->flags & ~APR_STD_FLAGS) | APR_INHERIT;
+
+        /* No need  to close the old file, _dup2() above did that for us */
+    }
+    else {
+        if (!DuplicateHandle(hproc, old_file->filehand, 
+                             hproc, &newhand, 0,
+                             FALSE, DUPLICATE_SAME_ACCESS)) {
+            return apr_get_os_error();
         }
-        else if (hFile == GetStdHandle(STD_INPUT_HANDLE)) {
-            if (!SetStdHandle(STD_INPUT_HANDLE, old_file->filehand))
-                return GetLastError();
+        newflags = old_file->flags & ~(APR_STD_FLAGS | APR_INHERIT);
+
+        if (new_file->filehand
+                && (new_file->filehand != INVALID_HANDLE_VALUE)) {
+            CloseHandle(new_file->filehand);
         }
-        else
-            return APR_ENOTIMPL;
     }
 
-    (*new_file)->cntxt = old_file->cntxt;
-    (*new_file)->fname = ap_pstrdup(old_file->cntxt, old_file->fname);
-    (*new_file)->demonfname = ap_pstrdup(old_file->cntxt, old_file->demonfname);
-    (*new_file)->lowerdemonfname = ap_pstrdup(old_file->cntxt, old_file->lowerdemonfname);
-    (*new_file)->append = old_file->append;
-/*   (*new_file)->protection = old_file->protection;
-    (*new_file)->user = old_file->user;
-    (*new_file)->group = old_file->group;*/
-    (*new_file)->size = old_file->size;
-    (*new_file)->atime = old_file->atime;    
-    (*new_file)->mtime = old_file->mtime;
-    (*new_file)->ctime = old_file->ctime;
-    ap_register_cleanup((*new_file)->cntxt, (void *)(*new_file), file_cleanup,
-                        ap_null_cleanup);
+    new_file->flags = newflags;
+    new_file->filehand = newhand;
+    new_file->fname = apr_pstrdup(new_file->pool, old_file->fname);
+    new_file->append = old_file->append;
+    new_file->buffered = FALSE;
+    new_file->ungetchar = old_file->ungetchar;
+
+#if APR_HAS_THREADS
+    if (old_file->mutex) {
+        apr_thread_mutex_create(&(new_file->mutex),
+                                APR_THREAD_MUTEX_DEFAULT, p);
+    }
+#endif
 
     return APR_SUCCESS;
+#endif /* !defined(_WIN32_WCE) */
 }
 
+APR_DECLARE(apr_status_t) apr_file_setaside(apr_file_t **new_file,
+                                            apr_file_t *old_file,
+                                            apr_pool_t *p)
+{
+    *new_file = (apr_file_t *)apr_pmemdup(p, old_file, sizeof(apr_file_t));
+    (*new_file)->pool = p;
+    if (old_file->buffered) {
+        (*new_file)->buffer = apr_palloc(p, old_file->bufsize);
+        (*new_file)->bufsize = old_file->bufsize;
+        if (old_file->direction == 1) {
+            memcpy((*new_file)->buffer, old_file->buffer, old_file->bufpos);
+        }
+        else {
+            memcpy((*new_file)->buffer, old_file->buffer, old_file->dataRead);
+        }
+    }
+    if (old_file->mutex) {
+        apr_thread_mutex_create(&((*new_file)->mutex),
+                                APR_THREAD_MUTEX_DEFAULT, p);
+        apr_thread_mutex_destroy(old_file->mutex);
+    }
+    if (old_file->fname) {
+        (*new_file)->fname = apr_pstrdup(p, old_file->fname);
+    }
+    if (!(old_file->flags & APR_FOPEN_NOCLEANUP)) {
+        apr_pool_cleanup_register(p, (void *)(*new_file), 
+                                  file_cleanup,
+                                  file_cleanup);
+    }
+
+    old_file->filehand = INVALID_HANDLE_VALUE;
+    apr_pool_cleanup_kill(old_file->pool, (void *)old_file,
+                          file_cleanup);
 
+#if APR_FILES_AS_SOCKETS
+    /* Create a pollset with room for one descriptor. */
+    /* ### check return codes */
+    (void) apr_pollset_create(&(*new_file)->pollset, 1, p, 0);
+#endif
+    return APR_SUCCESS;
+}
diff --git a/file_io/win32/fileio.h b/file_io/win32/fileio.h
deleted file mode 100644
index 974889dd03a..00000000000
--- a/file_io/win32/fileio.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef FILE_IO_H
-#define FILE_IO_H
-
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_TIME_H
-#include <time.h>
-#endif
-#ifdef HAVE_DIRENT_H
-#include <dirent.h>
-#endif
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
-#ifdef HAVE_UIO_H
-#include <sys/uio.h>
-#endif
-#include "apr_private.h"
-#include "apr_pools.h"
-#include "apr_general.h"
-#include "apr_file_io.h"
-#include "apr_errno.h"
-
-/* quick run-down of fields in windows' ap_file_t structure that may have 
- * obvious uses.
- * fname --  the filename as passed to the open call.
- * dwFileAttricutes -- Attributes used to open the file.
- * demonfname -- the canonicalized filename.  Used to store the result from
- *               ap_os_canonicalize_filename.
- * lowerdemonfname -- inserted at Ken Parzygnat's request, because of the
- *                    ugly way windows deals with case in the filesystem.
- * append -- Windows doesn't support the append concept when opening files.
- *           APR needs to keep track of this, and always make sure we append
- *           correctly when writing to a file with this flag set TRUE.
- */
-
-struct ap_file_t {
-    ap_pool_t *cntxt;
-    HANDLE filehand;
-    char *fname;
-    DWORD dwFileAttributes;
-    int eof_hit;
-    int pipe;
-    ap_interval_time_t timeout;
-    int buffered;     /* Not currently used on Windows */
-    int ungetchar;    /* Not used. Last char provided by an unget op. (-1 = no char)*/
-
-    char *demonfname; 
-    char *lowerdemonfname; 
-    int append; 
-
-    off_t size;
-    ap_time_t atime;
-    ap_time_t mtime;
-    ap_time_t ctime;
-};
-
-struct ap_dir_t {
-    ap_pool_t *cntxt;
-    char *dirname;
-    HANDLE dirhand;
-    WIN32_FIND_DATA *entry;
-};
-
-ap_status_t file_cleanup(void *);
-/*mode_t get_fileperms(ap_fileperms_t);
-*/
-API_EXPORT(char *) ap_os_systemcase_filename(struct ap_pool_t *pCont, 
-                                             const char *szFile);
-char * canonical_filename(struct ap_pool_t *pCont, const char *szFile);
-
-#endif  /* ! FILE_IO_H */
-
diff --git a/file_io/win32/filepath.c b/file_io/win32/filepath.c
new file mode 100644
index 00000000000..23870bc5461
--- /dev/null
+++ b/file_io/win32/filepath.c
@@ -0,0 +1,990 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_private.h"
+#include "apr_arch_file_io.h"
+#include "apr_strings.h"
+#include "apr_lib.h"
+#include <string.h>
+#include <ctype.h>
+
+#ifdef NETWARE
+#include <unistd.h>
+#include <fsio.h>
+#endif
+
+ /* WinNT accepts several odd forms of a 'root' path.  Under Unicode
+ * calls (ApiFunctionW) the //?/C:/foo or //?/UNC/mach/share/foo forms
+ * are accepted.  Ansi and Unicode functions both accept the //./C:/foo 
+ * form under WinNT/2K.  Since these forms are handled in the utf-8 to 
+ * unicode translation phase, we don't want the user confused by them, so 
+ * we will accept them but always return the canonical C:/ or //mach/share/
+ *
+ * OS2 appears immune from the nonsense :)
+ */
+
+APR_DECLARE(apr_status_t) apr_filepath_root(const char **rootpath, 
+                                            const char **inpath, 
+                                            apr_int32_t flags,
+                                            apr_pool_t *p)
+{
+    const char *testpath = *inpath;
+    char *newpath;
+#ifdef NETWARE
+    char seperator[2] = { 0, 0};
+    char server[APR_PATH_MAX+1];
+    char volume[APR_PATH_MAX+1];
+    char file[APR_PATH_MAX+1];
+    char *volsep = NULL;
+    int elements;
+
+    if (inpath && *inpath)
+        volsep = strchr (*inpath, ':');
+    else
+        return APR_EBADPATH;
+
+    if (strlen(*inpath) > APR_PATH_MAX) {
+        return APR_EBADPATH;
+    }
+
+    seperator[0] = (flags & APR_FILEPATH_NATIVE) ? '\\' : '/';
+
+    /* Allocate and initialize each of the segment buffers
+    */
+    server[0] = volume[0] = file[0] = '\0';
+
+    /* If we don't have a volume separator then don't bother deconstructing
+        the path since we won't use the deconstructed information anyway.
+    */
+    if (volsep) {
+        /* Split the inpath into its separate parts. */
+        deconstruct(testpath, server, volume, NULL, file, NULL, &elements, PATH_UNDEF);
+    
+        /* If we got a volume part then continue splitting out the root.
+            Otherwise we either have an incomplete or relative path
+        */
+        if (volume && strlen(volume) > 0) {
+            newpath = apr_pcalloc(p, strlen(server)+strlen(volume)+5);
+            construct(newpath, server, volume, NULL, NULL, NULL, PATH_NETWARE);
+
+            /* NetWare doesn't add the root slash so we need to add it manually.
+            */
+            strcat(newpath, seperator);
+            *rootpath = newpath;
+
+            /* Skip the inpath pointer down to the first non-root character
+            */
+            newpath = volsep;
+            do {
+                ++newpath;
+            } while (*newpath && ((*newpath == '/') || (*newpath == '\\')));
+            *inpath = newpath;
+
+            /* Need to handle APR_FILEPATH_TRUENAME checking here. */
+
+            return APR_SUCCESS;
+        }
+        else
+            return APR_EBADPATH;
+    }
+    else if ((**inpath == '/') || (**inpath == '\\')) {
+        /* if we have a root path without a volume then just split
+            in same manner as unix although this path will be
+            incomplete.
+        */
+        *rootpath = apr_pstrdup(p, seperator);
+        do {
+            ++(*inpath);
+        } while ((**inpath == '/') || (**inpath == '\\'));
+    }
+    else
+        return APR_ERELATIVE;
+
+    return APR_EINCOMPLETE;
+
+#else /* ndef(NETWARE) */
+
+    char seperator[2];
+    const char *delim1;
+    const char *delim2;
+
+    seperator[0] = (flags & APR_FILEPATH_NATIVE) ? '\\' : '/';
+    seperator[1] = 0;
+
+    if (testpath[0] == '/' || testpath[0] == '\\') {
+        if (testpath[1] == '/' || testpath[1] == '\\') {
+
+#ifdef WIN32 /* //server/share isn't the only // delimited syntax */
+            if ((testpath[2] == '?' || testpath[2] == '.')
+                    && (testpath[3] == '/' || testpath[3] == '\\')) {
+                if (IS_FNCHAR(testpath[4]) && testpath[5] == ':') 
+                {
+                    apr_status_t rv;
+                    testpath += 4;
+                    /* given  '//?/C: or //./C: let us try this
+                     * all over again from the drive designator
+                     */
+                    rv = apr_filepath_root(rootpath, &testpath, flags, p);
+                    if (!rv || rv == APR_EINCOMPLETE)
+                        *inpath = testpath;
+                    return rv;
+                }
+                else if (strncasecmp(testpath + 4, "UNC", 3) == 0
+                      && (testpath[7] == '/' || testpath[7] == '\\') 
+                      && (testpath[2] == '?')) {
+                    /* given  '//?/UNC/machine/share, a little magic 
+                     * at the end makes this all work out by using
+                     * 'C/machine' as the starting point and replacing
+                     * the UNC delimiters with \'s, including the 'C'
+                     */
+                    testpath += 6;
+                }
+                else
+                    /* This must not be a path to a file, but rather
+                     * a volume or device.  Die for now.
+                     */
+                    return APR_EBADPATH;
+            }
+#endif /* WIN32 (non - //server/share syntax) */
+
+            /* Evaluate path of '//[machine/[share[/]]]' */
+            delim1 = testpath + 2;
+            do {
+                /* Protect against //X/ where X is illegal */
+                if (*delim1 && !IS_FNCHAR(*(delim1++)))
+                    return APR_EBADPATH;
+            } while (*delim1 && *delim1 != '/' && *delim1 != '\\');
+
+            if (*delim1) {
+                apr_status_t rv;
+                delim2 = delim1 + 1;
+                while (*delim2 && *delim2 != '/' && *delim2 != '\\') {
+                    /* Protect against //machine/X/ where X is illegal */
+                    if (!IS_FNCHAR(*(delim2++)))
+                        return APR_EBADPATH;
+                } 
+
+                /* Copy the '//machine/[share[/]]' path, always providing 
+                 * an extra byte for the trailing slash.
+                 */
+                newpath = apr_pstrmemdup(p, testpath, delim2 - testpath + 1);
+
+                if (delim2 == delim1 + 1) {
+                    /* We found simply \\machine\, so give up already
+                     */
+                    *rootpath = newpath;
+                    *inpath = delim2;
+                    return APR_EINCOMPLETE;
+                }
+
+                if (flags & APR_FILEPATH_TRUENAME) {
+                    /* Validate the \\Machine\Share\ designation, 
+                     * Win32 will argue about slashed in UNC paths, 
+                     * so use backslashes till we finish testing,
+                     * and add the trailing backslash [required].
+                     * apr_pstrmemdup above guarentees us the new 
+                     * trailing null character.
+                     */
+                    newpath[0] = '\\';
+                    newpath[1] = '\\';
+                    newpath[delim1 - testpath] = '\\';
+                    newpath[delim2 - testpath] = '\\';
+
+                    rv = filepath_root_test(newpath, p);
+                    if (rv)
+                        return rv;
+                    rv = filepath_root_case(&newpath, newpath, p);
+                    if (rv)
+                        return rv;
+                    newpath[0] = seperator[0];
+                    newpath[1] = seperator[0];
+                    newpath[delim1 - testpath] = seperator[0];
+                    newpath[delim2 - testpath] = (*delim2 ? seperator[0] : '\0');
+                }
+                else {                
+                    /* Give back the caller's own choice of delimiters
+                     */
+                    newpath[0] = testpath[0];
+                    newpath[1] = testpath[1];
+                    newpath[delim1 - testpath] = *delim1;
+                    newpath[delim2 - testpath] = *delim2;
+                }
+
+                /* If this root included the trailing / or \ designation 
+                 * then lop off multiple trailing slashes and give back
+                 * appropriate delimiters.
+                 */
+                if (*delim2) {
+                    *inpath = delim2 + 1;
+                    while (**inpath == '/' || **inpath == '\\')
+                        ++*inpath;
+                }
+                else {
+                    *inpath = delim2;
+                }
+
+                *rootpath = newpath;
+                return APR_SUCCESS;
+            }
+            
+            /* Have path of '\\[machine]', if the machine is given,
+             * append same trailing slash as the leading slash
+             */
+            delim1 = strchr(testpath, '\0');
+            if (delim1 > testpath + 2) {
+                newpath = apr_pstrndup(p, testpath, delim1 - testpath + 1);
+                if (flags & APR_FILEPATH_TRUENAME)
+                    newpath[delim1 - testpath] = seperator[0];
+                else
+                    newpath[delim1 - testpath] = newpath[0];
+                newpath[delim1 - testpath + 1] = '\0';
+            }
+            else {
+                newpath = apr_pstrndup(p, testpath, delim1 - testpath);
+            }
+            if (flags & APR_FILEPATH_TRUENAME) {
+                newpath[0] = seperator[0];
+                newpath[1] = seperator[0];
+            }
+            *rootpath = newpath;
+            *inpath = delim1;
+            return APR_EINCOMPLETE;
+        }
+
+        /* Left with a path of '/', what drive are we asking about? 
+         */
+        *inpath = testpath + 1;
+        newpath = apr_palloc(p, 2);
+        if (flags & APR_FILEPATH_TRUENAME)
+            newpath[0] = seperator[0];
+        else
+            newpath[0] = testpath[0];
+        newpath[1] = '\0';
+        *rootpath = newpath;
+        return APR_EINCOMPLETE;
+    }
+
+    /* Evaluate path of 'd:[/]' */
+    if (IS_FNCHAR(*testpath) && testpath[1] == ':') 
+    {
+        apr_status_t rv;
+        /* Validate that D:\ drive exists, test must be rooted
+         * Note that posix/win32 insists a drive letter is upper case,
+         * so who are we to argue with a 'feature'.
+         * It is a safe fold, since only A-Z is legal, and has no
+         * side effects of legal mis-mapped non-us-ascii codes.
+         */
+        newpath = apr_palloc(p, 4);
+        newpath[0] = testpath[0];
+        newpath[1] = testpath[1];
+        newpath[2] = seperator[0];
+        newpath[3] = '\0';
+        if (flags & APR_FILEPATH_TRUENAME) {
+            newpath[0] = apr_toupper(newpath[0]);
+            rv = filepath_root_test(newpath, p);
+            if (rv)
+                return rv;
+        }
+        /* Just give back the root the user handed to us.
+         */
+        if (testpath[2] != '/' && testpath[2] != '\\') {
+            newpath[2] = '\0';
+            *rootpath = newpath;
+            *inpath = testpath + 2;
+            return APR_EINCOMPLETE;
+        }
+
+        /* strip off remaining slashes that designate the root,
+         * give the caller back their original choice of slash
+         * unless this is TRUENAME'ed
+         */
+        *inpath = testpath + 3;
+        while (**inpath == '/' || **inpath == '\\')
+            ++*inpath;
+        if (!(flags & APR_FILEPATH_TRUENAME))
+            newpath[2] = testpath[2];
+        *rootpath = newpath;
+        return APR_SUCCESS;
+    }
+
+    /* Nothing interesting */
+    return APR_ERELATIVE;
+
+#endif /* ndef(NETWARE) */
+}
+
+#if !defined(NETWARE)
+static int same_drive(const char *path1, const char *path2)
+{
+    char drive1 = path1[0];
+    char drive2 = path2[0];
+
+    if (!drive1 || !drive2 || path1[1] != ':' || path2[1] != ':')
+        return FALSE;
+
+    if (drive1 == drive2)
+        return TRUE;
+
+    if (drive1 >= 'a' && drive1 <= 'z')
+        drive1 += 'A' - 'a';
+
+    if (drive2 >= 'a' && drive2 <= 'z')
+        drive2 += 'A' - 'a';
+
+    return (drive1 == drive2);
+}
+#endif
+
+APR_DECLARE(apr_status_t) apr_filepath_merge(char **newpath, 
+                                             const char *basepath, 
+                                             const char *addpath, 
+                                             apr_int32_t flags,
+                                             apr_pool_t *p)
+{
+    char path[APR_PATH_MAX]; /* isn't null term */
+    const char *baseroot = NULL;
+    const char *addroot;
+    apr_size_t rootlen; /* the length of the root portion of path, d:/ is 3 */
+    apr_size_t baselen; /* the length of basepath (excluding baseroot) */
+    apr_size_t keptlen; /* the length of the retained basepath (incl root) */
+    apr_size_t pathlen; /* the length of the result path */
+    apr_size_t segend;  /* the end of the current segment */
+    apr_size_t seglen;  /* the length of the segment (excl trailing chars) */
+    apr_status_t basetype = 0; /* from parsing the basepath's baseroot */
+    apr_status_t addtype;      /* from parsing the addpath's addroot */
+    apr_status_t rv;
+#ifndef NETWARE
+    int fixunc = 0;  /* flag to complete an incomplete UNC basepath */
+#endif
+    
+    /* Treat null as an empty path, otherwise split addroot from the addpath
+     */
+    if (!addpath) {
+        addpath = addroot = "";
+        addtype = APR_ERELATIVE;
+    }
+    else {
+        /* This call _should_ test the path
+         */
+        addtype = apr_filepath_root(&addroot, &addpath, 
+                                    APR_FILEPATH_TRUENAME
+                                    | (flags & APR_FILEPATH_NATIVE),
+                                    p);
+        if (addtype == APR_SUCCESS) {
+            addtype = APR_EABSOLUTE;
+        }
+        else if (addtype == APR_ERELATIVE) {
+            addroot = "";
+        }
+        else if (addtype != APR_EINCOMPLETE) {
+            /* apr_filepath_root was incomprehensible so fail already
+             */
+            return addtype;
+        }
+    }
+
+    /* If addpath is (even partially) rooted, then basepath is
+     * unused.  Ths violates any APR_FILEPATH_SECUREROOTTEST 
+     * and APR_FILEPATH_NOTABSOLUTE flags specified.
+     */
+    if (addtype == APR_EABSOLUTE || addtype == APR_EINCOMPLETE)
+    {
+        if (flags & APR_FILEPATH_SECUREROOTTEST)
+            return APR_EABOVEROOT;
+        if (flags & APR_FILEPATH_NOTABSOLUTE)
+            return addtype;
+    }
+
+    /* Optimized tests before we query the current working path
+     */
+    if (!basepath) {
+
+        /* If APR_FILEPATH_NOTABOVEROOT wasn't specified,
+         * we won't test the root again, it's ignored.
+         * Waste no CPU retrieving the working path.
+         */
+        if (addtype == APR_EABSOLUTE && !(flags & APR_FILEPATH_NOTABOVEROOT)) {
+            basepath = baseroot = "";
+            basetype = APR_ERELATIVE;
+        }
+
+        /* If APR_FILEPATH_NOTABSOLUTE is specified, the caller 
+         * requires an absolutely relative result, So do not retrieve 
+         * the working path.
+         */
+        if (addtype == APR_ERELATIVE && (flags & APR_FILEPATH_NOTABSOLUTE)) {
+            basepath = baseroot = "";
+            basetype = APR_ERELATIVE;
+        }
+    }
+
+    if (!basepath) 
+    {
+        /* Start with the current working path.  This is bass akwards,
+         * but required since the compiler (at least vc) doesn't like
+         * passing the address of a char const* for a char** arg.
+         * We must grab the current path of the designated drive 
+         * if addroot is given in drive-relative form (e.g. d:foo)
+         */
+        char *getpath;
+#ifndef NETWARE
+        if (addtype == APR_EINCOMPLETE && addroot[1] == ':')
+            rv = filepath_drive_get(&getpath, addroot[0], flags, p);
+        else
+#endif
+            rv = apr_filepath_get(&getpath, flags, p);
+        if (rv != APR_SUCCESS)
+            return rv;
+        basepath = getpath;
+    }
+
+    if (!baseroot) {
+        /* This call should _not_ test the path
+         */
+        basetype = apr_filepath_root(&baseroot, &basepath,
+                                     (flags & APR_FILEPATH_NATIVE), p);
+        if (basetype == APR_SUCCESS) {
+            basetype = APR_EABSOLUTE;
+        }
+        else if (basetype == APR_ERELATIVE) {
+            baseroot = "";
+        }
+        else if (basetype != APR_EINCOMPLETE) {
+            /* apr_filepath_root was incomprehensible so fail already
+             */
+            return basetype;
+        }
+    }
+    baselen = strlen(basepath);
+
+    /* If APR_FILEPATH_NOTABSOLUTE is specified, the caller 
+     * requires an absolutely relative result.  If the given 
+     * basepath is not relative then fail.
+     */
+    if ((flags & APR_FILEPATH_NOTABSOLUTE) && basetype != APR_ERELATIVE)
+        return basetype;
+
+    /* The Win32 nightmare on unc street... start combining for
+     * many possible root combinations.
+     */
+    if (addtype == APR_EABSOLUTE)
+    {
+        /* Ignore the given root path, and start with the addroot
+         */
+        if ((flags & APR_FILEPATH_NOTABOVEROOT) 
+                && strncmp(baseroot, addroot, strlen(baseroot)))
+            return APR_EABOVEROOT;
+        keptlen = 0;
+        rootlen = pathlen = strlen(addroot);
+        memcpy(path, addroot, pathlen);
+    }
+    else if (addtype == APR_EINCOMPLETE)
+    {
+        /* There are several types of incomplete paths, 
+         *     incomplete UNC paths         (//foo/ or //),
+         *     drives without rooted paths  (d: as in d:foo), 
+         * and simple roots                 (/ as in /foo).
+         * Deal with these in significantly different manners...
+         */
+#ifndef NETWARE
+        if ((addroot[0] == '/' || addroot[0] == '\\') &&
+            (addroot[1] == '/' || addroot[1] == '\\')) 
+        {
+            /* Ignore the given root path if the incomplete addpath is UNC,
+             * (note that the final result will be incomplete).
+             */
+            if (flags & APR_FILEPATH_NOTRELATIVE)
+                return addtype;
+            if ((flags & APR_FILEPATH_NOTABOVEROOT) 
+                    && strncmp(baseroot, addroot, strlen(baseroot)))
+                return APR_EABOVEROOT;
+            fixunc = 1;
+            keptlen = 0;
+            rootlen = pathlen = strlen(addroot);
+            memcpy(path, addroot, pathlen);
+        }
+        else
+#endif            
+        if ((addroot[0] == '/' || addroot[0] == '\\') && !addroot[1]) 
+        {
+            /* Bring together the drive or UNC root from the baseroot
+             * if the addpath is a simple root and basepath is rooted,
+             * otherwise disregard the basepath entirely.
+             */
+            if (basetype != APR_EABSOLUTE && (flags & APR_FILEPATH_NOTRELATIVE))
+                return basetype;
+            if (basetype != APR_ERELATIVE) {
+#ifndef NETWARE
+                if (basetype == APR_INCOMPLETE 
+                        && (baseroot[0] == '/' || baseroot[0] == '\\')
+                        && (baseroot[1] == '/' || baseroot[1] == '\\'))
+                    fixunc = 1;
+#endif
+                keptlen = rootlen = pathlen = strlen(baseroot);
+                memcpy(path, baseroot, pathlen);
+            }
+            else {
+                if (flags & APR_FILEPATH_NOTABOVEROOT)
+                    return APR_EABOVEROOT;
+                keptlen = 0;
+                rootlen = pathlen = strlen(addroot);
+                memcpy(path, addroot, pathlen);
+            }
+        }
+#ifdef NETWARE
+        else if (filepath_has_drive(addroot, DRIVE_ONLY, p)) 
+        {
+            /* If the addroot is a drive (without a volume root)
+             * use the basepath _if_ it matches this drive letter!
+             * Otherwise we must discard the basepath.
+             */
+            if (!filepath_compare_drive(addroot, baseroot, p) && 
+                filepath_has_drive(baseroot, 0, p)) {
+#else
+        else if (addroot[0] && addroot[1] == ':' && !addroot[2]) 
+        {
+            /* If the addroot is a drive (without a volume root)
+             * use the basepath _if_ it matches this drive letter!
+             * Otherwise we must discard the basepath.
+             */
+            if (same_drive(addroot, baseroot)) {
+#endif
+                /* Base the result path on the basepath
+                 */
+                if (basetype != APR_EABSOLUTE && (flags & APR_FILEPATH_NOTRELATIVE))
+                    return basetype;
+                rootlen = strlen(baseroot);
+                keptlen = pathlen = rootlen + baselen;
+                if (keptlen >= sizeof(path))
+                    return APR_ENAMETOOLONG;
+                memcpy(path, baseroot, rootlen);
+                memcpy(path + rootlen, basepath, baselen);
+            } 
+            else {
+                if (flags & APR_FILEPATH_NOTRELATIVE)
+                    return addtype;
+                if (flags & APR_FILEPATH_NOTABOVEROOT)
+                    return APR_EABOVEROOT;
+                keptlen = 0;
+                rootlen = pathlen = strlen(addroot);
+                memcpy(path, addroot, pathlen);
+            }
+        }
+        else {
+            /* Now this is unexpected, we aren't aware of any other
+             * incomplete path forms!  Fail now.
+             */
+            return APR_EBADPATH;
+        }
+    }
+    else { /* addtype == APR_ERELATIVE */
+        /* If both paths are relative, fail early
+         */
+        if (basetype != APR_EABSOLUTE && (flags & APR_FILEPATH_NOTRELATIVE))
+            return basetype;
+
+#ifndef NETWARE
+        /* An incomplete UNC path must be completed
+         */
+        if (basetype == APR_INCOMPLETE 
+                && (baseroot[0] == '/' || baseroot[0] == '\\')
+                && (baseroot[1] == '/' || baseroot[1] == '\\'))
+            fixunc = 1;
+#endif
+
+        /* Base the result path on the basepath
+         */
+        rootlen = strlen(baseroot);
+        keptlen = pathlen = rootlen + baselen;
+        if (keptlen >= sizeof(path))
+            return APR_ENAMETOOLONG;
+        memcpy(path, baseroot, rootlen);
+        memcpy(path + rootlen, basepath, baselen);
+    }
+
+    /* '/' terminate the given root path unless it's already terminated
+     * or is an incomplete drive root.  Correct the trailing slash unless
+     * we have an incomplete UNC path still to fix.
+     */
+    if (pathlen && path[pathlen - 1] != ':') {
+        if (path[pathlen - 1] != '/' && path[pathlen - 1] != '\\') {
+            if (pathlen + 1 >= sizeof(path))
+                return APR_ENAMETOOLONG;
+        
+            path[pathlen++] = ((flags & APR_FILEPATH_NATIVE) ? '\\' : '/');
+        }
+    /*  XXX: wrong, but gotta figure out what I intended;
+     *  else if (!fixunc)
+     *      path[pathlen++] = ((flags & APR_FILEPATH_NATIVE) ? '\\' : '/');
+     */
+    }
+
+    while (*addpath) 
+    {
+        /* Parse each segment, find the closing '/' 
+         */
+        seglen = 0;
+        while (addpath[seglen] && addpath[seglen] != '/'
+                               && addpath[seglen] != '\\')
+            ++seglen;
+
+        /* Truncate all trailing spaces and all but the first two dots */
+        segend = seglen;
+        while (seglen && (addpath[seglen - 1] == ' ' 
+                       || addpath[seglen - 1] == '.')) {
+            if (seglen > 2 || addpath[seglen - 1] != '.' || addpath[0] != '.')
+                --seglen;
+            else
+                break;
+        }
+
+        if (seglen == 0 || (seglen == 1 && addpath[0] == '.')) 
+        {
+            /* NOTE: win32 _hates_ '/ /' and '/. /' (yes, with spaces in there)
+             * so eliminate all preconceptions that it is valid.
+             */
+            if (seglen < segend)
+                return APR_EBADPATH;
+
+#ifndef NETWARE
+            /* This isn't legal unless the unc path is completed
+             */
+            if (fixunc)
+                return APR_EBADPATH;
+#endif
+
+            /* Otherwise, this is a noop segment (/ or ./) so ignore it 
+             */
+        }
+        else if (seglen == 2 && addpath[0] == '.' && addpath[1] == '.') 
+        {
+            /* NOTE: win32 _hates_ '/.. /' (yes, with a space in there)
+             * and '/..../', some functions treat it as ".", and some 
+             * fail! Eliminate all preconceptions that they are valid.
+             */
+            if (seglen < segend && (seglen != 3 || addpath[2] != '.'))
+                return APR_EBADPATH;
+
+#ifndef NETWARE
+            /* This isn't legal unless the unc path is completed
+             */
+            if (fixunc)
+                return APR_EBADPATH;
+#endif
+
+            /* backpath (../) when an absolute path is given */
+            if (rootlen && (pathlen <= rootlen)) 
+            {
+                /* Attempt to move above root.  Always die if the 
+                 * APR_FILEPATH_SECUREROOTTEST flag is specified.
+                 */
+                if (flags & APR_FILEPATH_SECUREROOTTEST)
+                    return APR_EABOVEROOT;
+                
+                /* Otherwise this is simply a noop, above root is root.
+                 */
+            }
+            else if (pathlen == 0 
+                      || (pathlen >= 3 
+                           && (pathlen == 3
+                                || path[pathlen - 4] == ':'
+                                || path[pathlen - 4] == '/' 
+                                || path[pathlen - 4] == '\\')
+                           &&  path[pathlen - 3] == '.' 
+                           &&  path[pathlen - 2] == '.' 
+                           && (path[pathlen - 1] == '/' 
+                                || path[pathlen - 1] == '\\')))
+            {
+                /* Verified path is empty, exactly "..[/\]", or ends
+                 * in "[:/\]..[/\]" - these patterns we will not back
+                 * over since they aren't 'prior segements'.
+                 * 
+                 * If APR_FILEPATH_SECUREROOTTEST.was given, die now.
+                 */
+                if (flags & APR_FILEPATH_SECUREROOTTEST)
+                    return APR_EABOVEROOT;
+
+                /* Otherwise append another backpath.
+                 */
+                if (pathlen + 3 >= sizeof(path))
+                    return APR_ENAMETOOLONG;
+                path[pathlen++] = '.';
+                path[pathlen++] = '.';
+                if (addpath[segend]) {
+                    path[pathlen++] = ((flags & APR_FILEPATH_NATIVE) 
+                                    ? '\\' : ((flags & APR_FILEPATH_TRUENAME)
+                                           ? '/' : addpath[segend]));
+                }
+                /* The 'root' part of this path now includes the ../ path,
+                 * because that backpath will not be parsed by the truename
+                 * code below.
+                 */
+                keptlen = pathlen;
+            }
+            else 
+            {
+                /* otherwise crop the prior segment 
+                 */
+                do {
+                    --pathlen;
+                } while (pathlen && path[pathlen - 1] != '/'
+                                 && path[pathlen - 1] != '\\');
+
+                /* Now test if we are above where we started and back up
+                 * the keptlen offset to reflect the added/altered path.
+                 */
+                if (pathlen < keptlen) 
+                {
+                    if (flags & APR_FILEPATH_SECUREROOTTEST)
+                        return APR_EABOVEROOT;
+                    keptlen = pathlen;
+                }
+            }
+        }
+        else /* not empty or dots */
+        {
+#ifndef NETWARE
+            if (fixunc) {
+                const char *testpath = path;
+                const char *testroot;
+                apr_status_t testtype;
+                apr_size_t i = (addpath[segend] != '\0');
+                
+                /* This isn't legal unless the unc path is complete!
+                 */
+                if (seglen < segend)
+                    return APR_EBADPATH;
+                if (pathlen + seglen + 1 >= sizeof(path))
+                    return APR_ENAMETOOLONG;
+                memcpy(path + pathlen, addpath, seglen + i);
+                
+                /* Always add the trailing slash to a UNC segment
+                 */
+                path[pathlen + seglen] = ((flags & APR_FILEPATH_NATIVE) 
+                                             ? '\\' : '/');
+                pathlen += seglen + 1;
+
+                /* Recanonicalize the UNC root with the new UNC segment,
+                 * and if we succeed, reset this test and the rootlen,
+                 * and replace our path with the canonical UNC root path
+                 */
+                path[pathlen] = '\0';
+                /* This call _should_ test the path
+                 */
+                testtype = apr_filepath_root(&testroot, &testpath, 
+                                             APR_FILEPATH_TRUENAME
+                                             | (flags & APR_FILEPATH_NATIVE),
+                                             p);
+                if (testtype == APR_SUCCESS) {
+                    rootlen = pathlen = (testpath - path);
+                    memcpy(path, testroot, pathlen);
+                    fixunc = 0;
+                }
+                else if (testtype != APR_EINCOMPLETE) {
+                    /* apr_filepath_root was very unexpected so fail already
+                     */
+                    return testtype;
+                }
+            }
+            else
+#endif
+            {
+                /* An actual segment, append it to the destination path
+                 */
+                apr_size_t i = (addpath[segend] != '\0');
+                if (pathlen + seglen + i >= sizeof(path))
+                    return APR_ENAMETOOLONG;
+                memcpy(path + pathlen, addpath, seglen + i);
+                if (i)
+                    path[pathlen + seglen] = ((flags & APR_FILEPATH_NATIVE) 
+                                                 ? '\\' : '/');
+                pathlen += seglen + i;
+            }
+        }
+
+        /* Skip over trailing slash to the next segment
+         */
+        if (addpath[segend])
+            ++segend;
+
+        addpath += segend;
+    }
+    
+    /* keptlen will be the baselen unless the addpath contained
+     * backpath elements.  If so, and APR_FILEPATH_NOTABOVEROOT
+     * is specified (APR_FILEPATH_SECUREROOTTEST was caught above),
+     * compare the string beyond the root to assure the result path 
+     * is still within given basepath.  Note that the root path 
+     * segment is thoroughly tested prior to path parsing.
+     */
+    if ((flags & APR_FILEPATH_NOTABOVEROOT) && baselen) {
+        if (memcmp(basepath, path + rootlen, baselen) != 0)
+            return APR_EABOVEROOT;
+ 
+         /* Ahem... if we have a basepath without a trailing slash,
+          * we better be sure that /foo wasn't replaced with /foobar!
+          */
+        if (basepath[baselen - 1] != '/' && basepath[baselen - 1] != '\\'
+              && path[rootlen + baselen] && path[rootlen + baselen] != '/' 
+                                         && path[rootlen + baselen] != '\\')
+            return APR_EABOVEROOT;
+    }
+
+    if (addpath && (flags & APR_FILEPATH_TRUENAME)) {
+        /* We can always skip the root, it's already true-named. */
+        if (rootlen > keptlen)
+            keptlen = rootlen;
+        if ((path[keptlen] == '/') || (path[keptlen] == '\\')) {
+            /* By rights, keptlen may grown longer than pathlen.
+             * we wont' use it again (in that case) so we don't care.
+             */
+            ++keptlen;
+        }
+        /* Go through all the new segments */
+        while (keptlen < pathlen) {
+            apr_finfo_t finfo;
+            char saveslash = 0;
+            seglen = 0;
+            /* find any slash and set it aside for a minute. */
+            for (seglen = 0; keptlen + seglen < pathlen; ++seglen) {
+                if ((path[keptlen + seglen] == '/')  ||
+                    (path[keptlen + seglen] == '\\')) {
+                    saveslash = path[keptlen + seglen];
+                    break;
+                }
+            }
+            /* Null term for stat! */
+            path[keptlen + seglen] = '\0';
+            if ((rv = apr_stat(&finfo, path, 
+                               APR_FINFO_LINK | APR_FINFO_TYPE | APR_FINFO_NAME, p))
+                == APR_SUCCESS) {
+                apr_size_t namelen = strlen(finfo.name);
+
+#if defined(OS2) /* only has case folding, never aliases that change the length */
+
+                if (memcmp(finfo.name, path + keptlen, seglen) != 0) {
+                    memcpy(path + keptlen, finfo.name, namelen);
+                }
+#else /* WIN32 || NETWARE; here there be aliases that gire and gimble and change length */
+
+                if ((namelen != seglen) || 
+                    (memcmp(finfo.name, path + keptlen, seglen) != 0)) 
+                {
+                    if (namelen <= seglen) {
+                        memcpy(path + keptlen, finfo.name, namelen);
+                        if ((namelen < seglen) && saveslash) {
+                            memmove(path + keptlen + namelen + 1,
+                                   path + keptlen + seglen + 1,
+                                   pathlen - keptlen - seglen);
+                        }
+                        pathlen += namelen - seglen;
+                        seglen = namelen;
+                    }
+                    else { /* namelen > seglen */
+                        if (pathlen + namelen - seglen >= sizeof(path))
+                            return APR_ENAMETOOLONG;
+                        if (saveslash) {
+                            memmove(path + keptlen + namelen + 1,
+                                   path + keptlen + seglen + 1,
+                                   pathlen - keptlen - seglen);
+                        }
+                        memcpy(path + keptlen, finfo.name, namelen);
+                        pathlen += namelen - seglen;
+                        seglen = namelen;
+                    }
+                }
+#endif /* !OS2 (Whatever that alias was we're over it) */
+
+                /* That's it, the rest is path info. 
+                 * I don't know how we aught to handle this.  Should
+                 * we define a new error to indicate 'more info'?
+                 * Should we split out the rest of the path?
+                 */
+                if ((finfo.filetype != APR_DIR) && 
+                    (finfo.filetype != APR_LNK) && saveslash) 
+                    rv = APR_ENOTDIR;
+#ifdef XXX_FIGURE_THIS_OUT
+                {
+                    /* the example inserts a null between the end of 
+                     * the filename and the next segment, and increments
+                     * the path length so we would return both segments.
+                     */
+                    if (saveslash) {
+                        keptlen += seglen;
+                        path[keptlen] = saveslash;
+                        if (pathlen + 1 >= sizeof(path))
+                            return APR_ENAMETOOLONG;
+                        memmove(path + keptlen + 1,
+                               path + keptlen,
+                               pathlen - keptlen);
+                        path[keptlen] = '\0';
+                        ++pathlen;
+                        break;
+                    }
+                }
+#endif
+            }
+
+            /* put back the '/' */
+            if (saveslash) {
+                path[keptlen + seglen] = saveslash;
+                ++seglen;
+            }
+            keptlen += seglen;
+
+            if (rv != APR_SUCCESS) {
+                if (APR_STATUS_IS_ENOENT(rv))
+                    break;
+                if (APR_STATUS_IS_EPATHWILD(rv))
+                    /* This path included wildcards.  The path elements
+                     * that did not contain wildcards are canonicalized,
+                     * so we will return the path, although later elements
+                     * don't necessarily exist, and aren't canonical.
+                     */
+                    break;
+                else if (APR_STATUS_IS_ENOTDIR(rv))
+                    /* This is a little more serious, we just added a name
+                     * onto a filename (think http's PATH_INFO)
+                     * If the caller is foolish enough to do this, we expect
+                     * the've already canonicalized the root) that they knew
+                     * what they are doing :(
+                     */
+                    break;
+                else
+                    return rv;
+            }
+        }
+    }
+
+    *newpath = apr_pstrmemdup(p, path, pathlen);
+    return APR_SUCCESS;
+}
+
+
+APR_DECLARE(apr_status_t) apr_filepath_encoding(int *style, apr_pool_t *p)
+{
+#if APR_HAS_UNICODE_FS
+    IF_WIN_OS_IS_UNICODE
+    {
+        *style = APR_FILEPATH_ENCODING_UTF8;
+        return APR_SUCCESS;
+    }
+#endif
+
+    *style = APR_FILEPATH_ENCODING_LOCALE;
+    return APR_SUCCESS;
+}
diff --git a/file_io/win32/filestat.c b/file_io/win32/filestat.c
index 861f12b32e3..ba4160785d6 100644
--- a/file_io/win32/filestat.c
+++ b/file_io/win32/filestat.c
@@ -1,201 +1,825 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
+#include "apr.h"
+#include <aclapi.h>
 #include "apr_private.h"
-#include "fileio.h"
+#include "apr_arch_file_io.h"
 #include "apr_file_io.h"
 #include "apr_general.h"
+#include "apr_strings.h"
 #include "apr_errno.h"
 #include "apr_time.h"
 #include <sys/stat.h>
-#include "atime.h"
-#include "misc.h"
+#include "apr_arch_atime.h"
+#include "apr_arch_misc.h"
+
+/* We have to assure that the file name contains no '*'s, or other
+ * wildcards when using FindFirstFile to recover the true file name.
+ */
+static apr_status_t test_safe_name(const char *name)
+{
+    /* Only accept ':' in the second position of the filename,
+     * as the drive letter delimiter:
+     */
+    if (apr_isalpha(*name) && (name[1] == ':')) {
+        name += 2;
+    }
+    while (*name) {
+        if (!IS_FNCHAR(*name) && (*name != '\\') && (*name != '/')) {
+            if (*name == '?' || *name == '*')
+                return APR_EPATHWILD;
+            else
+                return APR_EBADPATH;
+        }
+        ++name;
+    }
+    return APR_SUCCESS;
+}
 
-#define S_ISLNK(m)  (0)
-#define S_ISREG(m)  (((m) & (S_IFMT))  == S_IFREG)
-#define S_ISDIR(m)  (((m) & (S_IFDIR)) == S_IFDIR)
+static apr_status_t free_localheap(void *heap) {
+    LocalFree(heap);
+    return APR_SUCCESS;
+}
 
-static ap_filetype_e filetype_from_mode(int mode)
+static apr_gid_t worldid = NULL;
+
+static void free_world(void)
 {
-    ap_filetype_e type = APR_NOFILE;
+    if (worldid) {
+        FreeSid(worldid);
+        worldid = NULL;
+    }
+}
 
-    if (S_ISREG(mode))
-        type = APR_REG;
-    if (S_ISDIR(mode))
-        type = APR_DIR;
-    if (S_ISLNK(mode))
-        type = APR_LNK;
+/* Left bit shifts from World scope to given scope */
+typedef enum prot_scope_e {
+    prot_scope_world = 0,
+    prot_scope_group = 4,
+    prot_scope_user =  8
+} prot_scope_e;
 
-    return type;
+static apr_fileperms_t convert_prot(ACCESS_MASK acc, prot_scope_e scope)
+{
+    /* These choices are based on the single filesystem bit that controls
+     * the given behavior.  They are -not- recommended for any set protection
+     * function, such a function should -set- use GENERIC_READ/WRITE/EXECUTE
+     */
+    apr_fileperms_t prot = 0;
+    if (acc & FILE_EXECUTE)
+        prot |= APR_FPROT_WEXECUTE;
+    if (acc & FILE_WRITE_DATA)
+        prot |= APR_FPROT_WWRITE;
+    if (acc & FILE_READ_DATA)
+        prot |= APR_FPROT_WREAD;
+    return (prot << scope);
 }
-BOOLEAN is_exe(const char* fname, ap_pool_t *cont) {
-    const char* exename;
-    const char* ext;
-    exename = strrchr(fname, '/');
-    if (!exename) {
-        exename = strrchr(fname, '\\');
+
+static void resolve_prot(apr_finfo_t *finfo, apr_int32_t wanted, PACL dacl)
+{
+    TRUSTEE_W ident = {NULL, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID};
+    ACCESS_MASK acc;
+    /*
+     * This function is only invoked for WinNT, 
+     * there is no reason for os_level testing here.
+     */
+    if ((wanted & APR_FINFO_WPROT) && !worldid) {
+        SID_IDENTIFIER_AUTHORITY SIDAuth = {SECURITY_WORLD_SID_AUTHORITY};
+        if (AllocateAndInitializeSid(&SIDAuth, 1, SECURITY_WORLD_RID,
+                                     0, 0, 0, 0, 0, 0, 0, &worldid))
+            atexit(free_world);
+        else
+            worldid = NULL;
     }
-    if (!exename) {
-        exename = fname;
+    if ((wanted & APR_FINFO_UPROT) && (finfo->valid & APR_FINFO_USER)) {
+        ident.TrusteeType = TRUSTEE_IS_USER;
+        ident.ptstrName = finfo->user;
+        /* GetEffectiveRightsFromAcl isn't supported under Win9x,
+         * which shouldn't come as a surprize.  Since we are passing
+         * TRUSTEE_IS_SID, always skip the A->W layer.
+         */
+        if (GetEffectiveRightsFromAclW(dacl, &ident, &acc) == ERROR_SUCCESS) {
+            finfo->protection |= convert_prot(acc, prot_scope_user);
+            finfo->valid |= APR_FINFO_UPROT;
+        }
     }
-    else {
-        exename++;
+    /* Windows NT: did not return group rights.
+     * Windows 2000 returns group rights information.
+     * Since WinNT kernels don't follow the unix model of 
+     * group associations, this all all pretty mute.
+     */
+    if ((wanted & APR_FINFO_GPROT) && (finfo->valid & APR_FINFO_GROUP)) {
+        ident.TrusteeType = TRUSTEE_IS_GROUP;
+        ident.ptstrName = finfo->group;
+        if (GetEffectiveRightsFromAclW(dacl, &ident, &acc) == ERROR_SUCCESS) {
+            finfo->protection |= convert_prot(acc, prot_scope_group);
+            finfo->valid |= APR_FINFO_GPROT;
+        }
+    }
+    if ((wanted & APR_FINFO_WPROT) && (worldid)) {
+        ident.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
+        ident.ptstrName = worldid;
+        if (GetEffectiveRightsFromAclW(dacl, &ident, &acc) == ERROR_SUCCESS) {
+            finfo->protection |= convert_prot(acc, prot_scope_world);
+            finfo->valid |= APR_FINFO_WPROT;
+        }
     }
-    ext = strrchr(exename, '.');
+}
 
-    if (ext && (!strcasecmp(ext,".exe") || !strcasecmp(ext,".com") || 
-                !strcasecmp(ext,".bat") || !strcasecmp(ext,".cmd"))) {
-        return TRUE;
+static apr_status_t resolve_ident(apr_finfo_t *finfo, const char *fname,
+                                  apr_int32_t wanted, apr_pool_t *pool)
+{
+    apr_file_t *thefile = NULL;
+    apr_status_t rv;
+    /* 
+     * NT5 (W2K) only supports symlinks in the same manner as mount points.
+     * This code should eventually take that into account, for now treat
+     * every reparse point as a symlink...
+     *
+     * We must open the file with READ_CONTROL if we plan to retrieve the
+     * user, group or permissions.
+     */
+    
+    if ((rv = apr_file_open(&thefile, fname, APR_OPENINFO
+                          | ((wanted & APR_FINFO_LINK) ? APR_OPENLINK : 0)
+                          | ((wanted & (APR_FINFO_PROT | APR_FINFO_OWNER))
+                                ? APR_READCONTROL : 0),
+                            APR_FPROT_OS_DEFAULT, pool)) == APR_SUCCESS) {
+        rv = apr_file_info_get(finfo, wanted, thefile);
+        finfo->filehand = NULL;
+        apr_file_close(thefile);
+    }
+    else if (APR_STATUS_IS_EACCES(rv) && (wanted & (APR_FINFO_PROT 
+                                                  | APR_FINFO_OWNER))) {
+        /* We have a backup plan.  Perhaps we couldn't grab READ_CONTROL?
+         * proceed without asking for that permission...
+         */
+        if ((rv = apr_file_open(&thefile, fname, APR_OPENINFO
+                              | ((wanted & APR_FINFO_LINK) ? APR_OPENLINK : 0),
+                                APR_FPROT_OS_DEFAULT, pool)) == APR_SUCCESS) {
+            rv = apr_file_info_get(finfo, wanted & ~(APR_FINFO_PROT 
+                                                 | APR_FINFO_OWNER),
+                                 thefile);
+            finfo->filehand = NULL;
+            apr_file_close(thefile);
+        }
     }
-    return FALSE;
+
+    if (rv != APR_SUCCESS && rv != APR_INCOMPLETE)
+        return (rv);
+
+    /* We picked up this case above and had opened the link's properties */
+    if (wanted & APR_FINFO_LINK)
+        finfo->valid |= APR_FINFO_LINK;
+
+    return rv;
 }
 
-ap_status_t ap_getfileinfo(ap_finfo_t *finfo, ap_file_t *thefile)
+static apr_status_t guess_protection_bits(apr_finfo_t *finfo,
+                                          apr_int32_t wanted)
 {
-    /* TODO: 
-     * Windows should call GetFileInformationByHandle(), which is similar 
-     * to fstat(), for the best performance. Then we would need to map the 
-     * BY_HANDLE_FILE_INFORMATION to ap_finfo_t. 
+    /* Read, write execute for owner.  In the Win9x environment, any
+     * readable file is executable (well, not entirely 100% true, but
+     * still looking for some cheap logic that would help us here.)
+     * The same holds on NT if a file doesn't have a DACL (e.g., on FAT)
      */
-    struct stat info;
-    int rv = stat(thefile->fname, &info);
-
-    if (rv == 0) {
-        finfo->protection = info.st_mode;
-        finfo->filetype = filetype_from_mode(info.st_mode);
-        finfo->user = info.st_uid;
-        finfo->group = info.st_gid;
-        finfo->size = info.st_size;
-        finfo->inode = info.st_ino;
-        ap_ansi_time_to_ap_time(&finfo->atime, info.st_atime);
-        ap_ansi_time_to_ap_time(&finfo->mtime, info.st_mtime);
-        ap_ansi_time_to_ap_time(&finfo->ctime, info.st_ctime);
-        return APR_SUCCESS;
+    if (finfo->protection & APR_FREADONLY) {
+        finfo->protection |= APR_FPROT_WREAD | APR_FPROT_WEXECUTE;
     }
     else {
-        return errno;
+        finfo->protection |= APR_FPROT_WREAD | APR_FPROT_WEXECUTE | APR_FPROT_WWRITE;
     }
+    finfo->protection |= (finfo->protection << prot_scope_group)
+                       | (finfo->protection << prot_scope_user);
+
+    finfo->valid |= APR_FINFO_UPROT | APR_FINFO_GPROT | APR_FINFO_WPROT;
+
+    return ((wanted & ~finfo->valid) ? APR_INCOMPLETE : APR_SUCCESS);
 }
-ap_status_t ap_stat(ap_finfo_t *finfo, const char *fname, ap_pool_t *cont)
+
+apr_status_t more_finfo(apr_finfo_t *finfo, const void *ufile, 
+                        apr_int32_t wanted, int whatfile)
 {
-    /* WIN32_FILE_ATTRIBUTE_DATA is an exact subset of the first 
-     * entries of WIN32_FIND_DATA
-     */
-    WIN32_FIND_DATA FileInformation;
-    HANDLE hFind;
-    ap_oslevel_e os_level;
-    ap_status_t rv = APR_SUCCESS;
+    PSID user = NULL, grp = NULL;
+    PACL dacl = NULL;
+    apr_status_t rv;
+
+    if (apr_os_level < APR_WIN_NT)
+        return guess_protection_bits(finfo, wanted);
+
+    if (wanted & (APR_FINFO_PROT | APR_FINFO_OWNER))
+    {
+        /* On NT this request is incredibly expensive, but accurate.
+         * Since the WinNT-only functions below are protected by the
+         * (apr_os_level < APR_WIN_NT) case above, we need no extra
+         * tests, but remember GetNamedSecurityInfo & GetSecurityInfo
+         * are not supported on 9x.
+         */
+        SECURITY_INFORMATION sinf = 0;
+        PSECURITY_DESCRIPTOR pdesc = NULL;
+        if (wanted & (APR_FINFO_USER | APR_FINFO_UPROT))
+            sinf |= OWNER_SECURITY_INFORMATION;
+        if (wanted & (APR_FINFO_GROUP | APR_FINFO_GPROT))
+            sinf |= GROUP_SECURITY_INFORMATION;
+        if (wanted & APR_FINFO_PROT)
+            sinf |= DACL_SECURITY_INFORMATION;
+        if (whatfile == MORE_OF_WFSPEC) {
+            apr_wchar_t *wfile = (apr_wchar_t*) ufile;
+            int fix = 0;
+            if (wcsncmp(wfile, L"\\\\?\\", 4) == 0) {
+                fix = 4;
+                if (wcsncmp(wfile + fix, L"UNC\\", 4) == 0)
+                    wfile[6] = L'\\', fix = 6;
+            }
+            rv = GetNamedSecurityInfoW(wfile + fix, 
+                                 SE_FILE_OBJECT, sinf,
+                                 ((wanted & (APR_FINFO_USER | APR_FINFO_UPROT)) ? &user : NULL),
+                                 ((wanted & (APR_FINFO_GROUP | APR_FINFO_GPROT)) ? &grp : NULL),
+                                 ((wanted & APR_FINFO_PROT) ? &dacl : NULL),
+                                 NULL, &pdesc);
+            if (fix == 6)
+                wfile[6] = L'C';
+        }
+        else if (whatfile == MORE_OF_FSPEC)
+            rv = GetNamedSecurityInfoA((char*)ufile, 
+                                 SE_FILE_OBJECT, sinf,
+                                 ((wanted & (APR_FINFO_USER | APR_FINFO_UPROT)) ? &user : NULL),
+                                 ((wanted & (APR_FINFO_GROUP | APR_FINFO_GPROT)) ? &grp : NULL),
+                                 ((wanted & APR_FINFO_PROT) ? &dacl : NULL),
+                                 NULL, &pdesc);
+        else if (whatfile == MORE_OF_HANDLE)
+            rv = GetSecurityInfo((HANDLE)ufile, 
+                                 SE_FILE_OBJECT, sinf,
+                                 ((wanted & (APR_FINFO_USER | APR_FINFO_UPROT)) ? &user : NULL),
+                                 ((wanted & (APR_FINFO_GROUP | APR_FINFO_GPROT)) ? &grp : NULL),
+                                 ((wanted & APR_FINFO_PROT) ? &dacl : NULL),
+                                 NULL, &pdesc);
+        else
+            return APR_INCOMPLETE; /* should not occur */
+        if (rv == ERROR_SUCCESS)
+            apr_pool_cleanup_register(finfo->pool, pdesc, free_localheap, 
+                                 apr_pool_cleanup_null);
+        else
+            user = grp = dacl = NULL;
+
+        if (user) {
+            finfo->user = user;
+            finfo->valid |= APR_FINFO_USER;
+        }
+
+        if (grp) {
+            finfo->group = grp;
+            finfo->valid |= APR_FINFO_GROUP;
+        }
 
-    memset(finfo,'\0', sizeof(*finfo));
+        if (dacl) {
+            /* Retrieved the discresionary access list */
+            resolve_prot(finfo, wanted, dacl);
+        }
+        else if (wanted & APR_FINFO_PROT)
+            guess_protection_bits(finfo, wanted);
+    }
 
-    if (!ap_get_oslevel(cont, &os_level) && os_level >= APR_WIN_98) {
-        if (!GetFileAttributesEx(fname, GetFileExInfoStandard, 
-                                 (WIN32_FILE_ATTRIBUTE_DATA*) &FileInformation)) {
-            rv = GetLastError();
+    if ((apr_os_level >= APR_WIN_2000) && (wanted & APR_FINFO_CSIZE)
+                                       && (finfo->filetype == APR_REG))
+    {
+        DWORD sizelo, sizehi;
+        if (whatfile == MORE_OF_HANDLE) {
+            /* Not available for development and implementation under
+             * a reasonable license; if you review the licensing
+             * terms and conditions of;
+             *   http://go.microsoft.com/fwlink/?linkid=84083
+             * you probably understand why APR chooses not to implement.
+             */
+            IOSB sb;
+            FSI fi;
+            if ((ZwQueryInformationFile((HANDLE)ufile, &sb, 
+                                       &fi, sizeof(fi), 5) == 0) 
+                    && (sb.Status == 0)) {
+                finfo->csize = fi.AllocationSize;
+                finfo->valid |= APR_FINFO_CSIZE;
+            }
+        }
+        else {
+            SetLastError(NO_ERROR);
+            if (whatfile == MORE_OF_WFSPEC)
+                sizelo = GetCompressedFileSizeW((apr_wchar_t*)ufile, &sizehi);
+            else if (whatfile == MORE_OF_FSPEC)
+                sizelo = GetCompressedFileSizeA((char*)ufile, &sizehi);
+            else
+                return APR_EGENERAL; /* should not occur */
+        
+            if (sizelo != INVALID_FILE_SIZE || GetLastError() == NO_ERROR) {
+#if APR_HAS_LARGE_FILES
+                finfo->csize =  (apr_off_t)sizelo
+                             | ((apr_off_t)sizehi << 32);
+#else
+                finfo->csize = (apr_off_t)sizelo;
+                if (finfo->csize < 0 || sizehi)
+                    finfo->csize = 0x7fffffff;
+#endif
+                finfo->valid |= APR_FINFO_CSIZE;
+            }
         }
     }
+    return ((wanted & ~finfo->valid) ? APR_INCOMPLETE : APR_SUCCESS);
+}
+
+
+/* This generic fillin depends upon byhandle to be passed as 0 when
+ * a WIN32_FILE_ATTRIBUTE_DATA or either WIN32_FIND_DATA [A or W] is
+ * passed for wininfo.  When the BY_HANDLE_FILE_INFORMATION structure
+ * is passed for wininfo, byhandle is passed as 1 to offset the one
+ * dword discrepancy in offset of the High/Low size structure members.
+ *
+ * The generic fillin returns 1 if the caller should further inquire
+ * if this is a CHR filetype.  If it's reasonably certain it can't be,
+ * then the function returns 0.
+ */
+int fillin_fileinfo(apr_finfo_t *finfo, 
+                    WIN32_FILE_ATTRIBUTE_DATA *wininfo, 
+                    int byhandle, apr_int32_t wanted) 
+{
+    DWORD *sizes = &wininfo->nFileSizeHigh + byhandle;
+    int warn = 0;
+
+    memset(finfo, '\0', sizeof(*finfo));
+
+    FileTimeToAprTime(&finfo->atime, &wininfo->ftLastAccessTime);
+    FileTimeToAprTime(&finfo->ctime, &wininfo->ftCreationTime);
+    FileTimeToAprTime(&finfo->mtime, &wininfo->ftLastWriteTime);
+
+#if APR_HAS_LARGE_FILES
+    finfo->size =  (apr_off_t)sizes[1]
+                | ((apr_off_t)sizes[0] << 32);
+#else
+    finfo->size = (apr_off_t)sizes[1];
+    if (finfo->size < 0 || sizes[0])
+        finfo->size = 0x7fffffff;
+#endif
+
+    if (wanted & APR_FINFO_LINK &&
+        wininfo->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
+        finfo->filetype = APR_LNK;
+    }
+    else if (wininfo->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+        finfo->filetype = APR_DIR;
+    }
+    else if (wininfo->dwFileAttributes & FILE_ATTRIBUTE_DEVICE) {
+        /* Warning: This test only succeeds on Win9x, on NT these files
+         * (con, aux, nul, lpt#, com# etc) escape early detection!
+         */
+        finfo->filetype = APR_CHR;
+    }
     else {
-        /*  The question remains, can we assume fname is not a wildcard?
-         *  Must we test it?
+        /* Warning: Short of opening the handle to the file, the 'FileType'
+         * appears to be unknowable (in any trustworthy or consistent sense)
+         * on WinNT/2K as far as PIPE, CHR, etc are concerned.
+         */
+        if (!wininfo->ftLastWriteTime.dwLowDateTime 
+                && !wininfo->ftLastWriteTime.dwHighDateTime 
+                && !finfo->size)
+            warn = 1;
+        finfo->filetype = APR_REG;
+    }
+
+    /* The following flags are [for this moment] private to Win32.
+     * That's the only excuse for not toggling valid bits to reflect them.
+     */
+    if (wininfo->dwFileAttributes & FILE_ATTRIBUTE_READONLY)
+        finfo->protection = APR_FREADONLY;
+    
+    finfo->valid = APR_FINFO_ATIME | APR_FINFO_CTIME | APR_FINFO_MTIME
+                 | APR_FINFO_SIZE  | APR_FINFO_TYPE;   /* == APR_FINFO_MIN */
+
+    /* Only byhandle optionally tests link targets, so tell that caller
+     * what it wants to hear, otherwise the byattributes is never
+     * reporting anything but the link.
+     */
+    if (!byhandle || (wanted & APR_FINFO_LINK))
+        finfo->valid |= APR_FINFO_LINK;
+    return warn;
+}
+
+
+APR_DECLARE(apr_status_t) apr_file_info_get(apr_finfo_t *finfo, apr_int32_t wanted,
+                                            apr_file_t *thefile)
+{
+    BY_HANDLE_FILE_INFORMATION FileInfo;
+
+    if (thefile->buffered) {
+        /* XXX: flush here is not mutex protected */
+        apr_status_t rv = apr_file_flush(thefile);
+        if (rv != APR_SUCCESS)
+            return rv;
+    }
+
+    /* GetFileInformationByHandle() is implemented via two syscalls:
+     * QueryInformationVolume and QueryAllInformationFile. Use cheaper
+     * GetFileSizeEx() API if we only need to get the file size. */
+    if (wanted == APR_FINFO_SIZE) {
+       LARGE_INTEGER size;
+
+       if (!GetFileSizeEx(thefile->filehand, &size)) {
+          return apr_get_os_error();
+       }
+
+       finfo->pool = thefile->pool;
+       finfo->fname = thefile->fname;
+       finfo->size = size.QuadPart;
+       finfo->valid = APR_FINFO_SIZE;
+
+       return APR_SUCCESS;
+    }
+
+    if (!GetFileInformationByHandle(thefile->filehand, &FileInfo)) {
+        return apr_get_os_error();
+    }
+
+    fillin_fileinfo(finfo, (WIN32_FILE_ATTRIBUTE_DATA *) &FileInfo, 1, wanted);
+
+    if (finfo->filetype == APR_REG)
+    {
+        /* Go the extra mile to be -certain- that we have a real, regular
+         * file, since the attribute bits aren't a certain thing.  Even
+         * though fillin should have hinted if we *must* do this, we
+         * don't need to take chances while the handle is already open.
          */
-        hFind = FindFirstFile(fname, &FileInformation);
-        if (hFind == INVALID_HANDLE_VALUE) {
-            rv = GetLastError();
-    	} else {
+        DWORD FileType;
+        if ((FileType = GetFileType(thefile->filehand))) {
+            if (FileType == FILE_TYPE_CHAR) {
+                finfo->filetype = APR_CHR;
+            }
+            else if (FileType == FILE_TYPE_PIPE) {
+                finfo->filetype = APR_PIPE;
+            }
+            /* Otherwise leave the original conclusion alone 
+             */
+        }
+    }
+
+    finfo->pool = thefile->pool;
+
+    /* ### The finfo lifetime may exceed the lifetime of thefile->pool
+     * but finfo's aren't managed in pools, so where on earth would
+     * we pstrdup the fname into???
+     */
+    finfo->fname = thefile->fname;
+ 
+    /* Extra goodies known only by GetFileInformationByHandle() */
+    finfo->inode  =  (apr_ino_t)FileInfo.nFileIndexLow
+                  | ((apr_ino_t)FileInfo.nFileIndexHigh << 32);
+    finfo->device = FileInfo.dwVolumeSerialNumber;
+    finfo->nlink  = FileInfo.nNumberOfLinks;
+
+    finfo->valid |= APR_FINFO_IDENT | APR_FINFO_NLINK;
+
+    /* If we still want something more (besides the name) go get it! 
+     */
+    if ((wanted &= ~finfo->valid) & ~APR_FINFO_NAME) {
+        return more_finfo(finfo, thefile->filehand, wanted, MORE_OF_HANDLE);
+    }
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_file_perms_set(const char *fname,
+                                           apr_fileperms_t perms)
+{
+    return APR_ENOTIMPL;
+}
+
+APR_DECLARE(apr_status_t) apr_stat(apr_finfo_t *finfo, const char *fname,
+                                   apr_int32_t wanted, apr_pool_t *pool)
+{
+    /* XXX: is constant - needs testing - which requires a lighter-weight root test fn */
+    int isroot = 0;
+    apr_status_t ident_rv = 0;
+    apr_status_t rv;
+#if APR_HAS_UNICODE_FS
+    apr_wchar_t wfname[APR_PATH_MAX];
+
+#endif
+    char *filename = NULL;
+    /* These all share a common subset of this structure */
+    union {
+        WIN32_FIND_DATAW w;
+        WIN32_FIND_DATAA n;
+        WIN32_FILE_ATTRIBUTE_DATA i;
+    } FileInfo;
+    
+    /* Catch fname length == MAX_PATH since GetFileAttributesEx fails 
+     * with PATH_NOT_FOUND.  We would rather indicate length error than 
+     * 'not found'
+     */        
+    if (strlen(fname) >= APR_PATH_MAX) {
+        return APR_ENAMETOOLONG;
+    }
+
+#if APR_HAS_UNICODE_FS
+    IF_WIN_OS_IS_UNICODE
+    {
+        if ((wanted & (APR_FINFO_IDENT | APR_FINFO_NLINK)) 
+               || (~wanted & APR_FINFO_LINK)) {
+            /* FindFirstFile and GetFileAttributesEx can't figure the inode,
+             * device or number of links, so we need to resolve with an open 
+             * file handle.  If the user has asked for these fields, fall over 
+             * to the get file info by handle method.  If we fail, or the user
+             * also asks for the file name, continue by our usual means.
+             *
+             * We also must use this method for a 'true' stat, that resolves
+             * a symlink (NTFS Junction) target.  This is because all fileinfo
+             * on a Junction always returns the junction, opening the target
+             * is the only way to resolve the target's attributes.
+             */
+            if ((ident_rv = resolve_ident(finfo, fname, wanted, pool)) 
+                    == APR_SUCCESS)
+                return ident_rv;
+            else if (ident_rv == APR_INCOMPLETE)
+                wanted &= ~finfo->valid;
+        }
+
+        if ((rv = utf8_to_unicode_path(wfname, sizeof(wfname) 
+                                            / sizeof(apr_wchar_t), fname)))
+            return rv;
+        if (!(wanted & APR_FINFO_NAME)) {
+            if (!GetFileAttributesExW(wfname, GetFileExInfoStandard, 
+                                      &FileInfo.i))
+                return apr_get_os_error();
+        }
+        else {
+            /* Guard against bogus wildcards and retrieve by name
+             * since we want the true name, and set aside a long
+             * enough string to handle the longest file name.
+             */
+            char tmpname[APR_FILE_MAX * 3 + 1];
+            HANDLE hFind;
+            if ((rv = test_safe_name(fname)) != APR_SUCCESS) {
+                return rv;
+            }
+            hFind = FindFirstFileW(wfname, &FileInfo.w);
+            if (hFind == INVALID_HANDLE_VALUE)
+                return apr_get_os_error();
             FindClose(hFind);
+            if (unicode_to_utf8_path(tmpname, sizeof(tmpname), 
+                                     FileInfo.w.cFileName)) {
+                return APR_ENAMETOOLONG;
+            }
+            filename = apr_pstrdup(pool, tmpname);
         }
     }
+#endif
+#if APR_HAS_ANSI_FS
+    ELSE_WIN_OS_IS_ANSI
+    {
+        const char *root = NULL;
+        const char *test = fname;
+        rv = apr_filepath_root(&root, &test, APR_FILEPATH_NATIVE, pool);
+        isroot = (root && *root && !(*test));
 
-    if (rv != APR_SUCCESS) {
-        /* a little ad-hoc canonicalization to the most common
-         * error conditions
-         */
-        if (rv == ERROR_FILE_NOT_FOUND || rv == ERROR_PATH_NOT_FOUND)
-            return APR_ENOENT;
-       return rv;
+        if ((apr_os_level >= APR_WIN_98) && (!(wanted & APR_FINFO_NAME) || isroot))
+        {
+            /* cannot use FindFile on a Win98 root, it returns \*
+             * GetFileAttributesExA is not available on Win95
+             */
+            if (!GetFileAttributesExA(fname, GetFileExInfoStandard, 
+                                     &FileInfo.i)) {
+                return apr_get_os_error();
+            }
+        }
+        else if (isroot) {
+            /* This is Win95 and we are trying to stat a root.  Lie.
+             */
+            if (GetDriveType(fname) != DRIVE_UNKNOWN) 
+            {
+                finfo->pool = pool;
+                finfo->filetype = 0;
+                finfo->mtime = apr_time_now();
+                finfo->protection |= APR_FPROT_WREAD | APR_FPROT_WEXECUTE | APR_FPROT_WWRITE;
+                finfo->protection |= (finfo->protection << prot_scope_group) 
+                                   | (finfo->protection << prot_scope_user);
+                finfo->valid |= APR_FINFO_TYPE | APR_FINFO_PROT 
+                              | APR_FINFO_MTIME
+                              | (wanted & APR_FINFO_LINK);
+                return (wanted &= ~finfo->valid) ? APR_INCOMPLETE 
+                                                 : APR_SUCCESS;
+            }
+            else
+                return APR_FROM_OS_ERROR(ERROR_PATH_NOT_FOUND);
+        }
+        else  {
+            /* Guard against bogus wildcards and retrieve by name
+             * since we want the true name, or are stuck in Win95,
+             * or are looking for the root of a Win98 drive.
+             */
+            HANDLE hFind;
+            if ((rv = test_safe_name(fname)) != APR_SUCCESS) {
+                return rv;
+            }
+            hFind = FindFirstFileA(fname, &FileInfo.n);
+            if (hFind == INVALID_HANDLE_VALUE) {
+                return apr_get_os_error();
+    	    } 
+            FindClose(hFind);
+            filename = apr_pstrdup(pool, FileInfo.n.cFileName);
+        }
     }
+#endif
 
-    /* Filetype - Directory or file? */
-    if (FileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
-        finfo->protection |= S_IFDIR;
-        finfo->filetype = APR_DIR;
+    if (ident_rv != APR_INCOMPLETE) {
+        if (fillin_fileinfo(finfo, (WIN32_FILE_ATTRIBUTE_DATA *) &FileInfo, 
+                            0, wanted))
+        {
+            /* Go the extra mile to assure we have a file.  WinNT/2000 seems
+             * to reliably translate char devices to the path '\\.\device'
+             * so go ask for the full path.
+             */
+            if (apr_os_level >= APR_WIN_NT)
+            {
+#if APR_HAS_UNICODE_FS
+                apr_wchar_t tmpname[APR_FILE_MAX];
+                apr_wchar_t *tmpoff = NULL;
+                if (GetFullPathNameW(wfname, sizeof(tmpname) / sizeof(apr_wchar_t),
+                                     tmpname, &tmpoff))
+                {
+                    if (!wcsncmp(tmpname, L"\\\\.\\", 4)) {
+#else
+                /* Same initial logic as above, but
+                 * only for WinNT/non-UTF-8 builds of APR:
+                 */
+                char tmpname[APR_FILE_MAX];
+                char *tmpoff;
+                if (GetFullPathName(fname, sizeof(tmpname), tmpname, &tmpoff))
+                {
+                    if (!strncmp(tmpname, "\\\\.\\", 4)) {
+#endif
+                        if (tmpoff == tmpname + 4) {
+                            finfo->filetype = APR_CHR;
+                        }
+                        /* For WHATEVER reason, CHR devices such as \\.\con 
+                         * or \\.\lpt1 *may*not* update tmpoff; in fact the
+                         * resulting tmpoff is set to NULL.  Guard against 
+                         * either case.
+                         *
+                         * This code is identical for wide and narrow chars...
+                         */
+                        else if (!tmpoff) {
+                            tmpoff = tmpname + 4;
+                            while (*tmpoff) {
+                                if (*tmpoff == '\\' || *tmpoff == '/') {
+                                    break;
+                                }
+                                ++tmpoff;
+                            }
+                            if (!*tmpoff) {
+                                finfo->filetype = APR_CHR;
+                            }
+                        }
+                    }
+                }
+                else {
+                    finfo->valid &= ~APR_FINFO_TYPE;
+                }
+
+            }
+            else {
+                finfo->valid &= ~APR_FINFO_TYPE;
+            }
+        }
+        finfo->pool = pool;
     }
-    else {
-        finfo->protection |= S_IFREG;
-        finfo->filetype = APR_REG;
+
+    if (filename && !isroot) {
+        finfo->name = filename;
+        finfo->valid |= APR_FINFO_NAME;
     }
-    /* Read, write execute for owner */
-    if (FileInformation.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
-        finfo->protection |= S_IREAD;
+
+    if (wanted &= ~finfo->valid) {
+        /* Caller wants more than APR_FINFO_MIN | APR_FINFO_NAME */
+#if APR_HAS_UNICODE_FS
+        if (apr_os_level >= APR_WIN_NT)
+            return more_finfo(finfo, wfname, wanted, MORE_OF_WFSPEC);
+#endif
+        return more_finfo(finfo, fname, wanted, MORE_OF_FSPEC);
     }
-    else {
-        finfo->protection |= S_IREAD;
-        finfo->protection |= S_IWRITE;
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_file_attrs_set(const char *fname,
+                                             apr_fileattrs_t attributes,
+                                             apr_fileattrs_t attr_mask,
+                                             apr_pool_t *pool)
+{
+    DWORD flags;
+    apr_status_t rv;
+#if APR_HAS_UNICODE_FS
+    apr_wchar_t wfname[APR_PATH_MAX];
+#endif
+
+    /* Don't do anything if we can't handle the requested attributes */
+    if (!(attr_mask & (APR_FILE_ATTR_READONLY
+                       | APR_FILE_ATTR_HIDDEN)))
+        return APR_SUCCESS;
+
+#if APR_HAS_UNICODE_FS
+    IF_WIN_OS_IS_UNICODE
+    {
+        if ((rv = utf8_to_unicode_path(wfname,
+                                       sizeof(wfname) / sizeof(wfname[0]),
+                                       fname)))
+            return rv;
+        flags = GetFileAttributesW(wfname);
+    }
+#endif
+#if APR_HAS_ANSI_FS
+    ELSE_WIN_OS_IS_ANSI
+    {
+        flags = GetFileAttributesA(fname);
+    }
+#endif
+
+    if (flags == 0xFFFFFFFF)
+        return apr_get_os_error();
+
+    if (attr_mask & APR_FILE_ATTR_READONLY)
+    {
+        if (attributes & APR_FILE_ATTR_READONLY)
+            flags |= FILE_ATTRIBUTE_READONLY;
+        else
+            flags &= ~FILE_ATTRIBUTE_READONLY;
+    }
+
+    if (attr_mask & APR_FILE_ATTR_HIDDEN)
+    {
+        if (attributes & APR_FILE_ATTR_HIDDEN)
+            flags |= FILE_ATTRIBUTE_HIDDEN;
+        else
+            flags &= ~FILE_ATTRIBUTE_HIDDEN;
+    }
+
+#if APR_HAS_UNICODE_FS
+    IF_WIN_OS_IS_UNICODE
+    {
+        rv = SetFileAttributesW(wfname, flags);
     }
-    /* Is this an executable? Guess based on the file extension. */
-    if (is_exe(fname, cont)) {
-        finfo->protection |= S_IEXEC;
+#endif
+#if APR_HAS_ANSI_FS
+    ELSE_WIN_OS_IS_ANSI
+    {
+        rv = SetFileAttributesA(fname, flags);
     }
-    /* File times */
-    FileTimeToAprTime(&finfo->atime, &FileInformation.ftLastAccessTime);
-    FileTimeToAprTime(&finfo->ctime, &FileInformation.ftCreationTime);
-    FileTimeToAprTime(&finfo->mtime, &FileInformation.ftLastWriteTime);
+#endif
 
-    /* File size 
-     * Note: This cannot handle files greater than can be held by an int */
-    finfo->size = FileInformation.nFileSizeLow;
+    if (rv == 0)
+        return apr_get_os_error();
 
     return APR_SUCCESS;
 }
 
+
+APR_DECLARE(apr_status_t) apr_file_mtime_set(const char *fname,
+                                             apr_time_t mtime,
+                                             apr_pool_t *pool)
+{
+    apr_file_t *thefile;
+    apr_status_t rv;
+
+    rv = apr_file_open(&thefile, fname,
+                       APR_FOPEN_READ | APR_WRITEATTRS,
+                       APR_FPROT_OS_DEFAULT, pool);
+    if (!rv)
+    {
+        FILETIME file_ctime;
+        FILETIME file_atime;
+        FILETIME file_mtime;
+
+        if (!GetFileTime(thefile->filehand,
+                         &file_ctime, &file_atime, &file_mtime))
+            rv = apr_get_os_error();
+        else
+        {
+            AprTimeToFileTime(&file_mtime, mtime);
+            if (!SetFileTime(thefile->filehand,
+                             &file_ctime, &file_atime, &file_mtime))
+                rv = apr_get_os_error();
+        }
+
+        apr_file_close(thefile);
+    }
+
+    return rv;
+}
diff --git a/file_io/win32/filesys.c b/file_io/win32/filesys.c
new file mode 100644
index 00000000000..e812139551a
--- /dev/null
+++ b/file_io/win32/filesys.c
@@ -0,0 +1,229 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_arch_file_io.h"
+#include "apr_strings.h"
+
+/* Win32 Exceptions:
+ *
+ * Note that trailing spaces and trailing periods are never recorded
+ * in the file system, except by a very obscure bug where any file
+ * that is created with a trailing space or period, followed by the 
+ * ':' stream designator on an NTFS volume can never be accessed again.
+ * In other words, don't ever accept them when designating a stream!
+ *
+ * An interesting side effect is that two or three periods are both 
+ * treated as the parent directory, although the fourth and on are
+ * not [strongly suggest all trailing periods are trimmed off, or
+ * down to two if there are no other characters.]
+ *
+ * Leading spaces and periods are accepted, however.
+ * The * ? < > codes all have wildcard side effects
+ * The " / \ : are exclusively component separator tokens 
+ * The system doesn't accept | for any (known) purpose 
+ * Oddly, \x7f _is_ acceptable ;)
+ */
+
+/* apr_c_is_fnchar[] maps Win32's file name and shell escape symbols
+ *
+ *   element & 1 == valid file name character [excluding delimiters]
+ *   element & 2 == character should be shell (caret) escaped from cmd.exe
+ *
+ * this must be in-sync with Apache httpd's gen_test_char.c for cgi escaping.
+ */
+
+const char apr_c_is_fnchar[256] =
+{/* Reject all ctrl codes... Escape \n and \r (ascii 10 and 13)      */
+    0,0,0,0,0,0,0,0,0,0,2,0,0,2,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ /*   ! " # $ % & ' ( ) * + , - . /  0 1 2 3 4 5 6 7 8 9 : ; < = > ? */
+    1,1,2,1,3,3,3,3,3,3,2,1,1,1,1,0, 1,1,1,1,1,1,1,1,1,1,0,3,2,1,2,2,
+ /* @ A B C D E F G H I J K L M N O  P Q R S T U V W X Y Z [ \ ] ^ _ */
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,3,2,3,3,1,
+ /* ` a b c d e f g h i j k l m n o  p q r s t u v w x y z { | } ~   */
+    3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,3,2,3,3,1,
+ /* High bit codes are accepted (subject to utf-8->Unicode xlation)  */
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
+};
+
+
+apr_status_t filepath_root_test(char *path, apr_pool_t *p)
+{
+    apr_status_t rv;
+#if APR_HAS_UNICODE_FS
+    if (apr_os_level >= APR_WIN_NT)
+    {
+        apr_wchar_t wpath[APR_PATH_MAX];
+        if ((rv = utf8_to_unicode_path(wpath, sizeof(wpath) 
+                                            / sizeof(apr_wchar_t), path)))
+            return rv;
+        rv = GetDriveTypeW(wpath);
+    }
+    else
+#endif
+        rv = GetDriveType(path);
+
+    if (rv == DRIVE_UNKNOWN || rv == DRIVE_NO_ROOT_DIR)
+        return APR_EBADPATH;
+    return APR_SUCCESS;
+}
+
+
+apr_status_t filepath_drive_get(char **rootpath, char drive, 
+                                apr_int32_t flags, apr_pool_t *p)
+{
+    char path[APR_PATH_MAX];
+#if APR_HAS_UNICODE_FS
+    IF_WIN_OS_IS_UNICODE
+    {
+        apr_wchar_t *ignored;
+        apr_wchar_t wdrive[8];
+        apr_wchar_t wpath[APR_PATH_MAX];
+        apr_status_t rv;
+        /* ???: This needs review, apparently "\\?\d:." returns "\\?\d:" 
+         * as if that is useful for anything.
+         */
+        wcscpy(wdrive, L"D:.");
+        wdrive[0] = (apr_wchar_t)(unsigned char)drive;
+        if (!GetFullPathNameW(wdrive, sizeof(wpath) / sizeof(apr_wchar_t), wpath, &ignored))
+            return apr_get_os_error();
+        if ((rv = unicode_to_utf8_path(path, sizeof(path), wpath)))
+            return rv;
+    }
+#endif
+#if APR_HAS_ANSI_FS
+    ELSE_WIN_OS_IS_ANSI
+    {
+        char *ignored;
+        char drivestr[4];
+        drivestr[0] = drive;
+        drivestr[1] = ':';
+        drivestr[2] = '.';;
+        drivestr[3] = '\0';
+        if (!GetFullPathName(drivestr, sizeof(path), path, &ignored))
+            return apr_get_os_error();
+    }
+#endif
+    if (!(flags & APR_FILEPATH_NATIVE)) {
+        for (*rootpath = path; **rootpath; ++*rootpath) {
+            if (**rootpath == '\\')
+                **rootpath = '/';
+        }
+    }
+    *rootpath = apr_pstrdup(p, path);
+    return APR_SUCCESS;
+}
+
+
+apr_status_t filepath_root_case(char **rootpath, char *root, apr_pool_t *p)
+{
+#if APR_HAS_UNICODE_FS
+    IF_WIN_OS_IS_UNICODE
+    {
+        apr_wchar_t *ignored;
+        apr_wchar_t wpath[APR_PATH_MAX];
+        apr_status_t rv;
+        apr_wchar_t wroot[APR_PATH_MAX];
+        /* ???: This needs review, apparently "\\?\d:." returns "\\?\d:" 
+         * as if that is useful for anything.
+         */
+        if ((rv = utf8_to_unicode_path(wroot, sizeof(wroot) 
+                                            / sizeof(apr_wchar_t), root)))
+            return rv;
+        if (!GetFullPathNameW(wroot, sizeof(wpath) / sizeof(apr_wchar_t), wpath, &ignored))
+            return apr_get_os_error();
+
+        /* Borrow wroot as a char buffer (twice as big as necessary) 
+         */
+        if ((rv = unicode_to_utf8_path((char*)wroot, sizeof(wroot), wpath)))
+            return rv;
+        *rootpath = apr_pstrdup(p, (char*)wroot);
+    }
+#endif
+#if APR_HAS_ANSI_FS
+    ELSE_WIN_OS_IS_ANSI
+    {
+        char path[APR_PATH_MAX];
+        char *ignored;
+        if (!GetFullPathName(root, sizeof(path), path, &ignored))
+            return apr_get_os_error();
+        *rootpath = apr_pstrdup(p, path);
+    }
+#endif
+    return APR_SUCCESS;
+}
+
+
+APR_DECLARE(apr_status_t) apr_filepath_get(char **rootpath, apr_int32_t flags,
+                                           apr_pool_t *p)
+{
+    char path[APR_PATH_MAX];
+#if APR_HAS_UNICODE_FS
+    IF_WIN_OS_IS_UNICODE
+    {
+        apr_wchar_t wpath[APR_PATH_MAX];
+        apr_status_t rv;
+        if (!GetCurrentDirectoryW(sizeof(wpath) / sizeof(apr_wchar_t), wpath))
+            return apr_get_os_error();
+        if ((rv = unicode_to_utf8_path(path, sizeof(path), wpath)))
+            return rv;
+    }
+#endif
+#if APR_HAS_ANSI_FS
+    ELSE_WIN_OS_IS_ANSI
+    {
+        if (!GetCurrentDirectory(sizeof(path), path))
+            return apr_get_os_error();
+    }
+#endif
+    if (!(flags & APR_FILEPATH_NATIVE)) {
+        for (*rootpath = path; **rootpath; ++*rootpath) {
+            if (**rootpath == '\\')
+                **rootpath = '/';
+        }
+    }
+    *rootpath = apr_pstrdup(p, path);
+    return APR_SUCCESS;
+}
+
+
+APR_DECLARE(apr_status_t) apr_filepath_set(const char *rootpath,
+                                           apr_pool_t *p)
+{
+#if APR_HAS_UNICODE_FS
+    IF_WIN_OS_IS_UNICODE
+    {
+        apr_wchar_t wpath[APR_PATH_MAX];
+        apr_status_t rv;
+        if ((rv = utf8_to_unicode_path(wpath, sizeof(wpath) 
+                                            / sizeof(apr_wchar_t), rootpath)))
+            return rv;
+        if (!SetCurrentDirectoryW(wpath))
+            return apr_get_os_error();
+    }
+#endif
+#if APR_HAS_ANSI_FS
+    ELSE_WIN_OS_IS_ANSI
+    {
+        if (!SetCurrentDirectory(rootpath))
+            return apr_get_os_error();
+    }
+#endif
+    return APR_SUCCESS;
+}
diff --git a/file_io/win32/flock.c b/file_io/win32/flock.c
new file mode 100644
index 00000000000..e08e08a7a40
--- /dev/null
+++ b/file_io/win32/flock.c
@@ -0,0 +1,86 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_arch_file_io.h"
+
+APR_DECLARE(apr_status_t) apr_file_lock(apr_file_t *thefile, int type)
+{
+#ifdef _WIN32_WCE
+    /* The File locking is unsuported on WCE */
+    return APR_ENOTIMPL;
+#else
+    const DWORD len = 0xffffffff;
+    DWORD flags; 
+
+    flags = ((type & APR_FLOCK_NONBLOCK) ? LOCKFILE_FAIL_IMMEDIATELY : 0)
+          + (((type & APR_FLOCK_TYPEMASK) == APR_FLOCK_SHARED) 
+                                       ? 0 : LOCKFILE_EXCLUSIVE_LOCK);
+    if (apr_os_level >= APR_WIN_NT) {
+        /* Syntax is correct, len is passed for LengthLow and LengthHigh*/
+        OVERLAPPED offset;
+        memset (&offset, 0, sizeof(offset));
+        if (!LockFileEx(thefile->filehand, flags, 0, len, len, &offset))
+            return apr_get_os_error();
+    }
+    else {
+        /* On Win9x, LockFile() never blocks.  Hack in a crufty poll.
+         *
+         * Note that this hack exposes threads to being unserviced forever,
+         * in the situation that the given lock has low availability.
+         * When implemented in the kernel, LockFile will typically use
+         * FIFO or round robin distribution to ensure all threads get 
+         * one crack at the lock; but in this case we can't emulate that.
+         *
+         * However Win9x are barely maintainable anyways, if the user does
+         * choose to build to them, this is the best we can do.
+         */
+        while (!LockFile(thefile->filehand, 0, 0, len, 0)) {
+            DWORD err = GetLastError();
+            if ((err == ERROR_LOCK_VIOLATION) && !(type & APR_FLOCK_NONBLOCK))
+            {
+                Sleep(500); /* pause for a half second */
+                continue;   /* ... and then poll again */
+            }
+            return APR_FROM_OS_ERROR(err);
+        }
+    }
+
+    return APR_SUCCESS;
+#endif /* !defined(_WIN32_WCE) */
+}
+
+APR_DECLARE(apr_status_t) apr_file_unlock(apr_file_t *thefile)
+{
+#ifdef _WIN32_WCE
+    return APR_ENOTIMPL;
+#else
+    DWORD len = 0xffffffff;
+
+    if (apr_os_level >= APR_WIN_NT) {
+        /* Syntax is correct, len is passed for LengthLow and LengthHigh*/
+        OVERLAPPED offset;
+        memset (&offset, 0, sizeof(offset));
+        if (!UnlockFileEx(thefile->filehand, 0, len, len, &offset))
+            return apr_get_os_error();
+    }
+    else {
+        if (!UnlockFile(thefile->filehand, 0, 0, len, 0))
+            return apr_get_os_error();
+    }
+
+    return APR_SUCCESS;
+#endif /* !defined(_WIN32_WCE) */
+}
diff --git a/file_io/win32/open.c b/file_io/win32/open.c
index df08302f861..b6c01432e81 100644
--- a/file_io/win32/open.c
+++ b/file_io/win32/open.c
@@ -1,124 +1,362 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
 #include "apr_private.h"
-#include "fileio.h"
+#include "apr_arch_file_io.h"
 #include "apr_file_io.h"
 #include "apr_general.h"
-#include "apr_lib.h"
+#include "apr_strings.h"
 #include "apr_portable.h"
+#include "apr_thread_mutex.h"
+#if APR_HAVE_ERRNO_H
 #include <errno.h>
+#endif
 #include <winbase.h>
 #include <string.h>
+#ifdef HAVE_SYS_STAT_H
 #include <sys/stat.h>
-#include "misc.h"
+#endif
+#include "apr_arch_misc.h"
+#include "apr_arch_inherit.h"
+#include <io.h>
+#include <winioctl.h>
+
+#if APR_HAS_UNICODE_FS
+apr_status_t utf8_to_unicode_path(apr_wchar_t* retstr, apr_size_t retlen, 
+                                  const char* srcstr)
+{
+    /* TODO: The computations could preconvert the string to determine
+     * the true size of the retstr, but that's a memory over speed
+     * tradeoff that isn't appropriate this early in development.
+     *
+     * Allocate the maximum string length based on leading 4 
+     * characters of \\?\ (allowing nearly unlimited path lengths) 
+     * plus the trailing null, then transform /'s into \\'s since
+     * the \\?\ form doesn't allow '/' path seperators.
+     *
+     * Note that the \\?\ form only works for local drive paths, and
+     * \\?\UNC\ is needed UNC paths.
+     */
+    apr_size_t srcremains = strlen(srcstr) + 1;
+    apr_wchar_t *t = retstr;
+    apr_status_t rv;
+
+    /* This is correct, we don't twist the filename if it is will
+     * definitely be shorter than 248 characters.  It merits some 
+     * performance testing to see if this has any effect, but there
+     * seem to be applications that get confused by the resulting
+     * Unicode \\?\ style file names, especially if they use argv[0]
+     * or call the Win32 API functions such as GetModuleName, etc.
+     * Not every application is prepared to handle such names.
+     * 
+     * Note also this is shorter than MAX_PATH, as directory paths 
+     * are actually limited to 248 characters. 
+     *
+     * Note that a utf-8 name can never result in more wide chars
+     * than the original number of utf-8 narrow chars.
+     */
+    if (srcremains > 248) {
+        if (srcstr[1] == ':' && (srcstr[2] == '/' || srcstr[2] == '\\')) {
+            wcscpy (retstr, L"\\\\?\\");
+            retlen -= 4;
+            t += 4;
+        }
+        else if ((srcstr[0] == '/' || srcstr[0] == '\\')
+              && (srcstr[1] == '/' || srcstr[1] == '\\')
+              && (srcstr[2] != '?')) {
+            /* Skip the slashes */
+            srcstr += 2;
+            srcremains -= 2;
+            wcscpy (retstr, L"\\\\?\\UNC\\");
+            retlen -= 8;
+            t += 8;
+        }
+    }
+
+    if ((rv = apr_conv_utf8_to_ucs2(srcstr, &srcremains, t, &retlen))) {
+        return (rv == APR_INCOMPLETE) ? APR_EINVAL : rv;
+    }
+    if (srcremains) {
+        return APR_ENAMETOOLONG;
+    }
+    for (; *t; ++t)
+        if (*t == L'/')
+            *t = L'\\';
+    return APR_SUCCESS;
+}
 
-ap_status_t file_cleanup(void *thefile)
+apr_status_t unicode_to_utf8_path(char* retstr, apr_size_t retlen,
+                                  const apr_wchar_t* srcstr)
 {
-    ap_file_t *file = thefile;
-    if (!CloseHandle(file->filehand)) {
-        return GetLastError();
+    /* Skip the leading 4 characters if the path begins \\?\, or substitute
+     * // for the \\?\UNC\ path prefix, allocating the maximum string
+     * length based on the remaining string, plus the trailing null.
+     * then transform \\'s back into /'s since the \\?\ form never
+     * allows '/' path seperators, and APR always uses '/'s.
+     */
+    apr_size_t srcremains = wcslen(srcstr) + 1;
+    apr_status_t rv;
+    char *t = retstr;
+    if (srcstr[0] == L'\\' && srcstr[1] == L'\\' && 
+        srcstr[2] == L'?'  && srcstr[3] == L'\\') {
+        if (srcstr[4] == L'U' && srcstr[5] == L'N' && 
+            srcstr[6] == L'C' && srcstr[7] == L'\\') {
+            srcremains -= 8;
+            srcstr += 8;
+            retstr[0] = '\\';
+            retstr[1] = '\\';
+            retlen -= 2;
+            t += 2;
+        }
+        else {
+            srcremains -= 4;
+            srcstr += 4;
+        }
+    }
+        
+    if ((rv = apr_conv_ucs2_to_utf8(srcstr, &srcremains, t, &retlen))) {
+        return rv;
+    }
+    if (srcremains) {
+        return APR_ENAMETOOLONG;
     }
-    file->filehand = INVALID_HANDLE_VALUE;
     return APR_SUCCESS;
 }
+#endif
 
-ap_status_t ap_open(ap_file_t **dafile, const char *fname, 
-                    ap_int32_t flag, ap_fileperms_t perm, ap_pool_t *cont)
+void *res_name_from_filename(const char *file, int global, apr_pool_t *pool)
 {
+#if APR_HAS_UNICODE_FS
+    IF_WIN_OS_IS_UNICODE
+    {
+        apr_wchar_t *wpre, *wfile, *ch;
+        apr_size_t n = strlen(file) + 1;
+        apr_size_t r, d;
+
+        if (apr_os_level >= APR_WIN_2000) {
+            if (global)
+                wpre = L"Global\\";
+            else
+                wpre = L"Local\\";
+        }
+        else
+            wpre = L"";
+        r = wcslen(wpre);
+
+        if (n > 256 - r) {
+            file += n - 256 - r;
+            n = 256;
+            /* skip utf8 continuation bytes */
+            while ((*file & 0xC0) == 0x80) {
+                ++file;
+                --n;
+            }
+        }
+        wfile = apr_palloc(pool, (r + n) * sizeof(apr_wchar_t));
+        wcscpy(wfile, wpre);
+        d = n;
+        if (apr_conv_utf8_to_ucs2(file, &n, wfile + r, &d)) {
+            return NULL;
+        }
+        for (ch = wfile + r; *ch; ++ch) {
+            if (*ch == ':' || *ch == '/' || *ch == '\\')
+                *ch = '_';
+        }
+        return wfile;
+    }
+#endif
+#if APR_HAS_ANSI_FS
+    ELSE_WIN_OS_IS_ANSI
+    {
+        char *nfile, *ch;
+        apr_size_t n = strlen(file) + 1;
+
+#if !APR_HAS_UNICODE_FS
+        apr_size_t r, d;
+        char *pre;
+
+        if (apr_os_level >= APR_WIN_2000) {
+            if (global)
+                pre = "Global\\";
+            else
+                pre = "Local\\";
+        }
+        else
+            pre = "";
+        r = strlen(pre);
+
+        if (n > 256 - r) {
+            file += n - 256 - r;
+            n = 256;
+        }
+        nfile = apr_palloc(pool, (r + n) * sizeof(apr_wchar_t));
+        memcpy(nfile, pre, r);
+        memcpy(nfile + r, file, n);
+#else
+        const apr_size_t r = 0;
+        if (n > 256) {
+            file += n - 256;
+            n = 256;
+        }
+        nfile = apr_pmemdup(pool, file, n);
+#endif
+        for (ch = nfile + r; *ch; ++ch) {
+            if (*ch == ':' || *ch == '/' || *ch == '\\')
+                *ch = '_';
+        }
+        return nfile;
+    }
+#endif
+}
+
+#if APR_HAS_UNICODE_FS
+static apr_status_t make_sparse_file(apr_file_t *file)
+{
+    BY_HANDLE_FILE_INFORMATION info;
+    apr_status_t rv;
+    DWORD bytesread = 0;
+    DWORD res;
+
+    /* test */
+
+    if (GetFileInformationByHandle(file->filehand, &info)
+            && (info.dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE))
+        return APR_SUCCESS;
+
+    if (file->pOverlapped) {
+        file->pOverlapped->Offset     = 0;
+        file->pOverlapped->OffsetHigh = 0;
+    }
+
+    if (DeviceIoControl(file->filehand, FSCTL_SET_SPARSE, NULL, 0, NULL, 0,
+                        &bytesread, file->pOverlapped)) {
+        rv = APR_SUCCESS;
+    }
+    else 
+    {
+        rv = apr_get_os_error();
+
+        if (rv == APR_FROM_OS_ERROR(ERROR_IO_PENDING))
+        {
+            do {
+                res = WaitForSingleObject(file->pOverlapped->hEvent, 
+                                          (file->timeout > 0)
+                                            ? (DWORD)(file->timeout/1000)
+                                            : ((file->timeout == -1) 
+                                                 ? INFINITE : 0));
+            } while (res == WAIT_ABANDONED);
+
+            if (res != WAIT_OBJECT_0) {
+                CancelIo(file->filehand);
+            }
+
+            if (GetOverlappedResult(file->filehand, file->pOverlapped, 
+                                    &bytesread, TRUE))
+                rv = APR_SUCCESS;
+            else
+                rv = apr_get_os_error();
+        }
+    }
+    return rv;
+}
+#endif
+
+apr_status_t file_cleanup(void *thefile)
+{
+    apr_file_t *file = thefile;
+    apr_status_t flush_rv = APR_SUCCESS;
+
+    if (file->filehand != INVALID_HANDLE_VALUE) {
+
+        if (file->buffered) {
+            /* XXX: flush here is not mutex protected */
+            flush_rv = apr_file_flush((apr_file_t *)thefile);
+        }
+
+        /* In order to avoid later segfaults with handle 'reuse',
+         * we must protect against the case that a dup2'ed handle
+         * is being closed, and invalidate the corresponding StdHandle 
+         * We also tell msvcrt when stdhandles are closed.
+         */
+        if (file->flags & APR_STD_FLAGS)
+        {
+            if ((file->flags & APR_STD_FLAGS) == APR_STDERR_FLAG) {
+                _close(2);
+                SetStdHandle(STD_ERROR_HANDLE, INVALID_HANDLE_VALUE);
+            }
+            else if ((file->flags & APR_STD_FLAGS) == APR_STDOUT_FLAG) {
+                _close(1);
+                SetStdHandle(STD_OUTPUT_HANDLE, INVALID_HANDLE_VALUE);
+            }
+            else if ((file->flags & APR_STD_FLAGS) == APR_STDIN_FLAG) {
+                _close(0);
+                SetStdHandle(STD_INPUT_HANDLE, INVALID_HANDLE_VALUE);
+            }
+        }
+        else
+            CloseHandle(file->filehand);
+
+        file->filehand = INVALID_HANDLE_VALUE;
+    }
+    if (file->pOverlapped && file->pOverlapped->hEvent) {
+        CloseHandle(file->pOverlapped->hEvent);
+        file->pOverlapped = NULL;
+    }
+    return flush_rv;
+}
+
+APR_DECLARE(apr_status_t) apr_file_open(apr_file_t **new, const char *fname,
+                                   apr_int32_t flag, apr_fileperms_t perm,
+                                   apr_pool_t *pool)
+{
+    HANDLE handle = INVALID_HANDLE_VALUE;
     DWORD oflags = 0;
     DWORD createflags = 0;
     DWORD attributes = 0;
     DWORD sharemode = FILE_SHARE_READ | FILE_SHARE_WRITE;
-    ap_oslevel_e level;
-
-    (*dafile) = (ap_file_t *)ap_pcalloc(cont, sizeof(ap_file_t));
+    apr_status_t rv;
 
-    (*dafile)->cntxt = cont;
-
-    if (flag & APR_READ) {
+    if (flag & APR_FOPEN_NONBLOCK) {
+        return APR_ENOTIMPL;
+    }
+    if (flag & APR_FOPEN_READ) {
         oflags |= GENERIC_READ;
     }
-    if (flag & APR_WRITE) {
+    if (flag & APR_FOPEN_WRITE) {
         oflags |= GENERIC_WRITE;
     }
-    if (!(flag & APR_READ) && !(flag & APR_WRITE)) {
-        (*dafile)->filehand = INVALID_HANDLE_VALUE;
-        return APR_EACCES;
+    if (flag & APR_WRITEATTRS) {
+        oflags |= FILE_WRITE_ATTRIBUTES;
     }
 
-    (*dafile)->fname = ap_pstrdup(cont, fname);
-
-    (*dafile)->demonfname = canonical_filename((*dafile)->cntxt, fname);
-    (*dafile)->lowerdemonfname = strlwr((*dafile)->demonfname);
- 
-    if (ap_get_oslevel(cont, &level) == APR_SUCCESS && level >= APR_WIN_NT) {
+    if (apr_os_level >= APR_WIN_NT) 
         sharemode |= FILE_SHARE_DELETE;
-    }
 
-    if (flag & APR_CREATE) {
-        if (flag & APR_EXCL) {
+    if (flag & APR_FOPEN_CREATE) {
+        if (flag & APR_FOPEN_EXCL) {
             /* only create new if file does not already exist */
             createflags = CREATE_NEW;
-        } else if (flag & APR_TRUNCATE) {
+        } else if (flag & APR_FOPEN_TRUNCATE) {
             /* truncate existing file or create new */
             createflags = CREATE_ALWAYS;
         } else {
             /* open existing but create if necessary */
             createflags = OPEN_ALWAYS;
         }
-    } else if (flag & APR_TRUNCATE) {
+    } else if (flag & APR_FOPEN_TRUNCATE) {
         /* only truncate if file already exists */
         createflags = TRUNCATE_EXISTING;
     } else {
@@ -126,85 +364,309 @@ ap_status_t ap_open(ap_file_t **dafile, const char *fname,
         createflags = OPEN_EXISTING;
     }
 
-    if ((flag & APR_EXCL) && !(flag & APR_CREATE)) {
-        (*dafile)->filehand = INVALID_HANDLE_VALUE;
+    if ((flag & APR_FOPEN_EXCL) && !(flag & APR_FOPEN_CREATE)) {
         return APR_EACCES;
     }   
+    
+    if (flag & APR_FOPEN_DELONCLOSE) {
+        attributes |= FILE_FLAG_DELETE_ON_CLOSE;
+    }
 
-    if (flag & APR_APPEND) {
-        (*dafile)->append = 1;
+    if (flag & APR_OPENLINK) {
+       attributes |= FILE_FLAG_OPEN_REPARSE_POINT;
     }
-    else {
-        (*dafile)->append = 0;
+
+    /* Without READ or WRITE, we fail unless apr called apr_file_open
+     * internally with the private APR_OPENINFO flag.
+     *
+     * With the APR_OPENINFO flag on NT, use the option flag
+     * FILE_FLAG_BACKUP_SEMANTICS to allow us to open directories.
+     * See the static resolve_ident() fn in file_io/win32/filestat.c
+     */
+    if (!(flag & (APR_FOPEN_READ | APR_FOPEN_WRITE))) {
+        if (flag & APR_OPENINFO) {
+            if (apr_os_level >= APR_WIN_NT) {
+                attributes |= FILE_FLAG_BACKUP_SEMANTICS;
+            }
+        }
+        else {
+            return APR_EACCES;
+        }
+        if (flag & APR_READCONTROL)
+            oflags |= READ_CONTROL;
     }
 
-    attributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN;
-    if (flag & APR_DELONCLOSE) {
-        attributes |= FILE_FLAG_DELETE_ON_CLOSE;
+    if (flag & APR_FOPEN_XTHREAD) {
+        /* This win32 specific feature is required 
+         * to allow multiple threads to work with the file.
+         */
+        attributes |= FILE_FLAG_OVERLAPPED;
+    }
+
+#if APR_HAS_UNICODE_FS
+    IF_WIN_OS_IS_UNICODE
+    {
+        apr_wchar_t wfname[APR_PATH_MAX];
+
+        if (flag & APR_FOPEN_SENDFILE_ENABLED) {
+            /* This feature is required to enable sendfile operations
+             * against the file on Win32. Also implies APR_FOPEN_XTHREAD.
+             */
+            flag |= APR_FOPEN_XTHREAD;
+            attributes |= FILE_FLAG_SEQUENTIAL_SCAN | FILE_FLAG_OVERLAPPED;
+        }
+
+        if ((rv = utf8_to_unicode_path(wfname, sizeof(wfname) 
+                                             / sizeof(apr_wchar_t), fname)))
+            return rv;
+        handle = CreateFileW(wfname, oflags, sharemode,
+                             NULL, createflags, attributes, 0);
+    }
+#endif
+#if APR_HAS_ANSI_FS
+    ELSE_WIN_OS_IS_ANSI {
+        handle = CreateFileA(fname, oflags, sharemode,
+                             NULL, createflags, attributes, 0);
+        /* This feature is not supported on this platform. */
+        flag &= ~APR_FOPEN_SENDFILE_ENABLED;
+    }
+#endif
+    if (handle == INVALID_HANDLE_VALUE) {
+        return apr_get_os_error();
     }
 
-    (*dafile)->filehand = CreateFile(fname, oflags, sharemode,
-                                     NULL, createflags, attributes, 0);
+    (*new) = (apr_file_t *)apr_pcalloc(pool, sizeof(apr_file_t));
+    (*new)->pool = pool;
+    (*new)->filehand = handle;
+    (*new)->fname = apr_pstrdup(pool, fname);
+    (*new)->flags = flag;
+    (*new)->timeout = -1;
+    (*new)->ungetchar = -1;
 
-    if ((*dafile)->filehand == INVALID_HANDLE_VALUE) {
-        return GetLastError();
+    if (flag & APR_FOPEN_APPEND) {
+        (*new)->append = 1;
+    }
+    if (flag & APR_FOPEN_BUFFERED) {
+        (*new)->buffered = 1;
+        (*new)->buffer = apr_palloc(pool, APR_FILE_DEFAULT_BUFSIZE);
+        (*new)->bufsize = APR_FILE_DEFAULT_BUFSIZE;
     }
-    if (flag & APR_APPEND) {
-        SetFilePointer((*dafile)->filehand, 0, NULL, FILE_END);
+    /* Need the mutex to share an apr_file_t across multiple threads */
+    if (flag & APR_FOPEN_XTHREAD) {
+        rv = apr_thread_mutex_create(&(*new)->mutex, 
+                                     APR_THREAD_MUTEX_DEFAULT, pool);
+        if (rv) {
+            if (file_cleanup(*new) == APR_SUCCESS) {
+                apr_pool_cleanup_kill(pool, *new, file_cleanup);
+            }
+            return rv;
+        }
     }
 
-    (*dafile)->eof_hit = 0;
-    ap_register_cleanup((*dafile)->cntxt, (void *)(*dafile), file_cleanup,
-                        ap_null_cleanup);
+#if APR_HAS_UNICODE_FS
+    if ((apr_os_level >= APR_WIN_2000) && ((*new)->flags & APR_FOPEN_SPARSE)) {
+        if ((rv = make_sparse_file(*new)) != APR_SUCCESS)
+            /* The great mystery; do we close the file and return an error?
+             * Do we add a new APR_INCOMPLETE style error saying opened, but
+             * NOTSPARSE?  For now let's simply mark the file as not-sparse.
+             */
+            (*new)->flags &= ~APR_FOPEN_SPARSE;
+    }
+    else
+#endif
+        /* This feature is not supported on this platform. */
+        (*new)->flags &= ~APR_FOPEN_SPARSE;
+
+#if APR_FILES_AS_SOCKETS
+    /* Create a pollset with room for one descriptor. */
+    /* ### check return codes */
+    (void) apr_pollset_create(&(*new)->pollset, 1, pool, 0);
+#endif
+    if (!(flag & APR_FOPEN_NOCLEANUP)) {
+        apr_pool_cleanup_register((*new)->pool, (void *)(*new), file_cleanup,
+                                  apr_pool_cleanup_null);
+    }
     return APR_SUCCESS;
 }
 
-ap_status_t ap_close(ap_file_t *file)
+APR_DECLARE(apr_status_t) apr_file_close(apr_file_t *file)
 {
-    ap_status_t stat;
+    apr_status_t stat;
     if ((stat = file_cleanup(file)) == APR_SUCCESS) {
-        ap_kill_cleanup(file->cntxt, file, file_cleanup);
+        apr_pool_cleanup_kill(file->pool, file, file_cleanup);
+
+        if (file->mutex) {
+            apr_thread_mutex_destroy(file->mutex);
+        }
+
         return APR_SUCCESS;
     }
     return stat;
 }
 
-ap_status_t ap_remove_file(char *path, ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_file_remove(const char *path, apr_pool_t *pool)
 {
-    char *temp = canonical_filename(cont, path);
-
-    if (DeleteFile(temp)) {
-        return APR_SUCCESS;
+#if APR_HAS_UNICODE_FS
+    IF_WIN_OS_IS_UNICODE
+    {
+        apr_wchar_t wpath[APR_PATH_MAX];
+        apr_status_t rv;
+        if ((rv = utf8_to_unicode_path(wpath, sizeof(wpath) 
+                                            / sizeof(apr_wchar_t), path))) {
+            return rv;
+        }
+        if (DeleteFileW(wpath))
+            return APR_SUCCESS;
     }
-    else {
-        return APR_EEXIST;
+#endif
+#if APR_HAS_ANSI_FS
+    ELSE_WIN_OS_IS_ANSI
+        if (DeleteFile(path))
+            return APR_SUCCESS;
+#endif
+    return apr_get_os_error();
+}
+
+APR_DECLARE(apr_status_t) apr_file_rename(const char *frompath,
+                                          const char *topath,
+                                          apr_pool_t *pool)
+{
+    IF_WIN_OS_IS_UNICODE
+    {
+#if APR_HAS_UNICODE_FS
+        apr_wchar_t wfrompath[APR_PATH_MAX], wtopath[APR_PATH_MAX];
+        apr_status_t rv;
+        if ((rv = utf8_to_unicode_path(wfrompath,
+                                       sizeof(wfrompath) / sizeof(apr_wchar_t),
+                                       frompath))) {
+            return rv;
+        }
+        if ((rv = utf8_to_unicode_path(wtopath,
+                                       sizeof(wtopath) / sizeof(apr_wchar_t),
+                                       topath))) {
+            return rv;
+        }
+#ifndef _WIN32_WCE
+        if (MoveFileExW(wfrompath, wtopath, MOVEFILE_REPLACE_EXISTING |
+                                            MOVEFILE_COPY_ALLOWED))
+#else
+        if (MoveFileW(wfrompath, wtopath))
+#endif
+            return APR_SUCCESS;
+#else
+        if (MoveFileEx(frompath, topath, MOVEFILE_REPLACE_EXISTING |
+                                         MOVEFILE_COPY_ALLOWED))
+            return APR_SUCCESS;
+#endif
     }
+#if APR_HAS_ANSI_FS
+    ELSE_WIN_OS_IS_ANSI
+    {
+        /* Windows 95 and 98 do not support MoveFileEx, so we'll use
+         * the old MoveFile function.  However, MoveFile requires that
+         * the new file not already exist...so we have to delete that
+         * file if it does.  Perhaps we should back up the to-be-deleted
+         * file in case something happens?
+         */
+        HANDLE handle = INVALID_HANDLE_VALUE;
+
+        if ((handle = CreateFile(topath, GENERIC_WRITE, 0, 0,  
+            OPEN_EXISTING, 0, 0 )) != INVALID_HANDLE_VALUE )
+        {
+            CloseHandle(handle);
+            if (!DeleteFile(topath))
+                return apr_get_os_error();
+        }
+        if (MoveFile(frompath, topath))
+            return APR_SUCCESS;
+    }        
+#endif
+    return apr_get_os_error();
 }
 
-ap_status_t ap_get_os_file(ap_os_file_t *thefile, ap_file_t *file)
+APR_DECLARE(apr_status_t) apr_file_link(const char *from_path, 
+                                           const char *to_path)
 {
-    if (file == NULL) {
-        return APR_ENOFILE;
+    apr_status_t rv = APR_SUCCESS;
+
+#if APR_HAS_UNICODE_FS
+    IF_WIN_OS_IS_UNICODE
+    {
+        apr_wchar_t wfrom_path[APR_PATH_MAX];
+        apr_wchar_t wto_path[APR_PATH_MAX];
+
+        if ((rv = utf8_to_unicode_path(wfrom_path,
+                                       sizeof(wfrom_path) / sizeof(apr_wchar_t),
+                                       from_path)))
+            return rv;
+        if ((rv = utf8_to_unicode_path(wto_path,
+                                       sizeof(wto_path) / sizeof(apr_wchar_t),
+                                       to_path)))
+            return rv;
+
+        if (!CreateHardLinkW(wto_path, wfrom_path, NULL))
+                return apr_get_os_error();
+    }
+#endif
+#if APR_HAS_ANSI_FS
+    ELSE_WIN_OS_IS_ANSI {
+        if (!CreateHardLinkA(to_path, from_path, NULL))
+                return apr_get_os_error();
     }
+#endif
+    return rv;
+}
+
+APR_DECLARE(apr_status_t) apr_os_file_get(apr_os_file_t *thefile,
+                                          apr_file_t *file)
+{
     *thefile = file->filehand;
     return APR_SUCCESS;
 }
 
-ap_status_t ap_put_os_file(ap_file_t **file, ap_os_file_t *thefile, 
-                           ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_os_file_put(apr_file_t **file,
+                                          apr_os_file_t *thefile,
+                                          apr_int32_t flags,
+                                          apr_pool_t *pool)
 {
-    if ((*file) == NULL) {
-        if (cont == NULL) {
-            return APR_ENOPOOL;
+    (*file) = apr_pcalloc(pool, sizeof(apr_file_t));
+    (*file)->pool = pool;
+    (*file)->filehand = *thefile;
+    (*file)->ungetchar = -1; /* no char avail */
+    (*file)->timeout = -1;
+    (*file)->flags = flags;
+
+    if (flags & APR_FOPEN_APPEND) {
+        (*file)->append = 1;
+    }
+    if (flags & APR_FOPEN_BUFFERED) {
+        (*file)->buffered = 1;
+        (*file)->buffer = apr_palloc(pool, APR_FILE_DEFAULT_BUFSIZE);
+        (*file)->bufsize = APR_FILE_DEFAULT_BUFSIZE;
+    }
+    if (flags & APR_FOPEN_XTHREAD) {
+        apr_status_t rv;
+        rv = apr_thread_mutex_create(&(*file)->mutex, 
+                                     APR_THREAD_MUTEX_DEFAULT, pool);
+        if (rv) {
+            return rv;
         }
-        (*file) = (ap_file_t *)ap_pcalloc(cont, sizeof(ap_file_t));
-        (*file)->cntxt = cont;
     }
-    (*file)->filehand = *thefile;
+
+#if APR_FILES_AS_SOCKETS
+    /* Create a pollset with room for one descriptor. */
+    /* ### check return codes */
+    (void) apr_pollset_create(&(*file)->pollset, 1, pool, 0);
+#endif
+    /* Should we be testing if thefile is a handle to 
+     * a PIPE and set up the mechanics appropriately?
+     *
+     *  (*file)->pipe;
+     */
     return APR_SUCCESS;
 }    
 
-ap_status_t ap_eof(ap_file_t *fptr)
+APR_DECLARE(apr_status_t) apr_file_eof(apr_file_t *fptr)
 {
     if (fptr->eof_hit == 1) {
         return APR_EOF;
@@ -212,19 +674,80 @@ ap_status_t ap_eof(ap_file_t *fptr)
     return APR_SUCCESS;
 }   
 
-ap_status_t ap_open_stderr(ap_file_t **thefile, ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_file_open_flags_stderr(apr_file_t **thefile, 
+                                                     apr_int32_t flags, 
+                                                     apr_pool_t *pool)
 {
-    (*thefile) = ap_pcalloc(cont, sizeof(ap_file_t));
-    if ((*thefile) == NULL) {
-        return APR_ENOMEM;
-    }
-    (*thefile)->filehand = GetStdHandle(STD_ERROR_HANDLE);
-    if ((*thefile)->filehand == INVALID_HANDLE_VALUE)
-        return GetLastError();
-    (*thefile)->cntxt = cont;
-    (*thefile)->fname = "STD_ERROR_HANDLE";
-    (*thefile)->eof_hit = 0;
+#ifdef _WIN32_WCE
+    return APR_ENOTIMPL;
+#else
+    apr_os_file_t file_handle;
 
-    return APR_SUCCESS;
+    apr_set_os_error(APR_SUCCESS);
+    file_handle = GetStdHandle(STD_ERROR_HANDLE);
+    if (!file_handle)
+        file_handle = INVALID_HANDLE_VALUE;
+
+    return apr_os_file_put(thefile, &file_handle,
+                           flags | APR_FOPEN_WRITE | APR_STDERR_FLAG, pool);
+#endif
 }
 
+APR_DECLARE(apr_status_t) apr_file_open_flags_stdout(apr_file_t **thefile, 
+                                                     apr_int32_t flags,
+                                                     apr_pool_t *pool)
+{
+#ifdef _WIN32_WCE
+    return APR_ENOTIMPL;
+#else
+    apr_os_file_t file_handle;
+
+    apr_set_os_error(APR_SUCCESS);
+    file_handle = GetStdHandle(STD_OUTPUT_HANDLE);
+    if (!file_handle)
+        file_handle = INVALID_HANDLE_VALUE;
+
+    return apr_os_file_put(thefile, &file_handle,
+                           flags | APR_FOPEN_WRITE | APR_STDOUT_FLAG, pool);
+#endif
+}
+
+APR_DECLARE(apr_status_t) apr_file_open_flags_stdin(apr_file_t **thefile, 
+                                                    apr_int32_t flags,
+                                                    apr_pool_t *pool)
+{
+#ifdef _WIN32_WCE
+    return APR_ENOTIMPL;
+#else
+    apr_os_file_t file_handle;
+
+    apr_set_os_error(APR_SUCCESS);
+    file_handle = GetStdHandle(STD_INPUT_HANDLE);
+    if (!file_handle)
+        file_handle = INVALID_HANDLE_VALUE;
+
+    return apr_os_file_put(thefile, &file_handle,
+                           flags | APR_FOPEN_READ | APR_STDIN_FLAG, pool);
+#endif
+}
+
+APR_DECLARE(apr_status_t) apr_file_open_stderr(apr_file_t **thefile, apr_pool_t *pool)
+{
+    return apr_file_open_flags_stderr(thefile, 0, pool);
+}
+
+APR_DECLARE(apr_status_t) apr_file_open_stdout(apr_file_t **thefile, apr_pool_t *pool)
+{
+    return apr_file_open_flags_stdout(thefile, 0, pool);
+}
+
+APR_DECLARE(apr_status_t) apr_file_open_stdin(apr_file_t **thefile, apr_pool_t *pool)
+{
+    return apr_file_open_flags_stdin(thefile, 0, pool);
+}
+
+APR_POOL_IMPLEMENT_ACCESSOR(file);
+
+APR_IMPLEMENT_INHERIT_SET(file, flags, pool, file_cleanup)
+ 
+APR_IMPLEMENT_INHERIT_UNSET(file, flags, pool, file_cleanup)
diff --git a/file_io/win32/pipe.c b/file_io/win32/pipe.c
index 1ab30ae0a18..6014582583d 100644
--- a/file_io/win32/pipe.c
+++ b/file_io/win32/pipe.c
@@ -1,117 +1,493 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "fileio.h"
+#include "apr_arch_file_io.h"
 #include "apr_file_io.h"
 #include "apr_general.h"
-#include "apr_lib.h"
+#include "apr_strings.h"
+#include "apr_escape.h"
+#if APR_HAVE_ERRNO_H
 #include <errno.h>
+#endif
 #include <string.h>
 #include <stdio.h>
+#if APR_HAVE_SYS_TYPES_H
 #include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
 #include <sys/stat.h>
-#include "misc.h"
+#endif
+#if APR_HAVE_PROCESS_H
+#include <process.h>            /* for getpid() on Win32 */
+#endif
+#include "apr_arch_misc.h"
 
-ap_status_t ap_set_pipe_timeout(ap_file_t *thepipe, ap_int32_t timeout)
+APR_DECLARE(apr_status_t) apr_file_pipe_timeout_set(apr_file_t *thepipe,
+                                            apr_interval_time_t timeout)
 {
-    DWORD dwMode;
-    ap_oslevel_e oslevel;
-
-    /* This code relies on the fact that anonymous pipes (which
-     * do not support nonblocking I/O) are really named pipes
-     * (which support nonblocking I/O) on Windows NT.
-     */
-    if (thepipe->pipe == 1) {
+    /* Always OK to unset timeouts */
+    if (timeout == -1) {
         thepipe->timeout = timeout;
-        if (ap_get_oslevel(thepipe->cntxt, &oslevel) == APR_SUCCESS &&
-            oslevel >= APR_WIN_NT) {
-            if (timeout == 0) {
-                dwMode = PIPE_NOWAIT;
-            } else {
-                dwMode = PIPE_WAIT;
-            }
-            SetNamedPipeHandleState(thepipe->filehand, &dwMode, NULL, NULL);
-        }
         return APR_SUCCESS;
     }
-    return APR_EINVAL;
+    if (!thepipe->pipe) {
+        return APR_ENOTIMPL;
+    }
+    if (timeout && !(thepipe->pOverlapped)) {
+        /* Cannot be nonzero if a pipe was opened blocking
+         */
+        return APR_EINVAL;
+    }
+    thepipe->timeout = timeout;
+    return APR_SUCCESS;
 }
 
-ap_status_t ap_create_pipe(ap_file_t **in, ap_file_t **out, ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_file_pipe_timeout_get(apr_file_t *thepipe,
+                                           apr_interval_time_t *timeout)
 {
+    /* Always OK to get the timeout (even if it's unset ... -1) */
+    *timeout = thepipe->timeout;
+    return APR_SUCCESS;
+}
+
+static apr_status_t file_pipe_create(apr_file_t **in,
+                                     apr_file_t **out,
+                                     apr_int32_t blocking,
+                                     apr_pool_t *pool_in,
+                                     apr_pool_t *pool_out)
+{
+#ifdef _WIN32_WCE
+    return APR_ENOTIMPL;
+#else
     SECURITY_ATTRIBUTES sa;
+    static unsigned long id = 0;
+    DWORD dwPipeMode;
+    DWORD dwOpenMode;
 
     sa.nLength = sizeof(sa);
-    sa.bInheritHandle = TRUE;
+
+#if APR_HAS_UNICODE_FS
+    IF_WIN_OS_IS_UNICODE
+        sa.bInheritHandle = FALSE;
+#endif
+#if APR_HAS_ANSI_FS
+    ELSE_WIN_OS_IS_ANSI
+        sa.bInheritHandle = TRUE;
+#endif
     sa.lpSecurityDescriptor = NULL;
 
-    (*in) = (ap_file_t *)ap_pcalloc(cont, sizeof(ap_file_t));
-    (*in)->cntxt = cont;
+    (*in) = (apr_file_t *)apr_pcalloc(pool_in, sizeof(apr_file_t));
+    (*in)->pool = pool_in;
+    (*in)->fname = NULL;
     (*in)->pipe = 1;
-    (*in)->fname = ap_pstrdup(cont, "PIPE");
     (*in)->timeout = -1;
     (*in)->ungetchar = -1;
-
-    (*out) = (ap_file_t *)ap_pcalloc(cont, sizeof(ap_file_t));
-    (*out)->cntxt = cont;
+    (*in)->eof_hit = 0;
+    (*in)->filePtr = 0;
+    (*in)->bufpos = 0;
+    (*in)->dataRead = 0;
+    (*in)->direction = 0;
+    (*in)->pOverlapped = NULL;
+#if APR_FILES_AS_SOCKETS
+    (void) apr_pollset_create(&(*in)->pollset, 1, p, 0);
+#endif
+    (*out) = (apr_file_t *)apr_pcalloc(pool_out, sizeof(apr_file_t));
+    (*out)->pool = pool_out;
+    (*out)->fname = NULL;
     (*out)->pipe = 1;
-    (*out)->fname = ap_pstrdup(cont, "PIPE");
     (*out)->timeout = -1;
+    (*out)->ungetchar = -1;
+    (*out)->eof_hit = 0;
+    (*out)->filePtr = 0;
+    (*out)->bufpos = 0;
+    (*out)->dataRead = 0;
+    (*out)->direction = 0;
+    (*out)->pOverlapped = NULL;
+#if APR_FILES_AS_SOCKETS
+    (void) apr_pollset_create(&(*out)->pollset, 1, p, 0);
+#endif
+    if (apr_os_level >= APR_WIN_NT) {
+        char rand[8];
+        int pid = getpid();
+#define FMT_PIPE_NAME "\\\\.\\pipe\\apr-pipe-%x.%lx."
+        /*                                    ^   ^ ^
+         *                                  pid   | |
+         *                                        | |
+         *                                       id |
+         *                                          |
+         *                        hex-escaped rand[8] (16 bytes)
+         */
+        char name[sizeof FMT_PIPE_NAME + 2 * sizeof(pid)
+                                       + 2 * sizeof(id)
+                                       + 2 * sizeof(rand)];
+        apr_size_t pos;
+
+        /* Create the read end of the pipe */
+        dwOpenMode = PIPE_ACCESS_INBOUND;
+#ifdef FILE_FLAG_FIRST_PIPE_INSTANCE
+        dwOpenMode |= FILE_FLAG_FIRST_PIPE_INSTANCE;
+#endif
+        if (blocking == APR_WRITE_BLOCK /* READ_NONBLOCK */
+               || blocking == APR_FULL_NONBLOCK) {
+            dwOpenMode |= FILE_FLAG_OVERLAPPED;
+            (*in)->pOverlapped =
+                    (OVERLAPPED*) apr_pcalloc((*in)->pool, sizeof(OVERLAPPED));
+            (*in)->pOverlapped->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+            (*in)->timeout = 0;
+        }
+        dwPipeMode = 0;
+
+        apr_generate_random_bytes(rand, sizeof rand);
+        pos = apr_snprintf(name, sizeof name, FMT_PIPE_NAME, pid, id++);
+        apr_escape_hex(name + pos, rand, sizeof rand, 0, NULL);
+
+        (*in)->filehand = CreateNamedPipe(name,
+                                          dwOpenMode,
+                                          dwPipeMode,
+                                          1,            /* nMaxInstances,   */
+                                          0,            /* nOutBufferSize,  */
+                                          65536,        /* nInBufferSize,   */
+                                          1,            /* nDefaultTimeOut, */
+                                          &sa);
+        if ((*in)->filehand == INVALID_HANDLE_VALUE) {
+            apr_status_t rv = apr_get_os_error();
+            file_cleanup(*in);
+            return rv;
+        }
 
-    if (!CreatePipe(&(*in)->filehand, &(*out)->filehand, &sa, 0)) {
-        return GetLastError();
+        /* Create the write end of the pipe */
+        dwOpenMode = FILE_ATTRIBUTE_NORMAL;
+        if (blocking == APR_READ_BLOCK /* WRITE_NONBLOCK */
+                || blocking == APR_FULL_NONBLOCK) {
+            dwOpenMode |= FILE_FLAG_OVERLAPPED;
+            (*out)->pOverlapped =
+                    (OVERLAPPED*) apr_pcalloc((*out)->pool, sizeof(OVERLAPPED));
+            (*out)->pOverlapped->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+            (*out)->timeout = 0;
+        }
+
+        (*out)->filehand = CreateFile(name,
+                                      GENERIC_WRITE,   /* access mode             */
+                                      0,               /* share mode              */
+                                      &sa,             /* Security attributes     */
+                                      OPEN_EXISTING,   /* dwCreationDisposition   */
+                                      dwOpenMode,      /* Pipe attributes         */
+                                      NULL);           /* handle to template file */
+        if ((*out)->filehand == INVALID_HANDLE_VALUE) {
+            apr_status_t rv = apr_get_os_error();
+            file_cleanup(*out);
+            file_cleanup(*in);
+            return rv;
+        }
+    }
+    else {
+        /* Pipes on Win9* are blocking. Live with it. */
+        if (!CreatePipe(&(*in)->filehand, &(*out)->filehand, &sa, 65536)) {
+            return apr_get_os_error();
+        }
     }
 
+    apr_pool_cleanup_register((*in)->pool, (void *)(*in), file_cleanup,
+                        apr_pool_cleanup_null);
+    apr_pool_cleanup_register((*out)->pool, (void *)(*out), file_cleanup,
+                        apr_pool_cleanup_null);
     return APR_SUCCESS;
+#endif /* _WIN32_WCE */
+}
+
+APR_DECLARE(apr_status_t) apr_file_pipe_create(apr_file_t **in,
+                                               apr_file_t **out,
+                                               apr_pool_t *pool)
+{
+    /* Default is full blocking pipes. */
+    return file_pipe_create(in, out, APR_FULL_BLOCK, pool, pool);
+}
+
+APR_DECLARE(apr_status_t) apr_file_pipe_create_ex(apr_file_t **in,
+                                                  apr_file_t **out,
+                                                  apr_int32_t blocking,
+                                                  apr_pool_t *pool)
+{
+    return file_pipe_create(in, out, blocking, pool, pool);
+}
+
+APR_DECLARE(apr_status_t) apr_file_pipe_create_pools(apr_file_t **in,
+                                                     apr_file_t **out,
+                                                     apr_int32_t blocking,
+                                                     apr_pool_t *pool_in,
+                                                     apr_pool_t *pool_out)
+{
+    return file_pipe_create(in, out, blocking, pool_in, pool_out);
+}
+
+APR_DECLARE(apr_status_t) apr_file_namedpipe_create(const char *filename,
+                                                    apr_fileperms_t perm,
+                                                    apr_pool_t *pool)
+{
+    /* Not yet implemented, interface not suitable.
+     * Win32 requires the named pipe to be *opened* at the time it's
+     * created, and to do so, blocking or non blocking must be elected.
+     */
+    return APR_ENOTIMPL;
+}
+
+
+/* XXX: Problem; we need to choose between blocking and nonblocking based
+ * on how *thefile was opened, and we don't have that information :-/
+ * Hack; assume a blocking socket, since the most common use for the fn
+ * would be to handle stdio-style or blocking pipes.  Win32 doesn't have
+ * select() blocking for pipes anyways :(
+ */
+APR_DECLARE(apr_status_t) apr_os_pipe_put_ex(apr_file_t **file,
+                                             apr_os_file_t *thefile,
+                                             int register_cleanup,
+                                             apr_pool_t *pool)
+{
+    (*file) = apr_pcalloc(pool, sizeof(apr_file_t));
+    (*file)->pool = pool;
+    (*file)->pipe = 1;
+    (*file)->timeout = -1;
+    (*file)->ungetchar = -1;
+    (*file)->filehand = *thefile;
+#if APR_FILES_AS_SOCKETS
+    (void) apr_pollset_create(&(*file)->pollset, 1, pool, 0);
+#endif
+    if (register_cleanup) {
+        apr_pool_cleanup_register(pool, *file, file_cleanup,
+                                  apr_pool_cleanup_null);
+    }
+
+    return APR_SUCCESS;
+}
+
+
+APR_DECLARE(apr_status_t) apr_os_pipe_put(apr_file_t **file,
+                                          apr_os_file_t *thefile,
+                                          apr_pool_t *pool)
+{
+    return apr_os_pipe_put_ex(file, thefile, 0, pool);
+}
+
+static apr_status_t create_socket_pipe(SOCKET *rd, SOCKET *wr)
+{
+    static int id = 0;
+    FD_SET rs;
+    SOCKET ls;
+    struct timeval socktm;
+    struct sockaddr_in pa;
+    struct sockaddr_in la;
+    struct sockaddr_in ca;
+    int nrd;
+    apr_status_t rv = APR_SUCCESS;
+    int ll = sizeof(la);
+    int lc = sizeof(ca);
+    unsigned long bm = 1;
+    int uid[2];
+    int iid[2];
+
+    *rd = INVALID_SOCKET;
+    *wr = INVALID_SOCKET;
+
+    /* Create the unique socket identifier
+     * so that we know the connection originated
+     * from us.
+     */
+    uid[0] = getpid();
+    uid[1] = id++;
+    if ((ls = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {
+        return apr_get_netos_error();
+    }
+
+    pa.sin_family = AF_INET;
+    pa.sin_port   = 0;
+    pa.sin_addr.s_addr = inet_addr("127.0.0.1");
+
+    if (bind(ls, (SOCKADDR *)&pa, sizeof(pa)) == SOCKET_ERROR) {
+        rv =  apr_get_netos_error();
+        goto cleanup;
+    }
+    if (getsockname(ls, (SOCKADDR *)&la, &ll) == SOCKET_ERROR) {
+        rv =  apr_get_netos_error();
+        goto cleanup;
+    }
+    if (listen(ls, 1) == SOCKET_ERROR) {
+        rv =  apr_get_netos_error();
+        goto cleanup;
+    }
+    if ((*wr = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {
+        rv = apr_get_netos_error();
+        goto cleanup;
+    }
+    if (connect(*wr, (SOCKADDR *)&la, sizeof(la)) == SOCKET_ERROR) {
+        rv =  apr_get_netos_error();
+        goto cleanup;
+    }
+    if (send(*wr, (char *)uid, sizeof(uid), 0) != sizeof(uid)) {
+        if ((rv =  apr_get_netos_error()) == 0) {
+            rv = APR_EINVAL;
+        }
+        goto cleanup;
+    }
+    if (ioctlsocket(ls, FIONBIO, &bm) == SOCKET_ERROR) {
+        rv = apr_get_netos_error();
+        goto cleanup;
+    }
+    for (;;) {
+        int ns;
+        int nc = 0;
+        /* Listening socket is nonblocking by now.
+         * The accept should create the socket
+         * immediatelly because we are connected already.
+         * However on buys systems this can take a while
+         * until winsock gets a chance to handle the events.
+         */
+        FD_ZERO(&rs);
+        FD_SET(ls, &rs);
+
+        socktm.tv_sec  = 1;
+        socktm.tv_usec = 0;
+        if ((ns = select(0, &rs, NULL, NULL, &socktm)) == SOCKET_ERROR) {
+            /* Accept still not signaled */
+            Sleep(100);
+            continue;
+        }
+        if (ns == 0) {
+            /* No connections in the last second */
+            continue;
+        }
+        if ((*rd = accept(ls, (SOCKADDR *)&ca, &lc)) == INVALID_SOCKET) {
+            rv =  apr_get_netos_error();
+            goto cleanup;
+        }
+        /* Verify the connection by reading the send identification.
+         */
+        do {
+            if (nc++)
+                Sleep(1);
+            nrd = recv(*rd, (char *)iid, sizeof(iid), 0);
+            rv = nrd == SOCKET_ERROR ? apr_get_netos_error() : APR_SUCCESS;
+        } while (APR_STATUS_IS_EAGAIN(rv));
+
+        if (nrd == sizeof(iid)) {
+            if (memcmp(uid, iid, sizeof(uid)) == 0) {
+                /* Wow, we recived what we send.
+                 * Put read side of the pipe to the blocking
+                 * mode and return.
+                 */
+                bm = 0;
+                if (ioctlsocket(*rd, FIONBIO, &bm) == SOCKET_ERROR) {
+                    rv = apr_get_netos_error();
+                    goto cleanup;
+                }
+                break;
+            }
+        }
+        else if (nrd == SOCKET_ERROR) {
+            goto cleanup;
+        }
+        closesocket(*rd);
+    }
+    /* We don't need the listening socket any more */
+    closesocket(ls);
+    return 0;
+
+cleanup:
+    /* Don't leak resources */
+    if (*rd != INVALID_SOCKET)
+        closesocket(*rd);
+    if (*wr != INVALID_SOCKET)
+        closesocket(*wr);
+
+    *rd = INVALID_SOCKET;
+    *wr = INVALID_SOCKET;
+    closesocket(ls);
+    return rv;
+}
+
+static apr_status_t socket_pipe_cleanup(void *thefile)
+{
+    apr_file_t *file = thefile;
+    if (file->filehand != INVALID_HANDLE_VALUE) {
+        shutdown((SOCKET)file->filehand, SD_BOTH);
+        closesocket((SOCKET)file->filehand);
+        file->filehand = INVALID_HANDLE_VALUE;
+    }
+    return APR_SUCCESS;
+}
+
+apr_status_t file_socket_pipe_create(apr_file_t **in,
+                                     apr_file_t **out,
+                                     apr_pool_t *p)
+{
+    apr_status_t rv;
+    SOCKET rd;
+    SOCKET wr;
+
+    if ((rv = create_socket_pipe(&rd, &wr)) != APR_SUCCESS) {
+        return rv;
+    }
+    (*in) = (apr_file_t *)apr_pcalloc(p, sizeof(apr_file_t));
+    (*in)->pool = p;
+    (*in)->fname = NULL;
+    (*in)->pipe = 1;
+    (*in)->timeout = -1;
+    (*in)->ungetchar = -1;
+    (*in)->eof_hit = 0;
+    (*in)->filePtr = 0;
+    (*in)->bufpos = 0;
+    (*in)->dataRead = 0;
+    (*in)->direction = 0;
+    (*in)->pOverlapped = (OVERLAPPED*)apr_pcalloc(p, sizeof(OVERLAPPED));
+    (*in)->filehand = (HANDLE)rd;
+
+    (*out) = (apr_file_t *)apr_pcalloc(p, sizeof(apr_file_t));
+    (*out)->pool = p;
+    (*out)->fname = NULL;
+    (*out)->pipe = 1;
+    (*out)->timeout = -1;
+    (*out)->ungetchar = -1;
+    (*out)->eof_hit = 0;
+    (*out)->filePtr = 0;
+    (*out)->bufpos = 0;
+    (*out)->dataRead = 0;
+    (*out)->direction = 0;
+    (*out)->pOverlapped = (OVERLAPPED*)apr_pcalloc(p, sizeof(OVERLAPPED));
+    (*out)->filehand = (HANDLE)wr;
+
+    apr_pool_cleanup_register(p, (void *)(*in), socket_pipe_cleanup,
+                              apr_pool_cleanup_null);
+    apr_pool_cleanup_register(p, (void *)(*out), socket_pipe_cleanup,
+                              apr_pool_cleanup_null);
+
+    return rv;
+}
+
+apr_status_t file_socket_pipe_close(apr_file_t *file)
+{
+    apr_status_t stat;
+    if (!file->pipe)
+        return apr_file_close(file);
+    if ((stat = socket_pipe_cleanup(file)) == APR_SUCCESS) {
+        apr_pool_cleanup_kill(file->pool, file, socket_pipe_cleanup);
+
+        if (file->mutex) {
+            apr_thread_mutex_destroy(file->mutex);
+        }
+
+        return APR_SUCCESS;
+    }
+    return stat;
 }
diff --git a/file_io/win32/readwrite.c b/file_io/win32/readwrite.c
index fb16769d834..5ad2c3b83ce 100644
--- a/file_io/win32/readwrite.c
+++ b/file_io/win32/readwrite.c
@@ -1,126 +1,523 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "fileio.h"
+#include "apr_arch_file_io.h"
 #include "apr_file_io.h"
 #include "apr_general.h"
+#include "apr_strings.h"
 #include "apr_lib.h"
 #include "apr_errno.h"
 #include <malloc.h>
-#include <windows.h>
-#include "atime.h"
+#include "apr_arch_atime.h"
+#include "apr_arch_misc.h"
+
+/*
+ * read_with_timeout() 
+ * Uses async i/o to emulate unix non-blocking i/o with timeouts.
+ */
+static apr_status_t read_with_timeout(apr_file_t *file, void *buf, apr_size_t len_in, apr_size_t *nbytes)
+{
+    apr_status_t rv;
+    DWORD res;
+    DWORD len = (DWORD)len_in;
+    DWORD bytesread = 0;
 
-#define GetFilePointer(hfile) SetFilePointer(hfile,0,NULL, FILE_CURRENT)
+    /* Handle the zero timeout non-blocking case */
+    if (file->timeout == 0) {
+        /* Peek at the pipe. If there is no data available, return APR_EAGAIN.
+         * If data is available, go ahead and read it.
+         */
+        if (file->pipe) {
+            DWORD bytes;
+            if (!PeekNamedPipe(file->filehand, NULL, 0, NULL, &bytes, NULL)) {
+                rv = apr_get_os_error();
+                if (rv == APR_FROM_OS_ERROR(ERROR_BROKEN_PIPE)) {
+                    rv = APR_EOF;
+                }
+                *nbytes = 0;
+                return rv;
+            }
+            else {
+                if (bytes == 0) {
+                    *nbytes = 0;
+                    return APR_EAGAIN;
+                }
+                if (len > bytes) {
+                    len = bytes;
+                }
+            }
+        }
+        else {
+            /* ToDo: Handle zero timeout non-blocking file i/o 
+             * This is not needed until an APR application needs to
+             * timeout file i/o (which means setting file i/o non-blocking)
+             */
+        }
+    }
 
-ap_status_t ap_read(ap_file_t *thefile, void *buf, ap_ssize_t *nbytes)
+    if (file->pOverlapped && !file->pipe) {
+        file->pOverlapped->Offset     = (DWORD)file->filePtr;
+        file->pOverlapped->OffsetHigh = (DWORD)(file->filePtr >> 32);
+    }
+
+    if (ReadFile(file->filehand, buf, len, 
+                 &bytesread, file->pOverlapped)) {
+        rv = APR_SUCCESS;
+    }
+    else {
+        rv = apr_get_os_error();
+        if (rv == APR_FROM_OS_ERROR(ERROR_IO_PENDING)) {
+            /* Wait for the pending i/o, timeout converted from us to ms
+             * Note that we loop if someone gives up the event, since
+             * folks suggest that WAIT_ABANDONED isn't actually a result
+             * but an alert that ownership of the event has passed from
+             * one owner to a new proc/thread.
+             */
+            do {
+                res = WaitForSingleObject(file->pOverlapped->hEvent, 
+                                          (file->timeout > 0)
+                                            ? (DWORD)(file->timeout/1000)
+                                            : ((file->timeout == -1) 
+                                                 ? INFINITE : 0));
+            } while (res == WAIT_ABANDONED);
+
+            /* There is one case that represents entirely
+             * successful operations, otherwise we will cancel
+             * the operation in progress.
+             */
+            if (res != WAIT_OBJECT_0) {
+                CancelIo(file->filehand);
+            }
+
+            /* Ignore any failures above.  Attempt to complete
+             * the overlapped operation and use only _its_ result.
+             * For example, CancelIo or WaitForSingleObject can
+             * fail if the handle is closed, yet the read may have
+             * completed before we attempted to CancelIo...
+             */
+            if (GetOverlappedResult(file->filehand, file->pOverlapped, 
+                                    &bytesread, TRUE)) {
+                rv = APR_SUCCESS;
+            }
+            else {
+                rv = apr_get_os_error();
+                if (((rv == APR_FROM_OS_ERROR(ERROR_IO_INCOMPLETE))
+                        || (rv == APR_FROM_OS_ERROR(ERROR_OPERATION_ABORTED)))
+                    && (res == WAIT_TIMEOUT))
+                    rv = APR_TIMEUP;
+            }
+        }
+        if (rv == APR_FROM_OS_ERROR(ERROR_BROKEN_PIPE)) {
+            /* Assume ERROR_BROKEN_PIPE signals an EOF reading from a pipe */
+            rv = APR_EOF;
+        } else if (rv == APR_FROM_OS_ERROR(ERROR_HANDLE_EOF)) {
+            /* Did we hit EOF reading from the handle? */
+            rv = APR_EOF;
+        }
+    }
+    
+    /* OK and 0 bytes read ==> end of file */
+    if (rv == APR_SUCCESS && bytesread == 0)
+        rv = APR_EOF;
+    
+    if (rv == APR_SUCCESS && file->pOverlapped && !file->pipe) {
+        file->filePtr += bytesread;
+    }
+    *nbytes = bytesread;
+    return rv;
+}
+
+static apr_status_t read_buffered(apr_file_t *thefile, void *buf, apr_size_t *len)
 {
-    DWORD bread;
-    int lasterror;
+    apr_status_t rv;
+    char *pos = (char *)buf;
+    apr_size_t blocksize;
+    apr_size_t size = *len;
 
-    if (ReadFile(thefile->filehand, buf, *nbytes, &bread, NULL)) {
-        *nbytes = bread;
-        return APR_SUCCESS;
+    if (thefile->direction == 1) {
+        rv = apr_file_flush(thefile);
+        if (rv != APR_SUCCESS) {
+            return rv;
+        }
+        thefile->bufpos = 0;
+        thefile->direction = 0;
+        thefile->dataRead = 0;
     }
 
-    *nbytes = 0;
-    lasterror = GetLastError();
-    if (lasterror == ERROR_BROKEN_PIPE) {
-        /* Assume ERROR_BROKEN_PIPE signals an EOF reading from a pipe */
+    rv = 0;
+    while (rv == 0 && size > 0) {
+        if (thefile->bufpos >= thefile->dataRead) {
+            apr_size_t read;
+            rv = read_with_timeout(thefile, thefile->buffer,
+                                   thefile->bufsize, &read);
+            if (read == 0) {
+                if (rv == APR_EOF)
+                    thefile->eof_hit = TRUE;
+                break;
+            }
+            else {
+                thefile->dataRead = read;
+                thefile->filePtr += thefile->dataRead;
+                thefile->bufpos = 0;
+            }
+        }
+
+        blocksize = size > thefile->dataRead - thefile->bufpos ? thefile->dataRead - thefile->bufpos : size;
+        memcpy(pos, thefile->buffer + thefile->bufpos, blocksize);
+        thefile->bufpos += blocksize;
+        pos += blocksize;
+        size -= blocksize;
+    }
+
+    *len = pos - (char *)buf;
+    if (*len) {
+        rv = APR_SUCCESS;
+    }
+
+    return rv;
+}
+
+APR_DECLARE(apr_status_t) apr_file_read(apr_file_t *thefile, void *buf, apr_size_t *len)
+{
+    apr_status_t rv;
+    DWORD bytes_read = 0;
+
+    if (*len <= 0) {
+        *len = 0;
         return APR_SUCCESS;
-    } else if (lasterror == ERROR_NO_DATA) {
-        /* Receive this error on a read to a pipe in nonblocking mode */
-        return APR_EAGAIN;
     }
 
-    return lasterror;
+    /* If the file is open for xthread support, allocate and
+     * initialize the overlapped and io completion event (hEvent). 
+     * Threads should NOT share an apr_file_t or its hEvent.
+     */
+    if ((thefile->flags & APR_FOPEN_XTHREAD) && !thefile->pOverlapped ) {
+        thefile->pOverlapped = (OVERLAPPED*) apr_pcalloc(thefile->pool, 
+                                                         sizeof(OVERLAPPED));
+        thefile->pOverlapped->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+        if (!thefile->pOverlapped->hEvent) {
+            rv = apr_get_os_error();
+            return rv;
+        }
+    }
+
+    /* Handle the ungetchar if there is one */
+    if (thefile->ungetchar != -1) {
+        bytes_read = 1;
+        *(char *)buf = (char)thefile->ungetchar;
+        buf = (char *)buf + 1;
+        (*len)--;
+        thefile->ungetchar = -1;
+        if (*len == 0) {
+            *len = bytes_read;
+            return APR_SUCCESS;
+        }
+    }
+    if (thefile->buffered) {
+        if (thefile->flags & APR_FOPEN_XTHREAD) {
+            apr_thread_mutex_lock(thefile->mutex);
+        }
+        rv = read_buffered(thefile, buf, len);
+        if (thefile->flags & APR_FOPEN_XTHREAD) {
+            apr_thread_mutex_unlock(thefile->mutex);
+        }
+    } else {  
+        /* Unbuffered i/o */
+        apr_size_t nbytes;
+        rv = read_with_timeout(thefile, buf, *len, &nbytes);
+        if (rv == APR_EOF)
+            thefile->eof_hit = TRUE;
+        *len = nbytes;
+    }
+
+    return rv;
 }
 
-ap_status_t ap_write(ap_file_t *thefile, void *buf, ap_ssize_t *nbytes)
+APR_DECLARE(apr_status_t) apr_file_rotating_check(apr_file_t *thefile)
 {
-    ap_status_t rv;
-    DWORD bwrote;
+    return APR_ENOTIMPL;
+}
 
-    if (!thefile->pipe && thefile->append) {
-        SetFilePointer(thefile->filehand, 0, NULL, FILE_END);
+APR_DECLARE(apr_status_t) apr_file_rotating_manual_check(apr_file_t *thefile,
+                                                         apr_time_t n)
+{
+    return APR_ENOTIMPL;
+}
+
+/* Helper function that adapts WriteFile() to apr_size_t instead
+ * of DWORD. */
+static apr_status_t write_helper(HANDLE filehand, const char *buf,
+                                 apr_size_t len, apr_size_t *pwritten)
+{
+    apr_size_t remaining = len;
+
+    *pwritten = 0;
+    do {
+        DWORD to_write;
+        DWORD written;
+
+        if (remaining > APR_DWORD_MAX) {
+            to_write = APR_DWORD_MAX;
+        }
+        else {
+            to_write = (DWORD)remaining;
+        }
+
+        if (!WriteFile(filehand, buf, to_write, &written, NULL)) {
+            *pwritten += written;
+            return apr_get_os_error();
+        }
+
+        *pwritten += written;
+        remaining -= written;
+        buf += written;
+    } while (remaining);
+
+    return APR_SUCCESS;
+}
+
+static apr_status_t write_buffered(apr_file_t *thefile, const char *buf,
+                                   apr_size_t len, apr_size_t *pwritten)
+{
+    apr_status_t rv;
+
+    if (thefile->direction == 0) {
+        /* Position file pointer for writing at the offset we are logically reading from */
+        apr_off_t offset = thefile->filePtr - thefile->dataRead + thefile->bufpos;
+        DWORD offlo = (DWORD)offset;
+        LONG offhi = (LONG)(offset >> 32);
+        if (offset != thefile->filePtr)
+            SetFilePointer(thefile->filehand, offlo, &offhi, FILE_BEGIN);
+        thefile->bufpos = thefile->dataRead = 0;
+        thefile->direction = 1;
     }
-    if (WriteFile(thefile->filehand, buf, *nbytes, &bwrote, NULL)) {
-        *nbytes = bwrote;
-        rv = APR_SUCCESS;
-    } 
-    else {
-        (*nbytes) = 0;
-        rv = GetLastError();
+
+    *pwritten = 0;
+
+    while (len > 0) {
+        if (thefile->bufpos == thefile->bufsize) { /* write buffer is full */
+            rv = apr_file_flush(thefile);
+            if (rv) {
+                return rv;
+            }
+        }
+        /* If our buffer is empty, and we cannot fit the remaining chunk
+         * into it, write the chunk with a single syscall and return.
+         */
+        if (thefile->bufpos == 0 && len > thefile->bufsize) {
+            apr_size_t written;
+
+            rv = write_helper(thefile->filehand, buf, len, &written);
+            thefile->filePtr += written;
+            *pwritten += written;
+            return rv;
+        }
+        else {
+            apr_size_t blocksize = len;
+
+            if (blocksize > thefile->bufsize - thefile->bufpos) {
+                blocksize = thefile->bufsize - thefile->bufpos;
+            }
+            memcpy(thefile->buffer + thefile->bufpos, buf, blocksize);
+            thefile->bufpos += blocksize;
+            buf += blocksize;
+            len -= blocksize;
+            *pwritten += blocksize;
+        }
     }
 
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_file_write(apr_file_t *thefile, const void *buf, apr_size_t *nbytes)
+{
+    apr_status_t rv;
+    DWORD bwrote;
+
+    /* If the file is open for xthread support, allocate and
+     * initialize the overlapped and io completion event (hEvent). 
+     * Threads should NOT share an apr_file_t or its hEvent.
+     */
+    if ((thefile->flags & APR_FOPEN_XTHREAD) && !thefile->pOverlapped ) {
+        thefile->pOverlapped = (OVERLAPPED*) apr_pcalloc(thefile->pool, 
+                                                         sizeof(OVERLAPPED));
+        thefile->pOverlapped->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+        if (!thefile->pOverlapped->hEvent) {
+            rv = apr_get_os_error();
+            return rv;
+        }
+    }
+
+    if (thefile->buffered) {
+        if (thefile->flags & APR_FOPEN_XTHREAD) {
+            apr_thread_mutex_lock(thefile->mutex);
+        }
+        rv = write_buffered(thefile, buf, *nbytes, nbytes);
+        if (thefile->flags & APR_FOPEN_XTHREAD) {
+            apr_thread_mutex_unlock(thefile->mutex);
+        }
+        return rv;
+    } else {
+        if (thefile->pipe) {
+            rv = WriteFile(thefile->filehand, buf, (DWORD)*nbytes, &bwrote,
+                           thefile->pOverlapped);
+        }
+        else if (thefile->append && !thefile->pOverlapped) {
+            OVERLAPPED ov = {0};
+
+            /* If the file is opened for synchronous I/O, take advantage of the
+             * documented way to atomically append data by calling WriteFile()
+             * with both the OVERLAPPED.Offset and OffsetHigh members set to
+             * 0xFFFFFFFF.  This avoids calling LockFile() that is otherwise
+             * required to avoid a race condition between seeking to the end
+             * and writing data.  Not locking the file improves robustness of
+             * such appends and avoids a deadlock when appending to an already
+             * locked file, as described in PR50058.
+             *
+             * We use this approach only for files opened for synchronous I/O
+             * because in this case the I/O Manager maintains the current file
+             * position.  Otherwise, the file offset returned or changed by
+             * the SetFilePointer() API is not guaranteed to be valid and that
+             * could, for instance, break apr_file_seek() calls after appending
+             * data.  Sadly, if a file is opened for asynchronous I/O, this
+             * call doesn't update the OVERLAPPED.Offset member to reflect the
+             * actual offset used when appending the data (which we could then
+             * use to make seeking and other operations involving filePtr work).
+             * Therefore, when appending to files opened for asynchronous I/O,
+             * we still use the LockFile + SetFilePointer + WriteFile approach.
+             *
+             * References:
+             * https://bz.apache.org/bugzilla/show_bug.cgi?id=50058
+             * https://msdn.microsoft.com/en-us/library/windows/desktop/aa365747
+             * https://msdn.microsoft.com/en-us/library/windows/hardware/ff567121
+             */
+            ov.Offset = MAXDWORD;
+            ov.OffsetHigh = MAXDWORD;
+            rv = WriteFile(thefile->filehand, buf, (DWORD)*nbytes, &bwrote, &ov);
+        }
+        else {
+            apr_off_t offset = 0;
+            apr_status_t rc;
+            if (thefile->append) {
+                if (thefile->flags & APR_FOPEN_XTHREAD) {
+                    /* apr_file_lock will mutex the file across processes.
+                     * The call to apr_thread_mutex_lock is added to avoid
+                     * a race condition between LockFile and WriteFile
+                     * that occasionally leads to deadlocked threads.
+                     */
+                    apr_thread_mutex_lock(thefile->mutex);
+                }
+                rc = apr_file_lock(thefile, APR_FLOCK_EXCLUSIVE);
+                if (rc != APR_SUCCESS) {
+                    if (thefile->flags & APR_FOPEN_XTHREAD) {
+                        apr_thread_mutex_unlock(thefile->mutex);
+                    }
+                    return rc;
+                }
+                rc = apr_file_seek(thefile, APR_END, &offset);
+                if (rc != APR_SUCCESS) {
+                    if (thefile->flags & APR_FOPEN_XTHREAD) {
+                        apr_thread_mutex_unlock(thefile->mutex);
+                    }
+                    return rc;
+                }
+            }
+            if (thefile->pOverlapped) {
+                thefile->pOverlapped->Offset     = (DWORD)thefile->filePtr;
+                thefile->pOverlapped->OffsetHigh = (DWORD)(thefile->filePtr >> 32);
+            }
+            rv = WriteFile(thefile->filehand, buf, (DWORD)*nbytes, &bwrote,
+                           thefile->pOverlapped);
+            if (thefile->append) {
+                apr_file_unlock(thefile);
+                if (thefile->flags & APR_FOPEN_XTHREAD) {
+                    apr_thread_mutex_unlock(thefile->mutex);
+                }
+            }
+        }
+        if (rv) {
+            *nbytes = bwrote;
+            rv = APR_SUCCESS;
+        }
+        else {
+            (*nbytes) = 0;
+            rv = apr_get_os_error();
+
+            /* XXX: This must be corrected, per the apr_file_read logic!!! */
+            if (rv == APR_FROM_OS_ERROR(ERROR_IO_PENDING)) {
+ 
+                DWORD timeout_ms;
+
+                if (thefile->timeout == 0) {
+                    timeout_ms = 0;
+                }
+                else if (thefile->timeout < 0) {
+                    timeout_ms = INFINITE;
+                }
+                else {
+                    timeout_ms = (DWORD)(thefile->timeout / 1000);
+                }
+	       
+                rv = WaitForSingleObject(thefile->pOverlapped->hEvent, timeout_ms);
+                switch (rv) {
+                    case WAIT_OBJECT_0:
+                        GetOverlappedResult(thefile->filehand, thefile->pOverlapped, 
+                                            &bwrote, TRUE);
+                        *nbytes = bwrote;
+                        rv = APR_SUCCESS;
+                        break;
+                    case WAIT_TIMEOUT:
+                        rv = (timeout_ms == 0) ? APR_EAGAIN : APR_TIMEUP;
+                        break;
+                    case WAIT_FAILED:
+                        rv = apr_get_os_error();
+                        break;
+                    default:
+                        break;
+                }
+                if (rv != APR_SUCCESS) {
+                    if (apr_os_level >= APR_WIN_98)
+                        CancelIo(thefile->filehand);
+                }
+            }
+        }
+        if (rv == APR_SUCCESS && thefile->pOverlapped && !thefile->pipe) {
+            thefile->filePtr += *nbytes;
+        }
+    }
     return rv;
 }
-/*
- * Too bad WriteFileGather() is not supported on 95&98 (or NT prior to SP2) 
+/* ToDo: Write for it anyway and test the oslevel!
+ * Too bad WriteFileGather() is not supported on 95&98 (or NT prior to SP2)
  */
-ap_status_t ap_writev(ap_file_t *thefile, const struct iovec *vec, ap_size_t nvec, 
-                      ap_ssize_t *nbytes)
+APR_DECLARE(apr_status_t) apr_file_writev(apr_file_t *thefile,
+                                     const struct iovec *vec,
+                                     apr_size_t nvec, 
+                                     apr_size_t *nbytes)
 {
-    ap_status_t rv = APR_SUCCESS;
-    int i;
-    DWORD bwrote = 0;
+    apr_status_t rv = APR_SUCCESS;
+    apr_size_t i;
+    apr_size_t bwrote = 0;
     char *buf;
 
     *nbytes = 0;
     for (i = 0; i < nvec; i++) {
         buf = vec[i].iov_base;
         bwrote = vec[i].iov_len;
-        rv = ap_write(thefile, buf, &bwrote);
+        rv = apr_file_write(thefile, buf, &bwrote);
         *nbytes += bwrote;
         if (rv != APR_SUCCESS) {
             break;
@@ -129,50 +526,31 @@ ap_status_t ap_writev(ap_file_t *thefile, const struct iovec *vec, ap_size_t nve
     return rv;
 }
 
-ap_status_t ap_putc(char ch, ap_file_t *thefile)
+APR_DECLARE(apr_status_t) apr_file_putc(char ch, apr_file_t *thefile)
 {
-    DWORD len = 1;
+    apr_size_t len = 1;
 
-    return ap_write(thefile, &ch, &len);
+    return apr_file_write(thefile, &ch, &len);
 }
 
-ap_status_t ap_ungetc(char ch, ap_file_t *thefile)
+APR_DECLARE(apr_status_t) apr_file_ungetc(char ch, apr_file_t *thefile)
 {
-    /* 
-     * Your application must provide its own serialization (locking) if
-     * it allows multiple threads to access the same file handle 
-     * concurrently.
-     *
-     * ToDo: This function does not use the char ch argument. Could add 
-     * gorpy code to read the file after the SetFilePointer() call to 
-     * make sure the character pushed back on the stream is the same as
-     * arg ch. Then, need to SetFilePointer() once more to reset the 
-     * file pointer to the point before the read. Yech... Just assume 
-     * the caller knows what he is doing.  There may be a nifty Win32 
-     * call for this I've not discovered....
-     */
-
-    /* SetFilePointer is only valid for a file device ...*/
-    if (GetFileType(thefile->filehand) != FILE_TYPE_DISK) {
-        return GetLastError();
-    }
-    /* and the file pointer is not pointing to the start of the file. */
-    if (GetFilePointer(thefile->filehand)) {
-        if (SetFilePointer(thefile->filehand, -1, NULL, FILE_CURRENT) 
-            == 0xFFFFFFFF) {
-            return GetLastError();
-        }
-    }
-
-    return APR_SUCCESS; 
+    thefile->ungetchar = (unsigned char) ch;
+    return APR_SUCCESS;
 }
 
-ap_status_t ap_getc(char *ch, ap_file_t *thefile)
+APR_DECLARE(apr_status_t) apr_file_getc(char *ch, apr_file_t *thefile)
 {
-    DWORD bread;
-    if (!ReadFile(thefile->filehand, ch, 1, &bread, NULL)) {
-        return GetLastError();
+    apr_status_t rc;
+    apr_size_t bread;
+
+    bread = 1;
+    rc = apr_file_read(thefile, ch, &bread);
+
+    if (rc) {
+        return rc;
     }
+    
     if (bread == 0) {
         thefile->eof_hit = TRUE;
         return APR_EOF;
@@ -180,74 +558,211 @@ ap_status_t ap_getc(char *ch, ap_file_t *thefile)
     return APR_SUCCESS; 
 }
 
-ap_status_t ap_puts(char *str, ap_file_t *thefile)
+APR_DECLARE(apr_status_t) apr_file_puts(const char *str, apr_file_t *thefile)
 {
-    DWORD len = strlen(str);
+    apr_size_t len = strlen(str);
 
-    return ap_write(thefile, str, &len);
+    return apr_file_write(thefile, str, &len);
 }
 
-ap_status_t ap_fgets(char *str, int len, ap_file_t *thefile)
+APR_DECLARE(apr_status_t) apr_file_gets(char *str, int len, apr_file_t *thefile)
 {
-    DWORD bread;
-    int i;
-    if (!ReadFile(thefile->filehand, str, len, &bread, NULL)) {
-        switch(GetLastError()) {
-        case ERROR_HANDLE_EOF:
-            return APR_EOF;
-        default:
-            return GetLastError();
+    apr_status_t rv = APR_SUCCESS;
+    apr_size_t nbytes;
+    const char *str_start = str;
+    char *final = str + len - 1;
+
+    /* If the file is open for xthread support, allocate and
+     * initialize the overlapped and io completion event (hEvent).
+     * Threads should NOT share an apr_file_t or its hEvent.
+     */
+    if ((thefile->flags & APR_FOPEN_XTHREAD) && !thefile->pOverlapped) {
+        thefile->pOverlapped = (OVERLAPPED*) apr_pcalloc(thefile->pool,
+                                                         sizeof(OVERLAPPED));
+        thefile->pOverlapped->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+        if (!thefile->pOverlapped->hEvent) {
+            rv = apr_get_os_error();
+            return rv;
         }
     }
-    if (bread == 0) {
-        thefile->eof_hit = TRUE;
-        return APR_EOF;
-    }
-    for (i=0; i<len; i++) {
-        if (str[i] == '\n') {
-            ++i;
-            if (i < len)
-                str[i] = '\0';
-            else
-                str [--i] = '\0';
-            SetFilePointer(thefile->filehand, (i - bread), NULL, FILE_CURRENT);
+
+    /* Handle the ungetchar if there is one. */
+    if (thefile->ungetchar != -1 && str < final) {
+        *str = thefile->ungetchar;
+        thefile->ungetchar = -1;
+        if (*str == '\n') {
+            *(++str) = '\0';
             return APR_SUCCESS;
         }
+        ++str;
     }
-    str[i] = '\0';
-    return APR_SUCCESS; 
+
+    /* If we have an underlying buffer, we can be *much* more efficient
+     * and skip over the read_with_timeout() calls.
+     */
+    if (thefile->buffered) {
+        if (thefile->flags & APR_FOPEN_XTHREAD) {
+            apr_thread_mutex_lock(thefile->mutex);
+        }
+
+        if (thefile->direction == 1) {
+            rv = apr_file_flush(thefile);
+            if (rv) {
+                if (thefile->flags & APR_FOPEN_XTHREAD) {
+                    apr_thread_mutex_unlock(thefile->mutex);
+                }
+                return rv;
+            }
+
+            thefile->direction = 0;
+            thefile->bufpos = 0;
+            thefile->dataRead = 0;
+        }
+
+        while (str < final) { /* leave room for trailing '\0' */
+            if (thefile->bufpos < thefile->dataRead) {
+                *str = thefile->buffer[thefile->bufpos++];
+            }
+            else {
+                nbytes = 1;
+                rv = read_buffered(thefile, str, &nbytes);
+                if (rv != APR_SUCCESS) {
+                    break;
+                }
+            }
+            if (*str == '\n') {
+                ++str;
+                break;
+            }
+            ++str;
+        }
+        if (thefile->flags & APR_FOPEN_XTHREAD) {
+            apr_thread_mutex_unlock(thefile->mutex);
+        }
+    }
+    else {
+        while (str < final) { /* leave room for trailing '\0' */
+            nbytes = 1;
+            rv = read_with_timeout(thefile, str, nbytes, &nbytes);
+            if (rv == APR_EOF)
+                thefile->eof_hit = TRUE;
+
+            if (rv != APR_SUCCESS) {
+                break;
+            }
+            if (*str == '\n') {
+                ++str;
+                break;
+            }
+            ++str;
+        }
+    }
+
+    /* We must store a terminating '\0' if we've stored any chars. We can
+     * get away with storing it if we hit an error first.
+     */
+    *str = '\0';
+    if (str > str_start) {
+        /* We stored chars; don't report EOF or any other errors;
+         * the app will find out about that on the next call.
+         */
+        return APR_SUCCESS;
+    }
+    return rv;
 }
-ap_status_t ap_flush(ap_file_t *thefile)
+
+APR_DECLARE(apr_status_t) apr_file_flush(apr_file_t *thefile)
 {
-    FlushFileBuffers(thefile->filehand);
+    if (thefile->buffered) {
+        apr_status_t rc = 0;
+
+        if (thefile->direction == 1 && thefile->bufpos) {
+            apr_size_t written;
+
+            rc = write_helper(thefile->filehand, thefile->buffer,
+                              thefile->bufpos, &written);
+            thefile->filePtr += written;
+
+            if (rc == 0)
+                thefile->bufpos = 0;
+        }
+
+        return rc;
+    }
+
+    /* There isn't anything to do if we aren't buffering the output
+     * so just return success.
+     */
     return APR_SUCCESS; 
 }
 
-static int printf_flush(ap_vformatter_buff_t *vbuff)
+APR_DECLARE(apr_status_t) apr_file_sync(apr_file_t *thefile){
+    apr_status_t rv;
+
+    rv = apr_file_flush(thefile);
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
+    if (!FlushFileBuffers(thefile->filehand)) {
+        rv = apr_get_os_error();
+    }
+
+    return rv;
+}
+
+APR_DECLARE(apr_status_t) apr_file_datasync(apr_file_t *thefile){
+    return apr_file_sync(thefile);
+}
+
+struct apr_file_printf_data {
+    apr_vformatter_buff_t vbuff;
+    apr_file_t *fptr;
+    char *buf;
+};
+
+static int file_printf_flush(apr_vformatter_buff_t *buff)
 {
-    /* I would love to print this stuff out to the file, but I will
-     * get that working later.  :)  For now, just return.
-     */
-    return -1;
+    struct apr_file_printf_data *data = (struct apr_file_printf_data *)buff;
+
+    if (apr_file_write_full(data->fptr, data->buf,
+                            data->vbuff.curpos - data->buf, NULL)) {
+        return -1;
+    }
+
+    data->vbuff.curpos = data->buf;
+    return 0;
 }
 
-API_EXPORT(int) ap_fprintf(ap_file_t *fptr, const char *format, ...)
+APR_DECLARE_NONSTD(int) apr_file_printf(apr_file_t *fptr, 
+                                        const char *format, ...)
 {
-    int cc;
+    struct apr_file_printf_data data;
     va_list ap;
-    char *buf;
-    int len;
+    int count;
 
-    buf = malloc(HUGE_STRING_LEN);
-    if (buf == NULL) {
+    data.buf = malloc(HUGE_STRING_LEN);
+    if (data.buf == NULL) {
         return 0;
     }
+    data.vbuff.curpos = data.buf;
+    data.vbuff.endpos = data.buf + HUGE_STRING_LEN;
+    data.fptr = fptr;
     va_start(ap, format);
-    len = ap_vsnprintf(buf, HUGE_STRING_LEN, format, ap);
-    cc = ap_puts(buf, fptr);
+    count = apr_vformatter(file_printf_flush,
+                           (apr_vformatter_buff_t *)&data, format, ap);
+    /* apr_vformatter does not call flush for the last bits */
+    if (count >= 0) file_printf_flush((apr_vformatter_buff_t *)&data);
+
     va_end(ap);
-    free(buf);
-    return (cc == APR_SUCCESS) ? len : -1;
+
+    free(data.buf);
+    return count;
 }
 
+APR_DECLARE(apr_status_t) apr_file_pipe_wait(apr_file_t *thepipe,
+                                             apr_wait_type_t direction)
+{
+    return APR_ENOTIMPL;
+}
 
diff --git a/file_io/win32/seek.c b/file_io/win32/seek.c
index 34b1fa22679..afe6edb0050 100644
--- a/file_io/win32/seek.c
+++ b/file_io/win32/seek.c
@@ -1,89 +1,203 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "fileio.h"
+#include "apr_arch_file_io.h"
 #include "apr_file_io.h"
 #include <errno.h>
 #include <string.h>
 
-ap_status_t ap_seek(ap_file_t *thefile, ap_seek_where_t where, ap_off_t *offset)
+static apr_status_t setptr(apr_file_t *thefile, apr_off_t pos )
 {
-    DWORD howmove;
-    DWORD rv;
+    apr_off_t newbufpos;
+    apr_status_t rv;
+    DWORD rc;
 
-    switch(where) {
-    case APR_SET: {
-        howmove = FILE_BEGIN;
-        break;
+    if (thefile->direction == 1) {
+        /* XXX: flush here is not mutex protected */
+        rv = apr_file_flush(thefile);
+        if (rv != APR_SUCCESS)
+            return rv;
+        thefile->bufpos = thefile->dataRead = 0;
+        thefile->direction = 0;
     }
-    case APR_CUR: {
-        howmove = FILE_CURRENT;
-        break;
-    }
-    case APR_END: {
-        howmove = FILE_END;
-        break;
+
+    /* We may be truncating to size here. 
+     * XXX: testing an 'unsigned' as >= 0 below indicates a bug
+     */
+    newbufpos = pos - (thefile->filePtr - thefile->dataRead);
+
+    if (newbufpos >= 0 && newbufpos <= (apr_off_t)thefile->dataRead) {
+        thefile->bufpos = (apr_size_t)newbufpos;
+        rv = APR_SUCCESS;
+    } else {
+        DWORD offlo = (DWORD)pos;
+        LONG  offhi = (LONG)(pos >> 32);
+        rc = SetFilePointer(thefile->filehand, offlo, &offhi, FILE_BEGIN);
+
+        if (rc == (DWORD)-1)
+            /* A legal value, perhaps?  MSDN implies prior SetLastError isn't
+             * needed, googling for SetLastError SetFilePointer seems
+             * to confirm this.  INVALID_SET_FILE_POINTER is too recently
+             * added for us to rely on it as a constant.
+             */
+            rv = apr_get_os_error();
+        else
+            rv = APR_SUCCESS;
+
+        if (rv == APR_SUCCESS) {
+            rv = APR_SUCCESS;
+            thefile->eof_hit = 0;
+            thefile->bufpos = thefile->dataRead = 0;
+            thefile->filePtr = pos;
+        }
     }
+
+    return rv;
+}
+
+
+APR_DECLARE(apr_status_t) apr_file_seek(apr_file_t *thefile, apr_seek_where_t where, apr_off_t *offset)
+{
+    apr_finfo_t finfo;
+    apr_status_t rc = APR_SUCCESS;
+
+    thefile->eof_hit = 0;
+
+    if (thefile->buffered) {
+        switch (where) {
+            case APR_SET:
+                rc = setptr(thefile, *offset);
+                break;
+
+            case APR_CUR:
+                rc = setptr(thefile, thefile->filePtr - thefile->dataRead 
+                                      + thefile->bufpos + *offset);
+                break;
+
+            case APR_END:
+                rc = apr_file_info_get(&finfo, APR_FINFO_SIZE, thefile);
+                if (rc == APR_SUCCESS)
+                    rc = setptr(thefile, finfo.size + *offset);
+                break;
+
+            default:
+                return APR_EINVAL;
+        }
+
+        *offset = thefile->filePtr - thefile->dataRead + thefile->bufpos;
+        return rc;
     }
+    /* A file opened with APR_FOPEN_XTHREAD has been opened for overlapped i/o.
+     * APR must explicitly track the file pointer in this case.
+     */
+    else if (thefile->pOverlapped || thefile->flags & APR_FOPEN_XTHREAD) {
+        switch(where) {
+            case APR_SET:
+                thefile->filePtr = *offset;
+                break;
+        
+            case APR_CUR:
+                thefile->filePtr += *offset;
+                break;
+        
+            case APR_END:
+                rc = apr_file_info_get(&finfo, APR_FINFO_SIZE, thefile);
+                if (rc == APR_SUCCESS && finfo.size + *offset >= 0)
+                    thefile->filePtr = finfo.size + *offset;
+                break;
 
-    rv = SetFilePointer(thefile->filehand, *offset, NULL, howmove);
-    if (rv == -1) {
-        *offset = -1;
-        return APR_EEXIST;
+            default:
+                return APR_EINVAL;
+        }
+        *offset = thefile->filePtr;
+        return rc;
     }
     else {
-        *offset = rv;
-        return APR_SUCCESS;
+        DWORD howmove;
+        DWORD offlo = (DWORD)*offset;
+        DWORD offhi = (DWORD)(*offset >> 32);
+
+        switch(where) {
+            case APR_SET:
+                howmove = FILE_BEGIN;   break;
+            case APR_CUR:
+                howmove = FILE_CURRENT; break;
+            case APR_END:
+                howmove = FILE_END;     break;
+            default:
+                return APR_EINVAL;
+        }
+        offlo = SetFilePointer(thefile->filehand, (LONG)offlo, 
+                               (LONG*)&offhi, howmove);
+        if (offlo == 0xFFFFFFFF)
+            rc = apr_get_os_error();
+        else
+            rc = APR_SUCCESS;
+        /* Since we can land at 0xffffffff we will measure our APR_SUCCESS */
+        if (rc == APR_SUCCESS)
+            *offset = ((apr_off_t)offhi << 32) | offlo;
+        return rc;
     }
 }
+
+
+APR_DECLARE(apr_status_t) apr_file_trunc(apr_file_t *thefile, apr_off_t offset)
+{
+    apr_status_t rv;
+    DWORD offlo = (DWORD)offset;
+    LONG  offhi = (LONG)(offset >> 32);
+    DWORD rc;
+
+    if (thefile->buffered) {
+        if (thefile->direction == 1) {
+            /* Figure out what needs to be flushed.  Don't flush the part
+             * of the write buffer that will get truncated anyway.
+             */
+            if (offset < thefile->filePtr) {
+                thefile->bufpos = 0;
+            }
+            else if (offset < thefile->filePtr + (apr_off_t)thefile->bufpos) {
+                thefile->bufpos = offset - thefile->filePtr;
+            }
+
+            if (thefile->bufpos != 0) {
+                rv = apr_file_flush(thefile);
+                if (rv != APR_SUCCESS)
+                    return rv;
+            }
+        }
+        else if (thefile->direction == 0) {
+            /* Discard the read buffer, as we are about to reposition
+             * ourselves to the end of file.
+             */
+            thefile->bufpos = 0;
+            thefile->dataRead = 0;
+        }
+    }
+
+    rc = SetFilePointer(thefile->filehand, offlo, &offhi, FILE_BEGIN);
+    if (rc == 0xFFFFFFFF)
+        if ((rv = apr_get_os_error()) != APR_SUCCESS)
+            return rv;
+    thefile->filePtr = offset;
+    /* Don't report EOF until the next read. */
+    thefile->eof_hit = 0;
+
+    if (!SetEndOfFile(thefile->filehand))
+        return apr_get_os_error();
+
+    return APR_SUCCESS;
+}
diff --git a/helpers/apr_rename.pl b/helpers/apr_rename.pl
new file mode 100755
index 00000000000..25b9d52d4c0
--- /dev/null
+++ b/helpers/apr_rename.pl
@@ -0,0 +1,106 @@
+#!/usr/bin/perl -w
+use strict;
+use ExtUtils::MakeMaker qw(prompt);
+use File::Find;
+
+my $just_check = @ARGV ? $ARGV[0] eq '-c' : 0;
+shift if $just_check;
+my $dir = shift || '.';
+my %names;
+
+my $prefix = 'apr_';
+
+while (<DATA>) {
+    chomp;
+    my($old, $new) = grep { s/^$prefix//o } split;
+    next unless $old and $new;
+    $names{$old} = $new;
+}
+
+my $pattern = join '|', keys %names;
+#print "replacement pattern=$pattern\n";
+
+find sub {
+    chomp;
+    return unless /\.[ch]$/;
+    my $file = "$File::Find::dir/$_";
+    print "looking in $file\n";
+
+    replace($_, !$just_check);
+
+}, $dir;
+
+sub replace {
+    my($file, $replace) = @_;
+    local *IN, *OUT;
+    my @lines;
+    my $found = 0;
+
+    open IN, $file or die "open $file: $!";
+
+    while (<IN>) {
+        for (m/[^_\"]*$prefix($pattern)\b/og) {
+            $found++;
+            print "   $file:$. apr_$_ -> apr_$names{$_}\n";
+        }
+        push @lines, $_ if $replace;
+    }
+
+    close IN;
+
+    return unless $found and $replace;
+
+#    my $ans = prompt("replace?", 'y');
+#    return unless $ans =~ /^y/i;
+
+    open OUT, ">$file" or die "open $file: $!";
+
+    for (@lines) {
+        unless (/^\#include/) {
+            s/([^_\"]*$prefix)($pattern)\b/$1$names{$2}/og;
+        }
+        print OUT $_;
+    }
+
+    close OUT;
+}
+
+__DATA__
+apr_time_t:
+apr_implode_gmt              apr_time_exp_gmt_get
+
+apr_socket_t:
+apr_close_socket             apr_socket_close
+apr_create_socket            apr_socket_create
+apr_get_sockaddr             apr_socket_addr_get
+apr_get_socketdata           apr_socket_data_get
+apr_set_socketdata           apr_socket_data_set
+apr_shutdown                 apr_socket_shutdown
+apr_bind                     apr_socket_bind
+apr_listen                   apr_socket_listen
+apr_accept                   apr_socket_accept
+apr_connect                  apr_socket_connect
+apr_send                     apr_socket_send
+apr_sendv                    apr_socket_sendv
+apr_sendto                   apr_socket_sendto
+apr_recvfrom                 apr_socket_recvfrom
+apr_sendfile                 apr_socket_sendfile
+apr_recv                     apr_socket_recv
+
+apr_filepath_*:
+apr_filename_of_pathname     apr_filepath_name_get
+
+apr_gid_t:
+apr_get_groupid              apr_gid_get
+apr_get_groupname            apr_gid_name_get
+apr_group_name_get           apr_gid_name_get
+apr_compare_groups           apr_gid_compare
+
+apr_uid_t:
+apr_get_home_directory       apr_uid_homepath_get
+apr_get_userid               apr_uid_get
+apr_current_userid           apr_uid_current
+apr_compare_users            apr_uid_compare
+apr_get_username             apr_uid_name_get
+apr_compare_users            apr_uid_compare
+
diff --git a/helpers/build-modules-c.awk b/helpers/build-modules-c.awk
deleted file mode 100644
index 15ff82ccfb4..00000000000
--- a/helpers/build-modules-c.awk
+++ /dev/null
@@ -1,56 +0,0 @@
-BEGIN {
-    RS = " "
-    modules[n++] = "core"
-    pmodules[pn++] = "core"
-} 
-{
-    modules[n] = $1;
-    pmodules[pn] = $1;
-    gsub("\n","",modules[n]);
-    gsub("\n","",pmodules[pn]);
-    ++n;
-    ++pn;
-} 
-END {
-    print "/*"
-    print " * modules.c --- automatically generated by Apache"
-    print " * configuration script.  DO NOT HAND EDIT!!!!!"
-    print " */"
-    print ""
-    print "#include \"ap_config.h\""
-    print "#include \"httpd.h\""
-    print "#include \"http_config.h\""
-    print ""
-    for (i = 0; i < pn; ++i) {
-        printf ("extern module %s_module;\n", pmodules[i])
-    }
-    print ""
-    print "/*"
-    print " *  Modules which implicitly form the"
-    print " *  list of activated modules on startup,"
-    print " *  i.e. these are the modules which are"
-    print " *  initially linked into the Apache processing"
-    print " *  [extendable under run-time via AddModule]"
-    print " */"
-    print "module *ap_prelinked_modules[] = {"
-    for (i = 0; i < n; ++i) {
-        printf "  &%s_module,\n", modules[i]
-    }
-    print "  NULL"
-    print "};"
-    print ""
-    print "/*"
-    print " *  Modules which initially form the"
-    print " *  list of available modules on startup,"
-    print " *  i.e. these are the modules which are"
-    print " *  initially loaded into the Apache process"
-    print " *  [extendable under run-time via LoadModule]"
-    print " */"
-    print "module *ap_preloaded_modules[] = {"
-    for (i = 0; i < pn; ++i) {
-        printf "  &%s_module,\n", pmodules[i]
-    }
-    print "  NULL"
-    print "};"
-    print ""
-}
diff --git a/helpers/config-stubs b/helpers/config-stubs
deleted file mode 100755
index aff00a57d48..00000000000
--- a/helpers/config-stubs
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh
-
-dir=$1
-for stubdir in `find $dir -type d`; do
-    if [ -r $stubdir/config.m4 ]; then
-        echo "sinclude($stubdir/config.m4)"
-    fi
-done
diff --git a/helpers/cvsclean b/helpers/cvsclean
deleted file mode 100755
index e98ec49b768..00000000000
--- a/helpers/cvsclean
+++ /dev/null
@@ -1,3 +0,0 @@
-#! /bin/sh
-
-${MAKE:-make} -f build/build.mk cvsclean
diff --git a/helpers/snapshot b/helpers/snapshot
deleted file mode 100755
index 9553a753f9d..00000000000
--- a/helpers/snapshot
+++ /dev/null
@@ -1,5 +0,0 @@
-#! /bin/sh
-
-test -n "$1" && ARG="DISTNAME='$1'"
-
-${MAKE:-make} $ARG -f build/build.mk snapshot
diff --git a/hooks/apr_hooks.c b/hooks/apr_hooks.c
new file mode 100644
index 00000000000..22045620433
--- /dev/null
+++ b/hooks/apr_hooks.c
@@ -0,0 +1,414 @@
+/* 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 <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "apr_pools.h"
+#include "apr_tables.h"
+#include "apr.h"
+#include "apr_hooks.h"
+#include "apr_hash.h"
+#include "apr_optional_hooks.h"
+#include "apr_optional.h"
+#define APR_WANT_MEMFUNC
+#define APR_WANT_STRFUNC
+#include "apr_want.h"
+
+#if 0
+#define apr_palloc(pool,size)   malloc(size)
+#endif
+
+APR_DECLARE_DATA apr_pool_t *apr_hook_global_pool = NULL;
+APR_DECLARE_DATA int apr_hook_debug_enabled = 0;
+APR_DECLARE_DATA const char *apr_hook_debug_current = NULL;
+
+/** @deprecated @see apr_hook_global_pool */
+APR_DECLARE_DATA apr_pool_t *apr_global_hook_pool = NULL;
+
+/** @deprecated @see apr_hook_debug_enabled */
+APR_DECLARE_DATA int apr_debug_module_hooks = 0;
+
+/** @deprecated @see apr_hook_debug_current */
+APR_DECLARE_DATA const char *apr_current_hooking_module = NULL;
+
+/* NB: This must echo the LINK_##name structure */
+typedef struct
+{
+    void (*dummy)(void *);
+    const char *szName;
+    const char * const *aszPredecessors;
+    const char * const *aszSuccessors;
+    int nOrder;
+} TSortData;
+
+typedef struct tsort_
+{
+    void *pData;
+    int nPredecessors;
+    struct tsort_ **ppPredecessors;
+    struct tsort_ *pNext;
+} TSort;
+
+#ifdef NETWARE
+#include "apr_private.h"
+#define get_apd                 APP_DATA* apd = (APP_DATA*)get_app_data(gLibId);
+#define s_aHooksToSort          ((apr_array_header_t *)(apd->gs_aHooksToSort))
+#define s_phOptionalHooks       ((apr_hash_t *)(apd->gs_phOptionalHooks))
+#define s_phOptionalFunctions   ((apr_hash_t *)(apd->gs_phOptionalFunctions))
+#endif
+
+static int crude_order(const void *a_,const void *b_)
+{
+    const TSortData *a=a_;
+    const TSortData *b=b_;
+
+    return a->nOrder-b->nOrder;
+}
+
+static TSort *prepare(apr_pool_t *p,TSortData *pItems,int nItems)
+{
+    TSort *pData=apr_palloc(p,nItems*sizeof *pData);
+    int n;
+
+    qsort(pItems,nItems,sizeof *pItems,crude_order);
+    for(n=0 ; n < nItems ; ++n) {
+        pData[n].nPredecessors=0;
+        pData[n].ppPredecessors=apr_pcalloc(p,nItems*sizeof *pData[n].ppPredecessors);
+        pData[n].pNext=NULL;
+        pData[n].pData=&pItems[n];
+    }
+
+    for(n=0 ; n < nItems ; ++n) {
+        int i,k;
+
+        for(i=0 ; pItems[n].aszPredecessors && pItems[n].aszPredecessors[i] ; ++i)
+            for(k=0 ; k < nItems ; ++k)
+                if(!strcmp(pItems[k].szName,pItems[n].aszPredecessors[i])) {
+                    int l;
+
+                    for(l=0 ; l < pData[n].nPredecessors ; ++l)
+                        if(pData[n].ppPredecessors[l] == &pData[k])
+                            goto got_it;
+                    pData[n].ppPredecessors[pData[n].nPredecessors]=&pData[k];
+                    ++pData[n].nPredecessors;
+                got_it:
+                    break;
+                }
+        for(i=0 ; pItems[n].aszSuccessors && pItems[n].aszSuccessors[i] ; ++i)
+            for(k=0 ; k < nItems ; ++k)
+                if(!strcmp(pItems[k].szName,pItems[n].aszSuccessors[i])) {
+                    int l;
+
+                    for(l=0 ; l < pData[k].nPredecessors ; ++l)
+                        if(pData[k].ppPredecessors[l] == &pData[n])
+                            goto got_it2;
+                    pData[k].ppPredecessors[pData[k].nPredecessors]=&pData[n];
+                    ++pData[k].nPredecessors;
+                got_it2:
+                    break;
+                }
+    }
+
+    return pData;
+}
+
+/* Topologically sort, dragging out-of-order items to the front. Note that
+   this tends to preserve things that want to be near the front better, and
+   changing that behaviour might compromise some of Apache's behaviour (in
+   particular, mod_log_forensic might otherwise get pushed to the end, and
+   core.c's log open function used to end up at the end when pushing items
+   to the back was the methedology). Also note that the algorithm could
+   go back to its original simplicity by sorting from the back instead of
+   the front.
+*/
+static TSort *tsort(TSort *pData,int nItems)
+{
+    int nTotal;
+    TSort *pHead=NULL;
+    TSort *pTail=NULL;
+
+    for(nTotal=0 ; nTotal < nItems ; ++nTotal) {
+        int n,i,k;
+
+        for(n=0 ; ; ++n) {
+            if(n == nItems)
+                assert(0);      /* we have a loop... */
+            if(!pData[n].pNext) {
+                if(pData[n].nPredecessors) {
+                    for(k=0 ; ; ++k) {
+                        assert(k < nItems);
+                        if(pData[n].ppPredecessors[k])
+                            break;
+                    }
+                    for(i=0 ; ; ++i) {
+                        assert(i < nItems);
+                        if(&pData[i] == pData[n].ppPredecessors[k]) {
+                            n=i-1;
+                            break;
+                        }
+                    }
+                } else
+                    break;
+            }
+        }
+        if(pTail)
+            pTail->pNext=&pData[n];
+        else
+            pHead=&pData[n];
+        pTail=&pData[n];
+        pTail->pNext=pTail;     /* fudge it so it looks linked */
+        for(i=0 ; i < nItems ; ++i)
+            for(k=0 ; k < nItems ; ++k)
+                if(pData[i].ppPredecessors[k] == &pData[n]) {
+                    --pData[i].nPredecessors;
+                    pData[i].ppPredecessors[k]=NULL;
+                    break;
+                }
+    }
+    pTail->pNext=NULL;  /* unfudge the tail */
+    return pHead;
+}
+
+static apr_array_header_t *sort_hook(apr_array_header_t *pHooks,
+                                     const char *szName)
+{
+    apr_pool_t *p;
+    TSort *pSort;
+    apr_array_header_t *pNew;
+    int n;
+
+    apr_pool_create(&p, apr_hook_global_pool);
+    pSort=prepare(p,(TSortData *)pHooks->elts,pHooks->nelts);
+    pSort=tsort(pSort,pHooks->nelts);
+    pNew=apr_array_make(apr_hook_global_pool,pHooks->nelts,sizeof(TSortData));
+    if(apr_hook_debug_enabled)
+        printf("Sorting %s:",szName);
+    for(n=0 ; pSort ; pSort=pSort->pNext,++n) {
+        TSortData *pHook;
+        assert(n < pHooks->nelts);
+        pHook=apr_array_push(pNew);
+        memcpy(pHook,pSort->pData,sizeof *pHook);
+        if(apr_hook_debug_enabled)
+            printf(" %s",pHook->szName);
+    }
+    if(apr_hook_debug_enabled)
+        fputc('\n',stdout);
+
+    /* destroy the pool - the sorted hooks were already copied */
+    apr_pool_destroy(p);
+
+    return pNew;
+}
+
+#ifndef NETWARE
+static apr_array_header_t *s_aHooksToSort;
+#endif
+
+typedef struct
+{
+    const char *szHookName;
+    apr_array_header_t **paHooks;
+} HookSortEntry;
+
+APR_DECLARE(void) apr_hook_sort_register(const char *szHookName,
+                                        apr_array_header_t **paHooks)
+{
+#ifdef NETWARE
+    get_apd
+#endif
+    HookSortEntry *pEntry;
+
+    if(!s_aHooksToSort)
+        s_aHooksToSort=apr_array_make(apr_hook_global_pool,1,sizeof(HookSortEntry));
+    pEntry=apr_array_push(s_aHooksToSort);
+    pEntry->szHookName=szHookName;
+    pEntry->paHooks=paHooks;
+}
+
+APR_DECLARE(void) apr_hook_sort_all(void)
+{
+#ifdef NETWARE
+    get_apd
+#endif
+    int n;
+
+    if (!s_aHooksToSort) {
+        s_aHooksToSort = apr_array_make(apr_hook_global_pool, 1, sizeof(HookSortEntry));
+    }
+
+    for(n=0 ; n < s_aHooksToSort->nelts ; ++n) {
+        HookSortEntry *pEntry=&((HookSortEntry *)s_aHooksToSort->elts)[n];
+        *pEntry->paHooks=sort_hook(*pEntry->paHooks,pEntry->szHookName);
+    }
+}
+
+#ifndef NETWARE
+static apr_hash_t *s_phOptionalHooks;
+static apr_hash_t *s_phOptionalFunctions;
+#endif
+
+APR_DECLARE(void) apr_hook_deregister_all(void)
+{
+#ifdef NETWARE
+    get_apd
+#endif
+    int n;
+
+    if (!s_aHooksToSort) {
+        return;
+    }
+
+    for(n=0 ; n < s_aHooksToSort->nelts ; ++n) {
+        HookSortEntry *pEntry=&((HookSortEntry *)s_aHooksToSort->elts)[n];
+        *pEntry->paHooks=NULL;
+    }
+    s_aHooksToSort=NULL;
+    s_phOptionalHooks=NULL;
+    s_phOptionalFunctions=NULL;
+}
+
+APR_DECLARE(void) apr_hook_debug_show(const char *szName,
+                                      const char * const *aszPre,
+                                      const char * const *aszSucc)
+{
+    int nFirst;
+
+    printf("  Hooked %s",szName);
+    if(aszPre) {
+        fputs(" pre(",stdout);
+        nFirst=1;
+        while(*aszPre) {
+            if(!nFirst)
+                fputc(',',stdout);
+            nFirst=0;
+            fputs(*aszPre,stdout);
+            ++aszPre;
+        }
+        fputc(')',stdout);
+    }
+    if(aszSucc) {
+        fputs(" succ(",stdout);
+        nFirst=1;
+        while(*aszSucc) {
+            if(!nFirst)
+                fputc(',',stdout);
+            nFirst=0;
+            fputs(*aszSucc,stdout);
+            ++aszSucc;
+        }
+        fputc(')',stdout);
+    }
+    fputc('\n',stdout);
+}
+
+/* Optional hook support */
+
+APR_DECLARE_EXTERNAL_HOOK(apr,APR,void,_optional,(void))
+
+APR_DECLARE(apr_array_header_t *) apr_optional_hook_get(const char *szName)
+{
+#ifdef NETWARE
+    get_apd
+#endif
+    apr_array_header_t **ppArray;
+
+    if(!s_phOptionalHooks)
+        return NULL;
+    ppArray=apr_hash_get(s_phOptionalHooks,szName,strlen(szName));
+    if(!ppArray)
+        return NULL;
+    return *ppArray;
+}
+
+APR_DECLARE(void) apr_optional_hook_add(const char *szName,void (*pfn)(void),
+                                        const char * const *aszPre,
+                                        const char * const *aszSucc,int nOrder)
+{
+#ifdef NETWARE
+    get_apd
+#endif
+    apr_array_header_t *pArray=apr_optional_hook_get(szName);
+    apr_LINK__optional_t *pHook;
+
+    if(!pArray) {
+        apr_array_header_t **ppArray;
+
+        pArray=apr_array_make(apr_hook_global_pool,1,
+                              sizeof(apr_LINK__optional_t));
+        if(!s_phOptionalHooks)
+            s_phOptionalHooks=apr_hash_make(apr_hook_global_pool);
+        ppArray=apr_palloc(apr_hook_global_pool,sizeof *ppArray);
+        *ppArray=pArray;
+        apr_hash_set(s_phOptionalHooks,szName,strlen(szName),ppArray);
+        apr_hook_sort_register(szName,ppArray);
+    }
+    pHook=apr_array_push(pArray);
+    pHook->pFunc=pfn;
+    pHook->aszPredecessors=aszPre;
+    pHook->aszSuccessors=aszSucc;
+    pHook->nOrder=nOrder;
+    pHook->szName=apr_hook_debug_current;
+    if(apr_hook_debug_enabled)
+        apr_hook_debug_show(szName,aszPre,aszSucc);
+}
+
+/* optional function support */
+
+APR_DECLARE(apr_opt_fn_t *) apr_dynamic_fn_retrieve(const char *szName)
+{
+#ifdef NETWARE
+    get_apd
+#endif
+    if(!s_phOptionalFunctions)
+        return NULL;
+    return (void(*)(void))apr_hash_get(s_phOptionalFunctions,szName,strlen(szName));
+}
+
+/* Deprecated */
+APR_DECLARE_NONSTD(void) apr_dynamic_fn_register(const char *szName,
+                                                  apr_opt_fn_t *pfn)
+{
+#ifdef NETWARE
+    get_apd
+#endif
+    if(!s_phOptionalFunctions)
+        s_phOptionalFunctions=apr_hash_make(apr_hook_global_pool);
+    apr_hash_set(s_phOptionalFunctions,szName,strlen(szName),(void *)pfn);
+}
+
+#if 0
+void main()
+{
+    const char *aszAPre[]={"b","c",NULL};
+    const char *aszBPost[]={"a",NULL};
+    const char *aszCPost[]={"b",NULL};
+    TSortData t1[]=
+    {
+        { "a",aszAPre,NULL },
+        { "b",NULL,aszBPost },
+        { "c",NULL,aszCPost }
+    };
+    TSort *pResult;
+
+    pResult=prepare(t1,3);
+    pResult=tsort(pResult,3);
+
+    for( ; pResult ; pResult=pResult->pNext)
+        printf("%s\n",pResult->pData->szName);
+}
+#endif
diff --git a/i18n/unix/.cvsignore b/i18n/unix/.cvsignore
deleted file mode 100644
index f3c7a7c5da6..00000000000
--- a/i18n/unix/.cvsignore
+++ /dev/null
@@ -1 +0,0 @@
-Makefile
diff --git a/i18n/unix/Makefile.in b/i18n/unix/Makefile.in
deleted file mode 100644
index 99b72897335..00000000000
--- a/i18n/unix/Makefile.in
+++ /dev/null
@@ -1,45 +0,0 @@
-
-RM=@RM@
-CC=@CC@
-RANLIB=@RANLIB@
-CFLAGS=@CFLAGS@ @OPTIM@
-LIBS=@LIBS@
-LDFLAGS=@LDFLAGS@ $(LIBS)
-INCDIR=../../include
-INCLUDES=-I$(INCDIR) -I.
-
-OBJS=xlate.o
-
-.c.o:
-	$(CC) $(CFLAGS) -c $(INCLUDES) $<
-
-all: $(OBJS)
-
-clean:
-	$(RM) -f *.o *.a *.so
-
-distclean: clean
-	-$(RM) -f Makefile
-
-$(OBJS): Makefile
-
-#
-# We really don't expect end users to use this rule.  It works only with
-# gcc, and rebuilds Makefile.tmpl.  You have to re-run Configure after
-# using it.
-#
-depend:
-	cp Makefile.in Makefile.in.bak \
-	    && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.in > Makefile.new \
-	    && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \
-	    && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
-	           -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
-		> Makefile.in \
-	    && rm Makefile.new
-
-# DO NOT REMOVE
-xlate.o: xlate.c $(INCDIR)/apr_private.h $(INCDIR)/apr_lib.h \
- $(INCDIR)/apr_general.h $(INCDIR)/apr.h \
- $(INCDIR)/apr_errno.h $(INCDIR)/apr_file_io.h \
- $(INCDIR)/apr_time.h $(INCDIR)/apr_thread_proc.h \
- $(INCDIR)/apr_xlate.h
diff --git a/i18n/unix/xlate.c b/i18n/unix/xlate.c
deleted file mode 100644
index ce9db86c58e..00000000000
--- a/i18n/unix/xlate.c
+++ /dev/null
@@ -1,282 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "apr_private.h"
-
-#include "apr_lib.h"
-#include "apr_xlate.h"
-
-/* If no implementation is available, don't generate code here since
- * apr_xlate.h emitted macros which return APR_ENOTIMPL.
- */
-
-#if APR_HAS_XLATE
-
-#ifdef HAVE_ICONV_H
-#include <iconv.h>
-#endif
-
-#ifndef min
-#define min(x,y) ((x) <= (y) ? (x) : (y))
-#endif
-
-struct ap_xlate_t {
-    ap_pool_t *pool;
-    char *frompage;
-    char *topage;
-    char *sbcs_table;
-#ifdef HAVE_ICONV
-    iconv_t ich;
-#endif
-};
-
-/* get_default_codepage()
- *
- * simple heuristic to determine codepage of source code so that
- * literal strings (e.g., "GET /\r\n") in source code can be translated
- * properly
- *
- * If appropriate, a symbol can be set at configure time to determine
- * this.  On EBCDIC platforms, it will be important how the code was
- * unpacked.
- */
-
-static const char *get_default_codepage(void)
-{
-#ifdef __MVS__
-    #ifdef __CODESET__
-        return __CODESET__;
-    #else
-        return "IBM-1047";
-    #endif
-#endif
-
-    if ('}' == 0xD0) {
-        return "IBM-1047";
-    }
-
-    if ('{' == 0xFB) {
-        return "EDF04";
-    }
-
-    if ('A' == 0xC1) {
-        return "EBCDIC"; /* not useful */
-    }
-
-    if ('A' == 0x41) {
-        return "ISO8859-1"; /* not necessarily true */
-    }
-
-    return "unknown";
-}
-
-static ap_status_t ap_xlate_cleanup(void *convset)
-{
-#ifdef HAVE_ICONV
-    ap_xlate_t *old = convset;
-
-    if (old->ich != (iconv_t)-1) {
-        if (iconv_close(old->ich)) {
-            return errno;
-        }
-    }
-#endif
-    return APR_SUCCESS;
-}
-
-#ifdef HAVE_ICONV
-static void check_sbcs(ap_xlate_t *convset)
-{
-    char inbuf[256], outbuf[256];
-    char *inbufptr = inbuf, *outbufptr = outbuf;
-    size_t inbytes_left, outbytes_left;
-    int i;
-    size_t translated;
-
-    for (i = 0; i < sizeof(inbuf); i++) {
-        inbuf[i] = i;
-    }
-
-    inbytes_left = outbytes_left = sizeof(inbuf);
-    translated = iconv(convset->ich, (const char **)&inbufptr, 
-                       &inbytes_left, &outbufptr, &outbytes_left);
-    if (translated != (size_t) -1 &&
-        inbytes_left == 0 &&
-        outbytes_left == 0) {
-        /* hurray... this is simple translation; save the table,
-         * close the iconv descriptor
-         */
-        
-        convset->sbcs_table = ap_palloc(convset->pool, sizeof(outbuf));
-        memcpy(convset->sbcs_table, outbuf, sizeof(outbuf));
-        iconv_close(convset->ich);
-        convset->ich = (iconv_t)-1;
-
-        /* TODO: add the table to the cache */
-    }
-}
-#endif /* HAVE_ICONV */
-
-ap_status_t ap_xlate_open(ap_xlate_t **convset, const char *topage,
-                          const char *frompage, ap_pool_t *pool)
-{
-    ap_status_t status;
-    ap_xlate_t *new;
-    int found = 0;
-
-    *convset = NULL;
-    
-    if (!topage) {
-        topage = get_default_codepage();
-    }
-
-    if (!frompage) {
-        frompage = get_default_codepage();
-    }
-    
-    new = (ap_xlate_t *)ap_palloc(pool, sizeof(ap_xlate_t));
-    if (!new) {
-        return APR_ENOMEM;
-    }
-
-    new->pool = pool;
-    new->topage = ap_pstrdup(pool, topage);
-    new->frompage = ap_pstrdup(pool, frompage);
-    if (!new->topage || !new->frompage) {
-        return APR_ENOMEM;
-    }
-
-#ifdef TODO
-    /* search cache of codepage pairs; we may be able to avoid the
-     * expensive iconv_open()
-     */
-
-    set found to non-zero if found in the cache
-#endif
-
-#ifdef HAVE_ICONV
-    if (!found) {
-        new->ich = iconv_open(topage, frompage);
-        if (new->ich == (iconv_t)-1) {
-            return errno;
-        }
-        found = 1;
-        check_sbcs(new);
-    }
-#endif /* HAVE_ICONV */
-
-    if (found) {
-        *convset = new;
-        ap_register_cleanup(pool, (void *)new, ap_xlate_cleanup,
-                            ap_null_cleanup);
-        status = APR_SUCCESS;
-    }
-    else {
-        status = EINVAL; /* same as what iconv() would return if it
-                            couldn't handle the pair */
-    }
-    
-    return status;
-}
-
-ap_status_t ap_xlate_conv_buffer(ap_xlate_t *convset, const char *inbuf,
-                                 ap_size_t *inbytes_left, char *outbuf,
-                                 ap_size_t *outbytes_left)
-{
-    ap_status_t status = APR_SUCCESS;
-#ifdef HAVE_ICONV
-    size_t translated;
-
-    if (convset->ich != (iconv_t)-1) {
-        char *inbufptr = (char *)inbuf;
-        char *outbufptr = outbuf;
-        
-        translated = iconv(convset->ich, (const char **)&inbufptr, 
-                           inbytes_left, &outbufptr, outbytes_left);
-        if (translated == (size_t)-1) {
-            return errno;
-        }
-    }
-    else
-#endif
-    {
-        int to_convert = min(*inbytes_left, *outbytes_left);
-        int converted = to_convert;
-        char *table = convset->sbcs_table;
-        
-        while (to_convert) {
-            *outbuf = table[(unsigned char)*inbuf];
-            ++outbuf;
-            ++inbuf;
-            --to_convert;
-        }
-        *inbytes_left -= converted;
-        *outbytes_left -= converted;
-    }
-
-    return status;
-}
-
-ap_status_t ap_xlate_close(ap_xlate_t *convset)
-{
-    ap_status_t status;
-
-    if ((status = ap_xlate_cleanup(convset)) == APR_SUCCESS) {
-        ap_kill_cleanup(convset->pool, convset, ap_xlate_cleanup);
-    }
-
-    return status;
-}
-
-#endif /* APR_HAS_XLATE */
diff --git a/include/.cvsignore b/include/.cvsignore
deleted file mode 100644
index e5db22b8d0b..00000000000
--- a/include/.cvsignore
+++ /dev/null
@@ -1,3 +0,0 @@
-apr.h
-apr_private.h
-apr_private.h.in
diff --git a/include/apr.h.in b/include/apr.h.in
index ce4e597755e..ea936158a50 100644
--- a/include/apr.h.in
+++ b/include/apr.h.in
@@ -1,6 +1,50 @@
+/* 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 APR_H
 #define APR_H
 
+/* GENERATED FILE WARNING!  DO NOT EDIT apr.h
+ *
+ * You must modify apr.h.in instead.
+ *
+ * And please, make an effort to stub apr.hw and apr.hnw in the process.
+ */
+
+/**
+ * @file apr.h
+ * @brief APR Platform Definitions
+ * @remark This is a generated header generated from include/apr.h.in by
+ * ./configure, or copied from include/apr.hw or include/apr.hnw 
+ * for Win32 or Netware by those build environments, respectively.
+ */
+
+/**
+ * @defgroup APR Apache Portability Runtime library
+ * @{
+ */
+/**
+ * @defgroup apr_platform Platform Definitions
+ * @{
+ * @warning
+ * <strong><em>The actual values of macros and typedefs on this page<br>
+ * are platform specific and should NOT be relied upon!</em></strong>
+ */
+
 /* So that we can use inline on some critical functions, and use
  * GNUC attributes (such as to get -Wall warnings for printf-like
  * functions).  Only do this in gcc 2.7 or later ... it may work
@@ -15,45 +59,228 @@
 #if !defined(__GNUC__) || __GNUC__ < 2 || \
     (__GNUC__ == 2 && __GNUC_MINOR__ < 7) ||\
     defined(NEXT)
-#define ap_inline
+#ifndef __attribute__
 #define __attribute__(__x)
-#define ENUM_BITFIELD(e,n,w)  signed int n : w
+#endif
+#define APR_INLINE
+#define APR_HAS_INLINE          0
+#else
+#define APR_INLINE __inline__
+#define APR_HAS_INLINE          1
+#endif
+
+#define APR_HAVE_ARPA_INET_H     @arpa_ineth@
+#define APR_HAVE_CONIO_H         @conioh@
+#define APR_HAVE_CRYPT_H         @crypth@
+#define APR_HAVE_CTYPE_H         @ctypeh@
+#define APR_HAVE_DIRENT_H        @direnth@
+#define APR_HAVE_ERRNO_H         @errnoh@
+#define APR_HAVE_FCNTL_H         @fcntlh@
+#define APR_HAVE_IFADDRS_H       @ifaddrsh@
+#define APR_HAVE_IO_H            @ioh@
+#define APR_HAVE_LIMITS_H        @limitsh@
+#define APR_HAVE_MSWSOCK_H       @mswsockh@
+#define APR_HAVE_NETDB_H         @netdbh@
+#define APR_HAVE_NETINET_IN_H    @netinet_inh@
+#define APR_HAVE_NETINET_SCTP_H  @netinet_sctph@
+#define APR_HAVE_NETINET_SCTP_UIO_H @netinet_sctp_uioh@
+#define APR_HAVE_NETINET_TCP_H   @netinet_tcph@
+#define APR_HAVE_PROCESS_H       @processh@
+#define APR_HAVE_PTHREAD_H       @pthreadh@
+#define APR_HAVE_SEMAPHORE_H     @semaphoreh@
+#define APR_HAVE_SIGNAL_H        @signalh@
+#define APR_HAVE_STDARG_H        @stdargh@
+#define APR_HAVE_STDDEF_H        @stddefh@
+#define APR_HAVE_STDINT_H        @stdint@
+#define APR_HAVE_STDIO_H         @stdioh@
+#define APR_HAVE_STDLIB_H        @stdlibh@
+#define APR_HAVE_STRING_H        @stringh@
+#define APR_HAVE_STRINGS_H       @stringsh@
+#define APR_HAVE_SYS_IOCTL_H     @sys_ioctlh@
+#define APR_HAVE_SYS_SENDFILE_H  @sys_sendfileh@
+#define APR_HAVE_SYS_SIGNAL_H    @sys_signalh@
+#define APR_HAVE_SYS_SOCKET_H    @sys_socketh@
+#define APR_HAVE_SYS_SOCKIO_H    @sys_sockioh@
+#define APR_HAVE_SYS_SYSLIMITS_H @sys_syslimitsh@
+#define APR_HAVE_SYS_TIME_H      @sys_timeh@
+#define APR_HAVE_SYS_TYPES_H     @sys_typesh@
+#define APR_HAVE_SYS_UIO_H       @sys_uioh@
+#define APR_HAVE_SYS_UN_H        @sys_unh@
+#define APR_HAVE_SYS_WAIT_H      @sys_waith@
+#define APR_HAVE_TIME_H          @timeh@
+#define APR_HAVE_UNISTD_H        @unistdh@
+#define APR_HAVE_WINDOWS_H       @windowsh@
+#define APR_HAVE_WINSOCK2_H      @winsock2h@
+#define APR_HAVE_WS2TCPIP_H      @ws2tcpiph@
+
+/** @} */
+/** @} */
+
+/* We don't include our conditional headers within the doxyblocks 
+ * or the extern "C" namespace 
+ */
+
+#if APR_HAVE_WINDOWS_H && defined(WIN32)
+/* If windows.h was already included, our preferences don't matter.
+ * If not, include a restricted set of windows headers to our tastes.
+ */
+#ifndef _WINDOWS_
+
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0501
+#endif
+
+#ifndef NOUSER
+#define NOUSER
+#endif
+#ifndef NOMCX
+#define NOMCX
+#endif
+#ifndef NOIME
+#define NOIME
+#endif
+
+/* Impossible to include winsock2.h after winsock.h, while windows.h
+ * attempts to load winsock.  Setting _WINSOCKAPI_ will dodge this.
+ */
+#if APR_HAVE_WINSOCK2_H
+#define _WINSOCKAPI_
+#endif
+
+#include <windows.h>
+#endif /* ndef _WINDOWS_ */
+#endif /* APR_HAVE_WINDOWS_H */
+
+#if APR_HAVE_WINSOCK2_H
+#include <winsock2.h>
+
+#if APR_HAVE_WS2TCPIP_H
+#include <ws2tcpip.h>
+#endif
+
+#if APR_HAVE_MSWSOCK_H
+#include <mswsock.h>
+#endif
+
+#else /* !APR_HAVE_WINSOCK2_H */
+
+#if APR_HAVE_WINSOCK_H
+#include <winsock.h>
+#endif
+
+#endif /* !APR_HAVE_WINSOCK2_H */
+
+#if APR_HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#if APR_HAVE_STDDEF_H
+#include <stddef.h>
+#endif
+
+#if APR_HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#if defined(__cplusplus) && !defined(__STDC_CONSTANT_MACROS)
+/* C99 7.18.4 requires that stdint.h only exposes INT64_C 
+ * and UINT64_C for C++ implementations if this is defined: */
+#define __STDC_CONSTANT_MACROS
+#endif
+
+#if APR_HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#if APR_HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+
+#ifdef OS2
+#define INCL_DOS
+#define INCL_DOSERRORS
+#include <os2.h>
+#endif
+
+/* header files for PATH_MAX, _POSIX_PATH_MAX */
+#if APR_HAVE_LIMITS_H
+#include <limits.h>
 #else
-#define ap_inline __inline__
-#define USE_GNU_INLINE
-#define ENUM_BITFIELD(e,n,w)  e n : w
+#if APR_HAVE_SYS_SYSLIMITS_H
+#include <sys/syslimits.h>
+#endif
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
 #endif
 
-#define APR_HAVE_ERRNO_H        @errnoh@
-#define APR_HAVE_DIRENT_H       @direnth@
-#define APR_HAVE_FCNTL_H        @fcntlh@
-#define APR_HAVE_NETINET_IN_H   @netinet_inh@
-#define APR_HAVE_PTHREAD_H      @pthreadh@
-#define APR_HAVE_STDARG_H       @stdargh@
-#define APR_HAVE_STDIO_H        @stdioh@
-#define APR_HAVE_SYS_TYPES_H    @sys_typesh@
-#define APR_HAVE_SYS_UIO_H      @sys_uioh@
-#define APR_HAVE_SIGNAL_H       @signalh@
+/**
+ * @addtogroup apr_platform
+ * @ingroup APR 
+ * @{
+ */
+
+#define APR_HAVE_SHMEM_MMAP_TMP     @havemmaptmp@
+#define APR_HAVE_SHMEM_MMAP_SHM     @havemmapshm@
+#define APR_HAVE_SHMEM_MMAP_ZERO    @havemmapzero@
+#define APR_HAVE_SHMEM_SHMGET_ANON  @haveshmgetanon@
+#define APR_HAVE_SHMEM_SHMGET       @haveshmget@
+#define APR_HAVE_SHMEM_MMAP_ANON    @havemmapanon@
+#define APR_HAVE_SHMEM_BEOS         @havebeosarea@
+
+#define APR_USE_SHMEM_MMAP_TMP     @usemmaptmp@
+#define APR_USE_SHMEM_MMAP_SHM     @usemmapshm@
+#define APR_USE_SHMEM_MMAP_ZERO    @usemmapzero@
+#define APR_USE_SHMEM_SHMGET_ANON  @useshmgetanon@
+#define APR_USE_SHMEM_SHMGET       @useshmget@
+#define APR_USE_SHMEM_MMAP_ANON    @usemmapanon@
+#define APR_USE_SHMEM_BEOS         @usebeosarea@
 
 #define APR_USE_FLOCK_SERIALIZE           @flockser@ 
 #define APR_USE_SYSVSEM_SERIALIZE         @sysvser@
+#define APR_USE_POSIXSEM_SERIALIZE        @posixser@
 #define APR_USE_FCNTL_SERIALIZE           @fcntlser@
 #define APR_USE_PROC_PTHREAD_SERIALIZE    @procpthreadser@ 
 #define APR_USE_PTHREAD_SERIALIZE         @pthreadser@ 
 
-#define APR_USES_ANONYMOUS_SHM            @anonymous_shm@
-#define APR_USES_FILEBASED_SHM            @filebased_shm@
-#define APR_USES_KEYBASED_SHM             @keybased_shm@
+#define APR_HAS_FLOCK_SERIALIZE           @hasflockser@
+#define APR_HAS_SYSVSEM_SERIALIZE         @hassysvser@
+#define APR_HAS_POSIXSEM_SERIALIZE        @hasposixser@
+#define APR_HAS_FCNTL_SERIALIZE           @hasfcntlser@
+#define APR_HAS_PROC_PTHREAD_SERIALIZE    @hasprocpthreadser@
 
+#define APR_PROCESS_LOCK_IS_GLOBAL        @proclockglobal@
 
+#define APR_HAVE_CORKABLE_TCP   @have_corkable_tcp@ 
+#define APR_HAVE_GETRLIMIT      @have_getrlimit@
 #define APR_HAVE_IN_ADDR        @have_in_addr@
-#define APR_HAVE_INET_ADDR      @inet_addr@
-#define APR_HAVE_INET_NETWORK   @inet_network@
+#define APR_HAVE_INET_ADDR      @have_inet_addr@
+#define APR_HAVE_INET_NETWORK   @have_inet_network@
+#define APR_HAVE_IPV6           @have_ipv6@
+#define APR_HAVE_SOCKADDR_UN    @have_sockaddr_un@
+#define APR_HAVE_MEMMOVE        @have_memmove@
+#define APR_HAVE_SETRLIMIT      @have_setrlimit@
+#define APR_HAVE_SIGACTION      @have_sigaction@
+#define APR_HAVE_SIGSUSPEND     @have_sigsuspend@
+#define APR_HAVE_SIGWAIT        @have_sigwait@
+#define APR_HAVE_SA_STORAGE     @have_sa_storage@
+#define APR_HAVE_STRCASECMP     @have_strcasecmp@
+#define APR_HAVE_STRDUP         @have_strdup@
+#define APR_HAVE_STRICMP        @have_stricmp@
+#define APR_HAVE_STRNCASECMP    @have_strncasecmp@
+#define APR_HAVE_STRNICMP       @have_strnicmp@
+#define APR_HAVE_STRSTR         @have_strstr@
+#define APR_HAVE_MEMCHR         @have_memchr@
+#define APR_HAVE_STRUCT_RLIMIT  @struct_rlimit@
 #define APR_HAVE_UNION_SEMUN    @have_union_semun@
-
-#if APR_HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
+#define APR_HAVE_SCTP           @have_sctp@
+#define APR_HAVE_IOVEC          @have_iovec@
 
 /*  APR Feature Macros */
 #define APR_HAS_SHARED_MEMORY     @sharedmem@
@@ -62,30 +289,279 @@
 #define APR_HAS_MMAP              @mmap@
 #define APR_HAS_FORK              @fork@
 #define APR_HAS_RANDOM            @rand@
-#define APR_HAS_XLATE             @iconv@
+#define APR_HAS_OTHER_CHILD       @oc@
+#define APR_HAS_DSO               @aprdso@
+#define APR_HAS_SO_ACCEPTFILTER   @acceptfilter@
+#define APR_HAS_UNICODE_FS        @have_unicode_fs@
+#define APR_HAS_PROC_INVOKED      @have_proc_invoked@
+#define APR_HAS_USER              @apr_has_user@
+#define APR_HAS_LARGE_FILES       @aprlfs@
+#define APR_HAS_XTHREAD_FILES     @apr_has_xthread_files@
+#define APR_HAS_OS_UUID           @osuuid@
+
+#define APR_PROCATTR_USER_SET_REQUIRES_PASSWORD @apr_procattr_user_set_requires_password@
+
+/* APR sets APR_FILES_AS_SOCKETS to 1 on systems where it is possible
+ * to poll on files/pipes.
+ */
+#define APR_FILES_AS_SOCKETS      @file_as_socket@
+
+/* This macro indicates whether or not EBCDIC is the native character set.
+ */
+#define APR_CHARSET_EBCDIC        @apr_charset_ebcdic@
+
+/* If we have a TCP implementation that can be "corked", what flag
+ * do we use?
+ */
+#define APR_TCP_NOPUSH_FLAG       @apr_tcp_nopush_flag@
+
+/* Is the TCP_NODELAY socket option inherited from listening sockets?
+*/
+#define APR_TCP_NODELAY_INHERITED @tcp_nodelay_inherited@
+
+/* Is the O_NONBLOCK flag inherited from listening sockets?
+*/
+#define APR_O_NONBLOCK_INHERITED @o_nonblock_inherited@
 
 /* Typedefs that APR needs. */
 
-typedef  @short_value@           ap_int16_t;
-typedef  unsigned @short_value@  ap_uint16_t;
-                                               
-typedef  @int_value@             ap_int32_t;
-typedef  unsigned @int_value@    ap_uint32_t;
-                                               
-typedef  @long_value@            ap_int64_t;
-typedef  unsigned @long_value@   ap_uint64_t;
+typedef  unsigned char           apr_byte_t;
+
+typedef  @short_value@           apr_int16_t;
+typedef  unsigned @short_value@  apr_uint16_t;
+
+typedef  @int_value@             apr_int32_t;
+typedef  unsigned @int_value@    apr_uint32_t;
+
+#define APR_SIZEOF_VOIDP @voidp_size@
+
+/*
+ * Darwin 10's default compiler (gcc42) builds for both 64 and
+ * 32 bit architectures unless specifically told not to.
+ * In those cases, we need to override types depending on how
+ * we're being built at compile time.
+ * NOTE: This is an ugly work-around for Darwin's
+ * concept of universal binaries, a single package
+ * (executable, lib, etc...) which contains both 32
+ * and 64 bit versions. The issue is that if APR is
+ * built universally, if something else is compiled
+ * against it, some bit sizes will depend on whether
+ * it is 32 or 64 bit. This is determined by the __LP64__
+ * flag. Since we need to support both, we have to
+ * handle OS X unqiuely.
+ */
+#ifdef DARWIN_10
+#undef APR_SIZEOF_VOIDP
+#undef INT64_C
+#undef UINT64_C
+#ifdef __LP64__
+ typedef  long            apr_int64_t;
+ typedef  unsigned long   apr_uint64_t;
+ #define APR_SIZEOF_VOIDP     8
+ #define INT64_C(v)   (v ## L)
+ #define UINT64_C(v)  (v ## UL)
+#else
+ typedef  long long            apr_int64_t;
+ typedef  unsigned long long   apr_uint64_t;
+ #define APR_SIZEOF_VOIDP     4
+ #define INT64_C(v)   (v ## LL)
+ #define UINT64_C(v)  (v ## ULL)
+#endif
+#else
+ typedef  @long_value@            apr_int64_t;
+ typedef  unsigned @long_value@   apr_uint64_t;
+#endif
+
+typedef  @size_t_value@          apr_size_t;
+typedef  @ssize_t_value@         apr_ssize_t;
+typedef  @off_t_value@           apr_off_t;
+typedef  @socklen_t_value@       apr_socklen_t;
+typedef  @ino_t_value@           apr_ino_t;
+
+#if APR_SIZEOF_VOIDP == 8
+typedef  apr_uint64_t            apr_uintptr_t;
+typedef  apr_int64_t             apr_intptr_t;
+#else
+typedef  apr_uint32_t            apr_uintptr_t;
+typedef  apr_int32_t             apr_intptr_t;
+#endif
+
+/* Are we big endian? */
+#define APR_IS_BIGENDIAN        @bigendian@
+
+/* Mechanisms to properly type numeric literals */
+@int64_literal@
+@uint64_literal@
+
+#ifdef INT16_MIN
+#define APR_INT16_MIN   INT16_MIN
+#else
+#define APR_INT16_MIN   (-0x7fff - 1)
+#endif
+
+#ifdef INT16_MAX
+#define APR_INT16_MAX  INT16_MAX
+#else
+#define APR_INT16_MAX   (0x7fff)
+#endif
+
+#ifdef UINT16_MAX
+#define APR_UINT16_MAX  UINT16_MAX
+#else
+#define APR_UINT16_MAX  (0xffff)
+#endif
+
+#ifdef INT32_MIN
+#define APR_INT32_MIN   INT32_MIN
+#else
+#define APR_INT32_MIN   (-0x7fffffff - 1)
+#endif
+
+#ifdef INT32_MAX
+#define APR_INT32_MAX  INT32_MAX
+#else
+#define APR_INT32_MAX  0x7fffffff
+#endif
+
+#ifdef UINT32_MAX
+#define APR_UINT32_MAX  UINT32_MAX
+#else
+#define APR_UINT32_MAX  (0xffffffffU)
+#endif
+
+#ifdef INT64_MIN
+#define APR_INT64_MIN   INT64_MIN
+#else
+#define APR_INT64_MIN   (APR_INT64_C(-0x7fffffffffffffff) - 1)
+#endif
+
+#ifdef INT64_MAX
+#define APR_INT64_MAX   INT64_MAX
+#else
+#define APR_INT64_MAX   APR_INT64_C(0x7fffffffffffffff)
+#endif
+
+#ifdef UINT64_MAX
+#define APR_UINT64_MAX  UINT64_MAX
+#else
+#define APR_UINT64_MAX  APR_UINT64_C(0xffffffffffffffff)
+#endif
+
+#define APR_SIZE_MAX    (~((apr_size_t)0))
 
-typedef  @size_t_value@          ap_size_t;
-typedef  @ssize_t_value@         ap_ssize_t;
-typedef  @off_t_value@           ap_off_t;
 
 /* Definitions that APR programs need to work properly. */
 
-#define API_THREAD_FUNC
-#define API_EXPORT(type)         type
-#define API_EXPORT_NONSTD(type)  type
-#define API_VAR_IMPORT           extern
-#define API_VAR_EXPORT           
+/**
+ * APR public API wrap for C++ compilers.
+ */
+#ifdef __cplusplus
+#define APR_BEGIN_DECLS     extern "C" {
+#define APR_END_DECLS       }
+#else
+#define APR_BEGIN_DECLS
+#define APR_END_DECLS
+#endif
+
+/** 
+ * Thread callbacks from APR functions must be declared with APR_THREAD_FUNC, 
+ * so that they follow the platform's calling convention.
+ * <PRE>
+ *
+ * void* APR_THREAD_FUNC my_thread_entry_fn(apr_thread_t *thd, void *data);
+ *
+ * </PRE>
+ */
+#define APR_THREAD_FUNC       @apr_thread_func@
+
+#if defined(DOXYGEN) || !defined(WIN32)
+
+/**
+ * The public APR functions are declared with APR_DECLARE(), so they may
+ * use the most appropriate calling convention.  Public APR functions with 
+ * variable arguments must use APR_DECLARE_NONSTD().
+ *
+ * @remark Both the declaration and implementations must use the same macro.
+ *
+ * <PRE>
+ * APR_DECLARE(rettype) apr_func(args)
+ * </PRE>
+ * @see APR_DECLARE_NONSTD @see APR_DECLARE_DATA
+ * @remark Note that when APR compiles the library itself, it passes the 
+ * symbol -DAPR_DECLARE_EXPORT to the compiler on some platforms (e.g. Win32) 
+ * to export public symbols from the dynamic library build.\n
+ * The user must define the APR_DECLARE_STATIC when compiling to target
+ * the static APR library on some platforms (e.g. Win32.)  The public symbols 
+ * are neither exported nor imported when APR_DECLARE_STATIC is defined.\n
+ * By default, compiling an application and including the APR public
+ * headers, without defining APR_DECLARE_STATIC, will prepare the code to be
+ * linked to the dynamic library.
+ */
+#define APR_DECLARE(type)            type 
+
+/**
+ * The public APR functions using variable arguments are declared with 
+ * APR_DECLARE_NONSTD(), as they must follow the C language calling convention.
+ * @see APR_DECLARE @see APR_DECLARE_DATA
+ * @remark Both the declaration and implementations must use the same macro.
+ * <PRE>
+ *
+ * APR_DECLARE_NONSTD(rettype) apr_func(args, ...);
+ *
+ * </PRE>
+ */
+#define APR_DECLARE_NONSTD(type)     type
+
+/**
+ * The public APR variables are declared with APR_DECLARE_DATA.
+ * This assures the appropriate indirection is invoked at compile time.
+ * @see APR_DECLARE @see APR_DECLARE_NONSTD
+ * @remark Note that the declaration and implementations use different forms,
+ * but both must include the macro.
+ * 
+ * <PRE>
+ *
+ * extern APR_DECLARE_DATA type apr_variable;\n
+ * APR_DECLARE_DATA type apr_variable = value;
+ *
+ * </PRE>
+ */
+#define APR_DECLARE_DATA
+
+#elif defined(APR_DECLARE_STATIC)
+#define APR_DECLARE(type)            type __stdcall
+#define APR_DECLARE_NONSTD(type)     type __cdecl
+#define APR_DECLARE_DATA
+#elif defined(APR_DECLARE_EXPORT)
+#define APR_DECLARE(type)            __declspec(dllexport) type __stdcall
+#define APR_DECLARE_NONSTD(type)     __declspec(dllexport) type __cdecl
+#define APR_DECLARE_DATA             __declspec(dllexport)
+#else
+#define APR_DECLARE(type)            __declspec(dllimport) type __stdcall
+#define APR_DECLARE_NONSTD(type)     __declspec(dllimport) type __cdecl
+#define APR_DECLARE_DATA             __declspec(dllimport)
+#endif
+
+#if !defined(WIN32) || defined(APU_MODULE_DECLARE_STATIC)
+/**
+ * Declare a dso module's exported module structure as APR_MODULE_DECLARE_DATA.
+ *
+ * Unless APR_MODULE_DECLARE_STATIC is defined at compile time, symbols 
+ * declared with APR_MODULE_DECLARE_DATA are always exported.
+ * @code
+ * module APR_MODULE_DECLARE_DATA mod_tag
+ * @endcode
+ */
+#define APR_MODULE_DECLARE_DATA
+#else
+#define APR_MODULE_DECLARE_DATA           __declspec(dllexport)
+#endif
+
+/**
+ * @deprecated
+ * @see APR_MODULE_DECLARE_DATA
+ */
+#define APU_MODULE_DECLARE_DATA           APR_MODULE_DECLARE_DATA
 
 /* Define APR_SSIZE_T_FMT.  
  * If ssize_t is an integer we define it to be "d",
@@ -95,25 +571,143 @@ typedef  @off_t_value@           ap_off_t;
  * to find the logic for this definition search for "ssize_t_fmt" in
  * configure.in.
  */
+
 @ssize_t_fmt@
 
+/* And APR_SIZE_T_FMT */
+@size_t_fmt@
+
 /* And APR_OFF_T_FMT */
 @off_t_fmt@
 
-/* Define ap_signal and related necessary definitions.
- */
-/* We are checking for HAVE_SIGACTION, but autoconf is filling this in 
- * for us automatically.
+/* And APR_PID_T_FMT */
+@pid_t_fmt@
+
+/* And APR_INT64_T_FMT */
+@int64_t_fmt@
+
+/* And APR_UINT64_T_FMT */
+@uint64_t_fmt@
+
+/* And APR_UINT64_T_HEX_FMT */
+@uint64_t_hex_fmt@
+
+/*
+ * Ensure we work with universal binaries on Darwin
  */
-#if @have_sigaction@ && !defined(NO_USE_SIGACTION)
-typedef void Sigfunc(int);
-Sigfunc *ap_signal(int signo, Sigfunc * func);
+#ifdef DARWIN_10
+
+#undef APR_HAS_LARGE_FILES
+#undef APR_SIZEOF_VOIDP
+#undef APR_INT64_T_FMT
+#undef APR_UINT64_T_FMT
+#undef APR_UINT64_T_HEX_FMT
+
+#ifdef __LP64__
+ #define APR_HAS_LARGE_FILES  0
+ #define APR_SIZEOF_VOIDP     8
+ #define APR_INT64_T_FMT      "ld"
+ #define APR_UINT64_T_FMT     "lu"
+ #define APR_UINT64_T_HEX_FMT "lx"
+#else
+ #define APR_HAS_LARGE_FILES  1
+ #define APR_SIZEOF_VOIDP     4
+ #define APR_INT64_T_FMT      "lld"
+ #define APR_UINT64_T_FMT     "llu"
+ #define APR_UINT64_T_HEX_FMT "llx"
+#endif
+
+#undef APR_IS_BIGENDIAN
+#ifdef __BIG_ENDIAN__
+ #define APR_IS_BIGENDIAN       1
+#else
+ #define APR_IS_BIGENDIAN       0
+#endif
 
-#if defined(SIG_ING) && !defined(SIG_ERR)
-#define SIG_ERR ((Sigfunc *)-1)
+#undef APR_OFF_T_FMT
+#define APR_OFF_T_FMT "lld"
+
+#endif /* DARWIN_10 */
+
+/* Does the proc mutex lock threads too */
+#ifdef WIN32
+#define APR_PROC_MUTEX_IS_GLOBAL      1
+#else
+#define APR_PROC_MUTEX_IS_GLOBAL      @proc_mutex_is_global@
 #endif
+
+/* Local machine definition for console and log output. */
+#define APR_EOL_STR              "@eolstr@"
+
+#if APR_HAVE_SYS_WAIT_H
+#ifdef WEXITSTATUS
+#define apr_wait_t       int
+#else
+#define apr_wait_t       union wait
+#define WEXITSTATUS(status)    (int)((status).w_retcode)
+#define WTERMSIG(status)       (int)((status).w_termsig)
+#endif /* !WEXITSTATUS */
+#elif defined(__MINGW32__)
+typedef int apr_wait_t;
+#endif /* HAVE_SYS_WAIT_H */
+
+#if defined(PATH_MAX)
+#define APR_PATH_MAX       PATH_MAX
+#elif defined(_POSIX_PATH_MAX)
+#define APR_PATH_MAX       _POSIX_PATH_MAX
 #else
-#define ap_signal(a,b) signal(a,b)
+#error no decision has been made on APR_PATH_MAX for your platform
+#endif
+
+#define APR_DSOPATH "@shlibpath_var@"
+
+/** @} */
+
+/*
+ * we always have SDBM (it's in our codebase)
+ */
+#define APU_HAVE_SDBM   @apu_have_sdbm@
+#define APU_HAVE_GDBM   @apu_have_gdbm@
+#define APU_HAVE_NDBM   @apu_have_ndbm@
+#define APU_HAVE_DB     @apu_have_db@
+
+#if APU_HAVE_DB
+#define APU_HAVE_DB_VERSION    @apu_db_version@
+#endif
+
+#define APU_HAVE_PGSQL         @apu_have_pgsql@
+#define APU_HAVE_MYSQL         @apu_have_mysql@
+#define APU_HAVE_SQLITE3       @apu_have_sqlite3@
+#define APU_HAVE_SQLITE2       @apu_have_sqlite2@
+#define APU_HAVE_ORACLE        @apu_have_oracle@
+#define APU_HAVE_ODBC          @apu_have_odbc@
+
+#define APU_HAVE_CRYPTO        @apu_have_crypto@
+#define APU_HAVE_OPENSSL       @apu_have_openssl@
+#define APU_HAVE_NSS           @apu_have_nss@
+#define APU_HAVE_COMMONCRYPTO  @apu_have_commoncrypto@
+
+#define APU_HAVE_ICONV         @have_iconv@
+#define APR_HAS_XLATE          (APU_HAVE_ICONV)
+
+#define APU_USE_EXPAT          @apu_has_expat@
+#define APU_USE_LIBXML2        @apu_has_libxml2@
+
+/* Definitions that only Win32 programs need to compile properly. */
+
+/* XXX These simply don't belong here, perhaps in apr_portable.h
+ * based on some APR_HAVE_PID/GID/UID?
+ */
+#ifdef WIN32
+#ifndef __GNUC__
+typedef  int         pid_t;
+#endif
+typedef  int         uid_t;
+typedef  int         gid_t;
+#endif
+
+#ifdef __cplusplus
+}
 #endif
 
 #endif /* APR_H */
diff --git a/include/apr.hnw b/include/apr.hnw
new file mode 100644
index 00000000000..120201bcee5
--- /dev/null
+++ b/include/apr.hnw
@@ -0,0 +1,502 @@
+/* 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 APR_H
+#define APR_H
+
+/* GENERATED FILE WARNING!  DO NOT EDIT apr.h
+ *
+ * You must modify apr.hnw instead.
+ *
+ * And please, make an effort to stub apr.hw and apr.h.in in the process.
+ *
+ * This is the NetWare specific version of apr.h.  It is copied from
+ * apr.hnw at the start of a NetWare build by the ./build/NWGNmakefile.
+ */
+
+#if defined(NETWARE) || defined(DOXYGEN)
+
+#undef  FD_SETSIZE
+#define FD_SETSIZE 1024
+
+#include <sys/types.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <time.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <netware.h>
+#include <library.h>
+#include <nks/thread.h>
+#include <nks/synch.h>
+#include <nks/time.h>
+#include <signal.h>
+#ifdef USE_WINSOCK
+#include <novsock2.h>
+#ifdef NW_BUILD_IPV6
+#include <novtcpip.h>
+#endif
+#else
+#include <sys/socket.h>
+#include <sys/select.h>
+#endif
+#include <sys/types.h>
+
+#define _POSIX_THREAD_SAFE_FUNCTIONS    1
+#define READDIR_IS_THREAD_SAFE          1
+
+/* Keep #include'd headers from within the __cplusplus or doxyblocks */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup apr_platform Platform Definitions
+ * @ingroup APR
+ * @{
+ */
+
+#define APR_INLINE
+#define APR_HAS_INLINE                  0
+#ifndef __attribute__
+#define __attribute__(__x)
+#endif
+#define ENUM_BITFIELD(e,n,w)  signed int n : w
+
+#define APR_HAVE_CONIO_H                0
+#define APR_HAVE_CRYPT_H                0
+#define APR_HAVE_CTYPE_H                1
+#define APR_HAVE_DIRENT_H               1
+#define APR_HAVE_ERRNO_H                1
+#define APR_HAVE_FCNTL_H                1
+#define APR_HAVE_IO_H                   0
+#define APR_HAVE_LIMITS_H               1
+#ifdef USE_WINSOCK
+#define APR_HAVE_ARPA_INET_H            0
+#define APR_HAVE_NETDB_H                0
+#define APR_HAVE_NETINET_IN_H           0
+#else
+#define APR_HAVE_ARPA_INET_H            1
+#define APR_HAVE_NETDB_H                1
+#define APR_HAVE_NETINET_IN_H           1
+#endif
+#define APR_HAVE_NETINET_SCTP_H         0
+#define APR_HAVE_NETINET_SCTP_UIO_H     0
+#define APR_HAVE_NETINET_TCP_H          0
+#define APR_HAVE_PTHREAD_H              0
+#define APR_HAVE_SIGNAL_H               1
+#define APR_HAVE_STDARG_H               1
+#define APR_HAVE_STDINT_H               0
+#define APR_HAVE_STDIO_H                1
+#define APR_HAVE_STDLIB_H               1
+#define APR_HAVE_STRING_H               1
+#define APR_HAVE_STRINGS_H              0
+#define APR_HAVE_STRTOLL                1
+#define APR_HAVE_SYS_SENDFILE_H         0
+#define APR_HAVE_SYS_SYSLIMITS_H        0
+#ifdef USE_WINSOCK
+#define APR_HAVE_SYS_SOCKET_H           0
+#define APR_HAVE_SYS_SOCKIO_H           0
+#define APR_HAVE_SYS_UN_H               0
+#else
+#define APR_HAVE_SYS_SOCKET_H           1
+#define APR_HAVE_SYS_SOCKIO_H           1
+#define APR_HAVE_SYS_UN_H               1
+#endif
+#define APR_HAVE_SYS_SIGNAL_H           1
+#define APR_HAVE_SYS_TIME_H             1
+#define APR_HAVE_SYS_TYPES_H            1
+#define APR_HAVE_SYS_UIO_H              1
+#define APR_HAVE_SYS_WAIT_H             1
+#define APR_HAVE_TIME_H                 1
+#define APR_HAVE_UNISTD_H               1
+
+#define APR_HAVE_SHMEM_MMAP_TMP         0
+#define APR_HAVE_SHMEM_MMAP_SHM         0
+#define APR_HAVE_SHMEM_MMAP_ZERO        0
+#define APR_HAVE_SHMEM_SHMGET_ANON      0
+#define APR_HAVE_SHMEM_SHMGET           0
+#define APR_HAVE_SHMEM_MMAP_ANON        0
+#define APR_HAVE_SHMEM_BEOS             0
+
+#define APR_USE_SHMEM_MMAP_TMP          0
+#define APR_USE_SHMEM_MMAP_SHM          0
+#define APR_USE_SHMEM_MMAP_ZERO         0
+#define APR_USE_SHMEM_SHMGET_ANON       0
+#define APR_USE_SHMEM_SHMGET            0
+#define APR_USE_SHMEM_MMAP_ANON         0
+#define APR_USE_SHMEM_BEOS              0
+
+#define APR_USE_FLOCK_SERIALIZE         0
+#define APR_USE_SYSVSEM_SERIALIZE       0
+#define APR_USE_FCNTL_SERIALIZE         0
+#define APR_USE_PROC_PTHREAD_SERIALIZE  0
+#define APR_USE_PTHREAD_SERIALIZE       0
+
+#define APR_HAS_FLOCK_SERIALIZE         0
+#define APR_HAS_SYSVSEM_SERIALIZE       0
+#define APR_HAS_FCNTL_SERIALIZE         0
+#define APR_HAS_PROC_PTHREAD_SERIALIZE  0
+#define APR_HAS_RWLOCK_SERIALIZE        0
+
+#define APR_HAS_LOCK_CREATE_NP          0
+
+#define APR_PROCESS_LOCK_IS_GLOBAL      1
+
+#define APR_FILE_BASED_SHM              0
+
+#define APR_HAVE_CORKABLE_TCP           0
+#define APR_HAVE_GETRLIMIT              0
+#define APR_HAVE_ICONV                  0
+#define APR_HAVE_IN_ADDR                1
+#define APR_HAVE_INET_ADDR              1
+#define APR_HAVE_INET_NETWORK           0
+#ifdef NW_BUILD_IPV6
+#define APR_HAVE_IPV6                   1
+#else
+#define APR_HAVE_IPV6                   0
+#endif
+#ifdef USE_WINSOCK
+#define APR_HAVE_SOCKADDR_UN            0
+#else
+#define APR_HAVE_SOCKADDR_UN            1
+#endif
+#define APR_HAVE_MEMCHR                 1
+#define APR_HAVE_MEMMOVE                1
+#define APR_HAVE_SETRLIMIT              0
+#define APR_HAVE_SIGACTION              0
+#define APR_HAVE_SIGSUSPEND             0
+#define APR_HAVE_SIGWAIT                0
+#define APR_HAVE_STRCASECMP             1
+#define APR_HAVE_STRDUP                 1
+#define APR_HAVE_STRICMP                1
+#define APR_HAVE_STRNCASECMP            1
+#define APR_HAVE_STRNICMP               1
+#define APR_HAVE_STRSTR                 1
+#define APR_HAVE_STRUCT_RLIMIT          0
+#define APR_HAVE_UNION_SEMUN            0
+#define APR_HAVE_SCTP                   0
+#define APR_HAVE_IOVEC                  1
+
+/*  APR Feature Macros */
+#define APR_HAS_SHARED_MEMORY           0
+#define APR_HAS_THREADS                 1
+#define APR_HAS_SENDFILE                0
+#define APR_HAS_MMAP                    0
+#define APR_HAS_FORK                    0
+#define APR_HAS_RANDOM                  1
+#define APR_HAS_OTHER_CHILD             0
+#define APR_HAS_DSO                     1
+#define APR_HAS_SO_ACCEPTFILTER         0
+#define APR_HAS_UNICODE_FS              0
+#define APR_HAS_PROC_INVOKED            0
+#define APR_HAS_USER                    1
+#define APR_HAS_LARGE_FILES             1
+#define APR_HAS_XTHREAD_FILES           0
+#define APR_HAS_OS_UUID                 0
+
+#define APR_PROCATTR_USER_SET_REQUIRES_PASSWORD 0
+
+/* Netware can poll on files/pipes.
+ */
+#define APR_FILES_AS_SOCKETS            1
+
+/* This macro indicates whether or not EBCDIC is the native character set.
+ */
+#define APR_CHARSET_EBCDIC              0
+
+/* Is the TCP_NODELAY socket option inherited from listening sockets?
+ */
+#define APR_TCP_NODELAY_INHERITED       1
+
+/* Is the O_NONBLOCK flag inherited from listening sockets?
+ */
+#define APR_O_NONBLOCK_INHERITED        1
+
+/* Typedefs that APR needs. */
+
+typedef  unsigned char     apr_byte_t;
+
+typedef  short             apr_int16_t;
+typedef  unsigned short    apr_uint16_t;
+
+typedef  int               apr_int32_t;
+typedef  unsigned int      apr_uint32_t;
+
+typedef  long long          apr_int64_t;
+typedef  unsigned long long apr_uint64_t;
+
+typedef  size_t            apr_size_t;
+typedef  ssize_t           apr_ssize_t;
+#if APR_HAS_LARGE_FILES
+typedef  off64_t           apr_off_t;
+#else
+typedef  off_t             apr_off_t;
+#endif
+#ifdef USE_WINSOCK
+typedef  int               apr_socklen_t;
+#else
+typedef  size_t            apr_socklen_t;
+#endif
+typedef  apr_uint64_t      apr_ino_t;
+
+/* Are we big endian? */
+/* XXX: Fatal assumption on Alpha platforms */
+#define APR_IS_BIGENDIAN   0
+
+#ifdef UNKNOWN_NETWARE_64BIT_FLAG_NEEDED
+#define APR_SIZEOF_VOIDP   8
+#else
+#define APR_SIZEOF_VOIDP   4
+#endif
+
+#if APR_SIZEOF_VOIDP == 8
+typedef  apr_uint64_t            apr_uintptr_t;
+typedef  apr_int64_t             apr_intptr_t;
+#else
+typedef  apr_uint32_t            apr_uintptr_t;
+typedef  apr_int32_t             apr_intptr_t;
+#endif
+
+/* Mechanisms to properly type numeric literals */
+#define APR_INT64_C(val) (val##LL)
+#define APR_UINT64_C(val) (val##ULL)
+
+#ifdef INT16_MIN
+#define APR_INT16_MIN   INT16_MIN
+#else
+#define APR_INT16_MIN   (-0x7fff - 1)
+#endif
+
+#ifdef INT16_MAX
+#define APR_INT16_MAX  INT16_MAX
+#else
+#define APR_INT16_MAX   (0x7fff)
+#endif
+
+#ifdef UINT16_MAX
+#define APR_UINT16_MAX  UINT16_MAX
+#else
+#define APR_UINT16_MAX  (0xffff)
+#endif
+
+#ifdef INT32_MIN
+#define APR_INT32_MIN   INT32_MIN
+#else
+#define APR_INT32_MIN   (-0x7fffffff - 1)
+#endif
+
+#ifdef INT32_MAX
+#define APR_INT32_MAX  INT32_MAX
+#else
+#define APR_INT32_MAX  0x7fffffff
+#endif
+
+#ifdef UINT32_MAX
+#define APR_UINT32_MAX  UINT32_MAX
+#else
+#define APR_UINT32_MAX  (0xffffffffU)
+#endif
+
+#ifdef INT64_MIN
+#define APR_INT64_MIN   INT64_MIN
+#else
+#define APR_INT64_MIN   (APR_INT64_C(-0x7fffffffffffffff) - 1)
+#endif
+
+#ifdef INT64_MAX
+#define APR_INT64_MAX   INT64_MAX
+#else
+#define APR_INT64_MAX   APR_INT64_C(0x7fffffffffffffff)
+#endif
+
+#ifdef UINT64_MAX
+#define APR_UINT64_MAX  UINT64_MAX
+#else
+#define APR_UINT64_MAX  APR_UINT64_C(0xffffffffffffffff)
+#endif
+
+#define APR_SIZE_MAX    (~((apr_size_t)0))
+
+/* PROC mutex is a GLOBAL mutex on Netware */
+#define APR_PROC_MUTEX_IS_GLOBAL        1
+
+/* Definitions that APR programs need to work properly. */
+
+/**
+ * APR public API wrap for C++ compilers.
+ */
+#ifdef __cplusplus
+#define APR_BEGIN_DECLS     extern "C" {
+#define APR_END_DECLS       }
+#else
+#define APR_BEGIN_DECLS
+#define APR_END_DECLS
+#endif
+
+/**
+ * Thread callbacks from APR functions must be declared with APR_THREAD_FUNC,
+ * so that they follow the platform's calling convention.
+ * @example
+ */
+/** void* APR_THREAD_FUNC my_thread_entry_fn(apr_thread_t *thd, void *data);
+ */
+#define APR_THREAD_FUNC
+
+/**
+ * The public APR functions are declared with APR_DECLARE(), so they may
+ * use the most appropriate calling convention.  Public APR functions with
+ * variable arguments must use APR_DECLARE_NONSTD().
+ *
+ * @remark Both the declaration and implementations must use the same macro.
+ * @example
+ */
+/** APR_DECLARE(rettype) apr_func(args)
+ * @see APR_DECLARE_NONSTD @see APR_DECLARE_DATA
+ * @remark Note that when APR compiles the library itself, it passes the
+ * symbol -DAPR_DECLARE_EXPORT to the compiler on some platforms (e.g. Win32)
+ * to export public symbols from the dynamic library build.\n
+ * The user must define the APR_DECLARE_STATIC when compiling to target
+ * the static APR library on some platforms (e.g. Win32.)  The public symbols
+ * are neither exported nor imported when APR_DECLARE_STATIC is defined.\n
+ * By default, compiling an application and including the APR public
+ * headers, without defining APR_DECLARE_STATIC, will prepare the code to be
+ * linked to the dynamic library.
+ */
+#define APR_DECLARE(type)            type
+
+/**
+ * The public APR functions using variable arguments are declared with
+ * APR_DECLARE_NONSTD(), as they must follow the C language calling convention.
+ * @see APR_DECLARE @see APR_DECLARE_DATA
+ * @remark Both the declaration and implementations must use the same macro.
+ * @example
+ */
+/** APR_DECLARE_NONSTD(rettype) apr_func(args, ...);
+ */
+#define APR_DECLARE_NONSTD(type)     type
+
+/**
+ * The public APR variables are declared with APR_DECLARE_DATA.
+ * This assures the appropriate indirection is invoked at compile time.
+ * @see APR_DECLARE @see APR_DECLARE_NONSTD
+ * @remark Note that the declaration and implementations use different forms,
+ * but both must include the macro.
+ * @example
+ */
+/** extern APR_DECLARE_DATA type apr_variable;\n
+ * APR_DECLARE_DATA type apr_variable = value;
+ */
+#define APR_DECLARE_DATA
+
+#if !defined(WIN32) || defined(APU_MODULE_DECLARE_STATIC)
+/**
+ * Declare a dso module's exported module structure as APR_MODULE_DECLARE_DATA.
+ *
+ * Unless APR_MODULE_DECLARE_STATIC is defined at compile time, symbols
+ * declared with APR_MODULE_DECLARE_DATA are always exported.
+ * @code
+ * module APR_MODULE_DECLARE_DATA mod_tag
+ * @endcode
+ */
+#define APR_MODULE_DECLARE_DATA
+#else
+#define APR_MODULE_DECLARE_DATA           __declspec(dllexport)
+#endif
+
+/**
+ * @deprecated
+ * @see APR_MODULE_DECLARE_DATA
+ */
+#define APU_MODULE_DECLARE_DATA           APR_MODULE_DECLARE_DATA
+
+#define APR_SSIZE_T_FMT          "d"
+
+#define APR_SIZE_T_FMT           "d"
+
+#if APR_HAS_LARGE_FILES
+#define APR_OFF_T_FMT            "lld"
+#else
+#define APR_OFF_T_FMT            "ld"
+#endif
+
+#define APR_PID_T_FMT            "d"
+
+/* Local machine definition for console and log output. */
+#define APR_EOL_STR              "\r\n"
+
+typedef int apr_wait_t;
+
+#define APR_PATH_MAX PATH_MAX
+
+#define APR_DSOPATH "PATH"
+
+#define APR_INT64_T_FMT          "lld"
+#define APR_UINT64_T_FMT         "llu"
+#define APR_UINT64_T_HEX_FMT     "llx"
+#define APR_TIME_T_FMT APR_INT64_T_FMT
+
+/*
+ * we always have SDBM (it's in our codebase)
+ */
+#define APU_HAVE_SDBM           1
+
+#ifndef APU_DSO_MODULE_BUILD
+#define APU_HAVE_GDBM           0
+#define APU_HAVE_NDBM           0
+#define APU_HAVE_DB             0
+
+#if APU_HAVE_DB
+#define APU_HAVE_DB_VERSION     0
+#endif
+#endif
+
+/*
+ * we always enable dynamic driver loads within apr_dbd
+ */
+#ifndef APU_DSO_MODULE_BUILD
+#define APU_HAVE_PGSQL          0
+#define APU_HAVE_MYSQL          0
+#define APU_HAVE_SQLITE3        0
+#define APU_HAVE_SQLITE2        0
+#define APU_HAVE_ORACLE         0
+#define APU_HAVE_ODBC           0
+#endif
+
+#define APU_HAVE_CRYPTO         0
+
+#ifndef APU_DSO_MODULE_BUILD
+#define APU_HAVE_OPENSSL        0
+#define APU_HAVE_NSS            0
+#define APU_HAVE_COMMONCRYPTO   0
+#endif
+
+#define APU_HAVE_ICONV          1
+#define APR_HAS_XLATE           (APU_HAVE_ICONV)
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NETWARE */
+
+#endif /* APR_H */
diff --git a/include/apr.hw b/include/apr.hw
index fab1dd365ab..6366ba93290 100644
--- a/include/apr.hw
+++ b/include/apr.hw
@@ -1,149 +1,741 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-/* 
- * Note: This is a Windows specific version of apr.h. It is renamed to
- * apr.h at the start of a Windows build.
+/* 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.
  */
 
-#ifdef WIN32
+
 #ifndef APR_H
 #define APR_H
 
+/* GENERATED FILE WARNING!  DO NOT EDIT apr.h
+ *
+ * You must modify apr.hw instead.
+ *
+ * And please, make an effort to stub apr.hnw and apr.h.in in the process.
+ *
+ * This is the Win32 specific version of apr.h.  It is copied from
+ * apr.hw by the apr.dsp and libapr.dsp projects.
+ */
+
+/**
+ * @file apr.h
+ * @brief APR Platform Definitions
+ * @remark This is a generated header generated from include/apr.h.in by
+ * ./configure, or copied from include/apr.hw or include/apr.hnw 
+ * for Win32 or Netware by those build environments, respectively.
+ */
+
+/* Make sure we have our platform identifier macro defined we ask for later.
+ */
+#if defined(_WIN32) && !defined(WIN32)
+#define WIN32 1
+#endif
+
+/* Ignore most warnings (back down to /W3) for poorly constructed headers,
+ * excluded from doxygen parsing
+ */
+#if defined(_MSC_VER) && _MSC_VER >= 1200
+#pragma warning(push, 3)
+#endif
+
+/* disable or reduce the frequency of...
+ *   C4057: indirection to slightly different base types
+ *   C4075: slight indirection changes (unsigned short* vs short[])
+ *   C4100: unreferenced formal parameter
+ *   C4127: conditional expression is constant
+ *   C4163: '_rotl64' : not available as an intrinsic function
+ *   C4201: nonstandard extension nameless struct/unions
+ *   C4244: int to char/short - precision loss
+ *   C4514: unreferenced inline function removed
+ */
+#if defined(_MSC_VER)
+#pragma warning(disable: 4100 4127 4163 4201 4514; once: 4057 4075 4244)
+#endif
+
+/* Ignore Microsoft's interpretation of secure development
+ * and the POSIX string handling API
+ */
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+#ifndef _CRT_SECURE_NO_DEPRECATE
+#define _CRT_SECURE_NO_DEPRECATE
+#endif
+#pragma warning(disable: 4996)
+#endif
+
+/**
+ * @file apr.h
+ * @brief APR Platform Definitions
+ * @remark This is a generated header generated from include/apr.h.in by
+ * ./configure, or copied from include/apr.hw or include/apr.hnw
+ * for Win32 or Netware by those build environments, respectively.
+ */
+
+/**
+ * @defgroup APR Apache Portability Runtime library
+ * @{
+ */
+/**
+ * @defgroup apr_platform Platform Definitions
+ * @{
+ * @warning
+ * <strong><em>The actual values of macros and typedefs on this page<br>
+ * are platform specific and should NOT be relied upon!</em></strong>
+ */
+
+/* So that we can use inline on some critical functions, and use
+ * GNUC attributes (such as to get -Wall warnings for printf-like
+ * functions).  Only do this in gcc 2.7 or later ... it may work
+ * on earlier stuff, but why chance it.
+ *
+ * We've since discovered that the gcc shipped with NeXT systems
+ * as "cc" is completely broken.  It claims to be __GNUC__ and so
+ * on, but it doesn't implement half of the things that __GNUC__
+ * means.  In particular it's missing inline and the __attribute__
+ * stuff.  So we hack around it.  PR#1613. -djg
+ */
+#if defined(_MSC_VER)
+#define APR_INLINE __inline
+#define APR_HAS_INLINE          1
+#ifndef __attribute__
+#define __attribute__(__x)
+#endif
+#elif !defined(__GNUC__) || __GNUC__ < 2 || \
+    (__GNUC__ == 2 && __GNUC_MINOR__ < 7) ||\
+    defined(NEXT)
+#ifndef __attribute__
+#define __attribute__(__x)
+#endif
+#define APR_INLINE
+#define APR_HAS_INLINE          0
+#else
+#define APR_INLINE __inline__
+#define APR_HAS_INLINE          1
+#endif
+
+#ifdef _WIN32_WCE
+#define APR_NOT_IN_WCE          0
+#else
+#define APR_NOT_IN_WCE          1
+#endif
+
+#define APR_HAVE_ARPA_INET_H    0
+#define APR_HAVE_CONIO_H         APR_NOT_IN_WCE
+#define APR_HAVE_CRYPT_H        0
+#define APR_HAVE_CTYPE_H         APR_NOT_IN_WCE
+#define APR_HAVE_DIRENT_H       0
+#define APR_HAVE_ERRNO_H         APR_NOT_IN_WCE
+#define APR_HAVE_FCNTL_H         APR_NOT_IN_WCE
+#define APR_HAVE_IFADDRS_H      0
+#define APR_HAVE_IO_H            APR_NOT_IN_WCE
+#define APR_HAVE_LIMITS_H        APR_NOT_IN_WCE
+#define APR_HAVE_MSWSOCK_H       APR_NOT_IN_WCE
+#define APR_HAVE_NETDB_H        0
+#define APR_HAVE_NETINET_IN_H   0
+#define APR_HAVE_NETINET_SCTP_H 0
+#define APR_HAVE_NETINET_SCTP_UIO_H 0
+#define APR_HAVE_NETINET_TCP_H  0
+#define APR_HAVE_PROCESS_H      1
+#define APR_HAVE_PTHREAD_H      0
+#define APR_HAVE_SEMAPHORE_H    0
+#define APR_HAVE_SIGNAL_H        APR_NOT_IN_WCE
+#define APR_HAVE_STDARG_H        APR_NOT_IN_WCE
+#define APR_HAVE_STDDEF_H        APR_NOT_IN_WCE
+#define APR_HAVE_STDINT_H       0
+#define APR_HAVE_STDIO_H         1
+#define APR_HAVE_STDLIB_H        1
+#define APR_HAVE_STRING_H        1
+#define APR_HAVE_STRINGS_H      0
+#define APR_HAVE_SYS_IOCTL_H    0
+#define APR_HAVE_SYS_SENDFILE_H 0
+#define APR_HAVE_SYS_SIGNAL_H   0
+#define APR_HAVE_SYS_SOCKET_H   0
+#define APR_HAVE_SYS_SOCKIO_H   0
+#define APR_HAVE_SYS_SYSLIMITS_H 0
+#define APR_HAVE_SYS_TIME_H     0
+#define APR_HAVE_SYS_TYPES_H     APR_NOT_IN_WCE
+#define APR_HAVE_SYS_UIO_H      0
+#define APR_HAVE_SYS_UN_H       0
+#define APR_HAVE_SYS_WAIT_H     0
+#define APR_HAVE_TIME_H          APR_NOT_IN_WCE
+#define APR_HAVE_UNISTD_H       0
+#define APR_HAVE_WINDOWS_H       1
+#define APR_HAVE_WINSOCK2_H      APR_NOT_IN_WCE
+#define APR_HAVE_WS2TCPIP_H      APR_NOT_IN_WCE
+
+/** @} */
+/** @} */
+
+/* We don't include our conditional headers within the doxyblocks
+ * or the extern "C" namespace
+ */
+
+/* If windows.h was already included, our preferences don't matter.
+ * If not, include a restricted set of windows headers to our tastes.
+ */
+#if APR_HAVE_WINDOWS_H
+#ifndef _WINDOWS_
+
 #ifndef WIN32_LEAN_AND_MEAN
 #define WIN32_LEAN_AND_MEAN
 #endif
+
 #ifndef _WIN32_WINNT
-/* 
- * Compile the server including all the Windows NT 4.0 header files by 
- * default.
+#define _WIN32_WINNT 0x0501
+#endif
+
+#ifndef NOUSER
+#define NOUSER
+#endif
+#ifndef NOMCX
+#define NOMCX
+#endif
+#ifndef NOIME
+#define NOIME
+#endif
+
+/* Impossible to include winsock2.h after winsock.h, while windows.h
+ * attempts to load winsock.  Setting _WINSOCKAPI_ will dodge this.
  */
-#define _WIN32_WINNT 0x0400
+#if APR_HAVE_WINSOCK2_H
+#define _WINSOCKAPI_
 #endif
+
 #include <windows.h>
+#endif
+#endif
+
+#if APR_HAVE_WINSOCK2_H
 #include <winsock2.h>
+
+#if APR_HAVE_WS2TCPIP_H
+#include <ws2tcpip.h>
+#endif
+
+#if APR_HAVE_MSWSOCK_H
 #include <mswsock.h>
+#endif
+
+#else /* !APR_HAVE_WINSOCK2_H */
+
+#if APR_HAVE_WINSOCK_H
+#include <winsock.h>
+#endif
+
+#endif /* !APR_HAVE_WINSOCK2_H */
+
+#if APR_HAVE_SYS_TYPES_H
 #include <sys/types.h>
+#endif
+
+#if APR_HAVE_STDDEF_H
 #include <stddef.h>
-#include <stdio.h>
-#include <time.h>
-#include <process.h>
-#include <signal.h>
-#include <stdlib.h>
+#endif
 
-#define ap_inline
-#define __attribute__(__x)
-#define ENUM_BITFIELD(e,n,w)  signed int n : w
+#if APR_HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
 
-#define APR_HAVE_ERRNO_H        1
-#define APR_HAVE_DIRENT_H       0
-#define APR_HAVE_FCNTL_H        0
-#define APR_HAVE_NETINET_IN_H   0
-#define APR_HAVE_PTHREAD_H      0
-#define APR_HAVE_STDARG_H       1
-#define APR_HAVE_STDIO_H        1
-#define APR_HAVE_SYS_TYPES_H    1
-#define APR_HAVE_SYS_UIO_H      0
-#define APR_HAVE_IN_ADDR        1
+#if APR_HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#if APR_HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
 
-#define APR_USE_FLOCK_SERIALIZE           0 
+/* header files for PATH_MAX, _POSIX_PATH_MAX */
+#if APR_HAVE_LIMITS_H
+#include <limits.h>
+#else
+#if APR_HAVE_SYS_SYSLIMITS_H
+#include <sys/syslimits.h>
+#endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup apr_platform
+ * @ingroup APR
+ * @{
+ */
+
+#define APR_HAVE_SHMEM_MMAP_TMP     0
+#define APR_HAVE_SHMEM_MMAP_SHM     0
+#define APR_HAVE_SHMEM_MMAP_ZERO    0
+#define APR_HAVE_SHMEM_SHMGET_ANON  0
+#define APR_HAVE_SHMEM_SHMGET       0
+#define APR_HAVE_SHMEM_MMAP_ANON    0
+#define APR_HAVE_SHMEM_BEOS         0
+
+#define APR_USE_SHMEM_MMAP_TMP     0
+#define APR_USE_SHMEM_MMAP_SHM     0
+#define APR_USE_SHMEM_MMAP_ZERO    0
+#define APR_USE_SHMEM_SHMGET_ANON  0
+#define APR_USE_SHMEM_SHMGET       0
+#define APR_USE_SHMEM_MMAP_ANON    0
+#define APR_USE_SHMEM_BEOS         0
+
+#define APR_USE_FLOCK_SERIALIZE           0
 #define APR_USE_SYSVSEM_SERIALIZE         0
+#define APR_USE_POSIXSEM_SERIALIZE        0
 #define APR_USE_FCNTL_SERIALIZE           0
-#define APR_USE_PROC_PTHREAD_SERIALIZE    0 
-#define APR_USE_PTHREAD_SERIALIZE         0 
+#define APR_USE_PROC_PTHREAD_SERIALIZE    0
+#define APR_USE_PTHREAD_SERIALIZE         0
 
-#if APR_HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
+#define APR_HAS_FLOCK_SERIALIZE           0
+#define APR_HAS_SYSVSEM_SERIALIZE         0
+#define APR_HAS_POSIXSEM_SERIALIZE        0
+#define APR_HAS_FCNTL_SERIALIZE           0
+#define APR_HAS_PROC_PTHREAD_SERIALIZE    0
+
+#define APR_PROCESS_LOCK_IS_GLOBAL        0
+
+#define APR_HAVE_CORKABLE_TCP   0
+#define APR_HAVE_GETRLIMIT      0
+#define APR_HAVE_ICONV          0
+#define APR_HAVE_IN_ADDR        1
+#define APR_HAVE_INET_ADDR      1
+#define APR_HAVE_INET_NETWORK   0
+#define APR_HAVE_IPV6           1
+#define APR_HAVE_SOCKADDR_UN    0
+#define APR_HAVE_MEMMOVE        1
+#define APR_HAVE_SETRLIMIT      0
+#define APR_HAVE_SIGACTION      0
+#define APR_HAVE_SIGSUSPEND     0
+#define APR_HAVE_SIGWAIT        0
+#define APR_HAVE_SA_STORAGE     0
+#define APR_HAVE_STRCASECMP     0
+#define APR_HAVE_STRDUP         1
+#define APR_HAVE_STRICMP        APR_NOT_IN_WCE
+#define APR_HAVE_STRNCASECMP    0
+#define APR_HAVE_STRNICMP       APR_NOT_IN_WCE
+#define APR_HAVE_STRSTR         1
+#define APR_HAVE_MEMCHR         1
+#define APR_HAVE_STRUCT_RLIMIT  0
+#define APR_HAVE_UNION_SEMUN    0
+#define APR_HAVE_SCTP           0
+#define APR_HAVE_IOVEC          0
 
 /*  APR Feature Macros */
-#define APR_HAS_THREADS  1
-#define APR_HAS_SENDFILE 1
-#define APR_HAS_MMAP     0
-#define APR_HAS_RANDOM   1
-#define APR_HAS_XLATE    0
+#define APR_HAS_SHARED_MEMORY     1
+#define APR_HAS_THREADS           1
+#define APR_HAS_SENDFILE          APR_NOT_IN_WCE
+#define APR_HAS_MMAP              1
+#define APR_HAS_FORK              0
+#define APR_HAS_RANDOM            1
+#define APR_HAS_OTHER_CHILD       1
+#define APR_HAS_DSO               1
+#define APR_HAS_SO_ACCEPTFILTER   0
+#define APR_HAS_UNICODE_FS        1
+#define APR_HAS_PROC_INVOKED      1
+#define APR_HAS_USER              APR_NOT_IN_WCE
+#define APR_HAS_LARGE_FILES       APR_NOT_IN_WCE
+#define APR_HAS_XTHREAD_FILES     APR_NOT_IN_WCE
+#define APR_HAS_OS_UUID           1
+
+#define APR_PROCATTR_USER_SET_REQUIRES_PASSWORD APR_NOT_IN_WCE
+
+/* APR sets APR_FILES_AS_SOCKETS to 1 on systems where it is possible
+ * to poll on files/pipes.
+ */
+#define APR_FILES_AS_SOCKETS      0
+
+/* This macro indicates whether or not EBCDIC is the native character set.
+ */
+#define APR_CHARSET_EBCDIC        0
+
+/* If we have a TCP implementation that can be "corked", what flag
+ * do we use?
+ */
+#define APR_TCP_NOPUSH_FLAG       0
+
+/* Is the TCP_NODELAY socket option inherited from listening sockets?
+ */
+#define APR_TCP_NODELAY_INHERITED 1
+
+/* Is the O_NONBLOCK flag inherited from listening sockets?
+ */
+#define APR_O_NONBLOCK_INHERITED 1
 
 /* Typedefs that APR needs. */
 
-typedef  short           ap_int16_t;
-typedef  unsigned short  ap_uint16_t;
-                                               
-typedef  int           ap_int32_t;
-typedef  unsigned int  ap_uint32_t;
-                                               
-typedef  __int64           ap_int64_t;
-typedef  unsigned __int64  ap_uint64_t;
-
-typedef  int         ap_size_t;
-typedef  int         ap_ssize_t;
-typedef  _off_t      ap_off_t;
+typedef  unsigned char     apr_byte_t;
+
+typedef  short             apr_int16_t;
+typedef  unsigned short    apr_uint16_t;
+
+typedef  int               apr_int32_t;
+typedef  unsigned int      apr_uint32_t;
+
+typedef  __int64           apr_int64_t;
+typedef  unsigned __int64  apr_uint64_t;
+
+typedef  size_t      apr_size_t;
+#if APR_HAVE_STDDEF_H
+typedef  ptrdiff_t   apr_ssize_t;
+#else
+typedef  int         apr_ssize_t;
+#endif
+
+#if APR_HAS_LARGE_FILES
+typedef  __int64     apr_off_t;
+#else
+typedef  long        apr_off_t;
+#endif
+typedef  int         apr_socklen_t;
+typedef  apr_uint64_t      apr_ino_t;
+
+#ifdef _WIN64
+#define APR_SIZEOF_VOIDP   8
+#else
+#define APR_SIZEOF_VOIDP   4
+#endif
+
+#if APR_SIZEOF_VOIDP == 8
+typedef  apr_uint64_t            apr_uintptr_t;
+typedef  apr_int64_t             apr_intptr_t;
+#else
+typedef  apr_uint32_t            apr_uintptr_t;
+typedef  apr_int32_t             apr_intptr_t;
+#endif
+
+/* Are we big endian? */
+/* XXX: Fatal assumption on Alpha platforms */
+#define APR_IS_BIGENDIAN        0
+
+/* Mechanisms to properly type numeric literals */
+
+#ifndef __GNUC__
+#define APR_INT64_C(val) (val##i64)
+#define APR_UINT64_C(val) (val##Ui64)
+#else
+#define APR_INT64_C(val) (val##LL)
+#define APR_UINT64_C(val) (val##ULL)
+#endif
+
+#ifdef INT16_MIN
+#define APR_INT16_MIN   INT16_MIN
+#else
+#define APR_INT16_MIN   (-0x7fff - 1)
+#endif
+
+#ifdef INT16_MAX
+#define APR_INT16_MAX  INT16_MAX
+#else
+#define APR_INT16_MAX   (0x7fff)
+#endif
+
+#ifdef UINT16_MAX
+#define APR_UINT16_MAX  UINT16_MAX
+#else
+#define APR_UINT16_MAX  (0xffff)
+#endif
+
+#ifdef INT32_MIN
+#define APR_INT32_MIN   INT32_MIN
+#else
+#define APR_INT32_MIN   (-0x7fffffff - 1)
+#endif
+
+#ifdef INT32_MAX
+#define APR_INT32_MAX  INT32_MAX
+#else
+#define APR_INT32_MAX  0x7fffffff
+#endif
+
+#ifdef UINT32_MAX
+#define APR_UINT32_MAX  UINT32_MAX
+#else
+#define APR_UINT32_MAX  (0xffffffffU)
+#endif
+
+#ifdef INT64_MIN
+#define APR_INT64_MIN   INT64_MIN
+#else
+#define APR_INT64_MIN   (APR_INT64_C(-0x7fffffffffffffff) - 1)
+#endif
+
+#ifdef INT64_MAX
+#define APR_INT64_MAX   INT64_MAX
+#else
+#define APR_INT64_MAX   APR_INT64_C(0x7fffffffffffffff)
+#endif
+
+#ifdef UINT64_MAX
+#define APR_UINT64_MAX  UINT64_MAX
+#else
+#define APR_UINT64_MAX  APR_UINT64_C(0xffffffffffffffff)
+#endif
+
+#define APR_SIZE_MAX    (~((apr_size_t)0))
+
+/* Definitions that APR programs need to work properly. */
+
+/**
+ * APR public API wrap for C++ compilers.
+ */
+#ifdef __cplusplus
+#define APR_BEGIN_DECLS     extern "C" {
+#define APR_END_DECLS       }
+#else
+#define APR_BEGIN_DECLS
+#define APR_END_DECLS
+#endif
+
+/**
+ * Thread callbacks from APR functions must be declared with APR_THREAD_FUNC,
+ * so that they follow the platform's calling convention.
+ * <PRE>
+ *
+ * void* APR_THREAD_FUNC my_thread_entry_fn(apr_thread_t *thd, void *data);
+ *
+ * </PRE>
+ */
+#define APR_THREAD_FUNC  __stdcall
+
+
+#if defined(DOXYGEN) || !defined(WIN32)
+
+/**
+ * The public APR functions are declared with APR_DECLARE(), so they may
+ * use the most appropriate calling convention.  Public APR functions with
+ * variable arguments must use APR_DECLARE_NONSTD().
+ *
+ * @remark Both the declaration and implementations must use the same macro.
+ *
+ * <PRE>
+ * APR_DECLARE(rettype) apr_func(args)
+ * </PRE>
+ * @see APR_DECLARE_NONSTD @see APR_DECLARE_DATA
+ * @remark Note that when APR compiles the library itself, it passes the
+ * symbol -DAPR_DECLARE_EXPORT to the compiler on some platforms (e.g. Win32)
+ * to export public symbols from the dynamic library build.\n
+ * The user must define the APR_DECLARE_STATIC when compiling to target
+ * the static APR library on some platforms (e.g. Win32.)  The public symbols
+ * are neither exported nor imported when APR_DECLARE_STATIC is defined.\n
+ * By default, compiling an application and including the APR public
+ * headers, without defining APR_DECLARE_STATIC, will prepare the code to be
+ * linked to the dynamic library.
+ */
+#define APR_DECLARE(type)            type
+
+/**
+ * The public APR functions using variable arguments are declared with
+ * APR_DECLARE_NONSTD(), as they must follow the C language calling convention.
+ * @see APR_DECLARE @see APR_DECLARE_DATA
+ * @remark Both the declaration and implementations must use the same macro.
+ * <PRE>
+ *
+ * APR_DECLARE_NONSTD(rettype) apr_func(args, ...);
+ *
+ * </PRE>
+ */
+#define APR_DECLARE_NONSTD(type)     type
+
+/**
+ * The public APR variables are declared with APR_DECLARE_DATA.
+ * This assures the appropriate indirection is invoked at compile time.
+ * @see APR_DECLARE @see APR_DECLARE_NONSTD
+ * @remark Note that the declaration and implementations use different forms,
+ * but both must include the macro.
+ *
+ * <PRE>
+ *
+ * extern APR_DECLARE_DATA type apr_variable;\n
+ * APR_DECLARE_DATA type apr_variable = value;
+ *
+ * </PRE>
+ */
+#define APR_DECLARE_DATA
+
+#elif defined(APR_DECLARE_STATIC)
+#define APR_DECLARE(type)            type __stdcall
+#define APR_DECLARE_NONSTD(type)     type __cdecl
+#define APR_DECLARE_DATA
+#elif defined(APR_DECLARE_EXPORT)
+#define APR_DECLARE(type)            __declspec(dllexport) type __stdcall
+#define APR_DECLARE_NONSTD(type)     __declspec(dllexport) type __cdecl
+#define APR_DECLARE_DATA             __declspec(dllexport)
+#else
+#define APR_DECLARE(type)            __declspec(dllimport) type __stdcall
+#define APR_DECLARE_NONSTD(type)     __declspec(dllimport) type __cdecl
+#define APR_DECLARE_DATA             __declspec(dllimport)
+#endif
+
+#if !defined(WIN32) || defined(APU_MODULE_DECLARE_STATIC)
+/**
+ * Declare a dso module's exported module structure as APR_MODULE_DECLARE_DATA.
+ *
+ * Unless APR_MODULE_DECLARE_STATIC is defined at compile time, symbols
+ * declared with APR_MODULE_DECLARE_DATA are always exported.
+ * @code
+ * module APR_MODULE_DECLARE_DATA mod_tag
+ * @endcode
+ */
+#define APR_MODULE_DECLARE_DATA
+#else
+#define APR_MODULE_DECLARE_DATA           __declspec(dllexport)
+#endif
+
+/**
+ * @deprecated
+ * @see APR_MODULE_DECLARE_DATA
+ */
+#define APU_MODULE_DECLARE_DATA           APR_MODULE_DECLARE_DATA
+
+/* Define APR_SSIZE_T_FMT.
+ * If ssize_t is an integer we define it to be "d",
+ * if ssize_t is a long int we define it to be "ld",
+ * if ssize_t is 64-bit, we define it to be msvc specific "I64d"
+ */
+#ifdef _WIN64
+#define APR_SSIZE_T_FMT          "I64d"
+#define APR_SIZE_T_FMT           "I64u"
+#else
+#define APR_SSIZE_T_FMT          "d"
+#define APR_SIZE_T_FMT           "u"
+#endif
+
+#if APR_HAS_LARGE_FILES
+#define APR_OFF_T_FMT            "I64d"
+#else
+#define APR_OFF_T_FMT            "d"
+#endif
+
+#define APR_PID_T_FMT            "d"
+
+#define APR_INT64_T_FMT          "I64d"
+#define APR_UINT64_T_FMT         "I64u"
+#define APR_UINT64_T_HEX_FMT     "I64x"
+
+/* No difference between PROC and GLOBAL mutex */
+#define APR_PROC_MUTEX_IS_GLOBAL      1
+
+/* Local machine definition for console and log output. */
+#define APR_EOL_STR              "\r\n"
+
+typedef int apr_wait_t;
+
+#if APR_HAS_UNICODE_FS
+/* An arbitrary size that is digestable. True max is a bit less than 32000 */
+#define APR_PATH_MAX 8192
+#else /* !APR_HAS_UNICODE_FS */
+#define APR_PATH_MAX MAX_PATH
+#endif
+
+#define APR_DSOPATH "PATH"
+
+/*
+ * we always have SDBM (it's in our codebase)
+ */
+#define APU_HAVE_SDBM           1
+
+#ifndef APU_DSO_MODULE_BUILD
+#define APU_HAVE_GDBM           0
+#define APU_HAVE_NDBM           0
+#define APU_HAVE_DB             0
+
+#if APU_HAVE_DB
+#define APU_HAVE_DB_VERSION     0
+#endif
+#endif
+
+/*
+ * we always enable dynamic driver loads within apr_dbd
+ * driver builds enable these flags individually
+ */
+#ifndef APU_DSO_MODULE_BUILD
+#define APU_HAVE_PGSQL          0
+#define APU_HAVE_MYSQL          0
+#define APU_HAVE_SQLITE3        0
+#define APU_HAVE_SQLITE2        0
+#define APU_HAVE_ORACLE         0
+#define APU_HAVE_ODBC           0
+#endif
+
+#define APU_HAVE_CRYPTO         0
+
+#ifndef APU_DSO_MODULE_BUILD
+#define APU_HAVE_OPENSSL        0
+#define APU_HAVE_NSS            0
+#define APU_HAVE_COMMONCRYPTO   0
+#endif
+
+#define APU_HAVE_ICONV          0
+#define APR_HAS_XLATE           (APU_HAVE_ICONV)
+
+#define APU_USE_EXPAT           1
+#define APU_USE_LIBXML2         0
+
+/** @} */
+
+/* Definitions that only Win32 programs need to compile properly. */
+
+/* XXX These simply don't belong here, perhaps in apr_portable.h
+ * based on some APR_HAVE_PID/GID/UID?
+ */
+#ifdef WIN32
+#ifndef __WATCOMC__
+#ifndef __GNUC__
 typedef  int         pid_t;
+#endif
 typedef  int         uid_t;
 typedef  int         gid_t;
+#endif
+#endif
+
+/* Typically defined in stdio.h or unistd.h
+ */
+#ifndef STDIN_FILENO
+#define STDIN_FILENO  0
+#endif
+#ifndef STDOUT_FILENO
+#define STDOUT_FILENO 1
+#endif
+#ifndef STDERR_FILENO
+#define STDERR_FILENO 2
+#endif
+
+#if APR_HAVE_IPV6
+
+/* Appears in later flavors, not the originals. */
+#ifndef in_addr6
+#define  in6_addr    in_addr6
+#endif
+
+#ifndef WS2TCPIP_INLINE
+#define IN6_IS_ADDR_V4MAPPED(a) \
+    (   (*(const apr_uint64_t *)(const void *)(&(a)->s6_addr[0]) == 0) \
+     && (*(const apr_uint32_t *)(const void *)(&(a)->s6_addr[8]) == ntohl(0x0000ffff)))
+#endif
+
+#endif /* APR_HAVE_IPV6 */
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Done with badly written headers, leave 'deprecated CRT' undeprecated
+ */
+#if defined(_MSC_VER) && _MSC_VER >= 1200
+#pragma warning(pop)
+#if _MSC_VER >= 1400
+#pragma warning(disable: 4996)
+#endif
+#endif
 
-/* Definitions that APR programs need to work properly. */
-#define APR_SSIZE_T_FMT          "d"
-#define API_THREAD_FUNC          __stdcall
-#define API_EXPORT(type)         type
-#define API_EXPORT_NONSTD(type)  type
-#define API_VAR_IMPORT           extern _declspec(dllimport)
-#define API_VAR_EXPORT
-
-/* struct iovec is needed to emulate Unix writev */
-struct iovec {
-    char* iov_base;
-    int   iov_len;
-};
 #endif /* APR_H */
-#endif /* WIN32 */
diff --git a/include/apr.hwc b/include/apr.hwc
new file mode 100644
index 00000000000..061a5299c0c
--- /dev/null
+++ b/include/apr.hwc
@@ -0,0 +1,742 @@
+/* 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 APR_H
+#define APR_H
+
+/* GENERATED FILE WARNING!  DO NOT EDIT apr.h
+ *
+ * You must modify apr.hwc instead.
+ *
+ * And please, make an effort to stub apr.hnw and apr.h.in in the process.
+ *
+ * This is the Win32 specific version of apr.h.  It is copied from
+ * apr.hw by the apr.dsp and libapr.dsp projects.
+ */
+
+/**
+ * @file apr.h
+ * @brief APR Platform Definitions
+ * @remark This is a generated header generated from include/apr.h.in by
+ * ./configure, or copied from include/apr.hw or include/apr.hnw 
+ * for Win32 or Netware by those build environments, respectively.
+ */
+
+/* Make sure we have our platform identifier macro defined we ask for later.
+ */
+#if defined(_WIN32) && !defined(WIN32)
+#define WIN32 1
+#endif
+
+/* Ignore most warnings (back down to /W3) for poorly constructed headers,
+ * excluded from doxygen parsing
+ */
+#if defined(_MSC_VER) && _MSC_VER >= 1200
+#pragma warning(push, 3)
+#endif
+
+/* disable or reduce the frequency of...
+ *   C4057: indirection to slightly different base types
+ *   C4075: slight indirection changes (unsigned short* vs short[])
+ *   C4100: unreferenced formal parameter
+ *   C4127: conditional expression is constant
+ *   C4163: '_rotl64' : not available as an intrinsic function
+ *   C4201: nonstandard extension nameless struct/unions
+ *   C4244: int to char/short - precision loss
+ *   C4514: unreferenced inline function removed
+ */
+#if defined(_MSC_VER)
+#pragma warning(disable: 4100 4127 4163 4201 4514; once: 4057 4075 4244)
+#endif
+
+/* Ignore Microsoft's interpretation of secure development
+ * and the POSIX string handling API
+ */
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+#ifndef _CRT_SECURE_NO_DEPRECATE
+#define _CRT_SECURE_NO_DEPRECATE
+#endif
+#pragma warning(disable: 4996)
+#endif
+
+/**
+ * @file apr.h
+ * @brief APR Platform Definitions
+ * @remark This is a generated header generated from include/apr.h.in by
+ * ./configure, or copied from include/apr.hw or include/apr.hnw
+ * for Win32 or Netware by those build environments, respectively.
+ */
+
+/**
+ * @defgroup APR Apache Portability Runtime library
+ * @{
+ */
+/**
+ * @defgroup apr_platform Platform Definitions
+ * @{
+ * @warning
+ * <strong><em>The actual values of macros and typedefs on this page<br>
+ * are platform specific and should NOT be relied upon!</em></strong>
+ */
+
+/* So that we can use inline on some critical functions, and use
+ * GNUC attributes (such as to get -Wall warnings for printf-like
+ * functions).  Only do this in gcc 2.7 or later ... it may work
+ * on earlier stuff, but why chance it.
+ *
+ * We've since discovered that the gcc shipped with NeXT systems
+ * as "cc" is completely broken.  It claims to be __GNUC__ and so
+ * on, but it doesn't implement half of the things that __GNUC__
+ * means.  In particular it's missing inline and the __attribute__
+ * stuff.  So we hack around it.  PR#1613. -djg
+ */
+#if defined(_MSC_VER)
+#define APR_INLINE __inline
+#define APR_HAS_INLINE          1
+#ifndef __attribute__
+#define __attribute__(__x)
+#endif
+#elif !defined(__GNUC__) || __GNUC__ < 2 || \
+    (__GNUC__ == 2 && __GNUC_MINOR__ < 7) ||\
+    defined(NEXT)
+#ifndef __attribute__
+#define __attribute__(__x)
+#endif
+#define APR_INLINE
+#define APR_HAS_INLINE          0
+#else
+#define APR_INLINE __inline__
+#define APR_HAS_INLINE          1
+#endif
+
+#ifdef _WIN32_WCE
+#define APR_NOT_IN_WCE          0
+#else
+#define APR_NOT_IN_WCE          1
+#endif
+
+#define APR_HAVE_ARPA_INET_H    0
+#define APR_HAVE_CONIO_H         APR_NOT_IN_WCE
+#define APR_HAVE_CRYPT_H        0
+#define APR_HAVE_CTYPE_H         APR_NOT_IN_WCE
+#define APR_HAVE_DIRENT_H       0
+#define APR_HAVE_ERRNO_H         APR_NOT_IN_WCE
+#define APR_HAVE_FCNTL_H         APR_NOT_IN_WCE
+#define APR_HAVE_IFADDRS_H      0
+#define APR_HAVE_IO_H            APR_NOT_IN_WCE
+#define APR_HAVE_LIMITS_H        APR_NOT_IN_WCE
+#define APR_HAVE_MSWSOCK_H       APR_NOT_IN_WCE
+#define APR_HAVE_NETDB_H        0
+#define APR_HAVE_NETINET_IN_H   0
+#define APR_HAVE_NETINET_SCTP_H 0
+#define APR_HAVE_NETINET_SCTP_UIO_H 0
+#define APR_HAVE_NETINET_TCP_H  0
+#define APR_HAVE_PROCESS_H      1
+#define APR_HAVE_PTHREAD_H      0
+#define APR_HAVE_SEMAPHORE_H    0
+#define APR_HAVE_SIGNAL_H        APR_NOT_IN_WCE
+#define APR_HAVE_STDARG_H        APR_NOT_IN_WCE
+#define APR_HAVE_STDDEF_H        APR_NOT_IN_WCE
+#define APR_HAVE_STDINT_H       0
+#define APR_HAVE_STDIO_H         1
+#define APR_HAVE_STDLIB_H        1
+#define APR_HAVE_STRING_H        1
+#define APR_HAVE_STRINGS_H      0
+#define APR_HAVE_SYS_IOCTL_H    0
+#define APR_HAVE_SYS_SENDFILE_H 0
+#define APR_HAVE_SYS_SIGNAL_H   0
+#define APR_HAVE_SYS_SOCKET_H   0
+#define APR_HAVE_SYS_SOCKIO_H   0
+#define APR_HAVE_SYS_SYSLIMITS_H 0
+#define APR_HAVE_SYS_TIME_H     0
+#define APR_HAVE_SYS_TYPES_H     APR_NOT_IN_WCE
+#define APR_HAVE_SYS_UIO_H      0
+#define APR_HAVE_SYS_UN_H       0
+#define APR_HAVE_SYS_WAIT_H     0
+#define APR_HAVE_TIME_H          APR_NOT_IN_WCE
+#define APR_HAVE_UNISTD_H       0
+#define APR_HAVE_WINDOWS_H       1
+#define APR_HAVE_WINSOCK2_H      APR_NOT_IN_WCE
+#define APR_HAVE_WS2TCPIP_H      APR_NOT_IN_WCE
+
+/** @} */
+/** @} */
+
+/* We don't include our conditional headers within the doxyblocks
+ * or the extern "C" namespace
+ */
+
+/* If windows.h was already included, our preferences don't matter.
+ * If not, include a restricted set of windows headers to our tastes.
+ */
+#if APR_HAVE_WINDOWS_H
+#ifndef _WINDOWS_
+
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT @win32_winnt_str@
+#endif
+
+#ifndef NOUSER
+#define NOUSER
+#endif
+#ifndef NOMCX
+#define NOMCX
+#endif
+#ifndef NOIME
+#define NOIME
+#endif
+
+/* Impossible to include winsock2.h after winsock.h, while windows.h
+ * attempts to load winsock.  Setting _WINSOCKAPI_ will dodge this.
+ */
+#if APR_HAVE_WINSOCK2_H
+#define _WINSOCKAPI_
+#endif
+
+#include <windows.h>
+#endif
+#endif
+
+#if APR_HAVE_WINSOCK2_H
+#include <winsock2.h>
+
+#if APR_HAVE_WS2TCPIP_H
+#include <ws2tcpip.h>
+#endif
+
+#if APR_HAVE_MSWSOCK_H
+#include <mswsock.h>
+#endif
+
+#else /* !APR_HAVE_WINSOCK2_H */
+
+#if APR_HAVE_WINSOCK_H
+#include <winsock.h>
+#endif
+
+#endif /* !APR_HAVE_WINSOCK2_H */
+
+#if APR_HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#if APR_HAVE_STDDEF_H
+#include <stddef.h>
+#endif
+
+#if APR_HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#if APR_HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#if APR_HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+
+/* header files for PATH_MAX, _POSIX_PATH_MAX */
+#if APR_HAVE_LIMITS_H
+#include <limits.h>
+#else
+#if APR_HAVE_SYS_SYSLIMITS_H
+#include <sys/syslimits.h>
+#endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup apr_platform
+ * @ingroup APR
+ * @{
+ */
+
+#define APR_HAVE_SHMEM_MMAP_TMP     0
+#define APR_HAVE_SHMEM_MMAP_SHM     0
+#define APR_HAVE_SHMEM_MMAP_ZERO    0
+#define APR_HAVE_SHMEM_SHMGET_ANON  0
+#define APR_HAVE_SHMEM_SHMGET       0
+#define APR_HAVE_SHMEM_MMAP_ANON    0
+#define APR_HAVE_SHMEM_BEOS         0
+
+#define APR_USE_SHMEM_MMAP_TMP     0
+#define APR_USE_SHMEM_MMAP_SHM     0
+#define APR_USE_SHMEM_MMAP_ZERO    0
+#define APR_USE_SHMEM_SHMGET_ANON  0
+#define APR_USE_SHMEM_SHMGET       0
+#define APR_USE_SHMEM_MMAP_ANON    0
+#define APR_USE_SHMEM_BEOS         0
+
+#define APR_USE_FLOCK_SERIALIZE           0
+#define APR_USE_SYSVSEM_SERIALIZE         0
+#define APR_USE_POSIXSEM_SERIALIZE        0
+#define APR_USE_FCNTL_SERIALIZE           0
+#define APR_USE_PROC_PTHREAD_SERIALIZE    0
+#define APR_USE_PTHREAD_SERIALIZE         0
+
+#define APR_HAS_FLOCK_SERIALIZE           0
+#define APR_HAS_SYSVSEM_SERIALIZE         0
+#define APR_HAS_POSIXSEM_SERIALIZE        0
+#define APR_HAS_FCNTL_SERIALIZE           0
+#define APR_HAS_PROC_PTHREAD_SERIALIZE    0
+
+#define APR_PROCESS_LOCK_IS_GLOBAL        0
+
+#define APR_HAVE_CORKABLE_TCP   0
+#define APR_HAVE_GETRLIMIT      0
+#define APR_HAVE_ICONV          0
+#define APR_HAVE_IN_ADDR        1
+#define APR_HAVE_INET_ADDR      1
+#define APR_HAVE_INET_NETWORK   0
+#define APR_HAVE_IPV6           @apr_have_ipv6_10@
+#define APR_HAVE_SOCKADDR_UN    0
+#define APR_HAVE_MEMMOVE        1
+#define APR_HAVE_SETRLIMIT      0
+#define APR_HAVE_SIGACTION      0
+#define APR_HAVE_SIGSUSPEND     0
+#define APR_HAVE_SIGWAIT        0
+#define APR_HAVE_SA_STORAGE     0
+#define APR_HAVE_STRCASECMP     0
+#define APR_HAVE_STRDUP         1
+#define APR_HAVE_STRICMP        APR_NOT_IN_WCE
+#define APR_HAVE_STRNCASECMP    0
+#define APR_HAVE_STRNICMP       APR_NOT_IN_WCE
+#define APR_HAVE_STRSTR         1
+#define APR_HAVE_MEMCHR         1
+#define APR_HAVE_STRUCT_RLIMIT  0
+#define APR_HAVE_UNION_SEMUN    0
+#define APR_HAVE_SCTP           0
+#define APR_HAVE_IOVEC          0
+
+/*  APR Feature Macros */
+#define APR_HAS_SHARED_MEMORY     1
+#define APR_HAS_THREADS           1
+#define APR_HAS_SENDFILE          APR_NOT_IN_WCE
+#define APR_HAS_MMAP              1
+#define APR_HAS_FORK              0
+#define APR_HAS_RANDOM            1
+#define APR_HAS_OTHER_CHILD       1
+#define APR_HAS_DSO               1
+#define APR_HAS_SO_ACCEPTFILTER   0
+#define APR_HAS_UNICODE_FS        1
+#define APR_HAS_PROC_INVOKED      1
+#define APR_HAS_USER              APR_NOT_IN_WCE
+#define APR_HAS_LARGE_FILES       APR_NOT_IN_WCE
+#define APR_HAS_XTHREAD_FILES     APR_NOT_IN_WCE
+#define APR_HAS_OS_UUID           1
+
+#define APR_PROCATTR_USER_SET_REQUIRES_PASSWORD APR_NOT_IN_WCE
+
+/* APR sets APR_FILES_AS_SOCKETS to 1 on systems where it is possible
+ * to poll on files/pipes.
+ */
+#define APR_FILES_AS_SOCKETS      0
+
+/* This macro indicates whether or not EBCDIC is the native character set.
+ */
+#define APR_CHARSET_EBCDIC        0
+
+/* If we have a TCP implementation that can be "corked", what flag
+ * do we use?
+ */
+#define APR_TCP_NOPUSH_FLAG       0
+
+/* Is the TCP_NODELAY socket option inherited from listening sockets?
+ */
+#define APR_TCP_NODELAY_INHERITED 1
+
+/* Is the O_NONBLOCK flag inherited from listening sockets?
+ */
+#define APR_O_NONBLOCK_INHERITED 1
+
+/* Typedefs that APR needs. */
+
+typedef  unsigned char     apr_byte_t;
+
+typedef  short             apr_int16_t;
+typedef  unsigned short    apr_uint16_t;
+
+typedef  int               apr_int32_t;
+typedef  unsigned int      apr_uint32_t;
+
+typedef  __int64           apr_int64_t;
+typedef  unsigned __int64  apr_uint64_t;
+
+typedef  size_t      apr_size_t;
+#if APR_HAVE_STDDEF_H
+typedef  ptrdiff_t   apr_ssize_t;
+#else
+typedef  int         apr_ssize_t;
+#endif
+
+#if APR_HAS_LARGE_FILES
+typedef  __int64     apr_off_t;
+#else
+typedef  long        apr_off_t;
+#endif
+typedef  int         apr_socklen_t;
+typedef  apr_uint64_t      apr_ino_t;
+
+#ifdef _WIN64
+#define APR_SIZEOF_VOIDP   8
+#else
+#define APR_SIZEOF_VOIDP   4
+#endif
+
+#if APR_SIZEOF_VOIDP == 8
+typedef  apr_uint64_t            apr_uintptr_t;
+typedef  apr_int64_t             apr_intptr_t;
+#else
+typedef  apr_uint32_t            apr_uintptr_t;
+typedef  apr_int32_t             apr_intptr_t;
+#endif
+
+/* Are we big endian? */
+/* XXX: Fatal assumption on Alpha platforms */
+#define APR_IS_BIGENDIAN        0
+
+/* Mechanisms to properly type numeric literals */
+
+#ifndef __GNUC__
+#define APR_INT64_C(val) (val##i64)
+#define APR_UINT64_C(val) (val##Ui64)
+#else
+#define APR_INT64_C(val) (val##LL)
+#define APR_UINT64_C(val) (val##ULL)
+#endif
+
+#ifdef INT16_MIN
+#define APR_INT16_MIN   INT16_MIN
+#else
+#define APR_INT16_MIN   (-0x7fff - 1)
+#endif
+
+#ifdef INT16_MAX
+#define APR_INT16_MAX  INT16_MAX
+#else
+#define APR_INT16_MAX   (0x7fff)
+#endif
+
+#ifdef UINT16_MAX
+#define APR_UINT16_MAX  UINT16_MAX
+#else
+#define APR_UINT16_MAX  (0xffff)
+#endif
+
+#ifdef INT32_MIN
+#define APR_INT32_MIN   INT32_MIN
+#else
+#define APR_INT32_MIN   (-0x7fffffff - 1)
+#endif
+
+#ifdef INT32_MAX
+#define APR_INT32_MAX  INT32_MAX
+#else
+#define APR_INT32_MAX  0x7fffffff
+#endif
+
+#ifdef UINT32_MAX
+#define APR_UINT32_MAX  UINT32_MAX
+#else
+#define APR_UINT32_MAX  (0xffffffffU)
+#endif
+
+#ifdef INT64_MIN
+#define APR_INT64_MIN   INT64_MIN
+#else
+#define APR_INT64_MIN   (APR_INT64_C(-0x7fffffffffffffff) - 1)
+#endif
+
+#ifdef INT64_MAX
+#define APR_INT64_MAX   INT64_MAX
+#else
+#define APR_INT64_MAX   APR_INT64_C(0x7fffffffffffffff)
+#endif
+
+#ifdef UINT64_MAX
+#define APR_UINT64_MAX  UINT64_MAX
+#else
+#define APR_UINT64_MAX  APR_UINT64_C(0xffffffffffffffff)
+#endif
+
+#define APR_SIZE_MAX    (~((apr_size_t)0))
+
+/* Definitions that APR programs need to work properly. */
+
+/**
+ * APR public API wrap for C++ compilers.
+ */
+#ifdef __cplusplus
+#define APR_BEGIN_DECLS     extern "C" {
+#define APR_END_DECLS       }
+#else
+#define APR_BEGIN_DECLS
+#define APR_END_DECLS
+#endif
+
+/**
+ * Thread callbacks from APR functions must be declared with APR_THREAD_FUNC,
+ * so that they follow the platform's calling convention.
+ * <PRE>
+ *
+ * void* APR_THREAD_FUNC my_thread_entry_fn(apr_thread_t *thd, void *data);
+ *
+ * </PRE>
+ */
+#define APR_THREAD_FUNC  __stdcall
+
+
+#if defined(DOXYGEN) || !defined(WIN32)
+
+/**
+ * The public APR functions are declared with APR_DECLARE(), so they may
+ * use the most appropriate calling convention.  Public APR functions with
+ * variable arguments must use APR_DECLARE_NONSTD().
+ *
+ * @remark Both the declaration and implementations must use the same macro.
+ *
+ * <PRE>
+ * APR_DECLARE(rettype) apr_func(args)
+ * </PRE>
+ * @see APR_DECLARE_NONSTD @see APR_DECLARE_DATA
+ * @remark Note that when APR compiles the library itself, it passes the
+ * symbol -DAPR_DECLARE_EXPORT to the compiler on some platforms (e.g. Win32)
+ * to export public symbols from the dynamic library build.\n
+ * The user must define the APR_DECLARE_STATIC when compiling to target
+ * the static APR library on some platforms (e.g. Win32.)  The public symbols
+ * are neither exported nor imported when APR_DECLARE_STATIC is defined.\n
+ * By default, compiling an application and including the APR public
+ * headers, without defining APR_DECLARE_STATIC, will prepare the code to be
+ * linked to the dynamic library.
+ */
+#define APR_DECLARE(type)            type
+
+/**
+ * The public APR functions using variable arguments are declared with
+ * APR_DECLARE_NONSTD(), as they must follow the C language calling convention.
+ * @see APR_DECLARE @see APR_DECLARE_DATA
+ * @remark Both the declaration and implementations must use the same macro.
+ * <PRE>
+ *
+ * APR_DECLARE_NONSTD(rettype) apr_func(args, ...);
+ *
+ * </PRE>
+ */
+#define APR_DECLARE_NONSTD(type)     type
+
+/**
+ * The public APR variables are declared with APR_DECLARE_DATA.
+ * This assures the appropriate indirection is invoked at compile time.
+ * @see APR_DECLARE @see APR_DECLARE_NONSTD
+ * @remark Note that the declaration and implementations use different forms,
+ * but both must include the macro.
+ *
+ * <PRE>
+ *
+ * extern APR_DECLARE_DATA type apr_variable;\n
+ * APR_DECLARE_DATA type apr_variable = value;
+ *
+ * </PRE>
+ */
+#define APR_DECLARE_DATA
+
+#elif defined(APR_DECLARE_STATIC)
+#define APR_DECLARE(type)            type __stdcall
+#define APR_DECLARE_NONSTD(type)     type __cdecl
+#define APR_DECLARE_DATA
+#elif defined(APR_DECLARE_EXPORT)
+#define APR_DECLARE(type)            __declspec(dllexport) type __stdcall
+#define APR_DECLARE_NONSTD(type)     __declspec(dllexport) type __cdecl
+#define APR_DECLARE_DATA             __declspec(dllexport)
+#else
+#define APR_DECLARE(type)            __declspec(dllimport) type __stdcall
+#define APR_DECLARE_NONSTD(type)     __declspec(dllimport) type __cdecl
+#define APR_DECLARE_DATA             __declspec(dllimport)
+#endif
+
+#if !defined(WIN32) || defined(APU_MODULE_DECLARE_STATIC)
+/**
+ * Declare a dso module's exported module structure as APR_MODULE_DECLARE_DATA.
+ *
+ * Unless APR_MODULE_DECLARE_STATIC is defined at compile time, symbols
+ * declared with APR_MODULE_DECLARE_DATA are always exported.
+ * @code
+ * module APR_MODULE_DECLARE_DATA mod_tag
+ * @endcode
+ */
+#define APR_MODULE_DECLARE_DATA
+#else
+#define APR_MODULE_DECLARE_DATA           __declspec(dllexport)
+#endif
+
+/**
+ * @deprecated
+ * @see APR_MODULE_DECLARE_DATA
+ */
+#define APU_MODULE_DECLARE_DATA           APR_MODULE_DECLARE_DATA
+
+/* Define APR_SSIZE_T_FMT.
+ * If ssize_t is an integer we define it to be "d",
+ * if ssize_t is a long int we define it to be "ld",
+ * if ssize_t is 64-bit, we define it to be msvc specific "I64d"
+ */
+#ifdef _WIN64
+#define APR_SSIZE_T_FMT          "I64d"
+#define APR_SIZE_T_FMT           "I64u"
+#else
+#define APR_SSIZE_T_FMT          "d"
+#define APR_SIZE_T_FMT           "u"
+#endif
+
+#if APR_HAS_LARGE_FILES
+#define APR_OFF_T_FMT            "I64d"
+#else
+#define APR_OFF_T_FMT            "d"
+#endif
+
+#define APR_PID_T_FMT            "d"
+
+#define APR_INT64_T_FMT          "I64d"
+#define APR_UINT64_T_FMT         "I64u"
+#define APR_UINT64_T_HEX_FMT     "I64x"
+
+/* No difference between PROC and GLOBAL mutex */
+#define APR_PROC_MUTEX_IS_GLOBAL      1
+
+/* Local machine definition for console and log output. */
+#define APR_EOL_STR              "\r\n"
+
+typedef int apr_wait_t;
+
+#if APR_HAS_UNICODE_FS
+/* An arbitrary size that is digestable. True max is a bit less than 32000 */
+#define APR_PATH_MAX 8192
+#else /* !APR_HAS_UNICODE_FS */
+#define APR_PATH_MAX MAX_PATH
+#endif
+
+#define APR_DSOPATH "PATH"
+
+/*
+ * we always have SDBM (it's in our codebase)
+ */
+#define APU_HAVE_SDBM           1
+
+#ifndef APU_DSO_MODULE_BUILD
+#define APU_HAVE_GDBM           0
+#define APU_HAVE_NDBM           0
+#define APU_HAVE_DB             0
+
+#if APU_HAVE_DB
+#define APU_HAVE_DB_VERSION     0
+#endif
+#endif
+
+/*
+ * Windows: Only dynamic driver loads within apr_dbd
+ *          are supported.  The driver builds enable
+ *          these flags individually.
+ */
+#ifndef APU_DSO_MODULE_BUILD
+#define APU_HAVE_PGSQL          0
+#define APU_HAVE_MYSQL          0
+#define APU_HAVE_SQLITE3        0
+#define APU_HAVE_SQLITE2        0
+#define APU_HAVE_ORACLE         0
+#define APU_HAVE_ODBC           0
+#endif
+
+#define APU_HAVE_CRYPTO         @apu_have_crypto_10@
+
+#ifndef APU_DSO_MODULE_BUILD
+#define APU_HAVE_OPENSSL        0
+#define APU_HAVE_NSS            0
+#define APU_HAVE_COMMONCRYPTO   0
+#endif
+
+#define APU_HAVE_ICONV          0
+#define APR_HAS_XLATE           (APU_HAVE_ICONV)
+
+#define APU_USE_EXPAT           @apu_use_expat_10@
+#define APU_USE_LIBXML2         @apu_use_libxml2_10@
+
+/** @} */
+
+/* Definitions that only Win32 programs need to compile properly. */
+
+/* XXX These simply don't belong here, perhaps in apr_portable.h
+ * based on some APR_HAVE_PID/GID/UID?
+ */
+#ifdef WIN32
+#ifndef __WATCOMC__
+#ifndef __GNUC__
+typedef  int         pid_t;
+#endif
+typedef  int         uid_t;
+typedef  int         gid_t;
+#endif
+#endif
+
+/* Typically defined in stdio.h or unistd.h
+ */
+#ifndef STDIN_FILENO
+#define STDIN_FILENO  0
+#endif
+#ifndef STDOUT_FILENO
+#define STDOUT_FILENO 1
+#endif
+#ifndef STDERR_FILENO
+#define STDERR_FILENO 2
+#endif
+
+#if APR_HAVE_IPV6
+
+/* Appears in later flavors, not the originals. */
+#ifndef in_addr6
+#define  in6_addr    in_addr6
+#endif
+
+#ifndef WS2TCPIP_INLINE
+#define IN6_IS_ADDR_V4MAPPED(a) \
+    (   (*(const apr_uint64_t *)(const void *)(&(a)->s6_addr[0]) == 0) \
+     && (*(const apr_uint32_t *)(const void *)(&(a)->s6_addr[8]) == ntohl(0x0000ffff)))
+#endif
+
+#endif /* APR_HAVE_IPV6 */
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Done with badly written headers, leave 'deprecated CRT' undeprecated
+ */
+#if defined(_MSC_VER) && _MSC_VER >= 1200
+#pragma warning(pop)
+#if _MSC_VER >= 1400
+#pragma warning(disable: 4996)
+#endif
+#endif
+
+#endif /* APR_H */
diff --git a/include/apr_allocator.h b/include/apr_allocator.h
new file mode 100644
index 00000000000..4d9d7622066
--- /dev/null
+++ b/include/apr_allocator.h
@@ -0,0 +1,194 @@
+/* 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 APR_ALLOCATOR_H
+#define APR_ALLOCATOR_H
+
+/**
+ * @file apr_allocator.h
+ * @brief APR Internal Memory Allocation
+ */
+
+#include "apr.h"
+#include "apr_errno.h"
+#define APR_WANT_MEMFUNC /**< For no good reason? */
+#include "apr_want.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup apr_allocator Internal Memory Allocation
+ * @ingroup APR 
+ * @{
+ */
+
+/** the allocator structure */
+typedef struct apr_allocator_t apr_allocator_t;
+/** the structure which holds information about the allocation */
+typedef struct apr_memnode_t apr_memnode_t;
+
+/** basic memory node structure
+ * @note The next, ref and first_avail fields are available for use by the
+ *       caller of apr_allocator_alloc(), the remaining fields are read-only.
+ *       The next field has to be used with caution and sensibly set when the
+ *       memnode is passed back to apr_allocator_free().  See apr_allocator_free()
+ *       for details.  
+ *       The ref and first_avail fields will be properly restored by
+ *       apr_allocator_free().
+ */
+struct apr_memnode_t {
+    apr_memnode_t *next;            /**< next memnode */
+    apr_memnode_t **ref;            /**< reference to self */
+    apr_uint32_t   index;           /**< size */
+    apr_uint32_t   free_index;      /**< how much free */
+    char          *first_avail;     /**< pointer to first free memory */
+    char          *endp;            /**< pointer to end of free memory */
+};
+
+/** The base size of a memory node - aligned.  */
+#define APR_MEMNODE_T_SIZE APR_ALIGN_DEFAULT(sizeof(apr_memnode_t))
+
+/** Symbolic constants */
+#define APR_ALLOCATOR_MAX_FREE_UNLIMITED 0
+
+/**
+ * Create a new allocator
+ * @param allocator The allocator we have just created.
+ *
+ */
+APR_DECLARE(apr_status_t) apr_allocator_create(apr_allocator_t **allocator)
+                          __attribute__((nonnull(1)));
+
+/**
+ * Destroy an allocator
+ * @param allocator The allocator to be destroyed
+ * @remark Any memnodes not given back to the allocator prior to destroying
+ *         will _not_ be free()d.
+ */
+APR_DECLARE(void) apr_allocator_destroy(apr_allocator_t *allocator)
+                  __attribute__((nonnull(1)));
+
+/**
+ * Allocate a block of mem from the allocator
+ * @param allocator The allocator to allocate from
+ * @param size The size of the mem to allocate (excluding the
+ *        memnode structure)
+ */
+APR_DECLARE(apr_memnode_t *) apr_allocator_alloc(apr_allocator_t *allocator,
+                                                 apr_size_t size)
+                             __attribute__((nonnull(1)));
+
+/**
+ * Free a list of blocks of mem, giving them back to the allocator.
+ * The list is typically terminated by a memnode with its next field
+ * set to NULL.
+ * @param allocator The allocator to give the mem back to
+ * @param memnode The memory node to return
+ */
+APR_DECLARE(void) apr_allocator_free(apr_allocator_t *allocator,
+                                     apr_memnode_t *memnode)
+                  __attribute__((nonnull(1,2)));
+ 
+/**
+ * Get the page/boundary size.
+ * @return The page size
+ */
+APR_DECLARE(apr_size_t) apr_allocator_page_size(void);
+
+/**
+ * Setup the minimum allocation order (in 2^order pages).
+ * @param order The order to set
+ * @return APR_SUCCESS, or APR_EINVAL if @a order above 9.
+ * @note Default is order-1 (e.g. 8K on systems with 4K pages).
+ * @remark Should be done at initialization time, never concurrently.
+ */
+APR_DECLARE(apr_status_t) apr_allocator_min_order_set(unsigned int order);
+
+/**
+ * Get the true size that would be allocated for the given size (including
+ * the header and alignment).
+ * @param list The allocator from which to the memory would be allocated
+ * @param size The size to align
+ * @return The aligned size (or zero on apr_size_t overflow)
+ */
+APR_DECLARE(apr_size_t) apr_allocator_align(apr_allocator_t *allocator,
+                                            apr_size_t size);
+
+#include "apr_pools.h"
+
+/**
+ * Set the owner of the allocator
+ * @param allocator The allocator to set the owner for
+ * @param pool The pool that is to own the allocator
+ * @remark Typically pool is the highest level pool using the allocator
+ */
+/*
+ * XXX: see if we can come up with something a bit better.  Currently
+ * you can make a pool an owner, but if the pool doesn't use the allocator
+ * the allocator will never be destroyed.
+ */
+APR_DECLARE(void) apr_allocator_owner_set(apr_allocator_t *allocator,
+                                          apr_pool_t *pool)
+                  __attribute__((nonnull(1)));
+
+/**
+ * Get the current owner of the allocator
+ * @param allocator The allocator to get the owner from
+ */
+APR_DECLARE(apr_pool_t *) apr_allocator_owner_get(apr_allocator_t *allocator)
+                          __attribute__((nonnull(1)));
+
+/**
+ * Set the current threshold at which the allocator should start
+ * giving blocks back to the system.
+ * @param allocator The allocator to set the threshold on
+ * @param size The threshold.  0 == unlimited.
+ */
+APR_DECLARE(void) apr_allocator_max_free_set(apr_allocator_t *allocator,
+                                             apr_size_t size)
+                  __attribute__((nonnull(1)));
+
+#include "apr_thread_mutex.h"
+
+#if APR_HAS_THREADS
+/**
+ * Set a mutex for the allocator to use
+ * @param allocator The allocator to set the mutex for
+ * @param mutex The mutex
+ */
+APR_DECLARE(void) apr_allocator_mutex_set(apr_allocator_t *allocator,
+                                          apr_thread_mutex_t *mutex)
+                  __attribute__((nonnull(1)));
+
+/**
+ * Get the mutex currently set for the allocator
+ * @param allocator The allocator
+ */
+APR_DECLARE(apr_thread_mutex_t *) apr_allocator_mutex_get(
+                                          apr_allocator_t *allocator)
+                                  __attribute__((nonnull(1)));
+
+#endif /* APR_HAS_THREADS */
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !APR_ALLOCATOR_H */
diff --git a/include/apr_anylock.h b/include/apr_anylock.h
new file mode 100644
index 00000000000..51e97ff3733
--- /dev/null
+++ b/include/apr_anylock.h
@@ -0,0 +1,128 @@
+/* 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 apr_anylock.h
+ * @brief APR-Util transparent any lock flavor wrapper
+ */
+#ifndef APR_ANYLOCK_H
+#define APR_ANYLOCK_H
+
+#include "apr_proc_mutex.h"
+#include "apr_thread_mutex.h"
+#include "apr_thread_rwlock.h"
+
+/** Structure that may contain any APR lock type */
+typedef struct apr_anylock_t {
+    /** Indicates what type of lock is in lock */
+    enum tm_lock {
+        apr_anylock_none,           /**< None */
+        apr_anylock_procmutex,      /**< Process-based */
+        apr_anylock_threadmutex,    /**< Thread-based */
+        apr_anylock_readlock,       /**< Read lock */
+        apr_anylock_writelock       /**< Write lock */
+    } type;
+    /** Union of all possible APR locks */
+    union apr_anylock_u_t {
+        apr_proc_mutex_t *pm;       /**< Process mutex */
+#if APR_HAS_THREADS
+        apr_thread_mutex_t *tm;     /**< Thread mutex */
+        apr_thread_rwlock_t *rw;    /**< Read-write lock */
+#endif
+    } lock;
+} apr_anylock_t;
+
+#if APR_HAS_THREADS
+
+/** Lock an apr_anylock_t structure */
+#define APR_ANYLOCK_LOCK(lck)                \
+    (((lck)->type == apr_anylock_none)         \
+      ? APR_SUCCESS                              \
+      : (((lck)->type == apr_anylock_threadmutex)  \
+          ? apr_thread_mutex_lock((lck)->lock.tm)    \
+          : (((lck)->type == apr_anylock_procmutex)    \
+              ? apr_proc_mutex_lock((lck)->lock.pm)      \
+              : (((lck)->type == apr_anylock_readlock)     \
+                  ? apr_thread_rwlock_rdlock((lck)->lock.rw) \
+                  : (((lck)->type == apr_anylock_writelock)    \
+                      ? apr_thread_rwlock_wrlock((lck)->lock.rw) \
+                      : APR_EINVAL)))))
+
+#else /* APR_HAS_THREADS */
+
+#define APR_ANYLOCK_LOCK(lck)                \
+    (((lck)->type == apr_anylock_none)         \
+      ? APR_SUCCESS                              \
+          : (((lck)->type == apr_anylock_procmutex)    \
+              ? apr_proc_mutex_lock((lck)->lock.pm)      \
+                      : APR_EINVAL))
+
+#endif /* APR_HAS_THREADS */
+
+#if APR_HAS_THREADS
+
+/** Try to lock an apr_anylock_t structure */
+#define APR_ANYLOCK_TRYLOCK(lck)                \
+    (((lck)->type == apr_anylock_none)            \
+      ? APR_SUCCESS                                 \
+      : (((lck)->type == apr_anylock_threadmutex)     \
+          ? apr_thread_mutex_trylock((lck)->lock.tm)    \
+          : (((lck)->type == apr_anylock_procmutex)       \
+              ? apr_proc_mutex_trylock((lck)->lock.pm)      \
+              : (((lck)->type == apr_anylock_readlock)        \
+                  ? apr_thread_rwlock_tryrdlock((lck)->lock.rw) \
+                  : (((lck)->type == apr_anylock_writelock)       \
+                      ? apr_thread_rwlock_trywrlock((lck)->lock.rw) \
+                          : APR_EINVAL)))))
+
+#else /* APR_HAS_THREADS */
+
+#define APR_ANYLOCK_TRYLOCK(lck)                \
+    (((lck)->type == apr_anylock_none)            \
+      ? APR_SUCCESS                                 \
+          : (((lck)->type == apr_anylock_procmutex)       \
+              ? apr_proc_mutex_trylock((lck)->lock.pm)      \
+                          : APR_EINVAL))
+
+#endif /* APR_HAS_THREADS */
+
+#if APR_HAS_THREADS
+
+/** Unlock an apr_anylock_t structure */
+#define APR_ANYLOCK_UNLOCK(lck)              \
+    (((lck)->type == apr_anylock_none)         \
+      ? APR_SUCCESS                              \
+      : (((lck)->type == apr_anylock_threadmutex)  \
+          ? apr_thread_mutex_unlock((lck)->lock.tm)  \
+          : (((lck)->type == apr_anylock_procmutex)    \
+              ? apr_proc_mutex_unlock((lck)->lock.pm)    \
+              : ((((lck)->type == apr_anylock_readlock) || \
+                  ((lck)->type == apr_anylock_writelock))    \
+                  ? apr_thread_rwlock_unlock((lck)->lock.rw)   \
+                      : APR_EINVAL))))
+
+#else /* APR_HAS_THREADS */
+
+#define APR_ANYLOCK_UNLOCK(lck)              \
+    (((lck)->type == apr_anylock_none)         \
+      ? APR_SUCCESS                              \
+          : (((lck)->type == apr_anylock_procmutex)    \
+              ? apr_proc_mutex_unlock((lck)->lock.pm)    \
+                      : APR_EINVAL))
+
+#endif /* APR_HAS_THREADS */
+
+#endif /* !APR_ANYLOCK_H */
diff --git a/include/apr_atomic.h b/include/apr_atomic.h
new file mode 100644
index 00000000000..f34fdd2bd2e
--- /dev/null
+++ b/include/apr_atomic.h
@@ -0,0 +1,140 @@
+/* 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 APR_ATOMIC_H
+#define APR_ATOMIC_H
+
+/**
+ * @file apr_atomic.h
+ * @brief APR Atomic Operations
+ */
+
+#include "apr.h"
+#include "apr_pools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup apr_atomic Atomic Operations
+ * @ingroup APR 
+ * @{
+ */
+
+/**
+ * this function is required on some platforms to initialize the
+ * atomic operation's internal structures
+ * @param p pool
+ * @return APR_SUCCESS on successful completion
+ * @remark Programs do NOT need to call this directly. APR will call this
+ *         automatically from apr_initialize.
+ * @internal
+ */
+APR_DECLARE(apr_status_t) apr_atomic_init(apr_pool_t *p);
+
+/*
+ * Atomic operations on 32-bit values
+ * Note: Each of these functions internally implements a memory barrier
+ * on platforms that require it
+ */
+
+/**
+ * atomically read an apr_uint32_t from memory
+ * @param mem the pointer
+ */
+APR_DECLARE(apr_uint32_t) apr_atomic_read32(volatile apr_uint32_t *mem);
+
+/**
+ * atomically set an apr_uint32_t in memory
+ * @param mem pointer to the object
+ * @param val value that the object will assume
+ */
+APR_DECLARE(void) apr_atomic_set32(volatile apr_uint32_t *mem, apr_uint32_t val);
+
+/**
+ * atomically add 'val' to an apr_uint32_t
+ * @param mem pointer to the object
+ * @param val amount to add
+ * @return old value pointed to by mem
+ */
+APR_DECLARE(apr_uint32_t) apr_atomic_add32(volatile apr_uint32_t *mem, apr_uint32_t val);
+
+/**
+ * atomically subtract 'val' from an apr_uint32_t
+ * @param mem pointer to the object
+ * @param val amount to subtract
+ */
+APR_DECLARE(void) apr_atomic_sub32(volatile apr_uint32_t *mem, apr_uint32_t val);
+
+/**
+ * atomically increment an apr_uint32_t by 1
+ * @param mem pointer to the object
+ * @return old value pointed to by mem
+ */
+APR_DECLARE(apr_uint32_t) apr_atomic_inc32(volatile apr_uint32_t *mem);
+
+/**
+ * atomically decrement an apr_uint32_t by 1
+ * @param mem pointer to the atomic value
+ * @return zero if the value becomes zero on decrement, otherwise non-zero
+ */
+APR_DECLARE(int) apr_atomic_dec32(volatile apr_uint32_t *mem);
+
+/**
+ * compare an apr_uint32_t's value with 'cmp'.
+ * If they are the same swap the value with 'with'
+ * @param mem pointer to the value
+ * @param with what to swap it with
+ * @param cmp the value to compare it to
+ * @return the old value of *mem
+ */
+APR_DECLARE(apr_uint32_t) apr_atomic_cas32(volatile apr_uint32_t *mem, apr_uint32_t with,
+                              apr_uint32_t cmp);
+
+/**
+ * exchange an apr_uint32_t's value with 'val'.
+ * @param mem pointer to the value
+ * @param val what to swap it with
+ * @return the old value of *mem
+ */
+APR_DECLARE(apr_uint32_t) apr_atomic_xchg32(volatile apr_uint32_t *mem, apr_uint32_t val);
+
+/**
+ * compare the pointer's value with cmp.
+ * If they are the same swap the value with 'with'
+ * @param mem pointer to the pointer
+ * @param with what to swap it with
+ * @param cmp the value to compare it to
+ * @return the old value of the pointer
+ */
+APR_DECLARE(void*) apr_atomic_casptr(void *volatile *mem, void *with, const void *cmp);
+
+/**
+ * exchange a pair of pointer values
+ * @param mem pointer to the pointer
+ * @param with what to swap it with
+ * @return the old value of the pointer
+ */
+APR_DECLARE(void*) apr_atomic_xchgptr(void *volatile *mem, void *with);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* !APR_ATOMIC_H */
diff --git a/include/apr_base64.h b/include/apr_base64.h
new file mode 100644
index 00000000000..406ca368eee
--- /dev/null
+++ b/include/apr_base64.h
@@ -0,0 +1,146 @@
+/* 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.
+ * The apr_vsnprintf/apr_snprintf functions are based on, and used with the
+ * permission of, the  SIO stdio-replacement strx_* functions by Panos
+ * Tsirigotis <panos@alumni.cs.colorado.edu> for xinetd.
+ */
+
+/**
+ * @file apr_base64.h
+ * @brief APR-UTIL Base64 Encoding
+ */
+#ifndef APR_BASE64_H
+#define APR_BASE64_H
+
+#include "apu.h"
+#include "apr_general.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup APR_Util_Base64 Base64 Encoding
+ * @ingroup APR
+ * @{
+ */
+
+/* Simple BASE64 encode/decode functions.
+ * 
+ * As we might encode binary strings, hence we require the length of
+ * the incoming plain source. And return the length of what we decoded.
+ *
+ * The decoding function takes any non valid char (i.e. whitespace, \0
+ * or anything non A-Z,0-9 etc) as terminal.
+ * 
+ * The handling of terminating \0 characters differs from function to
+ * function.
+ *
+ */
+
+/**
+ * Given the length of an un-encoded string, get the length of the
+ * encoded string.
+ * @param len the length of an unencoded string.
+ * @return the length of the string after it is encoded, including the
+ * trailing \0
+ */ 
+APR_DECLARE(int) apr_base64_encode_len(int len) __attribute__((pure));
+
+/**
+ * Encode a text string using base64encoding. On EBCDIC machines, the input
+ * is first converted to ASCII.
+ * @param coded_dst The destination string for the encoded string. A \0 is
+ * appended.
+ * @param plain_src The original string in plain text
+ * @param len_plain_src The length of the plain text string
+ * @return the length of the encoded string, including the trailing \0
+ */ 
+APR_DECLARE(int) apr_base64_encode(char * coded_dst, const char *plain_src, 
+                                   int len_plain_src)
+                 __attribute__((nonnull(1,2)));
+
+/**
+ * Encode an text string using base64encoding. This is the same as
+ * apr_base64_encode() except on EBCDIC machines, where the conversion of the
+ * input to ASCII is left out.
+ * @param coded_dst The destination string for the encoded string. A \0 is
+ * appended.
+ * @param plain_src The original string in plain text
+ * @param len_plain_src The length of the plain text string
+ * @return the length of the encoded string, including the trailing \0
+ */ 
+APR_DECLARE(int) apr_base64_encode_binary(char * coded_dst,
+                                          const unsigned char *plain_src,
+                                          int len_plain_src)
+                 __attribute__((nonnull(1,2)));
+
+/**
+ * Encode a string into memory allocated from a pool in base 64 format
+ * @param p The pool to allocate from
+ * @param string The plaintext string
+ * @return The encoded string
+ */
+APR_DECLARE(char *) apr_pbase64_encode(apr_pool_t *p, const char *string)
+        __attribute__((nonnull(1,2)));
+
+/**
+ * Determine the maximum buffer length required to decode the plain text
+ * string given the encoded string.
+ * @param coded_src The encoded string
+ * @return the maximum required buffer length for the plain text string
+ */ 
+APR_DECLARE(int) apr_base64_decode_len(const char * coded_src)
+                 __attribute__((nonnull(1))) __attribute__((pure));
+
+/**
+ * Decode a string to plain text. On EBCDIC machines, the result is then
+ * converted to EBCDIC.
+ * @param plain_dst The destination string for the plain text. A \0 is
+ * appended.
+ * @param coded_src The encoded string 
+ * @return the length of the plain text string (excluding the trailing \0)
+ */ 
+APR_DECLARE(int) apr_base64_decode(char * plain_dst, const char *coded_src)
+                 __attribute__((nonnull(1,2)));
+
+/**
+ * Decode an string to plain text. This is the same as apr_base64_decode()
+ * except no \0 is appended and on EBCDIC machines, the conversion of the
+ * output to EBCDIC is left out.
+ * @param plain_dst The destination string for the plain text. The string is
+ * not \0-terminated.
+ * @param coded_src The encoded string 
+ * @return the length of the plain text string
+ */ 
+APR_DECLARE(int) apr_base64_decode_binary(unsigned char * plain_dst, 
+                                          const char *coded_src)
+                 __attribute__((nonnull(1,2)));
+
+/**
+ * Decode a base64 encoded string into memory allocated from a pool
+ * @param p The pool to allocate from
+ * @param bufcoded The encoded string
+ * @return The decoded string
+ */
+APR_DECLARE(char *) apr_pbase64_decode(apr_pool_t *p, const char *bufcoded)
+        __attribute__((nonnull(1,2)));
+
+/** @} */
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* !APR_BASE64_H */
diff --git a/include/apr_buckets.h b/include/apr_buckets.h
new file mode 100644
index 00000000000..abecd16ef8a
--- /dev/null
+++ b/include/apr_buckets.h
@@ -0,0 +1,1651 @@
+/* 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 apr_buckets.h
+ * @brief APR-UTIL Buckets/Bucket Brigades
+ */
+
+#ifndef APR_BUCKETS_H
+#define APR_BUCKETS_H
+
+#if defined(APR_BUCKET_DEBUG) && !defined(APR_RING_DEBUG)
+#define APR_RING_DEBUG
+#endif
+
+#include "apu.h"
+#include "apr_network_io.h"
+#include "apr_file_io.h"
+#include "apr_general.h"
+#include "apr_mmap.h"
+#include "apr_errno.h"
+#include "apr_ring.h"
+#include "apr.h"
+#if APR_HAVE_SYS_UIO_H
+#include <sys/uio.h>	/* for struct iovec */
+#endif
+#if APR_HAVE_STDARG_H
+#include <stdarg.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup APR_Util_Bucket_Brigades Bucket Brigades
+ * @ingroup APR
+ * @{ 
+ */
+
+/** default bucket buffer size - 8KB minus room for memory allocator headers */
+#define APR_BUCKET_BUFF_SIZE 8000
+
+/** Determines how a bucket or brigade should be read */
+typedef enum {
+    APR_BLOCK_READ,   /**< block until data becomes available */
+    APR_NONBLOCK_READ /**< return immediately if no data is available */
+} apr_read_type_e;
+
+/**
+ * The one-sentence buzzword-laden overview: Bucket brigades represent
+ * a complex data stream that can be passed through a layered IO
+ * system without unnecessary copying. A longer overview follows...
+ *
+ * A bucket brigade is a doubly linked list (ring) of buckets, so we
+ * aren't limited to inserting at the front and removing at the end.
+ * Buckets are only passed around as members of a brigade, although
+ * singleton buckets can occur for short periods of time.
+ *
+ * Buckets are data stores of various types. They can refer to data in
+ * memory, or part of a file or mmap area, or the output of a process,
+ * etc. Buckets also have some type-dependent accessor functions:
+ * read, split, copy, setaside, and destroy.
+ *
+ * read returns the address and size of the data in the bucket. If the
+ * data isn't in memory then it is read in and the bucket changes type
+ * so that it can refer to the new location of the data. If all the
+ * data doesn't fit in the bucket then a new bucket is inserted into
+ * the brigade to hold the rest of it.
+ *
+ * split divides the data in a bucket into two regions. After a split
+ * the original bucket refers to the first part of the data and a new
+ * bucket inserted into the brigade after the original bucket refers
+ * to the second part of the data. Reference counts are maintained as
+ * necessary.
+ *
+ * setaside ensures that the data in the bucket has a long enough
+ * lifetime. Sometimes it is convenient to create a bucket referring
+ * to data on the stack in the expectation that it will be consumed
+ * (output to the network) before the stack is unwound. If that
+ * expectation turns out not to be valid, the setaside function is
+ * called to move the data somewhere safer.
+ *
+ * copy makes a duplicate of the bucket structure as long as it's
+ * possible to have multiple references to a single copy of the
+ * data itself.  Not all bucket types can be copied.
+ *
+ * destroy maintains the reference counts on the resources used by a
+ * bucket and frees them if necessary.
+ *
+ * Note: all of the above functions have wrapper macros (apr_bucket_read(),
+ * apr_bucket_destroy(), etc), and those macros should be used rather
+ * than using the function pointers directly.
+ *
+ * To write a bucket brigade, they are first made into an iovec, so that we
+ * don't write too little data at one time.  Currently we ignore compacting the
+ * buckets into as few buckets as possible, but if we really want good
+ * performance, then we need to compact the buckets before we convert to an
+ * iovec, or possibly while we are converting to an iovec.
+ */
+
+/*
+ * Forward declaration of the main types.
+ */
+
+/** @see apr_bucket_brigade */
+typedef struct apr_bucket_brigade apr_bucket_brigade;
+/** @see apr_bucket */
+typedef struct apr_bucket apr_bucket;
+/** @see apr_bucket_alloc_t */
+typedef struct apr_bucket_alloc_t apr_bucket_alloc_t;
+
+/** @see apr_bucket_type_t */
+typedef struct apr_bucket_type_t apr_bucket_type_t;
+
+/**
+ * Basic bucket type
+ */
+struct apr_bucket_type_t {
+    /**
+     * The name of the bucket type
+     */
+    const char *name;
+    /** 
+     * The number of functions this bucket understands.  Can not be less than
+     * five.
+     */
+    int num_func;
+    /**
+     * Whether the bucket contains metadata (ie, information that
+     * describes the regular contents of the brigade).  The metadata
+     * is not returned by apr_bucket_read() and is not indicated by
+     * the ->length of the apr_bucket itself.  In other words, an
+     * empty bucket is safe to arbitrarily remove if and only if it
+     * contains no metadata.  In this sense, "data" is just raw bytes
+     * that are the "content" of the brigade and "metadata" describes
+     * that data but is not a proper part of it.
+     */
+    enum {
+        /** This bucket type represents actual data to send to the client. */
+        APR_BUCKET_DATA = 0,
+        /** This bucket type represents metadata. */
+        APR_BUCKET_METADATA = 1
+    } is_metadata;
+    /**
+     * Free the private data and any resources used by the bucket (if they
+     *  aren't shared with another bucket).  This function is required to be
+     *  implemented for all bucket types, though it might be a no-op on some
+     *  of them (namely ones that never allocate any private data structures).
+     * @param data The private data pointer from the bucket to be destroyed
+     */
+    void (*destroy)(void *data);
+
+    /**
+     * Read the data from the bucket. This is required to be implemented
+     *  for all bucket types.
+     * @param b The bucket to read from
+     * @param str A place to store the data read.  Allocation should only be
+     *            done if absolutely necessary. 
+     * @param len The amount of data read.
+     * @param block Should this read function block if there is more data that
+     *              cannot be read immediately.
+     */
+    apr_status_t (*read)(apr_bucket *b, const char **str, apr_size_t *len, 
+                         apr_read_type_e block);
+    
+    /**
+     * Make it possible to set aside the data for at least as long as the
+     *  given pool. Buckets containing data that could potentially die before
+     *  this pool (e.g. the data resides on the stack, in a child pool of
+     *  the given pool, or in a disjoint pool) must somehow copy, shift, or
+     *  transform the data to have the proper lifetime.
+     * @param e The bucket to convert
+     * @remark Some bucket types contain data that will always outlive the
+     *         bucket itself. For example no data (EOS and FLUSH), or the data
+     *         resides in global, constant memory (IMMORTAL), or the data is on
+     *      the heap (HEAP). For these buckets, apr_bucket_setaside_noop can
+     *      be used.
+     */
+    apr_status_t (*setaside)(apr_bucket *e, apr_pool_t *pool);
+
+    /**
+     * Split one bucket in two at the specified position by duplicating
+     *  the bucket structure (not the data) and modifying any necessary
+     *  start/end/offset information.  If it's not possible to do this
+     *  for the bucket type (perhaps the length of the data is indeterminate,
+     *  as with pipe and socket buckets), then APR_ENOTIMPL is returned.
+     * @param e The bucket to split
+     * @param point The offset of the first byte in the new bucket
+     */
+    apr_status_t (*split)(apr_bucket *e, apr_size_t point);
+
+    /**
+     * Copy the bucket structure (not the data), assuming that this is
+     *  possible for the bucket type. If it's not, APR_ENOTIMPL is returned.
+     * @param e The bucket to copy
+     * @param c Returns a pointer to the new bucket
+     */
+    apr_status_t (*copy)(apr_bucket *e, apr_bucket **c);
+
+};
+
+/**
+ * apr_bucket structures are allocated on the malloc() heap and
+ * their lifetime is controlled by the parent apr_bucket_brigade
+ * structure. Buckets can move from one brigade to another e.g. by
+ * calling APR_BRIGADE_CONCAT(). In general the data in a bucket has
+ * the same lifetime as the bucket and is freed when the bucket is
+ * destroyed; if the data is shared by more than one bucket (e.g.
+ * after a split) the data is freed when the last bucket goes away.
+ */
+struct apr_bucket {
+    /** Links to the rest of the brigade */
+    APR_RING_ENTRY(apr_bucket) link;
+    /** The type of bucket.  */
+    const apr_bucket_type_t *type;
+    /** The length of the data in the bucket.  This could have been implemented
+     *  with a function, but this is an optimization, because the most
+     *  common thing to do will be to get the length.  If the length is unknown,
+     *  the value of this field will be (apr_size_t)(-1).
+     */
+    apr_size_t length;
+    /** The start of the data in the bucket relative to the private base
+     *  pointer.  The vast majority of bucket types allow a fixed block of
+     *  data to be referenced by multiple buckets, each bucket pointing to
+     *  a different segment of the data.  That segment starts at base+start
+     *  and ends at base+start+length.  
+     *  If the length == (apr_size_t)(-1), then start == -1.
+     */
+    apr_off_t start;
+    /** type-dependent data hangs off this pointer */
+    void *data;	
+    /**
+     * Pointer to function used to free the bucket. This function should
+     * always be defined and it should be consistent with the memory
+     * function used to allocate the bucket. For example, if malloc() is 
+     * used to allocate the bucket, this pointer should point to free().
+     * @param e Pointer to the bucket being freed
+     */
+    void (*free)(void *e);
+    /** The freelist from which this bucket was allocated */
+    apr_bucket_alloc_t *list;
+};
+
+/** A list of buckets */
+struct apr_bucket_brigade {
+    /** The pool to associate the brigade with.  The data is not allocated out
+     *  of the pool, but a cleanup is registered with this pool.  If the 
+     *  brigade is destroyed by some mechanism other than pool destruction,
+     *  the destroying function is responsible for killing the cleanup.
+     */
+    apr_pool_t *p;
+    /** The buckets in the brigade are on this list. */
+    /*
+     * The apr_bucket_list structure doesn't actually need a name tag
+     * because it has no existence independent of struct apr_bucket_brigade;
+     * the ring macros are designed so that you can leave the name tag
+     * argument empty in this situation but apparently the Windows compiler
+     * doesn't like that.
+     */
+    APR_RING_HEAD(apr_bucket_list, apr_bucket) list;
+    /** The freelist from which this bucket was allocated */
+    apr_bucket_alloc_t *bucket_alloc;
+};
+
+
+/**
+ * Function called when a brigade should be flushed
+ */
+typedef apr_status_t (*apr_brigade_flush)(apr_bucket_brigade *bb, void *ctx);
+
+/*
+ * define APR_BUCKET_DEBUG if you want your brigades to be checked for
+ * validity at every possible instant.  this will slow your code down
+ * substantially but is a very useful debugging tool.
+ */
+#ifdef APR_BUCKET_DEBUG
+
+#define APR_BRIGADE_CHECK_CONSISTENCY(b) do {                   \
+    APR_RING_CHECK_CONSISTENCY(&(b)->list, apr_bucket, link);   \
+    assert(b->p != NULL);                                       \
+    assert(b->bucket_alloc != NULL);                            \
+} while (0)
+
+#define APR_BUCKET_CHECK_CONSISTENCY(e)					\
+        APR_RING_CHECK_ELEM_CONSISTENCY((e), apr_bucket, link)
+
+#else
+/**
+ * checks the ring pointers in a bucket brigade for consistency.  an
+ * abort() will be triggered if any inconsistencies are found.
+ *   note: this is a no-op unless APR_BUCKET_DEBUG is defined.
+ * @param b The brigade
+ */
+#define APR_BRIGADE_CHECK_CONSISTENCY(b)
+/**
+ * checks the brigade a bucket is in for ring consistency.  an
+ * abort() will be triggered if any inconsistencies are found.
+ *   note: this is a no-op unless APR_BUCKET_DEBUG is defined.
+ * @param e The bucket
+ */
+#define APR_BUCKET_CHECK_CONSISTENCY(e)
+#endif
+
+
+/**
+ * Wrappers around the RING macros to reduce the verbosity of the code
+ * that handles bucket brigades.
+ */
+/**
+ * The magic pointer value that indicates the head of the brigade
+ * @remark This is used to find the beginning and end of the brigade, eg:
+ * <pre>
+ *      while (e != APR_BRIGADE_SENTINEL(b)) {
+ *          ...
+ *          e = APR_BUCKET_NEXT(e);
+ *      }
+ * </pre>
+ * @param  b The brigade
+ * @return The magic pointer value
+ */
+#define APR_BRIGADE_SENTINEL(b)	APR_RING_SENTINEL(&(b)->list, apr_bucket, link)
+
+/**
+ * Determine if the bucket brigade is empty
+ * @param b The brigade to check
+ * @return true or false
+ */
+#define APR_BRIGADE_EMPTY(b)	APR_RING_EMPTY(&(b)->list, apr_bucket, link)
+
+/**
+ * Return the first bucket in a brigade
+ * @param b The brigade to query
+ * @return The first bucket in the brigade
+ */
+#define APR_BRIGADE_FIRST(b)	APR_RING_FIRST(&(b)->list)
+/**
+ * Return the last bucket in a brigade
+ * @param b The brigade to query
+ * @return The last bucket in the brigade
+ */
+#define APR_BRIGADE_LAST(b)	APR_RING_LAST(&(b)->list)
+
+/**
+ * Insert a single bucket at the front of a brigade
+ * @param b The brigade to add to
+ * @param e The bucket to insert
+ */
+#define APR_BRIGADE_INSERT_HEAD(b, e) do {				\
+	apr_bucket *ap__b = (e);                                        \
+	APR_RING_INSERT_HEAD(&(b)->list, ap__b, apr_bucket, link);	\
+        APR_BRIGADE_CHECK_CONSISTENCY((b));				\
+    } while (0)
+
+/**
+ * Insert a single bucket at the end of a brigade
+ * @param b The brigade to add to
+ * @param e The bucket to insert
+ */
+#define APR_BRIGADE_INSERT_TAIL(b, e) do {				\
+	apr_bucket *ap__b = (e);					\
+	APR_RING_INSERT_TAIL(&(b)->list, ap__b, apr_bucket, link);	\
+        APR_BRIGADE_CHECK_CONSISTENCY((b));				\
+    } while (0)
+
+/**
+ * Concatenate brigade b onto the end of brigade a, leaving brigade b empty
+ * @param a The first brigade
+ * @param b The second brigade
+ */
+#define APR_BRIGADE_CONCAT(a, b) do {					\
+        APR_RING_CONCAT(&(a)->list, &(b)->list, apr_bucket, link);	\
+        APR_BRIGADE_CHECK_CONSISTENCY((a));				\
+    } while (0)
+
+/**
+ * Prepend brigade b onto the beginning of brigade a, leaving brigade b empty
+ * @param a The first brigade
+ * @param b The second brigade
+ */
+#define APR_BRIGADE_PREPEND(a, b) do {					\
+        APR_RING_PREPEND(&(a)->list, &(b)->list, apr_bucket, link);	\
+        APR_BRIGADE_CHECK_CONSISTENCY((a));				\
+    } while (0)
+
+/**
+ * Insert a single bucket before a specified bucket
+ * @param a The bucket to insert before
+ * @param b The bucket to insert
+ */
+#define APR_BUCKET_INSERT_BEFORE(a, b) do {				\
+	apr_bucket *ap__a = (a), *ap__b = (b);				\
+	APR_RING_INSERT_BEFORE(ap__a, ap__b, link);			\
+        APR_BUCKET_CHECK_CONSISTENCY(ap__a);				\
+    } while (0)
+
+/**
+ * Insert a single bucket after a specified bucket
+ * @param a The bucket to insert after
+ * @param b The bucket to insert
+ */
+#define APR_BUCKET_INSERT_AFTER(a, b) do {				\
+	apr_bucket *ap__a = (a), *ap__b = (b);				\
+	APR_RING_INSERT_AFTER(ap__a, ap__b, link);			\
+        APR_BUCKET_CHECK_CONSISTENCY(ap__a);				\
+    } while (0)
+
+/**
+ * Get the next bucket in the list
+ * @param e The current bucket
+ * @return The next bucket
+ */
+#define APR_BUCKET_NEXT(e)	APR_RING_NEXT((e), link)
+/**
+ * Get the previous bucket in the list
+ * @param e The current bucket
+ * @return The previous bucket
+ */
+#define APR_BUCKET_PREV(e)	APR_RING_PREV((e), link)
+
+/**
+ * Remove a bucket from its bucket brigade
+ * @param e The bucket to remove
+ */
+#define APR_BUCKET_REMOVE(e)	APR_RING_REMOVE((e), link)
+
+/**
+ * Initialize a new bucket's prev/next pointers
+ * @param e The bucket to initialize
+ */
+#define APR_BUCKET_INIT(e)	APR_RING_ELEM_INIT((e), link)
+
+/**
+ * Determine if a bucket contains metadata.  An empty bucket is
+ * safe to arbitrarily remove if and only if this is false.
+ * @param e The bucket to inspect
+ * @return true or false
+ */
+#define APR_BUCKET_IS_METADATA(e)    ((e)->type->is_metadata)
+
+/**
+ * Determine if a bucket is a FLUSH bucket
+ * @param e The bucket to inspect
+ * @return true or false
+ */
+#define APR_BUCKET_IS_FLUSH(e)       ((e)->type == &apr_bucket_type_flush)
+/**
+ * Determine if a bucket is an EOS bucket
+ * @param e The bucket to inspect
+ * @return true or false
+ */
+#define APR_BUCKET_IS_EOS(e)         ((e)->type == &apr_bucket_type_eos)
+/**
+ * Determine if a bucket is a FILE bucket
+ * @param e The bucket to inspect
+ * @return true or false
+ */
+#define APR_BUCKET_IS_FILE(e)        ((e)->type == &apr_bucket_type_file)
+/**
+ * Determine if a bucket is a PIPE bucket
+ * @param e The bucket to inspect
+ * @return true or false
+ */
+#define APR_BUCKET_IS_PIPE(e)        ((e)->type == &apr_bucket_type_pipe)
+/**
+ * Determine if a bucket is a SOCKET bucket
+ * @param e The bucket to inspect
+ * @return true or false
+ */
+#define APR_BUCKET_IS_SOCKET(e)      ((e)->type == &apr_bucket_type_socket)
+/**
+ * Determine if a bucket is a HEAP bucket
+ * @param e The bucket to inspect
+ * @return true or false
+ */
+#define APR_BUCKET_IS_HEAP(e)        ((e)->type == &apr_bucket_type_heap)
+/**
+ * Determine if a bucket is a TRANSIENT bucket
+ * @param e The bucket to inspect
+ * @return true or false
+ */
+#define APR_BUCKET_IS_TRANSIENT(e)   ((e)->type == &apr_bucket_type_transient)
+/**
+ * Determine if a bucket is a IMMORTAL bucket
+ * @param e The bucket to inspect
+ * @return true or false
+ */
+#define APR_BUCKET_IS_IMMORTAL(e)    ((e)->type == &apr_bucket_type_immortal)
+#if APR_HAS_MMAP
+/**
+ * Determine if a bucket is a MMAP bucket
+ * @param e The bucket to inspect
+ * @return true or false
+ */
+#define APR_BUCKET_IS_MMAP(e)        ((e)->type == &apr_bucket_type_mmap)
+#endif
+/**
+ * Determine if a bucket is a POOL bucket
+ * @param e The bucket to inspect
+ * @return true or false
+ */
+#define APR_BUCKET_IS_POOL(e)        ((e)->type == &apr_bucket_type_pool)
+
+/*
+ * General-purpose reference counting for the various bucket types.
+ *
+ * Any bucket type that keeps track of the resources it uses (i.e.
+ * most of them except for IMMORTAL, TRANSIENT, and EOS) needs to
+ * attach a reference count to the resource so that it can be freed
+ * when the last bucket that uses it goes away. Resource-sharing may
+ * occur because of bucket splits or buckets that refer to globally
+ * cached data. */
+
+/** @see apr_bucket_refcount */
+typedef struct apr_bucket_refcount apr_bucket_refcount;
+/**
+ * The structure used to manage the shared resource must start with an
+ * apr_bucket_refcount which is updated by the general-purpose refcount
+ * code. A pointer to the bucket-type-dependent private data structure
+ * can be cast to a pointer to an apr_bucket_refcount and vice versa.
+ */
+struct apr_bucket_refcount {
+    /** The number of references to this bucket */
+    int          refcount;
+};
+
+/*  *****  Reference-counted bucket types  *****  */
+
+/** @see apr_bucket_heap */
+typedef struct apr_bucket_heap apr_bucket_heap;
+/**
+ * A bucket referring to data allocated off the heap.
+ */
+struct apr_bucket_heap {
+    /** Number of buckets using this memory */
+    apr_bucket_refcount  refcount;
+    /** The start of the data actually allocated.  This should never be
+     * modified, it is only used to free the bucket.
+     */
+    char    *base;
+    /** how much memory was allocated */
+    apr_size_t  alloc_len;
+    /** function to use to delete the data */
+    void (*free_func)(void *data);
+};
+
+/** @see apr_bucket_pool */
+typedef struct apr_bucket_pool apr_bucket_pool;
+/**
+ * A bucket referring to data allocated from a pool
+ */
+struct apr_bucket_pool {
+    /** The pool bucket must be able to be easily morphed to a heap
+     * bucket if the pool gets cleaned up before all references are
+     * destroyed.  This apr_bucket_heap structure is populated automatically
+     * when the pool gets cleaned up, and subsequent calls to pool_read()
+     * will result in the apr_bucket in question being morphed into a
+     * regular heap bucket.  (To avoid having to do many extra refcount
+     * manipulations and b->data manipulations, the apr_bucket_pool
+     * struct actually *contains* the apr_bucket_heap struct that it
+     * will become as its first element; the two share their
+     * apr_bucket_refcount members.)
+     */
+    apr_bucket_heap  heap;
+    /** The block of data actually allocated from the pool.
+     * Segments of this block are referenced by adjusting
+     * the start and length of the apr_bucket accordingly.
+     * This will be NULL after the pool gets cleaned up.
+     */
+    const char *base;
+    /** The pool the data was allocated from.  When the pool
+     * is cleaned up, this gets set to NULL as an indicator
+     * to pool_read() that the data is now on the heap and
+     * so it should morph the bucket into a regular heap
+     * bucket before continuing.
+     */
+    apr_pool_t *pool;
+    /** The freelist this structure was allocated from, which is
+     * needed in the cleanup phase in order to allocate space on the heap
+     */
+    apr_bucket_alloc_t *list;
+};
+
+#if APR_HAS_MMAP
+/** @see apr_bucket_mmap */
+typedef struct apr_bucket_mmap apr_bucket_mmap;
+/**
+ * A bucket referring to an mmap()ed file
+ */
+struct apr_bucket_mmap {
+    /** Number of buckets using this memory */
+    apr_bucket_refcount  refcount;
+    /** The mmap this sub_bucket refers to */
+    apr_mmap_t *mmap;
+};
+#endif
+
+/** @see apr_bucket_file */
+typedef struct apr_bucket_file apr_bucket_file;
+/**
+ * A bucket referring to an file
+ */
+struct apr_bucket_file {
+    /** Number of buckets using this memory */
+    apr_bucket_refcount  refcount;
+    /** The file this bucket refers to */
+    apr_file_t *fd;
+    /** The pool into which any needed structures should
+     *  be created while reading from this file bucket */
+    apr_pool_t *readpool;
+#if APR_HAS_MMAP
+    /** Whether this bucket should be memory-mapped if
+     *  a caller tries to read from it */
+    int can_mmap;
+#endif /* APR_HAS_MMAP */
+    /** File read block size */
+    apr_size_t read_size;
+};
+
+/** @see apr_bucket_structs */
+typedef union apr_bucket_structs apr_bucket_structs;
+/**
+ * A union of all bucket structures so we know what
+ * the max size is.
+ */
+union apr_bucket_structs {
+    apr_bucket      b;      /**< Bucket */
+    apr_bucket_heap heap;   /**< Heap */
+    apr_bucket_pool pool;   /**< Pool */
+#if APR_HAS_MMAP
+    apr_bucket_mmap mmap;   /**< MMap */
+#endif
+    apr_bucket_file file;   /**< File */
+};
+
+/**
+ * The amount that apr_bucket_alloc() should allocate in the common case.
+ * Note: this is twice as big as apr_bucket_structs to allow breathing
+ * room for third-party bucket types.
+ */
+#define APR_BUCKET_ALLOC_SIZE  APR_ALIGN_DEFAULT(2*sizeof(apr_bucket_structs))
+
+/*  *****  Bucket Brigade Functions  *****  */
+/**
+ * Create a new bucket brigade.  The bucket brigade is originally empty.
+ * @param p The pool to associate with the brigade.  Data is not allocated out
+ *          of the pool, but a cleanup is registered.
+ * @param list The bucket allocator to use
+ * @return The empty bucket brigade
+ */
+APR_DECLARE(apr_bucket_brigade *) apr_brigade_create(apr_pool_t *p,
+                                                     apr_bucket_alloc_t *list)
+                                  __attribute__((nonnull(1,2)));
+
+/**
+ * Destroy an entire bucket brigade.  This includes destroying all of the
+ * buckets within the bucket brigade's bucket list. 
+ * @param b The bucket brigade to destroy
+ */
+APR_DECLARE(apr_status_t) apr_brigade_destroy(apr_bucket_brigade *b)
+                          __attribute__((nonnull(1)));
+
+/**
+ * Empty out an entire bucket brigade.  This includes destroying all of the
+ * buckets within the bucket brigade's bucket list.  This is similar to
+ * apr_brigade_destroy(), except that it does not deregister the brigade's
+ * pool cleanup function.
+ * @param data The bucket brigade to clean up
+ * @remark Generally, you should use apr_brigade_destroy().  This function
+ *         can be useful in situations where you have a single brigade that
+ *         you wish to reuse many times by destroying all of the buckets in
+ *         the brigade and putting new buckets into it later.
+ */
+APR_DECLARE(apr_status_t) apr_brigade_cleanup(void *data)
+                          __attribute__((nonnull(1)));
+
+/**
+ * Move the buckets from the tail end of the existing brigade @a b into
+ * the brigade @a a. If @a a is NULL a new brigade is created. Buckets
+ * from @a e to the last bucket (inclusively) of brigade @a b are moved
+ * from @a b to the returned brigade @a a.
+ *
+ * @param b The brigade to split
+ * @param e The first bucket to move
+ * @param a The brigade which should be used for the result or NULL if
+ *          a new brigade should be created. The brigade @a a will be
+ *          cleared if it is not empty.
+ * @return The brigade supplied in @a a or a new one if @a a was NULL.
+ * @warning Note that this function allocates a new brigade if @a a is
+ * NULL so memory consumption should be carefully considered.
+ */
+APR_DECLARE(apr_bucket_brigade *) apr_brigade_split_ex(apr_bucket_brigade *b,
+                                                       apr_bucket *e,
+                                                       apr_bucket_brigade *a)
+                                  __attribute__((nonnull(1,2)));
+
+/**
+ * Create a new bucket brigade and move the buckets from the tail end
+ * of an existing brigade into the new brigade.  Buckets from 
+ * @a e to the last bucket (inclusively) of brigade @a b
+ * are moved from @a b to the returned brigade.
+ * @param b The brigade to split 
+ * @param e The first bucket to move
+ * @return The new brigade
+ * @warning Note that this function always allocates a new brigade
+ * so memory consumption should be carefully considered.
+ */
+APR_DECLARE(apr_bucket_brigade *) apr_brigade_split(apr_bucket_brigade *b,
+                                                    apr_bucket *e)
+                                  __attribute__((nonnull(1,2)));
+
+/**
+ * Partition a bucket brigade at a given offset (in bytes from the start of
+ * the brigade).  This is useful whenever a filter wants to use known ranges
+ * of bytes from the brigade; the ranges can even overlap.
+ * @param b The brigade to partition
+ * @param point The offset at which to partition the brigade
+ * @param after_point Returns a pointer to the first bucket after the partition
+ * @return APR_SUCCESS on success, APR_INCOMPLETE if the contents of the
+ * brigade were shorter than @a point, or an error code.
+ * @remark if APR_INCOMPLETE is returned, @a after_point will be set to
+ * the brigade sentinel.
+ */
+APR_DECLARE(apr_status_t) apr_brigade_partition(apr_bucket_brigade *b,
+                                                apr_off_t point,
+                                                apr_bucket **after_point)
+                          __attribute__((nonnull(1,3)));
+
+/**
+ * Return the total length of the brigade.
+ * @param bb The brigade to compute the length of
+ * @param read_all Read unknown-length buckets to force a size
+ * @param length Returns the length of the brigade (up to the end, or up
+ *               to a bucket read error), or -1 if the brigade has buckets
+ *               of indeterminate length and read_all is 0.
+ */
+APR_DECLARE(apr_status_t) apr_brigade_length(apr_bucket_brigade *bb,
+                                             int read_all,
+                                             apr_off_t *length)
+                          __attribute__((nonnull(1,3)));
+
+/**
+ * Take a bucket brigade and store the data in a flat char*
+ * @param bb The bucket brigade to create the char* from
+ * @param c The char* to write into
+ * @param len The maximum length of the char array. On return, it is the
+ *            actual length of the char array.
+ */
+APR_DECLARE(apr_status_t) apr_brigade_flatten(apr_bucket_brigade *bb,
+                                              char *c,
+                                              apr_size_t *len)
+                          __attribute__((nonnull(1,2,3)));
+
+/**
+ * Creates a pool-allocated string representing a flat bucket brigade
+ * @param bb The bucket brigade to create the char array from
+ * @param c On return, the allocated char array
+ * @param len On return, the length of the char array.
+ * @param pool The pool to allocate the string from.
+ */
+APR_DECLARE(apr_status_t) apr_brigade_pflatten(apr_bucket_brigade *bb, 
+                                               char **c,
+                                               apr_size_t *len,
+                                               apr_pool_t *pool)
+                          __attribute__((nonnull(1,2,3,4)));
+
+/**
+ * Split a brigade to represent one LF line.
+ * @param bbOut The bucket brigade that will have the LF line appended to.
+ * @param bbIn The input bucket brigade to search for a LF-line.
+ * @param block The blocking mode to be used to split the line.
+ * @param maxbytes The maximum bytes to read.  If this many bytes are seen
+ *                 without a LF, the brigade will contain a partial line.
+ */
+APR_DECLARE(apr_status_t) apr_brigade_split_line(apr_bucket_brigade *bbOut,
+                                                 apr_bucket_brigade *bbIn,
+                                                 apr_read_type_e block,
+                                                 apr_off_t maxbytes)
+                          __attribute__((nonnull(1,2)));
+
+/**
+ * Create an iovec of the elements in a bucket_brigade... return number 
+ * of elements used.  This is useful for writing to a file or to the
+ * network efficiently.
+ * @param b The bucket brigade to create the iovec from
+ * @param vec The iovec to create
+ * @param nvec The number of elements in the iovec. On return, it is the
+ *             number of iovec elements actually filled out.
+ */
+APR_DECLARE(apr_status_t) apr_brigade_to_iovec(apr_bucket_brigade *b, 
+                                               struct iovec *vec, int *nvec)
+                          __attribute__((nonnull(1,2,3)));
+
+/**
+ * This function writes a list of strings into a bucket brigade. 
+ * @param b The bucket brigade to add to
+ * @param flush The flush function to use if the brigade is full
+ * @param ctx The structure to pass to the flush function
+ * @param va A list of strings to add
+ * @return APR_SUCCESS or error code.
+ */
+APR_DECLARE(apr_status_t) apr_brigade_vputstrs(apr_bucket_brigade *b,
+                                               apr_brigade_flush flush,
+                                               void *ctx,
+                                               va_list va)
+                          __attribute__((nonnull(1)));
+
+/**
+ * This function writes a string into a bucket brigade.
+ *
+ * The apr_brigade_write function attempts to be efficient with the
+ * handling of heap buckets. Regardless of the amount of data stored
+ * inside a heap bucket, heap buckets are a fixed size to promote their
+ * reuse.
+ *
+ * If an attempt is made to write a string to a brigade that already 
+ * ends with a heap bucket, this function will attempt to pack the
+ * string into the remaining space in the previous heap bucket, before
+ * allocating a new heap bucket.
+ *
+ * This function always returns APR_SUCCESS, unless a flush function is
+ * passed, in which case the return value of the flush function will be
+ * returned if used.
+ * @param b The bucket brigade to add to
+ * @param flush The flush function to use if the brigade is full
+ * @param ctx The structure to pass to the flush function
+ * @param str The string to add
+ * @param nbyte The number of bytes to write
+ * @return APR_SUCCESS or error code
+ */
+APR_DECLARE(apr_status_t) apr_brigade_write(apr_bucket_brigade *b,
+                                            apr_brigade_flush flush, void *ctx,
+                                            const char *str, apr_size_t nbyte)
+                          __attribute__((nonnull(1,4)));
+
+/**
+ * This function writes multiple strings into a bucket brigade.
+ * @param b The bucket brigade to add to
+ * @param flush The flush function to use if the brigade is full
+ * @param ctx The structure to pass to the flush function
+ * @param vec The strings to add (address plus length for each)
+ * @param nvec The number of entries in iovec
+ * @return APR_SUCCESS or error code
+ */
+APR_DECLARE(apr_status_t) apr_brigade_writev(apr_bucket_brigade *b,
+                                             apr_brigade_flush flush,
+                                             void *ctx,
+                                             const struct iovec *vec,
+                                             apr_size_t nvec)
+                          __attribute__((nonnull(1,4)));
+
+/**
+ * This function writes a string into a bucket brigade.
+ * @param bb The bucket brigade to add to
+ * @param flush The flush function to use if the brigade is full
+ * @param ctx The structure to pass to the flush function
+ * @param str The string to add
+ * @return APR_SUCCESS or error code
+ */
+APR_DECLARE(apr_status_t) apr_brigade_puts(apr_bucket_brigade *bb,
+                                           apr_brigade_flush flush, void *ctx,
+                                           const char *str)
+                          __attribute__((nonnull(1,4)));
+
+/**
+ * This function writes a character into a bucket brigade.
+ * @param b The bucket brigade to add to
+ * @param flush The flush function to use if the brigade is full
+ * @param ctx The structure to pass to the flush function
+ * @param c The character to add
+ * @return APR_SUCCESS or error code
+ */
+APR_DECLARE(apr_status_t) apr_brigade_putc(apr_bucket_brigade *b,
+                                           apr_brigade_flush flush, void *ctx,
+                                           const char c)
+                          __attribute__((nonnull(1)));
+
+/**
+ * This function writes an unspecified number of strings into a bucket brigade.
+ * @param b The bucket brigade to add to
+ * @param flush The flush function to use if the brigade is full
+ * @param ctx The structure to pass to the flush function
+ * @param ... The strings to add. The final string must be NULL
+ * @return APR_SUCCESS or error code
+ */
+APR_DECLARE_NONSTD(apr_status_t) apr_brigade_putstrs(apr_bucket_brigade *b,
+                                                     apr_brigade_flush flush,
+                                                     void *ctx, ...)
+#if defined(__GNUC__) && __GNUC__ >= 4
+    __attribute__((sentinel))
+#endif
+    __attribute__((nonnull(1)))
+    ;
+
+/**
+ * Evaluate a printf and put the resulting string at the end 
+ * of the bucket brigade.
+ * @param b The brigade to write to
+ * @param flush The flush function to use if the brigade is full
+ * @param ctx The structure to pass to the flush function
+ * @param fmt The format of the string to write
+ * @param ... The arguments to fill out the format
+ * @return APR_SUCCESS or error code
+ */
+APR_DECLARE_NONSTD(apr_status_t) apr_brigade_printf(apr_bucket_brigade *b, 
+                                                    apr_brigade_flush flush,
+                                                    void *ctx,
+                                                    const char *fmt, ...)
+                                 __attribute__((format(printf,4,5)))
+                                 __attribute__((nonnull(1)));
+
+/**
+ * Evaluate a printf and put the resulting string at the end 
+ * of the bucket brigade.
+ * @param b The brigade to write to
+ * @param flush The flush function to use if the brigade is full
+ * @param ctx The structure to pass to the flush function
+ * @param fmt The format of the string to write
+ * @param va The arguments to fill out the format
+ * @return APR_SUCCESS or error code
+ */
+APR_DECLARE(apr_status_t) apr_brigade_vprintf(apr_bucket_brigade *b, 
+                                              apr_brigade_flush flush,
+                                              void *ctx,
+                                              const char *fmt, va_list va)
+                          __attribute__((nonnull(1,4)));
+
+/**
+ * Utility function to insert a file (or a segment of a file) onto the
+ * end of the brigade.  The file is split into multiple buckets if it
+ * is larger than the maximum size which can be represented by a
+ * single bucket.
+ * @param bb the brigade to insert into
+ * @param f the file to insert
+ * @param start the offset of the start of the segment
+ * @param len the length of the segment of the file to insert
+ * @param p pool from which file buckets are allocated
+ * @return the last bucket inserted
+ */
+APR_DECLARE(apr_bucket *) apr_brigade_insert_file(apr_bucket_brigade *bb,
+                                                  apr_file_t *f,
+                                                  apr_off_t start,
+                                                  apr_off_t len,
+                                                  apr_pool_t *p)
+                          __attribute__((nonnull(1,2,5)));
+
+
+
+/*  *****  Bucket freelist functions *****  */
+/**
+ * Create a bucket allocator.
+ * @param p This pool's underlying apr_allocator_t is used to allocate memory
+ *          for the bucket allocator.  When the pool is destroyed, the bucket
+ *          allocator's cleanup routine will free all memory that has been
+ *          allocated from it.
+ * @remark  The reason the allocator gets its memory from the pool's
+ *          apr_allocator_t rather than from the pool itself is because
+ *          the bucket allocator will free large memory blocks back to the
+ *          allocator when it's done with them, thereby preventing memory
+ *          footprint growth that would occur if we allocated from the pool.
+ * @warning The allocator must never be used by more than one thread at a time.
+ */
+APR_DECLARE_NONSTD(apr_bucket_alloc_t *) apr_bucket_alloc_create(apr_pool_t *p);
+
+/**
+ * Create a bucket allocator.
+ * @param allocator This apr_allocator_t is used to allocate both the bucket
+ *          allocator and all memory handed out by the bucket allocator.  The
+ *          caller is responsible for destroying the bucket allocator and the
+ *          apr_allocator_t -- no automatic cleanups will happen.
+ * @warning The allocator must never be used by more than one thread at a time.
+ */
+APR_DECLARE_NONSTD(apr_bucket_alloc_t *) apr_bucket_alloc_create_ex(
+                                                 apr_allocator_t *allocator)
+                                         __attribute__((nonnull(1)));
+
+/**
+ * Destroy a bucket allocator.
+ * @param list The allocator to be destroyed
+ */
+APR_DECLARE_NONSTD(void) apr_bucket_alloc_destroy(apr_bucket_alloc_t *list)
+                         __attribute__((nonnull(1)));
+
+/**
+ * Get the aligned size corresponding to the requested size, but minus the
+ * allocator(s) overhead such that the allocation would remain in the
+ * same boundary.
+ * @param list The allocator from which to the memory would be allocated.
+ * @param size The requested size.
+ * @return The corresponding aligned/floored size.
+ */
+APR_DECLARE_NONSTD(apr_size_t) apr_bucket_alloc_aligned_floor(apr_bucket_alloc_t *list,
+                                                              apr_size_t size)
+                         __attribute__((nonnull(1)));
+
+/**
+ * Allocate memory for use by the buckets.
+ * @param size The amount to allocate.
+ * @param list The allocator from which to allocate the memory.
+ */
+APR_DECLARE_NONSTD(void *) apr_bucket_alloc(apr_size_t size,
+                                            apr_bucket_alloc_t *list)
+                           __attribute__((nonnull(2)));
+
+/**
+ * Free memory previously allocated with apr_bucket_alloc().
+ * @param block The block of memory to be freed.
+ */
+APR_DECLARE_NONSTD(void) apr_bucket_free(void *block)
+                         __attribute__((nonnull(1)));
+
+
+/*  *****  Bucket Functions  *****  */
+/**
+ * Free the resources used by a bucket. If multiple buckets refer to
+ * the same resource it is freed when the last one goes away.
+ * @see apr_bucket_delete()
+ * @param e The bucket to destroy
+ */
+#define apr_bucket_destroy(e) do {					\
+        (e)->type->destroy((e)->data);					\
+        (e)->free(e);							\
+    } while (0)
+
+/**
+ * Delete a bucket by removing it from its brigade (if any) and then
+ * destroying it.
+ * @remark This mainly acts as an aid in avoiding code verbosity.  It is
+ * the preferred exact equivalent to:
+ * <pre>
+ *      APR_BUCKET_REMOVE(e);
+ *      apr_bucket_destroy(e);
+ * </pre>
+ * @param e The bucket to delete
+ */
+#define apr_bucket_delete(e) do {					\
+        APR_BUCKET_REMOVE(e);						\
+        apr_bucket_destroy(e);						\
+    } while (0)
+
+/**
+ * Read some data from the bucket.
+ *
+ * The apr_bucket_read function returns a convenient amount of data
+ * from the bucket provided, writing the address and length of the
+ * data to the pointers provided by the caller. The function tries
+ * as hard as possible to avoid a memory copy.
+ *
+ * Buckets are expected to be a member of a brigade at the time they
+ * are read.
+ *
+ * In typical application code, buckets are read in a loop, and after
+ * each bucket is read and processed, it is moved or deleted from the
+ * brigade and the next bucket read.
+ *
+ * The definition of "convenient" depends on the type of bucket that
+ * is being read, and is decided by APR. In the case of memory based
+ * buckets such as heap and immortal buckets, a pointer will be
+ * returned to the location of the buffer containing the complete
+ * contents of the bucket.
+ *
+ * Some buckets, such as the socket bucket, might have no concept
+ * of length. If an attempt is made to read such a bucket, the
+ * apr_bucket_read function will read a convenient amount of data
+ * from the socket. The socket bucket is magically morphed into a
+ * heap bucket containing the just-read data, and a new socket bucket
+ * is inserted just after this heap bucket.
+ *
+ * To understand why apr_bucket_read might do this, consider the loop
+ * described above to read and process buckets. The current bucket
+ * is magically morphed into a heap bucket and returned to the caller.
+ * The caller processes the data, and deletes the heap bucket, moving
+ * onto the next bucket, the new socket bucket. This process repeats,
+ * giving the illusion of a bucket brigade that contains potentially
+ * infinite amounts of data. It is up to the caller to decide at what
+ * point to stop reading buckets.
+ *
+ * Some buckets, such as the file bucket, might have a fixed size,
+ * but be significantly larger than is practical to store in RAM in
+ * one go. As with the socket bucket, if an attempt is made to read
+ * from a file bucket, the file bucket is magically morphed into a
+ * heap bucket containing a convenient amount of data read from the
+ * current offset in the file. During the read, the offset will be
+ * moved forward on the file, and a new file bucket will be inserted
+ * directly after the current bucket representing the remainder of the
+ * file. If the heap bucket was large enough to store the whole
+ * remainder of the file, no more file buckets are inserted, and the
+ * file bucket will disappear completely.
+ *
+ * The pattern for reading buckets described above does create the
+ * illusion that the code is willing to swallow buckets that might be
+ * too large for the system to handle in one go. This however is just
+ * an illusion: APR will always ensure that large (file) or infinite
+ * (socket) buckets are broken into convenient bite sized heap buckets
+ * before data is returned to the caller.
+ *
+ * There is a potential gotcha to watch for: if buckets are read in a
+ * loop, and aren't deleted after being processed, the potentially large
+ * bucket will slowly be converted into RAM resident heap buckets. If
+ * the file is larger than available RAM, an out of memory condition
+ * could be caused if the application is not careful to manage this.
+ *
+ * @param e The bucket to read from
+ * @param str The location to store a pointer to the data in
+ * @param len The location to store the amount of data read
+ * @param block Whether the read function blocks
+ */
+#define apr_bucket_read(e,str,len,block) (e)->type->read(e, str, len, block)
+
+/**
+ * Setaside data so that stack data is not destroyed on returning from
+ * the function
+ * @param e The bucket to setaside
+ * @param p The pool to setaside into
+ */
+#define apr_bucket_setaside(e,p) (e)->type->setaside(e,p)
+
+/**
+ * Split one bucket in two at the point provided.
+ * 
+ * Once split, the original bucket becomes the first of the two new buckets.
+ * 
+ * (It is assumed that the bucket is a member of a brigade when this
+ * function is called).
+ * @param e The bucket to split
+ * @param point The offset to split the bucket at
+ */
+#define apr_bucket_split(e,point) (e)->type->split(e, point)
+
+/**
+ * Copy a bucket.
+ * @param e The bucket to copy
+ * @param c Returns a pointer to the new bucket
+ */
+#define apr_bucket_copy(e,c) (e)->type->copy(e, c)
+
+/* Bucket type handling */
+
+/**
+ * This function simply returns APR_SUCCESS to denote that the bucket does
+ * not require anything to happen for its setaside() function. This is
+ * appropriate for buckets that have "immortal" data -- the data will live
+ * at least as long as the bucket.
+ * @param data The bucket to setaside
+ * @param pool The pool defining the desired lifetime of the bucket data
+ * @return APR_SUCCESS
+ */ 
+APR_DECLARE_NONSTD(apr_status_t) apr_bucket_setaside_noop(apr_bucket *data,
+                                                          apr_pool_t *pool);
+
+/**
+ * A place holder function that signifies that the setaside function was not
+ * implemented for this bucket
+ * @param data The bucket to setaside
+ * @param pool The pool defining the desired lifetime of the bucket data
+ * @return APR_ENOTIMPL
+ */ 
+APR_DECLARE_NONSTD(apr_status_t) apr_bucket_setaside_notimpl(apr_bucket *data,
+                                                             apr_pool_t *pool);
+
+/**
+ * A place holder function that signifies that the split function was not
+ * implemented for this bucket
+ * @param data The bucket to split
+ * @param point The location to split the bucket
+ * @return APR_ENOTIMPL
+ */ 
+APR_DECLARE_NONSTD(apr_status_t) apr_bucket_split_notimpl(apr_bucket *data,
+                                                          apr_size_t point);
+
+/**
+ * A place holder function that signifies that the copy function was not
+ * implemented for this bucket
+ * @param e The bucket to copy
+ * @param c Returns a pointer to the new bucket
+ * @return APR_ENOTIMPL
+ */
+APR_DECLARE_NONSTD(apr_status_t) apr_bucket_copy_notimpl(apr_bucket *e,
+                                                         apr_bucket **c);
+
+/**
+ * A place holder function that signifies that this bucket does not need
+ * to do anything special to be destroyed.  That's only the case for buckets
+ * that either have no data (metadata buckets) or buckets whose data pointer
+ * points to something that's not a bucket-type-specific structure, as with
+ * simple buckets where data points to a string and pipe buckets where data
+ * points directly to the apr_file_t.
+ * @param data The bucket data to destroy
+ */ 
+APR_DECLARE_NONSTD(void) apr_bucket_destroy_noop(void *data);
+
+/**
+ * There is no apr_bucket_destroy_notimpl, because destruction is required
+ * to be implemented (it could be a noop, but only if that makes sense for
+ * the bucket type)
+ */
+
+/* There is no apr_bucket_read_notimpl, because it is a required function
+ */
+
+
+/* All of the bucket types implemented by the core */
+/**
+ * The flush bucket type.  This signifies that all data should be flushed to
+ * the next filter.  The flush bucket should be sent with the other buckets.
+ */
+APR_DECLARE_DATA extern const apr_bucket_type_t apr_bucket_type_flush;
+/**
+ * The EOS bucket type.  This signifies that there will be no more data, ever.
+ * All filters MUST send all data to the next filter when they receive a
+ * bucket of this type
+ */
+APR_DECLARE_DATA extern const apr_bucket_type_t apr_bucket_type_eos;
+/**
+ * The FILE bucket type.  This bucket represents a file on disk
+ */
+APR_DECLARE_DATA extern const apr_bucket_type_t apr_bucket_type_file;
+/**
+ * The HEAP bucket type.  This bucket represents a data allocated from the
+ * heap.
+ */
+APR_DECLARE_DATA extern const apr_bucket_type_t apr_bucket_type_heap;
+#if APR_HAS_MMAP
+/**
+ * The MMAP bucket type.  This bucket represents an MMAP'ed file
+ */
+APR_DECLARE_DATA extern const apr_bucket_type_t apr_bucket_type_mmap;
+#endif
+/**
+ * The POOL bucket type.  This bucket represents a data that was allocated
+ * from a pool.  IF this bucket is still available when the pool is cleared,
+ * the data is copied on to the heap.
+ */
+APR_DECLARE_DATA extern const apr_bucket_type_t apr_bucket_type_pool;
+/**
+ * The PIPE bucket type.  This bucket represents a pipe to another program.
+ */
+APR_DECLARE_DATA extern const apr_bucket_type_t apr_bucket_type_pipe;
+/**
+ * The IMMORTAL bucket type.  This bucket represents a segment of data that
+ * the creator is willing to take responsibility for.  The core will do
+ * nothing with the data in an immortal bucket
+ */
+APR_DECLARE_DATA extern const apr_bucket_type_t apr_bucket_type_immortal;
+/**
+ * The TRANSIENT bucket type.  This bucket represents a data allocated off
+ * the stack.  When the setaside function is called, this data is copied on
+ * to the heap
+ */
+APR_DECLARE_DATA extern const apr_bucket_type_t apr_bucket_type_transient;
+/**
+ * The SOCKET bucket type.  This bucket represents a socket to another machine
+ */
+APR_DECLARE_DATA extern const apr_bucket_type_t apr_bucket_type_socket;
+
+
+/*  *****  Simple buckets  *****  */
+
+/**
+ * Split a simple bucket into two at the given point.  Most non-reference
+ * counting buckets that allow multiple references to the same block of
+ * data (eg transient and immortal) will use this as their split function
+ * without any additional type-specific handling.
+ * @param b The bucket to be split
+ * @param point The offset of the first byte in the new bucket
+ * @return APR_EINVAL if the point is not within the bucket;
+ *         APR_ENOMEM if allocation failed;
+ *         or APR_SUCCESS
+ */
+APR_DECLARE_NONSTD(apr_status_t) apr_bucket_simple_split(apr_bucket *b,
+                                                         apr_size_t point);
+
+/**
+ * Copy a simple bucket.  Most non-reference-counting buckets that allow
+ * multiple references to the same block of data (eg transient and immortal)
+ * will use this as their copy function without any additional type-specific
+ * handling.
+ * @param a The bucket to copy
+ * @param b Returns a pointer to the new bucket
+ * @return APR_ENOMEM if allocation failed;
+ *         or APR_SUCCESS
+ */
+APR_DECLARE_NONSTD(apr_status_t) apr_bucket_simple_copy(apr_bucket *a,
+                                                        apr_bucket **b);
+
+
+/*  *****  Shared, reference-counted buckets  *****  */
+
+/**
+ * Initialize a bucket containing reference-counted data that may be
+ * shared. The caller must allocate the bucket if necessary and
+ * initialize its type-dependent fields, and allocate and initialize
+ * its own private data structure. This function should only be called
+ * by type-specific bucket creation functions.
+ * @param b The bucket to initialize
+ * @param data A pointer to the private data structure
+ *             with the reference count at the start
+ * @param start The start of the data in the bucket
+ *              relative to the private base pointer
+ * @param length The length of the data in the bucket
+ * @return The new bucket, or NULL if allocation failed
+ */
+APR_DECLARE(apr_bucket *) apr_bucket_shared_make(apr_bucket *b, void *data,
+				                 apr_off_t start, 
+                                                 apr_size_t length);
+
+/**
+ * Decrement the refcount of the data in the bucket. This function
+ * should only be called by type-specific bucket destruction functions.
+ * @param data The private data pointer from the bucket to be destroyed
+ * @return TRUE or FALSE; TRUE if the reference count is now
+ *         zero, indicating that the shared resource itself can
+ *         be destroyed by the caller.
+ */
+APR_DECLARE(int) apr_bucket_shared_destroy(void *data);
+
+/**
+ * Split a bucket into two at the given point, and adjust the refcount
+ * to the underlying data. Most reference-counting bucket types will
+ * be able to use this function as their split function without any
+ * additional type-specific handling.
+ * @param b The bucket to be split
+ * @param point The offset of the first byte in the new bucket
+ * @return APR_EINVAL if the point is not within the bucket;
+ *         APR_ENOMEM if allocation failed;
+ *         or APR_SUCCESS
+ */
+APR_DECLARE_NONSTD(apr_status_t) apr_bucket_shared_split(apr_bucket *b,
+                                                         apr_size_t point);
+
+/**
+ * Copy a refcounted bucket, incrementing the reference count. Most
+ * reference-counting bucket types will be able to use this function
+ * as their copy function without any additional type-specific handling.
+ * @param a The bucket to copy
+ * @param b Returns a pointer to the new bucket
+ * @return APR_ENOMEM if allocation failed;
+           or APR_SUCCESS
+ */
+APR_DECLARE_NONSTD(apr_status_t) apr_bucket_shared_copy(apr_bucket *a,
+                                                        apr_bucket **b);
+
+
+/*  *****  Functions to Create Buckets of varying types  *****  */
+/*
+ * Each bucket type foo has two initialization functions:
+ * apr_bucket_foo_make which sets up some already-allocated memory as a
+ * bucket of type foo; and apr_bucket_foo_create which allocates memory
+ * for the bucket, calls apr_bucket_make_foo, and initializes the
+ * bucket's list pointers. The apr_bucket_foo_make functions are used
+ * inside the bucket code to change the type of buckets in place;
+ * other code should call apr_bucket_foo_create. All the initialization
+ * functions change nothing if they fail.
+ */
+
+/**
+ * Create an End of Stream bucket.  This indicates that there is no more data
+ * coming from down the filter stack.  All filters should flush at this point.
+ * @param list The freelist from which this bucket should be allocated
+ * @return The new bucket, or NULL if allocation failed
+ */
+APR_DECLARE(apr_bucket *) apr_bucket_eos_create(apr_bucket_alloc_t *list);
+
+/**
+ * Make the bucket passed in an EOS bucket.  This indicates that there is no 
+ * more data coming from down the filter stack.  All filters should flush at 
+ * this point.
+ * @param b The bucket to make into an EOS bucket
+ * @return The new bucket, or NULL if allocation failed
+ */
+APR_DECLARE(apr_bucket *) apr_bucket_eos_make(apr_bucket *b)
+                          __attribute__((nonnull(1)));
+
+/**
+ * Create a flush  bucket.  This indicates that filters should flush their
+ * data.  There is no guarantee that they will flush it, but this is the
+ * best we can do.
+ * @param list The freelist from which this bucket should be allocated
+ * @return The new bucket, or NULL if allocation failed
+ */
+APR_DECLARE(apr_bucket *) apr_bucket_flush_create(apr_bucket_alloc_t *list)
+                          __attribute__((nonnull(1)));
+
+/**
+ * Make the bucket passed in a FLUSH  bucket.  This indicates that filters 
+ * should flush their data.  There is no guarantee that they will flush it, 
+ * but this is the best we can do.
+ * @param b The bucket to make into a FLUSH bucket
+ * @return The new bucket, or NULL if allocation failed
+ */
+APR_DECLARE(apr_bucket *) apr_bucket_flush_make(apr_bucket *b)
+                          __attribute__((nonnull(1)));
+
+/**
+ * Create a bucket referring to long-lived data.
+ * @param buf The data to insert into the bucket
+ * @param nbyte The size of the data to insert.
+ * @param list The freelist from which this bucket should be allocated
+ * @return The new bucket, or NULL if allocation failed
+ */
+APR_DECLARE(apr_bucket *) apr_bucket_immortal_create(const char *buf, 
+                                                     apr_size_t nbyte,
+                                                     apr_bucket_alloc_t *list)
+                          __attribute__((nonnull(1,3)));
+
+/**
+ * Make the bucket passed in a bucket refer to long-lived data
+ * @param b The bucket to make into a IMMORTAL bucket
+ * @param buf The data to insert into the bucket
+ * @param nbyte The size of the data to insert.
+ * @return The new bucket, or NULL if allocation failed
+ */
+APR_DECLARE(apr_bucket *) apr_bucket_immortal_make(apr_bucket *b, 
+                                                   const char *buf, 
+                                                   apr_size_t nbyte)
+                          __attribute__((nonnull(1,2)));
+
+/**
+ * Create a bucket referring to data on the stack.
+ * @param buf The data to insert into the bucket
+ * @param nbyte The size of the data to insert.
+ * @param list The freelist from which this bucket should be allocated
+ * @return The new bucket, or NULL if allocation failed
+ */
+APR_DECLARE(apr_bucket *) apr_bucket_transient_create(const char *buf, 
+                                                      apr_size_t nbyte,
+                                                      apr_bucket_alloc_t *list)
+                          __attribute__((nonnull(1,3)));
+
+/**
+ * Make the bucket passed in a bucket refer to stack data
+ * @param b The bucket to make into a TRANSIENT bucket
+ * @param buf The data to insert into the bucket
+ * @param nbyte The size of the data to insert.
+ * @return The new bucket, or NULL if allocation failed
+ */
+APR_DECLARE(apr_bucket *) apr_bucket_transient_make(apr_bucket *b, 
+                                                    const char *buf,
+                                                    apr_size_t nbyte)
+                          __attribute__((nonnull(1,2)));
+
+/**
+ * Create a bucket referring to memory on the heap. If the caller asks
+ * for the data to be copied, this function always allocates 4K of
+ * memory so that more data can be added to the bucket without
+ * requiring another allocation. Therefore not all the data may be put
+ * into the bucket. If copying is not requested then the bucket takes
+ * over responsibility for free()ing the memory.
+ * @param buf The buffer to insert into the bucket
+ * @param nbyte The size of the buffer to insert.
+ * @param free_func Function to use to free the data; NULL indicates that the
+ *                  bucket should make a copy of the data
+ * @param list The freelist from which this bucket should be allocated
+ * @return The new bucket, or NULL if allocation failed
+ */
+APR_DECLARE(apr_bucket *) apr_bucket_heap_create(const char *buf, 
+                                                 apr_size_t nbyte,
+                                                 void (*free_func)(void *data),
+                                                 apr_bucket_alloc_t *list)
+                          __attribute__((nonnull(1,4)));
+/**
+ * Make the bucket passed in a bucket refer to heap data
+ * @param b The bucket to make into a HEAP bucket
+ * @param buf The buffer to insert into the bucket
+ * @param nbyte The size of the buffer to insert.
+ * @param free_func Function to use to free the data; NULL indicates that the
+ *                  bucket should make a copy of the data
+ * @return The new bucket, or NULL if allocation failed
+ */
+APR_DECLARE(apr_bucket *) apr_bucket_heap_make(apr_bucket *b, const char *buf,
+                                               apr_size_t nbyte,
+                                               void (*free_func)(void *data))
+                          __attribute__((nonnull(1,2)));
+
+/**
+ * Create a bucket referring to memory allocated from a pool.
+ *
+ * @param buf The buffer to insert into the bucket
+ * @param length The number of bytes referred to by this bucket
+ * @param pool The pool the memory was allocated from
+ * @param list The freelist from which this bucket should be allocated
+ * @return The new bucket, or NULL if allocation failed
+ */
+APR_DECLARE(apr_bucket *) apr_bucket_pool_create(const char *buf, 
+                                                 apr_size_t length,
+                                                 apr_pool_t *pool,
+                                                 apr_bucket_alloc_t *list)
+                          __attribute__((nonnull(1,3,4)));
+
+/**
+ * Make the bucket passed in a bucket refer to pool data
+ * @param b The bucket to make into a pool bucket
+ * @param buf The buffer to insert into the bucket
+ * @param length The number of bytes referred to by this bucket
+ * @param pool The pool the memory was allocated from
+ * @return The new bucket, or NULL if allocation failed
+ */
+APR_DECLARE(apr_bucket *) apr_bucket_pool_make(apr_bucket *b, const char *buf,
+                                               apr_size_t length, 
+                                               apr_pool_t *pool)
+                          __attribute__((nonnull(1,2,4)));
+
+#if APR_HAS_MMAP
+/**
+ * Create a bucket referring to mmap()ed memory.
+ * @param mm The mmap to insert into the bucket
+ * @param start The offset of the first byte in the mmap
+ *              that this bucket refers to
+ * @param length The number of bytes referred to by this bucket
+ * @param list The freelist from which this bucket should be allocated
+ * @return The new bucket, or NULL if allocation failed
+ */
+APR_DECLARE(apr_bucket *) apr_bucket_mmap_create(apr_mmap_t *mm, 
+                                                 apr_off_t start,
+                                                 apr_size_t length,
+                                                 apr_bucket_alloc_t *list)
+                          __attribute__((nonnull(1,4)));
+
+/**
+ * Make the bucket passed in a bucket refer to an MMAP'ed file
+ * @param b The bucket to make into a MMAP bucket
+ * @param mm The mmap to insert into the bucket
+ * @param start The offset of the first byte in the mmap
+ *              that this bucket refers to
+ * @param length The number of bytes referred to by this bucket
+ * @return The new bucket, or NULL if allocation failed
+ */
+APR_DECLARE(apr_bucket *) apr_bucket_mmap_make(apr_bucket *b, apr_mmap_t *mm,
+                                               apr_off_t start, 
+                                               apr_size_t length)
+                          __attribute__((nonnull(1,2)));
+#endif
+
+/**
+ * Create a bucket referring to a socket.
+ * @param thissock The socket to put in the bucket
+ * @param list The freelist from which this bucket should be allocated
+ * @return The new bucket, or NULL if allocation failed
+ */
+APR_DECLARE(apr_bucket *) apr_bucket_socket_create(apr_socket_t *thissock,
+                                                   apr_bucket_alloc_t *list)
+                          __attribute__((nonnull(1,2)));
+/**
+ * Make the bucket passed in a bucket refer to a socket
+ * @param b The bucket to make into a SOCKET bucket
+ * @param thissock The socket to put in the bucket
+ * @return The new bucket, or NULL if allocation failed
+ */
+APR_DECLARE(apr_bucket *) apr_bucket_socket_make(apr_bucket *b, 
+                                                 apr_socket_t *thissock)
+                          __attribute__((nonnull(1,2)));
+
+/**
+ * Create a bucket referring to a pipe.
+ * @param thispipe The pipe to put in the bucket
+ * @param list The freelist from which this bucket should be allocated
+ * @return The new bucket, or NULL if allocation failed
+ */
+APR_DECLARE(apr_bucket *) apr_bucket_pipe_create(apr_file_t *thispipe,
+                                                 apr_bucket_alloc_t *list)
+                          __attribute__((nonnull(1,2)));
+
+/**
+ * Make the bucket passed in a bucket refer to a pipe
+ * @param b The bucket to make into a PIPE bucket
+ * @param thispipe The pipe to put in the bucket
+ * @return The new bucket, or NULL if allocation failed
+ */
+APR_DECLARE(apr_bucket *) apr_bucket_pipe_make(apr_bucket *b, 
+                                               apr_file_t *thispipe)
+                          __attribute__((nonnull(1,2)));
+
+/**
+ * Create a bucket referring to a file.
+ * @param fd The file to put in the bucket
+ * @param offset The offset where the data of interest begins in the file
+ * @param len The amount of data in the file we are interested in
+ * @param p The pool into which any needed structures should be created
+ *          while reading from this file bucket
+ * @param list The freelist from which this bucket should be allocated
+ * @return The new bucket, or NULL if allocation failed
+ * @remark If the file is truncated such that the segment of the file
+ * referenced by the bucket no longer exists, an attempt to read
+ * from the bucket will fail with APR_EOF. 
+ * @remark apr_brigade_insert_file() should generally be used to
+ * insert files into brigades, since that function can correctly
+ * handle large file issues.
+ */
+APR_DECLARE(apr_bucket *) apr_bucket_file_create(apr_file_t *fd,
+                                                 apr_off_t offset,
+                                                 apr_size_t len, 
+                                                 apr_pool_t *p,
+                                                 apr_bucket_alloc_t *list)
+                          __attribute__((nonnull(1,4,5)));
+
+/**
+ * Make the bucket passed in a bucket refer to a file
+ * @param b The bucket to make into a FILE bucket
+ * @param fd The file to put in the bucket
+ * @param offset The offset where the data of interest begins in the file
+ * @param len The amount of data in the file we are interested in
+ * @param p The pool into which any needed structures should be created
+ *          while reading from this file bucket
+ * @return The new bucket, or NULL if allocation failed
+ */
+APR_DECLARE(apr_bucket *) apr_bucket_file_make(apr_bucket *b, apr_file_t *fd,
+                                               apr_off_t offset,
+                                               apr_size_t len, apr_pool_t *p)
+                          __attribute__((nonnull(1,2,5)));
+
+/**
+ * Enable or disable memory-mapping for a FILE bucket (default is enabled)
+ * @param b The bucket
+ * @param enabled Whether memory-mapping should be enabled
+ * @return APR_SUCCESS normally, or an error code if the operation fails
+ */
+APR_DECLARE(apr_status_t) apr_bucket_file_enable_mmap(apr_bucket *b,
+                                                      int enabled)
+                          __attribute__((nonnull(1)));
+
+/**
+ * Set the size of the read buffer allocated by a FILE bucket (default
+ * is @a APR_BUCKET_BUFF_SIZE)
+ * memory-mapping is disabled only)
+ * @param b The bucket
+ * @param size Size of the allocated buffers
+ * @return APR_SUCCESS normally, or an error code if the operation fails
+ * @remark Relevant/used only when memory-mapping is disabled (@see
+ * apr_bucket_file_enable_mmap)
+ */
+APR_DECLARE(apr_status_t) apr_bucket_file_set_buf_size(apr_bucket *e,
+                                                       apr_size_t size);
+
+/** @} */
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !APR_BUCKETS_H */
diff --git a/include/apr_crypto.h b/include/apr_crypto.h
new file mode 100644
index 00000000000..68b196ad6e9
--- /dev/null
+++ b/include/apr_crypto.h
@@ -0,0 +1,506 @@
+/* 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 APR_CRYPTO_H
+#define APR_CRYPTO_H
+
+#include "apu.h"
+#include "apr_pools.h"
+#include "apr_tables.h"
+#include "apr_hash.h"
+#include "apu_errno.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @file apr_crypto.h
+ * @brief APR-UTIL Crypto library
+ */
+/**
+ * @defgroup APR_Util_Crypto Crypto routines
+ * @ingroup APR
+ * @{
+ */
+
+#if APU_HAVE_CRYPTO
+
+#ifndef APU_CRYPTO_RECOMMENDED_DRIVER
+#if APU_HAVE_COMMONCRYPTO
+#define APU_CRYPTO_RECOMMENDED_DRIVER "commoncrypto"
+#else
+#if APU_HAVE_OPENSSL
+#define APU_CRYPTO_RECOMMENDED_DRIVER "openssl"
+#else
+#if APU_HAVE_NSS
+#define APU_CRYPTO_RECOMMENDED_DRIVER "nss"
+#else
+#if APU_HAVE_MSCNG
+#define APU_CRYPTO_RECOMMENDED_DRIVER "mscng"
+#else
+#if APU_HAVE_MSCAPI
+#define APU_CRYPTO_RECOMMENDED_DRIVER "mscapi"
+#else
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+
+/**
+ * Symmetric Key types understood by the library.
+ *
+ * NOTE: It is expected that this list will grow over time.
+ *
+ * Interoperability Matrix:
+ *
+ * The matrix is based on the testcrypto.c unit test, which attempts to
+ * test whether a simple encrypt/decrypt will succeed, as well as testing
+ * whether an encrypted string by one library can be decrypted by the
+ * others.
+ *
+ * Some libraries will successfully encrypt and decrypt their own data,
+ * but won't decrypt data from another library. It is hoped that over
+ * time these anomalies will be found and fixed, but until then it is
+ * recommended that ciphers are chosen that interoperate across platform.
+ *
+ * An X below means the test passes, it does not necessarily mean that
+ * encryption performed is correct or secure. Applications should stick
+ * to ciphers that pass the interoperablity tests on the right hand side
+ * of the table.
+ *
+ * Aligned data is data whose length is a multiple of the block size for
+ * the chosen cipher. Padded data is data that is not aligned by block
+ * size and must be padded by the crypto library.
+ *
+ *                  OpenSSL    CommonCrypto   NSS       Interop
+ *                 Align  Pad  Align  Pad  Align  Pad  Align  Pad
+ * 3DES_192/CBC    X      X    X      X    X      X    X      X
+ * 3DES_192/ECB    X      X    X      X
+ * AES_256/CBC     X      X    X      X    X      X    X      X
+ * AES_256/ECB     X      X    X      X    X           X
+ * AES_192/CBC     X      X    X      X    X      X
+ * AES_192/ECB     X      X    X      X    X
+ * AES_128/CBC     X      X    X      X    X      X
+ * AES_128/ECB     X      X    X      X    X
+ *
+ * Conclusion: for padded data, use 3DES_192/CBC or AES_256/CBC. For
+ * aligned data, use 3DES_192/CBC, AES_256/CBC or AES_256/ECB.
+ */
+
+typedef enum
+{
+    APR_KEY_NONE, APR_KEY_3DES_192, /** 192 bit (3-Key) 3DES */
+    APR_KEY_AES_128, /** 128 bit AES */
+    APR_KEY_AES_192, /** 192 bit AES */
+    APR_KEY_AES_256
+/** 256 bit AES */
+} apr_crypto_block_key_type_e;
+
+typedef enum
+{
+    APR_MODE_NONE, /** An error condition */
+    APR_MODE_ECB, /** Electronic Code Book */
+    APR_MODE_CBC
+/** Cipher Block Chaining */
+} apr_crypto_block_key_mode_e;
+
+/* These are opaque structs.  Instantiation is up to each backend */
+typedef struct apr_crypto_driver_t apr_crypto_driver_t;
+typedef struct apr_crypto_t apr_crypto_t;
+typedef struct apr_crypto_config_t apr_crypto_config_t;
+typedef struct apr_crypto_key_t apr_crypto_key_t;
+typedef struct apr_crypto_block_t apr_crypto_block_t;
+
+typedef struct apr_crypto_block_key_type_t {
+    apr_crypto_block_key_type_e type;
+    int keysize;
+    int blocksize;
+    int ivsize;
+} apr_crypto_block_key_type_t;
+
+typedef struct apr_crypto_block_key_mode_t {
+    apr_crypto_block_key_mode_e mode;
+} apr_crypto_block_key_mode_t;
+
+typedef struct apr_crypto_passphrase_t {
+    const char *pass;
+    apr_size_t passLen;
+    const unsigned char * salt;
+    apr_size_t saltLen;
+    int iterations;
+} apr_crypto_passphrase_t;
+
+typedef struct apr_crypto_secret_t {
+    const unsigned char *secret;
+    apr_size_t secretLen;
+} apr_crypto_secret_t;
+
+typedef enum {
+    /** Key is derived from a passphrase */
+    APR_CRYPTO_KTYPE_PASSPHRASE     = 1,
+    /** Key is derived from a raw key */
+    APR_CRYPTO_KTYPE_SECRET     = 2,
+} apr_crypto_key_type;
+
+typedef struct apr_crypto_key_rec_t {
+    apr_crypto_key_type ktype;
+    apr_crypto_block_key_type_e type;
+    apr_crypto_block_key_mode_e mode;
+    int pad;
+    union {
+        apr_crypto_passphrase_t passphrase;
+        apr_crypto_secret_t secret;
+    } k;
+} apr_crypto_key_rec_t;
+
+/**
+ * @brief Perform once-only initialisation. Call once only.
+ *
+ * @param pool - pool to register any shutdown cleanups, etc
+ * @return APR_NOTIMPL in case of no crypto support.
+ */
+APR_DECLARE(apr_status_t) apr_crypto_init(apr_pool_t *pool);
+
+/**
+ * @brief Zero out the buffer provided when the pool is cleaned up.
+ *
+ * @param pool - pool to register the cleanup
+ * @param buffer - buffer to zero out
+ * @param size - size of the buffer to zero out
+ */
+APR_DECLARE(apr_status_t) apr_crypto_clear(apr_pool_t *pool, void *buffer,
+        apr_size_t size);
+
+/**
+ * @brief Always zero out the buffer provided, without being optimized out by
+ * the compiler.
+ *
+ * @param buffer - buffer to zero out
+ * @param size - size of the buffer to zero out
+ */
+APR_DECLARE(apr_status_t) apr_crypto_memzero(void *buffer, apr_size_t size);
+
+/**
+ * @brief Timing attacks safe buffers comparison, where the executing time does
+ * not depend on the bytes compared but solely on the number of bytes.
+ *
+ * @param buf1 - first buffer to compare
+ * @param buf2 - second buffer to compare
+ * @param size - size of the buffers to compare
+ * @return 1 if the buffers are equals, 0 otherwise.
+ */
+APR_DECLARE(int) apr_crypto_equals(const void *buf1, const void *buf2,
+                                   apr_size_t size);
+
+/**
+ * @brief Get the driver struct for a name
+ *
+ * @param driver - pointer to driver struct.
+ * @param name - driver name
+ * @param params - array of initialisation parameters
+ * @param result - result and error message on failure
+ * @param pool - (process) pool to register cleanup
+ * @return APR_SUCCESS for success
+ * @return APR_ENOTIMPL for no driver (when DSO not enabled)
+ * @return APR_EDSOOPEN if DSO driver file can't be opened
+ * @return APR_ESYMNOTFOUND if the driver file doesn't contain a driver
+ * @remarks NSS: the params can have "dir", "key3", "cert7" and "secmod"
+ *  keys, each followed by an equal sign and a value. Such key/value pairs can
+ *  be delimited by space or tab. If the value contains a space, surround the
+ *  whole key value pair in quotes: "dir=My Directory".
+ * @remarks OpenSSL: currently no params are supported.
+ */
+APR_DECLARE(apr_status_t) apr_crypto_get_driver(
+        const apr_crypto_driver_t **driver, const char *name,
+        const char *params, const apu_err_t **result, apr_pool_t *pool);
+
+/**
+ * @brief Return the name of the driver.
+ *
+ * @param driver - The driver in use.
+ * @return The name of the driver.
+ */
+APR_DECLARE(const char *) apr_crypto_driver_name(
+        const apr_crypto_driver_t *driver);
+
+/**
+ * @brief Get the result of the last operation on a context. If the result
+ *        is NULL, the operation was successful.
+ * @param result - the result structure
+ * @param f - context pointer
+ * @return APR_SUCCESS for success
+ */
+APR_DECLARE(apr_status_t) apr_crypto_error(const apu_err_t **result,
+        const apr_crypto_t *f);
+
+/**
+ * @brief Create a context for supporting encryption. Keys, certificates,
+ *        algorithms and other parameters will be set per context. More than
+ *        one context can be created at one time. A cleanup will be automatically
+ *        registered with the given pool to guarantee a graceful shutdown.
+ * @param f - context pointer will be written here
+ * @param driver - driver to use
+ * @param params - array of key parameters
+ * @param pool - process pool
+ * @return APR_ENOENGINE when the engine specified does not exist. APR_EINITENGINE
+ * if the engine cannot be initialised.
+ * @remarks NSS: currently no params are supported.
+ * @remarks OpenSSL: the params can have "engine" as a key, followed by an equal
+ *  sign and a value.
+ */
+APR_DECLARE(apr_status_t)
+        apr_crypto_make(apr_crypto_t **f, const apr_crypto_driver_t *driver,
+                const char *params, apr_pool_t *pool);
+
+/**
+ * @brief Get a hash table of key types, keyed by the name of the type against
+ * a pointer to apr_crypto_block_key_type_t, which in turn begins with an
+ * integer.
+ *
+ * @param types - hashtable of key types keyed to constants.
+ * @param f - encryption context
+ * @return APR_SUCCESS for success
+ */
+APR_DECLARE(apr_status_t) apr_crypto_get_block_key_types(apr_hash_t **types,
+        const apr_crypto_t *f);
+
+/**
+ * @brief Get a hash table of key modes, keyed by the name of the mode against
+ * a pointer to apr_crypto_block_key_mode_t, which in turn begins with an
+ * integer.
+ *
+ * @param modes - hashtable of key modes keyed to constants.
+ * @param f - encryption context
+ * @return APR_SUCCESS for success
+ */
+APR_DECLARE(apr_status_t) apr_crypto_get_block_key_modes(apr_hash_t **modes,
+        const apr_crypto_t *f);
+
+/**
+ * @brief Create a key from the provided secret or passphrase. The key is cleaned
+ *        up when the context is cleaned, and may be reused with multiple encryption
+ *        or decryption operations.
+ * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
+ *       *key is not NULL, *key must point at a previously created structure.
+ * @param key The key returned, see note.
+ * @param rec The key record, from which the key will be derived.
+ * @param f The context to use.
+ * @param p The pool to use.
+ * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
+ *         error occurred while generating the key. APR_ENOCIPHER if the type or mode
+ *         is not supported by the particular backend. APR_EKEYTYPE if the key type is
+ *         not known. APR_EPADDING if padding was requested but is not supported.
+ *         APR_ENOTIMPL if not implemented.
+ */
+APR_DECLARE(apr_status_t) apr_crypto_key(apr_crypto_key_t **key,
+        const apr_crypto_key_rec_t *rec, const apr_crypto_t *f, apr_pool_t *p);
+
+/**
+ * @brief Create a key from the given passphrase. By default, the PBKDF2
+ *        algorithm is used to generate the key from the passphrase. It is expected
+ *        that the same pass phrase will generate the same key, regardless of the
+ *        backend crypto platform used. The key is cleaned up when the context
+ *        is cleaned, and may be reused with multiple encryption or decryption
+ *        operations.
+ * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
+ *       *key is not NULL, *key must point at a previously created structure.
+ * @param key The key returned, see note.
+ * @param ivSize The size of the initialisation vector will be returned, based
+ *               on whether an IV is relevant for this type of crypto.
+ * @param pass The passphrase to use.
+ * @param passLen The passphrase length in bytes
+ * @param salt The salt to use.
+ * @param saltLen The salt length in bytes
+ * @param type 3DES_192, AES_128, AES_192, AES_256.
+ * @param mode Electronic Code Book / Cipher Block Chaining.
+ * @param doPad Pad if necessary.
+ * @param iterations Number of iterations to use in algorithm
+ * @param f The context to use.
+ * @param p The pool to use.
+ * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
+ *         error occurred while generating the key. APR_ENOCIPHER if the type or mode
+ *         is not supported by the particular backend. APR_EKEYTYPE if the key type is
+ *         not known. APR_EPADDING if padding was requested but is not supported.
+ *         APR_ENOTIMPL if not implemented.
+ * @deprecated Replaced by apr_crypto_key().
+ */
+APR_DECLARE(apr_status_t) apr_crypto_passphrase(apr_crypto_key_t **key,
+        apr_size_t *ivSize, const char *pass, apr_size_t passLen,
+        const unsigned char * salt, apr_size_t saltLen,
+        const apr_crypto_block_key_type_e type,
+        const apr_crypto_block_key_mode_e mode, const int doPad,
+        const int iterations, const apr_crypto_t *f, apr_pool_t *p);
+
+/**
+ * @brief Initialise a context for encrypting arbitrary data using the given key.
+ * @note If *ctx is NULL, a apr_crypto_block_t will be created from a pool. If
+ *       *ctx is not NULL, *ctx must point at a previously created structure.
+ * @param ctx The block context returned, see note.
+ * @param iv Optional initialisation vector. If the buffer pointed to is NULL,
+ *           an IV will be created at random, in space allocated from the pool.
+ *           If the buffer pointed to is not NULL, the IV in the buffer will be
+ *           used.
+ * @param key The key structure to use.
+ * @param blockSize The block size of the cipher.
+ * @param p The pool to use.
+ * @return Returns APR_ENOIV if an initialisation vector is required but not specified.
+ *         Returns APR_EINIT if the backend failed to initialise the context. Returns
+ *         APR_ENOTIMPL if not implemented.
+ */
+APR_DECLARE(apr_status_t) apr_crypto_block_encrypt_init(
+        apr_crypto_block_t **ctx, const unsigned char **iv,
+        const apr_crypto_key_t *key, apr_size_t *blockSize, apr_pool_t *p);
+
+/**
+ * @brief Encrypt data provided by in, write it to out.
+ * @note The number of bytes written will be written to outlen. If
+ *       out is NULL, outlen will contain the maximum size of the
+ *       buffer needed to hold the data, including any data
+ *       generated by apr_crypto_block_encrypt_finish below. If *out points
+ *       to NULL, a buffer sufficiently large will be created from
+ *       the pool provided. If *out points to a not-NULL value, this
+ *       value will be used as a buffer instead.
+ * @param out Address of a buffer to which data will be written,
+ *        see note.
+ * @param outlen Length of the output will be written here.
+ * @param in Address of the buffer to read.
+ * @param inlen Length of the buffer to read.
+ * @param ctx The block context to use.
+ * @return APR_ECRYPT if an error occurred. Returns APR_ENOTIMPL if
+ *         not implemented.
+ */
+APR_DECLARE(apr_status_t) apr_crypto_block_encrypt(unsigned char **out,
+        apr_size_t *outlen, const unsigned char *in, apr_size_t inlen,
+        apr_crypto_block_t *ctx);
+
+/**
+ * @brief Encrypt final data block, write it to out.
+ * @note If necessary the final block will be written out after being
+ *       padded. Typically the final block will be written to the
+ *       same buffer used by apr_crypto_block_encrypt, offset by the
+ *       number of bytes returned as actually written by the
+ *       apr_crypto_block_encrypt() call. After this call, the context
+ *       is cleaned and can be reused by apr_crypto_block_encrypt_init().
+ * @param out Address of a buffer to which data will be written. This
+ *            buffer must already exist, and is usually the same
+ *            buffer used by apr_evp_crypt(). See note.
+ * @param outlen Length of the output will be written here.
+ * @param ctx The block context to use.
+ * @return APR_ECRYPT if an error occurred.
+ * @return APR_EPADDING if padding was enabled and the block was incorrectly
+ *         formatted.
+ * @return APR_ENOTIMPL if not implemented.
+ */
+APR_DECLARE(apr_status_t) apr_crypto_block_encrypt_finish(unsigned char *out,
+        apr_size_t *outlen, apr_crypto_block_t *ctx);
+
+/**
+ * @brief Initialise a context for decrypting arbitrary data using the given key.
+ * @note If *ctx is NULL, a apr_crypto_block_t will be created from a pool. If
+ *       *ctx is not NULL, *ctx must point at a previously created structure.
+ * @param ctx The block context returned, see note.
+ * @param blockSize The block size of the cipher.
+ * @param iv Optional initialisation vector.
+ * @param key The key structure to use.
+ * @param p The pool to use.
+ * @return Returns APR_ENOIV if an initialisation vector is required but not specified.
+ *         Returns APR_EINIT if the backend failed to initialise the context. Returns
+ *         APR_ENOTIMPL if not implemented.
+ */
+APR_DECLARE(apr_status_t) apr_crypto_block_decrypt_init(
+        apr_crypto_block_t **ctx, apr_size_t *blockSize,
+        const unsigned char *iv, const apr_crypto_key_t *key, apr_pool_t *p);
+
+/**
+ * @brief Decrypt data provided by in, write it to out.
+ * @note The number of bytes written will be written to outlen. If
+ *       out is NULL, outlen will contain the maximum size of the
+ *       buffer needed to hold the data, including any data
+ *       generated by apr_crypto_block_decrypt_finish below. If *out points
+ *       to NULL, a buffer sufficiently large will be created from
+ *       the pool provided. If *out points to a not-NULL value, this
+ *       value will be used as a buffer instead.
+ * @param out Address of a buffer to which data will be written,
+ *        see note.
+ * @param outlen Length of the output will be written here.
+ * @param in Address of the buffer to read.
+ * @param inlen Length of the buffer to read.
+ * @param ctx The block context to use.
+ * @return APR_ECRYPT if an error occurred. Returns APR_ENOTIMPL if
+ *         not implemented.
+ */
+APR_DECLARE(apr_status_t) apr_crypto_block_decrypt(unsigned char **out,
+        apr_size_t *outlen, const unsigned char *in, apr_size_t inlen,
+        apr_crypto_block_t *ctx);
+
+/**
+ * @brief Decrypt final data block, write it to out.
+ * @note If necessary the final block will be written out after being
+ *       padded. Typically the final block will be written to the
+ *       same buffer used by apr_crypto_block_decrypt, offset by the
+ *       number of bytes returned as actually written by the
+ *       apr_crypto_block_decrypt() call. After this call, the context
+ *       is cleaned and can be reused by apr_crypto_block_decrypt_init().
+ * @param out Address of a buffer to which data will be written. This
+ *            buffer must already exist, and is usually the same
+ *            buffer used by apr_evp_crypt(). See note.
+ * @param outlen Length of the output will be written here.
+ * @param ctx The block context to use.
+ * @return APR_ECRYPT if an error occurred.
+ * @return APR_EPADDING if padding was enabled and the block was incorrectly
+ *         formatted.
+ * @return APR_ENOTIMPL if not implemented.
+ */
+APR_DECLARE(apr_status_t) apr_crypto_block_decrypt_finish(unsigned char *out,
+        apr_size_t *outlen, apr_crypto_block_t *ctx);
+
+/**
+ * @brief Clean encryption / decryption context.
+ * @note After cleanup, a context is free to be reused if necessary.
+ * @param ctx The block context to use.
+ * @return Returns APR_ENOTIMPL if not supported.
+ */
+APR_DECLARE(apr_status_t) apr_crypto_block_cleanup(apr_crypto_block_t *ctx);
+
+/**
+ * @brief Clean encryption / decryption context.
+ * @note After cleanup, a context is free to be reused if necessary.
+ * @param f The context to use.
+ * @return Returns APR_ENOTIMPL if not supported.
+ */
+APR_DECLARE(apr_status_t) apr_crypto_cleanup(apr_crypto_t *f);
+
+/**
+ * @brief Shutdown the crypto library.
+ * @note After shutdown, it is expected that the init function can be called again.
+ * @param driver - driver to use
+ * @return Returns APR_ENOTIMPL if not supported.
+ */
+APR_DECLARE(apr_status_t)
+        apr_crypto_shutdown(const apr_crypto_driver_t *driver);
+
+#endif /* APU_HAVE_CRYPTO */
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/apr_cstr.h b/include/apr_cstr.h
new file mode 100644
index 00000000000..3f1b1a0995a
--- /dev/null
+++ b/include/apr_cstr.h
@@ -0,0 +1,292 @@
+/* ====================================================================
+ *    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 apr_cstr.h
+ * @brief C string goodies.
+ */
+
+#ifndef APR_CSTR_H
+#define APR_CSTR_H
+
+#include <apr.h>          /* for apr_size_t */
+#include <apr_pools.h>    /* for apr_pool_t */
+#include <apr_tables.h>   /* for apr_array_header_t */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup apr_cstr C (POSIX) locale string functions
+ * @ingroup apr_strings
+ *
+ * The apr_cstr_* functions provide traditional C char * string text handling,
+ * and notabilty they treat all text in the C (a.k.a. POSIX) locale using the
+ * minimal POSIX character set, represented in either ASCII or a corresponding
+ * EBCDIC subset.
+ *
+ * Character values outside of that set are treated as opaque bytes, and all
+ * multi-byte character sequences are handled as individual distinct octets.
+ *
+ * Multi-byte characters sequences whose octets fall in the ASCII range cause
+ * unexpected results, such as in the ISO-2022-JP code page where ASCII octets
+ * occur within both shift-state and multibyte sequences.
+ *
+ * In the case of the UTF-8 encoding, all multibyte characters all fall outside
+ * of the C/POSIX range of characters, so these functions are generally safe
+ * to use on UTF-8 strings. The programmer must be aware that each octet may
+ * not represent a distinct printable character in such encodings.
+ *
+ * The standard C99/POSIX string functions, rather than apr_cstr, should be
+ * used in all cases where the current locale and encoding of the text is
+ * significant.
+ * @{
+ */
+
+
+/** Divide @a input into substrings, interpreting any char from @a sep
+ * as a token separator.
+ *
+ * Return an array of copies of those substrings (plain const char*),
+ * allocating both the array and the copies in @a pool.
+ *
+ * None of the elements added to the array contain any of the
+ * characters in @a sep_chars, and none of the new elements are empty
+ * (thus, it is possible that the returned array will have length
+ * zero).
+ *
+ * If @a chop_whitespace is TRUE, then remove leading and trailing
+ * whitespace from the returned strings.
+ *
+ * @since New in 1.6
+ */
+APR_DECLARE(apr_array_header_t *) apr_cstr_split(const char *input,
+                                                 const char *sep_chars,
+                                                 int chop_whitespace,
+                                                 apr_pool_t *pool);
+
+/** Like apr_cstr_split(), but append to existing @a array instead of
+ * creating a new one.  Allocate the copied substrings in @a pool
+ * (i.e., caller decides whether or not to pass @a array->pool as @a pool).
+ *
+ * @since New in 1.6
+ */
+APR_DECLARE(void) apr_cstr_split_append(apr_array_header_t *array,
+                                        const char *input,
+                                        const char *sep_chars,
+                                        int chop_whitespace,
+                                        apr_pool_t *pool);
+
+
+/** Return @c TRUE iff @a str matches any of the elements of @a list, a list
+ * of zero or more glob patterns.
+ *
+ * @since New in 1.6
+ */
+APR_DECLARE(int) apr_cstr_match_glob_list(const char *str,
+                                          const apr_array_header_t *list);
+
+/** Return @c TRUE iff @a str exactly matches any of the elements of @a list.
+ *
+ * @since New in 1.6
+ */
+APR_DECLARE(int) apr_cstr_match_list(const char *str,
+                                     const apr_array_header_t *list);
+
+/**
+ * Get the next token from @a *str interpreting any char from @a sep as a
+ * token separator.  Separators at the beginning of @a str will be skipped.
+ * Returns a pointer to the beginning of the first token in @a *str or NULL
+ * if no token is left.  Modifies @a str such that the next call will return
+ * the next token.
+ *
+ * @note The content of @a *str may be modified by this function.
+ *
+ * @since New in 1.6.
+ */
+APR_DECLARE(char *) apr_cstr_tokenize(const char *sep, char **str);
+
+/**
+ * Return the number of line breaks in @a msg, allowing any kind of newline
+ * termination (CR, LF, CRLF, or LFCR), even inconsistent.
+ *
+ * @since New in 1.6.
+ */
+APR_DECLARE(int) apr_cstr_count_newlines(const char *msg);
+
+#if 0 /* XXX: stringbuf logic is not present in APR */
+/**
+ * Return a cstring which is the concatenation of @a strings (an array
+ * of char *) each followed by @a separator (that is, @a separator
+ * will also end the resulting string).  Allocate the result in @a pool.
+ * If @a strings is empty, then return the empty string.
+ *
+ * @since New in 1.6.
+ */
+APR_DECLARE(char *) apr_cstr_join(const apr_array_header_t *strings,
+                                  const char *separator,
+                                  apr_pool_t *pool);
+#endif
+
+/**
+ * Perform a case-insensitive comparison of two strings @a atr1 and @a atr2,
+ * treating upper and lower case values of the 26 standard C/POSIX alphabetic
+ * characters as equivalent. Extended latin characters outside of this set
+ * are treated as unique octets, irrespective of the current locale.
+ *
+ * Returns in integer greater than, equal to, or less than 0,
+ * according to whether @a str1 is considered greater than, equal to,
+ * or less than @a str2.
+ *
+ * @since New in 1.6.
+ */
+APR_DECLARE(int) apr_cstr_casecmp(const char *str1, const char *str2);
+
+/**
+ * Perform a case-insensitive comparison of two strings @a atr1 and @a atr2,
+ * treating upper and lower case values of the 26 standard C/POSIX alphabetic
+ * characters as equivalent. Extended latin characters outside of this set
+ * are treated as unique octets, irrespective of the current locale.
+ *
+ * Returns in integer greater than, equal to, or less than 0,
+ * according to whether @a str1 is considered greater than, equal to,
+ * or less than @a str2.
+ *
+ * @since New in 1.6.
+ */
+APR_DECLARE(int) apr_cstr_casecmpn(const char *str1,
+                                   const char *str2,
+                                   apr_size_t n);
+
+/**
+ * Parse the C string @a str into a 64 bit number, and return it in @a *n.
+ * Assume that the number is represented in base @a base.
+ * Raise an error if conversion fails (e.g. due to overflow), or if the
+ * converted number is smaller than @a minval or larger than @a maxval.
+ *
+ * Leading whitespace in @a str is skipped in a locale-dependent way.
+ * After that, the string may contain an optional '+' (positive, default)
+ * or '-' (negative) character, followed by an optional '0x' prefix if
+ * @a base is 0 or 16, followed by numeric digits appropriate for the base.
+ * If there are any more characters after the numeric digits, an error is
+ * returned.
+ *
+ * If @a base is zero, then a leading '0x' or '0X' prefix means hexadecimal,
+ * else a leading '0' means octal (implemented, though not documented, in
+ * apr_strtoi64() in APR 0.9.0 through 1.5.0), else use base ten.
+ *
+ * @since New in 1.6.
+ */
+APR_DECLARE(apr_status_t) apr_cstr_strtoi64(apr_int64_t *n, const char *str,
+                                            apr_int64_t minval,
+                                            apr_int64_t maxval,
+                                            int base);
+
+/**
+ * Parse the C string @a str into a 64 bit number, and return it in @a *n.
+ * Assume that the number is represented in base 10.
+ * Raise an error if conversion fails (e.g. due to overflow).
+ *
+ * The behaviour otherwise is as described for apr_cstr_strtoi64().
+ *
+ * @since New in 1.6.
+ */
+APR_DECLARE(apr_status_t) apr_cstr_atoi64(apr_int64_t *n, const char *str);
+
+/**
+ * Parse the C string @a str into a 32 bit number, and return it in @a *n.
+ * Assume that the number is represented in base 10.
+ * Raise an error if conversion fails (e.g. due to overflow).
+ *
+ * The behaviour otherwise is as described for apr_cstr_strtoi64().
+ *
+ * @since New in 1.6.
+ */
+APR_DECLARE(apr_status_t) apr_cstr_atoi(int *n, const char *str);
+
+/**
+ * Parse the C string @a str into an unsigned 64 bit number, and return
+ * it in @a *n. Assume that the number is represented in base @a base.
+ * Raise an error if conversion fails (e.g. due to overflow), or if the
+ * converted number is smaller than @a minval or larger than @a maxval.
+ *
+ * Leading whitespace in @a str is skipped in a locale-dependent way.
+ * After that, the string may contain an optional '+' (positive, default)
+ * or '-' (negative) character, followed by an optional '0x' prefix if
+ * @a base is 0 or 16, followed by numeric digits appropriate for the base.
+ * If there are any more characters after the numeric digits, an error is
+ * returned.
+ *
+ * If @a base is zero, then a leading '0x' or '0X' prefix means hexadecimal,
+ * else a leading '0' means octal (as implemented, though not documented, in
+ * apr_strtoi64(), else use base ten.
+ *
+ * @warning The implementation returns APR_ERANGE if the parsed number
+ * is greater than APR_INT64_MAX, even if it is not greater than @a maxval.
+ *
+ * @since New in 1.6.
+ */
+APR_DECLARE(apr_status_t) apr_cstr_strtoui64(apr_uint64_t *n, const char *str,
+                                             apr_uint64_t minval,
+                                             apr_uint64_t maxval,
+                                             int base);
+
+/**
+ * Parse the C string @a str into an unsigned 64 bit number, and return
+ * it in @a *n. Assume that the number is represented in base 10.
+ * Raise an error if conversion fails (e.g. due to overflow).
+ *
+ * The behaviour otherwise is as described for apr_cstr_strtoui64(),
+ * including the upper limit of APR_INT64_MAX.
+ *
+ * @since New in 1.6.
+ */
+APR_DECLARE(apr_status_t) apr_cstr_atoui64(apr_uint64_t *n, const char *str);
+
+/**
+ * Parse the C string @a str into an unsigned 32 bit number, and return
+ * it in @a *n. Assume that the number is represented in base 10.
+ * Raise an error if conversion fails (e.g. due to overflow).
+ *
+ * The behaviour otherwise is as described for apr_cstr_strtoui64(),
+ * including the upper limit of APR_INT64_MAX.
+ *
+ * @since New in 1.6.
+ */
+APR_DECLARE(apr_status_t) apr_cstr_atoui(unsigned int *n, const char *str);
+
+/**
+ * Skip the common prefix @a prefix from the C string @a str, and return
+ * a pointer to the next character after the prefix.
+ * Return @c NULL if @a str does not start with @a prefix.
+ *
+ * @since New in 1.6.
+ */
+APR_DECLARE(const char *) apr_cstr_skip_prefix(const char *str,
+                                               const char *prefix);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif  /* SVN_STRING_H */
diff --git a/include/apr_date.h b/include/apr_date.h
new file mode 100644
index 00000000000..52a6d79da25
--- /dev/null
+++ b/include/apr_date.h
@@ -0,0 +1,106 @@
+/* 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 APR_DATE_H
+#define APR_DATE_H
+
+/**
+ * @file apr_date.h
+ * @brief APR-UTIL date routines
+ */
+
+/**
+ * @defgroup APR_Util_Date Date routines
+ * @ingroup APR
+ * @{
+ */
+
+/*
+ * apr_date.h: prototypes for date parsing utility routines
+ */
+
+#include "apu.h"
+#include "apr_time.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** A bad date. */
+#define APR_DATE_BAD ((apr_time_t)0)
+
+/**
+ * Compare a string to a mask
+ * @param data The string to compare
+ * @param mask Mask characters (arbitrary maximum is 256 characters):
+ * <PRE>
+ *   '\@' - uppercase letter
+ *   '\$' - lowercase letter
+ *   '\&' - hex digit
+ *   '#' - digit
+ *   '~' - digit or space
+ *   '*' - swallow remaining characters
+ * </PRE>
+ * @remark The mask tests for an exact match for any other character
+ * @return 1 if the string matches, 0 otherwise
+ */
+APR_DECLARE(int) apr_date_checkmask(const char *data, const char *mask);
+
+/**
+ * Parses an HTTP date in one of three standard forms:
+ * <PRE>
+ *     Sun, 06 Nov 1994 08:49:37 GMT  ; RFC 822, updated by RFC 1123
+ *     Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
+ *     Sun Nov  6 08:49:37 1994       ; ANSI C's asctime() format
+ * </PRE>
+ * @param date The date in one of the three formats above
+ * @return the apr_time_t number of microseconds since 1 Jan 1970 GMT, or
+ *         0 if this would be out of range or if the date is invalid.
+ */
+APR_DECLARE(apr_time_t) apr_date_parse_http(const char *date);
+
+/**
+ * Parses a string resembling an RFC 822 date.  This is meant to be
+ * leinent in its parsing of dates.  Hence, this will parse a wider 
+ * range of dates than apr_date_parse_http.
+ *
+ * The prominent mailer (or poster, if mailer is unknown) that has
+ * been seen in the wild is included for the unknown formats.
+ * <PRE>
+ *     Sun, 06 Nov 1994 08:49:37 GMT  ; RFC 822, updated by RFC 1123
+ *     Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
+ *     Sun Nov  6 08:49:37 1994       ; ANSI C's asctime() format
+ *     Sun, 6 Nov 1994 08:49:37 GMT   ; RFC 822, updated by RFC 1123
+ *     Sun, 06 Nov 94 08:49:37 GMT    ; RFC 822
+ *     Sun, 6 Nov 94 08:49:37 GMT     ; RFC 822
+ *     Sun, 06 Nov 94 08:49 GMT       ; Unknown [drtr\@ast.cam.ac.uk] 
+ *     Sun, 6 Nov 94 08:49 GMT        ; Unknown [drtr\@ast.cam.ac.uk]
+ *     Sun, 06 Nov 94 8:49:37 GMT     ; Unknown [Elm 70.85]
+ *     Sun, 6 Nov 94 8:49:37 GMT      ; Unknown [Elm 70.85] 
+ * </PRE>
+ *
+ * @param date The date in one of the formats above
+ * @return the apr_time_t number of microseconds since 1 Jan 1970 GMT, or
+ *         0 if this would be out of range or if the date is invalid.
+ */
+APR_DECLARE(apr_time_t) apr_date_parse_rfc(const char *date);
+
+/** @} */
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* !APR_DATE_H */
diff --git a/include/apr_dbd.h b/include/apr_dbd.h
new file mode 100644
index 00000000000..6b9032778b0
--- /dev/null
+++ b/include/apr_dbd.h
@@ -0,0 +1,552 @@
+/* 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.
+ */
+
+/* Overview of what this is and does:
+ * http://www.apache.org/~niq/dbd.html
+ */
+
+#ifndef APR_DBD_H
+#define APR_DBD_H
+
+#include "apu.h"
+#include "apr_pools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @file apr_dbd.h
+ * @brief APR-UTIL DBD library
+ */
+/**
+ * @defgroup APR_Util_DBD DBD routines
+ * @ingroup APR
+ * @{
+ */
+
+/**
+ * Mapping of C to SQL types, used for prepared statements.
+ * @remarks
+ * For apr_dbd_p[v]query/select functions, in and out parameters are always
+ * const char * (i.e. regular nul terminated strings). LOB types are passed
+ * with four (4) arguments: payload, length, table and column, all as const
+ * char *, where table and column are reserved for future use by Oracle.
+ * @remarks
+ * For apr_dbd_p[v]bquery/select functions, in and out parameters are
+ * described next to each enumeration constant and are generally native binary
+ * types or some APR data type. LOB types are passed with four (4) arguments:
+ * payload (char*), length (apr_size_t*), table (char*) and column (char*).
+ * Table and column are reserved for future use by Oracle.
+ */
+typedef enum {
+    APR_DBD_TYPE_NONE,
+    APR_DBD_TYPE_TINY,       /**< \%hhd : in, out: char* */
+    APR_DBD_TYPE_UTINY,      /**< \%hhu : in, out: unsigned char* */
+    APR_DBD_TYPE_SHORT,      /**< \%hd  : in, out: short* */
+    APR_DBD_TYPE_USHORT,     /**< \%hu  : in, out: unsigned short* */
+    APR_DBD_TYPE_INT,        /**< \%d   : in, out: int* */
+    APR_DBD_TYPE_UINT,       /**< \%u   : in, out: unsigned int* */
+    APR_DBD_TYPE_LONG,       /**< \%ld  : in, out: long* */
+    APR_DBD_TYPE_ULONG,      /**< \%lu  : in, out: unsigned long* */
+    APR_DBD_TYPE_LONGLONG,   /**< \%lld : in, out: apr_int64_t* */
+    APR_DBD_TYPE_ULONGLONG,  /**< \%llu : in, out: apr_uint64_t* */
+    APR_DBD_TYPE_FLOAT,      /**< \%f   : in, out: float* */
+    APR_DBD_TYPE_DOUBLE,     /**< \%lf  : in, out: double* */
+    APR_DBD_TYPE_STRING,     /**< \%s   : in: char*, out: char** */
+    APR_DBD_TYPE_TEXT,       /**< \%pDt : in: char*, out: char** */
+    APR_DBD_TYPE_TIME,       /**< \%pDi : in: char*, out: char** */
+    APR_DBD_TYPE_DATE,       /**< \%pDd : in: char*, out: char** */
+    APR_DBD_TYPE_DATETIME,   /**< \%pDa : in: char*, out: char** */
+    APR_DBD_TYPE_TIMESTAMP,  /**< \%pDs : in: char*, out: char** */
+    APR_DBD_TYPE_ZTIMESTAMP, /**< \%pDz : in: char*, out: char** */
+    APR_DBD_TYPE_BLOB,       /**< \%pDb : in: char* apr_size_t* char* char*, out: apr_bucket_brigade* */
+    APR_DBD_TYPE_CLOB,       /**< \%pDc : in: char* apr_size_t* char* char*, out: apr_bucket_brigade* */
+    APR_DBD_TYPE_NULL        /**< \%pDn : in: void*, out: void** */
+} apr_dbd_type_e;
+
+/* These are opaque structs.  Instantiation is up to each backend */
+typedef struct apr_dbd_driver_t apr_dbd_driver_t;
+typedef struct apr_dbd_t apr_dbd_t;
+typedef struct apr_dbd_transaction_t apr_dbd_transaction_t;
+typedef struct apr_dbd_results_t apr_dbd_results_t;
+typedef struct apr_dbd_row_t apr_dbd_row_t;
+typedef struct apr_dbd_prepared_t apr_dbd_prepared_t;
+
+/** apr_dbd_init: perform once-only initialisation.  Call once only.
+ *
+ *  @param pool - pool to register any shutdown cleanups, etc
+ */
+APR_DECLARE(apr_status_t) apr_dbd_init(apr_pool_t *pool);
+
+/** apr_dbd_get_driver: get the driver struct for a name
+ *
+ *  @param pool - (process) pool to register cleanup
+ *  @param name - driver name
+ *  @param driver - pointer to driver struct.
+ *  @return APR_SUCCESS for success
+ *  @return APR_ENOTIMPL for no driver (when DSO not enabled)
+ *  @return APR_EDSOOPEN if DSO driver file can't be opened
+ *  @return APR_ESYMNOTFOUND if the driver file doesn't contain a driver
+ */
+APR_DECLARE(apr_status_t) apr_dbd_get_driver(apr_pool_t *pool, const char *name,
+                                             const apr_dbd_driver_t **driver);
+
+/** apr_dbd_open_ex: open a connection to a backend
+ *
+ *  @param driver - driver struct.
+ *  @param pool - working pool
+ *  @param params - arguments to driver (implementation-dependent)
+ *  @param handle - pointer to handle to return
+ *  @param error - descriptive error.
+ *  @return APR_SUCCESS for success
+ *  @return APR_EGENERAL if driver exists but connection failed
+ *  @remarks PostgreSQL: the params is passed directly to the PQconnectdb()
+ *  function (check PostgreSQL documentation for more details on the syntax).
+ *  @remarks SQLite2: the params is split on a colon, with the first part used
+ *  as the filename and second part converted to an integer and used as file
+ *  mode.
+ *  @remarks SQLite3: the params is passed directly to the sqlite3_open()
+ *  function as a filename to be opened (check SQLite3 documentation for more
+ *  details).
+ *  @remarks Oracle: the params can have "user", "pass", "dbname" and "server"
+ *  keys, each followed by an equal sign and a value. Such key/value pairs can
+ *  be delimited by space, CR, LF, tab, semicolon, vertical bar or comma.
+ *  @remarks MySQL: the params can have "host", "port", "user", "pass",
+ *  "dbname", "sock", "flags" "fldsz", "group" and "reconnect" keys, each
+ *  followed by an equal sign and a value. Such key/value pairs can be
+ *  delimited by space, CR, LF, tab, semicolon, vertical bar or comma. For
+ *  now, "flags" can only recognise CLIENT_FOUND_ROWS (check MySQL manual for
+ *  details). The value associated with "fldsz" determines maximum amount of
+ *  memory (in bytes) for each of the fields in the result set of prepared
+ *  statements. By default, this value is 1 MB. The value associated with
+ *  "group" determines which group from configuration file to use (see
+ *  MYSQL_READ_DEFAULT_GROUP option of mysql_options() in MySQL manual).
+ *  Reconnect is set to 1 by default (i.e. true).
+ *  @remarks FreeTDS: the params can have "username", "password", "appname",
+ *  "dbname", "host", "charset", "lang" and "server" keys, each followed by an
+ *  equal sign and a value.
+ */
+APR_DECLARE(apr_status_t) apr_dbd_open_ex(const apr_dbd_driver_t *driver,
+                                          apr_pool_t *pool, const char *params,
+                                          apr_dbd_t **handle,
+                                          const char **error);
+
+/** apr_dbd_open: open a connection to a backend
+ *
+ *  @param driver - driver struct.
+ *  @param pool - working pool
+ *  @param params - arguments to driver (implementation-dependent)
+ *  @param handle - pointer to handle to return
+ *  @return APR_SUCCESS for success
+ *  @return APR_EGENERAL if driver exists but connection failed
+ *  @see apr_dbd_open_ex
+ */
+APR_DECLARE(apr_status_t) apr_dbd_open(const apr_dbd_driver_t *driver,
+                                       apr_pool_t *pool, const char *params,
+                                       apr_dbd_t **handle);
+
+/** apr_dbd_close: close a connection to a backend
+ *
+ *  @param driver - driver struct.
+ *  @param handle - handle to close
+ *  @return APR_SUCCESS for success or error status
+ */
+APR_DECLARE(apr_status_t) apr_dbd_close(const apr_dbd_driver_t *driver,
+                                        apr_dbd_t *handle);
+
+/* apr-function-shaped versions of things */
+
+/** apr_dbd_name: get the name of the driver
+ *
+ *  @param driver - the driver
+ *  @return - name
+ */
+APR_DECLARE(const char*) apr_dbd_name(const apr_dbd_driver_t *driver);
+
+/** apr_dbd_native_handle: get native database handle of the underlying db
+ *
+ *  @param driver - the driver
+ *  @param handle - apr_dbd handle
+ *  @return - native handle
+ */
+APR_DECLARE(void*) apr_dbd_native_handle(const apr_dbd_driver_t *driver,
+                                         apr_dbd_t *handle);
+
+/** check_conn: check status of a database connection
+ *
+ *  @param driver - the driver
+ *  @param pool - working pool
+ *  @param handle - the connection to check
+ *  @return APR_SUCCESS or error
+ */
+APR_DECLARE(int) apr_dbd_check_conn(const apr_dbd_driver_t *driver, apr_pool_t *pool,
+                                    apr_dbd_t *handle);
+
+/** apr_dbd_set_dbname: select database name.  May be a no-op if not supported.
+ *
+ *  @param driver - the driver
+ *  @param pool - working pool
+ *  @param handle - the connection
+ *  @param name - the database to select
+ *  @return 0 for success or error code
+ */
+APR_DECLARE(int) apr_dbd_set_dbname(const apr_dbd_driver_t *driver, apr_pool_t *pool,
+                                    apr_dbd_t *handle, const char *name);
+
+/** apr_dbd_transaction_start: start a transaction.  May be a no-op.
+ *
+ *  @param driver - the driver
+ *  @param pool - a pool to use for error messages (if any).
+ *  @param handle - the db connection
+ *  @param trans - ptr to a transaction.  May be null on entry
+ *  @return 0 for success or error code
+ *  @remarks Note that transaction modes, set by calling
+ *  apr_dbd_transaction_mode_set(), will affect all query/select calls within
+ *  a transaction. By default, any error in query/select during a transaction
+ *  will cause the transaction to inherit the error code and any further
+ *  query/select calls will fail immediately. Put transaction in "ignore
+ *  errors" mode to avoid that. Use "rollback" mode to do explicit rollback.
+ */
+APR_DECLARE(int) apr_dbd_transaction_start(const apr_dbd_driver_t *driver,
+                                           apr_pool_t *pool,
+                                           apr_dbd_t *handle,
+                                           apr_dbd_transaction_t **trans);
+
+/** apr_dbd_transaction_end: end a transaction
+ *  (commit on success, rollback on error).
+ *  May be a no-op.
+ *
+ *  @param driver - the driver
+ *  @param pool   - working pool
+ *  @param trans  - the transaction
+ *  @return 0 for success or error code
+ */
+APR_DECLARE(int) apr_dbd_transaction_end(const apr_dbd_driver_t *driver,
+                                         apr_pool_t *pool,
+                                         apr_dbd_transaction_t *trans);
+
+#define APR_DBD_TRANSACTION_COMMIT        0x00  /**< commit the transaction */
+#define APR_DBD_TRANSACTION_ROLLBACK      0x01  /**< rollback the transaction */
+#define APR_DBD_TRANSACTION_IGNORE_ERRORS 0x02  /**< ignore transaction errors */
+
+/** apr_dbd_transaction_mode_get: get the mode of transaction
+ *
+ *  @param driver - the driver
+ *  @param trans  - the transaction
+ *  @return mode of transaction
+ */
+APR_DECLARE(int) apr_dbd_transaction_mode_get(const apr_dbd_driver_t *driver,
+                                              apr_dbd_transaction_t *trans);
+
+/** apr_dbd_transaction_mode_set: set the mode of transaction
+ *
+ *  @param driver - the driver
+ *  @param trans  - the transaction
+ *  @param mode   - new mode of the transaction
+ *  @return the mode of transaction in force after the call
+ */
+APR_DECLARE(int) apr_dbd_transaction_mode_set(const apr_dbd_driver_t *driver,
+                                              apr_dbd_transaction_t *trans,
+                                              int mode);
+
+/** apr_dbd_query: execute an SQL query that doesn't return a result set
+ *
+ *  @param driver - the driver
+ *  @param handle - the connection
+ *  @param nrows - number of rows affected.
+ *  @param statement - the SQL statement to execute
+ *  @return 0 for success or error code
+ */
+APR_DECLARE(int) apr_dbd_query(const apr_dbd_driver_t *driver, apr_dbd_t *handle,
+                               int *nrows, const char *statement);
+
+/** apr_dbd_select: execute an SQL query that returns a result set
+ *
+ *  @param driver - the driver
+ *  @param pool - pool to allocate the result set
+ *  @param handle - the connection
+ *  @param res - pointer to result set pointer.  May point to NULL on entry
+ *  @param statement - the SQL statement to execute
+ *  @param random - 1 to support random access to results (seek any row);
+ *                  0 to support only looping through results in order
+ *                    (async access - faster)
+ *  @return 0 for success or error code
+ */
+APR_DECLARE(int) apr_dbd_select(const apr_dbd_driver_t *driver, apr_pool_t *pool,
+                                apr_dbd_t *handle, apr_dbd_results_t **res,
+                                const char *statement, int random);
+
+/** apr_dbd_num_cols: get the number of columns in a results set
+ *
+ *  @param driver - the driver
+ *  @param res - result set.
+ *  @return number of columns
+ */
+APR_DECLARE(int) apr_dbd_num_cols(const apr_dbd_driver_t *driver,
+                                  apr_dbd_results_t *res);
+
+/** apr_dbd_num_tuples: get the number of rows in a results set
+ *  of a synchronous select
+ *
+ *  @param driver - the driver
+ *  @param res - result set.
+ *  @return number of rows, or -1 if the results are asynchronous
+ */
+APR_DECLARE(int) apr_dbd_num_tuples(const apr_dbd_driver_t *driver,
+                                    apr_dbd_results_t *res);
+
+/** apr_dbd_get_row: get a row from a result set
+ *
+ *  @param driver - the driver
+ *  @param pool - pool to allocate the row
+ *  @param res - result set pointer
+ *  @param row - pointer to row pointer.  May point to NULL on entry
+ *  @param rownum - row number (counting from 1), or -1 for "next row".
+ *                  Ignored if random access is not supported.
+ *  @return 0 for success, -1 for rownum out of range or data finished
+ */
+APR_DECLARE(int) apr_dbd_get_row(const apr_dbd_driver_t *driver, apr_pool_t *pool,
+                                 apr_dbd_results_t *res, apr_dbd_row_t **row,
+                                 int rownum);
+
+/** apr_dbd_get_entry: get an entry from a row
+ *
+ *  @param driver - the driver
+ *  @param row - row pointer
+ *  @param col - entry number
+ *  @return value from the row, or NULL if col is out of bounds.
+ */
+APR_DECLARE(const char*) apr_dbd_get_entry(const apr_dbd_driver_t *driver,
+                                           apr_dbd_row_t *row, int col);
+
+/** apr_dbd_get_name: get an entry name from a result set
+ *
+ *  @param driver - the driver
+ *  @param res - result set pointer
+ *  @param col - entry number
+ *  @return name of the entry, or NULL if col is out of bounds.
+ */
+APR_DECLARE(const char*) apr_dbd_get_name(const apr_dbd_driver_t *driver,
+                                          apr_dbd_results_t *res, int col);
+
+
+/** apr_dbd_error: get current error message (if any)
+ *
+ *  @param driver - the driver
+ *  @param handle - the connection
+ *  @param errnum - error code from operation that returned an error
+ *  @return the database current error message, or message for errnum
+ *          (implementation-dependent whether errnum is ignored)
+ */
+APR_DECLARE(const char*) apr_dbd_error(const apr_dbd_driver_t *driver,
+                                       apr_dbd_t *handle, int errnum);
+
+/** apr_dbd_escape: escape a string so it is safe for use in query/select
+ *
+ *  @param driver - the driver
+ *  @param pool - pool to alloc the result from
+ *  @param string - the string to escape
+ *  @param handle - the connection
+ *  @return the escaped, safe string
+ */
+APR_DECLARE(const char*) apr_dbd_escape(const apr_dbd_driver_t *driver,
+                                        apr_pool_t *pool, const char *string,
+                                        apr_dbd_t *handle);
+
+/** apr_dbd_prepare: prepare a statement
+ *
+ *  @param driver - the driver
+ *  @param pool - pool to alloc the result from
+ *  @param handle - the connection
+ *  @param query - the SQL query
+ *  @param label - A label for the prepared statement.
+ *                 use NULL for temporary prepared statements
+ *                 (eg within a Request in httpd)
+ *  @param statement - statement to prepare.  May point to null on entry.
+ *  @return 0 for success or error code
+ *  @remarks To specify parameters of the prepared query, use \%s, \%d etc.
+ *  (see below for full list) in place of database specific parameter syntax
+ *  (e.g.  for PostgreSQL, this would be $1, $2, for SQLite3 this would be ?
+ *  etc.).  For instance: "SELECT name FROM customers WHERE name=%s" would be
+ *  a query that this function understands.
+ *  @remarks Here is the full list of format specifiers that this function
+ *  understands and what they map to in SQL: \%hhd (TINY INT), \%hhu (UNSIGNED
+ *  TINY INT), \%hd (SHORT), \%hu (UNSIGNED SHORT), \%d (INT), \%u (UNSIGNED
+ *  INT), \%ld (LONG), \%lu (UNSIGNED LONG), \%lld (LONG LONG), \%llu
+ *  (UNSIGNED LONG LONG), \%f (FLOAT, REAL), \%lf (DOUBLE PRECISION), \%s
+ *  (VARCHAR), \%pDt (TEXT), \%pDi (TIME), \%pDd (DATE), \%pDa (DATETIME),
+ *  \%pDs (TIMESTAMP), \%pDz (TIMESTAMP WITH TIME ZONE), \%pDb (BLOB), \%pDc
+ *  (CLOB) and \%pDn (NULL). Not all databases have support for all these
+ *  types, so the underlying driver will attempt the "best match" where
+ *  possible. A \% followed by any letter not in the above list will be
+ *  interpreted as VARCHAR (i.e. \%s).
+ */
+APR_DECLARE(int) apr_dbd_prepare(const apr_dbd_driver_t *driver, apr_pool_t *pool,
+                                 apr_dbd_t *handle, const char *query,
+                                 const char *label,
+                                 apr_dbd_prepared_t **statement);
+
+
+/** apr_dbd_pquery: query using a prepared statement + args
+ *
+ *  @param driver - the driver
+ *  @param pool - working pool
+ *  @param handle - the connection
+ *  @param nrows - number of rows affected.
+ *  @param statement - the prepared statement to execute
+ *  @param nargs - ignored (for backward compatibility only)
+ *  @param args - args to prepared statement
+ *  @return 0 for success or error code
+ */
+APR_DECLARE(int) apr_dbd_pquery(const apr_dbd_driver_t *driver, apr_pool_t *pool,
+                                apr_dbd_t *handle, int *nrows,
+                                apr_dbd_prepared_t *statement, int nargs,
+                                const char **args);
+
+/** apr_dbd_pselect: select using a prepared statement + args
+ *
+ *  @param driver - the driver
+ *  @param pool - working pool
+ *  @param handle - the connection
+ *  @param res - pointer to query results.  May point to NULL on entry
+ *  @param statement - the prepared statement to execute
+ *  @param random - Whether to support random-access to results
+ *  @param nargs - ignored (for backward compatibility only)
+ *  @param args - args to prepared statement
+ *  @return 0 for success or error code
+ */
+APR_DECLARE(int) apr_dbd_pselect(const apr_dbd_driver_t *driver, apr_pool_t *pool,
+                                 apr_dbd_t *handle, apr_dbd_results_t **res,
+                                 apr_dbd_prepared_t *statement, int random,
+                                 int nargs, const char **args);
+
+/** apr_dbd_pvquery: query using a prepared statement + args
+ *
+ *  @param driver - the driver
+ *  @param pool - working pool
+ *  @param handle - the connection
+ *  @param nrows - number of rows affected.
+ *  @param statement - the prepared statement to execute
+ *  @param ... - varargs list
+ *  @return 0 for success or error code
+ */
+APR_DECLARE_NONSTD(int) apr_dbd_pvquery(const apr_dbd_driver_t *driver, 
+                                        apr_pool_t *pool,
+                                        apr_dbd_t *handle, int *nrows,
+                                        apr_dbd_prepared_t *statement, ...);
+
+/** apr_dbd_pvselect: select using a prepared statement + args
+ *
+ *  @param driver - the driver
+ *  @param pool - working pool
+ *  @param handle - the connection
+ *  @param res - pointer to query results.  May point to NULL on entry
+ *  @param statement - the prepared statement to execute
+ *  @param random - Whether to support random-access to results
+ *  @param ... - varargs list
+ *  @return 0 for success or error code
+ */
+APR_DECLARE_NONSTD(int) apr_dbd_pvselect(const apr_dbd_driver_t *driver,
+                                         apr_pool_t *pool, apr_dbd_t *handle,
+                                         apr_dbd_results_t **res,
+                                         apr_dbd_prepared_t *statement,
+                                         int random, ...);
+
+/** apr_dbd_pbquery: query using a prepared statement + binary args
+ *
+ *  @param driver - the driver
+ *  @param pool - working pool
+ *  @param handle - the connection
+ *  @param nrows - number of rows affected.
+ *  @param statement - the prepared statement to execute
+ *  @param args - binary args to prepared statement
+ *  @return 0 for success or error code
+ */
+APR_DECLARE(int) apr_dbd_pbquery(const apr_dbd_driver_t *driver,
+                                 apr_pool_t *pool, apr_dbd_t *handle,
+                                 int *nrows, apr_dbd_prepared_t *statement,
+                                 const void **args);
+
+/** apr_dbd_pbselect: select using a prepared statement + binary args
+ *
+ *  @param driver - the driver
+ *  @param pool - working pool
+ *  @param handle - the connection
+ *  @param res - pointer to query results.  May point to NULL on entry
+ *  @param statement - the prepared statement to execute
+ *  @param random - Whether to support random-access to results
+ *  @param args - binary args to prepared statement
+ *  @return 0 for success or error code
+ */
+APR_DECLARE(int) apr_dbd_pbselect(const apr_dbd_driver_t *driver,
+                                  apr_pool_t *pool,
+                                  apr_dbd_t *handle, apr_dbd_results_t **res,
+                                  apr_dbd_prepared_t *statement, int random,
+                                  const void **args);
+
+/** apr_dbd_pvbquery: query using a prepared statement + binary args
+ *
+ *  @param driver - the driver
+ *  @param pool - working pool
+ *  @param handle - the connection
+ *  @param nrows - number of rows affected.
+ *  @param statement - the prepared statement to execute
+ *  @param ... - varargs list of binary args
+ *  @return 0 for success or error code
+ */
+APR_DECLARE_NONSTD(int) apr_dbd_pvbquery(const apr_dbd_driver_t *driver,
+                                         apr_pool_t *pool,
+                                         apr_dbd_t *handle, int *nrows,
+                                         apr_dbd_prepared_t *statement, ...);
+
+/** apr_dbd_pvbselect: select using a prepared statement + binary args
+ *
+ *  @param driver - the driver
+ *  @param pool - working pool
+ *  @param handle - the connection
+ *  @param res - pointer to query results.  May point to NULL on entry
+ *  @param statement - the prepared statement to execute
+ *  @param random - Whether to support random-access to results
+ *  @param ... - varargs list of binary args
+ *  @return 0 for success or error code
+ */
+APR_DECLARE_NONSTD(int) apr_dbd_pvbselect(const apr_dbd_driver_t *driver,
+                                          apr_pool_t *pool, apr_dbd_t *handle,
+                                          apr_dbd_results_t **res,
+                                          apr_dbd_prepared_t *statement,
+                                          int random, ...);
+
+/** apr_dbd_datum_get: get a binary entry from a row
+ *
+ *  @param driver - the driver
+ *  @param row - row pointer
+ *  @param col - entry number
+ *  @param type - type of data to get
+ *  @param data - pointer to data, allocated by the caller
+ *  @return APR_SUCCESS on success, APR_ENOENT if data is NULL or APR_EGENERAL
+ */
+APR_DECLARE(apr_status_t) apr_dbd_datum_get(const apr_dbd_driver_t *driver,
+                                            apr_dbd_row_t *row, int col,
+                                            apr_dbd_type_e type, void *data);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/apr_dbm.h b/include/apr_dbm.h
new file mode 100644
index 00000000000..017b9edea54
--- /dev/null
+++ b/include/apr_dbm.h
@@ -0,0 +1,227 @@
+/* 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 APR_DBM_H
+#define APR_DBM_H
+
+#include "apu.h"
+#include "apr.h"
+#include "apr_errno.h"
+#include "apr_pools.h"
+#include "apr_file_info.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @file apr_dbm.h
+ * @brief APR-UTIL DBM library
+ */
+/** 
+ * @defgroup APR_Util_DBM DBM routines
+ * @ingroup APR
+ * @{
+ */
+/**
+ * Structure for referencing a dbm
+ */
+typedef struct apr_dbm_t apr_dbm_t;
+
+/**
+ * Structure for referencing the datum record within a dbm
+ */
+typedef struct
+{
+    /** pointer to the 'data' to retrieve/store in the DBM */
+    char *dptr;
+    /** size of the 'data' to retrieve/store in the DBM */
+    apr_size_t dsize;
+} apr_datum_t;
+
+/* modes to open the DB */
+#define APR_DBM_READONLY        1       /**< open for read-only access */
+#define APR_DBM_READWRITE       2       /**< open for read-write access */
+#define APR_DBM_RWCREATE        3       /**< open for r/w, create if needed */
+#define APR_DBM_RWTRUNC         4       /**< open for r/w, truncating an existing
+                                          DB if present */
+/**
+ * Open a dbm file by file name and type of DBM
+ * @param dbm The newly opened database
+ * @param type The type of the DBM (not all may be available at run time)
+ * <pre>
+ *  db   for Berkeley DB files
+ *  gdbm for GDBM files
+ *  ndbm for NDBM files
+ *  sdbm for SDBM files (always available)
+ *  default for the default DBM type
+ *  </pre>
+ * @param name The dbm file name to open
+ * @param mode The flag value
+ * <PRE>
+ *           APR_DBM_READONLY   open for read-only access
+ *           APR_DBM_READWRITE  open for read-write access
+ *           APR_DBM_RWCREATE   open for r/w, create if needed
+ *           APR_DBM_RWTRUNC    open for r/w, truncate if already there
+ * </PRE>
+ * @param perm Permissions to apply to if created
+ * @param cntxt The pool to use when creating the dbm
+ * @remark The dbm name may not be a true file name, as many dbm packages
+ * append suffixes for seperate data and index files.
+ * @bug In apr-util 0.9 and 1.x, the type arg was case insensitive.  This
+ * was highly inefficient, and as of 2.x the dbm name must be provided in
+ * the correct case (lower case for all bundled providers)
+ */
+
+APR_DECLARE(apr_status_t) apr_dbm_open_ex(apr_dbm_t **dbm, const char* type, 
+                                       const char *name, 
+                                       apr_int32_t mode, apr_fileperms_t perm,
+                                       apr_pool_t *cntxt);
+
+
+/**
+ * Open a dbm file by file name
+ * @param dbm The newly opened database
+ * @param name The dbm file name to open
+ * @param mode The flag value
+ * <PRE>
+ *           APR_DBM_READONLY   open for read-only access
+ *           APR_DBM_READWRITE  open for read-write access
+ *           APR_DBM_RWCREATE   open for r/w, create if needed
+ *           APR_DBM_RWTRUNC    open for r/w, truncate if already there
+ * </PRE>
+ * @param perm Permissions to apply to if created
+ * @param cntxt The pool to use when creating the dbm
+ * @remark The dbm name may not be a true file name, as many dbm packages
+ * append suffixes for seperate data and index files.
+ */
+APR_DECLARE(apr_status_t) apr_dbm_open(apr_dbm_t **dbm, const char *name, 
+                                       apr_int32_t mode, apr_fileperms_t perm,
+                                       apr_pool_t *cntxt);
+
+/**
+ * Close a dbm file previously opened by apr_dbm_open
+ * @param dbm The database to close
+ */
+APR_DECLARE(void) apr_dbm_close(apr_dbm_t *dbm);
+
+/**
+ * Fetch a dbm record value by key
+ * @param dbm The database 
+ * @param key The key datum to find this record
+ * @param pvalue The value datum retrieved for this record
+ */
+APR_DECLARE(apr_status_t) apr_dbm_fetch(apr_dbm_t *dbm, apr_datum_t key,
+                                        apr_datum_t *pvalue);
+/**
+ * Store a dbm record value by key
+ * @param dbm The database 
+ * @param key The key datum to store this record by
+ * @param value The value datum to store in this record
+ */
+APR_DECLARE(apr_status_t) apr_dbm_store(apr_dbm_t *dbm, apr_datum_t key, 
+                                        apr_datum_t value);
+
+/**
+ * Delete a dbm record value by key
+ * @param dbm The database 
+ * @param key The key datum of the record to delete
+ * @remark It is not an error to delete a non-existent record.
+ */
+APR_DECLARE(apr_status_t) apr_dbm_delete(apr_dbm_t *dbm, apr_datum_t key);
+
+/**
+ * Search for a key within the dbm
+ * @param dbm The database 
+ * @param key The datum describing a key to test
+ */
+APR_DECLARE(int) apr_dbm_exists(apr_dbm_t *dbm, apr_datum_t key);
+
+/**
+ * Retrieve the first record key from a dbm
+ * @param dbm The database 
+ * @param pkey The key datum of the first record
+ */
+APR_DECLARE(apr_status_t) apr_dbm_firstkey(apr_dbm_t *dbm, apr_datum_t *pkey);
+
+/**
+ * Retrieve the next record key from a dbm
+ * @param dbm The database 
+ * @param pkey The key datum of the next record
+ */
+APR_DECLARE(apr_status_t) apr_dbm_nextkey(apr_dbm_t *dbm, apr_datum_t *pkey);
+
+/**
+ * Proactively toss any memory associated with the apr_datum_t.
+ * @param dbm The database 
+ * @param data The datum to free.
+ */
+APR_DECLARE(void) apr_dbm_freedatum(apr_dbm_t *dbm, apr_datum_t data);
+
+/**
+ * Report more information when an apr_dbm function fails.
+ * @param dbm The database
+ * @param errcode A DBM-specific value for the error (for logging). If this
+ *                isn't needed, it may be NULL.
+ * @param errbuf Location to store the error text
+ * @param errbufsize The size of the provided buffer
+ * @return The errbuf parameter, for convenience.
+ */
+APR_DECLARE(char *) apr_dbm_geterror(apr_dbm_t *dbm, int *errcode,
+                                     char *errbuf, apr_size_t errbufsize);
+/**
+ * If the specified file/path were passed to apr_dbm_open(), return the
+ * actual file/path names which would be (created and) used. At most, two
+ * files may be used; used2 may be NULL if only one file is used.
+ * @param pool The pool for allocating used1 and used2.
+ * @param type The type of DBM you require info on @see apr_dbm_open_ex
+ * @param pathname The path name to generate used-names from.
+ * @param used1 The first pathname used by the apr_dbm implementation.
+ * @param used2 The second pathname used by apr_dbm. If only one file is
+ *              used by the specific implementation, this will be set to NULL.
+ * @return An error if the specified type is invalid.
+ * @remark The dbm file(s) don't need to exist. This function only manipulates
+ *      the pathnames.
+ */
+APR_DECLARE(apr_status_t) apr_dbm_get_usednames_ex(apr_pool_t *pool,
+                                                   const char *type,
+                                                   const char *pathname,
+                                                   const char **used1,
+                                                   const char **used2);
+
+/**
+ * If the specified file/path were passed to apr_dbm_open(), return the
+ * actual file/path names which would be (created and) used. At most, two
+ * files may be used; used2 may be NULL if only one file is used.
+ * @param pool The pool for allocating used1 and used2.
+ * @param pathname The path name to generate used-names from.
+ * @param used1 The first pathname used by the apr_dbm implementation.
+ * @param used2 The second pathname used by apr_dbm. If only one file is
+ *              used by the specific implementation, this will be set to NULL.
+ * @remark The dbm file(s) don't need to exist. This function only manipulates
+ *      the pathnames.
+ */
+APR_DECLARE(void) apr_dbm_get_usednames(apr_pool_t *pool,
+                                        const char *pathname,
+                                        const char **used1,
+                                        const char **used2);
+
+/** @} */
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* !APR_DBM_H */
diff --git a/include/apr_dso.h b/include/apr_dso.h
index 01f71c34ca1..ac701cfdf55 100644
--- a/include/apr_dso.h
+++ b/include/apr_dso.h
@@ -1,121 +1,92 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 APR_DSO_DOT_H
 #define APR_DSO_DOT_H
 
-#include "apr_general.h"
+/**
+ * @file apr_dso.h
+ * @brief APR Dynamic Object Handling Routines
+ */
+
+#include "apr.h"
+#include "apr_pools.h"
 #include "apr_errno.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-typedef struct ap_dso_handle_t        ap_dso_handle_t;
-typedef void *                        ap_dso_handle_sym_t;
-
-/*
-
-=head1 ap_status_t ap_dso_init(void)
-
-B<Initialize the underlying DSO library.>
-
-=cut
+/**
+ * @defgroup apr_dso Dynamic Object Handling
+ * @ingroup APR 
+ * @{
  */
-ap_status_t ap_dso_init(void);
 
-/*
+#if APR_HAS_DSO || defined(DOXYGEN)
 
-=head1 ap_status_t ap_dso_load(ap_dso_handle_t **res_handle, const char *path, ap_pool_t *ctx)
-
-B<Load a DSO library.>
-
-    arg 1) Location to store new handle for the DSO.
-    arg 2) Path to the DSO library
-    arg 3) Pool to use. 
-
-=cut
+/**
+ * Structure for referencing dynamic objects
  */
-ap_status_t ap_dso_load(ap_dso_handle_t **res_handle, const char *path, 
-                        ap_pool_t *ctx);
-
-/*
-
-=head1 ap_status_t ap_dso_unload(ap_dso_handle_t *handle)
-
-B<Close a DSO library.>
+typedef struct apr_dso_handle_t       apr_dso_handle_t;
 
-    arg 1) handle to close.
-
-=cut
+/**
+ * Structure for referencing symbols from dynamic objects
+ */
+typedef void *                        apr_dso_handle_sym_t;
+
+/**
+ * Load a DSO library.
+ * @param res_handle Location to store new handle for the DSO.
+ * @param path Path to the DSO library
+ * @param ctx Pool to use.
+ * @bug We aught to provide an alternative to RTLD_GLOBAL, which
+ * is the only supported method of loading DSOs today.
  */
-ap_status_t ap_dso_unload(ap_dso_handle_t *handle);
+APR_DECLARE(apr_status_t) apr_dso_load(apr_dso_handle_t **res_handle, 
+                                       const char *path, apr_pool_t *ctx);
 
-/*
+/**
+ * Close a DSO library.
+ * @param handle handle to close.
+ */
+APR_DECLARE(apr_status_t) apr_dso_unload(apr_dso_handle_t *handle);
 
-=head1 ap_status_t ap_dso_sym(ap_dso_handle_sym_t *ressym, ap_dso_handle_t *handle *, const char *symname)
+/**
+ * Load a symbol from a DSO handle.
+ * @param ressym Location to store the loaded symbol
+ * @param handle handle to load the symbol from.
+ * @param symname Name of the symbol to load.
+ */
+APR_DECLARE(apr_status_t) apr_dso_sym(apr_dso_handle_sym_t *ressym, 
+                                      apr_dso_handle_t *handle,
+                                      const char *symname);
+
+/**
+ * Report more information when a DSO function fails.
+ * @param dso The dso handle that has been opened
+ * @param buf Location to store the dso error
+ * @param bufsize The size of the provided buffer
+ */
+APR_DECLARE(const char *) apr_dso_error(apr_dso_handle_t *dso, char *buf, apr_size_t bufsize);
 
-B<Load a symbol from a DSO handle.>
+#endif /* APR_HAS_DSO */
 
-    arg 1) Location to store the loaded symbol
-    arg 2) handle to load from.
-    arg 3) Name of the symbol to load.
+/** @} */
 
-=cut
- */
-ap_status_t ap_dso_sym(ap_dso_handle_sym_t *ressym, ap_dso_handle_t *handle, 
-                       const char *symname);
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/apr_env.h b/include/apr_env.h
new file mode 100644
index 00000000000..85ab67041fa
--- /dev/null
+++ b/include/apr_env.h
@@ -0,0 +1,67 @@
+/* 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 APR_ENV_H
+#define APR_ENV_H
+/**
+ * @file apr_env.h
+ * @brief APR Environment functions
+ */
+#include "apr_errno.h"
+#include "apr_pools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup apr_env Functions for manipulating the environment
+ * @ingroup APR 
+ * @{
+ */
+
+/**
+ * Get the value of an environment variable
+ * @param value the returned value, allocated from @a pool
+ * @param envvar the name of the environment variable
+ * @param pool where to allocate @a value and any temporary storage from
+ */
+APR_DECLARE(apr_status_t) apr_env_get(char **value, const char *envvar,
+                                      apr_pool_t *pool);
+
+/**
+ * Set the value of an environment variable
+ * @param envvar the name of the environment variable
+ * @param value the value to set
+ * @param pool where to allocate temporary storage from
+ */
+APR_DECLARE(apr_status_t) apr_env_set(const char *envvar, const char *value,
+                                      apr_pool_t *pool);
+
+/**
+ * Delete a variable from the environment
+ * @param envvar the name of the environment variable
+ * @param pool where to allocate temporary storage from
+ */
+APR_DECLARE(apr_status_t) apr_env_delete(const char *envvar, apr_pool_t *pool);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* ! APR_ENV_H */
diff --git a/include/apr_errno.h b/include/apr_errno.h
index 9eb186e41fd..d2abfb18f8b 100644
--- a/include/apr_errno.h
+++ b/include/apr_errno.h
@@ -1,249 +1,1342 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+/* 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 APR_ERRNO_H
 #define APR_ERRNO_H
 
+/**
+ * @file apr_errno.h
+ * @brief APR Error Codes
+ */
+
 #include "apr.h"
+
+#if APR_HAVE_ERRNO_H
 #include <errno.h>
+#endif
 
 #ifdef __cplusplus
 extern "C" {
 #endif /* __cplusplus */
 
-typedef int ap_status_t;
+/**
+ * @defgroup apr_errno Error Codes
+ * @ingroup APR 
+ * @{
+ */
+
+/**
+ * Type for specifying an error or status code.
+ */
+typedef int apr_status_t;
+
+/**
+ * Return a human readable string describing the specified error.
+ * @param statcode The error code to get a string for.
+ * @param buf A buffer to hold the error string.
+ * @param bufsize Size of the buffer to hold the string.
+ */
+APR_DECLARE(char *) apr_strerror(apr_status_t statcode, char *buf, 
+                                 apr_size_t bufsize);
+
+#if defined(DOXYGEN)
+/**
+ * @def APR_FROM_OS_ERROR(os_err_type syserr)
+ * Fold a platform specific error into an apr_status_t code.
+ * @return apr_status_t
+ * @param e The platform os error code.
+ * @warning  macro implementation; the syserr argument may be evaluated
+ *      multiple times.
+ */
+#define APR_FROM_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e + APR_OS_START_SYSERR)
+
+/**
+ * @def APR_TO_OS_ERROR(apr_status_t statcode)
+ * @return os_err_type
+ * Fold an apr_status_t code back to the native platform defined error.
+ * @param e The apr_status_t folded platform os error code.
+ * @warning  macro implementation; the statcode argument may be evaluated
+ *      multiple times.  If the statcode was not created by apr_get_os_error 
+ *      or APR_FROM_OS_ERROR, the results are undefined.
+ */
+#define APR_TO_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e - APR_OS_START_SYSERR)
 
-int ap_canonical_error(ap_status_t err);
+/** @def apr_get_os_error()
+ * @return apr_status_t the last platform error, folded into apr_status_t, on most platforms
+ * @remark This retrieves errno, or calls a GetLastError() style function, and
+ *      folds it with APR_FROM_OS_ERROR.  Some platforms (such as OS2) have no
+ *      such mechanism, so this call may be unsupported.  Do NOT use this
+ *      call for socket errors from socket, send, recv etc!
+ */
+
+/** @def apr_set_os_error(e)
+ * Reset the last platform error, unfolded from an apr_status_t, on some platforms
+ * @param e The OS error folded in a prior call to APR_FROM_OS_ERROR()
+ * @warning This is a macro implementation; the statcode argument may be evaluated
+ *      multiple times.  If the statcode was not created by apr_get_os_error
+ *      or APR_FROM_OS_ERROR, the results are undefined.  This macro sets
+ *      errno, or calls a SetLastError() style function, unfolding statcode
+ *      with APR_TO_OS_ERROR.  Some platforms (such as OS2) have no such
+ *      mechanism, so this call may be unsupported.
+ */
 
+/** @def apr_get_netos_error()
+ * Return the last socket error, folded into apr_status_t, on all platforms
+ * @remark This retrieves errno or calls a GetLastSocketError() style function,
+ *      and folds it with APR_FROM_OS_ERROR.
+ */
 
-/* APR_OS_START_ERROR is where the APR specific error values should start.
- * APR_OS_START_STATUS is where the APR specific status codes should start.
- * APR_OS_START_USEERR are reserved for applications that use APR that
- *     layer their own error codes along with APR's.
- * APR_OS_START_SYSERR should be used for system error values on 
- *     each platform.  
+/** @def apr_set_netos_error(e)
+ * Reset the last socket error, unfolded from an apr_status_t
+ * @param e The socket error folded in a prior call to APR_FROM_OS_ERROR()
+ * @warning This is a macro implementation; the statcode argument may be evaluated
+ *      multiple times.  If the statcode was not created by apr_get_os_error
+ *      or APR_FROM_OS_ERROR, the results are undefined.  This macro sets
+ *      errno, or calls a WSASetLastError() style function, unfolding 
+ *      socketcode with APR_TO_OS_ERROR.
  */
-#define APR_OS_START_ERROR     1000
-#define APR_OS_START_STATUS    (APR_OS_START_ERROR + 500)
-#define APR_OS_START_USEERR    (APR_OS_START_STATUS + 500)
-#define APR_OS_START_CANONERR  (APR_OS_START_USEERR + 500)
-#define APR_OS_START_SYSERR    (APR_OS_START_CANONERR + 500)
 
-#define APR_OS2_STATUS(e) (e == 0 ? APR_SUCCESS : e + APR_OS_START_SYSERR)
+#endif /* defined(DOXYGEN) */
+
+/**
+ * APR_OS_START_ERROR is where the APR specific error values start.
+ */
+#define APR_OS_START_ERROR     20000
+/**
+ * APR_OS_ERRSPACE_SIZE is the maximum number of errors you can fit
+ *    into one of the error/status ranges below -- except for
+ *    APR_OS_START_USERERR, which see.
+ */
+#define APR_OS_ERRSPACE_SIZE 50000
+/**
+ * APR_UTIL_ERRSPACE_SIZE is the size of the space that is reserved for
+ * use within apr-util. This space is reserved above that used by APR
+ * internally.
+ * @note This number MUST be smaller than APR_OS_ERRSPACE_SIZE by a
+ *       large enough amount that APR has sufficient room for its
+ *       codes.
+ */
+#define APR_UTIL_ERRSPACE_SIZE 20000
+/**
+ * APR_OS_START_STATUS is where the APR specific status codes start.
+ */
+#define APR_OS_START_STATUS    (APR_OS_START_ERROR + APR_OS_ERRSPACE_SIZE)
+/**
+ * APR_UTIL_START_STATUS is where APR-Util starts defining its
+ * status codes.
+ */
+#define APR_UTIL_START_STATUS   (APR_OS_START_STATUS + \
+                           (APR_OS_ERRSPACE_SIZE - APR_UTIL_ERRSPACE_SIZE))
+/**
+ * APR_OS_START_USERERR are reserved for applications that use APR that
+ *     layer their own error codes along with APR's.  Note that the
+ *     error immediately following this one is set ten times farther
+ *     away than usual, so that users of apr have a lot of room in
+ *     which to declare custom error codes.
+ *
+ * In general applications should try and create unique error codes. To try
+ * and assist in finding suitable ranges of numbers to use, the following
+ * ranges are known to be used by the listed applications. If your 
+ * application defines error codes please advise the range of numbers it
+ * uses to dev@apr.apache.org for inclusion in this list.
+ *
+ * Ranges shown are in relation to APR_OS_START_USERERR
+ *
+ * Subversion - Defined ranges, of less than 100, at intervals of 5000
+ *              starting at an offset of 5000, e.g.
+ *               +5000 to 5100,  +10000 to 10100
+ *
+ * Apache HTTPD - +2000 to 2999
+ */
+#define APR_OS_START_USERERR    (APR_OS_START_STATUS + APR_OS_ERRSPACE_SIZE)
+/**
+ * APR_OS_START_USEERR is obsolete, defined for compatibility only.
+ * Use APR_OS_START_USERERR instead.
+ */
+#define APR_OS_START_USEERR     APR_OS_START_USERERR
+/**
+ * APR_OS_START_CANONERR is where APR versions of errno values are defined
+ *     on systems which don't have the corresponding errno.
+ */
+#define APR_OS_START_CANONERR  (APR_OS_START_USERERR \
+                                 + (APR_OS_ERRSPACE_SIZE * 10))
+/**
+ * APR_OS_START_EAIERR folds EAI_ error codes from getaddrinfo() into 
+ *     apr_status_t values.
+ */
+#define APR_OS_START_EAIERR    (APR_OS_START_CANONERR + APR_OS_ERRSPACE_SIZE)
+/**
+ * APR_OS_START_SYSERR folds platform-specific system error values into 
+ *     apr_status_t values.
+ */
+#define APR_OS_START_SYSERR    (APR_OS_START_EAIERR + APR_OS_ERRSPACE_SIZE)
 
+/**
+ * @defgroup APR_ERROR_map APR Error Space
+ * <PRE>
+ * The following attempts to show the relation of the various constants
+ * used for mapping APR Status codes.
+ *
+ *       0          
+ *
+ *  20,000     APR_OS_START_ERROR
+ *
+ *         + APR_OS_ERRSPACE_SIZE (50,000)
+ *
+ *  70,000      APR_OS_START_STATUS
+ *
+ *         + APR_OS_ERRSPACE_SIZE - APR_UTIL_ERRSPACE_SIZE (30,000)
+ *
+ * 100,000      APR_UTIL_START_STATUS
+ *
+ *         + APR_UTIL_ERRSPACE_SIZE (20,000)
+ *
+ * 120,000      APR_OS_START_USERERR
+ *
+ *         + 10 x APR_OS_ERRSPACE_SIZE (50,000 * 10)
+ *
+ * 620,000      APR_OS_START_CANONERR
+ *
+ *         + APR_OS_ERRSPACE_SIZE (50,000)
+ *
+ * 670,000      APR_OS_START_EAIERR
+ *
+ *         + APR_OS_ERRSPACE_SIZE (50,000)
+ *
+ * 720,000      APR_OS_START_SYSERR
+ *
+ * </PRE>
+ */
+
+/** no error. */
 #define APR_SUCCESS 0
 
-/* APR ERROR VALUES */
+/** 
+ * @defgroup APR_Error APR Error Values
+ * <PRE>
+ * <b>APR ERROR VALUES</b>
+ * APR_ENOSTAT      APR was unable to perform a stat on the file 
+ * APR_ENOPOOL      APR was not provided a pool with which to allocate memory
+ * APR_EBADDATE     APR was given an invalid date 
+ * APR_EINVALSOCK   APR was given an invalid socket
+ * APR_ENOPROC      APR was not given a process structure
+ * APR_ENOTIME      APR was not given a time structure
+ * APR_ENODIR       APR was not given a directory structure
+ * APR_ENOLOCK      APR was not given a lock structure
+ * APR_ENOPOLL      APR was not given a poll structure
+ * APR_ENOSOCKET    APR was not given a socket
+ * APR_ENOTHREAD    APR was not given a thread structure
+ * APR_ENOTHDKEY    APR was not given a thread key structure
+ * APR_ENOSHMAVAIL  There is no more shared memory available
+ * APR_EDSOOPEN     APR was unable to open the dso object.  For more 
+ *                  information call apr_dso_error().
+ * APR_EGENERAL     General failure (specific information not available)
+ * APR_EBADIP       The specified IP address is invalid
+ * APR_EBADMASK     The specified netmask is invalid
+ * APR_ESYMNOTFOUND Could not find the requested symbol
+ * APR_ENOTENOUGHENTROPY Not enough entropy to continue
+ * </PRE>
+ *
+ * <PRE>
+ * <b>APR STATUS VALUES</b>
+ * APR_INCHILD        Program is currently executing in the child
+ * APR_INPARENT       Program is currently executing in the parent
+ * APR_DETACH         The thread is detached
+ * APR_NOTDETACH      The thread is not detached
+ * APR_CHILD_DONE     The child has finished executing
+ * APR_CHILD_NOTDONE  The child has not finished executing
+ * APR_TIMEUP         The operation did not finish before the timeout
+ * APR_INCOMPLETE     The operation was incomplete although some processing
+ *                    was performed and the results are partially valid
+ * APR_BADCH          Getopt found an option not in the option string
+ * APR_BADARG         Getopt found an option that is missing an argument 
+ *                    and an argument was specified in the option string
+ * APR_EOF            APR has encountered the end of the file
+ * APR_NOTFOUND       APR was unable to find the socket in the poll structure
+ * APR_ANONYMOUS      APR is using anonymous shared memory
+ * APR_FILEBASED      APR is using a file name as the key to the shared memory
+ * APR_KEYBASED       APR is using a shared key as the key to the shared memory
+ * APR_EINIT          Ininitalizer value.  If no option has been found, but 
+ *                    the status variable requires a value, this should be used
+ * APR_ENOTIMPL       The APR function has not been implemented on this 
+ *                    platform, either because nobody has gotten to it yet, 
+ *                    or the function is impossible on this platform.
+ * APR_EMISMATCH      Two passwords do not match.
+ * APR_EABSOLUTE      The given path was absolute.
+ * APR_ERELATIVE      The given path was relative.
+ * APR_EINCOMPLETE    The given path was neither relative nor absolute.
+ * APR_EABOVEROOT     The given path was above the root path.
+ * APR_EBUSY          The given lock was busy.
+ * APR_EPROC_UNKNOWN  The given process wasn't recognized by APR
+ * </PRE>
+ * @{
+ */
+/** @see APR_STATUS_IS_ENOSTAT */
 #define APR_ENOSTAT        (APR_OS_START_ERROR + 1)
+/** @see APR_STATUS_IS_ENOPOOL */
 #define APR_ENOPOOL        (APR_OS_START_ERROR + 2)
-#define APR_ENOFILE        (APR_OS_START_ERROR + 3)
+/* empty slot: +3 */
+/** @see APR_STATUS_IS_EBADDATE */
 #define APR_EBADDATE       (APR_OS_START_ERROR + 4)
+/** @see APR_STATUS_IS_EINVALSOCK */
 #define APR_EINVALSOCK     (APR_OS_START_ERROR + 5)
+/** @see APR_STATUS_IS_ENOPROC */
 #define APR_ENOPROC        (APR_OS_START_ERROR + 6)
+/** @see APR_STATUS_IS_ENOTIME */
 #define APR_ENOTIME        (APR_OS_START_ERROR + 7)
+/** @see APR_STATUS_IS_ENODIR */
 #define APR_ENODIR         (APR_OS_START_ERROR + 8)
+/** @see APR_STATUS_IS_ENOLOCK */
 #define APR_ENOLOCK        (APR_OS_START_ERROR + 9)
+/** @see APR_STATUS_IS_ENOPOLL */
 #define APR_ENOPOLL        (APR_OS_START_ERROR + 10)
+/** @see APR_STATUS_IS_ENOSOCKET */
 #define APR_ENOSOCKET      (APR_OS_START_ERROR + 11)
+/** @see APR_STATUS_IS_ENOTHREAD */
 #define APR_ENOTHREAD      (APR_OS_START_ERROR + 12)
+/** @see APR_STATUS_IS_ENOTHDKEY */
 #define APR_ENOTHDKEY      (APR_OS_START_ERROR + 13)
-/* empty slot: +14 */
+/** @see APR_STATUS_IS_EGENERAL */
+#define APR_EGENERAL       (APR_OS_START_ERROR + 14)
+/** @see APR_STATUS_IS_ENOSHMAVAIL */
 #define APR_ENOSHMAVAIL    (APR_OS_START_ERROR + 15)
-/* empty slot: +16 */
-/* empty slot: +17 */
+/** @see APR_STATUS_IS_EBADIP */
+#define APR_EBADIP         (APR_OS_START_ERROR + 16)
+/** @see APR_STATUS_IS_EBADMASK */
+#define APR_EBADMASK       (APR_OS_START_ERROR + 17)
 /* empty slot: +18 */
+/** @see APR_STATUS_IS_EDSOPEN */
 #define APR_EDSOOPEN       (APR_OS_START_ERROR + 19)
+/** @see APR_STATUS_IS_EABSOLUTE */
+#define APR_EABSOLUTE      (APR_OS_START_ERROR + 20)
+/** @see APR_STATUS_IS_ERELATIVE */
+#define APR_ERELATIVE      (APR_OS_START_ERROR + 21)
+/** @see APR_STATUS_IS_EINCOMPLETE */
+#define APR_EINCOMPLETE    (APR_OS_START_ERROR + 22)
+/** @see APR_STATUS_IS_EABOVEROOT */
+#define APR_EABOVEROOT     (APR_OS_START_ERROR + 23)
+/** @see APR_STATUS_IS_EBADPATH */
+#define APR_EBADPATH       (APR_OS_START_ERROR + 24)
+/** @see APR_STATUS_IS_EPATHWILD */
+#define APR_EPATHWILD      (APR_OS_START_ERROR + 25)
+/** @see APR_STATUS_IS_ESYMNOTFOUND */
+#define APR_ESYMNOTFOUND   (APR_OS_START_ERROR + 26)
+/** @see APR_STATUS_IS_EPROC_UNKNOWN */
+#define APR_EPROC_UNKNOWN  (APR_OS_START_ERROR + 27)
+/** @see APR_STATUS_IS_ENOTENOUGHENTROPY */
+#define APR_ENOTENOUGHENTROPY (APR_OS_START_ERROR + 28)
+/** @} */
+
+/** 
+ * @defgroup APR_STATUS_IS Status Value Tests
+ * @warning For any particular error condition, more than one of these tests
+ *      may match. This is because platform-specific error codes may not
+ *      always match the semantics of the POSIX codes these tests (and the
+ *      corresponding APR error codes) are named after. A notable example
+ *      are the APR_STATUS_IS_ENOENT and APR_STATUS_IS_ENOTDIR tests on
+ *      Win32 platforms. The programmer should always be aware of this and
+ *      adjust the order of the tests accordingly.
+ * @{
+ */
+/** 
+ * APR was unable to perform a stat on the file 
+ * @warning always use this test, as platform-specific variances may meet this
+ * more than one error code 
+ */
+#define APR_STATUS_IS_ENOSTAT(s)        ((s) == APR_ENOSTAT)
+/** 
+ * APR was not provided a pool with which to allocate memory 
+ * @warning always use this test, as platform-specific variances may meet this
+ * more than one error code 
+ */
+#define APR_STATUS_IS_ENOPOOL(s)        ((s) == APR_ENOPOOL)
+/** APR was given an invalid date  */
+#define APR_STATUS_IS_EBADDATE(s)       ((s) == APR_EBADDATE)
+/** APR was given an invalid socket */
+#define APR_STATUS_IS_EINVALSOCK(s)     ((s) == APR_EINVALSOCK)
+/** APR was not given a process structure */
+#define APR_STATUS_IS_ENOPROC(s)        ((s) == APR_ENOPROC)
+/** APR was not given a time structure */
+#define APR_STATUS_IS_ENOTIME(s)        ((s) == APR_ENOTIME)
+/** APR was not given a directory structure */
+#define APR_STATUS_IS_ENODIR(s)         ((s) == APR_ENODIR)
+/** APR was not given a lock structure */
+#define APR_STATUS_IS_ENOLOCK(s)        ((s) == APR_ENOLOCK)
+/** APR was not given a poll structure */
+#define APR_STATUS_IS_ENOPOLL(s)        ((s) == APR_ENOPOLL)
+/** APR was not given a socket */
+#define APR_STATUS_IS_ENOSOCKET(s)      ((s) == APR_ENOSOCKET)
+/** APR was not given a thread structure */
+#define APR_STATUS_IS_ENOTHREAD(s)      ((s) == APR_ENOTHREAD)
+/** APR was not given a thread key structure */
+#define APR_STATUS_IS_ENOTHDKEY(s)      ((s) == APR_ENOTHDKEY)
+/** Generic Error which can not be put into another spot */
+#define APR_STATUS_IS_EGENERAL(s)       ((s) == APR_EGENERAL)
+/** There is no more shared memory available */
+#define APR_STATUS_IS_ENOSHMAVAIL(s)    ((s) == APR_ENOSHMAVAIL)
+/** The specified IP address is invalid */
+#define APR_STATUS_IS_EBADIP(s)         ((s) == APR_EBADIP)
+/** The specified netmask is invalid */
+#define APR_STATUS_IS_EBADMASK(s)       ((s) == APR_EBADMASK)
+/* empty slot: +18 */
+/** 
+ * APR was unable to open the dso object.  
+ * For more information call apr_dso_error().
+ */
+#if defined(WIN32)
+#define APR_STATUS_IS_EDSOOPEN(s)       ((s) == APR_EDSOOPEN \
+                       || APR_TO_OS_ERROR(s) == ERROR_MOD_NOT_FOUND)
+#elif defined(OS2)
+#define APR_STATUS_IS_EDSOOPEN(s)       ((s) == APR_EDSOOPEN \
+                       || APR_TO_OS_ERROR(s) == ERROR_FILE_NOT_FOUND)
+#else
+#define APR_STATUS_IS_EDSOOPEN(s)       ((s) == APR_EDSOOPEN)
+#endif
+/** The given path was absolute. */
+#define APR_STATUS_IS_EABSOLUTE(s)      ((s) == APR_EABSOLUTE)
+/** The given path was relative. */
+#define APR_STATUS_IS_ERELATIVE(s)      ((s) == APR_ERELATIVE)
+/** The given path was neither relative nor absolute. */
+#define APR_STATUS_IS_EINCOMPLETE(s)    ((s) == APR_EINCOMPLETE)
+/** The given path was above the root path. */
+#define APR_STATUS_IS_EABOVEROOT(s)     ((s) == APR_EABOVEROOT)
+/** The given path was bad. */
+#define APR_STATUS_IS_EBADPATH(s)       ((s) == APR_EBADPATH)
+/** The given path contained wildcards. */
+#define APR_STATUS_IS_EPATHWILD(s)      ((s) == APR_EPATHWILD)
+/** Could not find the requested symbol.
+ * For more information call apr_dso_error().
+ */
+#if defined(WIN32)
+#define APR_STATUS_IS_ESYMNOTFOUND(s)   ((s) == APR_ESYMNOTFOUND \
+                       || APR_TO_OS_ERROR(s) == ERROR_PROC_NOT_FOUND)
+#elif defined(OS2)
+#define APR_STATUS_IS_ESYMNOTFOUND(s)   ((s) == APR_ESYMNOTFOUND \
+                       || APR_TO_OS_ERROR(s) == ERROR_INVALID_NAME)
+#else
+#define APR_STATUS_IS_ESYMNOTFOUND(s)   ((s) == APR_ESYMNOTFOUND)
+#endif
+/** The given process was not recognized by APR. */
+#define APR_STATUS_IS_EPROC_UNKNOWN(s)  ((s) == APR_EPROC_UNKNOWN)
+/** APR could not gather enough entropy to continue. */
+#define APR_STATUS_IS_ENOTENOUGHENTROPY(s) ((s) == APR_ENOTENOUGHENTROPY)
 
-/* APR STATUS VALUES */
+/** @} */
+
+/** 
+ * @addtogroup APR_Error
+ * @{
+ */
+/** @see APR_STATUS_IS_INCHILD */
 #define APR_INCHILD        (APR_OS_START_STATUS + 1)
+/** @see APR_STATUS_IS_INPARENT */
 #define APR_INPARENT       (APR_OS_START_STATUS + 2)
+/** @see APR_STATUS_IS_DETACH */
 #define APR_DETACH         (APR_OS_START_STATUS + 3)
+/** @see APR_STATUS_IS_NOTDETACH */
 #define APR_NOTDETACH      (APR_OS_START_STATUS + 4)
+/** @see APR_STATUS_IS_CHILD_DONE */
 #define APR_CHILD_DONE     (APR_OS_START_STATUS + 5)
+/** @see APR_STATUS_IS_CHILD_NOTDONE */
 #define APR_CHILD_NOTDONE  (APR_OS_START_STATUS + 6)
+/** @see APR_STATUS_IS_TIMEUP */
 #define APR_TIMEUP         (APR_OS_START_STATUS + 7)
-/* empty slot: +8 */
+/** @see APR_STATUS_IS_INCOMPLETE */
+#define APR_INCOMPLETE     (APR_OS_START_STATUS + 8)
 /* empty slot: +9 */
 /* empty slot: +10 */
 /* empty slot: +11 */
+/** @see APR_STATUS_IS_BADCH */
 #define APR_BADCH          (APR_OS_START_STATUS + 12)
+/** @see APR_STATUS_IS_BADARG */
 #define APR_BADARG         (APR_OS_START_STATUS + 13)
+/** @see APR_STATUS_IS_EOF */
 #define APR_EOF            (APR_OS_START_STATUS + 14)
+/** @see APR_STATUS_IS_NOTFOUND */
 #define APR_NOTFOUND       (APR_OS_START_STATUS + 15)
 /* empty slot: +16 */
 /* empty slot: +17 */
 /* empty slot: +18 */
+/** @see APR_STATUS_IS_ANONYMOUS */
 #define APR_ANONYMOUS      (APR_OS_START_STATUS + 19)
+/** @see APR_STATUS_IS_FILEBASED */
 #define APR_FILEBASED      (APR_OS_START_STATUS + 20)
+/** @see APR_STATUS_IS_KEYBASED */
 #define APR_KEYBASED       (APR_OS_START_STATUS + 21)
-
-/* A simple value to be used to initialze a status variable. */
+/** @see APR_STATUS_IS_EINIT */
 #define APR_EINIT          (APR_OS_START_STATUS + 22)  
-
-/* Not implemented either because we haven't gotten to it yet, or 
- * because it is not possible to do correctly.  
- */
+/** @see APR_STATUS_IS_ENOTIMPL */
 #define APR_ENOTIMPL       (APR_OS_START_STATUS + 23)
+/** @see APR_STATUS_IS_EMISMATCH */
+#define APR_EMISMATCH      (APR_OS_START_STATUS + 24)
+/** @see APR_STATUS_IS_EBUSY */
+#define APR_EBUSY          (APR_OS_START_STATUS + 25)
+/** @} */
 
-/* Passwords do not match.
+/** 
+ * @addtogroup APR_STATUS_IS
+ * @{
  */
-#define APR_EMISMATCH      (APR_OS_START_STATUS + 24)
+/** 
+ * Program is currently executing in the child 
+ * @warning
+ * always use this test, as platform-specific variances may meet this
+ * more than one error code */
+#define APR_STATUS_IS_INCHILD(s)        ((s) == APR_INCHILD)
+/** 
+ * Program is currently executing in the parent 
+ * @warning
+ * always use this test, as platform-specific variances may meet this
+ * more than one error code 
+ */
+#define APR_STATUS_IS_INPARENT(s)       ((s) == APR_INPARENT)
+/** 
+ * The thread is detached 
+ * @warning
+ * always use this test, as platform-specific variances may meet this
+ * more than one error code 
+ */
+#define APR_STATUS_IS_DETACH(s)         ((s) == APR_DETACH)
+/** 
+ * The thread is not detached 
+ * @warning
+ * always use this test, as platform-specific variances may meet this
+ * more than one error code 
+ */
+#define APR_STATUS_IS_NOTDETACH(s)      ((s) == APR_NOTDETACH)
+/** 
+ * The child has finished executing
+ * @warning
+ * always use this test, as platform-specific variances may meet this
+ * more than one error code 
+ */
+#define APR_STATUS_IS_CHILD_DONE(s)     ((s) == APR_CHILD_DONE)
+/** 
+ * The child has not finished executing
+ * @warning
+ * always use this test, as platform-specific variances may meet this
+ * more than one error code 
+ */
+#define APR_STATUS_IS_CHILD_NOTDONE(s)  ((s) == APR_CHILD_NOTDONE)
+/** 
+ * The operation did not finish before the timeout
+ * @warning
+ * always use this test, as platform-specific variances may meet this
+ * more than one error code 
+ */
+#define APR_STATUS_IS_TIMEUP(s)         ((s) == APR_TIMEUP)
+/** 
+ * The operation was incomplete although some processing was performed
+ * and the results are partially valid.
+ * @warning
+ * always use this test, as platform-specific variances may meet this
+ * more than one error code 
+ */
+#define APR_STATUS_IS_INCOMPLETE(s)     ((s) == APR_INCOMPLETE)
+/* empty slot: +9 */
+/* empty slot: +10 */
+/* empty slot: +11 */
+/** 
+ * Getopt found an option not in the option string
+ * @warning
+ * always use this test, as platform-specific variances may meet this
+ * more than one error code 
+ */
+#define APR_STATUS_IS_BADCH(s)          ((s) == APR_BADCH)
+/** 
+ * Getopt found an option not in the option string and an argument was 
+ * specified in the option string
+ * @warning
+ * always use this test, as platform-specific variances may meet this
+ * more than one error code 
+ */
+#define APR_STATUS_IS_BADARG(s)         ((s) == APR_BADARG)
+/** 
+ * APR has encountered the end of the file
+ * @warning
+ * always use this test, as platform-specific variances may meet this
+ * more than one error code 
+ */
+#define APR_STATUS_IS_EOF(s)            ((s) == APR_EOF)
+/** 
+ * APR was unable to find the socket in the poll structure
+ * @warning
+ * always use this test, as platform-specific variances may meet this
+ * more than one error code 
+ */
+#define APR_STATUS_IS_NOTFOUND(s)       ((s) == APR_NOTFOUND)
+/* empty slot: +16 */
+/* empty slot: +17 */
+/* empty slot: +18 */
+/** 
+ * APR is using anonymous shared memory
+ * @warning
+ * always use this test, as platform-specific variances may meet this
+ * more than one error code 
+ */
+#define APR_STATUS_IS_ANONYMOUS(s)      ((s) == APR_ANONYMOUS)
+/** 
+ * APR is using a file name as the key to the shared memory
+ * @warning
+ * always use this test, as platform-specific variances may meet this
+ * more than one error code 
+ */
+#define APR_STATUS_IS_FILEBASED(s)      ((s) == APR_FILEBASED)
+/** 
+ * APR is using a shared key as the key to the shared memory
+ * @warning
+ * always use this test, as platform-specific variances may meet this
+ * more than one error code 
+ */
+#define APR_STATUS_IS_KEYBASED(s)       ((s) == APR_KEYBASED)
+/** 
+ * Ininitalizer value.  If no option has been found, but 
+ * the status variable requires a value, this should be used
+ * @warning
+ * always use this test, as platform-specific variances may meet this
+ * more than one error code 
+ */
+#define APR_STATUS_IS_EINIT(s)          ((s) == APR_EINIT)
+/** 
+ * The APR function has not been implemented on this 
+ * platform, either because nobody has gotten to it yet, 
+ * or the function is impossible on this platform.
+ * @warning
+ * always use this test, as platform-specific variances may meet this
+ * more than one error code 
+ */
+#define APR_STATUS_IS_ENOTIMPL(s)       ((s) == APR_ENOTIMPL)
+/** 
+ * Two passwords do not match.
+ * @warning
+ * always use this test, as platform-specific variances may meet this
+ * more than one error code 
+ */
+#define APR_STATUS_IS_EMISMATCH(s)      ((s) == APR_EMISMATCH)
+/** 
+ * The given lock was busy
+ * @warning always use this test, as platform-specific variances may meet this
+ * more than one error code 
+ */
+#define APR_STATUS_IS_EBUSY(s)          ((s) == APR_EBUSY)
 
+/** @} */
 
+/** 
+ * @addtogroup APR_Error APR Error Values
+ * @{
+ */
 /* APR CANONICAL ERROR VALUES */
+/** @see APR_STATUS_IS_EACCES */
 #ifdef EACCES
 #define APR_EACCES EACCES
 #else
 #define APR_EACCES         (APR_OS_START_CANONERR + 1)
 #endif
 
+/** @see APR_STATUS_IS_EEXIST */
 #ifdef EEXIST
 #define APR_EEXIST EEXIST
 #else
 #define APR_EEXIST         (APR_OS_START_CANONERR + 2)
 #endif
 
+/** @see APR_STATUS_IS_ENAMETOOLONG */
 #ifdef ENAMETOOLONG
 #define APR_ENAMETOOLONG ENAMETOOLONG
 #else
 #define APR_ENAMETOOLONG   (APR_OS_START_CANONERR + 3)
 #endif
 
+/** @see APR_STATUS_IS_ENOENT */
 #ifdef ENOENT
 #define APR_ENOENT ENOENT
 #else
 #define APR_ENOENT         (APR_OS_START_CANONERR + 4)
 #endif
 
+/** @see APR_STATUS_IS_ENOTDIR */
 #ifdef ENOTDIR
 #define APR_ENOTDIR ENOTDIR
 #else
 #define APR_ENOTDIR        (APR_OS_START_CANONERR + 5)
 #endif
 
+/** @see APR_STATUS_IS_ENOSPC */
 #ifdef ENOSPC
 #define APR_ENOSPC ENOSPC
 #else
 #define APR_ENOSPC         (APR_OS_START_CANONERR + 6)
 #endif
 
-#ifdef ENONOMEM
+/** @see APR_STATUS_IS_ENOMEM */
+#ifdef ENOMEM
 #define APR_ENOMEM ENOMEM
 #else
 #define APR_ENOMEM         (APR_OS_START_CANONERR + 7)
 #endif
 
+/** @see APR_STATUS_IS_EMFILE */
 #ifdef EMFILE
 #define APR_EMFILE EMFILE
 #else
 #define APR_EMFILE         (APR_OS_START_CANONERR + 8)
 #endif
 
+/** @see APR_STATUS_IS_ENFILE */
 #ifdef ENFILE
 #define APR_ENFILE ENFILE
 #else
 #define APR_ENFILE         (APR_OS_START_CANONERR + 9)
 #endif
 
+/** @see APR_STATUS_IS_EBADF */
 #ifdef EBADF
 #define APR_EBADF EBADF
 #else
 #define APR_EBADF          (APR_OS_START_CANONERR + 10)
 #endif
 
+/** @see APR_STATUS_IS_EINVAL */
 #ifdef EINVAL
 #define APR_EINVAL EINVAL
 #else
 #define APR_EINVAL         (APR_OS_START_CANONERR + 11)
 #endif
 
+/** @see APR_STATUS_IS_ESPIPE */
 #ifdef ESPIPE
 #define APR_ESPIPE ESPIPE
 #else
 #define APR_ESPIPE         (APR_OS_START_CANONERR + 12)
 #endif
 
+/** 
+ * @see APR_STATUS_IS_EAGAIN 
+ * @warning use APR_STATUS_IS_EAGAIN instead of just testing this value
+ */
 #ifdef EAGAIN
 #define APR_EAGAIN EAGAIN
+#elif defined(EWOULDBLOCK)
+#define APR_EAGAIN EWOULDBLOCK
 #else
 #define APR_EAGAIN         (APR_OS_START_CANONERR + 13)
 #endif
 
+/** @see APR_STATUS_IS_EINTR */
 #ifdef EINTR
 #define APR_EINTR EINTR
 #else
 #define APR_EINTR          (APR_OS_START_CANONERR + 14)
 #endif
 
+/** @see APR_STATUS_IS_ENOTSOCK */
 #ifdef ENOTSOCK
 #define APR_ENOTSOCK ENOTSOCK
 #else
 #define APR_ENOTSOCK       (APR_OS_START_CANONERR + 15)
 #endif
 
+/** @see APR_STATUS_IS_ECONNREFUSED */
 #ifdef ECONNREFUSED
 #define APR_ECONNREFUSED ECONNREFUSED
 #else
 #define APR_ECONNREFUSED   (APR_OS_START_CANONERR + 16)
 #endif
 
+/** @see APR_STATUS_IS_EINPROGRESS */
 #ifdef EINPROGRESS
 #define APR_EINPROGRESS EINPROGRESS
 #else
 #define APR_EINPROGRESS    (APR_OS_START_CANONERR + 17)
 #endif
 
+/** 
+ * @see APR_STATUS_IS_ECONNABORTED
+ * @warning use APR_STATUS_IS_ECONNABORTED instead of just testing this value
+ */
+
+#ifdef ECONNABORTED
+#define APR_ECONNABORTED ECONNABORTED
+#else
+#define APR_ECONNABORTED   (APR_OS_START_CANONERR + 18)
+#endif
+
+/** @see APR_STATUS_IS_ECONNRESET */
+#ifdef ECONNRESET
+#define APR_ECONNRESET ECONNRESET
+#else
+#define APR_ECONNRESET     (APR_OS_START_CANONERR + 19)
+#endif
+
+/** @see APR_STATUS_IS_ETIMEDOUT 
+ *  @deprecated */
+#ifdef ETIMEDOUT
+#define APR_ETIMEDOUT ETIMEDOUT
+#else
+#define APR_ETIMEDOUT      (APR_OS_START_CANONERR + 20)
+#endif
+
+/** @see APR_STATUS_IS_EHOSTUNREACH */
+#ifdef EHOSTUNREACH
+#define APR_EHOSTUNREACH EHOSTUNREACH
+#else
+#define APR_EHOSTUNREACH   (APR_OS_START_CANONERR + 21)
+#endif
+
+/** @see APR_STATUS_IS_ENETUNREACH */
+#ifdef ENETUNREACH
+#define APR_ENETUNREACH ENETUNREACH
+#else
+#define APR_ENETUNREACH    (APR_OS_START_CANONERR + 22)
+#endif
+
+/** @see APR_STATUS_IS_EFTYPE */
+#ifdef EFTYPE
+#define APR_EFTYPE EFTYPE
+#else
+#define APR_EFTYPE        (APR_OS_START_CANONERR + 23)
+#endif
+
+/** @see APR_STATUS_IS_EPIPE */
+#ifdef EPIPE
+#define APR_EPIPE EPIPE
+#else
+#define APR_EPIPE         (APR_OS_START_CANONERR + 24)
+#endif
+
+/** @see APR_STATUS_IS_EXDEV */
+#ifdef EXDEV
+#define APR_EXDEV EXDEV
+#else
+#define APR_EXDEV         (APR_OS_START_CANONERR + 25)
+#endif
+
+/** @see APR_STATUS_IS_ENOTEMPTY */
+#ifdef ENOTEMPTY
+#define APR_ENOTEMPTY ENOTEMPTY
+#else
+#define APR_ENOTEMPTY     (APR_OS_START_CANONERR + 26)
+#endif
+
+/** @see APR_STATUS_IS_EAFNOSUPPORT */
+#ifdef EAFNOSUPPORT
+#define APR_EAFNOSUPPORT EAFNOSUPPORT
+#else
+#define APR_EAFNOSUPPORT  (APR_OS_START_CANONERR + 27)
+#endif
+
+/** @see APR_STATUS_IS_EOPNOTSUPP */
+#ifdef EOPNOTSUPP
+#define APR_EOPNOTSUPP EOPNOTSUPP
+#else
+#define APR_EOPNOTSUPP    (APR_OS_START_CANONERR + 28)
+#endif
+
+/** @see APR_STATUS_IS_ERANGE */
+#ifdef ERANGE
+#define APR_ERANGE ERANGE
+#else
+#define APR_ERANGE          (APR_OS_START_CANONERR + 29)
+#endif
+
+/** @} */
+
+#if defined(OS2) && !defined(DOXYGEN)
+
+#define APR_FROM_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e + APR_OS_START_SYSERR)
+#define APR_TO_OS_ERROR(e)   (e == 0 ? APR_SUCCESS : e - APR_OS_START_SYSERR)
+
+#define INCL_DOSERRORS
+#define INCL_DOS
+
+/* Leave these undefined.
+ * OS2 doesn't rely on the errno concept.
+ * The API calls always return a result codes which
+ * should be filtered through APR_FROM_OS_ERROR().
+ *
+ * #define apr_get_os_error()   (APR_FROM_OS_ERROR(GetLastError()))
+ * #define apr_set_os_error(e)  (SetLastError(APR_TO_OS_ERROR(e)))
+ */
+
+/* A special case, only socket calls require this;
+ */
+#define apr_get_netos_error()   (APR_FROM_OS_ERROR(errno))
+#define apr_set_netos_error(e)  (errno = APR_TO_OS_ERROR(e))
+
+/* These can't sit in a private header, so in spite of the extra size, 
+ * they need to be made available here.
+ */
+#define SOCBASEERR              10000
+#define SOCEPERM                (SOCBASEERR+1)             /* Not owner */
+#define SOCESRCH                (SOCBASEERR+3)             /* No such process */
+#define SOCEINTR                (SOCBASEERR+4)             /* Interrupted system call */
+#define SOCENXIO                (SOCBASEERR+6)             /* No such device or address */
+#define SOCEBADF                (SOCBASEERR+9)             /* Bad file number */
+#define SOCEACCES               (SOCBASEERR+13)            /* Permission denied */
+#define SOCEFAULT               (SOCBASEERR+14)            /* Bad address */
+#define SOCEINVAL               (SOCBASEERR+22)            /* Invalid argument */
+#define SOCEMFILE               (SOCBASEERR+24)            /* Too many open files */
+#define SOCEPIPE                (SOCBASEERR+32)            /* Broken pipe */
+#define SOCEOS2ERR              (SOCBASEERR+100)           /* OS/2 Error */
+#define SOCEWOULDBLOCK          (SOCBASEERR+35)            /* Operation would block */
+#define SOCEINPROGRESS          (SOCBASEERR+36)            /* Operation now in progress */
+#define SOCEALREADY             (SOCBASEERR+37)            /* Operation already in progress */
+#define SOCENOTSOCK             (SOCBASEERR+38)            /* Socket operation on non-socket */
+#define SOCEDESTADDRREQ         (SOCBASEERR+39)            /* Destination address required */
+#define SOCEMSGSIZE             (SOCBASEERR+40)            /* Message too long */
+#define SOCEPROTOTYPE           (SOCBASEERR+41)            /* Protocol wrong type for socket */
+#define SOCENOPROTOOPT          (SOCBASEERR+42)            /* Protocol not available */
+#define SOCEPROTONOSUPPORT      (SOCBASEERR+43)            /* Protocol not supported */
+#define SOCESOCKTNOSUPPORT      (SOCBASEERR+44)            /* Socket type not supported */
+#define SOCEOPNOTSUPP           (SOCBASEERR+45)            /* Operation not supported on socket */
+#define SOCEPFNOSUPPORT         (SOCBASEERR+46)            /* Protocol family not supported */
+#define SOCEAFNOSUPPORT         (SOCBASEERR+47)            /* Address family not supported by protocol family */
+#define SOCEADDRINUSE           (SOCBASEERR+48)            /* Address already in use */
+#define SOCEADDRNOTAVAIL        (SOCBASEERR+49)            /* Can't assign requested address */
+#define SOCENETDOWN             (SOCBASEERR+50)            /* Network is down */
+#define SOCENETUNREACH          (SOCBASEERR+51)            /* Network is unreachable */
+#define SOCENETRESET            (SOCBASEERR+52)            /* Network dropped connection on reset */
+#define SOCECONNABORTED         (SOCBASEERR+53)            /* Software caused connection abort */
+#define SOCECONNRESET           (SOCBASEERR+54)            /* Connection reset by peer */
+#define SOCENOBUFS              (SOCBASEERR+55)            /* No buffer space available */
+#define SOCEISCONN              (SOCBASEERR+56)            /* Socket is already connected */
+#define SOCENOTCONN             (SOCBASEERR+57)            /* Socket is not connected */
+#define SOCESHUTDOWN            (SOCBASEERR+58)            /* Can't send after socket shutdown */
+#define SOCETOOMANYREFS         (SOCBASEERR+59)            /* Too many references: can't splice */
+#define SOCETIMEDOUT            (SOCBASEERR+60)            /* Connection timed out */
+#define SOCECONNREFUSED         (SOCBASEERR+61)            /* Connection refused */
+#define SOCELOOP                (SOCBASEERR+62)            /* Too many levels of symbolic links */
+#define SOCENAMETOOLONG         (SOCBASEERR+63)            /* File name too long */
+#define SOCEHOSTDOWN            (SOCBASEERR+64)            /* Host is down */
+#define SOCEHOSTUNREACH         (SOCBASEERR+65)            /* No route to host */
+#define SOCENOTEMPTY            (SOCBASEERR+66)            /* Directory not empty */
+
+/* APR CANONICAL ERROR TESTS */
+#define APR_STATUS_IS_EACCES(s)         ((s) == APR_EACCES \
+                || (s) == APR_OS_START_SYSERR + ERROR_ACCESS_DENIED \
+                || (s) == APR_OS_START_SYSERR + ERROR_SHARING_VIOLATION)
+#define APR_STATUS_IS_EEXIST(s)         ((s) == APR_EEXIST \
+                || (s) == APR_OS_START_SYSERR + ERROR_OPEN_FAILED \
+                || (s) == APR_OS_START_SYSERR + ERROR_FILE_EXISTS \
+                || (s) == APR_OS_START_SYSERR + ERROR_ALREADY_EXISTS \
+                || (s) == APR_OS_START_SYSERR + ERROR_ACCESS_DENIED)
+#define APR_STATUS_IS_ENAMETOOLONG(s)   ((s) == APR_ENAMETOOLONG \
+                || (s) == APR_OS_START_SYSERR + ERROR_FILENAME_EXCED_RANGE \
+                || (s) == APR_OS_START_SYSERR + SOCENAMETOOLONG)
+#define APR_STATUS_IS_ENOENT(s)         ((s) == APR_ENOENT \
+                || (s) == APR_OS_START_SYSERR + ERROR_FILE_NOT_FOUND \
+                || (s) == APR_OS_START_SYSERR + ERROR_PATH_NOT_FOUND \
+                || (s) == APR_OS_START_SYSERR + ERROR_NO_MORE_FILES \
+                || (s) == APR_OS_START_SYSERR + ERROR_OPEN_FAILED)
+#define APR_STATUS_IS_ENOTDIR(s)        ((s) == APR_ENOTDIR)
+#define APR_STATUS_IS_ENOSPC(s)         ((s) == APR_ENOSPC \
+                || (s) == APR_OS_START_SYSERR + ERROR_DISK_FULL)
+#define APR_STATUS_IS_ENOMEM(s)         ((s) == APR_ENOMEM)
+#define APR_STATUS_IS_EMFILE(s)         ((s) == APR_EMFILE \
+                || (s) == APR_OS_START_SYSERR + ERROR_TOO_MANY_OPEN_FILES)
+#define APR_STATUS_IS_ENFILE(s)         ((s) == APR_ENFILE)
+#define APR_STATUS_IS_EBADF(s)          ((s) == APR_EBADF \
+                || (s) == APR_OS_START_SYSERR + ERROR_INVALID_HANDLE)
+#define APR_STATUS_IS_EINVAL(s)         ((s) == APR_EINVAL \
+                || (s) == APR_OS_START_SYSERR + ERROR_INVALID_PARAMETER \
+                || (s) == APR_OS_START_SYSERR + ERROR_INVALID_FUNCTION)
+#define APR_STATUS_IS_ESPIPE(s)         ((s) == APR_ESPIPE \
+                || (s) == APR_OS_START_SYSERR + ERROR_NEGATIVE_SEEK)
+#define APR_STATUS_IS_EAGAIN(s)         ((s) == APR_EAGAIN \
+                || (s) == APR_OS_START_SYSERR + ERROR_NO_DATA \
+                || (s) == APR_OS_START_SYSERR + SOCEWOULDBLOCK \
+                || (s) == APR_OS_START_SYSERR + ERROR_LOCK_VIOLATION)
+#define APR_STATUS_IS_EINTR(s)          ((s) == APR_EINTR \
+                || (s) == APR_OS_START_SYSERR + SOCEINTR)
+#define APR_STATUS_IS_ENOTSOCK(s)       ((s) == APR_ENOTSOCK \
+                || (s) == APR_OS_START_SYSERR + SOCENOTSOCK)
+#define APR_STATUS_IS_ECONNREFUSED(s)   ((s) == APR_ECONNREFUSED \
+                || (s) == APR_OS_START_SYSERR + SOCECONNREFUSED)
+#define APR_STATUS_IS_EINPROGRESS(s)    ((s) == APR_EINPROGRESS \
+                || (s) == APR_OS_START_SYSERR + SOCEINPROGRESS)
+#define APR_STATUS_IS_ECONNABORTED(s)   ((s) == APR_ECONNABORTED \
+                || (s) == APR_OS_START_SYSERR + SOCECONNABORTED)
+#define APR_STATUS_IS_ECONNRESET(s)     ((s) == APR_ECONNRESET \
+                || (s) == APR_OS_START_SYSERR + SOCECONNRESET)
+/* XXX deprecated */
+#define APR_STATUS_IS_ETIMEDOUT(s)         ((s) == APR_ETIMEDOUT \
+                || (s) == APR_OS_START_SYSERR + SOCETIMEDOUT)    
+#undef APR_STATUS_IS_TIMEUP
+#define APR_STATUS_IS_TIMEUP(s)         ((s) == APR_TIMEUP \
+                || (s) == APR_OS_START_SYSERR + SOCETIMEDOUT)    
+#define APR_STATUS_IS_EHOSTUNREACH(s)   ((s) == APR_EHOSTUNREACH \
+                || (s) == APR_OS_START_SYSERR + SOCEHOSTUNREACH)
+#define APR_STATUS_IS_ENETUNREACH(s)    ((s) == APR_ENETUNREACH \
+                || (s) == APR_OS_START_SYSERR + SOCENETUNREACH)
+#define APR_STATUS_IS_EFTYPE(s)         ((s) == APR_EFTYPE)
+#define APR_STATUS_IS_EPIPE(s)          ((s) == APR_EPIPE \
+                || (s) == APR_OS_START_SYSERR + ERROR_BROKEN_PIPE \
+                || (s) == APR_OS_START_SYSERR + SOCEPIPE)
+#define APR_STATUS_IS_EXDEV(s)          ((s) == APR_EXDEV \
+                || (s) == APR_OS_START_SYSERR + ERROR_NOT_SAME_DEVICE)
+#define APR_STATUS_IS_ENOTEMPTY(s)      ((s) == APR_ENOTEMPTY \
+                || (s) == APR_OS_START_SYSERR + ERROR_DIR_NOT_EMPTY \
+                || (s) == APR_OS_START_SYSERR + ERROR_ACCESS_DENIED)
+#define APR_STATUS_IS_EAFNOSUPPORT(s)   ((s) == APR_AFNOSUPPORT \
+                || (s) == APR_OS_START_SYSERR + SOCEAFNOSUPPORT)
+#define APR_STATUS_IS_EOPNOTSUPP(s)     ((s) == APR_EOPNOTSUPP \
+                || (s) == APR_OS_START_SYSERR + SOCEOPNOTSUPP)
+#define APR_STATUS_IS_ERANGE(s)         ((s) == APR_ERANGE)
+
+/*
+    Sorry, too tired to wrap this up for OS2... feel free to
+    fit the following into their best matches.
+
+    { ERROR_NO_SIGNAL_SENT,     ESRCH           },
+    { SOCEALREADY,              EALREADY        },
+    { SOCEDESTADDRREQ,          EDESTADDRREQ    },
+    { SOCEMSGSIZE,              EMSGSIZE        },
+    { SOCEPROTOTYPE,            EPROTOTYPE      },
+    { SOCENOPROTOOPT,           ENOPROTOOPT     },
+    { SOCEPROTONOSUPPORT,       EPROTONOSUPPORT },
+    { SOCESOCKTNOSUPPORT,       ESOCKTNOSUPPORT },
+    { SOCEPFNOSUPPORT,          EPFNOSUPPORT    },
+    { SOCEADDRINUSE,            EADDRINUSE      },
+    { SOCEADDRNOTAVAIL,         EADDRNOTAVAIL   },
+    { SOCENETDOWN,              ENETDOWN        },
+    { SOCENETRESET,             ENETRESET       },
+    { SOCENOBUFS,               ENOBUFS         },
+    { SOCEISCONN,               EISCONN         },
+    { SOCENOTCONN,              ENOTCONN        },
+    { SOCESHUTDOWN,             ESHUTDOWN       },
+    { SOCETOOMANYREFS,          ETOOMANYREFS    },
+    { SOCELOOP,                 ELOOP           },
+    { SOCEHOSTDOWN,             EHOSTDOWN       },
+    { SOCENOTEMPTY,             ENOTEMPTY       },
+    { SOCEPIPE,                 EPIPE           }
+*/
+
+#elif defined(WIN32) && !defined(DOXYGEN) /* !defined(OS2) */
+
+#define APR_FROM_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e + APR_OS_START_SYSERR)
+#define APR_TO_OS_ERROR(e)   (e == 0 ? APR_SUCCESS : e - APR_OS_START_SYSERR)
+
+#define apr_get_os_error()   (APR_FROM_OS_ERROR(GetLastError()))
+#define apr_set_os_error(e)  (SetLastError(APR_TO_OS_ERROR(e)))
+
+/* A special case, only socket calls require this:
+ */
+#define apr_get_netos_error()   (APR_FROM_OS_ERROR(WSAGetLastError()))
+#define apr_set_netos_error(e)   (WSASetLastError(APR_TO_OS_ERROR(e)))
+
+/* APR CANONICAL ERROR TESTS */
+#define APR_STATUS_IS_EACCES(s)         ((s) == APR_EACCES \
+                || (s) == APR_OS_START_SYSERR + ERROR_ACCESS_DENIED \
+                || (s) == APR_OS_START_SYSERR + ERROR_CANNOT_MAKE \
+                || (s) == APR_OS_START_SYSERR + ERROR_CURRENT_DIRECTORY \
+                || (s) == APR_OS_START_SYSERR + ERROR_DRIVE_LOCKED \
+                || (s) == APR_OS_START_SYSERR + ERROR_FAIL_I24 \
+                || (s) == APR_OS_START_SYSERR + ERROR_LOCK_VIOLATION \
+                || (s) == APR_OS_START_SYSERR + ERROR_LOCK_FAILED \
+                || (s) == APR_OS_START_SYSERR + ERROR_NOT_LOCKED \
+                || (s) == APR_OS_START_SYSERR + ERROR_NETWORK_ACCESS_DENIED \
+                || (s) == APR_OS_START_SYSERR + ERROR_SHARING_VIOLATION)
+#define APR_STATUS_IS_EEXIST(s)         ((s) == APR_EEXIST \
+                || (s) == APR_OS_START_SYSERR + ERROR_FILE_EXISTS \
+                || (s) == APR_OS_START_SYSERR + ERROR_ALREADY_EXISTS)
+#define APR_STATUS_IS_ENAMETOOLONG(s)   ((s) == APR_ENAMETOOLONG \
+                || (s) == APR_OS_START_SYSERR + ERROR_FILENAME_EXCED_RANGE \
+                || (s) == APR_OS_START_SYSERR + WSAENAMETOOLONG)
+#define APR_STATUS_IS_ENOENT(s)         ((s) == APR_ENOENT \
+                || (s) == APR_OS_START_SYSERR + ERROR_FILE_NOT_FOUND \
+                || (s) == APR_OS_START_SYSERR + ERROR_PATH_NOT_FOUND \
+                || (s) == APR_OS_START_SYSERR + ERROR_OPEN_FAILED \
+                || (s) == APR_OS_START_SYSERR + ERROR_NO_MORE_FILES)
+#define APR_STATUS_IS_ENOTDIR(s)        ((s) == APR_ENOTDIR \
+                || (s) == APR_OS_START_SYSERR + ERROR_PATH_NOT_FOUND \
+                || (s) == APR_OS_START_SYSERR + ERROR_BAD_NETPATH \
+                || (s) == APR_OS_START_SYSERR + ERROR_BAD_NET_NAME \
+                || (s) == APR_OS_START_SYSERR + ERROR_BAD_PATHNAME \
+                || (s) == APR_OS_START_SYSERR + ERROR_INVALID_DRIVE \
+                || (s) == APR_OS_START_SYSERR + ERROR_DIRECTORY)
+#define APR_STATUS_IS_ENOSPC(s)         ((s) == APR_ENOSPC \
+                || (s) == APR_OS_START_SYSERR + ERROR_DISK_FULL)
+#define APR_STATUS_IS_ENOMEM(s)         ((s) == APR_ENOMEM \
+                || (s) == APR_OS_START_SYSERR + ERROR_ARENA_TRASHED \
+                || (s) == APR_OS_START_SYSERR + ERROR_NOT_ENOUGH_MEMORY \
+                || (s) == APR_OS_START_SYSERR + ERROR_INVALID_BLOCK \
+                || (s) == APR_OS_START_SYSERR + ERROR_NOT_ENOUGH_QUOTA \
+                || (s) == APR_OS_START_SYSERR + ERROR_OUTOFMEMORY)
+#define APR_STATUS_IS_EMFILE(s)         ((s) == APR_EMFILE \
+                || (s) == APR_OS_START_SYSERR + ERROR_TOO_MANY_OPEN_FILES)
+#define APR_STATUS_IS_ENFILE(s)         ((s) == APR_ENFILE)
+#define APR_STATUS_IS_EBADF(s)          ((s) == APR_EBADF \
+                || (s) == APR_OS_START_SYSERR + ERROR_INVALID_HANDLE \
+                || (s) == APR_OS_START_SYSERR + ERROR_INVALID_TARGET_HANDLE)
+#define APR_STATUS_IS_EINVAL(s)         ((s) == APR_EINVAL \
+                || (s) == APR_OS_START_SYSERR + ERROR_INVALID_ACCESS \
+                || (s) == APR_OS_START_SYSERR + ERROR_INVALID_DATA \
+                || (s) == APR_OS_START_SYSERR + ERROR_INVALID_FUNCTION \
+                || (s) == APR_OS_START_SYSERR + ERROR_INVALID_HANDLE \
+                || (s) == APR_OS_START_SYSERR + ERROR_INVALID_PARAMETER \
+                || (s) == APR_OS_START_SYSERR + ERROR_NEGATIVE_SEEK)
+#define APR_STATUS_IS_ESPIPE(s)         ((s) == APR_ESPIPE \
+                || (s) == APR_OS_START_SYSERR + ERROR_SEEK_ON_DEVICE \
+                || (s) == APR_OS_START_SYSERR + ERROR_NEGATIVE_SEEK)
+#define APR_STATUS_IS_EAGAIN(s)         ((s) == APR_EAGAIN \
+                || (s) == APR_OS_START_SYSERR + ERROR_NO_DATA \
+                || (s) == APR_OS_START_SYSERR + ERROR_NO_PROC_SLOTS \
+                || (s) == APR_OS_START_SYSERR + ERROR_NESTING_NOT_ALLOWED \
+                || (s) == APR_OS_START_SYSERR + ERROR_MAX_THRDS_REACHED \
+                || (s) == APR_OS_START_SYSERR + ERROR_LOCK_VIOLATION \
+                || (s) == APR_OS_START_SYSERR + WSAEWOULDBLOCK)
+#define APR_STATUS_IS_EINTR(s)          ((s) == APR_EINTR \
+                || (s) == APR_OS_START_SYSERR + WSAEINTR)
+#define APR_STATUS_IS_ENOTSOCK(s)       ((s) == APR_ENOTSOCK \
+                || (s) == APR_OS_START_SYSERR + WSAENOTSOCK)
+#define APR_STATUS_IS_ECONNREFUSED(s)   ((s) == APR_ECONNREFUSED \
+                || (s) == APR_OS_START_SYSERR + WSAECONNREFUSED)
+#define APR_STATUS_IS_EINPROGRESS(s)    ((s) == APR_EINPROGRESS \
+                || (s) == APR_OS_START_SYSERR + WSAEINPROGRESS)
+#define APR_STATUS_IS_ECONNABORTED(s)   ((s) == APR_ECONNABORTED \
+                || (s) == APR_OS_START_SYSERR + WSAECONNABORTED)
+#define APR_STATUS_IS_ECONNRESET(s)     ((s) == APR_ECONNRESET \
+                || (s) == APR_OS_START_SYSERR + ERROR_NETNAME_DELETED \
+                || (s) == APR_OS_START_SYSERR + WSAECONNRESET)
+/* XXX deprecated */
+#define APR_STATUS_IS_ETIMEDOUT(s)         ((s) == APR_ETIMEDOUT \
+                || (s) == APR_OS_START_SYSERR + WSAETIMEDOUT \
+                || (s) == APR_OS_START_SYSERR + WAIT_TIMEOUT)
+#undef APR_STATUS_IS_TIMEUP
+#define APR_STATUS_IS_TIMEUP(s)         ((s) == APR_TIMEUP \
+                || (s) == APR_OS_START_SYSERR + WSAETIMEDOUT \
+                || (s) == APR_OS_START_SYSERR + WAIT_TIMEOUT)
+#define APR_STATUS_IS_EHOSTUNREACH(s)   ((s) == APR_EHOSTUNREACH \
+                || (s) == APR_OS_START_SYSERR + WSAEHOSTUNREACH)
+#define APR_STATUS_IS_ENETUNREACH(s)    ((s) == APR_ENETUNREACH \
+                || (s) == APR_OS_START_SYSERR + WSAENETUNREACH)
+#define APR_STATUS_IS_EFTYPE(s)         ((s) == APR_EFTYPE \
+                || (s) == APR_OS_START_SYSERR + ERROR_EXE_MACHINE_TYPE_MISMATCH \
+                || (s) == APR_OS_START_SYSERR + ERROR_INVALID_DLL \
+                || (s) == APR_OS_START_SYSERR + ERROR_INVALID_MODULETYPE \
+                || (s) == APR_OS_START_SYSERR + ERROR_BAD_EXE_FORMAT \
+                || (s) == APR_OS_START_SYSERR + ERROR_INVALID_EXE_SIGNATURE \
+                || (s) == APR_OS_START_SYSERR + ERROR_FILE_CORRUPT \
+                || (s) == APR_OS_START_SYSERR + ERROR_BAD_FORMAT)
+#define APR_STATUS_IS_EPIPE(s)          ((s) == APR_EPIPE \
+                || (s) == APR_OS_START_SYSERR + ERROR_BROKEN_PIPE)
+#define APR_STATUS_IS_EXDEV(s)          ((s) == APR_EXDEV \
+                || (s) == APR_OS_START_SYSERR + ERROR_NOT_SAME_DEVICE)
+#define APR_STATUS_IS_ENOTEMPTY(s)      ((s) == APR_ENOTEMPTY \
+                || (s) == APR_OS_START_SYSERR + ERROR_DIR_NOT_EMPTY)
+#define APR_STATUS_IS_EAFNOSUPPORT(s)   ((s) == APR_EAFNOSUPPORT \
+                || (s) == APR_OS_START_SYSERR + WSAEAFNOSUPPORT)
+#define APR_STATUS_IS_EOPNOTSUPP(s)     ((s) == APR_EOPNOTSUPP \
+                || (s) == APR_OS_START_SYSERR + WSAEOPNOTSUPP)
+#define APR_STATUS_IS_ERANGE(s)         ((s) == APR_ERANGE)
+
+#elif defined(NETWARE) && defined(USE_WINSOCK) && !defined(DOXYGEN) /* !defined(OS2) && !defined(WIN32) */
+
+#define APR_FROM_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e + APR_OS_START_SYSERR)
+#define APR_TO_OS_ERROR(e)   (e == 0 ? APR_SUCCESS : e - APR_OS_START_SYSERR)
+
+#define apr_get_os_error()    (errno)
+#define apr_set_os_error(e)   (errno = (e))
+
+/* A special case, only socket calls require this: */
+#define apr_get_netos_error()   (APR_FROM_OS_ERROR(WSAGetLastError()))
+#define apr_set_netos_error(e)  (WSASetLastError(APR_TO_OS_ERROR(e)))
+
+/* APR CANONICAL ERROR TESTS */
+#define APR_STATUS_IS_EACCES(s)         ((s) == APR_EACCES)
+#define APR_STATUS_IS_EEXIST(s)         ((s) == APR_EEXIST)
+#define APR_STATUS_IS_ENAMETOOLONG(s)   ((s) == APR_ENAMETOOLONG)
+#define APR_STATUS_IS_ENOENT(s)         ((s) == APR_ENOENT)
+#define APR_STATUS_IS_ENOTDIR(s)        ((s) == APR_ENOTDIR)
+#define APR_STATUS_IS_ENOSPC(s)         ((s) == APR_ENOSPC)
+#define APR_STATUS_IS_ENOMEM(s)         ((s) == APR_ENOMEM)
+#define APR_STATUS_IS_EMFILE(s)         ((s) == APR_EMFILE)
+#define APR_STATUS_IS_ENFILE(s)         ((s) == APR_ENFILE)
+#define APR_STATUS_IS_EBADF(s)          ((s) == APR_EBADF)
+#define APR_STATUS_IS_EINVAL(s)         ((s) == APR_EINVAL)
+#define APR_STATUS_IS_ESPIPE(s)         ((s) == APR_ESPIPE)
+
+#define APR_STATUS_IS_EAGAIN(s)         ((s) == APR_EAGAIN \
+                || (s) ==                       EWOULDBLOCK \
+                || (s) == APR_OS_START_SYSERR + WSAEWOULDBLOCK)
+#define APR_STATUS_IS_EINTR(s)          ((s) == APR_EINTR \
+                || (s) == APR_OS_START_SYSERR + WSAEINTR)
+#define APR_STATUS_IS_ENOTSOCK(s)       ((s) == APR_ENOTSOCK \
+                || (s) == APR_OS_START_SYSERR + WSAENOTSOCK)
+#define APR_STATUS_IS_ECONNREFUSED(s)   ((s) == APR_ECONNREFUSED \
+                || (s) == APR_OS_START_SYSERR + WSAECONNREFUSED)
+#define APR_STATUS_IS_EINPROGRESS(s)    ((s) == APR_EINPROGRESS \
+                || (s) == APR_OS_START_SYSERR + WSAEINPROGRESS)
+#define APR_STATUS_IS_ECONNABORTED(s)   ((s) == APR_ECONNABORTED \
+                || (s) == APR_OS_START_SYSERR + WSAECONNABORTED)
+#define APR_STATUS_IS_ECONNRESET(s)     ((s) == APR_ECONNRESET \
+                || (s) == APR_OS_START_SYSERR + WSAECONNRESET)
+/* XXX deprecated */
+#define APR_STATUS_IS_ETIMEDOUT(s)       ((s) == APR_ETIMEDOUT \
+                || (s) == APR_OS_START_SYSERR + WSAETIMEDOUT \
+                || (s) == APR_OS_START_SYSERR + WAIT_TIMEOUT)
+#undef APR_STATUS_IS_TIMEUP
+#define APR_STATUS_IS_TIMEUP(s)         ((s) == APR_TIMEUP \
+                || (s) == APR_OS_START_SYSERR + WSAETIMEDOUT \
+                || (s) == APR_OS_START_SYSERR + WAIT_TIMEOUT)
+#define APR_STATUS_IS_EHOSTUNREACH(s)   ((s) == APR_EHOSTUNREACH \
+                || (s) == APR_OS_START_SYSERR + WSAEHOSTUNREACH)
+#define APR_STATUS_IS_ENETUNREACH(s)    ((s) == APR_ENETUNREACH \
+                || (s) == APR_OS_START_SYSERR + WSAENETUNREACH)
+#define APR_STATUS_IS_ENETDOWN(s)       ((s) == APR_OS_START_SYSERR + WSAENETDOWN)
+#define APR_STATUS_IS_EFTYPE(s)         ((s) == APR_EFTYPE)
+#define APR_STATUS_IS_EPIPE(s)          ((s) == APR_EPIPE)
+#define APR_STATUS_IS_EXDEV(s)          ((s) == APR_EXDEV)
+#define APR_STATUS_IS_ENOTEMPTY(s)      ((s) == APR_ENOTEMPTY)
+#define APR_STATUS_IS_EAFNOSUPPORT(s)   ((s) == APR_EAFNOSUPPORT \
+                || (s) == APR_OS_START_SYSERR + WSAEAFNOSUPPORT)
+#define APR_STATUS_IS_EOPNOTSUPP(s)     ((s) == APR_EOPNOTSUPP \
+                || (s) == APR_OS_START_SYSERR + WSAEOPNOTSUPP)
+#define APR_STATUS_IS_ERANGE(s)         ((s) == APR_ERANGE)
+
+#else /* !defined(NETWARE) && !defined(OS2) && !defined(WIN32) */
+
+/*
+ *  os error codes are clib error codes
+ */
+#define APR_FROM_OS_ERROR(e)  (e)
+#define APR_TO_OS_ERROR(e)    (e)
+
+#define apr_get_os_error()    (errno)
+#define apr_set_os_error(e)   (errno = (e))
+
+/* A special case, only socket calls require this:
+ */
+#define apr_get_netos_error() (errno)
+#define apr_set_netos_error(e) (errno = (e))
+
+/** 
+ * @addtogroup APR_STATUS_IS
+ * @{
+ */
+
+/** permission denied */
+#define APR_STATUS_IS_EACCES(s)         ((s) == APR_EACCES)
+/** file exists */
+#define APR_STATUS_IS_EEXIST(s)         ((s) == APR_EEXIST)
+/** path name is too long */
+#define APR_STATUS_IS_ENAMETOOLONG(s)   ((s) == APR_ENAMETOOLONG)
+/**
+ * no such file or directory
+ * @remark
+ * EMVSCATLG can be returned by the automounter on z/OS for
+ * paths which do not exist.
+ */
+#ifdef EMVSCATLG
+#define APR_STATUS_IS_ENOENT(s)         ((s) == APR_ENOENT \
+                                      || (s) == EMVSCATLG)
+#else
+#define APR_STATUS_IS_ENOENT(s)         ((s) == APR_ENOENT)
+#endif
+/** not a directory */
+#define APR_STATUS_IS_ENOTDIR(s)        ((s) == APR_ENOTDIR)
+/** no space left on device */
+#ifdef EDQUOT
+#define APR_STATUS_IS_ENOSPC(s)         ((s) == APR_ENOSPC \
+                                      || (s) == EDQUOT)
+#else
+#define APR_STATUS_IS_ENOSPC(s)         ((s) == APR_ENOSPC)
+#endif
+/** not enough memory */
+#define APR_STATUS_IS_ENOMEM(s)         ((s) == APR_ENOMEM)
+/** too many open files */
+#define APR_STATUS_IS_EMFILE(s)         ((s) == APR_EMFILE)
+/** file table overflow */
+#define APR_STATUS_IS_ENFILE(s)         ((s) == APR_ENFILE)
+/** bad file # */
+#define APR_STATUS_IS_EBADF(s)          ((s) == APR_EBADF)
+/** invalid argument */
+#define APR_STATUS_IS_EINVAL(s)         ((s) == APR_EINVAL)
+/** illegal seek */
+#define APR_STATUS_IS_ESPIPE(s)         ((s) == APR_ESPIPE)
+
+/** operation would block */
+#if !defined(EWOULDBLOCK) || !defined(EAGAIN)
+#define APR_STATUS_IS_EAGAIN(s)         ((s) == APR_EAGAIN)
+#elif (EWOULDBLOCK == EAGAIN)
+#define APR_STATUS_IS_EAGAIN(s)         ((s) == APR_EAGAIN)
+#else
+#define APR_STATUS_IS_EAGAIN(s)         ((s) == APR_EAGAIN \
+                                      || (s) == EWOULDBLOCK)
+#endif
+
+/** interrupted system call */
+#define APR_STATUS_IS_EINTR(s)          ((s) == APR_EINTR)
+/** socket operation on a non-socket */
+#define APR_STATUS_IS_ENOTSOCK(s)       ((s) == APR_ENOTSOCK)
+/** Connection Refused */
+#define APR_STATUS_IS_ECONNREFUSED(s)   ((s) == APR_ECONNREFUSED)
+/** operation now in progress */
+#define APR_STATUS_IS_EINPROGRESS(s)    ((s) == APR_EINPROGRESS)
+
+/** 
+ * Software caused connection abort 
+ * @remark
+ * EPROTO on certain older kernels really means ECONNABORTED, so we need to 
+ * ignore it for them.  See discussion in new-httpd archives nh.9701 & nh.9603
+ *
+ * There is potentially a bug in Solaris 2.x x<6, and other boxes that 
+ * implement tcp sockets in userland (i.e. on top of STREAMS).  On these
+ * systems, EPROTO can actually result in a fatal loop.  See PR#981 for 
+ * example.  It's hard to handle both uses of EPROTO.
+ */
+#ifdef EPROTO
+#define APR_STATUS_IS_ECONNABORTED(s)    ((s) == APR_ECONNABORTED \
+                                       || (s) == EPROTO)
+#else
+#define APR_STATUS_IS_ECONNABORTED(s)    ((s) == APR_ECONNABORTED)
+#endif
+
+/** Connection Reset by peer */
+#define APR_STATUS_IS_ECONNRESET(s)      ((s) == APR_ECONNRESET)
+/** Operation timed out
+ *  @deprecated */
+#define APR_STATUS_IS_ETIMEDOUT(s)      ((s) == APR_ETIMEDOUT)
+/** no route to host */
+#define APR_STATUS_IS_EHOSTUNREACH(s)    ((s) == APR_EHOSTUNREACH)
+/** network is unreachable */
+#define APR_STATUS_IS_ENETUNREACH(s)     ((s) == APR_ENETUNREACH)
+/** inappropriate file type or format */
+#define APR_STATUS_IS_EFTYPE(s)          ((s) == APR_EFTYPE)
+/** broken pipe */
+#define APR_STATUS_IS_EPIPE(s)           ((s) == APR_EPIPE)
+/** cross device link */
+#define APR_STATUS_IS_EXDEV(s)           ((s) == APR_EXDEV)
+/** Directory Not Empty */
+#define APR_STATUS_IS_ENOTEMPTY(s)       ((s) == APR_ENOTEMPTY || \
+                                          (s) == APR_EEXIST)
+/** Address Family not supported */
+#define APR_STATUS_IS_EAFNOSUPPORT(s)    ((s) == APR_EAFNOSUPPORT)
+/** Socket operation not supported */
+#define APR_STATUS_IS_EOPNOTSUPP(s)      ((s) == APR_EOPNOTSUPP)
+
+/** Numeric value not representable */
+#define APR_STATUS_IS_ERANGE(s)         ((s) == APR_ERANGE)
+/** @} */
+
+#endif /* !defined(NETWARE) && !defined(OS2) && !defined(WIN32) */
+
+/** @} */
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/apr_escape.h b/include/apr_escape.h
new file mode 100644
index 00000000000..6d4e08be0f3
--- /dev/null
+++ b/include/apr_escape.h
@@ -0,0 +1,418 @@
+/* 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 apr_escape.h
+ * @brief APR-UTIL Escaping
+ */
+#ifndef APR_ESCAPE_H
+#define APR_ESCAPE_H
+#include "apu.h"
+#include "apr_general.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup APR_Util_Escaping Escape functions
+ * @ingroup APR
+ * @{
+ */
+
+/* Simple escape/unescape functions.
+ *
+ */
+
+/**
+ * When passing a string to one of the escape functions, this value can be
+ * passed to indicate a string-valued key, and have the length computed
+ * automatically.
+ */
+#define APR_ESCAPE_STRING      (-1)
+
+/**
+ * Apply LDAP distinguished name escaping as per RFC4514.
+ */
+#define APR_ESCAPE_LDAP_DN     (0x01)
+
+/**
+ * Apply LDAP filter escaping as per RFC4515.
+ */
+#define APR_ESCAPE_LDAP_FILTER (0x02)
+
+/**
+ * Apply both RFC4514 and RFC4515 LDAP escaping.
+ */
+#define APR_ESCAPE_LDAP_ALL    (0x03)
+
+/**
+ * Perform shell escaping on the provided string.
+ * 
+ * Shell escaping causes characters to be prefixed with a '\' character.
+ * @param escaped Optional buffer to write the encoded string, can be
+ * NULL
+ * @param str The original string
+ * @param slen The length of the original string, or APR_ESCAPE_STRING
+ * @param len If present, returns the length of the string
+ * @return APR_SUCCESS, or APR_NOTFOUND if no changes to the string were
+ * detected or the string was NULL
+ */
+APR_DECLARE(apr_status_t) apr_escape_shell(char *escaped, const char *str,
+        apr_ssize_t slen, apr_size_t *len);
+
+/**
+ * Perform shell escaping on the provided string, returning the result
+ * from the pool.
+ *
+ * Shell escaping causes characters to be prefixed with a '\' character.
+ *
+ * If no characters were escaped, the original string is returned.
+ * @param p Pool to allocate from
+ * @param str The original string
+ * @return the encoded string, allocated from the pool, or the original
+ * string if no escaping took place or the string was NULL.
+ */
+APR_DECLARE(const char *) apr_pescape_shell(apr_pool_t *p, const char *str)
+        __attribute__((nonnull(1)));
+
+/**
+ * Unescapes a URL, leaving reserved characters intact.
+ * @param escaped Optional buffer to write the encoded string, can be
+ * NULL
+ * @param url String to be unescaped
+ * @param slen The length of the original url, or APR_ESCAPE_STRING
+ * @param forbid Optional list of forbidden characters, in addition to
+ * 0x00
+ * @param reserved Optional list of reserved characters that will be
+ * left unescaped
+ * @param plus If non zero, '+' is converted to ' ' as per
+ * application/x-www-form-urlencoded encoding
+ * @param len If set, the length of the escaped string will be returned
+ * @return APR_SUCCESS on success, APR_NOTFOUND if no characters are
+ * decoded or the string is NULL, APR_EINVAL if a bad escape sequence is
+ * found, APR_BADCH if a character on the forbid list is found.
+ */
+APR_DECLARE(apr_status_t) apr_unescape_url(char *escaped, const char *url,
+        apr_ssize_t slen, const char *forbid, const char *reserved, int plus,
+        apr_size_t *len);
+
+/**
+ * Unescapes a URL, leaving reserved characters intact, returning the
+ * result from a pool.
+ * @param p Pool to allocate from
+ * @param url String to be unescaped in place
+ * @param forbid Optional list of forbidden characters, in addition to
+ * 0x00
+ * @param reserved Optional list of reserved characters that will be
+ * left unescaped
+ * @param plus If non zero, '+' is converted to ' ' as per
+ * application/x-www-form-urlencoded encoding
+ * @return A string allocated from the pool on success, the original string
+ * if no characters are decoded, or NULL if a bad escape sequence is found
+ * or if a character on the forbid list is found, or if the original string
+ * was NULL.
+ */
+APR_DECLARE(const char *) apr_punescape_url(apr_pool_t *p, const char *url,
+        const char *forbid, const char *reserved, int plus)
+        __attribute__((nonnull(1)));
+
+/**
+ * Escape a path segment, as defined in RFC1808.
+ * @param escaped Optional buffer to write the encoded string, can be
+ * NULL
+ * @param str The original string
+ * @param slen The length of the original string, or APR_ESCAPE_STRING
+ * @param len If present, returns the length of the string
+ * @return APR_SUCCESS, or APR_NOTFOUND if no changes to the string were
+ * detected or the string was NULL
+ */
+APR_DECLARE(apr_status_t) apr_escape_path_segment(char *escaped,
+        const char *str, apr_ssize_t slen, apr_size_t *len);
+
+/**
+ * Escape a path segment, as defined in RFC1808, returning the result from a
+ * pool.
+ * @param p Pool to allocate from
+ * @param str String to be escaped
+ * @return A string allocated from the pool on success, the original string
+ * if no characters are encoded or the string is NULL.
+ */
+APR_DECLARE(const char *) apr_pescape_path_segment(apr_pool_t *p,
+        const char *str) __attribute__((nonnull(1)));
+
+/**
+ * Converts an OS path to a URL, in an OS dependent way, as defined in RFC1808.
+ * In all cases if a ':' occurs before the first '/' in the URL, the URL should
+ * be prefixed with "./" (or the ':' escaped). In the case of Unix, this means
+ * leaving '/' alone, but otherwise doing what escape_path_segment() does. For
+ * efficiency reasons, we don't use escape_path_segment(), which is provided for
+ * reference. Again, RFC 1808 is where this stuff is defined.
+ *
+ * If partial is set, os_escape_path() assumes that the path will be appended to
+ * something with a '/' in it (and thus does not prefix "./").
+ * @param escaped Optional buffer to write the encoded string, can be
+ * NULL
+ * @param path The original string
+ * @param slen The length of the original string, or APR_ESCAPE_STRING
+ * @param partial If non zero, suppresses the prepending of "./"
+ * @param len If present, returns the length of the string
+ * @return APR_SUCCESS, or APR_NOTFOUND if no changes to the string were
+ * detected or if the string was NULL
+ */
+APR_DECLARE(apr_status_t) apr_escape_path(char *escaped, const char *path,
+        apr_ssize_t slen, int partial, apr_size_t *len);
+
+/**
+ * Converts an OS path to a URL, in an OS dependent way, as defined in RFC1808,
+ * returning the result from a pool.
+ *
+ * In all cases if a ':' occurs before the first '/' in the URL, the URL should
+ * be prefixed with "./" (or the ':' escaped). In the case of Unix, this means
+ * leaving '/' alone, but otherwise doing what escape_path_segment() does. For
+ * efficiency reasons, we don't use escape_path_segment(), which is provided for
+ * reference. Again, RFC 1808 is where this stuff is defined.
+ *
+ * If partial is set, os_escape_path() assumes that the path will be appended to
+ * something with a '/' in it (and thus does not prefix "./").
+ * @param p Pool to allocate from
+ * @param str The original string
+ * @param partial If non zero, suppresses the prepending of "./"
+ * @return A string allocated from the pool on success, the original string
+ * if no characters are encoded or if the string was NULL.
+ */
+APR_DECLARE(const char *) apr_pescape_path(apr_pool_t *p, const char *str,
+        int partial) __attribute__((nonnull(1)));
+
+/**
+ * Urlencode a string, as defined in
+ * http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1.
+ * @param escaped Optional buffer to write the encoded string, can be
+ * NULL
+ * @param str The original string
+ * @param slen The length of the original string, or APR_ESCAPE_STRING
+ * @param len If present, returns the length of the string
+ * @return APR_SUCCESS, or APR_NOTFOUND if no changes to the string were
+ * detected or if the stirng was NULL
+ */
+APR_DECLARE(apr_status_t) apr_escape_urlencoded(char *escaped, const char *str,
+        apr_ssize_t slen, apr_size_t *len);
+
+/**
+ * Urlencode a string, as defined in
+ * http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1, returning
+ * the result from a pool.
+ * @param p Pool to allocate from
+ * @param str String to be escaped
+ * @return A string allocated from the pool on success, the original string
+ * if no characters are encoded or if the string was NULL.
+ */
+APR_DECLARE(const char *) apr_pescape_urlencoded(apr_pool_t *p,
+        const char *str) __attribute__((nonnull(1)));
+
+/**
+ * Apply entity encoding to a string. Characters are replaced as follows:
+ * '<' becomes '&lt;', '>' becomes '&gt;', '&' becomes '&amp;', the
+ * double quote becomes '&quot;" and the single quote becomes '&apos;'.
+ *
+ * If toasc is not zero, any non ascii character will be encoded as
+ * '%\#ddd;', where ddd is the decimal code of the character.
+ * @param escaped Optional buffer to write the encoded string, can be
+ * NULL
+ * @param str The original string
+ * @param slen The length of the original string, or APR_ESCAPE_STRING
+ * @param toasc If non zero, encode non ascii characters
+ * @param len If present, returns the length of the string
+ * @return APR_SUCCESS, or APR_NOTFOUND if no changes to the string were
+ * detected or the string was NULL
+ */
+APR_DECLARE(apr_status_t) apr_escape_entity(char *escaped, const char *str,
+        apr_ssize_t slen, int toasc, apr_size_t *len);
+
+/**
+ * Apply entity encoding to a string, returning the result from a pool.
+ * Characters are replaced as follows: '<' becomes '&lt;', '>' becomes
+ * '&gt;', '&' becomes '&amp;', the double quote becomes '&quot;" and the
+ * single quote becomes '&apos;'.
+ * @param p Pool to allocate from
+ * @param str The original string
+ * @param toasc If non zero, encode non ascii characters
+ * @return A string allocated from the pool on success, the original string
+ * if no characters are encoded or the string is NULL.
+ */
+APR_DECLARE(const char *) apr_pescape_entity(apr_pool_t *p, const char *str,
+        int toasc) __attribute__((nonnull(1)));
+
+/**
+ * Decodes html entities or numeric character references in a string. If
+ * the string to be unescaped is syntactically incorrect, then the
+ * following fixups will be made:
+ * unknown entities will be left undecoded;
+ * references to unused numeric characters will be deleted.
+ * In particular, &#00; will not be decoded, but will be deleted.
+ * @param unescaped Optional buffer to write the encoded string, can be
+ * NULL
+ * @param str The original string
+ * @param slen The length of the original string, or APR_ESCAPE_STRING
+ * @param len If present, returns the length of the string
+ * @return APR_SUCCESS, or APR_NOTFOUND if no changes to the string were
+ * detected or the string was NULL
+ */
+APR_DECLARE(apr_status_t) apr_unescape_entity(char *unescaped, const char *str,
+        apr_ssize_t slen, apr_size_t *len);
+
+/**
+ * Decodes html entities or numeric character references in a string. If
+ * the string to be unescaped is syntactically incorrect, then the
+ * following fixups will be made:
+ * unknown entities will be left undecoded;
+ * references to unused numeric characters will be deleted.
+ * In particular, &#00; will not be decoded, but will be deleted.
+ * @param p Pool to allocate from
+ * @param str The original string
+ * @return A string allocated from the pool on success, the original string
+ * if no characters are encoded or the string is NULL.
+ */
+APR_DECLARE(const char *) apr_punescape_entity(apr_pool_t *p, const char *str)
+        __attribute__((nonnull(1)));
+
+/**
+ * Escape control characters in a string, as performed by the shell's
+ * 'echo' command. Characters are replaced as follows:
+ * \\a alert (bell), \\b backspace, \\f form feed, \\n new line, \\r carriage
+ * return, \\t horizontal tab, \\v vertical tab, \\ backslash.
+ *
+ * Any non ascii character will be encoded as '\\xHH', where HH is the hex
+ * code of the character.
+ *
+ * If quote is not zero, the double quote character will also be escaped.
+ * @param escaped Optional buffer to write the encoded string, can be
+ * NULL
+ * @param str The original string
+ * @param slen The length of the original string, or APR_ESCAPE_STRING
+ * @param quote If non zero, encode double quotes
+ * @param len If present, returns the length of the string
+ * @return APR_SUCCESS, or APR_NOTFOUND if no changes to the string were
+ * detected or the string was NULL
+ */
+APR_DECLARE(apr_status_t) apr_escape_echo(char *escaped, const char *str,
+        apr_ssize_t slen, int quote, apr_size_t *len);
+
+/**
+ * Escape control characters in a string, as performed by the shell's
+ * 'echo' command, and return the results from a pool. Characters are
+ * replaced as follows: \\a alert (bell), \\b backspace, \\f form feed,
+ * \\n new line, \\r carriage return, \\t horizontal tab, \\v vertical tab,
+ * \\ backslash.
+ *
+ * Any non ascii character will be encoded as '\\xHH', where HH is the hex
+ * code of the character.
+ *
+ * If quote is not zero, the double quote character will also be escaped.
+ * @param p Pool to allocate from
+ * @param str The original string
+ * @param quote If non zero, encode double quotes
+ * @return A string allocated from the pool on success, the original string
+ * if no characters are encoded or the string is NULL.
+ */
+APR_DECLARE(const char *) apr_pescape_echo(apr_pool_t *p, const char *str,
+        int quote);
+
+/**
+ * Convert binary data to a hex encoding.
+ * @param dest The destination buffer, can be NULL
+ * @param src The original buffer
+ * @param srclen The length of the original buffer
+ * @param colon If not zero, insert colon characters between hex digits.
+ * @param len If present, returns the length of the string
+ * @return APR_SUCCESS, or APR_NOTFOUND if the string was NULL
+ */
+APR_DECLARE(apr_status_t) apr_escape_hex(char *dest, const void *src,
+        apr_size_t srclen, int colon, apr_size_t *len);
+
+/**
+ * Convert binary data to a hex encoding, and return the results from a
+ * pool.
+ * @param p Pool to allocate from
+ * @param src The original buffer
+ * @param slen The length of the original buffer
+ * @param colon If not zero, insert colon characters between hex digits.
+ * @return A zero padded buffer allocated from the pool on success, or
+ * NULL if src was NULL.
+ */
+APR_DECLARE(const char *) apr_pescape_hex(apr_pool_t *p, const void *src,
+        apr_size_t slen, int colon) __attribute__((nonnull(1)));
+
+/**
+ * Convert hex encoded string to binary data.
+ * @param dest The destination buffer, can be NULL
+ * @param str The original buffer
+ * @param slen The length of the original buffer
+ * @param colon If not zero, ignore colon characters between hex digits.
+ * @param len If present, returns the length of the string
+ * @return APR_SUCCESS, or APR_NOTFOUND if the string was NULL, or APR_BADCH
+ * if a non hex character is present.
+ */
+APR_DECLARE(apr_status_t) apr_unescape_hex(void *dest, const char *str,
+        apr_ssize_t slen, int colon, apr_size_t *len);
+
+/**
+ * Convert hex encoding to binary data, and return the results from a pool.
+ * If the colon character appears between pairs of hex digits, it will be
+ * ignored.
+ * @param p Pool to allocate from
+ * @param str The original string
+ * @param colon If not zero, ignore colon characters between hex digits.
+ * @param len If present, returns the length of the final buffer
+ * @return A buffer allocated from the pool on success, or NULL if src was
+ * NULL, or a bad character was present.
+ */
+APR_DECLARE(const void *) apr_punescape_hex(apr_pool_t *p, const char *str,
+        int colon, apr_size_t *len);
+
+/**
+ * Apply LDAP escaping to binary data. Characters from RFC4514 and RFC4515
+ * are escaped with their hex equivalents.
+ * @param dest The destination buffer, can be NULL
+ * @param src The original buffer
+ * @param srclen The length of the original buffer
+ * @param flags APR_ESCAPE_LDAP_DN for RFC4514, APR_ESCAPE_LDAP_FILTER for
+ * RFC4515, APR_ESCAPE_LDAP_ALL for both
+ * @param len If present, returns the length of the string
+ * @return APR_SUCCESS, or APR_NOTFOUND if the string was NULL
+ */
+APR_DECLARE(apr_status_t) apr_escape_ldap(char *dest, const void *src,
+        apr_ssize_t srclen, int flags, apr_size_t *len);
+
+/**
+ * Apply LDAP escaping to binary data, and return the results from a
+ * pool. Characters from RFC4514 and RFC4515 are escaped with their hex
+ * equivalents.
+ * @param p Pool to allocate from
+ * @param src The original buffer
+ * @param slen The length of the original buffer
+ * @param flags APR_ESCAPE_LDAP_DN for RFC4514, APR_ESCAPE_LDAP_FILTER for
+ * RFC4515, APR_ESCAPE_LDAP_ALL for both
+ * @return A zero padded buffer allocated from the pool on success, or
+ * NULL if src was NULL.
+ */
+APR_DECLARE(const char *) apr_pescape_ldap(apr_pool_t *p, const void *src,
+        apr_ssize_t slen, int flags) __attribute__((nonnull(1)));
+
+/** @} */
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* !APR_ESCAPE_H */
diff --git a/include/apr_file_info.h b/include/apr_file_info.h
new file mode 100644
index 00000000000..1d19eb6a3f4
--- /dev/null
+++ b/include/apr_file_info.h
@@ -0,0 +1,428 @@
+/* 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 APR_FILE_INFO_H
+#define APR_FILE_INFO_H
+
+/**
+ * @file apr_file_info.h
+ * @brief APR File Information
+ */
+
+#include "apr.h"
+#include "apr_user.h"
+#include "apr_pools.h"
+#include "apr_tables.h"
+#include "apr_time.h"
+#include "apr_errno.h"
+
+#if APR_HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup apr_file_info File Information
+ * @ingroup APR 
+ * @{
+ */
+
+/* Many applications use the type member to determine the
+ * existance of a file or initialization of the file info,
+ * so the APR_NOFILE value must be distinct from APR_UNKFILE.
+ */
+
+/** apr_filetype_e values for the filetype member of the 
+ * apr_file_info_t structure
+ * @warning: Not all of the filetypes below can be determined.
+ * For example, a given platform might not correctly report 
+ * a socket descriptor as APR_SOCK if that type isn't 
+ * well-identified on that platform.  In such cases where
+ * a filetype exists but cannot be described by the recognized
+ * flags below, the filetype will be APR_UNKFILE.  If the
+ * filetype member is not determined, the type will be APR_NOFILE.
+ */
+
+typedef enum {
+    APR_NOFILE = 0,     /**< no file type determined */
+    APR_REG,            /**< a regular file */
+    APR_DIR,            /**< a directory */
+    APR_CHR,            /**< a character device */
+    APR_BLK,            /**< a block device */
+    APR_PIPE,           /**< a FIFO / pipe */
+    APR_LNK,            /**< a symbolic link */
+    APR_SOCK,           /**< a [unix domain] socket */
+    APR_UNKFILE = 127   /**< a file of some other unknown type */
+} apr_filetype_e; 
+
+/**
+ * @defgroup apr_file_permissions File Permissions flags 
+ * @{
+ */
+
+#define APR_FPROT_USETID      0x8000 /**< Set user id */
+#define APR_FPROT_UREAD       0x0400 /**< Read by user */
+#define APR_FPROT_UWRITE      0x0200 /**< Write by user */
+#define APR_FPROT_UEXECUTE    0x0100 /**< Execute by user */
+
+#define APR_FPROT_GSETID      0x4000 /**< Set group id */
+#define APR_FPROT_GREAD       0x0040 /**< Read by group */
+#define APR_FPROT_GWRITE      0x0020 /**< Write by group */
+#define APR_FPROT_GEXECUTE    0x0010 /**< Execute by group */
+
+#define APR_FPROT_WSTICKY     0x2000 /**< Sticky bit */
+#define APR_FPROT_WREAD       0x0004 /**< Read by others */
+#define APR_FPROT_WWRITE      0x0002 /**< Write by others */
+#define APR_FPROT_WEXECUTE    0x0001 /**< Execute by others */
+
+#define APR_FPROT_OS_DEFAULT  0x0FFF /**< use OS's default permissions */
+
+/* additional permission flags for apr_file_copy  and apr_file_append */
+#define APR_FPROT_FILE_SOURCE_PERMS 0x1000 /**< Copy source file's permissions */
+    
+/* backcompat */
+#define APR_USETID     APR_FPROT_USETID     /**< @deprecated @see APR_FPROT_USETID     */
+#define APR_UREAD      APR_FPROT_UREAD      /**< @deprecated @see APR_FPROT_UREAD      */
+#define APR_UWRITE     APR_FPROT_UWRITE     /**< @deprecated @see APR_FPROT_UWRITE     */
+#define APR_UEXECUTE   APR_FPROT_UEXECUTE   /**< @deprecated @see APR_FPROT_UEXECUTE   */
+#define APR_GSETID     APR_FPROT_GSETID     /**< @deprecated @see APR_FPROT_GSETID     */
+#define APR_GREAD      APR_FPROT_GREAD      /**< @deprecated @see APR_FPROT_GREAD      */
+#define APR_GWRITE     APR_FPROT_GWRITE     /**< @deprecated @see APR_FPROT_GWRITE     */
+#define APR_GEXECUTE   APR_FPROT_GEXECUTE   /**< @deprecated @see APR_FPROT_GEXECUTE   */
+#define APR_WSTICKY    APR_FPROT_WSTICKY    /**< @deprecated @see APR_FPROT_WSTICKY    */
+#define APR_WREAD      APR_FPROT_WREAD      /**< @deprecated @see APR_FPROT_WREAD      */
+#define APR_WWRITE     APR_FPROT_WWRITE     /**< @deprecated @see APR_FPROT_WWRITE     */
+#define APR_WEXECUTE   APR_FPROT_WEXECUTE   /**< @deprecated @see APR_FPROT_WEXECUTE   */
+#define APR_OS_DEFAULT APR_FPROT_OS_DEFAULT /**< @deprecated @see APR_FPROT_OS_DEFAULT */
+#define APR_FILE_SOURCE_PERMS APR_FPROT_FILE_SOURCE_PERMS /**< @deprecated @see APR_FPROT_FILE_SOURCE_PERMS */
+    
+/** @} */
+
+
+/**
+ * Structure for referencing directories.
+ */
+typedef struct apr_dir_t          apr_dir_t;
+/**
+ * Structure for determining file permissions.
+ */
+typedef apr_int32_t               apr_fileperms_t;
+#if (defined WIN32) || (defined NETWARE)
+/**
+ * Structure for determining the device the file is on.
+ */
+typedef apr_uint32_t              apr_dev_t;
+#else
+/**
+ * Structure for determining the device the file is on.
+ */
+typedef dev_t                     apr_dev_t;
+#endif
+
+/**
+ * @defgroup apr_file_stat Stat Functions
+ * @{
+ */
+/** file info structure */
+typedef struct apr_finfo_t        apr_finfo_t;
+
+#define APR_FINFO_LINK   0x00000001 /**< Stat the link not the file itself if it is a link */
+#define APR_FINFO_MTIME  0x00000010 /**< Modification Time */
+#define APR_FINFO_CTIME  0x00000020 /**< Creation or inode-changed time */
+#define APR_FINFO_ATIME  0x00000040 /**< Access Time */
+#define APR_FINFO_SIZE   0x00000100 /**< Size of the file */
+#define APR_FINFO_CSIZE  0x00000200 /**< Storage size consumed by the file */
+#define APR_FINFO_DEV    0x00001000 /**< Device */
+#define APR_FINFO_INODE  0x00002000 /**< Inode */
+#define APR_FINFO_NLINK  0x00004000 /**< Number of links */
+#define APR_FINFO_TYPE   0x00008000 /**< Type */
+#define APR_FINFO_USER   0x00010000 /**< User */
+#define APR_FINFO_GROUP  0x00020000 /**< Group */
+#define APR_FINFO_UPROT  0x00100000 /**< User protection bits */
+#define APR_FINFO_GPROT  0x00200000 /**< Group protection bits */
+#define APR_FINFO_WPROT  0x00400000 /**< World protection bits */
+#define APR_FINFO_ICASE  0x01000000 /**< if dev is case insensitive */
+#define APR_FINFO_NAME   0x02000000 /**< ->name in proper case */
+
+#define APR_FINFO_MIN    0x00008170 /**< type, mtime, ctime, atime, size */
+#define APR_FINFO_IDENT  0x00003000 /**< dev and inode */
+#define APR_FINFO_OWNER  0x00030000 /**< user and group */
+#define APR_FINFO_PROT   0x00700000 /**<  all protections */
+#define APR_FINFO_NORM   0x0073b170 /**<  an atomic unix apr_stat() */
+#define APR_FINFO_DIRENT 0x02000000 /**<  an atomic unix apr_dir_read() */
+
+/**
+ * The file information structure.  This is analogous to the POSIX
+ * stat structure.
+ */
+struct apr_finfo_t {
+    /** Allocates memory and closes lingering handles in the specified pool */
+    apr_pool_t *pool;
+    /** The bitmask describing valid fields of this apr_finfo_t structure 
+     *  including all available 'wanted' fields and potentially more */
+    apr_int32_t valid;
+    /** The access permissions of the file.  Mimics Unix access rights. */
+    apr_fileperms_t protection;
+    /** The type of file.  One of APR_REG, APR_DIR, APR_CHR, APR_BLK, APR_PIPE, 
+     * APR_LNK or APR_SOCK.  If the type is undetermined, the value is APR_NOFILE.
+     * If the type cannot be determined, the value is APR_UNKFILE.
+     */
+    apr_filetype_e filetype;
+    /** The user id that owns the file */
+    apr_uid_t user;
+    /** The group id that owns the file */
+    apr_gid_t group;
+    /** The inode of the file. */
+    apr_ino_t inode;
+    /** The id of the device the file is on. */
+    apr_dev_t device;
+    /** The number of hard links to the file. */
+    apr_int32_t nlink;
+    /** The size of the file */
+    apr_off_t size;
+    /** The storage size consumed by the file */
+    apr_off_t csize;
+    /** The time the file was last accessed */
+    apr_time_t atime;
+    /** The time the file was last modified */
+    apr_time_t mtime;
+    /** The time the file was created, or the inode was last changed */
+    apr_time_t ctime;
+    /** The pathname of the file (possibly unrooted) */
+    const char *fname;
+    /** The file's name (no path) in filesystem case */
+    const char *name;
+    /** Unused */
+    struct apr_file_t *filehand;
+};
+
+/**
+ * get the specified file's stats.  The file is specified by filename, 
+ * instead of using a pre-opened file.
+ * @param finfo Where to store the information about the file, which is
+ * never touched if the call fails.
+ * @param fname The name of the file to stat.
+ * @param wanted The desired apr_finfo_t fields, as a bit flag of APR_FINFO_
+                 values 
+ * @param pool the pool to use to allocate the new file. 
+ *
+ * @note If @c APR_INCOMPLETE is returned all the fields in @a finfo may
+ *       not be filled in, and you need to check the @c finfo->valid bitmask
+ *       to verify that what you're looking for is there.
+ */ 
+APR_DECLARE(apr_status_t) apr_stat(apr_finfo_t *finfo, const char *fname,
+                                   apr_int32_t wanted, apr_pool_t *pool);
+
+/** @} */
+/**
+ * @defgroup apr_dir Directory Manipulation Functions
+ * @{
+ */
+
+/**
+ * Open the specified directory.
+ * @param new_dir The opened directory descriptor.
+ * @param dirname The full path to the directory (use / on all systems)
+ * @param pool The pool to use.
+ */                        
+APR_DECLARE(apr_status_t) apr_dir_open(apr_dir_t **new_dir, 
+                                       const char *dirname, 
+                                       apr_pool_t *pool);
+
+/**
+ * close the specified directory. 
+ * @param thedir the directory descriptor to close.
+ */                        
+APR_DECLARE(apr_status_t) apr_dir_close(apr_dir_t *thedir);
+
+/**
+ * Read the next entry from the specified directory. 
+ * @param finfo the file info structure and filled in by apr_dir_read
+ * @param wanted The desired apr_finfo_t fields, as a bit flag of APR_FINFO_
+                 values 
+ * @param thedir the directory descriptor returned from apr_dir_open
+ * @remark No ordering is guaranteed for the entries read.
+ *
+ * @note If @c APR_INCOMPLETE is returned all the fields in @a finfo may
+ *       not be filled in, and you need to check the @c finfo->valid bitmask
+ *       to verify that what you're looking for is there. When no more
+ *       entries are available, APR_ENOENT is returned.
+ */                        
+APR_DECLARE(apr_status_t) apr_dir_read(apr_finfo_t *finfo, apr_int32_t wanted,
+                                       apr_dir_t *thedir);
+
+/**
+ * Rewind the directory to the first entry.
+ * @param thedir the directory descriptor to rewind.
+ */                        
+APR_DECLARE(apr_status_t) apr_dir_rewind(apr_dir_t *thedir);
+/** @} */
+
+/**
+ * @defgroup apr_filepath Filepath Manipulation Functions
+ * @{
+ */
+
+/** Cause apr_filepath_merge to fail if addpath is above rootpath 
+ * @bug in APR 0.9 and 1.x, this flag's behavior is undefined
+ * if the rootpath is NULL or empty.  In APR 2.0 this should be
+ * changed to imply NOTABSOLUTE if the rootpath is NULL or empty.
+ */
+#define APR_FILEPATH_NOTABOVEROOT   0x01
+
+/** internal: Only meaningful with APR_FILEPATH_NOTABOVEROOT */
+#define APR_FILEPATH_SECUREROOTTEST 0x02
+
+/** Cause apr_filepath_merge to fail if addpath is above rootpath,
+ * even given a rootpath /foo/bar and an addpath ../bar/bash
+ */
+#define APR_FILEPATH_SECUREROOT     0x03
+
+/** Fail apr_filepath_merge if the merged path is relative */
+#define APR_FILEPATH_NOTRELATIVE    0x04
+
+/** Fail apr_filepath_merge if the merged path is absolute */
+#define APR_FILEPATH_NOTABSOLUTE    0x08
+
+/** Return the file system's native path format (e.g. path delimiters
+ * of ':' on MacOS9, '\' on Win32, etc.) */
+#define APR_FILEPATH_NATIVE         0x10
+
+/** Resolve the true case of existing directories and file elements
+ * of addpath, (resolving any aliases on Win32) and append a proper 
+ * trailing slash if a directory
+ */
+#define APR_FILEPATH_TRUENAME       0x20
+
+/**
+ * Extract the rootpath from the given filepath
+ * @param rootpath the root file path returned with APR_SUCCESS or APR_EINCOMPLETE
+ * @param filepath the pathname to parse for its root component
+ * @param flags the desired rules to apply, from
+ * <PRE>
+ *      APR_FILEPATH_NATIVE    Use native path separators (e.g. '\' on Win32)
+ *      APR_FILEPATH_TRUENAME  Tests that the root exists, and makes it proper
+ * </PRE>
+ * @param p the pool to allocate the new path string from
+ * @remark on return, filepath points to the first non-root character in the
+ * given filepath.  In the simplest example, given a filepath of "/foo", 
+ * returns the rootpath of "/" and filepath points at "foo".  This is far 
+ * more complex on other platforms, which will canonicalize the root form
+ * to a consistant format, given the APR_FILEPATH_TRUENAME flag, and also
+ * test for the validity of that root (e.g., that a drive d:/ or network 
+ * share //machine/foovol/). 
+ * The function returns APR_ERELATIVE if filepath isn't rooted (an
+ * error), APR_EINCOMPLETE if the root path is ambiguous (but potentially
+ * legitimate, e.g. "/" on Windows is incomplete because it doesn't specify
+ * the drive letter), or APR_EBADPATH if the root is simply invalid.
+ * APR_SUCCESS is returned if filepath is an absolute path.
+ */
+APR_DECLARE(apr_status_t) apr_filepath_root(const char **rootpath, 
+                                            const char **filepath, 
+                                            apr_int32_t flags,
+                                            apr_pool_t *p);
+
+/**
+ * Merge additional file path onto the previously processed rootpath
+ * @param newpath the merged paths returned
+ * @param rootpath the root file path (NULL uses the current working path)
+ * @param addpath the path to add to the root path
+ * @param flags the desired APR_FILEPATH_ rules to apply when merging
+ * @param p the pool to allocate the new path string from
+ * @remark if the flag APR_FILEPATH_TRUENAME is given, and the addpath 
+ * contains wildcard characters ('*', '?') on platforms that don't support 
+ * such characters within filenames, the paths will be merged, but the 
+ * result code will be APR_EPATHWILD, and all further segments will not
+ * reflect the true filenames including the wildcard and following segments.
+ */                        
+APR_DECLARE(apr_status_t) apr_filepath_merge(char **newpath, 
+                                             const char *rootpath,
+                                             const char *addpath, 
+                                             apr_int32_t flags,
+                                             apr_pool_t *p);
+
+/**
+ * Split a search path into separate components
+ * @param pathelts the returned components of the search path
+ * @param liststr the search path (e.g., <tt>getenv("PATH")</tt>)
+ * @param p the pool to allocate the array and path components from
+ * @remark empty path components do not become part of @a pathelts.
+ * @remark the path separator in @a liststr is system specific;
+ * e.g., ':' on Unix, ';' on Windows, etc.
+ */
+APR_DECLARE(apr_status_t) apr_filepath_list_split(apr_array_header_t **pathelts,
+                                                  const char *liststr,
+                                                  apr_pool_t *p);
+
+/**
+ * Merge a list of search path components into a single search path
+ * @param liststr the returned search path; may be NULL if @a pathelts is empty
+ * @param pathelts the components of the search path
+ * @param p the pool to allocate the search path from
+ * @remark emtpy strings in the source array are ignored.
+ * @remark the path separator in @a liststr is system specific;
+ * e.g., ':' on Unix, ';' on Windows, etc.
+ */
+APR_DECLARE(apr_status_t) apr_filepath_list_merge(char **liststr,
+                                                  apr_array_header_t *pathelts,
+                                                  apr_pool_t *p);
+
+/**
+ * Return the default file path (for relative file names)
+ * @param path the default path string returned
+ * @param flags optional flag APR_FILEPATH_NATIVE to retrieve the
+ *              default file path in os-native format.
+ * @param p the pool to allocate the default path string from
+ */
+APR_DECLARE(apr_status_t) apr_filepath_get(char **path, apr_int32_t flags,
+                                           apr_pool_t *p);
+
+/**
+ * Set the default file path (for relative file names)
+ * @param path the default path returned
+ * @param p the pool to allocate any working storage
+ */
+APR_DECLARE(apr_status_t) apr_filepath_set(const char *path, apr_pool_t *p);
+
+/** The FilePath character encoding is unknown */
+#define APR_FILEPATH_ENCODING_UNKNOWN  0
+
+/** The FilePath character encoding is locale-dependent */
+#define APR_FILEPATH_ENCODING_LOCALE   1
+
+/** The FilePath character encoding is UTF-8 */
+#define APR_FILEPATH_ENCODING_UTF8     2
+
+/**
+ * Determine the encoding used internally by the FilePath functions
+ * @param style points to a variable which receives the encoding style flag
+ * @param p the pool to allocate any working storage
+ * @remark Use @c apr_os_locale_encoding and/or @c apr_os_default_encoding
+ * to get the name of the path encoding if it's not UTF-8.
+ */
+APR_DECLARE(apr_status_t) apr_filepath_encoding(int *style, apr_pool_t *p);
+/** @} */
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* ! APR_FILE_INFO_H */
diff --git a/include/apr_file_io.h b/include/apr_file_io.h
index 3bee3987e33..4611b1a153a 100644
--- a/include/apr_file_io.h
+++ b/include/apr_file_io.h
@@ -1,687 +1,1029 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 APR_FILE_IO_H
 #define APR_FILE_IO_H
 
-#include "apr_general.h"
+/**
+ * @file apr_file_io.h
+ * @brief APR File I/O Handling
+ */
+
+#include "apr.h"
+#include "apr_pools.h"
 #include "apr_time.h"
 #include "apr_errno.h"
-#if APR_HAVE_SYS_UIO_H
-#include <sys/uio.h>
-#endif
+#include "apr_file_info.h"
+#include "apr_inherit.h"
+
+#define APR_WANT_STDIO          /**< for SEEK_* */
+#define APR_WANT_IOVEC          /**< for apr_file_writev */
+#include "apr_want.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif /* __cplusplus */
 
-typedef enum {APR_NOFILE, APR_REG, APR_DIR, APR_CHR, APR_BLK, APR_PIPE, APR_LNK, 
-              APR_SOCK} ap_filetype_e; 
-
-/* Flags for ap_open */
-#define APR_READ       1           /* Open the file for reading */
-#define APR_WRITE      2           /* Open the file for writing */
-#define APR_CREATE     4           /* Create the file if not there */
-#define APR_APPEND     8           /* Append to the end of the file */
-#define APR_TRUNCATE   16          /* Open the file and truncate to 0 length */
-#define APR_BINARY     32          /* Open the file in binary mode */
-#define APR_EXCL       64          /* Open should fail if APR_CREATE and file
-				    exists. */
-#define APR_BUFFERED   128         /* Open the file for buffered I/O */
-#define APR_DELONCLOSE 256         /* Delete the file after close */
-
-/* flags for ap_seek */
-#define APR_SET SEEK_SET
-#define APR_CUR SEEK_CUR
-#define APR_END SEEK_END
-
-/* Permissions flags */
-#define APR_UREAD     0x400 
-#define APR_UWRITE    0x200
-#define APR_UEXECUTE  0x100
-
-#define APR_GREAD     0x040
-#define APR_GWRITE    0x020
-#define APR_GEXECUTE  0x010
-
-#define APR_WREAD     0x004
-#define APR_WWRITE    0x002
-#define APR_WEXECUTE  0x001
-
-#define APR_OS_DEFAULT 0xFFF
-
-/* should be same as whence type in lseek, POSIX defines this as int */
-typedef ap_int32_t       ap_seek_where_t;
-
-typedef struct ap_file_t            ap_file_t;
-typedef struct ap_finfo_t        ap_finfo_t;
-typedef struct ap_dir_t             ap_dir_t;
-typedef ap_int32_t               ap_fileperms_t;
-typedef uid_t                    ap_uid_t;
-typedef gid_t                    ap_gid_t;
-typedef ino_t                    ap_ino_t;
-
-struct ap_finfo_t {
-    ap_fileperms_t protection;
-    ap_filetype_e filetype;
-    ap_uid_t user;
-    ap_gid_t group;
-    ap_ino_t inode;
-    ap_off_t size;
-    ap_time_t atime;
-    ap_time_t mtime;
-    ap_time_t ctime;
-};
-
-/*   Function definitions */
-/*
-
-=head1 ap_status_t ap_open(ap_file_t **new, char *fname, ap_int32 flag, ap_fileperms perm, ap_pool_t *cont)
-
-B<Open the specified file.>
-
-    arg 1) The opened file descriptor.
-    arg 2) The full path to the file (using / on all systems)
-    arg 3) Or'ed value of:
-             APR_READ             open for reading
-             APR_WRITE            open for writing
-             APR_CREATE           create the file if not there
-             APR_APPEND           file ptr is set to end prior to all writes
-             APR_TRUNCATE         set length to zero if file exists
-             APR_BINARY           not a text file (This flag is ignored on 
-                                  UNIX because it has no meaning)
-             APR_BUFFERED         buffer the data.  Default is non-buffered
-             APR_EXCL             return error if APR_CREATE and file exists
-             APR_DELONCLOSE       delete the file after closing.
-    arg 4) Access permissions for file.
-    arg 5) The pool to use.
-
-B<NOTE>:  If perm is APR_OS_DEFAULT and the file is being created, appropriate
-          default permissions will be used.  *arg1 must point to a valid file_t, 
-          or NULL (in which case it will be allocated)
-
-=cut
+/**
+ * @defgroup apr_file_io File I/O Handling Functions
+ * @ingroup APR 
+ * @{
  */
-ap_status_t ap_open(ap_file_t **new, const char *fname, ap_int32_t flag, 
-                    ap_fileperms_t perm, ap_pool_t *cont);
-
-/*
-
-=head1 ap_status_t ap_close(ap_file_t *file)
 
-B<Close the specified file.>
-
-    arg 1) The file descriptor to close.
-
-=cut
+/**
+ * @defgroup apr_file_open_flags File Open Flags/Routines
+ * @{
  */
-ap_status_t ap_close(ap_file_t *file);
-
-/*
-
-=head1 ap_status_t ap_remove_file(char *path, ap_pool_t *cont) 
 
-B<delete the specified file.>
-
-    arg 1) The full path to the file (using / on all systems)
-    arg 2) The pool to use.
-
-B<NOTE>: If the file is open, it won't be removed until all instances are
-       closed.
-
-=cut
+/* Note to implementors: Values in the range 0x00100000--0x80000000
+   are reserved for platform-specific values. */
+
+#define APR_FOPEN_READ       0x00001  /**< Open the file for reading */
+#define APR_FOPEN_WRITE      0x00002  /**< Open the file for writing */
+#define APR_FOPEN_CREATE     0x00004  /**< Create the file if not there */
+#define APR_FOPEN_APPEND     0x00008  /**< Append to the end of the file */
+#define APR_FOPEN_TRUNCATE   0x00010  /**< Open the file and truncate
+                                         to 0 length */
+#define APR_FOPEN_BINARY     0x00020  /**< Open the file in binary mode
+				         (This flag is ignored on UNIX 
+					 because it has no meaning)*/
+#define APR_FOPEN_EXCL       0x00040  /**< Open should fail if #APR_FOPEN_CREATE
+                                         and file exists. */
+#define APR_FOPEN_BUFFERED   0x00080  /**< Open the file for buffered I/O */
+#define APR_FOPEN_DELONCLOSE 0x00100  /**< Delete the file after close */
+#define APR_FOPEN_XTHREAD    0x00200  /**< Platform dependent tag to open
+                                         the file for use across multiple
+                                         threads */
+#define APR_FOPEN_SHARELOCK  0x00400  /**< Platform dependent support for
+                                         higher level locked read/write
+                                         access to support writes across
+                                         process/machines */
+#define APR_FOPEN_NOCLEANUP  0x00800  /**< Do not register a cleanup
+                                         when the file is opened. The
+					 apr_os_file_t handle in apr_file_t
+					 will not be closed when the pool
+					 is destroyed. */
+#define APR_FOPEN_SENDFILE_ENABLED 0x01000 /**< Advisory flag that this
+                                             file should support
+                                             apr_socket_sendfile operation */
+#define APR_FOPEN_LARGEFILE   0x04000 /**< Platform dependent flag to enable
+                                       * large file support, see WARNING below 
+                                       */
+
+#define APR_FOPEN_SPARSE      0x08000 /**< Platform dependent flag to enable
+                                       * sparse file support, see WARNING below
+                                       */
+
+#define APR_FOPEN_ROTATING  0x10000 /**< Do file file rotation checking */
+ 
+#define APR_FOPEN_MANUAL_ROTATE  0x20000 /**< Enable Manual rotation */
+
+#define APR_FOPEN_NONBLOCK    0x40000 /**< Platform dependent flag to enable
+                                       * non blocking file io */
+
+ 
+
+/* backcompat */
+#define APR_READ             APR_FOPEN_READ       /**< @deprecated @see APR_FOPEN_READ */
+#define APR_WRITE            APR_FOPEN_WRITE      /**< @deprecated @see APR_FOPEN_WRITE */   
+#define APR_CREATE           APR_FOPEN_CREATE     /**< @deprecated @see APR_FOPEN_CREATE */   
+#define APR_APPEND           APR_FOPEN_APPEND     /**< @deprecated @see APR_FOPEN_APPEND */   
+#define APR_TRUNCATE         APR_FOPEN_TRUNCATE   /**< @deprecated @see APR_FOPEN_TRUNCATE */   
+#define APR_BINARY           APR_FOPEN_BINARY     /**< @deprecated @see APR_FOPEN_BINARY */   
+#define APR_EXCL             APR_FOPEN_EXCL       /**< @deprecated @see APR_FOPEN_EXCL */   
+#define APR_BUFFERED         APR_FOPEN_BUFFERED   /**< @deprecated @see APR_FOPEN_BUFFERED */   
+#define APR_DELONCLOSE       APR_FOPEN_DELONCLOSE /**< @deprecated @see APR_FOPEN_DELONCLOSE */   
+#define APR_XTHREAD          APR_FOPEN_XTHREAD    /**< @deprecated @see APR_FOPEN_XTHREAD */   
+#define APR_SHARELOCK        APR_FOPEN_SHARELOCK  /**< @deprecated @see APR_FOPEN_SHARELOCK */   
+#define APR_FILE_NOCLEANUP   APR_FOPEN_NOCLEANUP  /**< @deprecated @see APR_FOPEN_NOCLEANUP */   
+#define APR_SENDFILE_ENABLED APR_FOPEN_SENDFILE_ENABLED /**< @deprecated @see APR_FOPEN_SENDFILE_ENABLED */   
+#define APR_LARGEFILE        APR_FOPEN_LARGEFILE  /**< @deprecated @see APR_FOPEN_LARGEFILE */   
+
+/** @def APR_FOPEN_LARGEFILE 
+ * @warning APR_FOPEN_LARGEFILE flag only has effect on some
+ * platforms where sizeof(apr_off_t) == 4.  Where implemented, it
+ * allows opening and writing to a file which exceeds the size which
+ * can be represented by apr_off_t (2 gigabytes).  When a file's size
+ * does exceed 2Gb, apr_file_info_get() will fail with an error on the
+ * descriptor, likewise apr_stat()/apr_lstat() will fail on the
+ * filename.  apr_dir_read() will fail with #APR_INCOMPLETE on a
+ * directory entry for a large file depending on the particular
+ * APR_FINFO_* flags.  Generally, it is not recommended to use this
+ * flag.
+ *
+ * @def APR_FOPEN_SPARSE
+ * @warning APR_FOPEN_SPARSE may, depending on platform, convert a
+ * normal file to a sparse file.  Some applications may be unable
+ * to decipher a sparse file, so it's critical that the sparse file
+ * flag should only be used for files accessed only by APR or other
+ * applications known to be able to decipher them.  APR does not
+ * guarantee that it will compress the file into sparse segments
+ * if it was previously created and written without the sparse flag.
+ * On platforms which do not understand, or on file systems which
+ * cannot handle sparse files, the flag is ignored by apr_file_open().
+ *
+ * @def APR_FOPEN_NONBLOCK
+ * @warning APR_FOPEN_NONBLOCK is not implemented on all platforms.
+ * Callers should be prepared for it to fail with #APR_ENOTIMPL.
  */
-ap_status_t ap_remove_file(char *path, ap_pool_t *cont);
-
-/*
-
-=head1 ap_status_t ap_eof(ap_file_t *fptr) 
-
-B<Are we at the end of the file>
-
-    arg 1) The apr file we are testing.
 
-B<NOTE>:  Returns APR_EOF if we are at the end of file, APR_SUCCESS otherwise.
+/** @} */
 
-=cut
+/**
+ * @defgroup apr_file_seek_flags File Seek Flags
+ * @{
  */
-ap_status_t ap_eof(ap_file_t *fptr);
 
-/*
-
-=head1 ap_status_t ap_ferror(ap_file_t *fptr) 
-
-B<Is there an error on the stream?>
-
-    arg 1) The apr file we are testing.
-
-B<NOTE>:  Returns -1 if the error indicator is set, APR_SUCCESS otherwise.
+/* flags for apr_file_seek */
+/** Set the file position */
+#define APR_SET SEEK_SET
+/** Current */
+#define APR_CUR SEEK_CUR
+/** Go to end of file */
+#define APR_END SEEK_END
+/** @} */
 
-=cut
+/**
+ * @defgroup apr_file_attrs_set_flags File Attribute Flags
+ * @{
  */
-ap_status_t ap_ferror(ap_file_t *fptr);
-
-/*
 
-=head1 ap_status_t ap_open_stderr(ap_file_t **thefile, ap_pool_t *cont) 
+/* flags for apr_file_attrs_set */
+#define APR_FILE_ATTR_READONLY   0x01          /**< File is read-only */
+#define APR_FILE_ATTR_EXECUTABLE 0x02          /**< File is executable */
+#define APR_FILE_ATTR_HIDDEN     0x04          /**< File is hidden */
+/** @} */
 
-B<open standard error as an apr file pointer.>
-
-    arg 1) The apr file to use as stderr.
-    arg 2) The pool to allocate the file out of.
-
-=cut
+/**
+ * @defgroup apr_file_writev{_full} max iovec size
+ * @{
  */
-ap_status_t ap_open_stderr(ap_file_t **thefile, ap_pool_t *cont);
-
-/*
-
-=head1 ap_status_t ap_read(ap_file_t *thefile, void *buf, ap_ssize_t *nbytes)
-
-B<Read data from the specified file.>
+#if defined(DOXYGEN)
+#define APR_MAX_IOVEC_SIZE 1024                /**< System dependent maximum 
+                                                    size of an iovec array */
+#elif defined(IOV_MAX)
+#define APR_MAX_IOVEC_SIZE IOV_MAX
+#elif defined(MAX_IOVEC)
+#define APR_MAX_IOVEC_SIZE MAX_IOVEC
+#else
+#define APR_MAX_IOVEC_SIZE 1024
+#endif
+/** @} */
 
-    arg 1) The file descriptor to read from.
-    arg 2) The buffer to store the data to.
-    arg 3) On entry, the number of bytes to read; on exit, the number
-           of bytes read.
+/** File attributes */
+typedef apr_uint32_t apr_fileattrs_t;
 
-B<NOTE>:  ap_read will read up to the specified number of bytes, but never
-   more.  If there isn't enough data to fill that number of bytes, all of
-   the available data is read.  The third argument is modified to reflect the
-   number of bytes read.  If a char was put back into the stream via
-   ungetc, it will be the first character returned. 
-  
-   It is possible for both bytes to be read and an APR_EOF or other error
-   to be returned.
-  
-   APR_EINTR is never returned.
+/** Type to pass as whence argument to apr_file_seek. */
+typedef int       apr_seek_where_t;
 
-=cut
+/**
+ * Structure for referencing files.
  */
-ap_status_t ap_read(ap_file_t *thefile, void *buf, ap_ssize_t *nbytes);
-
-/*
-
-=head1 ap_status_t ap_write(ap_file_t *thefile, void *buf, ap_ssize_t *nbytes)
+typedef struct apr_file_t         apr_file_t;
 
-B<Write data to the specified file.>
-
-    arg 1) The file descriptor to write to.
-    arg 2) The buffer which contains the data.
-    arg 3) On entry, the number of bytes to write; on exit, the number
-           of bytes write.
-
-B<NOTE>:  ap_write will write up to the specified number of bytes, but never
-   more.  If the OS cannot write that many bytes, it will write as many as it
-   can.  The third argument is modified to reflect the * number of bytes 
-   written. 
-  
-   It is possible for both bytes to be written and an error to be
-   returned.
-  
-   APR_EINTR is never returned.
-
-=cut
+/* File lock types/flags */
+/**
+ * @defgroup apr_file_lock_types File Lock Types
+ * @{
  */
-ap_status_t ap_write(ap_file_t *thefile, void *buf, ap_ssize_t *nbytes);
-
-/*
 
-=head1 ap_status_t ap_writev(ap_file_t *thefile, struct iovec *vec, ap_size_t nvec, ap_ssize_t *nbytes)
-
-B<Write data from iovec array to the specified file.>
-
-    arg 1) The file descriptor to write to.
-    arg 2) The array from which to get the data to write to the file.
-    arg 3) The number of elements in the struct iovec array. This must be
-           smaller than AP_MAX_IOVEC_SIZE.  If it isn't, the function will
-           fail with APR_EINVAL.
-    arg 4) The number of bytes written.
-  
-   It is possible for both bytes to be written and an error to be
-   returned.
-  
-   APR_EINTR is never returned.
-  
-   ap_writev is available even if the underlying operating system
-   doesn't provide writev().
-
-=cut
+#define APR_FLOCK_SHARED        1       /**< Shared lock. More than one process
+                                           or thread can hold a shared lock
+                                           at any given time. Essentially,
+                                           this is a "read lock", preventing
+                                           writers from establishing an
+                                           exclusive lock. */
+#define APR_FLOCK_EXCLUSIVE     2       /**< Exclusive lock. Only one process
+                                           may hold an exclusive lock at any
+                                           given time. This is analogous to
+                                           a "write lock". */
+
+#define APR_FLOCK_TYPEMASK      0x000F  /**< mask to extract lock type */
+#define APR_FLOCK_NONBLOCK      0x0010  /**< do not block while acquiring the
+                                           file lock */
+/** @} */
+
+/**
+ * Open the specified file.
+ * @param newf The opened file descriptor.
+ * @param fname The full path to the file (using / on all systems)
+ * @param flag Or'ed value of:
+ * @li #APR_FOPEN_READ           open for reading
+ * @li #APR_FOPEN_WRITE          open for writing
+ * @li #APR_FOPEN_CREATE         create the file if not there
+ * @li #APR_FOPEN_APPEND         file ptr is set to end prior to all writes
+ * @li #APR_FOPEN_TRUNCATE       set length to zero if file exists
+ * @li #APR_FOPEN_BINARY         not a text file
+ * @li #APR_FOPEN_BUFFERED       buffer the data.  Default is non-buffered
+ * @li #APR_FOPEN_EXCL           return error if #APR_FOPEN_CREATE and file exists
+ * @li #APR_FOPEN_DELONCLOSE     delete the file after closing
+ * @li #APR_FOPEN_XTHREAD        Platform dependent tag to open the file
+ *                               for use across multiple threads
+ * @li #APR_FOPEN_SHARELOCK      Platform dependent support for higher
+ *                               level locked read/write access to support
+ *                               writes across process/machines
+ * @li #APR_FOPEN_NOCLEANUP      Do not register a cleanup with the pool 
+ *                               passed in on the @a pool argument (see below)
+ * @li #APR_FOPEN_SENDFILE_ENABLED  Open with appropriate platform semantics
+ *                               for sendfile operations.  Advisory only,
+ *                               apr_socket_sendfile does not check this flag
+ * @li #APR_FOPEN_LARGEFILE      Platform dependent flag to enable large file
+ *                               support, see WARNING below 
+ * @li #APR_FOPEN_SPARSE         Platform dependent flag to enable sparse file
+ *                               support, see WARNING below
+ * @li #APR_FOPEN_ROTATING       Do file file rotation checking
+ * @li #APR_FOPEN_MANUAL_ROTATE  Enable Manual rotation
+ * @li #APR_FOPEN_NONBLOCK       Platform dependent flag to enable
+ *                               non blocking file io
+ * @param perm Access permissions for file.
+ * @param pool The pool to use.
+ * @remark If perm is #APR_FPROT_OS_DEFAULT and the file is being created,
+ * appropriate default permissions will be used.
+ * @remark By default, the returned file descriptor will not be
+ * inherited by child processes created by apr_proc_create().  This
+ * can be changed using apr_file_inherit_set().
  */
-ap_status_t ap_writev(ap_file_t *thefile, const struct iovec *vec, 
-                      ap_size_t nvec, ap_ssize_t *nbytes);
-
-/*
+APR_DECLARE(apr_status_t) apr_file_open(apr_file_t **newf, const char *fname,
+                                        apr_int32_t flag, apr_fileperms_t perm,
+                                        apr_pool_t *pool);
 
-=head1 ap_status_t ap_putc(char ch, ap_file_t *thefile)
-
-B<put a character into the specified file.>
-
-    arg 1) The character to write.
-    arg 2) The file descriptor to write to
-
-=cut
+/**
+ * Close the specified file.
+ * @param file The file descriptor to close.
  */
-ap_status_t ap_putc(char ch, ap_file_t *thefile);
-
-/*
-
-=head1 ap_status_t ap_getc(char *ch, ap_file_t *thefil)
-
-B<get a character from the specified file.>
-
-    arg 1) The character to write.
-    arg 2) The file descriptor to write to
-
-=cut
+APR_DECLARE(apr_status_t) apr_file_close(apr_file_t *file);
+
+/**
+ * Delete the specified file.
+ * @param path The full path to the file (using / on all systems)
+ * @param pool The pool to use.
+ * @remark If the file is open, it won't be removed until all
+ * instances are closed.
  */
-ap_status_t ap_getc(char *ch, ap_file_t *thefile);
-
-/*
-
-=head1 ap_status_t ap_ungetc(char ch, ap_file_t *thefile)
-
-B<put a character back onto a specified stream.>
-
-    arg 1) The character to write.
-    arg 2) The file descriptor to write to
-
-=cut
+APR_DECLARE(apr_status_t) apr_file_remove(const char *path, apr_pool_t *pool);
+
+/**
+ * Rename the specified file.
+ * @param from_path The full path to the original file (using / on all systems)
+ * @param to_path The full path to the new file (using / on all systems)
+ * @param pool The pool to use.
+ * @warning If a file exists at the new location, then it will be
+ * overwritten.  Moving files or directories across devices may not be
+ * possible.
  */
-ap_status_t ap_ungetc(char ch, ap_file_t *thefile);
-
-/*
-
-=head1 ap_status_t ap_fgets(char *str, int len, ap_file_t *thefile)
-
-B<Get a string from a specified file.>
-
-    arg 1) The buffer to store the string in. 
-    arg 2) The length of the string
-    arg 3) The file descriptor to read from
-
-=cut
+APR_DECLARE(apr_status_t) apr_file_rename(const char *from_path, 
+                                          const char *to_path,
+                                          apr_pool_t *pool);
+
+/**
+ * Create a hard link to the specified file.
+ * @param from_path The full path to the original file (using / on all systems)
+ * @param to_path The full path to the new file (using / on all systems)
+ * @remark Both files must reside on the same device.
  */
-ap_status_t ap_fgets(char *str, int len, ap_file_t *thefile);
-
-/*
-
-=head1 ap_status_t ap_puts(char *str, ap_file_t *thefile)
-
-B<Put the string into a specified file.>
-
-    arg 1) The string to write. 
-    arg 2) The file descriptor to write to from
-
-=cut
+APR_DECLARE(apr_status_t) apr_file_link(const char *from_path, 
+                                          const char *to_path);
+
+/**
+ * Copy the specified file to another file.
+ * @param from_path The full path to the original file (using / on all systems)
+ * @param to_path The full path to the new file (using / on all systems)
+ * @param perms Access permissions for the new file if it is created.
+ *     In place of the usual or'd combination of file permissions, the
+ *     value #APR_FPROT_FILE_SOURCE_PERMS may be given, in which case the source
+ *     file's permissions are copied.
+ * @param pool The pool to use.
+ * @remark The new file does not need to exist, it will be created if required.
+ * @warning If the new file already exists, its contents will be overwritten.
  */
-ap_status_t ap_puts(char *str, ap_file_t *thefile);
-
-/*
-
-=head1 ap_status_t ap_flush(ap_file_t *thefile)
-
-B<Flush the file's buffer.>
-
-    arg 1) The file descriptor to flush
-
-=cut
+APR_DECLARE(apr_status_t) apr_file_copy(const char *from_path, 
+                                        const char *to_path,
+                                        apr_fileperms_t perms,
+                                        apr_pool_t *pool);
+
+/**
+ * Append the specified file to another file.
+ * @param from_path The full path to the source file (use / on all systems)
+ * @param to_path The full path to the destination file (use / on all systems)
+ * @param perms Access permissions for the destination file if it is created.
+ *     In place of the usual or'd combination of file permissions, the
+ *     value #APR_FPROT_FILE_SOURCE_PERMS may be given, in which case the source
+ *     file's permissions are copied.
+ * @param pool The pool to use.
+ * @remark The new file does not need to exist, it will be created if required.
+ * @remark Note that advanced filesystem permissions such as ACLs are not
+ * duplicated by this API. The target permissions (including duplicating the
+ * source file permissions) are assigned only when the target file does not yet
+ * exist.
  */
-ap_status_t ap_flush(ap_file_t *thefile);
-API_EXPORT(int) ap_fprintf(ap_file_t *fptr, const char *format, ...)
-        __attribute__((format(printf,2,3)));
+APR_DECLARE(apr_status_t) apr_file_append(const char *from_path, 
+                                          const char *to_path,
+                                          apr_fileperms_t perms,
+                                          apr_pool_t *pool);
+
+/**
+ * Are we at the end of the file
+ * @param fptr The apr file we are testing.
+ * @remark Returns #APR_EOF if we are at the end of file, #APR_SUCCESS otherwise.
+ */
+APR_DECLARE(apr_status_t) apr_file_eof(apr_file_t *fptr);
+
+/**
+ * Open standard error as an apr file pointer.
+ * @param thefile The apr file to use as stderr.
+ * @param pool The pool to allocate the file out of.
+ * 
+ * @remark The only reason that the apr_file_open_std* functions exist
+ * is that you may not always have a stderr/out/in on Windows.  This
+ * is generally a problem with newer versions of Windows and services.
+ * 
+ * @remark The other problem is that the C library functions generally work
+ * differently on Windows and Unix.  So, by using apr_file_open_std*
+ * functions, you can get a handle to an APR struct that works with
+ * the APR functions which are supposed to work identically on all
+ * platforms.
+ */
+APR_DECLARE(apr_status_t) apr_file_open_stderr(apr_file_t **thefile,
+                                               apr_pool_t *pool);
+
+/**
+ * open standard output as an apr file pointer.
+ * @param thefile The apr file to use as stdout.
+ * @param pool The pool to allocate the file out of.
+ * 
+ * @remark See remarks for apr_file_open_stderr().
+ */
+APR_DECLARE(apr_status_t) apr_file_open_stdout(apr_file_t **thefile,
+                                               apr_pool_t *pool);
+
+/**
+ * open standard input as an apr file pointer.
+ * @param thefile The apr file to use as stdin.
+ * @param pool The pool to allocate the file out of.
+ * 
+ * @remark See remarks for apr_file_open_stderr().
+ */
+APR_DECLARE(apr_status_t) apr_file_open_stdin(apr_file_t **thefile,
+                                              apr_pool_t *pool);
+
+/**
+ * open standard error as an apr file pointer, with flags.
+ * @param thefile The apr file to use as stderr.
+ * @param flags The flags to open the file with. Only the 
+ *              @li #APR_FOPEN_EXCL
+ *              @li #APR_FOPEN_BUFFERED
+ *              @li #APR_FOPEN_XTHREAD
+ *              @li #APR_FOPEN_SHARELOCK 
+ *              @li #APR_FOPEN_SENDFILE_ENABLED
+ *              @li #APR_FOPEN_LARGEFILE
+ *
+ *              flags should be used. The #APR_FOPEN_WRITE flag will
+ *              be set unconditionally.
+ * @param pool The pool to allocate the file out of.
+ * 
+ * @remark See remarks for apr_file_open_stderr().
+ */
+APR_DECLARE(apr_status_t) apr_file_open_flags_stderr(apr_file_t **thefile,
+                                                     apr_int32_t flags,
+                                                     apr_pool_t *pool);
+
+/**
+ * open standard output as an apr file pointer, with flags.
+ * @param thefile The apr file to use as stdout.
+ * @param flags The flags to open the file with. Only the 
+ *              @li #APR_FOPEN_EXCL
+ *              @li #APR_FOPEN_BUFFERED
+ *              @li #APR_FOPEN_XTHREAD
+ *              @li #APR_FOPEN_SHARELOCK 
+ *              @li #APR_FOPEN_SENDFILE_ENABLED
+ *              @li #APR_FOPEN_LARGEFILE
+ *
+ *              flags should be used. The #APR_FOPEN_WRITE flag will
+ *              be set unconditionally.
+ * @param pool The pool to allocate the file out of.
+ * 
+ * @remark See remarks for apr_file_open_stderr().
+ */
+APR_DECLARE(apr_status_t) apr_file_open_flags_stdout(apr_file_t **thefile,
+                                                     apr_int32_t flags,
+                                                     apr_pool_t *pool);
+
+/**
+ * open standard input as an apr file pointer, with flags.
+ * @param thefile The apr file to use as stdin.
+ * @param flags The flags to open the file with. Only the 
+ *              @li #APR_FOPEN_EXCL
+ *              @li #APR_FOPEN_BUFFERED
+ *              @li #APR_FOPEN_XTHREAD
+ *              @li #APR_FOPEN_SHARELOCK 
+ *              @li #APR_FOPEN_SENDFILE_ENABLED
+ *              @li #APR_FOPEN_LARGEFILE
+ *
+ *              flags should be used. The #APR_FOPEN_WRITE flag will
+ *              be set unconditionally.
+ * @param pool The pool to allocate the file out of.
+ * 
+ * @remark See remarks for apr_file_open_stderr().
+ */
+APR_DECLARE(apr_status_t) apr_file_open_flags_stdin(apr_file_t **thefile,
+                                                     apr_int32_t flags,
+                                                     apr_pool_t *pool);
+
+/**
+ * Read data from the specified file.
+ * @param thefile The file descriptor to read from.
+ * @param buf The buffer to store the data to.
+ * @param nbytes On entry, the number of bytes to read; on exit, the number
+ * of bytes read.
+ *
+ * @remark apr_file_read() will read up to the specified number of
+ * bytes, but never more.  If there isn't enough data to fill that
+ * number of bytes, all of the available data is read.  The third
+ * argument is modified to reflect the number of bytes read.  If a
+ * char was put back into the stream via ungetc, it will be the first
+ * character returned.
+ *
+ * @remark It is not possible for both bytes to be read and an #APR_EOF
+ * or other error to be returned.  #APR_EINTR is never returned.
+ */
+APR_DECLARE(apr_status_t) apr_file_read(apr_file_t *thefile, void *buf,
+                                        apr_size_t *nbytes);
+
+/**
+ * Write data to the specified file.
+ * @param thefile The file descriptor to write to.
+ * @param buf The buffer which contains the data.
+ * @param nbytes On entry, the number of bytes to write; on exit, the number 
+ *               of bytes written.
+ *
+ * @remark apr_file_write() will write up to the specified number of
+ * bytes, but never more.  If the OS cannot write that many bytes, it
+ * will write as many as it can.  The third argument is modified to
+ * reflect the * number of bytes written.
+ *
+ * @remark It is possible for both bytes to be written and an error to
+ * be returned.  #APR_EINTR is never returned.
+ */
+APR_DECLARE(apr_status_t) apr_file_write(apr_file_t *thefile, const void *buf,
+                                         apr_size_t *nbytes);
+
+/**
+ * Write data from iovec array to the specified file.
+ * @param thefile The file descriptor to write to.
+ * @param vec The array from which to get the data to write to the file.
+ * @param nvec The number of elements in the struct iovec array. This must 
+ *             be smaller than #APR_MAX_IOVEC_SIZE.  If it isn't, the function 
+ *             will fail with #APR_EINVAL.
+ * @param nbytes The number of bytes written.
+ *
+ * @remark It is possible for both bytes to be written and an error to
+ * be returned.  #APR_EINTR is never returned.
+ *
+ * @remark apr_file_writev() is available even if the underlying
+ * operating system doesn't provide writev().
+ */
+APR_DECLARE(apr_status_t) apr_file_writev(apr_file_t *thefile,
+                                          const struct iovec *vec,
+                                          apr_size_t nvec, apr_size_t *nbytes);
+
+/**
+ * Read data from the specified file, ensuring that the buffer is filled
+ * before returning.
+ * @param thefile The file descriptor to read from.
+ * @param buf The buffer to store the data to.
+ * @param nbytes The number of bytes to read.
+ * @param bytes_read If non-NULL, this will contain the number of bytes read.
+ *
+ * @remark apr_file_read_full() will read up to the specified number of
+ * bytes, but never more.  If there isn't enough data to fill that
+ * number of bytes, then the process/thread will block until it is
+ * available or EOF is reached.  If a char was put back into the
+ * stream via ungetc, it will be the first character returned.
+ *
+ * @remark It is possible for both bytes to be read and an error to be
+ * returned.  And if *bytes_read is less than nbytes, an accompanying
+ * error is _always_ returned.
+ *
+ * @remark #APR_EINTR is never returned.
+ */
+APR_DECLARE(apr_status_t) apr_file_read_full(apr_file_t *thefile, void *buf,
+                                             apr_size_t nbytes,
+                                             apr_size_t *bytes_read);
+
+/**
+ * Write data to the specified file, ensuring that all of the data is
+ * written before returning.
+ * @param thefile The file descriptor to write to.
+ * @param buf The buffer which contains the data.
+ * @param nbytes The number of bytes to write.
+ * @param bytes_written If non-NULL, set to the number of bytes written.
+ * 
+ * @remark apr_file_write_full() will write up to the specified number of
+ * bytes, but never more.  If the OS cannot write that many bytes, the
+ * process/thread will block until they can be written. Exceptional
+ * error such as "out of space" or "pipe closed" will terminate with
+ * an error.
+ *
+ * @remark It is possible for both bytes to be written and an error to
+ * be returned.  And if *bytes_written is less than nbytes, an
+ * accompanying error is _always_ returned.
+ *
+ * @remark #APR_EINTR is never returned.
+ */
+APR_DECLARE(apr_status_t) apr_file_write_full(apr_file_t *thefile, 
+                                              const void *buf,
+                                              apr_size_t nbytes, 
+                                              apr_size_t *bytes_written);
+
+
+/**
+ * Write data from iovec array to the specified file, ensuring that all of the
+ * data is written before returning.
+ * @param thefile The file descriptor to write to.
+ * @param vec The array from which to get the data to write to the file.
+ * @param nvec The number of elements in the struct iovec array. This must 
+ *             be smaller than #APR_MAX_IOVEC_SIZE.  If it isn't, the function 
+ *             will fail with #APR_EINVAL.
+ * @param nbytes The number of bytes written.
+ *
+ * @remark apr_file_writev_full() is available even if the underlying
+ * operating system doesn't provide writev().
+ */
+APR_DECLARE(apr_status_t) apr_file_writev_full(apr_file_t *thefile,
+                                               const struct iovec *vec,
+                                               apr_size_t nvec,
+                                               apr_size_t *nbytes);
+/**
+ * Write a character into the specified file.
+ * @param ch The character to write.
+ * @param thefile The file descriptor to write to
+ */
+APR_DECLARE(apr_status_t) apr_file_putc(char ch, apr_file_t *thefile);
 
-/*
+/**
+ * Read a character from the specified file.
+ * @param ch The character to read into
+ * @param thefile The file descriptor to read from
+ */
+APR_DECLARE(apr_status_t) apr_file_getc(char *ch, apr_file_t *thefile);
 
-=head1 ap_status_t ap_dupfile(ap_file_t **new_file, ap_file_t *old_file, ap_pool_t *p)
+/**
+ * Put a character back onto a specified stream.
+ * @param ch The character to write.
+ * @param thefile The file descriptor to write to
+ */
+APR_DECLARE(apr_status_t) apr_file_ungetc(char ch, apr_file_t *thefile);
+
+/**
+ * Read a line from the specified file
+ * @param str The buffer to store the string in. 
+ * @param len The length of the string
+ * @param thefile The file descriptor to read from
+ * @remark The buffer will be NUL-terminated if any characters are stored.
+ *         The newline at the end of the line will not be stripped.
+ */
+APR_DECLARE(apr_status_t) apr_file_gets(char *str, int len, 
+                                        apr_file_t *thefile);
 
-B<duplicate the specified file descriptor.>
+/**
+ * Write the string into the specified file.
+ * @param str The string to write. 
+ * @param thefile The file descriptor to write to
+ */
+APR_DECLARE(apr_status_t) apr_file_puts(const char *str, apr_file_t *thefile);
+
+/**
+ * Wait for a pipe to be ready for input or output
+ * @param thepipe the pipe to wait on
+ * @param direction whether to wait for reading or writing to be ready
+ *        Can be either #APR_WAIT_READ or #APR_WAIT_WRITE
+ * @remark Will time out if thepipe has a time out set for it
+ */
+APR_DECLARE(apr_status_t) apr_file_pipe_wait(apr_file_t *thepipe,
+                                             apr_wait_type_t direction);
 
-    arg 1) The structure to duplicate into. 
-    arg 2) The file to duplicate.
-    arg 3) The pool to use for the new file.
+/**
+ * Flush the file's buffer.
+ * @param thefile The file descriptor to flush
+ */
+APR_DECLARE(apr_status_t) apr_file_flush(apr_file_t *thefile);
 
-B<NOTE>: *arg1 must point to a valid ap_file_t, or point to NULL
+/**
+ * Transfer all file modified data and metadata to disk.
+ * @param thefile The file descriptor to sync
+ */
+APR_DECLARE(apr_status_t) apr_file_sync(apr_file_t *thefile);
 
-=cut
+/**
+ * Transfer all file modified data to disk.
+ * @param thefile The file descriptor to sync
+ */
+APR_DECLARE(apr_status_t) apr_file_datasync(apr_file_t *thefile);
+
+/**
+ * Duplicate the specified file descriptor.
+ * @param new_file The structure to duplicate into. 
+ * @param old_file The file to duplicate.
+ * @param p The pool to use for the new file.
+ * @remark *new_file must point to a valid apr_file_t, or point to NULL.
  */         
-ap_status_t ap_dupfile(ap_file_t **new_file, ap_file_t *old_file, ap_pool_t *p);
-
-/*
-
-=head1 ap_status_t ap_getfileinfo(ap_finfo_t *finfo, ap_file_t *thefile)
-
-B<get the specified file's stats..>
-
-    arg 1) Where to store the information about the file.
-    arg 2) The file to get information about. 
-
-=cut
- */ 
-ap_status_t ap_getfileinfo(ap_finfo_t *finfo, ap_file_t *thefile);
-ap_status_t ap_stat(ap_finfo_t *finfo, const char *fname, ap_pool_t *cont);
-
-/*
-
-=head1 ap_status_t ap_stat(ap_file_t **finfo, char *fname, ap_pool_t *cont)
-
-B<get the specified file's stats.  The file is specified by filename, instead of using a pre-opened file.>
-
-    arg 1) Where to store the information about the file.
-    arg 2) The name of the file to stat.
-    arg 3) the pool to use to allocate the new file. 
-
-=cut
- */ 
-ap_status_t ap_stat(ap_finfo_t *finfo, const char *fname, ap_pool_t *cont);
-
-/*
-
-=head1 ap_status_t ap_seek(ap_file_t *thefile, ap_seek_where_t where, ap_off_t *offset)
-
-B<Move the read/write file offset to a specified byte within a file.>
-
-    arg 1) The file descriptor
-    arg 2) How to move the pointer, one of:
-              APR_SET  --  set the offset to offset
-              APR_CUR  --  add the offset to the current position 
-              APR_END  --  add the offset to the current file size 
-    arg 3) The offset to move the pointer to.
+APR_DECLARE(apr_status_t) apr_file_dup(apr_file_t **new_file,
+                                       apr_file_t *old_file,
+                                       apr_pool_t *p);
+
+/**
+ * Duplicate the specified file descriptor and close the original
+ * @param new_file The old file that is to be closed and reused
+ * @param old_file The file to duplicate
+ * @param p        The pool to use for the new file
+ *
+ * @remark new_file MUST point at a valid apr_file_t. It cannot be NULL.
+ */
+APR_DECLARE(apr_status_t) apr_file_dup2(apr_file_t *new_file,
+                                        apr_file_t *old_file,
+                                        apr_pool_t *p);
+
+/**
+ * Move the specified file descriptor to a new pool
+ * @param new_file Pointer in which to return the new apr_file_t
+ * @param old_file The file to move
+ * @param p        The pool to which the descriptor is to be moved
+ * @remark Unlike apr_file_dup2(), this function doesn't do an
+ *         OS dup() operation on the underlying descriptor; it just
+ *         moves the descriptor's apr_file_t wrapper to a new pool.
+ * @remark The new pool need not be an ancestor of old_file's pool.
+ * @remark After calling this function, old_file may not be used
+ */
+APR_DECLARE(apr_status_t) apr_file_setaside(apr_file_t **new_file,
+                                            apr_file_t *old_file,
+                                            apr_pool_t *p);
+
+/**
+ * Give the specified apr file handle a new buffer 
+ * @param thefile  The file handle that is to be modified
+ * @param buffer   The buffer
+ * @param bufsize  The size of the buffer
+ * @remark It is possible to add a buffer to previously unbuffered
+ *         file handles, the #APR_FOPEN_BUFFERED flag will be added to
+ *         the file handle's flags. Likewise, with buffer=NULL and
+ *         bufsize=0 arguments it is possible to make a previously
+ *         buffered file handle unbuffered.
+ */
+APR_DECLARE(apr_status_t) apr_file_buffer_set(apr_file_t *thefile,
+                                              char * buffer,
+                                              apr_size_t bufsize);
 
-B<NOTE>:  The third argument is modified to be the offset the pointer
+/**
+ * Get the size of any buffer for the specified apr file handle 
+ * @param thefile  The file handle 
+ */
+APR_DECLARE(apr_size_t) apr_file_buffer_size_get(apr_file_t *thefile);
+
+/**
+ * Move the read/write file offset to a specified byte within a file.
+ * @param thefile The file descriptor
+ * @param where How to move the pointer, one of:
+ *              @li #APR_SET  --  set the offset to offset
+ *              @li #APR_CUR  --  add the offset to the current position 
+ *              @li #APR_END  --  add the offset to the current file size 
+ * @param offset The offset to move the pointer to.
+ * @remark The third argument is modified to be the offset the pointer
           was actually moved to.
-
-=cut
  */
-ap_status_t ap_seek(ap_file_t *thefile, ap_seek_where_t where,ap_off_t *offset);
-
-/*
-
-=head1 ap_status_t ap_opendir(ap_dir_t **new, char *dirname, ap_pool_t *cont)
-
-B<Open the specified directory.>
-
-    arg 1) The opened directory descriptor.
-    arg 2) The full path to the directory (use / on all systems)
-    arg 3) The pool to use.
-
-=cut
- */                        
-ap_status_t ap_opendir(ap_dir_t **new, const char *dirname, ap_pool_t *cont);
-
-/*
-
-=head1 ap_status_t ap_closedir(ap_dir_t *thedir)
-
-B<close the specified directory.> 
-
-    arg 1) the directory descriptor to close.
-
-=cut
- */                        
-ap_status_t ap_closedir(ap_dir_t *thedir);
-
-/*
-
-=head1 ap_status_t ap_readdir(ap_dir_t *thedir)
-
-B<Read the next entry from the specified directory.> 
-
-    arg 1) the directory descriptor to read from, and fill out.
-
-B<NOTE>: All systems return . and .. as the first two files.
-
-=cut
- */                        
-ap_status_t ap_readdir(ap_dir_t *thedir);
-
-/*
-
-=head1 ap_status_t ap_rewinddir(ap_dir_t *thedir)
-
-B<Rewind the directory to the first entry.>
-
-     arg 1) the directory descriptor to rewind.
-
-=cut
- */                        
-ap_status_t ap_rewinddir(ap_dir_t *thedir);
-
-/*
-
-=head1 ap_status_t ap_make_dir(const char *path, ap_fileperms_t perm, ap_pool_t *cont)
-
-B<Create a new directory on the file system.>
-
-    arg 1) the path for the directory to be created.  (use / on all systems)
-    arg 2) Permissions for the new direcoty.
-    arg 3) the pool to use.
-
-=cut
- */                        
-ap_status_t ap_make_dir(const char *path, ap_fileperms_t perm, 
-                        ap_pool_t *cont);
-
-/*
-
-=head1 ap_status_t ap_remove_dir(const char *path, ap_pool_t *cont)
-
-B<Remove directory from the file system.>
-
-    arg 1) the path for the directory to be removed.  (use / on all systems)
-    arg 2) the pool to use.
-
-=cut
- */                        
-ap_status_t ap_remove_dir(const char *path, ap_pool_t *cont);
-
-/*
-
-=head1 ap_status_t ap_create_pipe(ap_file_t **in, ap_file_t **out, ap_pool_t *cont)
-
-B<Create an anonymous pipe.>
-
-    arg 1) The file descriptor to use as input to the pipe.
-    arg 2) The file descriptor to use as output from the pipe.
-    arg 3) The pool to operate on.
-
-=cut
+APR_DECLARE(apr_status_t) apr_file_seek(apr_file_t *thefile, 
+                                   apr_seek_where_t where,
+                                   apr_off_t *offset);
+
+/**
+ * Create an anonymous pipe.
+ * @param in The newly created pipe's file for reading.
+ * @param out The newly created pipe's file for writing.
+ * @param pool The pool to operate on.
+ * @remark By default, the returned file descriptors will be inherited
+ * by child processes created using apr_proc_create().  This can be
+ * changed using apr_file_inherit_unset().
+ * @bug  Some platforms cannot toggle between blocking and nonblocking,
+ * and when passing a pipe as a standard handle to an application which
+ * does not expect it, a non-blocking stream will fluxor the client app.
+ * @deprecated @see apr_file_pipe_create_pools()
  */
-ap_status_t ap_create_pipe(ap_file_t **in, ap_file_t **out, ap_pool_t *cont);
-
-/*
-
-=head1 ap_status_t ap_create_namedpipe(char *filename, ap_fileperms_t perm, ap_pool_t *cont)
-
-B<Create a named pipe.>
-
-    arg 1) The filename of the named pipe
-    arg 2) The permissions for the newly created pipe.
-    arg 3) The pool to operate on.
-
-=cut
+APR_DECLARE(apr_status_t) apr_file_pipe_create(apr_file_t **in, 
+                                               apr_file_t **out,
+                                               apr_pool_t *pool);
+
+/**
+ * Create an anonymous pipe which portably supports async timeout options.
+ * @param in The newly created pipe's file for reading.
+ * @param out The newly created pipe's file for writing.
+ * @param blocking one of these values defined in apr_thread_proc.h;
+ *                 @li #APR_FULL_BLOCK
+ *                 @li #APR_READ_BLOCK
+ *                 @li #APR_WRITE_BLOCK
+ *                 @li #APR_FULL_NONBLOCK
+ * @param pool The pool to operate on.
+ * @remark By default, the returned file descriptors will be inherited
+ * by child processes created using apr_proc_create().  This can be
+ * changed using apr_file_inherit_unset().
+ * @remark Some platforms cannot toggle between blocking and nonblocking,
+ * and when passing a pipe as a standard handle to an application which
+ * does not expect it, a non-blocking stream will fluxor the client app.
+ * Use this function rather than apr_file_pipe_create() to create pipes 
+ * where one or both ends require non-blocking semantics.
+ * @deprecated @see apr_file_pipe_create_pools()
  */
-ap_status_t ap_create_namedpipe(char *filename, ap_fileperms_t perm, 
-                                ap_pool_t *cont);
-
-/*
-
-=head1 ap_status_t ap_set_pipe_timeout(ap_file_t *thepipe, ap_int32_t timeout)
-
-B<Set the timeout value for a pipe.>
-
-    arg 1) The pipe we are setting a timeout on.
-    arg 2) The timeout value in seconds.  Values < 0 mean wait forever, 0
-           means do not wait at all.
-
-=cut
+APR_DECLARE(apr_status_t) apr_file_pipe_create_ex(apr_file_t **in, 
+                                                  apr_file_t **out, 
+                                                  apr_int32_t blocking, 
+                                                  apr_pool_t *pool);
+
+/**
+ * Create an anonymous pipe which portably supports async timeout options,
+ * placing each side of the pipe in a different pool.
+ * @param in The newly created pipe's file for reading.
+ * @param out The newly created pipe's file for writing.
+ * @param blocking one of these values defined in apr_thread_proc.h;
+ *                 @li #APR_FULL_BLOCK
+ *                 @li #APR_READ_BLOCK
+ *                 @li #APR_WRITE_BLOCK
+ *                 @li #APR_FULL_NONBLOCK
+ * @param pool_in The pool for the reading pipe.
+ * @param pool_out The pool for the writing pipe.
+ * @remark By default, the returned file descriptors will be inherited
+ * by child processes created using apr_proc_create().  This can be
+ * changed using apr_file_inherit_unset().
+ * @remark Some platforms cannot toggle between blocking and nonblocking,
+ * and when passing a pipe as a standard handle to an application which
+ * does not expect it, a non-blocking stream will fluxor the client app.
+ * Use this function rather than apr_file_pipe_create() to create pipes
+ * where one or both ends require non-blocking semantics.
  */
-ap_status_t ap_set_pipe_timeout(ap_file_t *thepipe, ap_interval_time_t timeout);
-
-/*
-
-=head1 ap_status_t ap_block_pipe(ap_file_t *thepipe)
-
-B<Set a pipe to use blocking I/O.>
-
-    arg 1) The pipe to operate on.
-
-=cut
+APR_DECLARE(apr_status_t) apr_file_pipe_create_pools(apr_file_t **in,
+                                                     apr_file_t **out,
+                                                     apr_int32_t blocking,
+                                                     apr_pool_t *pool_in,
+                                                     apr_pool_t *pool_out);
+
+/**
+ * Create a named pipe.
+ * @param filename The filename of the named pipe
+ * @param perm The permissions for the newly created pipe.
+ * @param pool The pool to operate on.
  */
-ap_status_t ap_block_pipe(ap_file_t *thepipe);
-
-/*accessor and general file_io functions. */
-
-/*
-
-=head1 ap_status_t ap_get_filename(char **new, ap_file_t *thefile)
+APR_DECLARE(apr_status_t) apr_file_namedpipe_create(const char *filename, 
+                                                    apr_fileperms_t perm, 
+                                                    apr_pool_t *pool);
+
+/**
+ * Get the timeout value for a pipe or manipulate the blocking state.
+ * @param thepipe The pipe we are getting a timeout for.
+ * @param timeout The current timeout value in microseconds. 
+ */
+APR_DECLARE(apr_status_t) apr_file_pipe_timeout_get(apr_file_t *thepipe, 
+                                               apr_interval_time_t *timeout);
+
+/**
+ * Set the timeout value for a pipe or manipulate the blocking state.
+ * @param thepipe The pipe we are setting a timeout on.
+ * @param timeout The timeout value in microseconds.  Values < 0 mean wait 
+ *        forever, 0 means do not wait at all.
+ */
+APR_DECLARE(apr_status_t) apr_file_pipe_timeout_set(apr_file_t *thepipe, 
+                                                  apr_interval_time_t timeout);
+
+/** file (un)locking functions. */
+
+/**
+ * Establish a lock on the specified, open file. The lock may be advisory
+ * or mandatory, at the discretion of the platform. The lock applies to
+ * the file as a whole, rather than a specific range. Locks are established
+ * on a per-thread/process basis; a second lock by the same thread will not
+ * block.
+ * @param thefile The file to lock.
+ * @param type The type of lock to establish on the file.
+ */
+APR_DECLARE(apr_status_t) apr_file_lock(apr_file_t *thefile, int type);
 
-B<return the file name of the current file.>
+/**
+ * Remove any outstanding locks on the file.
+ * @param thefile The file to unlock.
+ */
+APR_DECLARE(apr_status_t) apr_file_unlock(apr_file_t *thefile);
 
-    arg 1) The path of the file.  
-    arg 2) The currently open file.
+/**accessor and general file_io functions. */
 
-=cut
+/**
+ * return the file name of the current file.
+ * @param new_path The path of the file.  
+ * @param thefile The currently open file.
  */                     
-ap_status_t ap_get_filename(char **new, ap_file_t *thefile);
-
-/*
-
-=head1 ap_status_t ap_get_dir_filename(char **new, ap_dir_t *thedir) 
-
-B<Get the file name of the current directory entry.>
-
-    arg 1) the file name of the directory entry. 
-    arg 2) the currently open directory.
-
-=cut
- */                        
-ap_status_t ap_get_dir_filename(char **new, ap_dir_t *thedir);
-
-/*
-
-=head1 ap_status_t ap_get_filedata(void **data, char *key, ap_file_t *file)
-
-B<Return the data associated with the current file.>
-
-    arg 1) The user data associated with the file.  
-    arg 2) The key to use for retreiving data associated with this file.
-    arg 3) The currently open file.
-
-=cut
+APR_DECLARE(apr_status_t) apr_file_name_get(const char **new_path, 
+                                            apr_file_t *thefile);
+    
+/**
+ * Return the data associated with the current file.
+ * @param data The user data associated with the file.  
+ * @param key The key to use for retrieving data associated with this file.
+ * @param file The currently open file.
  */                     
-ap_status_t ap_get_filedata(void **data, char *key, ap_file_t *file);
-
-/*
-
-=head1 ap_status_t ap_set_filedata(ap_file_t *file, void *data, char *key, ap_status (*cleanup) (void *))
-
-B<Set the data associated with the current file.>
-
-    arg 1) The currently open file.
-    arg 2) The user data to associate with the file.  
-    arg 3) The key to use for assocaiteing data with the file.
-    arg 4) The cleanup routine to use when the file is destroyed.
-
-=cut
+APR_DECLARE(apr_status_t) apr_file_data_get(void **data, const char *key, 
+                                            apr_file_t *file);
+
+/**
+ * Set the data associated with the current file.
+ * @param file The currently open file.
+ * @param data The user data to associate with the file.  
+ * @param key The key to use for associating data with the file.
+ * @param cleanup The cleanup routine to use when the file is destroyed.
  */                     
-ap_status_t ap_set_filedata(ap_file_t *file, void *data, char *key,
-                            ap_status_t (*cleanup) (void *));
-
-/*
-
-=head1 ap_status_t ap_dir_entry_size(ap_ssize_t *size, ap_dir_t *thedir)
-
-B<Get the size of the current directory entry.>
-
-    arg 1) the size of the directory entry. 
-    arg 2) the currently open directory.
+APR_DECLARE(apr_status_t) apr_file_data_set(apr_file_t *file, void *data,
+                                            const char *key,
+                                            apr_status_t (*cleanup)(void *));
+
+/**
+ * Write a string to a file using a printf format.
+ * @param fptr The file to write to.
+ * @param format The format string
+ * @param ... The values to substitute in the format string
+ * @return The number of bytes written
+ */ 
+APR_DECLARE_NONSTD(int) apr_file_printf(apr_file_t *fptr, 
+                                        const char *format, ...)
+        __attribute__((format(printf,2,3)));
 
-=cut
+/**
+ * set the specified file's permission bits.
+ * @param fname The file (name) to apply the permissions to.
+ * @param perms The permission bits to apply to the file.
+ *
+ * @warning Some platforms may not be able to apply all of the
+ * available permission bits; #APR_INCOMPLETE will be returned if some
+ * permissions are specified which could not be set.
+ *
+ * @warning Platforms which do not implement this feature will return
+ * #APR_ENOTIMPL.
+ */
+APR_DECLARE(apr_status_t) apr_file_perms_set(const char *fname,
+                                             apr_fileperms_t perms);
+
+/**
+ * Set attributes of the specified file.
+ * @param fname The full path to the file (using / on all systems)
+ * @param attributes Or'd combination of
+ *            @li #APR_FILE_ATTR_READONLY   - make the file readonly
+ *            @li #APR_FILE_ATTR_EXECUTABLE - make the file executable
+ *            @li #APR_FILE_ATTR_HIDDEN     - make the file hidden
+ * @param attr_mask Mask of valid bits in attributes.
+ * @param pool the pool to use.
+ * @remark This function should be used in preference to explicit manipulation
+ *      of the file permissions, because the operations to provide these
+ *      attributes are platform specific and may involve more than simply
+ *      setting permission bits.
+ * @warning Platforms which do not implement this feature will return
+ *      #APR_ENOTIMPL.
+ */
+APR_DECLARE(apr_status_t) apr_file_attrs_set(const char *fname,
+                                             apr_fileattrs_t attributes,
+                                             apr_fileattrs_t attr_mask,
+                                             apr_pool_t *pool);
+
+/**
+ * Set the mtime of the specified file.
+ * @param fname The full path to the file (using / on all systems)
+ * @param mtime The mtime to apply to the file.
+ * @param pool The pool to use.
+ * @warning Platforms which do not implement this feature will return
+ *      #APR_ENOTIMPL.
+ */
+APR_DECLARE(apr_status_t) apr_file_mtime_set(const char *fname,
+                                             apr_time_t mtime,
+                                             apr_pool_t *pool);
+
+/**
+ * Create a new directory on the file system.
+ * @param path the path for the directory to be created. (use / on all systems)
+ * @param perm Permissions for the new directory.
+ * @param pool the pool to use.
+ */                        
+APR_DECLARE(apr_status_t) apr_dir_make(const char *path, apr_fileperms_t perm, 
+                                       apr_pool_t *pool);
+
+/** Creates a new directory on the file system, but behaves like
+ * 'mkdir -p'. Creates intermediate directories as required. No error
+ * will be reported if PATH already exists.
+ * @param path the path for the directory to be created. (use / on all systems)
+ * @param perm Permissions for the new directory.
+ * @param pool the pool to use.
+ */
+APR_DECLARE(apr_status_t) apr_dir_make_recursive(const char *path,
+                                                 apr_fileperms_t perm,
+                                                 apr_pool_t *pool);
+
+/**
+ * Remove directory from the file system.
+ * @param path the path for the directory to be removed. (use / on all systems)
+ * @param pool the pool to use.
+ * @remark Removing a directory which is in-use (e.g., the current working
+ * directory, or during apr_dir_read, or with an open file) is not portable.
  */                        
-ap_status_t ap_dir_entry_size(ap_ssize_t *size, ap_dir_t *thedir);
+APR_DECLARE(apr_status_t) apr_dir_remove(const char *path, apr_pool_t *pool);
 
-/*
+/**
+ * get the specified file's stats.
+ * @param finfo Where to store the information about the file.
+ * @param wanted The desired apr_finfo_t fields, as a bit flag of APR_FINFO_* values 
+ * @param thefile The file to get information about.
+ */ 
+APR_DECLARE(apr_status_t) apr_file_info_get(apr_finfo_t *finfo, 
+                                            apr_int32_t wanted,
+                                            apr_file_t *thefile);
+    
+
+/**
+ * Truncate the file's length to the specified offset
+ * @param fp The file to truncate
+ * @param offset The offset to truncate to.
+ * @remark The read/write file offset is repositioned to offset.
+ */
+APR_DECLARE(apr_status_t) apr_file_trunc(apr_file_t *fp, apr_off_t offset);
 
-=head1 ap_status_t ap_dir_entry_mtime(ap_time_t *mtime, ap_dir_t *thedir)
+/**
+ * Retrieve the flags that were passed into apr_file_open()
+ * when the file was opened.
+ * @return apr_int32_t the flags
+ */
+APR_DECLARE(apr_int32_t) apr_file_flags_get(apr_file_t *f);
 
-B<Get the last modified time of the current directory entry.>
+/**
+ * Get the pool used by the file.
+ */
+APR_POOL_DECLARE_ACCESSOR(file);
 
-    arg 1) the last modified time of the directory entry. 
-    arg 2) the currently open directory.
+/**
+ * Set a file to be inherited by child processes.
+ *
+ */
+APR_DECLARE_INHERIT_SET(file);
 
-=cut
- */                        
-ap_status_t ap_dir_entry_mtime(ap_time_t *mtime, ap_dir_t *thedir);
+/**
+ * Unset a file from being inherited by child processes.
+ */
+APR_DECLARE_INHERIT_UNSET(file);
+
+/**
+ * Open a temporary file
+ * @param fp The apr file to use as a temporary file.
+ * @param templ The template to use when creating a temp file.
+ * @param flags The flags to open the file with. If this is zero,
+ *              the file is opened with 
+ *              #APR_FOPEN_CREATE | #APR_FOPEN_READ | #APR_FOPEN_WRITE |
+ *              #APR_FOPEN_EXCL | #APR_FOPEN_DELONCLOSE
+ * @param p The pool to allocate the file out of.
+ * @remark   
+ * This function  generates  a unique temporary file name from template.  
+ * The last six characters of template must be XXXXXX and these are replaced 
+ * with a string that makes the filename unique. Since it will  be  modified,
+ * template must not be a string constant, but should be declared as a character
+ * array.  
+ *
+ */
+APR_DECLARE(apr_status_t) apr_file_mktemp(apr_file_t **fp, char *templ,
+                                          apr_int32_t flags, apr_pool_t *p);
 
-/*
 
-=head1 ap_status_t ap_dir_entry_ftype(ap_filetype_e *type, ap_dir_t *thedir)
+/**
+ * Find an existing directory suitable as a temporary storage location.
+ * @param temp_dir The temp directory.
+ * @param p The pool to use for any necessary allocations.
+ * @remark   
+ * This function uses an algorithm to search for a directory that an
+ * an application can use for temporary storage.
+ *
+ */
+APR_DECLARE(apr_status_t) apr_temp_dir_get(const char **temp_dir, 
+                                           apr_pool_t *p);
+
 
-B<Get the file type of the current directory entry.>
+APR_DECLARE(apr_status_t) apr_file_rotating_check(apr_file_t *thefile);
+APR_DECLARE(apr_status_t) apr_file_rotating_manual_check(apr_file_t *thefile, apr_time_t time);
 
-    arg 1) the file type of the directory entry. 
-    arg 2) the currently open directory.
+/** @} */
 
-=cut
- */                        
-ap_status_t ap_dir_entry_ftype(ap_filetype_e *type, ap_dir_t *thedir);
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif  /* ! APR_FILE_IO_H */
-
-
diff --git a/include/apr_fnmatch.h b/include/apr_fnmatch.h
index c0300b6389b..f8c26cf3e1b 100644
--- a/include/apr_fnmatch.h
+++ b/include/apr_fnmatch.h
@@ -1,4 +1,4 @@
-/*-
+/*
  * Copyright (c) 1992, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
@@ -37,28 +37,117 @@
 #ifndef	_APR_FNMATCH_H_
 #define	_APR_FNMATCH_H_
 
+/**
+ * @file apr_fnmatch.h
+ * @brief APR FNMatch Functions
+ */
+
 #include "apr_errno.h"
+#include "apr_tables.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-#define	FNM_NOMATCH	1	/* Match failed. */
+/**
+ * @defgroup apr_fnmatch Filename Matching Functions
+ * @ingroup APR 
+ * @{
+ */
+
+#define APR_FNM_NOMATCH     1     /**< Match failed. */
+ 
+#define APR_FNM_NOESCAPE    0x01  /**< Disable backslash escaping. */
+#define APR_FNM_PATHNAME    0x02  /**< Slash must be matched by slash. */
+#define APR_FNM_PERIOD      0x04  /**< Leading period must be matched by period. */
+#define APR_FNM_CASE_BLIND  0x08  /**< Compare characters case-insensitively. */
+
+/**
+ * Try to match the string to the given pattern, return APR_SUCCESS if
+ *    match, else return APR_FNM_NOMATCH.  Note that there is no such thing as
+ *    an illegal pattern.
+ *
+ * With all flags unset, a pattern is interpreted as such:
+ *
+ * PATTERN: Backslash followed by any character, including another
+ *          backslash.<br/>
+ * MATCHES: That character exactly.
+ * 
+ * <p>
+ * PATTERN: ?<br/>
+ * MATCHES: Any single character.
+ * </p>
+ * 
+ * <p>
+ * PATTERN: *<br/>
+ * MATCHES: Any sequence of zero or more characters. (Note that multiple
+ *          *s in a row are equivalent to one.)
+ * 
+ * PATTERN: Any character other than \?*[ or a \ at the end of the pattern<br/>
+ * MATCHES: That character exactly. (Case sensitive.)
+ * 
+ * PATTERN: [ followed by a class description followed by ]<br/>
+ * MATCHES: A single character described by the class description.
+ *          (Never matches, if the class description reaches until the
+ *          end of the string without a ].) If the first character of
+ *          the class description is ^ or !, the sense of the description
+ *          is reversed.  The rest of the class description is a list of
+ *          single characters or pairs of characters separated by -. Any
+ *          of those characters can have a backslash in front of them,
+ *          which is ignored; this lets you use the characters ] and -
+ *          in the character class, as well as ^ and ! at the
+ *          beginning.  The pattern matches a single character if it
+ *          is one of the listed characters or falls into one of the
+ *          listed ranges (inclusive, case sensitive).  Ranges with
+ *          the first character larger than the second are legal but
+ *          never match. Edge cases: [] never matches, and [^] and [!]
+ *          always match without consuming a character.
+ * 
+ * Note that these patterns attempt to match the entire string, not
+ * just find a substring matching the pattern.
+ *
+ * @param pattern The pattern to match to
+ * @param strings The string we are trying to match
+ * @param flags flags to use in the match.  Bitwise OR of:
+ * <pre>
+ *              APR_FNM_NOESCAPE       Disable backslash escaping
+ *              APR_FNM_PATHNAME       Slash must be matched by slash
+ *              APR_FNM_PERIOD         Leading period must be matched by period
+ *              APR_FNM_CASE_BLIND     Compare characters case-insensitively.
+ * </pre>
+ */
+
+APR_DECLARE(apr_status_t) apr_fnmatch(const char *pattern, 
+                                      const char *strings, int flags);
 
-#define	FNM_NOESCAPE	0x01	/* Disable backslash escaping. */
-#define	FNM_PATHNAME	0x02	/* Slash must be matched by slash. */
-#define	FNM_PERIOD	0x04	/* Period must be matched by period. */
-/* This flag is an Apache addition */
-#define FNM_CASE_BLIND  0x08    /* Compare characters case ap_pool_t nsensitively. */
+/**
+ * Determine if the given pattern is a regular expression.
+ * @param pattern The pattern to search for glob characters.
+ * @return non-zero if pattern has any glob characters in it
+ */
+APR_DECLARE(int) apr_fnmatch_test(const char *pattern);
 
-API_EXPORT(ap_status_t) ap_fnmatch(const char *pattern, const char *strings,
-			    int flags);
+/**
+ * Find all files that match a specified pattern in a directory.
+ * @param dir_pattern The pattern to use for finding files, appended
+ * to the search directory.  The pattern is anything following the
+ * final forward or backward slash in the parameter.  If no slash
+ * is found, the current directory is searched.
+ * @param result Array to use when storing the results
+ * @param p The pool to use.
+ * @return APR_SUCCESS if no processing errors occurred, APR error
+ * code otherwise
+ * @remark The returned array may be empty even if APR_SUCCESS was
+ * returned.
+ */
+APR_DECLARE(apr_status_t) apr_match_glob(const char *dir_pattern, 
+                                         apr_array_header_t **result,
+                                         apr_pool_t *p);
 
-/* this function is an Apache addition */
-API_EXPORT(int) ap_is_fnmatch(const char *pattern);
+/** @} */
 
 #ifdef __cplusplus
 }
 #endif
 
-#endif /* !_FNMATCH_H_ */
+#endif /* !_APR_FNMATCH_H_ */
diff --git a/include/apr_general.h b/include/apr_general.h
index 5e86b6bc58d..07b49f59fbe 100644
--- a/include/apr_general.h
+++ b/include/apr_general.h
@@ -1,375 +1,253 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 APR_GENERAL_H
 #define APR_GENERAL_H
 
+/**
+ * @file apr_general.h
+ * This is collection of oddballs that didn't fit anywhere else,
+ * and might move to more appropriate headers with the release
+ * of APR 1.0.
+ * @brief APR Miscellaneous library routines
+ */
+
 #include "apr.h"
+#include "apr_pools.h"
+#include "apr_errno.h"
 
-#if APR_HAVE_STDIO_H
-#include <stdio.h>
-#endif
-#if APR_HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
 #if APR_HAVE_SIGNAL_H
 #include <signal.h>
 #endif
-#include "apr_errno.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif /* __cplusplus */
 
-#define TRUE 1
-#define FALSE 0
-
-#define MAXIMUM_WAIT_OBJECTS 64
-
-typedef int               ap_signum_t;
+/**
+ * @defgroup apr_general Miscellaneous library routines
+ * @ingroup APR 
+ * This is collection of oddballs that didn't fit anywhere else,
+ * and might move to more appropriate headers with the release
+ * of APR 1.0.
+ * @{
+ */
 
-#ifdef SIGHUP
-#define APR_SIGHUP SIGHUP
-#endif
-#ifdef SIGINT
-#define APR_SIGINT SIGINT
-#endif
-#ifdef SIGQUIT
-#define APR_SIGQUIT SIGQUIT
-#endif
-#ifdef SIGILL
-#define APR_SIGILL SIGILL
-#endif
-#ifdef SIGTRAP
-#define APR_SIGTRAP SIGTRAP
-#endif
-#ifdef SIGABRT
-#define APR_SIGABRT SIGABRT
-#endif
-#ifdef SIGIOT
-#define APR_SIGIOT SIGIOT
-#endif
-#ifdef SIGBUS
-#define APR_SIGBUS SIGBUS
-#endif
-#ifdef SIGFPE
-#define APR_SIGFPE SIGFPE
-#endif
-#ifdef SIGKILL
-#define APR_SIGKILL SIGKILL
-#endif
-#ifdef SIGUSR1
-#define APR_SIGUSR1 SIGUSR1
-#endif
-#ifdef SIGSEGV
-#define APR_SIGSEGV SIGSEGV
-#endif
-#ifdef SIGUSR2
-#define APR_SIGUSR2 SIGUSR2
-#endif
-#ifdef SIGPIPE
-#define APR_SIGPIPE SIGPIPE
-#endif
-#ifdef SIGALRM
-#define APR_SIGALRM SIGALRM
-#endif
-#ifdef SIGTERM
-#define APR_SIGTERM SIGTERM
-#endif
-#ifdef SIGSTKFLT
-#define APR_SIGSTKFLT SIGSTKFLT
-#endif
-#ifdef SIGCHLD
-#define APR_SIGCHLD SIGCHLD
-#endif
-#ifdef SIGCONT
-#define APR_SIGCONT SIGCONT
-#endif
-#ifdef SIGSTOP
-#define APR_SIGSTOP SIGSTOP
-#endif
-#ifdef SIGTSTP
-#define APR_SIGTSTP SIGTSTP
-#endif
-#ifdef SIGTTIN
-#define APR_SIGTTIN SIGTTIN
-#endif
-#ifdef SIGTTOU
-#define APR_SIGTTOU SIGTTOU
-#endif
-#ifdef SIGURG
-#define APR_SIGURG SIGURG
-#endif
-#ifdef SIGXCPU
-#define APR_SIGXCPU SIGXCPU
-#endif
-#ifdef SIGXFSZ
-#define APR_SIGXFSZ SIGXFSZ
-#endif
-#ifdef SIGVTALRM
-#define APR_SIGVTALRM SIGVTALRM
-#endif
-#ifdef SIGPROF
-#define APR_SIGPROF SIGPROF
-#endif
-#ifdef SIGWINCH
-#define APR_SIGWINCH SIGWINCH
+/** FALSE */
+#ifndef FALSE
+#define FALSE 0
 #endif
-#ifdef SIGIO
-#define APR_SIGIO SIGIO
+/** TRUE */
+#ifndef TRUE
+#define TRUE (!FALSE)
 #endif
 
-#ifdef WIN32
-#define APR_INLINE __inline
-#elif defined(__GNUC__) && defined(__GNUC__) && \
-      __GNUC__ >= 2 && __GNUC_MINOR__ >= 7
-#define APR_INLINE __inline__
-#else
-#define APR_INLINE /*nop*/
-#endif
+/** a space */
+#define APR_ASCII_BLANK  '\040'
+/** a carrige return */
+#define APR_ASCII_CR     '\015'
+/** a line feed */
+#define APR_ASCII_LF     '\012'
+/** a tab */
+#define APR_ASCII_TAB    '\011'
+
+/** signal numbers typedef */
+typedef int               apr_signum_t;
+
+/* Type of I/O to wait for */
+typedef enum { APR_WAIT_READ, APR_WAIT_WRITE } apr_wait_type_t;
 
-/* Finding offsets of elements within structures.
+/**
+ * Finding offsets of elements within structures.
  * Taken from the X code... they've sweated portability of this stuff
  * so we don't have to.  Sigh...
+ * @param p_type pointer type name
+ * @param field  data field within the structure pointed to
+ * @return offset
  */
 
-#if defined(CRAY) || (defined(__arm) && !defined(LINUX))
+#if defined(CRAY) || (defined(__arm) && !(defined(LINUX) || defined(__FreeBSD__)))
 #ifdef __STDC__
-#define XtOffset(p_type,field) _Offsetof(p_type,field)
+#define APR_OFFSET(p_type,field) _Offsetof(p_type,field)
 #else
 #ifdef CRAY2
-#define XtOffset(p_type,field) \
+#define APR_OFFSET(p_type,field) \
         (sizeof(int)*((unsigned int)&(((p_type)NULL)->field)))
 
 #else /* !CRAY2 */
 
-#define XtOffset(p_type,field) ((unsigned int)&(((p_type)NULL)->field))
+#define APR_OFFSET(p_type,field) ((unsigned int)&(((p_type)NULL)->field))
 
 #endif /* !CRAY2 */
 #endif /* __STDC__ */
 #else /* ! (CRAY || __arm) */
 
-#define XtOffset(p_type,field) \
+#define APR_OFFSET(p_type,field) \
         ((long) (((char *) (&(((p_type)NULL)->field))) - ((char *) NULL)))
 
 #endif /* !CRAY */
 
-#ifdef offsetof
-#define XtOffsetOf(s_type,field) offsetof(s_type,field)
+/**
+ * Finding offsets of elements within structures.
+ * @param s_type structure type name
+ * @param field  data field within the structure
+ * @return offset
+ */
+#if defined(offsetof) && !defined(__cplusplus)
+#define APR_OFFSETOF(s_type,field) offsetof(s_type,field)
 #else
-#define XtOffsetOf(s_type,field) XtOffset(s_type*,field)
+#define APR_OFFSETOF(s_type,field) APR_OFFSET(s_type*,field)
 #endif
 
-#if APR_HAS_RANDOM
-/*
-
-=head1 ap_status_t ap_generate_random_bytes(unsigned char * buf, int length)
-
-B<Generate a string of random bytes.>
+#ifndef DOXYGEN
 
-    arg 1) Random bytes go here
-    arg 2) size of the buffer
-
-=cut
+/* A couple of prototypes for functions in case some platform doesn't 
+ * have it
  */
-/* TODO: I'm not sure this is the best place to put this prototype...*/
-ap_status_t ap_generate_random_bytes(unsigned char * buf, int length);
+#if (!APR_HAVE_STRCASECMP) && (APR_HAVE_STRICMP) 
+#define strcasecmp(s1, s2) stricmp(s1, s2)
+#elif (!APR_HAVE_STRCASECMP)
+int strcasecmp(const char *a, const char *b);
 #endif
 
-typedef struct ap_pool_t {
-    union block_hdr *first;
-    union block_hdr *last;
-    struct cleanup *cleanups;
-    struct process_chain *subprocesses;
-    struct ap_pool_t *sub_pools;
-    struct ap_pool_t *sub_next;
-    struct ap_pool_t *sub_prev;
-    struct ap_pool_t *parent;
-    char *free_first_avail;
-#ifdef ALLOC_USE_MALLOC
-    void *allocation_list;
+#if (!APR_HAVE_STRNCASECMP) && (APR_HAVE_STRNICMP)
+#define strncasecmp(s1, s2, n) strnicmp(s1, s2, n)
+#elif (!APR_HAVE_STRNCASECMP)
+int strncasecmp(const char *a, const char *b, size_t n);
 #endif
-#ifdef POOL_DEBUG
-    ap_pool_t *joined;
-#endif
-    int (*apr_abort)(int retcode);
-    struct datastruct *prog_data;
-}ap_pool_t;
- 
-/* pool functions */
-/*
-
-=head1 ap_status_t ap_create_pool(ap_pool_t **newcont, ap_pool_t *cont)
-
-B<Create a new pool.>
 
-    arg 1) The pool we have just created.
-    arg 2) The parent pool.  If this is NULL, the new pool is a root
-           pool.  If it is non-NULL, the new pool will inherit all
-           of it's parent pool's attributes, except the ap_pool_t will 
-           be a sub-pool.
+#endif
 
-=cut
+/**
+ * Alignment macros
  */
-ap_status_t ap_create_pool(ap_pool_t **newcont, ap_pool_t *cont);
-
-/*
 
-=head1 ap_status_t ap_destroy_pool(ap_pool_t *cont)
+/* APR_ALIGN() is only to be used to align on a power of 2 boundary */
+#define APR_ALIGN(size, boundary) \
+    (((size) + ((boundary) - 1)) & ~((boundary) - 1))
 
-B<Free the pool and all of it's child pools'.>
+/** Default alignment */
+#define APR_ALIGN_DEFAULT(size) APR_ALIGN(size, 8)
 
-    arg 1) The pool to free.
 
-=cut
+/**
+ * String and memory functions
  */
 
-ap_status_t ap_exit(ap_pool_t *);
-
-/*
-
-=head1 ap_status_t ap_set_userdata(void *data, char *key, ap_status_t (*cleanup) (void *), ap_pool_t *cont)
-
-B<Set the data associated with the current pool>.
+/* APR_STRINGIFY is defined here, and also in apr_release.h, so wrap it */
+#ifndef APR_STRINGIFY
+/** Properly quote a value as a string in the C preprocessor */
+#define APR_STRINGIFY(n) APR_STRINGIFY_HELPER(n)
+/** Helper macro for APR_STRINGIFY */
+#define APR_STRINGIFY_HELPER(n) #n
+#endif
 
-    arg 1) The user data associated with the pool.
-    arg 2) The key to use for association
-    arg 3) The cleanup program to use to cleanup the data;
-    arg 4) The current pool.
+#if (!APR_HAVE_MEMMOVE)
+#define memmove(a,b,c) bcopy(b,a,c)
+#endif
 
-B<NOTE>:  The data to be attached to the pool should have the same
-          life span as the pool it is being attached to.
-          
-          Users of APR must take EXTREME care when choosing a key to
-          use for their data.  It is possible to accidentally overwrite
-          data by choosing a key that another part of the program is using
-          It is advised that steps are taken to ensure that a unique
-          key is used at all times.
+#if (!APR_HAVE_MEMCHR)
+void *memchr(const void *s, int c, size_t n);
+#endif
 
-=cut
+/**
+ * Macro to provide a way to turn an incomplete type into a complete
+ * type containing common pointers for a provider.
  */
-ap_status_t ap_set_userdata(void *data, char *key, 
-                            ap_status_t (*cleanup) (void *), 
-                            ap_pool_t *cont);
+#define APR_TYPEDEF_STRUCT(type, incompletion) \
+struct type { \
+   incompletion \
+   void *unk[]; \
+};
 
-/*
+/** @} */
 
-=head1 ap_status_t ap_get_userdata(void **data, char *key, ap_pool_t *cont)
-
-B<Return the data associated with the current pool.>
-
-    arg 1) The key for the data to retrieve
-    arg 2) The user data associated with the pool.
-    arg 3) The current pool.
-
-=cut
+/**
+ * @defgroup apr_library Library initialization and termination
+ * @{
  */
-ap_status_t ap_get_userdata(void **, char *key, ap_pool_t *cont);
-
-/*
-
-=head1 ap_status_t ap_initialize(void)
-
-B<Setup any APR internal data structures.  This MUST be the first function called for any APR program.>
 
-=cut
+/**
+ * Setup any APR internal data structures.  This MUST be the first function 
+ * called for any APR library. It is safe to call apr_initialize several
+ * times as long as apr_terminate is called the same number of times.
+ * @remark See apr_app_initialize if this is an application, rather than
+ * a library consumer of apr.
  */
-ap_status_t ap_initialize(void);
-
-/*
-
-=head1 void ap_terminate(void)
-
-B<Tear down any APR internal data structures which aren't torn down automatically.>
-
-B<NOTE>:  An APR program must call this function at termination once it 
-          has stopped using APR services.
-
-=cut
+APR_DECLARE(apr_status_t) apr_initialize(void);
+
+/**
+ * Set up an application with normalized argc, argv (and optionally env) in
+ * order to deal with platform-specific oddities, such as Win32 services,
+ * code pages and signals.  This must be the first function called for any
+ * APR program.
+ * @param argc Pointer to the argc that may be corrected
+ * @param argv Pointer to the argv that may be corrected
+ * @param env Pointer to the env that may be corrected, may be NULL
+ * @remark See apr_initialize if this is a library consumer of apr.
+ * Otherwise, this call is identical to apr_initialize, and must be closed
+ * with a call to apr_terminate at the end of program execution.
  */
-void ap_terminate(void);
-
-/*
-
-=head1 ap_status_t ap_set_abort(int (*apr_abort)(int retcode), ap_pool_t *cont)
-
-B<Set the APR_ABORT function.>
-
-B<NOTE>:  This is in for backwards compatability.  If the program using
-          APR wants APR to exit on a memory allocation error, then this
-          function should be called to set the function to use in order
-          to actually exit the program.  If this function is not called,
-          then APR will return an error and expect the calling program to
-          deal with the error accordingly.
-
-=cut
+APR_DECLARE(apr_status_t) apr_app_initialize(int *argc, 
+                                             char const * const * *argv, 
+                                             char const * const * *env);
+
+/**
+ * Tear down any APR internal data structures which aren't torn down 
+ * automatically. apr_terminate must be called once for every call to
+ * apr_initialize() or apr_app_initialize().
+ * @remark An APR program must call this function at termination once it 
+ *         has stopped using APR services.  The APR developers suggest using
+ *         atexit to ensure this is called.  When using APR from a language
+ *         other than C that has problems with the calling convention, use
+ *         apr_terminate2() instead.
  */
-ap_status_t ap_set_abort(int (*apr_abort)(int retcode), ap_pool_t *cont);
-
-/*
+APR_DECLARE_NONSTD(void) apr_terminate(void);
+
+/**
+ * Tear down any APR internal data structures which aren't torn down 
+ * automatically, same as apr_terminate
+ * @remark An APR program must call either the apr_terminate or apr_terminate2 
+ *         function once it it has finished using APR services.  The APR 
+ *         developers suggest using atexit(apr_terminate) to ensure this is done.
+ *         apr_terminate2 exists to allow non-c language apps to tear down apr, 
+ *         while apr_terminate is recommended from c language applications.
+ */
+APR_DECLARE(void) apr_terminate2(void);
 
-=head1 char *ap_strerror(ap_status_t statcode, char *buf, ap_size_t bufsize)
+/** @} */
 
-B<Return a human readable string describing the specified error.>
+/**
+ * @defgroup apr_random Random Functions
+ * @{
+ */
 
-    arg 1)  The error code the get a string for.
-    arg 2)  A buffer to hold the error string.
-    arg 3)  Size of the buffer to hold the string.
+#if APR_HAS_RANDOM || defined(DOXYGEN)
 
-=cut
+/* TODO: I'm not sure this is the best place to put this prototype...*/
+/**
+ * Generate random bytes.
+ * @param buf Buffer to fill with random bytes
+ * @param length Length of buffer in bytes
  */
-char *ap_strerror(ap_status_t statcode, char *buf, ap_size_t bufsize);
+APR_DECLARE(apr_status_t) apr_generate_random_bytes(unsigned char * buf, 
+                                                    apr_size_t length);
+
+#endif
+/** @} */
 
 #ifdef __cplusplus
 }
diff --git a/include/apr_getopt.h b/include/apr_getopt.h
index f9ae7603f91..75ad5663a0c 100644
--- a/include/apr_getopt.h
+++ b/include/apr_getopt.h
@@ -1,95 +1,160 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 APR_GETOPT_H
 #define APR_GETOPT_H
 
-API_VAR_IMPORT int
-    ap_opterr,                          /* if error message should be printed */
-    ap_optind,                          /* index into parent argv vector */
-    ap_optopt,                          /* character checked for validity */
-    ap_optreset;                        /* reset getopt */
-API_VAR_IMPORT char *
-    ap_optarg;                          /* argument associated with option */
+/**
+ * @file apr_getopt.h
+ * @brief APR Command Arguments (getopt)
+ */
+
+#include "apr_pools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
 
-/*
+/**
+ * @defgroup apr_getopt Command Argument Parsing
+ * @ingroup APR 
+ * @{
+ */
 
-=head1 ap_status_t ap_getopt(ap_int32_t nargc, char *const *nargv, const char *ostr, ap_int32_t *rv, ap_pool_t *cont)
+/** 
+ * An @c apr_getopt_t error callback function.
+ *
+ * @a arg is this @c apr_getopt_t's @c errarg member.
+ */
+typedef void (apr_getopt_err_fn_t)(void *arg, const char *err, ...);
 
-B<Parse the command line options passed to the program.>
+/** @see apr_getopt_t */
+typedef struct apr_getopt_t apr_getopt_t;
 
-    arg 1) The number of arguments passed to ap_getopt to parse
-    arg 2) The array of command line options to parse
-    arg 3) A string of characters that are acceptable options to the program.
-           characters followed by ":" are required to have an option 
-           associated 
-    arg 4) The next option found.  There are four potential values for 
-           this variable on exit. They are:
-               APR_EOF    --  No more options to parse
-               APR_BADCH  --  Found a bad option character
-               APR_BADARG --  Missing parameter for the found option
-               Other      --  The next option found.
-    arg 5) The pool to operate on.
+/**
+ * Structure to store command line argument information.
+ */ 
+struct apr_getopt_t {
+    /** context for processing */
+    apr_pool_t *cont;
+    /** function to print error message (NULL == no messages) */
+    apr_getopt_err_fn_t *errfn;
+    /** user defined first arg to pass to error message  */
+    void *errarg;
+    /** index into parent argv vector */
+    int ind;
+    /** character checked for validity */
+    int opt;
+    /** reset getopt */
+    int reset;
+    /** count of arguments */
+    int argc;
+    /** array of pointers to arguments */
+    const char **argv;
+    /** argument associated with option */
+    char const* place;
+    /** set to nonzero to support interleaving options with regular args */
+    int interleave;
+    /** start of non-option arguments skipped for interleaving */
+    int skip_start;
+    /** end of non-option arguments skipped for interleaving */
+    int skip_end;
+};
 
-B<NOTE>:  Arguments 2 and 3 are most commonly argc and argv from 
-          main(argc, argv)
+/** @see apr_getopt_option_t */
+typedef struct apr_getopt_option_t apr_getopt_option_t;
 
-=cut
+/**
+ * Structure used to describe options that getopt should search for.
  */
-ap_status_t ap_getopt(ap_int32_t nargc, char *const *nargv, const char *ostr,
-                      ap_int32_t *rv, ap_pool_t *cont);
+struct apr_getopt_option_t {
+    /** long option name, or NULL if option has no long name */
+    const char *name;
+    /** option letter, or a value greater than 255 if option has no letter */
+    int optch;
+    /** nonzero if option takes an argument */
+    int has_arg;
+    /** a description of the option */
+    const char *description;
+};
 
-#endif  /* ! APR_GETOPT_H */
+/**
+ * Initialize the arguments for parsing by apr_getopt().
+ * @param os   The options structure created for apr_getopt()
+ * @param cont The pool to operate on
+ * @param argc The number of arguments to parse
+ * @param argv The array of arguments to parse
+ * @remark Arguments 3 and 4 are most commonly argc and argv from main(argc, argv)
+ * The (*os)->errfn is initialized to fprintf(stderr... but may be overridden.
+ */
+APR_DECLARE(apr_status_t) apr_getopt_init(apr_getopt_t **os, apr_pool_t *cont,
+                                      int argc, const char * const *argv);
 
+/**
+ * Parse the options initialized by apr_getopt_init().
+ * @param os     The apr_opt_t structure returned by apr_getopt_init()
+ * @param opts   A string of characters that are acceptable options to the 
+ *               program.  Characters followed by ":" are required to have an 
+ *               option associated
+ * @param option_ch  The next option character parsed
+ * @param option_arg The argument following the option character:
+ * @return There are four potential status values on exit. They are:
+ * <PRE>
+ *             APR_EOF      --  No more options to parse
+ *             APR_BADCH    --  Found a bad option character
+ *             APR_BADARG   --  No argument followed the option flag
+ *             APR_SUCCESS  --  The next option was found.
+ * </PRE>
+ */
+APR_DECLARE(apr_status_t) apr_getopt(apr_getopt_t *os, const char *opts, 
+                                     char *option_ch, const char **option_arg);
+
+/**
+ * Parse the options initialized by apr_getopt_init(), accepting long
+ * options beginning with "--" in addition to single-character
+ * options beginning with "-".
+ * @param os     The apr_getopt_t structure created by apr_getopt_init()
+ * @param opts   A pointer to a list of apr_getopt_option_t structures, which
+ *               can be initialized with { "name", optch, has_args }.  has_args
+ *               is nonzero if the option requires an argument.  A structure
+ *               with an optch value of 0 terminates the list.
+ * @param option_ch  Receives the value of "optch" from the apr_getopt_option_t
+ *                   structure corresponding to the next option matched.
+ * @param option_arg Receives the argument following the option, if any.
+ * @return There are four potential status values on exit.   They are:
+ * <PRE>
+ *             APR_EOF      --  No more options to parse
+ *             APR_BADCH    --  Found a bad option character
+ *             APR_BADARG   --  No argument followed the option flag
+ *             APR_SUCCESS  --  The next option was found.
+ * </PRE>
+ * When APR_SUCCESS is returned, os->ind gives the index of the first
+ * non-option argument.  On error, a message will be printed to stdout unless
+ * os->err is set to 0.  If os->interleave is set to nonzero, options can come
+ * after arguments, and os->argv will be permuted to leave non-option arguments
+ * at the end (the original argv is unaffected).
+ */
+APR_DECLARE(apr_status_t) apr_getopt_long(apr_getopt_t *os,
+					  const apr_getopt_option_t *opts,
+					  int *option_ch,
+                                          const char **option_arg);
+/** @} */
 
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* ! APR_GETOPT_H */
diff --git a/include/apr_global_mutex.h b/include/apr_global_mutex.h
new file mode 100644
index 00000000000..d57ca453d9f
--- /dev/null
+++ b/include/apr_global_mutex.h
@@ -0,0 +1,196 @@
+/* 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 APR_GLOBAL_MUTEX_H
+#define APR_GLOBAL_MUTEX_H
+
+/**
+ * @file apr_global_mutex.h
+ * @brief APR Global Locking Routines
+ */
+
+#include "apr.h"
+#include "apr_proc_mutex.h"    /* only for apr_lockmech_e */
+#include "apr_pools.h"
+#include "apr_errno.h"
+#if APR_PROC_MUTEX_IS_GLOBAL
+#include "apr_proc_mutex.h"
+#endif
+#include "apr_time.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup APR_GlobalMutex Global Locking Routines
+ * @ingroup APR 
+ * @{
+ */
+
+#if !APR_PROC_MUTEX_IS_GLOBAL || defined(DOXYGEN)
+
+/** Opaque global mutex structure. */
+typedef struct apr_global_mutex_t apr_global_mutex_t;
+
+/*   Function definitions */
+
+/**
+ * Create and initialize a mutex that can be used to synchronize both
+ * processes and threads. Note: There is considerable overhead in using
+ * this API if only cross-process or cross-thread mutual exclusion is
+ * required. See apr_proc_mutex.h and apr_thread_mutex.h for more
+ * specialized lock routines.
+ * @param mutex the memory address where the newly created mutex will be
+ *        stored.
+ * @param fname A file name to use if the lock mechanism requires one.  This
+ *        argument should always be provided.  The lock code itself will
+ *        determine if it should be used.
+ * @param mech The mechanism to use for the interprocess lock, if any; one of
+ * <PRE>
+ *            APR_LOCK_FCNTL
+ *            APR_LOCK_FLOCK
+ *            APR_LOCK_SYSVSEM
+ *            APR_LOCK_POSIXSEM
+ *            APR_LOCK_PROC_PTHREAD
+ *            APR_LOCK_DEFAULT     pick the default mechanism for the platform
+ *            APR_LOCK_DEFAULT_TIMED pick the default timed mechanism
+ * </PRE>
+ * @param pool the pool from which to allocate the mutex.
+ * @warning Check APR_HAS_foo_SERIALIZE defines to see if the platform supports
+ *          APR_LOCK_foo.  Only APR_LOCK_DEFAULT is portable.
+ */
+APR_DECLARE(apr_status_t) apr_global_mutex_create(apr_global_mutex_t **mutex,
+                                                  const char *fname,
+                                                  apr_lockmech_e mech,
+                                                  apr_pool_t *pool);
+
+/**
+ * Re-open a mutex in a child process.
+ * @param mutex The newly re-opened mutex structure.
+ * @param fname A file name to use if the mutex mechanism requires one.  This
+ *              argument should always be provided.  The mutex code itself will
+ *              determine if it should be used.  This filename should be the 
+ *              same one that was passed to apr_global_mutex_create().
+ * @param pool The pool to operate on.
+ * @remark This function must be called to maintain portability, even
+ *         if the underlying lock mechanism does not require it.
+ */
+APR_DECLARE(apr_status_t) apr_global_mutex_child_init(
+                              apr_global_mutex_t **mutex,
+                              const char *fname,
+                              apr_pool_t *pool);
+
+/**
+ * Acquire the lock for the given mutex. If the mutex is already locked,
+ * the current thread will be put to sleep until the lock becomes available.
+ * @param mutex the mutex on which to acquire the lock.
+ */
+APR_DECLARE(apr_status_t) apr_global_mutex_lock(apr_global_mutex_t *mutex);
+
+/**
+ * Attempt to acquire the lock for the given mutex. If the mutex has already
+ * been acquired, the call returns immediately with APR_EBUSY. Note: it
+ * is important that the APR_STATUS_IS_EBUSY(s) macro be used to determine
+ * if the return value was APR_EBUSY, for portability reasons.
+ * @param mutex the mutex on which to attempt the lock acquiring.
+ */
+APR_DECLARE(apr_status_t) apr_global_mutex_trylock(apr_global_mutex_t *mutex);
+
+/**
+ * Attempt to acquire the lock for the given mutex until timeout expires.
+ * If the acquisition time outs, the call returns with APR_TIMEUP.
+ * @param mutex the mutex on which to attempt the lock acquiring.
+ * @param timeout the relative timeout (microseconds).
+ * @note A negative or nul timeout means immediate attempt, returning
+ *       APR_TIMEUP without blocking if it the lock is already acquired.
+ */
+APR_DECLARE(apr_status_t) apr_global_mutex_timedlock(apr_global_mutex_t *mutex,
+                                                 apr_interval_time_t timeout);
+
+/**
+ * Release the lock for the given mutex.
+ * @param mutex the mutex from which to release the lock.
+ */
+APR_DECLARE(apr_status_t) apr_global_mutex_unlock(apr_global_mutex_t *mutex);
+
+/**
+ * Destroy the mutex and free the memory associated with the lock.
+ * @param mutex the mutex to destroy.
+ */
+APR_DECLARE(apr_status_t) apr_global_mutex_destroy(apr_global_mutex_t *mutex);
+
+/**
+ * Return the name of the lockfile for the mutex, or NULL
+ * if the mutex doesn't use a lock file
+ */
+
+APR_DECLARE(const char *) apr_global_mutex_lockfile(apr_global_mutex_t *mutex);
+
+/**
+ * Get the mechanism of the mutex, as it relates to the actual method
+ * used for the underlying apr_proc_mutex_t.
+ * @param mutex the mutex to get the mechanism from.
+ */
+APR_DECLARE(apr_lockmech_e) apr_global_mutex_mech(apr_global_mutex_t *mutex);
+
+/**
+ * Get the mechanism's name of the mutex, as it relates to the actual method
+ * used for the underlying apr_proc_mutex_t.
+ * @param mutex the mutex to get the mechanism's name from.
+ */
+APR_DECLARE(const char *) apr_global_mutex_name(apr_global_mutex_t *mutex);
+
+/**
+ * Set mutex permissions.
+ */
+APR_PERMS_SET_IMPLEMENT(global_mutex);
+
+/**
+ * Get the pool used by this global_mutex.
+ * @return apr_pool_t the pool
+ */
+APR_POOL_DECLARE_ACCESSOR(global_mutex);
+
+#else /* APR_PROC_MUTEX_IS_GLOBAL */
+
+/* Some platforms [e.g. Win32] have cross process locks that are truly
+ * global locks, since there isn't the concept of cross-process locks.
+ * Define these platforms in terms of an apr_proc_mutex_t.
+ */
+
+#define apr_global_mutex_t          apr_proc_mutex_t
+#define apr_global_mutex_create     apr_proc_mutex_create
+#define apr_global_mutex_child_init apr_proc_mutex_child_init
+#define apr_global_mutex_lock       apr_proc_mutex_lock
+#define apr_global_mutex_trylock    apr_proc_mutex_trylock
+#define apr_global_mutex_unlock     apr_proc_mutex_unlock
+#define apr_global_mutex_destroy    apr_proc_mutex_destroy
+#define apr_global_mutex_lockfile   apr_proc_mutex_lockfile
+#define apr_global_mutex_mech       apr_proc_mutex_mech
+#define apr_global_mutex_name       apr_proc_mutex_name
+#define apr_global_mutex_perms_set  apr_proc_mutex_perms_set
+#define apr_global_mutex_pool_get   apr_proc_mutex_pool_get
+
+#endif
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* ndef APR_GLOBAL_MUTEX_H */
diff --git a/include/apr_hash.h b/include/apr_hash.h
new file mode 100644
index 00000000000..10922de8f14
--- /dev/null
+++ b/include/apr_hash.h
@@ -0,0 +1,297 @@
+/* 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 APR_HASH_H
+#define APR_HASH_H
+
+/**
+ * @file apr_hash.h
+ * @brief APR Hash Tables
+ */
+
+#include "apr_pools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup apr_hash Hash Tables
+ * @ingroup APR 
+ * @{
+ */
+
+/**
+ * When passing a key to apr_hash_set or apr_hash_get, this value can be
+ * passed to indicate a string-valued key, and have apr_hash compute the
+ * length automatically.
+ *
+ * @remark apr_hash will use strlen(key) for the length. The NUL terminator
+ *         is not included in the hash value (why throw a constant in?).
+ *         Since the hash table merely references the provided key (rather
+ *         than copying it), apr_hash_this() will return the NUL-term'd key.
+ */
+#define APR_HASH_KEY_STRING     (-1)
+
+/**
+ * Abstract type for hash tables.
+ */
+typedef struct apr_hash_t apr_hash_t;
+
+/**
+ * Abstract type for scanning hash tables.
+ */
+typedef struct apr_hash_index_t apr_hash_index_t;
+
+/**
+ * Callback functions for calculating hash values.
+ * @param key The key.
+ * @param klen The length of the key, or APR_HASH_KEY_STRING to use the string 
+ *             length. If APR_HASH_KEY_STRING then returns the actual key length.
+ */
+typedef unsigned int (*apr_hashfunc_t)(const char *key, apr_ssize_t *klen);
+
+/**
+ * The default hash function.
+ */
+APR_DECLARE_NONSTD(unsigned int) apr_hashfunc_default(const char *key,
+                                                      apr_ssize_t *klen);
+
+/**
+ * Create a hash table.
+ * @param pool The pool to allocate the hash table out of
+ * @return The hash table just created
+  */
+APR_DECLARE(apr_hash_t *) apr_hash_make(apr_pool_t *pool);
+
+/**
+ * Create a hash table with a custom hash function
+ * @param pool The pool to allocate the hash table out of
+ * @param hash_func A custom hash function.
+ * @return The hash table just created
+  */
+APR_DECLARE(apr_hash_t *) apr_hash_make_custom(apr_pool_t *pool, 
+                                               apr_hashfunc_t hash_func);
+
+/**
+ * Make a copy of a hash table
+ * @param pool The pool from which to allocate the new hash table
+ * @param h The hash table to clone
+ * @return The hash table just created
+ * @remark Makes a shallow copy
+ */
+APR_DECLARE(apr_hash_t *) apr_hash_copy(apr_pool_t *pool,
+                                        const apr_hash_t *h);
+
+/**
+ * Associate a value with a key in a hash table.
+ * @param ht The hash table
+ * @param key Pointer to the key
+ * @param klen Length of the key. Can be APR_HASH_KEY_STRING to use the string length.
+ * @param val Value to associate with the key
+ * @remark If the value is NULL the hash entry is deleted. The key is stored as is,
+ *         and so must have a lifetime at least as long as the hash table's pool.
+ */
+APR_DECLARE(void) apr_hash_set(apr_hash_t *ht, const void *key,
+                               apr_ssize_t klen, const void *val);
+
+/**
+ * Look up the value associated with a key in a hash table.
+ * @param ht The hash table
+ * @param key Pointer to the key
+ * @param klen Length of the key. Can be APR_HASH_KEY_STRING to use the string length.
+ * @return Returns NULL if the key is not present.
+ */
+APR_DECLARE(void *) apr_hash_get(apr_hash_t *ht, const void *key,
+                                 apr_ssize_t klen);
+
+/**
+ * Look up the value associated with a key in a hash table, or if none exists
+ * associate a value.
+ * @param ht The hash table
+ * @param key Pointer to the key
+ * @param klen Length of the key. Can be APR_HASH_KEY_STRING to use the string
+ *        length.
+ * @param val Value to associate with the key (if none exists).
+ * @return Returns the existing value if any, the given value otherwise.
+ * @remark If the given value is NULL and a hash entry exists, nothing is done.
+ */
+APR_DECLARE(void *) apr_hash_get_or_set(apr_hash_t *ht, const void *key,
+                                        apr_ssize_t klen, const void *val);
+
+/**
+ * Start iterating over the entries in a hash table.
+ * @param p The pool to allocate the apr_hash_index_t iterator. If this
+ *          pool is NULL, then an internal, non-thread-safe iterator is used.
+ * @param ht The hash table
+ * @return The iteration state
+ * @remark  There is no restriction on adding or deleting hash entries during
+ * an iteration (although the results may be unpredictable unless all you do
+ * is delete the current entry) and multiple iterations can be in
+ * progress at the same time.
+ *
+ * @par Example:
+ *
+ * @code
+ * int sum_values(apr_pool_t *p, apr_hash_t *ht)
+ * {
+ *     apr_hash_index_t *hi;
+ *     void *val;
+ *     int sum = 0;
+ *     for (hi = apr_hash_first(p, ht); hi; hi = apr_hash_next(hi)) {
+ *         apr_hash_this(hi, NULL, NULL, &val);
+ *         sum += *(int *)val;
+ *     }
+ *     return sum;
+ * }
+ * @endcode
+ */
+APR_DECLARE(apr_hash_index_t *) apr_hash_first(apr_pool_t *p, apr_hash_t *ht);
+
+/**
+ * Continue iterating over the entries in a hash table.
+ * @param hi The iteration state
+ * @return a pointer to the updated iteration state.  NULL if there are no more  
+ *         entries.
+ */
+APR_DECLARE(apr_hash_index_t *) apr_hash_next(apr_hash_index_t *hi);
+
+/**
+ * Get the current entry's details from the iteration state.
+ * @param hi The iteration state
+ * @param key Return pointer for the pointer to the key.
+ * @param klen Return pointer for the key length.
+ * @param val Return pointer for the associated value.
+ * @remark The return pointers should point to a variable that will be set to the
+ *         corresponding data, or they may be NULL if the data isn't interesting.
+ */
+APR_DECLARE(void) apr_hash_this(apr_hash_index_t *hi, const void **key, 
+                                apr_ssize_t *klen, void **val);
+
+/**
+ * Get the current entry's key from the iteration state.
+ * @param hi The iteration state
+ * @return The pointer to the key
+ */
+APR_DECLARE(const void*) apr_hash_this_key(apr_hash_index_t *hi);
+
+/**
+ * Get the current entry's key length from the iteration state.
+ * @param hi The iteration state
+ * @return The key length
+ */
+APR_DECLARE(apr_ssize_t) apr_hash_this_key_len(apr_hash_index_t *hi);
+
+/**
+ * Get the current entry's value from the iteration state.
+ * @param hi The iteration state
+ * @return The pointer to the value
+ */
+APR_DECLARE(void*) apr_hash_this_val(apr_hash_index_t *hi);
+
+/**
+ * Get the number of key/value pairs in the hash table.
+ * @param ht The hash table
+ * @return The number of key/value pairs in the hash table.
+ */
+APR_DECLARE(unsigned int) apr_hash_count(apr_hash_t *ht);
+
+/**
+ * Clear any key/value pairs in the hash table.
+ * @param ht The hash table
+ */
+APR_DECLARE(void) apr_hash_clear(apr_hash_t *ht);
+
+/**
+ * Merge two hash tables into one new hash table. The values of the overlay
+ * hash override the values of the base if both have the same key.  Both
+ * hash tables must use the same hash function.
+ * @param p The pool to use for the new hash table
+ * @param overlay The table to add to the initial table
+ * @param base The table that represents the initial values of the new table
+ * @return A new hash table containing all of the data from the two passed in
+ */
+APR_DECLARE(apr_hash_t *) apr_hash_overlay(apr_pool_t *p,
+                                           const apr_hash_t *overlay, 
+                                           const apr_hash_t *base);
+
+/**
+ * Merge two hash tables into one new hash table. If the same key
+ * is present in both tables, call the supplied merge function to
+ * produce a merged value for the key in the new table.  Both
+ * hash tables must use the same hash function.
+ * @param p The pool to use for the new hash table
+ * @param h1 The first of the tables to merge
+ * @param h2 The second of the tables to merge
+ * @param merger A callback function to merge values, or NULL to
+ *  make values from h1 override values from h2 (same semantics as
+ *  apr_hash_overlay())
+ * @param data Client data to pass to the merger function
+ * @return A new hash table containing all of the data from the two passed in
+ */
+APR_DECLARE(apr_hash_t *) apr_hash_merge(apr_pool_t *p,
+                                         const apr_hash_t *h1,
+                                         const apr_hash_t *h2,
+                                         void * (*merger)(apr_pool_t *p,
+                                                     const void *key,
+                                                     apr_ssize_t klen,
+                                                     const void *h1_val,
+                                                     const void *h2_val,
+                                                     const void *data),
+                                         const void *data);
+
+/**
+ * Declaration prototype for the iterator callback function of apr_hash_do().
+ *
+ * @param rec The data passed as the first argument to apr_hash_[v]do()
+ * @param key The key from this iteration of the hash table
+ * @param klen The key length from this iteration of the hash table
+ * @param value The value from this iteration of the hash table
+ * @remark Iteration continues while this callback function returns non-zero.
+ * To export the callback function for apr_hash_do() it must be declared 
+ * in the _NONSTD convention.
+ */
+typedef int (apr_hash_do_callback_fn_t)(void *rec, const void *key,
+                                                   apr_ssize_t klen,
+                                                   const void *value);
+
+/** 
+ * Iterate over a hash table running the provided function once for every
+ * element in the hash table. The @param comp function will be invoked for
+ * every element in the hash table.
+ *
+ * @param comp The function to run
+ * @param rec The data to pass as the first argument to the function
+ * @param ht The hash table to iterate over
+ * @return FALSE if one of the comp() iterations returned zero; TRUE if all
+ *            iterations returned non-zero
+ * @see apr_hash_do_callback_fn_t
+ */
+APR_DECLARE(int) apr_hash_do(apr_hash_do_callback_fn_t *comp,
+                             void *rec, const apr_hash_t *ht);
+
+/**
+ * Get a pointer to the pool which the hash table was created in
+ */
+APR_POOL_DECLARE_ACCESSOR(hash);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* !APR_HASH_H */
diff --git a/include/apr_hooks.h b/include/apr_hooks.h
new file mode 100644
index 00000000000..896ea72f3c2
--- /dev/null
+++ b/include/apr_hooks.h
@@ -0,0 +1,358 @@
+/* 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 APR_HOOKS_H
+#define APR_HOOKS_H
+
+#include "apu.h"
+/* For apr_array_header_t */
+#include "apr_tables.h"
+
+/**
+ * @file apr_hooks.h
+ * @brief Apache hook functions
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/**
+ * @defgroup APR_Util_Hook Hook Functions
+ * @ingroup APR
+ * @{
+ */
+
+/**
+ * @defgroup apr_hook_probes Hook probe capability
+ * APR hooks provide a trace probe capability for capturing
+ * the flow of control and return values with hooks.
+ *
+ * In order to use this facility, the application must define
+ * the symbol APR_HOOK_PROBES_ENABLED and the four APR_HOOK_PROBE_
+ * macros described below before including apr_hooks.h in files
+ * that use the APR_IMPLEMENT_EXTERNAL_HOOK_* macros.
+ *
+ * This probe facility is not provided for APR optional hooks.
+ * @{
+ */
+
+#ifdef APR_HOOK_PROBES_ENABLED
+#define APR_HOOK_INT_DCL_UD void *ud = NULL
+#else
+/** internal implementation detail to avoid the ud declaration when
+ * hook probes are not used
+ */
+#define APR_HOOK_INT_DCL_UD
+/**
+ * User-defined hook probe macro that is invoked when the hook
+ * is run, before calling any hook functions.
+ * @param ud A void * user data field that should be filled in by
+ * this macro, and will be provided to the other hook probe macros.
+ * @param ns The namespace prefix of the hook functions
+ * @param name The name of the hook
+ * @param args The argument list to the hook functions, with enclosing
+ * parens.
+ */
+#define APR_HOOK_PROBE_ENTRY(ud,ns,name,args)
+/**
+ * User-defined hook probe macro that is invoked after the hook
+ * has run.
+ * @param ud A void * user data field that was filled in by the user-
+ * provided APR_HOOK_PROBE_ENTRY().
+ * @param ns The namespace prefix of the hook functions
+ * @param name The name of the hook
+ * @param rv The return value of the hook, or 0 if the hook is void.
+ * @param args The argument list to the hook functions, with enclosing
+ * parens.
+ */
+#define APR_HOOK_PROBE_RETURN(ud,ns,name,rv,args)
+/**
+ * User-defined hook probe macro that is invoked before calling a
+ * hook function.
+ * @param ud A void * user data field that was filled in by the user-
+ * provided APR_HOOK_PROBE_ENTRY().
+ * @param ns The namespace prefix of the hook functions
+ * @param name The name of the hook
+ * @param src The value of apr_hook_debug_current at the time the function
+ * was hooked (usually the source file implementing the hook function).
+ * @param args The argument list to the hook functions, with enclosing
+ * parens.
+ */
+#define APR_HOOK_PROBE_INVOKE(ud,ns,name,src,args)
+/**
+ * User-defined hook probe macro that is invoked after calling a
+ * hook function.
+ * @param ud A void * user data field that was filled in by the user-
+ * provided APR_HOOK_PROBE_ENTRY().
+ * @param ns The namespace prefix of the hook functions
+ * @param name The name of the hook
+ * @param src The value of apr_hook_debug_current at the time the function
+ * was hooked (usually the source file implementing the hook function).
+ * @param rv The return value of the hook function, or 0 if the hook is void.
+ * @param args The argument list to the hook functions, with enclosing
+ * parens.
+ */
+#define APR_HOOK_PROBE_COMPLETE(ud,ns,name,src,rv,args)
+#endif
+
+/** @} */
+
+/** macro to return the prototype of the hook function */    
+#define APR_IMPLEMENT_HOOK_GET_PROTO(ns,link,name) \
+link##_DECLARE(apr_array_header_t *) ns##_hook_get_##name(void)
+
+/** macro to declare the hook correctly */    
+#define APR_DECLARE_EXTERNAL_HOOK(ns,link,ret,name,args) \
+typedef ret ns##_HOOK_##name##_t args; \
+link##_DECLARE(void) ns##_hook_##name(ns##_HOOK_##name##_t *pf, \
+                                      const char * const *aszPre, \
+                                      const char * const *aszSucc, int nOrder); \
+link##_DECLARE(ret) ns##_run_##name args; \
+APR_IMPLEMENT_HOOK_GET_PROTO(ns,link,name); \
+typedef struct ns##_LINK_##name##_t \
+    { \
+    ns##_HOOK_##name##_t *pFunc; \
+    const char *szName; \
+    const char * const *aszPredecessors; \
+    const char * const *aszSuccessors; \
+    int nOrder; \
+    } ns##_LINK_##name##_t;
+
+/** macro to declare the hook structure */    
+#define APR_HOOK_STRUCT(members) \
+static struct { members } _hooks;
+
+/** macro to link the hook structure */
+#define APR_HOOK_LINK(name) \
+    apr_array_header_t *link_##name;
+
+/** macro to implement the hook */
+#define APR_IMPLEMENT_EXTERNAL_HOOK_BASE(ns,link,name) \
+link##_DECLARE(void) ns##_hook_##name(ns##_HOOK_##name##_t *pf,const char * const *aszPre, \
+                                      const char * const *aszSucc,int nOrder) \
+    { \
+    ns##_LINK_##name##_t *pHook; \
+    if(!_hooks.link_##name) \
+	{ \
+	_hooks.link_##name=apr_array_make(apr_hook_global_pool,1,sizeof(ns##_LINK_##name##_t)); \
+	apr_hook_sort_register(#name,&_hooks.link_##name); \
+	} \
+    pHook=apr_array_push(_hooks.link_##name); \
+    pHook->pFunc=pf; \
+    pHook->aszPredecessors=aszPre; \
+    pHook->aszSuccessors=aszSucc; \
+    pHook->nOrder=nOrder; \
+    pHook->szName=apr_hook_debug_current; \
+    if(apr_hook_debug_enabled) \
+	apr_hook_debug_show(#name,aszPre,aszSucc); \
+    } \
+    APR_IMPLEMENT_HOOK_GET_PROTO(ns,link,name) \
+    { \
+        return _hooks.link_##name; \
+    }
+
+/**
+ * Implement a hook that has no return code, and therefore runs all of the
+ * registered functions
+ * @param ns The namespace prefix of the hook functions
+ * @param link The linkage declaration prefix of the hook
+ * @param name The name of the hook
+ * @param args_decl The declaration of the arguments for the hook
+ * @param args_use The names for the arguments for the hook
+ * @note The link prefix FOO corresponds to FOO_DECLARE() macros, which
+ * provide export linkage from the module that IMPLEMENTs the hook, and
+ * import linkage from external modules that link to the hook's module.
+ */
+#define APR_IMPLEMENT_EXTERNAL_HOOK_VOID(ns,link,name,args_decl,args_use) \
+APR_IMPLEMENT_EXTERNAL_HOOK_BASE(ns,link,name) \
+link##_DECLARE(void) ns##_run_##name args_decl \
+    { \
+    ns##_LINK_##name##_t *pHook; \
+    int n; \
+    APR_HOOK_INT_DCL_UD; \
+\
+    APR_HOOK_PROBE_ENTRY(ud, ns, name, args_use); \
+\
+    if(_hooks.link_##name) \
+        { \
+        pHook=(ns##_LINK_##name##_t *)_hooks.link_##name->elts; \
+        for(n=0 ; n < _hooks.link_##name->nelts ; ++n) \
+            { \
+            APR_HOOK_PROBE_INVOKE(ud, ns, name, (char *)pHook[n].szName, args_use); \
+	    pHook[n].pFunc args_use; \
+            APR_HOOK_PROBE_COMPLETE(ud, ns, name, (char *)pHook[n].szName, 0, args_use); \
+            } \
+        } \
+\
+    APR_HOOK_PROBE_RETURN(ud, ns, name, 0, args_use); \
+\
+    }
+
+/* FIXME: note that this returns ok when nothing is run. I suspect it should
+   really return decline, but that breaks Apache currently - Ben
+*/
+/**
+ * Implement a hook that runs until one of the functions returns something
+ * other than OK or DECLINE
+ * @param ns The namespace prefix of the hook functions
+ * @param link The linkage declaration prefix of the hook
+ * @param ret Type to return
+ * @param name The name of the hook
+ * @param args_decl The declaration of the arguments for the hook
+ * @param args_use The names for the arguments for the hook
+ * @param ok Success value
+ * @param decline Decline value
+ * @note The link prefix FOO corresponds to FOO_DECLARE() macros, which
+ * provide export linkage from the module that IMPLEMENTs the hook, and
+ * import linkage from external modules that link to the hook's module.
+ */
+#define APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(ns,link,ret,name,args_decl,args_use,ok,decline) \
+APR_IMPLEMENT_EXTERNAL_HOOK_BASE(ns,link,name) \
+link##_DECLARE(ret) ns##_run_##name args_decl \
+    { \
+    ns##_LINK_##name##_t *pHook; \
+    int n; \
+    ret rv = ok; \
+    APR_HOOK_INT_DCL_UD; \
+\
+    APR_HOOK_PROBE_ENTRY(ud, ns, name, args_use); \
+\
+    if(_hooks.link_##name) \
+        { \
+        pHook=(ns##_LINK_##name##_t *)_hooks.link_##name->elts; \
+        for(n=0 ; n < _hooks.link_##name->nelts ; ++n) \
+            { \
+            APR_HOOK_PROBE_INVOKE(ud, ns, name, (char *)pHook[n].szName, args_use); \
+            rv=pHook[n].pFunc args_use; \
+            APR_HOOK_PROBE_COMPLETE(ud, ns, name, (char *)pHook[n].szName, rv, args_use); \
+            if(rv != ok && rv != decline) \
+                break; \
+            rv = ok; \
+            } \
+        } \
+\
+    APR_HOOK_PROBE_RETURN(ud, ns, name, rv, args_use); \
+\
+    return rv; \
+    }
+
+
+/**
+ * Implement a hook that runs until the first function returns something
+ * other than the value of decline
+ * @param ns The namespace prefix of the hook functions
+ * @param link The linkage declaration prefix of the hook
+ * @param name The name of the hook
+ * @param ret Type to return
+ * @param args_decl The declaration of the arguments for the hook
+ * @param args_use The names for the arguments for the hook
+ * @param decline Decline value
+ * @note The link prefix FOO corresponds to FOO_DECLARE() macros, which
+ * provide export linkage from the module that IMPLEMENTs the hook, and
+ * import linkage from external modules that link to the hook's module.
+ */
+#define APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(ns,link,ret,name,args_decl,args_use,decline) \
+APR_IMPLEMENT_EXTERNAL_HOOK_BASE(ns,link,name) \
+link##_DECLARE(ret) ns##_run_##name args_decl \
+    { \
+    ns##_LINK_##name##_t *pHook; \
+    int n; \
+    ret rv = decline; \
+    APR_HOOK_INT_DCL_UD; \
+\
+    APR_HOOK_PROBE_ENTRY(ud, ns, name, args_use); \
+\
+    if(_hooks.link_##name) \
+        { \
+        pHook=(ns##_LINK_##name##_t *)_hooks.link_##name->elts; \
+        for(n=0 ; n < _hooks.link_##name->nelts ; ++n) \
+            { \
+            APR_HOOK_PROBE_INVOKE(ud, ns, name, (char *)pHook[n].szName, args_use); \
+            rv=pHook[n].pFunc args_use; \
+            APR_HOOK_PROBE_COMPLETE(ud, ns, name, (char *)pHook[n].szName, rv, args_use); \
+\
+            if(rv != decline) \
+                break; \
+            } \
+        } \
+\
+    APR_HOOK_PROBE_RETURN(ud, ns, name, rv, args_use); \
+\
+    return rv; \
+    }
+
+    /* Hook orderings */
+/** run this hook first, before ANYTHING */
+#define APR_HOOK_REALLY_FIRST	(-10)
+/** run this hook first */
+#define APR_HOOK_FIRST		0
+/** run this hook somewhere */
+#define APR_HOOK_MIDDLE		10
+/** run this hook after every other hook which is defined*/
+#define APR_HOOK_LAST		20
+/** run this hook last, after EVERYTHING */
+#define APR_HOOK_REALLY_LAST	30
+
+/**
+ * The global pool used to allocate any memory needed by the hooks.
+ */ 
+APR_DECLARE_DATA extern apr_pool_t *apr_hook_global_pool;
+
+/**
+ * A global variable to determine if debugging information about the
+ * hooks functions should be printed.
+ */ 
+APR_DECLARE_DATA extern int apr_hook_debug_enabled;
+
+/**
+ * The name of the module that is currently registering a function.
+ */ 
+APR_DECLARE_DATA extern const char *apr_hook_debug_current;
+
+/**
+ * Register a hook function to be sorted.
+ * @param szHookName The name of the Hook the function is registered for
+ * @param aHooks The array which stores all of the functions for this hook
+ */
+APR_DECLARE(void) apr_hook_sort_register(const char *szHookName, 
+                                        apr_array_header_t **aHooks);
+/**
+ * Sort all of the registered functions for a given hook.
+ */
+APR_DECLARE(void) apr_hook_sort_all(void);
+
+/**
+ * Print all of the information about the current hook.  This is used for
+ * debugging purposes.
+ * @param szName The name of the hook
+ * @param aszPre All of the functions in the predecessor array
+ * @param aszSucc All of the functions in the successor array
+ */
+APR_DECLARE(void) apr_hook_debug_show(const char *szName,
+                                      const char * const *aszPre,
+                                      const char * const *aszSucc);
+
+/**
+ * Remove all currently registered functions.
+ */
+APR_DECLARE(void) apr_hook_deregister_all(void);
+
+/** @} */
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* APR_HOOKS_H */
diff --git a/include/apr_inherit.h b/include/apr_inherit.h
new file mode 100644
index 00000000000..b9fe56fe449
--- /dev/null
+++ b/include/apr_inherit.h
@@ -0,0 +1,51 @@
+/* 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 APR_INHERIT_H
+#define APR_INHERIT_H
+
+/**
+ * @file apr_inherit.h 
+ * @brief APR File Handle Inheritance Helpers
+ * @remark This internal header includes internal declaration helpers 
+ * for other headers to declare apr_foo_inherit_[un]set functions.
+ */
+
+/**
+ * Prototype for type-specific declarations of apr_foo_inherit_set 
+ * functions.  
+ * @remark Doxygen unwraps this macro (via doxygen.conf) to provide 
+ * actual help for each specific occurrence of apr_foo_inherit_set.
+ * @remark the linkage is specified for APR. It would be possible to expand
+ *       the macros to support other linkages.
+ */
+#define APR_DECLARE_INHERIT_SET(type) \
+    APR_DECLARE(apr_status_t) apr_##type##_inherit_set( \
+                                          apr_##type##_t *the##type)
+
+/**
+ * Prototype for type-specific declarations of apr_foo_inherit_unset 
+ * functions.  
+ * @remark Doxygen unwraps this macro (via doxygen.conf) to provide 
+ * actual help for each specific occurrence of apr_foo_inherit_unset.
+ * @remark the linkage is specified for APR. It would be possible to expand
+ *       the macros to support other linkages.
+ */
+#define APR_DECLARE_INHERIT_UNSET(type) \
+    APR_DECLARE(apr_status_t) apr_##type##_inherit_unset( \
+                                          apr_##type##_t *the##type)
+
+#endif	/* ! APR_INHERIT_H */
diff --git a/include/apr_lib.h b/include/apr_lib.h
index 4b9153b8540..c86217f9195 100644
--- a/include/apr_lib.h
+++ b/include/apr_lib.h
@@ -1,373 +1,238 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+/* 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 APR_LIB_H
 #define APR_LIB_H
 
-#include "apr_general.h"
-#include "apr_file_io.h"
-#include "apr_thread_proc.h"
+/**
+ * @file apr_lib.h
+ * This is collection of oddballs that didn't fit anywhere else,
+ * and might move to more appropriate headers with the release
+ * of APR 1.0.
+ * @brief APR general purpose library routines
+ */
+
+#include "apr.h"
+#include "apr_errno.h"
 
+#if APR_HAVE_CTYPE_H
+#include <ctype.h>
+#endif
 #if APR_HAVE_STDARG_H
 #include <stdarg.h>
 #endif
-#if APR_HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
 
 #ifdef __cplusplus
 extern "C" {
 #endif /* __cplusplus */
 
+/**
+ * @defgroup apr_lib General Purpose Library Routines
+ * @ingroup APR 
+ * This is collection of oddballs that didn't fit anywhere else,
+ * and might move to more appropriate headers with the release
+ * of APR 1.0.
+ * @{
+ */
+
+/** A constant representing a 'large' string. */
 #define HUGE_STRING_LEN 8192
 
 /*
  * Define the structures used by the APR general-purpose library.
  */
 
-/*
- * Memory allocation stuff, like pools, arrays, and tables.  Pools
- * and tables are opaque structures to applications, but arrays are
- * published.
- */
-typedef struct ap_table_t ap_table_t;
-typedef struct ap_child_info_t ap_child_info_t;
-typedef void ap_mutex_t;
-typedef struct ap_array_header_t {
-    ap_pool_t *cont;
-    int elt_size;
-    int nelts;
-    int nalloc;
-    char *elts;
-} ap_array_header_t;
-
-typedef struct ap_table_entry_t {
-    char *key;          /* maybe NULL in future;
-                         * check when iterating thru table_elts
-                         */
-    char *val;
-} ap_table_entry_t;
-
-/* XXX: these know about the definition of struct ap_table_t in alloc.c.  That
- * definition is not here because it is supposed to be private, and by not
- * placing it here we are able to get compile-time diagnostics from modules
- * written which assume that a ap_table_t is the same as an ap_array_header_t. -djg
- */
-#define ap_table_elts(t) ((ap_array_header_t *)(t))
-#define ap_is_empty_table(t) (((t) == NULL)||(((ap_array_header_t *)(t))->nelts == 0))
+/** @see apr_vformatter_buff_t */
+typedef struct apr_vformatter_buff_t apr_vformatter_buff_t;
 
-/*
+/**
  * Structure used by the variable-formatter routines.
  */
-typedef struct ap_vformatter_buff_t {
+struct apr_vformatter_buff_t {
+    /** The current position */
     char *curpos;
+    /** The end position of the format string */
     char *endpos;
-} ap_vformatter_buff_t;
-
-enum kill_conditions {
-    kill_never,			/* process is never sent any signals */
-    kill_always,		/* process is sent SIGKILL on ap_pool_t cleanup */
-    kill_after_timeout,		/* SIGTERM, wait 3 seconds, SIGKILL */
-    just_wait,			/* wait forever for the process to complete */
-    kill_only_once		/* send SIGTERM and then wait */
 };
 
-/*
- * Define the prototypes for the various APR GP routines.
+/**
+ * return the final element of the pathname
+ * @param pathname The path to get the final element of
+ * @return the final element of the path
+ * @remark
+ * <PRE>
+ * For example:
+ *                 "/foo/bar/gum"    -> "gum"
+ *                 "/foo/bar/gum/"   -> ""
+ *                 "gum"             -> "gum"
+ *                 "bs\\path\\stuff" -> "stuff"
+ * </PRE>
  */
-API_EXPORT(char *) ap_cpystrn(char *d, const char *s, size_t l);
-API_EXPORT(ap_status_t) ap_tokenize_to_argv(char *arg_str, char ***argv_out,
-                                            ap_pool_t *token_context);
-API_EXPORT(const char *) ap_filename_of_pathname(const char *pathname);
-API_EXPORT(char *) ap_collapse_spaces(char *dest, const char *src);
-
-/*API_EXPORT(ap_mutex_t *) ap_create_mutex(void *m);*/
-API_EXPORT(int) ap_slack(int l, int h);
-API_EXPORT_NONSTD(ap_status_t) ap_execle(const char *c, const char *a, ...);
-API_EXPORT_NONSTD(ap_status_t) ap_execve(const char *c, const char *argv[],
-				  const char *envp[]);
-
-#define ap_create_mutex(x) (0)
-#define ap_release_mutex(x) (0)
-#define ap_acquire_mutex(x) (0)
-
-/* These macros allow correct support of 8-bit characters on systems which
- * support 8-bit characters.  Pretty dumb how the cast is required, but
- * that's legacy libc for ya.  These new macros do not support EOF like
- * the standard macros do.  Tough.
- */
-#define ap_isalnum(c) (isalnum(((unsigned char)(c))))
-#define ap_isalpha(c) (isalpha(((unsigned char)(c))))
-#define ap_iscntrl(c) (iscntrl(((unsigned char)(c))))
-#define ap_isdigit(c) (isdigit(((unsigned char)(c))))
-#define ap_isgraph(c) (isgraph(((unsigned char)(c))))
-#define ap_islower(c) (islower(((unsigned char)(c))))
-#define ap_isprint(c) (isprint(((unsigned char)(c))))
-#define ap_ispunct(c) (ispunct(((unsigned char)(c))))
-#define ap_isspace(c) (isspace(((unsigned char)(c))))
-#define ap_isupper(c) (isupper(((unsigned char)(c))))
-#define ap_isxdigit(c) (isxdigit(((unsigned char)(c))))
-#define ap_tolower(c) (tolower(((unsigned char)(c))))
-#define ap_toupper(c) (toupper(((unsigned char)(c))))
-
+APR_DECLARE(const char *) apr_filepath_name_get(const char *pathname);
 
-
-
-/*
+/**
+ * apr_killpg
  * Small utility macros to make things easier to read.  Not usually a
  * goal, to be sure..
  */
 
 #ifdef WIN32
-#define ap_killpg(x, y)
+#define apr_killpg(x, y)
 #else /* WIN32 */
 #ifdef NO_KILLPG
-#define ap_killpg(x, y)		(kill (-(x), (y)))
+#define apr_killpg(x, y)        (kill (-(x), (y)))
 #else /* NO_KILLPG */
-#define ap_killpg(x, y)		(killpg ((x), (y)))
+#define apr_killpg(x, y)        (killpg ((x), (y)))
 #endif /* NO_KILLPG */
 #endif /* WIN32 */
 
-/*
- * ap_vformatter() is a generic printf-style formatting routine
- * with some extensions.  The extensions are:
- *
- * %pA	takes a struct in_addr *, and prints it as a.b.c.d
- * %pI	takes a struct sockaddr_in * and prints it as a.b.c.d:port
- * %pp  takes a void * and outputs it in hex
- *
- * The %p hacks are to force gcc's printf warning code to skip
+/**
+ * apr_vformatter() is a generic printf-style formatting routine
+ * with some extensions.
+ * @param flush_func The function to call when the buffer is full
+ * @param c The buffer to write to
+ * @param fmt The format string
+ * @param ap The arguments to use to fill out the format string.
+ *
+ * @remark
+ * <PRE>
+ * The extensions are:
+ *
+ * - %%pA takes a struct in_addr *, and prints it as a.b.c.d
+ * - %%pI takes an apr_sockaddr_t * and prints it as a.b.c.d:port or
+ * \[ipv6-address\]:port
+ * - %%pT takes an apr_os_thread_t * and prints it in decimal
+ * ('0' is printed if !APR_HAS_THREADS)
+ * - %%pt takes an apr_os_thread_t * and prints it in hexadecimal
+ * ('0' is printed if !APR_HAS_THREADS)
+ * - %%pm takes an apr_status_t * and prints the appropriate error
+ * string (from apr_strerror) corresponding to that error code.
+ * - %%pp takes a void * and outputs it in hex
+ * - %%pB takes a apr_uint32_t * as bytes and outputs it's apr_strfsize
+ * - %%pF same as above, but takes a apr_off_t *
+ * - %%pS same as above, but takes a apr_size_t *
+ *
+ * %%pA, %%pI, %%pT, %%pp are available from APR 1.0.0 onwards (and in 0.9.x).
+ * %%pt is only available from APR 1.2.0 onwards.
+ * %%pm, %%pB, %%pF and %%pS are only available from APR 1.3.0 onwards.
+ *
+ * The %%p hacks are to force gcc's printf warning code to skip
  * over a pointer argument without complaining.  This does
- * mean that the ANSI-style %p (output a void * in hex format) won't
+ * mean that the ANSI-style %%p (output a void * in hex format) won't
  * work as expected at all, but that seems to be a fair trade-off
  * for the increased robustness of having printf-warnings work.
  *
- * Additionally, ap_vformatter allows for arbitrary output methods
- * using the ap_vformatter_buff and flush_func.
+ * Additionally, apr_vformatter allows for arbitrary output methods
+ * using the apr_vformatter_buff and flush_func.
  *
- * The ap_vformatter_buff has two elements curpos and endpos.
- * curpos is where ap_vformatter will write the next byte of output.
+ * The apr_vformatter_buff has two elements curpos and endpos.
+ * curpos is where apr_vformatter will write the next byte of output.
  * It proceeds writing output to curpos, and updating curpos, until
  * either the end of output is reached, or curpos == endpos (i.e. the
  * buffer is full).
  *
- * If the end of output is reached, ap_vformatter returns the
+ * If the end of output is reached, apr_vformatter returns the
  * number of bytes written.
  *
  * When the buffer is full, the flush_func is called.  The flush_func
  * can return -1 to indicate that no further output should be attempted,
- * and ap_vformatter will return immediately with -1.  Otherwise
+ * and apr_vformatter will return immediately with -1.  Otherwise
  * the flush_func should flush the buffer in whatever manner is
- * appropriate, re ap_pool_t nitialize curpos and endpos, and return 0.
+ * appropriate, re apr_pool_t nitialize curpos and endpos, and return 0.
  *
  * Note that flush_func is only invoked as a result of attempting to
  * write another byte at curpos when curpos >= endpos.  So for
  * example, it's possible when the output exactly matches the buffer
  * space available that curpos == endpos will be true when
- * ap_vformatter returns.
+ * apr_vformatter returns.
  *
- * ap_vformatter does not call out to any other code, it is entirely
+ * apr_vformatter does not call out to any other code, it is entirely
  * self-contained.  This allows the callers to do things which are
- * otherwise "unsafe".  For example, ap_psprintf uses the "scratch"
+ * otherwise "unsafe".  For example, apr_psprintf uses the "scratch"
  * space at the unallocated end of a block, and doesn't actually
- * complete the allocation until ap_vformatter returns.  ap_psprintf
- * would be completely broken if ap_vformatter were to call anything
- * that used a ap_pool_t.  Similarly http_bprintf() uses the "scratch"
+ * complete the allocation until apr_vformatter returns.  apr_psprintf
+ * would be completely broken if apr_vformatter were to call anything
+ * that used this same pool.  Similarly http_bprintf() uses the "scratch"
  * space at the end of its output buffer, and doesn't actually note
  * that the space is in use until it either has to flush the buffer
- * or until ap_vformatter returns.
- */
-
-API_EXPORT(int) ap_vformatter(int (*flush_func)(ap_vformatter_buff_t *b),
-			       ap_vformatter_buff_t *c, const char *fmt,
-			       va_list ap);
-
-
-/* A small routine to validate a plain text password with a password
- * that has been encrypted using any algorithm APR knows about.
- */
-API_EXPORT(ap_status_t) ap_validate_password(const char *passwd, const char *hash);
-
-
-/*
- * These are snprintf implementations based on ap_vformatter().
- *
- * Note that various standards and implementations disagree on the return
- * value of snprintf, and side-effects due to %n in the formatting string.
- * ap_snprintf behaves as follows:
- *
- * Process the format string until the entire string is exhausted, or
- * the buffer fills.  If the buffer fills then stop processing immediately
- * (so no further %n arguments are processed), and return the buffer
- * length.  In all cases the buffer is NUL terminated.
- *
- * In no event does ap_snprintf return a negative number.  It's not possible
- * to distinguish between an output which was truncated, and an output which
- * exactly filled the buffer.
- */
-API_EXPORT(int) ap_snprintf(char *buf, size_t len, const char *format, ...)
-	__attribute__((format(printf,3,4)));
-API_EXPORT(int) ap_vsnprintf(char *buf, size_t len, const char *format,
-			      va_list ap);
-
-/*
- * APR memory structure manipulators (pools, tables, and arrays).
+ * or until apr_vformatter returns.
+ * </PRE>
  */
-API_EXPORT(ap_pool_t *) ap_make_sub_pool(ap_pool_t *p, int (*apr_abort)(int retcode));
-API_EXPORT(void) ap_clear_pool(struct ap_pool_t *p);
-API_EXPORT(void) ap_destroy_pool(struct ap_pool_t *p);
-API_EXPORT(long) ap_bytes_in_pool(ap_pool_t *p);
-API_EXPORT(long) ap_bytes_in_free_blocks(void);
-API_EXPORT(ap_pool_t *) ap_find_pool(const void *ts);
-API_EXPORT(int) ap_pool_is_ancestor(ap_pool_t *a, ap_pool_t *b);
-API_EXPORT(void) ap_pool_join(ap_pool_t *p, ap_pool_t *sub);
-
-/* used to guarantee to the ap_pool_t debugging code that the sub ap_pool_t will not be
- * destroyed before the parent pool
+APR_DECLARE(int) apr_vformatter(int (*flush_func)(apr_vformatter_buff_t *b),
+			        apr_vformatter_buff_t *c, const char *fmt,
+			        va_list ap);
+
+/**
+ * Display a prompt and read in the password from stdin.
+ * @param prompt The prompt to display
+ * @param pwbuf Buffer to store the password
+ * @param bufsize The length of the password buffer.
+ * @remark If the password entered must be truncated to fit in
+ * the provided buffer, APR_ENAMETOOLONG will be returned.
+ * Note that the bufsize paramater is passed by reference for no
+ * reason; its value will never be modified by the apr_password_get()
+ * function.
  */
-#ifndef POOL_DEBUG
-#ifdef ap_pool_join
-#undef ap_pool_join
-#endif /* ap_pool_join */
-#define ap_pool_join(a,b)
-#endif /* POOL_DEBUG */
-
-
-API_EXPORT(void *) ap_palloc(struct ap_pool_t *c, int reqsize);
-API_EXPORT(void *) ap_pcalloc(struct ap_pool_t *p, int size);
-API_EXPORT(char *) ap_pstrdup(struct ap_pool_t *p, const char *s);
-API_EXPORT(char *) ap_pstrndup(struct ap_pool_t *p, const char *s, int n);
-API_EXPORT_NONSTD(char *) ap_pstrcat(struct ap_pool_t *p, ...);
-API_EXPORT(char *) ap_pvsprintf(struct ap_pool_t *p, const char *fmt, va_list ap);
-API_EXPORT_NONSTD(char *) ap_psprintf(struct ap_pool_t *p, const char *fmt, ...);
-API_EXPORT(ap_array_header_t *) ap_make_array(struct ap_pool_t *p, int nelts,
-						int elt_size);
-API_EXPORT(void *) ap_push_array(ap_array_header_t *arr);
-API_EXPORT(void) ap_array_cat(ap_array_header_t *dst,
-			       const ap_array_header_t *src);
-API_EXPORT(ap_array_header_t *) ap_copy_array(struct ap_pool_t *p,
-						const ap_array_header_t *arr);
-API_EXPORT(ap_array_header_t *)
-	ap_copy_array_hdr(struct ap_pool_t *p,
-			   const ap_array_header_t *arr);
-API_EXPORT(ap_array_header_t *)
-	ap_append_arrays(struct ap_pool_t *p,
-			  const ap_array_header_t *first,
-			  const ap_array_header_t *second);
-API_EXPORT(char *) ap_array_pstrcat(struct ap_pool_t *p,
-				     const ap_array_header_t *arr,
-				     const char sep);
-API_EXPORT(ap_table_t *) ap_make_table(struct ap_pool_t *p, int nelts);
-API_EXPORT(ap_table_t *) ap_copy_table(struct ap_pool_t *p, const ap_table_t *t);
-API_EXPORT(void) ap_clear_table(ap_table_t *t);
-API_EXPORT(const char *) ap_table_get(const ap_table_t *t, const char *key);
-API_EXPORT(void) ap_table_set(ap_table_t *t, const char *key,
-			       const char *val);
-API_EXPORT(void) ap_table_setn(ap_table_t *t, const char *key,
-				const char *val);
-API_EXPORT(void) ap_table_unset(ap_table_t *t, const char *key);
-API_EXPORT(void) ap_table_merge(ap_table_t *t, const char *key,
-				 const char *val);
-API_EXPORT(void) ap_table_mergen(ap_table_t *t, const char *key,
-				  const char *val);
-API_EXPORT(void) ap_table_add(ap_table_t *t, const char *key,
-			       const char *val);
-API_EXPORT(void) ap_table_addn(ap_table_t *t, const char *key,
-				const char *val);
-API_EXPORT(ap_table_t *) ap_overlay_tables(struct ap_pool_t *p,
-					     const ap_table_t *overlay,
-					     const ap_table_t *base);
-API_EXPORT(void)
-	ap_table_do(int (*comp) (void *, const char *, const char *),
-		     void *rec, const ap_table_t *t, ...);
-#define AP_OVERLAP_TABLES_SET   (0)
-#define AP_OVERLAP_TABLES_MERGE (1)
-API_EXPORT(void) ap_overlap_tables(ap_table_t *a, const ap_table_t *b,
-				    unsigned flags);
-API_EXPORT(void) ap_register_cleanup(struct ap_pool_t *p, void *data,
-				      ap_status_t (*plain_cleanup) (void *),
-				      ap_status_t (*child_cleanup) (void *));
-API_EXPORT(void) ap_kill_cleanup(struct ap_pool_t *p, void *data,
-				  ap_status_t (*cleanup) (void *));
-API_EXPORT(void) ap_run_cleanup(struct ap_pool_t *p, void *data,
-				 ap_status_t (*cleanup) (void *));
-API_EXPORT(void) ap_cleanup_for_exec(void);
-API_EXPORT(ap_status_t) ap_getpass(const char *prompt, char *pwbuf, size_t *bufsize);
-API_EXPORT_NONSTD(ap_status_t) ap_null_cleanup(void *data);
+APR_DECLARE(apr_status_t) apr_password_get(const char *prompt, char *pwbuf, 
+                                           apr_size_t *bufsize);
 
-API_EXPORT(void) ap_note_subprocess(struct ap_pool_t *a, ap_proc_t *pid,
-				     enum kill_conditions how);
-API_EXPORT(int)
-	ap_spawn_child(ap_pool_t *p,
-			int (*func) (void *a, ap_child_info_t *c),
-			void *data, enum kill_conditions kill_how,
-			FILE **pipe_in, FILE **pipe_out,
-			FILE **pipe_err);
+/** @} */
 
-API_EXPORT(char *) ap_cpystrn(char *dst, const char *src, size_t dst_size);
-
-/*
- * Routine definitions that only work on Windows.
+/**
+ * @defgroup apr_ctype ctype functions
+ * These macros allow correct support of 8-bit characters on systems which
+ * support 8-bit characters.  Pretty dumb how the cast is required, but
+ * that's legacy libc for ya.  These new macros do not support EOF like
+ * the standard macros do.  Tough.
+ * @{
  */
-
-/*#ifdef TPF*/
-#define ap_block_alarms()
-#define ap_unblock_alarms()
-/*#else 
-API_EXPORT(void) ap_block_alarms(void);
-API_EXPORT(void) ap_unblock_alarms(void);
-#endif */
+/** @see isalnum */
+#define apr_isalnum(c) (isalnum(((unsigned char)(c))))
+/** @see isalpha */
+#define apr_isalpha(c) (isalpha(((unsigned char)(c))))
+/** @see iscntrl */
+#define apr_iscntrl(c) (iscntrl(((unsigned char)(c))))
+/** @see isdigit */
+#define apr_isdigit(c) (isdigit(((unsigned char)(c))))
+/** @see isgraph */
+#define apr_isgraph(c) (isgraph(((unsigned char)(c))))
+/** @see islower*/
+#define apr_islower(c) (islower(((unsigned char)(c))))
+/** @see isascii */
+#if APR_CHARSET_EBCDIC || defined(isascii)
+#define apr_isascii(c) (isascii(((unsigned char)(c))))
+#else
+#define apr_isascii(c) (((c) & ~0x7f)==0)
+#endif
+/** @see isprint */
+#define apr_isprint(c) (isprint(((unsigned char)(c))))
+/** @see ispunct */
+#define apr_ispunct(c) (ispunct(((unsigned char)(c))))
+/** @see isspace */
+#define apr_isspace(c) (isspace(((unsigned char)(c))))
+/** @see isupper */
+#define apr_isupper(c) (isupper(((unsigned char)(c))))
+/** @see isxdigit */
+#define apr_isxdigit(c) (isxdigit(((unsigned char)(c))))
+/** @see tolower */
+#define apr_tolower(c) (tolower(((unsigned char)(c))))
+/** @see toupper */
+#define apr_toupper(c) (toupper(((unsigned char)(c))))
+
+/** @} */
 
 #ifdef __cplusplus
 }
diff --git a/include/apr_lock.h b/include/apr_lock.h
deleted file mode 100644
index b2ebc2382a8..00000000000
--- a/include/apr_lock.h
+++ /dev/null
@@ -1,197 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef APR_LOCKS_H
-#define APR_LOCKS_H
-
-#include "apr_general.h"
-#include "apr_errno.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-typedef enum {APR_CROSS_PROCESS, APR_INTRAPROCESS, APR_LOCKALL} ap_lockscope_e;
-
-typedef enum {APR_MUTEX, APR_READWRITE} ap_locktype_e;
-
-typedef struct ap_lock_t           ap_lock_t;
-
-/*   Function definitions */
-/*
-
-=head1 ap_status_t ap_create_lock(ap_lock_t **lock, ap_locktype_e type, ap_lockscope_e scope, const char *fname, ap_pool_t *cont)
-
-B<Create a new instance of a lock structure.>
-
-    arg 1) The newly created lock structure.
-    arg 2) The type of lock to create, one of:
-              APR_MUTEX
-              APR_READWRITE
-    arg 3) The scope of the lock to create, one of:
-              APR_CROSS_PROCESS -- lock processes from the protected area.
-              APR_INTRAPROCESS  -- lock threads from the protected area.
-              APR_LOCKALL       -- lock processes and threads from the
-                                   protected area.
-    arg 4) A file name to use if the lock mechanism requires one.  This
-          argument should always be provided.  The lock code itself will
-          determine if it should be used.
-    arg 5) The pool to operate on.
-
-B<NOTE>:  APR_CROSS_PROCESS may lock both processes and threads, but it is
-          only guaranteed to lock processes.
-
-=cut
- */
-ap_status_t ap_create_lock(ap_lock_t **lock, ap_locktype_e type, 
-                           ap_lockscope_e scope, const char *fname, 
-                           ap_pool_t *cont);
-
-/*
-
-=head1 ap_status_t ap_lock(ap_lock_t *lock)
-
-B<Lock a protected region.>
-
-    arg 1) The lock to set.
-
-=cut
- */
-ap_status_t ap_lock(ap_lock_t *lock);
-
-/*
-
-=head1 ap_status_t ap_unlock(ap_lock_t *lock)
-
-B<Unlock a protected region.>
- 
-    arg 1) The lock to reset.
-
-=cut
- */
-ap_status_t ap_unlock(ap_lock_t *lock);
-
-/*
-
-=head1 ap_status_t ap_destroy_lock(ap_lock_t *lock)
-
-B<Free the memory associated with a lock.>
- 
-    arg 1) The lock to free.
-
-B<NOTE>:  If the lock is currently active when it is destroyed, it 
-          will be unlocked first.
-
-=cut
- */
-ap_status_t ap_destroy_lock(ap_lock_t *lock);
-
-/*
-
-=head1 ap_status_t ap_child_init_lock(ap_lock_t **lock, const char *fname, ap_pool_t *cont)
-
-B<Re-open a lock in a child process.>
-
-    arg 1) The newly re-opened lock structure.
-    arg 2) A file name to use if the lock mechanism requires one.  This
-           argument should always be provided.  The lock code itself will
-           determine if it should be used.  This filename should be the same
-           one that was passed to ap_create_lock
-    arg 3) The pool to operate on.
-
-B<NOTE>:  This function doesn't always do something, it depends on the
-           locking mechanism chosen for the platform, but it is a good
-           idea to call it regardless, because it makes the code more
-           portable. 
-
-=cut
- */
-ap_status_t ap_child_init_lock(ap_lock_t **lock, const char *fname, 
-                               ap_pool_t *cont);
-
-/*
-
-=head1 ap_status_t ap_get_lockdata(ap_lock_t *lock, char *key, void *data)
-
-B<Return the pool associated with the current lock.>
-
-    arg 1) The currently open lock.
-    arg 2) The key to use when retreiving data associated with this lock
-    arg 3) The user data associated with the lock.
-
-=cut
- */
-ap_status_t ap_get_lockdata(ap_lock_t *lock, char *key, void *data);
-
-/*
-
-=head1 ap_status_t ap_set_lockdata(ap_lock_t *lock, void *data, char *key, ap_status_t (*cleanup) (void *))
-
-B<Return the pool associated with the current lock.>
-
-    arg 1) The currently open lock.
-    arg 2) The user data to associate with the lock.
-    arg 3) The key to use when associating data with this lock
-    arg 4) The cleanup to use when the lock is destroyed.
-
-=cut
- */
-ap_status_t ap_set_lockdata(ap_lock_t *lock, void *data, char *key,
-                            ap_status_t (*cleanup) (void *));
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif  /* ! APR_LOCKS_H */
diff --git a/include/apr_md4.h b/include/apr_md4.h
new file mode 100644
index 00000000000..e1336d6686b
--- /dev/null
+++ b/include/apr_md4.h
@@ -0,0 +1,135 @@
+/* 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 is derived from material copyright RSA Data Security, Inc.
+ * Their notice is reproduced below in its entirety.
+ *
+ * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+ * rights reserved.
+ *
+ * License to copy and use this software is granted provided that it
+ * is identified as the "RSA Data Security, Inc. MD4 Message-Digest
+ * Algorithm" in all material mentioning or referencing this software
+ * or this function.
+ *
+ * License is also granted to make and use derivative works provided
+ * that such works are identified as "derived from the RSA Data
+ * Security, Inc. MD4 Message-Digest Algorithm" in all material
+ * mentioning or referencing the derived work.
+ *
+ * RSA Data Security, Inc. makes no representations concerning either
+ * the merchantability of this software or the suitability of this
+ * software for any particular purpose. It is provided "as is"
+ * without express or implied warranty of any kind.
+ *
+ * These notices must be retained in any copies of any part of this
+ * documentation and/or software.
+ */
+
+#ifndef APR_MD4_H
+#define APR_MD4_H
+
+#include "apu.h"
+#include "apr_xlate.h"
+/**
+ * @file apr_md4.h
+ * @brief APR-UTIL MD4 Library
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup APR_Util_MD4 MD4 Library
+ * @ingroup APR
+ * @{
+ */
+
+/** The digestsize for MD4 */
+#define APR_MD4_DIGESTSIZE 16
+
+/** @see apr_md4_ctx_t */
+typedef struct apr_md4_ctx_t apr_md4_ctx_t;
+
+/** MD4 context. */
+struct apr_md4_ctx_t {
+    /** state (ABCD) */
+    apr_uint32_t state[4];
+    /** number of bits, modulo 2^64 (lsb first) */
+    apr_uint32_t count[2];
+    /** input buffer */
+    unsigned char buffer[64];
+#if APR_HAS_XLATE
+    /** translation handle */
+    apr_xlate_t *xlate;
+#endif
+};
+
+/**
+ * MD4 Initialize.  Begins an MD4 operation, writing a new context.
+ * @param context The MD4 context to initialize.
+ */
+APR_DECLARE(apr_status_t) apr_md4_init(apr_md4_ctx_t *context);
+
+#if APR_HAS_XLATE
+/**
+ * MDr4 translation setup.  Provides the APR translation handle to be used 
+ * for translating the content before calculating the digest.
+ * @param context The MD4 content to set the translation for.
+ * @param xlate The translation handle to use for this MD4 context 
+ */
+APR_DECLARE(apr_status_t) apr_md4_set_xlate(apr_md4_ctx_t *context,
+                                            apr_xlate_t *xlate);
+#else
+#define apr_md4_set_xlate(context, xlate) APR_ENOTIMPL
+#endif
+
+/**
+ * MD4 block update operation.  Continue an MD4 message-digest operation, 
+ * processing another message block, and updating the context.
+ * @param context The MD4 content to update.
+ * @param input next message block to update
+ * @param inputLen The length of the next message block
+ */
+APR_DECLARE(apr_status_t) apr_md4_update(apr_md4_ctx_t *context,
+                                         const unsigned char *input,
+                                         apr_size_t inputLen);
+
+/**
+ * MD4 finalization.  Ends an MD4 message-digest operation, writing the 
+ * message digest and zeroing the context
+ * @param digest The final MD4 digest
+ * @param context The MD4 content we are finalizing.
+ */
+APR_DECLARE(apr_status_t) apr_md4_final(
+                                    unsigned char digest[APR_MD4_DIGESTSIZE],
+                                    apr_md4_ctx_t *context);
+
+/**
+ * MD4 digest computation
+ * @param digest The MD4 digest
+ * @param input message block to use
+ * @param inputLen The length of the message block
+ */
+APR_DECLARE(apr_status_t) apr_md4(unsigned char digest[APR_MD4_DIGESTSIZE],
+                                  const unsigned char *input,
+                                  apr_size_t inputLen);
+
+/** @} */
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !APR_MD4_H */
diff --git a/include/apr_md5.h b/include/apr_md5.h
index 8f2506bc4bb..1e5ba359ec5 100644
--- a/include/apr_md5.h
+++ b/include/apr_md5.h
@@ -28,92 +28,149 @@
    documentation and/or software.
  */
 
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 APACHE_MD5_H
-#define APACHE_MD5_H
+#ifndef APR_MD5_H
+#define APR_MD5_H
 
-#include "apr_lib.h"
+#include "apu.h"
+#include "apr_xlate.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
+/**
+ * @file apr_md5.h
+ * @brief APR MD5 Routines
+ */
+
+/**
+ * @defgroup APR_MD5 MD5 Routines
+ * @ingroup APR
+ * @{
+ */
+
+/** The MD5 digest size */
+#define APR_MD5_DIGESTSIZE 16
+
+/** @see apr_md5_ctx_t */
+typedef struct apr_md5_ctx_t apr_md5_ctx_t;
+
+/** MD5 context. */
+struct apr_md5_ctx_t {
+    /** state (ABCD) */
+    apr_uint32_t state[4];
+    /** number of bits, modulo 2^64 (lsb first) */
+    apr_uint32_t count[2];
+    /** input buffer */
+    unsigned char buffer[64];
+    /** translation handle 
+     *  ignored if xlate is unsupported
+     */
+    apr_xlate_t *xlate;
+};
 
-#define MD5_DIGESTSIZE 16
+/**
+ * MD5 Initialize.  Begins an MD5 operation, writing a new context.
+ * @param context The MD5 context to initialize.
+ */
+APR_DECLARE(apr_status_t) apr_md5_init(apr_md5_ctx_t *context);
+
+/**
+ * MD5 translation setup.  Provides the APR translation handle to be used 
+ * for translating the content before calculating the digest.
+ * @param context The MD5 content to set the translation for.
+ * @param xlate The translation handle to use for this MD5 context 
+ */
+APR_DECLARE(apr_status_t) apr_md5_set_xlate(apr_md5_ctx_t *context,
+                                            apr_xlate_t *xlate);
 
-/* UINT4 defines a four byte word */
-typedef unsigned int UINT4;
+/**
+ * MD5 block update operation.  Continue an MD5 message-digest operation, 
+ * processing another message block, and updating the context.
+ * @param context The MD5 content to update.
+ * @param input next message block to update
+ * @param inputLen The length of the next message block
+ */
+APR_DECLARE(apr_status_t) apr_md5_update(apr_md5_ctx_t *context,
+                                         const void *input,
+                                         apr_size_t inputLen);
 
-/* MD5 context. */
-typedef struct {
-    UINT4 state[4];		/* state (ABCD) */
-    UINT4 count[2];		/* number of bits, modulo 2^64 (lsb first) */
-    unsigned char buffer[64];	/* input buffer */
-} ap_md5_ctx_t;
+/**
+ * MD5 finalization.  Ends an MD5 message-digest operation, writing the 
+ * message digest and zeroing the context
+ * @param digest The final MD5 digest
+ * @param context The MD5 content we are finalizing.
+ */
+APR_DECLARE(apr_status_t) apr_md5_final(unsigned char digest[APR_MD5_DIGESTSIZE],
+                                        apr_md5_ctx_t *context);
+
+/**
+ * MD5 in one step
+ * @param digest The final MD5 digest
+ * @param input The message block to use
+ * @param inputLen The length of the message block
+ */
+APR_DECLARE(apr_status_t) apr_md5(unsigned char digest[APR_MD5_DIGESTSIZE],
+                                  const void *input,
+                                  apr_size_t inputLen);
+
+/**
+ * Encode a password using an MD5 algorithm
+ * @param pw The password to encode
+ * @param salt The salt string to use for the encoding
+ * @param result The string to store the encoded password in
+ * @param nbytes The size of the result buffer
+ */
+APR_DECLARE(apr_status_t) apr_md5_encode(const char *pw, const char *salt,
+                                         char *result, apr_size_t nbytes);
+
+/**
+ * Encode a password using the bcrypt algorithm
+ * @param pw The password to encode
+ * @param count The cost of the encoding, possible values are 4 to 31
+ * @param salt Pointer to binary data to be used as salt for the encoding
+ * @param salt_len The size of the salt data (must be >= 16)
+ * @param out The string to store the encoded password in
+ * @param out_len The size of the result buffer (must be >= 61)
+ */
+APR_DECLARE(apr_status_t) apr_bcrypt_encode(const char *pw,
+                                            unsigned int count,
+                                            const unsigned char *salt,
+                                            apr_size_t salt_len,
+                                            char *out, apr_size_t out_len);
+
+/**
+ * Validate hashes created by APR-supported algorithms: md5, bcrypt, and sha1.
+ * hashes created by crypt are supported only on platforms that provide
+ * crypt(3), so don't rely on that function unless you know that your
+ * application will be run only on platforms that support it.  On platforms
+ * that don't support crypt(3), this falls back to a clear text string
+ * comparison.
+ * @param passwd The password to validate
+ * @param hash The password to validate against
+ */
+APR_DECLARE(apr_status_t) apr_password_validate(const char *passwd, 
+                                                const char *hash);
 
-API_EXPORT(ap_status_t) ap_MD5Init(ap_md5_ctx_t *context);
-API_EXPORT(ap_status_t) ap_MD5Update(ap_md5_ctx_t *context,
-                                     const unsigned char *input,
-                                     unsigned int inputLen);
-API_EXPORT(ap_status_t) ap_MD5Final(unsigned char digest[MD5_DIGESTSIZE],
-                                    ap_md5_ctx_t *context);
-API_EXPORT(ap_status_t) ap_MD5Encode(const char *password, const char *salt,
-                                     char *result, size_t nbytes);
 
+/** @} */
 #ifdef __cplusplus
 }
 #endif
 
-#endif	/* !APACHE_MD5_H */
+#endif /* !APR_MD5_H */
diff --git a/include/apr_memcache.h b/include/apr_memcache.h
new file mode 100644
index 00000000000..2a3bcaab88b
--- /dev/null
+++ b/include/apr_memcache.h
@@ -0,0 +1,444 @@
+/* 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 APR_MEMCACHE_H
+#define APR_MEMCACHE_H
+
+/**
+ * @file apr_memcache.h
+ * @brief Client interface for memcached
+ * @remark To use this interface you must have a separate memcached
+ * server running. See the memcached website at http://www.danga.com/memcached/
+ * for more information.
+ */
+
+#include "apr.h"
+#include "apr_pools.h"
+#include "apr_time.h"
+#include "apr_strings.h"
+#include "apr_network_io.h"
+#include "apr_buckets.h"
+#include "apr_ring.h"
+#include "apr_reslist.h"
+#include "apr_hash.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup APR_Util_MC Memcached Client Routines
+ * @ingroup APR
+ * @{
+ */
+
+/** Specifies the status of a memcached server */
+typedef enum
+{
+    APR_MC_SERVER_LIVE, /**< Server is alive and responding to requests */
+    APR_MC_SERVER_DEAD  /**< Server is not responding to requests */
+} apr_memcache_server_status_t;
+
+/** Opaque memcache client connection object */
+typedef struct apr_memcache_conn_t apr_memcache_conn_t;
+
+/** Memcache Server Info Object */
+typedef struct apr_memcache_server_t apr_memcache_server_t;
+struct apr_memcache_server_t
+{
+    const char *host; /**< Hostname of this Server */
+    apr_port_t port; /**< Port of this Server */
+    apr_memcache_server_status_t status; /**< @see apr_memcache_server_status_t */
+#if APR_HAS_THREADS || defined(DOXYGEN)
+    apr_reslist_t *conns; /**< Resource list of actual client connections */
+#else
+    apr_memcache_conn_t *conn;
+#endif
+    apr_pool_t *p; /** Pool to use for private allocations */
+#if APR_HAS_THREADS
+    apr_thread_mutex_t *lock;
+#endif
+    apr_time_t btime;
+};
+
+/* Custom hash callback function prototype, user for server selection.
+* @param baton user selected baton
+* @param data data to hash
+* @param data_len length of data
+*/
+typedef apr_uint32_t (*apr_memcache_hash_func)(void *baton,
+                                               const char *data,
+                                               const apr_size_t data_len);
+
+typedef struct apr_memcache_t apr_memcache_t;
+
+/* Custom Server Select callback function prototype.
+* @param baton user selected baton
+* @param mc memcache instance, use mc->live_servers to select a node
+* @param hash hash of the selected key.
+*/
+typedef apr_memcache_server_t* (*apr_memcache_server_func)(void *baton,
+                                                 apr_memcache_t *mc,
+                                                 const apr_uint32_t hash);
+
+/** Container for a set of memcached servers */
+struct apr_memcache_t
+{
+    apr_uint32_t flags; /**< Flags, Not currently used */
+    apr_uint16_t nalloc; /**< Number of Servers Allocated */
+    apr_uint16_t ntotal; /**< Number of Servers Added */
+    apr_memcache_server_t **live_servers; /**< Array of Servers */
+    apr_pool_t *p; /** Pool to use for allocations */
+    void *hash_baton;
+    apr_memcache_hash_func hash_func;
+    void *server_baton;
+    apr_memcache_server_func server_func;
+};
+
+/** Returned Data from a multiple get */
+typedef struct
+{
+    apr_status_t status;
+    const char* key;
+    apr_size_t len;
+    char *data;
+    apr_uint16_t flags;
+} apr_memcache_value_t;
+
+/**
+ * Creates a crc32 hash used to split keys between servers
+ * @param mc The memcache client object to use
+ * @param data Data to be hashed
+ * @param data_len Length of the data to use
+ * @return crc32 hash of data
+ * @remark The crc32 hash is not compatible with old memcached clients.
+ */
+APR_DECLARE(apr_uint32_t) apr_memcache_hash(apr_memcache_t *mc,
+                                            const char *data,
+                                            const apr_size_t data_len);
+
+/**
+ * Pure CRC32 Hash. Used by some clients.
+ */
+APR_DECLARE(apr_uint32_t) apr_memcache_hash_crc32(void *baton,
+                                                  const char *data,
+                                                  const apr_size_t data_len);
+
+/**
+ * hash compatible with the standard Perl Client.
+ */
+APR_DECLARE(apr_uint32_t) apr_memcache_hash_default(void *baton,
+                                                    const char *data,
+                                                    const apr_size_t data_len);
+
+/**
+ * Picks a server based on a hash
+ * @param mc The memcache client object to use
+ * @param hash Hashed value of a Key
+ * @return server that controls specified hash
+ * @see apr_memcache_hash
+ */
+APR_DECLARE(apr_memcache_server_t *) apr_memcache_find_server_hash(apr_memcache_t *mc, 
+                                                                   const apr_uint32_t hash);
+
+/**
+ * server selection compatible with the standard Perl Client.
+ */
+APR_DECLARE(apr_memcache_server_t *)
+apr_memcache_find_server_hash_default(void *baton,
+                                      apr_memcache_t *mc, 
+                                      const apr_uint32_t hash);
+
+/**
+ * Adds a server to a client object
+ * @param mc The memcache client object to use
+ * @param server Server to add
+ * @remark Adding servers is not thread safe, and should be done once at startup.
+ * @warning Changing servers after startup may cause keys to go to
+ * different servers.
+ */
+APR_DECLARE(apr_status_t) apr_memcache_add_server(apr_memcache_t *mc,
+                                                  apr_memcache_server_t *server);
+
+
+/**
+ * Finds a Server object based on a hostname/port pair
+ * @param mc The memcache client object to use
+ * @param host Hostname of the server
+ * @param port Port of the server
+ * @return Server with matching Hostname and Port, or NULL if none was found.
+ */
+APR_DECLARE(apr_memcache_server_t *) apr_memcache_find_server(apr_memcache_t *mc,
+                                                              const char *host,
+                                                              apr_port_t port);
+
+/**
+ * Enables a Server for use again
+ * @param mc The memcache client object to use
+ * @param ms Server to Activate
+ */
+APR_DECLARE(apr_status_t) apr_memcache_enable_server(apr_memcache_t *mc,
+                                                     apr_memcache_server_t *ms);
+
+
+/**
+ * Disable a Server
+ * @param mc The memcache client object to use
+ * @param ms Server to Disable
+ */
+APR_DECLARE(apr_status_t) apr_memcache_disable_server(apr_memcache_t *mc,
+                                                      apr_memcache_server_t *ms);
+
+/**
+ * Creates a new Server Object
+ * @param p Pool to use
+ * @param host hostname of the server
+ * @param port port of the server
+ * @param min  minimum number of client sockets to open
+ * @param smax soft maximum number of client connections to open
+ * @param max  hard maximum number of client connections
+ * @param ttl  time to live in microseconds of a client connection
+ * @param ns   location of the new server object
+ * @see apr_reslist_create
+ * @remark min, smax, and max are only used when APR_HAS_THREADS
+ */
+APR_DECLARE(apr_status_t) apr_memcache_server_create(apr_pool_t *p,
+                                                     const char *host,
+                                                     apr_port_t port,
+                                                     apr_uint32_t min,
+                                                     apr_uint32_t smax,
+                                                     apr_uint32_t max,
+                                                     apr_uint32_t ttl,
+                                                     apr_memcache_server_t **ns);
+/**
+ * Creates a new memcached client object
+ * @param p Pool to use
+ * @param max_servers maximum number of servers
+ * @param flags Not currently used
+ * @param mc   location of the new memcache client object
+ */
+APR_DECLARE(apr_status_t) apr_memcache_create(apr_pool_t *p,
+                                              apr_uint16_t max_servers,
+                                              apr_uint32_t flags,
+                                              apr_memcache_t **mc);
+
+/**
+ * Gets a value from the server, allocating the value out of p
+ * @param mc client to use
+ * @param p Pool to use
+ * @param key null terminated string containing the key
+ * @param baton location of the allocated value
+ * @param len   length of data at baton
+ * @param flags any flags set by the client for this key
+ * @return 
+ */
+APR_DECLARE(apr_status_t) apr_memcache_getp(apr_memcache_t *mc, 
+                                            apr_pool_t *p,
+                                            const char* key,
+                                            char **baton,
+                                            apr_size_t *len,
+                                            apr_uint16_t *flags);
+
+
+/**
+ * Add a key to a hash for a multiget query
+ *  if the hash (*value) is NULL it will be created
+ * @param data_pool pool from where the hash and their items are created from
+ * @param key null terminated string containing the key
+ * @param values hash of keys and values that this key will be added to
+ * @return
+ */
+APR_DECLARE(void) apr_memcache_add_multget_key(apr_pool_t *data_pool,
+                                               const char* key,
+                                               apr_hash_t **values);
+
+/**
+ * Gets multiple values from the server, allocating the values out of p
+ * @param mc client to use
+ * @param temp_pool Pool used for temporary allocations. May be cleared inside this
+ *        call.
+ * @param data_pool Pool used to allocate data for the returned values.
+ * @param values hash of apr_memcache_value_t keyed by strings, contains the
+ *        result of the multiget call.
+ * @return
+ */
+APR_DECLARE(apr_status_t) apr_memcache_multgetp(apr_memcache_t *mc,
+                                                apr_pool_t *temp_pool,
+                                                apr_pool_t *data_pool,
+                                                apr_hash_t *values);
+
+/**
+ * Sets a value by key on the server
+ * @param mc client to use
+ * @param key   null terminated string containing the key
+ * @param baton data to store on the server
+ * @param data_size   length of data at baton
+ * @param timeout time in seconds for the data to live on the server
+ * @param flags any flags set by the client for this key
+ */
+APR_DECLARE(apr_status_t) apr_memcache_set(apr_memcache_t *mc,
+                                           const char *key,
+                                           char *baton,
+                                           const apr_size_t data_size,
+                                           apr_uint32_t timeout,
+                                           apr_uint16_t flags);
+
+/**
+ * Adds value by key on the server
+ * @param mc client to use
+ * @param key   null terminated string containing the key
+ * @param baton data to store on the server
+ * @param data_size   length of data at baton
+ * @param timeout time for the data to live on the server
+ * @param flags any flags set by the client for this key
+ * @return APR_SUCCESS if the key was added, APR_EEXIST if the key 
+ * already exists on the server.
+ */
+APR_DECLARE(apr_status_t) apr_memcache_add(apr_memcache_t *mc,
+                                           const char *key,
+                                           char *baton,
+                                           const apr_size_t data_size,
+                                           apr_uint32_t timeout,
+                                           apr_uint16_t flags);
+
+/**
+ * Replaces value by key on the server
+ * @param mc client to use
+ * @param key   null terminated string containing the key
+ * @param baton data to store on the server
+ * @param data_size   length of data at baton
+ * @param timeout time for the data to live on the server
+ * @param flags any flags set by the client for this key
+ * @return APR_SUCCESS if the key was added, APR_EEXIST if the key 
+ * did not exist on the server.
+ */
+APR_DECLARE(apr_status_t) apr_memcache_replace(apr_memcache_t *mc,
+                                               const char *key,
+                                               char *baton,
+                                               const apr_size_t data_size,
+                                               apr_uint32_t timeout,
+                                               apr_uint16_t flags);
+/**
+ * Deletes a key from a server
+ * @param mc client to use
+ * @param key   null terminated string containing the key
+ * @param timeout time for the delete to stop other clients from adding
+ */
+APR_DECLARE(apr_status_t) apr_memcache_delete(apr_memcache_t *mc,
+                                              const char *key,
+                                              apr_uint32_t timeout);
+
+/**
+ * Increments a value
+ * @param mc client to use
+ * @param key   null terminated string containing the key
+ * @param n     number to increment by
+ * @param nv    new value after incrementing
+ */
+APR_DECLARE(apr_status_t) apr_memcache_incr(apr_memcache_t *mc, 
+                                            const char *key,
+                                            apr_int32_t n,
+                                            apr_uint32_t *nv);
+
+/**
+ * Decrements a value
+ * @param mc client to use
+ * @param key   null terminated string containing the key
+ * @param n     number to decrement by
+ * @param new_value    new value after decrementing
+ */
+APR_DECLARE(apr_status_t) apr_memcache_decr(apr_memcache_t *mc, 
+                                            const char *key,
+                                            apr_int32_t n,
+                                            apr_uint32_t *new_value);
+
+/**
+ * Query a server's version
+ * @param ms    server to query
+ * @param p     Pool to allocate answer from
+ * @param baton location to store server version string
+ */
+APR_DECLARE(apr_status_t) apr_memcache_version(apr_memcache_server_t *ms,
+                                               apr_pool_t *p,
+                                               char **baton);
+
+typedef struct
+{
+    /** Version string of this server */
+    const char *version;
+    /** Process id of this server process */
+    apr_uint32_t pid;
+    /** Number of seconds this server has been running */
+    apr_uint32_t uptime;
+    /** current UNIX time according to the server */
+    apr_time_t time;
+    /** The size of a pointer on the current machine */
+    apr_uint32_t pointer_size;
+    /** Accumulated user time for this process */
+    apr_time_t rusage_user;
+    /** Accumulated system time for this process */
+    apr_time_t rusage_system;
+    /** Current number of items stored by the server */
+    apr_uint32_t curr_items;
+    /** Total number of items stored by this server */
+    apr_uint32_t total_items;
+    /** Current number of bytes used by this server to store items */
+    apr_uint64_t bytes;
+    /** Number of open connections */
+    apr_uint32_t curr_connections;
+    /** Total number of connections opened since the server started running */
+    apr_uint32_t total_connections;
+    /** Number of connection structures allocated by the server */
+    apr_uint32_t connection_structures;
+    /** Cumulative number of retrieval requests */
+    apr_uint32_t cmd_get;
+    /** Cumulative number of storage requests */
+    apr_uint32_t cmd_set;
+    /** Number of keys that have been requested and found present */
+    apr_uint32_t get_hits;
+    /** Number of items that have been requested and not found */
+    apr_uint32_t get_misses;
+    /** Number of items removed from cache because they passed their
+        expiration time */
+    apr_uint64_t evictions;
+    /** Total number of bytes read by this server */
+    apr_uint64_t bytes_read;
+    /** Total number of bytes sent by this server */
+    apr_uint64_t bytes_written;
+    /** Number of bytes this server is allowed to use for storage. */
+    apr_uint32_t limit_maxbytes;
+    /** Number of threads the server is running (if built with threading) */
+    apr_uint32_t threads; 
+} apr_memcache_stats_t;
+
+/**
+ * Query a server for statistics
+ * @param ms    server to query
+ * @param p     Pool to allocate answer from
+ * @param stats location of the new statistics structure
+ */
+APR_DECLARE(apr_status_t) apr_memcache_stats(apr_memcache_server_t *ms, 
+                                             apr_pool_t *p,
+                                             apr_memcache_stats_t **stats);
+
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* APR_MEMCACHE_H */
diff --git a/include/apr_mmap.h b/include/apr_mmap.h
index 598b0e3f964..c14de1928ae 100644
--- a/include/apr_mmap.h
+++ b/include/apr_mmap.h
@@ -1,121 +1,171 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 APR_MMAP_H
 #define APR_MMAP_H
 
-#include "apr_general.h"
+/**
+ * @file apr_mmap.h
+ * @brief APR MMAP routines
+ */
+
+#include "apr.h"
+#include "apr_pools.h"
 #include "apr_errno.h"
-#include "apr_network_io.h"
-#include "apr_portable.h"
+#include "apr_ring.h"
+#include "apr_file_io.h"        /* for apr_file_t */
+
+#ifdef BEOS
+#include <kernel/OS.h>
+#endif
 
 #ifdef __cplusplus
 extern "C" {
 #endif /* __cplusplus */
 
-
-typedef struct ap_mmap_t            ap_mmap_t;
-
-/*   Function definitions */
-
-/* 
-
-=head1 ap_status_t ap_mmap_create(ap_mmap_t **new, ap_file_t *file, ap_off_t offset)
-
-B<Create a new mmap'ed file out of an existing APR file.>
-
-    arg 1) The newly created mmap'ed file.
-    arg 2) The file turn into an mmap.
-    arg 3) The offset into the file to start the data pointer at.
-    arg 4) The size of the file
-    arg 5) The pool to use when creating the mmap.
-
-=cut
+/**
+ * @defgroup apr_mmap MMAP (Memory Map) Routines
+ * @ingroup APR 
+ * @{
  */
-ap_status_t ap_mmap_create(ap_mmap_t ** newmmap, ap_file_t *file, ap_off_t offset,
-                 ap_size_t size, ap_pool_t *cntxt);
 
-/* 
-
-=head1 ap_status_t ap_mmap_delete(ap_mmap_t *mmap)
+/** MMap opened for reading */
+#define APR_MMAP_READ    1
+/** MMap opened for writing */
+#define APR_MMAP_WRITE   2
+
+/** @see apr_mmap_t */
+typedef struct apr_mmap_t            apr_mmap_t;
+
+/**
+ * @remark
+ * As far as I can tell the only really sane way to store an MMAP is as a
+ * void * and a length.  BeOS requires this area_id, but that's just a little
+ * something extra.  I am exposing this type, because it doesn't make much
+ * sense to keep it private, and opening it up makes some stuff easier in
+ * Apache.
+ */
+/** The MMAP structure */
+struct apr_mmap_t {
+    /** The pool the mmap structure was allocated out of. */
+    apr_pool_t *cntxt;
+#ifdef BEOS
+    /** An area ID.  Only valid on BeOS */
+    area_id area;
+#endif
+#ifdef WIN32
+    /** The handle of the file mapping */
+    HANDLE mhandle;
+    /** The start of the real memory page area (mapped view) */
+    void *mv;
+    /** The physical start, size and offset */
+    apr_off_t  pstart;
+    apr_size_t psize;
+    apr_off_t  poffset;
+#endif
+    /** The start of the memory mapped area */
+    void *mm;
+    /** The amount of data in the mmap */
+    apr_size_t size;
+    /** ring of apr_mmap_t's that reference the same
+     * mmap'ed region; acts in place of a reference count */
+    APR_RING_ENTRY(apr_mmap_t) link;
+};
+
+#if APR_HAS_MMAP || defined(DOXYGEN)
+
+/** @def APR_MMAP_THRESHOLD 
+ * Files have to be at least this big before they're mmap()d.  This is to deal
+ * with systems where the expense of doing an mmap() and an munmap() outweighs
+ * the benefit for small files.  It shouldn't be set lower than 1.
+ */
+#ifdef MMAP_THRESHOLD
+#  define APR_MMAP_THRESHOLD              MMAP_THRESHOLD
+#else
+#  ifdef SUNOS4
+#    define APR_MMAP_THRESHOLD            (8*1024)
+#  else
+#    define APR_MMAP_THRESHOLD            1
+#  endif /* SUNOS4 */
+#endif /* MMAP_THRESHOLD */
+
+/** @def APR_MMAP_LIMIT
+ * Maximum size of MMap region
+ */
+#ifdef MMAP_LIMIT
+#  define APR_MMAP_LIMIT                  MMAP_LIMIT
+#else
+#  define APR_MMAP_LIMIT                  (4*1024*1024)
+#endif /* MMAP_LIMIT */
 
-B<Remove a mmap'ed.>
+/** Can this file be MMaped */
+#define APR_MMAP_CANDIDATE(filelength) \
+    ((filelength >= APR_MMAP_THRESHOLD) && (filelength < APR_MMAP_LIMIT))
 
-    arg 1) The mmap'ed file.
+/*   Function definitions */
 
-=cut
+/** 
+ * Create a new mmap'ed file out of an existing APR file.
+ * @param newmmap The newly created mmap'ed file.
+ * @param file The file to turn into an mmap.
+ * @param offset The offset into the file to start the data pointer at.
+ * @param size The size of the file
+ * @param flag bit-wise or of:
+ * <PRE>
+ *          APR_MMAP_READ       MMap opened for reading
+ *          APR_MMAP_WRITE      MMap opened for writing
+ * </PRE>
+ * @param cntxt The pool to use when creating the mmap.
  */
-ap_status_t ap_mmap_delete(ap_mmap_t *mmap);
-
-/* 
-
-=head1 ap_status_t ap_mmap_offset(void **addr, ap_mmap_t *mmap, ap_offset_t offset)
+APR_DECLARE(apr_status_t) apr_mmap_create(apr_mmap_t **newmmap, 
+                                          apr_file_t *file, apr_off_t offset,
+                                          apr_size_t size, apr_int32_t flag,
+                                          apr_pool_t *cntxt);
+
+/**
+ * Duplicate the specified MMAP.
+ * @param new_mmap The structure to duplicate into. 
+ * @param old_mmap The mmap to duplicate.
+ * @param p The pool to use for new_mmap.
+ */         
+APR_DECLARE(apr_status_t) apr_mmap_dup(apr_mmap_t **new_mmap,
+                                       apr_mmap_t *old_mmap,
+                                       apr_pool_t *p);
+
+/**
+ * Remove a mmap'ed.
+ * @param mm The mmap'ed file.
+ */
+APR_DECLARE(apr_status_t) apr_mmap_delete(apr_mmap_t *mm);
 
-B<Move the pointer into the mmap'ed file to the specified offset.>
+/** 
+ * Move the pointer into the mmap'ed file to the specified offset.
+ * @param addr The pointer to the offset specified.
+ * @param mm The mmap'ed file.
+ * @param offset The offset to move to.
+ */
+APR_DECLARE(apr_status_t) apr_mmap_offset(void **addr, apr_mmap_t *mm, 
+                                          apr_off_t offset);
 
-    arg 1) The pointer to the offset specified.
-    arg 2) The mmap'ed file.
-    arg 3) The offset to move to.
+#endif /* APR_HAS_MMAP */
 
-=cut
- */
-ap_status_t ap_mmap_offset(void **addr, ap_mmap_t *mmap, ap_off_t offset);
+/** @} */
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif  /* ! APR_MMAP_H */
-
-
diff --git a/include/apr_network_io.h b/include/apr_network_io.h
index 8646f939efc..733bf5a1791 100644
--- a/include/apr_network_io.h
+++ b/include/apr_network_io.h
@@ -1,718 +1,956 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 APR_NETWORK_IO_H
 #define APR_NETWORK_IO_H
+/**
+ * @file apr_network_io.h
+ * @brief APR Network library
+ */
 
-#ifdef WIN32
-#include <winsock2.h>
-#endif
-
-#include "apr_general.h"
+#include "apr.h"
+#include "apr_pools.h"
 #include "apr_file_io.h"
 #include "apr_errno.h"
+#include "apr_inherit.h" 
+#include "apr_perms_set.h"
+
 #if APR_HAVE_NETINET_IN_H
 #include <netinet/in.h>
 #endif
+#if APR_HAVE_SYS_UN_H
+#include <sys/un.h>
+#endif
 
 #ifdef __cplusplus
 extern "C" {
 #endif /* __cplusplus */
 
-#ifndef MAX_SECS_TO_LINGER
-#define MAX_SECS_TO_LINGER 30
+/**
+ * @defgroup apr_network_io Network Routines
+ * @ingroup APR 
+ * @{
+ */
+
+#ifndef APR_MAX_SECS_TO_LINGER
+/** Maximum seconds to linger */
+#define APR_MAX_SECS_TO_LINGER 30
 #endif
 
 #ifndef APRMAXHOSTLEN
+/** Maximum hostname length */
 #define APRMAXHOSTLEN 256
 #endif
 
 #ifndef APR_ANYADDR
+/** Default 'any' address */
 #define APR_ANYADDR "0.0.0.0"
 #endif
 
-/* Socket option definitions */
-#define APR_SO_LINGER        1
-#define APR_SO_KEEPALIVE     2
-#define APR_SO_DEBUG         4
-#define APR_SO_NONBLOCK      8
-#define APR_SO_REUSEADDR     16
-#define APR_SO_TIMEOUT       32
-#define APR_SO_SNDBUF        64
-
-#define APR_POLLIN    0x001 
-#define APR_POLLPRI   0x002
-#define APR_POLLOUT   0x004
-#define APR_POLLERR   0x010
-#define APR_POLLHUP   0x020
-#define APR_POLLNVAL  0x040
-
-typedef enum {APR_SHUTDOWN_READ, APR_SHUTDOWN_WRITE, 
-	      APR_SHUTDOWN_READWRITE} ap_shutdown_how_e;
-
-/* We need to make sure we always have an in_addr type, so APR will just
+/**
+ * @defgroup apr_sockopt Socket option definitions
+ * @{
+ */
+#define APR_SO_LINGER        1    /**< Linger */
+#define APR_SO_KEEPALIVE     2    /**< Keepalive */
+#define APR_SO_DEBUG         4    /**< Debug */
+#define APR_SO_NONBLOCK      8    /**< Non-blocking IO */
+#define APR_SO_REUSEADDR     16   /**< Reuse addresses */
+#define APR_SO_SNDBUF        64   /**< Send buffer */
+#define APR_SO_RCVBUF        128  /**< Receive buffer */
+#define APR_SO_DISCONNECTED  256  /**< Disconnected */
+#define APR_TCP_NODELAY      512  /**< For SCTP sockets, this is mapped
+                                   * to STCP_NODELAY internally.
+                                   */
+#define APR_TCP_NOPUSH       1024 /**< No push */
+#define APR_RESET_NODELAY    2048 /**< This flag is ONLY set internally
+                                   * when we set APR_TCP_NOPUSH with
+                                   * APR_TCP_NODELAY set to tell us that
+                                   * APR_TCP_NODELAY should be turned on
+                                   * again when NOPUSH is turned off
+                                   */
+#define APR_INCOMPLETE_READ 4096  /**< Set on non-blocking sockets
+				   * (timeout != 0) on which the
+				   * previous read() did not fill a buffer
+				   * completely.  the next apr_socket_recv() 
+                                   * will first call select()/poll() rather than
+				   * going straight into read().  (Can also
+				   * be set by an application to force a
+				   * select()/poll() call before the next
+				   * read, in cases where the app expects
+				   * that an immediate read would fail.)
+				   */
+#define APR_INCOMPLETE_WRITE 8192 /**< like APR_INCOMPLETE_READ, but for write
+                                   * @see APR_INCOMPLETE_READ
+                                   */
+#define APR_IPV6_V6ONLY     16384 /**< Don't accept IPv4 connections on an
+                                   * IPv6 listening socket.
+                                   */
+#define APR_TCP_DEFER_ACCEPT 32768 /**< Delay accepting of new connections 
+                                    * until data is available.
+                                    * @see apr_socket_accept_filter
+                                    */
+#define APR_SO_BROADCAST     65536 /**< Allow broadcast
+                                    */
+#define APR_SO_FREEBIND     131072 /**< Allow binding to addresses not owned
+                                    * by any interface
+                                    */
+
+/** @} */
+
+/** Define what type of socket shutdown should occur. */
+typedef enum {
+    APR_SHUTDOWN_READ,          /**< no longer allow read request */
+    APR_SHUTDOWN_WRITE,         /**< no longer allow write requests */
+    APR_SHUTDOWN_READWRITE      /**< no longer allow read or write requests */
+} apr_shutdown_how_e;
+
+#define APR_IPV4_ADDR_OK  0x01  /**< @see apr_sockaddr_info_get() */
+#define APR_IPV6_ADDR_OK  0x02  /**< @see apr_sockaddr_info_get() */
+
+#if (!APR_HAVE_IN_ADDR)
+/**
+ * We need to make sure we always have an in_addr type, so APR will just
  * define it ourselves, if the platform doesn't provide it.
  */
-#if !defined(APR_HAVE_IN_ADDR)
 struct in_addr {
-    ap_uint32_t  s_addr;
-}
-#endif
-
-/* I guess not everybody uses inet_addr.  This defines ap_inet_addr
- * appropriately.
- */
-
-#if APR_HAVE_INET_ADDR
-#define ap_inet_addr    inet_addr
-#elif APR_HAVE_INET_NETWORK        /* only DGUX, as far as I know */
-#define ap_inet_addr    inet_network
-#endif
-
-typedef struct ap_socket_t     ap_socket_t;
-typedef struct ap_pollfd_t     ap_pollfd_t;
-typedef struct ap_hdtr_t       ap_hdtr_t;
-typedef struct in_addr      ap_in_addr;
-
-#if APR_HAS_SENDFILE
-/* A structure to encapsulate headers and trailers for ap_sendfile */
-struct ap_hdtr_t {
-    struct iovec* headers;
-    int numheaders;
-    struct iovec* trailers;
-    int numtrailers;
+    apr_uint32_t  s_addr; /**< storage to hold the IP# */
 };
 #endif
 
-/* function definitions */
-
-/*
-
-=head1 ap_status_t ap_create_tcp_socket(ap_socket_t **new, ap_pool_t *cont)
-
-B<Create a socket for tcp communication.>
-
-    arg 1) The new socket that has been setup. 
-    arg 2) The pool to use
-
-=cut
- */
-ap_status_t ap_create_tcp_socket(ap_socket_t **new, ap_pool_t *cont);
-
-/*
-
-=head1 ap_status_t ap_shutdown(ap_socket_t *thesocket, ap_shutdown_how_e how)
-
-B<Shutdown either reading, writing, or both sides of a tcp socket.>
-
-    arg 1) The socket to close 
-    arg 2) How to shutdown the socket.  One of:
-              APR_SHUTDOWN_READ      -- no longer allow read requests
-              APR_SHUTDOWN_WRITE     -- no longer allow write requests
-              APR_SHUTDOWN_READWRITE -- no longer allow read or write requests 
-
-B<NOTE>:  This does not actually close the socket descriptor, it just
-          controls which calls are still valid on the socket.
-
-=cut
- */
-ap_status_t ap_shutdown(ap_socket_t *ithesocket, ap_shutdown_how_e how);
-
-/*
-
-=head1 ap_status_t ap_close_socket(ap_socket_t *thesocket)
-
-B<Close a tcp socket.>
-
-    arg 1) The socket to close 
-
-=cut
+/** @def APR_INADDR_NONE
+ * Not all platforms have a real INADDR_NONE.  This macro replaces
+ * INADDR_NONE on all platforms.
  */
-ap_status_t ap_close_socket(ap_socket_t *thesocket);
-
-/*
-
-=head1 ap_status_t ap_bind(ap_socket_t *sock)
-
-B<Bind the socket to it's assocaited port>
-
-    arg 1) The socket to bind 
-
-B<NOTE>:  This is where we will find out if there is any other process
-          using the selected port.
-
-=cut
- */
-ap_status_t ap_bind(ap_socket_t *sock);
-
-/*
-
-=head1 ap_status_t ap_listen(ap_socket_t *sock, ap_int32_t backlog)
-
-B<Listen to a bound socketi for connections.> 
-
-    arg 1) The socket to listen on 
-    arg 2) The number of outstanding connections allowed in the sockets
-          listen queue.  If this value is less than zero, the listen
-          queue size is set to zero.  
-
-=cut
- */
-ap_status_t ap_listen(ap_socket_t *sock, ap_int32_t backlog);
-
-/*
-
-=head1 ap_status_t ap_accept(ap_socket_t **new, ap_socket_t *sock, ap_pool_t *connection_pool)
-
-B<Accept a new connection request>
-
-    arg 1) A copy of the socket that is connected to the socket that
-           made the connection request.  This is the socket which should
-           be used for all future communication.
-    arg 2) The socket we are listening on.
-    arg 3) The pool for the new socket.
+#ifdef INADDR_NONE
+#define APR_INADDR_NONE INADDR_NONE
+#else
+#define APR_INADDR_NONE ((unsigned int) 0xffffffff)
+#endif
 
-=cut
+/**
+ * @def APR_INET
+ * Not all platforms have these defined, so we'll define them here
+ * The default values come from FreeBSD 4.1.1
  */
-ap_status_t ap_accept(ap_socket_t **new, const ap_socket_t *sock, 
-                      ap_pool_t *connection_pool);
-
-/*
-
-=head1 ap_status_t ap_connect(ap_socket_t *sock, char *hostname)
-
-B<Issue a connection request to a socket either on the same machine or a different one.> 
-
-    arg 1) The socket we wish to use for our side of the connection 
-    arg 2) The hostname of the machine we wish to connect to.  If NULL,
-           APR assumes that the sockaddr_in in the apr_socket is completely
-           filled out.
-
-=cut
+#define APR_INET     AF_INET
+/** @def APR_UNSPEC
+ * Let the system decide which address family to use
  */
-ap_status_t ap_connect(ap_socket_t *sock, char *hostname);
-
-/*
-
-=head1 ap_status_t ap_get_remote_hostname(char **name, ap_socket_t *sock)
+#ifdef AF_UNSPEC
+#define APR_UNSPEC   AF_UNSPEC
+#else
+#define APR_UNSPEC   0
+#endif
+#if APR_HAVE_IPV6
+/** @def APR_INET6
+* IPv6 Address Family. Not all platforms may have this defined.
+*/
 
-B<Get name of the machine we are currently connected to.> 
+#define APR_INET6    AF_INET6
+#endif
 
-    arg 1) A buffer to store the hostname in.
-    arg 2) The socket to examine.
+#if APR_HAVE_SOCKADDR_UN
+#if defined (AF_UNIX)
+#define APR_UNIX    AF_UNIX
+#elif defined(AF_LOCAL)
+#define APR_UNIX    AF_LOCAL
+#else
+#error "Neither AF_UNIX nor AF_LOCAL is defined"
+#endif
+#else /* !APR_HAVE_SOCKADDR_UN */
+#if defined (AF_UNIX)
+#define APR_UNIX    AF_UNIX
+#elif defined(AF_LOCAL)
+#define APR_UNIX    AF_LOCAL
+#else
+/* TODO: Use a smarter way to detect unique APR_UNIX value */
+#define APR_UNIX    1234
+#endif
+#endif
 
-=cut
+/**
+ * @defgroup IP_Proto IP Protocol Definitions for use when creating sockets
+ * @{
  */
-ap_status_t ap_get_remote_hostname(char **name, ap_socket_t *sock);
-
-/*
+#define APR_PROTO_TCP       6   /**< TCP  */
+#define APR_PROTO_UDP      17   /**< UDP  */
+#define APR_PROTO_SCTP    132   /**< SCTP */
+/** @} */
 
-=head1 ap_status_t ap_gethostname(char *buf, ap_int32_t len, ap_pool_t *cont)
-
-B<Get name of the current machine> 
-
-    arg 1) A buffer to store the hostname in.
-    arg 2) The maximum length of the hostname that can be stored in the
-           buffer provided. 
-    arg 3) The pool to use.
-
-=cut
+/**
+ * Enum used to denote either the local and remote endpoint of a
+ * connection.
  */
-ap_status_t ap_gethostname(char *buf, int len, ap_pool_t *cont);
-
-/*
+typedef enum {
+    APR_LOCAL,   /**< Socket information for local end of connection */
+    APR_REMOTE   /**< Socket information for remote end of connection */
+} apr_interface_e;
 
-=head1 ap_status_t ap_get_socketdata(void **data, char *key, ap_socket_t *sock)
-
-B<Return the pool associated with the current socket.>
-
-    arg 1) The currently open socket.
-    arg 2) The user data associated with the socket.
-
-=cut
+/**
+ * The specific declaration of inet_addr's ... some platforms fall back
+ * inet_network (this is not good, but necessary)
  */
-ap_status_t ap_get_socketdata(void **data, char *key, ap_socket_t *sock);
-
-/*
-
-=head1 ap_status_t ap_set_socketdata(ap_socket_t *sock, void *data, char *key, ap_status_t (*cleanup) (void *))
-
-B<Set the pool associated with the current socket.>
-
-    arg 1) The currently open socket.
-    arg 2) The user data to associate with the socket.
-    arg 3) The key to associate with the data.
-    arg 4) The cleanup to call when the socket is destroyed.
 
-=cut
- */
-ap_status_t ap_set_socketdata(ap_socket_t *sock, void *data, char *key,
-                              ap_status_t (*cleanup) (void*));
-
-/*
-
-=head1 ap_status_t ap_send(ap_socket_t *sock, const char *buf, ap_ssize_t *len)
-
-B<Send data over a network.>
-
-    arg 1) The socket to send the data over.
-    arg 2) The buffer which contains the data to be sent. 
-    arg 3) On entry, the number of bytes to send; on exit, the number
-           of bytes sent.
-
-B<NOTE>:  This functions acts like a blocking write by default.  To change 
-          this behavior, use ap_setsocketopt with the APR_SO_TIMEOUT option.
-  
-   It is possible for both bytes to be sent and an error to be returned.
-  
-   APR_EINTR is never returned.
-
-=cut
- */
-ap_status_t ap_send(ap_socket_t *sock, const char *buf, ap_ssize_t *len);
-
-/*
-
-=head1 ap_status_t ap_sendv(ap_socket_t *sock, const struct iovec *vec, ap_int32_t nvec, ap_int32_t *len)
-
-B<Send multiple packets of data over a network.>
-
-    arg 1) The socket to send the data over.
-    arg 2) The array of iovec structs containing the data to send 
-    arg 3) The number of iovec structs in the array
-    arg 4) Receives the number of bytes actually written
-
-B<NOTE>:  This functions acts like a blocking write by default.  To change 
-          this behavior, use ap_setsocketopt with the APR_SO_TIMEOUT option.
-          The number of bytes actually sent is stored in argument 3.
-  
-   It is possible for both bytes to be sent and an error to be returned.
-  
-   APR_EINTR is never returned.
+#if APR_HAVE_INET_ADDR
+#define apr_inet_addr    inet_addr
+#elif APR_HAVE_INET_NETWORK        /* only DGUX, as far as I know */
+/**
+ * @warning
+ * not generally safe... inet_network() and inet_addr() perform
+ * different functions */
+#define apr_inet_addr    inet_network
+#endif
 
-=cut
- */
-ap_status_t ap_sendv(ap_socket_t *sock, const struct iovec *vec, 
-                     ap_int32_t nvec, ap_int32_t *len);
+/** A structure to represent sockets */
+typedef struct apr_socket_t     apr_socket_t;
+/**
+ * A structure to encapsulate headers and trailers for apr_socket_sendfile
+ */
+typedef struct apr_hdtr_t       apr_hdtr_t;
+/** A structure to represent in_addr */
+typedef struct in_addr          apr_in_addr_t;
+/** A structure to represent an IP subnet */
+typedef struct apr_ipsubnet_t apr_ipsubnet_t;
+
+/** @remark use apr_uint16_t just in case some system has a short that isn't 16 bits... */
+typedef apr_uint16_t            apr_port_t;
+
+/** @remark It's defined here as I think it should all be platform safe...
+ * @see apr_sockaddr_t
+ */
+typedef struct apr_sockaddr_t apr_sockaddr_t;
+/**
+ * APRs socket address type, used to ensure protocol independence
+ */
+struct apr_sockaddr_t {
+    /** The pool to use... */
+    apr_pool_t *pool;
+    /** The hostname */
+    char *hostname;
+    /** Either a string of the port number or the service name for the port */
+    char *servname;
+    /** The numeric port */
+    apr_port_t port;
+    /** The family */
+    apr_int32_t family;
+    /** How big is the sockaddr we're using? */
+    apr_socklen_t salen;
+    /** How big is the ip address structure we're using? */
+    int ipaddr_len;
+    /** How big should the address buffer be?  16 for v4 or 46 for v6
+     *  used in inet_ntop... */
+    int addr_str_len;
+    /** This points to the IP address structure within the appropriate
+     *  sockaddr structure.  */
+    void *ipaddr_ptr;
+    /** If multiple addresses were found by apr_sockaddr_info_get(), this 
+     *  points to a representation of the next address. */
+    apr_sockaddr_t *next;
+    /** Union of either IPv4 or IPv6 sockaddr. */
+    union {
+        /** IPv4 sockaddr structure */
+        struct sockaddr_in sin;
+#if APR_HAVE_IPV6
+        /** IPv6 sockaddr structure */
+        struct sockaddr_in6 sin6;
+#endif
+#if APR_HAVE_SA_STORAGE
+        /** Placeholder to ensure that the size of this union is not
+         * dependent on whether APR_HAVE_IPV6 is defined. */
+        struct sockaddr_storage sas;
+#endif
+#if APR_HAVE_SOCKADDR_UN
+        /** Unix domain socket sockaddr structure */
+        struct sockaddr_un unx;
+#endif
+    } sa;
+};
 
 #if APR_HAS_SENDFILE
-/*
-
-=head1 ap_status_t ap_sendfile(ap_socket_t *sock, ap_file_t *file, ap_hdtr_t *hdtr, ap_off_t *offset, ap_size_t *len, ap_int32_t flags)
-
-B<Send a file from an open file descriptor to a socket, along with optional headers and trailers>
-
-    arg 1) The socket to which we're writing
-    arg 2) The open file from which to read
-    arg 3) A structure containing the headers and trailers to send
-    arg 4) Offset into the file where we should begin writing
-    arg 5) Number of bytes to send 
-    arg 6) OS-specific flags to pass to sendfile()
-
-B<NOTE>:  This functions acts like a blocking write by default.  To change 
-          this behavior, use ap_setsocketopt with the APR_SO_TIMEOUT option.
-          The number of bytes actually sent is stored in argument 5.
-
-=cut
+/** 
+ * Support reusing the socket on platforms which support it (from disconnect,
+ * specifically Win32.
+ * @remark Optional flag passed into apr_socket_sendfile() 
  */
-ap_status_t ap_sendfile(ap_socket_t *sock, ap_file_t *file, ap_hdtr_t *hdtr, 
-                        ap_off_t *offset, ap_size_t *len, ap_int32_t flags);
+#define APR_SENDFILE_DISCONNECT_SOCKET      1
 #endif
 
-/*
-
-=head1 ap_status_t ap_recv(ap_socket_t *sock, char *buf, ap_ssize_t *len)
-
-B<Read data from a network.>
-
-    arg 1) The socket to read the data from.
-    arg 2) The buffer to store the data in. 
-    arg 3) On entry, the number of bytes to receive; on exit, the number
-           of bytes received.
-
-B<NOTE>:  This functions acts like a blocking read by default.  To change 
-          this behavior, use ap_setsocketopt with the APR_SO_TIMEOUT option.
-          The number of bytes actually sent is stored in argument 3.
-  
-   It is possible for both bytes to be received and an APR_EOF or
-   other error to be returned.
-  
-   APR_EINTR is never returned.
-
-=cut
- */
-ap_status_t ap_recv(ap_socket_t *sock, char *buf, ap_ssize_t *len);
-
-/*
-
-=head1 ap_status_t ap_setsocketopt(ap_socket_t *sock, ap_int32_t opt, ap_int32_t on)
-
-B<Setup socket options for the specified socket> 
-
-    arg 1) The socket to set up.
-    arg 2) The option we would like to configure.  One of:
-              APR_SO_DEBUG      --  turn on debugging information 
-              APR_SO_KEEPALIVE  --  keep connections active
-              APR_SO_LINGER     --  lingers on close if data is present
-              APR_SO_NONBLOCK   --  Turns blocking on/off for socket
-              APR_SO_REUSEADDR  --  The rules used in validating addresses
-                                    supplied to bind should allow reuse
-                                    of local addresses.
-              APR_SO_TIMEOUT    --  Set the timeout value in microseconds.
-                                    values < 0 mean wait forever.  0 means
-                                    don't wait at all.
-              APR_SO_SNDBUF     --  Set the SendBufferSize
-    arg 3) Are we turning the option on or off.
-
-=cut
- */
-ap_status_t ap_setsocketopt(ap_socket_t *sock, ap_int32_t opt, ap_int32_t on);
-
-/*
-
-=head1 ap_status_t ap_set_local_port(ap_socket_t *sock, ap_uint32_t port)
-      Assocaite a local port with a socket.
-
-    arg 1) The socket to set
-    arg 2) The local port this socket will be dealing with.
-
-B<NOTE>:  This does not bind the two together, it is just telling apr 
-          that this socket is going to use this port if possible.  If
-          the port is already used, we won't find out about it here.
-
-=cut
- */
-ap_status_t ap_set_local_port(ap_socket_t *sock, ap_uint32_t port);
-
-/*
-
-=head1 ap_status_t ap_set_remote_port(ap_socket_t *sock, ap_uint32_t port)
-
-B<Assocaite a remote port with a socket.>
-
-    arg 1) The socket to enquire about.
-    arg 2) The local port this socket will be dealing with.
-
-B<NOTE>:  This does not make a connection to the remote port, it is just 
-          telling apr which port ap_connect() should attempt to connect to.
-
-=cut
- */
-ap_status_t ap_set_remote_port(ap_socket_t *sock, ap_uint32_t port);
-
-/*
-
-=head1 ap_status_t ap_get_local_port(ap_uint32_t *port, ap_socket_t *sock)
-
-B<Return the local port with a socket.>
-
-    arg 1) The local port this socket is associated with.
-    arg 2) The socket to enquire about.
-
-=cut
- */
-ap_status_t ap_get_local_port(ap_uint32_t *port, ap_socket_t *sock);
-
-/*
-
-=head1 ap_status_t ap_get_remote_port(ap_uint32_t *port, ap_socket_t *sock)
-
-B<Return the remote port associated with a socket.>
-
-    arg 1) The remote port this socket is associated with.
-    arg 2) The socket to enquire about.
-
-=cut
- */
-ap_status_t ap_get_remote_port(ap_uint32_t *port, ap_socket_t *sock);
-
-/*
-
-=head1 ap_status_t ap_set_local_ipaddr(ap_socket_t *sock, cont char *addr)
-
-B<Assocaite a local socket addr with an apr socket.>
-
-    arg 1) The socket to use 
-    arg 2) The IP address to attach to the socket.
-           Use APR_ANYADDR to use any IP addr on the machine.
-
-B<NOTE>:  This does not bind the two together, it is just telling apr 
-          that this socket is going to use this address if possible. 
-
-=cut
- */
-ap_status_t ap_set_local_ipaddr(ap_socket_t *sock, const char *addr);
-
-/*
-
-=head1 ap_status_t ap_set_remote_ipaddr(ap_socket_t *sock, cont char *addr)
-
-B<Assocaite a remote socket addr with an apr socket.>
-
-    arg 1) The socket to use 
-    arg 2) The IP address to attach to the socket.
-
-B<NOTE>:  This does not make a connection to the remote address, it is just
-          telling apr which address ap_connect() should attempt to connect to.
-
-=cut
- */
-ap_status_t ap_set_remote_ipaddr(ap_socket_t *sock, const char *addr);
-
-/*
-
-=head1 ap_status_t ap_get_local_ipaddr(char **addr, const ap_socket_t *sock)
-
-B<Return the local IP address associated with an apr socket.>
+/** A structure to encapsulate headers and trailers for apr_socket_sendfile */
+struct apr_hdtr_t {
+    /** An iovec to store the headers sent before the file. */
+    struct iovec* headers;
+    /** number of headers in the iovec */
+    int numheaders;
+    /** An iovec to store the trailers sent after the file. */
+    struct iovec* trailers;
+    /** number of trailers in the iovec */
+    int numtrailers;
+};
 
-    arg 1) The local IP address associated with the socket.
-    arg 2) The socket to use 
+/* function definitions */
 
-=cut
+/**
+ * Create a socket.
+ * @param new_sock The new socket that has been set up.
+ * @param family The address family of the socket (e.g., APR_INET).
+ * @param type The type of the socket (e.g., SOCK_STREAM).
+ * @param protocol The protocol of the socket (e.g., APR_PROTO_TCP).
+ * @param cont The pool for the apr_socket_t and associated storage.
+ * @note The pool will be used by various functions that operate on the
+ *       socket. The caller must ensure that it is not used by other threads
+ *       at the same time.
+ */
+APR_DECLARE(apr_status_t) apr_socket_create(apr_socket_t **new_sock, 
+                                            int family, int type,
+                                            int protocol,
+                                            apr_pool_t *cont);
+
+/**
+ * Shutdown either reading, writing, or both sides of a socket.
+ * @param thesocket The socket to close 
+ * @param how How to shutdown the socket.  One of:
+ * <PRE>
+ *            APR_SHUTDOWN_READ         no longer allow read requests
+ *            APR_SHUTDOWN_WRITE        no longer allow write requests
+ *            APR_SHUTDOWN_READWRITE    no longer allow read or write requests 
+ * </PRE>
+ * @see apr_shutdown_how_e
+ * @remark This does not actually close the socket descriptor, it just
+ *      controls which calls are still valid on the socket.
+ */
+APR_DECLARE(apr_status_t) apr_socket_shutdown(apr_socket_t *thesocket,
+                                              apr_shutdown_how_e how);
+
+/**
+ * Close a socket.
+ * @param thesocket The socket to close 
+ */
+APR_DECLARE(apr_status_t) apr_socket_close(apr_socket_t *thesocket);
+
+/**
+ * Bind the socket to its associated port
+ * @param sock The socket to bind 
+ * @param sa The socket address to bind to
+ * @remark This may be where we will find out if there is any other process
+ *      using the selected port.
+ */
+APR_DECLARE(apr_status_t) apr_socket_bind(apr_socket_t *sock, 
+                                          apr_sockaddr_t *sa);
+
+/**
+ * Listen to a bound socket for connections.
+ * @param sock The socket to listen on 
+ * @param backlog The number of outstanding connections allowed in the sockets
+ *                listen queue.  If this value is less than zero, the listen
+ *                queue size is set to zero.  
+ */
+APR_DECLARE(apr_status_t) apr_socket_listen(apr_socket_t *sock, 
+                                            apr_int32_t backlog);
+
+/**
+ * Accept a new connection request
+ * @param new_sock A copy of the socket that is connected to the socket that
+ *                 made the connection request.  This is the socket which should
+ *                 be used for all future communication.
+ * @param sock The socket we are listening on.
+ * @param connection_pool The pool for the new socket.
+ * @note The pool will be used by various functions that operate on the
+ *       socket. The caller must ensure that it is not used by other threads
+ *       at the same time.
+ */
+APR_DECLARE(apr_status_t) apr_socket_accept(apr_socket_t **new_sock, 
+                                            apr_socket_t *sock,
+                                            apr_pool_t *connection_pool);
+
+/**
+ * Issue a connection request to a socket either on the same machine 
+ * or a different one.
+ * @param sock The socket we wish to use for our side of the connection 
+ * @param sa The address of the machine we wish to connect to.
+ */
+APR_DECLARE(apr_status_t) apr_socket_connect(apr_socket_t *sock,
+                                             apr_sockaddr_t *sa);
+
+/**
+ * Determine whether the receive part of the socket has been closed by
+ * the peer (such that a subsequent call to apr_socket_read would
+ * return APR_EOF), if the socket's receive buffer is empty.  This
+ * function does not block waiting for I/O.
+ *
+ * @param sock The socket to check
+ * @param atreadeof If APR_SUCCESS is returned, *atreadeof is set to
+ *                  non-zero if a subsequent read would return APR_EOF
+ * @return an error is returned if it was not possible to determine the
+ *         status, in which case *atreadeof is not changed.
+ */
+APR_DECLARE(apr_status_t) apr_socket_atreadeof(apr_socket_t *sock,
+                                               int *atreadeof);
+
+/**
+ * Create apr_sockaddr_t from hostname, address family, and port.
+ * @param sa The new apr_sockaddr_t.
+ * @param hostname The hostname or numeric address string to resolve/parse, or
+ *               NULL to build an address that corresponds to 0.0.0.0 or ::
+ *               or in case of APR_UNIX family it is absolute socket filename.
+ * @param family The address family to use, or APR_UNSPEC if the system should 
+ *               decide.
+ * @param port The port number.
+ * @param flags Special processing flags:
+ * <PRE>
+ *       APR_IPV4_ADDR_OK          first query for IPv4 addresses; only look
+ *                                 for IPv6 addresses if the first query failed;
+ *                                 only valid if family is APR_UNSPEC and hostname
+ *                                 isn't NULL; mutually exclusive with
+ *                                 APR_IPV6_ADDR_OK
+ *       APR_IPV6_ADDR_OK          first query for IPv6 addresses; only look
+ *                                 for IPv4 addresses if the first query failed;
+ *                                 only valid if family is APR_UNSPEC and hostname
+ *                                 isn't NULL and APR_HAVE_IPV6; mutually exclusive
+ *                                 with APR_IPV4_ADDR_OK
+ * </PRE>
+ * @param p The pool for the apr_sockaddr_t and associated storage.
+ */
+APR_DECLARE(apr_status_t) apr_sockaddr_info_get(apr_sockaddr_t **sa,
+                                          const char *hostname,
+                                          apr_int32_t family,
+                                          apr_port_t port,
+                                          apr_int32_t flags,
+                                          apr_pool_t *p);
+
+/**
+ * Copy apr_sockaddr_t src to dst on pool p.
+ * @param dst The destination apr_sockaddr_t.
+ * @param src The source apr_sockaddr_t.
+ * @param p The pool for the apr_sockaddr_t and associated storage.
+ */
+APR_DECLARE(apr_status_t) apr_sockaddr_info_copy(apr_sockaddr_t **dst,
+                                                 const apr_sockaddr_t *src,
+                                                 apr_pool_t *p);
+
+/* Set the zone of an IPv6 link-local address object.
+ * @param sa Socket address object
+ * @param zone_id Zone ID (textual "eth0" or numeric "3").
+ * @return Returns APR_EBADIP for non-IPv6 socket or an IPv6 address
+ * which isn't link-local.
+ */
+APR_DECLARE(apr_status_t) apr_sockaddr_zone_set(apr_sockaddr_t *sa,
+                                                const char *zone_id);
+
+
+/* Retrieve the zone of an IPv6 link-local address object.
+ * @param sa Socket address object
+ * @param name If non-NULL, set to the textual representation of the zone id
+ * @param id If non-NULL, set to the integer zone id
+ * @param p Pool from which *name is allocated if used.
+ * @return Returns APR_EBADIP for non-IPv6 socket or socket without any zone id
+ * set, or other error if the interface could not be mapped to a name.
+ * @remark Both name and id may be NULL, neither are modified if
+ * non-NULL in error cases.
+ */
+APR_DECLARE(apr_status_t) apr_sockaddr_zone_get(const apr_sockaddr_t *sa,
+                                                const char **name,
+                                                apr_uint32_t *id,
+                                                apr_pool_t *p);                                                
+    
+/**
+ * Look up the host name from an apr_sockaddr_t.
+ * @param hostname The hostname.
+ * @param sa The apr_sockaddr_t.
+ * @param flags Special processing flags.
+ * @remark Results can vary significantly between platforms
+ * when processing wildcard socket addresses.
+ */
+APR_DECLARE(apr_status_t) apr_getnameinfo(char **hostname,
+                                          apr_sockaddr_t *sa,
+                                          apr_int32_t flags);
+
+/**
+ * Parse hostname/IP address with scope id and port.
+ *
+ * Any of the following strings are accepted:
+ *   8080                  (just the port number)
+ *   www.apache.org        (just the hostname)
+ *   www.apache.org:8080   (hostname and port number)
+ *   [fe80::1]:80          (IPv6 numeric address string only)
+ *   [fe80::1%eth0]        (IPv6 numeric address string and scope id)
+ *
+ * Invalid strings:
+ *                         (empty string)
+ *   [abc]                 (not valid IPv6 numeric address string)
+ *   abc:65536             (invalid port number)
+ *
+ * @param addr The new buffer containing just the hostname.  On output, *addr 
+ *             will be NULL if no hostname/IP address was specfied.
+ * @param scope_id The new buffer containing just the scope id.  On output, 
+ *                 *scope_id will be NULL if no scope id was specified.
+ * @param port The port number.  On output, *port will be 0 if no port was 
+ *             specified.
+ *             ### FIXME: 0 is a legal port (per RFC 1700). this should
+ *             ### return something besides zero if the port is missing.
+ * @param str The input string to be parsed.
+ * @param p The pool from which *addr and *scope_id are allocated.
+ * @remark If scope id shouldn't be allowed, check for scope_id != NULL in 
+ *         addition to checking the return code.  If addr/hostname should be 
+ *         required, check for addr == NULL in addition to checking the 
+ *         return code.
+ */
+APR_DECLARE(apr_status_t) apr_parse_addr_port(char **addr,
+                                              char **scope_id,
+                                              apr_port_t *port,
+                                              const char *str,
+                                              apr_pool_t *p);
+
+/**
+ * Get name of the current machine
+ * @param buf A buffer to store the hostname in.
+ * @param len The maximum length of the hostname that can be stored in the
+ *            buffer provided.  The suggested length is APRMAXHOSTLEN + 1.
+ * @param cont The pool to use.
+ * @remark If the buffer was not large enough, an error will be returned.
+ */
+APR_DECLARE(apr_status_t) apr_gethostname(char *buf, int len, apr_pool_t *cont);
+
+/**
+ * Return the data associated with the current socket
+ * @param data The user data associated with the socket.
+ * @param key The key to associate with the user data.
+ * @param sock The currently open socket.
+ */
+APR_DECLARE(apr_status_t) apr_socket_data_get(void **data, const char *key,
+                                              apr_socket_t *sock);
+
+/**
+ * Set the data associated with the current socket.
+ * @param sock The currently open socket.
+ * @param data The user data to associate with the socket.
+ * @param key The key to associate with the data.
+ * @param cleanup The cleanup to call when the socket is destroyed.
+ */
+APR_DECLARE(apr_status_t) apr_socket_data_set(apr_socket_t *sock, void *data,
+                                              const char *key,
+                                              apr_status_t (*cleanup)(void*));
+
+/**
+ * Send data over a network.
+ * @param sock The socket to send the data over.
+ * @param buf The buffer which contains the data to be sent. 
+ * @param len On entry, the number of bytes to send; on exit, the number
+ *            of bytes sent.
+ * @remark
+ * <PRE>
+ * This functions acts like a blocking write by default.  To change 
+ * this behavior, use apr_socket_timeout_set() or the APR_SO_NONBLOCK
+ * socket option.
+ *
+ * It is possible for both bytes to be sent and an error to be returned.
+ *
+ * APR_EINTR is never returned.
+ * </PRE>
+ */
+APR_DECLARE(apr_status_t) apr_socket_send(apr_socket_t *sock, const char *buf, 
+                                          apr_size_t *len);
+
+/**
+ * Send multiple buffers over a network.
+ * @param sock The socket to send the data over.
+ * @param vec The array of iovec structs containing the data to send 
+ * @param nvec The number of iovec structs in the array
+ * @param len Receives the number of bytes actually written
+ * @remark
+ * <PRE>
+ * This functions acts like a blocking write by default.  To change 
+ * this behavior, use apr_socket_timeout_set() or the APR_SO_NONBLOCK
+ * socket option.
+ * The number of bytes actually sent is stored in argument 4.
+ *
+ * It is possible for both bytes to be sent and an error to be returned.
+ *
+ * APR_EINTR is never returned.
+ * </PRE>
+ */
+APR_DECLARE(apr_status_t) apr_socket_sendv(apr_socket_t *sock, 
+                                           const struct iovec *vec,
+                                           apr_int32_t nvec, apr_size_t *len);
+
+/**
+ * @param sock The socket to send from
+ * @param where The apr_sockaddr_t describing where to send the data
+ * @param flags The flags to use
+ * @param buf  The data to send
+ * @param len  The length of the data to send
+ */
+APR_DECLARE(apr_status_t) apr_socket_sendto(apr_socket_t *sock, 
+                                            apr_sockaddr_t *where,
+                                            apr_int32_t flags, const char *buf, 
+                                            apr_size_t *len);
+
+/**
+ * Read data from a socket.  On success, the address of the peer from
+ * which the data was sent is copied into the @a from parameter, and the
+ * @a len parameter is updated to give the number of bytes written to
+ * @a buf.
+ *
+ * @param from Updated with the address from which the data was received
+ * @param sock The socket to use
+ * @param flags The flags to use
+ * @param buf  The buffer to use
+ * @param len  The length of the available buffer
+ */
+
+APR_DECLARE(apr_status_t) apr_socket_recvfrom(apr_sockaddr_t *from, 
+                                              apr_socket_t *sock,
+                                              apr_int32_t flags, char *buf, 
+                                              apr_size_t *len);
+ 
+#if APR_HAS_SENDFILE || defined(DOXYGEN)
+
+/**
+ * Send a file from an open file descriptor to a socket, along with 
+ * optional headers and trailers
+ * @param sock The socket to which we're writing
+ * @param file The open file from which to read
+ * @param hdtr A structure containing the headers and trailers to send
+ * @param offset Offset into the file where we should begin writing
+ * @param len (input)  - Number of bytes to send from the file 
+ *            (output) - Number of bytes actually sent, 
+ *                       including headers, file, and trailers
+ * @param flags APR flags that are mapped to OS specific flags
+ * @remark This functions acts like a blocking write by default.  To change 
+ *         this behavior, use apr_socket_timeout_set() or the
+ *         APR_SO_NONBLOCK socket option.
+ * The number of bytes actually sent is stored in the len parameter.
+ * The offset parameter is passed by reference for no reason; its
+ * value will never be modified by the apr_socket_sendfile() function.
+ * It is possible for both bytes to be sent and an error to be returned.
+ */
+APR_DECLARE(apr_status_t) apr_socket_sendfile(apr_socket_t *sock, 
+                                              apr_file_t *file,
+                                              apr_hdtr_t *hdtr,
+                                              apr_off_t *offset,
+                                              apr_size_t *len,
+                                              apr_int32_t flags);
+
+#endif /* APR_HAS_SENDFILE */
+
+/**
+ * Read data from a network.
+ * @param sock The socket to read the data from.
+ * @param buf The buffer to store the data in. 
+ * @param len On entry, the number of bytes to receive; on exit, the number
+ *            of bytes received.
+ * @remark
+ * <PRE>
+ * This functions acts like a blocking read by default.  To change 
+ * this behavior, use apr_socket_timeout_set() or the APR_SO_NONBLOCK
+ * socket option.
+ * The number of bytes actually received is stored in argument 3.
+ *
+ * It is possible for both bytes to be received and an APR_EOF or
+ * other error to be returned.
+ *
+ * APR_EINTR is never returned.
+ * </PRE>
+ */
+APR_DECLARE(apr_status_t) apr_socket_recv(apr_socket_t *sock, 
+                                   char *buf, apr_size_t *len);
+
+/**
+ * Wait for a socket to be ready for input or output
+ * @param sock the socket to wait on
+ * @param direction whether to wait for reading or writing to be ready
+ * @remark Will time out if socket has a time out set for it
+ * @remark direction can be either APR_WAIT_READ or APR_WAIT_WRITE
+ */
+APR_DECLARE(apr_status_t) apr_socket_wait(apr_socket_t *sock, 
+                                          apr_wait_type_t direction);
+
+/**
+ * Setup socket options for the specified socket
+ * @param sock The socket to set up.
+ * @param opt The option we would like to configure.  One of:
+ * <PRE>
+ *            APR_SO_DEBUG      --  turn on debugging information 
+ *            APR_SO_KEEPALIVE  --  keep connections active
+ *            APR_SO_LINGER     --  lingers on close if data is present
+ *            APR_SO_NONBLOCK   --  Turns blocking on/off for socket
+ *                                  When this option is enabled, use
+ *                                  the APR_STATUS_IS_EAGAIN() macro to
+ *                                  see if a send or receive function
+ *                                  could not transfer data without
+ *                                  blocking.
+ *            APR_SO_REUSEADDR  --  The rules used in validating addresses
+ *                                  supplied to bind should allow reuse
+ *                                  of local addresses.
+ *            APR_SO_SNDBUF     --  Set the SendBufferSize
+ *            APR_SO_RCVBUF     --  Set the ReceiveBufferSize
+ *            APR_SO_FREEBIND   --  Allow binding to non-local IP address.
+ * </PRE>
+ * @param on Value for the option.
+ */
+APR_DECLARE(apr_status_t) apr_socket_opt_set(apr_socket_t *sock,
+                                             apr_int32_t opt, apr_int32_t on);
+
+/**
+ * Setup socket timeout for the specified socket
+ * @param sock The socket to set up.
+ * @param t Value for the timeout.
+ * <PRE>
+ *   t > 0  -- read and write calls return APR_TIMEUP if specified time
+ *             elapsess with no data read or written
+ *   t == 0 -- read and write calls never block
+ *   t < 0  -- read and write calls block
+ * </PRE>
+ */
+APR_DECLARE(apr_status_t) apr_socket_timeout_set(apr_socket_t *sock,
+                                                 apr_interval_time_t t);
+
+/**
+ * Query socket options for the specified socket
+ * @param sock The socket to query
+ * @param opt The option we would like to query.  One of:
+ * <PRE>
+ *            APR_SO_DEBUG      --  turn on debugging information 
+ *            APR_SO_KEEPALIVE  --  keep connections active
+ *            APR_SO_LINGER     --  lingers on close if data is present
+ *            APR_SO_NONBLOCK   --  Turns blocking on/off for socket
+ *            APR_SO_REUSEADDR  --  The rules used in validating addresses
+ *                                  supplied to bind should allow reuse
+ *                                  of local addresses.
+ *            APR_SO_SNDBUF     --  Set the SendBufferSize
+ *            APR_SO_RCVBUF     --  Set the ReceiveBufferSize
+ *            APR_SO_DISCONNECTED -- Query the disconnected state of the socket.
+ *                                  (Currently only used on Windows)
+ * </PRE>
+ * @param on Socket option returned on the call.
+ */
+APR_DECLARE(apr_status_t) apr_socket_opt_get(apr_socket_t *sock, 
+                                             apr_int32_t opt, apr_int32_t *on);
+
+/**
+ * Query socket timeout for the specified socket
+ * @param sock The socket to query
+ * @param t Socket timeout returned from the query.
+ */
+APR_DECLARE(apr_status_t) apr_socket_timeout_get(apr_socket_t *sock, 
+                                                 apr_interval_time_t *t);
+
+/**
+ * Query the specified socket if at the OOB/Urgent data mark
+ * @param sock The socket to query
+ * @param atmark Is set to true if socket is at the OOB/urgent mark,
+ *               otherwise is set to false.
+ */
+APR_DECLARE(apr_status_t) apr_socket_atmark(apr_socket_t *sock, 
+                                            int *atmark);
+
+/**
+ * Return an address associated with a socket; either the address to
+ * which the socket is bound locally or the address of the peer
+ * to which the socket is connected.
+ * @param sa The returned apr_sockaddr_t.
+ * @param which Whether to retrieve the local or remote address
+ * @param sock The socket to use
+ */
+APR_DECLARE(apr_status_t) apr_socket_addr_get(apr_sockaddr_t **sa,
+                                              apr_interface_e which,
+                                              apr_socket_t *sock);
+ 
+/**
+ * Return the IP address (in numeric address string format) in
+ * an APR socket address.  APR will allocate storage for the IP address 
+ * string from the pool of the apr_sockaddr_t.
+ * @param addr The IP address.
+ * @param sockaddr The socket address to reference.
+ */
+APR_DECLARE(apr_status_t) apr_sockaddr_ip_get(char **addr, 
+                                              apr_sockaddr_t *sockaddr);
+
+/**
+ * Write the IP address (in numeric address string format) of the APR
+ * socket address @a sockaddr into the buffer @a buf (of size @a buflen).
+ * @param sockaddr The socket address to reference.
+ */
+APR_DECLARE(apr_status_t) apr_sockaddr_ip_getbuf(char *buf, apr_size_t buflen,
+                                                 apr_sockaddr_t *sockaddr);
+
+/**
+ * See if the IP addresses in two APR socket addresses are
+ * equivalent.  Appropriate logic is present for comparing
+ * IPv4-mapped IPv6 addresses with IPv4 addresses.
+ *
+ * @param addr1 One of the APR socket addresses.
+ * @param addr2 The other APR socket address.
+ * @remark The return value will be non-zero if the addresses
+ * are equivalent.
  */
-ap_status_t ap_get_local_ipaddr(char **addr, const ap_socket_t *sock);
-
-/*
-
-=head1 ap_status_t ap_get_remote_ipaddr(char **addr, const ap_socket_t *sock)
-
-B<Return the remote IP address associated with an apr socket.>
+APR_DECLARE(int) apr_sockaddr_equal(const apr_sockaddr_t *addr1,
+                                    const apr_sockaddr_t *addr2);
 
-    arg 1) The remote IP address associated with the socket.
-    arg 2) The socket to use 
+/**
+ * See if the IP address in an APR socket address refers to the wildcard
+ * address for the protocol family (e.g., INADDR_ANY for IPv4).
+ *
+ * @param addr The APR socket address to examine.
+ * @remark The return value will be non-zero if the address is
+ * initialized and is the wildcard address.
+ */
+APR_DECLARE(int) apr_sockaddr_is_wildcard(const apr_sockaddr_t *addr);
+
+/**
+* Return the type of the socket.
+* @param sock The socket to query.
+* @param type The returned type (e.g., SOCK_STREAM).
+*/
+APR_DECLARE(apr_status_t) apr_socket_type_get(apr_socket_t *sock,
+                                              int *type);
+ 
+/**
+ * Given an apr_sockaddr_t and a service name, set the port for the service
+ * @param sockaddr The apr_sockaddr_t that will have its port set
+ * @param servname The name of the service you wish to use
+ */
+APR_DECLARE(apr_status_t) apr_getservbyname(apr_sockaddr_t *sockaddr, 
+                                            const char *servname);
+/**
+ * Build an ip-subnet representation from an IP address and optional netmask or
+ * number-of-bits.
+ * @param ipsub The new ip-subnet representation
+ * @param ipstr The input IP address string
+ * @param mask_or_numbits The input netmask or number-of-bits string, or NULL
+ * @param p The pool to allocate from
+ */
+APR_DECLARE(apr_status_t) apr_ipsubnet_create(apr_ipsubnet_t **ipsub, 
+                                              const char *ipstr, 
+                                              const char *mask_or_numbits, 
+                                              apr_pool_t *p);
+
+/**
+ * Test the IP address in an apr_sockaddr_t against a pre-built ip-subnet
+ * representation.
+ * @param ipsub The ip-subnet representation
+ * @param sa The socket address to test
+ * @return non-zero if the socket address is within the subnet, 0 otherwise
+ */
+APR_DECLARE(int) apr_ipsubnet_test(apr_ipsubnet_t *ipsub, apr_sockaddr_t *sa);
+
+#if APR_HAS_SO_ACCEPTFILTER || defined(DOXYGEN)
+/**
+ * Set an OS level accept filter.
+ * @param sock The socket to put the accept filter on.
+ * @param name The accept filter
+ * @param args Any extra args to the accept filter.  Passing NULL here removes
+ *             the accept filter. 
+ */
+apr_status_t apr_socket_accept_filter(apr_socket_t *sock, const char *name,
+                                      const char *args);
+#endif
 
-=cut
+/**
+ * Return the protocol of the socket.
+ * @param sock The socket to query.
+ * @param protocol The returned protocol (e.g., APR_PROTO_TCP).
  */
-ap_status_t ap_get_remote_ipaddr(char **addr, const ap_socket_t *sock);
-
-/*
+APR_DECLARE(apr_status_t) apr_socket_protocol_get(apr_socket_t *sock,
+                                                  int *protocol);
 
-=head1 ap_status_t ap_get_local_name(struct sockaddr_in **name, const ap_socket_t *sock)
-
-B<Return the local socket name as a BSD style struct sockaddr_in.>
-
-    arg 1) The local name associated with the socket.
-    arg 2) The socket to use 
-
-=cut
+/**
+ * Get the pool used by the socket.
  */
-ap_status_t ap_get_local_name(struct sockaddr_in **name, const ap_socket_t *sock);
-
-/*
+APR_POOL_DECLARE_ACCESSOR(socket);
 
-=head1 ap_status_t ap_get_remote_name(struct sockaddr_in **name, const ap_socket_t *sock)
-
-B<Return the remote socket name as a BSD style struct sockaddr_in.>
-
-    arg 1) The remote name associated with the socket.
-    arg 2) The socket to use 
-
-=cut
+/**
+ * Set a socket to be inherited by child processes.
  */
-ap_status_t ap_get_remote_name(struct sockaddr_in **name, const ap_socket_t *sock);
-
-/*
+APR_DECLARE_INHERIT_SET(socket);
 
-=head1 ap_status_t ap_setup_poll(ap_pollfd_t **new, ap_int32_t num, ap_pool_t *cont)
-
-B<Setup the memory required for poll to operate properly.>
-
-    arg 1) The poll structure to be used. 
-    arg 2) The number of socket descriptors to be polled.
-    arg 3) The pool to operate on.
-
-=cut
+/**
+ * Unset a socket from being inherited by child processes.
  */
-ap_status_t ap_setup_poll(ap_pollfd_t **new, ap_int32_t num, 
-                          ap_pool_t *cont);
-
-/*
-
-=head1 ap_status_t ap_poll(ap_pollfd_t *aprset, ap_int32_t *nsds, ap_interval_time_t timeout)
-
-B<Poll the sockets in the poll structure.>
-
-    arg 1) The poll structure we will be using. 
-    arg 2) The number of sockets we are polling. 
-    arg 3) The amount of time in microseconds to wait.  This is a maximum, not 
-           a minimum.  If a socket is signalled, we will wake up before this
-           time.  A negative number means wait until a socket is signalled.
+APR_DECLARE_INHERIT_UNSET(socket);
 
-B<NOTE>:  The number of sockets signalled is returned in the second argument. 
-
-          This is a blocking call, and it will not return until either a 
-          socket has been signalled, or the timeout has expired. 
-
-=cut
+/**
+ * Set socket permissions.
  */
-ap_status_t ap_poll(ap_pollfd_t *aprset, ap_int32_t *nsds, ap_interval_time_t timeout);
-
-/*
-
-=head1 ap_status_t ap_add_poll_socket(ap_pollfd_t *aprset, ap_socket_t *sock, ap_int16_t event)
+APR_PERMS_SET_IMPLEMENT(socket);
 
-B<Add a socket to the poll structure.> 
-
-    arg 1) The poll structure we will be using. 
-    arg 2) The socket to add to the current poll structure. 
-    arg 3) The events to look for when we do the poll.  One of:
-              APR_POLLIN    -- signal if read will not block
-              APR_POLLPRI   -- signal if prioirty data is availble to be read
-              APR_POLLOUT   -- signal if write will not block
-
-=cut
+/**
+ * @defgroup apr_mcast IP Multicast
+ * @{
  */
-ap_status_t ap_add_poll_socket(ap_pollfd_t *aprset, ap_socket_t *socket, 
-                               ap_int16_t event);
-
-/*
-
-=head1 ap_status_t ap_mask_poll_socket(ap_pollfd_t *aprset, ap_socket_t *sock, ap_int16_t events)
 
-B<Modfify a socket in the poll structure with mask.> 
-
-    arg 1) The poll structure we will be using. 
-    arg 2) The socket to modify in poll structure. 
-    arg 3) The events to stop looking for during the poll.  One of:
-              APR_POLLIN    -- signal if read will not block
-              APR_POLLPRI   -- signal if prioirty data is availble to be read
-              APR_POLLOUT   -- signal if write will not block
-
-=cut
+/**
+ * Join a Multicast Group
+ * @param sock The socket to join a multicast group
+ * @param join The address of the multicast group to join
+ * @param iface Address of the interface to use.  If NULL is passed, the 
+ *              default multicast interface will be used. (OS Dependent)
+ * @param source Source Address to accept transmissions from (non-NULL 
+ *               implies Source-Specific Multicast)
  */
-ap_status_t ap_mask_poll_socket(ap_pollfd_t *aprset, ap_socket_t *sock,
-                                  ap_int16_t events);
-/*
-
-=head1 ap_status_t ap_remove_poll_socket(ap_pollfd_t *aprset, ap_socket_t *sock)
-
-B<Remove a socket from the poll structure.> 
+APR_DECLARE(apr_status_t) apr_mcast_join(apr_socket_t *sock,
+                                         apr_sockaddr_t *join,
+                                         apr_sockaddr_t *iface,
+                                         apr_sockaddr_t *source);
 
-    arg 1) The poll structure we will be using. 
-    arg 2) The socket to remove from the current poll structure. 
-
-=cut
+/**
+ * Leave a Multicast Group.  All arguments must be the same as
+ * apr_mcast_join.
+ * @param sock The socket to leave a multicast group
+ * @param addr The address of the multicast group to leave
+ * @param iface Address of the interface to use.  If NULL is passed, the 
+ *              default multicast interface will be used. (OS Dependent)
+ * @param source Source Address to accept transmissions from (non-NULL 
+ *               implies Source-Specific Multicast)
  */
-ap_status_t ap_remove_poll_socket(ap_pollfd_t *aprset, ap_socket_t *sock);
-
-/*
-
-=head1 ap_status_t ap_clear_poll_sockets(ap_pollfd_t *aprset, ap_int16_t events)
+APR_DECLARE(apr_status_t) apr_mcast_leave(apr_socket_t *sock,
+                                          apr_sockaddr_t *addr,
+                                          apr_sockaddr_t *iface,
+                                          apr_sockaddr_t *source);
 
-B<Remove all sockets from the poll structure.> 
-
-    arg 1) The poll structure we will be using. 
-    arg 2) The events to clear from all sockets.  One of:
-              APR_POLLIN    -- signal if read will not block
-              APR_POLLPRI   -- signal if prioirty data is availble to be read
-              APR_POLLOUT   -- signal if write will not block
-
-=cut
+/**
+ * Set the Multicast Time to Live (ttl) for a multicast transmission.
+ * @param sock The socket to set the multicast ttl
+ * @param ttl Time to live to Assign. 0-255, default=1
+ * @remark If the TTL is 0, packets will only be seen by sockets on 
+ * the local machine, and only when multicast loopback is enabled.
  */
-ap_status_t ap_clear_poll_sockets(ap_pollfd_t *aprset, ap_int16_t events);
-
-/*
-
-=head1 ap_status_t ap_get_revents(ap_int_16_t *event, ap_socket_t *sock, ap_pollfd_t *aprset)
+APR_DECLARE(apr_status_t) apr_mcast_hops(apr_socket_t *sock,
+                                         apr_byte_t ttl);
 
-B<Get the return events for the specified socket.> 
-
-    arg 1) The returned events for the socket.  One of:
-              APR_POLLIN    -- Data is available to be read 
-              APR_POLLPRI   -- Prioirty data is availble to be read
-              APR_POLLOUT   -- Write will succeed
-              APR_POLLERR   -- An error occurred on the socket
-              APR_POLLHUP   -- The connection has been terminated
-              APR_POLLNVAL  -- This is an invalid socket to poll on.
-                               Socket not open.
-    arg 2) The socket we wish to get information about. 
-    arg 3) The poll structure we will be using. 
-
-=cut
+/**
+ * Toggle IP Multicast Loopback
+ * @param sock The socket to set multicast loopback
+ * @param opt 0=disable, 1=enable
  */
-ap_status_t ap_get_revents(ap_int16_t *event, ap_socket_t *sock, 
-                           ap_pollfd_t *aprset);
-
-/*
+APR_DECLARE(apr_status_t) apr_mcast_loopback(apr_socket_t *sock,
+                                             apr_byte_t opt);
 
-=head1 ap_status_t ap_get_polldata(ap_pollfd_t *pollfd, char *key, void *data)
 
-B<Return the pool associated with the current poll.>
-
-    arg 1) The currently open pollfd.
-    arg 2) The key to use for retreiving data associated with a poll struct.
-    arg 3) The user data associated with the pollfd.
-
-=cut
+/**
+ * Set the Interface to be used for outgoing Multicast Transmissions.
+ * @param sock The socket to set the multicast interface on
+ * @param iface Address of the interface to use for Multicast
  */
-ap_status_t ap_get_polldata(ap_pollfd_t *pollfd, char *key, void *data);
-
-/*
-
-=head1 ap_status_t ap_set_polldata(ap_pollfd_t *pollfd, void *data, char *key, ap_status_t (*cleanup) (void *))
+APR_DECLARE(apr_status_t) apr_mcast_interface(apr_socket_t *sock,
+                                              apr_sockaddr_t *iface);
 
-B<Return the pool associated with the current poll.>
-
-    arg 1) The currently open pollfd.
-    arg 2) The user data to associate with the pollfd.
-
-=cut
- */
-ap_status_t ap_set_polldata(ap_pollfd_t *pollfd, void *data, char *key,
-                            ap_status_t (*cleanup) (void *));
+/** @} */
 
-/*  accessor functions   */
+/** @} */
 
 #ifdef __cplusplus
 }
diff --git a/include/apr_optional.h b/include/apr_optional.h
new file mode 100644
index 00000000000..e628fa0d35c
--- /dev/null
+++ b/include/apr_optional.h
@@ -0,0 +1,92 @@
+/* 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 APR_OPTIONAL_H
+#define APR_OPTIONAL_H
+
+#include "apu.h"
+/** 
+ * @file apr_optional.h
+ * @brief APR-UTIL registration of functions exported by modules
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** 
+ * @defgroup APR_Util_Opt Optional Functions
+ * @ingroup APR
+ *
+ * Typesafe registration and retrieval of functions that may not be present
+ * (i.e. functions exported by optional modules)
+ * @{
+ */
+
+/**
+ * The type of an optional function.
+ * @param name The name of the function
+ */
+#define APR_OPTIONAL_FN_TYPE(name) apr_OFN_##name##_t
+
+/**
+ * Declare an optional function.
+ * @param ret The return type of the function
+ * @param name The name of the function
+ * @param args The function arguments (including brackets)
+ */
+#define APR_DECLARE_OPTIONAL_FN(ret,name,args) \
+typedef ret (APR_OPTIONAL_FN_TYPE(name)) args
+
+/**
+ * XXX: This doesn't belong here, then!
+ * Private function! DO NOT USE! 
+ * @internal
+ */
+
+typedef void (apr_opt_fn_t)(void);
+/** @internal */
+APR_DECLARE_NONSTD(void) apr_dynamic_fn_register(const char *szName, 
+                                                  apr_opt_fn_t *pfn);
+
+/**
+ * Register an optional function. This can be later retrieved, type-safely, by
+ * name. Like all global functions, the name must be unique. Note that,
+ * confusingly but correctly, the function itself can be static!
+ * @param name The name of the function
+ */
+#define APR_REGISTER_OPTIONAL_FN(name) do { \
+  APR_OPTIONAL_FN_TYPE(name) *apu__opt = name; \
+  apr_dynamic_fn_register(#name,(apr_opt_fn_t *)apu__opt); \
+} while (0)
+
+/** @internal
+ * Private function! DO NOT USE! 
+ */
+APR_DECLARE(apr_opt_fn_t *) apr_dynamic_fn_retrieve(const char *szName);
+
+/**
+ * Retrieve an optional function. Returns NULL if the function is not present.
+ * @param name The name of the function
+ */
+#define APR_RETRIEVE_OPTIONAL_FN(name) \
+	(APR_OPTIONAL_FN_TYPE(name) *)apr_dynamic_fn_retrieve(#name)
+
+/** @} */
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* APR_OPTIONAL_H */
diff --git a/include/apr_optional_hooks.h b/include/apr_optional_hooks.h
new file mode 100644
index 00000000000..ac100a24893
--- /dev/null
+++ b/include/apr_optional_hooks.h
@@ -0,0 +1,117 @@
+/* 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 apr_optional_hooks.h
+ * @brief Apache optional hook functions
+ */
+
+
+#ifndef APR_OPTIONAL_HOOK_H
+#define APR_OPTIONAL_HOOK_H
+
+#include "apr_tables.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/** 
+ * @defgroup APR_Util_OPT_HOOK Optional Hook Functions
+ * @ingroup APR_Util_Hook
+ * @{
+ */
+/**
+ * Function to implement the APR_OPTIONAL_HOOK Macro
+ * @internal
+ * @see APR_OPTIONAL_HOOK
+ *
+ * @param szName The name of the hook
+ * @param pfn A pointer to a function that will be called
+ * @param aszPre a NULL-terminated array of strings that name modules whose hooks should precede this one
+ * @param aszSucc a NULL-terminated array of strings that name modules whose hooks should succeed this one
+ * @param nOrder an integer determining order before honouring aszPre and aszSucc (for example HOOK_MIDDLE)
+ */
+
+
+APR_DECLARE(void) apr_optional_hook_add(const char *szName,void (*pfn)(void),
+					const char * const *aszPre,
+					const char * const *aszSucc,
+					int nOrder);
+
+/**
+ * Hook to an optional hook.
+ *
+ * @param ns The namespace prefix of the hook functions
+ * @param name The name of the hook
+ * @param pfn A pointer to a function that will be called
+ * @param aszPre a NULL-terminated array of strings that name modules whose hooks should precede this one
+ * @param aszSucc a NULL-terminated array of strings that name modules whose hooks should succeed this one
+ * @param nOrder an integer determining order before honouring aszPre and aszSucc (for example HOOK_MIDDLE)
+ */
+
+#define APR_OPTIONAL_HOOK(ns,name,pfn,aszPre,aszSucc,nOrder) do { \
+  ns##_HOOK_##name##_t *apu__hook = pfn; \
+  apr_optional_hook_add(#name,(void (*)(void))apu__hook,aszPre, aszSucc, nOrder); \
+} while (0)
+
+/**
+ * @internal
+ * @param szName - the name of the function
+ * @return the hook structure for a given hook
+ */
+APR_DECLARE(apr_array_header_t *) apr_optional_hook_get(const char *szName);
+
+/**
+ * Implement an optional hook that runs until one of the functions
+ * returns something other than OK or DECLINE.
+ *
+ * @param ns The namespace prefix of the hook functions
+ * @param link The linkage declaration prefix of the hook
+ * @param ret The type of the return value of the hook
+ * @param ret The type of the return value of the hook
+ * @param name The name of the hook
+ * @param args_decl The declaration of the arguments for the hook
+ * @param args_use The names for the arguments for the hook
+ * @param ok Success value
+ * @param decline Decline value
+ */
+#define APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(ns,link,ret,name,args_decl,args_use,ok,decline) \
+link##_DECLARE(ret) ns##_run_##name args_decl \
+    { \
+    ns##_LINK_##name##_t *pHook; \
+    int n; \
+    ret rv; \
+    apr_array_header_t *pHookArray=apr_optional_hook_get(#name); \
+\
+    if(!pHookArray) \
+	return ok; \
+\
+    pHook=(ns##_LINK_##name##_t *)pHookArray->elts; \
+    for(n=0 ; n < pHookArray->nelts ; ++n) \
+	{ \
+	rv=(pHook[n].pFunc)args_use; \
+\
+	if(rv != ok && rv != decline) \
+	    return rv; \
+	} \
+    return ok; \
+    }
+
+/** @} */
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* APR_OPTIONAL_HOOK_H */
diff --git a/include/apr_perms_set.h b/include/apr_perms_set.h
new file mode 100644
index 00000000000..92a1362b8e5
--- /dev/null
+++ b/include/apr_perms_set.h
@@ -0,0 +1,65 @@
+/* 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 APR_PERMS_SET_H
+#define APR_PERMS_SET_H
+
+/**
+ * @file apr_perms_set.h
+ * @brief APR Process Locking Routines
+ */
+
+#include "apr.h"
+#include "apr_pools.h"
+#include "apr_errno.h"
+#include "apr_user.h"
+#include "apr_file_info.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup apr_perms_set Object permission set functions
+ * @ingroup APR 
+ * @{
+ */
+
+/** Permission set callback function. */
+typedef apr_status_t (apr_perms_setfn_t)(void *object, apr_fileperms_t perms,
+                                         apr_uid_t uid, apr_gid_t gid);
+
+#define APR_PERMS_SET_IMPLEMENT(type) \
+    APR_DECLARE(apr_status_t) apr_##type##_perms_set \
+        (void *the##type, apr_fileperms_t perms, \
+         apr_uid_t uid, apr_gid_t gid)
+
+#define APR_PERMS_SET_ENOTIMPL(type) \
+    APR_DECLARE(apr_status_t) apr_##type##_perms_set \
+        (void *the##type, apr_fileperms_t perms, \
+         apr_uid_t uid, apr_gid_t gid) \
+        { return APR_ENOTIMPL ; }
+
+#define APR_PERMS_SET_FN(type) apr_##type##_perms_set
+
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* ! APR_PERMS_SET */
diff --git a/include/apr_poll.h b/include/apr_poll.h
new file mode 100644
index 00000000000..482d6ee1db7
--- /dev/null
+++ b/include/apr_poll.h
@@ -0,0 +1,446 @@
+/* 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 APR_POLL_H
+#define APR_POLL_H
+/**
+ * @file apr_poll.h
+ * @brief APR Poll interface
+ */
+#include "apr.h"
+#include "apr_pools.h"
+#include "apr_errno.h"
+#include "apr_inherit.h" 
+#include "apr_file_io.h" 
+#include "apr_network_io.h" 
+
+#if APR_HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup apr_poll Poll Routines
+ * @ingroup APR 
+ * @{
+ */
+
+/**
+ * @defgroup pollopts Poll options
+ * @ingroup apr_poll
+ * @{
+ */
+#define APR_POLLIN    0x001     /**< Can read without blocking */
+#define APR_POLLPRI   0x002     /**< Priority data available */
+#define APR_POLLOUT   0x004     /**< Can write without blocking */
+#define APR_POLLERR   0x010     /**< Pending error */
+#define APR_POLLHUP   0x020     /**< Hangup occurred */
+#define APR_POLLNVAL  0x040     /**< Descriptor invalid */
+/** @} */
+
+/**
+ * @defgroup pollflags Pollset Flags
+ * @ingroup apr_poll
+ * @{
+ */
+#define APR_POLLSET_THREADSAFE 0x001 /**< Adding or removing a descriptor is
+                                      * thread-safe
+                                      */
+#define APR_POLLSET_NOCOPY     0x002 /**< Descriptors passed to apr_pollset_add()
+                                      * are not copied
+                                      */
+#define APR_POLLSET_WAKEABLE   0x004 /**< Poll operations are interruptable by
+                                      * apr_pollset_wakeup() or apr_pollcb_wakeup()
+                                      */
+#define APR_POLLSET_NODEFAULT  0x010 /**< Do not try to use the default method if
+                                      * the specified non-default method cannot be
+                                      * used
+                                      */
+/** @} */
+
+/**
+ * Pollset Methods
+ */
+typedef enum {
+    APR_POLLSET_DEFAULT,        /**< Platform default poll method */
+    APR_POLLSET_SELECT,         /**< Poll uses select method */
+    APR_POLLSET_KQUEUE,         /**< Poll uses kqueue method */
+    APR_POLLSET_PORT,           /**< Poll uses Solaris event port method */
+    APR_POLLSET_EPOLL,          /**< Poll uses epoll method */
+    APR_POLLSET_POLL,           /**< Poll uses poll method */
+    APR_POLLSET_AIO_MSGQ        /**< Poll uses z/OS asio method */
+} apr_pollset_method_e;
+
+/** Used in apr_pollfd_t to determine what the apr_descriptor is */
+typedef enum { 
+    APR_NO_DESC,                /**< nothing here */
+    APR_POLL_SOCKET,            /**< descriptor refers to a socket */
+    APR_POLL_FILE,              /**< descriptor refers to a file */
+    APR_POLL_LASTDESC           /**< @deprecated descriptor is the last one in the list */
+} apr_datatype_e ;
+
+/** Union of either an APR file or socket. */
+typedef union {
+    apr_file_t *f;              /**< file */
+    apr_socket_t *s;            /**< socket */
+} apr_descriptor;
+
+/** @see apr_pollfd_t */
+typedef struct apr_pollfd_t apr_pollfd_t;
+
+/** Poll descriptor set. */
+struct apr_pollfd_t {
+    apr_pool_t *p;              /**< associated pool */
+    apr_datatype_e desc_type;   /**< descriptor type */
+    apr_int16_t reqevents;      /**< requested events */
+    apr_int16_t rtnevents;      /**< returned events */
+    apr_descriptor desc;        /**< @see apr_descriptor */
+    void *client_data;          /**< allows app to associate context */
+};
+
+
+/* General-purpose poll API for arbitrarily large numbers of
+ * file descriptors
+ */
+
+/** Opaque structure used for pollset API */
+typedef struct apr_pollset_t apr_pollset_t;
+
+/**
+ * Set up a pollset object
+ * @param pollset  The pointer in which to return the newly created object 
+ * @param size The maximum number of descriptors that this pollset can hold
+ * @param p The pool from which to allocate the pollset
+ * @param flags Optional flags to modify the operation of the pollset.
+ *
+ * @remark If flags contains APR_POLLSET_THREADSAFE, then a pollset is
+ *         created on which it is safe to make concurrent calls to
+ *         apr_pollset_add(), apr_pollset_remove() and apr_pollset_poll()
+ *         from separate threads.  This feature is only supported on some
+ *         platforms; the apr_pollset_create() call will fail with
+ *         APR_ENOTIMPL on platforms where it is not supported.
+ * @remark If flags contains APR_POLLSET_WAKEABLE, then a pollset is
+ *         created with an additional internal pipe object used for the
+ *         apr_pollset_wakeup() call. The actual size of pollset is
+ *         in that case @a size + 1. This feature is only supported on some
+ *         platforms; the apr_pollset_create() call will fail with
+ *         APR_ENOTIMPL on platforms where it is not supported.
+ * @remark If flags contains APR_POLLSET_NOCOPY, then the apr_pollfd_t
+ *         structures passed to apr_pollset_add() are not copied and
+ *         must have a lifetime at least as long as the pollset.
+ * @remark Some poll methods (including APR_POLLSET_KQUEUE,
+ *         APR_POLLSET_PORT, and APR_POLLSET_EPOLL) do not have a
+ *         fixed limit on the size of the pollset. For these methods,
+ *         the size parameter controls the maximum number of
+ *         descriptors that will be returned by a single call to
+ *         apr_pollset_poll().
+ */
+APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset,
+                                             apr_uint32_t size,
+                                             apr_pool_t *p,
+                                             apr_uint32_t flags);
+
+/**
+ * Set up a pollset object
+ * @param pollset  The pointer in which to return the newly created object 
+ * @param size The maximum number of descriptors that this pollset can hold
+ * @param p The pool from which to allocate the pollset
+ * @param flags Optional flags to modify the operation of the pollset.
+ * @param method Poll method to use. See #apr_pollset_method_e.  If this
+ *         method cannot be used, the default method will be used unless the
+ *         APR_POLLSET_NODEFAULT flag has been specified.
+ *
+ * @remark If flags contains APR_POLLSET_THREADSAFE, then a pollset is
+ *         created on which it is safe to make concurrent calls to
+ *         apr_pollset_add(), apr_pollset_remove() and apr_pollset_poll()
+ *         from separate threads.  This feature is only supported on some
+ *         platforms; the apr_pollset_create_ex() call will fail with
+ *         APR_ENOTIMPL on platforms where it is not supported.
+ * @remark If flags contains APR_POLLSET_WAKEABLE, then a pollset is
+ *         created with additional internal pipe object used for the
+ *         apr_pollset_wakeup() call. The actual size of pollset is
+ *         in that case size + 1. This feature is only supported on some
+ *         platforms; the apr_pollset_create_ex() call will fail with
+ *         APR_ENOTIMPL on platforms where it is not supported.
+ * @remark If flags contains APR_POLLSET_NOCOPY, then the apr_pollfd_t
+ *         structures passed to apr_pollset_add() are not copied and
+ *         must have a lifetime at least as long as the pollset.
+ * @remark Some poll methods (including APR_POLLSET_KQUEUE,
+ *         APR_POLLSET_PORT, and APR_POLLSET_EPOLL) do not have a
+ *         fixed limit on the size of the pollset. For these methods,
+ *         the size parameter controls the maximum number of
+ *         descriptors that will be returned by a single call to
+ *         apr_pollset_poll().
+ */
+APR_DECLARE(apr_status_t) apr_pollset_create_ex(apr_pollset_t **pollset,
+                                                apr_uint32_t size,
+                                                apr_pool_t *p,
+                                                apr_uint32_t flags,
+                                                apr_pollset_method_e method);
+
+/**
+ * Destroy a pollset object
+ * @param pollset The pollset to destroy
+ */
+APR_DECLARE(apr_status_t) apr_pollset_destroy(apr_pollset_t *pollset);
+
+/**
+ * Add a socket or file descriptor to a pollset
+ * @param pollset The pollset to which to add the descriptor
+ * @param descriptor The descriptor to add
+ * @remark If you set client_data in the descriptor, that value
+ *         will be returned in the client_data field whenever this
+ *         descriptor is signalled in apr_pollset_poll().
+ * @remark If the pollset has been created with APR_POLLSET_THREADSAFE
+ *         and thread T1 is blocked in a call to apr_pollset_poll() for
+ *         this same pollset that is being modified via apr_pollset_add()
+ *         in thread T2, the currently executing apr_pollset_poll() call in
+ *         T1 will either: (1) automatically include the newly added descriptor
+ *         in the set of descriptors it is watching or (2) return immediately
+ *         with APR_EINTR.  Option (1) is recommended, but option (2) is
+ *         allowed for implementations where option (1) is impossible
+ *         or impractical.
+ * @remark If the pollset has been created with APR_POLLSET_NOCOPY, the 
+ *         apr_pollfd_t structure referenced by descriptor will not be copied
+ *         and must have a lifetime at least as long as the pollset.
+ * @remark Do not add the same socket or file descriptor to the same pollset
+ *         multiple times, even if the requested events differ for the 
+ *         different calls to apr_pollset_add().  If the events of interest
+ *         for a descriptor change, you must first remove the descriptor 
+ *         from the pollset with apr_pollset_remove(), then add it again 
+ *         specifying all requested events.
+ */
+APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset,
+                                          const apr_pollfd_t *descriptor);
+
+/**
+ * Remove a descriptor from a pollset
+ * @param pollset The pollset from which to remove the descriptor
+ * @param descriptor The descriptor to remove
+ * @remark If the descriptor is not found, APR_NOTFOUND is returned.
+ * @remark If the pollset has been created with APR_POLLSET_THREADSAFE
+ *         and thread T1 is blocked in a call to apr_pollset_poll() for
+ *         this same pollset that is being modified via apr_pollset_remove()
+ *         in thread T2, the currently executing apr_pollset_poll() call in
+ *         T1 will either: (1) automatically exclude the newly added descriptor
+ *         in the set of descriptors it is watching or (2) return immediately
+ *         with APR_EINTR.  Option (1) is recommended, but option (2) is
+ *         allowed for implementations where option (1) is impossible
+ *         or impractical.
+ * @remark apr_pollset_remove() cannot be used to remove a subset of requested
+ *         events for a descriptor.  The reqevents field in the apr_pollfd_t
+ *         parameter must contain the same value when removing as when adding.
+ */
+APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset,
+                                             const apr_pollfd_t *descriptor);
+
+/**
+ * Block for activity on the descriptor(s) in a pollset
+ * @param pollset The pollset to use
+ * @param timeout The amount of time in microseconds to wait.  This is a
+ *                maximum, not a minimum.  If a descriptor is signalled, the
+ *                function will return before this time.  If timeout is
+ *                negative, the function will block until a descriptor is
+ *                signalled or until apr_pollset_wakeup() has been called.
+ * @param num Number of signalled descriptors (output parameter)
+ * @param descriptors Array of signalled descriptors (output parameter)
+ * @remark APR_EINTR will be returned if the pollset has been created with
+ *         APR_POLLSET_WAKEABLE, apr_pollset_wakeup() has been called while
+ *         waiting for activity, and there were no signalled descriptors at the
+ *         time of the wakeup call.
+ * @remark Multiple signalled conditions for the same descriptor may be reported
+ *         in one or more returned apr_pollfd_t structures, depending on the
+ *         implementation.
+ */
+APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset,
+                                           apr_interval_time_t timeout,
+                                           apr_int32_t *num,
+                                           const apr_pollfd_t **descriptors);
+
+/**
+ * Interrupt the blocked apr_pollset_poll() call.
+ * @param pollset The pollset to use
+ * @remark If the pollset was not created with APR_POLLSET_WAKEABLE the
+ *         return value is APR_EINIT.
+ */
+APR_DECLARE(apr_status_t) apr_pollset_wakeup(apr_pollset_t *pollset);
+
+/**
+ * Poll the descriptors in the poll structure
+ * @param aprset The poll structure we will be using. 
+ * @param numsock The number of descriptors we are polling
+ * @param nsds The number of descriptors signalled (output parameter)
+ * @param timeout The amount of time in microseconds to wait.  This is a
+ *                maximum, not a minimum.  If a descriptor is signalled, the
+ *                function will return before this time.  If timeout is
+ *                negative, the function will block until a descriptor is
+ *                signalled or until apr_pollset_wakeup() has been called.
+ * @remark The number of descriptors signalled is returned in the third argument. 
+ *         This is a blocking call, and it will not return until either a 
+ *         descriptor has been signalled or the timeout has expired. 
+ * @remark The rtnevents field in the apr_pollfd_t array will only be filled-
+ *         in if the return value is APR_SUCCESS.
+ */
+APR_DECLARE(apr_status_t) apr_poll(apr_pollfd_t *aprset, apr_int32_t numsock,
+                                   apr_int32_t *nsds, 
+                                   apr_interval_time_t timeout);
+
+/**
+ * Return a printable representation of the pollset method.
+ * @param pollset The pollset to use
+ */
+APR_DECLARE(const char *) apr_pollset_method_name(apr_pollset_t *pollset);
+
+/**
+ * Return a printable representation of the default pollset method
+ * (APR_POLLSET_DEFAULT).
+ */
+APR_DECLARE(const char *) apr_poll_method_defname(void);
+
+/** Opaque structure used for pollcb API */
+typedef struct apr_pollcb_t apr_pollcb_t;
+
+/**
+ * Set up a pollcb object
+ * @param pollcb  The pointer in which to return the newly created object 
+ * @param size The maximum number of descriptors that a single _poll can return.
+ * @param p The pool from which to allocate the pollcb
+ * @param flags Optional flags to modify the operation of the pollcb.
+ *
+ * @remark If flags contains APR_POLLSET_WAKEABLE, then a pollcb is
+ *         created with an additional internal pipe object used for the
+ *         apr_pollcb_wakeup() call. The actual size of pollcb is
+ *         in that case @a size + 1.
+ * @remark Pollcb is only supported on some platforms; the apr_pollcb_create()
+ *         call will fail with APR_ENOTIMPL on platforms where it is not supported.
+ */
+APR_DECLARE(apr_status_t) apr_pollcb_create(apr_pollcb_t **pollcb,
+                                            apr_uint32_t size,
+                                            apr_pool_t *p,
+                                            apr_uint32_t flags);
+
+/**
+ * Set up a pollcb object
+ * @param pollcb  The pointer in which to return the newly created object 
+ * @param size The maximum number of descriptors that a single _poll can return.
+ * @param p The pool from which to allocate the pollcb
+ * @param flags Optional flags to modify the operation of the pollcb.
+ * @param method Poll method to use. See #apr_pollset_method_e.  If this
+ *         method cannot be used, the default method will be used unless the
+ *         APR_POLLSET_NODEFAULT flag has been specified.
+ *
+ * @remark If flags contains APR_POLLSET_WAKEABLE, then a pollcb is
+ *         created with an additional internal pipe object used for the
+ *         apr_pollcb_wakeup() call. The actual size of pollcb is
+ *         in that case @a size + 1.
+ * @remark Pollcb is only supported on some platforms; the apr_pollcb_create_ex()
+ *         call will fail with APR_ENOTIMPL on platforms where it is not supported.
+ */
+APR_DECLARE(apr_status_t) apr_pollcb_create_ex(apr_pollcb_t **pollcb,
+                                               apr_uint32_t size,
+                                               apr_pool_t *p,
+                                               apr_uint32_t flags,
+                                               apr_pollset_method_e method);
+
+/**
+ * Add a socket or file descriptor to a pollcb
+ * @param pollcb The pollcb to which to add the descriptor
+ * @param descriptor The descriptor to add
+ * @remark If you set client_data in the descriptor, that value will be
+ *         returned in the client_data field whenever this descriptor is
+ *         signalled in apr_pollcb_poll().
+ * @remark Unlike the apr_pollset API, the descriptor is not copied, and users 
+ *         must retain the memory used by descriptor, as the same pointer will
+ *         be returned to them from apr_pollcb_poll.
+ * @remark Do not add the same socket or file descriptor to the same pollcb
+ *         multiple times, even if the requested events differ for the 
+ *         different calls to apr_pollcb_add().  If the events of interest
+ *         for a descriptor change, you must first remove the descriptor 
+ *         from the pollcb with apr_pollcb_remove(), then add it again 
+ *         specifying all requested events.
+ */
+APR_DECLARE(apr_status_t) apr_pollcb_add(apr_pollcb_t *pollcb,
+                                         apr_pollfd_t *descriptor);
+/**
+ * Remove a descriptor from a pollcb
+ * @param pollcb The pollcb from which to remove the descriptor
+ * @param descriptor The descriptor to remove
+ * @remark If the descriptor is not found, APR_NOTFOUND is returned.
+ * @remark apr_pollcb_remove() cannot be used to remove a subset of requested
+ *         events for a descriptor.  The reqevents field in the apr_pollfd_t
+ *         parameter must contain the same value when removing as when adding.
+ */
+APR_DECLARE(apr_status_t) apr_pollcb_remove(apr_pollcb_t *pollcb,
+                                            apr_pollfd_t *descriptor);
+
+/**
+ * Function prototype for pollcb handlers 
+ * @param baton Opaque baton passed into apr_pollcb_poll()
+ * @param descriptor Contains the notification for an active descriptor. 
+ *                   The @a rtnevents member describes which events were triggered
+ *                   for this descriptor.
+ * @remark If the pollcb handler does not return APR_SUCCESS, the apr_pollcb_poll()
+ *         call returns with the handler's return value.
+ */
+typedef apr_status_t (*apr_pollcb_cb_t)(void *baton, apr_pollfd_t *descriptor);
+
+/**
+ * Block for activity on the descriptor(s) in a pollcb
+ * @param pollcb The pollcb to use
+ * @param timeout The amount of time in microseconds to wait.  This is a
+ *                maximum, not a minimum.  If a descriptor is signalled, the
+ *                function will return before this time.  If timeout is
+ *                negative, the function will block until a descriptor is
+ *                signalled or until apr_pollcb_wakeup() has been called.
+ * @param func Callback function to call for each active descriptor.
+ * @param baton Opaque baton passed to the callback function.
+ * @remark Multiple signalled conditions for the same descriptor may be reported
+ *         in one or more calls to the callback function, depending on the
+ *         implementation.
+ * @remark APR_EINTR will be returned if the pollset has been created with
+ *         APR_POLLSET_WAKEABLE and apr_pollcb_wakeup() has been called while
+ *         waiting for activity.
+ */
+APR_DECLARE(apr_status_t) apr_pollcb_poll(apr_pollcb_t *pollcb,
+                                          apr_interval_time_t timeout,
+                                          apr_pollcb_cb_t func,
+                                          void *baton);
+
+/**
+ * Interrupt the blocked apr_pollcb_poll() call.
+ * @param pollcb The pollcb to use
+ * @remark If the pollcb was not created with APR_POLLSET_WAKEABLE the
+ *         return value is APR_EINIT.
+ */
+APR_DECLARE(apr_status_t) apr_pollcb_wakeup(apr_pollcb_t *pollcb);
+
+/**
+ * Return a printable representation of the pollcb method.
+ * @param pollcb The pollcb to use
+ */
+APR_DECLARE(const char *) apr_pollcb_method_name(apr_pollcb_t *pollcb);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* ! APR_POLL_H */
+
diff --git a/include/apr_pools.h b/include/apr_pools.h
index c485464e2d4..f87b90b98e6 100644
--- a/include/apr_pools.h
+++ b/include/apr_pools.h
@@ -1,65 +1,26 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef ap_POOLS_H
-#define ap_POOLS_H
+/* 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.
+ */
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+#ifndef APR_POOLS_H
+#define APR_POOLS_H
 
-/*
+/**
+ * @file apr_pools.h
+ * @brief APR memory allocation
+ *
  * Resource allocation routines...
  *
  * designed so that we don't have to keep track of EVERYTHING so that
@@ -67,178 +28,783 @@ extern "C" {
  * particularly in the presence of die()).
  *
  * Instead, we maintain pools, and allocate items (both memory and I/O
- * handlers) from the pools --- currently there are two, one for per
- * transaction info, and one for config info.  When a transaction is over,
- * we can delete everything in the per-transaction ap_pool_t without fear, and
- * without thinking too hard about it either.
+ * handlers) from the pools --- currently there are two, one for
+ * per-transaction info, and one for config info.  When a transaction is
+ * over, we can delete everything in the per-transaction apr_pool_t without
+ * fear, and without thinking too hard about it either.
  *
- * rst
+ * Note that most operations on pools are not thread-safe: a single pool
+ * should only be accessed by a single thread at any given time. The one
+ * exception to this rule is creating a subpool of a given pool: one or more
+ * threads can safely create subpools at the same time that another thread
+ * accesses the parent pool.
  */
 
-/* Arenas for configuration info and transaction info
- * --- actual layout of the ap_pool_t structure is private to 
- * alloc.c.  
+#include "apr.h"
+#include "apr_errno.h"
+#include "apr_general.h" /* for APR_STRINGIFY */
+#define APR_WANT_MEMFUNC /**< for no good reason? */
+#include "apr_want.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup apr_pools Memory Pool Functions
+ * @ingroup APR 
+ * @{
  */
 
-#include "apr_lib.h"
+/** The fundamental pool type */
+typedef struct apr_pool_t apr_pool_t;
 
-#if APR_HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
 
-struct process_chain {
-    ap_proc_t *pid;
-    enum kill_conditions kill_how;
-    struct process_chain *next;
-};
+/**
+ * Declaration helper macro to construct apr_foo_pool_get()s.
+ *
+ * This standardized macro is used by opaque (APR) data types to return
+ * the apr_pool_t that is associated with the data type.
+ *
+ * APR_POOL_DECLARE_ACCESSOR() is used in a header file to declare the
+ * accessor function. A typical usage and result would be:
+ * <pre>
+ *    APR_POOL_DECLARE_ACCESSOR(file);
+ * becomes:
+ *    APR_DECLARE(apr_pool_t *) apr_file_pool_get(const apr_file_t *thefile);
+ * </pre>
+ * @remark Doxygen unwraps this macro (via doxygen.conf) to provide 
+ * actual help for each specific occurrence of apr_foo_pool_get.
+ * @remark the linkage is specified for APR. It would be possible to expand
+ *       the macros to support other linkages.
+ */
+#define APR_POOL_DECLARE_ACCESSOR(type) \
+    APR_DECLARE(apr_pool_t *) apr_##type##_pool_get \
+        (const apr_##type##_t *the##type)
+
+/** 
+ * Implementation helper macro to provide apr_foo_pool_get()s.
+ *
+ * In the implementation, the APR_POOL_IMPLEMENT_ACCESSOR() is used to
+ * actually define the function. It assumes the field is named "pool".
+ */
+#define APR_POOL_IMPLEMENT_ACCESSOR(type) \
+    APR_DECLARE(apr_pool_t *) apr_##type##_pool_get \
+            (const apr_##type##_t *the##type) \
+        { return the##type->pool; }
 
-struct ap_table_t {
-    /* This has to be first to promote backwards compatibility with
-     * older modules which cast a ap_table_t * to an ap_array_header_t *...
-     * they should use the table_elts() function for most of the
-     * cases they do this for.
-     */
-    ap_array_header_t a;
-#ifdef MAKE_TABLE_PROFILE
-    void *creator;
-#endif
-};
 
-/*
- * Tables.  Implemented alist style, for now, though we try to keep
- * it so that imposing a hash table structure on top in the future
- * wouldn't be *too* hard...
+/**
+ * Pool debug levels
+ *
+ * <pre>
+ * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+ * ---------------------------------
+ * |   |   |   |   |   |   |   | x |  General debug code enabled (useful in
+ *                                    combination with --with-efence).
+ *
+ * |   |   |   |   |   |   | x |   |  Verbose output on stderr (report
+ *                                    CREATE, CLEAR, DESTROY).
+ *
+ * |   |   |   | x |   |   |   |   |  Verbose output on stderr (report
+ *                                    PALLOC, PCALLOC).
+ *
+ * |   |   |   |   |   | x |   |   |  Lifetime checking. On each use of a
+ *                                    pool, check its lifetime.  If the pool
+ *                                    is out of scope, abort().
+ *                                    In combination with the verbose flag
+ *                                    above, it will output LIFE in such an
+ *                                    event prior to aborting.
  *
- * Note that key comparisons for these are case-insensitive, largely
- * because that's what's appropriate and convenient everywhere they're
- * currently being used...
+ * |   |   |   |   | x |   |   |   |  Pool owner checking.  On each use of a
+ *                                    pool, check if the current thread is the
+ *                                    pool's owner.  If not, abort().  In
+ *                                    combination with the verbose flag above,
+ *                                    it will output OWNER in such an event
+ *                                    prior to aborting.  Use the debug
+ *                                    function apr_pool_owner_set() to switch
+ *                                    a pool's ownership.
+ *
+ * When no debug level was specified, assume general debug mode.
+ * If level 0 was specified, debugging is switched off.
+ * </pre>
  */
+#if defined(APR_POOL_DEBUG)
+/* If APR_POOL_DEBUG is blank, we get 1; if it is a number, we get -1. */
+#if (APR_POOL_DEBUG - APR_POOL_DEBUG -1 == 1)
+#undef APR_POOL_DEBUG
+#define APR_POOL_DEBUG 1
+#endif
+#else
+#define APR_POOL_DEBUG 0
+#endif
 
-ap_status_t ap_init_alloc(void);	/* Set up everything */
-void        ap_term_alloc(void);        /* Tear down everything */
+/** the place in the code where the particular function was called */
+#define APR_POOL__FILE_LINE__ __FILE__ ":" APR_STRINGIFY(__LINE__)
 
-/* used to guarantee to the pool debugging code that the sub pool will not be
- * destroyed before the parent pool
+
+
+/** A function that is called when allocation fails. */
+typedef int (*apr_abortfunc_t)(int retcode);
+
+/*
+ * APR memory structure manipulators (pools, tables, and arrays).
  */
-#ifndef POOL_DEBUG
-#ifdef ap_pool_join
-#undef ap_pool_join
-#endif /* ap_pool_join */
-#define ap_pool_join(a,b)
-#endif /* POOL_DEBUG */
 
-/* Clearing out EVERYTHING in an pool... destroys any sub-pools */
+/*
+ * Initialization
+ */
 
-/* Preparing for exec() --- close files, etc., but *don't* flush I/O
- * buffers, *don't* wait for subprocesses, and *don't* free any memory.
+/**
+ * Setup all of the internal structures required to use pools
+ * @remark Programs do NOT need to call this directly.  APR will call this
+ *      automatically from apr_initialize.
+ * @internal
  */
+APR_DECLARE(apr_status_t) apr_pool_initialize(void);
 
-/* routines to allocate memory from an pool... */
+/**
+ * Tear down all of the internal structures required to use pools
+ * @remark Programs do NOT need to call this directly.  APR will call this
+ *      automatically from apr_terminate.
+ * @internal
+ */
+APR_DECLARE(void) apr_pool_terminate(void);
 
-API_EXPORT_NONSTD(char *) ap_psprintf(struct ap_pool_t *, const char *fmt, ...)
-    __attribute__((format(printf,2,3)));
+/*
+ * Pool creation/destruction
+ */
 
-/* array and alist management... keeping lists of things.
- * Common enough to want common support code ...
+#include "apr_allocator.h"
+
+/**
+ * Create a new pool.
+ * @param newpool The pool we have just created.
+ * @param parent The parent pool.  If this is NULL, the new pool is a root
+ *        pool.  If it is non-NULL, the new pool will inherit all
+ *        of its parent pool's attributes, except the apr_pool_t will
+ *        be a sub-pool.
+ * @param abort_fn A function to use if the pool cannot allocate more memory.
+ * @param allocator The allocator to use with the new pool.  If NULL the
+ *        allocator of the parent pool will be used.
+ * @remark This function is thread-safe, in the sense that multiple threads
+ *         can safely create subpools of the same parent pool concurrently.
+ *         Similarly, a subpool can be created by one thread at the same
+ *         time that another thread accesses the parent pool.
  */
+APR_DECLARE(apr_status_t) apr_pool_create_ex(apr_pool_t **newpool,
+                                             apr_pool_t *parent,
+                                             apr_abortfunc_t abort_fn,
+                                             apr_allocator_t *allocator)
+                          __attribute__((nonnull(1)));
+
+/**
+ * Create a new unmanaged pool.
+ * @param newpool The pool we have just created.
+ * @param abort_fn A function to use if the pool cannot allocate more memory.
+ * @param allocator The allocator to use with the new pool.  If NULL a
+ *        new allocator will be created with the new pool as owner.
+ * @remark An unmanaged pool is a special pool without a parent; it will
+ *         NOT be destroyed upon apr_terminate.  It must be explicitly
+ *         destroyed by calling apr_pool_destroy, to prevent memory leaks.
+ *         Use of this function is discouraged, think twice about whether
+ *         you really really need it.
+ * @warning Any child cleanups registered against the new pool, or
+ *         against sub-pools thereof, will not be executed during an
+ *         invocation of apr_proc_create(), so resources created in an
+ *         "unmanaged" pool hierarchy will leak to child processes.
+ */
+APR_DECLARE(apr_status_t) apr_pool_create_unmanaged_ex(apr_pool_t **newpool,
+                                                   apr_abortfunc_t abort_fn,
+                                                   apr_allocator_t *allocator)
+                          __attribute__((nonnull(1)));
+
+/**
+ * Debug version of apr_pool_create_ex.
+ * @param newpool @see apr_pool_create.
+ * @param parent @see apr_pool_create.
+ * @param abort_fn @see apr_pool_create.
+ * @param allocator @see apr_pool_create.
+ * @param file_line Where the function is called from.
+ *        This is usually APR_POOL__FILE_LINE__.
+ * @remark Only available when APR_POOL_DEBUG is defined.
+ *         Call this directly if you have your apr_pool_create_ex
+ *         calls in a wrapper function and wish to override
+ *         the file_line argument to reflect the caller of
+ *         your wrapper function.  If you do not have
+ *         apr_pool_create_ex in a wrapper, trust the macro
+ *         and don't call apr_pool_create_ex_debug directly.
+ */
+APR_DECLARE(apr_status_t) apr_pool_create_ex_debug(apr_pool_t **newpool,
+                                                   apr_pool_t *parent,
+                                                   apr_abortfunc_t abort_fn,
+                                                   apr_allocator_t *allocator,
+                                                   const char *file_line)
+                          __attribute__((nonnull(1)));
+
+#if APR_POOL_DEBUG
+#define apr_pool_create_ex(newpool, parent, abort_fn, allocator)  \
+    apr_pool_create_ex_debug(newpool, parent, abort_fn, allocator, \
+                             APR_POOL__FILE_LINE__)
+#endif
 
-/* ap_array_pstrcat generates a new string from the ap_pool_t containing
- * the concatenated sequence of substrings referenced as elements within
- * the array.  The string will be empty if all substrings are empty or null,
- * or if there are no elements in the array.
- * If sep is non-NUL, it will be inserted between elements as a separator.
+  /**
+ * Debug version of apr_pool_create_unmanaged_ex.
+ * @param newpool @see apr_pool_create_unmanaged.
+ * @param abort_fn @see apr_pool_create_unmanaged.
+ * @param allocator @see apr_pool_create_unmanaged.
+ * @param file_line Where the function is called from.
+ *        This is usually APR_POOL__FILE_LINE__.
+ * @remark Only available when APR_POOL_DEBUG is defined.
+ *         Call this directly if you have your apr_pool_create_unmanaged_ex
+ *         calls in a wrapper function and wish to override
+ *         the file_line argument to reflect the caller of
+ *         your wrapper function.  If you do not have
+ *         apr_pool_create_unmanaged_ex in a wrapper, trust the macro
+ *         and don't call apr_pool_create_unmanaged_ex_debug directly.
  */
+APR_DECLARE(apr_status_t) apr_pool_create_unmanaged_ex_debug(apr_pool_t **newpool,
+                                                   apr_abortfunc_t abort_fn,
+                                                   apr_allocator_t *allocator,
+                                                   const char *file_line)
+                          __attribute__((nonnull(1)));
+
+#if APR_POOL_DEBUG
+#define apr_pool_create_unmanaged_ex(newpool, abort_fn, allocator)  \
+    apr_pool_create_unmanaged_ex_debug(newpool, abort_fn, allocator, \
+                                  APR_POOL__FILE_LINE__)
 
-/* copy_array copies the *entire* array.  copy_array_hdr just copies
- * the header, and arranges for the elements to be copied if (and only
- * if) the code subsequently does a push or arraycat.
+#endif
+
+/**
+ * Create a new pool.
+ * @param newpool The pool we have just created.
+ * @param parent The parent pool.  If this is NULL, the new pool is a root
+ *        pool.  If it is non-NULL, the new pool will inherit all
+ *        of its parent pool's attributes, except the apr_pool_t will
+ *        be a sub-pool.
+ * @remark This function is thread-safe, in the sense that multiple threads
+ *         can safely create subpools of the same parent pool concurrently.
+ *         Similarly, a subpool can be created by one thread at the same
+ *         time that another thread accesses the parent pool.
  */
+#if defined(DOXYGEN)
+APR_DECLARE(apr_status_t) apr_pool_create(apr_pool_t **newpool,
+                                          apr_pool_t *parent);
+#else
+#if APR_POOL_DEBUG
+#define apr_pool_create(newpool, parent) \
+    apr_pool_create_ex_debug(newpool, parent, NULL, NULL, \
+                             APR_POOL__FILE_LINE__)
+#else
+#define apr_pool_create(newpool, parent) \
+    apr_pool_create_ex(newpool, parent, NULL, NULL)
+#endif
+#endif
 
+/**
+ * Create a new unmanaged pool.
+ * @param newpool The pool we have just created.
+ */
+#if defined(DOXYGEN)
+APR_DECLARE(apr_status_t) apr_pool_create_unmanaged(apr_pool_t **newpool);
+#else
+#if APR_POOL_DEBUG
+#define apr_pool_create_unmanaged(newpool) \
+    apr_pool_create_unmanaged_ex_debug(newpool, NULL, NULL, \
+                                  APR_POOL__FILE_LINE__)
+#else
+#define apr_pool_create_unmanaged(newpool) \
+    apr_pool_create_unmanaged_ex(newpool, NULL, NULL)
+#endif
+#endif
 
+/**
+ * Find the pool's allocator
+ * @param pool The pool to get the allocator from.
+ */
+APR_DECLARE(apr_allocator_t *) apr_pool_allocator_get(apr_pool_t *pool)
+                               __attribute__((nonnull(1)));
+
+/**
+ * Clear all memory in the pool and run all the cleanups. This also destroys all
+ * subpools.
+ * @param p The pool to clear
+ * @remark This does not actually free the memory, it just allows the pool
+ *         to re-use this memory for the next allocation.
+ * @see apr_pool_destroy()
+ */
+APR_DECLARE(void) apr_pool_clear(apr_pool_t *p) __attribute__((nonnull(1)));
+
+/**
+ * Debug version of apr_pool_clear.
+ * @param p See: apr_pool_clear.
+ * @param file_line Where the function is called from.
+ *        This is usually APR_POOL__FILE_LINE__.
+ * @remark Only available when APR_POOL_DEBUG is defined.
+ *         Call this directly if you have your apr_pool_clear
+ *         calls in a wrapper function and wish to override
+ *         the file_line argument to reflect the caller of
+ *         your wrapper function.  If you do not have
+ *         apr_pool_clear in a wrapper, trust the macro
+ *         and don't call apr_pool_destroy_clear directly.
+ */
+APR_DECLARE(void) apr_pool_clear_debug(apr_pool_t *p,
+                                       const char *file_line)
+                  __attribute__((nonnull(1)));
 
-/* Conceptually, ap_overlap_tables does this:
+#if APR_POOL_DEBUG
+#define apr_pool_clear(p) \
+    apr_pool_clear_debug(p, APR_POOL__FILE_LINE__)
+#endif
 
-    ap_array_header_t *barr = ap_table_elts(b);
-    ap_table_entry_t *belt = (ap_table_entry_t *)barr->elts;
-    int i;
+/**
+ * Destroy the pool. This takes similar action as apr_pool_clear() and then
+ * frees all the memory.
+ * @param p The pool to destroy
+ * @remark This will actually free the memory
+ */
+APR_DECLARE(void) apr_pool_destroy(apr_pool_t *p) __attribute__((nonnull(1)));
+
+/**
+ * Debug version of apr_pool_destroy.
+ * @param p See: apr_pool_destroy.
+ * @param file_line Where the function is called from.
+ *        This is usually APR_POOL__FILE_LINE__.
+ * @remark Only available when APR_POOL_DEBUG is defined.
+ *         Call this directly if you have your apr_pool_destroy
+ *         calls in a wrapper function and wish to override
+ *         the file_line argument to reflect the caller of
+ *         your wrapper function.  If you do not have
+ *         apr_pool_destroy in a wrapper, trust the macro
+ *         and don't call apr_pool_destroy_debug directly.
+ */
+APR_DECLARE(void) apr_pool_destroy_debug(apr_pool_t *p,
+                                         const char *file_line)
+                  __attribute__((nonnull(1)));
 
-    for (i = 0; i < barr->nelts; ++i) {
-	if (flags & ap_OVERLAP_TABLES_MERGE) {
-	    ap_table_mergen(a, belt[i].key, belt[i].val);
-	}
-	else {
-	    ap_table_setn(a, belt[i].key, belt[i].val);
-	}
-    }
+#if APR_POOL_DEBUG
+#define apr_pool_destroy(p) \
+    apr_pool_destroy_debug(p, APR_POOL__FILE_LINE__)
+#endif
 
-    Except that it is more efficient (less space and cpu-time) especially
-    when b has many elements.
 
-    Notice the assumptions on the keys and values in b -- they must be
-    in an ancestor of a's pool.  In practice b and a are usually from
-    the same pool.
-*/
-#define ap_OVERLAP_TABLES_SET	(0)
-#define ap_OVERLAP_TABLES_MERGE	(1)
+/*
+ * Memory allocation
+ */
 
-/* A set of flags which indicate places where the server should raise(SIGSTOP).
- * This is useful for debugging, because you can then attach to that process
- * with gdb and continue.  This is important in cases where one_process
- * debugging isn't possible.
+/**
+ * Allocate a block of memory from a pool
+ * @param p The pool to allocate from
+ * @param size The amount of memory to allocate
+ * @return The allocated memory
+ */
+APR_DECLARE(void *) apr_palloc(apr_pool_t *p, apr_size_t size)
+#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
+                    __attribute__((alloc_size(2)))
+#endif
+                    __attribute__((nonnull(1)));
+
+/**
+ * Debug version of apr_palloc
+ * @param p See: apr_palloc
+ * @param size See: apr_palloc
+ * @param file_line Where the function is called from.
+ *        This is usually APR_POOL__FILE_LINE__.
+ * @return See: apr_palloc
  */
-#define SIGSTOP_DETACH                  1
-#define SIGSTOP_MAKE_CHILD              2                                       #define SIGSTOP_SPAWN_CHILD             4
-#define SIGSTOP_PIPED_LOG_SPAWN         8
-#define SIGSTOP_CGI_CHILD               16
+APR_DECLARE(void *) apr_palloc_debug(apr_pool_t *p, apr_size_t size,
+                                     const char *file_line)
+#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
+                    __attribute__((alloc_size(2)))
+#endif
+                    __attribute__((nonnull(1)));
 
-#ifdef DEBUG_SIGSTOP
-extern int raise_sigstop_flags;
-#define RAISE_SIGSTOP(x)        do { \
-        if (raise_sigstop_flags & SIGSTOP_##x) raise(SIGSTOP);\
-    } while (0)
-#else
-#define RAISE_SIGSTOP(x)
+#if APR_POOL_DEBUG
+#define apr_palloc(p, size) \
+    apr_palloc_debug(p, size, APR_POOL__FILE_LINE__)
 #endif
 
-#ifdef ULTRIX_BRAIN_DEATH
-#define ap_fdopen(d,m) fdopen((d), (char *)(m))
-#else
-#define ap_fdopen(d,m) fdopen((d), (m))
+/**
+ * Allocate a block of memory from a pool and set all of the memory to 0
+ * @param p The pool to allocate from
+ * @param size The amount of memory to allocate
+ * @return The allocated memory
+ */
+#if defined(DOXYGEN)
+APR_DECLARE(void *) apr_pcalloc(apr_pool_t *p, apr_size_t size);
+#elif !APR_POOL_DEBUG
+#define apr_pcalloc(p, size) memset(apr_palloc(p, size), 0, size)
 #endif
 
-/* XXX - the socket functions for pools should (and will) use APR sockets.
- * This is temporary. */
-#ifndef BEOS /* this really screws up BeOS R4.5 !! */
-#define closesocket(s) close(s)
+/**
+ * Debug version of apr_pcalloc
+ * @param p See: apr_pcalloc
+ * @param size See: apr_pcalloc
+ * @param file_line Where the function is called from.
+ *        This is usually APR_POOL__FILE_LINE__.
+ * @return See: apr_pcalloc
+ */
+APR_DECLARE(void *) apr_pcalloc_debug(apr_pool_t *p, apr_size_t size,
+                                      const char *file_line)
+                    __attribute__((nonnull(1)));
+
+#if APR_POOL_DEBUG
+#define apr_pcalloc(p, size) \
+    apr_pcalloc_debug(p, size, APR_POOL__FILE_LINE__)
 #endif
 
 
+/*
+ * Pool Properties
+ */
+
+/**
+ * Set the function to be called when an allocation failure occurs.
+ * @remark If the program wants APR to exit on a memory allocation error,
+ *      then this function can be called to set the callback to use (for
+ *      performing cleanup and then exiting). If this function is not called,
+ *      then APR will return an error and expect the calling program to
+ *      deal with the error accordingly.
+ */
+APR_DECLARE(void) apr_pool_abort_set(apr_abortfunc_t abortfunc,
+                                     apr_pool_t *pool)
+                  __attribute__((nonnull(2)));
+
+/**
+ * Get the abort function associated with the specified pool.
+ * @param pool The pool for retrieving the abort function.
+ * @return The abort function for the given pool.
+ */
+APR_DECLARE(apr_abortfunc_t) apr_pool_abort_get(apr_pool_t *pool)
+                             __attribute__((nonnull(1)));
+
+/**
+ * Get the parent pool of the specified pool.
+ * @param pool The pool for retrieving the parent pool.
+ * @return The parent of the given pool.
+ */
+APR_DECLARE(apr_pool_t *) apr_pool_parent_get(apr_pool_t *pool)
+                          __attribute__((nonnull(1)));
+
+/**
+ * Determine if pool a is an ancestor of pool b.
+ * @param a The pool to search
+ * @param b The pool to search for
+ * @return True if a is an ancestor of b, NULL is considered an ancestor
+ *         of all pools.
+ * @remark if compiled with APR_POOL_DEBUG, this function will also
+ * return true if A is a pool which has been guaranteed by the caller
+ * (using apr_pool_join) to have a lifetime at least as long as some
+ * ancestor of pool B.
+ */
+APR_DECLARE(int) apr_pool_is_ancestor(apr_pool_t *a, apr_pool_t *b);
+
+/**
+ * Tag a pool (give it a name)
+ * @param pool The pool to tag
+ * @param tag  The tag
+ */
+APR_DECLARE(void) apr_pool_tag(apr_pool_t *pool, const char *tag)
+                  __attribute__((nonnull(1)));
+
+/**
+ * Retrieve the tag name.
+ * @param pool The pool
+ * @return Tag name, or NULL if no name is set.
+ */
+APR_DECLARE(const char *) apr_pool_get_tag(apr_pool_t *pool)
+                  __attribute__((nonnull(1)));
+
+/*
+ * User data management
+ */
 
-/* XXX: these know about the definition of struct ap_table_t in alloc.c.  That
- * definition is not here because it is supposed to be private, and by not
- * placing it here we are able to get compile-time diagnostics from modules
- * written which assume that a ap_table_t is the same as an ap_array_header_t. -djg
+/**
+ * Set the data associated with the current pool
+ * @param data The user data associated with the pool.
+ * @param key The key to use for association
+ * @param cleanup The cleanup program to use to cleanup the data (NULL if none)
+ * @param pool The current pool
+ * @warning The data to be attached to the pool should have a life span
+ *          at least as long as the pool it is being attached to.
+ *
+ *      Users of APR must take EXTREME care when choosing a key to
+ *      use for their data.  It is possible to accidentally overwrite
+ *      data by choosing a key that another part of the program is using.
+ *      Therefore it is advised that steps are taken to ensure that unique
+ *      keys are used for all of the userdata objects in a particular pool
+ *      (the same key in two different pools or a pool and one of its
+ *      subpools is okay) at all times.  Careful namespace prefixing of
+ *      key names is a typical way to help ensure this uniqueness.
+ *
+ */
+APR_DECLARE(apr_status_t) apr_pool_userdata_set(const void *data,
+                                                const char *key,
+                                                apr_status_t (*cleanup)(void *),
+                                                apr_pool_t *pool)
+                          __attribute__((nonnull(2,4)));
+
+/**
+ * Set the data associated with the current pool
+ * @param data The user data associated with the pool.
+ * @param key The key to use for association
+ * @param cleanup The cleanup program to use to cleanup the data (NULL if none)
+ * @param pool The current pool
+ * @note same as apr_pool_userdata_set(), except that this version doesn't
+ *       make a copy of the key (this function is useful, for example, when
+ *       the key is a string literal)
+ * @warning This should NOT be used if the key could change addresses by
+ *       any means between the apr_pool_userdata_setn() call and a
+ *       subsequent apr_pool_userdata_get() on that key, such as if a
+ *       static string is used as a userdata key in a DSO and the DSO could
+ *       be unloaded and reloaded between the _setn() and the _get().  You
+ *       MUST use apr_pool_userdata_set() in such cases.
+ * @warning More generally, the key and the data to be attached to the
+ *       pool should have a life span at least as long as the pool itself.
+ *
  */
-#define ap_table_elts(t) ((ap_array_header_t *)(t))
-#define ap_is_empty_table(t) (((t) == NULL)||(((ap_array_header_t *)(t))->nelts == 0))
+APR_DECLARE(apr_status_t) apr_pool_userdata_setn(
+                                const void *data, const char *key,
+                                apr_status_t (*cleanup)(void *),
+                                apr_pool_t *pool)
+                          __attribute__((nonnull(2,4)));
+
+/**
+ * Return the data associated with the current pool.
+ * @param data The user data associated with the pool.
+ * @param key The key for the data to retrieve
+ * @param pool The current pool.
+ */
+APR_DECLARE(apr_status_t) apr_pool_userdata_get(void **data, const char *key,
+                                                apr_pool_t *pool)
+                          __attribute__((nonnull(1,2,3)));
 
-/* magic numbers --- min free bytes to consider a free ap_pool_t block useable,
- * and the min amount to allocate if we have to go to malloc() */
 
-#ifndef BLOCK_MINFREE
-#define BLOCK_MINFREE 4096
+/**
+ * @defgroup PoolCleanup  Pool Cleanup Functions
+ *
+ * Cleanups are performed in the reverse order they were registered.  That is:
+ * Last In, First Out.  A cleanup function can safely allocate memory from
+ * the pool that is being cleaned up. It can also safely register additional
+ * cleanups which will be run LIFO, directly after the current cleanup
+ * terminates.  Cleanups have to take caution in calling functions that
+ * create subpools. Subpools, created during cleanup will NOT automatically
+ * be cleaned up.  In other words, cleanups are to clean up after themselves.
+ *
+ * @{
+ */
+
+/**
+ * Register a function to be called when a pool is cleared or destroyed
+ * @param p The pool to register the cleanup with
+ * @param data The data to pass to the cleanup function.
+ * @param plain_cleanup The function to call when the pool is cleared
+ *                      or destroyed
+ * @param child_cleanup The function to call when a child process is about
+ *                      to exec - this function is called in the child, obviously!
+ */
+APR_DECLARE(void) apr_pool_cleanup_register(
+                            apr_pool_t *p, const void *data,
+                            apr_status_t (*plain_cleanup)(void *),
+                            apr_status_t (*child_cleanup)(void *))
+                  __attribute__((nonnull(3,4)));
+
+/**
+ * Register a function to be called when a pool is cleared or destroyed.
+ *
+ * Unlike apr_pool_cleanup_register which registers a cleanup
+ * that is called AFTER all subpools are destroyed, this function registers
+ * a function that will be called before any of the subpools are destroyed.
+ *
+ * @param p The pool to register the cleanup with
+ * @param data The data to pass to the cleanup function.
+ * @param plain_cleanup The function to call when the pool is cleared
+ *                      or destroyed
+ */
+APR_DECLARE(void) apr_pool_pre_cleanup_register(
+                            apr_pool_t *p, const void *data,
+                            apr_status_t (*plain_cleanup)(void *))
+                  __attribute__((nonnull(3)));
+
+/**
+ * Remove a previously registered cleanup function.
+ * 
+ * The cleanup most recently registered with @a p having the same values of
+ * @a data and @a cleanup will be removed.
+ *
+ * @param p The pool to remove the cleanup from
+ * @param data The data of the registered cleanup
+ * @param cleanup The function to remove from cleanup
+ * @remarks For some strange reason only the plain_cleanup is handled by this
+ *          function
+ */
+APR_DECLARE(void) apr_pool_cleanup_kill(apr_pool_t *p, const void *data,
+                                        apr_status_t (*cleanup)(void *))
+                  __attribute__((nonnull(3)));
+
+/**
+ * Replace the child cleanup function of a previously registered cleanup.
+ * 
+ * The cleanup most recently registered with @a p having the same values of
+ * @a data and @a plain_cleanup will have the registered child cleanup
+ * function replaced with @a child_cleanup.
+ *
+ * @param p The pool of the registered cleanup
+ * @param data The data of the registered cleanup
+ * @param plain_cleanup The plain cleanup function of the registered cleanup
+ * @param child_cleanup The function to register as the child cleanup
+ */
+APR_DECLARE(void) apr_pool_child_cleanup_set(
+                        apr_pool_t *p, const void *data,
+                        apr_status_t (*plain_cleanup)(void *),
+                        apr_status_t (*child_cleanup)(void *))
+                  __attribute__((nonnull(3,4)));
+
+/**
+ * Run the specified cleanup function immediately and unregister it.
+ *
+ * The cleanup most recently registered with @a p having the same values of
+ * @a data and @a cleanup will be removed and @a cleanup will be called
+ * with @a data as the argument.
+ *
+ * @param p The pool to remove the cleanup from
+ * @param data The data to remove from cleanup
+ * @param cleanup The function to remove from cleanup
+ */
+APR_DECLARE(apr_status_t) apr_pool_cleanup_run(apr_pool_t *p, void *data,
+                                               apr_status_t (*cleanup)(void *))
+                          __attribute__((nonnull(3)));
+
+/**
+ * An empty cleanup function.
+ * 
+ * Passed to apr_pool_cleanup_register() when no cleanup is required.
+ *
+ * @param data The data to cleanup, will not be used by this function.
+ */
+APR_DECLARE_NONSTD(apr_status_t) apr_pool_cleanup_null(void *data);
+
+/**
+ * Run all registered child cleanups, in preparation for an exec()
+ * call in a forked child -- close files, etc., but *don't* flush I/O
+ * buffers, *don't* wait for subprocesses, and *don't* free any
+ * memory.
+ */
+APR_DECLARE(void) apr_pool_cleanup_for_exec(void);
+
+/** @} */
+
+/**
+ * @defgroup PoolDebug Pool Debugging functions.
+ *
+ * pools have nested lifetimes -- sub_pools are destroyed when the
+ * parent pool is cleared.  We allow certain liberties with operations
+ * on things such as tables (and on other structures in a more general
+ * sense) where we allow the caller to insert values into a table which
+ * were not allocated from the table's pool.  The table's data will
+ * remain valid as long as all the pools from which its values are
+ * allocated remain valid.
+ *
+ * For example, if B is a sub pool of A, and you build a table T in
+ * pool B, then it's safe to insert data allocated in A or B into T
+ * (because B lives at most as long as A does, and T is destroyed when
+ * B is cleared/destroyed).  On the other hand, if S is a table in
+ * pool A, it is safe to insert data allocated in A into S, but it
+ * is *not safe* to insert data allocated from B into S... because
+ * B can be cleared/destroyed before A is (which would leave dangling
+ * pointers in T's data structures).
+ *
+ * In general we say that it is safe to insert data into a table T
+ * if the data is allocated in any ancestor of T's pool.  This is the
+ * basis on which the APR_POOL_DEBUG code works -- it tests these ancestor
+ * relationships for all data inserted into tables.  APR_POOL_DEBUG also
+ * provides tools (apr_pool_find, and apr_pool_is_ancestor) for other
+ * folks to implement similar restrictions for their own data
+ * structures.
+ *
+ * However, sometimes this ancestor requirement is inconvenient --
+ * sometimes it's necessary to create a sub pool where the sub pool is
+ * guaranteed to have the same lifetime as the parent pool.  This is a
+ * guarantee implemented by the *caller*, not by the pool code.  That
+ * is, the caller guarantees they won't destroy the sub pool
+ * individually prior to destroying the parent pool.
+ *
+ * In this case the caller must call apr_pool_join() to indicate this
+ * guarantee to the APR_POOL_DEBUG code.
+ *
+ * These functions are only implemented when #APR_POOL_DEBUG is set.
+ *
+ * @{
+ */
+#if APR_POOL_DEBUG || defined(DOXYGEN)
+/**
+ * Guarantee that a subpool has the same lifetime as the parent.
+ * @param p The parent pool
+ * @param sub The subpool
+ */
+APR_DECLARE(void) apr_pool_join(apr_pool_t *p, apr_pool_t *sub)
+                  __attribute__((nonnull(2)));
+
+/**
+ * Guarantee that a pool is only used by the current thread.
+ * This should be used when a pool is created by a different thread than
+ * the thread it is using, or if there is some locking in use to ensure
+ * that only one thread uses the pool at the same time.
+ *
+ * @param pool The pool
+ * @param flags Flags, currently unused
+ */
+APR_DECLARE(void) apr_pool_owner_set(apr_pool_t *pool, apr_uint32_t flags);
+
+/**
+ * Find a pool from something allocated in it.
+ * @param mem The thing allocated in the pool
+ * @return The pool it is allocated in
+ */
+APR_DECLARE(apr_pool_t *) apr_pool_find(const void *mem);
+
+/**
+ * Report the number of bytes currently in the pool
+ * @param p The pool to inspect
+ * @param recurse Recurse/include the subpools' sizes
+ * @return The number of bytes
+ */
+APR_DECLARE(apr_size_t) apr_pool_num_bytes(apr_pool_t *p, int recurse)
+                        __attribute__((nonnull(1)));
+
+/**
+ * Lock a pool
+ * @param pool The pool to lock
+ * @param flag  The flag
+ */
+APR_DECLARE(void) apr_pool_lock(apr_pool_t *pool, int flag);
+
+/* @} */
+
+#else /* APR_POOL_DEBUG or DOXYGEN */
+
+#ifdef apr_pool_join
+#undef apr_pool_join
+#endif
+#define apr_pool_join(a,b)
+
+#ifdef apr_pool_owner_set
+#undef apr_pool_owner_set
 #endif
-#ifndef BLOCK_MINALLOC
-#define BLOCK_MINALLOC 8192
+#define apr_pool_owner_set(a,b)
+
+#ifdef apr_pool_lock
+#undef apr_pool_lock
 #endif
+#define apr_pool_lock(pool, lock)
 
-/* Finally, some accounting */
+#endif /* APR_POOL_DEBUG or DOXYGEN */
 
-API_EXPORT(long) ap_bytes_in_pool(ap_pool_t *p);
-API_EXPORT(long) ap_bytes_in_free_blocks(void);
+/** @} */
 
 #ifdef __cplusplus
 }
 #endif
 
-#endif	/* !ap_POOLS_H */
+#endif /* !APR_POOLS_H */
diff --git a/include/apr_portable.h b/include/apr_portable.h
index dca3d43dd25..7bb7a3568e2 100644
--- a/include/apr_portable.h
+++ b/include/apr_portable.h
@@ -1,75 +1,41 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 header file is where you should put ANY platform specific information.
  * This should be the only header file that programs need to include that 
- * actually has platform dependant code which refers to the .
+ * actually has platform dependent code which refers to the .
  */
 #ifndef APR_PORTABLE_H
 #define APR_PORTABLE_H
+/**
+ * @file apr_portable.h
+ * @brief APR Portability Routines
+ */
 
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-#include "apr_general.h"
+#include "apr.h"
+#include "apr_pools.h"
 #include "apr_thread_proc.h"
 #include "apr_file_io.h"
 #include "apr_network_io.h"
 #include "apr_errno.h"
-#include "apr_lock.h"
+#include "apr_global_mutex.h"
+#include "apr_proc_mutex.h"
 #include "apr_time.h"
+#include "apr_dso.h"
+#include "apr_shm.h"
 
 #if APR_HAVE_DIRENT_H
 #include <dirent.h>
@@ -80,362 +46,494 @@ extern "C" {
 #if APR_HAVE_PTHREAD_H
 #include <pthread.h>
 #endif
-#if APR_HAVE_UNION_SEMUN
-#include <sys/sem.h>
+#if APR_HAVE_SEMAPHORE_H
+#include <semaphore.h>
 #endif
 
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup apr_portabile Portability Routines
+ * @ingroup APR 
+ * @{
+ */
+
 #ifdef WIN32
 /* The primitives for Windows types */
-typedef HANDLE                ap_os_file_t;
-typedef HANDLE                ap_os_dir_t;
-typedef SOCKET                ap_os_sock_t;
-typedef HANDLE                ap_os_lock_t;
-typedef HANDLE                ap_os_thread_t;
-typedef PROCESS_INFORMATION   ap_os_proc_t;
-typedef DWORD                 ap_os_threadkey_t; 
-typedef FILETIME              ap_os_imp_time_t;
-typedef SYSTEMTIME            ap_os_exp_time_t;
+typedef HANDLE                apr_os_file_t;
+typedef HANDLE                apr_os_dir_t;
+typedef SOCKET                apr_os_sock_t;
+typedef HANDLE                apr_os_proc_mutex_t;
+typedef HANDLE                apr_os_thread_t;
+typedef HANDLE                apr_os_proc_t;
+typedef DWORD                 apr_os_threadkey_t; 
+typedef FILETIME              apr_os_imp_time_t;
+typedef SYSTEMTIME            apr_os_exp_time_t;
+typedef HANDLE                apr_os_dso_handle_t;
+typedef HANDLE                apr_os_shm_t;
 
 #elif defined(OS2)
-#define INCL_DOS
-#include <os2.h>
-typedef HFILE                 ap_os_file_t;
-typedef HDIR                  ap_os_dir_t;
-typedef int                   ap_os_sock_t;
-typedef HMTX                  ap_os_lock_t;
-typedef TID                   ap_os_thread_t;
-typedef PID                   ap_os_proc_t;
-typedef PULONG                ap_os_threadkey_t; 
-typedef struct timeval        ap_os_imp_time_t;
-typedef struct tm             ap_os_exp_time_t;
-
-#elif defined(BEOS)
+typedef HFILE                 apr_os_file_t;
+typedef HDIR                  apr_os_dir_t;
+typedef int                   apr_os_sock_t;
+typedef HMTX                  apr_os_proc_mutex_t;
+typedef TID                   apr_os_thread_t;
+typedef PID                   apr_os_proc_t;
+typedef PULONG                apr_os_threadkey_t; 
+typedef struct timeval        apr_os_imp_time_t;
+typedef struct tm             apr_os_exp_time_t;
+typedef HMODULE               apr_os_dso_handle_t;
+typedef void*                 apr_os_shm_t;
+
+#elif defined(__BEOS__)
 #include <kernel/OS.h>
+#include <kernel/image.h>
 
-struct ap_os_lock_t {
-	/* Inter proc */
-	sem_id sem_interproc;
-	int32  ben_interproc;
-	/* Intra Proc */
-	sem_id sem_intraproc;
-	int32  ben_intraproc;
+struct apr_os_proc_mutex_t {
+	sem_id sem;
+	int32  ben;
 };
 
-typedef int                   ap_os_file_t;
-typedef DIR                   ap_os_dir_t;
-typedef int                   ap_os_sock_t;
-typedef struct ap_os_lock_t      ap_os_lock_t;
-typedef thread_id             ap_os_thread_t;
-typedef thread_id             ap_os_proc_t;
-typedef int                   ap_os_threadkey_t;
-typedef struct timeval        ap_os_imp_time_t;
-typedef struct tm             ap_os_exp_time_t;
+typedef int                   apr_os_file_t;
+typedef DIR                   apr_os_dir_t;
+typedef int                   apr_os_sock_t;
+typedef struct apr_os_proc_mutex_t  apr_os_proc_mutex_t;
+typedef thread_id             apr_os_thread_t;
+typedef thread_id             apr_os_proc_t;
+typedef int                   apr_os_threadkey_t;
+typedef struct timeval        apr_os_imp_time_t;
+typedef struct tm             apr_os_exp_time_t;
+typedef image_id              apr_os_dso_handle_t;
+typedef void*                 apr_os_shm_t;
+
+#elif defined(NETWARE)
+typedef int                   apr_os_file_t;
+typedef DIR                   apr_os_dir_t;
+typedef int                   apr_os_sock_t;
+typedef NXMutex_t *           apr_os_proc_mutex_t;
+typedef NXThreadId_t          apr_os_thread_t;
+typedef long                  apr_os_proc_t;
+typedef NXKey_t               apr_os_threadkey_t; 
+typedef struct timeval        apr_os_imp_time_t;
+typedef struct tm             apr_os_exp_time_t;
+typedef void *                apr_os_dso_handle_t;
+typedef void*                 apr_os_shm_t;
 
 #else
 /* Any other OS should go above this one.  This is the lowest common
  * denominator typedefs for  all UNIX-like systems.  :)
  */
 
-#ifdef NEED_UNION_SEMUN
-/* it makes no sense, but this isn't defined on solaris */
-union semun {
-    long val;
-    struct semid_ds *buf;
-    ushort *array;
-};
-#endif
-
-struct ap_os_lock_t {
-#if APR_USE_SYSVSEM_SERIALIZE
-    int crossproc;
-#elif APR_USE_FCNTL_SERIALIZE
+/** Basic OS process mutex structure. */
+struct apr_os_proc_mutex_t {
+#if APR_HAS_SYSVSEM_SERIALIZE || APR_HAS_FCNTL_SERIALIZE || APR_HAS_FLOCK_SERIALIZE
+    /** Value used for SYS V Semaphore, FCNTL and FLOCK serialization */
     int crossproc;
-#elif APR_USE_PROC_PTHREAD_SERIALIZE
-    pthread_mutex_t *crossproc; 
-#elif APR_USE_FLOCK_SERIALIZE
-    int crossproc;
-#else
-    /* No Interprocess serialization, too bad. */
 #endif
-#if APR_HAS_THREADS
-    /* If no threads, no need for thread locks */
-#if APR_USE_PTHREAD_SERIALIZE
-    pthread_mutex_t *intraproc;
+#if APR_HAS_PROC_PTHREAD_SERIALIZE
+    /** Value used for PTHREAD serialization */
+    pthread_mutex_t *pthread_interproc;
 #endif
+#if APR_HAS_POSIXSEM_SERIALIZE
+    /** Value used for POSIX semaphores serialization */
+    sem_t *psem_interproc;
 #endif
 };
 
-typedef int                   ap_os_file_t;
-typedef DIR                   ap_os_dir_t;
-typedef int                   ap_os_sock_t;
-typedef struct ap_os_lock_t      ap_os_lock_t;
+typedef int                   apr_os_file_t;        /**< native file */
+typedef DIR                   apr_os_dir_t;         /**< native dir */
+typedef int                   apr_os_sock_t;        /**< native dir */
+typedef struct apr_os_proc_mutex_t  apr_os_proc_mutex_t; /**< native process
+                                                          *   mutex
+                                                          */
 #if APR_HAS_THREADS && APR_HAVE_PTHREAD_H 
-typedef pthread_t             ap_os_thread_t;
-typedef pthread_key_t         ap_os_threadkey_t;
+typedef pthread_t             apr_os_thread_t;      /**< native thread */
+typedef pthread_key_t         apr_os_threadkey_t;   /**< native thread address
+                                                     *   space */
 #endif
-typedef pid_t                 ap_os_proc_t;
-typedef struct timeval        ap_os_imp_time_t;
-typedef struct tm             ap_os_exp_time_t;
+typedef pid_t                 apr_os_proc_t;        /**< native pid */
+typedef struct timeval        apr_os_imp_time_t;    /**< native timeval */
+typedef struct tm             apr_os_exp_time_t;    /**< native tm */
+/** @var apr_os_dso_handle_t
+ * native dso types
+ */
+#if defined(HPUX) || defined(HPUX10) || defined(HPUX11)
+#include <dl.h>
+typedef shl_t                 apr_os_dso_handle_t;
+#elif defined(DARWIN)
+#include <mach-o/dyld.h>
+typedef NSModule              apr_os_dso_handle_t;
+#else
+typedef void *                apr_os_dso_handle_t;
 #endif
+typedef void*                 apr_os_shm_t;         /**< native SHM */
 
-/*
-
-=head1 ap_status_t ap_get_os_file(ap_os_file_t *thefile, ap_file_t *file) 
-
-B<convert the file from apr type to os specific type.>
-
-    arg 1) The os specific file we are converting to
-    arg 2) The apr file to convert.
-
-B<NOTE>:  On Unix, it is only possible to get a file descriptor from 
-          an apr file type.
+#endif
 
-=cut
+/**
+ * @typedef apr_os_sock_info_t
+ * @brief alias for local OS socket
  */
-ap_status_t ap_get_os_file(ap_os_file_t *thefile, ap_file_t *file);     
-
-/*
-
-=head1 ap_status_t ap_get_os_dir(ap_os_dir_t **thedir, ap_dir_t *dir)
-
-B<convert the dir from apr type to os specific type.>
-
-    arg 1) The os specific dir we are converting to
-    arg 2) The apr dir to convert.
-
-=cut
- */   
-ap_status_t ap_get_os_dir(ap_os_dir_t **thedir, ap_dir_t *dir);      
-
-/*
-
-=head1 ap_status_t ap_get_os_sock(ap_os_sock_t *thesock, ap_socket_t *sock)
-
-B<Convert the socket from an apr type to an OS specific socket>
-
-    arg 1) The socket to convert.
-    arg 2) The os specifc equivelant of the apr socket..
-
-=cut
+/**
+ * everything APR needs to know about an active socket to construct
+ * an APR socket from it; currently, this is platform-independent
  */
-ap_status_t ap_get_os_sock(ap_os_sock_t *thesock, ap_socket_t *sock);
+struct apr_os_sock_info_t {
+    apr_os_sock_t *os_sock; /**< always required */
+    struct sockaddr *local; /**< NULL if not yet bound */
+    struct sockaddr *remote; /**< NULL if not connected */
+    int family;             /**< always required (APR_INET, APR_INET6, etc.) */
+    int type;               /**< always required (SOCK_STREAM, SOCK_DGRAM, etc.) */
+    int protocol;           /**< 0 or actual protocol (APR_PROTO_SCTP, APR_PROTO_TCP, etc.) */
+};
 
-/*
+typedef struct apr_os_sock_info_t apr_os_sock_info_t;
 
-=head1 ap_status_t ap_get_os_lock(ap_os_lock_t *oslock, ap_lock_t *lock)
+#if APR_PROC_MUTEX_IS_GLOBAL || defined(DOXYGEN)
+/** Opaque global mutex type */
+#define apr_os_global_mutex_t apr_os_proc_mutex_t
+/** @return apr_os_global_mutex */
+#define apr_os_global_mutex_get apr_os_proc_mutex_get
+#else
+    /** Thread and process mutex for those platforms where process mutexes
+     *  are not held in threads.
+     */
+    struct apr_os_global_mutex_t {
+        apr_pool_t *pool;
+        apr_proc_mutex_t *proc_mutex;
+#if APR_HAS_THREADS
+        apr_thread_mutex_t *thread_mutex;
+#endif /* APR_HAS_THREADS */
+    };
+    typedef struct apr_os_global_mutex_t apr_os_global_mutex_t;
 
-B<Convert the lock from os specific type to apr type>
+APR_DECLARE(apr_status_t) apr_os_global_mutex_get(apr_os_global_mutex_t *ospmutex, 
+                                                apr_global_mutex_t *pmutex);
+#endif
 
-    arg 1) The os specific lock we are converting to.
-    arg 2) The apr lock to convert.
 
-=cut
+/**
+ * convert the file from apr type to os specific type.
+ * @param thefile The os specific file we are converting to
+ * @param file The apr file to convert.
+ * @remark On Unix, it is only possible to get a file descriptor from 
+ *         an apr file type.
  */
-ap_status_t ap_get_os_lock(ap_os_lock_t *oslock, ap_lock_t *lock);     
+APR_DECLARE(apr_status_t) apr_os_file_get(apr_os_file_t *thefile,
+                                          apr_file_t *file);
 
-/*
-
-=head1 ap_status_t ap_get_os_proc(ap_os_proc_t *theproc, ap_proc_t *proc)
-
-B<convert the proc from os specific type to apr type.>
-
-    arg 1) The os specific proc we are converting to
-    arg 2) The apr proc we are converting
+/**
+ * convert the dir from apr type to os specific type.
+ * @param thedir The os specific dir we are converting to
+ * @param dir The apr dir to convert.
+ */   
+APR_DECLARE(apr_status_t) apr_os_dir_get(apr_os_dir_t **thedir, 
+                                         apr_dir_t *dir);
 
-=cut
+/**
+ * Convert the socket from an apr type to an OS specific socket
+ * @param thesock The socket to convert.
+ * @param sock The os specific equivalent of the apr socket..
  */
-ap_status_t ap_get_os_proc(ap_os_proc_t *theproc, ap_proc_t *proc);     
-
-/*
-
-=head1 ap_status_t ap_get_os_exp_time(ap_os_exp_time_t **ostime, ap_exploded_time_t *aprtime)
-
-B<Get the exploded time in the platforms native format.>
-
-    arg 1) the native time format
-    arg 2) the time to convert
+APR_DECLARE(apr_status_t) apr_os_sock_get(apr_os_sock_t *thesock,
+                                          apr_socket_t *sock);
 
-=cut
+/**
+ * Convert the proc mutex from apr type to os specific type
+ * @param ospmutex The os specific proc mutex we are converting to.
+ * @param pmutex The apr proc mutex to convert.
  */
-ap_status_t ap_get_os_exp_time(ap_os_exp_time_t **, ap_exploded_time_t *);     
-
-/*
-
-=head1 ap_status_t ap_get_os_imp_time(ap_os_imp_time_t **ostime, ap_time_t *aprtime)
-
-B<Get the imploded time in the platforms native format.>
-
-    arg 1) the native time format
-    arg 2) the time to convert
-
-=cut
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_get(apr_os_proc_mutex_t *ospmutex, 
+                                                apr_proc_mutex_t *pmutex);
+
+/**
+ * Convert the proc mutex from apr type to os specific type, also
+ * providing the mechanism used by the apr mutex.
+ * @param ospmutex The os specific proc mutex we are converting to.
+ * @param pmutex The apr proc mutex to convert.
+ * @param mech The mechanism used by the apr proc mutex (if not NULL).
+ * @remark Allows for disambiguation for platforms with multiple mechanisms
+ *         available.
  */
-ap_status_t ap_get_os_imp_time(ap_os_imp_time_t **, ap_time_t *);     
-#if APR_HAS_THREADS
-/*
-
-=head1 ap_status_t ap_get_os_thread(ap_thread_t *thethd, ap_os_thread_t *thd)
-
-B<convert the thread to os specific type from apr type.>
-
-    arg 1) The apr thread to convert
-    arg 2) The os specific thread we are converting to
-
-=cut
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_get_ex(apr_os_proc_mutex_t *ospmutex, 
+                                                   apr_proc_mutex_t *pmutex,
+                                                   apr_lockmech_e *mech);
+
+/**
+ * Get the exploded time in the platforms native format.
+ * @param ostime the native time format
+ * @param aprtime the time to convert
  */
-ap_status_t ap_get_os_thread(ap_os_thread_t *thethd, ap_thread_t *thd);
-
-/*
+APR_DECLARE(apr_status_t) apr_os_exp_time_get(apr_os_exp_time_t **ostime,
+                                 apr_time_exp_t *aprtime);
 
-=head1 ap_status_t ap_get_os_threadkey(ap_threadkey_t *thekey, ap_os_threadkey_t *key)
-
-B<convert the thread private memory key to os specific type from an apr type.>
-
-    arg 1) The apr handle we are converting from.
-    arg 2) The os specific handle we are converting to.
-
-=cut
+/**
+ * Get the imploded time in the platforms native format.
+ * @param ostime  the native time format
+ * @param aprtime the time to convert
  */
-ap_status_t ap_get_os_threadkey(ap_os_threadkey_t *thekey, ap_threadkey_t *key);
-#endif
+APR_DECLARE(apr_status_t) apr_os_imp_time_get(apr_os_imp_time_t **ostime, 
+                                              apr_time_t *aprtime);
 
-/*
-
-=head1 ap_status_t ap_put_os_file(ap_file_t **file, ap_os_file_t *thefile, ap_pool_t *cont) 
-
-B<convert the file from os specific type to apr type.>
-
-    arg 1) The apr file we are converting to.
-    arg 2) The os specific file to convert
-    arg 3) The pool to use if it is needed.
-
-B<NOTE>:  On Unix, it is only possible to put a file descriptor into
-          an apr file type.
+/**
+ * convert the shm from apr type to os specific type.
+ * @param osshm The os specific shm representation
+ * @param shm The apr shm to convert.
+ */   
+APR_DECLARE(apr_status_t) apr_os_shm_get(apr_os_shm_t *osshm,
+                                         apr_shm_t *shm);
 
-=cut
+#if APR_HAS_THREADS || defined(DOXYGEN)
+/** 
+ * @defgroup apr_os_thread Thread portability Routines
+ * @{ 
  */
-ap_status_t ap_put_os_file(ap_file_t **file, ap_os_file_t *thefile, 
-                           ap_pool_t *cont); 
-
-/*
-
-=head1 ap_status_t ap_put_os_dir(ap_dir_t **dir, ap_os_dir_t *thedir, ap_pool_t *cont)
-
-B<convert the dir from os specific type to apr type.>
-
-    arg 1) The apr dir we are converting to.
-    arg 2) The os specific dir to convert
-    arg 3) The pool to use when creating to apr directory.
-
-=cut
+/**
+ * convert the thread to os specific type from apr type.
+ * @param thethd The apr thread to convert
+ * @param thd The os specific thread we are converting to
  */
-ap_status_t ap_put_os_dir(ap_dir_t **dir, ap_os_dir_t *thedir, 
-                          ap_pool_t *cont); 
-
-/*
-
-=head1 ap_status_t ap_put_os_sock(ap_socket_t **sock, ap_os_socket_t *thesock, ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_os_thread_get(apr_os_thread_t **thethd, 
+                                            apr_thread_t *thd);
 
-B<Convert a socket from the os specific type to the apr type>
-
-    arg 1) The pool to use.
-    arg 2) The socket to convert to.
-    arg 3) The socket we are converting to an apr type.
-
-=cut
+/**
+ * convert the thread private memory key to os specific type from an apr type.
+ * @param thekey The apr handle we are converting from.
+ * @param key The os specific handle we are converting to.
  */
-ap_status_t ap_put_os_sock(ap_socket_t **sock, ap_os_sock_t *thesock, 
-                           ap_pool_t *cont);
-
-/*
-
-=head1 ap_status_t ap_put_os_lock(ap_lock_t **lock, ap_os_lock_t *, ap_pool_t *cont)
-
-B<Convert the lock from os specific type to apr type>
-
-    arg 1) The apr lock we are converting to.
-    arg 2) The os specific lock to convert.
-    arg 3) The pool to use if it is needed.
-
-=cut
+APR_DECLARE(apr_status_t) apr_os_threadkey_get(apr_os_threadkey_t *thekey,
+                                               apr_threadkey_t *key);
+
+/**
+ * convert the thread from os specific type to apr type.
+ * @param thd The apr thread we are converting to.
+ * @param thethd The os specific thread to convert
+ * @param cont The pool to use if it is needed.
  */
-ap_status_t ap_put_os_lock(ap_lock_t **lock, ap_os_lock_t *thelock, 
-                           ap_pool_t *cont); 
-
-/*
-
-=head1 ap_status_t ap_put_os_proc(ap_proc_t *proc, ap_os_proc_t *theproc, ap_pool_t *cont)
-
-B<convert the proc from os specific type to apr type.>
-
-    arg 1) The apr proc we are converting to.
-    arg 2) The os specific proc to convert
-    arg 3) The pool to use if it is needed.
-
-=cut
+APR_DECLARE(apr_status_t) apr_os_thread_put(apr_thread_t **thd,
+                                            apr_os_thread_t *thethd,
+                                            apr_pool_t *cont);
+
+/**
+ * convert the thread private memory key from os specific type to apr type.
+ * @param key The apr handle we are converting to.
+ * @param thekey The os specific handle to convert
+ * @param cont The pool to use if it is needed.
  */
-ap_status_t ap_put_os_proc(ap_proc_t **proc, ap_os_proc_t *theproc, 
-                           ap_pool_t *cont); 
-
-/*
-
-=head1 ap_status_t ap_put_os_imp_time(ap_time_t *aprtime, ap_os_imp_time_t **ostime, ap_pool_t, *cont)
-
-B<Put the imploded time in the APR format.>
-
-    arg 1) the APR time format
-    arg 2) the time to convert
-    arg 3) the pool to use if necessary
-
-=cut
+APR_DECLARE(apr_status_t) apr_os_threadkey_put(apr_threadkey_t **key,
+                                               apr_os_threadkey_t *thekey,
+                                               apr_pool_t *cont);
+/**
+ * Get the thread ID
  */
-ap_status_t ap_put_os_imp_time(ap_time_t *, ap_os_imp_time_t **, ap_pool_t *); 
-
-/*
-
-=head1 ap_status_t ap_put_os_exp_time(ap_exploded_time_t *aprtime, ap_os_exp_time_t **ostime, ap_pool_t, *cont)
-
-B<Put the exploded time in the APR format.>
-
-    arg 1) the APR time format
-    arg 2) the time to convert
-    arg 3) the pool to use if necessary
-
-=cut
+APR_DECLARE(apr_os_thread_t) apr_os_thread_current(void);
+
+/**
+ * Compare two thread id's
+ * @param tid1 1st Thread ID to compare
+ * @param tid2 2nd Thread ID to compare
+ * @return non-zero if the two threads are equal, zero otherwise
+ */ 
+APR_DECLARE(int) apr_os_thread_equal(apr_os_thread_t tid1, 
+                                     apr_os_thread_t tid2);
+
+/** @} */
+#endif /* APR_HAS_THREADS */
+
+/**
+ * convert the file from os specific type to apr type.
+ * @param file The apr file we are converting to.
+ * @param thefile The os specific file to convert
+ * @param flags The flags that were used to open this file.
+ * @param cont The pool to use if it is needed.
+ * @remark On Unix, it is only possible to put a file descriptor into
+ *         an apr file type.
+ */
+APR_DECLARE(apr_status_t) apr_os_file_put(apr_file_t **file,
+                                          apr_os_file_t *thefile,
+                                          apr_int32_t flags, apr_pool_t *cont); 
+
+/**
+ * convert the file from os specific type to apr type.
+ * @param file The apr file we are converting to.
+ * @param thefile The os specific pipe to convert
+ * @param cont The pool to use if it is needed.
+ * @remark On Unix, it is only possible to put a file descriptor into
+ *         an apr file type.
+ */
+APR_DECLARE(apr_status_t) apr_os_pipe_put(apr_file_t **file,
+                                          apr_os_file_t *thefile,
+                                          apr_pool_t *cont);
+
+/**
+ * convert the file from os specific type to apr type.
+ * @param file The apr file we are converting to.
+ * @param thefile The os specific pipe to convert
+ * @param register_cleanup A cleanup will be registered on the apr_file_t
+ *   to issue apr_file_close().
+ * @param cont The pool to use if it is needed.
+ * @remark On Unix, it is only possible to put a file descriptor into
+ *         an apr file type.
+ */
+APR_DECLARE(apr_status_t) apr_os_pipe_put_ex(apr_file_t **file,
+                                             apr_os_file_t *thefile,
+                                             int register_cleanup,
+                                             apr_pool_t *cont);
+
+/**
+ * convert the dir from os specific type to apr type.
+ * @param dir The apr dir we are converting to.
+ * @param thedir The os specific dir to convert
+ * @param cont The pool to use when creating to apr directory.
+ */
+APR_DECLARE(apr_status_t) apr_os_dir_put(apr_dir_t **dir,
+                                         apr_os_dir_t *thedir,
+                                         apr_pool_t *cont); 
+
+/**
+ * Convert a socket from the os specific type to the APR type. If
+ * sock points to NULL, a socket will be created from the pool
+ * provided. If **sock does not point to NULL, the structure pointed 
+ * to by sock will be reused and updated with the given socket.
+ * @param sock The pool to use.
+ * @param thesock The socket to convert to.
+ * @param cont The socket we are converting to an apr type.
+ * @remark If it is a true socket, it is best to call apr_os_sock_make()
+ *         and provide APR with more information about the socket.
  */
-ap_status_t ap_put_os_exp_time(ap_exploded_time_t *, ap_os_exp_time_t **, ap_pool_t *); 
+APR_DECLARE(apr_status_t) apr_os_sock_put(apr_socket_t **sock, 
+                                          apr_os_sock_t *thesock, 
+                                          apr_pool_t *cont);
+
+/**
+ * Create a socket from an existing descriptor and local and remote
+ * socket addresses.
+ * @param apr_sock The new socket that has been set up
+ * @param os_sock_info The os representation of the socket handle and
+ *        other characteristics of the socket
+ * @param cont The pool to use
+ * @remark If you only know the descriptor/handle or if it isn't really
+ *         a true socket, use apr_os_sock_put() instead.
+ */
+APR_DECLARE(apr_status_t) apr_os_sock_make(apr_socket_t **apr_sock,
+                                           apr_os_sock_info_t *os_sock_info,
+                                           apr_pool_t *cont);
+
+/**
+ * Convert the proc mutex from os specific type to apr type
+ * @param pmutex The apr proc mutex we are converting to.
+ * @param ospmutex The os specific proc mutex to convert.
+ * @param cont The pool to use if it is needed.
+ */
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_put(apr_proc_mutex_t **pmutex,
+                                                apr_os_proc_mutex_t *ospmutex,
+                                                apr_pool_t *cont); 
+
+/**
+ * Convert the proc mutex from os specific type to apr type, using the
+ * specified mechanism.
+ * @param pmutex The apr proc mutex we are converting to.
+ * @param ospmutex The os specific proc mutex to convert.
+ * @param mech The apr mutex locking mechanism
+ * @param register_cleanup Whether to destroy the os mutex with the apr
+ *        one (either on explicit destroy or pool cleanup).
+ * @param cont The pool to use if it is needed.
+ * @remark Allows for disambiguation for platforms with multiple mechanisms
+ *         available.
+ */
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_put_ex(apr_proc_mutex_t **pmutex,
+                                                apr_os_proc_mutex_t *ospmutex,
+                                                apr_lockmech_e mech,
+                                                int register_cleanup,
+                                                apr_pool_t *cont); 
+
+/**
+ * Put the imploded time in the APR format.
+ * @param aprtime the APR time format
+ * @param ostime the time to convert
+ * @param cont the pool to use if necessary
+ */
+APR_DECLARE(apr_status_t) apr_os_imp_time_put(apr_time_t *aprtime,
+                                              apr_os_imp_time_t **ostime,
+                                              apr_pool_t *cont); 
+
+/**
+ * Put the exploded time in the APR format.
+ * @param aprtime the APR time format
+ * @param ostime the time to convert
+ * @param cont the pool to use if necessary
+ */
+APR_DECLARE(apr_status_t) apr_os_exp_time_put(apr_time_exp_t *aprtime,
+                                              apr_os_exp_time_t **ostime,
+                                              apr_pool_t *cont); 
+
+/**
+ * convert the shared memory from os specific type to apr type.
+ * @param shm The apr shm representation of osshm
+ * @param osshm The os specific shm identity
+ * @param cont The pool to use if it is needed.
+ * @remark On fork()ed architectures, this is typically nothing more than
+ * the memory block mapped.  On non-fork architectures, this is typically
+ * some internal handle to pass the mapping from process to process.
+ */
+APR_DECLARE(apr_status_t) apr_os_shm_put(apr_shm_t **shm,
+                                         apr_os_shm_t *osshm,
+                                         apr_pool_t *cont); 
 
-#if APR_HAS_THREADS
-/*
 
-=head1 ap_status_t ap_put_os_thread(ap_thread_t *thd, ap_os_thread_t *thethd, ap_pool_t *cont)
+#if APR_HAS_DSO || defined(DOXYGEN)
+/** 
+ * @defgroup apr_os_dso DSO (Dynamic Loading) Portability Routines
+ * @{
+ */
+/**
+ * convert the dso handle from os specific to apr
+ * @param dso The apr handle we are converting to
+ * @param thedso the os specific handle to convert
+ * @param pool the pool to use if it is needed
+ */
+APR_DECLARE(apr_status_t) apr_os_dso_handle_put(apr_dso_handle_t **dso,
+                                                apr_os_dso_handle_t thedso,
+                                                apr_pool_t *pool);
+
+/**
+ * convert the apr dso handle into an os specific one
+ * @param aprdso The apr dso handle to convert
+ * @param dso The os specific dso to return
+ */
+APR_DECLARE(apr_status_t) apr_os_dso_handle_get(apr_os_dso_handle_t *dso,
+                                                apr_dso_handle_t *aprdso);
 
-B<convert the thread from os specific type to apr type.>
+/** @} */
+#endif /* APR_HAS_DSO */
 
-    arg 1) The apr thread we are converting to.
-    arg 2) The os specific thread to convert
-    arg 3) The pool to use if it is needed.
 
-=cut
+#if APR_HAS_OS_UUID
+/**
+ * Private: apr-util's apr_uuid module when supported by the platform
  */
-ap_status_t ap_put_os_thread(ap_thread_t **thd, ap_os_thread_t *thethd, 
-                             ap_pool_t *cont);
-
-/*
+APR_DECLARE(apr_status_t) apr_os_uuid_get(unsigned char *uuid_data);
+#endif
 
-=head1 ap_status_t ap_put_os_threadkey(ap_threadkey_t *key, ap_os_threadkey_t *thekey, ap_pool_t *cont)
 
-B<convert the thread private memory key from os specific type to apr type.>
+/**
+ * Get the name of the system default character set.
+ * @param pool the pool to allocate the name from, if needed
+ */
+APR_DECLARE(const char*) apr_os_default_encoding(apr_pool_t *pool);
 
-    arg 1) The apr handle we are converting to.
-    arg 2) The os specific handle to convert
-    arg 3) The pool to use if it is needed.
 
-=cut
+/**
+ * Get the name of the current locale character set.
+ * @param pool the pool to allocate the name from, if needed
+ * @remark Defers to apr_os_default_encoding if the current locale's
+ * data can't be retrieved on this system.
  */
-ap_status_t ap_put_os_threadkey(ap_threadkey_t **key, ap_os_threadkey_t *thekey, 
-                                ap_pool_t *cont);
-#endif
+APR_DECLARE(const char*) apr_os_locale_encoding(apr_pool_t *pool);
+
+/** @} */
 
 #ifdef __cplusplus
 }
diff --git a/include/apr_private.hw b/include/apr_private.hw
deleted file mode 100644
index d3015e35862..00000000000
--- a/include/apr_private.hw
+++ /dev/null
@@ -1,158 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-/*
- * Note: 
- * This is the windows specific autoconf like config file
- * which is used to generate apr_private.h at build time.
- * Do not put any code into this file which depends on
- * APR include files.
- */
-
-#ifdef WIN32
-
-#ifndef APR_CONFIG_H
-#define APR_CONFIG_H
-
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#endif
-#ifndef _WIN32_WINNT
-/* 
- * Compile the server including all the Windows NT 4.0 header files by 
- * default.
- */
-#define _WIN32_WINNT 0x0400
-#endif
-#include <windows.h>
-#include <winsock2.h>
-#include <mswsock.h>
-#include <sys/types.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <time.h>
-
-#define HAVE_SENDFILE 1
-
-/* Use this section to define all of the HAVE_FOO_H
- * that are required to build properly.
- */
-#define HAVE_CONIO_H 1
-#define HAVE_MALLOC_H 1
-#define HAVE_STDLIB_H 1
-#define HAVE_LIMITS_H 1
-#define HAVE_SIGNAL_H 1
-
-#define SIGHUP     1
-/* 2 is used for SIGINT on windows */
-#define SIGQUIT    3
-/* 4 is used for SIGILL on windows */
-#define SIGTRAP    5
-#define SIGIOT     6
-#define SIGBUS     7
-/* 8 is used for SIGFPE on windows */
-#define SIGKILL    9
-#define SIGUSR1    10
-/* 11 is used for SIGSEGV on windows */
-#define SIGUSR2    12
-#define SIGPIPE    13
-#define SIGALRM    14
-/* 15 is used for SIGTERM on windows */
-#define SIGSTKFLT  16
-#define SIGCHLD    17 
-#define SIGCONT    18
-#define SIGSTOP    19
-#define SIGTSTP    20
-/* 21 is used for SIGBREAK on windows */
-/* 22 is used for SIGABRT on windows */
-#define SIGTTIN    23
-#define SIGTTOU    24
-#define SIGURG     25
-#define SIGXCPU    26
-#define SIGXFSZ    27
-#define SIGVTALRM  28
-#define SIGPROF    29
-#define SIGWINCH   30
-#define SIGIO      31
-
-#define __attribute__(__x) 
-
-/* APR COMPATABILITY FUNCTIONS
- * This section should be used to define functions and
- * macros which are need to make Windows features look
- * like POSIX features.
- */
-typedef void (Sigfunc)(int);
-
-#define strcasecmp(s1, s2)       stricmp(s1, s2)
-#define sleep(t)                 Sleep(t * 1000)
-
-
-/* APR FEATURE MACROS.
- * This section should be used to define feature macros
- * that the windows port needs.
- */
-#define APR_HAS_THREADS        1
-
-#define SIZEOF_SHORT           2
-#define SIZEOF_INT             4
-#define SIZEOF_LONGLONG        8
-#define SIZEOF_CHAR            1
-#define SIZEOF_SSIZE_T         SIZEOF_INT
-
-unsigned __stdcall SignalHandling(void *);
-int thread_ready(void);
-
-#endif  /*APR_CONFIG_H*/
-#endif  /*WIN32*/
diff --git a/include/apr_proc_mutex.h b/include/apr_proc_mutex.h
new file mode 100644
index 00000000000..418c95048a7
--- /dev/null
+++ b/include/apr_proc_mutex.h
@@ -0,0 +1,192 @@
+/* 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 APR_PROC_MUTEX_H
+#define APR_PROC_MUTEX_H
+
+/**
+ * @file apr_proc_mutex.h
+ * @brief APR Process Locking Routines
+ */
+
+#include "apr.h"
+#include "apr_pools.h"
+#include "apr_errno.h"
+#include "apr_perms_set.h"
+#include "apr_time.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup apr_proc_mutex Process Locking Routines
+ * @ingroup APR 
+ * @{
+ */
+
+/** 
+ * Enumerated potential types for APR process locking methods
+ * @warning Check APR_HAS_foo_SERIALIZE defines to see if the platform supports
+ *          APR_LOCK_foo.  Only APR_LOCK_DEFAULT is portable.
+ */
+typedef enum {
+    APR_LOCK_FCNTL,         /**< fcntl() */
+    APR_LOCK_FLOCK,         /**< flock() */
+    APR_LOCK_SYSVSEM,       /**< System V Semaphores */
+    APR_LOCK_PROC_PTHREAD,  /**< POSIX pthread process-based locking */
+    APR_LOCK_POSIXSEM,      /**< POSIX semaphore process-based locking */
+    APR_LOCK_DEFAULT,       /**< Use the default process lock */
+    APR_LOCK_DEFAULT_TIMED  /**< Use the default process timed lock */
+} apr_lockmech_e;
+
+/** Opaque structure representing a process mutex. */
+typedef struct apr_proc_mutex_t apr_proc_mutex_t;
+
+/*   Function definitions */
+
+/**
+ * Create and initialize a mutex that can be used to synchronize processes.
+ * @param mutex the memory address where the newly created mutex will be
+ *        stored.
+ * @param fname A file name to use if the lock mechanism requires one.  This
+ *        argument should always be provided.  The lock code itself will
+ *        determine if it should be used.
+ * @param mech The mechanism to use for the interprocess lock, if any; one of
+ * <PRE>
+ *            APR_LOCK_FCNTL
+ *            APR_LOCK_FLOCK
+ *            APR_LOCK_SYSVSEM
+ *            APR_LOCK_POSIXSEM
+ *            APR_LOCK_PROC_PTHREAD
+ *            APR_LOCK_DEFAULT     pick the default mechanism for the platform
+ * </PRE>
+ * @param pool the pool from which to allocate the mutex.
+ * @see apr_lockmech_e
+ * @warning Check APR_HAS_foo_SERIALIZE defines to see if the platform supports
+ *          APR_LOCK_foo.  Only APR_LOCK_DEFAULT is portable.
+ */
+APR_DECLARE(apr_status_t) apr_proc_mutex_create(apr_proc_mutex_t **mutex,
+                                                const char *fname,
+                                                apr_lockmech_e mech,
+                                                apr_pool_t *pool);
+
+/**
+ * Re-open a mutex in a child process.
+ * @param mutex The newly re-opened mutex structure.
+ * @param fname A file name to use if the mutex mechanism requires one.  This
+ *              argument should always be provided.  The mutex code itself will
+ *              determine if it should be used.  This filename should be the 
+ *              same one that was passed to apr_proc_mutex_create().
+ * @param pool The pool to operate on.
+ * @remark This function must be called to maintain portability, even
+ *         if the underlying lock mechanism does not require it.
+ */
+APR_DECLARE(apr_status_t) apr_proc_mutex_child_init(apr_proc_mutex_t **mutex,
+                                                    const char *fname,
+                                                    apr_pool_t *pool);
+
+/**
+ * Acquire the lock for the given mutex. If the mutex is already locked,
+ * the current thread will be put to sleep until the lock becomes available.
+ * @param mutex the mutex on which to acquire the lock.
+ */
+APR_DECLARE(apr_status_t) apr_proc_mutex_lock(apr_proc_mutex_t *mutex);
+
+/**
+ * Attempt to acquire the lock for the given mutex. If the mutex has already
+ * been acquired, the call returns immediately with APR_EBUSY. Note: it
+ * is important that the APR_STATUS_IS_EBUSY(s) macro be used to determine
+ * if the return value was APR_EBUSY, for portability reasons.
+ * @param mutex the mutex on which to attempt the lock acquiring.
+ */
+APR_DECLARE(apr_status_t) apr_proc_mutex_trylock(apr_proc_mutex_t *mutex);
+
+/**
+ * Attempt to acquire the lock for the given mutex until timeout expires.
+ * If the acquisition time outs, the call returns with APR_TIMEUP.
+ * @param mutex the mutex on which to attempt the lock acquiring.
+ * @param timeout the relative timeout (microseconds).
+ * @note A negative or nul timeout means immediate attempt, returning
+ *       APR_TIMEUP without blocking if it the lock is already acquired.
+ */
+APR_DECLARE(apr_status_t) apr_proc_mutex_timedlock(apr_proc_mutex_t *mutex,
+                                               apr_interval_time_t timeout);
+
+/**
+ * Release the lock for the given mutex.
+ * @param mutex the mutex from which to release the lock.
+ */
+APR_DECLARE(apr_status_t) apr_proc_mutex_unlock(apr_proc_mutex_t *mutex);
+
+/**
+ * Destroy the mutex and free the memory associated with the lock.
+ * @param mutex the mutex to destroy.
+ */
+APR_DECLARE(apr_status_t) apr_proc_mutex_destroy(apr_proc_mutex_t *mutex);
+
+/**
+ * Destroy the mutex and free the memory associated with the lock.
+ * @param mutex the mutex to destroy.
+ * @note This function is generally used to kill a cleanup on an already
+ *       created mutex
+ */
+APR_DECLARE(apr_status_t) apr_proc_mutex_cleanup(void *mutex);
+
+/**
+ * Return the name of the lockfile for the mutex, or NULL
+ * if the mutex doesn't use a lock file
+ */
+
+APR_DECLARE(const char *) apr_proc_mutex_lockfile(apr_proc_mutex_t *mutex);
+
+/**
+ * Get the mechanism of the mutex, as it relates to the actual method
+ * used for the underlying apr_proc_mutex_t.
+ * @param mutex the mutex to get the mechanism from.
+ */
+APR_DECLARE(apr_lockmech_e) apr_proc_mutex_mech(apr_proc_mutex_t *mutex);
+
+/**
+ * Get the mechanism's name of the mutex, as it relates to the actual method
+ * used for the underlying apr_proc_mutex_t.
+ * @param mutex the mutex to get the mechanism's name from.
+ */
+APR_DECLARE(const char *) apr_proc_mutex_name(apr_proc_mutex_t *mutex);
+
+/**
+ * Display the name of the default mutex: APR_LOCK_DEFAULT
+ */
+APR_DECLARE(const char *) apr_proc_mutex_defname(void);
+
+/**
+ * Set mutex permissions.
+ */
+APR_PERMS_SET_IMPLEMENT(proc_mutex);
+
+/**
+ * Get the pool used by this proc_mutex.
+ * @return apr_pool_t the pool
+ */
+APR_POOL_DECLARE_ACCESSOR(proc_mutex);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* ! APR_PROC_MUTEX_H */
diff --git a/include/apr_queue.h b/include/apr_queue.h
new file mode 100644
index 00000000000..e345da5d453
--- /dev/null
+++ b/include/apr_queue.h
@@ -0,0 +1,171 @@
+/* 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 APR_QUEUE_H
+#define APR_QUEUE_H
+
+/**
+ * @file apr_queue.h
+ * @brief Thread Safe FIFO bounded queue
+ * @note Since most implementations of the queue are backed by a condition
+ * variable implementation, it isn't available on systems without threads.
+ * Although condition variables are sometimes available without threads.
+ */
+
+#include "apu.h"
+#include "apr_errno.h"
+#include "apr_pools.h"
+#include "apr_time.h"
+
+#if APR_HAS_THREADS
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup APR_Util_FIFO Thread Safe FIFO bounded queue
+ * @ingroup APR
+ * @{
+ */
+
+/**
+ * opaque structure
+ */
+typedef struct apr_queue_t apr_queue_t;
+
+/** 
+ * create a FIFO queue
+ * @param queue The new queue
+ * @param queue_capacity maximum size of the queue
+ * @param a pool to allocate queue from
+ */
+APR_DECLARE(apr_status_t) apr_queue_create(apr_queue_t **queue, 
+                                           unsigned int queue_capacity, 
+                                           apr_pool_t *a);
+
+/**
+ * push/add an object to the queue, blocking if the queue is already full
+ *
+ * @param queue the queue
+ * @param data the data
+ * @returns APR_EINTR the blocking was interrupted (try again)
+ * @returns APR_EOF the queue has been terminated
+ * @returns APR_SUCCESS on a successful push
+ */
+APR_DECLARE(apr_status_t) apr_queue_push(apr_queue_t *queue, void *data);
+
+/**
+ * pop/get an object from the queue, blocking if the queue is already empty
+ *
+ * @param queue the queue
+ * @param data the data
+ * @returns APR_EINTR the blocking was interrupted (try again)
+ * @returns APR_EOF if the queue has been terminated
+ * @returns APR_SUCCESS on a successful pop
+ */
+APR_DECLARE(apr_status_t) apr_queue_pop(apr_queue_t *queue, void **data);
+
+/**
+ * push/add an object to the queue, returning immediately if the queue is full
+ *
+ * @param queue the queue
+ * @param data the data
+ * @returns APR_EINTR the blocking operation was interrupted (try again)
+ * @returns APR_EAGAIN the queue is full
+ * @returns APR_EOF the queue has been terminated
+ * @returns APR_SUCCESS on a successful push
+ */
+APR_DECLARE(apr_status_t) apr_queue_trypush(apr_queue_t *queue, void *data);
+
+/**
+ * pop/get an object from the queue, returning immediately if the queue is empty
+ *
+ * @param queue the queue
+ * @param data the data
+ * @returns APR_EINTR the blocking operation was interrupted (try again)
+ * @returns APR_EAGAIN the queue is empty
+ * @returns APR_EOF the queue has been terminated
+ * @returns APR_SUCCESS on a successful pop
+ */
+APR_DECLARE(apr_status_t) apr_queue_trypop(apr_queue_t *queue, void **data);
+
+/**
+ * push/add an object to the queue, waiting a maximum of timeout microseconds
+ * before returning if the queue is empty
+ *
+ * @param queue the queue
+ * @param data the data
+ * @param timeout the timeout
+ * @returns APR_EINTR the blocking operation was interrupted (try again)
+ * @returns APR_EAGAIN the queue is empty and timeout is 0
+ * @returns APR_TIMEUP the queue is empty and the timeout expired
+ * @returns APR_EOF the queue has been terminated
+ * @returns APR_SUCCESS on a successful pop
+ */
+APR_DECLARE(apr_status_t) apr_queue_timedpush(apr_queue_t *queue, void *data,
+                                              apr_interval_time_t timeout);
+
+/**
+ * pop/get an object from the queue, waiting a maximum of timeout microseconds
+ * before returning if the queue is empty
+ *
+ * @param queue the queue
+ * @param data the data
+ * @param timeout the timeout
+ * @returns APR_EINTR the blocking operation was interrupted (try again)
+ * @returns APR_EAGAIN the queue is empty and timeout is 0
+ * @returns APR_TIMEUP the queue is empty and the timeout expired
+ * @returns APR_EOF the queue has been terminated
+ * @returns APR_SUCCESS on a successful pop
+ */
+APR_DECLARE(apr_status_t) apr_queue_timedpop(apr_queue_t *queue, void **data,
+                                             apr_interval_time_t timeout);
+
+/**
+ * returns the size of the queue.
+ *
+ * @warning this is not threadsafe, and is intended for reporting/monitoring
+ * of the queue.
+ * @param queue the queue
+ * @returns the size of the queue
+ */
+APR_DECLARE(unsigned int) apr_queue_size(apr_queue_t *queue);
+
+/**
+ * interrupt all the threads blocking on this queue.
+ *
+ * @param queue the queue
+ */
+APR_DECLARE(apr_status_t) apr_queue_interrupt_all(apr_queue_t *queue);
+
+/**
+ * terminate the queue, sending an interrupt to all the
+ * blocking threads
+ *
+ * @param queue the queue
+ */
+APR_DECLARE(apr_status_t) apr_queue_term(apr_queue_t *queue);
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
+
+#endif /* APR_HAS_THREADS */
+
+#endif /* APRQUEUE_H */
diff --git a/include/apr_random.h b/include/apr_random.h
new file mode 100644
index 00000000000..29154358dbf
--- /dev/null
+++ b/include/apr_random.h
@@ -0,0 +1,153 @@
+/* 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 APR_RANDOM_H
+#define APR_RANDOM_H
+
+/**
+ * @file apr_random.h
+ * @brief APR PRNG routines
+ */
+
+#include "apr_pools.h"
+#include "apr_thread_proc.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup apr_random PRNG Routines
+ * @ingroup APR
+ * @{
+ */
+
+typedef struct apr_crypto_hash_t apr_crypto_hash_t;
+
+typedef void apr_crypto_hash_init_t(apr_crypto_hash_t *hash);
+typedef void apr_crypto_hash_add_t(apr_crypto_hash_t *hash, const void *data,
+                                   apr_size_t bytes);
+typedef void apr_crypto_hash_finish_t(apr_crypto_hash_t *hash,
+                                      unsigned char *result);
+
+
+/* FIXME: make this opaque */
+struct apr_crypto_hash_t {
+    apr_crypto_hash_init_t *init;
+    apr_crypto_hash_add_t *add;
+    apr_crypto_hash_finish_t *finish;
+    apr_size_t size;
+    void *data;
+};
+
+/**
+ * Allocate and initialize the SHA-256 context
+ * @param p The pool to allocate from
+ */
+APR_DECLARE(apr_crypto_hash_t *) apr_crypto_sha256_new(apr_pool_t *p);
+
+/** Opaque PRNG structure. */
+typedef struct apr_random_t apr_random_t;
+
+/**
+ * Initialize a PRNG state
+ * @param g The PRNG state
+ * @param p The pool to allocate from
+ * @param pool_hash Pool hash functions
+ * @param key_hash Key hash functions
+ * @param prng_hash PRNG hash functions
+ */
+APR_DECLARE(void) apr_random_init(apr_random_t *g, apr_pool_t *p,
+                                  apr_crypto_hash_t *pool_hash,
+                                  apr_crypto_hash_t *key_hash,
+                                  apr_crypto_hash_t *prng_hash);
+/**
+ * Allocate and initialize (apr_crypto_sha256_new) a new PRNG state.
+ * @param p The pool to allocate from
+ */
+APR_DECLARE(apr_random_t *) apr_random_standard_new(apr_pool_t *p);
+
+/**
+ * Mix the randomness pools.
+ * @param g The PRNG state
+ * @param entropy_ Entropy buffer
+ * @param bytes Length of entropy_ in bytes
+ */
+APR_DECLARE(void) apr_random_add_entropy(apr_random_t *g,
+                                         const void *entropy_,
+                                         apr_size_t bytes);
+/**
+ * Generate cryptographically insecure random bytes.
+ * @param g The RNG state
+ * @param random Buffer to fill with random bytes
+ * @param bytes Length of buffer in bytes
+ */
+APR_DECLARE(apr_status_t) apr_random_insecure_bytes(apr_random_t *g,
+                                                    void *random,
+                                                    apr_size_t bytes);
+
+/**
+ * Generate cryptographically secure random bytes.
+ * @param g The RNG state
+ * @param random Buffer to fill with random bytes
+ * @param bytes Length of buffer in bytes
+ */
+APR_DECLARE(apr_status_t) apr_random_secure_bytes(apr_random_t *g,
+                                                  void *random,
+                                                  apr_size_t bytes);
+/**
+ * Ensures that E bits of conditional entropy are mixed into the PRNG
+ * before any further randomness is extracted.
+ * @param g The RNG state
+ */
+APR_DECLARE(void) apr_random_barrier(apr_random_t *g);
+
+/**
+ * Return APR_SUCCESS if the cryptographic PRNG has been seeded with
+ * enough data, APR_ENOTENOUGHENTROPY otherwise.
+ * @param r The RNG state
+ */
+APR_DECLARE(apr_status_t) apr_random_secure_ready(apr_random_t *r);
+
+/**
+ * Return APR_SUCCESS if the PRNG has been seeded with enough data,
+ * APR_ENOTENOUGHENTROPY otherwise.
+ * @param r The PRNG state
+ */
+APR_DECLARE(apr_status_t) apr_random_insecure_ready(apr_random_t *r);
+
+/**
+ * Mix the randomness pools after forking.
+ * @param proc The resulting process handle from apr_proc_fork()
+ * @remark Call this in the child after forking to mix the randomness
+ * pools. Note that its generally a bad idea to fork a process with a
+ * real PRNG in it - better to have the PRNG externally and get the
+ * randomness from there. However, if you really must do it, then you
+ * should supply all your entropy to all the PRNGs - don't worry, they
+ * won't produce the same output.
+ * @remark Note that apr_proc_fork() calls this for you, so only weird
+ * applications need ever call it themselves.
+ * @internal
+ */
+APR_DECLARE(void) apr_random_after_fork(apr_proc_t *proc);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !APR_RANDOM_H */
diff --git a/include/apr_redis.h b/include/apr_redis.h
new file mode 100644
index 00000000000..6333ae0e6be
--- /dev/null
+++ b/include/apr_redis.h
@@ -0,0 +1,459 @@
+/* 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 apr_redis.h
+ * @brief Client interface for redis
+ * @remark To use this interface you must have a separate redis
+ * for more information.
+ */
+
+#ifndef APR_REDIS_H
+#define APR_REDIS_H
+
+#include "apr.h"
+#include "apr_pools.h"
+#include "apr_time.h"
+#include "apr_strings.h"
+#include "apr_network_io.h"
+#include "apr_ring.h"
+#include "apr_buckets.h"
+#include "apr_reslist.h"
+#include "apr_hash.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#ifndef RC_DEFAULT_SERVER_PORT
+#define RC_DEFAULT_SERVER_PORT 6379
+#endif
+
+#ifndef RC_DEFAULT_SERVER_MIN
+#define RC_DEFAULT_SERVER_MIN 0
+#endif
+
+#ifndef RC_DEFAULT_SERVER_SMAX
+#define RC_DEFAULT_SERVER_SMAX 1
+#endif
+
+#ifndef RC_DEFAULT_SERVER_TTL
+#define RC_DEFAULT_SERVER_TTL 600
+#endif
+
+/**
+ * @defgroup APR_Util_RC Redis Client Routines
+ * @ingroup APR_Util
+ * @{
+ */
+
+/** Specifies the status of a redis server */
+typedef enum
+{
+    APR_RC_SERVER_LIVE, /**< Server is alive and responding to requests */
+    APR_RC_SERVER_DEAD  /**< Server is not responding to requests */
+} apr_redis_server_status_t;
+
+/** Opaque redis client connection object */
+typedef struct apr_redis_conn_t apr_redis_conn_t;
+
+/** Redis Server Info Object */
+typedef struct apr_redis_server_t apr_redis_server_t;
+struct apr_redis_server_t
+{
+    const char *host; /**< Hostname of this Server */
+    apr_port_t port; /**< Port of this Server */
+    apr_redis_server_status_t status; /**< @see apr_redis_server_status_t */
+#if APR_HAS_THREADS || defined(DOXYGEN)
+    apr_reslist_t *conns; /**< Resource list of actual client connections */
+#else
+    apr_redis_conn_t *conn;
+#endif
+    apr_pool_t *p; /** Pool to use for private allocations */
+#if APR_HAS_THREADS
+    apr_thread_mutex_t *lock;
+#endif
+    apr_time_t btime;
+    apr_uint32_t rwto;
+    struct
+    {
+        int major;
+        int minor;
+        int patch;
+        char *number;
+    } version;
+};
+
+typedef struct apr_redis_t apr_redis_t;
+
+/* Custom hash callback function prototype, user for server selection.
+* @param baton user selected baton
+* @param data data to hash
+* @param data_len length of data
+*/
+typedef apr_uint32_t (*apr_redis_hash_func)(void *baton,
+                                            const char *data,
+                                            const apr_size_t data_len);
+/* Custom Server Select callback function prototype.
+* @param baton user selected baton
+* @param rc redis instance, use rc->live_servers to select a node
+* @param hash hash of the selected key.
+*/
+typedef apr_redis_server_t* (*apr_redis_server_func)(void *baton,
+                                                 apr_redis_t *rc,
+                                                 const apr_uint32_t hash);
+
+/** Container for a set of redis servers */
+struct apr_redis_t
+{
+    apr_uint32_t flags; /**< Flags, Not currently used */
+    apr_uint16_t nalloc; /**< Number of Servers Allocated */
+    apr_uint16_t ntotal; /**< Number of Servers Added */
+    apr_redis_server_t **live_servers; /**< Array of Servers */
+    apr_pool_t *p; /** Pool to use for allocations */
+    void *hash_baton;
+    apr_redis_hash_func hash_func;
+    void *server_baton;
+    apr_redis_server_func server_func;
+};
+
+/**
+ * Creates a crc32 hash used to split keys between servers
+ * @param rc The redis client object to use
+ * @param data Data to be hashed
+ * @param data_len Length of the data to use
+ * @return crc32 hash of data
+ * @remark The crc32 hash is not compatible with old redisd clients.
+ */
+APR_DECLARE(apr_uint32_t) apr_redis_hash(apr_redis_t *rc,
+                                         const char *data,
+                                         const apr_size_t data_len);
+
+/**
+ * Pure CRC32 Hash. Used by some clients.
+ */
+APR_DECLARE(apr_uint32_t) apr_redis_hash_crc32(void *baton,
+                                               const char *data,
+                                               const apr_size_t data_len);
+
+/**
+ * hash compatible with the standard Perl Client.
+ */
+APR_DECLARE(apr_uint32_t) apr_redis_hash_default(void *baton,
+                                                 const char *data,
+                                                 const apr_size_t data_len);
+
+/**
+ * Picks a server based on a hash
+ * @param rc The redis client object to use
+ * @param hash Hashed value of a Key
+ * @return server that controls specified hash
+ * @see apr_redis_hash
+ */
+APR_DECLARE(apr_redis_server_t *) apr_redis_find_server_hash(apr_redis_t *rc,
+                                                             const apr_uint32_t hash);
+
+/**
+ * server selection compatible with the standard Perl Client.
+ */
+APR_DECLARE(apr_redis_server_t *) apr_redis_find_server_hash_default(void *baton,
+                                                                      apr_redis_t *rc,
+                                                                      const apr_uint32_t hash);
+
+/**
+ * Adds a server to a client object
+ * @param rc The redis client object to use
+ * @param server Server to add
+ * @remark Adding servers is not thread safe, and should be done once at startup.
+ * @warning Changing servers after startup may cause keys to go to
+ * different servers.
+ */
+APR_DECLARE(apr_status_t) apr_redis_add_server(apr_redis_t *rc,
+                                               apr_redis_server_t *server);
+
+
+/**
+ * Finds a Server object based on a hostname/port pair
+ * @param rc The redis client object to use
+ * @param host Hostname of the server
+ * @param port Port of the server
+ * @return Server with matching Hostname and Port, or NULL if none was found.
+ */
+APR_DECLARE(apr_redis_server_t *) apr_redis_find_server(apr_redis_t *rc,
+                                                        const char *host,
+                                                        apr_port_t port);
+
+/**
+ * Enables a Server for use again
+ * @param rc The redis client object to use
+ * @param rs Server to Activate
+ */
+APR_DECLARE(apr_status_t) apr_redis_enable_server(apr_redis_t *rc,
+                                                  apr_redis_server_t *rs);
+
+
+/**
+ * Disable a Server
+ * @param rc The redis client object to use
+ * @param rs Server to Disable
+ */
+APR_DECLARE(apr_status_t) apr_redis_disable_server(apr_redis_t *rc,
+                                                   apr_redis_server_t *rs);
+
+/**
+ * Creates a new Server Object
+ * @param p Pool to use
+ * @param host hostname of the server
+ * @param port port of the server
+ * @param min  minimum number of client sockets to open
+ * @param smax soft maximum number of client connections to open
+ * @param max  hard maximum number of client connections
+ * @param ttl  time to live in microseconds of a client connection
+ * @param rwto r/w timeout value in seconds of a client connection
+ * @param ns   location of the new server object
+ * @see apr_reslist_create
+ * @remark min, smax, and max are only used when APR_HAS_THREADS
+ */
+APR_DECLARE(apr_status_t) apr_redis_server_create(apr_pool_t *p,
+                                                  const char *host,
+                                                  apr_port_t port,
+                                                  apr_uint32_t min,
+                                                  apr_uint32_t smax,
+                                                  apr_uint32_t max,
+                                                  apr_uint32_t ttl,
+                                                  apr_uint32_t rwto,
+                                                  apr_redis_server_t **ns);
+/**
+ * Creates a new redisd client object
+ * @param p Pool to use
+ * @param max_servers maximum number of servers
+ * @param flags Not currently used
+ * @param rc   location of the new redis client object
+ */
+APR_DECLARE(apr_status_t) apr_redis_create(apr_pool_t *p,
+                                           apr_uint16_t max_servers,
+                                           apr_uint32_t flags,
+                                           apr_redis_t **rc);
+
+/**
+ * Gets a value from the server, allocating the value out of p
+ * @param rc client to use
+ * @param p Pool to use
+ * @param key null terminated string containing the key
+ * @param baton location of the allocated value
+ * @param len   length of data at baton
+ * @param flags any flags set by the client for this key
+ * @return 
+ */
+APR_DECLARE(apr_status_t) apr_redis_getp(apr_redis_t *rc,
+                                         apr_pool_t *p,
+                                         const char* key,
+                                         char **baton,
+                                         apr_size_t *len,
+                                         apr_uint16_t *flags);
+
+/**
+ * Sets a value by key on the server
+ * @param rc client to use
+ * @param key   null terminated string containing the key
+ * @param baton data to store on the server
+ * @param data_size   length of data at baton
+ * @param flags any flags set by the client for this key
+ */
+APR_DECLARE(apr_status_t) apr_redis_set(apr_redis_t *rc,
+                                        const char *key,
+                                        char *baton,
+                                        const apr_size_t data_size,
+                                        apr_uint16_t flags);
+
+/**
+ * Sets a value by key on the server
+ * @param rc client to use
+ * @param key   null terminated string containing the key
+ * @param baton data to store on the server
+ * @param data_size   length of data at baton
+ * @param timeout time in seconds for the data to live on the server
+ * @param flags any flags set by the client for this key
+ */
+APR_DECLARE(apr_status_t) apr_redis_setex(apr_redis_t *rc,
+                                          const char *key,
+                                          char *baton,
+                                          const apr_size_t data_size,
+                                          apr_uint32_t timeout,
+                                          apr_uint16_t flags);
+
+/**
+ * Deletes a key from a server
+ * @param rc client to use
+ * @param key   null terminated string containing the key
+ * @param timeout time for the delete to stop other clients from adding
+ */
+APR_DECLARE(apr_status_t) apr_redis_delete(apr_redis_t *rc,
+                                           const char *key,
+                                           apr_uint32_t timeout);
+
+/**
+ * Query a server's version
+ * @param rs    server to query
+ * @param p     Pool to allocate answer from
+ * @param baton location to store server version string
+ */
+APR_DECLARE(apr_status_t) apr_redis_version(apr_redis_server_t *rs,
+                                            apr_pool_t *p,
+                                            char **baton);
+
+/**
+ * Query a server's INFO
+ * @param rs    server to query
+ * @param p     Pool to allocate answer from
+ * @param baton location to store server INFO response string
+ */
+APR_DECLARE(apr_status_t) apr_redis_info(apr_redis_server_t *rs,
+                                         apr_pool_t *p,
+                                         char **baton);
+
+/**
+ * Increments a value
+ * @param rc client to use
+ * @param key   null terminated string containing the key
+ * @param inc     number to increment by
+ * @param new_value    new value after incrementing
+ */
+APR_DECLARE(apr_status_t) apr_redis_incr(apr_redis_t *rc,
+                                         const char *key,
+                                         apr_int32_t inc,
+                                         apr_uint32_t *new_value);
+/**
+ * Decrements a value
+ * @param rc client to use
+ * @param key   null terminated string containing the key
+ * @param inc     number to decrement by
+ * @param new_value    new value after decrementing
+ */
+APR_DECLARE(apr_status_t) apr_redis_decr(apr_redis_t *rc,
+                                         const char *key,
+                                         apr_int32_t inc,
+                                         apr_uint32_t *new_value);
+
+
+/**
+ * Pings the server
+ * @param rs Server to ping
+ */
+APR_DECLARE(apr_status_t) apr_redis_ping(apr_redis_server_t *rs);
+
+/**
+ * Gets multiple values from the server, allocating the values out of p
+ * @param rc client to use
+ * @param temp_pool Pool used for temporary allocations. May be cleared inside this
+ *        call.
+ * @param data_pool Pool used to allocate data for the returned values.
+ * @param values hash of apr_redis_value_t keyed by strings, contains the
+ *        result of the multiget call.
+ * @return
+ */
+APR_DECLARE(apr_status_t) apr_redis_multgetp(apr_redis_t *rc,
+                                             apr_pool_t *temp_pool,
+                                             apr_pool_t *data_pool,
+                                             apr_hash_t *values);
+
+typedef enum
+{
+    APR_RS_SERVER_MASTER, /**< Server is a master */
+    APR_RS_SERVER_SLAVE,  /**< Server is a slave */
+    APR_RS_SERVER_UNKNOWN  /**< Server role is unknown */
+} apr_redis_server_role_t;
+
+typedef struct
+{
+/* # Server */
+    /** Major version number of this server */
+    apr_uint32_t major;
+    /** Minor version number of this server */
+    apr_uint32_t minor;
+    /** Patch version number of this server */
+    apr_uint32_t patch;
+    /** Process id of this server process */
+    apr_uint32_t process_id;
+    /** Number of seconds this server has been running */
+    apr_uint32_t uptime_in_seconds;
+    /** Bitsize of the arch on the current machine */
+    apr_uint32_t arch_bits;
+
+/* # Clients */
+    /** Number of connected clients */
+    apr_uint32_t connected_clients;
+    /** Number of blocked clients */
+    apr_uint32_t blocked_clients;
+
+/* # Memory */
+    /** Max memory of this server */
+    apr_uint64_t maxmemory;
+    /** Amount of used memory */
+    apr_uint64_t used_memory;
+    /** Total memory available on this server */
+    apr_uint64_t total_system_memory;
+
+/* # Stats */
+    /** Total connections received */
+    apr_uint64_t total_connections_received;
+    /** Total commands processed */
+    apr_uint64_t total_commands_processed;
+    /** Total commands rejected */
+    apr_uint64_t rejected_connections;
+    /** Total net input bytes */
+    apr_uint64_t total_net_input_bytes;
+    /** Total net output bytes */
+    apr_uint64_t total_net_output_bytes;
+    /** Keyspace hits */
+    apr_uint64_t keyspace_hits;
+    /** Keyspace misses */
+    apr_uint64_t keyspace_misses;
+
+/* # Replication */
+    /** Role */
+    apr_redis_server_role_t role;
+    /** Number of connected slave */
+    apr_uint32_t connected_slaves;
+
+/* # CPU */
+    /** Accumulated CPU user time for this process */
+    apr_uint32_t used_cpu_sys;
+    /** Accumulated CPU system time for this process */
+    apr_uint32_t used_cpu_user;
+
+/* # Cluster */
+    /** Is cluster enabled */
+    apr_uint32_t cluster_enabled;
+} apr_redis_stats_t;
+
+/**
+ * Query a server for statistics
+ * @param rs    server to query
+ * @param p     Pool to allocate answer from
+ * @param stats location of the new statistics structure
+ */
+APR_DECLARE(apr_status_t) apr_redis_stats(apr_redis_server_t *rs,
+                                          apr_pool_t *p,
+                                          apr_redis_stats_t **stats);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* APR_REDIS_H */
diff --git a/include/apr_reslist.h b/include/apr_reslist.h
new file mode 100644
index 00000000000..4e09e12aacb
--- /dev/null
+++ b/include/apr_reslist.h
@@ -0,0 +1,183 @@
+/* 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 APR_RESLIST_H
+#define APR_RESLIST_H
+
+/** 
+ * @file apr_reslist.h
+ * @brief APR-UTIL Resource List Routines
+ */
+
+#include "apr.h"
+#include "apu.h"
+#include "apr_pools.h"
+#include "apr_errno.h"
+#include "apr_time.h"
+
+/**
+ * @defgroup APR_Util_RL Resource List Routines
+ * @ingroup APR
+ * @{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/** Opaque resource list object */
+typedef struct apr_reslist_t apr_reslist_t;
+
+/* Generic constructor called by resource list when it needs to create a
+ * resource.
+ * @param resource opaque resource
+ * @param params flags
+ * @param pool  Pool
+ */
+typedef apr_status_t (*apr_reslist_constructor)(void **resource, void *params,
+                                                apr_pool_t *pool);
+
+/* Generic destructor called by resource list when it needs to destroy a
+ * resource.
+ * @param resource opaque resource
+ * @param params flags
+ * @param pool  Pool
+ */
+typedef apr_status_t (*apr_reslist_destructor)(void *resource, void *params,
+                                               apr_pool_t *pool);
+
+/* Cleanup order modes */
+#define APR_RESLIST_CLEANUP_DEFAULT  0       /**< default pool cleanup */
+#define APR_RESLIST_CLEANUP_FIRST    1       /**< use pool pre cleanup */
+
+/**
+ * Create a new resource list with the following parameters:
+ * @param reslist An address where the pointer to the new resource
+ *                list will be stored.
+ * @param min Allowed minimum number of available resources. Zero
+ *            creates new resources only when needed.
+ * @param smax Resources will be destroyed during reslist maintenance to
+ *             meet this maximum restriction as they expire (reach their ttl).
+ * @param hmax Absolute maximum limit on the number of total resources.
+ * @param ttl If non-zero, sets the maximum amount of time in microseconds an
+ *            unused resource is valid.  Any resource which has exceeded this
+ *            time will be destroyed, either when encountered by
+ *            apr_reslist_acquire() or during reslist maintenance.
+ * @param con Constructor routine that is called to create a new resource.
+ * @param de Destructor routine that is called to destroy an expired resource.
+ * @param params Passed to constructor and deconstructor
+ * @param pool The pool from which to create this resource list. Also the
+ *             same pool that is passed to the constructor and destructor
+ *             routines.
+ * @remark If APR has been compiled without thread support, hmax will be
+ *         automatically set to 1 and values of min and smax will be forced to
+ *         1 for any non-zero value.
+ */
+APR_DECLARE(apr_status_t) apr_reslist_create(apr_reslist_t **reslist,
+                                             int min, int smax, int hmax,
+                                             apr_interval_time_t ttl,
+                                             apr_reslist_constructor con,
+                                             apr_reslist_destructor de,
+                                             void *params,
+                                             apr_pool_t *pool);
+
+/**
+ * Destroy the given resource list and all resources controlled by
+ * this list.
+ * FIXME: Should this block until all resources become available,
+ *        or maybe just destroy all the free ones, or maybe destroy
+ *        them even though they might be in use by something else?
+ *        Currently it will abort if there are resources that haven't
+ *        been released, so there is an assumption that all resources
+ *        have been released to the list before calling this function.
+ * @param reslist The reslist to destroy
+ */
+APR_DECLARE(apr_status_t) apr_reslist_destroy(apr_reslist_t *reslist);
+
+/**
+ * Retrieve a resource from the list, creating a new one if necessary.
+ * If we have met our maximum number of resources, we will block
+ * until one becomes available.
+ * @param reslist The resource list.
+ * @param resource An address where the pointer to the resource
+ *                will be stored.
+ */
+APR_DECLARE(apr_status_t) apr_reslist_acquire(apr_reslist_t *reslist,
+                                              void **resource);
+
+/**
+ * Return a resource back to the list of available resources.
+ * @param reslist The resource list.
+ * @param resource The resource to return to the list.
+ */
+APR_DECLARE(apr_status_t) apr_reslist_release(apr_reslist_t *reslist,
+                                              void *resource);
+
+/**
+ * Set the timeout the acquire will wait for a free resource
+ * when the maximum number of resources is exceeded.
+ * @param reslist The resource list.
+ * @param timeout Timeout to wait. The zero waits forever.
+ */
+APR_DECLARE(void) apr_reslist_timeout_set(apr_reslist_t *reslist,
+                                          apr_interval_time_t timeout);
+
+/**
+ * Return the number of outstanding resources.
+ * @param reslist The resource list.
+ */
+APR_DECLARE(apr_uint32_t) apr_reslist_acquired_count(apr_reslist_t *reslist);
+
+/**
+ * Invalidate a resource in the pool - e.g. a database connection
+ * that returns a "lost connection" error and can't be restored.
+ * Use this instead of apr_reslist_release if the resource is bad.
+ * @param reslist The resource list.
+ * @param resource The resource to invalidate.
+ */
+APR_DECLARE(apr_status_t) apr_reslist_invalidate(apr_reslist_t *reslist,
+                                                 void *resource);
+
+/**
+ * Perform routine maintenance on the resource list. This call
+ * may instantiate new resources or expire old resources.
+ * @param reslist The resource list.
+ */
+APR_DECLARE(apr_status_t) apr_reslist_maintain(apr_reslist_t *reslist);
+
+/**
+ * Set reslist cleanup order.
+ * @param reslist The resource list.
+ * @param mode Cleanup order mode
+ * <PRE>
+ *           APR_RESLIST_CLEANUP_DEFAULT  default pool cleanup order
+ *           APR_RESLIST_CLEANUP_FIRST    use pool pre cleanup
+ * </PRE>
+ * @remark If APR_RESLIST_CLEANUP_FIRST is used the destructors will
+ * be called before child pools of the pool used to create the reslist
+ * are destroyed. This allows to explicitly destroy the child pools
+ * inside reslist destructors.
+ */
+APR_DECLARE(void) apr_reslist_cleanup_order_set(apr_reslist_t *reslist,
+                                                apr_uint32_t mode);
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
+
+#endif  /* ! APR_RESLIST_H */
diff --git a/include/apr_ring.h b/include/apr_ring.h
new file mode 100644
index 00000000000..eec735fcf58
--- /dev/null
+++ b/include/apr_ring.h
@@ -0,0 +1,513 @@
+/* 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 code draws heavily from the 4.4BSD <sys/queue.h> macros
+ * and Dean Gaudet's "splim/ring.h".
+ * <http://www.freebsd.org/cgi/cvsweb.cgi/src/sys/sys/queue.h>
+ * <http://www.arctic.org/~dean/splim/>
+ *
+ * We'd use Dean's code directly if we could guarantee the
+ * availability of inline functions.
+ */
+
+#ifndef APR_RING_H
+#define APR_RING_H
+
+/**
+ * @file apr_ring.h
+ * @brief APR Rings
+ */
+
+/*
+ * for offsetof()
+ */
+#include "apr_general.h"
+
+/**
+ * @defgroup apr_ring Ring Macro Implementations
+ * @ingroup APR 
+ * A ring is a kind of doubly-linked list that can be manipulated
+ * without knowing where its head is.
+ * @{
+ */
+
+/**
+ * The Ring Element
+ *
+ * A ring element struct is linked to the other elements in the ring
+ * through its ring entry field, e.g.
+ * <pre>
+ *      struct my_element_t {
+ *          APR_RING_ENTRY(my_element_t) link;
+ *          int foo;
+ *          char *bar;
+ *      };
+ * </pre>
+ *
+ * An element struct may be put on more than one ring if it has more
+ * than one APR_RING_ENTRY field. Each APR_RING_ENTRY has a corresponding
+ * APR_RING_HEAD declaration.
+ *
+ * @warning For strict C standards compliance you should put the APR_RING_ENTRY
+ * first in the element struct unless the head is always part of a larger
+ * object with enough earlier fields to accommodate the offsetof() used
+ * to compute the ring sentinel below. You can usually ignore this caveat.
+ */
+#define APR_RING_ENTRY(elem)						\
+    struct {								\
+	struct elem * volatile next;					\
+	struct elem * volatile prev;					\
+    }
+
+/**
+ * The Ring Head
+ *
+ * Each ring is managed via its head, which is a struct declared like this:
+ * <pre>
+ *      APR_RING_HEAD(my_ring_t, my_element_t);
+ *      struct my_ring_t ring, *ringp;
+ * </pre>
+ *
+ * This struct looks just like the element link struct so that we can
+ * be sure that the typecasting games will work as expected.
+ *
+ * The first element in the ring is next after the head, and the last
+ * element is just before the head.
+ */
+#define APR_RING_HEAD(head, elem)					\
+    struct head {							\
+	struct elem * volatile next;					\
+	struct elem * volatile prev;					\
+    }
+
+/**
+ * The Ring Sentinel
+ *
+ * This is the magic pointer value that occurs before the first and
+ * after the last elements in the ring, computed from the address of
+ * the ring's head.  The head itself isn't an element, but in order to
+ * get rid of all the special cases when dealing with the ends of the
+ * ring, we play typecasting games to make it look like one.
+ *
+ * Here is a diagram to illustrate the arrangements of the next and
+ * prev pointers of each element in a single ring. Note that they point
+ * to the start of each element, not to the APR_RING_ENTRY structure.
+ *
+ * <pre>
+ *     +->+------+<-+  +->+------+<-+  +->+------+<-+
+ *     |  |struct|  |  |  |struct|  |  |  |struct|  |
+ *    /   | elem |   \/   | elem |   \/   | elem |  \
+ * ...    |      |   /\   |      |   /\   |      |   ...
+ *        +------+  |  |  +------+  |  |  +------+
+ *   ...--|prev  |  |  +--|ring  |  |  +--|prev  |
+ *        |  next|--+     | entry|--+     |  next|--...
+ *        +------+        +------+        +------+
+ *        | etc. |        | etc. |        | etc. |
+ *        :      :        :      :        :      :
+ * </pre>
+ *
+ * The APR_RING_HEAD is nothing but a bare APR_RING_ENTRY. The prev
+ * and next pointers in the first and last elements don't actually
+ * point to the head, they point to a phantom place called the
+ * sentinel. Its value is such that last->next->next == first because
+ * the offset from the sentinel to the head's next pointer is the same
+ * as the offset from the start of an element to its next pointer.
+ * This also works in the opposite direction.
+ *
+ * <pre>
+ *        last                            first
+ *     +->+------+<-+  +->sentinel<-+  +->+------+<-+
+ *     |  |struct|  |  |            |  |  |struct|  |
+ *    /   | elem |   \/              \/   | elem |  \
+ * ...    |      |   /\              /\   |      |   ...
+ *        +------+  |  |  +------+  |  |  +------+
+ *   ...--|prev  |  |  +--|ring  |  |  +--|prev  |
+ *        |  next|--+     |  head|--+     |  next|--...
+ *        +------+        +------+        +------+
+ *        | etc. |                        | etc. |
+ *        :      :                        :      :
+ * </pre>
+ *
+ * Note that the offset mentioned above is different for each kind of
+ * ring that the element may be on, and each kind of ring has a unique
+ * name for its APR_RING_ENTRY in each element, and has its own type
+ * for its APR_RING_HEAD.
+ *
+ * Note also that if the offset is non-zero (which is required if an
+ * element has more than one APR_RING_ENTRY), the unreality of the
+ * sentinel may have bad implications on very perverse implementations
+ * of C -- see the warning in APR_RING_ENTRY.
+ *
+ * @param hp   The head of the ring
+ * @param elem The name of the element struct
+ * @param link The name of the APR_RING_ENTRY in the element struct
+ */
+#define APR_RING_SENTINEL(hp, elem, link)				\
+    (struct elem *)((char *)(&(hp)->next) - APR_OFFSETOF(struct elem, link))
+
+/**
+ * The first element of the ring
+ * @param hp   The head of the ring
+ */
+#define APR_RING_FIRST(hp)	(hp)->next
+/**
+ * The last element of the ring
+ * @param hp   The head of the ring
+ */
+#define APR_RING_LAST(hp)	(hp)->prev
+/**
+ * The next element in the ring
+ * @param ep   The current element
+ * @param link The name of the APR_RING_ENTRY in the element struct
+ */
+#define APR_RING_NEXT(ep, link)	(ep)->link.next
+/**
+ * The previous element in the ring
+ * @param ep   The current element
+ * @param link The name of the APR_RING_ENTRY in the element struct
+ */
+#define APR_RING_PREV(ep, link)	(ep)->link.prev
+
+
+/**
+ * Initialize a ring
+ * @param hp   The head of the ring
+ * @param elem The name of the element struct
+ * @param link The name of the APR_RING_ENTRY in the element struct
+ */
+#define APR_RING_INIT(hp, elem, link) do {				\
+	APR_RING_FIRST((hp)) = APR_RING_SENTINEL((hp), elem, link);	\
+	APR_RING_LAST((hp))  = APR_RING_SENTINEL((hp), elem, link);	\
+    } while (0)
+
+/**
+ * Determine if a ring is empty
+ * @param hp   The head of the ring
+ * @param elem The name of the element struct
+ * @param link The name of the APR_RING_ENTRY in the element struct
+ * @return true or false
+ */
+#define APR_RING_EMPTY(hp, elem, link)					\
+    (APR_RING_FIRST((hp)) == APR_RING_SENTINEL((hp), elem, link))
+
+/**
+ * Initialize a singleton element
+ * @param ep   The element
+ * @param link The name of the APR_RING_ENTRY in the element struct
+ */
+#define APR_RING_ELEM_INIT(ep, link) do {				\
+	APR_RING_NEXT((ep), link) = (ep);				\
+	APR_RING_PREV((ep), link) = (ep);				\
+    } while (0)
+
+
+/**
+ * Splice the sequence ep1..epN into the ring before element lep
+ *   (..lep.. becomes ..ep1..epN..lep..)
+ * @warning This doesn't work for splicing before the first element or on
+ *   empty rings... see APR_RING_SPLICE_HEAD for one that does
+ * @param lep  Element in the ring to splice before
+ * @param ep1  First element in the sequence to splice in
+ * @param epN  Last element in the sequence to splice in
+ * @param link The name of the APR_RING_ENTRY in the element struct
+ */
+#define APR_RING_SPLICE_BEFORE(lep, ep1, epN, link) do {		\
+	APR_RING_NEXT((epN), link) = (lep);				\
+	APR_RING_PREV((ep1), link) = APR_RING_PREV((lep), link);	\
+	APR_RING_NEXT(APR_RING_PREV((lep), link), link) = (ep1);	\
+	APR_RING_PREV((lep), link) = (epN);				\
+    } while (0)
+
+/**
+ * Splice the sequence ep1..epN into the ring after element lep
+ *   (..lep.. becomes ..lep..ep1..epN..)
+ * @warning This doesn't work for splicing after the last element or on
+ *   empty rings... see APR_RING_SPLICE_TAIL for one that does
+ * @param lep  Element in the ring to splice after
+ * @param ep1  First element in the sequence to splice in
+ * @param epN  Last element in the sequence to splice in
+ * @param link The name of the APR_RING_ENTRY in the element struct
+ */
+#define APR_RING_SPLICE_AFTER(lep, ep1, epN, link) do {			\
+	APR_RING_PREV((ep1), link) = (lep);				\
+	APR_RING_NEXT((epN), link) = APR_RING_NEXT((lep), link);	\
+	APR_RING_PREV(APR_RING_NEXT((lep), link), link) = (epN);	\
+	APR_RING_NEXT((lep), link) = (ep1);				\
+    } while (0)
+
+/**
+ * Insert the element nep into the ring before element lep
+ *   (..lep.. becomes ..nep..lep..)
+ * @warning This doesn't work for inserting before the first element or on
+ *   empty rings... see APR_RING_INSERT_HEAD for one that does
+ * @param lep  Element in the ring to insert before
+ * @param nep  Element to insert
+ * @param link The name of the APR_RING_ENTRY in the element struct
+ */
+#define APR_RING_INSERT_BEFORE(lep, nep, link)				\
+	APR_RING_SPLICE_BEFORE((lep), (nep), (nep), link)
+
+/**
+ * Insert the element nep into the ring after element lep
+ *   (..lep.. becomes ..lep..nep..)
+ * @warning This doesn't work for inserting after the last element or on
+ *   empty rings... see APR_RING_INSERT_TAIL for one that does
+ * @param lep  Element in the ring to insert after
+ * @param nep  Element to insert
+ * @param link The name of the APR_RING_ENTRY in the element struct
+ */
+#define APR_RING_INSERT_AFTER(lep, nep, link)				\
+	APR_RING_SPLICE_AFTER((lep), (nep), (nep), link)
+
+
+/**
+ * Splice the sequence ep1..epN into the ring before the first element
+ *   (..hp.. becomes ..hp..ep1..epN..)
+ * @param hp   Head of the ring
+ * @param ep1  First element in the sequence to splice in
+ * @param epN  Last element in the sequence to splice in
+ * @param elem The name of the element struct
+ * @param link The name of the APR_RING_ENTRY in the element struct
+ */
+#define APR_RING_SPLICE_HEAD(hp, ep1, epN, elem, link)			\
+	APR_RING_SPLICE_AFTER(APR_RING_SENTINEL((hp), elem, link),	\
+			     (ep1), (epN), link)
+
+/**
+ * Splice the sequence ep1..epN into the ring after the last element
+ *   (..hp.. becomes ..ep1..epN..hp..)
+ * @param hp   Head of the ring
+ * @param ep1  First element in the sequence to splice in
+ * @param epN  Last element in the sequence to splice in
+ * @param elem The name of the element struct
+ * @param link The name of the APR_RING_ENTRY in the element struct
+ */
+#define APR_RING_SPLICE_TAIL(hp, ep1, epN, elem, link)			\
+	APR_RING_SPLICE_BEFORE(APR_RING_SENTINEL((hp), elem, link),	\
+			     (ep1), (epN), link)
+
+/**
+ * Insert the element nep into the ring before the first element
+ *   (..hp.. becomes ..hp..nep..)
+ * @param hp   Head of the ring
+ * @param nep  Element to insert
+ * @param elem The name of the element struct
+ * @param link The name of the APR_RING_ENTRY in the element struct
+ */
+#define APR_RING_INSERT_HEAD(hp, nep, elem, link)			\
+	APR_RING_SPLICE_HEAD((hp), (nep), (nep), elem, link)
+
+/**
+ * Insert the element nep into the ring after the last element
+ *   (..hp.. becomes ..nep..hp..)
+ * @param hp   Head of the ring
+ * @param nep  Element to insert
+ * @param elem The name of the element struct
+ * @param link The name of the APR_RING_ENTRY in the element struct
+ */
+#define APR_RING_INSERT_TAIL(hp, nep, elem, link)			\
+	APR_RING_SPLICE_TAIL((hp), (nep), (nep), elem, link)
+
+/**
+ * Concatenate ring h2 onto the end of ring h1, leaving h2 empty.
+ * @param h1   Head of the ring to concatenate onto
+ * @param h2   Head of the ring to concatenate
+ * @param elem The name of the element struct
+ * @param link The name of the APR_RING_ENTRY in the element struct
+ */
+#define APR_RING_CONCAT(h1, h2, elem, link) do {			\
+	if (!APR_RING_EMPTY((h2), elem, link)) {			\
+	    APR_RING_SPLICE_BEFORE(APR_RING_SENTINEL((h1), elem, link),	\
+				  APR_RING_FIRST((h2)),			\
+				  APR_RING_LAST((h2)), link);		\
+	    APR_RING_INIT((h2), elem, link);				\
+	}								\
+    } while (0)
+
+/**
+ * Prepend ring h2 onto the beginning of ring h1, leaving h2 empty.
+ * @param h1   Head of the ring to prepend onto
+ * @param h2   Head of the ring to prepend
+ * @param elem The name of the element struct
+ * @param link The name of the APR_RING_ENTRY in the element struct
+ */
+#define APR_RING_PREPEND(h1, h2, elem, link) do {			\
+	if (!APR_RING_EMPTY((h2), elem, link)) {			\
+	    APR_RING_SPLICE_AFTER(APR_RING_SENTINEL((h1), elem, link),	\
+				  APR_RING_FIRST((h2)),			\
+				  APR_RING_LAST((h2)), link);		\
+	    APR_RING_INIT((h2), elem, link);				\
+	}								\
+    } while (0)
+
+/**
+ * Unsplice a sequence of elements from a ring
+ * @warning The unspliced sequence is left with dangling pointers at either end
+ * @param ep1  First element in the sequence to unsplice
+ * @param epN  Last element in the sequence to unsplice
+ * @param link The name of the APR_RING_ENTRY in the element struct
+ */
+#define APR_RING_UNSPLICE(ep1, epN, link) do {				\
+	APR_RING_NEXT(APR_RING_PREV((ep1), link), link) =		\
+		     APR_RING_NEXT((epN), link);			\
+	APR_RING_PREV(APR_RING_NEXT((epN), link), link) =		\
+		     APR_RING_PREV((ep1), link);			\
+    } while (0)
+
+/**
+ * Remove a single element from a ring
+ * @warning The unspliced element is left with dangling pointers at either end
+ * @param ep   Element to remove
+ * @param link The name of the APR_RING_ENTRY in the element struct
+ */
+#define APR_RING_REMOVE(ep, link)					\
+    APR_RING_UNSPLICE((ep), (ep), link)
+
+/**
+ * Iterate over a ring
+ * @param ep The current element
+ * @param head The head of the ring
+ * @param elem The name of the element struct
+ * @param link The name of the APR_RING_ENTRY in the element struct
+ */
+#define APR_RING_FOREACH(ep, head, elem, link)                          \
+    for (ep = APR_RING_FIRST(head);                                     \
+         ep != APR_RING_SENTINEL(head, elem, link);                     \
+         ep = APR_RING_NEXT(ep, link))
+
+/**
+ * Iterate over a ring safe against removal of the current element
+ * @param ep1 The current element
+ * @param ep2 Iteration cursor
+ * @param head The head of the ring
+ * @param elem The name of the element struct
+ * @param link The name of the APR_RING_ENTRY in the element struct
+ */
+#define APR_RING_FOREACH_SAFE(ep1, ep2, head, elem, link)               \
+    for (ep1 = APR_RING_FIRST(head), ep2 = APR_RING_NEXT(ep1, link);    \
+         ep1 != APR_RING_SENTINEL(head, elem, link);                    \
+         ep1 = ep2, ep2 = APR_RING_NEXT(ep1, link))
+
+/* Debugging tools: */
+
+#ifdef APR_RING_DEBUG
+#include <stdio.h>
+#include <assert.h>
+
+#define APR_RING_CHECK_ONE(msg, ptr)					\
+	fprintf(stderr, "*** %s %p\n", msg, ptr)
+
+#define APR_RING_CHECK(hp, elem, link, msg)				\
+	APR_RING_CHECK_ELEM(APR_RING_SENTINEL(hp, elem, link), elem, link, msg)
+
+#define APR_RING_CHECK_ELEM(ep, elem, link, msg) do {			\
+	struct elem *start = (ep);					\
+	struct elem *here = start;					\
+	fprintf(stderr, "*** ring check start -- %s\n", msg);		\
+	do {								\
+	    fprintf(stderr, "\telem %p\n", here);			\
+	    fprintf(stderr, "\telem->next %p\n",			\
+		    APR_RING_NEXT(here, link));				\
+	    fprintf(stderr, "\telem->prev %p\n",			\
+		    APR_RING_PREV(here, link));				\
+	    fprintf(stderr, "\telem->next->prev %p\n",			\
+		    APR_RING_PREV(APR_RING_NEXT(here, link), link));	\
+	    fprintf(stderr, "\telem->prev->next %p\n",			\
+		    APR_RING_NEXT(APR_RING_PREV(here, link), link));	\
+	    if (APR_RING_PREV(APR_RING_NEXT(here, link), link) != here) { \
+		fprintf(stderr, "\t*** elem->next->prev != elem\n");	\
+		break;							\
+	    }								\
+	    if (APR_RING_NEXT(APR_RING_PREV(here, link), link) != here) { \
+		fprintf(stderr, "\t*** elem->prev->next != elem\n");	\
+		break;							\
+	    }								\
+	    here = APR_RING_NEXT(here, link);				\
+	} while (here != start);					\
+	fprintf(stderr, "*** ring check end\n");			\
+    } while (0)
+
+#define APR_RING_CHECK_CONSISTENCY(hp, elem, link)			\
+	APR_RING_CHECK_ELEM_CONSISTENCY(APR_RING_SENTINEL(hp, elem, link),\
+					elem, link)
+
+#define APR_RING_CHECK_ELEM_CONSISTENCY(ep, elem, link) do {		\
+	struct elem *start = (ep);					\
+	struct elem *here = start;					\
+	do {								\
+	    assert(APR_RING_PREV(APR_RING_NEXT(here, link), link) == here); \
+	    assert(APR_RING_NEXT(APR_RING_PREV(here, link), link) == here); \
+	    here = APR_RING_NEXT(here, link);				\
+	} while (here != start);					\
+    } while (0)
+
+#else
+/**
+ * Print a single pointer value to STDERR
+ *   (This is a no-op unless APR_RING_DEBUG is defined.)
+ * @param msg Descriptive message
+ * @param ptr Pointer value to print
+ */
+#define APR_RING_CHECK_ONE(msg, ptr)
+/**
+ * Dump all ring pointers to STDERR, starting with the head and looping all
+ * the way around the ring back to the head.  Aborts if an inconsistency
+ * is found.
+ *   (This is a no-op unless APR_RING_DEBUG is defined.)
+ * @param hp   Head of the ring
+ * @param elem The name of the element struct
+ * @param link The name of the APR_RING_ENTRY in the element struct
+ * @param msg  Descriptive message
+ */
+#define APR_RING_CHECK(hp, elem, link, msg)
+/**
+ * Loops around a ring and checks all the pointers for consistency.  Pops
+ * an assertion if any inconsistency is found.  Same idea as APR_RING_CHECK()
+ * except that it's silent if all is well.
+ *   (This is a no-op unless APR_RING_DEBUG is defined.)
+ * @param hp   Head of the ring
+ * @param elem The name of the element struct
+ * @param link The name of the APR_RING_ENTRY in the element struct
+ */
+#define APR_RING_CHECK_CONSISTENCY(hp, elem, link)
+/**
+ * Dump all ring pointers to STDERR, starting with the given element and
+ * looping all the way around the ring back to that element.  Aborts if
+ * an inconsistency is found.
+ *   (This is a no-op unless APR_RING_DEBUG is defined.)
+ * @param ep   The element
+ * @param elem The name of the element struct
+ * @param link The name of the APR_RING_ENTRY in the element struct
+ * @param msg  Descriptive message
+ */
+#define APR_RING_CHECK_ELEM(ep, elem, link, msg)
+/**
+ * Loops around a ring, starting with the given element, and checks all
+ * the pointers for consistency.  Pops an assertion if any inconsistency
+ * is found.  Same idea as APR_RING_CHECK_ELEM() except that it's silent
+ * if all is well.
+ *   (This is a no-op unless APR_RING_DEBUG is defined.)
+ * @param ep   The element
+ * @param elem The name of the element struct
+ * @param link The name of the APR_RING_ENTRY in the element struct
+ */
+#define APR_RING_CHECK_ELEM_CONSISTENCY(ep, elem, link)
+#endif
+
+/** @} */ 
+
+#endif /* !APR_RING_H */
diff --git a/include/apr_rmm.h b/include/apr_rmm.h
new file mode 100644
index 00000000000..cdb7e39d73f
--- /dev/null
+++ b/include/apr_rmm.h
@@ -0,0 +1,137 @@
+/* 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 APR_RMM_H
+#define APR_RMM_H
+/** 
+ * @file apr_rmm.h
+ * @brief APR-UTIL Relocatable Memory Management Routines
+ */
+/**
+ * @defgroup APR_Util_RMM Relocatable Memory Management Routines
+ * @ingroup APR
+ * @{
+ */
+
+#include "apr.h"
+#include "apr_pools.h"
+#include "apr_errno.h"
+#include "apu.h"
+#include "apr_anylock.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/** Structure to access Relocatable, Managed Memory */
+typedef struct apr_rmm_t apr_rmm_t;
+
+/** Fundamental allocation unit, within a specific apr_rmm_t */
+typedef apr_size_t   apr_rmm_off_t;
+
+/**
+ * Initialize a relocatable memory block to be managed by the apr_rmm API.
+ * @param rmm The relocatable memory block
+ * @param lock An apr_anylock_t of the appropriate type of lock, or NULL
+ *             if no locking is required.
+ * @param membuf The block of relocatable memory to be managed
+ * @param memsize The size of relocatable memory block to be managed
+ * @param cont The pool to use for local storage and management
+ * @remark Both @param membuf and @param memsize must be aligned
+ * (for instance using APR_ALIGN_DEFAULT).
+ */
+APR_DECLARE(apr_status_t) apr_rmm_init(apr_rmm_t **rmm, apr_anylock_t *lock,
+                                       void *membuf, apr_size_t memsize, 
+                                       apr_pool_t *cont);
+
+/**
+ * Destroy a managed memory block.
+ * @param rmm The relocatable memory block to destroy
+ */
+APR_DECLARE(apr_status_t) apr_rmm_destroy(apr_rmm_t *rmm);
+
+/**
+ * Attach to a relocatable memory block already managed by the apr_rmm API.
+ * @param rmm The relocatable memory block
+ * @param lock An apr_anylock_t of the appropriate type of lock
+ * @param membuf The block of relocatable memory already under management
+ * @param cont The pool to use for local storage and management
+ */
+APR_DECLARE(apr_status_t) apr_rmm_attach(apr_rmm_t **rmm, apr_anylock_t *lock,
+                                         void *membuf, apr_pool_t *cont);
+
+/**
+ * Detach from the managed block of memory.
+ * @param rmm The relocatable memory block to detach from
+ */
+APR_DECLARE(apr_status_t) apr_rmm_detach(apr_rmm_t *rmm);
+
+/**
+ * Allocate memory from the block of relocatable memory.
+ * @param rmm The relocatable memory block
+ * @param reqsize How much memory to allocate
+ */
+APR_DECLARE(apr_rmm_off_t) apr_rmm_malloc(apr_rmm_t *rmm, apr_size_t reqsize);
+
+/**
+ * Realloc memory from the block of relocatable memory.
+ * @param rmm The relocatable memory block
+ * @param entity The memory allocation to realloc
+ * @param reqsize The new size
+ */
+APR_DECLARE(apr_rmm_off_t) apr_rmm_realloc(apr_rmm_t *rmm, void *entity, apr_size_t reqsize);
+
+/**
+ * Allocate memory from the block of relocatable memory and initialize it to zero.
+ * @param rmm The relocatable memory block
+ * @param reqsize How much memory to allocate
+ */
+APR_DECLARE(apr_rmm_off_t) apr_rmm_calloc(apr_rmm_t *rmm, apr_size_t reqsize);
+
+/**
+ * Free allocation returned by apr_rmm_malloc or apr_rmm_calloc.
+ * @param rmm The relocatable memory block
+ * @param entity The memory allocation to free
+ */
+APR_DECLARE(apr_status_t) apr_rmm_free(apr_rmm_t *rmm, apr_rmm_off_t entity);
+
+/**
+ * Retrieve the physical address of a relocatable allocation of memory
+ * @param rmm The relocatable memory block
+ * @param entity The memory allocation to free
+ * @return address The address, aligned with APR_ALIGN_DEFAULT.
+ */
+APR_DECLARE(void *) apr_rmm_addr_get(apr_rmm_t *rmm, apr_rmm_off_t entity);
+
+/**
+ * Compute the offset of a relocatable allocation of memory
+ * @param rmm The relocatable memory block
+ * @param entity The physical address to convert to an offset
+ */
+APR_DECLARE(apr_rmm_off_t) apr_rmm_offset_get(apr_rmm_t *rmm, void *entity);
+
+/**
+ * Compute the required overallocation of memory needed to fit n allocs
+ * @param n The number of alloc/calloc regions desired
+ */
+APR_DECLARE(apr_size_t) apr_rmm_overhead_get(int n);
+
+#ifdef __cplusplus
+}
+#endif
+/** @} */
+#endif  /* ! APR_RMM_H */
+
diff --git a/include/apr_sdbm.h b/include/apr_sdbm.h
new file mode 100644
index 00000000000..632ee2386c3
--- /dev/null
+++ b/include/apr_sdbm.h
@@ -0,0 +1,177 @@
+/* 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.
+ */
+
+/*
+ * sdbm - ndbm work-alike hashed database library
+ * based on Per-Ake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
+ * author: oz@nexus.yorku.ca
+ * status: ex-public domain
+ */
+
+#ifndef APR_SDBM_H
+#define APR_SDBM_H
+
+#include "apu.h"
+#include "apr_errno.h"
+#include "apr_file_io.h"   /* for apr_fileperms_t */
+
+/** 
+ * @file apr_sdbm.h
+ * @brief apr-util SDBM library
+ */
+/**
+ * @defgroup APR_Util_DBM_SDBM SDBM library
+ * @ingroup APR_Util_DBM
+ * @{
+ */
+
+/**
+ * Structure for referencing an sdbm
+ */
+typedef struct apr_sdbm_t apr_sdbm_t;
+
+/**
+ * Structure for referencing the datum record within an sdbm
+ */
+typedef struct {
+    /** pointer to the data stored/retrieved */
+    char *dptr;
+    /** size of data */
+    /* apr_ssize_t for release 2.0??? */
+    int dsize;
+} apr_sdbm_datum_t;
+
+/* The extensions used for the database files */
+/** SDBM Directory file extension */
+#define APR_SDBM_DIRFEXT	".dir"
+/** SDBM page file extension */
+#define APR_SDBM_PAGFEXT	".pag"
+
+/* flags to sdbm_store */
+#define APR_SDBM_INSERT     0   /**< Insert */
+#define APR_SDBM_REPLACE    1   /**< Replace */
+#define APR_SDBM_INSERTDUP  2   /**< Insert with duplicates */
+
+/**
+ * Open an sdbm database by file name
+ * @param db The newly opened database
+ * @param name The sdbm file to open
+ * @param mode The flag values (APR_FOPEN_READ and APR_FOPEN_BINARY flags are
+ * implicit)
+ * <PRE>
+ *           APR_FOPEN_WRITE      open for read-write access
+ *           APR_FOPEN_CREATE     create the sdbm if it does not exist
+ *           APR_FOPEN_TRUNCATE   empty the contents of the sdbm
+ *           APR_FOPEN_EXCL       fail for APR_FOPEN_CREATE if the file exists
+ *           APR_FOPEN_DELONCLOSE delete the sdbm when closed
+ *           APR_FOPEN_SHARELOCK  support locking across process/machines
+ * </PRE>
+ * @param perms Permissions to apply to if created
+ * @param p The pool to use when creating the sdbm
+ * @remark The sdbm name is not a true file name, as sdbm appends suffixes 
+ * for seperate data and index files.
+ */
+APR_DECLARE(apr_status_t) apr_sdbm_open(apr_sdbm_t **db, const char *name, 
+                                        apr_int32_t mode, 
+                                        apr_fileperms_t perms, apr_pool_t *p);
+
+/**
+ * Close an sdbm file previously opened by apr_sdbm_open
+ * @param db The database to close
+ */
+APR_DECLARE(apr_status_t) apr_sdbm_close(apr_sdbm_t *db);
+
+/**
+ * Lock an sdbm database for concurency of multiple operations
+ * @param db The database to lock
+ * @param type The lock type
+ * <PRE>
+ *           APR_FLOCK_SHARED
+ *           APR_FLOCK_EXCLUSIVE
+ * </PRE>
+ * @remark Calls to apr_sdbm_lock may be nested.  All apr_sdbm functions
+ * perform implicit locking.  Since an APR_FLOCK_SHARED lock cannot be 
+ * portably promoted to an APR_FLOCK_EXCLUSIVE lock, apr_sdbm_store and 
+ * apr_sdbm_delete calls will fail if an APR_FLOCK_SHARED lock is held.
+ * The apr_sdbm_lock call requires the database to be opened with the
+ * APR_FOPEN_SHARELOCK mode value.
+ */
+APR_DECLARE(apr_status_t) apr_sdbm_lock(apr_sdbm_t *db, int type);
+
+/**
+ * Release an sdbm lock previously aquired by apr_sdbm_lock
+ * @param db The database to unlock
+ */
+APR_DECLARE(apr_status_t) apr_sdbm_unlock(apr_sdbm_t *db);
+
+/**
+ * Fetch an sdbm record value by key
+ * @param db The database 
+ * @param value The value datum retrieved for this record
+ * @param key The key datum to find this record
+ */
+APR_DECLARE(apr_status_t) apr_sdbm_fetch(apr_sdbm_t *db, 
+                                         apr_sdbm_datum_t *value, 
+                                         apr_sdbm_datum_t key);
+
+/**
+ * Store an sdbm record value by key
+ * @param db The database 
+ * @param key The key datum to store this record by
+ * @param value The value datum to store in this record
+ * @param opt The method used to store the record
+ * <PRE>
+ *           APR_SDBM_INSERT     return an error if the record exists
+ *           APR_SDBM_REPLACE    overwrite any existing record for key
+ * </PRE>
+ */
+APR_DECLARE(apr_status_t) apr_sdbm_store(apr_sdbm_t *db, apr_sdbm_datum_t key,
+                                         apr_sdbm_datum_t value, int opt);
+
+/**
+ * Delete an sdbm record value by key
+ * @param db The database 
+ * @param key The key datum of the record to delete
+ * @remark It is not an error to delete a non-existent record.
+ */
+APR_DECLARE(apr_status_t) apr_sdbm_delete(apr_sdbm_t *db, 
+                                          const apr_sdbm_datum_t key);
+
+/**
+ * Retrieve the first record key from a dbm
+ * @param db The database 
+ * @param key The key datum of the first record
+ * @remark The keys returned are not ordered.  To traverse the list of keys
+ * for an sdbm opened with APR_FOPEN_SHARELOCK, the caller must use apr_sdbm_lock
+ * prior to retrieving the first record, and hold the lock until after the
+ * last call to apr_sdbm_nextkey.
+ */
+APR_DECLARE(apr_status_t) apr_sdbm_firstkey(apr_sdbm_t *db, apr_sdbm_datum_t *key);
+
+/**
+ * Retrieve the next record key from an sdbm
+ * @param db The database 
+ * @param key The key datum of the next record
+ */
+APR_DECLARE(apr_status_t) apr_sdbm_nextkey(apr_sdbm_t *db, apr_sdbm_datum_t *key);
+
+/**
+ * Returns true if the sdbm database opened for read-only access
+ * @param db The database to test
+ */
+APR_DECLARE(int) apr_sdbm_rdonly(apr_sdbm_t *db);
+/** @} */
+#endif /* APR_SDBM_H */
diff --git a/include/apr_sha1.h b/include/apr_sha1.h
new file mode 100644
index 00000000000..c7ba3cf3cbf
--- /dev/null
+++ b/include/apr_sha1.h
@@ -0,0 +1,121 @@
+/* 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.
+ */
+/* NIST Secure Hash Algorithm
+ * 	heavily modified by Uwe Hollerbach uh@alumni.caltech edu
+ * 	from Peter C. Gutmann's implementation as found in
+ * 	Applied Cryptography by Bruce Schneier
+ * 	This code is hereby placed in the public domain
+ */
+
+#ifndef APR_SHA1_H
+#define APR_SHA1_H
+
+#include "apu.h"
+#include "apr_general.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @file apr_sha1.h
+ * @brief APR-UTIL SHA1 library
+ */
+
+/** size of the SHA1 DIGEST */
+#define APR_SHA1_DIGESTSIZE 20
+
+/**
+ * Define the Magic String prefix that identifies a password as being
+ * hashed using our algorithm.
+ */
+#define APR_SHA1PW_ID "{SHA}"
+
+/** length of the SHA Password */
+#define APR_SHA1PW_IDLEN 5
+
+/** @see apr_sha1_ctx_t */
+typedef struct apr_sha1_ctx_t apr_sha1_ctx_t;
+
+/** 
+ * SHA1 context structure
+ */
+struct apr_sha1_ctx_t {
+    /** message digest */
+    apr_uint32_t digest[5];
+    /** 64-bit bit counts */
+    apr_uint32_t count_lo, count_hi;
+    /** SHA data buffer */
+    apr_uint32_t data[16];
+    /** unprocessed amount in data */
+    int local;
+};
+
+/**
+ * Provide a means to SHA1 crypt/encode a plaintext password in a way which
+ * makes password file compatible with those commonly use in netscape web
+ * and ldap installations.
+ * @param clear The plaintext password
+ * @param len The length of the plaintext password
+ * @param out The encrypted/encoded password
+ * @note SHA1 support is useful for migration purposes, but is less
+ *     secure than Apache's password format, since Apache's (MD5)
+ *     password format uses a random eight character salt to generate
+ *     one of many possible hashes for the same password.  Netscape
+ *     uses plain SHA1 without a salt, so the same password
+ *     will always generate the same hash, making it easier
+ *     to break since the search space is smaller.
+ */
+APR_DECLARE(void) apr_sha1_base64(const char *clear, int len, char *out);
+
+/**
+ * Initialize the SHA digest
+ * @param context The SHA context to initialize
+ */
+APR_DECLARE(void) apr_sha1_init(apr_sha1_ctx_t *context);
+
+/**
+ * Update the SHA digest
+ * @param context The SHA1 context to update
+ * @param input The buffer to add to the SHA digest
+ * @param inputLen The length of the input buffer
+ */
+APR_DECLARE(void) apr_sha1_update(apr_sha1_ctx_t *context, const char *input,
+                                unsigned int inputLen);
+
+/**
+ * Update the SHA digest with binary data
+ * @param context The SHA1 context to update
+ * @param input The buffer to add to the SHA digest
+ * @param inputLen The length of the input buffer
+ */
+APR_DECLARE(void) apr_sha1_update_binary(apr_sha1_ctx_t *context,
+                                       const unsigned char *input,
+                                       unsigned int inputLen);
+
+/**
+ * Finish computing the SHA digest
+ * @param digest the output buffer in which to store the digest
+ * @param context The context to finalize
+ */
+APR_DECLARE(void) apr_sha1_final(unsigned char digest[APR_SHA1_DIGESTSIZE],
+                               apr_sha1_ctx_t *context);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* APR_SHA1_H */
diff --git a/include/apr_shm.h b/include/apr_shm.h
new file mode 100644
index 00000000000..635c654b17f
--- /dev/null
+++ b/include/apr_shm.h
@@ -0,0 +1,229 @@
+/* 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 APR_SHM_H
+#define APR_SHM_H
+
+/**
+ * @file apr_shm.h
+ * @brief APR Shared Memory Routines
+ */
+
+#include "apr.h"
+#include "apr_pools.h"
+#include "apr_errno.h"
+#include "apr_perms_set.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup apr_shm Shared Memory Routines
+ * @ingroup APR 
+ * @{
+ */
+
+/**
+ * Private, platform-specific data struture representing a shared memory
+ * segment.
+ */
+typedef struct apr_shm_t apr_shm_t;
+
+/**
+ * Create and make accessible a shared memory segment with default
+ * properties.
+ * @param m The shared memory structure to create.
+ * @param reqsize The desired size of the segment.
+ * @param filename The file to use for shared memory on platforms that
+ *        require it.
+ * @param pool the pool from which to allocate the shared memory
+ *        structure.
+ * @remark A note about Anonymous vs. Named shared memory segments:
+ *         Not all plaforms support anonymous shared memory segments, but in
+ *         some cases it is prefered over other types of shared memory
+ *         implementations. Passing a NULL 'file' parameter to this function
+ *         will cause the subsystem to use anonymous shared memory segments.
+ *         If such a system is not available, APR_ENOTIMPL is returned.
+ * @remark A note about allocation sizes:
+ *         On some platforms it is necessary to store some metainformation
+ *         about the segment within the actual segment. In order to supply
+ *         the caller with the requested size it may be necessary for the
+ *         implementation to request a slightly greater segment length
+ *         from the subsystem. In all cases, the apr_shm_baseaddr_get()
+ *         function will return the first usable byte of memory.
+ * 
+ */
+APR_DECLARE(apr_status_t) apr_shm_create(apr_shm_t **m,
+                                         apr_size_t reqsize,
+                                         const char *filename,
+                                         apr_pool_t *pool);
+
+/**
+ * Special processing flags for apr_shm_create_ex() and apr_shm_attach_ex().
+ */
+#define APR_SHM_NS_LOCAL    1 /* Create or attach to named shared memory
+                               * segment in the "Local" namespace on
+                               * Windows.  (Ignored on other platforms.)
+                               * By default, the "Global" namespace is
+                               * used for privileged processes and the
+                               * "Local" namespace is used otherwise.
+                               */
+#define APR_SHM_NS_GLOBAL   2 /* Create or attach to named shared memory
+                               * segment in the "Global" namespace on
+                               * Windows.  (Ignored on other platforms.)
+                               */
+
+/**
+ * Create and make accessible a shared memory segment with platform-
+ * specific processing.
+ * @param m The shared memory structure to create.
+ * @param reqsize The desired size of the segment.
+ * @param filename The file to use for shared memory on platforms that
+ *        require it.
+ * @param pool the pool from which to allocate the shared memory
+ *        structure.
+ * @param flags mask of APR_SHM_* (defined above)
+ * @remark A note about Anonymous vs. Named shared memory segments:
+ *         Not all plaforms support anonymous shared memory segments, but in
+ *         some cases it is prefered over other types of shared memory
+ *         implementations. Passing a NULL 'file' parameter to this function
+ *         will cause the subsystem to use anonymous shared memory segments.
+ *         If such a system is not available, APR_ENOTIMPL is returned.
+ * @remark A note about allocation sizes:
+ *         On some platforms it is necessary to store some metainformation
+ *         about the segment within the actual segment. In order to supply
+ *         the caller with the requested size it may be necessary for the
+ *         implementation to request a slightly greater segment length
+ *         from the subsystem. In all cases, the apr_shm_baseaddr_get()
+ *         function will return the first usable byte of memory.
+ * 
+ */
+APR_DECLARE(apr_status_t) apr_shm_create_ex(apr_shm_t **m,
+                                            apr_size_t reqsize,
+                                            const char *filename,
+                                            apr_pool_t *pool,
+                                            apr_int32_t flags);
+
+/**
+ * Remove named resource associated with a shared memory segment,
+ * preventing attachments to the resource, but not destroying it.
+ * @param filename The filename associated with shared-memory segment which
+ *        needs to be removed
+ * @param pool The pool used for file operations
+ * @remark This function is only supported on platforms which support
+ * name-based shared memory segments, and will return APR_ENOTIMPL on
+ * platforms without such support.  Removing the file while the shm
+ * is in use is not entirely portable, caller may use this to enhance
+ * obscurity of the resource, but be prepared for the call to fail,
+ * and for concurrent attempts to create a resource of the same name
+ * to also fail.  The pool cleanup of apr_shm_create (apr_shm_destroy)
+ * also removes the named resource.
+ */
+APR_DECLARE(apr_status_t) apr_shm_remove(const char *filename,
+                                         apr_pool_t *pool);
+
+/**
+ * Delete named resource associated with a shared memory segment,
+ * preventing attachments to the resource.
+ * @param m The shared memory segment structure to delete.
+ * @remark This function is only supported on platforms which support
+ * name-based shared memory segments, and will return APR_ENOTIMPL on
+ * platforms without such support.  Removing the file while the shm
+ * is in use is not entirely portable, caller may use this to enhance
+ * obscurity of the resource, but be prepared for the call to fail,
+ * and for concurrent attempts to create a resource of the same name
+ * to also fail.  The pool cleanup of apr_shm_create (apr_shm_destroy)
+ * also removes the named resource.
+ */
+APR_DECLARE(apr_status_t) apr_shm_delete(apr_shm_t *m);
+
+/**
+ * Destroy a shared memory segment and associated memory.
+ * @param m The shared memory segment structure to destroy.
+ */
+APR_DECLARE(apr_status_t) apr_shm_destroy(apr_shm_t *m);
+
+/**
+ * Attach to a shared memory segment that was created
+ * by another process.
+ * @param m The shared memory structure to create.
+ * @param filename The file used to create the original segment.
+ *        (This MUST match the original filename.)
+ * @param pool the pool from which to allocate the shared memory
+ *        structure for this process.
+ */
+APR_DECLARE(apr_status_t) apr_shm_attach(apr_shm_t **m,
+                                         const char *filename,
+                                         apr_pool_t *pool);
+
+/**
+ * Attach to a shared memory segment that was created
+ * by another process, with platform-specific processing.
+ * @param m The shared memory structure to create.
+ * @param filename The file used to create the original segment.
+ *        (This MUST match the original filename.)
+ * @param pool the pool from which to allocate the shared memory
+ *        structure for this process.
+ * @param flags mask of APR_SHM_* (defined above)
+ */
+APR_DECLARE(apr_status_t) apr_shm_attach_ex(apr_shm_t **m,
+                                            const char *filename,
+                                            apr_pool_t *pool,
+                                            apr_int32_t flags);
+
+/**
+ * Detach from a shared memory segment without destroying it.
+ * @param m The shared memory structure representing the segment
+ *        to detach from.
+ */
+APR_DECLARE(apr_status_t) apr_shm_detach(apr_shm_t *m);
+
+/**
+ * Retrieve the base address of the shared memory segment.
+ * NOTE: This address is only usable within the callers address
+ * space, since this API does not guarantee that other attaching
+ * processes will maintain the same address mapping.
+ * @param m The shared memory segment from which to retrieve
+ *        the base address.
+ * @return address, aligned by APR_ALIGN_DEFAULT.
+ */
+APR_DECLARE(void *) apr_shm_baseaddr_get(const apr_shm_t *m);
+
+/**
+ * Retrieve the length of a shared memory segment in bytes.
+ * @param m The shared memory segment from which to retrieve
+ *        the segment length.
+ */
+APR_DECLARE(apr_size_t) apr_shm_size_get(const apr_shm_t *m);
+
+/**
+ * Set shared memory permissions.
+ */
+APR_PERMS_SET_IMPLEMENT(shm);
+
+/**
+ * Get the pool used by this shared memory segment.
+ */
+APR_POOL_DECLARE_ACCESSOR(shm);
+
+/** @} */ 
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* APR_SHM_T */
diff --git a/include/apr_shmem.h b/include/apr_shmem.h
deleted file mode 100644
index 47cf5944fe4..00000000000
--- a/include/apr_shmem.h
+++ /dev/null
@@ -1,213 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef APR_SHMEM_H
-#define APR_SHMEM_H
-
-#include "apr.h"
-#include "apr_general.h"
-#include "apr_errno.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-#if APR_USES_ANONYMOUS_SHM
-typedef   void           ap_shm_name_t;
-#elif APR_USES_FILEBASED_SHM
-typedef   char *         ap_shm_name_t;
-#elif APR_USES_KEYBASED_SHM
-typedef   key_t          ap_shm_name_t;
-#endif
-
-typedef   struct shmem_t ap_shmem_t;
-
-/*
-
-=head1 ap_status_t ap_shm_init(ap_shmem_t *m, ap_size_t reqsize, char *file)
-
-B<Create a pool of shared memory for use later.>
-
-    arg 1) The shared memory block.
-    arg 2) The size of the shared memory pool.
-    arg 3) The file to use for the shared memory on platforms that
-           require it.
-    arg 4) The pool to use
-
-=cut
- */
-ap_status_t ap_shm_init(ap_shmem_t **m, ap_size_t reqsize, const char *file, ap_pool_t *cont);
-
-/*
-
-=head1 ap_status_t ap_shm_destroy(ap_shmem_t *m)
-
-B<Destroy the shared memory block.>
-
-    arg 1) The shared memory block to destroy. 
-
-=cut
- */
-ap_status_t ap_shm_destroy(ap_shmem_t *m);
-
-/*
-
-=head1 ap_status_t ap_shm_malloc(ap_shmem_t *c, ap_size_t reqsize)
-
-B<allocate memory from the block of shared memory.>
-
-    arg 1) The shared memory block to destroy. 
-    arg 2) How much memory to allocate
-
-=cut
- */
-void *ap_shm_malloc(ap_shmem_t *c, ap_size_t reqsize);
-
-/*
-
-=head1 void *ap_shm_calloc(ap_shmem_t *shared, ap_size_t size)
-
-B<allocate memory from the block of shared memory and initialize it to zero.>
-
-    arg 1) The shared memory block to destroy. 
-    arg 2) How much memory to allocate
-
-=cut
- */
-void *ap_shm_calloc(ap_shmem_t *shared, ap_size_t size);
-
-/*
-
-=head1 ap_status_t ap_shm_free(ap_shmem_t *shared, void *entity)
-
-B<free shared memory previously allocated.>
-
-    arg 1) The shared memory block to destroy. 
-
-=cut
- */
-ap_status_t ap_shm_free(ap_shmem_t *shared, void *free);
-
-/*
-
-=head1 ap_status_t ap_get_shm_name(ap_shmem_t *c, ap_shm_name_t **name)
-
-B<Get the name of the shared memory segment if not using anonymous shared memory.>
-
-    arg 1)  The shared memory block to destroy. 
-    arg 2)  The name of the shared memory block, NULL if anonymous 
-            shared memory.
-   return) APR_USES_ANONYMOUS_SHM if we are using anonymous shared
-           memory.  APR_USES_FILEBASED_SHM if our shared memory is
-           based on file access.  APR_USES_KEYBASED_SHM if shared
-           memory is based on a key value such as shmctl.  If the
-           shared memory is anonymous, the name is NULL.
-
-=cut
- */
-ap_status_t ap_get_shm_name(ap_shmem_t *c, ap_shm_name_t **name);
-
-/*
-
-=head1 ap_status_t ap_set_shm_name(ap_shmem_t *c, ap_shm_name_t *name)
-
-B<Set the name of the shared memory segment if not using
-anonymous shared memory.>  This is to allow processes to open
-shared memory created by another process.
-
-    arg 1)  The shared memory block to destroy. 
-    arg 2)  The name of the shared memory block, NULL if anonymous 
-            shared memory.
-   return) APR_USES_ANONYMOUS_SHM if we are using anonymous shared
-           memory.  APR_SUCCESS if we are using named shared memory
-           and we were able to assign the name correctly. 
-
-=cut
- */
-ap_status_t ap_set_shm_name(ap_shmem_t *c, ap_shm_name_t *name);
-
-/*
-
-=head1 ap_status_t ap_open_shmem(ap_shmem_t *c)
-
-B<Open the shared memory block in a child process.> 
-
-    arg 1)  The shared memory block to open in the child. 
-   return) This should be called after ap_set_shm_name.  The ap_shmem_t 
-           variable must refer to the memory segment to open.
-
-=cut
- */
-ap_status_t ap_open_shmem(ap_shmem_t *c);
-
-/*
-
-=head1 ap_status_t ap_shm_avail(ap_shmem_t *c, ap_size_t *size)
-
-B<Determine how much memory is available in the specified shared memory block>
-
-    arg 1)  The shared memory block to open in the child. 
-    arg 2)  The amount of space available in the shared memory block.
-
-=cut
- */
-ap_status_t ap_shm_avail(ap_shmem_t *c, ap_size_t *avail);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif  /* ! APR_FILE_IO_H */
-
-
diff --git a/include/apr_signal.h b/include/apr_signal.h
index 34f02ce3737..20631333023 100644
--- a/include/apr_signal.h
+++ b/include/apr_signal.h
@@ -1,73 +1,109 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 APR_SIGNAL_H
 #define APR_SIGNAL_H
 
-#include "apr_general.h"
-#include "apr_errno.h"
+/**
+ * @file apr_signal.h
+ * @brief APR Signal Handling
+ */
+
+#include "apr.h"
+#include "apr_pools.h"
+
+#if APR_HAVE_SIGNAL_H
+#include <signal.h>
+#endif
 
 #ifdef __cplusplus
 extern "C" {
 #endif /* __cplusplus */
 
-typedef int ap_signum_t;
+/**
+ * @defgroup apr_signal Signal Handling
+ * @ingroup APR
+ * @{
+ */
 
-#ifdef __cplusplus
-}
+#if APR_HAVE_SIGACTION || defined(DOXYGEN)
+
+#if defined(DARWIN) && !defined(__cplusplus) && !defined(_ANSI_SOURCE)
+/* work around Darwin header file bugs
+ *   http://www.opensource.apple.com/bugs/X/BSD%20Kernel/2657228.html
+ */
+#undef SIG_DFL
+#undef SIG_IGN
+#undef SIG_ERR
+#define SIG_DFL (void (*)(int))0
+#define SIG_IGN (void (*)(int))1
+#define SIG_ERR (void (*)(int))-1
 #endif
 
-#endif  /* ! APR_SIGNAL_H */
+/** Function prototype for signal handlers */
+typedef void apr_sigfunc_t(int);
+
+/**
+ * Set the signal handler function for a given signal
+ * @param signo The signal (eg... SIGWINCH)
+ * @param func the function to get called
+ */
+APR_DECLARE(apr_sigfunc_t *) apr_signal(int signo, apr_sigfunc_t * func);
 
+#if defined(SIG_IGN) && !defined(SIG_ERR)
+#define SIG_ERR ((apr_sigfunc_t *) -1)
+#endif
+
+#else /* !APR_HAVE_SIGACTION */
+#define apr_signal(a, b) signal(a, b)
+#endif
+
+
+/**
+ * Get the description for a specific signal number
+ * @param signum The signal number
+ * @return The description of the signal
+ */
+APR_DECLARE(const char *) apr_signal_description_get(int signum);
+
+/**
+ * APR-private function for initializing the signal package
+ * @internal
+ * @param pglobal The internal, global pool
+ */
+void apr_signal_init(apr_pool_t *pglobal);
+
+/**
+ * Block the delivery of a particular signal
+ * @param signum The signal number
+ * @return status
+ */
+APR_DECLARE(apr_status_t) apr_signal_block(int signum);
+
+/**
+ * Enable the delivery of a particular signal
+ * @param signum The signal number
+ * @return status
+ */
+APR_DECLARE(apr_status_t) apr_signal_unblock(int signum);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
 
+#endif /* APR_SIGNAL_H */
diff --git a/include/apr_siphash.h b/include/apr_siphash.h
new file mode 100644
index 00000000000..d25498bfaf0
--- /dev/null
+++ b/include/apr_siphash.h
@@ -0,0 +1,147 @@
+/* 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.
+ */
+/*
+   SipHash reference C implementation
+   Copyright (c) 2012-2014 Jean-Philippe Aumasson
+   <jeanphilippe.aumasson@gmail.com>
+   Copyright (c) 2012-2014 Daniel J. Bernstein <djb@cr.yp.to>
+   To the extent possible under law, the author(s) have dedicated all copyright
+   and related and neighboring rights to this software to the public domain
+   worldwide. This software is distributed without any warranty.
+   You should have received a copy of the CC0 Public Domain Dedication along
+   with this software. If not, see
+   <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#ifndef APR_SIPHASH_H
+#define APR_SIPHASH_H
+
+#include "apr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @file apr_siphash.h
+ * @brief APR-UTIL siphash library
+ *        "SipHash-c-d is a family of pseudorandom functions (a.k.a. keyed
+ *        hash functions) optimized for speed on short messages", designed by
+ *        Jean-Philippe Aumasson and Daniel J. Bernstein. It generates a 64bit
+ *        hash (or MAC) from the message and a 128bit key.
+ *        See http://cr.yp.to/siphash/siphash-20120620.pdf for the details,
+ *        c is the number of compression rounds, d the number of finalization
+ *        rounds; we also define fast implementations for c = 2 with d = 4 (aka
+ *        siphash-2-4), and c = 4 with d = 8 (aka siphash-4-8), as recommended
+ *        parameters per the authors.
+ */
+
+/** size of the siphash digest */
+#define APR_SIPHASH_DSIZE 8
+
+/** size of the siphash key */
+#define APR_SIPHASH_KSIZE 16
+
+
+/**
+ * @brief Computes SipHash-c-d, producing a 64bit (APR_SIPHASH_DSIZE) hash
+ * from a message and a 128bit (APR_SIPHASH_KSIZE) secret key.
+ * @param src The message
+ * @param len The length of the message
+ * @param key The secret key
+ * @param c   The number of compression rounds
+ * @param d   The number of finalization rounds
+ * @return The hash value as a 64bit unsigned integer
+ */
+APR_DECLARE(apr_uint64_t) apr_siphash(const void *src, apr_size_t len,
+                              const unsigned char key[APR_SIPHASH_KSIZE],
+                                      unsigned int c, unsigned int d);
+
+/**
+ * @brief Computes SipHash-c-d, producing a 64bit (APR_SIPHASH_DSIZE) hash
+ * from a message and a 128bit (APR_SIPHASH_KSIZE) secret key, into a possibly
+ * unaligned buffer (using the little endian representation as defined by the
+ * authors for interoperabilty) usable as a MAC.
+ * @param out The output buffer (or MAC)
+ * @param src The message
+ * @param len The length of the message
+ * @param key The secret key
+ * @param c   The number of compression rounds
+ * @param d   The number of finalization rounds
+ * @return The hash value as a 64bit unsigned integer
+ */
+APR_DECLARE(void) apr_siphash_auth(unsigned char out[APR_SIPHASH_DSIZE],
+                                   const void *src, apr_size_t len,
+                             const unsigned char key[APR_SIPHASH_KSIZE],
+                                   unsigned int c, unsigned int d);
+
+/**
+ * @brief Computes SipHash-2-4, producing a 64bit (APR_SIPHASH_DSIZE) hash
+ * from a message and a 128bit (APR_SIPHASH_KSIZE) secret key.
+ * @param src The message to hash
+ * @param len The length of the message
+ * @param key The secret key
+ * @return The hash value as a 64bit unsigned integer
+ */
+APR_DECLARE(apr_uint64_t) apr_siphash24(const void *src, apr_size_t len,
+                               const unsigned char key[APR_SIPHASH_KSIZE]);
+
+/**
+ * @brief Computes SipHash-2-4, producing a 64bit (APR_SIPHASH_DSIZE) hash
+ * from a message and a 128bit (APR_SIPHASH_KSIZE) secret key, into a possibly
+ * unaligned buffer (using the little endian representation as defined by the
+ * authors for interoperabilty) usable as a MAC.
+ * @param out The output buffer (or MAC)
+ * @param src The message
+ * @param len The length of the message
+ * @param key The secret key
+ * @return The hash value as a 64bit unsigned integer
+ */
+APR_DECLARE(void) apr_siphash24_auth(unsigned char out[APR_SIPHASH_DSIZE],
+                                     const void *src, apr_size_t len,
+                               const unsigned char key[APR_SIPHASH_KSIZE]);
+
+/**
+ * @brief Computes SipHash-4-8, producing a 64bit (APR_SIPHASH_DSIZE) hash
+ * from a message and a 128bit (APR_SIPHASH_KSIZE) secret key.
+ * @param src The message
+ * @param len The length of the message
+ * @param key The secret key
+ * @return The hash value as a 64bit unsigned integer
+ */
+APR_DECLARE(apr_uint64_t) apr_siphash48(const void *src, apr_size_t len,
+                               const unsigned char key[APR_SIPHASH_KSIZE]);
+
+/**
+ * @brief Computes SipHash-4-8, producing a 64bit (APR_SIPHASH_DSIZE) hash
+ * from a message and a 128bit (APR_SIPHASH_KSIZE) secret key, into a possibly
+ * unaligned buffer (using the little endian representation as defined by the
+ * authors for interoperabilty) usable as a MAC.
+ * @param out The output buffer (or MAC)
+ * @param src The message
+ * @param len The length of the message
+ * @param key The secret key
+ * @return The hash value as a 64bit unsigned integer
+ */
+APR_DECLARE(void) apr_siphash48_auth(unsigned char out[APR_SIPHASH_DSIZE],
+                                     const void *src, apr_size_t len,
+                               const unsigned char key[APR_SIPHASH_KSIZE]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* APR_SIPHASH_H */
diff --git a/include/apr_skiplist.h b/include/apr_skiplist.h
new file mode 100644
index 00000000000..1e7ab258c44
--- /dev/null
+++ b/include/apr_skiplist.h
@@ -0,0 +1,381 @@
+/* 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 APR_SKIPLIST_H
+#define APR_SKIPLIST_H
+/**
+ * @file apr_skiplist.h
+ * @brief APR skip list implementation
+ */
+
+#include "apr.h"
+#include "apr_portable.h"
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup apr_skiplist Skip list implementation
+ * Refer to http://en.wikipedia.org/wiki/Skip_list for information
+ * about the purpose of and ideas behind skip lists.
+ * @ingroup APR
+ * @{
+ */
+
+/**
+ * apr_skiplist_compare is the function type that must be implemented 
+ * per object type that is used in a skip list for comparisons to maintain
+ * order
+ * */
+typedef int (*apr_skiplist_compare) (void *, void *);
+
+/**
+ * apr_skiplist_freefunc is the function type that must be implemented
+ * to handle elements as they are removed from a skip list.
+ */
+typedef void (*apr_skiplist_freefunc) (void *);
+
+/** Opaque structure used to represent the skip list */
+struct apr_skiplist;
+/** Opaque structure used to represent the skip list */
+typedef struct apr_skiplist apr_skiplist;
+
+/** 
+ * Opaque structure used to represent abstract nodes in the skip list
+ * (an abstraction above the raw elements which are collected in the
+ * skip list).
+ */
+struct apr_skiplistnode;
+/** Opaque structure */
+typedef struct apr_skiplistnode apr_skiplistnode;
+
+/**
+ * Allocate memory using the same mechanism as the skip list.
+ * @param sl The skip list
+ * @param size The amount to allocate
+ * @remark If a pool was provided to apr_skiplist_init(), memory will
+ * be allocated from the pool or from a free list maintained with
+ * the skip list.  Otherwise, memory will be allocated using the
+ * C standard library heap functions.
+ */
+APR_DECLARE(void *) apr_skiplist_alloc(apr_skiplist *sl, size_t size);
+
+/**
+ * Free memory using the same mechanism as the skip list.
+ * @param sl The skip list
+ * @param mem The object to free
+ * @remark If a pool was provided to apr_skiplist_init(), memory will
+ * be added to a free list maintained with the skip list and be available
+ * to operations on the skip list or to other calls to apr_skiplist_alloc().
+ * Otherwise, memory will be freed using the  C standard library heap
+ * functions.
+ */
+APR_DECLARE(void) apr_skiplist_free(apr_skiplist *sl, void *mem);
+
+/**
+ * Allocate a new skip list
+ * @param sl The pointer in which to return the newly created skip list
+ * @param p The pool from which to allocate the skip list (optional).
+ * @remark Unlike most APR functions, a pool is optional.  If no pool
+ * is provided, the C standard library heap functions will be used instead.
+ */
+APR_DECLARE(apr_status_t) apr_skiplist_init(apr_skiplist **sl, apr_pool_t *p);
+
+/**
+ * Set the comparison functions to be used for searching the skip list.
+ * @param sl The skip list
+ * @param XXX1 FIXME
+ * @param XXX2 FIXME
+ *
+ * @remark If existing comparison functions are being replaced, the index
+ * will be replaced during this call.  That is a potentially expensive
+ * operation.
+ */
+APR_DECLARE(void) apr_skiplist_set_compare(apr_skiplist *sl, apr_skiplist_compare XXX1,
+                             apr_skiplist_compare XXX2);
+
+/**
+ * Set the indexing functions to the specified comparison functions and
+ * rebuild the index.
+ * @param sl The skip list
+ * @param XXX1 FIXME
+ * @param XXX2 FIXME
+ *
+ * @remark If an index already exists, it will not be replaced and the
+ * comparison functions will not be changed.
+ */
+APR_DECLARE(void) apr_skiplist_add_index(apr_skiplist *sl, apr_skiplist_compare XXX1,
+                        apr_skiplist_compare XXX2);
+
+/**
+ * Return the list maintained by the skip list abstraction.
+ * @param sl The skip list
+ */
+APR_DECLARE(apr_skiplistnode *) apr_skiplist_getlist(apr_skiplist *sl);
+
+/**
+ * Return the next matching element in the skip list using the specified
+ * comparison function.
+ * @param sl The skip list
+ * @param data The value to search for
+ * @param iter A pointer to the returned skip list node representing the element
+ * found
+ * @param func The comparison function to use
+ */
+APR_DECLARE(void *) apr_skiplist_find_compare(apr_skiplist *sl,
+                               void *data,
+                               apr_skiplistnode **iter,
+                               apr_skiplist_compare func);
+
+/**
+ * Return the next matching element in the skip list using the current comparison
+ * function.
+ * @param sl The skip list
+ * @param data The value to search for
+ * @param iter A pointer to the returned skip list node representing the element
+ * found
+ */
+APR_DECLARE(void *) apr_skiplist_find(apr_skiplist *sl, void *data, apr_skiplistnode **iter);
+
+/**
+ * Return the last matching element in the skip list using the specified
+ * comparison function.
+ * @param sl The skip list
+ * @param data The value to search for
+ * @param iter A pointer to the returned skip list node representing the element
+ * found
+ * @param func The comparison function to use
+ */
+APR_DECLARE(void *) apr_skiplist_last_compare(apr_skiplist *sli, void *data,
+                                              apr_skiplistnode **iter,
+                                              apr_skiplist_compare comp);
+
+/**
+ * Return the last matching element in the skip list using the current comparison
+ * function.
+ * @param sl The skip list
+ * @param data The value to search for
+ * @param iter A pointer to the returned skip list node representing the element
+ * found
+ */
+APR_DECLARE(void *) apr_skiplist_last(apr_skiplist *sl, void *data,
+                                      apr_skiplistnode **iter);
+
+/**
+ * Return the next element in the skip list.
+ * @param sl The skip list
+ * @param iter On entry, a pointer to the skip list node to start with; on return,
+ * a pointer to the skip list node representing the element returned
+ * @remark If iter points to a NULL value on entry, NULL will be returned.
+ */
+APR_DECLARE(void *) apr_skiplist_next(apr_skiplist *sl, apr_skiplistnode **iter);
+
+/**
+ * Return the previous element in the skip list.
+ * @param sl The skip list
+ * @param iter On entry, a pointer to the skip list node to start with; on return,
+ * a pointer to the skip list node representing the element returned
+ * @remark If iter points to a NULL value on entry, NULL will be returned.
+ */
+APR_DECLARE(void *) apr_skiplist_previous(apr_skiplist *sl, apr_skiplistnode **iter);
+
+/**
+ * Return the element of the skip list node
+ * @param iter The skip list node
+ */
+APR_DECLARE(void *) apr_skiplist_element(apr_skiplistnode *iter);
+
+/**
+ * Insert an element into the skip list using the specified comparison function
+ * if it does not already exist.
+ * @param sl The skip list
+ * @param data The element to insert
+ * @param comp The comparison function to use for placement into the skip list
+ */
+APR_DECLARE(apr_skiplistnode *) apr_skiplist_insert_compare(apr_skiplist *sl,
+                                          void *data, apr_skiplist_compare comp);
+
+/**
+ * Insert an element into the skip list using the existing comparison function
+ * if it does not already exist.
+ * @param sl The skip list
+ * @param data The element to insert
+ * @remark If no comparison function has been set for the skip list, the element
+ * will not be inserted and NULL will be returned.
+ */
+APR_DECLARE(apr_skiplistnode *) apr_skiplist_insert(apr_skiplist* sl, void *data);
+
+/**
+ * Add an element into the skip list using the specified comparison function
+ * allowing for duplicates.
+ * @param sl The skip list
+ * @param data The element to add
+ * @param comp The comparison function to use for placement into the skip list
+ */
+APR_DECLARE(apr_skiplistnode *) apr_skiplist_add_compare(apr_skiplist *sl,
+                                          void *data, apr_skiplist_compare comp);
+
+/**
+ * Add an element into the skip list using the existing comparison function
+ * allowing for duplicates.
+ * @param sl The skip list
+ * @param data The element to insert
+ * @remark If no comparison function has been set for the skip list, the element
+ * will not be inserted and NULL will be returned.
+ */
+APR_DECLARE(apr_skiplistnode *) apr_skiplist_add(apr_skiplist* sl, void *data);
+
+/**
+ * Add an element into the skip list using the specified comparison function
+ * removing the existing duplicates.
+ * @param sl The skip list
+ * @param data The element to insert
+ * @param comp The comparison function to use for placement into the skip list
+ * @param myfree A function to be called for each removed duplicate
+ * @remark If no comparison function has been set for the skip list, the element
+ * will not be inserted, none will be replaced, and NULL will be returned.
+ */
+APR_DECLARE(apr_skiplistnode *) apr_skiplist_replace_compare(apr_skiplist *sl,
+                                    void *data, apr_skiplist_freefunc myfree,
+                                    apr_skiplist_compare comp);
+
+/**
+ * Add an element into the skip list using the existing comparison function
+ * removing the existing duplicates.
+ * @param sl The skip list
+ * @param data The element to insert
+ * @param myfree A function to be called for each removed duplicate
+ * @remark If no comparison function has been set for the skip list, the element
+ * will not be inserted, none will be replaced, and NULL will be returned.
+ */
+APR_DECLARE(apr_skiplistnode *) apr_skiplist_replace(apr_skiplist *sl,
+                                    void *data, apr_skiplist_freefunc myfree);
+
+/**
+ * Remove a node from the skip list.
+ * @param sl The skip list
+ * @param iter The skip list node to remove
+ * @param myfree A function to be called for the removed element
+ */
+APR_DECLARE(int) apr_skiplist_remove_node(apr_skiplist *sl,
+                                          apr_skiplistnode *iter,
+                                          apr_skiplist_freefunc myfree);
+
+/**
+ * Remove an element from the skip list using the specified comparison function for
+ * locating the element. In the case of duplicates, the 1st entry will be removed.
+ * @param sl The skip list
+ * @param data The element to remove
+ * @param myfree A function to be called for each removed element
+ * @param comp The comparison function to use for placement into the skip list
+ * @remark If the element is not found, 0 will be returned.  Otherwise, the heightXXX
+ * will be returned.
+ */
+APR_DECLARE(int) apr_skiplist_remove_compare(apr_skiplist *sl, void *data,
+                               apr_skiplist_freefunc myfree, apr_skiplist_compare comp);
+
+/**
+ * Remove an element from the skip list using the existing comparison function for
+ * locating the element. In the case of duplicates, the 1st entry will be removed.
+ * @param sl The skip list
+ * @param data The element to remove
+ * @param myfree A function to be called for each removed element
+ * @remark If the element is not found, 0 will be returned.  Otherwise, the heightXXX
+ * will be returned.
+ * @remark If no comparison function has been set for the skip list, the element
+ * will not be removed and 0 will be returned.
+ */
+APR_DECLARE(int) apr_skiplist_remove(apr_skiplist *sl, void *data, apr_skiplist_freefunc myfree);
+
+/**
+ * Remove all elements from the skip list.
+ * @param sl The skip list
+ * @param myfree A function to be called for each removed element
+ */
+APR_DECLARE(void) apr_skiplist_remove_all(apr_skiplist *sl, apr_skiplist_freefunc myfree);
+
+/**
+ * Remove each element from the skip list.
+ * @param sl The skip list
+ * @param myfree A function to be called for each removed element
+ */
+APR_DECLARE(void) apr_skiplist_destroy(apr_skiplist *sl, apr_skiplist_freefunc myfree);
+
+/**
+ * Return the first element in the skip list, removing the element from the skip list.
+ * @param sl The skip list
+ * @param myfree A function to be called for the removed element
+ * @remark NULL will be returned if there are no elements
+ */
+APR_DECLARE(void *) apr_skiplist_pop(apr_skiplist *sl, apr_skiplist_freefunc myfree);
+
+/**
+ * Return the first element in the skip list, leaving the element in the skip list.
+ * @param sl The skip list
+ * @remark NULL will be returned if there are no elements
+ */
+APR_DECLARE(void *) apr_skiplist_peek(apr_skiplist *sl);
+
+/**
+ * Return the size of the list (number of elements), in O(1).
+ * @param sl The skip list
+ */
+APR_DECLARE(size_t) apr_skiplist_size(const apr_skiplist *sl);
+
+/**
+ * Return the height of the list (number of skip paths), in O(1).
+ * @param sl The skip list
+ */
+APR_DECLARE(int) apr_skiplist_height(const apr_skiplist *sl);
+
+/**
+ * Return the predefined maximum height of the skip list.
+ * @param sl The skip list
+ */
+APR_DECLARE(int) apr_skiplist_preheight(const apr_skiplist *sl);
+
+/**
+ * Set a predefined maximum height for the skip list.
+ * @param sl The skip list
+ * @param to The preheight to set, or a nul/negative value to disable.
+ * @remark When a preheight is used, the height of each inserted element is
+ * computed randomly up to this preheight instead of the current skip list's
+ * height plus one used by the default implementation. Using a preheight can
+ * probably ensure more fairness with long living elements (since with an
+ * adaptative height, former elements may have been created with a low height,
+ * hence a longest path to reach them while the skip list grows). On the other
+ * hand, the default behaviour (preheight <= 0) with a growing and decreasing
+ * maximum height is more adaptative/suitable for short living values.
+ * @note Should be called before any insertion/add.
+ */
+APR_DECLARE(void) apr_skiplist_set_preheight(apr_skiplist *sl, int to);
+
+/**
+ * Merge two skip lists.  XXX SEMANTICS
+ * @param sl1 One of two skip lists to be merged
+ * @param sl2 The other of two skip lists to be merged
+ */
+APR_DECLARE(apr_skiplist *) apr_skiplist_merge(apr_skiplist *sl1, apr_skiplist *sl2);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ! APR_SKIPLIST_H */
diff --git a/include/apr_strings.h b/include/apr_strings.h
new file mode 100644
index 00000000000..c0642adb211
--- /dev/null
+++ b/include/apr_strings.h
@@ -0,0 +1,380 @@
+/* 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.
+ */
+
+/* Portions of this file are covered by */
+/* -*- mode: c; c-file-style: "k&r" -*-
+
+  strnatcmp.c -- Perform 'natural order' comparisons of strings in C.
+  Copyright (C) 2000 by Martin Pool <mbp@humbug.org.au>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef APR_STRINGS_H
+#define APR_STRINGS_H
+
+/**
+ * @file apr_strings.h
+ * @brief APR Strings library
+ */
+
+#include "apr.h"
+#include "apr_errno.h"
+#include "apr_pools.h"
+#define APR_WANT_IOVEC
+#include "apr_want.h"
+
+#if APR_HAVE_STDARG_H
+#include <stdarg.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup apr_strings String routines
+ * @ingroup APR 
+ * @{
+ */
+
+/**
+ * Do a natural order comparison of two strings.
+ * @param a The first string to compare
+ * @param b The second string to compare
+ * @return Either <0, 0, or >0.  If the first string is less than the second
+ *          this returns <0, if they are equivalent it returns 0, and if the
+ *          first string is greater than second string it retuns >0.
+ */
+APR_DECLARE(int) apr_strnatcmp(char const *a, char const *b);
+
+/**
+ * Do a natural order comparison of two strings ignoring the case of the 
+ * strings.
+ * @param a The first string to compare
+ * @param b The second string to compare
+ * @return Either <0, 0, or >0.  If the first string is less than the second
+ *         this returns <0, if they are equivalent it returns 0, and if the
+ *         first string is greater than second string it retuns >0.
+ */
+APR_DECLARE(int) apr_strnatcasecmp(char const *a, char const *b);
+
+/**
+ * duplicate a string into memory allocated out of a pool
+ * @param p The pool to allocate out of
+ * @param s The string to duplicate
+ * @return The new string or NULL if s == NULL
+ */
+APR_DECLARE(char *) apr_pstrdup(apr_pool_t *p, const char *s);
+
+/**
+ * Create a null-terminated string by making a copy of a sequence
+ * of characters and appending a null byte
+ * @param p The pool to allocate out of
+ * @param s The block of characters to duplicate
+ * @param n The number of characters to duplicate
+ * @return The new string or NULL if s == NULL
+ * @remark This is a faster alternative to apr_pstrndup, for use
+ *         when you know that the string being duplicated really
+ *         has 'n' or more characters.  If the string might contain
+ *         fewer characters, use apr_pstrndup.
+ */
+APR_DECLARE(char *) apr_pstrmemdup(apr_pool_t *p, const char *s, apr_size_t n)
+#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
+    __attribute__((alloc_size(3)))
+#endif
+    ;
+
+/**
+ * Duplicate at most n characters of a string into memory allocated 
+ * out of a pool; the new string will be NUL-terminated
+ * @param p The pool to allocate out of
+ * @param s The string to duplicate
+ * @param n The maximum number of characters to duplicate
+ * @return The new string or NULL if s == NULL
+ * @remark The amount of memory allocated from the pool is the length
+ *         of the returned string including the NUL terminator
+ */
+APR_DECLARE(char *) apr_pstrndup(apr_pool_t *p, const char *s, apr_size_t n);
+
+/**
+ * Duplicate a block of memory.
+ *
+ * @param p The pool to allocate from
+ * @param m The memory to duplicate
+ * @param n The number of bytes to duplicate
+ * @return The new block of memory or NULL if m == NULL
+ */
+APR_DECLARE(void *) apr_pmemdup(apr_pool_t *p, const void *m, apr_size_t n)
+#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
+    __attribute__((alloc_size(3)))
+#endif
+    ;
+
+/**
+ * Concatenate multiple strings, allocating memory out a pool
+ * @param p The pool to allocate out of
+ * @param ... The strings to concatenate.  The final string must be NULL
+ * @return The new string
+ */
+APR_DECLARE_NONSTD(char *) apr_pstrcat(apr_pool_t *p, ...)
+#if defined(__GNUC__) && __GNUC__ >= 4
+    __attribute__((sentinel))
+#endif
+    ;
+
+/**
+ * Concatenate multiple strings specified in a writev-style vector
+ * @param p The pool from which to allocate
+ * @param vec The strings to concatenate
+ * @param nvec The number of strings to concatenate
+ * @param nbytes (output) strlen of new string (pass in NULL to omit)
+ * @return The new string
+ */
+APR_DECLARE(char *) apr_pstrcatv(apr_pool_t *p, const struct iovec *vec,
+                                 apr_size_t nvec, apr_size_t *nbytes);
+
+/**
+ * printf-style style printing routine.  The data is output to a string 
+ * allocated from a pool
+ * @param p The pool to allocate out of
+ * @param fmt The format of the string
+ * @param ap The arguments to use while printing the data
+ * @return The new string
+ */
+APR_DECLARE(char *) apr_pvsprintf(apr_pool_t *p, const char *fmt, va_list ap);
+
+/**
+ * printf-style style printing routine.  The data is output to a string 
+ * allocated from a pool
+ * @param p The pool to allocate out of
+ * @param fmt The format of the string
+ * @param ... The arguments to use while printing the data
+ * @return The new string
+ */
+APR_DECLARE_NONSTD(char *) apr_psprintf(apr_pool_t *p, const char *fmt, ...)
+        __attribute__((format(printf,2,3)));
+
+/**
+ * Copy up to dst_size characters from src to dst; does not copy
+ * past a NUL terminator in src, but always terminates dst with a NUL
+ * regardless.
+ * @param dst The destination string
+ * @param src The source string
+ * @param dst_size The space available in dst; dst always receives
+ *                 NUL termination, so if src is longer than
+ *                 dst_size, the actual number of characters copied is
+ *                 dst_size - 1.
+ * @return Pointer to the NUL terminator of the destination string, dst
+ * @remark
+ * <PRE>
+ * Note the differences between this function and strncpy():
+ *  1) strncpy() doesn't always NUL terminate; apr_cpystrn() does.
+ *  2) strncpy() pads the destination string with NULs, which is often 
+ *     unnecessary; apr_cpystrn() does not.
+ *  3) strncpy() returns a pointer to the beginning of the dst string;
+ *     apr_cpystrn() returns a pointer to the NUL terminator of dst, 
+ *     to allow a check for truncation.
+ * </PRE>
+ */
+APR_DECLARE(char *) apr_cpystrn(char *dst, const char *src,
+                                apr_size_t dst_size);
+
+/**
+ * Remove all whitespace from a string
+ * @param dest The destination string.  It is okay to modify the string
+ *             in place.  Namely dest == src
+ * @param src The string to rid the spaces from.
+ * @return A pointer to the destination string's null terminator.
+ */
+APR_DECLARE(char *) apr_collapse_spaces(char *dest, const char *src);
+
+/**
+ * Convert the arguments to a program from one string to an array of 
+ * strings terminated by a NULL pointer
+ * @param arg_str The arguments to convert
+ * @param argv_out Output location.  This is a pointer to an array of strings.
+ * @param token_context Pool to use.
+ */
+APR_DECLARE(apr_status_t) apr_tokenize_to_argv(const char *arg_str,
+                                               char ***argv_out,
+                                               apr_pool_t *token_context);
+
+/**
+ * Split a string into separate null-terminated tokens.  The tokens are 
+ * delimited in the string by one or more characters from the sep
+ * argument.
+ * @param str The string to separate; this should be specified on the
+ *            first call to apr_strtok() for a given string, and NULL
+ *            on subsequent calls.
+ * @param sep The set of delimiters
+ * @param last State saved by apr_strtok() between calls.
+ * @return The next token from the string
+ * @note the 'last' state points to the trailing NUL char of the final
+ * token, otherwise it points to the character following the current
+ * token (all successive or empty occurances of sep are skiped on the
+ * subsequent call to apr_strtok).  Therefore it is possible to avoid
+ * a strlen() determination, with the following logic;
+ * toklen = last - retval; if (*last) --toklen;
+ */
+APR_DECLARE(char *) apr_strtok(char *str, const char *sep, char **last);
+
+/**
+ * @defgroup APR_Strings_Snprintf snprintf implementations
+ * @warning
+ * These are snprintf implementations based on apr_vformatter().
+ *
+ * Note that various standards and implementations disagree on the return
+ * value of snprintf, and side-effects due to %n in the formatting string.
+ * apr_snprintf (and apr_vsnprintf) behaves as follows:
+ *
+ * Process the format string until the entire string is exhausted, or
+ * the buffer fills.  If the buffer fills then stop processing immediately
+ * (so no further %n arguments are processed), and return the buffer
+ * length.  In all cases the buffer is NUL terminated. It will return the
+ * number of characters inserted into the buffer, not including the
+ * terminating NUL. As a special case, if len is 0, apr_snprintf will
+ * return the number of characters that would have been inserted if
+ * the buffer had been infinite (in this case, *buffer can be NULL)
+ *
+ * In no event does apr_snprintf return a negative number.
+ * @{
+ */
+
+/**
+ * snprintf routine based on apr_vformatter.  This means it understands the
+ * same extensions.
+ * @param buf The buffer to write to
+ * @param len The size of the buffer
+ * @param format The format string
+ * @param ... The arguments to use to fill out the format string.
+ */
+APR_DECLARE_NONSTD(int) apr_snprintf(char *buf, apr_size_t len,
+                                     const char *format, ...)
+        __attribute__((format(printf,3,4)));
+
+/**
+ * vsnprintf routine based on apr_vformatter.  This means it understands the
+ * same extensions.
+ * @param buf The buffer to write to
+ * @param len The size of the buffer
+ * @param format The format string
+ * @param ap The arguments to use to fill out the format string.
+ */
+APR_DECLARE(int) apr_vsnprintf(char *buf, apr_size_t len, const char *format,
+                               va_list ap);
+/** @} */
+
+/**
+ * create a string representation of an int, allocated from a pool
+ * @param p The pool from which to allocate
+ * @param n The number to format
+ * @return The string representation of the number
+ */
+APR_DECLARE(char *) apr_itoa(apr_pool_t *p, int n);
+
+/**
+ * create a string representation of a long, allocated from a pool
+ * @param p The pool from which to allocate
+ * @param n The number to format
+ * @return The string representation of the number
+ */
+APR_DECLARE(char *) apr_ltoa(apr_pool_t *p, long n);
+
+/**
+ * create a string representation of an apr_off_t, allocated from a pool
+ * @param p The pool from which to allocate
+ * @param n The number to format
+ * @return The string representation of the number
+ */
+APR_DECLARE(char *) apr_off_t_toa(apr_pool_t *p, apr_off_t n);
+
+/**
+ * Convert a numeric string into an apr_off_t numeric value.
+ * @param offset The value of the parsed string.
+ * @param buf The string to parse. It may contain optional whitespace,
+ *   followed by an optional '+' (positive, default) or '-' (negative)
+ *   character, followed by an optional '0x' prefix if base is 0 or 16,
+ *   followed by numeric digits appropriate for base.
+ * @param end A pointer to the end of the valid character in buf. If
+ *   not NULL, it is set to the first invalid character in buf.
+ * @param base A numeric base in the range between 2 and 36 inclusive,
+ *   or 0.  If base is zero, buf will be treated as base ten unless its
+ *   digits are prefixed with '0x', in which case it will be treated as
+ *   base 16.
+ * @bug *end breaks type safety; where *buf is const, *end needs to be
+ * declared as const in APR 2.0
+ */
+APR_DECLARE(apr_status_t) apr_strtoff(apr_off_t *offset, const char *buf, 
+                                      char **end, int base);
+
+/**
+ * parse a numeric string into a 64-bit numeric value
+ * @param buf The string to parse. It may contain optional whitespace,
+ *   followed by an optional '+' (positive, default) or '-' (negative)
+ *   character, followed by an optional '0x' prefix if base is 0 or 16,
+ *   followed by numeric digits appropriate for base.
+ * @param end A pointer to the end of the valid character in buf. If
+ *   not NULL, it is set to the first invalid character in buf.
+ * @param base A numeric base in the range between 2 and 36 inclusive,
+ *   or 0.  If base is zero, buf will be treated as base ten unless its
+ *   digits are prefixed with '0x', in which case it will be treated as
+ *   base 16.
+ * @return The numeric value of the string.  On overflow, errno is set
+ * to ERANGE.  On success, errno is set to 0.
+ */
+APR_DECLARE(apr_int64_t) apr_strtoi64(const char *buf, char **end, int base);
+
+/**
+ * parse a base-10 numeric string into a 64-bit numeric value.
+ * Equivalent to apr_strtoi64(buf, (char**)NULL, 10).
+ * @param buf The string to parse
+ * @return The numeric value of the string.  On overflow, errno is set
+ * to ERANGE.  On success, errno is set to 0.
+ */
+APR_DECLARE(apr_int64_t) apr_atoi64(const char *buf);
+
+/**
+ * Format a binary size (magnitiudes are 2^10 rather than 10^3) from an apr_off_t,
+ * as bytes, K, M, T, etc, to a four character compacted human readable string.
+ * @param size The size to format
+ * @param buf The 5 byte text buffer (counting the trailing null)
+ * @return The buf passed to apr_strfsize()
+ * @remark All negative sizes report '  - ', apr_strfsize only formats positive values.
+ */
+APR_DECLARE(char *) apr_strfsize(apr_off_t size, char *buf);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* !APR_STRINGS_H */
diff --git a/include/apr_strmatch.h b/include/apr_strmatch.h
new file mode 100644
index 00000000000..713970c9081
--- /dev/null
+++ b/include/apr_strmatch.h
@@ -0,0 +1,81 @@
+/* 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 APR_STRMATCH_H
+#define APR_STRMATCH_H
+/**
+ * @file apr_strmatch.h
+ * @brief APR-UTIL string matching routines
+ */
+
+#include "apu.h"
+#include "apr_pools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup APR_Util_StrMatch String matching routines
+ * @ingroup APR
+ * @{
+ */
+
+/** @see apr_strmatch_pattern */
+typedef struct apr_strmatch_pattern apr_strmatch_pattern;
+
+/**
+ * Precompiled search pattern
+ */
+struct apr_strmatch_pattern {
+    /** Function called to compare */
+    const char *(*compare)(const apr_strmatch_pattern *this_pattern,
+                           const char *s, apr_size_t slen);
+    const char *pattern;    /**< Current pattern */
+    apr_size_t length;      /**< Current length */
+    void *context;          /**< hook to add precomputed metadata */
+};
+
+#if defined(DOXYGEN)
+/**
+ * Search for a precompiled pattern within a string
+ * @param pattern The pattern
+ * @param s The string in which to search for the pattern
+ * @param slen The length of s (excluding null terminator)
+ * @return A pointer to the first instance of the pattern in s, or
+ *         NULL if not found
+ */
+APR_DECLARE(const char *) apr_strmatch(const apr_strmatch_pattern *pattern,
+                                       const char *s, apr_size_t slen);
+#else
+#define apr_strmatch(pattern, s, slen) (*((pattern)->compare))((pattern), (s), (slen))
+#endif
+
+/**
+ * Precompile a pattern for matching using the Boyer-Moore-Horspool algorithm
+ * @param p The pool from which to allocate the pattern
+ * @param s The pattern string
+ * @param case_sensitive Whether the matching should be case-sensitive
+ * @return a pointer to the compiled pattern, or NULL if compilation fails
+ */
+APR_DECLARE(const apr_strmatch_pattern *) apr_strmatch_precompile(apr_pool_t *p, const char *s, int case_sensitive);
+
+/** @} */
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* !APR_STRMATCH_H */
diff --git a/include/apr_strnatcmp.h b/include/apr_strnatcmp.h
deleted file mode 100644
index c65f6dfb6d5..00000000000
--- a/include/apr_strnatcmp.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* -*- mode: c; c-file-style: "k&r" -*-
-
-  strnatcmp.c -- Perform 'natural order' comparisons of strings in C.
-  Copyright (C) 2000 by Martin Pool <mbp@humbug.org.au>
-
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-
-  1. The origin of this software must not be misrepresented; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-  2. Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-  3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef APR_STRNATCMP_H
-#define APR_STRNATCMP_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-int ap_strnatcmp(char const *a, char const *b);
-int ap_strnatcasecmp(char const *a, char const *b);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif  /* !APR_STRNATCMP_H */
diff --git a/include/apr_tables.h b/include/apr_tables.h
new file mode 100644
index 00000000000..fe3084bd646
--- /dev/null
+++ b/include/apr_tables.h
@@ -0,0 +1,507 @@
+/* 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 APR_TABLES_H
+#define APR_TABLES_H
+
+/**
+ * @file apr_tables.h
+ * @brief APR Table library
+ */
+
+#include "apr.h"
+#include "apr_pools.h"
+
+#if APR_HAVE_STDARG_H
+#include <stdarg.h>     /* for va_list */
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup apr_tables Table and Array Functions
+ * @ingroup APR 
+ * Arrays are used to store data which is referenced sequentially or
+ * as a stack.  Functions are provided to push and pop individual
+ * elements as well as to operate on the entire array.
+ *
+ * Tables are used to store data which can be referenced by key.
+ * Limited capabilities are provided for tables with multiple elements
+ * which share a key; while key lookup will return only a single
+ * element, iteration is available.  Additionally, a table can be
+ * compressed to resolve duplicates.
+ *
+ * Both arrays and tables may store string or binary data; some features,
+ * such as concatenation or merging of elements, work only for string
+ * data.
+ * @{
+ */
+
+/** the table abstract data type */
+typedef struct apr_table_t apr_table_t;
+
+/** @see apr_array_header_t */
+typedef struct apr_array_header_t apr_array_header_t;
+
+/** An opaque array type */
+struct apr_array_header_t {
+    /** The pool the array is allocated out of */
+    apr_pool_t *pool;
+    /** The amount of memory allocated for each element of the array */
+    int elt_size;
+    /** The number of active elements in the array */
+    int nelts;
+    /** The number of elements allocated in the array */
+    int nalloc;
+    /** The elements in the array */
+    char *elts;
+};
+
+/**
+ * The (opaque) structure for string-content tables.
+ */
+typedef struct apr_table_entry_t apr_table_entry_t;
+
+/** The type for each entry in a string-content table */
+struct apr_table_entry_t {
+    /** The key for the current table entry */
+    char *key;          /* maybe NULL in future;
+                         * check when iterating thru table_elts
+                         */
+    /** The value for the current table entry */
+    char *val;
+
+    /** A checksum for the key, for use by the apr_table internals */
+    apr_uint32_t key_checksum;
+};
+
+/**
+ * Get the elements from a table.
+ * @param t The table
+ * @return An array containing the contents of the table
+ */
+APR_DECLARE(const apr_array_header_t *) apr_table_elts(const apr_table_t *t);
+
+/**
+ * Determine if the table is empty (either NULL or having no elements).
+ * @param t The table to check
+ * @return True if empty, False otherwise
+ */
+APR_DECLARE(int) apr_is_empty_table(const apr_table_t *t);
+
+/**
+ * Determine if the array is empty (either NULL or having no elements).
+ * @param a The array to check
+ * @return True if empty, False otherwise
+ */
+APR_DECLARE(int) apr_is_empty_array(const apr_array_header_t *a);
+
+/**
+ * Create an array.
+ * @param p The pool to allocate the memory out of
+ * @param nelts the number of elements in the initial array
+ * @param elt_size The size of each element in the array.
+ * @return The new array
+ */
+APR_DECLARE(apr_array_header_t *) apr_array_make(apr_pool_t *p,
+                                                 int nelts, int elt_size);
+
+/**
+ * Add a new element to an array (as a first-in, last-out stack).
+ * @param arr The array to add an element to.
+ * @return Location for the new element in the array.
+ * @remark If there are no free spots in the array, then this function will
+ *         allocate new space for the new element.
+ */
+APR_DECLARE(void *) apr_array_push(apr_array_header_t *arr);
+
+/** A helper macro for accessing a member of an APR array.
+ *
+ * @param ary the array
+ * @param i the index into the array to return
+ * @param type the type of the objects stored in the array
+ *
+ * @return the item at index i
+ */
+#define APR_ARRAY_IDX(ary,i,type) (((type *)(ary)->elts)[i])
+
+/** A helper macro for pushing elements into an APR array.
+ *
+ * @param ary the array
+ * @param type the type of the objects stored in the array
+ *
+ * @return the location where the new object should be placed
+ */
+#define APR_ARRAY_PUSH(ary,type) (*((type *)apr_array_push(ary)))
+
+/**
+ * Remove an element from an array (as a first-in, last-out stack).
+ * @param arr The array to remove an element from.
+ * @return Location of the element in the array.
+ * @remark If there are no elements in the array, NULL is returned.
+ */
+APR_DECLARE(void *) apr_array_pop(apr_array_header_t *arr);
+
+/**
+ * Remove all elements from an array.
+ * @param arr The array to remove all elements from.
+ * @remark As the underlying storage is allocated from a pool, no
+ * memory is freed by this operation, but is available for reuse.
+ */
+APR_DECLARE(void) apr_array_clear(apr_array_header_t *arr);
+
+/**
+ * Concatenate two arrays together.
+ * @param dst The destination array, and the one to go first in the combined 
+ *            array
+ * @param src The source array to add to the destination array
+ */
+APR_DECLARE(void) apr_array_cat(apr_array_header_t *dst,
+			        const apr_array_header_t *src);
+
+/**
+ * Copy the entire array.
+ * @param p The pool to allocate the copy of the array out of
+ * @param arr The array to copy
+ * @return An exact copy of the array passed in
+ * @remark The alternate apr_array_copy_hdr copies only the header, and arranges 
+ *         for the elements to be copied if (and only if) the code subsequently
+ *         does a push or arraycat.
+ */
+APR_DECLARE(apr_array_header_t *) apr_array_copy(apr_pool_t *p,
+                                      const apr_array_header_t *arr);
+/**
+ * Copy the headers of the array, and arrange for the elements to be copied if
+ * and only if the code subsequently does a push or arraycat.
+ * @param p The pool to allocate the copy of the array out of
+ * @param arr The array to copy
+ * @return An exact copy of the array passed in
+ * @remark The alternate apr_array_copy copies the *entire* array.
+ */
+APR_DECLARE(apr_array_header_t *) apr_array_copy_hdr(apr_pool_t *p,
+                                      const apr_array_header_t *arr);
+
+/**
+ * Append one array to the end of another, creating a new array in the process.
+ * @param p The pool to allocate the new array out of
+ * @param first The array to put first in the new array.
+ * @param second The array to put second in the new array.
+ * @return A new array containing the data from the two arrays passed in.
+*/
+APR_DECLARE(apr_array_header_t *) apr_array_append(apr_pool_t *p,
+                                      const apr_array_header_t *first,
+                                      const apr_array_header_t *second);
+
+/**
+ * Generate a new string from the apr_pool_t containing the concatenated 
+ * sequence of substrings referenced as elements within the array.  The string 
+ * will be empty if all substrings are empty or null, or if there are no 
+ * elements in the array.  If sep is non-NUL, it will be inserted between 
+ * elements as a separator.
+ * @param p The pool to allocate the string out of
+ * @param arr The array to generate the string from
+ * @param sep The separator to use
+ * @return A string containing all of the data in the array.
+ */
+APR_DECLARE(char *) apr_array_pstrcat(apr_pool_t *p,
+				      const apr_array_header_t *arr,
+				      const char sep);
+
+/**
+ * Make a new table.
+ * @param p The pool to allocate the pool out of
+ * @param nelts The number of elements in the initial table.
+ * @return The new table.
+ * @warning This table can only store text data
+ */
+APR_DECLARE(apr_table_t *) apr_table_make(apr_pool_t *p, int nelts);
+
+/**
+ * Create a new table and copy another table into it.
+ * @param p The pool to allocate the new table out of
+ * @param t The table to copy
+ * @return A copy of the table passed in
+ * @warning The table keys and respective values are not copied
+ */
+APR_DECLARE(apr_table_t *) apr_table_copy(apr_pool_t *p,
+                                          const apr_table_t *t);
+
+/**
+ * Create a new table whose contents are deep copied from the given
+ * table. A deep copy operation copies all fields, and makes copies
+ * of dynamically allocated memory pointed to by the fields.
+ * @param p The pool to allocate the new table out of
+ * @param t The table to clone
+ * @return A deep copy of the table passed in
+ */
+APR_DECLARE(apr_table_t *) apr_table_clone(apr_pool_t *p,
+                                           const apr_table_t *t);
+
+/**
+ * Delete all of the elements from a table.
+ * @param t The table to clear
+ */
+APR_DECLARE(void) apr_table_clear(apr_table_t *t);
+
+/**
+ * Get the value associated with a given key from the table.  After this call,
+ * the data is still in the table.
+ * @param t The table to search for the key
+ * @param key The key to search for (case does not matter)
+ * @return The value associated with the key, or NULL if the key does not exist. 
+ */
+APR_DECLARE(const char *) apr_table_get(const apr_table_t *t, const char *key);
+
+/**
+ * Get values associated with a given key from the table.      If more than one
+ * value exists, return a comma separated list of values.  After this call, the
+ * data is still in the table.
+ * @param p The pool to allocate the combined value from, if necessary
+ * @param t The table to search for the key
+ * @param key The key to search for (case does not matter)
+ * @return The value associated with the key, or NULL if the key does not exist.
+ */
+APR_DECLARE(const char *) apr_table_getm(apr_pool_t *p, const apr_table_t *t,
+                                         const char *key);
+
+/**
+ * Add a key/value pair to a table.  If another element already exists with the
+ * same key, this will overwrite the old data.
+ * @param t The table to add the data to.
+ * @param key The key to use (case does not matter)
+ * @param val The value to add
+ * @remark When adding data, this function makes a copy of both the key and the
+ *         value.
+ */
+APR_DECLARE(void) apr_table_set(apr_table_t *t, const char *key,
+                                const char *val);
+
+/**
+ * Add a key/value pair to a table.  If another element already exists with the
+ * same key, this will overwrite the old data.
+ * @param t The table to add the data to.
+ * @param key The key to use (case does not matter)
+ * @param val The value to add
+ * @warning When adding data, this function does not make a copy of the key or 
+ *          the value, so care should be taken to ensure that the values will 
+ *          not change after they have been added..
+ */
+APR_DECLARE(void) apr_table_setn(apr_table_t *t, const char *key,
+                                 const char *val);
+
+/**
+ * Remove data from the table.
+ * @param t The table to remove data from
+ * @param key The key of the data being removed (case does not matter)
+ */
+APR_DECLARE(void) apr_table_unset(apr_table_t *t, const char *key);
+
+/**
+ * Add data to a table by merging the value with data that has already been 
+ * stored. The merging is done by concatenating the two values, separated
+ * by the string ", ".
+ * @param t The table to search for the data
+ * @param key The key to merge data for (case does not matter)
+ * @param val The data to add
+ * @remark If the key is not found, then this function acts like apr_table_add
+ */
+APR_DECLARE(void) apr_table_merge(apr_table_t *t, const char *key,
+                                  const char *val);
+
+/**
+ * Add data to a table by merging the value with data that has already been 
+ * stored. The merging is done by concatenating the two values, separated
+ * by the string ", ".
+ * @param t The table to search for the data
+ * @param key The key to merge data for (case does not matter)
+ * @param val The data to add
+ * @remark If the key is not found, then this function acts like apr_table_addn
+ */
+APR_DECLARE(void) apr_table_mergen(apr_table_t *t, const char *key,
+                                   const char *val);
+
+/**
+ * Add data to a table, regardless of whether there is another element with the
+ * same key.
+ * @param t The table to add to
+ * @param key The key to use
+ * @param val The value to add.
+ * @remark When adding data, this function makes a copy of both the key and the
+ *         value.
+ */
+APR_DECLARE(void) apr_table_add(apr_table_t *t, const char *key,
+                                const char *val);
+
+/**
+ * Add data to a table, regardless of whether there is another element with the
+ * same key.
+ * @param t The table to add to
+ * @param key The key to use
+ * @param val The value to add.
+ * @remark When adding data, this function does not make a copy of the key or the
+ *         value, so care should be taken to ensure that the values will not 
+ *         change after they have been added.
+ */
+APR_DECLARE(void) apr_table_addn(apr_table_t *t, const char *key,
+                                 const char *val);
+
+/**
+ * Merge two tables into one new table.
+ * @param p The pool to use for the new table
+ * @param overlay The first table to put in the new table
+ * @param base The table to add at the end of the new table
+ * @return A new table containing all of the data from the two passed in
+ */
+APR_DECLARE(apr_table_t *) apr_table_overlay(apr_pool_t *p,
+                                             const apr_table_t *overlay,
+                                             const apr_table_t *base);
+
+/**
+ * Declaration prototype for the iterator callback function of apr_table_do()
+ * and apr_table_vdo().
+ * @param rec The data passed as the first argument to apr_table_[v]do()
+ * @param key The key from this iteration of the table
+ * @param value The value from this iteration of the table
+ * @remark Iteration continues while this callback function returns non-zero.
+ * To export the callback function for apr_table_[v]do() it must be declared 
+ * in the _NONSTD convention.
+ * @see apr_table_do @see apr_table_vdo
+ */
+typedef int (apr_table_do_callback_fn_t)(void *rec, const char *key, 
+                                                    const char *value);
+
+/** 
+ * Iterate over a table running the provided function once for every
+ * element in the table.  The varargs array must be a list of zero or
+ * more (char *) keys followed by a NULL pointer.  If zero keys are
+ * given, the @param comp function will be invoked for every element
+ * in the table.  Otherwise, the function is invoked only for those
+ * elements matching the keys specified.
+ *
+ * If an invocation of the comp function returns zero,
+ * iteration will continue using the next specified key, if any.
+ *
+ * @param comp The function to run
+ * @param rec The data to pass as the first argument to the function
+ * @param t The table to iterate over
+ * @param ... A varargs array of zero or more (char *) keys followed by NULL
+ * @return FALSE if one of the comp() iterations returned zero; TRUE if all
+ *            iterations returned non-zero
+ * @see apr_table_do_callback_fn_t @see apr_table_vdo
+ */
+APR_DECLARE_NONSTD(int) apr_table_do(apr_table_do_callback_fn_t *comp,
+                                     void *rec, const apr_table_t *t, ...)
+#if defined(__GNUC__) && __GNUC__ >= 4
+    __attribute__((sentinel))
+#endif
+    ;
+
+/** 
+ * Iterate over a table running the provided function once for every
+ * element in the table.  The vp varargs parameter must be a
+ * list of zero or more (char *) keys followed by a NULL pointer.  If
+ * zero keys are given, the @param comp function will be invoked for
+ * every element in the table.  Otherwise, the function is invoked
+ * only for those elements matching the keys specified.
+ *
+ * If an invocation of the comp function returns zero,
+ * iteration will continue using the next specified key, if any.
+ *
+ * @param comp The function to run
+ * @param rec The data to pass as the first argument to the function
+ * @param t The table to iterate over
+ * @param vp List of zero or more (char *) keys followed by NULL
+ * @return FALSE if one of the comp() iterations returned zero; TRUE if all
+ *            iterations returned non-zero
+ * @see apr_table_do_callback_fn_t @see apr_table_do
+ */
+APR_DECLARE(int) apr_table_vdo(apr_table_do_callback_fn_t *comp,
+                               void *rec, const apr_table_t *t, va_list vp);
+
+/** flag for overlap to use apr_table_setn */
+#define APR_OVERLAP_TABLES_SET   (0)
+/** flag for overlap to use apr_table_mergen */
+#define APR_OVERLAP_TABLES_MERGE (1)
+/** flag for overlap to use apr_table_addn */
+#define APR_OVERLAP_TABLES_ADD   (2)
+/**
+ * For each element in table b, either use setn or mergen to add the data
+ * to table a.  Which method is used is determined by the flags passed in.
+ * @param a The table to add the data to.
+ * @param b The table to iterate over, adding its data to table a
+ * @param flags How to add the table to table a.  One of:
+ *          APR_OVERLAP_TABLES_SET        Use apr_table_setn
+ *          APR_OVERLAP_TABLES_MERGE      Use apr_table_mergen
+ *          APR_OVERLAP_TABLES_ADD        Use apr_table_addn
+ * @remark  When merging duplicates, the two values are concatenated,
+ *          separated by the string ", ".
+ * @remark  This function is highly optimized, and uses less memory and CPU cycles
+ *          than a function that just loops through table b calling other functions.
+ */
+/**
+ * Conceptually, apr_table_overlap does this:
+ *
+ * <pre>
+ *  apr_array_header_t *barr = apr_table_elts(b);
+ *  apr_table_entry_t *belt = (apr_table_entry_t *)barr->elts;
+ *  int i;
+ *
+ *  for (i = 0; i < barr->nelts; ++i) {
+ *      if (flags & APR_OVERLAP_TABLES_MERGE) {
+ *          apr_table_mergen(a, belt[i].key, belt[i].val);
+ *      }
+ *      else if (flags & APR_OVERLAP_TABLES_ADD) {
+ *          apr_table_addn(a, belt[i].key, belt[i].val);
+ *      }
+ *      else {
+ *          apr_table_setn(a, belt[i].key, belt[i].val);
+ *      }
+ *  }
+ * </pre>
+ *
+ *  Except that it is more efficient (less space and cpu-time) especially
+ *  when b has many elements.
+ *
+ *  Notice the assumptions on the keys and values in b -- they must be
+ *  in an ancestor of a's pool.  In practice b and a are usually from
+ *  the same pool.
+ */
+
+APR_DECLARE(void) apr_table_overlap(apr_table_t *a, const apr_table_t *b,
+                                     unsigned flags);
+
+/**
+ * Eliminate redundant entries in a table by either overwriting
+ * or merging duplicates.
+ *
+ * @param t Table.
+ * @param flags APR_OVERLAP_TABLES_MERGE to merge, or
+ *              APR_OVERLAP_TABLES_SET to overwrite, or
+ *              APR_OVERLAP_TABLES_ADD to add
+ * @remark When merging duplicates, the two values are concatenated,
+ *         separated by the string ", ".
+ */
+APR_DECLARE(void) apr_table_compress(apr_table_t *t, unsigned flags);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* ! APR_TABLES_H */
diff --git a/include/apr_thread_cond.h b/include/apr_thread_cond.h
new file mode 100644
index 00000000000..199f1dedc2a
--- /dev/null
+++ b/include/apr_thread_cond.h
@@ -0,0 +1,139 @@
+/* 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 APR_THREAD_COND_H
+#define APR_THREAD_COND_H
+
+/**
+ * @file apr_thread_cond.h
+ * @brief APR Condition Variable Routines
+ */
+
+#include "apr.h"
+#include "apr_pools.h"
+#include "apr_errno.h"
+#include "apr_time.h"
+#include "apr_thread_mutex.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#if APR_HAS_THREADS || defined(DOXYGEN)
+
+/**
+ * @defgroup apr_thread_cond Condition Variable Routines
+ * @ingroup APR 
+ * @{
+ */
+
+/** Opaque structure for thread condition variables */
+typedef struct apr_thread_cond_t apr_thread_cond_t;
+
+/**
+ * Note: destroying a condition variable (or likewise, destroying or
+ * clearing the pool from which a condition variable was allocated) if
+ * any threads are blocked waiting on it gives undefined results.
+ */
+
+/**
+ * Create and initialize a condition variable that can be used to signal
+ * and schedule threads in a single process.
+ * @param cond the memory address where the newly created condition variable
+ *        will be stored.
+ * @param pool the pool from which to allocate the condition.
+ */
+APR_DECLARE(apr_status_t) apr_thread_cond_create(apr_thread_cond_t **cond,
+                                                 apr_pool_t *pool);
+
+/**
+ * Put the active calling thread to sleep until signaled to wake up. Each
+ * condition variable must be associated with a mutex, and that mutex must
+ * be locked before  calling this function, or the behavior will be
+ * undefined. As the calling thread is put to sleep, the given mutex
+ * will be simultaneously released; and as this thread wakes up the lock
+ * is again simultaneously acquired.
+ * @param cond the condition variable on which to block.
+ * @param mutex the mutex that must be locked upon entering this function,
+ *        is released while the thread is asleep, and is again acquired before
+ *        returning from this function.
+ * @remark Spurious wakeups may occur. Before and after every call to wait on
+ * a condition variable, the caller should test whether the condition is already
+ * met.
+ */
+APR_DECLARE(apr_status_t) apr_thread_cond_wait(apr_thread_cond_t *cond,
+                                               apr_thread_mutex_t *mutex);
+
+/**
+ * Put the active calling thread to sleep until signaled to wake up or
+ * the timeout is reached. Each condition variable must be associated
+ * with a mutex, and that mutex must be locked before calling this
+ * function, or the behavior will be undefined. As the calling thread
+ * is put to sleep, the given mutex will be simultaneously released;
+ * and as this thread wakes up the lock is again simultaneously acquired.
+ * @param cond the condition variable on which to block.
+ * @param mutex the mutex that must be locked upon entering this function,
+ *        is released while the thread is asleep, and is again acquired before
+ *        returning from this function.
+ * @param timeout The amount of time in microseconds to wait. This is 
+ *        a maximum, not a minimum. If the condition is signaled, we 
+ *        will wake up before this time, otherwise the error APR_TIMEUP
+ *        is returned.
+ */
+APR_DECLARE(apr_status_t) apr_thread_cond_timedwait(apr_thread_cond_t *cond,
+                                                    apr_thread_mutex_t *mutex,
+                                                    apr_interval_time_t timeout);
+
+/**
+ * Signals a single thread, if one exists, that is blocking on the given
+ * condition variable. That thread is then scheduled to wake up and acquire
+ * the associated mutex. Although it is not required, if predictable scheduling
+ * is desired, that mutex must be locked while calling this function.
+ * @param cond the condition variable on which to produce the signal.
+ * @remark If no threads are waiting on the condition variable, nothing happens.
+ */
+APR_DECLARE(apr_status_t) apr_thread_cond_signal(apr_thread_cond_t *cond);
+
+/**
+ * Signals all threads blocking on the given condition variable.
+ * Each thread that was signaled is then scheduled to wake up and acquire
+ * the associated mutex. This will happen in a serialized manner.
+ * @param cond the condition variable on which to produce the broadcast.
+ * @remark If no threads are waiting on the condition variable, nothing happens.
+ */
+APR_DECLARE(apr_status_t) apr_thread_cond_broadcast(apr_thread_cond_t *cond);
+
+/**
+ * Destroy the condition variable and free the associated memory.
+ * @param cond the condition variable to destroy.
+ */
+APR_DECLARE(apr_status_t) apr_thread_cond_destroy(apr_thread_cond_t *cond);
+
+/**
+ * Get the pool used by this thread_cond.
+ * @return apr_pool_t the pool
+ */
+APR_POOL_DECLARE_ACCESSOR(thread_cond);
+
+#endif /* APR_HAS_THREADS */
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* ! APR_THREAD_COND_H */
diff --git a/include/apr_thread_mutex.h b/include/apr_thread_mutex.h
new file mode 100644
index 00000000000..8eb617291b8
--- /dev/null
+++ b/include/apr_thread_mutex.h
@@ -0,0 +1,123 @@
+/* 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 APR_THREAD_MUTEX_H
+#define APR_THREAD_MUTEX_H
+
+/**
+ * @file apr_thread_mutex.h
+ * @brief APR Thread Mutex Routines
+ */
+
+#include "apr.h"
+#include "apr_errno.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#if APR_HAS_THREADS || defined(DOXYGEN)
+
+/**
+ * @defgroup apr_thread_mutex Thread Mutex Routines
+ * @ingroup APR 
+ * @{
+ */
+
+/** Opaque thread-local mutex structure */
+typedef struct apr_thread_mutex_t apr_thread_mutex_t;
+
+#define APR_THREAD_MUTEX_DEFAULT  0x0   /**< platform-optimal lock behavior */
+#define APR_THREAD_MUTEX_NESTED   0x1   /**< enable nested (recursive) locks */
+#define APR_THREAD_MUTEX_UNNESTED 0x2   /**< disable nested locks */
+#define APR_THREAD_MUTEX_TIMED    0x4   /**< enable timed locks */
+
+/* Delayed the include to avoid a circular reference */
+#include "apr_pools.h"
+#include "apr_time.h"
+
+/**
+ * Create and initialize a mutex that can be used to synchronize threads.
+ * @param mutex the memory address where the newly created mutex will be
+ *        stored.
+ * @param flags Or'ed value of:
+ * <PRE>
+ *           APR_THREAD_MUTEX_DEFAULT   platform-optimal lock behavior.
+ *           APR_THREAD_MUTEX_NESTED    enable nested (recursive) locks.
+ *           APR_THREAD_MUTEX_UNNESTED  disable nested locks (non-recursive).
+ * </PRE>
+ * @param pool the pool from which to allocate the mutex.
+ * @warning Be cautious in using APR_THREAD_MUTEX_DEFAULT.  While this is the
+ * most optimal mutex based on a given platform's performance characteristics,
+ * it will behave as either a nested or an unnested lock.
+ */
+APR_DECLARE(apr_status_t) apr_thread_mutex_create(apr_thread_mutex_t **mutex,
+                                                  unsigned int flags,
+                                                  apr_pool_t *pool);
+/**
+ * Acquire the lock for the given mutex. If the mutex is already locked,
+ * the current thread will be put to sleep until the lock becomes available.
+ * @param mutex the mutex on which to acquire the lock.
+ */
+APR_DECLARE(apr_status_t) apr_thread_mutex_lock(apr_thread_mutex_t *mutex);
+
+/**
+ * Attempt to acquire the lock for the given mutex. If the mutex has already
+ * been acquired, the call returns immediately with APR_EBUSY. Note: it
+ * is important that the APR_STATUS_IS_EBUSY(s) macro be used to determine
+ * if the return value was APR_EBUSY, for portability reasons.
+ * @param mutex the mutex on which to attempt the lock acquiring.
+ */
+APR_DECLARE(apr_status_t) apr_thread_mutex_trylock(apr_thread_mutex_t *mutex);
+
+/**
+ * Attempt to acquire the lock for the given mutex until timeout expires.
+ * If the acquisition time outs, the call returns with APR_TIMEUP.
+ * @param mutex the mutex on which to attempt the lock acquiring.
+ * @param timeout the relative timeout (microseconds).
+ * @note A timeout negative or nul means immediate attempt, returning
+ *       APR_TIMEUP without blocking if it the lock is already acquired.
+ */
+APR_DECLARE(apr_status_t) apr_thread_mutex_timedlock(apr_thread_mutex_t *mutex,
+                                                 apr_interval_time_t timeout);
+
+/**
+ * Release the lock for the given mutex.
+ * @param mutex the mutex from which to release the lock.
+ */
+APR_DECLARE(apr_status_t) apr_thread_mutex_unlock(apr_thread_mutex_t *mutex);
+
+/**
+ * Destroy the mutex and free the memory associated with the lock.
+ * @param mutex the mutex to destroy.
+ */
+APR_DECLARE(apr_status_t) apr_thread_mutex_destroy(apr_thread_mutex_t *mutex);
+
+/**
+ * Get the pool used by this thread_mutex.
+ * @return apr_pool_t the pool
+ */
+APR_POOL_DECLARE_ACCESSOR(thread_mutex);
+
+#endif /* APR_HAS_THREADS */
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* ! APR_THREAD_MUTEX_H */
diff --git a/include/apr_thread_pool.h b/include/apr_thread_pool.h
new file mode 100644
index 00000000000..84abd661e87
--- /dev/null
+++ b/include/apr_thread_pool.h
@@ -0,0 +1,299 @@
+/*
+ * 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 APU_THREAD_POOL_H
+#define APU_THREAD_POOL_H
+
+#include "apu.h"
+#include "apr_thread_proc.h"
+
+/**
+ * @file apr_thread_pool.h
+ * @brief APR Thread Pool Library
+
+ * @remarks This library implements a thread pool using apr_thread_t. A thread
+ * pool is a set of threads that can be created in advance or on demand until a
+ * maximum number. When a task is scheduled, the thread pool will find an idle
+ * thread to handle the task. In case all existing threads are busy and the
+ * number of tasks in the queue is higher than the adjustable threshold, the
+ * pool will try to create a new thread to serve the task if the maximum number
+ * has not been reached. Otherwise, the task will be put into a queue based on
+ * priority, which can be valued from 0 to 255, with higher values being served
+ * first. If there are tasks with the same priority, the new task might be put at
+ * the top or at the bottom - it depends on which function is used to put the task.
+ *
+ * @remarks There may be the case where the thread pool can use up to the maximum
+ * number of threads at peak load, but having those threads idle afterwards. A
+ * maximum number of idle threads can be set so that the extra idling threads will
+ * be terminated to save system resources.
+ */
+#if APR_HAS_THREADS
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup APR_Util_TP Thread Pool routines
+ * @ingroup APR
+ * @{
+ */
+
+/** Opaque Thread Pool structure. */
+typedef struct apr_thread_pool apr_thread_pool_t;
+
+#define APR_THREAD_TASK_PRIORITY_LOWEST 0
+#define APR_THREAD_TASK_PRIORITY_LOW 63
+#define APR_THREAD_TASK_PRIORITY_NORMAL 127
+#define APR_THREAD_TASK_PRIORITY_HIGH 191
+#define APR_THREAD_TASK_PRIORITY_HIGHEST 255
+
+/**
+ * Create a thread pool
+ * @param me The pointer in which to return the newly created apr_thread_pool
+ * object, or NULL if thread pool creation fails.
+ * @param init_threads The number of threads to be created initially, this number
+ * will also be used as the initial value for the maximum number of idle threads.
+ * @param max_threads The maximum number of threads that can be created
+ * @param pool The pool to use
+ * @return APR_SUCCESS if the thread pool was created successfully. Otherwise,
+ * the error code.
+ */
+APR_DECLARE(apr_status_t) apr_thread_pool_create(apr_thread_pool_t **me,
+                                                 apr_size_t init_threads,
+                                                 apr_size_t max_threads,
+                                                 apr_pool_t *pool);
+
+/**
+ * Destroy the thread pool and stop all the threads
+ * @return APR_SUCCESS if all threads are stopped.
+ */
+APR_DECLARE(apr_status_t) apr_thread_pool_destroy(apr_thread_pool_t *me);
+
+/**
+ * Schedule a task to the bottom of the tasks of same priority.
+ * @param me The thread pool
+ * @param func The task function
+ * @param param The parameter for the task function
+ * @param priority The priority of the task.
+ * @param owner Owner of this task.
+ * @return APR_SUCCESS if the task had been scheduled successfully
+ */
+APR_DECLARE(apr_status_t) apr_thread_pool_push(apr_thread_pool_t *me,
+                                               apr_thread_start_t func,
+                                               void *param,
+                                               apr_byte_t priority,
+                                               void *owner);
+/**
+ * Schedule a task to be run after a delay
+ * @param me The thread pool
+ * @param func The task function
+ * @param param The parameter for the task function
+ * @param time Time in microseconds
+ * @param owner Owner of this task.
+ * @return APR_SUCCESS if the task had been scheduled successfully
+ */
+APR_DECLARE(apr_status_t) apr_thread_pool_schedule(apr_thread_pool_t *me,
+                                                   apr_thread_start_t func,
+                                                   void *param,
+                                                   apr_interval_time_t time,
+                                                   void *owner);
+
+/**
+ * Schedule a task to the top of the tasks of same priority.
+ * @param me The thread pool
+ * @param func The task function
+ * @param param The parameter for the task function
+ * @param priority The priority of the task.
+ * @param owner Owner of this task.
+ * @return APR_SUCCESS if the task had been scheduled successfully
+ */
+APR_DECLARE(apr_status_t) apr_thread_pool_top(apr_thread_pool_t *me,
+                                              apr_thread_start_t func,
+                                              void *param,
+                                              apr_byte_t priority,
+                                              void *owner);
+
+/**
+ * Cancel tasks submitted by the owner. If there is any task from the owner that
+ * is currently running, the function will spin until the task finished.
+ * @param me The thread pool
+ * @param owner Owner of the task
+ * @return APR_SUCCESS if the task has been cancelled successfully
+ * @note The task function should not be calling cancel, otherwise the function
+ * may get stuck forever. The function assert if it detect such a case.
+ */
+APR_DECLARE(apr_status_t) apr_thread_pool_tasks_cancel(apr_thread_pool_t *me,
+                                                       void *owner);
+
+/**
+ * Get the current number of tasks waiting in the queue
+ * @param me The thread pool
+ * @return Number of tasks in the queue
+ */
+APR_DECLARE(apr_size_t) apr_thread_pool_tasks_count(apr_thread_pool_t *me);
+
+/**
+ * Get the current number of scheduled tasks waiting in the queue
+ * @param me The thread pool
+ * @return Number of scheduled tasks in the queue
+ */
+APR_DECLARE(apr_size_t) apr_thread_pool_scheduled_tasks_count(apr_thread_pool_t *me);
+
+/**
+ * Get the current number of threads
+ * @param me The thread pool
+ * @return Total number of threads
+ */
+APR_DECLARE(apr_size_t) apr_thread_pool_threads_count(apr_thread_pool_t *me);
+
+/**
+ * Get the current number of busy threads
+ * @param me The thread pool
+ * @return Number of busy threads
+ */
+APR_DECLARE(apr_size_t) apr_thread_pool_busy_count(apr_thread_pool_t *me);
+
+/**
+ * Get the current number of idle threads
+ * @param me The thread pool
+ * @return Number of idle threads
+ */
+APR_DECLARE(apr_size_t) apr_thread_pool_idle_count(apr_thread_pool_t *me);
+
+/**
+ * Access function for the maximum number of idle threads. Number of current
+ * idle threads will be reduced to the new limit.
+ * @param me The thread pool
+ * @param cnt The number
+ * @return The number of threads that were stopped.
+ */
+APR_DECLARE(apr_size_t) apr_thread_pool_idle_max_set(apr_thread_pool_t *me,
+                                                     apr_size_t cnt);
+
+/**
+ * Get number of tasks that have run
+ * @param me The thread pool
+ * @return Number of tasks that have run
+ */
+APR_DECLARE(apr_size_t)
+    apr_thread_pool_tasks_run_count(apr_thread_pool_t * me);
+
+/**
+ * Get high water mark of the number of tasks waiting to run
+ * @param me The thread pool
+ * @return High water mark of tasks waiting to run
+ */
+APR_DECLARE(apr_size_t)
+    apr_thread_pool_tasks_high_count(apr_thread_pool_t * me);
+
+/**
+ * Get high water mark of the number of threads
+ * @param me The thread pool
+ * @return High water mark of threads in thread pool
+ */
+APR_DECLARE(apr_size_t)
+    apr_thread_pool_threads_high_count(apr_thread_pool_t * me);
+
+/**
+ * Get the number of idle threads that were destroyed after timing out
+ * @param me The thread pool
+ * @return Number of idle threads that timed out
+ */
+APR_DECLARE(apr_size_t)
+    apr_thread_pool_threads_idle_timeout_count(apr_thread_pool_t * me);
+
+/**
+ * Access function for the maximum number of idle threads
+ * @param me The thread pool
+ * @return The current maximum number
+ */
+APR_DECLARE(apr_size_t) apr_thread_pool_idle_max_get(apr_thread_pool_t *me);
+
+/**
+ * Access function for the maximum number of threads.
+ * @param me The thread pool
+ * @param cnt Number of threads
+ * @return The original maximum number of threads
+ */
+APR_DECLARE(apr_size_t) apr_thread_pool_thread_max_set(apr_thread_pool_t *me,
+                                                       apr_size_t cnt);
+
+/**
+ * Access function for the maximum wait time (in microseconds) of an
+ * idling thread that exceeds the maximum number of idling threads.
+ * A non-zero value allows for the reaping of idling threads to shrink
+ * over time.  Which helps reduce thrashing.
+ * @param me The thread pool
+ * @param timeout The number of microseconds an idle thread should wait
+ * till it reaps itself
+ * @return The original maximum wait time
+ */
+APR_DECLARE(apr_interval_time_t)
+    apr_thread_pool_idle_wait_set(apr_thread_pool_t * me,
+                                  apr_interval_time_t timeout);
+
+/**
+ * Access function for the maximum wait time (in microseconds) of an
+ * idling thread that exceeds the maximum number of idling threads
+ * @param me The thread pool
+ * @return The current maximum wait time
+ */
+APR_DECLARE(apr_interval_time_t)
+    apr_thread_pool_idle_wait_get(apr_thread_pool_t * me);
+
+/**
+ * Access function for the maximum number of threads
+ * @param me The thread pool
+ * @return The current maximum number
+ */
+APR_DECLARE(apr_size_t) apr_thread_pool_thread_max_get(apr_thread_pool_t *me);
+
+/**
+ * Access function for the threshold of tasks in queue to trigger a new thread.
+ * @param me The thread pool
+ * @param val The new threshold
+ * @return The original threshold
+ */
+APR_DECLARE(apr_size_t) apr_thread_pool_threshold_set(apr_thread_pool_t *me,
+                                                      apr_size_t val);
+
+/**
+ * Access function for the threshold of tasks in queue to trigger a new thread.
+ * @param me The thread pool
+ * @return The current threshold
+ */
+APR_DECLARE(apr_size_t) apr_thread_pool_threshold_get(apr_thread_pool_t * me);
+
+/**
+ * Get owner of the task currently been executed by the thread.
+ * @param thd The thread is executing a task
+ * @param owner Pointer to receive owner of the task.
+ * @return APR_SUCCESS if the owner is retrieved successfully
+ */
+APR_DECLARE(apr_status_t) apr_thread_pool_task_owner_get(apr_thread_t *thd,
+                                                         void **owner);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* APR_HAS_THREADS */
+#endif /* !APR_THREAD_POOL_H */
diff --git a/include/apr_thread_proc.h b/include/apr_thread_proc.h
index b2625366c80..a09bdb0bf49 100644
--- a/include/apr_thread_proc.h
+++ b/include/apr_thread_proc.h
@@ -1,666 +1,834 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 APR_THREAD_PROC_H
 #define APR_THREAD_PROC_H
 
+/**
+ * @file apr_thread_proc.h
+ * @brief APR Thread and Process Library
+ */
+
+#include "apr.h"
 #include "apr_file_io.h"
-#include "apr_general.h"
+#include "apr_pools.h"
 #include "apr_errno.h"
+#include "apr_perms_set.h"
+
+#if APR_HAVE_STRUCT_RLIMIT
+#include <sys/time.h>
+#include <sys/resource.h>
+#endif
 
 #ifdef __cplusplus
 extern "C" {
 #endif /* __cplusplus */
 
-typedef enum {APR_SHELLCMD, APR_PROGRAM} ap_cmdtype_e;
-typedef enum {APR_WAIT, APR_NOWAIT} ap_wait_how_e;
-
+/**
+ * @defgroup apr_thread_proc Threads and Process Functions
+ * @ingroup APR 
+ * @{
+ */
+
+typedef enum {
+    APR_SHELLCMD,           /**< use the shell to invoke the program */
+    APR_PROGRAM,            /**< invoke the program directly, no copied env */
+    APR_PROGRAM_ENV,        /**< invoke the program, replicating our environment */
+    APR_PROGRAM_PATH,       /**< find program on PATH, use our environment */
+    APR_SHELLCMD_ENV        /**< use the shell to invoke the program,
+                             *   replicating our environment
+                             */
+} apr_cmdtype_e;
+
+typedef enum {
+    APR_WAIT,           /**< wait for the specified process to finish */
+    APR_NOWAIT          /**< do not wait -- just see if it has finished */
+} apr_wait_how_e;
+
+/* I am specifically calling out the values so that the macros below make
+ * more sense.  Yes, I know I don't need to, but I am hoping this makes what
+ * I am doing more clear.  If you want to add more reasons to exit, continue
+ * to use bitmasks.
+ */
+typedef enum {
+    APR_PROC_EXIT = 1,          /**< process exited normally */
+    APR_PROC_SIGNAL = 2,        /**< process exited due to a signal */
+    APR_PROC_SIGNAL_CORE = 4    /**< process exited and dumped a core file */
+} apr_exit_why_e;
+
+/** did we exit the process */
+#define APR_PROC_CHECK_EXIT(x)        (x & APR_PROC_EXIT)
+/** did we get a signal */
+#define APR_PROC_CHECK_SIGNALED(x)    (x & APR_PROC_SIGNAL)
+/** did we get core */
+#define APR_PROC_CHECK_CORE_DUMP(x)   (x & APR_PROC_SIGNAL_CORE)
+
+/** @see apr_procattr_io_set */
 #define APR_NO_PIPE          0
+/** @see apr_procattr_io_set and apr_file_pipe_create_ex */
 #define APR_FULL_BLOCK       1
+/** @see apr_procattr_io_set and apr_file_pipe_create_ex */
 #define APR_FULL_NONBLOCK    2
+/** @see apr_procattr_io_set */
 #define APR_PARENT_BLOCK     3
+/** @see apr_procattr_io_set */
 #define APR_CHILD_BLOCK      4
+/** @see apr_procattr_io_set */
+#define APR_NO_FILE          8
+
+/** @see apr_file_pipe_create_ex */
+#define APR_READ_BLOCK       3
+/** @see apr_file_pipe_create_ex */
+#define APR_WRITE_BLOCK      4
+
+/** @see apr_procattr_io_set 
+ * @note Win32 only effective with version 1.2.12, portably introduced in 1.3.0
+ */
+#define APR_NO_FILE          8
 
-#define APR_OC_REASON_DEATH         0     /* child has died, caller must call
+/** @see apr_procattr_limit_set */
+#define APR_LIMIT_CPU        0
+/** @see apr_procattr_limit_set */
+#define APR_LIMIT_MEM        1
+/** @see apr_procattr_limit_set */
+#define APR_LIMIT_NPROC      2
+/** @see apr_procattr_limit_set */
+#define APR_LIMIT_NOFILE     3
+
+/**
+ * @defgroup APR_OC Other Child Flags
+ * @{
+ */
+#define APR_OC_REASON_DEATH         0     /**< child has died, caller must call
                                            * unregister still */
-#define APR_OC_REASON_UNWRITABLE    1     /* write_fd is unwritable */
-#define APR_OC_REASON_RESTART       2     /* a restart is occuring, perform
+#define APR_OC_REASON_UNWRITABLE    1     /**< currently unused. */
+#define APR_OC_REASON_RESTART       2     /**< a restart is occurring, perform
                                            * any necessary cleanup (including
                                            * sending a special signal to child)
                                            */
-#define APR_OC_REASON_UNREGISTER    3     /* unregister has been called, do
+#define APR_OC_REASON_UNREGISTER    3     /**< unregister has been called, do
                                            * whatever is necessary (including
                                            * kill the child) */
-#define APR_OC_REASON_LOST          4     /* somehow the child exited without
+#define APR_OC_REASON_LOST          4     /**< somehow the child exited without
                                            * us knowing ... buggy os? */
+#define APR_OC_REASON_RUNNING       5     /**< a health check is occurring, 
+                                           * for most maintainence functions
+                                           * this is a no-op.
+                                           */
+/** @} */
+
+/** The APR process type */
+typedef struct apr_proc_t {
+    /** The process ID */
+    pid_t pid;
+    /** Parent's side of pipe to child's stdin */
+    apr_file_t *in;
+    /** Parent's side of pipe to child's stdout */
+    apr_file_t *out;
+    /** Parent's side of pipe to child's stdouterr */
+    apr_file_t *err;
+#if APR_HAS_PROC_INVOKED || defined(DOXYGEN)
+    /** Diagnositics/debugging string of the command invoked for 
+     *  this process [only present if APR_HAS_PROC_INVOKED is true]
+     * @remark Only enabled on Win32 by default.
+     * @bug This should either always or never be present in release
+     * builds - since it breaks binary compatibility.  We may enable
+     * it always in APR 1.0 yet leave it undefined in most cases.
+     */
+    char *invoked;
+#endif
+#if defined(WIN32) || defined(DOXYGEN)
+    /** (Win32 only) Creator's handle granting access to the process
+     * @remark This handle is closed and reset to NULL in every case
+     * corresponding to a waitpid() on Unix which returns the exit status.
+     * Therefore Win32 correspond's to Unix's zombie reaping characteristics
+     * and avoids potential handle leaks.
+     */
+    HANDLE hproc;
+#endif
+} apr_proc_t;
 
-typedef struct ap_thread_t           ap_thread_t;
-typedef struct ap_threadattr_t       ap_threadattr_t;
-typedef struct ap_proc_t		  ap_proc_t;
-typedef struct ap_procattr_t         ap_procattr_t;
-
-typedef struct ap_threadkey_t        ap_threadkey_t;
-typedef struct ap_other_child_rec_t  ap_other_child_rec_t;
-
-typedef void *(API_THREAD_FUNC *ap_thread_start_t)(void *);
-
-/* Thread Function definitions */
-
-/*
-
-=head1 ap_status_t ap_create_threadattr(ap_threadattr_t **new, ap_pool_t *cont)
-
-B<Create and initialize a new threadattr variable>
-
-    arg 1) The newly created threadattr.
-    arg 2) The pool to use
-
-=cut
- */
-ap_status_t ap_create_threadattr(ap_threadattr_t **new, ap_pool_t *cont);
-
-/*
-
-=head1 ap_status_t ap_setthreadattr_detach(ap_threadattr_t *attr, ap_int32_t on)
-
-B<Set if newly created threads should be created in detach mode.>
-
-    arg 1) The threadattr to affect 
-    arg 2) Thread detach state on or off
-
-=cut
- */
-ap_status_t ap_setthreadattr_detach(ap_threadattr_t *attr, ap_int32_t on);
-
-/*
-
-=head1 ap_status_t ap_getthreadattr_detach(ap_threadattr_t *attr)
-
-B<Get the detach mode for this threadattr.>
-
-    arg 1) The threadattr to reference 
-
-=cut
- */
-ap_status_t ap_getthreadattr_detach(ap_threadattr_t *iattr);
-
-/*
-
-=head1 ap_status_t ap_create_thread(ap_thread_t **new, ap_threadattr_t *attr, ap_thread_start_t func, void *data, ap_pool_t *cont)
-
-B<Create a new thread of execution> 
-
-    arg 1) The newly created thread handle.
-    arg 2) The threadattr to use to determine how to create the thread
-    arg 3) The function to start the new thread in
-    arg 4) Any data to be passed to the starting function
-    arg 5) The pool to use
-
-=cut
- */
-ap_status_t ap_create_thread(ap_thread_t **new, ap_threadattr_t *attr, 
-                             ap_thread_start_t func, void *data, 
-                             ap_pool_t *cont);
-
-/*
-
-=head1 ap_status_t ap_thread_exit(ap_thread_t *thd, ap_status_t *retval)
-
-B<stop the current thread> 
-
-    arg 1) The thread to stop
-    arg 2) The return value to pass back to any thread that cares
-
-=cut
- */
-ap_status_t ap_thread_exit(ap_thread_t *thd, ap_status_t *retval);
-
-/*
-
-=head1 ap_status_t ap_thread_join(ap_status_t *retval, ap_thread_t *thd)
-
-B<block until the desired thread stops executing.>
-
-    arg 1) The return value from the dead thread.
-    arg 2) The thread to join
-
-=cut
- */
-ap_status_t ap_thread_join(ap_status_t *retval, ap_thread_t *thd); 
-
-/*
-
-=head1 ap_status_t ap_thread_detach(ap_thread_t *thd)
-
-B<detach a thread>
-
-    arg 1) The thread to detach 
-
-=cut
- */
-ap_status_t ap_thread_detach(ap_thread_t *thd);
-
-/*
-
-=head1 ap_status_t ap_get_threaddata(void **data, char *key, ap_thread_t *thread)
-
-B<Return the pool associated with the current thread.>
-
-    arg 1) The user data associated with the thread.
-    arg 2) The key to associate with the data
-    arg 3) The currently open thread.
-
-=cut
- */
-ap_status_t ap_get_threaddata(void **data, char *key, ap_thread_t *thread);
-
-/*
-
-=head1 ap_status_t ap_set_threaddata(void *data, char *key, ap_status_t (*cleanup) (void *), ap_thread_t *thread)
-
-B<Return the pool associated with the current thread.>
-
-    arg 1) The user data to associate with the thread.
-    arg 2) The key to use for associating the data with the tread
-    arg 3) The cleanup routine to use when the thread is destroyed.
-    arg 4) The currently open thread.
-
-=cut
- */
-ap_status_t ap_set_threaddata(void *data, char *key,
-                              ap_status_t (*cleanup) (void *), 
-                              ap_thread_t *thread);
-
-/*
-
-=head1 ap_status_t ap_create_thread_private(ap_threadkey_t **key, void (*dest)(void *), ap_pool_t *cont)
-
-B<Create and initialize a new thread private address space>
-
-    arg 1) The thread private handle.
-    arg 2) The destructor to use when freeing the private memory.
-    arg 3) The pool to use
-
-=cut
- */
-ap_status_t ap_create_thread_private(ap_threadkey_t **key, void (*dest)(void *),
-                                     ap_pool_t *cont);
-
-/*
-
-=head1 ap_status_t ap_get_thread_private(void **new, ap_threadkey_t *key)
-
-B<Get a pointer to the thread private memory>
-
-    arg 1) The data stored in private memory 
-    arg 2) The handle for the desired thread private memory 
-
-=cut
- */
-ap_status_t ap_get_thread_private(void **new, ap_threadkey_t *key);
-
-/*
-
-=head1 ap_status_t ap_set_thread_private(void *priv, ap_threadkey_t *key)
-
-B<Set the data to be stored in thread private memory>
-
-    arg 1) The data to be stored in private memory 
-    arg 2) The handle for the desired thread private memory 
-
-=cut
- */
-ap_status_t ap_set_thread_private(void *priv, ap_threadkey_t *key);
-
-/*
-
-=head1 ap_status_t ap_delete_thread_private(ap_threadkey_t *key)
-
-B<Free the thread private memory>
-
-    arg 1) The handle for the desired thread private memory 
-
-=cut
- */
-ap_status_t ap_delete_thread_private(ap_threadkey_t *key);
-
-/*
-
-=head1 ap_status_t ap_get_threadkeydata(void **data, char *key, ap_threadkey_t *threadkey)
-
-B<Return the pool associated with the current threadkey.>
-
-    arg 1) The user data associated with the threadkey.
-    arg 2) The key associated with the data
-    arg 3) The currently open threadkey.
-
-=cut
- */
-ap_status_t ap_get_threadkeydata(void **data, char *key, ap_threadkey_t *threadkey);
-
-/*
-
-=head1 ap_status_t ap_set_threadkeydata(void *data, char *key, ap_status_t (*cleanup) (void *), ap_threadkey_t *threadkey)
-
-B<Return the pool associated with the current threadkey.>
-
-    arg 1) The data to set.
-    arg 2) The key to associate with the data.
-    arg 3) The cleanup routine to use when the file is destroyed.
-    arg 4) The currently open threadkey.
-
-=cut
- */
-ap_status_t ap_set_threadkeydata(void *data, char *key,
-                                 ap_status_t (*cleanup) (void *), 
-                                 ap_threadkey_t *threadkey);
-
-/* Process Function definitions */
-/*
-
-=head1 ap_status_t ap_createprocattr_init(ap_procattr_t **new, ap_pool_t *cont)
-
-B<Create and initialize a new procattr variable> 
-
-    arg 1) The newly created procattr. 
-    arg 2) The pool to use
-
-=cut
- */
-ap_status_t ap_createprocattr_init(ap_procattr_t **new, ap_pool_t *cont);
-
-/*
-
-=head1 ap_status_t ap_setprocattr_io(ap_procattr_t *attr, ap_int32_t in, ap_int32_t *out, ap_int32_t err)
-
-B<Determine if any of stdin, stdout, or stderr should be linked to pipes when starting a child process.> 
-
-    arg 1) The procattr we care about. 
-    arg 2) Should stdin be a pipe back to the parent?
-    arg 3) Should stdout be a pipe back to the parent?
-    arg 4) Should stderr be a pipe back to the parent?
-
-=cut
- */
-ap_status_t ap_setprocattr_io(ap_procattr_t *attr, ap_int32_t in, 
-                              ap_int32_t out, ap_int32_t err);
-
-/*
-
-=head1 ap_status_t ap_setprocattr_childin(ap_procattr_t *attr, ap_file_t *child_in, ap_file_t *parent_in)
-
-B<Set the child_in and/or parent_in values to existing ap_file_t values.> 
-
-    arg 1) The procattr we care about. 
-    arg 2) ap_file_t value to use as child_in. Must be a valid file.
-    arg 3) ap_file_t value to use as parent_in. Must be a valid file.
-
-B<NOTE>:  This is NOT a required initializer function. This is
-          useful if you have already opened a pipe (or multiple files)
-          that you wish to use, perhaps persistently across mutiple
-          process invocations - such as a log file. You can save some 
-          extra function calls by not creating your own pipe since this
-          creates one in the process space for you.
-
-=cut
- */
-ap_status_t ap_setprocattr_childin(struct ap_procattr_t *attr, ap_file_t *child_in,
-                                   ap_file_t *parent_in);
-
-/*
-
-=head1 ap_status_t ap_setprocattr_childout(ap_procattr_t *attr, ap_file_t *child_out, ap_file_t *parent_out)
-
-B<Set the child_out and parent_out values to existing ap_file_t values.> 
-
-    arg 1) The procattr we care about. 
-    arg 2) ap_file_t value to use as child_out. Must be a valid file.
-    arg 3) ap_file_t value to use as parent_out. Must be a valid file.
-
-B<NOTE>:  This is NOT a required initializer function. This is
-          useful if you have already opened a pipe (or multiple files)
-          that you wish to use, perhaps persistently across mutiple
-          process invocations - such as a log file. 
-
-=cut
- */
-ap_status_t ap_setprocattr_childout(struct ap_procattr_t *attr, 
-                                    ap_file_t *child_out, 
-                                    ap_file_t *parent_out);
-
-/*
-
-=head1 ap_status_t ap_setprocattr_childerr(ap_procattr_t *attr, ap_file_t *child_err, ap_file_t *parent_err)
-
-B<Set the child_err and parent_err values to existing ap_file_t values.> 
-
-    arg 1) The procattr we care about. 
-    arg 2) ap_file_t value to use as child_err. Must be a valid file.
-    arg 3) ap_file_t value to use as parent_err. Must be a valid file.
-
-B<NOTE>:  This is NOT a required initializer function. This is
-          useful if you have already opened a pipe (or multiple files)
-          that you wish to use, perhaps persistently across mutiple
-          process invocations - such as a log file. 
-
-=cut
- */
-ap_status_t ap_setprocattr_childerr(struct ap_procattr_t *attr, 
-                                    ap_file_t *child_err,
-                                    ap_file_t *parent_err);
-
-/*
-
-=head1 ap_status_t ap_setprocattr_dir(ap_procattr_t *attr, constchar *dir) 
-
-B<Set which directory the child process should start executing in.> 
-
-    arg 1) The procattr we care about. 
-    arg 2) Which dir to start in.  By default, this is the same dir as
-          the parent currently resides in, when the createprocess call
-          is made. 
-
-=cut
- */
-ap_status_t ap_setprocattr_dir(ap_procattr_t *attr, const char *dir);
-
-/*
-
-=head1 ap_status_t ap_setprocattr_cmdtype(ap_procattr_t *attr, ap_cmdtype_e cmd)
-
-B<Set what type of command the child process will call.>
-
-    arg 1) The procattr we care about. 
-    arg 2) The type of command.  One of:
-              APR_SHELLCMD --  Shell script
-              APR_PROGRAM  --  Executable program   (default) 
-
-=cut
- */
-ap_status_t ap_setprocattr_cmdtype(ap_procattr_t *attr, ap_cmdtype_e cmd);
-
-/*
-
-=head1 ap_status_t ap_setprocattr_detach(ap_procattr_t *attr, ap_int32_t detach)
-
-B<Determine if the chlid should start in detached state.>
-
-    arg 1) The procattr we care about. 
-    arg 2) Should the child start in detached state?  Default is no. 
-
-=cut
- */
-ap_status_t ap_setprocattr_detach(ap_procattr_t *attr, ap_int32_t detach);
-
-/*
-
-=head1 ap_status_t ap_get_procdata(char *key, void *data, ap_proc_t *proc)
-
-B<Return the pool associated with the current proc.>
-
-    arg 1) The key associated with the data to retreive.
-    arg 2) The user data associated with the proc.
-    arg 3) The currently open proc.
-
-=cut
+/**
+ * The prototype for APR child errfn functions.  (See the description
+ * of apr_procattr_child_errfn_set() for more information.)
+ * It is passed the following parameters:
+ * @param pool Pool associated with the apr_proc_t.  If your child
+ *             error function needs user data, associate it with this
+ *             pool.
+ * @param err APR error code describing the error
+ * @param description Text description of type of processing which failed
  */
-ap_status_t ap_get_procdata(char *key, void *data, ap_proc_t *proc);
+typedef void (apr_child_errfn_t)(apr_pool_t *proc, apr_status_t err,
+                                 const char *description);
 
-/*
+/** Opaque Thread structure. */
+typedef struct apr_thread_t           apr_thread_t;
 
-=head1 ap_status_t ap_set_procdata(void *data, char *key, ap_status_t (*cleanup) (void *), ap_proc_t *proc)
+/** Opaque Thread attributes structure. */
+typedef struct apr_threadattr_t       apr_threadattr_t;
 
-B<Return the pool associated with the current proc.>
+/** Opaque Process attributes structure. */
+typedef struct apr_procattr_t         apr_procattr_t;
 
-    arg 1) The user data to associate with the file.
-    arg 2) The key to use for assocaiteing data with the file.
-    arg 3) The cleanup routine to use when the file is destroyed.
-    arg 4) The current process.
+/** Opaque control variable for one-time atomic variables.  */
+typedef struct apr_thread_once_t      apr_thread_once_t;
 
-=cut
- */
-ap_status_t ap_set_procdata(void *data, char *key,
-                            ap_status_t (*cleanup) (void *), ap_proc_t *proc);
-
-/*
-
-=head1 ap_status_t ap_get_childin(ap_file_t **new, ap_proc_t *proc) 
-
-B<Get the file handle that is assocaited with a child's stdin.>
+/** Opaque thread private address space. */
+typedef struct apr_threadkey_t        apr_threadkey_t;
 
-    arg 1) The returned file handle. 
-    arg 2) The process handle that corresponds to the desired child process 
+/** Opaque record of child process. */
+typedef struct apr_other_child_rec_t  apr_other_child_rec_t;
 
-=cut
+/**
+ * The prototype for any APR thread worker functions.
  */
-ap_status_t ap_get_childin(ap_file_t **new, ap_proc_t *proc);
-
-/*
-
-=head1 ap_status_t ap_get_childout(ap_file_t **new, ap_proc_t *proc) 
-
-B<Get the file handle that is assocaited with a child's stdout.>
+typedef void *(APR_THREAD_FUNC *apr_thread_start_t)(apr_thread_t*, void*);
 
-    arg 1) The returned file handle. 
-    arg 2) The process handle that corresponds to the desired child process 
+typedef enum {
+    APR_KILL_NEVER,             /**< process is never killed (i.e., never sent
+                                 * any signals), but it will be reaped if it exits
+                                 * before the pool is cleaned up */
+    APR_KILL_ALWAYS,            /**< process is sent SIGKILL on apr_pool_t cleanup */
+    APR_KILL_AFTER_TIMEOUT,     /**< SIGTERM, wait 3 seconds, SIGKILL */
+    APR_JUST_WAIT,              /**< wait forever for the process to complete */
+    APR_KILL_ONLY_ONCE          /**< send SIGTERM and then wait */
+} apr_kill_conditions_e;
 
-=cut
- */
-ap_status_t ap_get_childout(ap_file_t **new, ap_proc_t *proc);
-
-/*
+/* Thread Function definitions */
 
-=head1 ap_status_t ap_get_childerr(ap_file_t **new, ap_proc_t *proc) 
+#if APR_HAS_THREADS
+
+/**
+ * Create and initialize a new threadattr variable
+ * @param new_attr The newly created threadattr.
+ * @param cont The pool to use
+ */
+APR_DECLARE(apr_status_t) apr_threadattr_create(apr_threadattr_t **new_attr, 
+                                                apr_pool_t *cont);
+
+/**
+ * Set if newly created threads should be created in detached state.
+ * @param attr The threadattr to affect 
+ * @param on Non-zero if detached threads should be created.
+ */
+APR_DECLARE(apr_status_t) apr_threadattr_detach_set(apr_threadattr_t *attr, 
+                                                    apr_int32_t on);
+
+/**
+ * Get the detach state for this threadattr.
+ * @param attr The threadattr to reference
+ * @return APR_DETACH if threads are to be detached, or APR_NOTDETACH
+ * if threads are to be joinable. 
+ */
+APR_DECLARE(apr_status_t) apr_threadattr_detach_get(apr_threadattr_t *attr);
+
+/**
+ * Set the stack size of newly created threads.
+ * @param attr The threadattr to affect 
+ * @param stacksize The stack size in bytes
+ */
+APR_DECLARE(apr_status_t) apr_threadattr_stacksize_set(apr_threadattr_t *attr,
+                                                       apr_size_t stacksize);
+
+/**
+ * Set the stack guard area size of newly created threads.
+ * @param attr The threadattr to affect 
+ * @param guardsize The stack guard area size in bytes
+ * @note Thread library implementations commonly use a "guard area"
+ * after each thread's stack which is not readable or writable such that
+ * stack overflows cause a segfault; this consumes e.g. 4K of memory
+ * and increases memory management overhead.  Setting the guard area
+ * size to zero hence trades off reliable behaviour on stack overflow
+ * for performance. */
+APR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr,
+                                                       apr_size_t guardsize);
+
+/**
+ * Create a new thread of execution
+ * @param new_thread The newly created thread handle.
+ * @param attr The threadattr to use to determine how to create the thread
+ * @param func The function to start the new thread in
+ * @param data Any data to be passed to the starting function
+ * @param cont The pool to use
+ */
+APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new_thread, 
+                                            apr_threadattr_t *attr, 
+                                            apr_thread_start_t func, 
+                                            void *data, apr_pool_t *cont);
+
+/**
+ * stop the current thread
+ * @param thd The thread to stop
+ * @param retval The return value to pass back to any thread that cares
+ */
+APR_DECLARE(apr_status_t) apr_thread_exit(apr_thread_t *thd, 
+                                          apr_status_t retval);
+
+/**
+ * block until the desired thread stops executing.
+ * @param retval The return value from the dead thread.
+ * @param thd The thread to join
+ */
+APR_DECLARE(apr_status_t) apr_thread_join(apr_status_t *retval, 
+                                          apr_thread_t *thd); 
+
+/**
+ * force the current thread to yield the processor
+ */
+APR_DECLARE(void) apr_thread_yield(void);
+
+/**
+ * Initialize the control variable for apr_thread_once.  If this isn't
+ * called, apr_initialize won't work.
+ * @param control The control variable to initialize
+ * @param p The pool to allocate data from.
+ */
+APR_DECLARE(apr_status_t) apr_thread_once_init(apr_thread_once_t **control,
+                                               apr_pool_t *p);
+
+/**
+ * Run the specified function one time, regardless of how many threads
+ * call it.
+ * @param control The control variable.  The same variable should
+ *                be passed in each time the function is tried to be
+ *                called.  This is how the underlying functions determine
+ *                if the function has ever been called before.
+ * @param func The function to call.
+ */
+APR_DECLARE(apr_status_t) apr_thread_once(apr_thread_once_t *control,
+                                          void (*func)(void));
+
+/**
+ * detach a thread
+ * @param thd The thread to detach 
+ */
+APR_DECLARE(apr_status_t) apr_thread_detach(apr_thread_t *thd);
+
+/**
+ * Return user data associated with the current thread.
+ * @param data The user data associated with the thread.
+ * @param key The key to associate with the data
+ * @param thread The currently open thread.
+ */
+APR_DECLARE(apr_status_t) apr_thread_data_get(void **data, const char *key,
+                                             apr_thread_t *thread);
+
+/**
+ * Set user data associated with the current thread.
+ * @param data The user data to associate with the thread.
+ * @param key The key to use for associating the data with the thread
+ * @param cleanup The cleanup routine to use when the thread is destroyed.
+ * @param thread The currently open thread.
+ */
+APR_DECLARE(apr_status_t) apr_thread_data_set(void *data, const char *key,
+                                             apr_status_t (*cleanup) (void *),
+                                             apr_thread_t *thread);
+
+/**
+ * Create and initialize a new thread private address space
+ * @param key The thread private handle.
+ * @param dest The destructor to use when freeing the private memory.
+ * @param cont The pool to use
+ */
+APR_DECLARE(apr_status_t) apr_threadkey_private_create(apr_threadkey_t **key, 
+                                                    void (*dest)(void *),
+                                                    apr_pool_t *cont);
+
+/**
+ * Get a pointer to the thread private memory
+ * @param new_mem The data stored in private memory 
+ * @param key The handle for the desired thread private memory 
+ */
+APR_DECLARE(apr_status_t) apr_threadkey_private_get(void **new_mem, 
+                                                 apr_threadkey_t *key);
+
+/**
+ * Set the data to be stored in thread private memory
+ * @param priv The data to be stored in private memory 
+ * @param key The handle for the desired thread private memory 
+ */
+APR_DECLARE(apr_status_t) apr_threadkey_private_set(void *priv, 
+                                                 apr_threadkey_t *key);
+
+/**
+ * Free the thread private memory
+ * @param key The handle for the desired thread private memory 
+ */
+APR_DECLARE(apr_status_t) apr_threadkey_private_delete(apr_threadkey_t *key);
+
+/**
+ * Return the pool associated with the current threadkey.
+ * @param data The user data associated with the threadkey.
+ * @param key The key associated with the data
+ * @param threadkey The currently open threadkey.
+ */
+APR_DECLARE(apr_status_t) apr_threadkey_data_get(void **data, const char *key,
+                                                apr_threadkey_t *threadkey);
+
+/**
+ * Return the pool associated with the current threadkey.
+ * @param data The data to set.
+ * @param key The key to associate with the data.
+ * @param cleanup The cleanup routine to use when the file is destroyed.
+ * @param threadkey The currently open threadkey.
+ */
+APR_DECLARE(apr_status_t) apr_threadkey_data_set(void *data, const char *key,
+                                                apr_status_t (*cleanup) (void *),
+                                                apr_threadkey_t *threadkey);
 
-B<Get the file handle that is assocaited with a child's stderr.>
+#endif
 
-    arg 1) The returned file handle. 
-    arg 2) The process handle that corresponds to the desired child process 
+/**
+ * Create and initialize a new procattr variable
+ * @param new_attr The newly created procattr. 
+ * @param cont The pool to use
+ */
+APR_DECLARE(apr_status_t) apr_procattr_create(apr_procattr_t **new_attr,
+                                                  apr_pool_t *cont);
+
+/**
+ * Determine if any of stdin, stdout, or stderr should be linked to pipes 
+ * when starting a child process.
+ * @param attr The procattr we care about. 
+ * @param in Should stdin be a pipe back to the parent?
+ * @param out Should stdout be a pipe back to the parent?
+ * @param err Should stderr be a pipe back to the parent?
+ * @note If APR_NO_PIPE, there will be no special channel, the child
+ * inherits the parent's corresponding stdio stream.  If APR_NO_FILE is 
+ * specified, that corresponding stream is closed in the child (and will
+ * be INVALID_HANDLE_VALUE when inspected on Win32). This can have ugly 
+ * side effects, as the next file opened in the child on Unix will fall
+ * into the stdio stream fd slot!
+ */
+APR_DECLARE(apr_status_t) apr_procattr_io_set(apr_procattr_t *attr, 
+                                             apr_int32_t in, apr_int32_t out,
+                                             apr_int32_t err);
+
+/**
+ * Set the child_in and/or parent_in values to existing apr_file_t values.
+ * @param attr The procattr we care about. 
+ * @param child_in apr_file_t value to use as child_in. Must be a valid file.
+ * @param parent_in apr_file_t value to use as parent_in. Must be a valid file.
+ * @remark  This is NOT a required initializer function. This is
+ *          useful if you have already opened a pipe (or multiple files)
+ *          that you wish to use, perhaps persistently across multiple
+ *          process invocations - such as a log file. You can save some 
+ *          extra function calls by not creating your own pipe since this
+ *          creates one in the process space for you.
+ * @bug Note that calling this function with two NULL files on some platforms
+ * creates an APR_FULL_BLOCK pipe, but this behavior is neither portable nor
+ * is it supported.  @see apr_procattr_io_set instead for simple pipes.
+ */
+APR_DECLARE(apr_status_t) apr_procattr_child_in_set(struct apr_procattr_t *attr,
+                                                  apr_file_t *child_in,
+                                                  apr_file_t *parent_in);
+
+/**
+ * Set the child_out and parent_out values to existing apr_file_t values.
+ * @param attr The procattr we care about. 
+ * @param child_out apr_file_t value to use as child_out. Must be a valid file.
+ * @param parent_out apr_file_t value to use as parent_out. Must be a valid file.
+ * @remark This is NOT a required initializer function. This is
+ *         useful if you have already opened a pipe (or multiple files)
+ *         that you wish to use, perhaps persistently across multiple
+ *         process invocations - such as a log file. 
+ * @bug Note that calling this function with two NULL files on some platforms
+ * creates an APR_FULL_BLOCK pipe, but this behavior is neither portable nor
+ * is it supported.  @see apr_procattr_io_set instead for simple pipes.
+ */
+APR_DECLARE(apr_status_t) apr_procattr_child_out_set(struct apr_procattr_t *attr,
+                                                   apr_file_t *child_out,
+                                                   apr_file_t *parent_out);
+
+/**
+ * Set the child_err and parent_err values to existing apr_file_t values.
+ * @param attr The procattr we care about. 
+ * @param child_err apr_file_t value to use as child_err. Must be a valid file.
+ * @param parent_err apr_file_t value to use as parent_err. Must be a valid file.
+ * @remark This is NOT a required initializer function. This is
+ *         useful if you have already opened a pipe (or multiple files)
+ *         that you wish to use, perhaps persistently across multiple
+ *         process invocations - such as a log file. 
+ * @bug Note that calling this function with two NULL files on some platforms
+ * creates an APR_FULL_BLOCK pipe, but this behavior is neither portable nor
+ * is it supported.  @see apr_procattr_io_set instead for simple pipes.
+ */
+APR_DECLARE(apr_status_t) apr_procattr_child_err_set(struct apr_procattr_t *attr,
+                                                   apr_file_t *child_err,
+                                                   apr_file_t *parent_err);
+
+/**
+ * Set which directory the child process should start executing in.
+ * @param attr The procattr we care about. 
+ * @param dir Which dir to start in.  By default, this is the same dir as
+ *            the parent currently resides in, when the createprocess call
+ *            is made. 
+ */
+APR_DECLARE(apr_status_t) apr_procattr_dir_set(apr_procattr_t *attr, 
+                                              const char *dir);
+
+/**
+ * Set what type of command the child process will call.
+ * @param attr The procattr we care about. 
+ * @param cmd The type of command.  One of:
+ * <PRE>
+ *            APR_SHELLCMD     --  Anything that the shell can handle
+ *            APR_PROGRAM      --  Executable program   (default) 
+ *            APR_PROGRAM_ENV  --  Executable program, copy environment
+ *            APR_PROGRAM_PATH --  Executable program on PATH, copy env
+ * </PRE>
+ */
+APR_DECLARE(apr_status_t) apr_procattr_cmdtype_set(apr_procattr_t *attr,
+                                                  apr_cmdtype_e cmd);
+
+/**
+ * Determine if the child should start in detached state.
+ * @param attr The procattr we care about. 
+ * @param detach Should the child start in detached state?  Default is no. 
+ */
+APR_DECLARE(apr_status_t) apr_procattr_detach_set(apr_procattr_t *attr, 
+                                                 apr_int32_t detach);
+
+#if APR_HAVE_STRUCT_RLIMIT
+/**
+ * Set the Resource Utilization limits when starting a new process.
+ * @param attr The procattr we care about. 
+ * @param what Which limit to set, one of:
+ * <PRE>
+ *                 APR_LIMIT_CPU
+ *                 APR_LIMIT_MEM
+ *                 APR_LIMIT_NPROC
+ *                 APR_LIMIT_NOFILE
+ * </PRE>
+ * @param limit Value to set the limit to.
+ */
+APR_DECLARE(apr_status_t) apr_procattr_limit_set(apr_procattr_t *attr, 
+                                                apr_int32_t what,
+                                                struct rlimit *limit);
+#endif
 
-=cut
- */
-ap_status_t ap_get_childerr(ap_file_t **new, ap_proc_t *proc);
+/**
+ * Specify an error function to be called in the child process if APR
+ * encounters an error in the child prior to running the specified program.
+ * @param attr The procattr describing the child process to be created.
+ * @param errfn The function to call in the child process.
+ * @remark At the present time, it will only be called from apr_proc_create()
+ *         on platforms where fork() is used.  It will never be called on other
+ *         platforms, on those platforms apr_proc_create() will return the error
+ *         in the parent process rather than invoke the callback in the now-forked
+ *         child process.
+ */
+APR_DECLARE(apr_status_t) apr_procattr_child_errfn_set(apr_procattr_t *attr,
+                                                       apr_child_errfn_t *errfn);
+
+/**
+ * Specify that apr_proc_create() should do whatever it can to report
+ * failures to the caller of apr_proc_create(), rather than find out in
+ * the child.
+ * @param attr The procattr describing the child process to be created.
+ * @param chk Flag to indicate whether or not extra work should be done
+ *            to try to report failures to the caller.
+ * @remark This flag only affects apr_proc_create() on platforms where
+ *         fork() is used.  This leads to extra overhead in the calling
+ *         process, but that may help the application handle such
+ *         errors more gracefully.
+ */
+APR_DECLARE(apr_status_t) apr_procattr_error_check_set(apr_procattr_t *attr,
+                                                       apr_int32_t chk);
+
+/**
+ * Determine if the child should start in its own address space or using the 
+ * current one from its parent
+ * @param attr The procattr we care about. 
+ * @param addrspace Should the child start in its own address space?  Default
+ *                  is no on NetWare and yes on other platforms.
+ */
+APR_DECLARE(apr_status_t) apr_procattr_addrspace_set(apr_procattr_t *attr,
+                                                       apr_int32_t addrspace);
+
+/**
+ * Set the username used for running process
+ * @param attr The procattr we care about. 
+ * @param username The username used
+ * @param password User password if needed. Password is needed on WIN32
+ *                 or any other platform having
+ *                 APR_PROCATTR_USER_SET_REQUIRES_PASSWORD set.
+ */
+APR_DECLARE(apr_status_t) apr_procattr_user_set(apr_procattr_t *attr,
+                                                const char *username,
+                                                const char *password);
+
+/**
+ * Set the group used for running process
+ * @param attr The procattr we care about. 
+ * @param groupname The group name  used
+ */
+APR_DECLARE(apr_status_t) apr_procattr_group_set(apr_procattr_t *attr,
+                                                 const char *groupname);
+
+
+/**
+ * Register permission set function
+ * @param attr The procattr we care about. 
+ * @param perms_set_fn Permission set callback
+ * @param data Data to pass to permission callback function
+ * @param perms Permissions to set
+ */
+APR_DECLARE(apr_status_t) apr_procattr_perms_set_register(apr_procattr_t *attr,
+                                                 apr_perms_setfn_t *perms_set_fn,
+                                                 void *data,
+                                                 apr_fileperms_t perms);
 
 #if APR_HAS_FORK
-/*
-
-=head1 ap_status_t ap_fork(ap_proc_t **proc, ap_pool_t *cont) 
-
-B<This is currently the only non-portable call in APR.  This executes a standard unix fork.>
-
-    arg 1) The resulting process handle. 
-    arg 2) The pool to use. 
-
-=cut
- */
-ap_status_t ap_fork(ap_proc_t **proc, ap_pool_t *cont);
+/**
+ * This is currently the only non-portable call in APR.  This executes 
+ * a standard unix fork.
+ * @param proc The resulting process handle. 
+ * @param cont The pool to use. 
+ * @remark returns APR_INCHILD for the child, and APR_INPARENT for the parent
+ * or an error.
+ */
+APR_DECLARE(apr_status_t) apr_proc_fork(apr_proc_t *proc, apr_pool_t *cont);
 #endif
 
-/*
-
-=head1 ap_status_t ap_create_process(ap_proc_t **new, const char *progname, char *const args[], char **env, ap_procattr_t *attr, ap_pool_t *cont) 
-
-B<Create a new process and execute a new program within that process.>
-
-    arg 1) The resulting process handle.
-    arg 2) The program to run 
-    arg 3) the arguments to pass to the new program.  The first one should
-           be the program name.
-    arg 4) The new environment ap_table_t for the new process.  This should be a
-           list of NULL-terminated strings.
-    arg 5) the procattr we should use to determine how to create the new
-           process
-    arg 6) The pool to use. 
-
-=cut
- */
-ap_status_t ap_create_process(ap_proc_t **new, const char *progname, 
-                              char *const args[], char **env, 
-                              ap_procattr_t *attr, ap_pool_t *cont);
-
-/*
-
-=head1 ap_status_t ap_wait_proc(ap_proc_t *proc, ap_wait_how waithow) 
-
-B<Wait for a child process to die>
-
-    arg 1) The process handle that corresponds to the desired child process 
-    arg 2) How should we wait.  One of:
-              APR_WAIT   -- block until the child process dies.
-              APR_NOWAIT -- return immediately regardless of if the 
-                            child is dead or not.
-
-B<NOTE>:  The childs status is in the return code to this process.  It is 
-          one of:
-              APR_CHILD_DONE     -- child is no longer running.
-              APR_CHILD_NOTDONE  -- child is still running.
-
-=cut
- */
-ap_status_t ap_wait_proc(ap_proc_t *proc, ap_wait_how_e waithow);
-
-/*
-
-=head1 ap_status_t ap_detach(ap_proc_t **new, ap_pool_t *cont)
-
-B<Detach the process from the controlling terminal.>
-
-    arg 1) The new process handler
-    arg 2) The pool to use if it is needed.
-
-=cut
- */
-ap_status_t ap_detach(ap_proc_t **new, ap_pool_t *cont);
-
-/*
+/**
+ * Create a new process and execute a new program within that process.
+ * @param new_proc The resulting process handle.
+ * @param progname The program to run 
+ * @param args the arguments to pass to the new program.  The first 
+ *             one should be the program name.
+ * @param env The new environment table for the new process.  This 
+ *            should be a list of NULL-terminated strings. This argument
+ *            is ignored for APR_PROGRAM_ENV, APR_PROGRAM_PATH, and
+ *            APR_SHELLCMD_ENV types of commands.
+ * @param attr the procattr we should use to determine how to create the new
+ *         process
+ * @param pool The pool to use.
+ * @note This function returns without waiting for the new process to terminate;
+ * use apr_proc_wait for that.
+ */
+APR_DECLARE(apr_status_t) apr_proc_create(apr_proc_t *new_proc,
+                                          const char *progname,
+                                          const char * const *args,
+                                          const char * const *env, 
+                                          apr_procattr_t *attr, 
+                                          apr_pool_t *pool);
+
+/**
+ * Wait for a child process to die
+ * @param proc The process handle that corresponds to the desired child process 
+ * @param exitcode The returned exit status of the child, if a child process 
+ *                 dies, or the signal that caused the child to die.
+ *                 On platforms that don't support obtaining this information, 
+ *                 the status parameter will be returned as APR_ENOTIMPL.
+ * @param exitwhy Why the child died, the bitwise or of:
+ * <PRE>
+ *            APR_PROC_EXIT         -- process terminated normally
+ *            APR_PROC_SIGNAL       -- process was killed by a signal
+ *            APR_PROC_SIGNAL_CORE  -- process was killed by a signal, and
+ *                                     generated a core dump.
+ * </PRE>
+ * @param waithow How should we wait.  One of:
+ * <PRE>
+ *            APR_WAIT   -- block until the child process dies.
+ *            APR_NOWAIT -- return immediately regardless of if the 
+ *                          child is dead or not.
+ * </PRE>
+ * @remark The child's status is in the return code to this process.  It is one of:
+ * <PRE>
+ *            APR_CHILD_DONE     -- child is no longer running.
+ *            APR_CHILD_NOTDONE  -- child is still running.
+ * </PRE>
+ */
+APR_DECLARE(apr_status_t) apr_proc_wait(apr_proc_t *proc,
+                                        int *exitcode, apr_exit_why_e *exitwhy,
+                                        apr_wait_how_e waithow);
+
+/**
+ * Wait for any current child process to die and return information 
+ * about that child.
+ * @param proc Pointer to NULL on entry, will be filled out with child's 
+ *             information 
+ * @param exitcode The returned exit status of the child, if a child process 
+ *                 dies, or the signal that caused the child to die.
+ *                 On platforms that don't support obtaining this information, 
+ *                 the status parameter will be returned as APR_ENOTIMPL.
+ * @param exitwhy Why the child died, the bitwise or of:
+ * <PRE>
+ *            APR_PROC_EXIT         -- process terminated normally
+ *            APR_PROC_SIGNAL       -- process was killed by a signal
+ *            APR_PROC_SIGNAL_CORE  -- process was killed by a signal, and
+ *                                     generated a core dump.
+ * </PRE>
+ * @param waithow How should we wait.  One of:
+ * <PRE>
+ *            APR_WAIT   -- block until the child process dies.
+ *            APR_NOWAIT -- return immediately regardless of if the 
+ *                          child is dead or not.
+ * </PRE>
+ * @param p Pool to allocate child information out of.
+ * @bug Passing proc as a *proc rather than **proc was an odd choice
+ * for some platforms... this should be revisited in 1.0
+ */
+APR_DECLARE(apr_status_t) apr_proc_wait_all_procs(apr_proc_t *proc,
+                                                  int *exitcode,
+                                                  apr_exit_why_e *exitwhy,
+                                                  apr_wait_how_e waithow,
+                                                  apr_pool_t *p);
+
+#define APR_PROC_DETACH_FOREGROUND 0    /**< Do not detach */
+#define APR_PROC_DETACH_DAEMONIZE 1     /**< Detach */
+
+/**
+ * Detach the process from the controlling terminal.
+ * @param daemonize set to non-zero if the process should daemonize
+ *                  and become a background process, else it will
+ *                  stay in the foreground.
+ */
+APR_DECLARE(apr_status_t) apr_proc_detach(int daemonize);
+
+/**
+ * Register an other_child -- a child associated to its registered 
+ * maintence callback.  This callback is invoked when the process
+ * dies, is disconnected or disappears.
+ * @param proc The child process to register.
+ * @param maintenance maintenance is a function that is invoked with a 
+ *                    reason and the data pointer passed here.
+ * @param data Opaque context data passed to the maintenance function.
+ * @param write_fd This argument is currently unused and should be passed 
+ *                 as NULL.
+ * @param p The pool to use for allocating memory.
+ */
+APR_DECLARE(void) apr_proc_other_child_register(apr_proc_t *proc, 
+                                           void (*maintenance) (int reason, 
+                                                                void *, 
+                                                                int status),
+                                           void *data, apr_file_t *write_fd,
+                                           apr_pool_t *p);
+
+/**
+ * Stop watching the specified other child.  
+ * @param data The data to pass to the maintenance function.  This is
+ *             used to find the process to unregister.
+ * @warning Since this can be called by a maintenance function while we're
+ *          scanning the other_children list, all scanners should protect 
+ *          themself by loading ocr->next before calling any maintenance 
+ *          function.
+ */
+APR_DECLARE(void) apr_proc_other_child_unregister(void *data);
+
+/**
+ * Notify the maintenance callback of a registered other child process
+ * that application has detected an event, such as death.
+ * @param proc The process to check
+ * @param reason The reason code to pass to the maintenance function
+ * @param status The status to pass to the maintenance function
+ * @remark An example of code using this behavior;
+ * <pre>
+ * rv = apr_proc_wait_all_procs(&proc, &exitcode, &status, APR_WAIT, p);
+ * if (APR_STATUS_IS_CHILD_DONE(rv)) {
+ * \#if APR_HAS_OTHER_CHILD
+ *     if (apr_proc_other_child_alert(&proc, APR_OC_REASON_DEATH, status)
+ *             == APR_SUCCESS) {
+ *         ;  (already handled)
+ *     }
+ *     else
+ * \#endif
+ *         [... handling non-otherchild processes death ...]
+ * </pre>
+ */
+APR_DECLARE(apr_status_t) apr_proc_other_child_alert(apr_proc_t *proc, 
+                                                     int reason,
+                                                     int status);
+
+/**
+ * Test one specific other child processes and invoke the maintenance callback 
+ * with the appropriate reason code, if still running, or the appropriate reason 
+ * code if the process is no longer healthy.
+ * @param ocr The registered other child
+ * @param reason The reason code (e.g. APR_OC_REASON_RESTART) if still running
+ */
+APR_DECLARE(void) apr_proc_other_child_refresh(apr_other_child_rec_t *ocr,
+                                               int reason);
+
+/**
+ * Test all registered other child processes and invoke the maintenance callback 
+ * with the appropriate reason code, if still running, or the appropriate reason 
+ * code if the process is no longer healthy.
+ * @param reason The reason code (e.g. APR_OC_REASON_RESTART) to running processes
+ */
+APR_DECLARE(void) apr_proc_other_child_refresh_all(int reason);
+
+/** 
+ * Terminate a process.
+ * @param proc The process to terminate.
+ * @param sig How to kill the process.
+ */
+APR_DECLARE(apr_status_t) apr_proc_kill(apr_proc_t *proc, int sig);
+
+/**
+ * Register a process to be killed when a pool dies.
+ * @param a The pool to use to define the processes lifetime 
+ * @param proc The process to register
+ * @param how How to kill the process, one of:
+ * <PRE>
+ *         APR_KILL_NEVER         -- process is never sent any signals
+ *         APR_KILL_ALWAYS        -- process is sent SIGKILL on apr_pool_t cleanup
+ *         APR_KILL_AFTER_TIMEOUT -- SIGTERM, wait 3 seconds, SIGKILL
+ *         APR_JUST_WAIT          -- wait forever for the process to complete
+ *         APR_KILL_ONLY_ONCE     -- send SIGTERM and then wait
+ * </PRE>
+ */
+APR_DECLARE(void) apr_pool_note_subprocess(apr_pool_t *a, apr_proc_t *proc,
+                                           apr_kill_conditions_e how);
+
+#if APR_HAS_THREADS 
+
+#if (APR_HAVE_SIGWAIT || APR_HAVE_SIGSUSPEND) && !defined(OS2)
+
+/**
+ * Setup the process for a single thread to be used for all signal handling.
+ * @warning This must be called before any threads are created
+ */
+APR_DECLARE(apr_status_t) apr_setup_signal_thread(void);
+
+/**
+ * Make the current thread listen for signals.  This thread will loop
+ * forever, calling a provided function whenever it receives a signal.  That
+ * functions should return 1 if the signal has been handled, 0 otherwise.
+ * @param signal_handler The function to call when a signal is received
+ * apr_status_t apr_signal_thread((int)(*signal_handler)(int signum))
+ */
+APR_DECLARE(apr_status_t) apr_signal_thread(int(*signal_handler)(int signum));
+
+#endif /* (APR_HAVE_SIGWAIT || APR_HAVE_SIGSUSPEND) && !defined(OS2) */
+
+/**
+ * Get the child-pool used by the thread from the thread info.
+ * @return apr_pool_t the pool
+ */
+APR_POOL_DECLARE_ACCESSOR(thread);
+
+#endif /* APR_HAS_THREADS */
+
+/** @} */
 
-=head1 void ap_register_other_child(ap_proc_t *pid, void (*maintenance) (int reason, void *data, int status), void *data, int write_fd, ap_pool_t *p)
-
-B<Register an other_child -- a child which must be kept track of so that the program knows when it has dies or disappeared.>
-
-    arg 1)  pid is the pid of the child.
-    arg 2)  maintenance is a function that is invoked with a reason and the
-            data pointer passed here.
-    arg 3)  The data to pass to the maintenance function.
-    arg 4)  An fd that is probed for writing.  If it is ever unwritable
-            then the maintenance is invoked with reason OC_REASON_UNWRITABLE.
-    arg 5)  The pool to use for allocating memory.
-
-=cut
- */
-/* XXX: it's not clear how write_fd can be made portable -- i think this
- * needs to take an ap_file_t, expecting the write_fd to be a pipe. -dean
- */
-void ap_register_other_child(ap_proc_t *pid, 
-                             void (*maintenance) (int reason, void *, int status),
-                             void *data, int write_fd, ap_pool_t *p);
-
-/*
-
-=head1 void ap_unregister_other_child(void *data)
-
-B<Stop watching the specified process.>
-
-    arg 1) The data to pass to the maintenance function.  This is
-           used to find the process to unregister.
-
-B<NOTE>:  Since this can be called by a maintenance function while we're
-          scanning the other_children list, all scanners should protect 
-          themself by loading ocr->next before calling any maintenance 
-          function.
-
-=cut
- */
-void ap_unregister_other_children(void *data);
-
-/*
-
-=head1 ap_status_t ap_reap_other_child(ap_proc_t *pid, int status)
-
-B<Check on the specified process.  If it is gone, call the maintenance function.>
-
-    arg 1) The process to check.
-
-=cut
- */
-ap_status_t ap_reap_other_child(ap_proc_t *pid, int status); 
-
-/*
-
-=head1 void ap_check_other_child(void)
-
-B<Loop through all registered other_children and call the appropriate maintenance function when necessary.>
-
-=cut
- */
-void ap_check_other_child(void); 
-
-/*
-
-=head1 ap_status_t ap_kill(ap_proc_t *proc, int sig)
-
-B<Terminate a process.>
-
-    arg 1) The process to terminate.
-    arg 2) How to kill the process.
-
-=cut
- */
-ap_status_t ap_kill(ap_proc_t *proc, int sig);
 #ifdef __cplusplus
 }
 #endif
 
-#endif  /* ! APR_FILE_IO_H */
+#endif  /* ! APR_THREAD_PROC_H */
 
diff --git a/include/apr_thread_rwlock.h b/include/apr_thread_rwlock.h
new file mode 100644
index 00000000000..0bd958fbfa3
--- /dev/null
+++ b/include/apr_thread_rwlock.h
@@ -0,0 +1,129 @@
+/* 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 APR_THREAD_RWLOCK_H
+#define APR_THREAD_RWLOCK_H
+
+/**
+ * @file apr_thread_rwlock.h
+ * @brief APR Reader/Writer Lock Routines
+ */
+
+#include "apr.h"
+#include "apr_pools.h"
+#include "apr_errno.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#if APR_HAS_THREADS
+
+/**
+ * @defgroup apr_thread_rwlock Reader/Writer Lock Routines
+ * @ingroup APR 
+ * @{
+ */
+
+/** Opaque read-write thread-safe lock. */
+typedef struct apr_thread_rwlock_t apr_thread_rwlock_t;
+
+/**
+ * Note: The following operations have undefined results: unlocking a
+ * read-write lock which is not locked in the calling thread; write
+ * locking a read-write lock which is already locked by the calling
+ * thread; destroying a read-write lock more than once; clearing or
+ * destroying the pool from which a <b>locked</b> read-write lock is
+ * allocated.
+ */
+
+/**
+ * Create and initialize a read-write lock that can be used to synchronize
+ * threads.
+ * @param rwlock the memory address where the newly created readwrite lock
+ *        will be stored.
+ * @param pool the pool from which to allocate the mutex.
+ */
+APR_DECLARE(apr_status_t) apr_thread_rwlock_create(apr_thread_rwlock_t **rwlock,
+                                                   apr_pool_t *pool);
+/**
+ * Acquire a shared-read lock on the given read-write lock. This will allow
+ * multiple threads to enter the same critical section while they have acquired
+ * the read lock.
+ * @param rwlock the read-write lock on which to acquire the shared read.
+ */
+APR_DECLARE(apr_status_t) apr_thread_rwlock_rdlock(apr_thread_rwlock_t *rwlock);
+
+/**
+ * Attempt to acquire the shared-read lock on the given read-write lock. This
+ * is the same as apr_thread_rwlock_rdlock(), only that the function fails
+ * if there is another thread holding the write lock, or if there are any
+ * write threads blocking on the lock. If the function fails for this case,
+ * APR_EBUSY will be returned. Note: it is important that the
+ * APR_STATUS_IS_EBUSY(s) macro be used to determine if the return value was
+ * APR_EBUSY, for portability reasons.
+ * @param rwlock the rwlock on which to attempt the shared read.
+ */
+APR_DECLARE(apr_status_t) apr_thread_rwlock_tryrdlock(apr_thread_rwlock_t *rwlock);
+
+/**
+ * Acquire an exclusive-write lock on the given read-write lock. This will
+ * allow only one single thread to enter the critical sections. If there
+ * are any threads currently holding the read-lock, this thread is put to
+ * sleep until it can have exclusive access to the lock.
+ * @param rwlock the read-write lock on which to acquire the exclusive write.
+ */
+APR_DECLARE(apr_status_t) apr_thread_rwlock_wrlock(apr_thread_rwlock_t *rwlock);
+
+/**
+ * Attempt to acquire the exclusive-write lock on the given read-write lock. 
+ * This is the same as apr_thread_rwlock_wrlock(), only that the function fails
+ * if there is any other thread holding the lock (for reading or writing),
+ * in which case the function will return APR_EBUSY. Note: it is important
+ * that the APR_STATUS_IS_EBUSY(s) macro be used to determine if the return
+ * value was APR_EBUSY, for portability reasons.
+ * @param rwlock the rwlock on which to attempt the exclusive write.
+ */
+APR_DECLARE(apr_status_t) apr_thread_rwlock_trywrlock(apr_thread_rwlock_t *rwlock);
+
+/**
+ * Release either the read or write lock currently held by the calling thread
+ * associated with the given read-write lock.
+ * @param rwlock the read-write lock to be released (unlocked).
+ */
+APR_DECLARE(apr_status_t) apr_thread_rwlock_unlock(apr_thread_rwlock_t *rwlock);
+
+/**
+ * Destroy the read-write lock and free the associated memory.
+ * @param rwlock the rwlock to destroy.
+ */
+APR_DECLARE(apr_status_t) apr_thread_rwlock_destroy(apr_thread_rwlock_t *rwlock);
+
+/**
+ * Get the pool used by this thread_rwlock.
+ * @return apr_pool_t the pool
+ */
+APR_POOL_DECLARE_ACCESSOR(thread_rwlock);
+
+#endif  /* APR_HAS_THREADS */
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* ! APR_THREAD_RWLOCK_H */
diff --git a/include/apr_time.h b/include/apr_time.h
index e38cdb84b75..b0efd791c98 100644
--- a/include/apr_time.h
+++ b/include/apr_time.h
@@ -1,183 +1,234 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 APR_TIME_H
 #define APR_TIME_H
 
-#include "apr_general.h"
+/**
+ * @file apr_time.h
+ * @brief APR Time Library
+ */
+
+#include "apr.h"
 #include "apr_errno.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif /* __cplusplus */
 
-API_VAR_IMPORT const char ap_month_snames[12][4];
-API_VAR_IMPORT const char ap_day_snames[7][4];
-
-/* number of microseconds since 00:00:00 january 1, 1970 UTC */
-typedef ap_int64_t ap_time_t;
-
-/* intervals for I/O timeouts, in microseconds */
-typedef ap_int32_t ap_interval_time_t;
-
-#ifdef WIN32
-#define AP_USEC_PER_SEC ((LONGLONG) 1000000)
-#else
-/* XXX: this is wrong -- the LL is only required if int64 is implemented as
- * a long long, it could be just a long on some platforms.  the C99
- * correct way of doing this is to use INT64_C(1000000) which comes
- * from stdint.h.  we'd probably be doing a Good Thing to check for
- * INT64_C in autoconf... or otherwise define an AP_INT64_C(). -dean
- */
-#define AP_USEC_PER_SEC (1000000LL)
-#endif
-
-/*
-
-=head1 ap_time_t ap_now(void)
-
-B<return the current time>
-
-=cut
+/**
+ * @defgroup apr_time Time Routines
+ * @ingroup APR 
+ * @{
  */
-ap_time_t ap_now(void);
 
-/* a structure similar to ANSI struct tm with the following differences:
-   - tm_usec isn't an ANSI field
-   - tm_gmtoff isn't an ANSI field (it's a bsdism)
-*/
-typedef struct {
-    ap_int32_t tm_usec;	/* microseconds past tm_sec */
-    ap_int32_t tm_sec;	/* (0-61) seconds past tm_min */
-    ap_int32_t tm_min;  /* (0-59) minutes past tm_hour */
-    ap_int32_t tm_hour; /* (0-23) hours past midnight */
-    ap_int32_t tm_mday; /* (1-31) day of the month */
-    ap_int32_t tm_mon;  /* (0-11) month of the year */
-    ap_int32_t tm_year; /* year since 1900 */
-    ap_int32_t tm_wday; /* (0-6) days since sunday */
-    ap_int32_t tm_yday; /* (0-365) days since jan 1 */
-    ap_int32_t tm_isdst; /* daylight saving time */
-    ap_int32_t tm_gmtoff; /* seconds east of UTC */
-} ap_exploded_time_t;
+/** month names */
+APR_DECLARE_DATA extern const char apr_month_snames[12][4];
+/** day names */
+APR_DECLARE_DATA extern const char apr_day_snames[7][4];
 
-/*
 
-=head1 ap_status_t ap_ansi_time_to_ap_time(ap_time_t *result, time_t input)
+/** number of microseconds since 00:00:00 January 1, 1970 UTC */
+typedef apr_int64_t apr_time_t;
 
-B<convert an ansi time_t to an ap_time_t>
 
-    arg 1) the resulting ap_time_t
-    arg 2) the time_t to convert
+/** mechanism to properly type apr_time_t literals */
+#define APR_TIME_C(val) APR_INT64_C(val)
 
-=cut
- */
-ap_status_t ap_ansi_time_to_ap_time(ap_time_t *result, time_t input);
+/** mechanism to properly print apr_time_t values */
+#define APR_TIME_T_FMT APR_INT64_T_FMT
 
-/*
+/** intervals for I/O timeouts, in microseconds */
+typedef apr_int64_t apr_interval_time_t;
+/** short interval for I/O timeouts, in microseconds */
+typedef apr_int32_t apr_short_interval_time_t;
 
-=head1 ap_status_t ap_explode_gmt(ap_exploded_time_t *result, ap_time_t input)
+/** number of microseconds per second */
+#define APR_USEC_PER_SEC APR_TIME_C(1000000)
 
-B<convert a time to its human readable components in GMT timezone>
+/** @return apr_time_t as a second */
+#define apr_time_sec(time) ((time) / APR_USEC_PER_SEC)
 
-    arg 1) the exploded time
-    arg 2) the time to explode
+/** @return apr_time_t as a usec */
+#define apr_time_usec(time) ((time) % APR_USEC_PER_SEC)
 
-=cut
- */
-ap_status_t ap_explode_gmt(ap_exploded_time_t *result, ap_time_t input);
+/** @return apr_time_t as a msec */
+#define apr_time_msec(time) (((time) / 1000) % 1000)
 
-/*
+/** @return apr_time_t as a msec */
+#define apr_time_as_msec(time) ((time) / 1000)
 
-=head1 ap_status_t ap_explode_localtime(ap_exploded_time_t *result, ap_time_t input)
+/** @return milliseconds as an apr_time_t */
+#define apr_time_from_msec(msec) ((apr_time_t)(msec) * 1000)
 
-B<convert a time to its human readable components in local timezone>
+/** @return seconds as an apr_time_t */
+#define apr_time_from_sec(sec) ((apr_time_t)(sec) * APR_USEC_PER_SEC)
 
-    arg 1) the exploded time
-    arg 2) the time to explode
+/** @return a second and usec combination as an apr_time_t */
+#define apr_time_make(sec, usec) ((apr_time_t)(sec) * APR_USEC_PER_SEC \
+                                + (apr_time_t)(usec))
 
-=cut
+/**
+ * @return the current time
  */
-ap_status_t ap_explode_localtime(ap_exploded_time_t *result, ap_time_t input);
-
-/*
-
-=head1 ap_status_t ap_implode_time(ap_time_t *t, ap_exploded_time_t *xt)
+APR_DECLARE(apr_time_t) apr_time_now(void);
 
-B<Convert time value from human readable format to number of seconds since epoch>
+/** @see apr_time_exp_t */
+typedef struct apr_time_exp_t apr_time_exp_t;
 
-    arg 1) the resulting imploded time
-    arg 2) the input exploded time
-
-=cut
+/**
+ * a structure similar to ANSI struct tm with the following differences:
+ *  - tm_usec isn't an ANSI field
+ *  - tm_gmtoff isn't an ANSI field (it's a BSDism)
+ */
+struct apr_time_exp_t {
+    /** microseconds past tm_sec */
+    apr_int32_t tm_usec;
+    /** (0-61) seconds past tm_min */
+    apr_int32_t tm_sec;
+    /** (0-59) minutes past tm_hour */
+    apr_int32_t tm_min;
+    /** (0-23) hours past midnight */
+    apr_int32_t tm_hour;
+    /** (1-31) day of the month */
+    apr_int32_t tm_mday;
+    /** (0-11) month of the year */
+    apr_int32_t tm_mon;
+    /** year since 1900 */
+    apr_int32_t tm_year;
+    /** (0-6) days since Sunday */
+    apr_int32_t tm_wday;
+    /** (0-365) days since January 1 */
+    apr_int32_t tm_yday;
+    /** daylight saving time */
+    apr_int32_t tm_isdst;
+    /** seconds east of UTC */
+    apr_int32_t tm_gmtoff;
+};
+
+/* Delayed the include to avoid a circular reference */
+#include "apr_pools.h"
+
+/**
+ * Convert an ansi time_t to an apr_time_t
+ * @param result the resulting apr_time_t
+ * @param input the time_t to convert
+ */
+APR_DECLARE(apr_status_t) apr_time_ansi_put(apr_time_t *result, 
+                                                    time_t input);
+
+/**
+ * Convert a time to its human readable components using an offset
+ * from GMT.
+ * @param result the exploded time
+ * @param input the time to explode
+ * @param offs the number of seconds offset to apply
+ */
+APR_DECLARE(apr_status_t) apr_time_exp_tz(apr_time_exp_t *result,
+                                          apr_time_t input,
+                                          apr_int32_t offs);
+
+/**
+ * Convert a time to its human readable components (GMT).
+ * @param result the exploded time
+ * @param input the time to explode
  */
-ap_status_t ap_implode_time(ap_time_t *result, ap_exploded_time_t *input);
+APR_DECLARE(apr_status_t) apr_time_exp_gmt(apr_time_exp_t *result, 
+                                           apr_time_t input);
 
-/* ap_rfc822_date formats dates in the RFC822
-   format in an efficient manner.  it is a fixed length
-   format and requires the indicated amount of storage
-   including trailing \0 */
-#define AP_RFC822_DATE_LEN (30)
-ap_status_t ap_rfc822_date(char *date_str, ap_time_t t);
+/**
+ * Convert a time to its human readable components in the local timezone.
+ * @param result the exploded time
+ * @param input the time to explode
+ */
+APR_DECLARE(apr_status_t) apr_time_exp_lt(apr_time_exp_t *result, 
+                                          apr_time_t input);
+
+/**
+ * Convert time value from human readable format to a numeric apr_time_t
+ * (elapsed microseconds since the epoch).
+ * @param result the resulting imploded time
+ * @param input the input exploded time
+ */
+APR_DECLARE(apr_status_t) apr_time_exp_get(apr_time_t *result, 
+                                           apr_time_exp_t *input);
+
+/**
+ * Convert time value from human readable format to a numeric apr_time_t that
+ * always represents GMT.
+ * @param result the resulting imploded time
+ * @param input the input exploded time
+ */
+APR_DECLARE(apr_status_t) apr_time_exp_gmt_get(apr_time_t *result, 
+                                               apr_time_exp_t *input);
 
-/* ap_ctime formats dates in the ctime() format
-   in an efficient manner.  it is a fixed length format
-   and requires the indicated amount of storage
-   including trailing \0 */
-#define AP_CTIME_LEN (25)
-ap_status_t ap_ctime(char *date_str, ap_time_t t);
+/**
+ * Sleep for the specified number of micro-seconds.
+ * @param t desired amount of time to sleep.
+ * @warning May sleep for longer than the specified time. 
+ */
+APR_DECLARE(void) apr_sleep(apr_interval_time_t t);
+
+/** length of a RFC822 Date */
+#define APR_RFC822_DATE_LEN (30)
+/**
+ * apr_rfc822_date formats dates in the RFC822
+ * format in an efficient manner.  It is a fixed length
+ * format which requires APR_RFC822_DATA_LEN bytes of storage,
+ * including the trailing NUL terminator.
+ * @param date_str String to write to.
+ * @param t the time to convert 
+ */
+APR_DECLARE(apr_status_t) apr_rfc822_date(char *date_str, apr_time_t t);
+
+/** length of a CTIME date */
+#define APR_CTIME_LEN (25)
+/**
+ * apr_ctime formats dates in the ctime() format
+ * in an efficient manner.  It is a fixed length format
+ * and requires APR_CTIME_LEN bytes of storage including
+ * the trailing NUL terminator.
+ * Unlike ANSI/ISO C ctime(), apr_ctime() does not include
+ * a \\n at the end of the string.
+ * @param date_str String to write to.
+ * @param t the time to convert 
+ */
+APR_DECLARE(apr_status_t) apr_ctime(char *date_str, apr_time_t t);
+
+/**
+ * Formats the exploded time according to the format specified
+ * @param s string to write to
+ * @param retsize The length of the returned string
+ * @param max The maximum length of the string
+ * @param format The format for the time string
+ * @param tm The time to convert
+ */
+APR_DECLARE(apr_status_t) apr_strftime(char *s, apr_size_t *retsize, 
+                                       apr_size_t max, const char *format, 
+                                       apr_time_exp_t *tm);
+
+/**
+ * Improve the clock resolution for the lifetime of the given pool.
+ * Generally this is only desirable on benchmarking and other very
+ * time-sensitive applications, and has no impact on most platforms.
+ * @param p The pool to associate the finer clock resolution 
+ */
+APR_DECLARE(void) apr_time_clock_hires(apr_pool_t *p);
 
-ap_status_t ap_strftime(char *s, ap_size_t *retsize, ap_size_t max, const char *format, ap_exploded_time_t *tm);
+/** @} */
 
 #ifdef __cplusplus
 }
diff --git a/include/apr_uri.h b/include/apr_uri.h
new file mode 100644
index 00000000000..25ad8f281af
--- /dev/null
+++ b/include/apr_uri.h
@@ -0,0 +1,178 @@
+/* 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.
+ */
+
+/*
+ * apr_uri.h: External Interface of apr_uri.c
+ */
+
+/**
+ * @file apr_uri.h
+ * @brief APR-UTIL URI Routines
+ */
+
+#ifndef APR_URI_H
+#define APR_URI_H
+
+#include "apu.h"
+
+#include "apr_network_io.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup APR_Util_URI URI
+ * @ingroup APR
+ * @{
+ */
+
+#define APR_URI_FTP_DEFAULT_PORT         21 /**< default FTP port */
+#define APR_URI_SSH_DEFAULT_PORT         22 /**< default SSH port */
+#define APR_URI_TELNET_DEFAULT_PORT      23 /**< default telnet port */
+#define APR_URI_GOPHER_DEFAULT_PORT      70 /**< default Gopher port */
+#define APR_URI_HTTP_DEFAULT_PORT        80 /**< default HTTP port */
+#define APR_URI_POP_DEFAULT_PORT        110 /**< default POP port */
+#define APR_URI_NNTP_DEFAULT_PORT       119 /**< default NNTP port */
+#define APR_URI_IMAP_DEFAULT_PORT       143 /**< default IMAP port */
+#define APR_URI_PROSPERO_DEFAULT_PORT   191 /**< default Prospero port */
+#define APR_URI_WAIS_DEFAULT_PORT       210 /**< default WAIS port */
+#define APR_URI_LDAP_DEFAULT_PORT       389 /**< default LDAP port */
+#define APR_URI_HTTPS_DEFAULT_PORT      443 /**< default HTTPS port */
+#define APR_URI_RTSP_DEFAULT_PORT       554 /**< default RTSP port */
+#define APR_URI_SNEWS_DEFAULT_PORT      563 /**< default SNEWS port */
+#define APR_URI_ACAP_DEFAULT_PORT       674 /**< default ACAP port */
+#define APR_URI_NFS_DEFAULT_PORT       2049 /**< default NFS port */
+#define APR_URI_TIP_DEFAULT_PORT       3372 /**< default TIP port */
+#define APR_URI_SIP_DEFAULT_PORT       5060 /**< default SIP port */
+
+/** Flags passed to unparse_uri_components(): */
+/** suppress "scheme://user\@site:port" */
+#define APR_URI_UNP_OMITSITEPART    (1U<<0)
+/** Just omit user */
+#define APR_URI_UNP_OMITUSER        (1U<<1)
+/** Just omit password */
+#define APR_URI_UNP_OMITPASSWORD    (1U<<2)
+/** omit "user:password\@" part */
+#define APR_URI_UNP_OMITUSERINFO    (APR_URI_UNP_OMITUSER | \
+                                     APR_URI_UNP_OMITPASSWORD)
+/** Show plain text password (default: show XXXXXXXX) */
+#define APR_URI_UNP_REVEALPASSWORD  (1U<<3)
+/** Show "scheme://user\@site:port" only */
+#define APR_URI_UNP_OMITPATHINFO    (1U<<4)
+/** Omit the "?queryarg" from the path */
+#define APR_URI_UNP_OMITQUERY       (1U<<5)
+
+/** @see apr_uri_t */
+typedef struct apr_uri_t apr_uri_t;
+
+/**
+ * A structure to encompass all of the fields in a uri
+ */
+struct apr_uri_t {
+    /** scheme ("http"/"ftp"/...) */
+    char *scheme;
+    /** combined [user[:password]\@]host[:port] */
+    char *hostinfo;
+    /** user name, as in http://user:passwd\@host:port/ */
+    char *user;
+    /** password, as in http://user:passwd\@host:port/ */
+    char *password;
+    /** hostname from URI (or from Host: header) */
+    char *hostname;
+    /** port string (integer representation is in "port") */
+    char *port_str;
+    /** the request path (or NULL if only scheme://host was given) */
+    char *path;
+    /** Everything after a '?' in the path, if present */
+    char *query;
+    /** Trailing "#fragment" string, if present */
+    char *fragment;
+
+    /** structure returned from gethostbyname() */
+    struct hostent *hostent;
+
+    /** The port number, numeric, valid only if port_str != NULL */
+    apr_port_t port;
+    
+    /** has the structure been initialized */
+    unsigned is_initialized:1;
+
+    /** has the DNS been looked up yet */
+    unsigned dns_looked_up:1;
+    /** has the dns been resolved yet */
+    unsigned dns_resolved:1;
+};
+
+/* apr_uri.c */
+/**
+ * Return the default port for a given scheme.  The schemes recognized are
+ * http, ftp, https, gopher, wais, nntp, snews, and prospero
+ * @param scheme_str The string that contains the current scheme
+ * @return The default port for this scheme
+ */ 
+APR_DECLARE(apr_port_t) apr_uri_port_of_scheme(const char *scheme_str);
+
+/**
+ * Unparse a apr_uri_t structure to an URI string.  Optionally 
+ * suppress the password for security reasons.
+ * @param p The pool to allocate out of
+ * @param uptr All of the parts of the uri
+ * @param flags How to unparse the uri.  One of:
+ * <PRE>
+ *    APR_URI_UNP_OMITSITEPART        Suppress "scheme://user\@site:port" 
+ *    APR_URI_UNP_OMITUSER            Just omit user 
+ *    APR_URI_UNP_OMITPASSWORD        Just omit password 
+ *    APR_URI_UNP_OMITUSERINFO        Omit "user:password\@" part
+ *    APR_URI_UNP_REVEALPASSWORD      Show plain text password (default: show XXXXXXXX)
+ *    APR_URI_UNP_OMITPATHINFO        Show "scheme://user\@site:port" only 
+ *    APR_URI_UNP_OMITQUERY           Omit "?queryarg" or "#fragment" 
+ * </PRE>
+ * @return The uri as a string
+ */
+APR_DECLARE(char *) apr_uri_unparse(apr_pool_t *p, 
+                                    const apr_uri_t *uptr,
+                                    unsigned flags);
+
+/**
+ * Parse a given URI, fill in all supplied fields of a apr_uri_t
+ * structure. This eliminates the necessity of extracting host, port,
+ * path, query info repeatedly in the modules.
+ * @param p The pool to allocate out of
+ * @param uri The uri to parse
+ * @param uptr The apr_uri_t to fill out
+ * @return APR_SUCCESS for success or error code
+ */
+APR_DECLARE(apr_status_t) apr_uri_parse(apr_pool_t *p, const char *uri, 
+                                        apr_uri_t *uptr);
+
+/**
+ * Special case for CONNECT parsing: it comes with the hostinfo part only
+ * @param p The pool to allocate out of
+ * @param hostinfo The hostinfo string to parse
+ * @param uptr The apr_uri_t to fill out
+ * @return APR_SUCCESS for success or error code
+ */
+APR_DECLARE(apr_status_t) apr_uri_parse_hostinfo(apr_pool_t *p, 
+                                                 const char *hostinfo, 
+                                                 apr_uri_t *uptr);
+
+/** @} */
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* APR_URI_H */
diff --git a/include/apr_user.h b/include/apr_user.h
new file mode 100644
index 00000000000..0e0a3ac5ac5
--- /dev/null
+++ b/include/apr_user.h
@@ -0,0 +1,158 @@
+/* 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 APR_USER_H
+#define APR_USER_H
+
+/**
+ * @file apr_user.h
+ * @brief APR User ID Services 
+ */
+
+#include "apr.h"
+#include "apr_errno.h"
+#include "apr_pools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup apr_user User and Group ID Services
+ * @ingroup APR 
+ * @{
+ */
+
+/**
+ * Structure for determining user ownership.
+ */
+#ifdef WIN32
+typedef PSID                      apr_uid_t;
+#else
+typedef uid_t                     apr_uid_t;
+#endif
+
+/**
+ * Structure for determining group ownership.
+ */
+#ifdef WIN32
+typedef PSID                      apr_gid_t;
+#else
+typedef gid_t                     apr_gid_t;
+#endif
+
+#if APR_HAS_USER 
+
+/**
+ * Get the userid (and groupid) of the calling process
+ * @param userid   Returns the user id
+ * @param groupid  Returns the user's group id
+ * @param p The pool from which to allocate working space
+ * @remark This function is available only if APR_HAS_USER is defined.
+ */
+APR_DECLARE(apr_status_t) apr_uid_current(apr_uid_t *userid,
+                                          apr_gid_t *groupid,
+                                          apr_pool_t *p);
+
+/**
+ * Get the user name for a specified userid
+ * @param username Pointer to new string containing user name (on output)
+ * @param userid The userid
+ * @param p The pool from which to allocate the string
+ * @remark This function is available only if APR_HAS_USER is defined.
+ */
+APR_DECLARE(apr_status_t) apr_uid_name_get(char **username, apr_uid_t userid,
+                                           apr_pool_t *p);
+
+/**
+ * Get the userid (and groupid) for the specified username
+ * @param userid   Returns the user id
+ * @param groupid  Returns the user's group id
+ * @param username The username to look up
+ * @param p The pool from which to allocate working space
+ * @remark This function is available only if APR_HAS_USER is defined.
+ */
+APR_DECLARE(apr_status_t) apr_uid_get(apr_uid_t *userid, apr_gid_t *groupid,
+                                      const char *username, apr_pool_t *p);
+
+/**
+ * Get the home directory for the named user
+ * @param dirname Pointer to new string containing directory name (on output)
+ * @param username The named user
+ * @param p The pool from which to allocate the string
+ * @remark This function is available only if APR_HAS_USER is defined.
+ */
+APR_DECLARE(apr_status_t) apr_uid_homepath_get(char **dirname, 
+                                               const char *username, 
+                                               apr_pool_t *p);
+
+/**
+ * Compare two user identifiers for equality.
+ * @param left One uid to test
+ * @param right Another uid to test
+ * @return APR_SUCCESS if the apr_uid_t structures identify the same user,
+ * APR_EMISMATCH if not, APR_BADARG if an apr_uid_t is invalid.
+ * @remark This function is available only if APR_HAS_USER is defined.
+ */
+#if defined(WIN32)
+APR_DECLARE(apr_status_t) apr_uid_compare(apr_uid_t left, apr_uid_t right);
+#else
+#define apr_uid_compare(left,right) (((left) == (right)) ? APR_SUCCESS : APR_EMISMATCH)
+#endif
+
+/**
+ * Get the group name for a specified groupid
+ * @param groupname Pointer to new string containing group name (on output)
+ * @param groupid The groupid
+ * @param p The pool from which to allocate the string
+ * @remark This function is available only if APR_HAS_USER is defined.
+ */
+APR_DECLARE(apr_status_t) apr_gid_name_get(char **groupname, 
+                                             apr_gid_t groupid, apr_pool_t *p);
+
+/**
+ * Get the groupid for a specified group name
+ * @param groupid Pointer to the group id (on output)
+ * @param groupname The group name to look up
+ * @param p The pool from which to allocate the string
+ * @remark This function is available only if APR_HAS_USER is defined.
+ */
+APR_DECLARE(apr_status_t) apr_gid_get(apr_gid_t *groupid, 
+                                      const char *groupname, apr_pool_t *p);
+
+/**
+ * Compare two group identifiers for equality.
+ * @param left One gid to test
+ * @param right Another gid to test
+ * @return APR_SUCCESS if the apr_gid_t structures identify the same group,
+ * APR_EMISMATCH if not, APR_BADARG if an apr_gid_t is invalid.
+ * @remark This function is available only if APR_HAS_USER is defined.
+ */
+#if defined(WIN32)
+APR_DECLARE(apr_status_t) apr_gid_compare(apr_gid_t left, apr_gid_t right);
+#else
+#define apr_gid_compare(left,right) (((left) == (right)) ? APR_SUCCESS : APR_EMISMATCH)
+#endif
+
+#endif  /* ! APR_HAS_USER */
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* ! APR_USER_H */
diff --git a/include/apr_uuid.h b/include/apr_uuid.h
new file mode 100644
index 00000000000..bb8841f1cda
--- /dev/null
+++ b/include/apr_uuid.h
@@ -0,0 +1,76 @@
+/* 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 apr_uuid.h
+ * @brief APR UUID library
+ */
+#ifndef APR_UUID_H
+#define APR_UUID_H
+
+#include "apu.h"
+#include "apr_errno.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup APR_UUID UUID Handling
+ * @ingroup APR
+ * @{
+ */
+
+/**
+ * we represent a UUID as a block of 16 bytes.
+ */
+
+typedef struct {
+    unsigned char data[16]; /**< the actual UUID */
+} apr_uuid_t;
+
+/** UUIDs are formatted as: 00112233-4455-6677-8899-AABBCCDDEEFF */
+#define APR_UUID_FORMATTED_LENGTH 36
+
+
+/**
+ * Generate and return a (new) UUID
+ * @param uuid The resulting UUID
+ */ 
+APR_DECLARE(void) apr_uuid_get(apr_uuid_t *uuid);
+
+/**
+ * Format a UUID into a string, following the standard format
+ * @param buffer The buffer to place the formatted UUID string into. It must
+ *               be at least APR_UUID_FORMATTED_LENGTH + 1 bytes long to hold
+ *               the formatted UUID and a null terminator
+ * @param uuid The UUID to format
+ */ 
+APR_DECLARE(void) apr_uuid_format(char *buffer, const apr_uuid_t *uuid);
+
+/**
+ * Parse a standard-format string into a UUID
+ * @param uuid The resulting UUID
+ * @param uuid_str The formatted UUID
+ */ 
+APR_DECLARE(apr_status_t) apr_uuid_parse(apr_uuid_t *uuid, const char *uuid_str);
+
+/** @} */
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* APR_UUID_H */
diff --git a/include/apr_version.h b/include/apr_version.h
new file mode 100644
index 00000000000..c528be42d98
--- /dev/null
+++ b/include/apr_version.h
@@ -0,0 +1,164 @@
+/* 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 APR_VERSION_H
+#define APR_VERSION_H
+
+/**
+ * @file apr_version.h
+ * @brief APR Versioning Interface
+ * 
+ * APR's Version
+ *
+ * There are several different mechanisms for accessing the version. There
+ * is a string form, and a set of numbers; in addition, there are constants
+ * which can be compiled into your application, and you can query the library
+ * being used for its actual version.
+ *
+ * Note that it is possible for an application to detect that it has been
+ * compiled against a different version of APR by use of the compile-time
+ * constants and the use of the run-time query function.
+ *
+ * APR version numbering follows the guidelines specified in:
+ *
+ *     http://apr.apache.org/versioning.html
+ */
+
+
+#define APR_COPYRIGHT "Copyright (c) 2000-2018 The Apache Software " \
+                      "Foundation or its licensors, as applicable."
+
+/* The numeric compile-time version constants. These constants are the
+ * authoritative version numbers for APR. 
+ */
+
+/** major version 
+ * Major API changes that could cause compatibility problems for older
+ * programs such as structure size changes.  No binary compatibility is
+ * possible across a change in the major version.
+ */
+#define APR_MAJOR_VERSION       2
+
+/** minor version
+ * Minor API changes that do not cause binary compatibility problems.
+ * Reset to 0 when upgrading APR_MAJOR_VERSION
+ */
+#define APR_MINOR_VERSION       0
+
+/** patch level 
+ * The Patch Level never includes API changes, simply bug fixes.
+ * Reset to 0 when upgrading APR_MINOR_VERSION
+ */
+#define APR_PATCH_VERSION       0
+
+/** 
+ * The symbol APR_IS_DEV_VERSION is only defined for internal,
+ * "development" copies of APR.  It is undefined for released versions
+ * of APR.
+ */
+#define APR_IS_DEV_VERSION
+
+/**
+ * Check at compile time if the APR version is at least a certain
+ * level.
+ * @param major The major version component of the version checked
+ * for (e.g., the "1" of "1.3.0").
+ * @param minor The minor version component of the version checked
+ * for (e.g., the "3" of "1.3.0").
+ * @param patch The patch level component of the version checked
+ * for (e.g., the "0" of "1.3.0").
+ * @remark This macro is available with APR versions starting with
+ * 1.3.0.
+ */
+#define APR_VERSION_AT_LEAST(major,minor,patch)                    \
+(((major) < APR_MAJOR_VERSION)                                     \
+ || ((major) == APR_MAJOR_VERSION && (minor) < APR_MINOR_VERSION) \
+ || ((major) == APR_MAJOR_VERSION && (minor) == APR_MINOR_VERSION && (patch) <= APR_PATCH_VERSION))
+
+#if defined(APR_IS_DEV_VERSION) || defined(DOXYGEN)
+/** Internal: string form of the "is dev" flag */
+#ifndef APR_IS_DEV_STRING
+#define APR_IS_DEV_STRING "-dev"
+#endif
+#else
+#define APR_IS_DEV_STRING ""
+#endif
+
+/* APR_STRINGIFY is defined here, and also in apr_general.h, so wrap it */
+#ifndef APR_STRINGIFY
+/** Properly quote a value as a string in the C preprocessor */
+#define APR_STRINGIFY(n) APR_STRINGIFY_HELPER(n)
+/** Helper macro for APR_STRINGIFY */
+#define APR_STRINGIFY_HELPER(n) #n
+#endif
+
+/** The formatted string of APR's version */
+#define APR_VERSION_STRING \
+     APR_STRINGIFY(APR_MAJOR_VERSION) "." \
+     APR_STRINGIFY(APR_MINOR_VERSION) "." \
+     APR_STRINGIFY(APR_PATCH_VERSION) \
+     APR_IS_DEV_STRING
+
+/** An alternative formatted string of APR's version */
+/* macro for Win32 .rc files using numeric csv representation */
+#define APR_VERSION_STRING_CSV APR_MAJOR_VERSION, \
+                               APR_MINOR_VERSION, \
+                               APR_PATCH_VERSION
+
+
+#ifndef APR_VERSION_ONLY
+
+/* The C language API to access the version at run time, 
+ * as opposed to compile time.  APR_VERSION_ONLY may be defined 
+ * externally when preprocessing apr_version.h to obtain strictly 
+ * the C Preprocessor macro declarations.
+ */
+
+#include "apr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** 
+ * The numeric version information is broken out into fields within this 
+ * structure. 
+ */
+typedef struct {
+    int major;      /**< major number */
+    int minor;      /**< minor number */
+    int patch;      /**< patch number */
+    int is_dev;     /**< is development (1 or 0) */
+} apr_version_t;
+
+/**
+ * Return APR's version information information in a numeric form.
+ *
+ *  @param pvsn Pointer to a version structure for returning the version
+ *              information.
+ */
+APR_DECLARE(void) apr_version(apr_version_t *pvsn);
+
+/** Return APR's version information as a string. */
+APR_DECLARE(const char *) apr_version_string(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ndef APR_VERSION_ONLY */
+
+#endif /* ndef APR_VERSION_H */
diff --git a/include/apr_want.h b/include/apr_want.h
new file mode 100644
index 00000000000..2863b0018a1
--- /dev/null
+++ b/include/apr_want.h
@@ -0,0 +1,124 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"        /* configuration data */
+/**
+ * @file apr_want.h
+ * @brief APR Standard Headers Support
+ *
+ * <PRE>
+ * Features:
+ *
+ *   APR_WANT_STRFUNC:  strcmp, strcat, strcpy, etc
+ *   APR_WANT_MEMFUNC:  memcmp, memcpy, etc
+ *   APR_WANT_STDIO:    <stdio.h> and related bits
+ *   APR_WANT_IOVEC:    struct iovec
+ *   APR_WANT_BYTEFUNC: htons, htonl, ntohl, ntohs
+ *
+ * Typical usage:
+ *
+ *   \#define APR_WANT_STRFUNC
+ *   \#define APR_WANT_MEMFUNC
+ *   \#include "apr_want.h"
+ *
+ * The appropriate headers will be included.
+ *
+ * Note: it is safe to use this in a header (it won't interfere with other
+ *       headers' or source files' use of apr_want.h)
+ * </PRE>
+ */
+
+/* --------------------------------------------------------------------- */
+
+#ifdef APR_WANT_STRFUNC
+
+#if APR_HAVE_STRING_H
+#include <string.h>
+#endif
+#if APR_HAVE_STRINGS_H
+#include <strings.h>
+#endif
+
+#undef APR_WANT_STRFUNC
+#endif
+
+/* --------------------------------------------------------------------- */
+
+#ifdef APR_WANT_MEMFUNC
+
+#if APR_HAVE_STRING_H
+#include <string.h>
+#endif
+
+#undef APR_WANT_MEMFUNC
+#endif
+
+/* --------------------------------------------------------------------- */
+
+#ifdef APR_WANT_STDIO
+
+#if APR_HAVE_STDIO_H
+#include <stdio.h>
+#endif
+
+#undef APR_WANT_STDIO
+#endif
+
+/* --------------------------------------------------------------------- */
+
+#ifdef APR_WANT_IOVEC
+
+#if APR_HAVE_IOVEC
+
+#if APR_HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#endif
+
+#else
+
+#ifndef APR_IOVEC_DEFINED
+#define APR_IOVEC_DEFINED
+struct iovec
+{
+    void *iov_base;
+    size_t iov_len;
+};
+#endif /* !APR_IOVEC_DEFINED */
+
+#endif /* APR_HAVE_IOVEC */
+
+#undef APR_WANT_IOVEC
+#endif
+
+/* --------------------------------------------------------------------- */
+
+#ifdef APR_WANT_BYTEFUNC
+
+/* Single Unix says they are in arpa/inet.h.  Linux has them in
+ * netinet/in.h.  FreeBSD has them in arpa/inet.h but requires that
+ * netinet/in.h be included first.
+ */
+#if APR_HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#if APR_HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#undef APR_WANT_BYTEFUNC
+#endif
+
+/* --------------------------------------------------------------------- */
diff --git a/include/apr_xlate.h b/include/apr_xlate.h
index 39c891da7fb..6f27fda0be8 100644
--- a/include/apr_xlate.h
+++ b/include/apr_xlate.h
@@ -1,169 +1,161 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 APR_XLATE_H
 #define APR_XLATE_H
 
-#include "apr.h"
-#include "apr_general.h"
-#include "apr_time.h"
+#include "apu.h"
+#include "apr_pools.h"
 #include "apr_errno.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif /* __cplusplus */
 
-/* APR_HAS_XLATE determines whether or not useful implementations of 
- * ap_xlate_open() et al are provided. 
- *
- * If APR_HAS_XLATE is zero, ap_xlate_open() et al will all return 
- * APR_ENOTIMPL at run-time.
+/**
+ * @file apr_xlate.h
+ * @brief APR I18N translation library
  */
 
-#if ! APR_HAS_XLATE
-
-typedef void                         ap_xlate_t;
-
-/* For platforms where we don't bother with translating between charsets,
- * these are macros which always return failure.
+/**
+ * @defgroup APR_XLATE I18N translation library
+ * @ingroup APR
+ * @{
  */
-
-#define ap_xlate_open(convset, topage, frompage, pool) APR_ENOTIMPL
-
-#define ap_xlate_conv_buffer(convset, inbuf, inbytes_left, outbuf, \
-                          outbytes_left) APR_ENOTIMPL
-
-/* The purpose of ap_xlate_conv_char is to translate one character
- * at a time.  This needs to be written carefully so that it works
- * with double-byte character sets. 
+/** Opaque translation buffer */
+typedef struct apr_xlate_t            apr_xlate_t;
+
+/**
+ * Set up for converting text from one charset to another.
+ * @param convset The handle to be filled in by this function
+ * @param topage The name of the target charset
+ * @param frompage The name of the source charset
+ * @param pool The pool to use
+ * @remark
+ *  Specify APR_DEFAULT_CHARSET for one of the charset
+ *  names to indicate the charset of the source code at
+ *  compile time.  This is useful if there are literal
+ *  strings in the source code which must be translated
+ *  according to the charset of the source code.
+ *  APR_DEFAULT_CHARSET is not useful if the source code
+ *  of the caller was not encoded in the same charset as
+ *  APR at compile time.
+ *
+ * @remark
+ *  Specify APR_LOCALE_CHARSET for one of the charset
+ *  names to indicate the charset of the current locale.
+ *
+ * @remark
+ *  Return APR_EINVAL if unable to procure a convset, or APR_ENOTIMPL
+ *  if charset transcoding is not available in this instance of
+ *  apr-util at all (i.e., APR_HAS_XLATE is undefined).
  */
-#define ap_xlate_conv_char(convset, inchar, outchar) APR_ENOTIMPL
-
-#define ap_xlate_close(convset) APR_ENOTIMPL
-
-#else  /* ! APR_HAS_XLATE */
-
-typedef struct ap_xlate_t            ap_xlate_t;
-
-/*
-
-=head1 ap_status_t ap_xlate_open(ap_xlate_t **convset, const char *topage, const char *frompage, ap_pool_t *pool)
-
-B<Set up for converting text from one charset to another.>
-
-    arg 1) The handle to be filled in by this function
-    arg 2) The name of the target charset
-    arg 3) The name of the source charset
-    arg 4) The pool to use
-
-B<NOTE>:  Specify APR_DEFAULT_CHARSET for one of the charset
-          names to indicate the charset of the source code at
-          compile time.  This is useful if there are literal
-          strings in the source code which must be translated
-          according to the charset of the source code.
-          APR_DEFAULT_CHARSET is not useful if the source code
-          of the caller was not encoded in the same charset as
-          APR at compile time.
-
-=cut
+APR_DECLARE(apr_status_t) apr_xlate_open(apr_xlate_t **convset, 
+                                         const char *topage, 
+                                         const char *frompage, 
+                                         apr_pool_t *pool);
+
+/** 
+ * This is to indicate the charset of the sourcecode at compile time
+ * names to indicate the charset of the source code at
+ * compile time.  This is useful if there are literal
+ * strings in the source code which must be translated
+ * according to the charset of the source code.
  */
-ap_status_t ap_xlate_open(ap_xlate_t **convset, const char *topage, 
-                       const char *frompage, ap_pool_t *pool);
-
-#define APR_DEFAULT_CHARSET NULL
-
-/*
-
-=head1 ap_status_t ap_xlate_conv_buffer(ap_xlate_t *convset, const char *inbuf, ap_size_t *inbytes_left, char *outbuf, ap_size_t outbytes_left)
-
-B<Convert a buffer of text from one codepage to another.>
-
-    arg 1) The handle allocated by ap_xlate_open, specifying the parameters
-           of conversion
-    arg 2) The address of the source buffer
-    arg 3) Input: the amount of input data to be translated
-           Output: the amount of input data not yet translated    
-    arg 4) The address of the destination buffer
-    arg 5) Input: the size of the output buffer
-           Output: the amount of the output buffer not yet used
-
-=cut
+#define APR_DEFAULT_CHARSET (const char *)0
+/**
+ * To indicate charset names of the current locale 
  */
-ap_status_t ap_xlate_conv_buffer(ap_xlate_t *convset, const char *inbuf, 
-                              ap_size_t *inbytes_left, char *outbuf,
-                              ap_size_t *outbytes_left);
-
-/* The purpose of ap_xlate_conv_char is to translate one character
+#define APR_LOCALE_CHARSET (const char *)1
+
+/**
+ * Find out whether or not the specified conversion is single-byte-only.
+ * @param convset The handle allocated by apr_xlate_open, specifying the 
+ *                parameters of conversion
+ * @param onoff Output: whether or not the conversion is single-byte-only
+ * @remark
+ *  Return APR_ENOTIMPL if charset transcoding is not available
+ *  in this instance of apr-util (i.e., APR_HAS_XLATE is undefined).
+ */
+APR_DECLARE(apr_status_t) apr_xlate_sb_get(apr_xlate_t *convset, int *onoff);
+
+/**
+ * Convert a buffer of text from one codepage to another.
+ * @param convset The handle allocated by apr_xlate_open, specifying 
+ *                the parameters of conversion
+ * @param inbuf The address of the source buffer
+ * @param inbytes_left Input: the amount of input data to be translated
+ *                     Output: the amount of input data not yet translated    
+ * @param outbuf The address of the destination buffer
+ * @param outbytes_left Input: the size of the output buffer
+ *                      Output: the amount of the output buffer not yet used
+ * @remark
+ * Returns APR_ENOTIMPL if charset transcoding is not available
+ * in this instance of apr-util (i.e., APR_HAS_XLATE is undefined).
+ * Returns APR_INCOMPLETE if the input buffer ends in an incomplete
+ * multi-byte character.
+ *
+ * To correctly terminate the output buffer for some multi-byte
+ * character set encodings, a final call must be made to this function
+ * after the complete input string has been converted, passing
+ * the inbuf and inbytes_left parameters as NULL.  (Note that this
+ * mode only works from version 1.1.0 onwards)
+ */
+APR_DECLARE(apr_status_t) apr_xlate_conv_buffer(apr_xlate_t *convset, 
+                                                const char *inbuf, 
+                                                apr_size_t *inbytes_left, 
+                                                char *outbuf,
+                                                apr_size_t *outbytes_left);
+
+/* @see apr_file_io.h the comment in apr_file_io.h about this hack */
+#ifdef APR_NOT_DONE_YET
+/**
+ * The purpose of apr_xlate_conv_char is to translate one character
  * at a time.  This needs to be written carefully so that it works
  * with double-byte character sets. 
+ * @param convset The handle allocated by apr_xlate_open, specifying the
+ *                parameters of conversion
+ * @param inchar The character to convert
+ * @param outchar The converted character
  */
-ap_status_t ap_xlate_conv_char(ap_xlate_t *convset, char inchar, char outchar);
-
-/*
-
-=head1 ap_status_t ap_xlate_close(ap_xlate_t *convset)
-
-B<Close a codepage translation handle.>
-
-    arg 1) The codepage translation handle to close
+APR_DECLARE(apr_status_t) apr_xlate_conv_char(apr_xlate_t *convset, 
+                                              char inchar, char outchar);
+#endif
 
-=cut
+/**
+ * Convert a single-byte character from one charset to another.
+ * @param convset The handle allocated by apr_xlate_open, specifying the 
+ *                parameters of conversion
+ * @param inchar The single-byte character to convert.
+ * @warning This only works when converting between single-byte character sets.
+ *          -1 will be returned if the conversion can't be performed.
  */
-ap_status_t ap_xlate_close(ap_xlate_t *convset);
-
-#endif  /* ! APR_HAS_XLATE */
+APR_DECLARE(apr_int32_t) apr_xlate_conv_byte(apr_xlate_t *convset, 
+                                             unsigned char inchar);
+
+/**
+ * Close a codepage translation handle.
+ * @param convset The codepage translation handle to close
+ * @remark
+ *  Return APR_ENOTIMPL if charset transcoding is not available
+ *  in this instance of apr-util (i.e., APR_HAS_XLATE is undefined).
+ */
+APR_DECLARE(apr_status_t) apr_xlate_close(apr_xlate_t *convset);
 
+/** @} */
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/apr_xml.h b/include/apr_xml.h
new file mode 100644
index 00000000000..bd0b1000ca0
--- /dev/null
+++ b/include/apr_xml.h
@@ -0,0 +1,358 @@
+/* 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 apr_xml.h
+ * @brief APR-UTIL XML Library
+ */
+#ifndef APR_XML_H
+#define APR_XML_H
+
+/**
+ * @defgroup APR_Util_XML XML 
+ * @ingroup APR
+ * @{
+ */
+#include "apr_pools.h"
+#include "apr_tables.h"
+#include "apr_file_io.h"
+
+#include "apu.h"
+#if APR_CHARSET_EBCDIC
+#include "apr_xlate.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @package Apache XML library
+ */
+
+/* -------------------------------------------------------------------- */
+
+/* ### these will need to move at some point to a more logical spot */
+
+/** @see apr_text */
+typedef struct apr_text apr_text;
+
+/** Structure to keep a linked list of pieces of text */
+struct apr_text {
+    /** The current piece of text */
+    const char *text;
+    /** a pointer to the next piece of text */
+    struct apr_text *next;
+};
+
+/** @see apr_text_header */
+typedef struct apr_text_header apr_text_header;
+
+/** A list of pieces of text */
+struct apr_text_header {
+    /** The first piece of text in the list */
+    apr_text *first;
+    /** The last piece of text in the list */
+    apr_text *last;
+};
+
+/**
+ * Append a piece of text to the end of a list
+ * @param p The pool to allocate out of
+ * @param hdr The text header to append to
+ * @param text The new text to append
+ */
+APR_DECLARE(void) apr_text_append(apr_pool_t *p, apr_text_header *hdr,
+                                  const char *text);
+
+
+/* --------------------------------------------------------------------
+**
+** XML PARSING
+*/
+
+/*
+** Qualified namespace values
+**
+** APR_XML_NS_DAV_ID
+**    We always insert the "DAV:" namespace URI at the head of the
+**    namespace array. This means that it will always be at ID==0,
+**    making it much easier to test for.
+**
+** APR_XML_NS_NONE
+**    This special ID is used for two situations:
+**
+**    1) The namespace prefix begins with "xml" (and we do not know
+**       what it means). Namespace prefixes with "xml" (any case) as
+**       their first three characters are reserved by the XML Namespaces
+**       specification for future use. mod_dav will pass these through
+**       unchanged. When this identifier is used, the prefix is LEFT in
+**       the element/attribute name. Downstream processing should not
+**       prepend another prefix.
+**
+**    2) The element/attribute does not have a namespace.
+**
+**       a) No prefix was used, and a default namespace has not been
+**          defined.
+**       b) No prefix was used, and the default namespace was specified
+**          to mean "no namespace". This is done with a namespace
+**          declaration of:  xmlns=""
+**          (this declaration is typically used to override a previous
+**          specification for the default namespace)
+**
+**       In these cases, we need to record that the elem/attr has no
+**       namespace so that we will not attempt to prepend a prefix.
+**       All namespaces that are used will have a prefix assigned to
+**       them -- mod_dav will never set or use the default namespace
+**       when generating XML. This means that "no prefix" will always
+**       mean "no namespace".
+**
+**    In both cases, the XML generation will avoid prepending a prefix.
+**    For the first case, this means the original prefix/name will be
+**    inserted into the output stream. For the latter case, it means
+**    the name will have no prefix, and since we never define a default
+**    namespace, this means it will have no namespace.
+**
+** Note: currently, mod_dav understands the "xmlns" prefix and the
+**     "xml:lang" attribute. These are handled specially (they aren't
+**     left within the XML tree), so the APR_XML_NS_NONE value won't ever
+**     really apply to these values.
+*/
+#define APR_XML_NS_DAV_ID	0	/**< namespace ID for "DAV:" */
+#define APR_XML_NS_NONE		-10	/**< no namespace for this elem/attr */
+
+#define APR_XML_NS_ERROR_BASE	-100	/**< used only during processing */
+/** Is this namespace an error? */
+#define APR_XML_NS_IS_ERROR(e)	((e) <= APR_XML_NS_ERROR_BASE)
+
+/** @see apr_xml_attr */
+typedef struct apr_xml_attr apr_xml_attr;
+/** @see apr_xml_elem */
+typedef struct apr_xml_elem apr_xml_elem;
+/** @see apr_xml_doc */
+typedef struct apr_xml_doc apr_xml_doc;
+
+/** apr_xml_attr: holds a parsed XML attribute */
+struct apr_xml_attr {
+    /** attribute name */
+    const char *name;
+    /** index into namespace array */
+    int ns;
+
+    /** attribute value */
+    const char *value;
+
+    /** next attribute */
+    struct apr_xml_attr *next;
+};
+
+/** apr_xml_elem: holds a parsed XML element */
+struct apr_xml_elem {
+    /** element name */
+    const char *name;
+    /** index into namespace array */
+    int ns;
+    /** xml:lang for attrs/contents */
+    const char *lang;
+
+    /** cdata right after start tag */
+    apr_text_header first_cdata;
+    /** cdata after MY end tag */
+    apr_text_header following_cdata;
+
+    /** parent element */
+    struct apr_xml_elem *parent;	
+    /** next (sibling) element */
+    struct apr_xml_elem *next;	
+    /** first child element */
+    struct apr_xml_elem *first_child;
+    /** first attribute */
+    struct apr_xml_attr *attr;		
+
+    /* used only during parsing */
+    /** last child element */
+    struct apr_xml_elem *last_child;
+    /** namespaces scoped by this elem */
+    struct apr_xml_ns_scope *ns_scope;
+
+    /* used by modules during request processing */
+    /** Place for modules to store private data */
+    void *priv;
+};
+
+/** Is this XML element empty? */
+#define APR_XML_ELEM_IS_EMPTY(e) ((e)->first_child == NULL && \
+                                  (e)->first_cdata.first == NULL)
+
+/** apr_xml_doc: holds a parsed XML document */
+struct apr_xml_doc {
+    /** root element */
+    apr_xml_elem *root;	
+    /** array of namespaces used */
+    apr_array_header_t *namespaces;
+};
+
+/** Opaque XML parser structure */
+typedef struct apr_xml_parser apr_xml_parser;
+
+/**
+ * Create an XML parser
+ * @param pool The pool for allocating the parser and the parse results.
+ * @return The new parser.
+ */
+APR_DECLARE(apr_xml_parser *) apr_xml_parser_create(apr_pool_t *pool);
+
+/**
+ * Parse a File, producing a xml_doc
+ * @param p      The pool for allocating the parse results.
+ * @param parser A pointer to *parser (needed so calling function can get
+ *               errors), will be set to NULL on successful completion.
+ * @param ppdoc  A pointer to *apr_xml_doc (which has the parsed results in it)
+ * @param xmlfd  A file to read from.
+ * @param buffer_length Buffer length which would be suitable 
+ * @return Any errors found during parsing.
+ */
+APR_DECLARE(apr_status_t) apr_xml_parse_file(apr_pool_t *p,
+                                             apr_xml_parser **parser,
+                                             apr_xml_doc **ppdoc,
+                                             apr_file_t *xmlfd,
+                                             apr_size_t buffer_length);
+
+
+/**
+ * Feed input into the parser
+ * @param parser The XML parser for parsing this data.
+ * @param data The data to parse.
+ * @param len The length of the data.
+ * @return Any errors found during parsing.
+ * @remark Use apr_xml_parser_geterror() to get more error information.
+ */
+APR_DECLARE(apr_status_t) apr_xml_parser_feed(apr_xml_parser *parser,
+                                              const char *data,
+                                              apr_size_t len);
+
+/**
+ * Terminate the parsing and return the result
+ * @param parser The XML parser for parsing this data.
+ * @param pdoc The resulting parse information. May be NULL to simply
+ *             terminate the parsing without fetching the info.
+ * @return Any errors found during the final stage of parsing.
+ * @remark Use apr_xml_parser_geterror() to get more error information.
+ */
+APR_DECLARE(apr_status_t) apr_xml_parser_done(apr_xml_parser *parser,
+                                              apr_xml_doc **pdoc);
+
+/**
+ * Fetch additional error information from the parser.
+ * @param parser The XML parser to query for errors.
+ * @param errbuf A buffer for storing error text.
+ * @param errbufsize The length of the error text buffer.
+ * @return The error buffer
+ */
+APR_DECLARE(char *) apr_xml_parser_geterror(apr_xml_parser *parser,
+                                            char *errbuf,
+                                            apr_size_t errbufsize);
+
+
+/**
+ * Converts an XML element tree to flat text 
+ * @param p The pool to allocate out of
+ * @param elem The XML element to convert
+ * @param style How to covert the XML.  One of:
+ * <PRE>
+ *     APR_XML_X2T_FULL                start tag, contents, end tag 
+ *     APR_XML_X2T_INNER               contents only 
+ *     APR_XML_X2T_LANG_INNER          xml:lang + inner contents 
+ *     APR_XML_X2T_FULL_NS_LANG        FULL + ns defns + xml:lang 
+ *     APR_XML_X2T_PARSED              original prefixes
+ * </PRE>
+ * @param namespaces The namespace of the current XML element
+ * @param ns_map Namespace mapping
+ * @param pbuf Buffer to put the converted text into
+ * @param psize Size of the converted text
+ */
+APR_DECLARE(void) apr_xml_to_text(apr_pool_t *p, const apr_xml_elem *elem,
+                                  int style, apr_array_header_t *namespaces,
+                                  int *ns_map, const char **pbuf,
+                                  apr_size_t *psize);
+
+/* style argument values: */
+#define APR_XML_X2T_FULL         0	/**< start tag, contents, end tag */
+#define APR_XML_X2T_INNER        1	/**< contents only */
+#define APR_XML_X2T_LANG_INNER   2	/**< xml:lang + inner contents */
+#define APR_XML_X2T_FULL_NS_LANG 3	/**< FULL + ns defns + xml:lang */
+#define APR_XML_X2T_PARSED       4	/**< original prefixes */
+
+/**
+ * empty XML element
+ * @param p The pool to allocate out of
+ * @param elem The XML element to empty
+ * @return the string that was stored in the XML element
+ */
+APR_DECLARE(const char *) apr_xml_empty_elem(apr_pool_t *p,
+                                             const apr_xml_elem *elem);
+
+/**
+ * quote an XML string
+ * Replace '\<', '\>', and '\&' with '\&lt;', '\&gt;', and '\&amp;'.
+ * @param p The pool to allocate out of
+ * @param s The string to quote
+ * @param quotes If quotes is true, then replace '&quot;' with '\&quot;'.
+ * @return The quoted string
+ * @note If the string does not contain special characters, it is not
+ * duplicated into the pool and the original string is returned.
+ */
+APR_DECLARE(const char *) apr_xml_quote_string(apr_pool_t *p, const char *s,
+                                               int quotes);
+
+/**
+ * Quote an XML element
+ * @param p The pool to allocate out of
+ * @param elem The element to quote
+ */
+APR_DECLARE(void) apr_xml_quote_elem(apr_pool_t *p, apr_xml_elem *elem);
+
+/* manage an array of unique URIs: apr_xml_insert_uri() and APR_XML_URI_ITEM() */
+
+/**
+ * return the URI's (existing) index, or insert it and return a new index 
+ * @param uri_array array to insert into
+ * @param uri The uri to insert
+ * @return int The uri's index
+ */
+APR_DECLARE(int) apr_xml_insert_uri(apr_array_header_t *uri_array,
+                                    const char *uri);
+
+/** Get the URI item for this XML element */
+#define APR_XML_GET_URI_ITEM(ary, i) (((const char * const *)(ary)->elts)[i])
+
+#if APR_CHARSET_EBCDIC
+/**
+ * Convert parsed tree in EBCDIC 
+ * @param p The pool to allocate out of
+ * @param pdoc The apr_xml_doc to convert.
+ * @param xlate The translation handle to use.
+ * @return Any errors found during conversion.
+ */
+APR_DECLARE(apr_status_t) apr_xml_parser_convert_doc(apr_pool_t *p,
+                                                     apr_xml_doc *pdoc,
+                                                     apr_xlate_t *convset);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+/** @} */
+#endif /* APR_XML_H */
diff --git a/include/apu.h b/include/apu.h
new file mode 100644
index 00000000000..ab119730fd5
--- /dev/null
+++ b/include/apu.h
@@ -0,0 +1,23 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* @file apu.h
+ * @brief APR-Utility main file
+ * @deprecated @see apr.h
+ */
+
+#include <apr.h>
+
diff --git a/include/apu_errno.h b/include/apu_errno.h
new file mode 100644
index 00000000000..58585b71483
--- /dev/null
+++ b/include/apu_errno.h
@@ -0,0 +1,173 @@
+/* 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 APU_ERRNO_H
+#define APU_ERRNO_H
+
+/**
+ * @file apu_errno.h
+ * @brief APR-Util Error Codes
+ */
+
+#include "apr.h"
+#include "apr_errno.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup apu_errno Error Codes
+ * @ingroup APR
+ * @{
+ */
+
+/**
+ * @defgroup APR_Util_Error APR_Util Error Values
+ * <PRE>
+ * <b>APU ERROR VALUES</b>
+ * APR_ENOKEY         The key provided was empty or NULL
+ * APR_ENOIV          The initialisation vector provided was NULL
+ * APR_EKEYTYPE       The key type was not recognised
+ * APR_ENOSPACE       The buffer supplied was not big enough
+ * APR_ECRYPT         An error occurred while encrypting or decrypting
+ * APR_EPADDING       Padding was not supported
+ * APR_EKEYLENGTH     The key length was incorrect
+ * APR_ENOCIPHER      The cipher provided was not recognised
+ * APR_ENODIGEST      The digest provided was not recognised
+ * APR_ENOENGINE      The engine provided was not recognised
+ * APR_EINITENGINE    The engine could not be initialised
+ * APR_EREINIT        Underlying crypto has already been initialised
+ * </PRE>
+ *
+ * <PRE>
+ * <b>APR STATUS VALUES</b>
+ * APR_INCHILD        Program is currently executing in the child
+ * </PRE>
+ * @{
+ */
+/** @see APR_STATUS_IS_ENOKEY */
+#define APR_ENOKEY           (APR_UTIL_START_STATUS + 1)
+/** @see APR_STATUS_IS_ENOIV */
+#define APR_ENOIV            (APR_UTIL_START_STATUS + 2)
+/** @see APR_STATUS_IS_EKEYTYPE */
+#define APR_EKEYTYPE         (APR_UTIL_START_STATUS + 3)
+/** @see APR_STATUS_IS_ENOSPACE */
+#define APR_ENOSPACE         (APR_UTIL_START_STATUS + 4)
+/** @see APR_STATUS_IS_ECRYPT */
+#define APR_ECRYPT           (APR_UTIL_START_STATUS + 5)
+/** @see APR_STATUS_IS_EPADDING */
+#define APR_EPADDING         (APR_UTIL_START_STATUS + 6)
+/** @see APR_STATUS_IS_EKEYLENGTH */
+#define APR_EKEYLENGTH       (APR_UTIL_START_STATUS + 7)
+/** @see APR_STATUS_IS_ENOCIPHER */
+#define APR_ENOCIPHER        (APR_UTIL_START_STATUS + 8)
+/** @see APR_STATUS_IS_ENODIGEST */
+#define APR_ENODIGEST        (APR_UTIL_START_STATUS + 9)
+/** @see APR_STATUS_IS_ENOENGINE */
+#define APR_ENOENGINE        (APR_UTIL_START_STATUS + 10)
+/** @see APR_STATUS_IS_EINITENGINE */
+#define APR_EINITENGINE      (APR_UTIL_START_STATUS + 11)
+/** @see APR_STATUS_IS_EREINIT */
+#define APR_EREINIT          (APR_UTIL_START_STATUS + 12)
+/** @} */
+
+/**
+ * @defgroup APU_STATUS_IS Status Value Tests
+ * @warning For any particular error condition, more than one of these tests
+ *      may match. This is because platform-specific error codes may not
+ *      always match the semantics of the POSIX codes these tests (and the
+ *      corresponding APR error codes) are named after. A notable example
+ *      are the APR_STATUS_IS_ENOENT and APR_STATUS_IS_ENOTDIR tests on
+ *      Win32 platforms. The programmer should always be aware of this and
+ *      adjust the order of the tests accordingly.
+ * @{
+ */
+
+/** @} */
+
+/**
+ * @addtogroup APR_Util_Error
+ * @{
+ */
+/**
+ * The key was empty or not provided
+ */
+#define APR_STATUS_IS_ENOKEY(s)        ((s) == APR_ENOKEY)
+/**
+ * The initialisation vector was not provided
+ */
+#define APR_STATUS_IS_ENOIV(s)        ((s) == APR_ENOIV)
+/**
+ * The key type was not recognised
+ */
+#define APR_STATUS_IS_EKEYTYPE(s)        ((s) == APR_EKEYTYPE)
+/**
+ * The buffer provided was not big enough
+ */
+#define APR_STATUS_IS_ENOSPACE(s)        ((s) == APR_ENOSPACE)
+/**
+ * An error occurred while encrypting or decrypting
+ */
+#define APR_STATUS_IS_ECRYPT(s)        ((s) == APR_ECRYPT)
+/**
+ * An error occurred while padding
+ */
+#define APR_STATUS_IS_EPADDING(s)        ((s) == APR_EPADDING)
+/**
+ * An error occurred with the key length
+ */
+#define APR_STATUS_IS_EKEYLENGTH(s)        ((s) == APR_EKEYLENGTH)
+/**
+ * The cipher provided was not recognised
+ */
+#define APR_STATUS_IS_ENOCIPHER(s)        ((s) == APR_ENOCIPHER)
+/**
+ * The digest provided was not recognised
+ */
+#define APR_STATUS_IS_ENODIGEST(s)        ((s) == APR_ENODIGEST)
+/**
+ * The engine provided was not recognised
+ */
+#define APR_STATUS_IS_ENOENGINE(s)        ((s) == APR_ENOENGINE)
+/**
+ * The engine could not be initialised
+ */
+#define APR_STATUS_IS_EINITENGINE(s)        ((s) == APR_EINITENGINE)
+/**
+ * Crypto has already been initialised
+ */
+#define APR_STATUS_IS_EREINIT(s)        ((s) == APR_EREINIT)
+/** @} */
+
+/**
+ * This structure allows the underlying API error codes to be returned
+ * along with plain text error messages that explain to us mere mortals
+ * what really happened.
+ */
+typedef struct apu_err_t {
+    const char *reason;
+    const char *msg;
+    int rc;
+} apu_err_t;
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* ! APU_ERRNO_H */
diff --git a/include/apu_version.h b/include/apu_version.h
new file mode 100644
index 00000000000..b46aad5033f
--- /dev/null
+++ b/include/apu_version.h
@@ -0,0 +1,87 @@
+/* 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 APU_VERSION_H
+#define APU_VERSION_H
+
+/**
+ * @file apu_version.h
+ * @brief APR-util Versioning Interface
+ * 
+ * APR-util's Version
+ *
+ * There are several different mechanisms for accessing the version. There
+ * is a string form, and a set of numbers; in addition, there are constants
+ * which can be compiled into your application, and you can query the library
+ * being used for its actual version.
+ *
+ * Note that it is possible for an application to detect that it has been
+ * compiled against a different version of APU by use of the compile-time
+ * constants and the use of the run-time query function.
+ *
+ * APU version numbering follows the guidelines specified in:
+ *
+ *     http://apr.apache.org/versioning.html
+ */
+
+
+#include "apr_version.h"
+
+/* The numeric compile-time version constants. These constants are the
+ * authoritative version numbers for APU. This file remains as strictly
+ * a compatibility stub.
+ */
+
+/** major version 
+ * Major API changes that could cause compatibility problems for older
+ * programs such as structure size changes.  No binary compatibility is
+ * possible across a change in the major version.
+ * In 2.0, for legacy support, this is an identity of the APR version.
+ * @deprecated @see APR_MAJOR_VERSION
+ */
+#define APU_MAJOR_VERSION       APR_MAJOR_VERSION
+
+/** minor version
+ * Minor API changes that do not cause binary compatibility problems.
+ * Reset to 0 when upgrading APU_MAJOR_VERSION
+ * In 2.0, for legacy support, this is an identity of the APR version.
+ * @deprecated @see APR_MINOR_VERSION
+ */
+#define APU_MINOR_VERSION       APR_MINOR_VERSION
+
+/** patch level 
+ * The Patch Level never includes API changes, simply bug fixes.
+ * Reset to 0 when upgrading APR_MINOR_VERSION
+ * In 2.0, for legacy support, this is an identity of the APR version.
+ * @deprecated @see APR_PATCH_VERSION
+ */
+#define APU_PATCH_VERSION       APR_PATCH_VERSION
+
+/** 
+ * The symbol APU_IS_DEV_VERSION is only defined for internal,
+ * "development" copies of APU.  It is undefined for released versions
+ * of APU.
+ * In 2.0, for legacy support, this is an identity of the APR version.
+ * @deprecated @see APR_IS_DEV_VERSION
+ */
+#ifdef APR_IS_DEV_VERSION
+#  define APU_IS_DEV_VERSION
+#endif
+
+/** Internal: string form of the "is dev" flag */
+#define APU_IS_DEV_STRING       APR_IS_DEV_STRING
+
+#endif /* ndef APU_VERSION_H */
diff --git a/include/apu_want.h.in b/include/apu_want.h.in
new file mode 100644
index 00000000000..a296e5c5c69
--- /dev/null
+++ b/include/apu_want.h.in
@@ -0,0 +1,51 @@
+/* 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 "apu.h"        /* configuration data */
+
+/**
+ * @file apu_want.h
+ * @brief APR Standard Headers Support
+ *
+ * <PRE>
+ * Features:
+ *
+ *   APU_WANT_DB:       <@apu_db_header@>
+ *
+ * Typical usage:
+ *
+ *   #define APU_WANT_DB
+ *   #include "apu_want.h"
+ *
+ * The appropriate headers will be included.
+ *
+ * Note: it is safe to use this in a header (it won't interfere with other
+ *       headers' or source files' use of apu_want.h)
+ * </PRE>
+ */
+
+/* --------------------------------------------------------------------- */
+
+#ifdef APU_WANT_DB
+
+#if APU_HAVE_DB
+#include <@apu_db_header@>
+#endif
+
+#undef APU_WANT_DB
+#endif
+
+/* --------------------------------------------------------------------- */
diff --git a/include/apu_want.hnw b/include/apu_want.hnw
new file mode 100644
index 00000000000..afdc9f74ca6
--- /dev/null
+++ b/include/apu_want.hnw
@@ -0,0 +1,52 @@
+/* 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 "apu.h"        /* configuration data */
+
+/**
+ * @file apu_want.h
+ * @brief APR Standard Headers Support
+ *
+ * <PRE>
+ * Features:
+ *
+ *   APU_WANT_DB:       <@apu_db_header>
+ *
+ * Typical usage:
+ *
+ *   #define APU_WANT_DB
+ *   #include "apu_want.h"
+ *
+ * The appropriate headers will be included.
+ *
+ * Note: it is safe to use this in a header (it won't interfere with other
+ *       headers' or source files' use of apu_want.h)
+ * </PRE>
+ */
+
+/* --------------------------------------------------------------------- */
+
+#ifdef APU_WANT_DB
+
+#if APU_HAVE_DB
+/* win32 note.. you will need to change this for db1 */
+#include <db.h>
+#endif
+
+#undef APU_WANT_DB
+#endif
+
+/* --------------------------------------------------------------------- */
diff --git a/include/apu_want.hw b/include/apu_want.hw
new file mode 100644
index 00000000000..8bb56ce79f0
--- /dev/null
+++ b/include/apu_want.hw
@@ -0,0 +1,52 @@
+/* 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 "apu.h"        /* configuration data */
+
+/**
+ * @file apu_want.h
+ * @brief APR Standard Headers Support
+ *
+ * <PRE>
+ * Features:
+ *
+ *   APU_WANT_DB:       <db.h>
+ *
+ * Typical usage:
+ *
+ *   #define APU_WANT_DB
+ *   #include "apu_want.h"
+ *
+ * The appropriate headers will be included.
+ *
+ * Note: it is safe to use this in a header (it won't interfere with other
+ *       headers' or source files' use of apu_want.h)
+ * </PRE>
+ */
+
+/* --------------------------------------------------------------------- */
+
+#ifdef APU_WANT_DB
+
+#if APU_HAVE_DB
+/* win32 note.. you will need to change this for db1 */
+#include <db.h>
+#endif
+
+#undef APU_WANT_DB
+#endif
+
+/* --------------------------------------------------------------------- */
diff --git a/include/arch/aix/apr_arch_dso.h b/include/arch/aix/apr_arch_dso.h
new file mode 100644
index 00000000000..d1cac684f6e
--- /dev/null
+++ b/include/arch/aix/apr_arch_dso.h
@@ -0,0 +1,41 @@
+/* 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 DSO_H
+#define DSO_H
+
+#include "apr_private.h"
+#include "apr_general.h"
+#include "apr_pools.h"
+#include "apr_dso.h"
+#include "apr.h"
+
+#if APR_HAS_DSO
+
+void *dlopen(const char *path, int mode);
+void *dlsym(void *handle, const char *symbol);
+const char *dlerror(void);
+int dlclose(void *handle);
+
+struct apr_dso_handle_t {
+    apr_pool_t  *pool;
+    void          *handle;
+    const char *errormsg;
+};
+
+#endif
+
+#endif
diff --git a/include/arch/aix/dso.h b/include/arch/aix/dso.h
deleted file mode 100644
index 392a92015ab..00000000000
--- a/include/arch/aix/dso.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef DSO_H
-#define DSO_H
-
-#include "apr_private.h"
-#include "apr_general.h"
-#include "apr_pools.h"
-#include "apr_dso.h"
-
-void *dlopen(const char *path, int mode);
-void *dlsym(void *handle, const char *symbol);
-const char *dlerror(void);
-int dlclose(void *handle);
-
-struct ap_dso_handle_t {
-    ap_pool_t  *cont;
-    void          *handle;
-};
-
-#endif
diff --git a/include/arch/beos/apr_arch_dso.h b/include/arch/beos/apr_arch_dso.h
new file mode 100644
index 00000000000..fbc5c2ff013
--- /dev/null
+++ b/include/arch/beos/apr_arch_dso.h
@@ -0,0 +1,41 @@
+/* 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 DSO_H
+#define DSO_H
+
+#include "apr_private.h"
+#include "apr_general.h"
+#include "apr_pools.h"
+#include "apr_errno.h"
+#include "apr_dso.h"
+#include "apr.h"
+#include <kernel/image.h>
+#include <string.h>
+
+#if APR_HAS_DSO
+
+struct apr_dso_handle_t {
+    image_id      handle;    /* Handle to the DSO loaded */
+    apr_pool_t   *pool;
+    const char   *errormsg;  /* if the load fails, we have an error
+                              * message here :)
+                              */
+};
+
+#endif
+
+#endif
diff --git a/include/arch/beos/apr_arch_proc_mutex.h b/include/arch/beos/apr_arch_proc_mutex.h
new file mode 100644
index 00000000000..c60d8c6228a
--- /dev/null
+++ b/include/arch/beos/apr_arch_proc_mutex.h
@@ -0,0 +1,36 @@
+/* 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 PROC_MUTEX_H
+#define PROC_MUTEX_H
+
+#include "apr_pools.h"
+#include "apr_proc_mutex.h"
+#include "apr_file_io.h"
+#include "apr_general.h"
+#include "apr_lib.h"
+#include "apr_portable.h"
+
+struct apr_proc_mutex_t {
+    apr_pool_t *pool;
+    
+    /* Our lock :) */
+    sem_id Lock;
+    int32  LockCount;
+};
+
+#endif  /* PROC_MUTEX_H */
+
diff --git a/include/arch/beos/apr_arch_thread_cond.h b/include/arch/beos/apr_arch_thread_cond.h
new file mode 100644
index 00000000000..c9420b53cb0
--- /dev/null
+++ b/include/arch/beos/apr_arch_thread_cond.h
@@ -0,0 +1,46 @@
+/* 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 THREAD_COND_H
+#define THREAD_COND_H
+
+#include <kernel/OS.h>
+#include "apr_pools.h"
+#include "apr_thread_cond.h"
+#include "apr_file_io.h"
+#include "apr_general.h"
+#include "apr_lib.h"
+#include "apr_portable.h"
+#include "apr_ring.h"
+
+struct waiter_t {
+    APR_RING_ENTRY(waiter_t) link;
+    sem_id sem;
+};
+
+struct apr_thread_cond_t {
+    apr_pool_t *pool;
+    sem_id lock;
+    apr_thread_mutex_t *condlock;
+    thread_id owner;
+    /* active list */
+    APR_RING_HEAD(active_list, waiter_t) alist;
+    /* free list */
+    APR_RING_HEAD(free_list,   waiter_t) flist;
+};
+
+#endif  /* THREAD_COND_H */
+
diff --git a/include/arch/beos/apr_arch_thread_mutex.h b/include/arch/beos/apr_arch_thread_mutex.h
new file mode 100644
index 00000000000..bb7d4ae80ba
--- /dev/null
+++ b/include/arch/beos/apr_arch_thread_mutex.h
@@ -0,0 +1,42 @@
+/* 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 THREAD_MUTEX_H
+#define THREAD_MUTEX_H
+
+#include <kernel/OS.h>
+#include "apr_pools.h"
+#include "apr_thread_mutex.h"
+#include "apr_file_io.h"
+#include "apr_general.h"
+#include "apr_lib.h"
+#include "apr_portable.h"
+
+struct apr_thread_mutex_t {
+    apr_pool_t *pool;
+    
+    /* Our lock :) */
+    sem_id Lock;
+    int32  LockCount;
+
+    /* If we nest locks we need these... */
+    int nested;  
+    apr_os_thread_t owner;
+    int owner_ref;
+};
+
+#endif  /* THREAD_MUTEX_H */
+
diff --git a/include/arch/beos/apr_arch_thread_rwlock.h b/include/arch/beos/apr_arch_thread_rwlock.h
new file mode 100644
index 00000000000..694b0d50465
--- /dev/null
+++ b/include/arch/beos/apr_arch_thread_rwlock.h
@@ -0,0 +1,45 @@
+/* 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 THREAD_RWLOCK_H
+#define THREAD_RWLOCK_H
+
+#include <kernel/OS.h>
+#include "apr_pools.h"
+#include "apr_thread_rwlock.h"
+#include "apr_file_io.h"
+#include "apr_general.h"
+#include "apr_lib.h"
+#include "apr_portable.h"
+
+struct apr_thread_rwlock_t {
+    apr_pool_t *pool;
+
+    /* Our lock :) */
+    sem_id Lock;
+    int32  LockCount;
+    /* Read/Write lock stuff */
+    sem_id Read;
+    int32  ReadCount;
+    sem_id Write;
+    int32  WriteCount;
+    int32  Nested;
+
+    thread_id writer;
+};
+
+#endif  /* THREAD_RWLOCK_H */
+
diff --git a/include/arch/beos/apr_arch_threadproc.h b/include/arch/beos/apr_arch_threadproc.h
new file mode 100644
index 00000000000..13de0536345
--- /dev/null
+++ b/include/arch/beos/apr_arch_threadproc.h
@@ -0,0 +1,95 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_thread_proc.h"
+#include "apr_arch_file_io.h"
+#include "apr_file_io.h"
+#include "apr_thread_proc.h"
+#include "apr_general.h"
+#include "apr_portable.h"
+#include <kernel/OS.h>
+#include <signal.h>
+#include <string.h>
+#include <sys/wait.h>
+#include <image.h>
+
+#ifndef THREAD_PROC_H
+#define THREAD_PROC_H
+
+#define SHELL_PATH "/bin/sh"
+
+#define PTHREAD_CANCEL_AYNCHRONOUS  CANCEL_ASYNCH; 
+#define PTHREAD_CANCEL_DEFERRED     CANCEL_DEFER; 
+                                   
+#define PTHREAD_CANCEL_ENABLE       CANCEL_ENABLE; 
+#define PTHREAD_CANCEL_DISABLE      CANCEL_DISABLE; 
+
+#define BEOS_MAX_DATAKEYS	128
+
+struct apr_thread_t {
+    apr_pool_t *pool;
+    thread_id td;
+    void *data;
+    apr_thread_start_t func;
+    apr_status_t exitval;
+};
+
+struct apr_threadattr_t {
+    apr_pool_t *pool;
+    int32 attr;
+    int detached;
+    int joinable;
+};
+
+struct apr_threadkey_t {
+    apr_pool_t *pool;
+	int32  key;
+};
+
+struct beos_private_data {
+	const void ** data;
+	int count;
+	volatile thread_id  td;
+};
+
+struct beos_key {
+	int  assigned;
+	int  count;
+	sem_id  lock;
+	int32  ben_lock;
+	void (* destructor) (void *);
+};
+
+struct apr_procattr_t {
+    apr_pool_t *pool;
+    apr_file_t *parent_in;
+    apr_file_t *child_in;
+    apr_file_t *parent_out;
+    apr_file_t *child_out;
+    apr_file_t *parent_err;
+    apr_file_t *child_err;
+    char *currdir;
+    apr_int32_t cmdtype;
+    apr_int32_t detached;
+};
+
+struct apr_thread_once_t {
+    sem_id sem;
+    int hit;
+};
+
+#endif  /* ! THREAD_PROC_H */
+
diff --git a/include/arch/beos/dso.h b/include/arch/beos/dso.h
deleted file mode 100644
index 2666d779ad2..00000000000
--- a/include/arch/beos/dso.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef DSO_H
-#define DSO_H
-
-#include "apr_private.h"
-#include "apr_general.h"
-#include "apr_pools.h"
-#include "apr_errno.h"
-#include "apr_dso.h"
-#include <kernel/image.h>
-
-struct ap_dso_handle_t {
-    image_id       handle;    /* Handle to the DSO loaded */
-    ap_pool_t   *cont;
-};
-
-#endif
diff --git a/include/arch/beos/locks.h b/include/arch/beos/locks.h
deleted file mode 100644
index 0160b5e71aa..00000000000
--- a/include/arch/beos/locks.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef LOCKS_H
-#define LOCKS_H
-
-#include <kernel/OS.h>
-#include "apr_lock.h"
-#include "apr_file_io.h"
-#include "apr_general.h"
-#include "apr_lib.h"
-
-struct ap_lock_t {
-    ap_pool_t *cntxt;
-    ap_locktype_e type;
-    ap_lockscope_e scope;
-    int curr_locked;
-    char *fname;
-	/* Inter proc */
-	sem_id sem_interproc;
-	int32  ben_interproc;
-	/* Intra Proc */
-	sem_id sem_intraproc;
-	int32  ben_intraproc;
-    /* At some point, we should do a scope for both inter and intra process
-     *  locking here.  Something like pthread_mutex with PTHREAD_PROCESS_SHARED
-     */    
-};
-
-#endif  /* LOCKS_H */
-
diff --git a/include/arch/beos/networkio.h b/include/arch/beos/networkio.h
deleted file mode 100644
index 3966acf433b..00000000000
--- a/include/arch/beos/networkio.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef NETWORK_IO_H
-#define NETWORK_IO_H
-
-#include <socket.h>
-#include <netdb.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-#include <sys/time.h>
-#include "apr_network_io.h"
-#include "apr_general.h"
-#include "apr_portable.h"
-#include "apr_lib.h"
-#include "fileio.h"
-#include "apr_errno.h"
-
-/* The definition of isascii was missed from the PowerPC ctype.h
- *
- * It will be included in the next release, but until then... */
-#if __POWERPC__
-#define isascii(c) (((c) & ~0x7f)==0)
-#endif
-
-#include "apr_general.h"
-#include <ByteOrder.h> /* for the ntohs definition */
-
-#define POLLIN	 1
-#define POLLPRI  2
-#define POLLOUT  4
-#define POLLERR  8
-#define POLLHUP  16
-#define POLLNVAL 32
-
-struct ap_socket_t {
-    ap_pool_t *cntxt;
-    int socketdes;
-    struct sockaddr_in *local_addr;
-    struct sockaddr_in *remote_addr;
-    int addr_len;
-    ap_interval_time_t timeout;
-    int connected;
-};
-
-struct ap_pollfd_t {
-    ap_pool_t *cntxt;
-    struct ap_socket_t *sock;
-    fd_set *read;
-    fd_set *write;
-    fd_set *except;
-    int highsock;
-};
-
-ap_int16_t get_event(ap_int16_t);
-
-int inet_aton(const char *cp, struct in_addr *addr);
-
-#endif  /* ! NETWORK_IO_H */
-
diff --git a/include/arch/beos/threadproc.h b/include/arch/beos/threadproc.h
deleted file mode 100644
index 4588105d15f..00000000000
--- a/include/arch/beos/threadproc.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "apr_thread_proc.h"
-#include "fileio.h"
-#include "apr_file_io.h"
-#include "apr_thread_proc.h"
-#include "apr_file_io.h"
-#include "apr_general.h"
-#include "apr_portable.h"
-#include  <kernel/OS.h>
-#include <signal.h>
-#include <string.h>
-#include <sys/wait.h>
-
-#ifndef THREAD_PROC_H
-#define THREAD_PROC_H
-
-#define SHELL_PATH "/bin/sh"
-
-#define PTHREAD_CANCEL_AYNCHRONOUS  CANCEL_ASYNCH; 
-#define PTHREAD_CANCEL_DEFERRED     CANCEL_DEFER; 
-                                   
-#define PTHREAD_CANCEL_ENABLE       CANCEL_ENABLE; 
-#define PTHREAD_CANCEL_DISABLE      CANCEL_DISABLE; 
-
-#define BEOS_MAX_DATAKEYS	128
-
-struct ap_thread_t {
-    ap_pool_t *cntxt;
-    thread_id td;
-};
-
-struct ap_threadattr_t {
-    ap_pool_t *cntxt;
-    int32 attr;
-    int detached;
-    int joinable;
-};
-
-struct ap_threadkey_t {
-    ap_pool_t *cntxt;
-	int32  key;
-};
-
-struct beos_private_data {
-	const void ** data;
-	int count;
-	volatile thread_id  td;
-};
-
-struct beos_key {
-	int  assigned;
-	int  count;
-	sem_id  lock;
-	int32  ben_lock;
-	void (* destructor) ();
-};
-
-struct ap_procattr_t {
-    ap_pool_t *cntxt;
-    ap_file_t *parent_in;
-    ap_file_t *child_in;
-    ap_file_t *parent_out;
-    ap_file_t *child_out;
-    ap_file_t *parent_err;
-    ap_file_t *child_err;
-    char *currdir;
-    ap_int32_t cmdtype;
-    ap_int32_t detached;
-};
-
-struct ap_proc_t {
-    ap_pool_t *cntxt;
-    thread_id pid;
-    struct ap_procattr_t *attr;
-};
-
-/* we need a structure to pass off to the thread that will run any
- * new process we create */
-
-#endif  /* ! THREAD_PROC_H */
-
diff --git a/include/arch/netware/apr_arch_dso.h b/include/arch/netware/apr_arch_dso.h
new file mode 100644
index 00000000000..ea0fe8c254c
--- /dev/null
+++ b/include/arch/netware/apr_arch_dso.h
@@ -0,0 +1,43 @@
+/* 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 DSO_H
+#define DSO_H
+
+#include "apr_private.h"
+#include "apr_general.h"
+#include "apr_pools.h"
+#include "apr_dso.h"
+#include "apr.h"
+
+#include <dlfcn.h>
+
+typedef struct sym_list sym_list;
+
+struct sym_list {
+    sym_list *next;
+    char *symbol;
+};
+
+struct apr_dso_handle_t {
+    apr_pool_t  *pool;
+    void        *handle;
+    const char  *errormsg;
+    sym_list    *symbols;
+    char        *path;
+};
+
+#endif
diff --git a/include/arch/netware/apr_arch_file_io.h b/include/arch/netware/apr_arch_file_io.h
new file mode 100644
index 00000000000..659eb200625
--- /dev/null
+++ b/include/arch/netware/apr_arch_file_io.h
@@ -0,0 +1,187 @@
+/* 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 FILE_IO_H
+#define FILE_IO_H
+
+#include "apr.h"
+#include "apr_private.h"
+#include "apr_general.h"
+#include "apr_tables.h"
+#include "apr_file_io.h"
+#include "apr_file_info.h"
+#include "apr_errno.h"
+#include "apr_lib.h"
+#include "apr_poll.h"
+#include "apr_time.h"
+
+/* System headers the file I/O library needs */
+#if APR_HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#if APR_HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#if APR_HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#if APR_HAVE_STRING_H
+#include <string.h>
+#endif
+#if APR_HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#if APR_HAVE_DIRENT_H
+#include <dirent.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if APR_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if APR_HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if APR_HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#endif
+#if APR_HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#include <fsio.h>
+
+/* End System headers */
+
+#define APR_FILE_DEFAULT_BUFSIZE 4096
+/* For backwards compat */
+#define APR_FILE_BUFSIZE APR_FILE_DEFAULT_BUFSIZE
+
+#if APR_HAS_THREADS
+#define file_lock(f)   do { \
+                           if ((f)->thlock) \
+                               apr_thread_mutex_lock((f)->thlock); \
+                       } while (0)
+#define file_unlock(f) do { \
+                           if ((f)->thlock) \
+                               apr_thread_mutex_unlock((f)->thlock); \
+                       } while (0)
+#else
+#define file_lock(f)   do {} while (0)
+#define file_unlock(f) do {} while (0)
+#endif
+
+#if APR_HAS_LARGE_FILES
+#define lseek(f,o,w) lseek64(f,o,w)
+#define ftruncate(f,l) ftruncate64(f,l)
+#endif
+
+typedef struct stat struct_stat;
+
+typedef struct apr_rotating_info_t {
+    apr_finfo_t finfo;
+    apr_interval_time_t timeout;
+    apr_time_t lastcheck;
+    int oflags;
+    int manual;
+    apr_fileperms_t perm;
+} apr_rotating_info_t;
+
+struct apr_file_t {
+    apr_pool_t *pool;
+    int filedes;
+    char *fname;
+    apr_int32_t flags;
+    int eof_hit;
+    int is_pipe;
+    apr_interval_time_t timeout;
+    int buffered;
+    enum {BLK_UNKNOWN, BLK_OFF, BLK_ON } blocking;
+    int ungetchar;    /* Last char provided by an unget op. (-1 = no char)*/
+
+    /* if there is a timeout set, then this pollset is used */
+    apr_pollset_t *pollset;
+
+    /* Stuff for buffered mode */
+    char *buffer;
+    apr_size_t bufpos;    /* Read/Write position in buffer */
+    apr_size_t bufsize;   /* The buffer size */
+    apr_off_t dataRead;   /* amount of valid data read into buffer */
+    int direction;            /* buffer being used for 0 = read, 1 = write */
+    apr_off_t filePtr;    /* position in file of handle */
+#if APR_HAS_THREADS
+    struct apr_thread_mutex_t *thlock;
+#endif
+    apr_rotating_info_t *rotating;
+};
+
+struct apr_dir_t {
+    apr_pool_t *pool;
+    char *dirname;
+    DIR *dirstruct;
+    struct dirent *entry;
+};
+
+typedef struct apr_stat_entry_t apr_stat_entry_t;
+
+struct apr_stat_entry_t {
+    struct stat info;
+    char *casedName;
+    apr_time_t expire;
+    NXPathCtx_t pathCtx;
+};
+
+#define MAX_SERVER_NAME     64
+#define MAX_VOLUME_NAME     64
+#define MAX_PATH_NAME       256
+#define MAX_FILE_NAME       256
+
+#define DRIVE_ONLY          1
+
+/* If the user passes d: vs. D: (or //mach/share vs. //MACH/SHARE),
+ * we need to fold the case to canonical form.  This function is
+ * supposed to do so.
+ */
+apr_status_t filepath_root_case(char **rootpath, char *root, apr_pool_t *p);
+
+/* This function check to see of the given path includes a drive/volume
+ * specifier.  If the _only_ parameter is set to DRIVE_ONLY then it 
+ * check to see of the path only contains a drive/volume specifier and
+ * nothing else.
+ */
+apr_status_t filepath_has_drive(const char *rootpath, int only, apr_pool_t *p);
+
+/* This function compares the drive/volume specifiers for each given path.
+ * It returns zero if they match or non-zero if not. 
+ */
+apr_status_t filepath_compare_drive(const char *path1, const char *path2, apr_pool_t *p);
+
+apr_status_t apr_unix_file_cleanup(void *);
+apr_status_t apr_unix_child_file_cleanup(void *);
+
+mode_t apr_unix_perms2mode(apr_fileperms_t perms);
+apr_fileperms_t apr_unix_mode2perms(mode_t mode);
+
+apr_status_t apr_file_flush_locked(apr_file_t *thefile);
+apr_status_t apr_file_info_get_locked(apr_finfo_t *finfo, apr_int32_t wanted,
+                                      apr_file_t *thefile);
+
+#endif  /* ! FILE_IO_H */
+
diff --git a/include/arch/netware/apr_arch_global_mutex.h b/include/arch/netware/apr_arch_global_mutex.h
new file mode 100644
index 00000000000..4167d378211
--- /dev/null
+++ b/include/arch/netware/apr_arch_global_mutex.h
@@ -0,0 +1,29 @@
+/* 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 GLOBAL_MUTEX_H
+#define GLOBAL_MUTEX_H
+
+#include "apr_global_mutex.h"
+#include "apr_thread_mutex.h"
+
+struct apr_global_mutex_t {
+    apr_pool_t *pool;
+    apr_thread_mutex_t *mutex;
+};
+
+#endif  /* GLOBAL_MUTEX_H */
+
diff --git a/include/arch/netware/apr_arch_internal_time.h b/include/arch/netware/apr_arch_internal_time.h
new file mode 100644
index 00000000000..59f1067208a
--- /dev/null
+++ b/include/arch/netware/apr_arch_internal_time.h
@@ -0,0 +1,26 @@
+/* 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 TIME_INTERNAL_H
+#define TIME_INTERNAL_H
+
+#include "apr.h"
+
+#define TZONE           (*___timezone())
+
+void apr_netware_setup_time(void);
+
+#endif  /* TIME_INTERNAL_H */
diff --git a/include/arch/netware/apr_arch_networkio.h b/include/arch/netware/apr_arch_networkio.h
new file mode 100644
index 00000000000..63f17abe595
--- /dev/null
+++ b/include/arch/netware/apr_arch_networkio.h
@@ -0,0 +1,31 @@
+/* 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 NETWORK_IO_H
+
+#ifdef USE_WINSOCK
+/* Making sure that we include the correct networkio.h since the
+    the project file is configured to first look for headers in
+    arch/netware and then arch/unix. But in this specific case we 
+    want arch/win32.
+*/
+#include <../win32/apr_arch_networkio.h>
+#else
+#include <../unix/apr_arch_networkio.h>
+#endif
+
+#endif  /* ! NETWORK_IO_H */
+
diff --git a/include/arch/netware/apr_arch_pre_nw.h b/include/arch/netware/apr_arch_pre_nw.h
new file mode 100644
index 00000000000..9b441402ccc
--- /dev/null
+++ b/include/arch/netware/apr_arch_pre_nw.h
@@ -0,0 +1,60 @@
+/* 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 __pre_nw__
+#define __pre_nw__
+
+#include <stdint.h>
+
+#ifdef __MWERKS__
+#pragma precompile_target "precomp.mch"
+#endif
+
+#ifndef NETWARE
+#define NETWARE
+#endif
+
+#ifndef N_PLAT_NLM
+#define N_PLAT_NLM
+#endif
+
+#define FAR
+#define far
+
+/* no-op for Codewarrior C compiler; all functions are cdecl by default */
+#define cdecl
+
+/* if we have wchar_t enabled in C++, predefine this type to avoid
+   a conflict in Novell's header files */
+#ifndef __GNUC__
+#ifndef DOXYGEN
+#if (__option(cplusplus) && __option(wchar_type))
+#define _WCHAR_T
+#endif
+#endif
+#endif
+
+/* C9X defintion used by MSL C++ library */
+#define DECIMAL_DIG 17
+
+/* some code may want to use the MS convention for long long */
+#ifndef __int64
+#define __int64 long long
+#endif
+
+#endif
+
+
+
diff --git a/include/arch/netware/apr_arch_proc_mutex.h b/include/arch/netware/apr_arch_proc_mutex.h
new file mode 100644
index 00000000000..7a634c2e50d
--- /dev/null
+++ b/include/arch/netware/apr_arch_proc_mutex.h
@@ -0,0 +1,29 @@
+/* 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 PROC_MUTEX_H
+#define PROC_MUTEX_H
+
+#include "apr_proc_mutex.h"
+#include "apr_thread_mutex.h"
+
+struct apr_proc_mutex_t {
+    apr_pool_t *pool;
+    apr_thread_mutex_t *mutex;
+};
+
+#endif  /* PROC_MUTEX_H */
+
diff --git a/include/arch/netware/apr_arch_thread_cond.h b/include/arch/netware/apr_arch_thread_cond.h
new file mode 100644
index 00000000000..b11a5f86a74
--- /dev/null
+++ b/include/arch/netware/apr_arch_thread_cond.h
@@ -0,0 +1,29 @@
+/* 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 THREAD_COND_H
+#define THREAD_COND_H
+
+#include "apr_thread_cond.h"
+#include <nks/synch.h>
+
+struct apr_thread_cond_t {
+    apr_pool_t *pool;
+    NXCond_t *cond;
+};
+
+#endif  /* THREAD_COND_H */
+
diff --git a/include/arch/netware/apr_arch_thread_mutex.h b/include/arch/netware/apr_arch_thread_mutex.h
new file mode 100644
index 00000000000..18702fc7d03
--- /dev/null
+++ b/include/arch/netware/apr_arch_thread_mutex.h
@@ -0,0 +1,32 @@
+/* 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 THREAD_MUTEX_H
+#define THREAD_MUTEX_H
+
+#include "apr_thread_mutex.h"
+#include "apr_thread_cond.h"
+#include <nks/synch.h>
+
+struct apr_thread_mutex_t {
+    apr_pool_t *pool;
+    NXMutex_t *mutex;
+    apr_thread_cond_t *cond;
+    int locked, num_waiters;
+};
+
+#endif  /* THREAD_MUTEX_H */
+
diff --git a/include/arch/netware/apr_arch_thread_rwlock.h b/include/arch/netware/apr_arch_thread_rwlock.h
new file mode 100644
index 00000000000..d2dbd42f798
--- /dev/null
+++ b/include/arch/netware/apr_arch_thread_rwlock.h
@@ -0,0 +1,29 @@
+/* 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 THREAD_RWLOCK_H
+#define THREAD_RWLOCK_H
+
+#include "apr_thread_rwlock.h"
+#include <nks/synch.h>
+
+struct apr_thread_rwlock_t {
+    apr_pool_t *pool;
+    NXRwLock_t *rwlock;
+};
+
+#endif  /* THREAD_RWLOCK_H */
+
diff --git a/include/arch/netware/apr_arch_threadproc.h b/include/arch/netware/apr_arch_threadproc.h
new file mode 100644
index 00000000000..2fee2c00eeb
--- /dev/null
+++ b/include/arch/netware/apr_arch_threadproc.h
@@ -0,0 +1,80 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_thread_proc.h"
+#include "apr_file_io.h"
+
+#include <sys/wait.h>
+
+#ifndef THREAD_PROC_H
+#define THREAD_PROC_H
+
+#define SHELL_PATH ""
+#define APR_DEFAULT_STACK_SIZE 65536
+
+struct apr_thread_t {
+    apr_pool_t *pool;
+    NXContext_t ctx;
+    NXThreadId_t td;
+    char *thread_name;
+    apr_int32_t cancel;
+    apr_int32_t cancel_how;
+    void *data;
+    apr_thread_start_t func;
+    apr_status_t exitval;
+};
+
+struct apr_threadattr_t {
+    apr_pool_t *pool;
+    apr_size_t  stack_size;
+    apr_int32_t detach;
+    char *thread_name;
+};
+
+struct apr_threadkey_t {
+    apr_pool_t *pool;
+    NXKey_t key;
+};
+
+struct apr_procattr_t {
+    apr_pool_t *pool;
+    apr_file_t *parent_in;
+    apr_file_t *child_in;
+    apr_file_t *parent_out;
+    apr_file_t *child_out;
+    apr_file_t *parent_err;
+    apr_file_t *child_err;
+    char *currdir;
+    apr_int32_t cmdtype;
+    apr_int32_t detached;
+    apr_int32_t addrspace;
+};
+
+struct apr_thread_once_t {
+    unsigned long value;
+};
+
+/*
+struct apr_proc_t {
+    apr_pool_t *pool;
+    pid_t pid;
+    apr_procattr_t *attr;
+};
+*/
+
+#endif  /* ! THREAD_PROC_H */
+
diff --git a/include/arch/netware/apr_private.h b/include/arch/netware/apr_private.h
new file mode 100644
index 00000000000..c4558afa78c
--- /dev/null
+++ b/include/arch/netware/apr_private.h
@@ -0,0 +1,210 @@
+/* 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.
+ */
+
+/*
+ * Note: 
+ * This is the netware-specific autoconf-like config file
+ * which unix creates at ./configure time.
+ */
+
+#ifndef APR_PRIVATE_H
+#define APR_PRIVATE_H
+
+/* Pick up publicly advertised headers and symbols before the
+ * APR internal private headers and symbols
+ */
+#include <apr.h>
+
+/* Pick up privately consumed headers */
+#include <ndkvers.h>
+
+/* Include alloca.h to get compiler-dependent defines */ 
+#include <alloca.h>
+
+/* Use this section to define all of the HAVE_FOO_H
+ * that are required to build properly.
+ */
+#define HAVE_ALLOCA_H   1
+#define HAVE_DLFCN_H    1
+#define HAVE_LIMITS_H   1
+#define HAVE_SIGNAL_H   1
+#define HAVE_STDDEF_H   1
+#define HAVE_STDLIB_H   1
+#ifndef USE_WINSOCK
+#define HAVE_SYS_SELECT_H 1
+#define HAVE_WRITEV       1
+#endif
+#define HAVE_SYS_STAT_H 1
+#define HAVE_SYS_MMAN_H 1
+#define HAVE_FCNTL_H    1
+#define HAVE_ICONV_H    1
+#define HAVE_UTIME_H    1
+
+#define HAVE_STRICMP    1
+#define HAVE_STRNICMP   1
+#define HAVE_STRDUP     1
+#define HAVE_STRSTR     1
+#define HAVE_MEMCHR     1
+#define HAVE_CALLOC     1
+#define HAVE_UTIME      1
+
+#define HAVE_GETENV     1
+#define HAVE_SETENV     1
+#define HAVE_UNSETENV   1
+
+#define HAVE_WRITEV     1
+
+#define HAVE_GETPASS_R  1
+/*
+ * Hack around older NDKs which have only the getpassword() function,
+ * a threadsafe, API-equivalent of getpass_r().
+ */
+#if (CURRENT_NDK_THRESHOLD < 709060000)
+#define getpass_r       getpassword
+#endif
+
+#ifdef NW_BUILD_IPV6
+#define HAVE_GETADDRINFO 1
+#define HAVE_GETNAMEINFO 1
+#endif
+
+/* 1 is used for SIGABRT on netware */
+/* 2 is used for SIGFPE on netware */
+/* 3 is used for SIGILL on netware */
+/* 4 is used for SIGINT on netware */
+/* 5 is used for SIGSEGV on netware */
+/* 6 is used for SIGTERM on netware */
+/* 7 is used for SIGPOLL on netware */
+
+#if (CURRENT_NDK_THRESHOLD < 306030000)
+#define SIGKILL         11
+#define SIGALRM         13
+#define SIGCHLD         14 
+#define SIGCONT         15
+#define SIGHUP          16
+#define SIGPIPE         17
+#define SIGQUIT         18
+#define SIGSTOP         19
+#define SIGTSTP         20
+#define SIGTTIN         21
+#define SIGTTOU         22
+#define SIGUSR1         23
+#define SIGUSR2         24
+#endif
+
+#define SIGTRAP         25
+#define SIGIOT          26
+#define SIGSTKFLT       28
+#define SIGURG          29
+#define SIGXCPU         30
+#define SIGXFSZ         31
+#define SIGVTALRM       32
+#define SIGPROF         33
+#define SIGWINCH        34
+#define SIGIO           35
+
+#if (CURRENT_NDK_THRESHOLD < 406230000)
+#undef  SA_NOCLDSTOP
+#define SA_NOCLDSTOP    0x00000001
+#endif
+#ifndef SIGBUS
+#define SIGBUS          SIGSEGV
+#endif
+
+#define _getch()               getcharacter()
+
+#define SIZEOF_CHAR            1
+#define SIZEOF_SHORT           2
+#define SIZEOF_INT             4
+#define SIZEOF_LONGLONG        8
+#define SIZEOF_SSIZE_T         SIZEOF_INT
+
+void netware_pool_proc_cleanup();
+
+/* NLM registration routines for managing which NLMs
+    are using the library. */
+int register_NLM(void *NLMHandle);
+int unregister_NLM(void *NLMHandle);
+
+/* Application global data management */
+extern int  gLibId;
+extern void *gLibHandle;
+
+typedef struct app_data {
+    int     initialized;
+    void*   gPool;
+    void*   gs_aHooksToSort;
+    void*   gs_phOptionalHooks;
+    void*   gs_phOptionalFunctions;
+    void*   gs_nlmhandle;
+    rtag_t  gs_startup_rtag;
+    rtag_t  gs_socket_rtag;
+    rtag_t  gs_lookup_rtag;
+    rtag_t  gs_event_rtag;
+    rtag_t  gs_pcp_rtag;
+    void*   gs_xref_head;
+} APP_DATA;
+
+int setGlobalPool(void *data);
+void* getGlobalPool();
+int setStatCache(void *data);
+void* getStatCache();
+
+/* Redefine malloc to use the library malloc call so 
+    that all of the memory resources will be owned
+    and can be shared by the library. */
+#undef malloc
+#define malloc(x) library_malloc(gLibHandle,x)
+#ifndef __MWERKS__
+#define _alloca         alloca
+#endif
+
+/* 64-bit integer conversion function */
+#define APR_INT64_STRFN strtoll
+
+#if APR_HAS_LARGE_FILES
+#define APR_OFF_T_STRFN strtoll
+#else
+#define APR_OFF_T_STRFN strtol
+#endif
+
+/* used to check DWORD overflow for 64bit compiles */
+#define APR_DWORD_MAX   0xFFFFFFFFUL
+
+/* Always compile Netware with DSO support for .nlm builds */
+#define APU_DSO_BUILD   0
+
+/*
+ * NetWare does not have GDBM, and we always use the bundled (new) Expat
+ */
+
+/* Define if you have the gdbm library (-lgdbm). */
+/* #undef HAVE_LIBGDBM */
+
+/* define if Expat 1.0 or 1.1 was found */
+/* #undef APR_HAVE_OLD_EXPAT */
+
+/* NetWare uses its own ICONV implementation. */
+#define HAVE_ICONV_H 1
+
+/*
+ * check for newer NDKs which use now correctly 'const char*' with iconv.
+ */
+#if (CURRENT_NDK_THRESHOLD >= 705110000)
+#define APU_ICONV_INBUF_CONST
+#endif
+
+#endif  /*APR_PRIVATE_H*/
diff --git a/include/arch/os2/apr_arch_dso.h b/include/arch/os2/apr_arch_dso.h
new file mode 100644
index 00000000000..2bda6b7c663
--- /dev/null
+++ b/include/arch/os2/apr_arch_dso.h
@@ -0,0 +1,37 @@
+/* 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 DSO_H
+#define DSO_H
+
+#include "apr_private.h"
+#include "apr_general.h"
+#include "apr_pools.h"
+#include "apr_dso.h"
+#include "apr.h"
+
+#if APR_HAS_DSO
+
+struct apr_dso_handle_t {
+    apr_pool_t  *cont;       /* Context for returning error strings */
+    HMODULE       handle;     /* Handle to the DSO loaded            */
+    apr_status_t   load_error;
+    char          *failed_module;
+};
+
+#endif
+
+#endif
diff --git a/include/arch/os2/apr_arch_file_io.h b/include/arch/os2/apr_arch_file_io.h
new file mode 100644
index 00000000000..a742bf47729
--- /dev/null
+++ b/include/arch/os2/apr_arch_file_io.h
@@ -0,0 +1,87 @@
+/* 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 FILE_IO_H
+#define FILE_IO_H
+
+#include "apr_private.h"
+#include "apr_general.h"
+#include "apr_thread_mutex.h"
+#include "apr_file_io.h"
+#include "apr_file_info.h"
+#include "apr_errno.h"
+#include "apr_poll.h"
+
+/* We have an implementation of mkstemp but it's not very multi-threading 
+ * friendly & is part of the POSIX emulation rather than native so don't
+ * use it.
+ */
+#undef HAVE_MKSTEMP
+
+#define APR_FILE_DEFAULT_BUFSIZE 4096
+#define APR_FILE_BUFSIZE APR_FILE_DEFAULT_BUFSIZE
+
+struct apr_file_t {
+    apr_pool_t *pool;
+    HFILE filedes;
+    char * fname;
+    int isopen;
+    int buffered;
+    int eof_hit;
+    apr_int32_t flags;
+    int timeout;
+    int pipe;
+    HEV pipeSem;
+    enum { BLK_UNKNOWN, BLK_OFF, BLK_ON } blocking;
+
+    /* Stuff for buffered mode */
+    char *buffer;
+    apr_size_t bufsize;        /* The size of the buffer                    */
+    apr_size_t bufpos;         /* Read/Write position in buffer             */
+    unsigned long dataRead;    /* amount of valid data read into buffer     */
+    int direction;             /* buffer being used for 0 = read, 1 = write */
+    unsigned long filePtr;     /* position in file of handle                */
+    apr_thread_mutex_t *mutex; /* mutex semaphore, must be owned to access
+                                  the above fields                          */
+    int ungetchar;
+};
+
+struct apr_dir_t {
+    apr_pool_t *pool;
+    char *dirname;
+    ULONG handle;
+    FILEFINDBUF3 entry;
+    int validentry;
+};
+
+apr_status_t apr_file_cleanup(void *);
+apr_status_t apr_os2_time_to_apr_time(apr_time_t *result, FDATE os2date, 
+                                      FTIME os2time);
+apr_status_t apr_apr_time_to_os2_time(FDATE *os2date, FTIME *os2time,
+                                      apr_time_t aprtime);
+
+/* see win32/fileio.h for description of these */
+extern const char c_is_fnchar[256];
+
+#define IS_FNCHAR(c) c_is_fnchar[(unsigned char)c]
+
+apr_status_t filepath_root_test(char *path, apr_pool_t *p);
+apr_status_t filepath_drive_get(char **rootpath, char drive, 
+                                apr_int32_t flags, apr_pool_t *p);
+apr_status_t filepath_root_case(char **rootpath, char *root, apr_pool_t *p);
+
+#endif  /* ! FILE_IO_H */
+
diff --git a/include/arch/os2/apr_arch_networkio.h b/include/arch/os2/apr_arch_networkio.h
new file mode 100644
index 00000000000..10c6de81fbb
--- /dev/null
+++ b/include/arch/os2/apr_arch_networkio.h
@@ -0,0 +1,76 @@
+/* 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 NETWORK_IO_H
+#define NETWORK_IO_H
+
+#include "apr_private.h"
+#include "apr_network_io.h"
+#include "apr_general.h"
+#include "apr_arch_os2calls.h"
+#include "apr_poll.h"
+
+#if APR_HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
+typedef struct sock_userdata_t sock_userdata_t;
+struct sock_userdata_t {
+    sock_userdata_t *next;
+    const char *key;
+    void *data;
+};
+
+struct apr_socket_t {
+    apr_pool_t *pool;
+    int socketdes;
+    int type;
+    int protocol;
+    apr_sockaddr_t *local_addr;
+    apr_sockaddr_t *remote_addr;
+    apr_interval_time_t timeout;
+    int nonblock;
+    int local_port_unknown;
+    int local_interface_unknown;
+    int remote_addr_unknown;
+    apr_int32_t options;
+    apr_int32_t inherit;
+    sock_userdata_t *userdata;
+
+    /* if there is a timeout set, then this pollset is used */
+    apr_pollset_t *pollset;
+};
+
+/* Error codes returned from sock_errno() */
+#define SOCBASEERR              10000
+#define SOCEPERM                (SOCBASEERR+1)             /* Not owner */
+#define SOCESRCH                (SOCBASEERR+3)             /* No such process */
+#define SOCEINTR                (SOCBASEERR+4)             /* Interrupted system call */
+#define SOCENXIO                (SOCBASEERR+6)             /* No such device or address */
+#define SOCEBADF                (SOCBASEERR+9)             /* Bad file number */
+#define SOCEACCES               (SOCBASEERR+13)            /* Permission denied */
+#define SOCEFAULT               (SOCBASEERR+14)            /* Bad address */
+#define SOCEINVAL               (SOCBASEERR+22)            /* Invalid argument */
+#define SOCEMFILE               (SOCBASEERR+24)            /* Too many open files */
+#define SOCEPIPE                (SOCBASEERR+32)            /* Broken pipe */
+#define SOCEOS2ERR              (SOCBASEERR+100)            /* OS/2 Error */
+
+const char *apr_inet_ntop(int af, const void *src, char *dst, apr_size_t size);
+int apr_inet_pton(int af, const char *src, void *dst);
+void apr_sockaddr_vars_set(apr_sockaddr_t *, int, apr_port_t);
+
+#endif  /* ! NETWORK_IO_H */
+
diff --git a/include/arch/os2/apr_arch_os2calls.h b/include/arch/os2/apr_arch_os2calls.h
new file mode 100644
index 00000000000..3c739bfd19f
--- /dev/null
+++ b/include/arch/os2/apr_arch_os2calls.h
@@ -0,0 +1,59 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_errno.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+
+extern int (*apr_os2_socket)(int, int, int);
+extern int (*apr_os2_select)(int *, int, int, int, long);
+extern int (*apr_os2_sock_errno)();
+extern int (*apr_os2_accept)(int, struct sockaddr *, int *);
+extern int (*apr_os2_bind)(int, struct sockaddr *, int);
+extern int (*apr_os2_connect)(int, struct sockaddr *, int);
+extern int (*apr_os2_getpeername)(int, struct sockaddr *, int *);
+extern int (*apr_os2_getsockname)(int, struct sockaddr *, int *);
+extern int (*apr_os2_getsockopt)(int, int, int, char *, int *);
+extern int (*apr_os2_ioctl)(int, int, caddr_t, int);
+extern int (*apr_os2_listen)(int, int);
+extern int (*apr_os2_recv)(int, char *, int, int);
+extern int (*apr_os2_send)(int, const char *, int, int);
+extern int (*apr_os2_setsockopt)(int, int, int, char *, int);
+extern int (*apr_os2_shutdown)(int, int);
+extern int (*apr_os2_soclose)(int);
+extern int (*apr_os2_writev)(int, struct iovec *, int);
+extern int (*apr_os2_sendto)(int, const char *, int, int, const struct sockaddr *, int);
+extern int (*apr_os2_recvfrom)(int, char *, int, int, struct sockaddr *, int *);
+
+#define socket apr_os2_socket
+#define select apr_os2_select
+#define sock_errno apr_os2_sock_errno
+#define accept apr_os2_accept
+#define bind apr_os2_bind
+#define connect apr_os2_connect
+#define getpeername apr_os2_getpeername
+#define getsockname apr_os2_getsockname
+#define getsockopt apr_os2_getsockopt
+#define ioctl apr_os2_ioctl
+#define listen apr_os2_listen
+#define recv apr_os2_recv
+#define send apr_os2_send
+#define setsockopt apr_os2_setsockopt
+#define shutdown apr_os2_shutdown
+#define soclose apr_os2_soclose
+#define writev apr_os2_writev
+#define sendto apr_os2_sendto
+#define recvfrom apr_os2_recvfrom
diff --git a/include/arch/os2/apr_arch_proc_mutex.h b/include/arch/os2/apr_arch_proc_mutex.h
new file mode 100644
index 00000000000..8caf3369dcc
--- /dev/null
+++ b/include/arch/os2/apr_arch_proc_mutex.h
@@ -0,0 +1,31 @@
+/* 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 PROC_MUTEX_H
+#define PROC_MUTEX_H
+
+#include "apr_proc_mutex.h"
+#include "apr_file_io.h"
+
+struct apr_proc_mutex_t {
+    apr_pool_t *pool;
+    HMTX hMutex;
+    TID owner;
+    int lock_count;
+};
+
+#endif  /* PROC_MUTEX_H */
+
diff --git a/include/arch/os2/apr_arch_thread_cond.h b/include/arch/os2/apr_arch_thread_cond.h
new file mode 100644
index 00000000000..aa0a7ca6f8e
--- /dev/null
+++ b/include/arch/os2/apr_arch_thread_cond.h
@@ -0,0 +1,33 @@
+/* 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 THREAD_COND_H
+#define THREAD_COND_H
+
+#include "apr_thread_cond.h"
+#include "apr_file_io.h"
+
+struct apr_thread_cond_t {
+    apr_pool_t *pool;
+    HEV semaphore;
+    HMTX mutex;
+    unsigned long num_waiting;
+    unsigned long num_wake;
+    unsigned long generation;
+};
+
+#endif  /* THREAD_COND_H */
+
diff --git a/include/arch/os2/apr_arch_thread_mutex.h b/include/arch/os2/apr_arch_thread_mutex.h
new file mode 100644
index 00000000000..3ae2a41db78
--- /dev/null
+++ b/include/arch/os2/apr_arch_thread_mutex.h
@@ -0,0 +1,29 @@
+/* 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 THREAD_MUTEX_H
+#define THREAD_MUTEX_H
+
+#include "apr_thread_mutex.h"
+#include "apr_file_io.h"
+
+struct apr_thread_mutex_t {
+    apr_pool_t *pool;
+    HMTX hMutex;
+};
+
+#endif  /* THREAD_MUTEX_H */
+
diff --git a/include/arch/os2/apr_arch_thread_rwlock.h b/include/arch/os2/apr_arch_thread_rwlock.h
new file mode 100644
index 00000000000..7187d5cb2e5
--- /dev/null
+++ b/include/arch/os2/apr_arch_thread_rwlock.h
@@ -0,0 +1,31 @@
+/* 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 THREAD_RWLOCK_H
+#define THREAD_RWLOCK_H
+
+#include "apr_thread_rwlock.h"
+#include "apr_file_io.h"
+
+struct apr_thread_rwlock_t {
+    apr_pool_t *pool;
+    int readers;
+    HMTX write_lock;
+    HEV read_done;
+};
+
+#endif  /* THREAD_RWLOCK_H */
+
diff --git a/include/arch/os2/apr_arch_threadproc.h b/include/arch/os2/apr_arch_threadproc.h
new file mode 100644
index 00000000000..c8017adbff3
--- /dev/null
+++ b/include/arch/os2/apr_arch_threadproc.h
@@ -0,0 +1,67 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_thread_proc.h"
+#include "apr_file_io.h"
+
+#ifndef THREAD_PROC_H
+#define THREAD_PROC_H
+
+#define APR_THREADATTR_DETACHED 1
+
+#define SHELL_PATH "cmd.exe"
+#define APR_THREAD_STACKSIZE 65536
+
+struct apr_threadattr_t {
+    apr_pool_t *pool;
+    unsigned long attr;
+    apr_size_t stacksize;
+};
+
+struct apr_thread_t {
+    apr_pool_t *pool;
+    struct apr_threadattr_t *attr;
+    unsigned long tid;
+    apr_thread_start_t func;
+    void *data;
+    apr_status_t exitval;
+};
+
+struct apr_threadkey_t {
+    apr_pool_t *pool;
+    unsigned long *key;
+};
+
+struct apr_procattr_t {
+    apr_pool_t *pool;
+    apr_file_t *parent_in;
+    apr_file_t *child_in;
+    apr_file_t *parent_out;
+    apr_file_t *child_out;
+    apr_file_t *parent_err;
+    apr_file_t *child_err;
+    char *currdir;
+    apr_int32_t cmdtype;
+    apr_int32_t detached;
+};
+
+struct apr_thread_once_t {
+    unsigned long sem;
+    char hit;
+};
+
+#endif  /* ! THREAD_PROC_H */
+
diff --git a/include/arch/os2/dso.h b/include/arch/os2/dso.h
deleted file mode 100644
index 02855bb0c7b..00000000000
--- a/include/arch/os2/dso.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef DSO_H
-#define DSO_H
-
-#define INCL_DOS
-#include <os2.h>
-
-#include "apr_private.h"
-#include "apr_general.h"
-#include "apr_pools.h"
-#include "apr_dso.h"
-
-struct ap_dso_handle_t {
-    ap_pool_t  *cont;       /* Context for returning error strings */
-    HMODULE       handle;     /* Handle to the DSO loaded            */
-    char          *failed_module;
-};
-
-#endif
diff --git a/include/arch/os2/fileio.h b/include/arch/os2/fileio.h
deleted file mode 100644
index b2d6d6d2ef0..00000000000
--- a/include/arch/os2/fileio.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef FILE_IO_H
-#define FILE_IO_H
-
-#define INCL_DOS
-#include <os2.h>
-
-#include "apr_private.h"
-#include "apr_general.h"
-#include "apr_lock.h"
-#include "apr_file_io.h"
-#include "apr_errno.h"
-
-#define APR_FILE_BUFSIZE 4096
-
-struct ap_file_t {
-    ap_pool_t *cntxt;
-    HFILE filedes;
-    char * fname;
-    int isopen;
-    int buffered;
-    int eof_hit;
-    ap_int32_t flags;
-    int timeout;
-    int pipe;
-    HEV pipeSem;
-
-    /* Stuff for buffered mode */
-    char *buffer;
-    int bufpos;               // Read/Write position in buffer
-    unsigned long dataRead;   // amount of valid data read into buffer
-    int direction;            // buffer being used for 0 = read, 1 = write
-    unsigned long filePtr;    // position in file of handle
-    ap_lock_t *mutex;         // mutex semaphore, must be owned to access the above fields
-};
-
-struct ap_dir_t {
-    ap_pool_t *cntxt;
-    char *dirname;
-    ULONG handle;
-    FILEFINDBUF3 entry;
-    int validentry;
-};
-
-ap_status_t apr_file_cleanup(void *);
-ap_status_t ap_os2_time_to_ap_time(ap_time_t *result, FDATE os2date, FTIME os2time);
-
-#endif  /* ! FILE_IO_H */
-
diff --git a/include/arch/os2/locks.h b/include/arch/os2/locks.h
deleted file mode 100644
index d416b6b0833..00000000000
--- a/include/arch/os2/locks.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef LOCKS_H
-#define LOCKS_H
-
-#include "apr_lock.h"
-#include "apr_file_io.h"
-#define INCL_DOS
-#include <os2.h>
-
-struct ap_lock_t {
-    ap_pool_t *cntxt;
-    ap_locktype_e type;
-    ap_lockscope_e scope;
-    char *fname;
-    HMTX hMutex;
-    TID owner;
-    int lock_count;
-    TIB *tib;
-};
-
-void setup_lock();
-
-#endif  /* LOCKS_H */
-
diff --git a/include/arch/os2/networkio.h b/include/arch/os2/networkio.h
deleted file mode 100644
index 63424de6a74..00000000000
--- a/include/arch/os2/networkio.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef NETWORK_IO_H
-#define NETWORK_IO_H
-
-#include "apr_network_io.h"
-#include "apr_general.h"
-#include "os2calls.h"
-
-struct ap_socket_t {
-    ap_pool_t *cntxt;
-    int socketdes;
-    struct sockaddr_in *local_addr;
-    struct sockaddr_in *remote_addr;
-    int addr_len;
-    ap_interval_time_t timeout;
-    int nonblock;
-};
-
-struct ap_pollfd_t {
-    ap_pool_t *cntxt;
-    int *socket_list;
-    int *r_socket_list;
-    int num_read;
-    int num_write;
-    int num_except;
-    int num_total;
-};
-
-/* Error codes returned from sock_errno() */
-#define SOCBASEERR              10000
-#define SOCEPERM                (SOCBASEERR+1)             /* Not owner */
-#define SOCESRCH                (SOCBASEERR+3)             /* No such process */
-#define SOCEINTR                (SOCBASEERR+4)             /* Interrupted system call */
-#define SOCENXIO                (SOCBASEERR+6)             /* No such device or address */
-#define SOCEBADF                (SOCBASEERR+9)             /* Bad file number */
-#define SOCEACCES               (SOCBASEERR+13)            /* Permission denied */
-#define SOCEFAULT               (SOCBASEERR+14)            /* Bad address */
-#define SOCEINVAL               (SOCBASEERR+22)            /* Invalid argument */
-#define SOCEMFILE               (SOCBASEERR+24)            /* Too many open files */
-#define SOCEPIPE                (SOCBASEERR+32)            /* Broken pipe */
-#define SOCEOS2ERR              (SOCBASEERR+100)            /* OS/2 Error */
-
-#endif  /* ! NETWORK_IO_H */
-
diff --git a/include/arch/os2/os2calls.h b/include/arch/os2/os2calls.h
deleted file mode 100644
index 40d54ee6e68..00000000000
--- a/include/arch/os2/os2calls.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-
-extern int (*apr_os2_socket)(int, int, int);
-extern int (*apr_os2_select)(int *, int, int, int, long);
-extern int (*apr_os2_sock_errno)();
-extern int (*apr_os2_accept)(int, struct sockaddr *, int *);
-extern int (*apr_os2_bind)(int, struct sockaddr *, int);
-extern int (*apr_os2_connect)(int, struct sockaddr *, int);
-extern int (*apr_os2_getpeername)(int, struct sockaddr *, int *);
-extern int (*apr_os2_getsockname)(int, struct sockaddr *, int *);
-extern int (*apr_os2_getsockopt)(int, int, int, char *, int *);
-extern int (*apr_os2_ioctl)(int, int, caddr_t, int);
-extern int (*apr_os2_listen)(int, int);
-extern int (*apr_os2_recv)(int, char *, int, int);
-extern int (*apr_os2_send)(int, const char *, int, int);
-extern int (*apr_os2_setsockopt)(int, int, int, char *, int);
-extern int (*apr_os2_shutdown)(int, int);
-extern int (*apr_os2_soclose)(int);
-extern int (*apr_os2_writev)(int, struct iovec *, int);
-
-#define socket apr_os2_socket
-#define select apr_os2_select
-#define sock_errno apr_os2_sock_errno
-#define accept apr_os2_accept
-#define bind apr_os2_bind
-#define connect apr_os2_connect
-#define getpeername apr_os2_getpeername
-#define getsockname apr_os2_getsockname
-#define getsockopt apr_os2_getsockopt
-#define ioctl apr_os2_ioctl
-#define listen apr_os2_listen
-#define recv apr_os2_recv
-#define send apr_os2_send
-#define setsockopt apr_os2_setsockopt
-#define shutdown apr_os2_shutdown
-#define soclose apr_os2_soclose
-#define writev apr_os2_writev
-
-
-/* Error codes returned by above calls */
-#define SOCBASEERR              10000
-
-#define SOCEPERM                (SOCBASEERR+1)             /* Not owner */
-#define SOCESRCH                (SOCBASEERR+3)             /* No such process */
-#define SOCEINTR                (SOCBASEERR+4)             /* Interrupted system call */
-#define SOCENXIO                (SOCBASEERR+6)             /* No such device or address */
-#define SOCEBADF                (SOCBASEERR+9)             /* Bad file number */
-#define SOCEACCES               (SOCBASEERR+13)            /* Permission denied */
-#define SOCEFAULT               (SOCBASEERR+14)            /* Bad address */
-#define SOCEINVAL               (SOCBASEERR+22)            /* Invalid argument */
-#define SOCEMFILE               (SOCBASEERR+24)            /* Too many open files */
-#define SOCEPIPE                (SOCBASEERR+32)            /* Broken pipe */
-#define SOCEOS2ERR              (SOCBASEERR+100)           /* OS/2 Error */
-#define SOCEWOULDBLOCK          (SOCBASEERR+35)            /* Operation would block */
-#define SOCEINPROGRESS          (SOCBASEERR+36)            /* Operation now in progress */
-#define SOCEALREADY             (SOCBASEERR+37)            /* Operation already in progress */
-#define SOCENOTSOCK             (SOCBASEERR+38)            /* Socket operation on non-socket */
-#define SOCEDESTADDRREQ         (SOCBASEERR+39)            /* Destination address required */
-#define SOCEMSGSIZE             (SOCBASEERR+40)            /* Message too long */
-#define SOCEPROTOTYPE           (SOCBASEERR+41)            /* Protocol wrong type for socket */
-#define SOCENOPROTOOPT          (SOCBASEERR+42)            /* Protocol not available */
-#define SOCEPROTONOSUPPORT      (SOCBASEERR+43)            /* Protocol not supported */
-#define SOCESOCKTNOSUPPORT      (SOCBASEERR+44)            /* Socket type not supported */
-#define SOCEOPNOTSUPP           (SOCBASEERR+45)            /* Operation not supported on socket */
-#define SOCEPFNOSUPPORT         (SOCBASEERR+46)            /* Protocol family not supported */
-#define SOCEAFNOSUPPORT         (SOCBASEERR+47)            /* Address family not supported by protocol family */
-#define SOCEADDRINUSE           (SOCBASEERR+48)            /* Address already in use */
-#define SOCEADDRNOTAVAIL        (SOCBASEERR+49)            /* Can't assign requested address */
-#define SOCENETDOWN             (SOCBASEERR+50)            /* Network is down */
-#define SOCENETUNREACH          (SOCBASEERR+51)            /* Network is unreachable */
-#define SOCENETRESET            (SOCBASEERR+52)            /* Network dropped connection on reset */
-#define SOCECONNABORTED         (SOCBASEERR+53)            /* Software caused connection abort */
-#define SOCECONNRESET           (SOCBASEERR+54)            /* Connection reset by peer */
-#define SOCENOBUFS              (SOCBASEERR+55)            /* No buffer space available */
-#define SOCEISCONN              (SOCBASEERR+56)            /* Socket is already connected */
-#define SOCENOTCONN             (SOCBASEERR+57)            /* Socket is not connected */
-#define SOCESHUTDOWN            (SOCBASEERR+58)            /* Can't send after socket shutdown */
-#define SOCETOOMANYREFS         (SOCBASEERR+59)            /* Too many references: can't splice */
-#define SOCETIMEDOUT            (SOCBASEERR+60)            /* Connection timed out */
-#define SOCECONNREFUSED         (SOCBASEERR+61)            /* Connection refused */
-#define SOCELOOP                (SOCBASEERR+62)            /* Too many levels of symbolic links */
-#define SOCENAMETOOLONG         (SOCBASEERR+63)            /* File name too long */
-#define SOCEHOSTDOWN            (SOCBASEERR+64)            /* Host is down */
-#define SOCEHOSTUNREACH         (SOCBASEERR+65)            /* No route to host */
-#define SOCENOTEMPTY            (SOCBASEERR+66)            /* Directory not empty */
diff --git a/include/arch/os2/threadproc.h b/include/arch/os2/threadproc.h
deleted file mode 100644
index cfcca8d621c..00000000000
--- a/include/arch/os2/threadproc.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "apr_thread_proc.h"
-#include "apr_file_io.h"
-
-#ifndef THREAD_PROC_H
-#define THREAD_PROC_H
-
-#define APR_THREADATTR_DETACHED 1
-
-#define SHELL_PATH "cmd.exe"
-#define APR_THREAD_STACKSIZE 65536
-
-struct ap_threadattr_t {
-    ap_pool_t *cntxt;
-    unsigned long attr;
-};
-
-struct ap_thread_t {
-    ap_pool_t *cntxt;
-    struct ap_threadattr_t *attr;
-    unsigned long tid;
-    ap_thread_start_t func;
-    void *data;
-    void *rv;
-};
-
-struct ap_threadkey_t {
-    ap_pool_t *cntxt;
-    unsigned long *key;
-};
-
-struct ap_procattr_t {
-    ap_pool_t *cntxt;
-    ap_file_t *parent_in;
-    ap_file_t *child_in;
-    ap_file_t *parent_out;
-    ap_file_t *child_out;
-    ap_file_t *parent_err;
-    ap_file_t *child_err;
-    char *currdir;
-    ap_int32_t cmdtype;
-    ap_int32_t detached;
-};
-
-struct ap_proc_t {
-    ap_pool_t *cntxt;
-    pid_t pid;
-    struct ap_procattr_t *attr;
-    int running;
-};
-
-typedef void (*os2_thread_start_t)(void *);
-
-#endif  /* ! THREAD_PROC_H */
-
diff --git a/include/arch/os390/apr_arch_dso.h b/include/arch/os390/apr_arch_dso.h
new file mode 100644
index 00000000000..4263297b407
--- /dev/null
+++ b/include/arch/os390/apr_arch_dso.h
@@ -0,0 +1,39 @@
+/* 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 DSO_H
+#define DSO_H
+
+#include "apr_private.h"
+#include "apr_general.h"
+#include "apr_pools.h"
+#include "apr_dso.h"
+#include "apr.h"
+
+#if APR_HAS_DSO
+
+#include <dll.h>
+
+struct apr_dso_handle_t {
+    dllhandle  *handle;     /* Handle to the DSO loaded            */
+    int failing_errno;      /* Don't save the buffer returned by
+                               strerror(); it gets reused          */
+    apr_pool_t *pool;
+};
+
+#endif
+
+#endif
diff --git a/include/arch/unix/apr_arch_atomic.h b/include/arch/unix/apr_arch_atomic.h
new file mode 100644
index 00000000000..f8019060e50
--- /dev/null
+++ b/include/arch/unix/apr_arch_atomic.h
@@ -0,0 +1,45 @@
+/* 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 ATOMIC_H
+#define ATOMIC_H
+
+#include "apr.h"
+#include "apr_private.h"
+#include "apr_atomic.h"
+#include "apr_thread_mutex.h"
+
+#if defined(USE_ATOMICS_GENERIC)
+/* noop */
+#elif defined(__GNUC__) && defined(__STRICT_ANSI__)
+/* force use of generic atomics if building e.g. with -std=c89, which
+ * doesn't allow inline asm */
+#   define USE_ATOMICS_GENERIC
+#elif HAVE_ATOMIC_BUILTINS
+#   define USE_ATOMICS_BUILTINS
+#elif defined(SOLARIS2) && SOLARIS2 >= 10
+#   define USE_ATOMICS_SOLARIS
+#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+#   define USE_ATOMICS_IA32
+#elif defined(__GNUC__) && (defined(__PPC__) || defined(__ppc__))
+#   define USE_ATOMICS_PPC
+#elif defined(__GNUC__) && (defined(__s390__) || defined(__s390x__))
+#   define USE_ATOMICS_S390
+#else
+#   define USE_ATOMICS_GENERIC
+#endif
+
+#endif /* ATOMIC_H */
diff --git a/include/arch/unix/apr_arch_dso.h b/include/arch/unix/apr_arch_dso.h
new file mode 100644
index 00000000000..d82182d48b8
--- /dev/null
+++ b/include/arch/unix/apr_arch_dso.h
@@ -0,0 +1,63 @@
+/* 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 DSO_H
+#define DSO_H
+
+#include "apr_private.h"
+#include "apr_general.h"
+#include "apr_pools.h"
+#include "apr_dso.h"
+#include "apr.h"
+
+#if APR_HAS_DSO
+
+#ifdef HAVE_MACH_O_DYLD_H
+#include <mach-o/dyld.h>
+#endif
+
+#ifdef HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#ifdef HAVE_DL_H
+#include <dl.h>
+#endif
+
+#ifndef RTLD_NOW
+#define RTLD_NOW 1
+#endif
+
+#ifndef RTLD_GLOBAL
+#define RTLD_GLOBAL 0
+#endif
+
+#if (defined(__DragonFly__) ||\
+     defined(__FreeBSD__) ||\
+     defined(__OpenBSD__) ||\
+     defined(__NetBSD__)     ) && !defined(__ELF__)
+#define DLSYM_NEEDS_UNDERSCORE
+#endif
+
+struct apr_dso_handle_t {
+    apr_pool_t    *pool;
+    void          *handle;
+    const char    *errormsg;
+};
+
+#endif
+
+#endif
diff --git a/include/arch/unix/apr_arch_file_io.h b/include/arch/unix/apr_arch_file_io.h
new file mode 100644
index 00000000000..5847cdc2c79
--- /dev/null
+++ b/include/arch/unix/apr_arch_file_io.h
@@ -0,0 +1,186 @@
+/* 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 FILE_IO_H
+#define FILE_IO_H
+
+#include "apr.h"
+#include "apr_private.h"
+#include "apr_general.h"
+#include "apr_tables.h"
+#include "apr_file_io.h"
+#include "apr_file_info.h"
+#include "apr_errno.h"
+#include "apr_lib.h"
+#include "apr_thread_mutex.h"
+#ifndef WAITIO_USES_POLL
+#include "apr_poll.h"
+#endif
+#include "apr_time.h"
+
+
+/* System headers the file I/O library needs */
+#if APR_HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#if APR_HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#if APR_HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#if APR_HAVE_STRING_H
+#include <string.h>
+#endif
+#if APR_HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#if APR_HAVE_DIRENT_H
+#include <dirent.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if APR_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if APR_HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if APR_HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#endif
+#if APR_HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef BEOS
+#include <kernel/OS.h>
+#endif
+/* Hunting down DEV_BSIZE if not from dirent.h, sys/stat.h etc */
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#if BEOS_BONE
+# ifndef BONE7
+  /* prior to BONE/7 fd_set & select were defined in sys/socket.h */
+#  include <sys/socket.h>
+# else
+  /* Be moved the fd_set stuff and also the FIONBIO definition... */
+#  include <sys/ioctl.h>
+# endif
+#endif
+/* End System headers */
+
+#define APR_FILE_DEFAULT_BUFSIZE 4096
+/* For backwards-compat */
+#define APR_FILE_BUFSIZE  APR_FILE_DEFAULT_BUFSIZE
+
+typedef struct apr_rotating_info_t {
+    apr_finfo_t finfo;
+    apr_interval_time_t timeout;
+    apr_time_t lastcheck;
+    int oflags;
+    int manual;
+    apr_fileperms_t perm;
+} apr_rotating_info_t;
+
+struct apr_file_t {
+    apr_pool_t *pool;
+    int filedes;
+    char *fname;
+    apr_int32_t flags;
+    int eof_hit;
+    int is_pipe;
+    apr_interval_time_t timeout;
+    int buffered;
+    enum {BLK_UNKNOWN, BLK_OFF, BLK_ON } blocking;
+    int ungetchar;    /* Last char provided by an unget op. (-1 = no char)*/
+#ifndef WAITIO_USES_POLL
+    /* if there is a timeout set, then this pollset is used */
+    apr_pollset_t *pollset;
+#endif
+    /* Stuff for buffered mode */
+    char *buffer;
+    apr_size_t bufpos;        /* Read/Write position in buffer */
+    apr_size_t bufsize;       /* The size of the buffer */
+    unsigned long dataRead;   /* amount of valid data read into buffer */
+    int direction;            /* buffer being used for 0 = read, 1 = write */
+    apr_off_t filePtr;        /* position in file of handle */
+#if APR_HAS_THREADS
+    struct apr_thread_mutex_t *thlock;
+#endif
+    apr_rotating_info_t *rotating;
+};
+
+#if APR_HAS_THREADS
+#define file_lock(f)   do { \
+                           if ((f)->thlock) \
+                               apr_thread_mutex_lock((f)->thlock); \
+                       } while (0)
+#define file_unlock(f) do { \
+                           if ((f)->thlock) \
+                               apr_thread_mutex_unlock((f)->thlock); \
+                       } while (0)
+#else
+#define file_lock(f)   do {} while (0)
+#define file_unlock(f) do {} while (0)
+#endif
+
+#if APR_HAS_LARGE_FILES && defined(_LARGEFILE64_SOURCE)
+#define stat(f,b) stat64(f,b)
+#define lstat(f,b) lstat64(f,b)
+#define fstat(f,b) fstat64(f,b)
+#define lseek(f,o,w) lseek64(f,o,w)
+#define ftruncate(f,l) ftruncate64(f,l)
+typedef struct stat64 struct_stat;
+#else
+typedef struct stat struct_stat;
+#endif
+
+/* readdir64_r is only used in specific cases: */
+#if APR_HAS_THREADS && defined(_POSIX_THREAD_SAFE_FUNCTIONS) \
+    && !defined(READDIR_IS_THREAD_SAFE) && defined(HAVE_READDIR64_R)
+#define APR_USE_READDIR64_R
+#endif
+
+struct apr_dir_t {
+    apr_pool_t *pool;
+    char *dirname;
+    DIR *dirstruct;
+#ifdef APR_USE_READDIR64_R
+    struct dirent64 *entry;
+#else
+    struct dirent *entry;
+#endif
+};
+
+apr_status_t apr_unix_file_cleanup(void *);
+apr_status_t apr_unix_child_file_cleanup(void *);
+
+mode_t apr_unix_perms2mode(apr_fileperms_t perms);
+apr_fileperms_t apr_unix_mode2perms(mode_t mode);
+
+apr_status_t apr_file_flush_locked(apr_file_t *thefile);
+apr_status_t apr_file_info_get_locked(apr_finfo_t *finfo, apr_int32_t wanted,
+                                      apr_file_t *thefile);
+
+
+#endif  /* ! FILE_IO_H */
+
diff --git a/include/arch/unix/apr_arch_global_mutex.h b/include/arch/unix/apr_arch_global_mutex.h
new file mode 100644
index 00000000000..3add9ecfa75
--- /dev/null
+++ b/include/arch/unix/apr_arch_global_mutex.h
@@ -0,0 +1,37 @@
+/* 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 GLOBAL_MUTEX_H
+#define GLOBAL_MUTEX_H
+
+#include "apr.h"
+#include "apr_private.h"
+#include "apr_general.h"
+#include "apr_lib.h"
+#include "apr_global_mutex.h"
+#include "apr_arch_proc_mutex.h"
+#include "apr_arch_thread_mutex.h"
+
+struct apr_global_mutex_t {
+    apr_pool_t *pool;
+    apr_proc_mutex_t *proc_mutex;
+#if APR_HAS_THREADS
+    apr_thread_mutex_t *thread_mutex;
+#endif /* APR_HAS_THREADS */
+};
+
+#endif  /* GLOBAL_MUTEX_H */
+
diff --git a/include/arch/unix/apr_arch_inherit.h b/include/arch/unix/apr_arch_inherit.h
new file mode 100644
index 00000000000..21543c1e1c3
--- /dev/null
+++ b/include/arch/unix/apr_arch_inherit.h
@@ -0,0 +1,64 @@
+/* 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 INHERIT_H
+#define INHERIT_H
+
+#include "apr_inherit.h"
+
+#define APR_INHERIT (1 << 24)    /* Must not conflict with other bits */
+
+#define APR_IMPLEMENT_INHERIT_SET(name, flag, pool, cleanup)        \
+apr_status_t apr_##name##_inherit_set(apr_##name##_t *the##name)    \
+{                                                                   \
+    if (the##name->flag & APR_FOPEN_NOCLEANUP)                      \
+        return APR_EINVAL;                                          \
+    if (!(the##name->flag & APR_INHERIT)) {                         \
+        int flags = fcntl(the##name->name##des, F_GETFD);           \
+        if (flags == -1)                                            \
+            return errno;                                           \
+        flags &= ~(FD_CLOEXEC);                                     \
+        if (fcntl(the##name->name##des, F_SETFD, flags) == -1)      \
+            return errno;                                           \
+        the##name->flag |= APR_INHERIT;                             \
+        apr_pool_child_cleanup_set(the##name->pool,                 \
+                                   (void *)the##name,               \
+                                   cleanup, apr_pool_cleanup_null); \
+    }                                                               \
+    return APR_SUCCESS;                                             \
+}
+
+#define APR_IMPLEMENT_INHERIT_UNSET(name, flag, pool, cleanup)      \
+apr_status_t apr_##name##_inherit_unset(apr_##name##_t *the##name)  \
+{                                                                   \
+    if (the##name->flag & APR_FOPEN_NOCLEANUP)                      \
+        return APR_EINVAL;                                          \
+    if (the##name->flag & APR_INHERIT) {                            \
+        int flags;                                                  \
+        if ((flags = fcntl(the##name->name##des, F_GETFD)) == -1)   \
+            return errno;                                           \
+        flags |= FD_CLOEXEC;                                        \
+        if (fcntl(the##name->name##des, F_SETFD, flags) == -1)      \
+            return errno;                                           \
+        the##name->flag &= ~APR_INHERIT;                            \
+        apr_pool_child_cleanup_set(the##name->pool,                 \
+                                   (void *)the##name,               \
+                                   cleanup, cleanup);               \
+    }                                                               \
+    return APR_SUCCESS;                                             \
+}
+
+#endif	/* ! INHERIT_H */
diff --git a/include/arch/unix/apr_arch_internal_time.h b/include/arch/unix/apr_arch_internal_time.h
new file mode 100644
index 00000000000..6e12c67439a
--- /dev/null
+++ b/include/arch/unix/apr_arch_internal_time.h
@@ -0,0 +1,24 @@
+/* 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 TIME_INTERNAL_H
+#define TIME_INTERNAL_H
+
+#include "apr.h"
+
+void apr_unix_setup_time(void);
+
+#endif  /* TIME_INTERNAL_H */
diff --git a/include/arch/unix/apr_arch_misc.h b/include/arch/unix/apr_arch_misc.h
new file mode 100644
index 00000000000..1e8ab0b7541
--- /dev/null
+++ b/include/arch/unix/apr_arch_misc.h
@@ -0,0 +1,66 @@
+/* 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 MISC_H
+#define MISC_H
+
+#include "apr.h"
+#include "apr_portable.h"
+#include "apr_private.h"
+#include "apr_general.h"
+#include "apr_pools.h"
+#include "apr_getopt.h"
+#include "apr_thread_proc.h"
+#include "apr_file_io.h"
+#include "apr_errno.h"
+#include "apr_getopt.h"
+
+#if APR_HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#if APR_HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+#if APR_HAVE_PTHREAD_H
+#include <pthread.h>
+#endif
+
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if APR_HAVE_STRING_H
+#include <string.h>
+#endif
+
+#ifdef BEOS
+#include <kernel/OS.h>
+#endif
+
+struct apr_other_child_rec_t {
+    apr_pool_t *p;
+    struct apr_other_child_rec_t *next;
+    apr_proc_t *proc;
+    void (*maintenance) (int, void *, int);
+    void *data;
+};
+
+#if defined(WIN32) || defined(NETWARE)
+#define WSAHighByte 2
+#define WSALowByte 0
+#endif
+
+#endif  /* ! MISC_H */
+
diff --git a/include/arch/unix/apr_arch_networkio.h b/include/arch/unix/apr_arch_networkio.h
new file mode 100644
index 00000000000..5f3189d9666
--- /dev/null
+++ b/include/arch/unix/apr_arch_networkio.h
@@ -0,0 +1,145 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef NETWORK_IO_H
+#define NETWORK_IO_H
+
+#include "apr.h"
+#include "apr_private.h"
+#include "apr_network_io.h"
+#include "apr_errno.h"
+#include "apr_general.h"
+#include "apr_lib.h"
+#ifndef WAITIO_USES_POLL
+#include "apr_poll.h"
+#endif
+
+/* System headers the network I/O library needs */
+#if APR_HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#if APR_HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#endif
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#if APR_HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#if APR_HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#if APR_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if APR_HAVE_STRING_H
+#include <string.h>
+#endif
+#if APR_HAVE_NETINET_TCP_H
+#include <netinet/tcp.h>
+#endif
+#if APR_HAVE_NETINET_SCTP_UIO_H
+#include <netinet/sctp_uio.h>
+#endif
+#if APR_HAVE_NETINET_SCTP_H
+#include <netinet/sctp.h>
+#endif
+#if APR_HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#if APR_HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#if APR_HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#if APR_HAVE_SYS_SOCKIO_H
+#include <sys/sockio.h>
+#endif
+#if APR_HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#if APR_HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#if APR_HAVE_SYS_SENDFILE_H
+#include <sys/sendfile.h>
+#endif
+#if APR_HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+/* End System Headers */
+
+#ifndef HAVE_POLLIN
+#define POLLIN   1
+#define POLLPRI  2
+#define POLLOUT  4
+#define POLLERR  8
+#define POLLHUP  16
+#define POLLNVAL 32
+#endif
+
+typedef struct sock_userdata_t sock_userdata_t;
+struct sock_userdata_t {
+    sock_userdata_t *next;
+    const char *key;
+    void *data;
+};
+
+struct apr_socket_t {
+    apr_pool_t *pool;
+    int socketdes;
+    int type;
+    int protocol;
+    apr_sockaddr_t *local_addr;
+    apr_sockaddr_t *remote_addr;
+    apr_interval_time_t timeout; 
+#ifndef HAVE_POLL
+    int connected;
+#endif
+#if APR_HAVE_SOCKADDR_UN
+    int bound;
+#endif
+    int local_port_unknown;
+    int local_interface_unknown;
+    int remote_addr_unknown;
+    apr_int32_t options;
+    apr_int32_t inherit;
+    sock_userdata_t *userdata;
+#ifndef WAITIO_USES_POLL
+    /* if there is a timeout set, then this pollset is used */
+    apr_pollset_t *pollset;
+#endif
+};
+
+const char *apr_inet_ntop(int af, const void *src, char *dst, apr_size_t size);
+int apr_inet_pton(int af, const char *src, void *dst);
+void apr_sockaddr_vars_set(apr_sockaddr_t *, int, apr_port_t);
+
+#define apr_is_option_set(skt, option)  \
+    (((skt)->options & (option)) == (option))
+
+#define apr_set_option(skt, option, on) \
+    do {                                 \
+        if (on)                          \
+            (skt)->options |= (option);         \
+        else                             \
+            (skt)->options &= ~(option);        \
+    } while (0)
+
+#endif  /* ! NETWORK_IO_H */
+
diff --git a/include/arch/unix/apr_arch_poll_private.h b/include/arch/unix/apr_arch_poll_private.h
new file mode 100644
index 00000000000..ff813123134
--- /dev/null
+++ b/include/arch/unix/apr_arch_poll_private.h
@@ -0,0 +1,189 @@
+/* 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 APR_ARCH_POLL_PRIVATE_H
+#define APR_ARCH_POLL_PRIVATE_H
+
+#if HAVE_POLL_H
+#include <poll.h>
+#endif
+
+#if HAVE_SYS_POLL_H
+#include <sys/poll.h>
+#endif
+
+#ifdef HAVE_PORT_CREATE
+#include <port.h>
+#include <sys/port_impl.h>
+#endif
+
+#ifdef HAVE_KQUEUE
+#include <sys/types.h>
+#include <sys/event.h>
+#include <sys/time.h>
+#endif
+
+#ifdef HAVE_EPOLL
+#include <sys/epoll.h>
+#endif
+
+#ifdef NETWARE
+#define HAS_SOCKETS(dt) (dt == APR_POLL_SOCKET) ? 1 : 0
+#define HAS_PIPES(dt) (dt == APR_POLL_FILE) ? 1 : 0
+#endif
+
+#if defined(HAVE_AIO_H) && defined(HAVE_AIO_MSGQ)
+#define _AIO_OS390	/* enable a bunch of z/OS aio.h definitions */
+#include <aio.h>	/* aiocb	*/
+#endif
+
+/* Choose the best method platform specific to use in apr_pollset */
+#ifdef HAVE_KQUEUE
+#define POLLSET_USES_KQUEUE
+#define POLLSET_DEFAULT_METHOD APR_POLLSET_KQUEUE
+#elif defined(HAVE_PORT_CREATE)
+#define POLLSET_USES_PORT
+#define POLLSET_DEFAULT_METHOD APR_POLLSET_PORT
+#elif defined(HAVE_EPOLL)
+#define POLLSET_USES_EPOLL
+#define POLLSET_DEFAULT_METHOD APR_POLLSET_EPOLL
+#elif defined(HAVE_AIO_MSGQ)
+#define POLLSET_USES_AIO_MSGQ
+#define POLLSET_DEFAULT_METHOD APR_POLLSET_AIO_MSGQ
+#elif defined(HAVE_POLL)
+#define POLLSET_USES_POLL
+#define POLLSET_DEFAULT_METHOD APR_POLLSET_POLL
+#else
+#define POLLSET_USES_SELECT
+#define POLLSET_DEFAULT_METHOD APR_POLLSET_SELECT
+#endif
+
+#ifdef WIN32
+#define POLL_USES_SELECT
+#undef POLLSET_DEFAULT_METHOD
+#define POLLSET_DEFAULT_METHOD APR_POLLSET_SELECT
+#else
+#ifdef HAVE_POLL
+#define POLL_USES_POLL
+#else
+#define POLL_USES_SELECT
+#endif
+#endif
+
+#if defined(POLLSET_USES_KQUEUE) || defined(POLLSET_USES_EPOLL) || defined(POLLSET_USES_PORT) || defined(POLLSET_USES_AIO_MSGQ)
+
+#include "apr_ring.h"
+
+#if APR_HAS_THREADS
+#include "apr_thread_mutex.h"
+#define pollset_lock_rings() \
+    if (pollset->flags & APR_POLLSET_THREADSAFE) \
+        apr_thread_mutex_lock(pollset->p->ring_lock);
+#define pollset_unlock_rings() \
+    if (pollset->flags & APR_POLLSET_THREADSAFE) \
+        apr_thread_mutex_unlock(pollset->p->ring_lock);
+#else
+#define pollset_lock_rings()
+#define pollset_unlock_rings()
+#endif
+
+typedef struct pfd_elem_t pfd_elem_t;
+
+struct pfd_elem_t {
+    APR_RING_ENTRY(pfd_elem_t) link;
+    apr_pollfd_t pfd;
+#ifdef HAVE_PORT_CREATE
+   int on_query_ring;
+#endif
+};
+
+#endif
+
+typedef struct apr_pollset_private_t apr_pollset_private_t;
+typedef struct apr_pollset_provider_t apr_pollset_provider_t;
+typedef struct apr_pollcb_provider_t apr_pollcb_provider_t;
+
+struct apr_pollset_t
+{
+    apr_pool_t *pool;
+    apr_uint32_t nelts;
+    apr_uint32_t nalloc;
+    apr_uint32_t flags;
+    /* Pipe descriptors used for wakeup */
+    apr_file_t *wakeup_pipe[2];
+    apr_pollfd_t wakeup_pfd;
+    apr_pollset_private_t *p;
+    const apr_pollset_provider_t *provider;
+};
+
+typedef union {
+#if defined(HAVE_EPOLL)
+    struct epoll_event *epoll;
+#endif
+#if defined(HAVE_PORT_CREATE)
+    port_event_t *port;
+#endif
+#if defined(HAVE_KQUEUE)
+    struct kevent *ke;
+#endif
+#if defined(HAVE_POLL)
+    struct pollfd *ps;
+#endif
+    void *undef;
+} apr_pollcb_pset;
+
+struct apr_pollcb_t {
+    apr_pool_t *pool;
+    apr_uint32_t nelts;
+    apr_uint32_t nalloc;
+    apr_uint32_t flags;
+    /* Pipe descriptors used for wakeup */
+    apr_file_t *wakeup_pipe[2];
+    apr_pollfd_t wakeup_pfd;
+    int fd;
+    apr_pollcb_pset pollset;
+    apr_pollfd_t **copyset;
+    const apr_pollcb_provider_t *provider;
+};
+
+struct apr_pollset_provider_t {
+    apr_status_t (*create)(apr_pollset_t *, apr_uint32_t, apr_pool_t *, apr_uint32_t);
+    apr_status_t (*add)(apr_pollset_t *, const apr_pollfd_t *);
+    apr_status_t (*remove)(apr_pollset_t *, const apr_pollfd_t *);
+    apr_status_t (*poll)(apr_pollset_t *, apr_interval_time_t, apr_int32_t *, const apr_pollfd_t **);
+    apr_status_t (*cleanup)(apr_pollset_t *);
+    const char *name;
+};
+
+struct apr_pollcb_provider_t {
+    apr_status_t (*create)(apr_pollcb_t *, apr_uint32_t, apr_pool_t *, apr_uint32_t);
+    apr_status_t (*add)(apr_pollcb_t *, apr_pollfd_t *);
+    apr_status_t (*remove)(apr_pollcb_t *, apr_pollfd_t *);
+    apr_status_t (*poll)(apr_pollcb_t *, apr_interval_time_t, apr_pollcb_cb_t, void *);
+    apr_status_t (*cleanup)(apr_pollcb_t *);
+    const char *name;
+};
+
+/* 
+ * Private functions used for the implementation of both apr_pollcb_* and 
+ * apr_pollset_*
+ */
+apr_status_t apr_poll_create_wakeup_pipe(apr_pool_t *pool, apr_pollfd_t *pfd, 
+                                         apr_file_t **wakeup_pipe);
+apr_status_t apr_poll_close_wakeup_pipe(apr_file_t **wakeup_pipe);
+void apr_poll_drain_wakeup_pipe(apr_file_t **wakeup_pipe);
+
+#endif /* APR_ARCH_POLL_PRIVATE_H */
diff --git a/include/arch/unix/apr_arch_proc_mutex.h b/include/arch/unix/apr_arch_proc_mutex.h
new file mode 100644
index 00000000000..cfa0049f754
--- /dev/null
+++ b/include/arch/unix/apr_arch_proc_mutex.h
@@ -0,0 +1,121 @@
+/* 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 PROC_MUTEX_H
+#define PROC_MUTEX_H
+
+#include "apr.h"
+#include "apr_private.h"
+#include "apr_general.h"
+#include "apr_lib.h"
+#include "apr_proc_mutex.h"
+#include "apr_pools.h"
+#include "apr_portable.h"
+#include "apr_file_io.h"
+#include "apr_arch_file_io.h"
+#include "apr_time.h"
+
+/* System headers required by Locks library */
+#if APR_HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#if APR_HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#if APR_HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#ifdef HAVE_SYS_IPC_H
+#include <sys/ipc.h>
+#endif
+#ifdef HAVE_SYS_SEM_H
+#include <sys/sem.h>
+#endif
+#ifdef HAVE_SYS_FILE_H
+#include <sys/file.h>
+#endif
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if APR_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if APR_HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+#if APR_HAVE_PTHREAD_H
+#include <pthread.h>
+#endif
+/* End System Headers */
+
+struct apr_proc_mutex_unix_lock_methods_t {
+    unsigned int flags;
+    apr_status_t (*create)(apr_proc_mutex_t *, const char *);
+    apr_status_t (*acquire)(apr_proc_mutex_t *);
+    apr_status_t (*tryacquire)(apr_proc_mutex_t *);
+    apr_status_t (*timedacquire)(apr_proc_mutex_t *, apr_interval_time_t);
+    apr_status_t (*release)(apr_proc_mutex_t *);
+    apr_status_t (*cleanup)(void *);
+    apr_status_t (*child_init)(apr_proc_mutex_t **, apr_pool_t *, const char *);
+    apr_status_t (*perms_set)(apr_proc_mutex_t *, apr_fileperms_t, apr_uid_t, apr_gid_t);
+    apr_lockmech_e mech;
+    const char *name;
+};
+typedef struct apr_proc_mutex_unix_lock_methods_t apr_proc_mutex_unix_lock_methods_t;
+
+/* bit values for flags field in apr_unix_lock_methods_t */
+#define APR_PROCESS_LOCK_MECH_IS_GLOBAL          1
+
+#if !APR_HAVE_UNION_SEMUN && defined(APR_HAS_SYSVSEM_SERIALIZE)
+union semun {
+    int val;
+    struct semid_ds *buf;
+    unsigned short *array;
+};
+#endif
+
+struct apr_proc_mutex_t {
+    apr_pool_t *pool;
+    const apr_proc_mutex_unix_lock_methods_t *meth;
+    int curr_locked;
+    char *fname;
+
+    apr_os_proc_mutex_t os;     /* Native mutex holder. */
+
+#if APR_HAS_FCNTL_SERIALIZE || APR_HAS_FLOCK_SERIALIZE
+    apr_file_t *interproc;      /* For apr_file_ calls on native fd. */
+    int interproc_closing;      /* whether the native fd is opened/closed with
+                                 * 'interproc' or apr_os_file_put()ed (hence
+                                 * needing an an explicit close for consistency
+                                 * with other methods).
+                                 */
+#endif
+#if APR_HAS_PROC_PTHREAD_SERIALIZE
+    int pthread_refcounting;    /* Whether the native mutex is refcounted or
+                                 * apr_os_proc_mutex_put()ed, which makes
+                                 * refcounting impossible/undesirable.
+                                 */
+#endif
+};
+
+void apr_proc_mutex_unix_setup_lock(void);
+
+#endif  /* PROC_MUTEX_H */
+
diff --git a/include/arch/unix/apr_arch_shm.h b/include/arch/unix/apr_arch_shm.h
new file mode 100644
index 00000000000..e9d25cadb40
--- /dev/null
+++ b/include/arch/unix/apr_arch_shm.h
@@ -0,0 +1,74 @@
+/* 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 SHM_H
+#define SHM_H
+
+#include "apr.h"
+#include "apr_private.h"
+#include "apr_general.h"
+#include "apr_lib.h"
+#include "apr_shm.h"
+#include "apr_pools.h"
+#include "apr_file_io.h"
+#include "apr_network_io.h"
+#include "apr_portable.h"
+
+#if APR_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+#ifdef HAVE_SYS_IPC_H
+#include <sys/ipc.h>
+#endif
+#ifdef HAVE_SYS_MUTEX_H
+#include <sys/mutex.h>
+#endif
+#ifdef HAVE_SYS_SHM_H
+#include <sys/shm.h>
+#endif
+#if !defined(SHM_R)
+#define SHM_R 0400
+#endif
+#if !defined(SHM_W)
+#define SHM_W 0200
+#endif
+#ifdef HAVE_SYS_FILE_H
+#include <sys/file.h>
+#endif
+
+/* Not all systems seem to have MAP_FAILED defined, but it should always
+ * just be (void *)-1. */
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *)-1)
+#endif
+
+struct apr_shm_t {
+    apr_pool_t *pool;
+    void *base;          /* base real address */
+    void *usable;        /* base usable address */
+    apr_size_t reqsize;  /* requested segment size */
+    apr_size_t realsize; /* actual segment size */
+    const char *filename;      /* NULL if anonymous */
+#if APR_USE_SHMEM_SHMGET || APR_USE_SHMEM_SHMGET_ANON
+    int shmid;          /* shmem ID returned from shmget() */
+    key_t shmkey;       /* shmem key IPC_ANON or returned from ftok() */
+#endif
+};
+
+#endif /* SHM_H */
diff --git a/include/arch/unix/apr_arch_thread_cond.h b/include/arch/unix/apr_arch_thread_cond.h
new file mode 100644
index 00000000000..5c2b51d1f4b
--- /dev/null
+++ b/include/arch/unix/apr_arch_thread_cond.h
@@ -0,0 +1,42 @@
+/* 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 THREAD_COND_H
+#define THREAD_COND_H
+
+#include "apr.h"
+#include "apr_private.h"
+#include "apr_general.h"
+#include "apr_lib.h"
+#include "apr_thread_mutex.h"
+#include "apr_thread_cond.h"
+#include "apr_pools.h"
+
+#if APR_HAVE_PTHREAD_H
+#include <pthread.h>
+#endif
+
+/* XXX: Should we have a better autoconf search, something like
+ * APR_HAS_PTHREAD_COND? -aaron */
+#if APR_HAS_THREADS
+struct apr_thread_cond_t {
+    apr_pool_t *pool;
+    pthread_cond_t cond;
+};
+#endif
+
+#endif  /* THREAD_COND_H */
+
diff --git a/include/arch/unix/apr_arch_thread_mutex.h b/include/arch/unix/apr_arch_thread_mutex.h
new file mode 100644
index 00000000000..4fe46c3b427
--- /dev/null
+++ b/include/arch/unix/apr_arch_thread_mutex.h
@@ -0,0 +1,42 @@
+/* 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 THREAD_MUTEX_H
+#define THREAD_MUTEX_H
+
+#include "apr.h"
+#include "apr_private.h"
+#include "apr_general.h"
+#include "apr_thread_mutex.h"
+#include "apr_thread_cond.h"
+#include "apr_portable.h"
+#include "apr_atomic.h"
+
+#if APR_HAVE_PTHREAD_H
+#include <pthread.h>
+#endif
+
+#if APR_HAS_THREADS
+struct apr_thread_mutex_t {
+    apr_pool_t *pool;
+    pthread_mutex_t mutex;
+    apr_thread_cond_t *cond;
+    int locked, num_waiters;
+};
+#endif
+
+#endif  /* THREAD_MUTEX_H */
+
diff --git a/include/arch/unix/apr_arch_thread_rwlock.h b/include/arch/unix/apr_arch_thread_rwlock.h
new file mode 100644
index 00000000000..2cb43af6a35
--- /dev/null
+++ b/include/arch/unix/apr_arch_thread_rwlock.h
@@ -0,0 +1,49 @@
+/* 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 THREAD_RWLOCK_H
+#define THREAD_RWLOCK_H
+
+#include "apr.h"
+#include "apr_private.h"
+#include "apr_general.h"
+#include "apr_thread_rwlock.h"
+#include "apr_pools.h"
+
+#if APR_HAVE_PTHREAD_H
+/* this gives us pthread_rwlock_t */
+#include <pthread.h>
+#endif
+
+#if APR_HAS_THREADS
+#ifdef HAVE_PTHREAD_RWLOCKS
+
+struct apr_thread_rwlock_t {
+    apr_pool_t *pool;
+    pthread_rwlock_t rwlock;
+};
+
+#else
+
+struct apr_thread_rwlock_t {
+    apr_pool_t *pool;
+};
+#endif
+
+#endif
+
+#endif  /* THREAD_RWLOCK_H */
+
diff --git a/include/arch/unix/apr_arch_threadproc.h b/include/arch/unix/apr_arch_threadproc.h
new file mode 100644
index 00000000000..7a3b3c0925b
--- /dev/null
+++ b/include/arch/unix/apr_arch_threadproc.h
@@ -0,0 +1,119 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_private.h"
+#include "apr_thread_proc.h"
+#include "apr_file_io.h"
+#include "apr_arch_file_io.h"
+#include "apr_perms_set.h"
+
+/* System headers required for thread/process library */
+#if APR_HAVE_PTHREAD_H
+#include <pthread.h>
+#endif
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+#if APR_HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+#if APR_HAVE_STRING_H
+#include <string.h>
+#endif
+#if APR_HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+#if APR_HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_SCHED_H
+#include <sched.h>
+#endif
+/* End System Headers */
+
+
+#ifndef THREAD_PROC_H
+#define THREAD_PROC_H
+
+#define SHELL_PATH "/bin/sh"
+
+#if APR_HAS_THREADS
+
+struct apr_thread_t {
+    apr_pool_t *pool;
+    pthread_t *td;
+    void *data;
+    apr_thread_start_t func;
+    apr_status_t exitval;
+};
+
+struct apr_threadattr_t {
+    apr_pool_t *pool;
+    pthread_attr_t attr;
+};
+
+struct apr_threadkey_t {
+    apr_pool_t *pool;
+    pthread_key_t key;
+};
+
+struct apr_thread_once_t {
+    pthread_once_t once;
+};
+
+#endif
+
+typedef struct apr_procattr_pscb_t apr_procattr_pscb_t;
+struct apr_procattr_pscb_t {
+    struct apr_procattr_pscb_t *next;
+    apr_perms_setfn_t *perms_set_fn;
+    apr_fileperms_t perms;
+    const void *data;
+};
+
+struct apr_procattr_t {
+    apr_pool_t *pool;
+    apr_file_t *parent_in;
+    apr_file_t *child_in;
+    apr_file_t *parent_out;
+    apr_file_t *child_out;
+    apr_file_t *parent_err;
+    apr_file_t *child_err;
+    char *currdir;
+    apr_int32_t cmdtype;
+    apr_int32_t detached;
+#ifdef RLIMIT_CPU
+    struct rlimit *limit_cpu;
+#endif
+#if defined (RLIMIT_DATA) || defined (RLIMIT_VMEM) || defined(RLIMIT_AS)
+    struct rlimit *limit_mem;
+#endif
+#ifdef RLIMIT_NPROC
+    struct rlimit *limit_nproc;
+#endif
+#ifdef RLIMIT_NOFILE
+    struct rlimit *limit_nofile;
+#endif
+    apr_child_errfn_t *errfn;
+    apr_int32_t errchk;
+    apr_uid_t   uid;
+    apr_gid_t   gid;
+    apr_procattr_pscb_t *perms_set_callbacks;
+};
+
+#endif  /* ! THREAD_PROC_H */
+
diff --git a/include/arch/unix/dso.h b/include/arch/unix/dso.h
deleted file mode 100644
index 67bf85104d2..00000000000
--- a/include/arch/unix/dso.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef DSO_H
-#define DSO_H
-
-#include "apr_private.h"
-#include "apr_general.h"
-#include "apr_pools.h"
-#include "apr_dso.h"
-
-#ifdef HAVE_DLFCN_H
-#include <dlfcn.h>
-#endif
-
-#ifdef HAVE_DL_H
-#include <dl.h>
-#endif
-
-#ifndef RTLD_NOW
-#define RTLD_NOW 1
-#endif
-
-#ifndef RTLD_GLOBAL
-#define RTLD_GLOBAL 0
-#endif
-
-#if (defined(__FreeBSD__) ||\
-     defined(__OpenBSD__) ||\
-     defined(__NetBSD__)     ) && !defined(__ELF__)
-#define DLSYM_NEEDS_UNDERSCORE
-#endif
-
-struct ap_dso_handle_t {
-    ap_pool_t  *cont;
-    void          *handle;
-};
-
-#endif
diff --git a/include/arch/unix/fileio.h b/include/arch/unix/fileio.h
deleted file mode 100644
index 1ef43ba0922..00000000000
--- a/include/arch/unix/fileio.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef FILE_IO_H
-#define FILE_IO_H
-
-#include "apr_private.h"
-#include "apr_general.h"
-#include "apr_file_io.h"
-#include "apr_errno.h"
-#include "apr_lib.h"
-
-/* System headers the file I/O library needs */
-#if HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#if HAVE_STRING_H
-#include <string.h>
-#endif
-#if HAVE_DIRENT_H
-#include <dirent.h>
-#endif
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_STDIO_H
-#include <stdio.h>
-#endif
-#if HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#if HAVE_SYS_UIO_H
-#include <sys/uio.h>
-#endif
-#if HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#ifdef BEOS
-#include <kernel/OS.h>
-#endif
-/* End System headers */
-
-#define APR_FILE_BUFSIZE 4096
-
-struct ap_file_t {
-    ap_pool_t *cntxt;
-    int filedes;
-    char * fname;
-    int oflags;
-    int eof_hit;
-    int pipe;
-    ap_interval_time_t timeout;
-    int buffered;
-    int ungetchar;    /* Last char provided by an unget op. (-1 = no char)*/
-
-    /* Stuff for buffered mode */
-    char *buffer;
-    int bufpos;               /* Read/Write position in buffer */
-    unsigned long dataRead;   /* amount of valid data read into buffer */
-    int direction;            /* buffer being used for 0 = read, 1 = write */
-    unsigned long filePtr;    /* position in file of handle */
-#if APR_HAS_THREADS
-    struct ap_lock_t *thlock;
-#endif
-};
-
-struct ap_dir_t {
-    ap_pool_t *cntxt;
-    char *dirname;
-    DIR *dirstruct;
-    struct dirent *entry;
-};
-
-ap_status_t ap_unix_file_cleanup(void *);
-mode_t ap_unix_get_fileperms(ap_fileperms_t);
-
-#endif  /* ! FILE_IO_H */
-
diff --git a/include/arch/unix/locks.h b/include/arch/unix/locks.h
deleted file mode 100644
index f6d37100d5e..00000000000
--- a/include/arch/unix/locks.h
+++ /dev/null
@@ -1,157 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef LOCKS_H
-#define LOCKS_H
-
-#include "apr_private.h"
-#include "apr_general.h"
-#include "apr_lib.h"
-#include "apr_lock.h"
-
-/* System headers required by Locks library */
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_STRING_H
-#include <string.h>
-#endif
-#if HAVE_USLOCKS_H
-#include <uslocks.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#if HAVE_SYS_IPC_H
-#include <sys/ipc.h>
-#endif
-#if HAVE_SYS_SEM_H
-#include <sys/sem.h>
-#endif
-#if HAVE_SYS_FILE_H
-#include <sys/file.h>
-#endif
-#if HAVE_STDIO_H
-#include <stdio.h>
-#endif
-#if HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#if HAVE_SYS_MMAN_H
-#include <sys/mman.h>
-#endif
-
-#if APR_HAS_THREADS
-#if HAVE_PTHREAD_H
-#include <pthread.h>
-#endif
-#endif
-/* End System Headers */
-
-#if !APR_HAVE_UNION_SEMUN && APR_USE_SYSVSEM_SERIALIZE
-/* it makes no sense, but this isn't defined on solaris */
-union semun {
-    long val;
-    struct semid_ds *buf;
-    ushort *array;
-};
-#endif
-
-struct ap_lock_t {
-    ap_pool_t *cntxt;
-    ap_locktype_e type;
-    ap_lockscope_e scope;
-    int curr_locked;
-    char *fname;
-#if USE_SYSVSEM_SERIALIZE
-    int interproc;
-#elif USE_FCNTL_SERIALIZE
-    int interproc;
-#elif USE_PROC_PTHREAD_SERIALIZE
-    pthread_mutex_t *interproc;
-#elif USE_FLOCK_SERIALIZE
-    int interproc;
-#else
-    /* No Interprocess serialization.  Too bad. */
-#endif 
-#if APR_HAS_THREADS
-    /* APR doesn't have threads, no sense in having an thread lock mechanism.
-     */
-#if USE_PTHREAD_SERIALIZE
-    pthread_mutex_t *intraproc;
-#endif
-#endif
-    /* At some point, we should do a scope for both inter and intra process
-     *  locking here.  Something like pthread_mutex with PTHREAD_PROCESS_SHARED
-     */    
-};
-
-#if APR_HAS_THREADS
-ap_status_t ap_unix_create_intra_lock(struct ap_lock_t *new);
-ap_status_t ap_unix_lock_intra(struct ap_lock_t *lock);
-ap_status_t ap_unix_unlock_intra(struct ap_lock_t *lock);
-ap_status_t ap_unix_destroy_intra_lock(struct ap_lock_t *lock);
-#endif
-
-void ap_unix_setup_lock(void);
-ap_status_t ap_unix_create_inter_lock(struct ap_lock_t *new);
-ap_status_t ap_unix_lock_inter(struct ap_lock_t *lock);
-ap_status_t ap_unix_unlock_inter(struct ap_lock_t *lock);
-ap_status_t ap_unix_destroy_inter_lock(struct ap_lock_t *lock);
-
-ap_status_t ap_unix_child_init_lock(struct ap_lock_t **lock, ap_pool_t *cont, 
-                            const char *fname);
-
-#endif  /* LOCKS_H */
-
diff --git a/include/arch/unix/misc.h b/include/arch/unix/misc.h
deleted file mode 100644
index bb754bbf62e..00000000000
--- a/include/arch/unix/misc.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef MISC_H
-#define MISC_H
-
-#include "apr.h"
-#include "apr_private.h"
-#include "apr_general.h"
-#include "apr_pools.h"
-#include "apr_getopt.h"
-#include "apr_thread_proc.h"
-#include "apr_errno.h"
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STDIO_H
-#include <stdio.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_SIGNAL_H
-#include <signal.h>
-#endif
-#ifdef HAVE_PTHREAD_H
-#include <pthread.h>
-#endif
- 
-typedef struct datastruct {
-    void *data;
-    char *key;
-    struct datastruct *next;
-    struct datastruct *prev;
-} datastruct;
-
-struct ap_other_child_rec_t {
-    struct ap_other_child_rec_t *next;
-    int pid;
-    void (*maintenance) (int, void *, int);
-    void *data;
-    int write_fd;
-};
-
-
-#endif  /* ! MISC_H */
-
diff --git a/include/arch/unix/mmap.c b/include/arch/unix/mmap.c
deleted file mode 100644
index 5e5b571f7d1..00000000000
--- a/include/arch/unix/mmap.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifdef BEOS
-#include "../beos/mmap_h.h"
-#else
-#include "mmap_h.h"
-#endif
-
-#include "apr_portable.h"
-
-#if HAVE_MMAP
-
-static ap_status_t mmap_cleanup(void *themmap)
-{
-    ap_mmap_t *mm = themmap;
-    int rv;
-    rv = munmap(mm->mm, mm->size);
-
-    if (rv == 0) {
-        mm->mm = (caddr_t)-1;
-        return APR_SUCCESS;
-    }
-    else
-        return errno;
-}
-
-ap_status_t ap_mmap_create(ap_mmap_t **new, ap_file_t *file, ap_off_t offset, 
-       ap_size_t size, ap_pool_t *cont)
-{
-    caddr_t mm;
-   
-    if (file == NULL || file->filedes == -1)
-        return APR_EBADF;
-
-    (*new) = (ap_mmap_t *)ap_palloc(cont, sizeof(ap_mmap_t));
-    
-    ap_seek(file, APR_SET, &offset);
-    mm = mmap(NULL, size, PROT_READ, MAP_SHARED, file->filedes ,0);
-
-    if (mm == (caddr_t)-1) {
-        /* we failed to get an mmap'd file... */
-        return APR_ENOMEM;
-    }
-    (*new)->mm = mm;
-    (*new)->size = size;
-    (*new)->cntxt = cont;
-
-    /* register the cleanup... */
-    ap_register_cleanup((*new)->cntxt, (void*)(*new), mmap_cleanup,
-             ap_null_cleanup);
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_mmap_delete(ap_mmap_t *mmap)
-{
-    ap_status_t rv;
-
-    if (mmap->mm == (caddr_t) -1)
-        return APR_ENOENT;
-      
-    if ((rv = mmap_cleanup(mmap)) == APR_SUCCESS) {
-        ap_kill_cleanup(mmap->cntxt, mmap, mmap_cleanup);
-        return APR_SUCCESS;
-    }
-    return rv;
-}
-
-#endif
diff --git a/include/arch/unix/networkio.h b/include/arch/unix/networkio.h
deleted file mode 100644
index 9880b04318d..00000000000
--- a/include/arch/unix/networkio.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef NETWORK_IO_H
-#define NETWORK_IO_H
-
-#include "apr_private.h"
-#include "apr_network_io.h"
-#include "apr_errno.h"
-#include "apr_general.h"
-#include "apr_lib.h"
-
-/* System headers the network I/O library needs */
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#if HAVE_SYS_UIO_H
-#include <sys/uio.h>
-#endif
-#if HAVE_POLL_H
-#include <poll.h>
-#endif
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#if HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_STRING_H
-#include <string.h>
-#endif
-#if HAVE_NETINET_TCP_H
-#include <netinet/tcp.h>
-#endif
-#if HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-#if HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-#if HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#if HAVE_NETDB_H
-#include <netdb.h>
-#endif
-#if HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#if HAVE_SYS_SENDFILE_H
-#include <sys/sendfile.h>
-#endif
-/* End System Headers */
-
-struct ap_socket_t {
-    ap_pool_t *cntxt;
-    int socketdes;
-    struct sockaddr_in *local_addr;
-    struct sockaddr_in *remote_addr;
-    socklen_t addr_len;
-    ap_interval_time_t timeout; 
-#ifndef HAVE_POLL
-    int connected;
-#endif
-};
-
-struct ap_pollfd_t {
-    ap_pool_t *cntxt;
-#ifdef HAVE_POLL
-    struct pollfd *pollset;
-    int num;
-    int curpos;
-#else
-    fd_set *read;
-    fd_set *write;
-    fd_set *except;
-    int highsock;
-#endif
-    ap_int16_t *events;
-    ap_int16_t *revents;
-
-};
-
-#endif  /* ! NETWORK_IO_H */
-
diff --git a/include/arch/unix/threadproc.h b/include/arch/unix/threadproc.h
deleted file mode 100644
index ea4c8289db7..00000000000
--- a/include/arch/unix/threadproc.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "apr_private.h"
-#include "apr_thread_proc.h"
-#include "apr_file_io.h"
-#include "fileio.h"
-
-/* System headers required for thread/process library */
-#if HAVE_PTHREAD_H
-#include <pthread.h>
-#endif
-#if HAVE_SIGNAL_H
-#include <signal.h>
-#endif
-#if HAVE_STRING_H
-#include <string.h>
-#endif
-#if HAVE_SYS_WAIT_H
-#include <sys/wait.h>
-#endif
-#if HAVE_STRING_H
-#include <string.h>
-#endif
-/* End System Headers */
-
-
-#ifndef THREAD_PROC_H
-#define THREAD_PROC_H
-
-#define SHELL_PATH "/bin/sh"
-
-#if APR_HAS_THREADS
-struct ap_thread_t {
-    ap_pool_t *cntxt;
-    pthread_t *td;
-};
-
-struct ap_threadattr_t {
-    ap_pool_t *cntxt;
-    pthread_attr_t *attr;
-};
-
-struct ap_threadkey_t {
-    ap_pool_t *cntxt;
-    pthread_key_t key;
-};
-#endif
-
-struct ap_procattr_t {
-    ap_pool_t *cntxt;
-    ap_file_t *parent_in;
-    ap_file_t *child_in;
-    ap_file_t *parent_out;
-    ap_file_t *child_out;
-    ap_file_t *parent_err;
-    ap_file_t *child_err;
-    char *currdir;
-    ap_int32_t cmdtype;
-    ap_int32_t detached;
-};
-
-struct ap_proc_t {
-    ap_pool_t *cntxt;
-    pid_t pid;
-    struct ap_procattr_t *attr;
-};
-
-/*This will move to ap_threadproc.h in time, but I need to figure it out
- * on windows first.  :)
- */
-ap_status_t ap_detach(struct ap_proc_t **, ap_pool_t *);
-
-#endif  /* ! THREAD_PROC_H */
-
diff --git a/include/arch/win32/apr_arch_atime.h b/include/arch/win32/apr_arch_atime.h
new file mode 100644
index 00000000000..35f2041a971
--- /dev/null
+++ b/include/arch/win32/apr_arch_atime.h
@@ -0,0 +1,63 @@
+/* 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 ATIME_H
+#define ATIME_H
+
+#include "apr_private.h"
+#include "apr_time.h"
+#if APR_HAVE_TIME_H
+#include <time.h>
+#endif
+
+struct atime_t {
+    apr_pool_t *cntxt;
+    apr_time_t currtime;
+    SYSTEMTIME *explodedtime;
+};
+
+
+/* Number of micro-seconds between the beginning of the Windows epoch
+ * (Jan. 1, 1601) and the Unix epoch (Jan. 1, 1970) 
+ */
+#define APR_DELTA_EPOCH_IN_USEC   APR_TIME_C(11644473600000000);
+
+
+static APR_INLINE void FileTimeToAprTime(apr_time_t *result, FILETIME *input)
+{
+    /* Convert FILETIME one 64 bit number so we can work with it. */
+    *result = input->dwHighDateTime;
+    *result = (*result) << 32;
+    *result |= input->dwLowDateTime;
+    *result /= 10;    /* Convert from 100 nano-sec periods to micro-seconds. */
+    *result -= APR_DELTA_EPOCH_IN_USEC;  /* Convert from Windows epoch to Unix epoch */
+    return;
+}
+
+
+static APR_INLINE void AprTimeToFileTime(LPFILETIME pft, apr_time_t t)
+{
+    LONGLONG ll;
+    t += APR_DELTA_EPOCH_IN_USEC;
+    ll = t * 10;
+    pft->dwLowDateTime = (DWORD)ll;
+    pft->dwHighDateTime = (DWORD) (ll >> 32);
+    return;
+}
+
+
+#endif  /* ! ATIME_H */
+
diff --git a/include/arch/win32/apr_arch_dso.h b/include/arch/win32/apr_arch_dso.h
new file mode 100644
index 00000000000..e2e4e40f2ea
--- /dev/null
+++ b/include/arch/win32/apr_arch_dso.h
@@ -0,0 +1,36 @@
+/* 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 DSO_H
+#define DSO_H
+
+#include "apr_private.h"
+#include "apr_general.h"
+#include "apr_pools.h"
+#include "apr_dso.h"
+#include "apr.h"
+
+#if APR_HAS_DSO
+
+struct apr_dso_handle_t {
+    apr_pool_t  *cont;
+    void          *handle;
+    apr_status_t   load_error;
+};
+
+#endif
+
+#endif
diff --git a/include/arch/win32/apr_arch_file_io.h b/include/arch/win32/apr_arch_file_io.h
new file mode 100644
index 00000000000..7c5996cab3b
--- /dev/null
+++ b/include/arch/win32/apr_arch_file_io.h
@@ -0,0 +1,263 @@
+/* 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 FILE_IO_H
+#define FILE_IO_H
+
+#include "apr.h"
+#include "apr_private.h"
+#include "apr_pools.h"
+#include "apr_general.h"
+#include "apr_tables.h"
+#include "apr_thread_mutex.h"
+#include "apr_file_io.h"
+#include "apr_file_info.h"
+#include "apr_errno.h"
+#include "apr_arch_misc.h"
+#include "apr_poll.h"
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if APR_HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+#if APR_HAVE_DIRENT_H
+#include <dirent.h>
+#endif
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+
+#if APR_HAS_UNICODE_FS
+#include "arch/win32/apr_arch_utf8.h"
+#include <wchar.h>
+
+/* Helper functions for the WinNT ApiW() functions.  APR treats all
+ * resource identifiers (files, etc) by their UTF-8 name, to provide 
+ * access to all named identifiers.  [UTF-8 completely maps Unicode 
+ * into char type strings.]
+ *
+ * The _path flavors below provide us fast mappings of the
+ * Unicode filename //?/D:/path and //?/UNC/mach/share/path mappings,
+ * which allow unlimited (well, 32000 wide character) length names.
+ * These prefixes may appear in Unicode, but must not appear in the
+ * Ascii API calls.  So we tack them on in utf8_to_unicode_path, and
+ * strip them right back off in unicode_to_utf8_path.
+ */
+apr_status_t utf8_to_unicode_path(apr_wchar_t* dststr, apr_size_t dstchars, 
+                                  const char* srcstr);
+apr_status_t unicode_to_utf8_path(char* dststr, apr_size_t dstchars, 
+                                  const apr_wchar_t* srcstr);
+
+#endif /* APR_HAS_UNICODE_FS */
+
+/* Another Helper functions for the WinNT ApiW() functions.  We need to
+ * derive some 'resource' names (max length 255 characters, prefixed with
+ * Global/ or Local/ on WinNT) from something that looks like a filename.
+ * Since 'resource' names never contain slashes, convert these to '_'s
+ * and return the appropriate char* or wchar* for ApiA or ApiW calls.
+ */
+
+void *res_name_from_filename(const char *file, int global, apr_pool_t *pool);
+
+#define APR_FILE_MAX MAX_PATH
+
+#define APR_FILE_DEFAULT_BUFSIZE 4096
+/* For backwards-compat */
+#define APR_FILE_BUFSIZE APR_FILE_DEFAULT_BUFSIZE
+
+/* obscure ommissions from msvc's sys/stat.h */
+#ifdef _MSC_VER
+#define S_IFIFO        _S_IFIFO /* pipe */
+#define S_IFBLK        0060000  /* Block Special */
+#define S_IFLNK        0120000  /* Symbolic Link */
+#define S_IFSOCK       0140000  /* Socket */
+#define S_IFWHT        0160000  /* Whiteout */
+#endif
+
+/* Internal Flags for apr_file_open */
+#define APR_OPENINFO     0x00100000 /* Open without READ or WRITE access */
+#define APR_OPENLINK     0x00200000 /* Open a link itself, if supported */
+#define APR_READCONTROL  0x00400000 /* Read the file's owner/perms */
+#define APR_WRITECONTROL 0x00800000 /* Modify the file's owner/perms */
+/* #define APR_INHERIT   0x01000000 -- Defined in apr_arch_inherit.h! */
+#define APR_STDIN_FLAG   0x02000000 /* Obtained via apr_file_open_stdin() */
+#define APR_STDOUT_FLAG  0x04000000 /* Obtained via apr_file_open_stdout() */
+#define APR_STDERR_FLAG  0x06000000 /* Obtained via apr_file_open_stderr() */
+#define APR_STD_FLAGS    (APR_STDIN_FLAG | APR_STDOUT_FLAG | APR_STDERR_FLAG)
+#define APR_WRITEATTRS   0x08000000 /* Modify the file's attributes */
+
+/* Entries missing from the MSVC 5.0 Win32 SDK:
+ */
+#ifndef FILE_ATTRIBUTE_DEVICE
+#define FILE_ATTRIBUTE_DEVICE        0x00000040
+#endif
+#ifndef FILE_ATTRIBUTE_REPARSE_POINT
+#define FILE_ATTRIBUTE_REPARSE_POINT 0x00000400
+#endif
+#ifndef FILE_FLAG_OPEN_NO_RECALL
+#define FILE_FLAG_OPEN_NO_RECALL     0x00100000
+#endif
+#ifndef FILE_FLAG_OPEN_REPARSE_POINT
+#define FILE_FLAG_OPEN_REPARSE_POINT 0x00200000
+#endif
+#ifndef TRUSTEE_IS_WELL_KNOWN_GROUP
+#define TRUSTEE_IS_WELL_KNOWN_GROUP  5
+#endif
+
+/* Information bits available from the WIN32 FindFirstFile function */
+#define APR_FINFO_WIN32_DIR (APR_FINFO_NAME  | APR_FINFO_TYPE \
+                           | APR_FINFO_CTIME | APR_FINFO_ATIME \
+                           | APR_FINFO_MTIME | APR_FINFO_SIZE)
+
+/* Sneak the Readonly bit through finfo->protection for internal use _only_ */
+#define APR_FREADONLY 0x10000000 
+
+/* Private function for apr_stat/lstat/getfileinfo/dir_read */
+int fillin_fileinfo(apr_finfo_t *finfo, WIN32_FILE_ATTRIBUTE_DATA *wininfo, 
+                    int byhandle, apr_int32_t wanted);
+
+/* Private function that extends apr_stat/lstat/getfileinfo/dir_read */
+apr_status_t more_finfo(apr_finfo_t *finfo, const void *ufile, 
+                        apr_int32_t wanted, int whatfile);
+
+/* whatfile types for the ufile arg */
+#define MORE_OF_HANDLE 0
+#define MORE_OF_FSPEC  1
+#define MORE_OF_WFSPEC 2
+
+/* quick run-down of fields in windows' apr_file_t structure that may have 
+ * obvious uses.
+ * fname --  the filename as passed to the open call.
+ * dwFileAttricutes -- Attributes used to open the file.
+ * append -- Windows doesn't support the append concept when opening files.
+ *           APR needs to keep track of this, and always make sure we append
+ *           correctly when writing to a file with this flag set TRUE.
+ */
+
+/* for apr_poll.c */
+#define filedes filehand
+
+struct apr_file_t {
+    apr_pool_t *pool;
+    HANDLE filehand;
+    BOOLEAN pipe;              /* Is this a pipe of a file? */
+    OVERLAPPED *pOverlapped;
+    apr_interval_time_t timeout;
+    apr_int32_t flags;
+
+    /* File specific info */
+    apr_finfo_t *finfo;
+    char *fname;
+    DWORD dwFileAttributes;
+    int eof_hit;
+    BOOLEAN buffered;          /* Use buffered I/O? */
+    int ungetchar;             /* Last char provided by an unget op. (-1 = no char) */
+    int append; 
+
+    /* Stuff for buffered mode */
+    char *buffer;
+    apr_size_t bufpos;         /* Read/Write position in buffer             */
+    apr_size_t bufsize;        /* The size of the buffer                    */
+    apr_size_t dataRead;       /* amount of valid data read into buffer     */
+    int direction;             /* buffer being used for 0 = read, 1 = write */
+    apr_off_t filePtr;         /* position in file of handle                */
+    apr_thread_mutex_t *mutex; /* mutex semaphore, must be owned to access
+                                  the above fields                          */
+
+#if APR_FILES_AS_SOCKETS
+    /* if there is a timeout set, then this pollset is used */
+    apr_pollset_t *pollset;
+#endif
+    /* Pipe specific info */    
+};
+
+struct apr_dir_t {
+    apr_pool_t *pool;
+    HANDLE dirhand;
+    apr_size_t rootlen;
+    char *dirname;
+    char *name;
+    union {
+#if APR_HAS_UNICODE_FS
+        struct {
+            WIN32_FIND_DATAW *entry;
+        } w;
+#endif
+#if APR_HAS_ANSI_FS
+        struct {
+            WIN32_FIND_DATAA *entry;
+        } n;
+#endif        
+    };
+    int bof;
+};
+
+/* There are many goofy characters the filesystem can't accept
+ * or can confound the cmd.exe shell.  Here's the list
+ * [declared in filesys.c]
+ */
+extern const char apr_c_is_fnchar[256];
+
+#define IS_FNCHAR(c) (apr_c_is_fnchar[(unsigned char)(c)] & 1)
+#define IS_SHCHAR(c) ((apr_c_is_fnchar[(unsigned char)(c)] & 2) == 2)
+
+
+/* If the user passes APR_FILEPATH_TRUENAME to either
+ * apr_filepath_root or apr_filepath_merge, this fn determines
+ * that the root really exists.  It's expensive, wouldn't want
+ * to do this too frequenly.
+ */
+apr_status_t filepath_root_test(char *path, apr_pool_t *p);
+
+
+/* The apr_filepath_merge wants to canonicalize the cwd to the 
+ * addpath if the user passes NULL as the old root path (this
+ * isn't true of an empty string "", which won't be concatenated.
+ *
+ * But we need to figure out what the cwd of a given volume is,
+ * when the user passes D:foo.  This fn will determine D:'s cwd.
+ *
+ * If flags includes the bit APR_FILEPATH_NATIVE, the path returned
+ * is in the os-native format.
+ */
+apr_status_t filepath_drive_get(char **rootpath, char drive, 
+                                apr_int32_t flags, apr_pool_t *p);
+
+
+/* If the user passes d: vs. D: (or //mach/share vs. //MACH/SHARE),
+ * we need to fold the case to canonical form.  This function is
+ * supposed to do so.
+ */
+apr_status_t filepath_root_case(char **rootpath, char *root, apr_pool_t *p);
+
+
+apr_status_t file_cleanup(void *);
+
+apr_status_t file_socket_pipe_create(apr_file_t **in,
+                                     apr_file_t **out,
+                                     apr_pool_t *p);
+
+apr_status_t file_socket_pipe_close(apr_file_t *file);
+
+#endif  /* ! FILE_IO_H */
diff --git a/include/arch/win32/apr_arch_inherit.h b/include/arch/win32/apr_arch_inherit.h
new file mode 100644
index 00000000000..8969af664d8
--- /dev/null
+++ b/include/arch/win32/apr_arch_inherit.h
@@ -0,0 +1,123 @@
+/* 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 INHERIT_H
+#define INHERIT_H
+
+#include "apr_inherit.h"
+
+#define APR_INHERIT (1 << 24)    /* Must not conflict with other bits */
+
+#if APR_HAS_UNICODE_FS && APR_HAS_ANSI_FS
+/* !defined(_WIN32_WCE) is implicit here */
+
+#define APR_IMPLEMENT_INHERIT_SET(name, flag, pool, cleanup)        \
+APR_DECLARE(apr_status_t) apr_##name##_inherit_set(apr_##name##_t *the##name) \
+{                                                                   \
+    IF_WIN_OS_IS_UNICODE                                            \
+    {                                                               \
+/*     if (!SetHandleInformation(the##name->filehand,              \
+ *                                HANDLE_FLAG_INHERIT,              \
+ *                                HANDLE_FLAG_INHERIT))             \
+ *          return apr_get_os_error();                              \
+ */  }                                                               \
+    ELSE_WIN_OS_IS_ANSI                                             \
+    {                                                               \
+        HANDLE temp, hproc = GetCurrentProcess();                   \
+        if (!DuplicateHandle(hproc, the##name->filehand,            \
+                             hproc, &temp, 0, TRUE,                 \
+                             DUPLICATE_SAME_ACCESS))                \
+            return apr_get_os_error();                              \
+        CloseHandle(the##name->filehand);                           \
+        the##name->filehand = temp;                                 \
+    }                                                               \
+    return APR_SUCCESS;                                             \
+}
+
+#define APR_IMPLEMENT_INHERIT_UNSET(name, flag, pool, cleanup)      \
+APR_DECLARE(apr_status_t) apr_##name##_inherit_unset(apr_##name##_t *the##name)\
+{                                                                   \
+    IF_WIN_OS_IS_UNICODE                                            \
+    {                                                               \
+/*      if (!SetHandleInformation(the##name->filehand,              \
+ *                                HANDLE_FLAG_INHERIT, 0))          \
+ *          return apr_get_os_error();                              \
+ */ }                                                               \
+    ELSE_WIN_OS_IS_ANSI                                             \
+    {                                                               \
+        HANDLE temp, hproc = GetCurrentProcess();                   \
+        if (!DuplicateHandle(hproc, the##name->filehand,            \
+                             hproc, &temp, 0, FALSE,                \
+                             DUPLICATE_SAME_ACCESS))                \
+            return apr_get_os_error();                              \
+        CloseHandle(the##name->filehand);                           \
+        the##name->filehand = temp;                                 \
+    }                                                               \
+    return APR_SUCCESS;                                             \
+}
+
+#elif APR_HAS_ANSI_FS || defined(_WIN32_WCE)
+
+#define APR_IMPLEMENT_INHERIT_SET(name, flag, pool, cleanup)        \
+APR_DECLARE(apr_status_t) apr_##name##_inherit_set(apr_##name##_t *the##name) \
+{                                                                   \
+    HANDLE temp, hproc = GetCurrentProcess();                       \
+    if (!DuplicateHandle(hproc, the##name->filehand,                \
+                         hproc, &temp, 0, TRUE,                     \
+                         DUPLICATE_SAME_ACCESS))                    \
+        return apr_get_os_error();                                  \
+    CloseHandle(the##name->filehand);                               \
+    the##name->filehand = temp;                                     \
+    return APR_SUCCESS;                                             \
+}
+
+#define APR_IMPLEMENT_INHERIT_UNSET(name, flag, pool, cleanup)      \
+APR_DECLARE(apr_status_t) apr_##name##_inherit_unset(apr_##name##_t *the##name)\
+{                                                                   \
+    HANDLE temp, hproc = GetCurrentProcess();                       \
+    if (!DuplicateHandle(hproc, the##name->filehand,                \
+                         hproc, &temp, 0, FALSE,                    \
+                         DUPLICATE_SAME_ACCESS))                    \
+        return apr_get_os_error();                                  \
+    CloseHandle(the##name->filehand);                               \
+    the##name->filehand = temp;                                     \
+    return APR_SUCCESS;                                             \
+}
+
+#else /* APR_HAS_UNICODE_FS && !APR_HAS_ANSI_FS && !defined(_WIN32_WCE) */
+
+#define APR_IMPLEMENT_INHERIT_SET(name, flag, pool, cleanup)        \
+APR_DECLARE(apr_status_t) apr_##name##_inherit_set(apr_##name##_t *the##name) \
+{                                                                   \
+/*  if (!SetHandleInformation(the##name->filehand,                  \
+ *                            HANDLE_FLAG_INHERIT,                  \
+ *                            HANDLE_FLAG_INHERIT))                 \
+ *      return apr_get_os_error();                                  \
+ */ return APR_SUCCESS;                                             \
+}
+
+#define APR_IMPLEMENT_INHERIT_UNSET(name, flag, pool, cleanup)      \
+APR_DECLARE(apr_status_t) apr_##name##_inherit_unset(apr_##name##_t *the##name)\
+{                                                                   \
+/*  if (!SetHandleInformation(the##name->filehand,                  \
+ *                            HANDLE_FLAG_INHERIT, 0))              \
+ *      return apr_get_os_error();                                  \
+ */ return APR_SUCCESS;                                             \
+}
+
+#endif /* defined(APR_HAS_UNICODE_FS) */
+
+#endif	/* ! INHERIT_H */
diff --git a/include/arch/win32/apr_arch_misc.h b/include/arch/win32/apr_arch_misc.h
new file mode 100644
index 00000000000..2ee562ec375
--- /dev/null
+++ b/include/arch/win32/apr_arch_misc.h
@@ -0,0 +1,386 @@
+/* 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 MISC_H
+#define MISC_H
+
+#include "apr.h"
+#include "apr_portable.h"
+#include "apr_private.h"
+#include "apr_general.h"
+#include "apr_pools.h"
+#include "apr_getopt.h"
+#include "apr_thread_proc.h"
+#include "apr_file_io.h"
+#include "apr_errno.h"
+#include "apr_getopt.h"
+
+#if APR_HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#if APR_HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+#if APR_HAVE_PTHREAD_H
+#include <pthread.h>
+#endif
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if APR_HAVE_STRING_H
+#include <string.h>
+#endif
+#ifndef _WIN32_WCE
+#include <tlhelp32.h>
+#endif
+
+struct apr_other_child_rec_t {
+    apr_pool_t *p;
+    struct apr_other_child_rec_t *next;
+    apr_proc_t *proc;
+    void (*maintenance) (int, void *, int);
+    void *data;
+};
+
+#define WSAHighByte 2
+#define WSALowByte 0
+
+/* start.c and apr_app.c helpers and communication within misc.c
+ *
+ * They are not for public consumption, although apr_app_init_complete
+ * must be an exported symbol to avoid reinitialization.
+ */
+extern int APR_DECLARE_DATA apr_app_init_complete;
+
+int apr_wastrtoastr(char const * const * *retarr, 
+                    wchar_t const * const *arr, int args);
+
+/* Platform specific designation of run time os version.
+ * Gaps allow for specific service pack levels that
+ * export new kernel or winsock functions or behavior.
+ */
+typedef enum {
+        APR_WIN_UNK =       0,
+        APR_WIN_UNSUP =     1,
+        APR_WIN_95 =       10,
+        APR_WIN_95_B =     11,
+        APR_WIN_95_OSR2 =  12,
+        APR_WIN_98 =       14,
+        APR_WIN_98_SE =    16,
+        APR_WIN_ME =       18,
+
+	APR_WIN_UNICODE =  20, /* Prior versions support only narrow chars */
+
+        APR_WIN_CE_3 =     23, /* CE is an odd beast, not supporting */
+                               /* some pre-NT features, such as the    */
+        APR_WIN_NT =       30, /* narrow charset APIs (fooA fns), while  */
+        APR_WIN_NT_3_5 =   35, /* not supporting some NT-family features.  */
+        APR_WIN_NT_3_51 =  36,
+
+        APR_WIN_NT_4 =     40,
+        APR_WIN_NT_4_SP2 = 42,
+        APR_WIN_NT_4_SP3 = 43,
+        APR_WIN_NT_4_SP4 = 44,
+        APR_WIN_NT_4_SP5 = 45,
+        APR_WIN_NT_4_SP6 = 46,
+
+        APR_WIN_2000 =     50,
+        APR_WIN_2000_SP1 = 51,
+        APR_WIN_2000_SP2 = 52,
+        APR_WIN_XP =       60,
+        APR_WIN_XP_SP1 =   61,
+        APR_WIN_XP_SP2 =   62,
+        APR_WIN_2003 =     70,
+        APR_WIN_VISTA =    80,
+        APR_WIN_7  =       90,
+        APR_WIN_8  =       100
+} apr_oslevel_e;
+
+extern APR_DECLARE_DATA apr_oslevel_e apr_os_level;
+
+apr_status_t apr_get_oslevel(apr_oslevel_e *);
+
+/* The APR_HAS_ANSI_FS symbol is PRIVATE, and internal to APR.
+ * APR only supports char data for filenames.  Like most applications,
+ * characters >127 are essentially undefined.  APR_HAS_UNICODE_FS lets
+ * the application know that utf-8 is the encoding method of APR, and
+ * only incidently hints that we have Wide OS calls.
+ *
+ * APR_HAS_ANSI_FS is simply an OS flag to tell us all calls must be
+ * the unicode eqivilant.
+ */
+
+#define APR_HAS_ANSI_FS           0
+
+/* IF_WIN_OS_IS_UNICODE / ELSE_WIN_OS_IS_ANSI help us keep the code trivial
+ * where have runtime tests for unicode-ness, that aren't needed in any
+ * build which supports only WINNT or WCE.
+ */
+#if APR_HAS_ANSI_FS && APR_HAS_UNICODE_FS
+#define IF_WIN_OS_IS_UNICODE if (apr_os_level >= APR_WIN_UNICODE)
+#define ELSE_WIN_OS_IS_ANSI else
+#else /* APR_HAS_UNICODE_FS */
+#define IF_WIN_OS_IS_UNICODE
+#define ELSE_WIN_OS_IS_ANSI
+#endif /* APR_HAS_ANSI_FS && APR_HAS_UNICODE_FS */
+
+#if defined(_MSC_VER) && !defined(_WIN32_WCE)
+#include "crtdbg.h"
+
+static APR_INLINE void* apr_malloc_dbg(size_t size, const char* filename,
+                                       int linenumber)
+{
+    return _malloc_dbg(size, _CRT_BLOCK, filename, linenumber);
+}
+
+static APR_INLINE void* apr_realloc_dbg(void* userData, size_t newSize,
+                                        const char* filename, int linenumber)
+{
+    return _realloc_dbg(userData, newSize, _CRT_BLOCK, filename, linenumber);
+}
+
+#else
+
+static APR_INLINE void* apr_malloc_dbg(size_t size, const char* filename,
+                                       int linenumber)
+{
+    return malloc(size);
+}
+
+static APR_INLINE void* apr_realloc_dbg(void* userData, size_t newSize,
+                                        const char* filename, int linenumber)
+{
+    return realloc(userData, newSize);
+}
+
+#endif  /* ! _MSC_VER */
+
+typedef enum {
+    DLL_WINBASEAPI = 0,    /* kernel32 From WinBase.h       */
+    DLL_WINADVAPI = 1,     /* advapi32 From WinBase.h       */
+    DLL_WINSOCKAPI = 2,    /* mswsock  From WinSock.h       */
+    DLL_WINSOCK2API = 3,   /* ws2_32   From WinSock2.h      */
+    DLL_SHSTDAPI = 4,      /* shell32  From ShellAPI.h      */
+    DLL_NTDLL = 5,         /* shell32  From our real kernel */
+    DLL_defined = 6        /* must define as last idx_ + 1  */
+} apr_dlltoken_e;
+
+FARPROC apr_load_dll_func(apr_dlltoken_e fnLib, char *fnName, int ordinal);
+
+/* The apr_load_dll_func call WILL return 0 set error to
+ * ERROR_INVALID_FUNCTION if the function cannot be loaded
+ */
+#define APR_DECLARE_LATE_DLL_FUNC(lib, rettype, calltype, fn, ord, args, names) \
+    typedef rettype (calltype *apr_winapi_fpt_##fn) args; \
+    static apr_winapi_fpt_##fn apr_winapi_pfn_##fn = NULL; \
+    static int apr_winapi_chk_##fn = 0; \
+    static APR_INLINE int apr_winapi_ld_##fn(void) \
+    {   if (apr_winapi_pfn_##fn) return 1; \
+        if (apr_winapi_chk_##fn ++) return 0; \
+        if (!apr_winapi_pfn_##fn) \
+            apr_winapi_pfn_##fn = (apr_winapi_fpt_##fn) \
+                                      apr_load_dll_func(lib, #fn, ord); \
+        if (apr_winapi_pfn_##fn) return 1; else return 0; }; \
+    static APR_INLINE rettype apr_winapi_##fn args \
+    {   if (apr_winapi_ld_##fn()) \
+            return (*(apr_winapi_pfn_##fn)) names; \
+        else { SetLastError(ERROR_INVALID_FUNCTION); return 0;} }; \
+
+#define APR_HAVE_LATE_DLL_FUNC(fn) apr_winapi_ld_##fn()
+
+/* Provide late bound declarations of every API function missing from
+ * one or more supported releases of the Win32 API
+ *
+ * lib is the enumerated token from apr_dlltoken_e, and must correspond
+ * to the string table entry in start.c used by the apr_load_dll_func().
+ * Token names (attempt to) follow Windows.h declarations prefixed by DLL_
+ * in order to facilitate comparison.  Use the exact declaration syntax
+ * and names from Windows.h to prevent ambigutity and bugs.
+ *
+ * rettype and calltype follow the original declaration in Windows.h
+ * fn is the true function name - beware Ansi/Unicode #defined macros
+ * ord is the ordinal within the library, use 0 if it varies between versions
+ * args is the parameter list following the original declaration, in parens
+ * names is the parameter list sans data types, enclosed in parens
+ *
+ * #undef/re#define the Ansi/Unicode generic name to abate confusion
+ * In the case of non-text functions, simply #define the original name
+ */
+
+#if !defined(_WIN32_WCE)
+/* This group is NOT available to all versions of WinNT,
+ * these we must always look up
+ */
+
+#ifdef GetCompressedFileSizeA
+#undef GetCompressedFileSizeA
+#endif
+APR_DECLARE_LATE_DLL_FUNC(DLL_WINBASEAPI, DWORD, WINAPI, GetCompressedFileSizeA, 0, (
+    IN LPCSTR lpFileName,
+    OUT LPDWORD lpFileSizeHigh),
+    (lpFileName, lpFileSizeHigh));
+#define GetCompressedFileSizeA apr_winapi_GetCompressedFileSizeA
+#undef GetCompressedFileSize
+#define GetCompressedFileSize apr_winapi_GetCompressedFileSizeA
+
+#ifdef GetCompressedFileSizeW
+#undef GetCompressedFileSizeW
+#endif
+APR_DECLARE_LATE_DLL_FUNC(DLL_WINBASEAPI, DWORD, WINAPI, GetCompressedFileSizeW, 0, (
+    IN LPCWSTR lpFileName,
+    OUT LPDWORD lpFileSizeHigh),
+    (lpFileName, lpFileSizeHigh));
+#define GetCompressedFileSizeW apr_winapi_GetCompressedFileSizeW
+
+
+APR_DECLARE_LATE_DLL_FUNC(DLL_NTDLL, LONG, WINAPI, NtQueryTimerResolution, 0, (
+    ULONG *pMaxRes,  /* Minimum NS Resolution */
+    ULONG *pMinRes,  /* Maximum NS Resolution */
+    ULONG *pCurRes), /* Current NS Resolution */
+    (pMaxRes, pMinRes, pCurRes));
+#define QueryTimerResolution apr_winapi_NtQueryTimerResolution
+
+APR_DECLARE_LATE_DLL_FUNC(DLL_NTDLL, LONG, WINAPI, NtSetTimerResolution, 0, (
+    ULONG ReqRes,    /* Requested NS Clock Resolution */
+    BOOL  Acquire,   /* Aquire (1) or Release (0) our interest */
+    ULONG *pNewRes), /* The NS Clock Resolution granted */
+    (ReqRes, Acquire, pNewRes));
+#define SetTimerResolution apr_winapi_NtSetTimerResolution
+
+typedef struct PBI {
+    LONG      ExitStatus;
+    PVOID     PebBaseAddress;
+    apr_uintptr_t AffinityMask;
+    LONG      BasePriority;
+    apr_uintptr_t UniqueProcessId;
+    apr_uintptr_t InheritedFromUniqueProcessId;
+} PBI, *PPBI;
+
+APR_DECLARE_LATE_DLL_FUNC(DLL_NTDLL, LONG, WINAPI, NtQueryInformationProcess, 0, (
+    HANDLE hProcess,  /* Obvious */
+    INT   info,       /* Use 0 for PBI documented above */
+    PVOID pPI,        /* The PIB buffer */
+    ULONG LenPI,      /* Use sizeof(PBI) */
+    ULONG *pSizePI),  /* returns pPI buffer used (may pass NULL) */
+    (hProcess, info, pPI, LenPI, pSizePI));
+#define QueryInformationProcess apr_winapi_NtQueryInformationProcess
+
+APR_DECLARE_LATE_DLL_FUNC(DLL_NTDLL, LONG, WINAPI, NtQueryObject, 0, (
+    HANDLE hObject,   /* Obvious */
+    INT   info,       /* Use 0 for PBI documented above */
+    PVOID pOI,        /* The PIB buffer */
+    ULONG LenOI,      /* Use sizeof(PBI) */
+    ULONG *pSizeOI),  /* returns pPI buffer used (may pass NULL) */
+    (hObject, info, pOI, LenOI, pSizeOI));
+#define QueryObject apr_winapi_NtQueryObject
+
+typedef struct IOSB {
+    union {
+    UINT Status;
+    PVOID reserved;
+    };
+    apr_uintptr_t Information; /* Varies by op, consumed buffer size for FSI below */
+} IOSB, *PIOSB;
+
+typedef struct FSI {
+    LONGLONG AllocationSize;
+    LONGLONG EndOfFile;
+    ULONG    NumberOfLinks;
+    BOOL     DeletePending;
+    BOOL     Directory;
+} FSI, *PFSI;
+
+APR_DECLARE_LATE_DLL_FUNC(DLL_NTDLL, LONG, WINAPI, ZwQueryInformationFile, 0, (
+    HANDLE hObject,    /* Obvious */
+    PVOID  pIOSB,      /* Point to the IOSB buffer for detailed return results */
+    PVOID  pFI,        /* The buffer, using FIB above */
+    ULONG  LenFI,      /* Use sizeof(FI) */
+    ULONG  info),      /* Use 5 for FSI documented above*/
+    (hObject, pIOSB, pFI, LenFI, info));
+#define ZwQueryInformationFile apr_winapi_ZwQueryInformationFile
+
+#ifdef CreateToolhelp32Snapshot
+#undef CreateToolhelp32Snapshot
+#endif
+APR_DECLARE_LATE_DLL_FUNC(DLL_WINBASEAPI, HANDLE, WINAPI, CreateToolhelp32Snapshot, 0, (
+    DWORD dwFlags,
+    DWORD th32ProcessID),
+    (dwFlags, th32ProcessID));
+#define CreateToolhelp32Snapshot apr_winapi_CreateToolhelp32Snapshot
+
+#ifdef Process32FirstW
+#undef Process32FirstW
+#endif
+APR_DECLARE_LATE_DLL_FUNC(DLL_WINBASEAPI, BOOL, WINAPI, Process32FirstW, 0, (
+    HANDLE hSnapshot,
+    LPPROCESSENTRY32W lppe),
+    (hSnapshot, lppe));
+#define Process32FirstW apr_winapi_Process32FirstW
+
+#ifdef Process32NextW
+#undef Process32NextW
+#endif
+APR_DECLARE_LATE_DLL_FUNC(DLL_WINBASEAPI, BOOL, WINAPI, Process32NextW, 0, (
+    HANDLE hSnapshot,
+    LPPROCESSENTRY32W lppe),
+    (hSnapshot, lppe));
+#define Process32NextW apr_winapi_Process32NextW
+
+#if !defined(POLLERR)
+/* Event flag definitions for WSAPoll(). */
+#define POLLRDNORM  0x0100
+#define POLLRDBAND  0x0200
+#define POLLIN      (POLLRDNORM | POLLRDBAND)
+#define POLLPRI     0x0400
+
+#define POLLWRNORM  0x0010
+#define POLLOUT     (POLLWRNORM)
+#define POLLWRBAND  0x0020
+
+#define POLLERR     0x0001
+#define POLLHUP     0x0002
+#define POLLNVAL    0x0004
+
+typedef struct pollfd {
+    SOCKET  fd;
+    SHORT   events;
+    SHORT   revents;
+
+} WSAPOLLFD, *PWSAPOLLFD, FAR *LPWSAPOLLFD;
+
+#endif /* !defined(POLLERR) */
+#ifdef WSAPoll
+#undef WSAPoll
+#endif
+APR_DECLARE_LATE_DLL_FUNC(DLL_WINSOCK2API, int, WSAAPI, WSAPoll, 0, (
+    IN OUT LPWSAPOLLFD fdArray,
+    IN ULONG fds,
+    IN INT timeout),
+    (fdArray, fds, timeout));
+#define WSAPoll apr_winapi_WSAPoll
+#define HAVE_POLL   1
+
+#ifdef SetDllDirectoryW
+#undef SetDllDirectoryW
+#endif
+APR_DECLARE_LATE_DLL_FUNC(DLL_WINBASEAPI, BOOL, WINAPI, SetDllDirectoryW, 0, (
+    IN LPCWSTR lpPathName),
+    (lpPathName));
+#define SetDllDirectoryW apr_winapi_SetDllDirectoryW
+
+#endif /* !defined(_WIN32_WCE) */
+
+#endif  /* ! MISC_H */
diff --git a/include/arch/win32/apr_arch_networkio.h b/include/arch/win32/apr_arch_networkio.h
new file mode 100644
index 00000000000..04be55595d1
--- /dev/null
+++ b/include/arch/win32/apr_arch_networkio.h
@@ -0,0 +1,90 @@
+/* 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 NETWORK_IO_H
+#define NETWORK_IO_H
+
+#include "apr_network_io.h"
+#include "apr_general.h"
+#include "apr_poll.h"
+
+typedef struct sock_userdata_t sock_userdata_t;
+struct sock_userdata_t {
+    sock_userdata_t *next;
+    const char *key;
+    void *data;
+};
+
+struct apr_socket_t {
+    apr_pool_t         *pool;
+    SOCKET              socketdes;
+    int                 type; /* SOCK_STREAM, SOCK_DGRAM */
+    int                 protocol;
+    apr_sockaddr_t     *local_addr;
+    apr_sockaddr_t     *remote_addr;
+    int                 timeout_ms; /* MUST MATCH if timeout > 0 */
+    apr_interval_time_t timeout;
+    apr_int32_t         disconnected;
+    int                 local_port_unknown;
+    int                 local_interface_unknown;
+    int                 remote_addr_unknown;
+    apr_int32_t         options;
+    apr_int32_t         inherit;
+#if APR_HAS_SENDFILE
+    /* As of 07.20.04, the overlapped structure is only used by 
+     * apr_socket_sendfile and that's where it will be allocated 
+     * and initialized.
+     */
+    OVERLAPPED         *overlapped;
+#endif
+    sock_userdata_t    *userdata;
+
+    /* if there is a timeout set, then this pollset is used */
+    apr_pollset_t *pollset;
+};
+
+#ifdef _WIN32_WCE
+#ifndef WSABUF
+typedef struct _WSABUF {
+    u_long      len;     /* the length of the buffer */
+    char FAR *  buf;     /* the pointer to the buffer */
+} WSABUF, FAR * LPWSABUF;
+#endif
+#else
+#ifdef _MSC_VER
+#define HAVE_STRUCT_IPMREQ
+#endif
+#endif
+
+apr_status_t status_from_res_error(int);
+
+const char *apr_inet_ntop(int af, const void *src, char *dst, apr_size_t size);
+int apr_inet_pton(int af, const char *src, void *dst);
+void apr_sockaddr_vars_set(apr_sockaddr_t *, int, apr_port_t);
+
+#define apr_is_option_set(skt, option)  \
+    (((skt)->options & (option)) == (option))
+
+#define apr_set_option(skt, option, on) \
+    do {                                 \
+        if (on)                          \
+            (skt)->options |= (option);         \
+        else                             \
+            (skt)->options &= ~(option);        \
+    } while (0)
+
+#endif  /* ! NETWORK_IO_H */
+
diff --git a/include/arch/win32/apr_arch_proc_mutex.h b/include/arch/win32/apr_arch_proc_mutex.h
new file mode 100644
index 00000000000..4e3e3993996
--- /dev/null
+++ b/include/arch/win32/apr_arch_proc_mutex.h
@@ -0,0 +1,29 @@
+/* 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 PROC_MUTEX_H
+#define PROC_MUTEX_H
+
+#include "apr_proc_mutex.h"
+
+struct apr_proc_mutex_t {
+    apr_pool_t *pool;
+    HANDLE handle;
+    const char *fname;
+};
+
+#endif  /* PROC_MUTEX_H */
+
diff --git a/include/arch/win32/apr_arch_thread_cond.h b/include/arch/win32/apr_arch_thread_cond.h
new file mode 100644
index 00000000000..c7f69f80646
--- /dev/null
+++ b/include/arch/win32/apr_arch_thread_cond.h
@@ -0,0 +1,32 @@
+/* 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 THREAD_COND_H
+#define THREAD_COND_H
+
+#include "apr_thread_cond.h"
+
+struct apr_thread_cond_t {
+    apr_pool_t *pool;
+    HANDLE semaphore;
+    CRITICAL_SECTION csection;
+    unsigned long num_waiting;
+    unsigned long num_wake;
+    unsigned long generation;
+};
+
+#endif  /* THREAD_COND_H */
+
diff --git a/include/arch/win32/apr_arch_thread_mutex.h b/include/arch/win32/apr_arch_thread_mutex.h
new file mode 100644
index 00000000000..13d3c1cbd57
--- /dev/null
+++ b/include/arch/win32/apr_arch_thread_mutex.h
@@ -0,0 +1,40 @@
+/* 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 THREAD_MUTEX_H
+#define THREAD_MUTEX_H
+
+#include "apr_pools.h"
+
+typedef enum thread_mutex_type {
+    thread_mutex_critical_section,
+    thread_mutex_unnested_event,
+    thread_mutex_nested_mutex
+} thread_mutex_type;
+
+/* handle applies only to unnested_event on all platforms 
+ * and nested_mutex on Win9x only.  Otherwise critical_section 
+ * is used for NT nexted mutexes providing optimal performance.
+ */
+struct apr_thread_mutex_t {
+    apr_pool_t       *pool;
+    thread_mutex_type type;
+    HANDLE            handle;
+    CRITICAL_SECTION  section;
+};
+
+#endif  /* THREAD_MUTEX_H */
+
diff --git a/include/arch/win32/apr_arch_thread_rwlock.h b/include/arch/win32/apr_arch_thread_rwlock.h
new file mode 100644
index 00000000000..1177e529103
--- /dev/null
+++ b/include/arch/win32/apr_arch_thread_rwlock.h
@@ -0,0 +1,30 @@
+/* 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 THREAD_RWLOCK_H
+#define THREAD_RWLOCK_H
+
+#include "apr_thread_rwlock.h"
+
+struct apr_thread_rwlock_t {
+    apr_pool_t *pool;
+    HANDLE      write_mutex;
+    HANDLE      read_event;
+    LONG        readers;
+};
+
+#endif  /* THREAD_RWLOCK_H */
+
diff --git a/include/arch/win32/apr_arch_threadproc.h b/include/arch/win32/apr_arch_threadproc.h
new file mode 100644
index 00000000000..d3ce9c51860
--- /dev/null
+++ b/include/arch/win32/apr_arch_threadproc.h
@@ -0,0 +1,74 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_private.h"
+#include "apr_thread_proc.h"
+#include "apr_file_io.h"
+
+#ifndef THREAD_PROC_H
+#define THREAD_PROC_H
+
+#define SHELL_PATH "cmd.exe"
+
+struct apr_thread_t {
+    apr_pool_t *pool;
+    HANDLE td;
+    apr_int32_t cancel;
+    apr_int32_t cancel_how;
+    void *data;
+    apr_thread_start_t func;
+    apr_status_t exitval;
+};
+
+struct apr_threadattr_t {
+    apr_pool_t *pool;
+    apr_int32_t detach;
+    apr_size_t stacksize;
+};
+
+struct apr_threadkey_t {
+    apr_pool_t *pool;
+    DWORD key;
+};
+
+struct apr_procattr_t {
+    apr_pool_t *pool;
+    apr_file_t *parent_in;
+    apr_file_t *child_in;
+    apr_file_t *parent_out;
+    apr_file_t *child_out;
+    apr_file_t *parent_err;
+    apr_file_t *child_err;
+    char *currdir;
+    apr_int32_t cmdtype;
+    apr_int32_t detached;
+    apr_child_errfn_t *errfn;
+    apr_int32_t errchk;
+#ifndef _WIN32_WCE
+    HANDLE     user_token;
+    LPSECURITY_ATTRIBUTES   sa;
+    LPVOID                  sd;
+#endif
+};
+
+struct apr_thread_once_t {
+    long value;
+};
+
+extern apr_status_t apr_threadproc_init(apr_pool_t *pool);
+
+#endif  /* ! THREAD_PROC_H */
+
diff --git a/include/arch/win32/apr_arch_utf8.h b/include/arch/win32/apr_arch_utf8.h
new file mode 100644
index 00000000000..84f8bf775ef
--- /dev/null
+++ b/include/arch/win32/apr_arch_utf8.h
@@ -0,0 +1,56 @@
+/* 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 UTF8_H
+#define UTF8_H
+
+#include "apr.h"
+#include "apr_lib.h"
+#include "apr_errno.h"
+
+/* If we ever support anything more exciting than char... this could move.
+ */
+typedef apr_uint16_t apr_wchar_t;
+
+/**
+ * An APR internal function for fast utf-8 octet-encoded Unicode conversion
+ * to the ucs-2 wide Unicode format.  This function is used for filename and 
+ * other resource conversions for platforms providing native Unicode support.
+ *
+ * @tip Only the errors APR_EINVAL and APR_INCOMPLETE may occur, the former
+ * when the character code is invalid (in or out of context) and the later
+ * when more characters were expected, but insufficient characters remain.
+ */
+APR_DECLARE(apr_status_t) apr_conv_utf8_to_ucs2(const char *in, 
+                                                apr_size_t *inbytes,
+                                                apr_wchar_t *out, 
+                                                apr_size_t *outwords);
+
+/**
+ * An APR internal function for fast ucs-2 wide Unicode format conversion to 
+ * the utf-8 octet-encoded Unicode.  This function is used for filename and 
+ * other resource conversions for platforms providing native Unicode support.
+ *
+ * @tip Only the errors APR_EINVAL and APR_INCOMPLETE may occur, the former
+ * when the character code is invalid (in or out of context) and the later
+ * when more words were expected, but insufficient words remain.
+ */
+APR_DECLARE(apr_status_t) apr_conv_ucs2_to_utf8(const apr_wchar_t *in, 
+                                                apr_size_t *inwords,
+                                                char *out, 
+                                                apr_size_t *outbytes);
+
+#endif /* def UTF8_H */
diff --git a/include/arch/win32/apr_dbg_win32_handles.h b/include/arch/win32/apr_dbg_win32_handles.h
new file mode 100644
index 00000000000..471cd66dbfc
--- /dev/null
+++ b/include/arch/win32/apr_dbg_win32_handles.h
@@ -0,0 +1,217 @@
+/* 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 APR_DBG_WIN32_HANDLES_H
+#define APR_DBG_WIN32_HANDLES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* USAGE:
+ * 
+ * Add the following include to apr_private.h for internal debugging,
+ * or copy this header into apr/include add the include below to apr.h
+ * for really global debugging;
+ *
+ *   #include "apr_dbg_win32_handles.h"
+ *
+ * apr_dbg_log is the crux of this function ... it uses Win32 API and
+ * no apr calls itself to log all activity to a file named for the
+ * executing application with a .pid suffix.  Ergo several instances
+ * may be executing and logged at once.
+ *
+ * HANDLE apr_dbg_log(char* fn, HANDLE ha, char* fl, int ln, int nh 
+ *                           [, HANDLE *hv, char *dsc...])
+ *
+ * returns: the handle passed in ha, which is cast back to the real return type.
+ *
+ * formats one line into the debug log file if nh is zero;
+ * ha (hex) seq(hex) tid(hex) fn     fl         ln
+ * xxxxxxxx xxxxxxxx xxxxxxxx func() sourcefile:lineno
+ * The macro apr_dbg_rv makes this simple to implement for many APIs
+ * that simply take args that don't interest us, and return a handle.
+ *
+ * formats multiple lines (nh) into the debug log file for each hv/dsc pair
+ * (nh must correspond to the number of pairs);
+ * hv (hex) seq(hex) tid(hex) fn   dsc  fl         ln
+ * xxxxxxxx xxxxxxxx xxxxxxxx func(arg) sourcefile:lineno
+ * In this later usage, hv is the still the return value but is not
+ * treated as a handle.
+ */
+
+APR_DECLARE_NONSTD(HANDLE) apr_dbg_log(char* fn, HANDLE ha, char* fl, int ln, 
+                                       int nh,/* HANDLE *hv, char *dsc */...);
+
+#define apr_dbg_rv(fn, args) (apr_dbg_log(#fn,(fn) args,__FILE__,__LINE__,0))
+
+#define CloseHandle(h) \
+    ((BOOL)apr_dbg_log("CloseHandle", \
+                       (HANDLE)(CloseHandle)(h), \
+                       __FILE__,__LINE__,1, \
+                       &(h),""))
+
+#define CreateEventA(sd,b1,b2,nm) apr_dbg_rv(CreateEventA,(sd,b1,b2,nm))
+#define CreateEventW(sd,b1,b2,nm) apr_dbg_rv(CreateEventW,(sd,b1,b2,nm))
+
+#define CreateFileA(nm,d1,d2,sd,d3,d4,h) apr_dbg_rv(CreateFileA,(nm,d1,d2,sd,d3,d4,h))
+#define CreateFileW(nm,d1,d2,sd,d3,d4,h) apr_dbg_rv(CreateFileW,(nm,d1,d2,sd,d3,d4,h))
+
+#define CreateFileMappingA(fh,sd,d1,d2,d3,nm) apr_dbg_rv(CreateFileMappingA,(fh,sd,d1,d2,d3,nm))
+#define CreateFileMappingW(fh,sd,d1,d2,d3,nm) apr_dbg_rv(CreateFileMappingW,(fh,sd,d1,d2,d3,nm))
+
+#define CreateMutexA(sd,b,nm) apr_dbg_rv(CreateMutexA,(sd,b,nm))
+#define CreateMutexW(sd,b,nm) apr_dbg_rv(CreateMutexW,(sd,b,nm))
+
+#define CreateIoCompletionPort(h1,h2,pd1,d2) apr_dbg_rv(CreateIoCompletionPort,(h1,h2,pd1,d2))
+
+#define CreateNamedPipeA(nm,d1,d2,d3,d4,d5,d6,sd) apr_dbg_rv(CreateNamedPipeA,(nm,d1,d2,d3,d4,d5,d6,sd))
+#define CreateNamedPipeW(nm,d1,d2,d3,d4,d5,d6,sd) apr_dbg_rv(CreateNamedPipeW,(nm,d1,d2,d3,d4,d5,d6,sd))
+
+#define CreatePipe(ph1,ph2,sd,d) \
+    ((BOOL)apr_dbg_log("CreatePipe", \
+                       (HANDLE)(CreatePipe)(ph1,ph2,sd,d), \
+                       __FILE__,__LINE__,2, \
+                       (ph1),"hRead", \
+                       (ph2),"hWrite"))
+
+#define CreateProcessA(s1,s2,sd1,sd2,b,d1,s3,s4,pd2,hr) \
+    ((BOOL)apr_dbg_log("CreateProcessA", \
+                       (HANDLE)(CreateProcessA)(s1,s2,sd1,sd2,b,d1,s3,s4,pd2,hr), \
+                       __FILE__,__LINE__,2, \
+                       &((hr)->hProcess),"hProcess", \
+                       &((hr)->hThread),"hThread"))
+#define CreateProcessW(s1,s2,sd1,sd2,b,d1,s3,s4,pd2,hr) \
+    ((BOOL)apr_dbg_log("CreateProcessW", \
+                       (HANDLE)(CreateProcessW)(s1,s2,sd1,sd2,b,d1,s3,s4,pd2,hr), \
+                       __FILE__,__LINE__,2, \
+                       &((hr)->hProcess),"hProcess", \
+                       &((hr)->hThread),"hThread"))
+
+#define CreateSemaphoreA(sd,d1,d2,nm) apr_dbg_rv(CreateSemaphoreA,(sd,d1,d2,nm))
+#define CreateSemaphoreW(sd,d1,d2,nm) apr_dbg_rv(CreateSemaphoreW,(sd,d1,d2,nm))
+
+#define CreateThread(sd,d1,fn,pv,d2,pd3) apr_dbg_rv(CreateThread,(sd,d1,fn,pv,d2,pd3))
+
+#define DeregisterEventSource(h) \
+    ((BOOL)apr_dbg_log("DeregisterEventSource", \
+                       (HANDLE)(DeregisterEventSource)(h), \
+                       __FILE__,__LINE__,1, \
+                       &(h),""))
+
+#define DuplicateHandle(h1,h2,h3,ph4,d1,b,d2) \
+    ((BOOL)apr_dbg_log("DuplicateHandle", \
+                       (HANDLE)(DuplicateHandle)(h1,h2,h3,ph4,d1,b,d2), \
+                       __FILE__,__LINE__,2, \
+                       (ph4),((h3)==GetCurrentProcess()) \
+                                   ? "Target" : "EXTERN Target", \
+                       &(h2),((h1)==GetCurrentProcess()) \
+                                 ? "Source" : "EXTERN Source"))
+
+#define GetCurrentProcess() \
+    (apr_dbg_log("GetCurrentProcess", \
+                 (GetCurrentProcess)(),__FILE__,__LINE__,0))
+
+#define GetCurrentThread() \
+    (apr_dbg_log("GetCurrentThread", \
+                 (GetCurrentThread)(),__FILE__,__LINE__,0))
+
+#define GetModuleHandleA(nm) apr_dbg_rv(GetModuleHandleA,(nm))
+#define GetModuleHandleW(nm) apr_dbg_rv(GetModuleHandleW,(nm))
+
+#define GetStdHandle(d) apr_dbg_rv(GetStdHandle,(d))
+
+#define LoadLibraryA(nm) apr_dbg_rv(LoadLibraryA,(nm))
+#define LoadLibraryW(nm) apr_dbg_rv(LoadLibraryW,(nm))
+
+#define LoadLibraryExA(nm,h,d) apr_dbg_rv(LoadLibraryExA,(nm,h,d))
+#define LoadLibraryExW(nm,h,d) apr_dbg_rv(LoadLibraryExW,(nm,h,d))
+
+#define OpenEventA(d,b,nm) apr_dbg_rv(OpenEventA,(d,b,nm))
+#define OpenEventW(d,b,nm) apr_dbg_rv(OpenEventW,(d,b,nm))
+
+#define OpenFileMappingA(d,b,nm) apr_dbg_rv(OpenFileMappingA,(d,b,nm))
+#define OpenFileMappingW(d,b,nm) apr_dbg_rv(OpenFileMappingW,(d,b,nm))
+
+#define RegisterEventSourceA(s1,s2) apr_dbg_rv(RegisterEventSourceA,(s1,s2))
+#define RegisterEventSourceW(s1,s2) apr_dbg_rv(RegisterEventSourceW,(s1,s2))
+
+#define SetEvent(h) \
+    ((BOOL)apr_dbg_log("SetEvent", \
+                       (HANDLE)(SetEvent)(h), \
+                       __FILE__,__LINE__,1, \
+                       &(h),""))
+
+#define SetStdHandle(d,h) \
+    ((BOOL)apr_dbg_log("SetStdHandle", \
+                       (HANDLE)(SetStdHandle)(d,h), \
+                       __FILE__,__LINE__,1,&(h),""))
+
+#define socket(i1,i2,i3) \
+    ((SOCKET)apr_dbg_log("socket", \
+                         (HANDLE)(socket)(i1,i2,i3), \
+                       __FILE__,__LINE__,0))
+
+#define WaitForSingleObject(h,d) \
+    ((DWORD)apr_dbg_log("WaitForSingleObject", \
+                        (HANDLE)(WaitForSingleObject)(h,d), \
+                        __FILE__,__LINE__,1,&(h),"Signaled"))
+
+#define WaitForSingleObjectEx(h,d,b) \
+    ((DWORD)apr_dbg_log("WaitForSingleObjectEx", \
+                        (HANDLE)(WaitForSingleObjectEx)(h,d,b), \
+                        __FILE__,__LINE__,1,&(h),"Signaled"))
+
+#define WaitForMultipleObjects(d1,ah,b,d2) \
+    ((DWORD)apr_dbg_log("WaitForMultipleObjects", \
+                        (HANDLE)(WaitForMultipleObjects)(d1,ah,b,d2), \
+                        __FILE__,__LINE__,1,ah,"Signaled"))
+
+#define WaitForMultipleObjectsEx(d1,ah,b1,d2,b2) \
+    ((DWORD)apr_dbg_log("WaitForMultipleObjectsEx", \
+                        (HANDLE)(WaitForMultipleObjectsEx)(d1,ah,b1,d2,b2), \
+                        __FILE__,__LINE__,1,ah,"Signaled"))
+
+#define WSASocketA(i1,i2,i3,pi,g,dw) \
+    ((SOCKET)apr_dbg_log("WSASocketA", \
+                         (HANDLE)(WSASocketA)(i1,i2,i3,pi,g,dw), \
+                       __FILE__,__LINE__,0))
+
+#define WSASocketW(i1,i2,i3,pi,g,dw) \
+    ((SOCKET)apr_dbg_log("WSASocketW", \
+                         (HANDLE)(WSASocketW)(i1,i2,i3,pi,g,dw), \
+                       __FILE__,__LINE__,0))
+
+#define closesocket(sh) \
+    ((int)apr_dbg_log("closesocket", \
+                      (HANDLE)(closesocket)(sh), \
+                      __FILE__,__LINE__,1,&(sh),""))
+
+#define _beginthread(fn,d,pv) \
+    ((unsigned long)apr_dbg_log("_beginthread", \
+                                (HANDLE)(_beginthread)(fn,d,pv), \
+                                __FILE__,__LINE__,0))
+
+#define _beginthreadex(sd,d1,fn,pv,d2,pd3) \
+    ((unsigned long)apr_dbg_log("_beginthreadex", \
+                                (HANDLE)(_beginthreadex)(sd,d1,fn,pv,d2,pd3), \
+                                __FILE__,__LINE__,0))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !defined(APR_DBG_WIN32_HANDLES_H) */
diff --git a/include/arch/win32/apr_private.h b/include/arch/win32/apr_private.h
index d3015e35862..9f12efa189d 100644
--- a/include/arch/win32/apr_private.h
+++ b/include/arch/win32/apr_private.h
@@ -1,99 +1,76 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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.
  */
 
 /*
  * Note: 
- * This is the windows specific autoconf like config file
- * which is used to generate apr_private.h at build time.
- * Do not put any code into this file which depends on
- * APR include files.
+ * This is the win32-specific autoconf-like config file
+ * which unix creates at ./configure time.
  */
 
-#ifdef WIN32
+#ifndef APR_PRIVATE_H
+#define APR_PRIVATE_H
 
-#ifndef APR_CONFIG_H
-#define APR_CONFIG_H
+/* Pick up publicly advertised headers and symbols before the
+ * APR internal private headers and symbols
+ */
+#include <apr.h>
 
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#endif
-#ifndef _WIN32_WINNT
 /* 
- * Compile the server including all the Windows NT 4.0 header files by 
- * default.
+ * Add a _very_few_ declarations missing from the restricted set of headers
+ * (If this list becomes extensive, re-enable the required headers in apr.hw!)
+ * ACL headers were excluded by default, so include them now.
  */
-#define _WIN32_WINNT 0x0400
+#ifndef SW_HIDE
+#define SW_HIDE             0
 #endif
-#include <windows.h>
-#include <winsock2.h>
-#include <mswsock.h>
-#include <sys/types.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <time.h>
 
-#define HAVE_SENDFILE 1
+/* For the misc.h late-loaded dynamic symbols, we need some obscure types 
+ * Avoid dragging in wtypes.h unless it's absolutely necessary [generally
+ * not with APR itself, until some GUI-related security is introduced.]
+ */
+#ifndef _WIN32_WCE
+#define HAVE_ACLAPI 1
+#ifdef __wtypes_h__
+#include <accctrl.h>
+#else
+#define __wtypes_h__
+#include <accctrl.h>
+#undef __wtypes_h__
+#endif
+#else
+#define HAVE_ACLAPI 0
+#endif
 
 /* Use this section to define all of the HAVE_FOO_H
  * that are required to build properly.
  */
-#define HAVE_CONIO_H 1
-#define HAVE_MALLOC_H 1
-#define HAVE_STDLIB_H 1
 #define HAVE_LIMITS_H 1
+#define HAVE_MALLOC_H 1
+#define HAVE_PROCESS_H APR_NOT_IN_WCE
 #define HAVE_SIGNAL_H 1
+#define HAVE_STDDEF_H APR_NOT_IN_WCE
+#define HAVE_STDLIB_H 1
+
+#define HAVE_STRICMP  1
+#define HAVE_STRNICMP 1
+#define HAVE_STRDUP   1
+#define HAVE_STRSTR   1
+#define HAVE_MEMCHR   1
 
+#ifndef __WATCOMC__
 #define SIGHUP     1
 /* 2 is used for SIGINT on windows */
 #define SIGQUIT    3
@@ -106,6 +83,7 @@
 #define SIGUSR1    10
 /* 11 is used for SIGSEGV on windows */
 #define SIGUSR2    12
+#endif
 #define SIGPIPE    13
 #define SIGALRM    14
 /* 15 is used for SIGTERM on windows */
@@ -126,8 +104,6 @@
 #define SIGWINCH   30
 #define SIGIO      31
 
-#define __attribute__(__x) 
-
 /* APR COMPATABILITY FUNCTIONS
  * This section should be used to define functions and
  * macros which are need to make Windows features look
@@ -135,15 +111,11 @@
  */
 typedef void (Sigfunc)(int);
 
-#define strcasecmp(s1, s2)       stricmp(s1, s2)
-#define sleep(t)                 Sleep(t * 1000)
-
-
-/* APR FEATURE MACROS.
- * This section should be used to define feature macros
- * that the windows port needs.
- */
-#define APR_HAS_THREADS        1
+#define sleep(t)                 Sleep((t) * 1000)
+/* For now workaround for Watcom'S lack of _commit() */
+#ifdef __WATCOMC__
+#define _commit                  fsync
+#endif
 
 #define SIZEOF_SHORT           2
 #define SIZEOF_INT             4
@@ -154,5 +126,73 @@ typedef void (Sigfunc)(int);
 unsigned __stdcall SignalHandling(void *);
 int thread_ready(void);
 
-#endif  /*APR_CONFIG_H*/
-#endif  /*WIN32*/
+#if !APR_HAVE_ERRNO_H
+APR_DECLARE_DATA int errno;
+#define ENOSPC 1
+#endif
+
+#if APR_HAVE_IPV6
+#define HAVE_GETADDRINFO 1
+#define HAVE_GETNAMEINFO 1
+#define HAVE_IF_INDEXTONAME 1
+#define HAVE_IF_NAMETOINDEX 1
+#endif
+
+/* MSVC 7.0 introduced _strtoi64 */
+#if _MSC_VER >= 1300 && _INTEGRAL_MAX_BITS >= 64 && !defined(_WIN32_WCE)
+#define APR_INT64_STRFN	      _strtoi64
+#endif
+
+#if APR_HAS_LARGE_FILES
+#ifdef APR_INT64_STRFN
+#define APR_OFF_T_STRFN         APR_INT64_STRFN
+#else
+#define APR_OFF_T_STRFN         apr_strtoi64
+#endif
+#else
+#if defined(_WIN32_WCE)
+#define APR_OFF_T_STRFN         strtol
+#else
+#define APR_OFF_T_STRFN         strtoi
+#endif
+#endif
+
+/* used to check for DWORD overflow in 64bit compiles */
+#define APR_DWORD_MAX 0xFFFFFFFFUL
+
+/* Compile win32 with DSO support for .dll builds
+ * Pair the static xml build for static apr-2.lib
+ */
+#ifdef APR_DECLARE_STATIC
+#define APU_DSO_BUILD           0
+#define XML_STATIC              1
+#else
+#define APU_DSO_BUILD           1
+#endif
+
+/* Presume a standard, modern (5.x) mysql sdk */
+#define HAVE_MY_GLOBAL_H        1
+
+/* my_sys.h is broken on VC/Win32, and apparently not required */
+/* #undef HAVE_MY_SYS_H           0 */
+
+/* Windows ODBC sql.h is always present */
+#define HAVE_SQL_H              1
+
+#define HAVE_ICONV_H 1
+
+/*
+ * Windows does not have GDBM, and we always use the bundled (new) Expat
+ */
+
+/* Define if you have the gdbm library (-lgdbm).  */
+/* #undef HAVE_LIBGDBM */
+
+/* define if Expat 1.0 or 1.1 was found */
+/* #undef APR_HAVE_OLD_EXPAT */
+
+#ifdef HAVE_PROCESS_H
+#include <process.h>
+#endif
+
+#endif  /*APR_PRIVATE_H*/
diff --git a/include/arch/win32/atime.h b/include/arch/win32/atime.h
deleted file mode 100644
index cf5ab487386..00000000000
--- a/include/arch/win32/atime.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef ATIME_H
-#define ATIME_H
-
-#include "apr_private.h"
-#include "apr_time.h"
-#include <time.h>
-
-struct atime_t {
-    ap_pool_t *cntxt;
-    ap_time_t currtime;
-    SYSTEMTIME *explodedtime;
-};
-    
-void FileTimeToAprTime(ap_time_t *atime, FILETIME *ft);
-void AprTimeToFileTime(LPFILETIME pft, ap_time_t t);
-
-#endif  /* ! ATIME_H */
-
diff --git a/include/arch/win32/dso.h b/include/arch/win32/dso.h
deleted file mode 100644
index 745db192dce..00000000000
--- a/include/arch/win32/dso.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef DSO_H
-#define DSO_H
-
-#include "apr_private.h"
-#include "apr_general.h"
-#include "apr_pools.h"
-#include "apr_dso.h"
-
-struct ap_dso_handle_t {
-    ap_pool_t  *cont;
-    void          *handle;
-};
-
-#endif
diff --git a/include/arch/win32/fileio.h b/include/arch/win32/fileio.h
deleted file mode 100644
index 974889dd03a..00000000000
--- a/include/arch/win32/fileio.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef FILE_IO_H
-#define FILE_IO_H
-
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_TIME_H
-#include <time.h>
-#endif
-#ifdef HAVE_DIRENT_H
-#include <dirent.h>
-#endif
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
-#ifdef HAVE_UIO_H
-#include <sys/uio.h>
-#endif
-#include "apr_private.h"
-#include "apr_pools.h"
-#include "apr_general.h"
-#include "apr_file_io.h"
-#include "apr_errno.h"
-
-/* quick run-down of fields in windows' ap_file_t structure that may have 
- * obvious uses.
- * fname --  the filename as passed to the open call.
- * dwFileAttricutes -- Attributes used to open the file.
- * demonfname -- the canonicalized filename.  Used to store the result from
- *               ap_os_canonicalize_filename.
- * lowerdemonfname -- inserted at Ken Parzygnat's request, because of the
- *                    ugly way windows deals with case in the filesystem.
- * append -- Windows doesn't support the append concept when opening files.
- *           APR needs to keep track of this, and always make sure we append
- *           correctly when writing to a file with this flag set TRUE.
- */
-
-struct ap_file_t {
-    ap_pool_t *cntxt;
-    HANDLE filehand;
-    char *fname;
-    DWORD dwFileAttributes;
-    int eof_hit;
-    int pipe;
-    ap_interval_time_t timeout;
-    int buffered;     /* Not currently used on Windows */
-    int ungetchar;    /* Not used. Last char provided by an unget op. (-1 = no char)*/
-
-    char *demonfname; 
-    char *lowerdemonfname; 
-    int append; 
-
-    off_t size;
-    ap_time_t atime;
-    ap_time_t mtime;
-    ap_time_t ctime;
-};
-
-struct ap_dir_t {
-    ap_pool_t *cntxt;
-    char *dirname;
-    HANDLE dirhand;
-    WIN32_FIND_DATA *entry;
-};
-
-ap_status_t file_cleanup(void *);
-/*mode_t get_fileperms(ap_fileperms_t);
-*/
-API_EXPORT(char *) ap_os_systemcase_filename(struct ap_pool_t *pCont, 
-                                             const char *szFile);
-char * canonical_filename(struct ap_pool_t *pCont, const char *szFile);
-
-#endif  /* ! FILE_IO_H */
-
diff --git a/include/arch/win32/locks.h b/include/arch/win32/locks.h
deleted file mode 100644
index 602c2eb673f..00000000000
--- a/include/arch/win32/locks.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef LOCKS_H
-#define LOCKS_H
-
-#include "apr_lock.h"
-
-struct ap_lock_t {
-    ap_pool_t *cntxt;
-    ap_locktype_e type;
-    ap_lockscope_e scope;
-    HANDLE mutex;
-    CRITICAL_SECTION section;
-    char *fname;
-};
-
-#endif  /* LOCKS_H */
-
diff --git a/include/arch/win32/misc.h b/include/arch/win32/misc.h
deleted file mode 100644
index bb754bbf62e..00000000000
--- a/include/arch/win32/misc.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef MISC_H
-#define MISC_H
-
-#include "apr.h"
-#include "apr_private.h"
-#include "apr_general.h"
-#include "apr_pools.h"
-#include "apr_getopt.h"
-#include "apr_thread_proc.h"
-#include "apr_errno.h"
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STDIO_H
-#include <stdio.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_SIGNAL_H
-#include <signal.h>
-#endif
-#ifdef HAVE_PTHREAD_H
-#include <pthread.h>
-#endif
- 
-typedef struct datastruct {
-    void *data;
-    char *key;
-    struct datastruct *next;
-    struct datastruct *prev;
-} datastruct;
-
-struct ap_other_child_rec_t {
-    struct ap_other_child_rec_t *next;
-    int pid;
-    void (*maintenance) (int, void *, int);
-    void *data;
-    int write_fd;
-};
-
-
-#endif  /* ! MISC_H */
-
diff --git a/include/arch/win32/networkio.h b/include/arch/win32/networkio.h
deleted file mode 100644
index 58d82f8b126..00000000000
--- a/include/arch/win32/networkio.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef NETWORK_IO_H
-#define NETWORK_IO_H
-
-#include "apr_network_io.h"
-#include "apr_general.h"
-
-struct ap_socket_t {
-    ap_pool_t *cntxt;
-    SOCKET sock;
-    struct sockaddr_in *local_addr;
-    struct sockaddr_in *remote_addr;
-    size_t addr_len;
-    ap_interval_time_t timeout;
-};
-
-struct ap_pollfd_t {
-    ap_pool_t *cntxt;
-    fd_set *read;
-    int numread;
-    fd_set *write;
-    int numwrite;
-    fd_set *except;
-    int numexcept;    
-};
-
-ap_status_t status_from_res_error(int);
-
-#endif  /* ! NETWORK_IO_H */
-
diff --git a/include/arch/win32/threadproc.h b/include/arch/win32/threadproc.h
deleted file mode 100644
index 16667de67e7..00000000000
--- a/include/arch/win32/threadproc.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "apr_private.h"
-#include "apr_thread_proc.h"
-#include "apr_file_io.h"
-#include <windows.h>
-
-#ifndef THREAD_PROC_H
-#define THREAD_PROC_H
-
-#define SHELL_PATH "cmd.exe"
-
-struct ap_thread_t {
-    ap_pool_t *cntxt;
-    HANDLE td;
-    ap_int32_t cancel;
-    ap_int32_t cancel_how;
-};
-
-struct ap_threadattr_t {
-    ap_pool_t *cntxt;
-    ap_int32_t detach;
-};
-
-struct ap_threadkey_t {
-    ap_pool_t *cntxt;
-    DWORD key;
-};
-
-struct ap_procattr_t {
-    ap_pool_t *cntxt;
-    STARTUPINFO si;
-    ap_file_t *parent_in;
-    ap_file_t *child_in;
-    ap_file_t *parent_out;
-    ap_file_t *child_out;
-    ap_file_t *parent_err;
-    ap_file_t *child_err;
-    char *currdir;
-    ap_int32_t cmdtype;
-    ap_int32_t detached;
-};
-
-struct ap_proc_t {
-    ap_pool_t *cntxt;
-    PROCESS_INFORMATION pi;
-    struct ap_procattr_t *attr;
-};
-
-#endif  /* ! THREAD_PROC_H */
-
diff --git a/include/private/apr_crypto_internal.h b/include/private/apr_crypto_internal.h
new file mode 100644
index 00000000000..1ea838bfb7d
--- /dev/null
+++ b/include/private/apr_crypto_internal.h
@@ -0,0 +1,297 @@
+/* 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 APR_CRYPTO_INTERNAL_H
+#define APR_CRYPTO_INTERNAL_H
+
+#include <stdarg.h>
+
+#include "apr_crypto.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if APU_HAVE_CRYPTO
+
+struct apr_crypto_driver_t {
+
+    /** name */
+    const char *name;
+
+    /**
+     * @brief: allow driver to perform once-only initialisation.
+     * Called once only.
+     * @param pool The pool to register the cleanup in.
+     * @param params Optional init parameter string.
+     * @param rc Driver-specific additional error code
+     */
+    apr_status_t (*init)(apr_pool_t *pool, const char *params,
+            const apu_err_t **result);
+
+    /**
+     * @brief Create a context for supporting encryption. Keys, certificates,
+     *        algorithms and other parameters will be set per context. More than
+     *        one context can be created at one time. A cleanup will be automatically
+     *        registered with the given pool to guarantee a graceful shutdown.
+     * @param f - context pointer will be written here
+     * @param provider - provider to use
+     * @param params - array of key parameters
+     * @param pool - process pool
+     * @return APR_ENOENGINE when the engine specified does not exist. APR_EINITENGINE
+     * if the engine cannot be initialised.
+     */
+    apr_status_t (*make)(apr_crypto_t **f, const apr_crypto_driver_t *provider,
+            const char *params, apr_pool_t *pool);
+
+    /**
+     * @brief Get a hash table of key types, keyed by the name of the type against
+     * a pointer to apr_crypto_block_key_type_t.
+     *
+     * @param types - hashtable of key types keyed to constants.
+     * @param f - encryption context
+     * @return APR_SUCCESS for success
+     */
+    apr_status_t (*get_block_key_types)(apr_hash_t **types,
+            const apr_crypto_t *f);
+
+    /**
+     * @brief Get a hash table of key modes, keyed by the name of the mode against
+     * a pointer to apr_crypto_block_key_mode_t.
+     *
+     * @param modes - hashtable of key modes keyed to constants.
+     * @param f - encryption context
+     * @return APR_SUCCESS for success
+     */
+    apr_status_t (*get_block_key_modes)(apr_hash_t **modes,
+            const apr_crypto_t *f);
+
+    /**
+     * @brief Create a key from the given passphrase. By default, the PBKDF2
+     *        algorithm is used to generate the key from the passphrase. It is expected
+     *        that the same pass phrase will generate the same key, regardless of the
+     *        backend crypto platform used. The key is cleaned up when the context
+     *        is cleaned, and may be reused with multiple encryption or decryption
+     *        operations.
+     * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
+     *       *key is not NULL, *key must point at a previously created structure.
+     * @param key The key returned, see note.
+     * @param ivSize The size of the initialisation vector will be returned, based
+     *               on whether an IV is relevant for this type of crypto.
+     * @param pass The passphrase to use.
+     * @param passLen The passphrase length in bytes
+     * @param salt The salt to use.
+     * @param saltLen The salt length in bytes
+     * @param type 3DES_192, AES_128, AES_192, AES_256.
+     * @param mode Electronic Code Book / Cipher Block Chaining.
+     * @param doPad Pad if necessary.
+     * @param iterations Iteration count
+     * @param f The context to use.
+     * @param p The pool to use.
+     * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
+     *         error occurred while generating the key. APR_ENOCIPHER if the type or mode
+     *         is not supported by the particular backend. APR_EKEYTYPE if the key type is
+     *         not known. APR_EPADDING if padding was requested but is not supported.
+     *         APR_ENOTIMPL if not implemented.
+     */
+    apr_status_t (*passphrase)(apr_crypto_key_t **key, apr_size_t *ivSize,
+            const char *pass, apr_size_t passLen, const unsigned char * salt,
+            apr_size_t saltLen, const apr_crypto_block_key_type_e type,
+            const apr_crypto_block_key_mode_e mode, const int doPad,
+            const int iterations, const apr_crypto_t *f, apr_pool_t *p);
+
+    /**
+     * @brief Initialise a context for encrypting arbitrary data using the given key.
+     * @note If *ctx is NULL, a apr_crypto_block_t will be created from a pool. If
+     *       *ctx is not NULL, *ctx must point at a previously created structure.
+     * @param ctx The block context returned, see note.
+     * @param iv Optional initialisation vector. If the buffer pointed to is NULL,
+     *           an IV will be created at random, in space allocated from the pool.
+     *           If the buffer pointed to is not NULL, the IV in the buffer will be
+     *           used.
+     * @param key The key structure.
+     * @param blockSize The block size of the cipher.
+     * @param p The pool to use.
+     * @return Returns APR_ENOIV if an initialisation vector is required but not specified.
+     *         Returns APR_EINIT if the backend failed to initialise the context. Returns
+     *         APR_ENOTIMPL if not implemented.
+     */
+    apr_status_t (*block_encrypt_init)(apr_crypto_block_t **ctx,
+            const unsigned char **iv, const apr_crypto_key_t *key,
+            apr_size_t *blockSize, apr_pool_t *p);
+
+    /**
+     * @brief Encrypt data provided by in, write it to out.
+     * @note The number of bytes written will be written to outlen. If
+     *       out is NULL, outlen will contain the maximum size of the
+     *       buffer needed to hold the data, including any data
+     *       generated by apr_crypto_block_encrypt_finish below. If *out points
+     *       to NULL, a buffer sufficiently large will be created from
+     *       the pool provided. If *out points to a not-NULL value, this
+     *       value will be used as a buffer instead.
+     * @param out Address of a buffer to which data will be written,
+     *        see note.
+     * @param outlen Length of the output will be written here.
+     * @param in Address of the buffer to read.
+     * @param inlen Length of the buffer to read.
+     * @param ctx The block context to use.
+     * @return APR_ECRYPT if an error occurred. Returns APR_ENOTIMPL if
+     *         not implemented.
+     */
+    apr_status_t (*block_encrypt)(unsigned char **out, apr_size_t *outlen,
+            const unsigned char *in, apr_size_t inlen, apr_crypto_block_t *ctx);
+
+    /**
+     * @brief Encrypt final data block, write it to out.
+     * @note If necessary the final block will be written out after being
+     *       padded. Typically the final block will be written to the
+     *       same buffer used by apr_crypto_block_encrypt, offset by the
+     *       number of bytes returned as actually written by the
+     *       apr_crypto_block_encrypt() call. After this call, the context
+     *       is cleaned and can be reused by apr_crypto_block_encrypt_init().
+     * @param out Address of a buffer to which data will be written. This
+     *            buffer must already exist, and is usually the same
+     *            buffer used by apr_evp_crypt(). See note.
+     * @param outlen Length of the output will be written here.
+     * @param ctx The block context to use.
+     * @return APR_ECRYPT if an error occurred.
+     * @return APR_EPADDING if padding was enabled and the block was incorrectly
+     *         formatted.
+     * @return APR_ENOTIMPL if not implemented.
+     */
+    apr_status_t (*block_encrypt_finish)(unsigned char *out,
+            apr_size_t *outlen, apr_crypto_block_t *ctx);
+
+    /**
+     * @brief Initialise a context for decrypting arbitrary data using the given key.
+     * @note If *ctx is NULL, a apr_crypto_block_t will be created from a pool. If
+     *       *ctx is not NULL, *ctx must point at a previously created structure.
+     * @param ctx The block context returned, see note.
+     * @param blockSize The block size of the cipher.
+     * @param iv Optional initialisation vector. If the buffer pointed to is NULL,
+     *           an IV will be created at random, in space allocated from the pool.
+     *           If the buffer is not NULL, the IV in the buffer will be used.
+     * @param key The key structure.
+     * @param p The pool to use.
+     * @return Returns APR_ENOIV if an initialisation vector is required but not specified.
+     *         Returns APR_EINIT if the backend failed to initialise the context. Returns
+     *         APR_ENOTIMPL if not implemented.
+     */
+    apr_status_t (*block_decrypt_init)(apr_crypto_block_t **ctx,
+            apr_size_t *blockSize, const unsigned char *iv,
+            const apr_crypto_key_t *key, apr_pool_t *p);
+
+    /**
+     * @brief Decrypt data provided by in, write it to out.
+     * @note The number of bytes written will be written to outlen. If
+     *       out is NULL, outlen will contain the maximum size of the
+     *       buffer needed to hold the data, including any data
+     *       generated by apr_crypto_block_decrypt_finish below. If *out points
+     *       to NULL, a buffer sufficiently large will be created from
+     *       the pool provided. If *out points to a not-NULL value, this
+     *       value will be used as a buffer instead.
+     * @param out Address of a buffer to which data will be written,
+     *        see note.
+     * @param outlen Length of the output will be written here.
+     * @param in Address of the buffer to read.
+     * @param inlen Length of the buffer to read.
+     * @param ctx The block context to use.
+     * @return APR_ECRYPT if an error occurred. Returns APR_ENOTIMPL if
+     *         not implemented.
+     */
+    apr_status_t (*block_decrypt)(unsigned char **out, apr_size_t *outlen,
+            const unsigned char *in, apr_size_t inlen, apr_crypto_block_t *ctx);
+
+    /**
+     * @brief Decrypt final data block, write it to out.
+     * @note If necessary the final block will be written out after being
+     *       padded. Typically the final block will be written to the
+     *       same buffer used by apr_crypto_block_decrypt, offset by the
+     *       number of bytes returned as actually written by the
+     *       apr_crypto_block_decrypt() call. After this call, the context
+     *       is cleaned and can be reused by apr_crypto_block_decrypt_init().
+     * @param out Address of a buffer to which data will be written. This
+     *            buffer must already exist, and is usually the same
+     *            buffer used by apr_evp_crypt(). See note.
+     * @param outlen Length of the output will be written here.
+     * @param ctx The block context to use.
+     * @return APR_ECRYPT if an error occurred.
+     * @return APR_EPADDING if padding was enabled and the block was incorrectly
+     *         formatted.
+     * @return APR_ENOTIMPL if not implemented.
+     */
+    apr_status_t (*block_decrypt_finish)(unsigned char *out,
+            apr_size_t *outlen, apr_crypto_block_t *ctx);
+
+    /**
+     * @brief Clean encryption / decryption context.
+     * @note After cleanup, a context is free to be reused if necessary.
+     * @param ctx The block context to use.
+     * @return Returns APR_ENOTIMPL if not supported.
+     */
+    apr_status_t (*block_cleanup)(apr_crypto_block_t *ctx);
+
+    /**
+     * @brief Clean encryption / decryption context.
+     * @note After cleanup, a context is free to be reused if necessary.
+     * @param f The context to use.
+     * @return Returns APR_ENOTIMPL if not supported.
+     */
+    apr_status_t (*cleanup)(apr_crypto_t *f);
+
+    /**
+     * @brief Clean encryption / decryption context.
+     * @note After cleanup, a context is free to be reused if necessary.
+     * @return Returns APR_ENOTIMPL if not supported.
+     */
+    apr_status_t (*shutdown)(void);
+
+    /**
+     * @brief: fetch the most recent error from this driver.
+     * @param result - the result structure
+     * @param f - context pointer
+     * @return APR_SUCCESS for success.
+     */
+    apr_status_t (*error)(const apu_err_t **result, const apr_crypto_t *f);
+
+    /**
+     * @brief Create a key from the provided secret or passphrase. The key is cleaned
+     *        up when the context is cleaned, and may be reused with multiple encryption
+     *        or decryption operations.
+     * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
+     *       *key is not NULL, *key must point at a previously created structure.
+     * @param key The key returned, see note.
+     * @param rec The key record, from which the key will be derived.
+     * @param f The context to use.
+     * @param p The pool to use.
+     * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
+     *         error occurred while generating the key. APR_ENOCIPHER if the type or mode
+     *         is not supported by the particular backend. APR_EKEYTYPE if the key type is
+     *         not known. APR_EPADDING if padding was requested but is not supported.
+     *         APR_ENOTIMPL if not implemented.
+     */
+    apr_status_t (*key)(apr_crypto_key_t **key, const apr_crypto_key_rec_t *rec,
+            const apr_crypto_t *f, apr_pool_t *p);
+
+};
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/private/apr_dbd_internal.h b/include/private/apr_dbd_internal.h
new file mode 100644
index 00000000000..3d50cc603e1
--- /dev/null
+++ b/include/private/apr_dbd_internal.h
@@ -0,0 +1,365 @@
+/* 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.
+ */
+
+/* Overview of what this is and does:
+ * http://www.apache.org/~niq/dbd.html
+ */
+
+#ifndef APR_DBD_INTERNAL_H
+#define APR_DBD_INTERNAL_H
+
+#include <stdarg.h>
+
+#include "apr_dbd.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define TXN_IGNORE_ERRORS(t) \
+  ((t) && ((t)->mode & APR_DBD_TRANSACTION_IGNORE_ERRORS))
+#define TXN_NOTICE_ERRORS(t) \
+  ((t) && !((t)->mode & APR_DBD_TRANSACTION_IGNORE_ERRORS))
+
+#define TXN_DO_COMMIT(t)   (!((t)->mode & APR_DBD_TRANSACTION_ROLLBACK))
+#define TXN_DO_ROLLBACK(t) ((t)->mode & APR_DBD_TRANSACTION_ROLLBACK)
+
+#define TXN_MODE_BITS \
+  (APR_DBD_TRANSACTION_ROLLBACK|APR_DBD_TRANSACTION_IGNORE_ERRORS)
+
+struct apr_dbd_driver_t {
+    /** name */
+    const char *name;
+
+    /** init: allow driver to perform once-only initialisation.
+     *  Called once only.  May be NULL
+     */
+    void (*init)(apr_pool_t *pool);
+
+    /** native_handle: return the native database handle of the underlying db
+     *
+     * @param handle - apr_dbd handle
+     * @return - native handle
+     */
+    void *(*native_handle)(apr_dbd_t *handle);
+
+    /** open: obtain a database connection from the server rec.
+     *  Must be explicitly closed when you're finished with it.
+     *  WARNING: only use this when you need a connection with
+     *  a lifetime other than a request
+     *
+     *  @param pool - a pool to use for error messages (if any).
+     *  @param params - connection parameters.
+     *  @param error - descriptive error.
+     *  @return database handle, or NULL on error.
+     */
+    apr_dbd_t *(*open)(apr_pool_t *pool, const char *params,
+                       const char **error);
+
+    /** check_conn: check status of a database connection
+     *
+     *  @param pool - a pool to use for error messages (if any).
+     *  @param handle - the connection to check
+     *  @return APR_SUCCESS or error
+     */
+    apr_status_t (*check_conn)(apr_pool_t *pool, apr_dbd_t *handle);
+
+    /** close: close/release a connection obtained from open()
+     *
+     *  @param handle - the connection to release
+     *  @return APR_SUCCESS or error
+     */
+    apr_status_t (*close)(apr_dbd_t *handle);
+
+    /** set_dbname: select database name.  May be a no-op if not supported.
+     *
+     *  @param pool - working pool
+     *  @param handle - the connection
+     *  @param name - the database to select
+     *  @return 0 for success or error code
+     */
+    int (*set_dbname)(apr_pool_t* pool, apr_dbd_t *handle, const char *name);
+
+    /** transaction: start a transaction.  May be a no-op.
+     *
+     *  @param pool   - a pool to use for error messages (if any).
+     *  @param handle - the connection
+     *  @param trans  - ptr to a transaction.  May be null on entry
+     *  @return 0 for success or error code
+     */
+    int (*start_transaction)(apr_pool_t *pool, apr_dbd_t *handle,
+                             apr_dbd_transaction_t **trans);
+
+    /** end_transaction: end a transaction
+     *  (commit on success, rollback on error).
+     *  May be a no-op.
+     *
+     *  @param trans - the transaction.
+     *  @return 0 for success or error code
+     */
+    int (*end_transaction)(apr_dbd_transaction_t *trans);
+
+    /** query: execute an SQL query that doesn't return a result set
+     *
+     *  @param handle - the connection
+     *  @param nrows - number of rows affected.
+     *  @param statement - the SQL statement to execute
+     *  @return 0 for success or error code
+     */
+    int (*query)(apr_dbd_t *handle, int *nrows, const char *statement);
+
+    /** select: execute an SQL query that returns a result set
+     *
+     *  @param pool - pool to allocate the result set
+     *  @param handle - the connection
+     *  @param res - pointer to result set pointer.  May point to NULL on entry
+     *  @param statement - the SQL statement to execute
+     *  @param random - 1 to support random access to results (seek any row);
+     *                  0 to support only looping through results in order
+     *                    (async access - faster)
+     *  @return 0 for success or error code
+     */
+    int (*select)(apr_pool_t *pool, apr_dbd_t *handle, apr_dbd_results_t **res,
+                  const char *statement, int random);
+
+    /** num_cols: get the number of columns in a results set
+     *
+     *  @param res - result set.
+     *  @return number of columns
+     */
+    int (*num_cols)(apr_dbd_results_t *res);
+
+    /** num_tuples: get the number of rows in a results set
+     *  of a synchronous select
+     *
+     *  @param res - result set.
+     *  @return number of rows, or -1 if the results are asynchronous
+     */
+    int (*num_tuples)(apr_dbd_results_t *res);
+
+    /** get_row: get a row from a result set
+     *
+     *  @param pool - pool to allocate the row
+     *  @param res - result set pointer
+     *  @param row - pointer to row pointer.  May point to NULL on entry
+     *  @param rownum - row number, or -1 for "next row".  Ignored if random
+     *                  access is not supported.
+     *  @return 0 for success, -1 for rownum out of range or data finished
+     */
+    int (*get_row)(apr_pool_t *pool, apr_dbd_results_t *res,
+                   apr_dbd_row_t **row, int rownum);
+  
+    /** get_entry: get an entry from a row
+     *
+     *  @param row - row pointer
+     *  @param col - entry number
+     *  @param val - entry to fill
+     *  @return 0 for success, -1 for no data, +1 for general error
+     */
+    const char* (*get_entry)(const apr_dbd_row_t *row, int col);
+  
+    /** error: get current error message (if any)
+     *
+     *  @param handle - the connection
+     *  @param errnum - error code from operation that returned an error
+     *  @return the database current error message, or message for errnum
+     *          (implementation-dependent whether errnum is ignored)
+     */
+    const char *(*error)(apr_dbd_t *handle, int errnum);
+  
+    /** escape: escape a string so it is safe for use in query/select
+     *
+     *  @param pool - pool to alloc the result from
+     *  @param string - the string to escape
+     *  @param handle - the connection
+     *  @return the escaped, safe string
+     */
+    const char *(*escape)(apr_pool_t *pool, const char *string,
+                          apr_dbd_t *handle);
+  
+    /** prepare: prepare a statement
+     *
+     *  @param pool - pool to alloc the result from
+     *  @param handle - the connection
+     *  @param query - the SQL query
+     *  @param label - A label for the prepared statement.
+     *                 use NULL for temporary prepared statements
+     *                 (eg within a Request in httpd)
+     *  @param nargs - number of parameters in the query
+     *  @param nvals - number of values passed in p[b]query/select
+     *  @param types - pointer to an array with types of parameters
+     *  @param statement - statement to prepare.  May point to null on entry.
+     *  @return 0 for success or error code
+     */
+    int (*prepare)(apr_pool_t *pool, apr_dbd_t *handle, const char *query,
+                   const char *label, int nargs, int nvals,
+                   apr_dbd_type_e *types, apr_dbd_prepared_t **statement);
+
+    /** pvquery: query using a prepared statement + args
+     *
+     *  @param pool - working pool
+     *  @param handle - the connection
+     *  @param nrows - number of rows affected.
+     *  @param statement - the prepared statement to execute
+     *  @param args - args to prepared statement
+     *  @return 0 for success or error code
+     */
+    int (*pvquery)(apr_pool_t *pool, apr_dbd_t *handle, int *nrows,
+                   apr_dbd_prepared_t *statement, va_list args);
+
+    /** pvselect: select using a prepared statement + args
+     *
+     *  @param pool - working pool
+     *  @param handle - the connection
+     *  @param res - pointer to query results.  May point to NULL on entry
+     *  @param statement - the prepared statement to execute
+     *  @param random - Whether to support random-access to results
+     *  @param args - args to prepared statement
+     *  @return 0 for success or error code
+     */
+    int (*pvselect)(apr_pool_t *pool, apr_dbd_t *handle,
+                    apr_dbd_results_t **res,
+                    apr_dbd_prepared_t *statement, int random, va_list args);
+
+    /** pquery: query using a prepared statement + args
+     *
+     *  @param pool - working pool
+     *  @param handle - the connection
+     *  @param nrows - number of rows affected.
+     *  @param statement - the prepared statement to execute
+     *  @param args - args to prepared statement
+     *  @return 0 for success or error code
+     */
+    int (*pquery)(apr_pool_t *pool, apr_dbd_t *handle, int *nrows,
+                  apr_dbd_prepared_t *statement, const char **args);
+
+    /** pselect: select using a prepared statement + args
+     *
+     *  @param pool - working pool
+     *  @param handle - the connection
+     *  @param res - pointer to query results.  May point to NULL on entry
+     *  @param statement - the prepared statement to execute
+     *  @param random - Whether to support random-access to results
+     *  @param args - args to prepared statement
+     *  @return 0 for success or error code
+     */
+    int (*pselect)(apr_pool_t *pool, apr_dbd_t *handle,
+                   apr_dbd_results_t **res, apr_dbd_prepared_t *statement,
+                   int random, const char **args);
+
+  
+    /** get_name: get a column title from a result set
+     *
+     *  @param res - result set pointer
+     *  @param col - entry number
+     *  @return param name, or NULL if col is out of bounds.
+     */
+    const char* (*get_name)(const apr_dbd_results_t *res, int col);
+
+    /** transaction_mode_get: get the mode of transaction
+     *
+     *  @param trans - the transaction.
+     *  @return mode of transaction
+     */
+    int (*transaction_mode_get)(apr_dbd_transaction_t *trans);
+
+    /** transaction_mode_set: get the mode of transaction
+     *
+     *  @param trans - the transaction.
+     *  @param mode  - new mode of the transaction
+     *  @return the mode of transaction in force after the call
+     */
+    int (*transaction_mode_set)(apr_dbd_transaction_t *trans, int mode);
+
+    /** format of prepared statement parameters */
+    const char *pformat;
+
+    /** pvbquery: query using a prepared statement + binary args
+     *
+     *  @param pool - working pool
+     *  @param handle - the connection
+     *  @param nrows - number of rows affected.
+     *  @param statement - the prepared statement to execute
+     *  @param args - binary args to prepared statement
+     *  @return 0 for success or error code
+     */
+    int (*pvbquery)(apr_pool_t *pool, apr_dbd_t *handle, int *nrows,
+                    apr_dbd_prepared_t *statement, va_list args);
+
+    /** pvbselect: select using a prepared statement + binary args
+     *
+     *  @param pool - working pool
+     *  @param handle - the connection
+     *  @param res - pointer to query results.  May point to NULL on entry
+     *  @param statement - the prepared statement to execute
+     *  @param random - Whether to support random-access to results
+     *  @param args - binary args to prepared statement
+     *  @return 0 for success or error code
+     */
+    int (*pvbselect)(apr_pool_t *pool, apr_dbd_t *handle,
+                     apr_dbd_results_t **res,
+                     apr_dbd_prepared_t *statement, int random, va_list args);
+
+    /** pbquery: query using a prepared statement + binary args
+     *
+     *  @param pool - working pool
+     *  @param handle - the connection
+     *  @param nrows - number of rows affected.
+     *  @param statement - the prepared statement to execute
+     *  @param args - binary args to prepared statement
+     *  @return 0 for success or error code
+     */
+    int (*pbquery)(apr_pool_t *pool, apr_dbd_t *handle, int *nrows,
+                   apr_dbd_prepared_t *statement,const void **args);
+
+    /** pbselect: select using a prepared statement + binary args
+     *
+     *  @param pool - working pool
+     *  @param handle - the connection
+     *  @param res - pointer to query results.  May point to NULL on entry
+     *  @param statement - the prepared statement to execute
+     *  @param random - Whether to support random-access to results
+     *  @param args - binary args to prepared statement
+     *  @return 0 for success or error code
+     */
+    int (*pbselect)(apr_pool_t *pool, apr_dbd_t *handle,
+                    apr_dbd_results_t **res, apr_dbd_prepared_t *statement,
+                    int random, const void **args);
+  
+    /** datum_get: get a binary entry from a row
+     *
+     *  @param row - row pointer
+     *  @param col - entry number
+     *  @param type - type of data to get
+     *  @param data - pointer to data, allocated by the caller
+     *  @return APR_SUCCESS, an error code on error or if col is out of bounds
+     */
+    apr_status_t (*datum_get)(const apr_dbd_row_t *row, int col,
+                              apr_dbd_type_e type, void *data);
+};
+
+/* Export mutex lock/unlock for drivers that need it 
+ * deprecated; create a per-dbd mutex within the (*init) function
+ * to avoid blocking other providers running on other threads
+ */
+APR_DECLARE(apr_status_t) apr_dbd_mutex_lock(void);
+APR_DECLARE(apr_status_t) apr_dbd_mutex_unlock(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/private/apr_dbd_odbc_v2.h b/include/private/apr_dbd_odbc_v2.h
new file mode 100644
index 00000000000..b8da7b181f9
--- /dev/null
+++ b/include/private/apr_dbd_odbc_v2.h
@@ -0,0 +1,119 @@
+/* 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.
+ */
+
+
+/*  ONLY USED FOR ODBC Version 2   -DODBCV2
+*
+*   Re-define everything to work (more-or-less) in an ODBC V2 environment
+*       Random access to retrieved rows is not supported - i.e. calls to apr_dbd_select() cannot
+*       have a 'random' argument of 1.  apr_dbd_get_row() must always pass rownum as 0 (get next row)
+*
+*/
+
+#define SQLHANDLE SQLHENV /* Presumes that ENV, DBC, and STMT handles are all the same datatype */
+#define SQL_NULL_HANDLE 0
+#define SQL_HANDLE_STMT 1
+#define SQL_HANDLE_DBC  2
+#define SQL_HANDLE_ENV  3
+#define SQL_NO_DATA     SQL_NO_DATA_FOUND
+
+#ifndef SQL_SUCCEEDED
+#define SQL_SUCCEEDED(rc) (((rc)&(~1))==0)
+#endif
+
+#undef SQLSetEnvAttr
+#define SQLSetEnvAttr(henv, Attribute, Value, StringLength)  (0)
+
+#undef SQLAllocHandle
+#define SQLAllocHandle(type, parent, hndl) \
+(     (type == SQL_HANDLE_STMT) ? SQLAllocStmt(parent, hndl) \
+    : (type == SQL_HANDLE_ENV)  ? SQLAllocEnv(hndl) \
+    :                             SQLAllocConnect(parent, hndl)  \
+)
+
+#undef SQLFreeHandle
+#define SQLFreeHandle(type, hndl) \
+(     (type == SQL_HANDLE_STMT) ? SQLFreeStmt(hndl, SQL_DROP) \
+    : (type == SQL_HANDLE_ENV)  ? SQLFreeEnv(hndl) \
+    :                             SQLFreeConnect(hndl)  \
+)
+
+#undef SQLGetDiagRec
+#define SQLGetDiagRec(type, h, i, state, native, buffer, bufsize, reslen) \
+        SQLError(  (type == SQL_HANDLE_ENV) ? h : NULL, \
+                   (type == SQL_HANDLE_DBC) ? h : NULL, \
+                   (type == SQL_HANDLE_STMT) ? h : NULL, \
+                   state, native, buffer, bufsize, reslen)
+
+#undef SQLCloseCursor
+#define SQLCloseCursor(stmt) SQLFreeStmt(stmt, SQL_CLOSE)
+
+#undef SQLGetConnectAttr
+#define SQLGetConnectAttr(hdbc, fOption, ValuePtr, BufferLength, NULL) \
+    SQLGetConnectOption(hdbc, fOption, ValuePtr)
+
+#undef SQLSetConnectAttr
+#define SQLSetConnectAttr(hdbc, fOption, ValuePtr, BufferLength) \
+        SQLSetConnectOption(hdbc, fOption, (SQLUINTEGER) ValuePtr)
+
+#undef SQLSetStmtAttr
+#define SQLSetStmtAttr(hstmt, fOption, ValuePtr, BufferLength) (0); return APR_ENOTIMPL;
+
+#undef SQLEndTran
+#define SQLEndTran(hType, hdbc,type)  SQLTransact(henv, hdbc, type)
+
+#undef SQLFetchScroll
+#define SQLFetchScroll(stmt, orient, rownum) (0); return APR_ENOTIMPL;
+
+#define SQL_DESC_TYPE           SQL_COLUMN_TYPE
+#define SQL_DESC_CONCISE_TYPE   SQL_COLUMN_TYPE
+#define SQL_DESC_DISPLAY_SIZE   SQL_COLUMN_DISPLAY_SIZE
+#define SQL_DESC_OCTET_LENGTH   SQL_COLUMN_LENGTH
+#define SQL_DESC_UNSIGNED       SQL_COLUMN_UNSIGNED
+
+#undef SQLColAttribute
+#define SQLColAttribute(s, c, f, a, l, m, n) SQLColAttributes(s, c, f, a, l, m, n)
+
+#define SQL_ATTR_ACCESS_MODE            SQL_ACCESS_MODE
+#define SQL_ATTR_AUTOCOMMIT             SQL_AUTOCOMMIT
+#define SQL_ATTR_CONNECTION_TIMEOUT     113
+#define SQL_ATTR_CURRENT_CATALOG        SQL_CURRENT_QUALIFIER
+#define SQL_ATTR_DISCONNECT_BEHAVIOR    114
+#define SQL_ATTR_ENLIST_IN_DTC          1207
+#define SQL_ATTR_ENLIST_IN_XA           1208
+
+#define SQL_ATTR_CONNECTION_DEAD        1209
+#define SQL_CD_TRUE                     1L   /* Connection is closed/dead */
+#define SQL_CD_FALSE                    0L   /* Connection is open/available */
+
+#define SQL_ATTR_LOGIN_TIMEOUT          SQL_LOGIN_TIMEOUT
+#define SQL_ATTR_ODBC_CURSORS           SQL_ODBC_CURSORS
+#define SQL_ATTR_PACKET_SIZE            SQL_PACKET_SIZE
+#define SQL_ATTR_QUIET_MODE             SQL_QUIET_MODE
+#define SQL_ATTR_TRACE                  SQL_OPT_TRACE
+#define SQL_ATTR_TRACEFILE              SQL_OPT_TRACEFILE
+#define SQL_ATTR_TRANSLATE_LIB          SQL_TRANSLATE_DLL
+#define SQL_ATTR_TRANSLATE_OPTION       SQL_TRANSLATE_OPTION
+#define SQL_ATTR_TXN_ISOLATION          SQL_TXN_ISOLATION
+
+#define SQL_ATTR_CURSOR_SCROLLABLE -1
+
+#define SQL_C_SBIGINT (SQL_BIGINT+SQL_SIGNED_OFFSET)   /* SIGNED BIGINT */
+#define SQL_C_UBIGINT (SQL_BIGINT+SQL_UNSIGNED_OFFSET) /* UNSIGNED BIGINT */
+
+#define SQL_FALSE           0
+#define SQL_TRUE            1
+
diff --git a/include/private/apr_dbm_private.h b/include/private/apr_dbm_private.h
new file mode 100644
index 00000000000..1844435f20d
--- /dev/null
+++ b/include/private/apr_dbm_private.h
@@ -0,0 +1,121 @@
+/* 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 APR_DBM_PRIVATE_H
+#define APR_DBM_PRIVATE_H
+
+#include "apr.h"
+#include "apr_errno.h"
+#include "apr_pools.h"
+#include "apr_dbm.h"
+#include "apr_file_io.h"
+
+#include "apu.h"
+
+/* ### for now, include the DBM selection; this will go away once we start
+   ### building and linking all of the DBMs at once. */
+#include "apu_select_dbm.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @internal */
+
+/**
+ * Most DBM libraries take a POSIX mode for creating files.  Don't trust
+ * the mode_t type, some platforms may not support it, int is safe.
+ */
+APR_DECLARE(int) apr_posix_perms2mode(apr_fileperms_t perm);
+
+/**
+ * Structure to describe the operations of the DBM
+ */
+typedef struct {
+    /** The name of the DBM Type */
+    const char *name;
+
+    /** Open the DBM */
+    apr_status_t (*open)(apr_dbm_t **pdb, const char *pathname,
+                         apr_int32_t mode, apr_fileperms_t perm,
+                         apr_pool_t *pool);
+
+    /** Close the DBM */
+    void (*close)(apr_dbm_t *dbm);
+
+    /** Fetch a dbm record value by key */
+    apr_status_t (*fetch)(apr_dbm_t *dbm, apr_datum_t key,
+                                   apr_datum_t * pvalue);
+
+    /** Store a dbm record value by key */
+    apr_status_t (*store)(apr_dbm_t *dbm, apr_datum_t key, apr_datum_t value);
+
+    /** Delete a dbm record value by key */
+    apr_status_t (*del)(apr_dbm_t *dbm, apr_datum_t key);
+
+    /** Search for a key within the dbm */
+    int (*exists)(apr_dbm_t *dbm, apr_datum_t key);
+
+    /** Retrieve the first record key from a dbm */
+    apr_status_t (*firstkey)(apr_dbm_t *dbm, apr_datum_t * pkey);
+
+    /** Retrieve the next record key from a dbm */
+    apr_status_t (*nextkey)(apr_dbm_t *dbm, apr_datum_t * pkey);
+
+    /** Proactively toss any memory associated with the apr_datum_t. */
+    void (*freedatum)(apr_dbm_t *dbm, apr_datum_t data);
+
+    /** Get the names that the DBM will use for a given pathname. */
+    void (*getusednames)(apr_pool_t *pool,
+                         const char *pathname,
+                         const char **used1,
+                         const char **used2);
+
+} apr_dbm_type_t;
+
+
+/**
+ * The actual DBM
+ */
+struct apr_dbm_t
+{ 
+    /** Associated pool */
+    apr_pool_t *pool;
+
+    /** pointer to DB Implementation Specific data */
+    void *file;
+
+    /** Current integer error code */
+    int errcode;
+    /** Current string error code */
+    const char *errmsg;
+
+    /** the type of DBM */
+    const apr_dbm_type_t *type;
+};
+
+
+/* Declare all of the DBM provider tables */
+APR_MODULE_DECLARE_DATA extern const apr_dbm_type_t apr_dbm_type_sdbm;
+APR_MODULE_DECLARE_DATA extern const apr_dbm_type_t apr_dbm_type_gdbm;
+APR_MODULE_DECLARE_DATA extern const apr_dbm_type_t apr_dbm_type_ndbm;
+APR_MODULE_DECLARE_DATA extern const apr_dbm_type_t apr_dbm_type_db;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* APR_DBM_PRIVATE_H */
diff --git a/include/private/apr_support.h b/include/private/apr_support.h
new file mode 100644
index 00000000000..90491ec7604
--- /dev/null
+++ b/include/private/apr_support.h
@@ -0,0 +1,77 @@
+/* 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 APR_SUPPORT_H
+#define APR_SUPPORT_H
+
+/**
+ * @file apr_support.h
+ * @brief APR Support functions
+ */
+
+#include "apr.h"
+#include "apr_network_io.h"
+#include "apr_file_io.h"
+#include "apr_private.h"
+
+#if HAVE_VALGRIND
+#include <valgrind.h>
+#include <memcheck.h>
+
+extern int apr_running_on_valgrind;
+
+#define APR_IF_VALGRIND(x)                                      \
+    do { if (apr_running_on_valgrind) { x; } } while (0)
+
+#else
+#define APR_IF_VALGRIND(x)
+#endif /* HAVE_VALGRIND */
+
+#define APR_VALGRIND_NOACCESS(addr_, size_)                     \
+    APR_IF_VALGRIND(VALGRIND_MAKE_MEM_NOACCESS(addr_, size_))
+#define APR_VALGRIND_UNDEFINED(addr_, size_)                    \
+    APR_IF_VALGRIND(VALGRIND_MAKE_MEM_UNDEFINED(addr_, size_))
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup apr_support Internal APR support functions
+ * @ingroup APR 
+ * @{
+ */
+
+/**
+ * Wait for IO to occur or timeout.
+ *
+ * @param f The file to wait on.
+ * @param s The socket to wait on if @a f is @c NULL.
+ * @param for_read If non-zero wait for data to be available to read,
+ *        otherwise wait for data to be able to be written. 
+ * @return APR_TIMEUP if we run out of time.
+ */
+apr_status_t apr_wait_for_io_or_timeout(apr_file_t *f, apr_socket_t *s,
+                                        int for_read);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* ! APR_SUPPORT_H */
diff --git a/include/private/apu_internal.h b/include/private/apu_internal.h
new file mode 100644
index 00000000000..21075c5c4a4
--- /dev/null
+++ b/include/private/apu_internal.h
@@ -0,0 +1,51 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_dso.h"
+#include "apu.h"
+
+#ifndef APU_INTERNAL_H
+#define APU_INTERNAL_H
+
+#if APR_HAVE_MODULAR_DSO
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* For modular dso loading, an internal interlock to allow us to
+ * continue to initialize modules by multiple threads, the caller
+ * of apu_dso_load must lock first, and not unlock until any init
+ * finalization is complete.
+ */
+apr_status_t apu_dso_init(apr_pool_t *pool);
+
+apr_status_t apu_dso_mutex_lock(void);
+apr_status_t apu_dso_mutex_unlock(void);
+
+apr_status_t apu_dso_load(apr_dso_handle_t **dso, apr_dso_handle_sym_t *dsoptr,
+                          const char *module, const char *modsym,
+                          apr_pool_t *pool);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* APR_HAVE_MODULAR_DSO */
+
+#endif /* APU_INTERNAL_H */
+
diff --git a/include/private/apu_select_dbm.h.in b/include/private/apu_select_dbm.h.in
new file mode 100644
index 00000000000..b69aec032cd
--- /dev/null
+++ b/include/private/apu_select_dbm.h.in
@@ -0,0 +1,28 @@
+/* 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 APU_SELECT_DBM_H
+#define APU_SELECT_DBM_H
+
+/*
+** The following macros control what features APRUTIL will use
+*/
+#define APU_USE_SDBM    @apu_use_sdbm@
+#define APU_USE_NDBM    @apu_use_ndbm@
+#define APU_USE_GDBM    @apu_use_gdbm@
+#define APU_USE_DB      @apu_use_db@
+
+#endif	/* !APU_SELECT_DBM_H */
diff --git a/include/private/apu_select_dbm.hw b/include/private/apu_select_dbm.hw
new file mode 100644
index 00000000000..97c7b6c22ba
--- /dev/null
+++ b/include/private/apu_select_dbm.hw
@@ -0,0 +1,28 @@
+/* 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 APU_SELECT_DBM_H
+#define APU_SELECT_DBM_H
+
+/*
+** The following macros control what features APRUTIL will use
+*/
+#define APU_USE_SDBM    1
+#define APU_USE_GDBM    0
+#define APU_USE_NDBM    0
+#define APU_USE_DB      0
+
+#endif	/* !APU_SELECT_DBM_H */
diff --git a/lib/.cvsignore b/lib/.cvsignore
deleted file mode 100644
index f3c7a7c5da6..00000000000
--- a/lib/.cvsignore
+++ /dev/null
@@ -1 +0,0 @@
-Makefile
diff --git a/lib/Makefile.in b/lib/Makefile.in
deleted file mode 100644
index 183a3293264..00000000000
--- a/lib/Makefile.in
+++ /dev/null
@@ -1,101 +0,0 @@
-#CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
-#LIBS=$(EXTRA_LIBS) $(LIBS1)
-#INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
-#LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
-
-CC=@CC@
-RANLIB=@RANLIB@
-AR=@AR@
-RM=@RM@
-CFLAGS=@CFLAGS@ @OPTIM@
-LIBS=@LIBS@
-LDFLAGS=@LDFLAGS@ $(LIBS)
-INCDIR=../include
-INCDIR1=../misc/@OSDIR@
-INCLUDES=-I$(INCDIR) -I$(INCDIR1)
-
-#LIB=@LIBPREFIX@apr.a
-
-OBJS=apr_cpystrn.o \
-	apr_fnmatch.o \
-	apr_execve.o \
-	apr_md5.o \
-	apr_pools.o \
-	apr_signal.o \
-	apr_snprintf.o \
-	apr_tables.o \
-	apr_getpass.o \
-	apr_strnatcmp.o
-
-.c.o:
-	$(CC) $(CFLAGS) -c $(INCLUDES) $<
-
-all: $(OBJS)
-
-clean:
-	$(RM) -f *.o *.a *.so
-
-distclean: clean
-	-$(RM) -f Makefile
-
-$(OBJS): Makefile
-
-#$(LIB): $(OBJS)
-#	$(RM) -f $@
-#	$(AR) cr $@ $(OBJS)
-#	$(RANLIB) $@
-
-#
-# We really don't expect end users to use this rule.  It works only with
-# gcc, and rebuilds Makefile.tmpl.  You have to re-run Configure after
-# using it.
-#
-depend:
-	cp Makefile.in Makefile.in.bak \
-	    && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.in > Makefile.new \
-	    && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \
-	    && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
-	           -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
-		> Makefile.in \
-	    && rm Makefile.new
-
-# DO NOT REMOVE
-apr_cpystrn.o: apr_cpystrn.c $(INCDIR)/apr_private.h \
- $(INCDIR)/apr_lib.h $(INCDIR)/apr_general.h $(INCDIR)/apr.h \
- $(INCDIR)/apr_errno.h $(INCDIR)/apr_file_io.h $(INCDIR)/apr_time.h \
- $(INCDIR)/apr_thread_proc.h
-apr_execve.o: apr_execve.c $(INCDIR)/apr_private.h
-apr_fnmatch.o: apr_fnmatch.c $(INCDIR)/apr_private.h \
- $(INCDIR)/apr_fnmatch.h $(INCDIR)/apr_errno.h $(INCDIR)/apr.h \
- $(INCDIR)/apr_lib.h $(INCDIR)/apr_general.h \
- $(INCDIR)/apr_file_io.h $(INCDIR)/apr_time.h \
- $(INCDIR)/apr_thread_proc.h
-apr_getpass.o: apr_getpass.c $(INCDIR)/apr_private.h \
- $(INCDIR)/apr_lib.h $(INCDIR)/apr_general.h $(INCDIR)/apr.h \
- $(INCDIR)/apr_errno.h $(INCDIR)/apr_file_io.h $(INCDIR)/apr_time.h \
- $(INCDIR)/apr_thread_proc.h
-apr_md5.o: apr_md5.c $(INCDIR)/apr_private.h $(INCDIR)/apr_md5.h \
- $(INCDIR)/apr_lib.h $(INCDIR)/apr_general.h $(INCDIR)/apr.h \
- $(INCDIR)/apr_errno.h $(INCDIR)/apr_file_io.h $(INCDIR)/apr_time.h \
- $(INCDIR)/apr_thread_proc.h
-apr_pools.o: apr_pools.c $(INCDIR)/apr_private.h \
- $(INCDIR)/apr_portable.h $(INCDIR)/apr_general.h $(INCDIR)/apr.h \
- $(INCDIR)/apr_errno.h $(INCDIR)/apr_thread_proc.h \
- $(INCDIR)/apr_file_io.h $(INCDIR)/apr_time.h \
- $(INCDIR)/apr_network_io.h $(INCDIR)/apr_lock.h \
- $(INCDIR)/apr_pools.h $(INCDIR)/apr_lib.h ../misc/unix/misc.h \
- $(INCDIR)/apr_getopt.h
-apr_signal.o: apr_signal.c $(INCDIR)/apr_private.h \
- $(INCDIR)/apr_lib.h $(INCDIR)/apr_general.h $(INCDIR)/apr.h \
- $(INCDIR)/apr_errno.h $(INCDIR)/apr_file_io.h $(INCDIR)/apr_time.h \
- $(INCDIR)/apr_thread_proc.h
-apr_snprintf.o: apr_snprintf.c $(INCDIR)/apr_private.h \
- $(INCDIR)/apr_lib.h $(INCDIR)/apr_general.h $(INCDIR)/apr.h \
- $(INCDIR)/apr_errno.h $(INCDIR)/apr_file_io.h $(INCDIR)/apr_time.h \
- $(INCDIR)/apr_thread_proc.h
-apr_strnatcmp.o: apr_strnatcmp.c $(INCDIR)/apr_strnatcmp.h
-apr_tables.o: apr_tables.c $(INCDIR)/apr_private.h \
- $(INCDIR)/apr_general.h $(INCDIR)/apr.h $(INCDIR)/apr_errno.h \
- $(INCDIR)/apr_pools.h $(INCDIR)/apr_lib.h $(INCDIR)/apr_file_io.h \
- $(INCDIR)/apr_time.h $(INCDIR)/apr_thread_proc.h \
- ../misc/unix/misc.h $(INCDIR)/apr_getopt.h
diff --git a/lib/apr_cpystrn.c b/lib/apr_cpystrn.c
deleted file mode 100644
index 7dbb615a9ae..00000000000
--- a/lib/apr_cpystrn.c
+++ /dev/null
@@ -1,241 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "apr_private.h"
-#include "apr_lib.h"
-
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#if HAVE_STRING_H
-#include <string.h>
-#endif
-#if HAVE_CTYPE_H
-#include <ctype.h>
-#endif
-
-/*
- * Apache's "replacement" for the strncpy() function. We roll our
- * own to implement these specific changes:
- *   (1) strncpy() doesn't always null terminate and we want it to.
- *   (2) strncpy() null fills, which is bogus, esp. when copy 8byte
- *       strings into 8k blocks.
- *   (3) Instead of returning the pointer to the beginning of
- *       the destination string, we return a pointer to the
- *       terminating '\0' to allow us to "check" for truncation
- *
- * ap_cpystrn() follows the same call structure as strncpy().
- */
-
-API_EXPORT(char *) ap_cpystrn(char *dst, const char *src, size_t dst_size)
-{
-
-    char *d, *end;
-
-    if (dst_size == 0) {
-        return (dst);
-    }
-
-    d = dst;
-    end = dst + dst_size - 1;
-
-    for (; d < end; ++d, ++src) {
-	if (!(*d = *src)) {
-	    return (d);
-	}
-    }
-
-    *d = '\0';	/* always null terminate */
-
-    return (d);
-}
-
-
-/*
- * This function provides a way to parse a generic argument string
- * into a standard argv[] form of argument list. It respects the 
- * usual "whitespace" and quoteing rules. In the future this could
- * be expanded to include support for the ap_call_exec command line
- * string processing (including converting '+' to ' ' and doing the 
- * url processing. It does not currently support this function.
- *
- *    token_context: Context from which pool allocations will occur.
- *    arg_str:       Input argument string for conversion to argv[].
- *    argv_out:      Output location. This is a pointer to an array
- *                   of pointers to strings (ie. &(char *argv[]).
- *                   This value will be allocated from the contexts
- *                   pool and filled in with copies of the tokens
- *                   found during parsing of the arg_str. 
- */
-API_EXPORT(ap_status_t) ap_tokenize_to_argv(char *arg_str, char ***argv_out,
-                                            ap_pool_t *token_context)
-{
-    char *cp, *tmpCnt;
-    int isquoted, numargs = 0, rc = APR_SUCCESS;
-
-#define SKIP_WHITESPACE(cp) \
-    for ( ; *cp == ' ' || *cp == '\t'; ) { \
-        cp++; \
-    };
-
-#define CHECK_QUOTATION(cp,isquoted) \
-    isquoted = 0; \
-    if (*cp == '"') { \
-        isquoted = 1; \
-        cp++; \
-    }
-
-/* DETERMINE_NEXTSTRING:
- * At exit, cp will point to one of the following:  NULL, SPACE, TAB or QUOTE.
- * NULL implies the argument string has been fully traversed.
- */
-#define DETERMINE_NEXTSTRING(cp,isquoted) \
-    for ( ; *cp != '\0'; cp++) { \
-        if (   (isquoted    && (*cp     == ' ' || *cp     == '\t')) \
-            || (*cp == '\\' && (*(cp+1) == ' ' || *(cp+1) == '\t'))) { \
-            cp++; \
-            continue; \
-        } \
-        if (   (!isquoted && (*cp == ' ' || *cp == '\t')) \
-            || (isquoted  && *cp == '"')                  ) { \
-            break; \
-        } \
-    }
-
-    cp = arg_str;
-    SKIP_WHITESPACE(cp);
-    tmpCnt = cp;
-
-    /* This is ugly and expensive, but if anyone wants to figure a
-     * way to support any number of args without counting and 
-     * allocating, please go ahead and change the code.
-     */
-    while (*tmpCnt != '\0') {
-        CHECK_QUOTATION(tmpCnt, isquoted);
-        DETERMINE_NEXTSTRING(tmpCnt, isquoted);
-        numargs++;
-        SKIP_WHITESPACE(tmpCnt);
-    }
-
-    *argv_out = ap_palloc(token_context, numargs*sizeof(char*));
-    if (*argv_out == NULL) {
-        return (APR_ENOMEM);
-    }
-
-    /*  determine first argument */
-    numargs = 0;
-    while (*cp != '\0') {
-        CHECK_QUOTATION(cp, isquoted);
-        tmpCnt = cp;
-        DETERMINE_NEXTSTRING(cp, isquoted);
-        if (*cp == '\0') {
-            (*argv_out)[numargs] = ap_pstrdup(token_context, tmpCnt);
-            numargs++;
-            (*argv_out)[numargs] = '\0';
-            break;
-        }
-        else {
-            *cp++ = '\0';
-            (*argv_out)[numargs] = ap_pstrdup(token_context, tmpCnt);
-            numargs++;
-        }
-        
-        SKIP_WHITESPACE(cp);
-    }
-
-    return(rc);
-}
-
-/* Filename_of_pathname returns the final element of the pathname.
- * Using the current platform's filename syntax.
- *   "/foo/bar/gum" -> "gum"
- *   "/foo/bar/gum/" -> ""
- *   "gum" -> "gum"
- *   "wi\\n32\\stuff" -> "stuff
- *
- * Corrected Win32 to accept "a/b\\stuff", "a:stuff"
- */
-
-const char *ap_filename_of_pathname(const char *pathname)
-{
-    const char path_separator = '/';
-    const char *s = strrchr(pathname, path_separator);
-
-#ifdef WIN32
-    const char path_separator_win = '\\';
-    const char drive_separator_win = ':';
-    const char *s2 = strrchr(pathname, path_separator_win);
-
-    if (s2 > s) s = s2;
-
-    if (!s) s = strrchr(pathname, drive_separator_win);
-#endif
-
-    return s ? ++s : pathname;
-}
-
-/* length of dest assumed >= length of src
- * collapse in place (src == dest) is legal.
- * returns terminating null ptr to dest string.
- */
-API_EXPORT(char *) ap_collapse_spaces(char *dest, const char *src)
-{
-    while (*src) {
-        if (!ap_isspace(*src)) 
-            *dest++ = *src;
-        ++src;
-    }
-    *dest = 0;
-    return (dest);
-}
diff --git a/lib/apr_execve.c b/lib/apr_execve.c
deleted file mode 100644
index d972a182148..00000000000
--- a/lib/apr_execve.c
+++ /dev/null
@@ -1,386 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-/*
- * Portions of this code are under this license:
- *
- * Copyright (c) 1980, 1991 The Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#ifndef WIN32
-#include "apr_private.h"
-#endif
-/*---------------------------------------------------------------*/
-
-#ifdef NEED_HASHBANG_EMUL
-
-#undef execle
-#undef execve
-
-static const char **hashbang(const char *filename, char * const *argv);
-
-
-/* Historically, a list of arguments on the stack was often treated as
- * being equivalent to an array (since they already were "contiguous"
- * on the stack, and the arguments were pushed in the correct order).
- * On today's processors, this is not necessarily equivalent, because
- * often arguments are padded or passed partially in registers,
- * or the stack direction is backwards.
- * To be on the safe side, we copy the argument list to our own
- * local argv[] array. The va_arg logic makes sure we do the right thing.
- * XXX: malloc() is used because we expect to be overlaid soon.
- */
-APR_EXPORT_NONSTD(ap_status_t) ap_execle(const char *filename, 
-                                         const char *argv0, ...)
-{
-    va_list adummy;
-    char **envp;
-    char **argv;
-    int argc, ret;
-
-    /* First pass: Count arguments on stack */
-    va_start(adummy, argv0);
-    for (argc = 1; va_arg(adummy, char *) != NULL; ++argc) {
-	continue;
-    }
-    va_end(adummy);
-
-    if ((argv = (char **) malloc((argc + 2) * sizeof(*argv))) == NULL) {
-	return APR_ENOMEM;
-    }
-
-    /* Pass two --- copy the argument strings into the result space */
-    va_start(adummy, argv0);
-    argv[0] = (char *)argv0;
-    for (argc = 1; (argv[argc] = va_arg(adummy, char *)) != NULL; ++argc) {
-	continue;
-    }
-    envp = va_arg(adummy, char **);
-    va_end(adummy);
-
-    ap_execve(filename, argv, envp);
-    ret = errno;
-    free(argv);
-
-    return ret;
-}
-
-/* Count number of entries in vector "args", including the trailing NULL entry
- */
-static int
-count_args(char * const *args)
-{
-    int i;
-    for (i = 0; args[i] != NULL; ++i) {
-	continue;
-    }
-    return i+1;
-}
-
-/* Emulate the execve call, respecting a #!/interpreter line if present.
- * On "real" unixes, the kernel does this.
- * We have to fiddle with the argv array to make it work on platforms
- * which don't support the "hashbang" interpreter line by default.
- */
-APR_EXPORT(ap_status_t) ap_execve(const char *filename, char * const argv[],
-                                  char * const envp[])
-{
-    char **script_argv;
-    extern char **environ;
-
-    if (envp == NULL) {
-	envp = (char * const *) environ;
-    }
-
-    /* Try to execute the file directly first: */
-    execve(filename, argv, envp);
-
-    /* Still with us? Then something went seriously wrong.
-     * From the (linux) man page:
-     * EACCES The file is not a regular file.
-     * EACCES Execute permission is denied for the file.
-     * EACCES Search  permission  is denied on a component of the path prefix.
-     * EPERM  The file system is mounted noexec.
-     * EPERM  The file system is mounted nosuid and the file  has an SUID
-     *        or SGID bit set.
-     * E2BIG  The argument list is too big.
-     * ENOEXEC The magic number in the file is incorrect.
-     * EFAULT filename  points  outside  your  accessible address space.
-     * ENAMETOOLONG filename is too long.
-     * ENOENT The file does not exist.
-     * ENOMEM Insufficient kernel memory was available.
-     * ENOTDIR A component of the path prefix is not a  directory.
-     * ELOOP  filename contains a circular reference (i.e., via a symbolic link)
-     */
-
-    if (errno == ENOEXEC) {
-	/* Probably a script.
-	 * Have a look; if there's a "#!" header then try to emulate
-	 * the feature found in all modern OS's:
-	 * Interpret the line following the #! as a command line
-	 * in shell style.
-	 */
-	if ((script_argv = (char **)hashbang(filename, argv)) != NULL) {
-
-	    /* new filename is the interpreter to call */
-	    filename = script_argv[0];
-
-	    /* Restore argv[0] as on entry */
-	    if (argv[0] != NULL) {
-		script_argv[0] = argv[0];
-	    }
-
-	    execve(filename, script_argv, envp);
-
-	    free(script_argv);
-	}
-	/*
-	 * Script doesn't start with a hashbang line!
-	 * So, try to have the default shell execute it.
-	 * For this, the size of argv must be increased by one
-	 * entry: the shell's name. The remaining args are appended.
-	 */
-	else {
-	    int i = count_args(argv) + 1;   /* +1 for leading SHELL_PATH */
-
-	    if ((script_argv = malloc(sizeof(*script_argv) * i)) == NULL) {
-		return APR_ENOMEM;
-	    }
-
-	    script_argv[0] = SHELL_PATH;
-
-	    while (i > 0) {
-		script_argv[i] = argv[i-1];
-		--i;
-	    }
-
-	    execve(SHELL_PATH, script_argv, envp);
-
-	    free(script_argv);
-	}
-    }
-    return errno;
-}
-
-/*---------------------------------------------------------------*/
-
-/*
- * From: peter@zeus.dialix.oz.au (Peter Wemm)
- * (taken from tcsh)
- * If exec() fails look first for a #! [word] [word] ....
- * If it is, splice the header into the argument list and retry.
- * Return value: the original argv array (sans argv[0]), with the
- * script's argument list prepended.
- * XXX: malloc() is used so that everything can be free()ed after a failure.
- */
-#define HACKBUFSZ 1024		/* Max chars in #! vector */
-#define HACKVECSZ 128		/* Max words in #! vector */
-static const char **hashbang(const char *filename, char * const *argv)
-{
-    char lbuf[HACKBUFSZ];
-    char *sargv[HACKVECSZ];
-    const char **newargv;
-    char *p, *ws;
-    int fd;
-    int sargc = 0;
-    int i, j;
-#ifdef WIN32
-    int fw = 0;			/* found at least one word */
-    int first_word = 0;
-#endif /* WIN32 */
-
-    if ((fd = open(filename, O_RDONLY)) == -1) {
-	return NULL;
-    }
-
-    if (read(fd, (char *) lbuf, 2) != 2
-	|| lbuf[0] != '#' || lbuf[1] != '!'
-	|| read(fd, (char *) lbuf, HACKBUFSZ) <= 0) {
-	close(fd);
-	return NULL;
-    }
-
-    close(fd);
-
-    ws = NULL;			/* word started = 0 */
-
-    for (p = lbuf; p < &lbuf[HACKBUFSZ];) {
-	switch (*p) {
-	case ' ':
-	case '\t':
-#ifdef NEW_CRLF
-	case '\r':
-#endif /*NEW_CRLF */
-	    if (ws) {		/* a blank after a word.. save it */
-		*p = '\0';
-#ifndef WIN32
-		if (sargc < HACKVECSZ - 1) {
-		    sargv[sargc++] = ws;
-		}
-		ws = NULL;
-#else /* WIN32 */
-		if (sargc < HACKVECSZ - 1) {
-		    sargv[sargc] = first_word ? NULL : hb_subst(ws);
-		    if (sargv[sargc] == NULL) {
-			sargv[sargc] = ws;
-		    }
-		    sargc++;
-		}
-		ws = NULL;
-		fw = 1;
-		first_word = 1;
-#endif /* WIN32 */
-	    }
-	    p++;
-	    continue;
-
-	case '\0':		/* Whoa!! what the hell happened */
-	    return NULL;
-
-	case '\n':		/* The end of the line. */
-	    if (
-#ifdef WIN32
-		   fw ||
-#endif /* WIN32 */
-		   ws) {	/* terminate the last word */
-		*p = '\0';
-#ifndef WIN32
-		if (sargc < HACKVECSZ - 1) {
-		    sargv[sargc++] = ws;
-		}
-#else /* WIN32 */
-		if (sargc < HACKVECSZ - 1) {	/* deal with the 1-word case */
-		    sargv[sargc] = first_word ? NULL : hb_subst(ws);
-		    if (sargv[sargc] == NULL) {
-			sargv[sargc] = ws;
-		    }
-		    sargc++;
-		}
-#endif /* !WIN32 */
-		sargv[sargc] = NULL;
-	    }
-	    /* Count number of entries in the old argv vector */
-	    for (i = 0; argv[i] != NULL; ++i) {
-		continue;
-	    }
-	    ++i;
-
-	    newargv = (const char **) malloc((p - lbuf + 1)
-                      + (i + sargc + 1) * sizeof(*newargv));
-	    if (newargv == NULL) {
-		return NULL;
-	    }
-	    ws = &((char *) newargv)[(i + sargc + 1) * sizeof(*newargv)];
-
-	    /* Copy entries to allocated memory */
-	    for (j = 0; j < sargc; ++j) {
-		newargv[j] = strcpy(ws, sargv[j]);
-		ws += strlen(ws) + 1;	/* skip trailing '\0' */
-	    }
-	    newargv[sargc] = filename;
-
-	    /* Append the old array. The old argv[0] is skipped. */
-	    if (i > 1) {
-		memcpy(&newargv[sargc + 1], &argv[1],
-                       (i - 1) * sizeof(*newargv));
-	    }
-	
-	    newargv[sargc + i] = NULL;
-
-	    ws = NULL;
-
-	    return newargv;
-
-	default:
-	    if (!ws) {		/* Start a new word? */
-		ws = p;
-	    }
-	    p++;
-	    break;
-	}
-    }
-    return NULL;
-}
-#else
-extern void ap_execve_is_not_here(void);
-void ap_execve_is_not_here(void) {}
-#endif /* NEED_HASHBANG_EMUL */
diff --git a/lib/apr_fnmatch.c b/lib/apr_fnmatch.c
deleted file mode 100644
index 9936917b53f..00000000000
--- a/lib/apr_fnmatch.c
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * Copyright (c) 1989, 1993, 1994
- *      The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Guido van Rossum.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by the University of
- *      California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)fnmatch.c	8.2 (Berkeley) 4/16/94";
-#endif /* LIBC_SCCS and not lint */
-
-/*
- * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6.
- * Compares a filename or pathname to a pattern.
- */
-#ifndef WIN32
-#include "apr_private.h"
-#endif
-#include "apr_fnmatch.h"
-#include "apr_lib.h"
-#include <string.h>
-#ifdef HAVE_CTYPE_H
-# include <ctype.h>
-#endif
-
-#define	EOS	'\0'
-
-static const char *rangematch(const char *, int, int);
-
-API_EXPORT(ap_status_t) ap_fnmatch(const char *pattern, const char *string, int flags)
-{
-    const char *stringstart;
-    char c, test;
-
-    for (stringstart = string;;) {
-	switch (c = *pattern++) {
-	case EOS:
-	    return (*string == EOS ? APR_SUCCESS : FNM_NOMATCH);
-	case '?':
-	    if (*string == EOS) {
-		return (FNM_NOMATCH);
-	    }
-	    if (*string == '/' && (flags & FNM_PATHNAME)) {
-		return (FNM_NOMATCH);
-	    }
-	    if (*string == '.' && (flags & FNM_PERIOD) &&
-		(string == stringstart ||
-		 ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) {
-		return (FNM_NOMATCH);
-	    }
-	    ++string;
-	    break;
-	case '*':
-	    c = *pattern;
-	    /* Collapse multiple stars. */
-	    while (c == '*') {
-		c = *++pattern;
-	    }
-
-	    if (*string == '.' && (flags & FNM_PERIOD) &&
-		(string == stringstart ||
-		 ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) {
-		return (FNM_NOMATCH);
-	    }
-
-	    /* Optimize for pattern with * at end or before /. */
-	    if (c == EOS) {
-		if (flags & FNM_PATHNAME) {
-		    return (strchr(string, '/') == NULL ? APR_SUCCESS : FNM_NOMATCH);
-		}
-		else {
-		    return (APR_SUCCESS);
-		}
-	    }
-	    else if (c == '/' && flags & FNM_PATHNAME) {
-	        if ((string = strchr(string, '/')) == NULL) {
-		    return (FNM_NOMATCH);
-		}
-		break;
-	    }
-
-	    /* General case, use recursion. */
-	    while ((test = *string) != EOS) {
-	        if (!ap_fnmatch(pattern, string, flags & ~FNM_PERIOD)) {
-		    return (APR_SUCCESS);
-		}
-		if (test == '/' && flags & FNM_PATHNAME) {
-		    break;
-		}
-		++string;
-	    }
-	    return (FNM_NOMATCH);
-	case '[':
-	    if (*string == EOS) {
-		return (FNM_NOMATCH);
-	    }
-	    if (*string == '/' && flags & FNM_PATHNAME) {
-		return (FNM_NOMATCH);
-	    }
-	    if (*string == '.' && (flags & FNM_PERIOD) &&
-		(string == stringstart ||
-		 ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) {
-	        return (FNM_NOMATCH);
-	    }
-	    if ((pattern = rangematch(pattern, *string, flags)) == NULL) {
-		return (FNM_NOMATCH);
-	    }
-	    ++string;
-	    break;
-	case '\\':
-	    if (!(flags & FNM_NOESCAPE)) {
-		if ((c = *pattern++) == EOS) {
-		    c = '\\';
-		    --pattern;
-		}
-	    }
-	    /* FALLTHROUGH */
-	default:
-	    if (flags & FNM_CASE_BLIND) {
-	        if (ap_tolower(c) != ap_tolower(*string)) {
-		    return (FNM_NOMATCH);
-		}
-	    }
-	    else if (c != *string) {
-	        return (FNM_NOMATCH);
-	    }
-	    string++;
-	    break;
-	}
-    /* NOTREACHED */
-    }
-}
-
-static const char *rangematch(const char *pattern, int test, int flags)
-{
-    int negate, ok;
-    char c, c2;
-
-    /*
-     * A bracket expression starting with an unquoted circumflex
-     * character produces unspecified results (IEEE 1003.2-1992,
-     * 3.13.2).  This implementation treats it like '!', for
-     * consistency with the regular expression syntax.
-     * J.T. Conklin (conklin@ngai.kaleida.com)
-     */
-    if ((negate = (*pattern == '!' || *pattern == '^'))) {
-	++pattern;
-    }
-
-    for (ok = 0; (c = *pattern++) != ']';) {
-        if (c == '\\' && !(flags & FNM_NOESCAPE)) {
-	    c = *pattern++;
-	}
-	if (c == EOS) {
-	    return (NULL);
-	}
-	if (*pattern == '-' && (c2 = *(pattern + 1)) != EOS && c2 != ']') {
-	    pattern += 2;
-	    if (c2 == '\\' && !(flags & FNM_NOESCAPE)) {
-		c2 = *pattern++;
-	    }
-	    if (c2 == EOS) {
-		return (NULL);
-	    }
-	    if ((c <= test && test <= c2)
-		|| ((flags & FNM_CASE_BLIND)
-		    && ((ap_tolower(c) <= ap_tolower(test))
-			&& (ap_tolower(test) <= ap_tolower(c2))))) {
-		ok = 1;
-	    }
-	}
-	else if ((c == test)
-		 || ((flags & FNM_CASE_BLIND)
-		     && (ap_tolower(c) == ap_tolower(test)))) {
-	    ok = 1;
-	}
-    }
-    return (ok == negate ? NULL : pattern);
-}
-
-
-/* This function is an Apache addition */
-/* return non-zero if pattern has any glob chars in it */
-API_EXPORT(int) ap_is_fnmatch(const char *pattern)
-{
-    int nesting;
-
-    nesting = 0;
-    while (*pattern) {
-	switch (*pattern) {
-	case '?':
-	case '*':
-	    return 1;
-
-	case '\\':
-	    if (*pattern++ == '\0') {
-		return 0;
-	    }
-	    break;
-
-	case '[':	/* '[' is only a glob if it has a matching ']' */
-	    ++nesting;
-	    break;
-
-	case ']':
-	    if (nesting) {
-		return 1;
-	    }
-	    break;
-	}
-	++pattern;
-    }
-    return 0;
-}
diff --git a/lib/apr_getpass.c b/lib/apr_getpass.c
deleted file mode 100644
index 1eaf30346ad..00000000000
--- a/lib/apr_getpass.c
+++ /dev/null
@@ -1,216 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-/* ap_getpass.c: abstraction to provide for obtaining a password from the
- * command line in whatever way the OS supports.  In the best case, it's a
- * wrapper for the system library's getpass() routine; otherwise, we
- * use one we define ourselves.
- */
-#include "apr_private.h"
-#include "apr_lib.h"
-#include "apr_errno.h"
-#include <sys/types.h>
-#include <errno.h>
-
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_CONIO_H
-#include <conio.h>
-#endif
-
-#if defined(HAVE_TERMIOS_H) && !defined(HAVE_GETPASS)
-#include <termios.h>
-#endif
-
-#ifndef CHARSET_EBCDIC
-#define LF 10
-#define CR 13
-#else /* CHARSET_EBCDIC */
-#define LF '\n'
-#define CR '\r'
-#endif /* CHARSET_EBCDIC */
-
-#define MAX_STRING_LEN 256
-
-#define ERR_OVERFLOW 5
-
-#ifndef HAVE_GETPASS
-
-/* MPE, Win32 and BeOS all lack a native getpass() */
-
-#if !defined(HAVE_TERMIOS_H) && !defined(WIN32)
-/*
- * MPE lacks getpass() and a way to suppress stdin echo.  So for now, just
- * issue the prompt and read the results with echo.  (Ugh).
- */
-
-static char *getpass(const char *prompt)
-{
-    static char password[MAX_STRING_LEN];
-
-    fputs(prompt, stderr);
-    gets((char *) &password);
-
-    if (strlen((char *) &password) > (MAX_STRING_LEN - 1)) {
-	password[MAX_STRING_LEN - 1] = '\0';
-    }
-
-    return (char *) &password;
-}
-
-#elif defined (HAVE_TERMIOS_H)
-static char *getpass(const char *prompt)
-{
-    struct termios attr;
-    static char password[MAX_STRING_LEN];
-    int n=0;
-    fputs(prompt, stderr);
-    fflush(stderr);
-	
-    if (tcgetattr(STDIN_FILENO, &attr) != 0)
-        return NULL;
-	attr.c_lflag &= ~(ECHO);
-    
-	if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &attr) != 0)
-		return NULL;
-    while ((password[n] = getchar()) != '\n') {
-        if (password[n] >= ' ' && password[n] <= '~') {
-            n++;
-        } else {
-            fprintf(stderr,"\n");
-            fputs(prompt, stderr);
-            fflush(stderr);
-            n = 0;
-        }
-    }
- 
-    password[n] = '\0';
-    printf("\n");
-    if (n > (MAX_STRING_LEN - 1)) {
-        password[MAX_STRING_LEN - 1] = '\0';
-    }
-
-    attr.c_lflag |= ECHO;
-    tcsetattr(STDIN_FILENO, TCSANOW, &attr);
-    return (char*) &password;
-}
-
-#else
-
-/*
- * Windows lacks getpass().  So we'll re-implement it here.
- */
-
-static char *getpass(const char *prompt)
-{
-    static char password[MAX_STRING_LEN];
-    int n = 0;
-
-    fputs(prompt, stderr);
-    
-    while ((password[n] = _getch()) != '\r') {
-        if (password[n] >= ' ' && password[n] <= '~') {
-            n++;
-            printf("*");
-        }
-	else {
-            printf("\n");
-            fputs(prompt, stderr);
-            n = 0;
-        }
-    }
- 
-    password[n] = '\0';
-    printf("\n");
-
-    if (n > (MAX_STRING_LEN - 1)) {
-        password[MAX_STRING_LEN - 1] = '\0';
-    }
-
-    return (char *) &password;
-}
-
-#endif /* no getchar or _getch */
-
-#endif /* no getpass */
-
-/*
- * Use the OS getpass() routine (or our own) to obtain a password from
- * the input stream.
- *
- * Exit values:
- *  0: Success
- *  5: Partial success; entered text truncated to the size of the
- *     destination buffer
- *
- * Restrictions: Truncation also occurs according to the host system's
- * getpass() semantics, or at position 255 if our own version is used,
- * but the caller is *not* made aware of it.
- */
-
-API_EXPORT(ap_status_t) ap_getpass(const char *prompt, char *pwbuf, size_t *bufsiz)
-{
-    char *pw_got = NULL;
-    int result = 0;
-
-    pw_got = getpass(prompt);
-    if (strlen(pw_got) > (*bufsiz - 1)) {
-	*bufsiz = ERR_OVERFLOW;
-        return APR_ENAMETOOLONG;
-    }
-    ap_cpystrn(pwbuf, pw_got, *bufsiz);
-    *bufsiz = result;
-    return APR_SUCCESS; 
-}
diff --git a/lib/apr_md5.c b/lib/apr_md5.c
deleted file mode 100644
index 6db49eda742..00000000000
--- a/lib/apr_md5.c
+++ /dev/null
@@ -1,620 +0,0 @@
-/*
- * This is work is derived from material Copyright RSA Data Security, Inc.
- *
- * The RSA copyright statement and Licence for that original material is
- * included below. This is followed by the Apache copyright statement and
- * licence for the modifications made to that material.
- */
-
-/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
- */
-
-/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
-   rights reserved.
-
-   License to copy and use this software is granted provided that it
-   is identified as the "RSA Data Security, Inc. MD5 Message-Digest
-   Algorithm" in all material mentioning or referencing this software
-   or this function.
-
-   License is also granted to make and use derivative works provided
-   that such works are identified as "derived from the RSA Data
-   Security, Inc. MD5 Message-Digest Algorithm" in all material
-   mentioning or referencing the derived work.
-
-   RSA Data Security, Inc. makes no representations concerning either
-   the merchantability of this software or the suitability of this
-   software for any particular purpose. It is provided "as is"
-   without express or implied warranty of any kind.
-
-   These notices must be retained in any copies of any part of this
-   documentation and/or software.
- */
-
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-/*
- * The ap_MD5Encode() routine uses much code obtained from the FreeBSD 3.0
- * MD5 crypt() function, which is licenced as follows:
- * ----------------------------------------------------------------------------
- * "THE BEER-WARE LICENSE" (Revision 42):
- * <phk@login.dknet.dk> wrote this file.  As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
- * ----------------------------------------------------------------------------
- */
-#ifndef WIN32
-#include "apr_private.h"
-#endif
-#include "apr_md5.h"
-#include "apr_lib.h"
-
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_CRYPT_H
-#include <crypt.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-/* Constants for MD5Transform routine.
- */
-
-#define S11 7
-#define S12 12
-#define S13 17
-#define S14 22
-#define S21 5
-#define S22 9
-#define S23 14
-#define S24 20
-#define S31 4
-#define S32 11
-#define S33 16
-#define S34 23
-#define S41 6
-#define S42 10
-#define S43 15
-#define S44 21
-
-static void MD5Transform(UINT4 state[4], const unsigned char block[64]);
-static void Encode(unsigned char *output, const UINT4 *input,
-		   unsigned int len);
-static void Decode(UINT4 *output, const unsigned char *input,
-		   unsigned int len);
-
-static unsigned char PADDING[64] =
-{
-    0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-/* F, G, H and I are basic MD5 functions.
- */
-#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
-#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
-#define H(x, y, z) ((x) ^ (y) ^ (z))
-#define I(x, y, z) ((y) ^ ((x) | (~z)))
-
-/* ROTATE_LEFT rotates x left n bits.
- */
-#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
-
-/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
-   Rotation is separate from addition to prevent recomputation.
- */
-#define FF(a, b, c, d, x, s, ac) { \
- (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
- (a) = ROTATE_LEFT ((a), (s)); \
- (a) += (b); \
-  }
-#define GG(a, b, c, d, x, s, ac) { \
- (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
- (a) = ROTATE_LEFT ((a), (s)); \
- (a) += (b); \
-  }
-#define HH(a, b, c, d, x, s, ac) { \
- (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
- (a) = ROTATE_LEFT ((a), (s)); \
- (a) += (b); \
-  }
-#define II(a, b, c, d, x, s, ac) { \
- (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
- (a) = ROTATE_LEFT ((a), (s)); \
- (a) += (b); \
-  }
-
-/* MD5 initialization. Begins an MD5 operation, writing a new context.
- */
-API_EXPORT(ap_status_t) ap_MD5Init(ap_md5_ctx_t *context)
-{
-    context->count[0] = context->count[1] = 0;
-    /* Load magic initialization constants. */
-    context->state[0] = 0x67452301;
-    context->state[1] = 0xefcdab89;
-    context->state[2] = 0x98badcfe;
-    context->state[3] = 0x10325476;
-    return APR_SUCCESS;
-}
-
-/* MD5 block update operation. Continues an MD5 message-digest
-   operation, processing another message block, and updating the
-   context.
- */
-API_EXPORT(ap_status_t) ap_MD5Update(ap_md5_ctx_t *context,
-                                     const unsigned char *input,
-                                     unsigned int inputLen)
-{
-    unsigned int i, idx, partLen;
-
-    /* Compute number of bytes mod 64 */
-    idx = (unsigned int) ((context->count[0] >> 3) & 0x3F);
-
-    /* Update number of bits */
-    if ((context->count[0] += ((UINT4) inputLen << 3)) < ((UINT4) inputLen << 3))
-	context->count[1]++;
-    context->count[1] += (UINT4) inputLen >> 29;
-
-    partLen = 64 - idx;
-
-    /* Transform as many times as possible. */
-#ifndef CHARSET_EBCDIC
-    if (inputLen >= partLen) {
-	memcpy(&context->buffer[idx], input, partLen);
-	MD5Transform(context->state, context->buffer);
-
-	for (i = partLen; i + 63 < inputLen; i += 64)
-	    MD5Transform(context->state, &input[i]);
-
-	idx = 0;
-    }
-    else
-	i = 0;
-
-    /* Buffer remaining input */
-    memcpy(&context->buffer[idx], &input[i], inputLen - i);
-#else /*CHARSET_EBCDIC*/
-    if (inputLen >= partLen) {
-	ebcdic2ascii_strictly(&context->buffer[idx], input, partLen);
-	MD5Transform(context->state, context->buffer);
-
-	for (i = partLen; i + 63 < inputLen; i += 64) {
-	    unsigned char inp_tmp[64];
-	    ebcdic2ascii_strictly(inp_tmp, &input[i], 64);
-	    MD5Transform(context->state, inp_tmp);
-	}
-
-	idx = 0;
-    }
-    else
-	i = 0;
-
-    /* Buffer remaining input */
-    ebcdic2ascii_strictly(&context->buffer[idx], &input[i], inputLen - i);
-#endif /*CHARSET_EBCDIC*/
-    return APR_SUCCESS;
-}
-
-/* MD5 finalization. Ends an MD5 message-digest operation, writing the
-   the message digest and zeroizing the context.
- */
-API_EXPORT(ap_status_t) ap_MD5Final(unsigned char digest[MD5_DIGESTSIZE],
-                                    ap_md5_ctx_t *context)
-{
-    unsigned char bits[8];
-    unsigned int idx, padLen;
-
-
-    /* Save number of bits */
-    Encode(bits, context->count, 8);
-
-#ifdef CHARSET_EBCDIC
-    /* XXX: @@@: In order to make this no more complex than necessary,
-     * this kludge converts the bits[] array using the ascii-to-ebcdic
-     * table, because the following ap_MD5Update() re-translates
-     * its input (ebcdic-to-ascii).
-     * Otherwise, we would have to pass a "conversion" flag to ap_MD5Update()
-     */
-    ascii2ebcdic(bits,bits,8);
-
-    /* Since everything is converted to ascii within ap_MD5Update(), 
-     * the initial 0x80 (PADDING[0]) must be stored as 0x20 
-     */
-    PADDING[0] = os_toebcdic[0x80];
-#endif /*CHARSET_EBCDIC*/
-
-    /* Pad out to 56 mod 64. */
-    idx = (unsigned int) ((context->count[0] >> 3) & 0x3f);
-    padLen = (idx < 56) ? (56 - idx) : (120 - idx);
-    ap_MD5Update(context, PADDING, padLen);
-
-    /* Append length (before padding) */
-    ap_MD5Update(context, bits, 8);
-
-    /* Store state in digest */
-    Encode(digest, context->state, MD5_DIGESTSIZE);
-
-    /* Zeroize sensitive information. */
-    memset(context, 0, sizeof(*context));
-    
-    return APR_SUCCESS;
-}
-
-/* MD5 basic transformation. Transforms state based on block. */
-static void MD5Transform(UINT4 state[4], const unsigned char block[64])
-{
-    UINT4 a = state[0], b = state[1], c = state[2], d = state[3],
-          x[MD5_DIGESTSIZE];
-
-    Decode(x, block, 64);
-
-    /* Round 1 */
-    FF(a, b, c, d, x[0], S11, 0xd76aa478);	/* 1 */
-    FF(d, a, b, c, x[1], S12, 0xe8c7b756);	/* 2 */
-    FF(c, d, a, b, x[2], S13, 0x242070db);	/* 3 */
-    FF(b, c, d, a, x[3], S14, 0xc1bdceee);	/* 4 */
-    FF(a, b, c, d, x[4], S11, 0xf57c0faf);	/* 5 */
-    FF(d, a, b, c, x[5], S12, 0x4787c62a);	/* 6 */
-    FF(c, d, a, b, x[6], S13, 0xa8304613);	/* 7 */
-    FF(b, c, d, a, x[7], S14, 0xfd469501);	/* 8 */
-    FF(a, b, c, d, x[8], S11, 0x698098d8);	/* 9 */
-    FF(d, a, b, c, x[9], S12, 0x8b44f7af);	/* 10 */
-    FF(c, d, a, b, x[10], S13, 0xffff5bb1);	/* 11 */
-    FF(b, c, d, a, x[11], S14, 0x895cd7be);	/* 12 */
-    FF(a, b, c, d, x[12], S11, 0x6b901122);	/* 13 */
-    FF(d, a, b, c, x[13], S12, 0xfd987193);	/* 14 */
-    FF(c, d, a, b, x[14], S13, 0xa679438e);	/* 15 */
-    FF(b, c, d, a, x[15], S14, 0x49b40821);	/* 16 */
-
-    /* Round 2 */
-    GG(a, b, c, d, x[1], S21, 0xf61e2562);	/* 17 */
-    GG(d, a, b, c, x[6], S22, 0xc040b340);	/* 18 */
-    GG(c, d, a, b, x[11], S23, 0x265e5a51);	/* 19 */
-    GG(b, c, d, a, x[0], S24, 0xe9b6c7aa);	/* 20 */
-    GG(a, b, c, d, x[5], S21, 0xd62f105d);	/* 21 */
-    GG(d, a, b, c, x[10], S22, 0x2441453);	/* 22 */
-    GG(c, d, a, b, x[15], S23, 0xd8a1e681);	/* 23 */
-    GG(b, c, d, a, x[4], S24, 0xe7d3fbc8);	/* 24 */
-    GG(a, b, c, d, x[9], S21, 0x21e1cde6);	/* 25 */
-    GG(d, a, b, c, x[14], S22, 0xc33707d6);	/* 26 */
-    GG(c, d, a, b, x[3], S23, 0xf4d50d87);	/* 27 */
-    GG(b, c, d, a, x[8], S24, 0x455a14ed);	/* 28 */
-    GG(a, b, c, d, x[13], S21, 0xa9e3e905);	/* 29 */
-    GG(d, a, b, c, x[2], S22, 0xfcefa3f8);	/* 30 */
-    GG(c, d, a, b, x[7], S23, 0x676f02d9);	/* 31 */
-    GG(b, c, d, a, x[12], S24, 0x8d2a4c8a);	/* 32 */
-
-    /* Round 3 */
-    HH(a, b, c, d, x[5], S31, 0xfffa3942);	/* 33 */
-    HH(d, a, b, c, x[8], S32, 0x8771f681);	/* 34 */
-    HH(c, d, a, b, x[11], S33, 0x6d9d6122);	/* 35 */
-    HH(b, c, d, a, x[14], S34, 0xfde5380c);	/* 36 */
-    HH(a, b, c, d, x[1], S31, 0xa4beea44);	/* 37 */
-    HH(d, a, b, c, x[4], S32, 0x4bdecfa9);	/* 38 */
-    HH(c, d, a, b, x[7], S33, 0xf6bb4b60);	/* 39 */
-    HH(b, c, d, a, x[10], S34, 0xbebfbc70);	/* 40 */
-    HH(a, b, c, d, x[13], S31, 0x289b7ec6);	/* 41 */
-    HH(d, a, b, c, x[0], S32, 0xeaa127fa);	/* 42 */
-    HH(c, d, a, b, x[3], S33, 0xd4ef3085);	/* 43 */
-    HH(b, c, d, a, x[6], S34, 0x4881d05);	/* 44 */
-    HH(a, b, c, d, x[9], S31, 0xd9d4d039);	/* 45 */
-    HH(d, a, b, c, x[12], S32, 0xe6db99e5);	/* 46 */
-    HH(c, d, a, b, x[15], S33, 0x1fa27cf8);	/* 47 */
-    HH(b, c, d, a, x[2], S34, 0xc4ac5665);	/* 48 */
-
-    /* Round 4 */
-    II(a, b, c, d, x[0], S41, 0xf4292244);	/* 49 */
-    II(d, a, b, c, x[7], S42, 0x432aff97);	/* 50 */
-    II(c, d, a, b, x[14], S43, 0xab9423a7);	/* 51 */
-    II(b, c, d, a, x[5], S44, 0xfc93a039);	/* 52 */
-    II(a, b, c, d, x[12], S41, 0x655b59c3);	/* 53 */
-    II(d, a, b, c, x[3], S42, 0x8f0ccc92);	/* 54 */
-    II(c, d, a, b, x[10], S43, 0xffeff47d);	/* 55 */
-    II(b, c, d, a, x[1], S44, 0x85845dd1);	/* 56 */
-    II(a, b, c, d, x[8], S41, 0x6fa87e4f);	/* 57 */
-    II(d, a, b, c, x[15], S42, 0xfe2ce6e0);	/* 58 */
-    II(c, d, a, b, x[6], S43, 0xa3014314);	/* 59 */
-    II(b, c, d, a, x[13], S44, 0x4e0811a1);	/* 60 */
-    II(a, b, c, d, x[4], S41, 0xf7537e82);	/* 61 */
-    II(d, a, b, c, x[11], S42, 0xbd3af235);	/* 62 */
-    II(c, d, a, b, x[2], S43, 0x2ad7d2bb);	/* 63 */
-    II(b, c, d, a, x[9], S44, 0xeb86d391);	/* 64 */
-
-    state[0] += a;
-    state[1] += b;
-    state[2] += c;
-    state[3] += d;
-
-    /* Zeroize sensitive information. */
-    memset(x, 0, sizeof(x));
-}
-
-/* Encodes input (UINT4) into output (unsigned char). Assumes len is
-   a multiple of 4.
- */
-static void Encode(unsigned char *output, const UINT4 *input, unsigned int len)
-{
-    unsigned int i, j;
-    UINT4 k;
-
-    for (i = 0, j = 0; j < len; i++, j += 4) {
-	k = input[i];
-	output[j] = (unsigned char) (k & 0xff);
-	output[j + 1] = (unsigned char) ((k >> 8) & 0xff);
-	output[j + 2] = (unsigned char) ((k >> 16) & 0xff);
-	output[j + 3] = (unsigned char) ((k >> 24) & 0xff);
-    }
-}
-
-/* Decodes input (unsigned char) into output (UINT4). Assumes len is
- * a multiple of 4.
- */
-static void Decode(UINT4 *output, const unsigned char *input, unsigned int len)
-{
-    unsigned int i, j;
-
-    for (i = 0, j = 0; j < len; i++, j += 4)
-	output[i] = ((UINT4) input[j]) | (((UINT4) input[j + 1]) << 8) |
-	    (((UINT4) input[j + 2]) << 16) | (((UINT4) input[j + 3]) << 24);
-}
-
-/*
- * Define the Magic String prefix that identifies a password as being
- * hashed using our algorithm.
- */
-static const char *apr1_id = "$apr1$";
-
-/*
- * The following MD5 password encryption code was largely borrowed from
- * the FreeBSD 3.0 /usr/src/lib/libcrypt/crypt.c file, which is
- * licenced as stated at the top of this file.
- */
-
-static void to64(char *s, unsigned long v, int n)
-{
-    static unsigned char itoa64[] =         /* 0 ... 63 => ASCII - 64 */
-	"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
-
-    while (--n >= 0) {
-	*s++ = itoa64[v&0x3f];
-	v >>= 6;
-    }
-}
-
-API_EXPORT(ap_status_t) ap_MD5Encode(const char *pw, const char *salt,
-			      char *result, size_t nbytes)
-{
-    /*
-     * Minimum size is 8 bytes for salt, plus 1 for the trailing NUL,
-     * plus 4 for the '$' separators, plus the password hash itself.
-     * Let's leave a goodly amount of leeway.
-     */
-
-    char passwd[120], *p;
-    const char *sp, *ep;
-    unsigned char final[MD5_DIGESTSIZE];
-    int sl, pl, i;
-    ap_md5_ctx_t ctx, ctx1;
-    unsigned long l;
-
-    /* 
-     * Refine the salt first.  It's possible we were given an already-hashed
-     * string as the salt argument, so extract the actual salt value from it
-     * if so.  Otherwise just use the string up to the first '$' as the salt.
-     */
-    sp = salt;
-
-    /*
-     * If it starts with the magic string, then skip that.
-     */
-    if (!strncmp(sp, apr1_id, strlen(apr1_id))) {
-	sp += strlen(apr1_id);
-    }
-
-    /*
-     * It stops at the first '$' or 8 chars, whichever comes first
-     */
-    for (ep = sp; (*ep != '\0') && (*ep != '$') && (ep < (sp + 8)); ep++) {
-	continue;
-    }
-
-    /*
-     * Get the length of the true salt
-     */
-    sl = ep - sp;
-
-    /*
-     * 'Time to make the doughnuts..'
-     */
-    ap_MD5Init(&ctx);
-
-    /*
-     * The password first, since that is what is most unknown
-     */
-    ap_MD5Update(&ctx, (unsigned char *)pw, strlen(pw));
-
-    /*
-     * Then our magic string
-     */
-    ap_MD5Update(&ctx, (unsigned char *)apr1_id, strlen(apr1_id));
-
-    /*
-     * Then the raw salt
-     */
-    ap_MD5Update(&ctx, (unsigned char *)sp, sl);
-
-    /*
-     * Then just as many characters of the MD5(pw, salt, pw)
-     */
-    ap_MD5Init(&ctx1);
-    ap_MD5Update(&ctx1, (unsigned char *)pw, strlen(pw));
-    ap_MD5Update(&ctx1, (unsigned char *)sp, sl);
-    ap_MD5Update(&ctx1, (unsigned char *)pw, strlen(pw));
-    ap_MD5Final(final, &ctx1);
-    for (pl = strlen(pw); pl > 0; pl -= MD5_DIGESTSIZE) {
-	ap_MD5Update(&ctx, final, (pl > MD5_DIGESTSIZE) ? MD5_DIGESTSIZE : pl);
-    }
-
-    /*
-     * Don't leave anything around in vm they could use.
-     */
-    memset(final, 0, sizeof(final));
-
-    /*
-     * Then something really weird...
-     */
-    for (i = strlen(pw); i != 0; i >>= 1) {
-	if (i & 1) {
-	    ap_MD5Update(&ctx, final, 1);
-	}
-	else {
-	    ap_MD5Update(&ctx, (unsigned char *)pw, 1);
-	}
-    }
-
-    /*
-     * Now make the output string.  We know our limitations, so we
-     * can use the string routines without bounds checking.
-     */
-    strcpy(passwd, apr1_id);
-    strncat(passwd, sp, sl);
-    strcat(passwd, "$");
-
-    ap_MD5Final(final, &ctx);
-
-    /*
-     * And now, just to make sure things don't run too fast..
-     * On a 60 Mhz Pentium this takes 34 msec, so you would
-     * need 30 seconds to build a 1000 entry dictionary...
-     */
-    for (i = 0; i < 1000; i++) {
-	ap_MD5Init(&ctx1);
-	if (i & 1) {
-	    ap_MD5Update(&ctx1, (unsigned char *)pw, strlen(pw));
-	}
-	else {
-	    ap_MD5Update(&ctx1, final, MD5_DIGESTSIZE);
-	}
-	if (i % 3) {
-	    ap_MD5Update(&ctx1, (unsigned char *)sp, sl);
-	}
-
-	if (i % 7) {
-	    ap_MD5Update(&ctx1, (unsigned char *)pw, strlen(pw));
-	}
-
-	if (i & 1) {
-	    ap_MD5Update(&ctx1, final, MD5_DIGESTSIZE);
-	}
-	else {
-	    ap_MD5Update(&ctx1, (unsigned char *)pw, strlen(pw));
-	}
-	ap_MD5Final(final,&ctx1);
-    }
-
-    p = passwd + strlen(passwd);
-
-    l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(p, l, 4); p += 4;
-    l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(p, l, 4); p += 4;
-    l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(p, l, 4); p += 4;
-    l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(p, l, 4); p += 4;
-    l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; to64(p, l, 4); p += 4;
-    l =                    final[11]                ; to64(p, l, 2); p += 2;
-    *p = '\0';
-
-    /*
-     * Don't leave anything around in vm they could use.
-     */
-    memset(final, 0, sizeof(final));
-
-    ap_cpystrn(result, passwd, nbytes - 1);
-    return APR_SUCCESS;
-}
-
-/*
- * Validate a plaintext password against a smashed one.  Use either
- * crypt() (if available) or ap_MD5Encode(), depending upon the format
- * of the smashed input password.  Return APR_SUCCESS if they match, or
- * APR_EMISMATCH if they don't.
- */
-
-API_EXPORT(ap_status_t) ap_validate_password(const char *passwd, const char *hash)
-{
-    char sample[120];
-#ifndef WIN32
-    char *crypt_pw;
-#endif
-    if (!strncmp(hash, apr1_id, strlen(apr1_id))) {
-	/*
-	 * The hash was created using our custom algorithm.
-	 */
-	ap_MD5Encode(passwd, hash, sample, sizeof(sample));
-    }
-    else {
-	/*
-	 * It's not our algorithm, so feed it to crypt() if possible.
-	 */
-#if defined(WIN32) || defined(BEOS)
-	ap_cpystrn(sample, passwd, sizeof(sample) - 1);
-#else
-	crypt_pw = crypt(passwd, hash);
-	ap_cpystrn(sample, crypt_pw, sizeof(sample) - 1);
-#endif
-    }
-    return (strcmp(sample, hash) == 0) ? APR_SUCCESS : APR_EMISMATCH;
-}
diff --git a/lib/apr_pools.c b/lib/apr_pools.c
deleted file mode 100644
index 0d853a730ab..00000000000
--- a/lib/apr_pools.c
+++ /dev/null
@@ -1,1364 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-/*
- * Resource allocation code... the code here is responsible for making
- * sure that nothing leaks.
- *
- * rst --- 4/95 --- 6/95
- */
-
-#include "apr_private.h"
-
-#include "apr_portable.h" /* for get_os_proc */
-#include "apr_general.h"
-#include "apr_pools.h"
-#include "apr_lib.h"
-#include "apr_lock.h"
-#include "misc.h"
-
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_SYS_SIGNAL_H
-#include <sys/signal.h>
-#endif
-#ifdef HAVE_SIGNAL_H
-#include <signal.h>
-#endif
-#ifdef HAVE_SYS_WAIT_H
-#include <sys/wait.h>
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
-
-/*
- * Debugging support: Define this to enable code which helps detect re-use
- * of freed memory and other such nonsense.
- *
- * The theory is simple.  The FILL_BYTE (0xa5) is written over all malloc'd
- * memory as we receive it, and is written over everything that we free up
- * during a clear_pool.  We check that blocks on the free list always
- * have the FILL_BYTE in them, and we check during palloc() that the bytes
- * still have FILL_BYTE in them.  If you ever see garbage URLs or whatnot
- * containing lots of 0xa5s then you know something used data that's been
- * freed or uninitialized.
- */
-/* #define ALLOC_DEBUG */
-
-/*
- * Debugging support: If defined all allocations will be done with
- * malloc and free()d appropriately at the end.  This is intended to be
- * used with something like Electric Fence or Purify to help detect
- * memory problems.  Note that if you're using efence then you should also
- * add in ALLOC_DEBUG.  But don't add in ALLOC_DEBUG if you're using Purify
- * because ALLOC_DEBUG would hide all the uninitialized read errors that
- * Purify can diagnose.
- */
-/* #define ALLOC_USE_MALLOC */
-
-/*
- * Pool debugging support:  This is intended to detect cases where the
- * wrong pool is used when assigning data to an object in another pool.
- * In particular, it causes the table_{set,add,merge}n routines to check
- * that their arguments are safe for the ap_table_t they're being placed in.
- * It currently only works with the unix multiprocess model, but could
- * be extended to others.
- */
-/* #define POOL_DEBUG */
-
-/*
- * Provide diagnostic information about make_table() calls which are
- * possibly too small.  This requires a recent gcc which supports
- * __builtin_return_address().  The error_log output will be a
- * message such as:
- *    table_push: ap_table_t created by 0x804d874 hit limit of 10
- * Use "l *0x804d874" to find the source that corresponds to.  It
- * indicates that a ap_table_t allocated by a call at that address has
- * possibly too small an initial ap_table_t size guess.
- */
-/* #define MAKE_TABLE_PROFILE */
-
-/*
- * Provide some statistics on the cost of allocations.  It requires a
- * bit of an understanding of how alloc.c works.
- */
-/* #define ALLOC_STATS */
-
-#ifdef POOL_DEBUG
-#ifdef ALLOC_USE_MALLOC
-#error "sorry, no support for ALLOC_USE_MALLOC and POOL_DEBUG at the same time"
-#endif /* ALLOC_USE_MALLOC */
-
-#ifdef MULTITHREAD
-# error "sorry, no support for MULTITHREAD and POOL_DEBUG at the same time"
-#endif /* MULTITHREAD */
-
-#endif /* POOL_DEBUG */
-
-#ifdef ALLOC_USE_MALLOC
-#undef BLOCK_MINFREE
-#undef BLOCK_MINALLOC
-#define BLOCK_MINFREE	0
-#define BLOCK_MINALLOC	0
-#endif /* ALLOC_USE_MALLOC */
-
-#define AP_SLACK_LOW    1
-#define AP_SLACK_HIGH   2
-
-
-/*****************************************************************
- *
- * Managing free storage blocks...
- */
-
-union align {
-    /*
-     * Types which are likely to have the longest RELEVANT alignment
-     * restrictions...
-     */
-
-    char *cp;
-    void (*f) (void);
-    long l;
-    FILE *fp;
-    double d;
-};
-
-#define CLICK_SZ (sizeof(union align))
-
-union block_hdr {
-    union align a;
-
-    /* Actual header... */
-
-    struct {
-	char *endp;
-	union block_hdr *next;
-	char *first_avail;
-#ifdef POOL_DEBUG
-	union block_hdr *global_next;
-	ap_pool_t *owning_pool;
-#endif /* POOL_DEBUG */
-    } h;
-};
-
-#define APR_ABORT(conditional, retcode, func, str) \
-    if (conditional) { \
-        if ((func) == NULL) { \
-            return NULL; \
-        } \
-        else { \
-            fprintf(stderr, "%s", str); \
-            (*(func))(retcode); \
-        } \
-    }
-
-/*
- * Static cells for managing our internal synchronisation.
- */
-static union block_hdr *block_freelist = NULL;
-
-#if APR_HAS_THREADS
-static ap_lock_t *alloc_mutex;
-static ap_lock_t *spawn_mutex;
-#endif
-
-#ifdef POOL_DEBUG
-static char *known_stack_point;
-static int stack_direction;
-static union block_hdr *global_block_list;
-#define FREE_POOL	((ap_pool_t *)(-1))
-#endif /* POOL_DEBUG */
-
-#ifdef ALLOC_STATS
-static unsigned long long num_free_blocks_calls;
-static unsigned long long num_blocks_freed;
-static unsigned max_blocks_in_one_free;
-static unsigned num_malloc_calls;
-static unsigned num_malloc_bytes;
-#endif /* ALLOC_STATS */
-
-#ifdef ALLOC_DEBUG
-#define FILL_BYTE	((char)(0xa5))
-#define debug_fill(ptr,size)	((void)memset((ptr), FILL_BYTE, (size)))
-
-static APR_INLINE void debug_verify_filled(const char *ptr, const char *endp,
-					   const char *error_msg)
-{
-    for ( ; ptr < endp; ++ptr) {
-	if (*ptr != FILL_BYTE) {
-	    fputs(error_msg, stderr);
-	    abort();
-	    exit(1);
-	}
-    }
-}
-
-#else /* ALLOC_DEBUG */
-#define debug_fill(a,b)
-#define debug_verify_filled(a,b,c)
-#endif /* ALLOC_DEBUG */
-
-/*
- * Get a completely new block from the system pool. Note that we rely on
- * malloc() to provide aligned memory.
- */
-
-static union block_hdr *malloc_block(int size, int (*apr_abort)(int retcode))
-{
-    union block_hdr *blok;
-
-#ifdef ALLOC_DEBUG
-    /* make some room at the end which we'll fill and expect to be
-     * always filled
-     */
-    size += CLICK_SZ;
-#endif /* ALLOC_DEBUG */
-
-#ifdef ALLOC_STATS
-    ++num_malloc_calls;
-    num_malloc_bytes += size + sizeof(union block_hdr);
-#endif /* ALLOC_STATS */
-
-    blok = (union block_hdr *) malloc(size + sizeof(union block_hdr));
-    APR_ABORT(blok == NULL, APR_ENOMEM, apr_abort,
-              "Ouch!  malloc failed in malloc_block()\n");
-    debug_fill(blok, size + sizeof(union block_hdr));
-    blok->h.next = NULL;
-    blok->h.first_avail = (char *) (blok + 1);
-    blok->h.endp = size + blok->h.first_avail;
-
-#ifdef ALLOC_DEBUG
-    blok->h.endp -= CLICK_SZ;
-#endif /* ALLOC_DEBUG */
-
-#ifdef POOL_DEBUG
-    blok->h.global_next = global_block_list;
-    global_block_list = blok;
-    blok->h.owning_pool = NULL;
-#endif /* POOL_DEBUG */
-
-    return blok;
-}
-
-
-
-#if defined(ALLOC_DEBUG) && !defined(ALLOC_USE_MALLOC)
-static void chk_on_blk_list(union block_hdr *blok, union block_hdr *free_blk)
-{
-    debug_verify_filled(blok->h.endp, blok->h.endp + CLICK_SZ,
-			"Ouch!  Someone trounced the padding "
-			"at the end of a block!\n");
-    while (free_blk) {
-	if (free_blk == blok) {
-            fprintf(stderr, "Ouch!  Freeing free block\n");
-	    abort();
-	    exit(1);
-	}
-	free_blk = free_blk->h.next;
-    }
-}
-#else /* defined(ALLOC_DEBUG) && !defined(ALLOC_USE_MALLOC) */
-#define chk_on_blk_list(_x, _y)
-#endif /* defined(ALLOC_DEBUG) && !defined(ALLOC_USE_MALLOC) */
-
-/* Free a chain of blocks --- must be called with alarms blocked. */
-
-static void free_blocks(union block_hdr *blok)
-{
-#ifdef ALLOC_USE_MALLOC
-    union block_hdr *next;
-
-    for ( ; blok; blok = next) {
-	next = blok->h.next;
-	free(blok);
-    }
-#else /* ALLOC_USE_MALLOC */
-
-#ifdef ALLOC_STATS
-    unsigned num_blocks;
-#endif /* ALLOC_STATS */
-
-    /*
-     * First, put new blocks at the head of the free list ---
-     * we'll eventually bash the 'next' pointer of the last block
-     * in the chain to point to the free blocks we already had.
-     */
-
-    union block_hdr *old_free_list;
-
-    if (blok == NULL) {
-	return;			/* Sanity check --- freeing empty pool? */
-    }
-
-#if APR_HAS_THREADS
-    ap_lock(alloc_mutex);
-#endif
-    old_free_list = block_freelist;
-    block_freelist = blok;
-
-    /*
-     * Next, adjust first_avail pointers of each block --- have to do it
-     * sooner or later, and it simplifies the search in new_block to do it
-     * now.
-     */
-
-#ifdef ALLOC_STATS
-    num_blocks = 1;
-#endif /* ALLOC_STATS */
-
-    while (blok->h.next != NULL) {
-
-#ifdef ALLOC_STATS
-	++num_blocks;
-#endif /* ALLOC_STATS */
-
-	chk_on_blk_list(blok, old_free_list);
-	blok->h.first_avail = (char *) (blok + 1);
-	debug_fill(blok->h.first_avail, blok->h.endp - blok->h.first_avail);
-#ifdef POOL_DEBUG
-	blok->h.owning_pool = FREE_POOL;
-#endif /* POOL_DEBUG */
-	blok = blok->h.next;
-    }
-
-    chk_on_blk_list(blok, old_free_list);
-    blok->h.first_avail = (char *) (blok + 1);
-    debug_fill(blok->h.first_avail, blok->h.endp - blok->h.first_avail);
-#ifdef POOL_DEBUG
-    blok->h.owning_pool = FREE_POOL;
-#endif /* POOL_DEBUG */
-
-    /* Finally, reset next pointer to get the old free blocks back */
-
-    blok->h.next = old_free_list;
-
-#ifdef ALLOC_STATS
-    if (num_blocks > max_blocks_in_one_free) {
-	max_blocks_in_one_free = num_blocks;
-    }
-    ++num_free_blocks_calls;
-    num_blocks_freed += num_blocks;
-#endif /* ALLOC_STATS */
-
-#if APR_HAS_THREADS
-    ap_unlock(alloc_mutex);
-#endif /* APR_HAS_THREADS */
-#endif /* ALLOC_USE_MALLOC */
-}
-
-/*
- * Get a new block, from our own free list if possible, from the system
- * if necessary.  Must be called with alarms blocked.
- */
-
-static union block_hdr *new_block(int min_size, int (*apr_abort)(int retcode))
-{
-    union block_hdr **lastptr = &block_freelist;
-    union block_hdr *blok = block_freelist;
-
-    /* First, see if we have anything of the required size
-     * on the free list...
-     */
-
-    while (blok != NULL) {
-	if (min_size + BLOCK_MINFREE <= blok->h.endp - blok->h.first_avail) {
-	    *lastptr = blok->h.next;
-	    blok->h.next = NULL;
-	    debug_verify_filled(blok->h.first_avail, blok->h.endp,
-				"Ouch!  Someone trounced a block "
-				"on the free list!\n");
-	    return blok;
-	}
-	else {
-	    lastptr = &blok->h.next;
-	    blok = blok->h.next;
-	}
-    }
-
-    /* Nope. */
-
-    min_size += BLOCK_MINFREE;
-    blok = malloc_block((min_size > BLOCK_MINALLOC)
-			? min_size : BLOCK_MINALLOC, apr_abort);
-    return blok;
-}
-
-
-/* Accounting */
-
-static long bytes_in_block_list(union block_hdr *blok)
-{
-    long size = 0;
-
-    while (blok) {
-	size += blok->h.endp - (char *) (blok + 1);
-	blok = blok->h.next;
-    }
-
-    return size;
-}
-
-
-/*****************************************************************
- *
- * Pool internals and management...
- * NB that subprocesses are not handled by the generic cleanup code,
- * basically because we don't want cleanups for multiple subprocesses
- * to result in multiple three-second pauses.
- */
-
-struct process_chain;
-struct cleanup;
-
-static void run_cleanups(struct cleanup *c);
-static void free_proc_chain(struct process_chain *p);
-
-static ap_pool_t *permanent_pool;
-
-/* Each pool structure is allocated in the start of its own first block,
- * so we need to know how many bytes that is (once properly aligned...).
- * This also means that when a pool's sub-pool is destroyed, the storage
- * associated with it is *completely* gone, so we have to make sure it
- * gets taken off the parent's sub-pool list...
- */
-
-#define POOL_HDR_CLICKS (1 + ((sizeof(struct ap_pool_t) - 1) / CLICK_SZ))
-#define POOL_HDR_BYTES (POOL_HDR_CLICKS * CLICK_SZ)
-
-API_EXPORT(ap_pool_t *) ap_make_sub_pool(ap_pool_t *p, int (*apr_abort)(int retcode))
-{
-    union block_hdr *blok;
-    ap_pool_t *new_pool;
-
-    ap_block_alarms();
-
-#if APR_HAS_THREADS
-    ap_lock(alloc_mutex);
-#endif
-
-    blok = new_block(POOL_HDR_BYTES, apr_abort);
-    new_pool = (ap_pool_t *) blok->h.first_avail;
-    blok->h.first_avail += POOL_HDR_BYTES;
-#ifdef POOL_DEBUG
-    blok->h.owning_pool = new_pool;
-#endif
-
-    memset((char *) new_pool, '\0', sizeof(struct ap_pool_t));
-    new_pool->free_first_avail = blok->h.first_avail;
-    new_pool->first = new_pool->last = blok;
-
-    if (p) {
-	new_pool->parent = p;
-	new_pool->sub_next = p->sub_pools;
-	if (new_pool->sub_next) {
-	    new_pool->sub_next->sub_prev = new_pool;
-	}
-	p->sub_pools = new_pool;
-    }
-    else {
-        permanent_pool = new_pool;
-    }
-
-#if APR_HAS_THREADS
-    ap_unlock(alloc_mutex);
-#endif
-    ap_unblock_alarms();
-
-    return new_pool;
-}
-
-#ifdef POOL_DEBUG
-static void stack_var_init(char *s)
-{
-    char t;
-
-    if (s < &t) {
-	stack_direction = 1; /* stack grows up */
-    }
-    else {
-	stack_direction = -1; /* stack grows down */
-    }
-}
-#endif
-
-#ifdef ALLOC_STATS
-static void dump_stats(void)
-{
-    fprintf(stderr,
-	    "alloc_stats: [%d] #free_blocks %llu #blocks %llu max "
-	    "%u #malloc %u #bytes %u\n",
-	(int) getpid(),
-	num_free_blocks_calls,
-	num_blocks_freed,
-	max_blocks_in_one_free,
-	num_malloc_calls,
-	num_malloc_bytes);
-}
-#endif
-
-/*****************************************************************
- *
- * Managing generic cleanups.  
- */
-
-struct cleanup {
-    void *data;
-    ap_status_t (*plain_cleanup) (void *);
-    ap_status_t (*child_cleanup) (void *);
-    struct cleanup *next;
-};
-
-static void * ap_pool_palloc(ap_pool_t *a, int reqsize, int (*apr_abort)(int retcode));
-
-#if 0
-static void ap_register_pool_cleanup(struct ap_pool_t *p, void *data,
-				      ap_status_t (*plain_cleanup) (void *),
-				      ap_status_t (*child_cleanup) (void *))
-{
-    struct cleanup *c;
-
-    if (p != NULL) {
-        c = (struct cleanup *) ap_pool_palloc(p, sizeof(struct cleanup), NULL);
-        c->data = data;
-        c->plain_cleanup = plain_cleanup;
-        c->child_cleanup = child_cleanup;
-        c->next = p->cleanups;
-        p->cleanups = c;
-    }
-}
-#endif
-
-API_EXPORT(void) ap_register_cleanup(ap_pool_t *p, void *data,
-				      ap_status_t (*plain_cleanup) (void *),
-				      ap_status_t (*child_cleanup) (void *))
-{
-    struct cleanup *c;
-
-    if (p != NULL) {
-        c = (struct cleanup *) ap_palloc(p, sizeof(struct cleanup));
-        c->data = data;
-        c->plain_cleanup = plain_cleanup;
-        c->child_cleanup = child_cleanup;
-        c->next = p->cleanups;
-        p->cleanups = c;
-    }
-}
-
-API_EXPORT(void) ap_kill_cleanup(ap_pool_t *p, void *data,
-				  ap_status_t (*cleanup) (void *))
-{
-    struct cleanup *c;
-    struct cleanup **lastp;
-
-    if (p == NULL)
-        return;
-    c = p->cleanups;
-    lastp = &p->cleanups;
-    while (c) {
-        if (c->data == data && c->plain_cleanup == cleanup) {
-            *lastp = c->next;
-            break;
-        }
-
-        lastp = &c->next;
-        c = c->next;
-    }
-}
-
-API_EXPORT(void) ap_run_cleanup(ap_pool_t *p, void *data,
-				 ap_status_t (*cleanup) (void *))
-{
-    ap_block_alarms();		/* Run cleanup only once! */
-    (*cleanup) (data);
-    ap_kill_cleanup(p, data, cleanup);
-    ap_unblock_alarms();
-}
-
-static void run_cleanups(struct cleanup *c)
-{
-    while (c) {
-	(*c->plain_cleanup) (c->data);
-	c = c->next;
-    }
-}
-
-static void run_child_cleanups(struct cleanup *c)
-{
-    while (c) {
-	(*c->child_cleanup) (c->data);
-	c = c->next;
-    }
-}
-
-static void cleanup_pool_for_exec(ap_pool_t *p)
-{
-    run_child_cleanups(p->cleanups);
-    p->cleanups = NULL;
-
-    for (p = p->sub_pools; p; p = p->sub_next) {
-	cleanup_pool_for_exec(p);
-    }
-}
-
-API_EXPORT(void) ap_cleanup_for_exec(void)
-{
-#if !defined(WIN32) && !defined(OS2)
-    /*
-     * Don't need to do anything on NT or OS/2, because I
-     * am actually going to spawn the new process - not
-     * exec it. All handles that are not inheritable, will
-     * be automajically closed. The only problem is with
-     * file handles that are open, but there isn't much
-     * I can do about that (except if the child decides
-     * to go out and close them
-     */
-    ap_block_alarms();
-    cleanup_pool_for_exec(permanent_pool);
-    ap_unblock_alarms();
-#endif /* ndef WIN32 */
-}
-
-API_EXPORT_NONSTD(ap_status_t) ap_null_cleanup(void *data)
-{
-    /* do nothing cleanup routine */
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_init_alloc(void)
-{
-#if APR_HAS_THREADS
-    ap_status_t status;
-#endif
-#ifdef POOL_DEBUG
-    char s;
-
-    known_stack_point = &s;
-    stack_var_init(&s);
-#endif
-#if APR_HAS_THREADS
-    status = ap_create_lock(&alloc_mutex, APR_MUTEX, APR_INTRAPROCESS,
-                   NULL, NULL);
-    if (status != APR_SUCCESS) {
-        ap_destroy_lock(alloc_mutex); 
-        return status;
-    }
-    status = ap_create_lock(&spawn_mutex, APR_MUTEX, APR_INTRAPROCESS,
-                   NULL, NULL);
-    if (status != APR_SUCCESS) {
-        ap_destroy_lock(spawn_mutex); 
-        return status;
-    }
-#endif
-
-#ifdef ALLOC_STATS
-    atexit(dump_stats);
-#endif
-
-    return APR_SUCCESS;
-}
-
-void ap_term_alloc(void)
-{
-#if APR_HAS_THREADS
-    ap_destroy_lock(alloc_mutex);
-    ap_destroy_lock(spawn_mutex);
-#endif
-}
-
-/* We only want to lock the mutex if we are being called from ap_clear_pool.
- * This is because if we also call this function from ap_destroy_real_pool,
- * which also locks the same mutex, and recursive locks aren't portable.  
- * This way, we are garaunteed that we only lock this mutex once when calling
- * either one of these functions.
- */
-API_EXPORT(void) ap_clear_pool(ap_pool_t *a)
-{
-    ap_block_alarms();
-
-    while (a->sub_pools) {
-	ap_destroy_pool(a->sub_pools);
-    }
-    /*
-     * Don't hold the mutex during cleanups.
-     */
-    run_cleanups(a->cleanups);
-    a->cleanups = NULL;
-    free_proc_chain(a->subprocesses);
-    a->subprocesses = NULL;
-    free_blocks(a->first->h.next);
-    a->first->h.next = NULL;
-
-    a->last = a->first;
-    a->first->h.first_avail = a->free_first_avail;
-    debug_fill(a->first->h.first_avail,
-	       a->first->h.endp - a->first->h.first_avail);
-
-#ifdef ALLOC_USE_MALLOC
-    {
-	void *c, *n;
-
-	for (c = a->allocation_list; c; c = n) {
-	    n = *(void **)c;
-	    free(c);
-	}
-	a->allocation_list = NULL;
-    }
-#endif
-
-    ap_unblock_alarms();
-}
-
-API_EXPORT(void) ap_destroy_pool(ap_pool_t *a)
-{
-    ap_block_alarms();
-    ap_clear_pool(a);
-#if APR_HAS_THREADS
-    ap_lock(alloc_mutex);
-#endif
-
-    if (a->parent) {
-	if (a->parent->sub_pools == a) {
-	    a->parent->sub_pools = a->sub_next;
-	}
-	if (a->sub_prev) {
-	    a->sub_prev->sub_next = a->sub_next;
-	}
-	if (a->sub_next) {
-	    a->sub_next->sub_prev = a->sub_prev;
-	}
-    }
-#if APR_HAS_THREADS
-    ap_unlock(alloc_mutex);
-#endif
-    free_blocks(a->first);
-    ap_unblock_alarms();
-}
-
-API_EXPORT(long) ap_bytes_in_pool(ap_pool_t *p)
-{
-    return bytes_in_block_list(p->first);
-}
-API_EXPORT(long) ap_bytes_in_free_blocks(void)
-{
-    return bytes_in_block_list(block_freelist);
-}
-
-/*****************************************************************
- * POOL_DEBUG support
- */
-#ifdef POOL_DEBUG
-
-/* the unix linker defines this symbol as the last byte + 1 of
- * the executable... so it includes TEXT, BSS, and DATA
- */
-extern char _end;
-
-/* is ptr in the range [lo,hi) */
-#define is_ptr_in_range(ptr, lo, hi) \
-    (((unsigned long)(ptr) - (unsigned long)(lo)) \
-     < (unsigned long)(hi) - (unsigned long)(lo))
-
-/* Find the pool that ts belongs to, return NULL if it doesn't
- * belong to any pool.
- */
-API_EXPORT(ap_pool_t *) ap_find_pool(const void *ts, int (apr_abort)(int retcode))
-{
-    const char *s = ts;
-    union block_hdr **pb;
-    union block_hdr *b;
-
-    /* short-circuit stuff which is in TEXT, BSS, or DATA */
-    if (is_ptr_in_range(s, 0, &_end)) {
-	return NULL;
-    }
-    /* consider stuff on the stack to also be in the NULL pool...
-     * XXX: there's cases where we don't want to assume this
-     */
-    APR_ABORT((stack_direction == -1 && 
-              is_ptr_in_range(s, &ts, known_stack_point)) || 
-              (stack_direction == 1 &&    
-              is_ptr_in_range(s, known_stack_point, &ts)), 1, apr_abort,
-              "Ouch!  find_pool() called on pointer in a free block\n");
-    ap_block_alarms();
-    /* search the global_block_list */
-    for (pb = &global_block_list; *pb; pb = &b->h.global_next) {
-	b = *pb;
-	if (is_ptr_in_range(s, b, b->h.endp)) {
-	    if (b->h.owning_pool == FREE_POOL) {
-		abort();
-		exit(1);
-	    }
-	    if (b != global_block_list) {
-		/*
-		 * promote b to front of list, this is a hack to speed
-		 * up the lookup
-		 */
-		*pb = b->h.global_next;
-		b->h.global_next = global_block_list;
-		global_block_list = b;
-	    }
-	    ap_unblock_alarms();
-	    return b->h.owning_pool;
-	}
-    }
-    ap_unblock_alarms();
-    return NULL;
-}
-
-/* return TRUE iff a is an ancestor of b
- * NULL is considered an ancestor of all pools
- */
-API_EXPORT(int) ap_pool_is_ancestor(ap_pool_t *a, ap_pool_t *b)
-{
-    if (a == NULL) {
-	return 1;
-    }
-    while (a->joined) {
-	a = a->joined;
-    }
-    while (b) {
-	if (a == b) {
-	    return 1;
-	}
-	b = b->parent;
-    }
-    return 0;
-}
-
-/*
- * All blocks belonging to sub will be changed to point to p
- * instead.  This is a guarantee by the caller that sub will not
- * be destroyed before p is.
- */
-API_EXPORT(void) ap_pool_join(ap_pool_t *p, ap_pool_t *sub, 
-                              int (*apr_abort)(int retcode))
-{
-    union block_hdr *b;
-
-    /* We could handle more general cases... but this is it for now. */
-    APR_ABORT(sub->parent != p, 1, apr_abort,
-              "pool_join: p is not a parent of sub\n");
-    ap_block_alarms();
-    while (p->joined) {
-	p = p->joined;
-    }
-    sub->joined = p;
-    for (b = global_block_list; b; b = b->h.global_next) {
-	if (b->h.owning_pool == sub) {
-	    b->h.owning_pool = p;
-	}
-    }
-    ap_unblock_alarms();
-}
-#endif
-
-/*****************************************************************
- *
- * Allocating stuff...
- */
-
-void * ap_palloc(ap_pool_t *a, int reqsize)
-{
-#ifdef ALLOC_USE_MALLOC
-    int size = reqsize + CLICK_SZ;
-    void *ptr;
-
-    if (a == NULL) {
-        return malloc(reqsize);
-    }
-    ap_block_alarms();
-    if (c == NULL) {
-        return malloc(reqsize);
-    }
-    ptr = malloc(size);
-    if (ptr == NULL) {
-	fputs("Ouch!  Out of memory!\n", stderr);
-	exit(1);
-    }
-    debug_fill(ptr, size); /* might as well get uninitialized protection */
-    *(void **)ptr = a->allocation_list;
-    a->allocation_list = ptr;
-    ap_unblock_alarms();
-    return (char *)ptr + CLICK_SZ;
-#else
-
-    /*
-     * Round up requested size to an even number of alignment units
-     * (core clicks)
-     */
-    int nclicks;
-    int size;
-
-    /* First, see if we have space in the block most recently
-     * allocated to this pool
-     */
-
-    union block_hdr *blok;
-    char *first_avail;
-    char *new_first_avail;
-
-    if (a == NULL) {
-        return malloc(reqsize);
-    }
-
-    nclicks = 1 + ((reqsize - 1) / CLICK_SZ);
-    size = nclicks * CLICK_SZ;
-
-    /* First, see if we have space in the block most recently
-     * allocated to this pool
-     */
-
-    blok = a->last;
-    first_avail = blok->h.first_avail;
-
-    if (reqsize <= 0) {
-	return NULL;
-    }
-
-    new_first_avail = first_avail + size;
-
-    if (new_first_avail <= blok->h.endp) {
-	debug_verify_filled(first_avail, blok->h.endp,
-			    "Ouch!  Someone trounced past the end "
-			    "of their allocation!\n");
-	blok->h.first_avail = new_first_avail;
-	return (void *) first_avail;
-    }
-
-    /* Nope --- get a new one that's guaranteed to be big enough */
-
-    ap_block_alarms();
-
-#if APR_HAS_THREADS
-    ap_lock(alloc_mutex);
-#endif
-
-    blok = new_block(size, a->apr_abort);
-    a->last->h.next = blok;
-    a->last = blok;
-#ifdef POOL_DEBUG
-    blok->h.owning_pool = a;
-#endif
-
-#if APR_HAS_THREADS
-    ap_unlock(alloc_mutex);
-#endif
-
-    ap_unblock_alarms();
-
-    first_avail = blok->h.first_avail;
-    blok->h.first_avail += size;
-
-    return (void *) first_avail;
-#endif
-}
-
-API_EXPORT(void *) ap_pcalloc(ap_pool_t *a, int size)
-{
-    void *res = ap_palloc(a, size);
-    memset(res, '\0', size);
-    return res;
-}
-
-API_EXPORT(char *) ap_pstrdup(ap_pool_t *a, const char *s)
-{
-    char *res;
-    size_t len;
-
-    if (s == NULL) {
-	return NULL;
-    }
-    len = strlen(s) + 1;
-    res = ap_palloc(a, len);
-    memcpy(res, s, len);
-    return res;
-}
-
-API_EXPORT(char *) ap_pstrndup(ap_pool_t *a, const char *s, int n)
-{
-    char *res;
-
-    if (s == NULL) {
-	return NULL;
-    }
-    res = ap_palloc(a, n + 1);
-    memcpy(res, s, n);
-    res[n] = '\0';
-    return res;
-}
-
-API_EXPORT_NONSTD(char *) ap_pstrcat(ap_pool_t *a, ...)
-{
-    char *cp, *argp, *res;
-
-    /* Pass one --- find length of required string */
-
-    int len = 0;
-    va_list adummy;
-
-    va_start(adummy, a);
-
-    while ((cp = va_arg(adummy, char *)) != NULL) {
-	len += strlen(cp);
-    }
-
-    va_end(adummy);
-
-    /* Allocate the required string */
-
-    res = (char *) ap_palloc(a, len + 1);
-    cp = res;
-    *cp = '\0';
-
-    /* Pass two --- copy the argument strings into the result space */
-
-    va_start(adummy, a);
-
-    while ((argp = va_arg(adummy, char *)) != NULL) {
-	strcpy(cp, argp);
-	cp += strlen(argp);
-    }
-
-    va_end(adummy);
-
-    /* Return the result string */
-
-    return res;
-}
-
-/*
- * ap_psprintf is implemented by writing directly into the current
- * block of the pool, starting right at first_avail.  If there's
- * insufficient room, then a new block is allocated and the earlier
- * output is copied over.  The new block isn't linked into the pool
- * until all the output is done.
- *
- * Note that this is completely safe because nothing else can
- * allocate in this ap_pool_t while ap_psprintf is running.  alarms are
- * blocked, and the only thing outside of alloc.c that's invoked
- * is ap_vformatter -- which was purposefully written to be
- * self-contained with no callouts.
- */
-
-struct psprintf_data {
-    ap_vformatter_buff_t vbuff;
-#ifdef ALLOC_USE_MALLOC
-    char *base;
-#else
-    union block_hdr *blok;
-    int got_a_new_block;
-#endif
-};
-
-static int psprintf_flush(ap_vformatter_buff_t *vbuff)
-{
-    struct psprintf_data *ps = (struct psprintf_data *)vbuff;
-#ifdef ALLOC_USE_MALLOC
-    int size;
-    char *ptr;
-
-    size = (char *)ps->vbuff.curpos - ps->base;
-    ptr = realloc(ps->base, 2*size);
-    if (ptr == NULL) {
-	fputs("Ouch!  Out of memory!\n", stderr);
-	exit(1);
-    }
-    ps->base = ptr;
-    ps->vbuff.curpos = ptr + size;
-    ps->vbuff.endpos = ptr + 2*size - 1;
-    return 0;
-#else
-    union block_hdr *blok;
-    union block_hdr *nblok;
-    size_t cur_len;
-    char *strp;
-
-    blok = ps->blok;
-    strp = ps->vbuff.curpos;
-    cur_len = strp - blok->h.first_avail;
-
-    /* must try another blok */
-#if APR_HAS_THREADS
-    ap_lock(alloc_mutex);
-#endif
-    nblok = new_block(2 * cur_len, NULL);
-#if APR_HAS_THREADS
-    ap_unlock(alloc_mutex);
-#endif
-    memcpy(nblok->h.first_avail, blok->h.first_avail, cur_len);
-    ps->vbuff.curpos = nblok->h.first_avail + cur_len;
-    /* save a byte for the NUL terminator */
-    ps->vbuff.endpos = nblok->h.endp - 1;
-
-    /* did we allocate the current blok? if so free it up */
-    if (ps->got_a_new_block) {
-	debug_fill(blok->h.first_avail, blok->h.endp - blok->h.first_avail);
-#if APR_HAS_THREADS
-        ap_lock(alloc_mutex);
-#endif
-	blok->h.next = block_freelist;
-	block_freelist = blok;
-#if APR_HAS_THREADS
-        ap_unlock(alloc_mutex);
-#endif
-    }
-    ps->blok = nblok;
-    ps->got_a_new_block = 1;
-    /* note that we've deliberately not linked the new block onto
-     * the pool yet... because we may need to flush again later, and
-     * we'd have to spend more effort trying to unlink the block.
-     */
-    return 0;
-#endif
-}
-
-API_EXPORT(char *) ap_pvsprintf(ap_pool_t *p, const char *fmt, va_list ap)
-{
-#ifdef ALLOC_USE_MALLOC
-    struct psprintf_data ps;
-    void *ptr;
-
-    ap_block_alarms();
-    ps.base = malloc(512);
-    if (ps.base == NULL) {
-	fputs("Ouch!  Out of memory!\n", stderr);
-	exit(1);
-    }
-    /* need room at beginning for allocation_list */
-    ps.vbuff.curpos = ps.base + CLICK_SZ;
-    ps.vbuff.endpos = ps.base + 511;
-    ap_vformatter(psprintf_flush, &ps.vbuff, fmt, ap);
-    *ps.vbuff.curpos++ = '\0';
-    ptr = ps.base;
-    /* shrink */
-    ptr = realloc(ptr, (char *)ps.vbuff.curpos - (char *)ptr);
-    if (ptr == NULL) {
-	fputs("Ouch!  Out of memory!\n", stderr);
-	exit(1);
-    }
-    *(void **)ptr = p->allocation_list;
-    p->allocation_list = ptr;
-    ap_unblock_alarms();
-    return (char *)ptr + CLICK_SZ;
-#else
-    struct psprintf_data ps;
-    char *strp;
-    int size;
-
-    ap_block_alarms();
-    ps.blok = p->last;
-    ps.vbuff.curpos = ps.blok->h.first_avail;
-    ps.vbuff.endpos = ps.blok->h.endp - 1;	/* save one for NUL */
-    ps.got_a_new_block = 0;
-
-    ap_vformatter(psprintf_flush, &ps.vbuff, fmt, ap);
-
-    strp = ps.vbuff.curpos;
-    *strp++ = '\0';
-
-    size = strp - ps.blok->h.first_avail;
-    size = (1 + ((size - 1) / CLICK_SZ)) * CLICK_SZ;
-    strp = ps.blok->h.first_avail;	/* save away result pointer */
-    ps.blok->h.first_avail += size;
-
-    /* have to link the block in if it's a new one */
-    if (ps.got_a_new_block) {
-	p->last->h.next = ps.blok;
-	p->last = ps.blok;
-#ifdef POOL_DEBUG
-	ps.blok->h.owning_pool = p;
-#endif
-    }
-    ap_unblock_alarms();
-
-    return strp;
-#endif
-}
-
-API_EXPORT_NONSTD(char *) ap_psprintf(ap_pool_t *p, const char *fmt, ...)
-{
-    va_list ap;
-    char *res;
-
-    va_start(ap, fmt);
-    res = ap_pvsprintf(p, fmt, ap);
-    va_end(ap);
-    return res;
-}
-
-
-/*****************************************************************
- *
- * More grotty system stuff... subprocesses.  Frump.  These don't use
- * the generic cleanup interface because I don't want multiple
- * subprocesses to result in multiple three-second pauses; the
- * subprocesses have to be "freed" all at once.  If someone comes
- * along with another resource they want to allocate which has the
- * same property, we might want to fold support for that into the
- * generic interface, but for now, it's a special case
- */
-
-API_EXPORT(void) ap_note_subprocess(ap_pool_t *a, ap_proc_t *pid,
-				     enum kill_conditions how)
-{
-    struct process_chain *new =
-    (struct process_chain *) ap_palloc(a, sizeof(struct process_chain));
-
-    new->pid = pid;
-    new->kill_how = how;
-    new->next = a->subprocesses;
-    a->subprocesses = new;
-}
-
-static void free_proc_chain(struct process_chain *procs)
-{
-    /* Dispose of the subprocesses we've spawned off in the course of
-     * whatever it was we're cleaning up now.  This may involve killing
-     * some of them off...
-     */
-    struct process_chain *p;
-    int need_timeout = 0;
-
-    if (procs == NULL) {
-	return;			/* No work.  Whew! */
-    }
-
-    /* First, check to see if we need to do the SIGTERM, sleep, SIGKILL
-     * dance with any of the processes we're cleaning up.  If we've got
-     * any kill-on-sight subprocesses, ditch them now as well, so they
-     * don't waste any more cycles doing whatever it is that they shouldn't
-     * be doing anymore.
-     */
-
-#ifndef NEED_WAITPID
-    /* Pick up all defunct processes */
-    for (p = procs; p; p = p->next) {
-        if (ap_wait_proc(p->pid, APR_NOWAIT) == APR_CHILD_DONE) {
-            p->kill_how = kill_never;
-        }
-    }
-#endif
-
-    for (p = procs; p; p = p->next) {
-        if ((p->kill_how == kill_after_timeout)
-            || (p->kill_how == kill_only_once)) {
-            /*
-             * Subprocess may be dead already.  Only need the timeout if not.
-             * Note: ap_kill on Windows is TerminateProcess(), which is 
-             * similar to a SIGKILL, so always give the process a timeout
-             * under Windows before killing it.
-             */
-#ifdef WIN32
-            need_timeout = 1;
-#else
-	    if (ap_kill(p->pid, APR_SIGTERM) == APR_SUCCESS) {
-		need_timeout = 1;
-	    }
-#endif
-	}
-	else if (p->kill_how == kill_always) {
-	    ap_kill(p->pid, APR_SIGKILL);
-	}
-    }
-
-    /* Sleep only if we have to... */
-    if (need_timeout) {
-	sleep(3);
-    }
-
-    /* OK, the scripts we just timed out for have had a chance to clean up
-     * --- now, just get rid of them, and also clean up the system accounting
-     * goop...
-     */
-    for (p = procs; p; p = p->next) {
-	if (p->kill_how == kill_after_timeout) {
-	    ap_kill(p->pid, APR_SIGKILL);
-	}
-    }
-#ifdef WIN32
-    /* 
-     * Do we need an APR function to clean-up a proc_t?
-     */
-    {
-        PROCESS_INFORMATION pi;
-        for (p = procs; p; p = p->next) {
-            ap_get_os_proc(&pi, p->pid);
-            CloseHandle(pi.hProcess);
-        }
-    }
-#endif /* WIN32 */
-
-    /* Now wait for all the signaled processes to die */
-    for (p = procs; p; p = p->next) {
-	if (p->kill_how != kill_never) {
-	    (void) ap_wait_proc(p->pid, APR_WAIT);
-	}
-    }
-}
diff --git a/lib/apr_signal.c b/lib/apr_signal.c
deleted file mode 100644
index 9fd1164c8a7..00000000000
--- a/lib/apr_signal.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "apr_private.h"
-#include "apr_lib.h"
-#ifdef HAVE_SIGNAL_H
-#include <signal.h>
-#endif
-
-#if !defined(NO_USE_SIGACTION) && defined(HAVE_SIGACTION)
-/*
- * Replace standard signal() with the more reliable sigaction equivalent
- * from W. Richard Stevens' "Advanced Programming in the UNIX Environment"
- * (the version that does not automatically restart system calls).
- */
-Sigfunc *ap_signal(int signo, Sigfunc * func)
-{
-    struct sigaction act, oact;
-
-    act.sa_handler = func;
-    sigemptyset(&act.sa_mask);
-    act.sa_flags = 0;
-#ifdef  SA_INTERRUPT		/* SunOS */
-    act.sa_flags |= SA_INTERRUPT;
-#endif
-    if (sigaction(signo, &act, &oact) < 0)
-	return SIG_ERR;
-    return oact.sa_handler;
-}
-#else
-/* need some function in this file, otherwise the linker on NeXT bitches */
-void ap_signal_is_not_here(void) {}
-#endif
diff --git a/lib/apr_snprintf.c b/lib/apr_snprintf.c
deleted file mode 100644
index c5ea415ec35..00000000000
--- a/lib/apr_snprintf.c
+++ /dev/null
@@ -1,1194 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifdef WIN32
-#include <winsock2.h>
-#endif
-#include "apr_private.h"
-
-#include "apr_lib.h"
-#include <math.h>
-#ifdef HAVE_CTYPE_H
-#include <ctype.h>
-#endif
-#if HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#ifdef HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-#ifdef HAVE_LIMITS_H
-#include <limits.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-typedef enum {
-    NO = 0, YES = 1
-} boolean_e;
-
-#ifndef FALSE
-#define FALSE			0
-#endif
-#ifndef TRUE
-#define TRUE			1
-#endif
-#ifndef AP_LONGEST_LONG
-#define AP_LONGEST_LONG		long
-#endif
-#define NUL			'\0'
-#define WIDE_INT		long
-#define WIDEST_INT		AP_LONGEST_LONG
-
-typedef WIDE_INT wide_int;
-typedef unsigned WIDE_INT u_wide_int;
-typedef WIDEST_INT widest_int;
-#ifdef __TANDEM
-/* Although Tandem supports "long long" there is no unsigned variant. */
-typedef unsigned long       u_widest_int;
-#else
-typedef unsigned WIDEST_INT u_widest_int;
-#endif
-typedef int bool_int;
-
-#define S_NULL			"(null)"
-#define S_NULL_LEN		6
-
-#define FLOAT_DIGITS		6
-#define EXPONENT_LENGTH		10
-
-/*
- * NUM_BUF_SIZE is the size of the buffer used for arithmetic conversions
- *
- * XXX: this is a magic number; do not decrease it
- */
-#define NUM_BUF_SIZE		512
-
-/*
- * cvt.c - IEEE floating point formatting routines for FreeBSD
- * from GNU libc-4.6.27.  Modified to be thread safe.
- */
-
-/*
- *    ap_ecvt converts to decimal
- *      the number of digits is specified by ndigit
- *      decpt is set to the position of the decimal point
- *      sign is set to 0 for positive, 1 for negative
- */
-
-#define	NDIG	80
-
-/* buf must have at least NDIG bytes */
-static char *ap_cvt(double arg, int ndigits, int *decpt, int *sign, int eflag, char *buf)
-{
-    register int r2;
-    double fi, fj;
-    register char *p, *p1;
-    
-    if (ndigits >= NDIG - 1)
-	ndigits = NDIG - 2;
-    r2 = 0;
-    *sign = 0;
-    p = &buf[0];
-    if (arg < 0) {
-	*sign = 1;
-	arg = -arg;
-    }
-    arg = modf(arg, &fi);
-    p1 = &buf[NDIG];
-    /*
-     * Do integer part
-     */
-    if (fi != 0) {
-	p1 = &buf[NDIG];
-	while (fi != 0) {
-	    fj = modf(fi / 10, &fi);
-	    *--p1 = (int) ((fj + .03) * 10) + '0';
-	    r2++;
-	}
-	while (p1 < &buf[NDIG])
-	    *p++ = *p1++;
-    }
-    else if (arg > 0) {
-	while ((fj = arg * 10) < 1) {
-	    arg = fj;
-	    r2--;
-	}
-    }
-    p1 = &buf[ndigits];
-    if (eflag == 0)
-	p1 += r2;
-    *decpt = r2;
-    if (p1 < &buf[0]) {
-	buf[0] = '\0';
-	return (buf);
-    }
-    while (p <= p1 && p < &buf[NDIG]) {
-	arg *= 10;
-	arg = modf(arg, &fj);
-	*p++ = (int) fj + '0';
-    }
-    if (p1 >= &buf[NDIG]) {
-	buf[NDIG - 1] = '\0';
-	return (buf);
-    }
-    p = p1;
-    *p1 += 5;
-    while (*p1 > '9') {
-	*p1 = '0';
-	if (p1 > buf)
-	    ++ * --p1;
-	else {
-	    *p1 = '1';
-	    (*decpt)++;
-	    if (eflag == 0) {
-		if (p > buf)
-		    *p = '0';
-		p++;
-	    }
-	}
-    }
-    *p = '\0';
-    return (buf);
-}
-
-static char *ap_ecvt(double arg, int ndigits, int *decpt, int *sign, char *buf)
-{
-    return (ap_cvt(arg, ndigits, decpt, sign, 1, buf));
-}
-
-static char *ap_fcvt(double arg, int ndigits, int *decpt, int *sign, char *buf)
-{
-    return (ap_cvt(arg, ndigits, decpt, sign, 0, buf));
-}
-
-/*
- * ap_gcvt  - Floating output conversion to
- * minimal length string
- */
-
-static char *ap_gcvt(double number, int ndigit, char *buf, boolean_e altform)
-{
-    int sign, decpt;
-    register char *p1, *p2;
-    register int i;
-    char buf1[NDIG];
-
-    p1 = ap_ecvt(number, ndigit, &decpt, &sign, buf1);
-    p2 = buf;
-    if (sign)
-	*p2++ = '-';
-    for (i = ndigit - 1; i > 0 && p1[i] == '0'; i--)
-	ndigit--;
-    if ((decpt >= 0 && decpt - ndigit > 4)
-	|| (decpt < 0 && decpt < -3)) {		/* use E-style */
-	decpt--;
-	*p2++ = *p1++;
-	*p2++ = '.';
-	for (i = 1; i < ndigit; i++)
-	    *p2++ = *p1++;
-	*p2++ = 'e';
-	if (decpt < 0) {
-	    decpt = -decpt;
-	    *p2++ = '-';
-	}
-	else
-	    *p2++ = '+';
-	if (decpt / 100 > 0)
-	    *p2++ = decpt / 100 + '0';
-	if (decpt / 10 > 0)
-	    *p2++ = (decpt % 100) / 10 + '0';
-	*p2++ = decpt % 10 + '0';
-    }
-    else {
-	if (decpt <= 0) {
-	    if (*p1 != '0')
-		*p2++ = '.';
-	    while (decpt < 0) {
-		decpt++;
-		*p2++ = '0';
-	    }
-	}
-	for (i = 1; i <= ndigit; i++) {
-	    *p2++ = *p1++;
-	    if (i == decpt)
-		*p2++ = '.';
-	}
-	if (ndigit < decpt) {
-	    while (ndigit++ < decpt)
-		*p2++ = '0';
-	    *p2++ = '.';
-	}
-    }
-    if (p2[-1] == '.' && !altform)
-	p2--;
-    *p2 = '\0';
-    return (buf);
-}
-
-/*
- * The INS_CHAR macro inserts a character in the buffer and writes
- * the buffer back to disk if necessary
- * It uses the char pointers sp and bep:
- *      sp points to the next available character in the buffer
- *      bep points to the end-of-buffer+1
- * While using this macro, note that the nextb pointer is NOT updated.
- *
- * NOTE: Evaluation of the c argument should not have any side-effects
- */
-#define INS_CHAR(c, sp, bep, cc)				\
-	    {							\
-		if (sp >= bep) {				\
-		    vbuff->curpos = sp;                         \
-		    if (flush_func(vbuff))			\
-			return -1;				\
-		    sp = vbuff->curpos;				\
-		    bep = vbuff->endpos;			\
-		} 						\
-		*sp++ = (c);					\
-		cc++; 						\
-	    }
-
-#define NUM( c )			( c - '0' )
-
-#define STR_TO_DEC( str, num )		\
-    num = NUM( *str++ ) ;		\
-    while ( ap_isdigit( *str ) )		\
-    {					\
-	num *= 10 ;			\
-	num += NUM( *str++ ) ;		\
-    }
-
-/*
- * This macro does zero padding so that the precision
- * requirement is satisfied. The padding is done by
- * adding '0's to the left of the string that is going
- * to be printed.
- */
-#define FIX_PRECISION( adjust, precision, s, s_len )	\
-    if ( adjust )					\
-	while ( s_len < precision )			\
-	{						\
-	    *--s = '0' ;				\
-	    s_len++ ;					\
-	}
-
-/*
- * Macro that does padding. The padding is done by printing
- * the character ch.
- */
-#define PAD( width, len, ch )	do		\
-	{					\
-	    INS_CHAR( ch, sp, bep, cc ) ;	\
-	    width-- ;				\
-	}					\
-	while ( width > len )
-
-/*
- * Prefix the character ch to the string str
- * Increase length
- * Set the has_prefix flag
- */
-#define PREFIX( str, length, ch )	 *--str = ch ; length++ ; has_prefix = YES
-
-
-/*
- * Convert num to its decimal format.
- * Return value:
- *   - a pointer to a string containing the number (no sign)
- *   - len contains the length of the string
- *   - is_negative is set to TRUE or FALSE depending on the sign
- *     of the number (always set to FALSE if is_unsigned is TRUE)
- *
- * The caller provides a buffer for the string: that is the buf_end argument
- * which is a pointer to the END of the buffer + 1 (i.e. if the buffer
- * is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
- *
- * Note: we have 2 versions. One is used when we need to use quads
- * (conv_10_quad), the other when we don't (conv_10). We're assuming the
- * latter is faster.
- */
-static char *conv_10(register wide_int num, register bool_int is_unsigned,
-		     register bool_int *is_negative, char *buf_end,
-		     register int *len)
-{
-    register char *p = buf_end;
-    register u_wide_int magnitude;
-
-    if (is_unsigned) {
-	magnitude = (u_wide_int) num;
-	*is_negative = FALSE;
-    }
-    else {
-	*is_negative = (num < 0);
-
-	/*
-	 * On a 2's complement machine, negating the most negative integer 
-	 * results in a number that cannot be represented as a signed integer.
-	 * Here is what we do to obtain the number's magnitude:
-	 *      a. add 1 to the number
-	 *      b. negate it (becomes positive)
-	 *      c. convert it to unsigned
-	 *      d. add 1
-	 */
-	if (*is_negative) {
-	    wide_int t = num + 1;
-
-	    magnitude = ((u_wide_int) -t) + 1;
-	}
-	else
-	    magnitude = (u_wide_int) num;
-    }
-
-    /*
-     * We use a do-while loop so that we write at least 1 digit 
-     */
-    do {
-	register u_wide_int new_magnitude = magnitude / 10;
-
-	*--p = (char) (magnitude - new_magnitude * 10 + '0');
-	magnitude = new_magnitude;
-    }
-    while (magnitude);
-
-    *len = buf_end - p;
-    return (p);
-}
-
-static char *conv_10_quad(widest_int num, register bool_int is_unsigned,
-		     register bool_int *is_negative, char *buf_end,
-		     register int *len)
-{
-    register char *p = buf_end;
-    u_widest_int magnitude;
-
-    /*
-     * We see if we can use the faster non-quad version by checking the
-     * number against the largest long value it can be. If <=, we
-     * punt to the quicker version.
-     */
-    if ((num <= ULONG_MAX && is_unsigned) || (num <= LONG_MAX && !is_unsigned))
-    	return(conv_10( (wide_int)num, is_unsigned, is_negative,
-	       buf_end, len));
-
-    if (is_unsigned) {
-	magnitude = (u_widest_int) num;
-	*is_negative = FALSE;
-    }
-    else {
-	*is_negative = (num < 0);
-
-	/*
-	 * On a 2's complement machine, negating the most negative integer 
-	 * results in a number that cannot be represented as a signed integer.
-	 * Here is what we do to obtain the number's magnitude:
-	 *      a. add 1 to the number
-	 *      b. negate it (becomes positive)
-	 *      c. convert it to unsigned
-	 *      d. add 1
-	 */
-	if (*is_negative) {
-	    widest_int t = num + 1;
-
-	    magnitude = ((u_widest_int) -t) + 1;
-	}
-	else
-	    magnitude = (u_widest_int) num;
-    }
-
-    /*
-     * We use a do-while loop so that we write at least 1 digit 
-     */
-    do {
-	u_widest_int new_magnitude = magnitude / 10;
-
-	*--p = (char) (magnitude - new_magnitude * 10 + '0');
-	magnitude = new_magnitude;
-    }
-    while (magnitude);
-
-    *len = buf_end - p;
-    return (p);
-}
-
-
-
-static char *conv_in_addr(struct in_addr *ia, char *buf_end, int *len)
-{
-    unsigned addr = ntohl(ia->s_addr);
-    char *p = buf_end;
-    bool_int is_negative;
-    int sub_len;
-
-    p = conv_10((addr & 0x000000FF)      , TRUE, &is_negative, p, &sub_len);
-    *--p = '.';
-    p = conv_10((addr & 0x0000FF00) >>  8, TRUE, &is_negative, p, &sub_len);
-    *--p = '.';
-    p = conv_10((addr & 0x00FF0000) >> 16, TRUE, &is_negative, p, &sub_len);
-    *--p = '.';
-    p = conv_10((addr & 0xFF000000) >> 24, TRUE, &is_negative, p, &sub_len);
-
-    *len = buf_end - p;
-    return (p);
-}
-
-
-
-static char *conv_sockaddr_in(struct sockaddr_in *si, char *buf_end, int *len)
-{
-    char *p = buf_end;
-    bool_int is_negative;
-    int sub_len;
-
-    p = conv_10(ntohs(si->sin_port), TRUE, &is_negative, p, &sub_len);
-    *--p = ':';
-    p = conv_in_addr(&si->sin_addr, p, &sub_len);
-
-    *len = buf_end - p;
-    return (p);
-}
-
-
-
-/*
- * Convert a floating point number to a string formats 'f', 'e' or 'E'.
- * The result is placed in buf, and len denotes the length of the string
- * The sign is returned in the is_negative argument (and is not placed
- * in buf).
- */
-static char *conv_fp(register char format, register double num,
-    boolean_e add_dp, int precision, bool_int *is_negative,
-    char *buf, int *len)
-{
-    register char *s = buf;
-    register char *p;
-    int decimal_point;
-    char buf1[NDIG];
-
-    if (format == 'f')
-	p = ap_fcvt(num, precision, &decimal_point, is_negative, buf1);
-    else			/* either e or E format */
-	p = ap_ecvt(num, precision + 1, &decimal_point, is_negative, buf1);
-
-    /*
-     * Check for Infinity and NaN
-     */
-    if (ap_isalpha(*p)) {
-	*len = strlen(strcpy(buf, p));
-	*is_negative = FALSE;
-	return (buf);
-    }
-
-    if (format == 'f') {
-	if (decimal_point <= 0) {
-	    *s++ = '0';
-	    if (precision > 0) {
-		*s++ = '.';
-		while (decimal_point++ < 0)
-		    *s++ = '0';
-	    }
-	    else if (add_dp)
-		*s++ = '.';
-	}
-	else {
-	    while (decimal_point-- > 0)
-		*s++ = *p++;
-	    if (precision > 0 || add_dp)
-		*s++ = '.';
-	}
-    }
-    else {
-	*s++ = *p++;
-	if (precision > 0 || add_dp)
-	    *s++ = '.';
-    }
-
-    /*
-     * copy the rest of p, the NUL is NOT copied
-     */
-    while (*p)
-	*s++ = *p++;
-
-    if (format != 'f') {
-	char temp[EXPONENT_LENGTH];	/* for exponent conversion */
-	int t_len;
-	bool_int exponent_is_negative;
-
-	*s++ = format;		/* either e or E */
-	decimal_point--;
-	if (decimal_point != 0) {
-	    p = conv_10((wide_int) decimal_point, FALSE, &exponent_is_negative,
-			&temp[EXPONENT_LENGTH], &t_len);
-	    *s++ = exponent_is_negative ? '-' : '+';
-
-	    /*
-	     * Make sure the exponent has at least 2 digits
-	     */
-	    if (t_len == 1)
-		*s++ = '0';
-	    while (t_len--)
-		*s++ = *p++;
-	}
-	else {
-	    *s++ = '+';
-	    *s++ = '0';
-	    *s++ = '0';
-	}
-    }
-
-    *len = s - buf;
-    return (buf);
-}
-
-
-/*
- * Convert num to a base X number where X is a power of 2. nbits determines X.
- * For example, if nbits is 3, we do base 8 conversion
- * Return value:
- *      a pointer to a string containing the number
- *
- * The caller provides a buffer for the string: that is the buf_end argument
- * which is a pointer to the END of the buffer + 1 (i.e. if the buffer
- * is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
- *
- * As with conv_10, we have a faster version which is used when
- * the number isn't quad size.
- */
-static char *conv_p2(register u_wide_int num, register int nbits,
-		     char format, char *buf_end, register int *len)
-{
-    register int mask = (1 << nbits) - 1;
-    register char *p = buf_end;
-    static const char low_digits[] = "0123456789abcdef";
-    static const char upper_digits[] = "0123456789ABCDEF";
-    register const char *digits = (format == 'X') ? upper_digits : low_digits;
-
-    do {
-	*--p = digits[num & mask];
-	num >>= nbits;
-    }
-    while (num);
-
-    *len = buf_end - p;
-    return (p);
-}
-
-static char *conv_p2_quad(u_widest_int num, register int nbits,
-		     char format, char *buf_end, register int *len)
-{
-    register int mask = (1 << nbits) - 1;
-    register char *p = buf_end;
-    static const char low_digits[] = "0123456789abcdef";
-    static const char upper_digits[] = "0123456789ABCDEF";
-    register const char *digits = (format == 'X') ? upper_digits : low_digits;
-
-    if (num <= ULONG_MAX)
-    	return(conv_p2( (u_wide_int)num, nbits, format, buf_end, len));
-
-    do {
-	*--p = digits[num & mask];
-	num >>= nbits;
-    }
-    while (num);
-
-    *len = buf_end - p;
-    return (p);
-}
-
-
-/*
- * Do format conversion placing the output in buffer
- */
-API_EXPORT(int) ap_vformatter(int (*flush_func)(ap_vformatter_buff_t *),
-    ap_vformatter_buff_t *vbuff, const char *fmt, va_list ap)
-{
-    register char *sp;
-    register char *bep;
-    register int cc = 0;
-    register int i;
-
-    register char *s = NULL;
-    char *q;
-    int s_len;
-
-    register int min_width = 0;
-    int precision = 0;
-    enum {
-	LEFT, RIGHT
-    } adjust;
-    char pad_char;
-    char prefix_char;
-
-    double fp_num;
-    widest_int i_quad = (widest_int) 0;
-    u_widest_int ui_quad;
-    wide_int i_num = (wide_int) 0;
-    u_wide_int ui_num;
-
-    char num_buf[NUM_BUF_SIZE];
-    char char_buf[2];		/* for printing %% and %<unknown> */
-
-    enum var_type_enum {
-    	IS_QUAD, IS_LONG, IS_SHORT, IS_INT
-    };
-    enum var_type_enum var_type = IS_INT;
-
-    /*
-     * Flag variables
-     */
-    boolean_e alternate_form;
-    boolean_e print_sign;
-    boolean_e print_blank;
-    boolean_e adjust_precision;
-    boolean_e adjust_width;
-    bool_int is_negative;
-
-    sp = vbuff->curpos;
-    bep = vbuff->endpos;
-
-    while (*fmt) {
-	if (*fmt != '%') {
-	    INS_CHAR(*fmt, sp, bep, cc);
-	}
-	else {
-	    /*
-	     * Default variable settings
-	     */
-	    adjust = RIGHT;
-	    alternate_form = print_sign = print_blank = NO;
-	    pad_char = ' ';
-	    prefix_char = NUL;
-
-	    fmt++;
-
-	    /*
-	     * Try to avoid checking for flags, width or precision
-	     */
-	    if (!ap_islower(*fmt)) {
-		/*
-		 * Recognize flags: -, #, BLANK, +
-		 */
-		for (;; fmt++) {
-		    if (*fmt == '-')
-			adjust = LEFT;
-		    else if (*fmt == '+')
-			print_sign = YES;
-		    else if (*fmt == '#')
-			alternate_form = YES;
-		    else if (*fmt == ' ')
-			print_blank = YES;
-		    else if (*fmt == '0')
-			pad_char = '0';
-		    else
-			break;
-		}
-
-		/*
-		 * Check if a width was specified
-		 */
-		if (ap_isdigit(*fmt)) {
-		    STR_TO_DEC(fmt, min_width);
-		    adjust_width = YES;
-		}
-		else if (*fmt == '*') {
-		    min_width = va_arg(ap, int);
-		    fmt++;
-		    adjust_width = YES;
-		    if (min_width < 0) {
-			adjust = LEFT;
-			min_width = -min_width;
-		    }
-		}
-		else
-		    adjust_width = NO;
-
-		/*
-		 * Check if a precision was specified
-		 *
-		 * XXX: an unreasonable amount of precision may be specified
-		 * resulting in overflow of num_buf. Currently we
-		 * ignore this possibility.
-		 */
-		if (*fmt == '.') {
-		    adjust_precision = YES;
-		    fmt++;
-		    if (ap_isdigit(*fmt)) {
-			STR_TO_DEC(fmt, precision);
-		    }
-		    else if (*fmt == '*') {
-			precision = va_arg(ap, int);
-			fmt++;
-			if (precision < 0)
-			    precision = 0;
-		    }
-		    else
-			precision = 0;
-		}
-		else
-		    adjust_precision = NO;
-	    }
-	    else
-		adjust_precision = adjust_width = NO;
-
-	    /*
-	     * Modifier check
-	     */
-	    if (*fmt == 'q') {
-		var_type = IS_QUAD;
-		fmt++;
-	    }
-	    else if (*fmt == 'l') {
-		var_type = IS_LONG;
-		fmt++;
-	    }
-	    else if (*fmt == 'h') {
-		var_type = IS_SHORT;
-		fmt++;
-	    }
-	    else {
-		var_type = IS_INT;
-	    }
-
-	    /*
-	     * Argument extraction and printing.
-	     * First we determine the argument type.
-	     * Then, we convert the argument to a string.
-	     * On exit from the switch, s points to the string that
-	     * must be printed, s_len has the length of the string
-	     * The precision requirements, if any, are reflected in s_len.
-	     *
-	     * NOTE: pad_char may be set to '0' because of the 0 flag.
-	     *   It is reset to ' ' by non-numeric formats
-	     */
-	    switch (*fmt) {
-	    case 'u':
-	    	if (var_type == IS_QUAD) {
-		    i_quad = va_arg(ap, u_widest_int);
-		    s = conv_10_quad(i_quad, 1, &is_negative,
-			    &num_buf[NUM_BUF_SIZE], &s_len);
-		}
-		else {
-		    if (var_type == IS_LONG)
-			i_num = (wide_int) va_arg(ap, u_wide_int);
-		    else if (var_type == IS_SHORT)
-			i_num = (wide_int) (unsigned short) va_arg(ap, unsigned int);
-		    else
-			i_num = (wide_int) va_arg(ap, unsigned int);
-		    s = conv_10(i_num, 1, &is_negative,
-			    &num_buf[NUM_BUF_SIZE], &s_len);
-		}
-		FIX_PRECISION(adjust_precision, precision, s, s_len);
-		break;
-
-	    case 'd':
-	    case 'i':
-	    	if (var_type == IS_QUAD) {
-		    i_quad = va_arg(ap, widest_int);
-		    s = conv_10_quad(i_quad, 0, &is_negative,
-			    &num_buf[NUM_BUF_SIZE], &s_len);
-		}
-		else {
-		    if (var_type == IS_LONG)
-			i_num = (wide_int) va_arg(ap, wide_int);
-		    else if (var_type == IS_SHORT)
-			i_num = (wide_int) (short) va_arg(ap, int);
-		    else
-			i_num = (wide_int) va_arg(ap, int);
-		    s = conv_10(i_num, 0, &is_negative,
-			    &num_buf[NUM_BUF_SIZE], &s_len);
-		}
-		FIX_PRECISION(adjust_precision, precision, s, s_len);
-
-		if (is_negative)
-		    prefix_char = '-';
-		else if (print_sign)
-		    prefix_char = '+';
-		else if (print_blank)
-		    prefix_char = ' ';
-		break;
-
-
-	    case 'o':
-		if (var_type == IS_QUAD) {
-		    ui_quad = va_arg(ap, u_widest_int);
-		    s = conv_p2_quad(ui_quad, 3, *fmt,
-			    &num_buf[NUM_BUF_SIZE], &s_len);
-		}
-		else {
-		    if (var_type == IS_LONG)
-			ui_num = (u_wide_int) va_arg(ap, u_wide_int);
-		    else if (var_type == IS_SHORT)
-			ui_num = (u_wide_int) (unsigned short) va_arg(ap, unsigned int);
-		    else
-			ui_num = (u_wide_int) va_arg(ap, unsigned int);
-		    s = conv_p2(ui_num, 3, *fmt,
-			    &num_buf[NUM_BUF_SIZE], &s_len);
-		}
-		FIX_PRECISION(adjust_precision, precision, s, s_len);
-		if (alternate_form && *s != '0') {
-		    *--s = '0';
-		    s_len++;
-		}
-		break;
-
-
-	    case 'x':
-	    case 'X':
-		if (var_type == IS_QUAD) {
-		    ui_quad = va_arg(ap, u_widest_int);
-		    s = conv_p2_quad(ui_quad, 4, *fmt,
-			    &num_buf[NUM_BUF_SIZE], &s_len);
-		}
-		else {
-		    if (var_type == IS_LONG)
-			ui_num = (u_wide_int) va_arg(ap, u_wide_int);
-		    else if (var_type == IS_SHORT)
-			ui_num = (u_wide_int) (unsigned short) va_arg(ap, unsigned int);
-		    else
-			ui_num = (u_wide_int) va_arg(ap, unsigned int);
-		    s = conv_p2(ui_num, 4, *fmt,
-			    &num_buf[NUM_BUF_SIZE], &s_len);
-		}
-		FIX_PRECISION(adjust_precision, precision, s, s_len);
-		if (alternate_form && i_num != 0) {
-		    *--s = *fmt;	/* 'x' or 'X' */
-		    *--s = '0';
-		    s_len += 2;
-		}
-		break;
-
-
-	    case 's':
-		s = va_arg(ap, char *);
-		if (s != NULL) {
-		    s_len = strlen(s);
-		    if (adjust_precision && precision < s_len)
-			s_len = precision;
-		}
-		else {
-		    s = S_NULL;
-		    s_len = S_NULL_LEN;
-		}
-		pad_char = ' ';
-		break;
-
-
-	    case 'f':
-	    case 'e':
-	    case 'E':
-		fp_num = va_arg(ap, double);
-		/*
-		 * * We use &num_buf[ 1 ], so that we have room for the sign
-		 */
-		s = conv_fp(*fmt, fp_num, alternate_form,
-			(adjust_precision == NO) ? FLOAT_DIGITS : precision,
-			    &is_negative, &num_buf[1], &s_len);
-		if (is_negative)
-		    prefix_char = '-';
-		else if (print_sign)
-		    prefix_char = '+';
-		else if (print_blank)
-		    prefix_char = ' ';
-		break;
-
-
-	    case 'g':
-	    case 'G':
-		if (adjust_precision == NO)
-		    precision = FLOAT_DIGITS;
-		else if (precision == 0)
-		    precision = 1;
-		/*
-		 * * We use &num_buf[ 1 ], so that we have room for the sign
-		 */
-		s = ap_gcvt(va_arg(ap, double), precision, &num_buf[1],
-		            alternate_form);
-		if (*s == '-')
-		    prefix_char = *s++;
-		else if (print_sign)
-		    prefix_char = '+';
-		else if (print_blank)
-		    prefix_char = ' ';
-
-		s_len = strlen(s);
-
-		if (alternate_form && (q = strchr(s, '.')) == NULL) {
-		    s[s_len++] = '.';
-		    s[s_len] = '\0'; /* delimit for following strchr() */
-		}
-		if (*fmt == 'G' && (q = strchr(s, 'e')) != NULL)
-		    *q = 'E';
-		break;
-
-
-	    case 'c':
-		char_buf[0] = (char) (va_arg(ap, int));
-		s = &char_buf[0];
-		s_len = 1;
-		pad_char = ' ';
-		break;
-
-
-	    case '%':
-		char_buf[0] = '%';
-		s = &char_buf[0];
-		s_len = 1;
-		pad_char = ' ';
-		break;
-
-
-	    case 'n':
-	    	if (var_type == IS_QUAD)
-		    *(va_arg(ap, widest_int *)) = cc;
-		else if (var_type == IS_LONG)
-		    *(va_arg(ap, long *)) = cc;
-		else if (var_type == IS_SHORT)
-		    *(va_arg(ap, short *)) = cc;
-		else
-		    *(va_arg(ap, int *)) = cc;
-		break;
-
-		/*
-		 * This is where we extend the printf format, with a second
-		 * type specifier
-		 */
-	    case 'p':
-		switch(*++fmt) {
-		    /*
-		     * If the pointer size is equal to or smaller than the size
-		     * of the largest unsigned int, we convert the pointer to a
-		     * hex number, otherwise we print "%p" to indicate that we
-		     * don't handle "%p".
-		     */
-		case 'p':
-#ifdef AP_VOID_P_IS_QUAD
-		    if (sizeof(void *) <= sizeof(u_widest_int)) {
-		    	ui_quad = (u_widest_int) va_arg(ap, void *);
-			s = conv_p2_quad(ui_quad, 4, 'x',
-				&num_buf[NUM_BUF_SIZE], &s_len);
-		    }
-#else
-		    if (sizeof(void *) <= sizeof(u_wide_int)) {
-		    	ui_num = (u_wide_int) va_arg(ap, void *);
-			s = conv_p2(ui_num, 4, 'x',
-				&num_buf[NUM_BUF_SIZE], &s_len);
-		    }
-#endif
-		    else {
-			s = "%p";
-			s_len = 2;
-			prefix_char = NUL;
-		    }
-		    pad_char = ' ';
-		    break;
-
-		    /* print a struct sockaddr_in as a.b.c.d:port */
-		case 'I':
-		    {
-			struct sockaddr_in *si;
-
-			si = va_arg(ap, struct sockaddr_in *);
-			if (si != NULL) {
-			    s = conv_sockaddr_in(si, &num_buf[NUM_BUF_SIZE], &s_len);
-			    if (adjust_precision && precision < s_len)
-				s_len = precision;
-			}
-			else {
-			    s = S_NULL;
-			    s_len = S_NULL_LEN;
-			}
-			pad_char = ' ';
-		    }
-		    break;
-
-		    /* print a struct in_addr as a.b.c.d */
-		case 'A':
-		    {
-			struct in_addr *ia;
-
-			ia = va_arg(ap, struct in_addr *);
-			if (ia != NULL) {
-			    s = conv_in_addr(ia, &num_buf[NUM_BUF_SIZE], &s_len);
-			    if (adjust_precision && precision < s_len)
-				s_len = precision;
-			}
-			else {
-			    s = S_NULL;
-			    s_len = S_NULL_LEN;
-			}
-			pad_char = ' ';
-		    }
-		    break;
-
-		case NUL:
-		    /* if %p ends the string, oh well ignore it */
-		    continue;
-
-		default:
-		    s = "bogus %p";
-		    s_len = 8;
-		    prefix_char = NUL;
-		    break;
-		}
-		break;
-
-	    case NUL:
-		/*
-		 * The last character of the format string was %.
-		 * We ignore it.
-		 */
-		continue;
-
-
-		/*
-		 * The default case is for unrecognized %'s.
-		 * We print %<char> to help the user identify what
-		 * option is not understood.
-		 * This is also useful in case the user wants to pass
-		 * the output of format_converter to another function
-		 * that understands some other %<char> (like syslog).
-		 * Note that we can't point s inside fmt because the
-		 * unknown <char> could be preceded by width etc.
-		 */
-	    default:
-		char_buf[0] = '%';
-		char_buf[1] = *fmt;
-		s = char_buf;
-		s_len = 2;
-		pad_char = ' ';
-		break;
-	    }
-
-	    if (prefix_char != NUL && s != S_NULL && s != char_buf) {
-		*--s = prefix_char;
-		s_len++;
-	    }
-
-	    if (adjust_width && adjust == RIGHT && min_width > s_len) {
-		if (pad_char == '0' && prefix_char != NUL) {
-		    INS_CHAR(*s, sp, bep, cc);
-		    s++;
-		    s_len--;
-		    min_width--;
-		}
-		PAD(min_width, s_len, pad_char);
-	    }
-
-	    /*
-	     * Print the string s. 
-	     */
-	    for (i = s_len; i != 0; i--) {
-		INS_CHAR(*s, sp, bep, cc);
-		s++;
-	    }
-
-	    if (adjust_width && adjust == LEFT && min_width > s_len)
-		PAD(min_width, s_len, pad_char);
-	}
-	fmt++;
-    }
-    vbuff->curpos = sp;
-    return cc;
-}
-
-
-static int snprintf_flush(ap_vformatter_buff_t *vbuff)
-{
-    /* if the buffer fills we have to abort immediately, there is no way
-     * to "flush" an ap_snprintf... there's nowhere to flush it to.
-     */
-    return -1;
-}
-
-
-API_EXPORT(int) ap_snprintf(char *buf, size_t len, const char *format,...)
-{
-    int cc;
-    va_list ap;
-    ap_vformatter_buff_t vbuff;
-
-    if (len == 0)
-	return 0;
-
-    /* save one byte for nul terminator */
-    vbuff.curpos = buf;
-    vbuff.endpos = buf + len - 1;
-    va_start(ap, format);
-    cc = ap_vformatter(snprintf_flush, &vbuff, format, ap);
-    va_end(ap);
-    *vbuff.curpos = '\0';
-    return (cc == -1) ? len : cc;
-}
-
-
-API_EXPORT(int) ap_vsnprintf(char *buf, size_t len, const char *format,
-			     va_list ap)
-{
-    int cc;
-    ap_vformatter_buff_t vbuff;
-
-    if (len == 0)
-	return 0;
-
-    /* save one byte for nul terminator */
-    vbuff.curpos = buf;
-    vbuff.endpos = buf + len - 1;
-    cc = ap_vformatter(snprintf_flush, &vbuff, format, ap);
-    *vbuff.curpos = '\0';
-    return (cc == -1) ? len : cc;
-}
diff --git a/lib/apr_tables.c b/lib/apr_tables.c
deleted file mode 100644
index 79181ab8283..00000000000
--- a/lib/apr_tables.c
+++ /dev/null
@@ -1,769 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-/*
- * Resource allocation code... the code here is responsible for making
- * sure that nothing leaks.
- *
- * rst --- 4/95 --- 6/95
- */
-
-#include "apr_private.h"
-
-#include "apr_general.h"
-#include "apr_pools.h"
-#include "apr_lib.h"
-#include "misc.h"
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-/*****************************************************************
- * This file contains array and ap_table_t functions only.
- */
-
-/*****************************************************************
- *
- * The 'array' functions...
- */
-
-static void make_array_core(ap_array_header_t *res, ap_pool_t *c,
-			    int nelts, int elt_size)
-{
-    /*
-     * Assure sanity if someone asks for
-     * array of zero elts.
-     */
-    if (nelts < 1) {
-	nelts = 1;
-    }
-
-    res->elts = ap_pcalloc(c, nelts * elt_size);
-
-    res->cont = c;
-    res->elt_size = elt_size;
-    res->nelts = 0;		/* No active elements yet... */
-    res->nalloc = nelts;	/* ...but this many allocated */
-}
-
-API_EXPORT(ap_array_header_t *) ap_make_array(ap_pool_t *p,
-						int nelts, int elt_size)
-{
-    ap_array_header_t *res;
-
-    res = (ap_array_header_t *) ap_palloc(p, sizeof(ap_array_header_t));
-    make_array_core(res, p, nelts, elt_size);
-    return res;
-}
-
-API_EXPORT(void *) ap_push_array(ap_array_header_t *arr)
-{
-    if (arr->nelts == arr->nalloc) {
-	int new_size = (arr->nalloc <= 0) ? 1 : arr->nalloc * 2;
-	char *new_data;
-
-	new_data = ap_pcalloc(arr->cont, arr->elt_size * new_size);
-
-	memcpy(new_data, arr->elts, arr->nalloc * arr->elt_size);
-	arr->elts = new_data;
-	arr->nalloc = new_size;
-    }
-
-    ++arr->nelts;
-    return arr->elts + (arr->elt_size * (arr->nelts - 1));
-}
-
-API_EXPORT(void) ap_array_cat(ap_array_header_t *dst,
-			       const ap_array_header_t *src)
-{
-    int elt_size = dst->elt_size;
-
-    if (dst->nelts + src->nelts > dst->nalloc) {
-	int new_size = (dst->nalloc <= 0) ? 1 : dst->nalloc * 2;
-	char *new_data;
-
-	while (dst->nelts + src->nelts > new_size) {
-	    new_size *= 2;
-	}
-
-	new_data = ap_pcalloc(dst->cont, elt_size * new_size);
-	memcpy(new_data, dst->elts, dst->nalloc * elt_size);
-
-	dst->elts = new_data;
-	dst->nalloc = new_size;
-    }
-
-    memcpy(dst->elts + dst->nelts * elt_size, src->elts,
-	   elt_size * src->nelts);
-    dst->nelts += src->nelts;
-}
-
-API_EXPORT(ap_array_header_t *) ap_copy_array(ap_pool_t *p,
-						const ap_array_header_t *arr)
-{
-    ap_array_header_t *res = ap_make_array(p, arr->nalloc, arr->elt_size);
-
-    memcpy(res->elts, arr->elts, arr->elt_size * arr->nelts);
-    res->nelts = arr->nelts;
-    return res;
-}
-
-/* This cute function copies the array header *only*, but arranges
- * for the data section to be copied on the first push or arraycat.
- * It's useful when the elements of the array being copied are
- * read only, but new stuff *might* get added on the end; we have the
- * overhead of the full copy only where it is really needed.
- */
-
-static APR_INLINE void copy_array_hdr_core(ap_array_header_t *res,
-					   const ap_array_header_t *arr)
-{
-    res->elts = arr->elts;
-    res->elt_size = arr->elt_size;
-    res->nelts = arr->nelts;
-    res->nalloc = arr->nelts;	/* Force overflow on push */
-}
-
-API_EXPORT(ap_array_header_t *)
-    ap_copy_array_hdr(ap_pool_t *p,
-		       const ap_array_header_t *arr)
-{
-    ap_array_header_t *res;
-
-    res = (ap_array_header_t *) ap_palloc(p, sizeof(ap_array_header_t));
-    res->cont = p;
-    copy_array_hdr_core(res, arr);
-    return res;
-}
-
-/* The above is used here to avoid consing multiple new array bodies... */
-
-API_EXPORT(ap_array_header_t *)
-    ap_append_arrays(ap_pool_t *p,
-		      const ap_array_header_t *first,
-		      const ap_array_header_t *second)
-{
-    ap_array_header_t *res = ap_copy_array_hdr(p, first);
-
-    ap_array_cat(res, second);
-    return res;
-}
-
-/* ap_array_pstrcat generates a new string from the ap_pool_t containing
- * the concatenated sequence of substrings referenced as elements within
- * the array.  The string will be empty if all substrings are empty or null,
- * or if there are no elements in the array.
- * If sep is non-NUL, it will be inserted between elements as a separator.
- */
-API_EXPORT(char *) ap_array_pstrcat(ap_pool_t *p,
-				     const ap_array_header_t *arr,
-				     const char sep)
-{
-    char *cp, *res, **strpp;
-    int i, len;
-
-    if (arr->nelts <= 0 || arr->elts == NULL) {    /* Empty table? */
-        return (char *) ap_pcalloc(p, 1);
-    }
-
-    /* Pass one --- find length of required string */
-
-    len = 0;
-    for (i = 0, strpp = (char **) arr->elts; ; ++strpp) {
-        if (strpp && *strpp != NULL) {
-            len += strlen(*strpp);
-        }
-        if (++i >= arr->nelts) {
-            break;
-	}
-        if (sep) {
-            ++len;
-	}
-    }
-
-    /* Allocate the required string */
-
-    res = (char *) ap_palloc(p, len + 1);
-    cp = res;
-
-    /* Pass two --- copy the argument strings into the result space */
-
-    for (i = 0, strpp = (char **) arr->elts; ; ++strpp) {
-        if (strpp && *strpp != NULL) {
-            len = strlen(*strpp);
-            memcpy(cp, *strpp, len);
-            cp += len;
-        }
-        if (++i >= arr->nelts) {
-            break;
-	}
-        if (sep) {
-            *cp++ = sep;
-	}
-    }
-
-    *cp = '\0';
-
-    /* Return the result string */
-
-    return res;
-}
-
-
-/*****************************************************************
- *
- * The "table" functions.
- */
-
-/*
- * XXX: if you tweak this you should look at is_empty_table() and table_elts()
- * in alloc.h
- */
-#ifdef MAKE_TABLE_PROFILE
-static ap_table_entry_t *table_push(ap_table_t *t)
-{
-    if (t->a.nelts == t->a.nalloc) {
-        return NULL;
-    }
-    return (ap_table_entry_t *) ap_push_array(&t->a);
-}
-#else /* MAKE_TABLE_PROFILE */
-#define table_push(t)	((ap_table_entry_t *) ap_push_array(&(t)->a))
-#endif /* MAKE_TABLE_PROFILE */
-
-
-API_EXPORT(ap_table_t *) ap_make_table(ap_pool_t *p, int nelts)
-{
-    ap_table_t *t = ap_palloc(p, sizeof(ap_table_t));
-
-    make_array_core(&t->a, p, nelts, sizeof(ap_table_entry_t));
-#ifdef MAKE_TABLE_PROFILE
-    t->creator = __builtin_return_address(0);
-#endif
-    return t;
-}
-
-API_EXPORT(ap_table_t *) ap_copy_table(ap_pool_t *p, const ap_table_t *t)
-{
-    ap_table_t *new = ap_palloc(p, sizeof(ap_table_t));
-
-#ifdef POOL_DEBUG
-    /* we don't copy keys and values, so it's necessary that t->a.pool
-     * have a life span at least as long as p
-     */
-    if (!ap_pool_is_ancestor(t->a.cont->pool, p->pool)) {
-	fprintf(stderr, "copy_table: t's pool is not an ancestor of p\n");
-	abort();
-    }
-#endif
-    make_array_core(&new->a, p, t->a.nalloc, sizeof(ap_table_entry_t));
-    memcpy(new->a.elts, t->a.elts, t->a.nelts * sizeof(ap_table_entry_t));
-    new->a.nelts = t->a.nelts;
-    return new;
-}
-
-API_EXPORT(void) ap_clear_table(ap_table_t *t)
-{
-    t->a.nelts = 0;
-}
-
-API_EXPORT(const char *) ap_table_get(const ap_table_t *t, const char *key)
-{
-    ap_table_entry_t *elts = (ap_table_entry_t *) t->a.elts;
-    int i;
-
-    if (key == NULL) {
-	return NULL;
-    }
-
-    for (i = 0; i < t->a.nelts; ++i) {
-	if (!strcasecmp(elts[i].key, key)) {
-	    return elts[i].val;
-	}
-    }
-
-    return NULL;
-}
-
-API_EXPORT(void) ap_table_set(ap_table_t *t, const char *key,
-			       const char *val)
-{
-    register int i, j, k;
-    ap_table_entry_t *elts = (ap_table_entry_t *) t->a.elts;
-    int done = 0;
-
-    for (i = 0; i < t->a.nelts; ) {
-	if (!strcasecmp(elts[i].key, key)) {
-	    if (!done) {
-		elts[i].val = ap_pstrdup(t->a.cont, val);
-		done = 1;
-		++i;
-	    }
-	    else {		/* delete an extraneous element */
-		for (j = i, k = i + 1; k < t->a.nelts; ++j, ++k) {
-		    elts[j].key = elts[k].key;
-		    elts[j].val = elts[k].val;
-		}
-		--t->a.nelts;
-	    }
-	}
-	else {
-	    ++i;
-	}
-    }
-
-    if (!done) {
-	elts = (ap_table_entry_t *) table_push(t);
-	elts->key = ap_pstrdup(t->a.cont, key);
-	elts->val = ap_pstrdup(t->a.cont, val);
-    }
-}
-
-API_EXPORT(void) ap_table_setn(ap_table_t *t, const char *key,
-				const char *val)
-{
-    register int i, j, k;
-    ap_table_entry_t *elts = (ap_table_entry_t *) t->a.elts;
-    int done = 0;
-
-#ifdef POOL_DEBUG
-    {
-	if (!ap_pool_is_ancestor(ap_find_pool(key), t->a.cont->pool)) {
-	    fprintf(stderr, "table_set: key not in ancestor pool of t\n");
-	    abort();
-	}
-	if (!ap_pool_is_ancestor(ap_find_pool(val), t->a.cont->pool)) {
-	    fprintf(stderr, "table_set: val not in ancestor pool of t\n");
-	    abort();
-	}
-    }
-#endif
-
-    for (i = 0; i < t->a.nelts; ) {
-	if (!strcasecmp(elts[i].key, key)) {
-	    if (!done) {
-		elts[i].val = (char *)val;
-		done = 1;
-		++i;
-	    }
-	    else {		/* delete an extraneous element */
-		for (j = i, k = i + 1; k < t->a.nelts; ++j, ++k) {
-		    elts[j].key = elts[k].key;
-		    elts[j].val = elts[k].val;
-		}
-		--t->a.nelts;
-	    }
-	}
-	else {
-	    ++i;
-	}
-    }
-
-    if (!done) {
-	elts = (ap_table_entry_t *) table_push(t);
-	elts->key = (char *)key;
-	elts->val = (char *)val;
-    }
-}
-
-API_EXPORT(void) ap_table_unset(ap_table_t *t, const char *key)
-{
-    register int i, j, k;
-    ap_table_entry_t *elts = (ap_table_entry_t *) t->a.elts;
-
-    for (i = 0; i < t->a.nelts; ) {
-	if (!strcasecmp(elts[i].key, key)) {
-
-	    /* found an element to skip over
-	     * there are any number of ways to remove an element from
-	     * a contiguous block of memory.  I've chosen one that
-	     * doesn't do a memcpy/bcopy/array_delete, *shrug*...
-	     */
-	    for (j = i, k = i + 1; k < t->a.nelts; ++j, ++k) {
-		elts[j].key = elts[k].key;
-		elts[j].val = elts[k].val;
-	    }
-	    --t->a.nelts;
-	}
-	else {
-	    ++i;
-	}
-    }
-}
-
-API_EXPORT(void) ap_table_merge(ap_table_t *t, const char *key,
-				 const char *val)
-{
-    ap_table_entry_t *elts = (ap_table_entry_t *) t->a.elts;
-    int i;
-
-    for (i = 0; i < t->a.nelts; ++i) {
-	if (!strcasecmp(elts[i].key, key)) {
-	    elts[i].val = ap_pstrcat(t->a.cont, elts[i].val, ", ", val, NULL);
-	    return;
-	}
-    }
-
-    elts = (ap_table_entry_t *) table_push(t);
-    elts->key = ap_pstrdup(t->a.cont, key);
-    elts->val = ap_pstrdup(t->a.cont, val);
-}
-
-API_EXPORT(void) ap_table_mergen(ap_table_t *t, const char *key,
-				  const char *val)
-{
-    ap_table_entry_t *elts = (ap_table_entry_t *) t->a.elts;
-    int i;
-
-#ifdef POOL_DEBUG
-    {
-	if (!ap_pool_is_ancestor(ap_find_pool(key), t->a.cont->pool)) {
-	    fprintf(stderr, "table_set: key not in ancestor pool of t\n");
-	    abort();
-	}
-	if (!ap_pool_is_ancestor(ap_find_pool(val), t->a.cont->pool)) {
-	    fprintf(stderr, "table_set: key not in ancestor pool of t\n");
-	    abort();
-	}
-    }
-#endif
-
-    for (i = 0; i < t->a.nelts; ++i) {
-	if (!strcasecmp(elts[i].key, key)) {
-	    elts[i].val = ap_pstrcat(t->a.cont, elts[i].val, ", ", val, NULL);
-	    return;
-	}
-    }
-
-    elts = (ap_table_entry_t *) table_push(t);
-    elts->key = (char *)key;
-    elts->val = (char *)val;
-}
-
-API_EXPORT(void) ap_table_add(ap_table_t *t, const char *key,
-			       const char *val)
-{
-    ap_table_entry_t *elts = (ap_table_entry_t *) t->a.elts;
-
-    elts = (ap_table_entry_t *) table_push(t);
-    elts->key = ap_pstrdup(t->a.cont, key);
-    elts->val = ap_pstrdup(t->a.cont, val);
-}
-
-API_EXPORT(void) ap_table_addn(ap_table_t *t, const char *key,
-				const char *val)
-{
-    ap_table_entry_t *elts = (ap_table_entry_t *) t->a.elts;
-
-#ifdef POOL_DEBUG
-    {
-	if (!ap_pool_is_ancestor(ap_find_pool(key), t->a.cont->pool)) {
-	    fprintf(stderr, "table_set: key not in ancestor pool of t\n");
-	    abort();
-	}
-	if (!ap_pool_is_ancestor(ap_find_pool(val), t->a.cont->pool)) {
-	    fprintf(stderr, "table_set: key not in ancestor pool of t\n");
-	    abort();
-	}
-    }
-#endif
-
-    elts = (ap_table_entry_t *) table_push(t);
-    elts->key = (char *)key;
-    elts->val = (char *)val;
-}
-
-API_EXPORT(ap_table_t *) ap_overlay_tables(ap_pool_t *p,
-					     const ap_table_t *overlay,
-					     const ap_table_t *base)
-{
-    ap_table_t *res;
-
-#ifdef POOL_DEBUG
-    /* we don't copy keys and values, so it's necessary that
-     * overlay->a.pool and base->a.pool have a life span at least
-     * as long as p
-     */
-    if (!ap_pool_is_ancestor(overlay->a.cont->pool, p->pool)) {
-	fprintf(stderr,
-		"overlay_tables: overlay's pool is not an ancestor of p\n");
-	abort();
-    }
-    if (!ap_pool_is_ancestor(base->a.cont->pool, p->pool)) {
-	fprintf(stderr,
-		"overlay_tables: base's pool is not an ancestor of p\n");
-	abort();
-    }
-#endif
-
-    res = ap_palloc(p, sizeof(ap_table_t));
-    /* behave like append_arrays */
-    res->a.cont = p;
-    copy_array_hdr_core(&res->a, &overlay->a);
-    ap_array_cat(&res->a, &base->a);
-
-    return res;
-}
-
-/* And now for something completely abstract ...
-
- * For each key value given as a vararg:
- *   run the function pointed to as
- *     int comp(void *r, char *key, char *value);
- *   on each valid key-value pair in the ap_table_t t that matches the vararg key,
- *   or once for every valid key-value pair if the vararg list is empty,
- *   until the function returns false (0) or we finish the table.
- *
- * Note that we restart the traversal for each vararg, which means that
- * duplicate varargs will result in multiple executions of the function
- * for each matching key.  Note also that if the vararg list is empty,
- * only one traversal will be made and will cut short if comp returns 0.
- *
- * Note that the table_get and table_merge functions assume that each key in
- * the ap_table_t is unique (i.e., no multiple entries with the same key).  This
- * function does not make that assumption, since it (unfortunately) isn't
- * true for some of Apache's tables.
- *
- * Note that rec is simply passed-on to the comp function, so that the
- * caller can pass additional info for the task.
- */
-API_EXPORT(void) ap_table_do(int (*comp) (void *, const char *, const char *),
-			      void *rec, const ap_table_t *t, ...)
-{
-    va_list vp;
-    char *argp;
-    ap_table_entry_t *elts = (ap_table_entry_t *) t->a.elts;
-    int rv, i;
-
-    va_start(vp, t);
-
-    argp = va_arg(vp, char *);
-
-    do {
-	for (rv = 1, i = 0; rv && (i < t->a.nelts); ++i) {
-	    if (elts[i].key && (!argp || !strcasecmp(elts[i].key, argp))) {
-		rv = (*comp) (rec, elts[i].key, elts[i].val);
-	    }
-	}
-    } while (argp && ((argp = va_arg(vp, char *)) != NULL));
-
-    va_end(vp);
-}
-
-/* Curse libc and the fact that it doesn't guarantee a stable sort.  We
- * have to enforce stability ourselves by using the order field.  If it
- * provided a stable sort then we wouldn't even need temporary storage to
- * do the work below. -djg
- *
- * ("stable sort" means that equal keys retain their original relative
- * ordering in the output.)
- */
-typedef struct {
-    char *key;
-    char *val;
-    int order;
-} overlap_key;
-
-static int sort_overlap(const void *va, const void *vb)
-{
-    const overlap_key *a = va;
-    const overlap_key *b = vb;
-    int r;
-
-    r = strcasecmp(a->key, b->key);
-    if (r) {
-	return r;
-    }
-    return a->order - b->order;
-}
-
-/* prefer to use the stack for temp storage for overlaps smaller than this */
-#ifndef ap_OVERLAP_TABLES_ON_STACK
-#define ap_OVERLAP_TABLES_ON_STACK	(512)
-#endif
-
-API_EXPORT(void) ap_overlap_tables(ap_table_t *a, const ap_table_t *b,
-				    unsigned flags)
-{
-    overlap_key cat_keys_buf[ap_OVERLAP_TABLES_ON_STACK];
-    overlap_key *cat_keys;
-    int nkeys;
-    ap_table_entry_t *e;
-    ap_table_entry_t *last_e;
-    overlap_key *left;
-    overlap_key *right;
-    overlap_key *last;
-
-    nkeys = a->a.nelts + b->a.nelts;
-    if (nkeys < ap_OVERLAP_TABLES_ON_STACK) {
-	cat_keys = cat_keys_buf;
-    }
-    else {
-	/* XXX: could use scratch free space in a or b's pool instead...
-	 * which could save an allocation in b's pool.
-	 */
-	cat_keys = ap_palloc(b->a.cont, sizeof(overlap_key) * nkeys);
-    }
-
-    nkeys = 0;
-
-    /* Create a list of the entries from a concatenated with the entries
-     * from b.
-     */
-    e = (ap_table_entry_t *)a->a.elts;
-    last_e = e + a->a.nelts;
-    while (e < last_e) {
-	cat_keys[nkeys].key = e->key;
-	cat_keys[nkeys].val = e->val;
-	cat_keys[nkeys].order = nkeys;
-	++nkeys;
-	++e;
-    }
-
-    e = (ap_table_entry_t *)b->a.elts;
-    last_e = e + b->a.nelts;
-    while (e < last_e) {
-	cat_keys[nkeys].key = e->key;
-	cat_keys[nkeys].val = e->val;
-	cat_keys[nkeys].order = nkeys;
-	++nkeys;
-	++e;
-    }
-
-    qsort(cat_keys, nkeys, sizeof(overlap_key), sort_overlap);
-
-    /* Now iterate over the sorted list and rebuild a.
-     * Start by making sure it has enough space.
-     */
-    a->a.nelts = 0;
-    if (a->a.nalloc < nkeys) {
-	a->a.elts = ap_palloc(a->a.cont, a->a.elt_size * nkeys * 2);
-	a->a.nalloc = nkeys * 2;
-    }
-
-    /*
-     * In both the merge and set cases we retain the invariant:
-     *
-     * left->key, (left+1)->key, (left+2)->key, ..., (right-1)->key
-     * are all equal keys.  (i.e. strcasecmp returns 0)
-     *
-     * We essentially need to find the maximal
-     * right for each key, then we can do a quick merge or set as
-     * appropriate.
-     */
-
-    if (flags & ap_OVERLAP_TABLES_MERGE) {
-	left = cat_keys;
-	last = left + nkeys;
-	while (left < last) {
-	    right = left + 1;
-	    if (right == last
-		|| strcasecmp(left->key, right->key)) {
-		ap_table_addn(a, left->key, left->val);
-		left = right;
-	    }
-	    else {
-		char *strp;
-		char *value;
-		size_t len;
-
-		/* Have to merge some headers.  Let's re-use the order field,
-		 * since it's handy... we'll store the length of val there.
-		 */
-		left->order = strlen(left->val);
-		len = left->order;
-		do {
-		    right->order = strlen(right->val);
-		    len += 2 + right->order;
-		    ++right;
-		} while (right < last
-			 && !strcasecmp(left->key, right->key));
-		/* right points one past the last header to merge */
-		value = ap_palloc(a->a.cont, len + 1);
-		strp = value;
-		for (;;) {
-		    memcpy(strp, left->val, left->order);
-		    strp += left->order;
-		    ++left;
-		    if (left == right) {
-			break;
-		    }
-		    *strp++ = ',';
-		    *strp++ = ' ';
-		}
-		*strp = 0;
-		ap_table_addn(a, (left-1)->key, value);
-	    }
-	}
-    }
-    else {
-	left = cat_keys;
-	last = left + nkeys;
-	while (left < last) {
-	    right = left + 1;
-	    while (right < last && !strcasecmp(left->key, right->key)) {
-		++right;
-	    }
-	    ap_table_addn(a, (right-1)->key, (right-1)->val);
-	    left = right;
-	}
-    }
-}
-
diff --git a/libapr.def b/libapr.def
deleted file mode 100644
index b9fe301fef7..00000000000
--- a/libapr.def
+++ /dev/null
@@ -1,251 +0,0 @@
-; aprlib.def :
-
-LIBRARY aprlib
-DESCRIPTION ''
-
-EXPORTS
-	; Add new API calls to the end of this list.
-	ap_opendir   @1
-	ap_closedir   @2
-	ap_readdir   @3
-	ap_rewinddir   @4
-	ap_make_dir   @5
-	ap_remove_dir   @6
-	ap_dir_entry_size   @7
-	ap_dir_entry_mtime   @8
-	ap_dir_entry_ftype   @9
-	ap_get_dir_filename   @10
-;	ap_get_filename   @11
-	ap_stat		  @11
-;	ap_get_filesize   @12
-;	ap_get_fileatime   @13
-;	ap_get_filectime   @14
-;	ap_make_iov   @15
-	ap_dupfile   @16
-	ap_getfileinfo   @17
-	ap_open   @18
-	ap_close   @19
-	ap_remove_file   @20
-	ap_create_pipe   @21
-	ap_read   @22
-	ap_write   @23
-	ap_seek   @24
-    	ap_get_filedata   @25
-    	ap_set_filedata   @26
-    	ap_get_os_file   @27
-	ap_put_os_file @28
-    	ap_get_os_dir   @29
-    	ap_putc   @30
-    	ap_getc   @31
-	ap_puts @32
-	ap_fgets @33
-	ap_flush @34
-    	ap_fprintf   @35
-    	ap_eof   @36
-;	ap_get_filetype @37
-	ap_writev @38
-	; locks
-	ap_create_lock   @39
-	ap_lock   @40
-	ap_unlock   @41
-	ap_destroy_lock   @42
-	ap_child_init_lock   @43
-	ap_get_lockdata   @44
-	ap_set_lockdata   @45
-	ap_get_os_lock   @46
-	ap_create_tcp_socket   @47
-	ap_shutdown   @48
-	ap_close_socket   @49
-	ap_bind   @50
-	ap_listen   @51
-	ap_accept   @52
-	ap_connect   @53
-	ap_get_remote_hostname   @54
-	ap_gethostname   @55
-	ap_send   @56
-	ap_recv   @57
-	ap_setsocketopt   @58
-	ap_sendv @59
-	ap_sendfile  @60
-	ap_setup_poll   @61
-	ap_poll   @62
-	ap_add_poll_socket   @63
-	ap_get_revents   @64
-	ap_get_socketdata   @65
-	ap_set_socketdata   @66
-	ap_get_polldata   @67
-	ap_set_polldata   @68
-	ap_put_os_sock @69
-	ap_get_os_sock   @70
-	ap_remove_poll_socket   @71
-	ap_clear_poll_sockets   @72
-;	ap_setipaddr @73
-;	ap_getipaddr @74
-;	ap_create_signal   @75
-;	ap_setup_signal   @76
-;       SignalHandling   @77
-;	ap_send_signal    @78
-;       thread_ready   @79
-	ap_createprocattr_init   @80
-	ap_setprocattr_io   @81
-	ap_setprocattr_dir   @82
-	ap_setprocattr_cmdtype   @83
-	ap_setprocattr_detach   @84
-	ap_create_process   @85
-	ap_get_childin   @86
-	ap_get_childout   @87
-	ap_get_childerr   @88
-	ap_wait_proc   @89
-	ap_kill   @90
-	ap_create_threadattr   @91
-	ap_setthreadattr_detach   @92
-	ap_getthreadattr_detach   @93
-	ap_create_thread   @94
-	ap_thread_exit   @95
-	ap_thread_join   @96
-	ap_thread_detach   @97
-;	ap_cancel_thread   @98
-	ap_create_thread_private   @99
-	ap_get_thread_private   @100
-	ap_set_thread_private   @101
-	ap_delete_thread_private   @102
-	ap_get_threaddata    @103
-	ap_set_threaddata    @104
-	ap_get_threadkeydata    @105
-	ap_set_threadkeydata    @106
-	ap_get_procdata    @107
-;	ap_set_procdata    @108
-	ap_get_os_proc   @109
-	ap_get_os_thread   @110
-	ap_get_os_threadkey   @111
-	ap_os_systemcase_filename   @112
-	canonical_filename   @113
-	ap_create_pool   @114
-	ap_destroy_context   @115
-;	WinTimeToUnixTime   @116
-;	ap_get_oslevel   @117
-	ap_get_userdata   @118
-	ap_set_userdata   @119
-	ap_initialize   @120
-	ap_getopt    @121
-	ap_opterr   @122 DATA
-	ap_optind   @123 DATA
-	ap_optopt   @124 DATA
-	ap_optreset   @125 DATA
-	ap_optarg   @126 DATA
-;	ap_make_time   @127
-	ap_ansi_time_to_ap_time @127
-;	ap_current_time   @128
-	ap_now		  @128
-;	ap_explode_time   @129
-	ap_explode_gmt	  @129
-;	ap_implode_time   @130
-	ap_explode_localtime @130
-;	ap_get_curtime   @131
-	ap_implode_time	 @131
-;	ap_get_sec   @132
-	ap_get_os_imp_time	@132
-;	ap_get_min   @133
-	ap_get_os_exp_time	@133
-;	ap_get_hour   @134
-	ap_put_os_imp_time	@134
-;	ap_get_mday   @135
-	ap_put_os_exp_time	@135
-;	ap_get_mon   @136
-	ap_ctime     @136
-;	ap_get_year   @137
-	ap_rfc822_date	@137
-;	ap_get_wday   @138
-	ap_strftime   @138
-;	ap_set_sec   @139
-;	ap_set_min   @140
-;	ap_set_hour   @141
-;	ap_set_mday   @142
-;	ap_set_mon   @143
-;	ap_set_year   @144
-;	ap_set_wday   @145
-;	ap_get_timedata   @146
-;	ap_set_timedata   @147
-;	ap_get_os_time   @148
-;	ap_timediff   @149
-	ap_MD5Final   @150
-	ap_MD5Init   @151
-	ap_MD5Update   @152
-	ap_cpystrn   @153
-	ap_register_cleanup   @154
-	ap_kill_cleanup   @155
-	ap_fnmatch   @156
-	ap_is_fnmatch   @157
-	ap_MD5Encode   @158
-	ap_validate_password   @159
-	ap_make_sub_pool   @160
-	ap_init_alloc   @161
-	ap_clear_pool   @162
-	ap_destroy_pool   @163
-	ap_bytes_in_pool   @164
-	ap_bytes_in_free_blocks   @165
-	ap_palloc   @166
-	ap_pcalloc   @167
-	ap_pstrdup   @168
-	ap_pstrndup   @169
-	ap_pstrcat   @170
-	ap_pvsprintf   @171
-	ap_psprintf   @172
-	ap_make_array   @173
-	ap_push_array   @174
-	ap_array_cat   @175
-	ap_copy_array   @176
-	ap_copy_array_hdr   @177
-	ap_append_arrays   @178
-	ap_array_pstrcat   @179
-	ap_make_table   @180
-	ap_copy_table   @181
-	ap_clear_table   @182
-	ap_table_get   @183
-	ap_table_set   @184
-	ap_table_setn   @185
-	ap_table_unset   @186
-	ap_table_merge   @187
-	ap_table_mergen   @188
-	ap_table_add   @189
-	ap_table_addn   @190
-	ap_overlay_tables @191
-	ap_table_do   @192
-	ap_overlap_tables   @193
-	ap_run_cleanup   @194
-	ap_cleanup_for_exec   @195
-	ap_null_cleanup   @196
-	ap_note_subprocess   @197
-;	ap_slack   @198
-	ap_vformatter   @199
-	ap_snprintf   @200
-	ap_vsnprintf   @201
-	ap_getpass   @202
-	ap_ungetc @203
-	ap_tokenize_to_argv @204
-	ap_filename_of_pathname @205
-	ap_get_remote_name @206
-	ap_get_local_name @207
-	ap_get_local_ipaddr @208
-	ap_set_local_ipaddr @209
-	ap_get_remote_ipaddr @210
-	ap_set_remote_ipaddr @211
-	ap_get_local_port @212
-	ap_set_local_port @213
-	ap_get_remote_port @214
-	ap_set_remote_port @215
-	ap_open_stderr @216
-        ap_set_pipe_timeout   @217
-        ap_terminate @218
-        ap_dso_load @219
-        ap_dso_unload @220
-        ap_dso_sym @221
-        ap_dso_init @222
-        ap_collapse_spaces @223
-	ap_month_snames @224
-	ap_day_snames @225
-	ap_canonical_error @226
-	ap_strerror @227
-	ap_generate_random_bytes @228
-	ap_strnatcmp @229
-	ap_strnatcasecmp @230
diff --git a/libapr.dsp b/libapr.dsp
index 05f5831e2a3..3c4e53b54c5 100644
--- a/libapr.dsp
+++ b/libapr.dsp
@@ -1,36 +1,37 @@
-# Microsoft Developer Studio Project File - Name="aprlibdll" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# Microsoft Developer Studio Project File - Name="libapr" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
 # ** DO NOT EDIT **
 
 # TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
 
-CFG=aprlibdll - Win32 Debug
+CFG=libapr - 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 "aprlibdll.mak".
+!MESSAGE NMAKE /f "libapr.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 "aprlibdll.mak" CFG="aprlibdll - Win32 Debug"
+!MESSAGE NMAKE /f "libapr.mak" CFG="libapr - Win32 Release"
 !MESSAGE 
 !MESSAGE Possible choices for configuration are:
 !MESSAGE 
-!MESSAGE "aprlibdll - Win32 Release" (based on\
- "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "aprlibdll - Win32 Debug" (based on\
- "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "libapr - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "libapr - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "libapr - x64 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "libapr - x64 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)" == "aprlibdll - Win32 Release"
+!IF  "$(CFG)" == "libapr - Win32 Release"
 
 # PROP BASE Use_MFC 0
 # PROP BASE Use_Debug_Libraries 0
@@ -43,21 +44,26 @@ RSC=rc.exe
 # PROP Intermediate_Dir "Release"
 # PROP Ignore_Export_Lib 0
 # PROP Target_Dir ""
-# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "./include" /I "./inc" /I "./misc/win32" /I "./file_io/win32" /I "./time/win32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
-# SUBTRACT CPP /YX
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /Zi /O2 /Oy- /I "./include" /I "./include/private" /I "./include/arch/win32" /I "./include/arch/unix" /I "../expat/lib" /D "NDEBUG" /D "APR_DECLARE_EXPORT" /D "WIN32" /D "WINNT" /D "_WINDOWS" /Fo"$(INTDIR)\" /Fd"$(INTDIR)\libapr_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
 # ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /i "./include" /d "NDEBUG" /d "APR_VERSION_ONLY"
 BSC32=bscmake.exe
 # ADD BASE BSC32 /nologo
 # ADD BSC32 /nologo
 LINK32=link.exe
-# ADD BASE LINK32 apr.lib kernel32.lib advapi32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /map /machine:I386 /def:".\aprlib.def" /out:"Release/aprlib.dll" /libpath:"LibR" /base:@"..\..\os\win32\BaseAddr.ref",aprlib
-# ADD LINK32 apr.lib kernel32.lib advapi32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /map /machine:I386 /def:".\aprlib.def" /out:"Release/aprlib.dll" /libpath:"LibR" /base:@"..\..\os\win32\BaseAddr.ref",aprlib
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib shell32.lib rpcrt4.lib /nologo /base:"0x6EEC0000" /subsystem:windows /dll /incremental:no /debug /opt:ref
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib shell32.lib rpcrt4.lib libexpat.lib /nologo /base:"0x6EEC0000" /subsystem:windows /dll /incremental:no /debug /libpath:"..\expat\win32\bin\Release" /out:"Release\libapr-2.dll" /pdb:"Release\libapr-2.pdb" /implib:"Release\libapr-2.lib" /MACHINE:X86 /opt:ref
+# Begin Special Build Tool
+TargetPath=Release\libapr-2.dll
+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)" == "aprlibdll - Win32 Debug"
+!ELSEIF  "$(CFG)" == "libapr - Win32 Debug"
 
 # PROP BASE Use_MFC 0
 # PROP BASE Use_Debug_Libraries 1
@@ -70,34 +76,1153 @@ LINK32=link.exe
 # PROP Intermediate_Dir "Debug"
 # PROP Ignore_Export_Lib 0
 # PROP Target_Dir ""
-# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "./include" /I "./inc" /I "./misc/win32" /I "./file_io/win32" /I "./time/win32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
-# SUBTRACT CPP /YX
-# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE CPP /nologo /MDd /W3 /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /EHsc /c
+# ADD CPP /nologo /MDd /W3 /Zi /Od /I "./include" /I "./include/private" /I "./include/arch/win32" /I "./include/arch/unix" /I "../expat/lib" /D "_DEBUG" /D "APR_DECLARE_EXPORT" /D "WIN32" /D "WINNT" /D "_WINDOWS" /Fo"$(INTDIR)\" /Fd"$(INTDIR)\libapr_src" /FD /EHsc /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
 # ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /i "./include" /d "_DEBUG" /d "APR_VERSION_ONLY"
 BSC32=bscmake.exe
 # ADD BASE BSC32 /nologo
 # ADD BSC32 /nologo
 LINK32=link.exe
-# ADD BASE LINK32 aprlib.lib kernel32.lib advapi32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /map /debug /machine:I386 /def:".\aprlib.def" /out:"Debug/aprlib.dll" /libpath:"LibD" /base:@"..\..\os\win32\BaseAddr.ref",aprlib
-# ADD LINK32 apr.lib kernel32.lib advapi32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /map /debug /machine:I386 /def:".\aprlib.def" /out:"Debug/aprlib.dll" /libpath:"LibD" /base:@"..\..\os\win32\BaseAddr.ref",aprlib
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib shell32.lib rpcrt4.lib /nologo /base:"0x6EEC0000" /subsystem:windows /dll /incremental:no /debug
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib shell32.lib rpcrt4.lib libexpat.lib /nologo /base:"0x6EEC0000" /subsystem:windows /dll /incremental:no /debug /libpath:"..\expat\win32\bin\Debug" /out:"Debug\libapr-2.dll" /pdb:"Debug\libapr-2.pdb" /implib:"Debug\libapr-2.lib" /MACHINE:X86
+# Begin Special Build Tool
+TargetPath=Debug\libapr-2.dll
+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)" == "libapr - x64 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "x64\Release"
+# PROP BASE Intermediate_Dir "x64\Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "x64\Release"
+# PROP Intermediate_Dir "x64\Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /Zi /O2 /Oy- /I "./include" /I "./include/private" /I "./include/arch/win32" /I "./include/arch/unix" /I "../expat/lib" /D "NDEBUG" /D "APR_DECLARE_EXPORT" /D "WIN32" /D "WINNT" /D "_WINDOWS" /Fo"$(INTDIR)\" /Fd"$(INTDIR)\libapr_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /i "./include" /d "NDEBUG" /d "APR_VERSION_ONLY"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib shell32.lib rpcrt4.lib /nologo /base:"0x6EEC0000" /subsystem:windows /dll /incremental:no /debug /opt:ref
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib shell32.lib rpcrt4.lib libexpat.lib /nologo /base:"0x6EEC0000" /subsystem:windows /dll /incremental:no /debug /libpath:"..\expat\win32\bin\x64\Release" /out:"x64\Release\libapr-2.dll" /pdb:"x64\Release\libapr-2.pdb" /implib:"x64\Release\libapr-2.lib" /MACHINE:X64 /opt:ref
+# Begin Special Build Tool
+TargetPath=x64\Release\libapr-2.dll
+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)" == "libapr - x64 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "x64\Debug"
+# PROP BASE Intermediate_Dir "x64\Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "x64\Debug"
+# PROP Intermediate_Dir "x64\Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /EHsc /c
+# ADD CPP /nologo /MDd /W3 /Zi /Od /I "./include" /I "./include/private" /I "./include/arch/win32" /I "./include/arch/unix" /I "../expat/lib" /D "_DEBUG" /D "APR_DECLARE_EXPORT" /D "WIN32" /D "WINNT" /D "_WINDOWS" /Fo"$(INTDIR)\" /Fd"$(INTDIR)\libapr_src" /FD /EHsc /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /i "./include" /d "_DEBUG" /d "APR_VERSION_ONLY"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib shell32.lib rpcrt4.lib /nologo /base:"0x6EEC0000" /subsystem:windows /dll /incremental:no /debug
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib shell32.lib rpcrt4.lib libexpat.lib /nologo /base:"0x6EEC0000" /subsystem:windows /dll /incremental:no /debug /libpath:"..\expat\win32\bin\x64\Debug" /out:"x64\Debug\libapr-2.dll" /pdb:"x64\Debug\libapr-2.pdb" /implib:"x64\Debug\libapr-2.lib" /MACHINE:X64
+# Begin Special Build Tool
+TargetPath=x64\Debug\libapr-2.dll
+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 "aprlibdll - Win32 Release"
-# Name "aprlibdll - Win32 Debug"
+# Name "libapr - Win32 Release"
+# Name "libapr - Win32 Debug"
+# Name "libapr - x64 Release"
+# Name "libapr - x64 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter ".c"
+# Begin Group "atomic"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\atomic\win32\apr_atomic.c
+# End Source File
+# End Group
+# Begin Group "buckets"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\buckets\apr_brigade.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_alloc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_eos.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_file.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_flush.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_heap.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_mmap.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_pipe.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_pool.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_refcount.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_simple.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_socket.c
+# End Source File
+# End Group
+# Begin Group "crypto"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\crypto\apr_crypto.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\crypto\apr_md4.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\crypto\apr_md5.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\crypto\apr_passwd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\crypto\apr_sha1.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\crypto\apr_siphash.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\crypto\crypt_blowfish.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\crypto\crypt_blowfish.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\crypto\getuuid.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\crypto\uuid.c
+# End Source File
+# End Group
+# Begin Group "dbd"
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\dbd\apr_dbd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbd\apr_dbd_mysql.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbd\apr_dbd_odbc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbd\apr_dbd_oracle.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbd\apr_dbd_pgsql.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbd\apr_dbd_sqlite2.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbd\apr_dbd_sqlite3.c
+# End Source File
+# End Group
+# Begin Group "dbm"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\dbm\apr_dbm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbm\apr_dbm_berkeleydb.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbm\apr_dbm_gdbm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbm\apr_dbm_sdbm.c
+# End Source File
+# End Group
+# Begin Group "dso"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\dso\win32\dso.c
+# End Source File
+# End Group
+# Begin Group "encoding"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\encoding\apr_base64.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\encoding\apr_escape.c
+# End Source File
+# End Group
+# Begin Group "file_io"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\file_io\win32\buffer.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\file_io\unix\copy.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\file_io\win32\dir.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\file_io\unix\fileacc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\file_io\win32\filedup.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\file_io\win32\filepath.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\file_io\unix\filepath_util.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\file_io\win32\filestat.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\file_io\win32\filesys.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\file_io\win32\flock.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\file_io\unix\fullrw.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\file_io\unix\mktemp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\file_io\win32\open.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\file_io\win32\pipe.c
+# End Source File
 # Begin Source File
 
-SOURCE=.\misc\win32\aprlib.c
+SOURCE=.\file_io\win32\readwrite.c
 # End Source File
 # Begin Source File
 
-SOURCE=.\aprlib.def
+SOURCE=.\file_io\win32\seek.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\file_io\unix\tempdir.c
+# End Source File
+# End Group
+# Begin Group "hooks"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\hooks\apr_hooks.c
+# End Source File
+# End Group
+# Begin Group "locks"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\locks\win32\proc_mutex.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\locks\win32\thread_cond.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\locks\win32\thread_mutex.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\locks\win32\thread_rwlock.c
+# End Source File
+# End Group
+# Begin Group "memcache"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\memcache\apr_memcache.c
+# End Source File
+# End Group
+# Begin Group "memory"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\memory\unix\apr_pools.c
+# End Source File
+# End Group
+# Begin Group "misc"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\misc\win32\apr_app.c
 # PROP Exclude_From_Build 1
 # End Source File
+# Begin Source File
+
+SOURCE=.\misc\win32\charset.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\misc\win32\env.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\misc\unix\errorcodes.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\misc\unix\getopt.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\misc\win32\internal.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\misc\win32\misc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\misc\unix\otherchild.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\misc\win32\rand.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\misc\win32\start.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\misc\win32\utf8.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\misc\unix\version.c
+# End Source File
+# End Group
+# Begin Group "mmap"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\mmap\unix\common.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mmap\win32\mmap.c
+# End Source File
+# End Group
+# Begin Group "network_io"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\network_io\unix\inet_ntop.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\network_io\unix\inet_pton.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\network_io\unix\multicast.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\network_io\win32\sendrecv.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\network_io\unix\sockaddr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\network_io\win32\sockets.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\network_io\unix\socket_util.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\network_io\win32\sockopt.c
+# End Source File
+# End Group
+# Begin Group "passwd"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\passwd\apr_getpass.c
+# End Source File
+# End Group
+# Begin Group "poll"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\poll\unix\pollcb.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\poll\unix\pollset.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\poll\unix\poll.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\poll\unix\select.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\poll\unix\wakeup.c
+# End Source File
+# End Group
+# Begin Group "random"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\random\unix\apr_random.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\random\unix\sha2.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\random\unix\sha2_glue.c
+# End Source File
+# End Group
+# Begin Group "sdbm"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\dbm\sdbm\sdbm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbm\sdbm\sdbm_hash.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbm\sdbm\sdbm_lock.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbm\sdbm\sdbm_pair.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbm\sdbm\sdbm_pair.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbm\sdbm\sdbm_private.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbm\sdbm\sdbm_tune.h
+# End Source File
+# End Group
+# Begin Group "shmem"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\shmem\win32\shm.c
+# End Source File
+# End Group
+# Begin Group "strings"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\strings\apr_cpystrn.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\strings\apr_fnmatch.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\strings\apr_snprintf.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\strings\apr_strings.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\strings\apr_strnatcmp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\strings\apr_strtok.c
+# End Source File
+# End Group
+# Begin Group "strmatch"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\strmatch\apr_strmatch.c
+# End Source File
+# End Group
+# Begin Group "tables"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\tables\apr_hash.c
+# Begin Source File
+
+SOURCE=.\tables\apr_tables.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\tables\apr_skiplist.c
+# End Source File
+# End Group
+# Begin Group "threadproc"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\threadproc\win32\proc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\threadproc\win32\signals.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\threadproc\win32\thread.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\threadproc\win32\threadpriv.c
+# End Source File
+# End Group
+# Begin Group "time"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\time\win32\time.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\time\win32\timestr.c
+# End Source File
+# End Group
+# Begin Group "uri"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\uri\apr_uri.c
+# End Source File
+# End Group
+# Begin Group "user"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\user\win32\groupinfo.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\user\win32\userinfo.c
+# End Source File
+# End Group
+# Begin Group "util-misc"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\util-misc\apr_date.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\util-misc\apu_dso.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\util-misc\apr_queue.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\util-misc\apr_reslist.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\util-misc\apr_rmm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\util-misc\apr_thread_pool.c
+# End Source File
+# End Group
+# Begin Group "xlate"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\xlate\xlate.c
+# End Source File
+# End Group
+# Begin Group "xml"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\xml\apr_xml.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\xml\apr_xml_expat.c
+# End Source File
+# End Group
+# End Group
+# Begin Group "Private Header Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\include\arch\win32\apr_arch_atime.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\arch\win32\apr_arch_dso.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\arch\win32\apr_arch_file_io.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\arch\win32\apr_arch_inherit.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\arch\win32\apr_arch_misc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\arch\win32\apr_arch_networkio.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\arch\win32\apr_arch_thread_mutex.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\arch\win32\apr_arch_thread_rwlock.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\arch\win32\apr_arch_threadproc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\arch\win32\apr_arch_utf8.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\arch\win32\apr_private.h
+# End Source File
+# End Group
+# Begin Group "Public Header Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\include\apr.h.in
+# PROP Exclude_From_Build 1
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr.hnw
+# PROP Exclude_From_Build 1
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr.hw
+
+!IF  "$(CFG)" == "libapr - Win32 Release"
+
+# Begin Custom Build - Creating apr.h from apr.hw, apr_escape_test_char.h from gen_test_char.exe
+InputPath=.\include\apr.hw
+
+".\include\apr.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	type .\include\apr.hw > .\include\apr.h
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "libapr - Win32 Debug"
+
+# Begin Custom Build - Creating apr.h from apr.hw, apr_escape_test_char.h from gen_test_char.exe
+InputPath=.\include\apr.hw
+
+".\include\apr.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	type .\include\apr.hw > .\include\apr.h
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "libapr - x64 Release"
+
+# Begin Custom Build - Creating apr.h from apr.hw, apr_escape_test_char.h from gen_test_char.exe
+InputPath=.\include\apr.hw
+
+".\include\apr.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	type .\include\apr.hw > .\include\apr.h
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "libapr - x64 Debug"
+
+# Begin Custom Build - Creating apr.h from apr.hw, apr_escape_test_char.h from gen_test_char.exe
+InputPath=.\include\apr.hw
+
+".\include\apr.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	type .\include\apr.hw > .\include\apr.h
+
+# End Custom Build
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_allocator.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_atomic.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_dso.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_env.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_errno.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_escape.h
+
+!IF  "$(CFG)" == "libapr - Win32 Release"
+
+# Begin Custom Build - Creating gen_test_char.exe and apr_escape_test_char.h
+InputPath=.\include\apr_escape.h
+
+".\include\apr_escape_test_char.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl.exe /nologo /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /I ".\include" /Fo.\Release\gen_test_char /Fe.\Release\gen_test_char.exe .\tools\gen_test_char.c 
+	.\Release\gen_test_char.exe > .\include\apr_escape_test_char.h
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "libapr - Win32 Debug"
+
+# Begin Custom Build - Creating gen_test_char.exe and apr_escape_test_char.h
+InputPath=.\include\apr_escape.h
+
+".\include\apr_escape_test_char.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl.exe /nologo /W3 /EHsc /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /I ".\include" /Fo.\Debug\gen_test_char /Fe.\Debug\gen_test_char.exe .\tools\gen_test_char.c  
+	.\Debug\gen_test_char.exe > .\include\apr_escape_test_char.h
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "libapr - x64 Release"
+
+# Begin Custom Build - Creating gen_test_char.exe and apr_escape_test_char.h
+InputPath=.\include\apr_escape.h
+
+".\include\apr_escape_test_char.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl.exe /nologo /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /I ".\include" /Fo.\x64\Release\gen_test_char /Fe.\x64\Release\gen_test_char.exe .\tools\gen_test_char.c 
+	.\x64\Release\gen_test_char.exe > .\include\apr_escape_test_char.h
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "libapr - x64 Debug"
+
+# Begin Custom Build - Creating gen_test_char.exe and apr_escape_test_char.h
+InputPath=.\include\apr_escape.h
+
+".\include\apr_escape_test_char.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl.exe /nologo /W3 /EHsc /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /I ".\include" /Fo.\x64\Debug\gen_test_char /Fe.\x64\Debug\gen_test_char.exe .\tools\gen_test_char.c 
+	.\x64\Debug\gen_test_char.exe > .\include\apr_escape_test_char.h
+
+# End Custom Build
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_file_info.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_file_io.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_fnmatch.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_general.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_getopt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_global_mutex.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_hash.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_inherit.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_lib.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_mmap.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_network_io.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_poll.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_pools.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_portable.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_proc_mutex.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_random.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_ring.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_shm.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_signal.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_skiplist.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_strings.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_support.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_tables.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_thread_cond.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_thread_mutex.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_thread_proc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_thread_rwlock.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_time.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_user.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_version.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_want.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apu.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\private\apu_select_dbm.h.in
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\private\apu_select_dbm.hw
+
+!IF  "$(CFG)" == "libapr - Win32 Release"
+
+# Begin Custom Build - Creating apu_select_dbm.h from apu_select_dbm.hw
+InputPath=.\include\private\apu_select_dbm.hw
+
+".\include\private\apu_select_dbm.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	type .\include\private\apu_select_dbm.hw > .\include\private\apu_select_dbm.h
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "libapr - Win32 Debug"
+
+# Begin Custom Build - Creating apu_select_dbm.h from apu_select_dbm.hw
+InputPath=.\include\private\apu_select_dbm.hw
+
+".\include\private\apu_select_dbm.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	type .\include\private\apu_select_dbm.hw > .\include\private\apu_select_dbm.h
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "libapr - x64 Release"
+
+# Begin Custom Build - Creating apu_select_dbm.h from apu_select_dbm.hw
+InputPath=.\include\private\apu_select_dbm.hw
+
+".\include\private\apu_select_dbm.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	type .\include\private\apu_select_dbm.hw > .\include\private\apu_select_dbm.h
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "libapr - x64 Debug"
+
+# Begin Custom Build - Creating apu_select_dbm.h from apu_select_dbm.hw
+InputPath=.\include\private\apu_select_dbm.hw
+
+".\include\private\apu_select_dbm.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	type .\include\private\apu_select_dbm.hw > .\include\private\apu_select_dbm.h
+
+# End Custom Build
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apu_want.h.in
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apu_want.hnw
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apu_want.hw
+
+!IF  "$(CFG)" == "libapr - Win32 Release"
+
+# Begin Custom Build - Creating apu_want.h from apu_want.hw
+InputPath=.\include\apu_want.hw
+
+".\include\apu_want.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	type .\include\apu_want.hw > .\include\apu_want.h
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "libapr - Win32 Debug"
+
+# Begin Custom Build - Creating apu_want.h from apu_want.hw
+InputPath=.\include\apu_want.hw
+
+".\include\apu_want.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	type .\include\apu_want.hw > .\include\apu_want.h
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "libapr - x64 Release"
+
+# Begin Custom Build - Creating apu_want.h from apu_want.hw
+InputPath=.\include\apu_want.hw
+
+".\include\apu_want.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	type .\include\apu_want.hw > .\include\apu_want.h
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "libapr - x64 Debug"
+
+# Begin Custom Build - Creating apu_want.h from apu_want.hw
+InputPath=.\include\apu_want.hw
+
+".\include\apu_want.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	type .\include\apu_want.hw > .\include\apu_want.h
+
+# End Custom Build
+
+!ENDIF 
+
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\libapr.rc
+# End Source File
 # End Target
 # End Project
diff --git a/libapr.rc b/libapr.rc
new file mode 100644
index 00000000000..f7386f06d97
--- /dev/null
+++ b/libapr.rc
@@ -0,0 +1,66 @@
+#include "apr_version.h"
+
+#define APR_LICENSE \
+  "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\r\n\r\n" \
+  "http://www.apache.org/licenses/LICENSE-2.0\r\n\r\n" \
+  "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."
+
+#ifdef DLL_NAME
+#define APR_DLL_BASENAME APR_STRINGIFY(DLL_NAME) "-" APR_STRINGIFY(APR_MAJOR_VERSION)
+#define APR_DLL_DESCRIPTION "Apache Portable Runtime " APR_STRINGIFY(DLL_NAME) " Module"
+#else
+#define APR_DLL_BASENAME "libapr-" APR_STRINGIFY(APR_MAJOR_VERSION)
+#define APR_DLL_DESCRIPTION "Apache Portable Runtime Library"
+#endif
+
+
+1 VERSIONINFO
+ FILEVERSION APR_VERSION_STRING_CSV,0
+ PRODUCTVERSION APR_VERSION_STRING_CSV,0
+ FILEFLAGSMASK 0x3fL
+#if defined(APR_IS_DEV_VERSION)
+#if defined(_DEBUG)
+ FILEFLAGS 0x03L
+#else
+ FILEFLAGS 0x02L
+#endif
+#else
+#if defined(_DEBUG)
+ FILEFLAGS 0x01L
+#else
+ FILEFLAGS 0x00L
+#endif
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+  BLOCK "StringFileInfo"
+  BEGIN
+    BLOCK "040904b0"
+    BEGIN
+      VALUE "Comments", APR_LICENSE "\0"
+      VALUE "CompanyName", "Apache Software Foundation\0"
+      VALUE "FileDescription", APR_DLL_DESCRIPTION "\0"
+      VALUE "FileVersion", APR_VERSION_STRING "\0"
+      VALUE "InternalName", APR_DLL_BASENAME "\0"
+      VALUE "LegalCopyright", APR_COPYRIGHT "\0"
+      VALUE "OriginalFilename", APR_DLL_BASENAME ".dll\0"
+      VALUE "ProductName", "Apache Portable Runtime Project\0"
+      VALUE "ProductVersion", APR_VERSION_STRING "\0"
+    END
+  END
+  BLOCK "VarFileInfo"
+  BEGIN
+    VALUE "Translation", 0x409, 1200
+  END
+END
diff --git a/locks/beos/Makefile.in b/locks/beos/Makefile.in
deleted file mode 100644
index 7fa364b431d..00000000000
--- a/locks/beos/Makefile.in
+++ /dev/null
@@ -1,64 +0,0 @@
-#CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
-#LIBS=$(EXTRA_LIBS) $(LIBS1)
-#INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
-#LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
-
-CC=@CC@
-RANLIB=@RANLIB@
-CFLAGS=@CFLAGS@ @OPTIM@
-LIBS=@LIBS@
-LDFLAGS=@LDFLAGS@ $(LIBS)
-INCDIR=../../include
-INCDIR1=../../file_io/unix
-INCLUDES=-I$(INCDIR) -I$(INCDIR1) -I.
-
-LIB=liblock.a
-
-OBJS=locks.o \
-	crossproc.o \
-	intraproc.o \
-
-.c.o:
-	$(CC) $(CFLAGS) -c $(INCLUDES) $<
-
-all: $(LIB)
-
-clean:
-	$(RM) -f *.o *.a *.so
-
-distclean: clean
-	-$(RM) -f Makefile
-
-$(OBJS): Makefile
-
-$(LIB): $(OBJS)
-	$(RM) -f $@
-	$(AR) cr $@ $(OBJS)
-	$(RANLIB) $@
-
-#
-# We really don't expect end users to use this rule.  It works only with
-# gcc, and rebuilds Makefile.tmpl.  You have to re-run Configure after
-# using it.
-#
-depend:
-	cp Makefile.in Makefile.in.bak \
-	    && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.in > Makefile.new \
-	    && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \
-	    && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
-	           -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
-		> Makefile.in \
-	    && rm Makefile.new
-
-# DO NOT REMOVE
-crossproc.o: crossproc.c ../../include/apr_lock.h \
- ../../include/apr_general.h ../../include/apr_private.h \
- ../../include/apr_errno.h ../../include/apr_lib.h \
- ../../include/apr_file_io.h locks.h
-intraproc.o: intraproc.c ../../include/apr_lock.h \
- ../../include/apr_general.h ../../include/apr_private.h \
- ../../include/apr_errno.h locks.h ../../include/apr_file_io.h \
- ../../include/apr_lib.h
-locks.o: locks.c ../../include/apr_lock.h ../../include/apr_general.h \
- ../../include/apr_private.h ../../include/apr_errno.h locks.h \
- ../../include/apr_file_io.h
diff --git a/locks/beos/crossproc.c b/locks/beos/crossproc.c
deleted file mode 100644
index 388dba8edfc..00000000000
--- a/locks/beos/crossproc.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "locks.h"
-
-ap_status_t lock_inter_cleanup(void * data)
-{
-    ap_lock_t *lock = (ap_lock_t*)data;
-    if (lock->curr_locked == 1) {
-    	if (atomic_add(&lock->ben_interproc , -1) > 1){
-            release_sem (lock->sem_interproc);
-    	}
-    }
-    delete_sem(lock->sem_interproc);
-    return APR_SUCCESS;
-}    
-
-ap_status_t create_inter_lock(ap_lock_t *new)
-{
-    int32 stat;
-    
-    new->sem_interproc = (sem_id)ap_palloc(new->cntxt, sizeof(sem_id));
-    new->ben_interproc = (int32)ap_palloc(new->cntxt, sizeof(int32));
-
-    if ((stat = create_sem(0, "ap_interproc")) < B_NO_ERROR) {
-        lock_inter_cleanup(new);
-        return stat;
-    }
-    new->ben_interproc = 0;
-    new->curr_locked = 0;
-    new->sem_interproc = stat;
-    ap_register_cleanup(new->cntxt, (void *)new, lock_inter_cleanup,
-                        ap_null_cleanup);
-    return APR_SUCCESS;
-}
-
-ap_status_t lock_inter(ap_lock_t *lock)
-{
-    int32 stat;
-    
-	if (atomic_add(&lock->ben_interproc, 1) > 0){
-		if ((stat = acquire_sem(lock->sem_interproc)) != B_NO_ERROR){
-		    atomic_add(&lock->ben_interproc, -1);
-		    return stat;
-		}
-	}
-    lock->curr_locked = 1;
-    return APR_SUCCESS;
-}
-
-ap_status_t unlock_inter(ap_lock_t *lock)
-{
-    int32 stat;
-    
-	if (atomic_add(&lock->ben_interproc, -1) > 1){
-        if ((stat = release_sem(lock->sem_interproc)) != B_NO_ERROR) {
-            atomic_add(&lock->ben_interproc, 1);
-            return stat;
-        }
-    }
-    lock->curr_locked = 0;
-    return APR_SUCCESS;
-}
-
-ap_status_t destroy_inter_lock(ap_lock_t *lock)
-{
-    ap_status_t stat;
-    if ((stat = lock_inter_cleanup(lock)) == APR_SUCCESS) {
-        ap_kill_cleanup(lock->cntxt, lock, lock_inter_cleanup);
-        return APR_SUCCESS;
-    }
-    return stat;
-}
-
-ap_status_t child_init_lock(ap_lock_t **lock, ap_pool_t *cont, char *fname)
-{
-    return APR_SUCCESS;
-}
diff --git a/locks/beos/intraproc.c b/locks/beos/intraproc.c
deleted file mode 100644
index 89bfc17bc01..00000000000
--- a/locks/beos/intraproc.c
+++ /dev/null
@@ -1,126 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "locks.h"
-
-ap_status_t lock_intra_cleanup(void *data)
-{
-    ap_lock_t *lock = (ap_lock_t *)data;
-    if (lock->curr_locked == 1) {
-    	if (atomic_add(&lock->ben_intraproc , -1) > 1){
-            release_sem (lock->sem_intraproc);
-    	} else {
-            return errno;
-    	}
-    }
-    delete_sem(lock->sem_intraproc);
-    return APR_SUCCESS;
-}    
-
-ap_status_t create_intra_lock(ap_lock_t *new)
-{
-    int32 stat;
-    new->sem_intraproc = (sem_id)ap_palloc(new->cntxt, sizeof(sem_id));
-    new->ben_intraproc = (int32)ap_palloc(new->cntxt, sizeof(int32));
-    
-    
-    if ((stat = create_sem(0, "ap_intraproc")) < B_NO_ERROR){
-    	lock_intra_cleanup(new);
-        return stat;
-    }
-    new->ben_intraproc = 0;
-    new->sem_intraproc = stat;
-    new->curr_locked = 0;
-    ap_register_cleanup(new->cntxt, (void *)new, lock_intra_cleanup,
-                        ap_null_cleanup);
-    return APR_SUCCESS;
-}
-
-ap_status_t lock_intra(ap_lock_t *lock)
-{
-    int32 stat;
-    
-    if (atomic_add (&lock->ben_intraproc, 1) > 0){
-        if ((stat = acquire_sem(lock->sem_intraproc)) != B_NO_ERROR){
-            atomic_add(&lock->ben_intraproc,-1);
-	        return stat;
-        }
-    }
-    lock->curr_locked = 1;
-    return APR_SUCCESS;
-}
-
-ap_status_t unlock_intra(ap_lock_t *lock)
-{
-    int32 stat;
-    
-    if (atomic_add(&lock->ben_intraproc, -1) > 1){
-        if ((stat = release_sem(lock->sem_intraproc)) != B_NO_ERROR) {
-            atomic_add(&lock->ben_intraproc, 1);
-            return stat;
-        }
-    }
-    lock->curr_locked = 0;
-    return APR_SUCCESS;
-}
-
-ap_status_t destroy_intra_lock(ap_lock_t *lock)
-{
-    ap_status_t stat;
-    if ((stat = lock_intra_cleanup(lock)) == APR_SUCCESS) {
-        ap_kill_cleanup(lock->cntxt, lock, lock_intra_cleanup);
-        return APR_SUCCESS;
-    }
-    return stat;
-}
diff --git a/locks/beos/locks.c b/locks/beos/locks.c
deleted file mode 100644
index 362b281771c..00000000000
--- a/locks/beos/locks.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "locks.h"
-
-ap_status_t ap_create_lock(ap_lock_t **lock, ap_locktype_e type, 
-                           ap_lockscope_e scope, const char *fname, 
-                           ap_pool_t *cont)
-{
-    ap_lock_t *new;
-    ap_status_t stat;
-    
-    new = (ap_lock_t *)ap_palloc(cont, sizeof(ap_lock_t));
-    if (new == NULL){
-        return APR_ENOMEM;
-    }
-    
-    new->cntxt = cont;
-    new->type  = type;
-    new->scope = scope;
-    new->fname = ap_pstrdup(cont, fname);
-
-    if (scope != APR_CROSS_PROCESS) {
-        if ((stat = create_intra_lock(new)) != APR_SUCCESS) {
-            return stat;
-        }
-    }
-    if (scope != APR_INTRAPROCESS) {
-        if ((stat = create_inter_lock(new)) != APR_SUCCESS) {
-            return stat;
-        }
-    }
-    (*lock) = new;
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_lock(ap_lock_t *lock)
-{
-    ap_status_t stat;
-    
-    if (lock->scope != APR_CROSS_PROCESS) {
-        if ((stat = lock_intra(lock)) != APR_SUCCESS) {
-            return stat;
-        }
-    }
-    if (lock->scope != APR_INTRAPROCESS) {
-        if ((stat = lock_inter(lock)) != APR_SUCCESS) {
-            return stat;
-        }
-    }
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_unlock(ap_lock_t *lock)
-{
-    ap_status_t stat;
-    if (lock->scope != APR_CROSS_PROCESS) {
-        if ((stat = unlock_intra(lock)) != APR_SUCCESS) {
-            return stat;
-        }
-    }
-    if (lock->scope != APR_INTRAPROCESS) {
-        if ((stat = unlock_inter(lock)) != APR_SUCCESS) {
-            return stat;
-        }
-    }
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_destroy_lock(ap_lock_t *lock)
-{
-    ap_status_t stat; 
-    if (lock->scope != APR_CROSS_PROCESS) {
-        if ((stat = destroy_intra_lock(lock)) != APR_SUCCESS) {
-            return stat;
-        }
-    }
-    if (lock->scope != APR_INTRAPROCESS) {
-        if ((stat = destroy_inter_lock(lock)) != APR_SUCCESS) {
-            return stat;
-        }
-    }
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_child_init_lock(ap_lock_t **lock, const char *fname, 
-			       ap_pool_t *cont)
-{
-    ap_status_t stat;
-    if ((*lock)->scope != APR_CROSS_PROCESS) {
-        if ((stat = child_init_lock(lock, cont, fname)) != APR_SUCCESS) {
-            return stat;
-        }
-    }
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_get_lockdata(ap_lock_t *lock, char *key, void *data)
-{
-    if (lock != NULL) {
-        return ap_get_userdata(data, key, lock->cntxt);
-    }
-    else {
-        data = NULL;
-        return APR_ENOLOCK;
-    }
-}
-
-ap_status_t ap_set_lockdata(ap_lock_t *lock, void *data, char *key,
-                            ap_status_t (*cleanup) (void *))
-{
-    if (lock != NULL) {
-        return ap_set_userdata(data, key, cleanup, lock->cntxt);
-    }
-    else {
-        data = NULL;
-        return APR_ENOLOCK;
-    }
-}
-
diff --git a/locks/beos/locks.h b/locks/beos/locks.h
deleted file mode 100644
index 0160b5e71aa..00000000000
--- a/locks/beos/locks.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef LOCKS_H
-#define LOCKS_H
-
-#include <kernel/OS.h>
-#include "apr_lock.h"
-#include "apr_file_io.h"
-#include "apr_general.h"
-#include "apr_lib.h"
-
-struct ap_lock_t {
-    ap_pool_t *cntxt;
-    ap_locktype_e type;
-    ap_lockscope_e scope;
-    int curr_locked;
-    char *fname;
-	/* Inter proc */
-	sem_id sem_interproc;
-	int32  ben_interproc;
-	/* Intra Proc */
-	sem_id sem_intraproc;
-	int32  ben_intraproc;
-    /* At some point, we should do a scope for both inter and intra process
-     *  locking here.  Something like pthread_mutex with PTHREAD_PROCESS_SHARED
-     */    
-};
-
-#endif  /* LOCKS_H */
-
diff --git a/locks/beos/proc_mutex.c b/locks/beos/proc_mutex.c
new file mode 100644
index 00000000000..35a5e8f107e
--- /dev/null
+++ b/locks/beos/proc_mutex.c
@@ -0,0 +1,242 @@
+/* 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.
+ */
+
+/*Read/Write locking implementation based on the MultiLock code from
+ * Stephen Beaulieu <hippo@be.com>
+ */
+ 
+#include "apr_arch_proc_mutex.h"
+#include "apr_strings.h"
+#include "apr_portable.h"
+
+static apr_status_t _proc_mutex_cleanup(void * data)
+{
+    apr_proc_mutex_t *lock = (apr_proc_mutex_t*)data;
+    if (lock->LockCount != 0) {
+        /* we're still locked... */
+        while (atomic_add(&lock->LockCount , -1) > 1){
+            /* OK we had more than one person waiting on the lock so 
+             * the sem is also locked. Release it until we have no more
+             * locks left.
+             */
+            release_sem (lock->Lock);
+        }
+    }
+    delete_sem(lock->Lock);
+    return APR_SUCCESS;
+}    
+
+APR_DECLARE(apr_status_t) apr_proc_mutex_create(apr_proc_mutex_t **mutex,
+                                                const char *fname,
+                                                apr_lockmech_e mech,
+                                                apr_pool_t *pool)
+{
+    apr_proc_mutex_t *new;
+    apr_status_t stat = APR_SUCCESS;
+  
+    if (mech != APR_LOCK_DEFAULT && mech != APR_LOCK_DEFAULT_TIMED) {
+        return APR_ENOTIMPL;
+    }
+
+    new = (apr_proc_mutex_t *)apr_pcalloc(pool, sizeof(apr_proc_mutex_t));
+    if (new == NULL){
+        return APR_ENOMEM;
+    }
+    
+    if ((stat = create_sem(0, "APR_Lock")) < B_NO_ERROR) {
+        _proc_mutex_cleanup(new);
+        return stat;
+    }
+    new->LockCount = 0;
+    new->Lock = stat;  
+    new->pool  = pool;
+
+    apr_pool_cleanup_register(new->pool, (void *)new, _proc_mutex_cleanup,
+                              apr_pool_cleanup_null);
+
+    (*mutex) = new;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_proc_mutex_child_init(apr_proc_mutex_t **mutex,
+                                                    const char *fname,
+                                                    apr_pool_t *pool)
+{
+    return APR_SUCCESS;
+}
+    
+APR_DECLARE(apr_status_t) apr_proc_mutex_lock(apr_proc_mutex_t *mutex)
+{
+    int32 stat;
+    
+    if (atomic_add(&mutex->LockCount, 1) > 0) {
+        if ((stat = acquire_sem(mutex->Lock)) < B_NO_ERROR) {
+            atomic_add(&mutex->LockCount, -1);
+            return stat;
+        }
+    }
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_proc_mutex_trylock(apr_proc_mutex_t *mutex)
+{
+    int32 stat;
+
+    if (atomic_add(&mutex->LockCount, 1) > 0) {
+        stat = acquire_sem_etc(mutex->Lock, 1, 0, 0);
+        if (stat < B_NO_ERROR) {
+            atomic_add(&mutex->LockCount, -1);
+            if (stat == B_WOULD_BLOCK) {
+                stat = APR_EBUSY;
+            }
+            return stat;
+        }
+    }
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_proc_mutex_timedlock(apr_proc_mutex_t *mutex,
+                                               apr_interval_time_t timeout)
+{
+    int32 stat;
+
+    if (atomic_add(&mutex->LockCount, 1) > 0) {
+        if (timeout <= 0) {
+            stat = B_TIMED_OUT;
+        }
+        else {
+            stat = acquire_sem_etc(mutex->Lock, 1, B_RELATIVE_TIMEOUT,
+                                   timeout);
+        }
+        if (stat < B_NO_ERROR) {
+            atomic_add(&mutex->LockCount, -1);
+            if (stat == B_TIMED_OUT) {
+                stat = APR_TIMEUP;
+            }
+            return stat;
+        }
+    }
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_proc_mutex_unlock(apr_proc_mutex_t *mutex)
+{
+    int32 stat;
+    
+    if (atomic_add(&mutex->LockCount, -1) > 1) {
+        if ((stat = release_sem(mutex->Lock)) < B_NO_ERROR) {
+            atomic_add(&mutex->LockCount, 1);
+            return stat;
+        }
+    }
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_proc_mutex_destroy(apr_proc_mutex_t *mutex)
+{
+    apr_status_t stat;
+    if ((stat = _proc_mutex_cleanup(mutex)) == APR_SUCCESS) {
+        apr_pool_cleanup_kill(mutex->pool, mutex, _proc_mutex_cleanup);
+        return APR_SUCCESS;
+    }
+    return stat;
+}
+
+APR_DECLARE(apr_status_t) apr_proc_mutex_cleanup(void *mutex)
+{
+    return _proc_mutex_cleanup(mutex);
+}
+
+
+APR_DECLARE(const char *) apr_proc_mutex_lockfile(apr_proc_mutex_t *mutex)
+{
+    return NULL;
+}
+
+APR_DECLARE(apr_lockmech_e) apr_proc_mutex_mech(apr_proc_mutex_t *mutex)
+{
+    return APR_LOCK_DEFAULT;
+}
+
+APR_DECLARE(const char *) apr_proc_mutex_name(apr_proc_mutex_t *mutex)
+{
+    return "beossem";
+}
+
+APR_DECLARE(const char *) apr_proc_mutex_defname(void)
+{
+    return "beossem";
+}
+
+APR_PERMS_SET_ENOTIMPL(proc_mutex)
+
+APR_POOL_IMPLEMENT_ACCESSOR(proc_mutex)
+
+/* Implement OS-specific accessors defined in apr_portable.h */
+
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_get_ex(apr_os_proc_mutex_t *ospmutex, 
+                                                   apr_proc_mutex_t *pmutex,
+                                                   apr_lockmech_e *mech)
+{
+    ospmutex->sem = pmutex->Lock;
+    ospmutex->ben = pmutex->LockCount;
+    if (mech) {
+        *mech = APR_LOCK_DEFAULT;
+    }
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_get(apr_os_proc_mutex_t *ospmutex,
+                                                apr_proc_mutex_t *pmutex)
+{
+    return apr_os_proc_mutex_get_ex(ospmutex, pmutex, NULL);
+}
+
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_put_ex(apr_proc_mutex_t **pmutex,
+                                                apr_os_proc_mutex_t *ospmutex,
+                                                apr_lockmech_e mech,
+                                                int register_cleanup,
+                                                apr_pool_t *pool)
+{
+    if (pool == NULL) {
+        return APR_ENOPOOL;
+    }
+    if (mech != APR_LOCK_DEFAULT && mech != APR_LOCK_DEFAULT_TIMED) {
+        return APR_ENOTIMPL;
+    }
+
+    if ((*pmutex) == NULL) {
+        (*pmutex) = (apr_proc_mutex_t *)apr_pcalloc(pool, sizeof(apr_proc_mutex_t));
+        (*pmutex)->pool = pool;
+    }
+    (*pmutex)->Lock = ospmutex->sem;
+    (*pmutex)->LockCount = ospmutex->ben;
+
+    if (register_cleanup) {
+        apr_pool_cleanup_register(pool, *pmutex, _proc_mutex_cleanup,
+                                  apr_pool_cleanup_null);
+    }
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_put(apr_proc_mutex_t **pmutex,
+                                                apr_os_proc_mutex_t *ospmutex,
+                                                apr_pool_t *pool)
+{
+    return apr_os_proc_mutex_put_ex(pmutex, ospmutex, APR_LOCK_DEFAULT,
+                                    0, pool);
+}
+
diff --git a/locks/beos/thread_cond.c b/locks/beos/thread_cond.c
new file mode 100644
index 00000000000..a0978c008c8
--- /dev/null
+++ b/locks/beos/thread_cond.c
@@ -0,0 +1,186 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_arch_thread_mutex.h"
+#include "apr_arch_thread_cond.h"
+#include "apr_strings.h"
+#include "apr_portable.h"
+
+static apr_status_t thread_cond_cleanup(void *data)
+{
+    struct waiter *w;
+    apr_thread_cond_t *cond = (apr_thread_cond_t *)data;
+
+    acquire_sem(cond->lock);
+    delete_sem(cond->lock);
+
+    return APR_SUCCESS;
+}
+
+static struct waiter_t *make_waiter(apr_pool_t *pool)
+{
+    struct waiter_t *w = (struct waiter_t*)
+                       apr_palloc(pool, sizeof(struct waiter_t));
+    if (w == NULL)
+        return NULL;
+      
+    w->sem  = create_sem(0, "apr conditional waiter");
+    if (w->sem < 0)
+        return NULL;
+
+    APR_RING_ELEM_INIT(w, link);
+    
+    return w;
+}
+  
+APR_DECLARE(apr_status_t) apr_thread_cond_create(apr_thread_cond_t **cond,
+                                                 apr_pool_t *pool)
+{
+    apr_thread_cond_t *new_cond;
+    sem_id rv;
+    int i;
+
+    new_cond = (apr_thread_cond_t *)apr_palloc(pool, sizeof(apr_thread_cond_t));
+
+    if (new_cond == NULL)
+        return APR_ENOMEM;
+
+    if ((rv = create_sem(1, "apr conditional lock")) < B_OK)
+        return rv;
+    
+    new_cond->lock = rv;
+    new_cond->pool = pool;
+    APR_RING_INIT(&new_cond->alist, waiter_t, link);
+    APR_RING_INIT(&new_cond->flist, waiter_t, link);
+        
+    for (i=0;i < 10 ;i++) {
+        struct waiter_t *nw = make_waiter(pool);
+        APR_RING_INSERT_TAIL(&new_cond->flist, nw, waiter_t, link);
+    }
+
+    apr_pool_cleanup_register(new_cond->pool,
+                              (void *)new_cond, thread_cond_cleanup,
+                              apr_pool_cleanup_null);
+
+    *cond = new_cond;
+    return APR_SUCCESS;
+}
+
+
+static apr_status_t do_wait(apr_thread_cond_t *cond, apr_thread_mutex_t *mutex,
+                            apr_interval_time_t timeout)
+{
+    struct waiter_t *wait;
+    thread_id cth = find_thread(NULL);
+    apr_status_t rv;
+    int flags = B_RELATIVE_TIMEOUT;
+    
+    /* We must be the owner of the mutex or we can't do this... */    
+    if (mutex->owner != cth) {
+        /* What should we return??? */
+        return APR_EINVAL;
+    }
+
+    acquire_sem(cond->lock);
+    wait = APR_RING_FIRST(&cond->flist);
+    if (wait)
+        APR_RING_REMOVE(wait, link);
+    else
+        wait = make_waiter(cond->pool);   
+    APR_RING_INSERT_TAIL(&cond->alist, wait, waiter_t, link);
+    cond->condlock = mutex;
+    release_sem(cond->lock);
+       
+    apr_thread_mutex_unlock(cond->condlock);
+
+    if (timeout == 0)
+        flags = 0;
+        
+    rv = acquire_sem_etc(wait->sem, 1, flags, timeout);
+
+    apr_thread_mutex_lock(cond->condlock);
+    
+    if (rv != B_OK) {
+        if (rv == B_TIMED_OUT)
+            return APR_TIMEUP;
+        return rv;       
+    }
+
+    acquire_sem(cond->lock);
+    APR_RING_REMOVE(wait, link);
+    APR_RING_INSERT_TAIL(&cond->flist, wait, waiter_t, link);
+    release_sem(cond->lock);
+    
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_cond_wait(apr_thread_cond_t *cond,
+                                               apr_thread_mutex_t *mutex)
+{
+    return do_wait(cond, mutex, 0);
+}
+
+APR_DECLARE(apr_status_t) apr_thread_cond_timedwait(apr_thread_cond_t *cond,
+                                                    apr_thread_mutex_t *mutex,
+                                                    apr_interval_time_t timeout)
+{
+    return do_wait(cond, mutex, timeout);
+}
+
+APR_DECLARE(apr_status_t) apr_thread_cond_signal(apr_thread_cond_t *cond)
+{
+    struct waiter_t *wake;
+
+    acquire_sem(cond->lock);    
+    if (!APR_RING_EMPTY(&cond->alist, waiter_t, link)) {
+        wake = APR_RING_FIRST(&cond->alist);
+        APR_RING_REMOVE(wake, link);
+        release_sem(wake->sem);
+        APR_RING_INSERT_TAIL(&cond->flist, wake, waiter_t, link);
+    }
+    release_sem(cond->lock);
+    
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_cond_broadcast(apr_thread_cond_t *cond)
+{
+    struct waiter_t *wake;
+    
+    acquire_sem(cond->lock);
+    while (! APR_RING_EMPTY(&cond->alist, waiter_t, link)) {
+        wake = APR_RING_FIRST(&cond->alist);
+        APR_RING_REMOVE(wake, link);
+        release_sem(wake->sem);
+        APR_RING_INSERT_TAIL(&cond->flist, wake, waiter_t, link);
+    }
+    release_sem(cond->lock);
+    
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_cond_destroy(apr_thread_cond_t *cond)
+{
+    apr_status_t stat;
+    if ((stat = thread_cond_cleanup(cond)) == APR_SUCCESS) {
+        apr_pool_cleanup_kill(cond->pool, cond, thread_cond_cleanup);
+        return APR_SUCCESS;
+    }
+    return stat;
+}
+
+APR_POOL_IMPLEMENT_ACCESSOR(thread_cond)
+
diff --git a/locks/beos/thread_mutex.c b/locks/beos/thread_mutex.c
new file mode 100644
index 00000000000..e4099d8826d
--- /dev/null
+++ b/locks/beos/thread_mutex.c
@@ -0,0 +1,202 @@
+/* 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.
+ */
+
+/*Read/Write locking implementation based on the MultiLock code from
+ * Stephen Beaulieu <hippo@be.com>
+ */
+ 
+#include "apr_arch_thread_mutex.h"
+#include "apr_strings.h"
+#include "apr_portable.h"
+
+static apr_status_t _thread_mutex_cleanup(void * data)
+{
+    apr_thread_mutex_t *lock = (apr_thread_mutex_t*)data;
+    if (lock->LockCount != 0) {
+        /* we're still locked... */
+        while (atomic_add(&lock->LockCount , -1) > 1){
+            /* OK we had more than one person waiting on the lock so 
+             * the sem is also locked. Release it until we have no more
+             * locks left.
+             */
+            release_sem (lock->Lock);
+        }
+    }
+    delete_sem(lock->Lock);
+    return APR_SUCCESS;
+}    
+
+APR_DECLARE(apr_status_t) apr_thread_mutex_create(apr_thread_mutex_t **mutex,
+                                                  unsigned int flags,
+                                                  apr_pool_t *pool)
+{
+    apr_thread_mutex_t *new_m;
+    apr_status_t stat = APR_SUCCESS;
+  
+    new_m = (apr_thread_mutex_t *)apr_pcalloc(pool, sizeof(apr_thread_mutex_t));
+    if (new_m == NULL){
+        return APR_ENOMEM;
+    }
+    
+    if ((stat = create_sem(0, "APR_Lock")) < B_NO_ERROR) {
+        _thread_mutex_cleanup(new_m);
+        return stat;
+    }
+    new_m->LockCount = 0;
+    new_m->Lock = stat;  
+    new_m->pool  = pool;
+
+    /* Optimal default is APR_THREAD_MUTEX_UNNESTED, 
+     * no additional checks required for either flag.
+     */
+    new_m->nested = flags & APR_THREAD_MUTEX_NESTED;
+
+    apr_pool_cleanup_register(new_m->pool, (void *)new_m, _thread_mutex_cleanup,
+                              apr_pool_cleanup_null);
+
+    (*mutex) = new_m;
+    return APR_SUCCESS;
+}
+
+#if APR_HAS_CREATE_LOCKS_NP
+APR_DECLARE(apr_status_t) apr_thread_mutex_create_np(apr_thread_mutex_t **mutex,
+                                                   const char *fname,
+                                                   apr_lockmech_e_np mech,
+                                                   apr_pool_t *pool)
+{
+    return APR_ENOTIMPL;
+}       
+#endif
+  
+APR_DECLARE(apr_status_t) apr_thread_mutex_lock(apr_thread_mutex_t *mutex)
+{
+    int32 stat;
+    thread_id me = find_thread(NULL);
+    
+    if (mutex->nested && mutex->owner == me) {
+        mutex->owner_ref++;
+        return APR_SUCCESS;
+    }
+    
+    if (atomic_add(&mutex->LockCount, 1) > 0) {
+        if ((stat = acquire_sem(mutex->Lock)) < B_NO_ERROR) {
+            /* Oh dear, acquire_sem failed!!  */
+            atomic_add(&mutex->LockCount, -1);
+            return stat;
+        }
+    }
+
+    mutex->owner = me;
+    mutex->owner_ref = 1;
+    
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_mutex_trylock(apr_thread_mutex_t *mutex)
+{
+    int32 stat;
+    thread_id me = find_thread(NULL);
+    
+    if (mutex->nested && mutex->owner == me) {
+        mutex->owner_ref++;
+        return APR_SUCCESS;
+    }
+    
+    if (atomic_add(&mutex->LockCount, 1) > 0) {
+        if ((stat = acquire_sem_etc(mutex->Lock, 1, 0, 0)) < B_NO_ERROR) {
+            atomic_add(&mutex->LockCount, -1);
+            if (stat == B_WOULD_BLOCK) {
+                stat = APR_EBUSY;
+            }
+            return stat;
+        }
+    }
+
+    mutex->owner = me;
+    mutex->owner_ref = 1;
+    
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_mutex_timedlock(apr_thread_mutex_t *mutex,
+                                                 apr_interval_time_t timeout)
+{
+    int32 stat;
+    thread_id me = find_thread(NULL);
+    
+    if (mutex->nested && mutex->owner == me) {
+        mutex->owner_ref++;
+        return APR_SUCCESS;
+    }
+    
+    if (atomic_add(&mutex->LockCount, 1) > 0) {
+        if (timeout <= 0) {
+            stat = B_TIMED_OUT;
+        }
+        else {
+            stat = acquire_sem_etc(mutex->Lock, 1, B_RELATIVE_TIMEOUT,
+                                   timeout);
+        }
+        if (stat < B_NO_ERROR) {
+            atomic_add(&mutex->LockCount, -1);
+            if (stat == B_TIMED_OUT) {
+                stat = APR_TIMEUP;
+            }
+            return stat;
+        }
+    }
+
+    mutex->owner = me;
+    mutex->owner_ref = 1;
+    
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_mutex_unlock(apr_thread_mutex_t *mutex)
+{
+    int32 stat;
+        
+    if (mutex->nested && mutex->owner == find_thread(NULL)) {
+        mutex->owner_ref--;
+        if (mutex->owner_ref > 0)
+            return APR_SUCCESS;
+    }
+    
+    if (atomic_add(&mutex->LockCount, -1) > 1) {
+        if ((stat = release_sem(mutex->Lock)) < B_NO_ERROR) {
+            atomic_add(&mutex->LockCount, 1);
+            return stat;
+        }
+    }
+
+    mutex->owner = -1;
+    mutex->owner_ref = 0;
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_mutex_destroy(apr_thread_mutex_t *mutex)
+{
+    apr_status_t stat;
+    if ((stat = _thread_mutex_cleanup(mutex)) == APR_SUCCESS) {
+        apr_pool_cleanup_kill(mutex->pool, mutex, _thread_mutex_cleanup);
+        return APR_SUCCESS;
+    }
+    return stat;
+}
+
+APR_POOL_IMPLEMENT_ACCESSOR(thread_mutex)
+
diff --git a/locks/beos/thread_rwlock.c b/locks/beos/thread_rwlock.c
new file mode 100644
index 00000000000..a540b445574
--- /dev/null
+++ b/locks/beos/thread_rwlock.c
@@ -0,0 +1,190 @@
+/* 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.
+ */
+
+/*Read/Write locking implementation based on the MultiLock code from
+ * Stephen Beaulieu <hippo@be.com>
+ */
+ 
+#include "apr_arch_thread_rwlock.h"
+#include "apr_strings.h"
+#include "apr_portable.h"
+
+#define BIG_NUM 100000
+
+static apr_status_t _thread_rw_cleanup(void * data)
+{
+    apr_thread_rwlock_t *mutex = (apr_thread_rwlock_t*)data;
+
+    if (mutex->ReadCount != 0) {
+    	while (atomic_add(&mutex->ReadCount , -1) > 1){
+            release_sem (mutex->Read);
+    	}
+    }
+    if (mutex->WriteCount != 0) {
+    	while (atomic_add(&mutex->WriteCount , -1) > 1){
+            release_sem (mutex->Write);
+    	}
+    }
+    if (mutex->LockCount != 0) {
+    	while (atomic_add(&mutex->LockCount , -1) > 1){
+            release_sem (mutex->Lock);
+    	}
+    }
+    
+    delete_sem(mutex->Read);
+    delete_sem(mutex->Write);
+    delete_sem(mutex->Lock);
+    return APR_SUCCESS;
+}    
+
+APR_DECLARE(apr_status_t) apr_thread_rwlock_create(apr_thread_rwlock_t **rwlock,
+                                                   apr_pool_t *pool)
+{
+    apr_thread_rwlock_t *new;
+  
+    new = (apr_thread_rwlock_t *)apr_pcalloc(pool, sizeof(apr_thread_rwlock_t));
+    if (new == NULL){
+        return APR_ENOMEM;
+    }
+    
+    new->pool  = pool;
+    /* we need to make 3 locks... */
+    new->ReadCount = 0;
+    new->WriteCount = 0;
+    new->LockCount = 0;
+    new->Read  = create_sem(0, "APR_ReadLock");
+    new->Write = create_sem(0, "APR_WriteLock");
+    new->Lock  = create_sem(0, "APR_Lock");
+    
+    if (new->Lock < 0 || new->Read < 0 || new->Write < 0) {
+        _thread_rw_cleanup(new);
+        return -1;
+    }
+
+    apr_pool_cleanup_register(new->pool, (void *)new, _thread_rw_cleanup,
+                              apr_pool_cleanup_null);
+    (*rwlock) = new;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_rwlock_rdlock(apr_thread_rwlock_t *rwlock)
+{
+    int32 rv = APR_SUCCESS;
+
+    if (find_thread(NULL) == rwlock->writer) {
+        /* we're the writer - no problem */
+        rwlock->Nested++;
+    } else {
+        /* we're not the writer */
+        int32 r = atomic_add(&rwlock->ReadCount, 1);
+        if (r < 0) {
+            /* Oh dear, writer holds lock, wait for sem */
+            rv = acquire_sem_etc(rwlock->Read, 1, B_DO_NOT_RESCHEDULE,
+                                 B_INFINITE_TIMEOUT);
+        }
+    }
+
+    return rv;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_rwlock_tryrdlock(apr_thread_rwlock_t *rwlock)
+{
+    return APR_ENOTIMPL;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_rwlock_wrlock(apr_thread_rwlock_t *rwlock)
+{
+    int rv = APR_SUCCESS;
+
+    if (find_thread(NULL) == rwlock->writer) {
+        rwlock->Nested++;
+    } else {
+        /* we're not the writer... */
+        if (atomic_add(&rwlock->LockCount, 1) >= 1) {
+            /* we're locked - acquire the sem */
+            rv = acquire_sem_etc(rwlock->Lock, 1, B_DO_NOT_RESCHEDULE,
+                                 B_INFINITE_TIMEOUT);
+        }
+        if (rv == APR_SUCCESS) {
+            /* decrement the ReadCount to a large -ve number so that
+             * we block on new readers...
+             */
+            int32 readers = atomic_add(&rwlock->ReadCount, -BIG_NUM);
+            if (readers > 0) {
+                /* readers are holding the lock */
+                rv = acquire_sem_etc(rwlock->Write, readers, B_DO_NOT_RESCHEDULE,
+                                     B_INFINITE_TIMEOUT);
+            }
+            if (rv == APR_SUCCESS)
+                rwlock->writer = find_thread(NULL);
+        }
+    }
+    
+    return rv;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_rwlock_trywrlock(apr_thread_rwlock_t *rwlock)
+{
+    return APR_ENOTIMPL;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_rwlock_unlock(apr_thread_rwlock_t *rwlock)
+{
+    apr_status_t rv = APR_SUCCESS;
+    int32 readers;
+
+    /* we know we hold the lock, so don't check it :) */
+    if (find_thread(NULL) == rwlock->writer) {
+    /* we know we hold the lock, so don't check it :) */
+        if (rwlock->Nested > 1) {
+            /* we're recursively locked */
+            rwlock->Nested--;
+            return APR_SUCCESS;
+        }
+        /* OK so we need to release the sem if we have it :) */
+        readers = atomic_add(&rwlock->ReadCount, BIG_NUM) + BIG_NUM;
+        if (readers > 0) {
+            rv = release_sem_etc(rwlock->Read, readers, B_DO_NOT_RESCHEDULE);
+        }
+        if (rv == APR_SUCCESS) {
+            rwlock->writer = -1;
+            if (atomic_add(&rwlock->LockCount, -1) > 1) {
+                rv = release_sem_etc(rwlock->Lock, 1, B_DO_NOT_RESCHEDULE);
+            }
+        }
+    } else {
+       /* We weren't the Writer, so just release the ReadCount... */
+       if (atomic_add(&rwlock->ReadCount, -1) < 0) {
+            /* we have a writer waiting for the lock, so release it */
+            rv = release_sem_etc(rwlock->Write, 1, B_DO_NOT_RESCHEDULE);
+        }
+    }
+
+    return rv;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_rwlock_destroy(apr_thread_rwlock_t *rwlock)
+{
+    apr_status_t stat;
+    if ((stat = _thread_rw_cleanup(rwlock)) == APR_SUCCESS) {
+        apr_pool_cleanup_kill(rwlock->pool, rwlock, _thread_rw_cleanup);
+        return APR_SUCCESS;
+    }
+    return stat;
+}
+
+APR_POOL_IMPLEMENT_ACCESSOR(thread_rwlock)
+
diff --git a/locks/netware/proc_mutex.c b/locks/netware/proc_mutex.c
new file mode 100644
index 00000000000..287011b0683
--- /dev/null
+++ b/locks/netware/proc_mutex.c
@@ -0,0 +1,184 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_private.h"
+#include "apr_portable.h"
+#include "apr_arch_proc_mutex.h"
+#include "apr_arch_thread_mutex.h"
+
+APR_DECLARE(apr_status_t) apr_proc_mutex_create(apr_proc_mutex_t **mutex,
+                                                const char *fname,
+                                                apr_lockmech_e mech,
+                                                apr_pool_t *pool)
+{
+    apr_status_t ret;
+    apr_proc_mutex_t *new_mutex;
+    unsigned int flags = APR_THREAD_MUTEX_DEFAULT;
+
+    *mutex = NULL;
+    if (mech == APR_LOCK_DEFAULT_TIMED) {
+        flags |= APR_THREAD_MUTEX_TIMED;
+    }
+    else if (mech != APR_LOCK_DEFAULT) {
+        return APR_ENOTIMPL;
+    }
+
+    new_mutex = (apr_proc_mutex_t *)apr_pcalloc(pool, sizeof(apr_proc_mutex_t));
+    if (new_mutex == NULL) {
+        return APR_ENOMEM;
+    }     
+    
+    new_mutex->pool = pool;
+    ret = apr_thread_mutex_create(&(new_mutex->mutex), flags, pool);
+
+    if (ret == APR_SUCCESS)
+        *mutex = new_mutex;
+
+    return ret;
+}
+
+APR_DECLARE(apr_status_t) apr_proc_mutex_child_init(apr_proc_mutex_t **mutex,
+                                                    const char *fname,
+                                                    apr_pool_t *pool)
+{
+    return APR_SUCCESS;
+}
+    
+APR_DECLARE(apr_status_t) apr_proc_mutex_lock(apr_proc_mutex_t *mutex)
+{
+    if (mutex)
+        return apr_thread_mutex_lock(mutex->mutex);
+    return APR_ENOLOCK;
+}
+
+APR_DECLARE(apr_status_t) apr_proc_mutex_trylock(apr_proc_mutex_t *mutex)
+{
+    if (mutex)
+        return apr_thread_mutex_trylock(mutex->mutex);
+    return APR_ENOLOCK;
+}
+
+APR_DECLARE(apr_status_t) apr_proc_mutex_timedlock(apr_proc_mutex_t *mutex,
+                                               apr_interval_time_t timeout)
+{
+    if (mutex)
+        return apr_thread_mutex_timedlock(mutex->mutex, timeout);
+    return APR_ENOLOCK;
+}
+
+APR_DECLARE(apr_status_t) apr_proc_mutex_unlock(apr_proc_mutex_t *mutex)
+{
+    if (mutex)
+        return apr_thread_mutex_unlock(mutex->mutex);
+    return APR_ENOLOCK;
+}
+
+APR_DECLARE(apr_status_t) apr_proc_mutex_cleanup(void *mutex)
+{
+    return apr_proc_mutex_destroy(mutex);
+}
+
+APR_DECLARE(apr_status_t) apr_proc_mutex_destroy(apr_proc_mutex_t *mutex)
+{
+    if (mutex)
+        return apr_thread_mutex_destroy(mutex->mutex);
+    return APR_ENOLOCK;
+}
+
+APR_DECLARE(const char *) apr_proc_mutex_lockfile(apr_proc_mutex_t *mutex)
+{
+    return NULL;
+}
+
+APR_DECLARE(apr_lockmech_e) apr_proc_mutex_mech(apr_proc_mutex_t *mutex)
+{
+    return APR_LOCK_DEFAULT;
+}
+
+APR_DECLARE(const char *) apr_proc_mutex_name(apr_proc_mutex_t *mutex)
+{
+    return "netwarethread";
+}
+
+APR_DECLARE(const char *) apr_proc_mutex_defname(void)
+{
+    return "netwarethread";
+}
+
+APR_PERMS_SET_ENOTIMPL(proc_mutex)
+
+APR_POOL_IMPLEMENT_ACCESSOR(proc_mutex)
+
+/* Implement OS-specific accessors defined in apr_portable.h */
+
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_get_ex(apr_os_proc_mutex_t *ospmutex, 
+                                                   apr_proc_mutex_t *pmutex,
+                                                   apr_lockmech_e *mech)
+{
+    if (!pmutex->mutex) {
+        return APR_ENOLOCK;
+    }
+
+    *ospmutex = pmutex->mutex->mutex;
+    if (mech) {
+        *mech = APR_LOCK_DEFAULT;
+    }
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_get(apr_os_proc_mutex_t *ospmutex,
+                                                apr_proc_mutex_t *pmutex)
+{
+    return apr_os_proc_mutex_get_ex(ospmutex, pmutex, NULL);
+}
+
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_put_ex(apr_proc_mutex_t **pmutex,
+                                                apr_os_proc_mutex_t *ospmutex,
+                                                apr_lockmech_e mech,
+                                                int register_cleanup,
+                                                apr_pool_t *pool)
+{
+    if (pool == NULL) {
+        return APR_ENOPOOL;
+    }
+    if (mech != APR_LOCK_DEFAULT) {
+        return APR_ENOTIMPL;
+    }
+
+    if ((*pmutex) == NULL) {
+        (*pmutex) = apr_pcalloc(pool, sizeof(apr_proc_mutex_t));
+        (*pmutex)->pool = pool;
+    }
+    (*pmutex)->mutex = apr_pcalloc(pool, sizeof(apr_thread_mutex_t));
+    (*pmutex)->mutex->mutex = *ospmutex;
+    (*pmutex)->mutex->pool = pool;
+
+    if (register_cleanup) {
+        apr_pool_cleanup_register(pool, *pmutex, apr_proc_mutex_cleanup,
+                                  apr_pool_cleanup_null);
+    }
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_put(apr_proc_mutex_t **pmutex,
+                                                apr_os_proc_mutex_t *ospmutex,
+                                                apr_pool_t *pool)
+{
+    return apr_os_proc_mutex_put_ex(pmutex, ospmutex, APR_LOCK_DEFAULT,
+                                    0, pool);
+}
+
diff --git a/locks/netware/thread_cond.c b/locks/netware/thread_cond.c
new file mode 100644
index 00000000000..432b0d2908b
--- /dev/null
+++ b/locks/netware/thread_cond.c
@@ -0,0 +1,111 @@
+/* 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 <nks/errno.h>
+
+#include "apr.h"
+#include "apr_private.h"
+#include "apr_general.h"
+#include "apr_strings.h"
+#include "apr_arch_thread_mutex.h"
+#include "apr_arch_thread_cond.h"
+#include "apr_portable.h"
+
+static apr_status_t thread_cond_cleanup(void *data)
+{
+    apr_thread_cond_t *cond = (apr_thread_cond_t *)data;
+
+    NXCondFree(cond->cond);        
+    return APR_SUCCESS;
+} 
+
+APR_DECLARE(apr_status_t) apr_thread_cond_create(apr_thread_cond_t **cond,
+                                                 apr_pool_t *pool)
+{
+    apr_thread_cond_t *new_cond = NULL;
+
+    new_cond = (apr_thread_cond_t *)apr_pcalloc(pool, sizeof(apr_thread_cond_t));
+	
+	if(new_cond ==NULL) {
+        return APR_ENOMEM;
+    }     
+    new_cond->pool = pool;
+
+    new_cond->cond = NXCondAlloc(NULL);
+    
+    if(new_cond->cond == NULL)
+        return APR_ENOMEM;
+
+    apr_pool_cleanup_register(new_cond->pool, new_cond, 
+                                (void*)thread_cond_cleanup,
+                                apr_pool_cleanup_null);
+   *cond = new_cond;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_cond_wait(apr_thread_cond_t *cond,
+                                               apr_thread_mutex_t *mutex)
+{
+    if (NXCondWait(cond->cond, mutex->mutex) != 0)
+        return APR_EINTR;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_cond_timedwait(apr_thread_cond_t *cond,
+                                                    apr_thread_mutex_t *mutex,
+                                                    apr_interval_time_t timeout)
+{
+    int rc;
+    if (timeout < 0) {
+        rc = NXCondWait(cond->cond, mutex->mutex);
+    }
+    else {
+        timeout = timeout * 1000 / NXGetSystemTick();
+        rc = NXCondTimedWait(cond->cond, mutex->mutex, timeout);
+        if (rc == NX_ETIMEDOUT) {
+            return APR_TIMEUP;
+        }
+    }
+    if (rc != 0) {
+        return APR_EINTR;
+    }
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_cond_signal(apr_thread_cond_t *cond)
+{
+    NXCondSignal(cond->cond);
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_cond_broadcast(apr_thread_cond_t *cond)
+{
+    NXCondBroadcast(cond->cond);
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_cond_destroy(apr_thread_cond_t *cond)
+{
+    apr_status_t stat;
+    if ((stat = thread_cond_cleanup(cond)) == APR_SUCCESS) {
+        apr_pool_cleanup_kill(cond->pool, cond, thread_cond_cleanup);
+        return APR_SUCCESS;
+    }
+    return stat;
+}
+
+APR_POOL_IMPLEMENT_ACCESSOR(thread_cond)
+
diff --git a/locks/netware/thread_mutex.c b/locks/netware/thread_mutex.c
new file mode 100644
index 00000000000..435abebba30
--- /dev/null
+++ b/locks/netware/thread_mutex.c
@@ -0,0 +1,181 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_private.h"
+#include "apr_general.h"
+#include "apr_strings.h"
+#include "apr_arch_thread_mutex.h"
+#include "apr_thread_cond.h"
+#include "apr_portable.h"
+
+static apr_status_t thread_mutex_cleanup(void *data)
+{
+    apr_thread_mutex_t *mutex = (apr_thread_mutex_t *)data;
+
+    NXMutexFree(mutex->mutex);        
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_mutex_create(apr_thread_mutex_t **mutex,
+                                                  unsigned int flags,
+                                                  apr_pool_t *pool)
+{
+    apr_thread_mutex_t *new_mutex = NULL;
+
+    /* XXX: Implement _UNNESTED flavor and favor _DEFAULT for performance
+     */
+    if (flags & APR_THREAD_MUTEX_UNNESTED) {
+        return APR_ENOTIMPL;
+    }
+    new_mutex = (apr_thread_mutex_t *)apr_pcalloc(pool, sizeof(apr_thread_mutex_t));
+
+    if (new_mutex == NULL) {
+        return APR_ENOMEM;
+    }     
+    new_mutex->pool = pool;
+
+    new_mutex->mutex = NXMutexAlloc(NX_MUTEX_RECURSIVE, 0, NULL);
+    
+    if(new_mutex->mutex == NULL)
+        return APR_ENOMEM;
+
+    if (flags & APR_THREAD_MUTEX_TIMED) {
+        apr_status_t rv = apr_thread_cond_create(&new_mutex->cond, pool);
+        if (rv != APR_SUCCESS) {
+            NXMutexFree(new_mutex->mutex);        
+            return rv;
+        }
+    }
+
+    apr_pool_cleanup_register(new_mutex->pool, new_mutex, 
+                                (void*)thread_mutex_cleanup,
+                                apr_pool_cleanup_null);
+   *mutex = new_mutex;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_mutex_lock(apr_thread_mutex_t *mutex)
+{
+    if (mutex->cond) {
+        apr_status_t rv;
+        NXLock(mutex->mutex);
+        if (mutex->locked) {
+            mutex->num_waiters++;
+            rv = apr_thread_cond_wait(mutex->cond, mutex);
+            mutex->num_waiters--;
+        }
+        else {
+            mutex->locked = 1;
+            rv = APR_SUCCESS;
+        }
+        NXUnlock(mutex->mutex);
+        return rv;
+    }
+
+    NXLock(mutex->mutex);
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_mutex_trylock(apr_thread_mutex_t *mutex)
+{
+    if (mutex->cond) {
+        apr_status_t rv;
+        NXLock(mutex->mutex);
+        if (mutex->locked) {
+            rv = APR_EBUSY;
+        }
+        else {
+            mutex->locked = 1;
+            rv = APR_SUCCESS;
+        }
+        NXUnlock(mutex->mutex);
+        return rv;
+    }
+
+    if (!NXTryLock(mutex->mutex))
+        return APR_EBUSY;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_mutex_timedlock(apr_thread_mutex_t *mutex,
+                                                 apr_interval_time_t timeout)
+{
+    if (mutex->cond) {
+        apr_status_t rv = APR_SUCCESS;
+
+        NXLock(mutex->mutex);
+        if (mutex->locked) {
+            if (timeout <= 0) {
+                rv = APR_TIMEUP;
+            }
+            else {
+                mutex->num_waiters++;
+                do {
+                    rv = apr_thread_cond_timedwait(mutex->cond, mutex,
+                                                   timeout);
+                } while (rv == APR_SUCCESS && mutex->locked);
+                mutex->num_waiters--;
+            }
+        }
+        if (rv == APR_SUCCESS) {
+            mutex->locked = 1;
+        }
+        NXUnlock(mutex->mutex);
+        return rv;
+    }
+
+    return APR_ENOTIMPL;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_mutex_unlock(apr_thread_mutex_t *mutex)
+{
+    apr_status_t rv = APR_SUCCESS;
+
+    if (mutex->cond) {
+        NXLock(mutex->mutex);
+
+        if (!mutex->locked) {
+            rv = APR_EINVAL;
+        }
+        else if (mutex->num_waiters) {
+            rv = apr_thread_cond_signal(mutex->cond);
+        }
+        if (rv == APR_SUCCESS) {
+            mutex->locked = 0;
+        }
+    }
+
+    NXUnlock(mutex->mutex);
+    return rv;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_mutex_destroy(apr_thread_mutex_t *mutex)
+{
+    apr_status_t stat, rv = APR_SUCCESS;
+    if (mutex->cond) {
+        rv = apr_thread_cond_destroy(mutex->cond);
+        mutex->cond = NULL;
+    }
+    stat = apr_pool_cleanup_run(mutex->pool, mutex, thread_mutex_cleanup);
+    if (stat == APR_SUCCESS && rv) {
+        stat = rv;
+    }
+    return stat;
+}
+
+APR_POOL_IMPLEMENT_ACCESSOR(thread_mutex)
+
diff --git a/locks/netware/thread_rwlock.c b/locks/netware/thread_rwlock.c
new file mode 100644
index 00000000000..f971aefd47b
--- /dev/null
+++ b/locks/netware/thread_rwlock.c
@@ -0,0 +1,102 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_private.h"
+#include "apr_general.h"
+#include "apr_strings.h"
+#include "apr_arch_thread_rwlock.h"
+#include "apr_portable.h"
+
+static apr_status_t thread_rwlock_cleanup(void *data)
+{
+    apr_thread_rwlock_t *rwlock = (apr_thread_rwlock_t *)data;
+
+    NXRwLockFree (rwlock->rwlock);
+    return APR_SUCCESS;
+} 
+
+APR_DECLARE(apr_status_t) apr_thread_rwlock_create(apr_thread_rwlock_t **rwlock,
+                                                   apr_pool_t *pool)
+{
+    apr_thread_rwlock_t *new_rwlock = NULL;
+   
+    NXHierarchy_t hierarchy = 1;   /* for libc NKS NXRwLockAlloc */
+    NXLockInfo_t *info;            /* for libc NKS NXRwLockAlloc */
+
+    new_rwlock = (apr_thread_rwlock_t *)apr_pcalloc(pool, sizeof(apr_thread_rwlock_t));
+
+    if(new_rwlock ==NULL) {
+        return APR_ENOMEM;
+    }     
+    new_rwlock->pool = pool;
+    
+    info = (NXLockInfo_t *)apr_pcalloc(pool, sizeof(NXLockInfo_t));
+    new_rwlock->rwlock = NXRwLockAlloc(hierarchy, info);
+    if(new_rwlock->rwlock == NULL)
+        return APR_ENOMEM;
+
+    apr_pool_cleanup_register(new_rwlock->pool, new_rwlock, thread_rwlock_cleanup,
+                              apr_pool_cleanup_null);
+    *rwlock = new_rwlock;
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_rwlock_rdlock(apr_thread_rwlock_t *rwlock)
+{
+    NXRdLock(rwlock->rwlock);
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_rwlock_tryrdlock(apr_thread_rwlock_t *rwlock)
+{
+    if (!NXTryRdLock(rwlock->rwlock))
+        return APR_EBUSY;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_rwlock_wrlock(apr_thread_rwlock_t *rwlock)
+{
+    NXWrLock(rwlock->rwlock);
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_rwlock_trywrlock(apr_thread_rwlock_t *rwlock)
+{
+    if (!NXTryWrLock(rwlock->rwlock))
+        return APR_EBUSY;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_rwlock_unlock(apr_thread_rwlock_t *rwlock)
+{
+    NXRwUnlock(rwlock->rwlock);
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_rwlock_destroy(apr_thread_rwlock_t *rwlock)
+{
+    apr_status_t stat;
+    if ((stat = thread_rwlock_cleanup(rwlock)) == APR_SUCCESS) {
+        apr_pool_cleanup_kill(rwlock->pool, rwlock, thread_rwlock_cleanup);
+        return APR_SUCCESS;
+    }
+    return stat;
+}
+
+APR_POOL_IMPLEMENT_ACCESSOR(thread_rwlock)
+
diff --git a/locks/os2/.cvsignore b/locks/os2/.cvsignore
deleted file mode 100644
index f3c7a7c5da6..00000000000
--- a/locks/os2/.cvsignore
+++ /dev/null
@@ -1 +0,0 @@
-Makefile
diff --git a/locks/os2/Makefile.in b/locks/os2/Makefile.in
deleted file mode 100644
index 9ba454f10f7..00000000000
--- a/locks/os2/Makefile.in
+++ /dev/null
@@ -1,59 +0,0 @@
-#CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
-#LIBS=$(EXTRA_LIBS) $(LIBS1)
-#INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
-#LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
-
-CC=@CC@
-RANLIB=@RANLIB@
-CFLAGS=@CFLAGS@ @OPTIM@
-LIBS=@LIBS@
-LDFLAGS=@LDFLAGS@ $(LIBS)
-INCDIR=../../inc
-INCDIR1=../../include
-INCDIR2=../../file_io/os2
-INCLUDES=-I$(INCDIR) -I$(INCDIR1) -I$(INCDIR2) -I.
-
-LIB=lock.a
-
-OBJS=locks.o
-
-.c.o:
-	$(CC) $(CFLAGS) -c $(INCLUDES) $<
-
-all: $(LIB)
-
-clean:
-	$(RM) -f *.o *.a *.so
-
-distclean: clean
-	-$(RM) -f Makefile
-
-$(OBJS): Makefile
-
-$(LIB): $(OBJS)
-	$(RM) -f $@
-	$(AR) cr $@ $(OBJS)
-	$(RANLIB) $@
-
-#
-# We really don't expect end users to use this rule.  It works only with
-# gcc, and rebuilds Makefile.tmpl.  You have to re-run Configure after
-# using it.
-#
-depend:
-	cp Makefile.in Makefile.in.bak \
-	    && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.in > Makefile.new \
-	    && gcc -MM $(INCLUDES) $(CFLAGS) *.c | sed -e "s%\\\\\(.\)%/\\1%g" >> Makefile.new \
-	    && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
-                   -e '1,$$s: $(INCDIR1)/: $$(INCDIR1)/:g' \
-                   -e '1,$$s: $(INCDIR2)/: $$(INCDIR2)/:g' \
-	           -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
-		> Makefile.in \
-	    && rm Makefile.new
-
-# DO NOT REMOVE
-locks.o: locks.c $(INCDIR1)/apr_general.h $(INCDIR1)/apr.h \
- $(INCDIR1)/apr_errno.h $(INCDIR1)/apr_lib.h \
- $(INCDIR1)/apr_file_io.h $(INCDIR1)/apr_time.h \
- $(INCDIR1)/apr_thread_proc.h locks.h $(INCDIR1)/apr_lock.h \
- $(INCDIR2)/fileio.h $(INCDIR1)/apr_private.h
diff --git a/locks/os2/locks.c b/locks/os2/locks.c
deleted file mode 100644
index dc288b6c9c5..00000000000
--- a/locks/os2/locks.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "apr_general.h"
-#include "apr_lib.h"
-#include "locks.h"
-#include "fileio.h"
-#include <string.h>
-#define INCL_DOS
-#include <os2.h>
-
-#define CurrentTid (lock->tib->tib_ptib2->tib2_ultid)
-
-
-void setup_lock()
-{
-}
-
-
-
-static ap_status_t lock_cleanup(void *thelock)
-{
-    ap_lock_t *lock = thelock;
-    return ap_destroy_lock(lock);
-}
-
-
-
-ap_status_t ap_create_lock(ap_lock_t **lock, ap_locktype_e type, ap_lockscope_e scope, 
-			   const char *fname, ap_pool_t *cont)
-{
-    ap_lock_t *new;
-    ULONG rc;
-    char *semname;
-    PIB *ppib;
-
-    new = (ap_lock_t *)ap_palloc(cont, sizeof(ap_lock_t));
-    new->cntxt = cont;
-    new->type  = type;
-    new->scope = scope;
-    new->owner = 0;
-    new->lock_count = 0;
-    new->fname = ap_pstrdup(cont, fname);
-    DosGetInfoBlocks(&(new->tib), &ppib);
-
-    if (fname == NULL)
-        semname = NULL;
-    else
-        semname = ap_pstrcat(cont, "/SEM32/", fname, NULL);
-
-    rc = DosCreateMutexSem(semname, &(new->hMutex), scope == APR_CROSS_PROCESS ? DC_SEM_SHARED : 0, FALSE);
-    *lock = new;
-
-    if (!rc)
-        ap_register_cleanup(cont, new, lock_cleanup, ap_null_cleanup);
-
-    return APR_OS2_STATUS(rc);
-}
-
-
-
-ap_status_t ap_child_init_lock(ap_lock_t **lock, const char *fname,
-			       ap_pool_t *cont)
-{
-    int rc;
-    PIB *ppib;
-
-    *lock = (ap_lock_t *)ap_palloc(cont, sizeof(ap_lock_t));
-
-    if (lock == NULL)
-        return APR_ENOMEM;
-
-    DosGetInfoBlocks(&((*lock)->tib), &ppib);
-    (*lock)->owner = 0;
-    (*lock)->lock_count = 0;
-    rc = DosOpenMutexSem( (char *)fname, &(*lock)->hMutex );
-
-    if (!rc)
-        ap_register_cleanup(cont, *lock, lock_cleanup, ap_null_cleanup);
-
-    return APR_OS2_STATUS(rc);
-}
-
-
-
-ap_status_t ap_lock(ap_lock_t *lock)
-{
-    ULONG rc;
-    
-    rc = DosRequestMutexSem(lock->hMutex, SEM_INDEFINITE_WAIT);
-
-    if (rc == 0) {
-        lock->owner = CurrentTid;
-        lock->lock_count++;
-    }
-
-    return APR_OS2_STATUS(rc);
-}
-
-
-
-ap_status_t ap_unlock(ap_lock_t *lock)
-{
-    ULONG rc;
-    
-    if (lock->owner == CurrentTid && lock->lock_count > 0) {
-        lock->lock_count--;
-        rc = DosReleaseMutexSem(lock->hMutex);
-        return APR_OS2_STATUS(rc);
-    }
-    
-    return APR_SUCCESS;
-}
-
-
-
-ap_status_t ap_destroy_lock(ap_lock_t *lock)
-{
-    ULONG rc;
-    ap_status_t stat = APR_SUCCESS;
-
-    if (lock->owner == CurrentTid) {
-        while (lock->lock_count > 0 && stat == APR_SUCCESS)
-            stat = ap_unlock(lock);
-    }
-
-    if (stat != APR_SUCCESS)
-        return stat;
-        
-    if (lock->hMutex == 0)
-        return APR_SUCCESS;
-
-    rc = DosCloseMutexSem(lock->hMutex);
-    
-    if (!rc)
-        lock->hMutex = 0;
-        
-    return APR_OS2_STATUS(rc);
-}
diff --git a/locks/os2/locks.h b/locks/os2/locks.h
deleted file mode 100644
index d416b6b0833..00000000000
--- a/locks/os2/locks.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef LOCKS_H
-#define LOCKS_H
-
-#include "apr_lock.h"
-#include "apr_file_io.h"
-#define INCL_DOS
-#include <os2.h>
-
-struct ap_lock_t {
-    ap_pool_t *cntxt;
-    ap_locktype_e type;
-    ap_lockscope_e scope;
-    char *fname;
-    HMTX hMutex;
-    TID owner;
-    int lock_count;
-    TIB *tib;
-};
-
-void setup_lock();
-
-#endif  /* LOCKS_H */
-
diff --git a/locks/os2/proc_mutex.c b/locks/os2/proc_mutex.c
new file mode 100644
index 00000000000..a86c208b324
--- /dev/null
+++ b/locks/os2/proc_mutex.c
@@ -0,0 +1,289 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_general.h"
+#include "apr_lib.h"
+#include "apr_strings.h"
+#include "apr_portable.h"
+#include "apr_arch_proc_mutex.h"
+#include "apr_arch_file_io.h"
+#include <string.h>
+#include <stddef.h>
+
+#define CurrentTid (*_threadid)
+
+static char *fixed_name(const char *fname, apr_pool_t *pool)
+{
+    char *semname;
+
+    if (fname == NULL)
+        semname = NULL;
+    else {
+        /* Semaphores don't live in the file system, fix up the name */
+        while (*fname == '/' || *fname == '\\') {
+            fname++;
+        }
+
+        semname = apr_pstrcat(pool, "/SEM32/", fname, NULL);
+
+        if (semname[8] == ':') {
+            semname[8] = '$';
+        }
+    }
+
+    return semname;
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_proc_mutex_cleanup(void *vmutex)
+{
+    apr_proc_mutex_t *mutex = vmutex;
+    return apr_proc_mutex_destroy(mutex);
+}
+
+APR_DECLARE(const char *) apr_proc_mutex_lockfile(apr_proc_mutex_t *mutex)
+{
+    return NULL;
+}
+
+APR_DECLARE(apr_lockmech_e) apr_proc_mutex_mech(apr_proc_mutex_t *mutex)
+{
+    return APR_LOCK_DEFAULT;
+}
+
+APR_DECLARE(const char *) apr_proc_mutex_name(apr_proc_mutex_t *mutex)
+{
+    return "os2sem";
+}
+
+APR_DECLARE(const char *) apr_proc_mutex_defname(void)
+{
+    return "os2sem";
+}
+
+
+APR_DECLARE(apr_status_t) apr_proc_mutex_create(apr_proc_mutex_t **mutex,
+                                                const char *fname,
+                                                apr_lockmech_e mech,
+                                                apr_pool_t *pool)
+{
+    apr_proc_mutex_t *new;
+    ULONG rc;
+    char *semname;
+
+    if (mech != APR_LOCK_DEFAULT && mech != APR_LOCK_DEFAULT_TIMED) {
+        return APR_ENOTIMPL;
+    }
+
+    new = (apr_proc_mutex_t *)apr_palloc(pool, sizeof(apr_proc_mutex_t));
+    new->pool       = pool;
+    new->owner      = 0;
+    new->lock_count = 0;
+    *mutex = new;
+
+    semname = fixed_name(fname, pool);
+    rc = DosCreateMutexSem(semname, &(new->hMutex), DC_SEM_SHARED, FALSE);
+
+    if (!rc) {
+        apr_pool_cleanup_register(pool, new, apr_proc_mutex_cleanup, apr_pool_cleanup_null);
+    }
+
+    return APR_FROM_OS_ERROR(rc);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_proc_mutex_child_init(apr_proc_mutex_t **mutex,
+                                                    const char *fname,
+                                                    apr_pool_t *pool)
+{
+    apr_proc_mutex_t *new;
+    ULONG rc;
+    char *semname;
+
+    new = (apr_proc_mutex_t *)apr_palloc(pool, sizeof(apr_proc_mutex_t));
+    new->pool       = pool;
+    new->owner      = 0;
+    new->lock_count = 0;
+
+    semname = fixed_name(fname, pool);
+    rc = DosOpenMutexSem(semname, &(new->hMutex));
+    *mutex = new;
+
+    if (!rc) {
+        apr_pool_cleanup_register(pool, new, apr_proc_mutex_cleanup, apr_pool_cleanup_null);
+    }
+
+    return APR_FROM_OS_ERROR(rc);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_proc_mutex_lock(apr_proc_mutex_t *mutex)
+{
+    ULONG rc = DosRequestMutexSem(mutex->hMutex, SEM_INDEFINITE_WAIT);
+
+    if (rc == 0) {
+        mutex->owner = CurrentTid;
+        mutex->lock_count++;
+    }
+
+    return APR_FROM_OS_ERROR(rc);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_proc_mutex_trylock(apr_proc_mutex_t *mutex)
+{
+    ULONG rc = DosRequestMutexSem(mutex->hMutex, SEM_IMMEDIATE_RETURN);
+
+    if (rc == 0) {
+        mutex->owner = CurrentTid;
+        mutex->lock_count++;
+    }
+
+    return (rc == ERROR_TIMEOUT) ? APR_EBUSY : APR_FROM_OS_ERROR(rc);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_proc_mutex_timedlock(apr_proc_mutex_t *mutex,
+                                               apr_interval_time_t timeout)
+{
+    ULONG rc;
+    
+    if (timeout <= 0) {
+        rc = DosRequestMutexSem(mutex->hMutex, SEM_IMMEDIATE_RETURN);
+    }
+    else {
+        rc = DosRequestMutexSem(mutex->hMutex, apr_time_as_msec(timeout));
+    }
+
+    if (rc == 0) {
+        mutex->owner = CurrentTid;
+        mutex->lock_count++;
+    }
+
+    return (rc == ERROR_TIMEOUT) ? APR_TIMEUP : APR_FROM_OS_ERROR(rc);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_proc_mutex_unlock(apr_proc_mutex_t *mutex)
+{
+    ULONG rc;
+
+    if (mutex->owner == CurrentTid && mutex->lock_count > 0) {
+        mutex->lock_count--;
+        rc = DosReleaseMutexSem(mutex->hMutex);
+        return APR_FROM_OS_ERROR(rc);
+    }
+
+    return APR_SUCCESS;
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_proc_mutex_destroy(apr_proc_mutex_t *mutex)
+{
+    ULONG rc;
+    apr_status_t status = APR_SUCCESS;
+
+    if (mutex->owner == CurrentTid) {
+        while (mutex->lock_count > 0 && status == APR_SUCCESS) {
+            status = apr_proc_mutex_unlock(mutex);
+        }
+    }
+
+    if (status != APR_SUCCESS) {
+        return status;
+    }
+
+    if (mutex->hMutex == 0) {
+        return APR_SUCCESS;
+    }
+
+    rc = DosCloseMutexSem(mutex->hMutex);
+
+    if (!rc) {
+        mutex->hMutex = 0;
+    }
+
+    return APR_FROM_OS_ERROR(rc);
+}
+
+APR_PERMS_SET_ENOTIMPL(proc_mutex)
+
+APR_POOL_IMPLEMENT_ACCESSOR(proc_mutex)
+
+
+
+/* Implement OS-specific accessors defined in apr_portable.h */
+
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_get_ex(apr_os_proc_mutex_t *ospmutex, 
+                                                   apr_proc_mutex_t *pmutex,
+                                                   apr_lockmech_e *mech)
+{
+    *ospmutex = pmutex->hMutex;
+    if (mech) {
+        *mech = APR_LOCK_DEFAULT;
+    }
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_get(apr_os_proc_mutex_t *ospmutex,
+                                                apr_proc_mutex_t *pmutex)
+{
+    return apr_os_proc_mutex_get_ex(ospmutex, pmutex, NULL);
+}
+
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_put_ex(apr_proc_mutex_t **pmutex,
+                                                apr_os_proc_mutex_t *ospmutex,
+                                                apr_lockmech_e mech,
+                                                int register_cleanup,
+                                                apr_pool_t *pool)
+{
+    apr_proc_mutex_t *new;
+    if (pool == NULL) {
+        return APR_ENOPOOL;
+    }
+    if (mech != APR_LOCK_DEFAULT && mech != APR_LOCK_DEFAULT_TIMED) {
+        return APR_ENOTIMPL;
+    }
+
+    new = (apr_proc_mutex_t *)apr_palloc(pool, sizeof(apr_proc_mutex_t));
+    new->pool       = pool;
+    new->owner      = 0;
+    new->lock_count = 0;
+    new->hMutex     = *ospmutex;
+    *pmutex = new;
+
+    if (register_cleanup) {
+        apr_pool_cleanup_register(pool, *pmutex, apr_proc_mutex_cleanup,
+                                  apr_pool_cleanup_null);
+    }
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_put(apr_proc_mutex_t **pmutex,
+                                                apr_os_proc_mutex_t *ospmutex,
+                                                apr_pool_t *pool)
+{
+    return apr_os_proc_mutex_put_ex(pmutex, ospmutex, APR_LOCK_DEFAULT,
+                                    0, pool);
+}
+
diff --git a/locks/os2/thread_cond.c b/locks/os2/thread_cond.c
new file mode 100644
index 00000000000..86dbb8881ad
--- /dev/null
+++ b/locks/os2/thread_cond.c
@@ -0,0 +1,194 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_general.h"
+#include "apr_lib.h"
+#include "apr_strings.h"
+#include "apr_portable.h"
+#include "apr_arch_thread_mutex.h"
+#include "apr_arch_thread_cond.h"
+#include "apr_arch_file_io.h"
+#include <string.h>
+
+#ifndef DCE_POSTONE
+#define DCE_POSTONE   0x0800 /* Post one flag */
+#endif
+
+static apr_status_t thread_cond_cleanup(void *data)
+{
+    apr_thread_cond_t *cv = data;
+
+    if (cv->semaphore) {
+        DosCloseEventSem(cv->semaphore);
+    }
+
+    if (cv->mutex) {
+        DosCloseMutexSem(cv->mutex);
+    }
+
+    return APR_SUCCESS;
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_thread_cond_create(apr_thread_cond_t **cond,
+                                                 apr_pool_t *pool)
+{
+    int rc;
+    apr_thread_cond_t *cv;
+
+    cv = apr_pcalloc(pool, sizeof(**cond));
+    rc = DosCreateEventSem(NULL, &cv->semaphore, DCE_POSTONE, FALSE);
+
+    if (rc == 0) {
+        rc = DosCreateMutexSem(NULL, &cv->mutex, 0, FALSE);
+    }
+
+    *cond = cv;
+    cv->pool = pool;
+    apr_pool_cleanup_register(cv->pool, cv, thread_cond_cleanup,
+                              apr_pool_cleanup_null);
+
+    return APR_FROM_OS_ERROR(rc);
+}
+
+
+
+static apr_status_t thread_cond_timedwait(apr_thread_cond_t *cond,
+                                          apr_thread_mutex_t *mutex,
+                                          ULONG timeout_ms )
+{
+    ULONG rc;
+    apr_status_t rv = APR_SUCCESS;
+    int wake = FALSE;
+    unsigned long generation;
+
+    DosRequestMutexSem(cond->mutex, SEM_INDEFINITE_WAIT);
+    cond->num_waiting++;
+    generation = cond->generation;
+    DosReleaseMutexSem(cond->mutex);
+
+    apr_thread_mutex_unlock(mutex);
+
+    do {
+        rc = DosWaitEventSem(cond->semaphore, timeout_ms);
+
+        DosRequestMutexSem(cond->mutex, SEM_INDEFINITE_WAIT);
+
+        if (cond->num_wake) {
+            if (cond->generation != generation) {
+                cond->num_wake--;
+                cond->num_waiting--;
+                rv = APR_SUCCESS;
+                break;
+            } else {
+                wake = TRUE;
+            }
+        }
+        else if (rc != 0) {
+            cond->num_waiting--;
+            rv = APR_TIMEUP;
+            break;
+        }
+
+        DosReleaseMutexSem(cond->mutex);
+
+        if (wake) {
+            wake = FALSE;
+            DosPostEventSem(cond->semaphore);
+        }
+    } while (1);
+
+    DosReleaseMutexSem(cond->mutex);
+    apr_thread_mutex_lock(mutex);
+    return rv;
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_thread_cond_wait(apr_thread_cond_t *cond,
+                                               apr_thread_mutex_t *mutex)
+{
+    return thread_cond_timedwait(cond, mutex, SEM_INDEFINITE_WAIT);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_thread_cond_timedwait(apr_thread_cond_t *cond,
+                                                    apr_thread_mutex_t *mutex,
+                                                    apr_interval_time_t timeout)
+{
+    ULONG timeout_ms = (timeout >= 0) ? apr_time_as_msec(timeout)
+                                      : SEM_INDEFINITE_WAIT;
+    return thread_cond_timedwait(cond, mutex, timeout_ms);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_thread_cond_signal(apr_thread_cond_t *cond)
+{
+    int wake = FALSE;
+
+    DosRequestMutexSem(cond->mutex, SEM_INDEFINITE_WAIT);
+
+    if (cond->num_waiting > cond->num_wake) {
+        wake = TRUE;
+        cond->num_wake++;
+        cond->generation++;
+    }
+
+    DosReleaseMutexSem(cond->mutex);
+
+    if (wake) {
+        DosPostEventSem(cond->semaphore);
+    }
+
+    return APR_SUCCESS;
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_thread_cond_broadcast(apr_thread_cond_t *cond)
+{
+    unsigned long num_wake = 0;
+
+    DosRequestMutexSem(cond->mutex, SEM_INDEFINITE_WAIT);
+
+    if (cond->num_waiting > cond->num_wake) {
+        num_wake = cond->num_waiting - cond->num_wake;
+        cond->num_wake = cond->num_waiting;
+        cond->generation++;
+    }
+
+    DosReleaseMutexSem(cond->mutex);
+
+    for (; num_wake; num_wake--) {
+        DosPostEventSem(cond->semaphore);
+    }
+
+    return APR_SUCCESS;
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_thread_cond_destroy(apr_thread_cond_t *cond)
+{
+    return apr_pool_cleanup_run(cond->pool, cond, thread_cond_cleanup);
+}
+
+
+
+APR_POOL_IMPLEMENT_ACCESSOR(thread_cond)
diff --git a/locks/os2/thread_mutex.c b/locks/os2/thread_mutex.c
new file mode 100644
index 00000000000..884004ce2de
--- /dev/null
+++ b/locks/os2/thread_mutex.c
@@ -0,0 +1,120 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_general.h"
+#include "apr_lib.h"
+#include "apr_strings.h"
+#include "apr_portable.h"
+#include "apr_arch_thread_mutex.h"
+#include "apr_arch_file_io.h"
+#include <string.h>
+#include <stddef.h>
+
+static apr_status_t thread_mutex_cleanup(void *themutex)
+{
+    apr_thread_mutex_t *mutex = themutex;
+    return apr_thread_mutex_destroy(mutex);
+}
+
+
+
+/* XXX: Need to respect APR_THREAD_MUTEX_[UN]NESTED flags argument
+ *      or return APR_ENOTIMPL!!!
+ */
+APR_DECLARE(apr_status_t) apr_thread_mutex_create(apr_thread_mutex_t **mutex,
+                                                  unsigned int flags,
+                                                  apr_pool_t *pool)
+{
+    apr_thread_mutex_t *new_mutex;
+    ULONG rc;
+
+    new_mutex = (apr_thread_mutex_t *)apr_palloc(pool, sizeof(apr_thread_mutex_t));
+    new_mutex->pool = pool;
+
+    rc = DosCreateMutexSem(NULL, &(new_mutex->hMutex), 0, FALSE);
+    *mutex = new_mutex;
+
+    if (!rc)
+        apr_pool_cleanup_register(pool, new_mutex, thread_mutex_cleanup, apr_pool_cleanup_null);
+
+    return APR_FROM_OS_ERROR(rc);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_thread_mutex_lock(apr_thread_mutex_t *mutex)
+{
+    ULONG rc = DosRequestMutexSem(mutex->hMutex, SEM_INDEFINITE_WAIT);
+    return APR_FROM_OS_ERROR(rc);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_thread_mutex_trylock(apr_thread_mutex_t *mutex)
+{
+    ULONG rc = DosRequestMutexSem(mutex->hMutex, SEM_IMMEDIATE_RETURN);
+
+    return (rc == ERROR_TIMEOUT) ? APR_EBUSY : APR_FROM_OS_ERROR(rc);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_thread_mutex_timedlock(apr_thread_mutex_t *mutex,
+                                                 apr_interval_time_t timeout)
+{
+    ULONG rc;
+
+    if (timeout <= 0) {
+        rc = DosRequestMutexSem(mutex->hMutex, SEM_IMMEDIATE_RETURN);
+    }
+    else {
+        rc = DosRequestMutexSem(mutex->hMutex, apr_time_as_msec(timeout));
+    }
+
+    return (rc == ERROR_TIMEOUT) ? APR_TIMEUP : APR_FROM_OS_ERROR(rc);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_thread_mutex_unlock(apr_thread_mutex_t *mutex)
+{
+    ULONG rc = DosReleaseMutexSem(mutex->hMutex);
+    return APR_FROM_OS_ERROR(rc);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_thread_mutex_destroy(apr_thread_mutex_t *mutex)
+{
+    ULONG rc;
+
+    if (mutex->hMutex == 0)
+        return APR_SUCCESS;
+
+    while (DosReleaseMutexSem(mutex->hMutex) == 0);
+
+    rc = DosCloseMutexSem(mutex->hMutex);
+
+    if (!rc) {
+        mutex->hMutex = 0;
+        return APR_SUCCESS;
+    }
+
+    return APR_FROM_OS_ERROR(rc);
+}
+
+APR_POOL_IMPLEMENT_ACCESSOR(thread_mutex)
+
diff --git a/locks/os2/thread_rwlock.c b/locks/os2/thread_rwlock.c
new file mode 100644
index 00000000000..195a56bda3e
--- /dev/null
+++ b/locks/os2/thread_rwlock.c
@@ -0,0 +1,200 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_general.h"
+#include "apr_lib.h"
+#include "apr_strings.h"
+#include "apr_portable.h"
+#include "apr_arch_thread_rwlock.h"
+#include "apr_arch_file_io.h"
+#include <string.h>
+
+static apr_status_t thread_rwlock_cleanup(void *therwlock)
+{
+    apr_thread_rwlock_t *rwlock = therwlock;
+    return apr_thread_rwlock_destroy(rwlock);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_thread_rwlock_create(apr_thread_rwlock_t **rwlock,
+                                                   apr_pool_t *pool)
+{
+    apr_thread_rwlock_t *new_rwlock;
+    ULONG rc;
+
+    new_rwlock = (apr_thread_rwlock_t *)apr_palloc(pool, sizeof(apr_thread_rwlock_t));
+    new_rwlock->pool = pool;
+    new_rwlock->readers = 0;
+
+    rc = DosCreateMutexSem(NULL, &(new_rwlock->write_lock), 0, FALSE);
+
+    if (rc)
+        return APR_FROM_OS_ERROR(rc);
+
+    rc = DosCreateEventSem(NULL, &(new_rwlock->read_done), 0, FALSE);
+
+    if (rc)
+        return APR_FROM_OS_ERROR(rc);
+
+    *rwlock = new_rwlock;
+
+    if (!rc)
+        apr_pool_cleanup_register(pool, new_rwlock, thread_rwlock_cleanup,
+                                  apr_pool_cleanup_null);
+
+    return APR_FROM_OS_ERROR(rc);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_thread_rwlock_rdlock(apr_thread_rwlock_t *rwlock)
+{
+    ULONG rc, posts;
+
+    rc = DosRequestMutexSem(rwlock->write_lock, SEM_INDEFINITE_WAIT);
+
+    if (rc)
+        return APR_FROM_OS_ERROR(rc);
+
+    /* We've successfully acquired the writer mutex so we can't be locked
+     * for write which means it's ok to add a reader lock. The writer mutex
+     * doubles as race condition protection for the readers counter.
+     */
+    rwlock->readers++;
+    DosResetEventSem(rwlock->read_done, &posts);
+    rc = DosReleaseMutexSem(rwlock->write_lock);
+    return APR_FROM_OS_ERROR(rc);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_thread_rwlock_tryrdlock(apr_thread_rwlock_t *rwlock)
+{
+    /* As above but with different wait time */
+    ULONG rc, posts;
+
+    rc = DosRequestMutexSem(rwlock->write_lock, SEM_IMMEDIATE_RETURN);
+
+    if (rc)
+        return APR_FROM_OS_ERROR(rc);
+
+    rwlock->readers++;
+    DosResetEventSem(rwlock->read_done, &posts);
+    rc = DosReleaseMutexSem(rwlock->write_lock);
+    return APR_FROM_OS_ERROR(rc);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_thread_rwlock_wrlock(apr_thread_rwlock_t *rwlock)
+{
+    ULONG rc;
+
+    rc = DosRequestMutexSem(rwlock->write_lock, SEM_INDEFINITE_WAIT);
+
+    if (rc)
+        return APR_FROM_OS_ERROR(rc);
+
+    /* We've got the writer lock but we have to wait for all readers to
+     * unlock before it's ok to use it
+     */
+
+    if (rwlock->readers) {
+        rc = DosWaitEventSem(rwlock->read_done, SEM_INDEFINITE_WAIT);
+
+        if (rc)
+            DosReleaseMutexSem(rwlock->write_lock);
+    }
+
+    return APR_FROM_OS_ERROR(rc);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_thread_rwlock_trywrlock(apr_thread_rwlock_t *rwlock)
+{
+    ULONG rc;
+
+    rc = DosRequestMutexSem(rwlock->write_lock, SEM_IMMEDIATE_RETURN);
+
+    if (rc)
+        return APR_FROM_OS_ERROR(rc);
+
+    /* We've got the writer lock but we have to wait for all readers to
+     * unlock before it's ok to use it
+     */
+
+    if (rwlock->readers) {
+        /* There are readers active, give up */
+        DosReleaseMutexSem(rwlock->write_lock);
+        rc = ERROR_TIMEOUT;
+    }
+
+    return APR_FROM_OS_ERROR(rc);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_thread_rwlock_unlock(apr_thread_rwlock_t *rwlock)
+{
+    ULONG rc;
+
+    /* First, guess that we're unlocking a writer */
+    rc = DosReleaseMutexSem(rwlock->write_lock);
+
+    if (rc == ERROR_NOT_OWNER) {
+        /* Nope, we must have a read lock */
+        if (rwlock->readers) {
+            DosEnterCritSec();
+            rwlock->readers--;
+
+            if (rwlock->readers == 0) {
+                DosPostEventSem(rwlock->read_done);
+            }
+
+            DosExitCritSec();
+            rc = 0;
+        }
+    }
+
+    return APR_FROM_OS_ERROR(rc);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_thread_rwlock_destroy(apr_thread_rwlock_t *rwlock)
+{
+    ULONG rc;
+
+    if (rwlock->write_lock == 0)
+        return APR_SUCCESS;
+
+    while (DosReleaseMutexSem(rwlock->write_lock) == 0);
+
+    rc = DosCloseMutexSem(rwlock->write_lock);
+
+    if (!rc) {
+        rwlock->write_lock = 0;
+        DosCloseEventSem(rwlock->read_done);
+        return APR_SUCCESS;
+    }
+
+    return APR_FROM_OS_ERROR(rc);
+}
+
+APR_POOL_IMPLEMENT_ACCESSOR(thread_rwlock)
+
diff --git a/locks/unix/.cvsignore b/locks/unix/.cvsignore
deleted file mode 100644
index f3c7a7c5da6..00000000000
--- a/locks/unix/.cvsignore
+++ /dev/null
@@ -1 +0,0 @@
-Makefile
diff --git a/locks/unix/Makefile.in b/locks/unix/Makefile.in
deleted file mode 100644
index 80bd8da69fc..00000000000
--- a/locks/unix/Makefile.in
+++ /dev/null
@@ -1,70 +0,0 @@
-#CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
-#LIBS=$(EXTRA_LIBS) $(LIBS1)
-#INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
-#LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
-
-RM=@RM@
-CC=@CC@
-RANLIB=@RANLIB@
-CFLAGS=@CFLAGS@ @OPTIM@
-LIBS=@LIBS@
-LDFLAGS=@LDFLAGS@ $(LIBS)
-INCDIR1=../../include
-INCDIR2=../../file_io/unix
-INCLUDES=-I$(INCDIR1) -I$(INCDIR2) -I.
-
-#LIB=liblock.a
-
-OBJS=locks.o \
-	crossproc.o \
-	intraproc.o
-
-.c.o:
-	$(CC) $(CFLAGS) -c $(INCLUDES) $<
-
-all: $(OBJS)
-
-clean:
-	$(RM) -f *.o *.a *.so
-
-distclean: clean
-	-$(RM) -f Makefile
-
-$(OBJS): Makefile
-
-#$(LIB): $(OBJS)
-#	$(RM) -f $@
-#	$(AR) cr $@ $(OBJS)
-#	$(RANLIB) $@
-
-#
-# We really don't expect end users to use this rule.  It works only with
-# gcc, and rebuilds Makefile.tmpl.  You have to re-run Configure after
-# using it.
-#
-depend:
-	cp Makefile.in Makefile.in.bak \
-	    && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.in > Makefile.new \
-	    && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \
-	    && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
-	           -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
-		> Makefile.in \
-	    && rm Makefile.new
-
-# DO NOT REMOVE
-crossproc.o: crossproc.c locks.h ../../include/apr_private.h \
- ../../include/apr_general.h ../../include/apr.h \
- ../../include/apr_errno.h ../../include/apr_lib.h \
- ../../include/apr_file_io.h ../../include/apr_time.h \
- ../../include/apr_thread_proc.h ../../include/apr_lock.h
-intraproc.o: intraproc.c locks.h ../../include/apr_private.h \
- ../../include/apr_general.h ../../include/apr.h \
- ../../include/apr_errno.h ../../include/apr_lib.h \
- ../../include/apr_file_io.h ../../include/apr_time.h \
- ../../include/apr_thread_proc.h ../../include/apr_lock.h
-locks.o: locks.c locks.h ../../include/apr_private.h \
- ../../include/apr_general.h ../../include/apr.h \
- ../../include/apr_errno.h ../../include/apr_lib.h \
- ../../include/apr_file_io.h ../../include/apr_time.h \
- ../../include/apr_thread_proc.h ../../include/apr_lock.h \
- ../../include/apr_portable.h ../../include/apr_network_io.h
diff --git a/locks/unix/crossproc.c b/locks/unix/crossproc.c
deleted file mode 100644
index cddd80f4a36..00000000000
--- a/locks/unix/crossproc.c
+++ /dev/null
@@ -1,403 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "locks.h"
-
-#if defined (USE_SYSVSEM_SERIALIZE)  
-
-static struct sembuf op_on;
-static struct sembuf op_off;
-
-void ap_unix_setup_lock(void)
-{
-    op_on.sem_num = 0;
-    op_on.sem_op = -1;
-    op_on.sem_flg = SEM_UNDO;
-    op_off.sem_num = 0;
-    op_off.sem_op = 1;
-    op_off.sem_flg = SEM_UNDO;
-}
-
-static ap_status_t lock_cleanup(void *lock_)
-{
-    ap_lock_t *lock=lock_;
-    union semun ick;
-    
-    if (lock->interproc != -1) {
-        ick.val = 0;
-        semctl(lock->interproc, 0, IPC_RMID, ick);
-    }
-    return APR_SUCCESS;
-}    
-
-ap_status_t ap_unix_create_inter_lock(ap_lock_t *new)
-{
-    union semun ick;
-    
-    new->interproc = semget(IPC_PRIVATE, 1, IPC_CREAT | 0600);
-
-    if (new->interproc < 0) {
-        lock_cleanup(new);
-        return errno;
-    }
-    ick.val = 1;
-    if (semctl(new->interproc, 0, SETVAL, ick) < 0) {
-        lock_cleanup(new);
-        return errno;
-    }
-    new->curr_locked = 0;
-    ap_register_cleanup(new->cntxt, (void *)new, lock_cleanup, ap_null_cleanup);
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_unix_lock_inter(ap_lock_t *lock)
-{
-    lock->curr_locked = 1;
-    if (semop(lock->interproc, &op_on, 1) < 0) {
-        return errno;
-    }
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_unix_unlock_inter(ap_lock_t *lock)
-{
-    if (semop(lock->interproc, &op_off, 1) < 0) {
-        return errno;
-    }
-    lock->curr_locked = 0;
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_unix_destroy_inter_lock(ap_lock_t *lock)
-{
-    ap_status_t stat;
-
-    if ((stat = lock_cleanup(lock)) == APR_SUCCESS) {
-        ap_kill_cleanup(lock->cntxt, lock, lock_cleanup);
-        return APR_SUCCESS;
-    }
-    return stat;
-}
-
-ap_status_t ap_unix_child_init_lock(ap_lock_t **lock, ap_pool_t *cont, char *fname)
-{
-    return APR_SUCCESS;
-}
-
-#elif defined (USE_PROC_PTHREAD_SERIALIZE)  
-
-void ap_unix_setup_lock(void)
-{
-}
-
-static ap_status_t lock_cleanup(void *lock_)
-{
-    ap_lock_t *lock=lock_;
-
-    if (lock->curr_locked == 1) {
-        if (pthread_mutex_unlock(lock->interproc)) {
-            return errno;
-        } 
-        if (munmap((caddr_t)lock->interproc, sizeof(pthread_mutex_t))){
-            return errno;
-        }
-    }
-    return APR_SUCCESS;
-}    
-
-ap_status_t ap_unix_create_inter_lock(ap_lock_t *new)
-{
-    ap_status_t stat;
-    int fd;
-    pthread_mutexattr_t mattr;
-
-    fd = open("/dev/zero", O_RDWR);
-    if (fd < 0) {
-        return errno;
-    }
-
-    new->interproc = (pthread_mutex_t *)mmap((caddr_t) 0, 
-                              sizeof(pthread_mutex_t), 
-                              PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 
-    if (new->interproc == (pthread_mutex_t *) (caddr_t) -1) {
-        return errno;
-    }
-    close(fd);
-    if ((stat = pthread_mutexattr_init(&mattr))) {
-        lock_cleanup(new);
-        return stat;
-    }
-    if ((stat = pthread_mutexattr_setpshared(&mattr, 
-                                              PTHREAD_PROCESS_SHARED))) {
-        lock_cleanup(new);
-        return stat;
-    }
-
-    if ((stat = pthread_mutex_init(new->interproc, &mattr))) {
-        lock_cleanup(new);
-        return stat;
-    }
-
-    if ((stat = pthread_mutexattr_destroy(&mattr))) {
-        lock_cleanup(new);
-        return stat;
-    }
-
-    new->curr_locked = 0;
-    ap_register_cleanup(new->cntxt, (void *)new, lock_cleanup, ap_null_cleanup);
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_unix_lock_inter(ap_lock_t *lock)
-{
-    ap_status_t stat;
-    lock->curr_locked = 1;
-    if (stat = pthread_mutex_lock(lock->interproc)) {
-        return stat;
-    }
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_unix_unlock_inter(ap_lock_t *lock)
-{
-    ap_status_t stat;
-
-    if (stat = pthread_mutex_unlock(lock->interproc)) {
-        return stat;
-    }
-    lock->curr_locked = 0;
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_unix_destroy_inter_lock(ap_lock_t *lock)
-{
-    ap_status_t stat;
-    if ((stat = lock_cleanup(lock)) == APR_SUCCESS) {
-        ap_kill_cleanup(lock->cntxt, lock, lock_cleanup);
-        return APR_SUCCESS;
-    }
-    return stat;
-}
-
-ap_status_t ap_unix_child_init_lock(ap_lock_t **lock, ap_pool_t *cont, char *fname)
-{
-    return APR_SUCCESS;
-}
-
-#elif defined (USE_FCNTL_SERIALIZE)  
-
-static struct flock lock_it;
-static struct flock unlock_it;
-
-void ap_unix_setup_lock(void)
-{
-    lock_it.l_whence = SEEK_SET;        /* from current point */
-    lock_it.l_start = 0;                /* -"- */
-    lock_it.l_len = 0;                  /* until end of file */
-    lock_it.l_type = F_WRLCK;           /* set exclusive/write lock */
-    lock_it.l_pid = 0;                  /* pid not actually interesting */
-    unlock_it.l_whence = SEEK_SET;      /* from current point */
-    unlock_it.l_start = 0;              /* -"- */
-    unlock_it.l_len = 0;                /* until end of file */
-    unlock_it.l_type = F_UNLCK;         /* set exclusive/write lock */
-    unlock_it.l_pid = 0;                /* pid not actually interesting */
-}
-
-static ap_status_t lock_cleanup(void *lock_)
-{
-    ap_lock_t *lock=lock_;
-
-    if (lock->curr_locked == 1) {
-        if (fcntl(lock->interproc, F_SETLKW, &unlock_it) < 0) {
-            return errno;
-        }
-        lock->curr_locked=0;
-    }
-    return APR_SUCCESS;
-}    
-
-ap_status_t ap_unix_create_inter_lock(ap_lock_t *new)
-{
-    new->interproc = open(new->fname, O_CREAT | O_WRONLY | O_EXCL, 0644);
-
-    if (new->interproc < 0) {
-        lock_cleanup(new);
-        return errno;
-    }
-
-    new->curr_locked=0;
-    unlink(new->fname);
-    ap_register_cleanup(new->cntxt, new, lock_cleanup, ap_null_cleanup);
-    return APR_SUCCESS; 
-}
-
-ap_status_t ap_unix_lock_inter(ap_lock_t *lock)
-{
-    lock->curr_locked=1;
-    if (fcntl(lock->interproc, F_SETLKW, &lock_it) < 0) {
-        return errno;
-    }
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_unix_unlock_inter(ap_lock_t *lock)
-{
-    if (fcntl(lock->interproc, F_SETLKW, &unlock_it) < 0) {
-        return errno;
-    }
-    lock->curr_locked=0;
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_unix_destroy_inter_lock(ap_lock_t *lock)
-{
-    ap_status_t stat;
-    if ((stat = lock_cleanup(lock)) == APR_SUCCESS) {
-        ap_kill_cleanup(lock->cntxt, lock, lock_cleanup);
-        return APR_SUCCESS;
-    }
-    return stat;
-}
-
-ap_status_t ap_unix_child_init_lock(ap_lock_t **lock, ap_pool_t *cont, 
-                                    const char *fname)
-{
-    return APR_SUCCESS;
-}
-
-#elif defined (USE_FLOCK_SERIALIZE)
-
-void ap_unix_setup_lock(void)
-{
-}
-
-static ap_status_t lock_cleanup(void *lock_)
-{
-    ap_lock_t *lock=lock_;
-
-    if (lock->curr_locked == 1) {
-        if (flock(lock->interproc, LOCK_UN) < 0) {
-            return errno;
-        }
-        lock->curr_locked = 0;
-    }
-    unlink(lock->fname);
-    return APR_SUCCESS;
-}    
-
-ap_status_t ap_unix_create_inter_lock(ap_lock_t *new)
-{
-    new->interproc = open(new->fname, O_CREAT | O_WRONLY | O_EXCL, 0600);
-
-    if (new->interproc < 0) {
-        lock_cleanup(new);
-        return errno;
-    }
-    new->curr_locked = 0;
-    ap_register_cleanup(new->cntxt, (void *)new, lock_cleanup, ap_null_cleanup);
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_unix_lock_inter(ap_lock_t *lock)
-{
-    lock->curr_locked = 1;
-    if (flock(lock->interproc, LOCK_EX) < 0) {
-        return errno;
-    }
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_unix_unlock_inter(ap_lock_t *lock)
-{
-    if (flock(lock->interproc, LOCK_UN) < 0) {
-        return errno;
-    }
-    lock->curr_locked = 0;
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_unix_destroy_inter_lock(ap_lock_t *lock)
-{
-    ap_status_t stat;
-    if ((stat = lock_cleanup(lock)) == APR_SUCCESS) {
-        ap_kill_cleanup(lock->cntxt, lock, lock_cleanup);
-        return APR_SUCCESS;
-    }
-    return stat;
-}
-
-ap_status_t ap_unix_child_init_lock(ap_lock_t **lock, ap_pool_t *cont, 
-                            const char *fname)
-{
-    ap_lock_t *new;
-
-    new = (ap_lock_t *)ap_palloc(cont, sizeof(ap_lock_t));
-
-    new->fname = ap_pstrdup(cont, fname);
-    new->interproc = open(new->fname, O_CREAT | O_WRONLY | O_EXCL, 0600);
-    if (new->interproc == -1) {
-        destroy_inter_lock(new);
-        return errno;
-    }
-    return APR_SUCCESS;
-}
-
-#else
-/* No inter-process mutex on this platform.  Use at your own risk */
-#define create_inter_lock(x, y)
-#define lock_inter(x, y)
-#define unlock_inter(x, y)
-#define destroy_inter_lock(x, y)
-#define child_init_lock(x, y, z)
-#endif
diff --git a/locks/unix/global_mutex.c b/locks/unix/global_mutex.c
new file mode 100644
index 00000000000..22592060d2f
--- /dev/null
+++ b/locks/unix/global_mutex.c
@@ -0,0 +1,241 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+
+#include "apr_strings.h"
+#include "apr_arch_global_mutex.h"
+#include "apr_proc_mutex.h"
+#include "apr_thread_mutex.h"
+#include "apr_portable.h"
+
+static apr_status_t global_mutex_cleanup(void *data)
+{
+    apr_global_mutex_t *m = (apr_global_mutex_t *)data;
+    apr_status_t rv;
+
+    rv = apr_proc_mutex_destroy(m->proc_mutex);
+
+#if APR_HAS_THREADS
+    if (m->thread_mutex) {
+        if (rv != APR_SUCCESS) {
+            (void)apr_thread_mutex_destroy(m->thread_mutex);
+        }
+        else {
+            rv = apr_thread_mutex_destroy(m->thread_mutex);
+        }
+    }
+#endif /* APR_HAS_THREADS */
+
+    return rv;
+}
+
+APR_DECLARE(apr_status_t) apr_global_mutex_create(apr_global_mutex_t **mutex,
+                                                  const char *fname,
+                                                  apr_lockmech_e mech,
+                                                  apr_pool_t *pool)
+{
+    apr_status_t rv;
+    apr_global_mutex_t *m;
+
+    m = (apr_global_mutex_t *)apr_palloc(pool, sizeof(*m));
+    m->pool = pool;
+
+    rv = apr_proc_mutex_create(&m->proc_mutex, fname, mech, m->pool);
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
+#if APR_HAS_THREADS
+    if (m->proc_mutex->meth->flags & APR_PROCESS_LOCK_MECH_IS_GLOBAL) {
+        m->thread_mutex = NULL; /* We don't need a thread lock. */
+    }
+    else {
+        rv = apr_thread_mutex_create(&m->thread_mutex,
+                                     APR_THREAD_MUTEX_DEFAULT, m->pool);
+        if (rv != APR_SUCCESS) {
+            rv = apr_proc_mutex_destroy(m->proc_mutex);
+            return rv;
+        }
+    }
+#endif /* APR_HAS_THREADS */
+
+    apr_pool_cleanup_register(m->pool, (void *)m,
+                              global_mutex_cleanup, apr_pool_cleanup_null);
+    *mutex = m;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_global_mutex_child_init(
+                              apr_global_mutex_t **mutex,
+                              const char *fname,
+                              apr_pool_t *pool)
+{
+    apr_status_t rv;
+
+    rv = apr_proc_mutex_child_init(&((*mutex)->proc_mutex), fname, pool);
+    return rv;
+}
+
+APR_DECLARE(apr_status_t) apr_global_mutex_lock(apr_global_mutex_t *mutex)
+{
+    apr_status_t rv;
+
+#if APR_HAS_THREADS
+    if (mutex->thread_mutex) {
+        rv = apr_thread_mutex_lock(mutex->thread_mutex);
+        if (rv != APR_SUCCESS) {
+            return rv;
+        }
+    }
+#endif /* APR_HAS_THREADS */
+
+    rv = apr_proc_mutex_lock(mutex->proc_mutex);
+
+#if APR_HAS_THREADS
+    if (rv != APR_SUCCESS) {
+        if (mutex->thread_mutex) {
+            (void)apr_thread_mutex_unlock(mutex->thread_mutex);
+        }
+    }
+#endif /* APR_HAS_THREADS */
+
+    return rv;
+}
+
+APR_DECLARE(apr_status_t) apr_global_mutex_trylock(apr_global_mutex_t *mutex)
+{
+    apr_status_t rv;
+
+#if APR_HAS_THREADS
+    if (mutex->thread_mutex) {
+        rv = apr_thread_mutex_trylock(mutex->thread_mutex);
+        if (rv != APR_SUCCESS) {
+            return rv;
+        }
+    }
+#endif /* APR_HAS_THREADS */
+
+    rv = apr_proc_mutex_trylock(mutex->proc_mutex);
+
+#if APR_HAS_THREADS
+    if (rv != APR_SUCCESS) {
+        if (mutex->thread_mutex) {
+            (void)apr_thread_mutex_unlock(mutex->thread_mutex);
+        }
+    }
+#endif /* APR_HAS_THREADS */
+
+    return rv;
+}
+
+APR_DECLARE(apr_status_t) apr_global_mutex_timedlock(apr_global_mutex_t *mutex,
+                                                 apr_interval_time_t timeout)
+{
+    apr_status_t rv;
+
+#if APR_HAS_THREADS
+    if (mutex->thread_mutex) {
+        apr_time_t expiry = 0;
+        if (timeout > 0) {
+            expiry = apr_time_now() + timeout;
+        }
+        rv = apr_thread_mutex_timedlock(mutex->thread_mutex, timeout);
+        if (rv != APR_SUCCESS) {
+            return rv;
+        }
+        if (expiry) {
+            timeout = expiry - apr_time_now();
+            if (timeout < 0) {
+                timeout = 0;
+            }
+        }
+    }
+#endif /* APR_HAS_THREADS */
+
+    rv = apr_proc_mutex_timedlock(mutex->proc_mutex, timeout);
+
+#if APR_HAS_THREADS
+    if (rv != APR_SUCCESS) {
+        if (mutex->thread_mutex) {
+            (void)apr_thread_mutex_unlock(mutex->thread_mutex);
+        }
+    }
+#endif /* APR_HAS_THREADS */
+
+    return rv;
+}
+
+APR_DECLARE(apr_status_t) apr_global_mutex_unlock(apr_global_mutex_t *mutex)
+{
+    apr_status_t rv;
+
+    rv = apr_proc_mutex_unlock(mutex->proc_mutex);
+#if APR_HAS_THREADS
+    if (mutex->thread_mutex) {
+        if (rv != APR_SUCCESS) {
+            (void)apr_thread_mutex_unlock(mutex->thread_mutex);
+        }
+        else {
+            rv = apr_thread_mutex_unlock(mutex->thread_mutex);
+        }
+    }
+#endif /* APR_HAS_THREADS */
+    return rv;
+}
+
+APR_DECLARE(apr_status_t) apr_os_global_mutex_get(apr_os_global_mutex_t *ospmutex,
+                                                apr_global_mutex_t *pmutex)
+{
+    ospmutex->pool = pmutex->pool;
+    ospmutex->proc_mutex = pmutex->proc_mutex;
+#if APR_HAS_THREADS
+    ospmutex->thread_mutex = pmutex->thread_mutex;
+#endif
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_global_mutex_destroy(apr_global_mutex_t *mutex)
+{
+    return apr_pool_cleanup_run(mutex->pool, mutex, global_mutex_cleanup);
+}
+
+APR_DECLARE(const char *) apr_global_mutex_lockfile(apr_global_mutex_t *mutex)
+{
+    return apr_proc_mutex_lockfile(mutex->proc_mutex);
+}
+
+APR_DECLARE(apr_lockmech_e) apr_global_mutex_mech(apr_global_mutex_t *mutex)
+{
+    return apr_proc_mutex_mech(mutex->proc_mutex);
+}
+
+APR_DECLARE(const char *) apr_global_mutex_name(apr_global_mutex_t *mutex)
+{
+    return apr_proc_mutex_name(mutex->proc_mutex);
+}
+
+APR_PERMS_SET_IMPLEMENT(global_mutex)
+{
+    apr_status_t rv;
+    apr_global_mutex_t *mutex = (apr_global_mutex_t *)theglobal_mutex;
+
+    rv = APR_PERMS_SET_FN(proc_mutex)(mutex->proc_mutex, perms, uid, gid);
+    return rv;
+}
+
+APR_POOL_IMPLEMENT_ACCESSOR(global_mutex)
+
diff --git a/locks/unix/intraproc.c b/locks/unix/intraproc.c
deleted file mode 100644
index feb2c52c62f..00000000000
--- a/locks/unix/intraproc.c
+++ /dev/null
@@ -1,121 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "locks.h"
-
-#if APR_HAS_THREADS
-
-#if defined(USE_PTHREAD_SERIALIZE)  
-
-static ap_status_t lock_intra_cleanup(void *data)
-{
-    ap_lock_t *lock = (ap_lock_t *) data;
-    return pthread_mutex_unlock(lock->intraproc);
-}    
-
-ap_status_t ap_unix_create_intra_lock(ap_lock_t *new)
-{
-    ap_status_t stat;
-    pthread_mutexattr_t mattr;
-
-    new->intraproc = (pthread_mutex_t *)ap_palloc(new->cntxt, 
-                              sizeof(pthread_mutex_t));
-    if (new->intraproc == NULL ) {
-        return errno;
-    }
-    if ((stat = pthread_mutexattr_init(&mattr))) {
-        lock_intra_cleanup(new);
-        return stat;
-    }
-
-    if ((stat = pthread_mutex_init(new->intraproc, &mattr))) {
-        lock_intra_cleanup(new);
-        return stat;
-    }
-
-    if ((stat = pthread_mutexattr_destroy(&mattr))) {
-        lock_intra_cleanup(new);
-        return stat;
-    }
-
-    new->curr_locked = 0;
-    ap_register_cleanup(new->cntxt, (void *)new, lock_intra_cleanup,
-                        ap_null_cleanup);
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_unix_lock_intra(ap_lock_t *lock)
-{
-    return pthread_mutex_lock(lock->intraproc);
-}
-
-ap_status_t ap_unix_unlock_intra(ap_lock_t *lock)
-{
-    ap_status_t status;
-
-    status = pthread_mutex_unlock(lock->intraproc);
-    return status;
-}
-
-ap_status_t ap_unix_destroy_intra_lock(ap_lock_t *lock)
-{
-    ap_status_t stat;
-    if ((stat = lock_intra_cleanup(lock)) == APR_SUCCESS) {
-        ap_kill_cleanup(lock->cntxt, lock, lock_intra_cleanup);
-        return APR_SUCCESS;
-    }
-    return stat;
-}
-#endif
-#endif
diff --git a/locks/unix/locks.c b/locks/unix/locks.c
deleted file mode 100644
index 2a648654c78..00000000000
--- a/locks/unix/locks.c
+++ /dev/null
@@ -1,230 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "locks.h"
-#include "apr_portable.h"
-
-ap_status_t ap_create_lock(ap_lock_t **lock, ap_locktype_e type, 
-                           ap_lockscope_e scope, const char *fname, 
-                           ap_pool_t *cont)
-{
-    ap_lock_t *new;
-    ap_status_t stat;
-
-    new = (ap_lock_t *)ap_palloc(cont, sizeof(ap_lock_t));
-
-    new->cntxt = cont;
-    new->type  = type;
-    new->scope = scope;
-#if defined(USE_FCNTL_SERIALIZE) || defined(USE_FLOCK_SERIALIZE)
-    /* file-based serialization primitives */
-    if (scope != APR_INTRAPROCESS) {
-        if (fname != NULL) {
-            new->fname = ap_pstrdup(cont, fname);
-        }
-        else {
-            new->fname = ap_pstrdup(cont, tempnam(NULL, NULL));
-            unlink(new->fname);
-	}
-    }
-#endif
-
-    if (scope != APR_CROSS_PROCESS) {
-#if APR_HAS_THREADS
-        if ((stat = ap_unix_create_intra_lock(new)) != APR_SUCCESS) {
-            return stat;
-        }
-#else
-        return APR_ENOTIMPL;
-#endif
-    }
-    if (scope != APR_INTRAPROCESS) {
-        if ((stat = ap_unix_create_inter_lock(new)) != APR_SUCCESS) {
-            return stat;
-        }
-    }
-    *lock = new;
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_lock(ap_lock_t *lock)
-{
-    ap_status_t stat;
-    if (lock->scope != APR_CROSS_PROCESS) {
-#if APR_HAS_THREADS
-        if ((stat = ap_unix_lock_intra(lock)) != APR_SUCCESS) {
-            return stat;
-        }
-#else
-        return APR_ENOTIMPL;
-#endif
-    }
-    if (lock->scope != APR_INTRAPROCESS) {
-        if ((stat = ap_unix_lock_inter(lock)) != APR_SUCCESS) {
-            return stat;
-        }
-    }
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_unlock(ap_lock_t *lock)
-{
-    ap_status_t stat;
-
-    if (lock->scope != APR_CROSS_PROCESS) {
-#if APR_HAS_THREADS
-        if ((stat = ap_unix_unlock_intra(lock)) != APR_SUCCESS) {
-            return stat;
-        }
-#else
-        return APR_ENOTIMPL;
-#endif
-    }
-    if (lock->scope != APR_INTRAPROCESS) {
-        if ((stat = ap_unix_unlock_inter(lock)) != APR_SUCCESS) {
-            return stat;
-        }
-    }
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_destroy_lock(ap_lock_t *lock)
-{
-    ap_status_t stat;
-    if (lock->scope != APR_CROSS_PROCESS) {
-#if APR_HAS_THREADS
-        if ((stat = ap_unix_destroy_intra_lock(lock)) != APR_SUCCESS) {
-            return stat;
-        }
-#else
-        return APR_ENOTIMPL;
-#endif
-    }
-    if (lock->scope != APR_INTRAPROCESS) {
-        if ((stat = ap_unix_destroy_inter_lock(lock)) != APR_SUCCESS) {
-            return stat;
-        }
-    }
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_child_init_lock(ap_lock_t **lock, const char *fname, 
-                               ap_pool_t *cont)
-{
-    ap_status_t stat;
-    if ((*lock)->scope != APR_CROSS_PROCESS) {
-        if ((stat = ap_unix_child_init_lock(lock, cont, fname)) != APR_SUCCESS) {
-            return stat;
-        }
-    }
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_get_lockdata(ap_lock_t *lock, char *key, void *data)
-{
-    if (lock != NULL) {
-        return ap_get_userdata(data, key, lock->cntxt);
-    }
-    else {
-        data = NULL;
-        return APR_ENOLOCK;
-    }
-}
-
-ap_status_t ap_set_lockdata(ap_lock_t *lock, void *data, char *key,
-                            ap_status_t (*cleanup) (void *))
-{
-    if (lock != NULL) {
-        return ap_set_userdata(data, key, cleanup, lock->cntxt);
-    }
-    else {
-        data = NULL;
-        return APR_ENOLOCK;
-    }
-}
-
-ap_status_t ap_get_os_lock(ap_os_lock_t *oslock, ap_lock_t *lock)
-{
-    if (lock == NULL) {
-        return APR_ENOLOCK;
-    }
-    oslock->crossproc = lock->interproc;
-#if APR_HAS_THREADS
-#if USE_PTHREAD_SERIALIZE
-    oslock->intraproc = lock->intraproc;
-#endif
-#endif
-
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_put_os_lock(ap_lock_t **lock, ap_os_lock_t *thelock, 
-                           ap_pool_t *cont)
-{
-    if (cont == NULL) {
-        return APR_ENOPOOL;
-    }
-    if ((*lock) == NULL) {
-        (*lock) = (ap_lock_t *)ap_palloc(cont, sizeof(ap_lock_t));
-        (*lock)->cntxt = cont;
-    }
-    (*lock)->interproc = thelock->crossproc;
-#if APR_HAS_THREADS
-#if defined (USE_PTHREAD_SERIALIZE)
-    (*lock)->intraproc = thelock->intraproc;
-#endif
-#endif
-    return APR_SUCCESS;
-}
-    
diff --git a/locks/unix/locks.h b/locks/unix/locks.h
deleted file mode 100644
index f6d37100d5e..00000000000
--- a/locks/unix/locks.h
+++ /dev/null
@@ -1,157 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef LOCKS_H
-#define LOCKS_H
-
-#include "apr_private.h"
-#include "apr_general.h"
-#include "apr_lib.h"
-#include "apr_lock.h"
-
-/* System headers required by Locks library */
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_STRING_H
-#include <string.h>
-#endif
-#if HAVE_USLOCKS_H
-#include <uslocks.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#if HAVE_SYS_IPC_H
-#include <sys/ipc.h>
-#endif
-#if HAVE_SYS_SEM_H
-#include <sys/sem.h>
-#endif
-#if HAVE_SYS_FILE_H
-#include <sys/file.h>
-#endif
-#if HAVE_STDIO_H
-#include <stdio.h>
-#endif
-#if HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#if HAVE_SYS_MMAN_H
-#include <sys/mman.h>
-#endif
-
-#if APR_HAS_THREADS
-#if HAVE_PTHREAD_H
-#include <pthread.h>
-#endif
-#endif
-/* End System Headers */
-
-#if !APR_HAVE_UNION_SEMUN && APR_USE_SYSVSEM_SERIALIZE
-/* it makes no sense, but this isn't defined on solaris */
-union semun {
-    long val;
-    struct semid_ds *buf;
-    ushort *array;
-};
-#endif
-
-struct ap_lock_t {
-    ap_pool_t *cntxt;
-    ap_locktype_e type;
-    ap_lockscope_e scope;
-    int curr_locked;
-    char *fname;
-#if USE_SYSVSEM_SERIALIZE
-    int interproc;
-#elif USE_FCNTL_SERIALIZE
-    int interproc;
-#elif USE_PROC_PTHREAD_SERIALIZE
-    pthread_mutex_t *interproc;
-#elif USE_FLOCK_SERIALIZE
-    int interproc;
-#else
-    /* No Interprocess serialization.  Too bad. */
-#endif 
-#if APR_HAS_THREADS
-    /* APR doesn't have threads, no sense in having an thread lock mechanism.
-     */
-#if USE_PTHREAD_SERIALIZE
-    pthread_mutex_t *intraproc;
-#endif
-#endif
-    /* At some point, we should do a scope for both inter and intra process
-     *  locking here.  Something like pthread_mutex with PTHREAD_PROCESS_SHARED
-     */    
-};
-
-#if APR_HAS_THREADS
-ap_status_t ap_unix_create_intra_lock(struct ap_lock_t *new);
-ap_status_t ap_unix_lock_intra(struct ap_lock_t *lock);
-ap_status_t ap_unix_unlock_intra(struct ap_lock_t *lock);
-ap_status_t ap_unix_destroy_intra_lock(struct ap_lock_t *lock);
-#endif
-
-void ap_unix_setup_lock(void);
-ap_status_t ap_unix_create_inter_lock(struct ap_lock_t *new);
-ap_status_t ap_unix_lock_inter(struct ap_lock_t *lock);
-ap_status_t ap_unix_unlock_inter(struct ap_lock_t *lock);
-ap_status_t ap_unix_destroy_inter_lock(struct ap_lock_t *lock);
-
-ap_status_t ap_unix_child_init_lock(struct ap_lock_t **lock, ap_pool_t *cont, 
-                            const char *fname);
-
-#endif  /* LOCKS_H */
-
diff --git a/locks/unix/proc_mutex.c b/locks/unix/proc_mutex.c
new file mode 100644
index 00000000000..a8002c6bd4b
--- /dev/null
+++ b/locks/unix/proc_mutex.c
@@ -0,0 +1,1669 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_strings.h"
+#include "apr_arch_proc_mutex.h"
+#include "apr_arch_file_io.h" /* for apr_mkstemp() */
+#include "apr_md5.h" /* for apr_md5() */
+#include "apr_atomic.h"
+
+APR_DECLARE(apr_status_t) apr_proc_mutex_destroy(apr_proc_mutex_t *mutex)
+{
+    apr_status_t rv = apr_proc_mutex_cleanup(mutex);
+    if (rv == APR_SUCCESS) {
+        apr_pool_cleanup_kill(mutex->pool, mutex, apr_proc_mutex_cleanup);
+    }
+    return rv;
+}
+
+#if APR_HAS_POSIXSEM_SERIALIZE || APR_HAS_FCNTL_SERIALIZE || \
+    APR_HAS_SYSVSEM_SERIALIZE
+static apr_status_t proc_mutex_no_child_init(apr_proc_mutex_t **mutex,
+                                             apr_pool_t *cont,
+                                             const char *fname)
+{
+    return APR_SUCCESS;
+}
+#endif    
+
+#if APR_HAS_POSIXSEM_SERIALIZE || APR_HAS_PROC_PTHREAD_SERIALIZE
+static apr_status_t proc_mutex_no_perms_set(apr_proc_mutex_t *mutex,
+                                            apr_fileperms_t perms,
+                                            apr_uid_t uid,
+                                            apr_gid_t gid)
+{
+    return APR_ENOTIMPL;
+}
+#endif    
+
+#if APR_HAS_FCNTL_SERIALIZE \
+    || APR_HAS_FLOCK_SERIALIZE \
+    || (APR_HAS_SYSVSEM_SERIALIZE \
+        && !defined(HAVE_SEMTIMEDOP)) \
+    || (APR_HAS_POSIXSEM_SERIALIZE \
+        && !defined(HAVE_SEM_TIMEDWAIT)) \
+    || (APR_HAS_PROC_PTHREAD_SERIALIZE \
+        && !defined(HAVE_PTHREAD_MUTEX_TIMEDLOCK) \
+        && !defined(HAVE_PTHREAD_CONDATTR_SETPSHARED))
+static apr_status_t proc_mutex_spinsleep_timedacquire(apr_proc_mutex_t *mutex,
+                                                  apr_interval_time_t timeout)
+{
+#define SLEEP_TIME apr_time_from_msec(10)
+    apr_status_t rv;
+    for (;;) {
+        rv = apr_proc_mutex_trylock(mutex);
+        if (!APR_STATUS_IS_EBUSY(rv)) {
+            if (rv == APR_SUCCESS) {
+                mutex->curr_locked = 1;
+            }
+            break;
+        }
+        if (timeout <= 0) {
+            rv = APR_TIMEUP;
+            break;
+        }
+        if (timeout > SLEEP_TIME) {
+            apr_sleep(SLEEP_TIME);
+            timeout -= SLEEP_TIME;
+        }
+        else {
+            apr_sleep(timeout);
+            timeout = 0;
+        }
+    }
+    return rv;
+}
+#endif
+
+#if APR_HAS_POSIXSEM_SERIALIZE
+
+#ifndef SEM_FAILED
+#define SEM_FAILED (-1)
+#endif
+
+static apr_status_t proc_mutex_posix_cleanup(void *mutex_)
+{
+    apr_proc_mutex_t *mutex = mutex_;
+    
+    if (sem_close(mutex->os.psem_interproc) < 0) {
+        return errno;
+    }
+
+    return APR_SUCCESS;
+}    
+
+static apr_status_t proc_mutex_posix_create(apr_proc_mutex_t *new_mutex,
+                                            const char *fname)
+{
+    #define APR_POSIXSEM_NAME_MAX 30
+    #define APR_POSIXSEM_NAME_MIN 13
+    sem_t *psem;
+    char semname[APR_MD5_DIGESTSIZE * 2 + 2];
+    
+    /*
+     * This bogusness is to follow what appears to be the
+     * lowest common denominator in Posix semaphore naming:
+     *   - start with '/'
+     *   - be at most 14 chars
+     *   - be unique and not match anything on the filesystem
+     *
+     * Because of this, we use fname to generate an md5 hex checksum
+     * and use that as the name of the semaphore. If no filename was
+     * given, we create one based on the time. We tuck the name
+     * away, since it might be useful for debugging.
+     *
+     * To  make this as robust as possible, we initially try something
+     * larger (and hopefully more unique) and gracefully fail down to the
+     * LCD above.
+     *
+     * NOTE: Darwin (Mac OS X) seems to be the most restrictive
+     * implementation. Versions previous to Darwin 6.2 had the 14
+     * char limit, but later rev's allow up to 31 characters.
+     *
+     */
+    if (fname) {
+        unsigned char digest[APR_MD5_DIGESTSIZE];   /* note dependency on semname here */
+        const char *hex = "0123456789abcdef";
+        char *p = semname;
+        int i;
+        apr_md5(digest, fname, strlen(fname));
+        *p++ = '/';     /* must start with /, right? */
+        for (i = 0; i < sizeof(digest); i++) {
+            *p++ = hex[digest[i] >> 4];
+            *p++ = hex[digest[i] & 0xF];
+        }
+        semname[APR_POSIXSEM_NAME_MAX] = '\0';
+    } else {
+        apr_time_t now;
+        unsigned long sec;
+        unsigned long usec;
+        now = apr_time_now();
+        sec = apr_time_sec(now);
+        usec = apr_time_usec(now);
+        apr_snprintf(semname, sizeof(semname), "/ApR.%lxZ%lx", sec, usec);
+    }
+    do {
+        psem = sem_open(semname, O_CREAT | O_EXCL, 0644, 1);
+    } while (psem == (sem_t *)SEM_FAILED && errno == EINTR);
+    if (psem == (sem_t *)SEM_FAILED) {
+        if (errno == ENAMETOOLONG) {
+            /* Oh well, good try */
+            semname[APR_POSIXSEM_NAME_MIN] = '\0';
+        } else {
+            return errno;
+        }
+        do {
+            psem = sem_open(semname, O_CREAT | O_EXCL, 0644, 1);
+        } while (psem == (sem_t *)SEM_FAILED && errno == EINTR);
+    }
+
+    if (psem == (sem_t *)SEM_FAILED) {
+        return errno;
+    }
+    /* Ahhh. The joys of Posix sems. Predelete it... */
+    sem_unlink(semname);
+    new_mutex->os.psem_interproc = psem;
+    new_mutex->fname = apr_pstrdup(new_mutex->pool, semname);
+    apr_pool_cleanup_register(new_mutex->pool, (void *)new_mutex,
+                              apr_proc_mutex_cleanup, 
+                              apr_pool_cleanup_null);
+    return APR_SUCCESS;
+}
+
+static apr_status_t proc_mutex_posix_acquire(apr_proc_mutex_t *mutex)
+{
+    int rc;
+
+    do {
+        rc = sem_wait(mutex->os.psem_interproc);
+    } while (rc < 0 && errno == EINTR);
+    if (rc < 0) {
+        return errno;
+    }
+    mutex->curr_locked = 1;
+    return APR_SUCCESS;
+}
+
+static apr_status_t proc_mutex_posix_tryacquire(apr_proc_mutex_t *mutex)
+{
+    int rc;
+
+    do {
+        rc = sem_trywait(mutex->os.psem_interproc);
+    } while (rc < 0 && errno == EINTR);
+    if (rc < 0) {
+        if (errno == EAGAIN) {
+            return APR_EBUSY;
+        }
+        return errno;
+    }
+    mutex->curr_locked = 1;
+    return APR_SUCCESS;
+}
+
+#if defined(HAVE_SEM_TIMEDWAIT)
+static apr_status_t proc_mutex_posix_timedacquire(apr_proc_mutex_t *mutex,
+                                              apr_interval_time_t timeout)
+{
+    if (timeout <= 0) {
+        apr_status_t rv = proc_mutex_posix_tryacquire(mutex);
+        return (rv == APR_EBUSY) ? APR_TIMEUP : rv;
+    }
+    else {
+        int rc;
+        struct timespec abstime;
+
+        timeout += apr_time_now();
+        abstime.tv_sec = apr_time_sec(timeout);
+        abstime.tv_nsec = apr_time_usec(timeout) * 1000; /* nanoseconds */
+        
+        do {
+            rc = sem_timedwait(mutex->os.psem_interproc, &abstime);
+        } while (rc < 0 && errno == EINTR);
+        if (rc < 0) {
+            if (errno == ETIMEDOUT) {
+                return APR_TIMEUP;
+            }
+            return errno;
+        }
+    }
+    mutex->curr_locked = 1;
+    return APR_SUCCESS;
+}
+#endif
+
+static apr_status_t proc_mutex_posix_release(apr_proc_mutex_t *mutex)
+{
+    mutex->curr_locked = 0;
+    if (sem_post(mutex->os.psem_interproc) < 0) {
+        /* any failure is probably fatal, so no big deal to leave
+         * ->curr_locked at 0. */
+        return errno;
+    }
+    return APR_SUCCESS;
+}
+
+static const apr_proc_mutex_unix_lock_methods_t mutex_posixsem_methods =
+{
+#if APR_PROCESS_LOCK_IS_GLOBAL || !APR_HAS_THREADS || defined(POSIXSEM_IS_GLOBAL)
+    APR_PROCESS_LOCK_MECH_IS_GLOBAL,
+#else
+    0,
+#endif
+    proc_mutex_posix_create,
+    proc_mutex_posix_acquire,
+    proc_mutex_posix_tryacquire,
+#if defined(HAVE_SEM_TIMEDWAIT)
+    proc_mutex_posix_timedacquire,
+#else
+    proc_mutex_spinsleep_timedacquire,
+#endif
+    proc_mutex_posix_release,
+    proc_mutex_posix_cleanup,
+    proc_mutex_no_child_init,
+    proc_mutex_no_perms_set,
+    APR_LOCK_POSIXSEM,
+    "posixsem"
+};
+
+#endif /* Posix sem implementation */
+
+#if APR_HAS_SYSVSEM_SERIALIZE
+
+static struct sembuf proc_mutex_op_on;
+static struct sembuf proc_mutex_op_try;
+static struct sembuf proc_mutex_op_off;
+
+static void proc_mutex_sysv_setup(void)
+{
+    proc_mutex_op_on.sem_num = 0;
+    proc_mutex_op_on.sem_op = -1;
+    proc_mutex_op_on.sem_flg = SEM_UNDO;
+    proc_mutex_op_try.sem_num = 0;
+    proc_mutex_op_try.sem_op = -1;
+    proc_mutex_op_try.sem_flg = SEM_UNDO | IPC_NOWAIT;
+    proc_mutex_op_off.sem_num = 0;
+    proc_mutex_op_off.sem_op = 1;
+    proc_mutex_op_off.sem_flg = SEM_UNDO;
+}
+
+static apr_status_t proc_mutex_sysv_cleanup(void *mutex_)
+{
+    apr_proc_mutex_t *mutex=mutex_;
+    union semun ick;
+    
+    if (mutex->os.crossproc != -1) {
+        ick.val = 0;
+        semctl(mutex->os.crossproc, 0, IPC_RMID, ick);
+    }
+    return APR_SUCCESS;
+}    
+
+static apr_status_t proc_mutex_sysv_create(apr_proc_mutex_t *new_mutex,
+                                           const char *fname)
+{
+    union semun ick;
+    apr_status_t rv;
+    
+    new_mutex->os.crossproc = semget(IPC_PRIVATE, 1, IPC_CREAT | 0600);
+    if (new_mutex->os.crossproc == -1) {
+        rv = errno;
+        proc_mutex_sysv_cleanup(new_mutex);
+        return rv;
+    }
+    ick.val = 1;
+    if (semctl(new_mutex->os.crossproc, 0, SETVAL, ick) < 0) {
+        rv = errno;
+        proc_mutex_sysv_cleanup(new_mutex);
+        new_mutex->os.crossproc = -1;
+        return rv;
+    }
+    new_mutex->curr_locked = 0;
+    apr_pool_cleanup_register(new_mutex->pool,
+                              (void *)new_mutex, apr_proc_mutex_cleanup, 
+                              apr_pool_cleanup_null);
+    return APR_SUCCESS;
+}
+
+static apr_status_t proc_mutex_sysv_acquire(apr_proc_mutex_t *mutex)
+{
+    int rc;
+
+    do {
+        rc = semop(mutex->os.crossproc, &proc_mutex_op_on, 1);
+    } while (rc < 0 && errno == EINTR);
+    if (rc < 0) {
+        return errno;
+    }
+    mutex->curr_locked = 1;
+    return APR_SUCCESS;
+}
+
+static apr_status_t proc_mutex_sysv_tryacquire(apr_proc_mutex_t *mutex)
+{
+    int rc;
+
+    do {
+        rc = semop(mutex->os.crossproc, &proc_mutex_op_try, 1);
+    } while (rc < 0 && errno == EINTR);
+    if (rc < 0) {
+        if (errno == EAGAIN) {
+            return APR_EBUSY;
+        }
+        return errno;
+    }
+    mutex->curr_locked = 1;
+    return APR_SUCCESS;
+}
+
+#if defined(HAVE_SEMTIMEDOP)
+static apr_status_t proc_mutex_sysv_timedacquire(apr_proc_mutex_t *mutex,
+                                             apr_interval_time_t timeout)
+{
+    if (timeout <= 0) {
+        apr_status_t rv = proc_mutex_sysv_tryacquire(mutex);
+        return (rv == APR_EBUSY) ? APR_TIMEUP : rv;
+    }
+    else {
+        int rc;
+        struct timespec reltime;
+
+        reltime.tv_sec = apr_time_sec(timeout);
+        reltime.tv_nsec = apr_time_usec(timeout) * 1000; /* nanoseconds */
+
+        do {
+            rc = semtimedop(mutex->os.crossproc, &proc_mutex_op_on, 1,
+                            &reltime);
+        } while (rc < 0 && errno == EINTR);
+        if (rc < 0) {
+            if (errno == EAGAIN) {
+                return APR_TIMEUP;
+            }
+            return errno;
+        }
+    }
+    mutex->curr_locked = 1;
+    return APR_SUCCESS;
+}
+#endif
+
+static apr_status_t proc_mutex_sysv_release(apr_proc_mutex_t *mutex)
+{
+    int rc;
+
+    mutex->curr_locked = 0;
+    do {
+        rc = semop(mutex->os.crossproc, &proc_mutex_op_off, 1);
+    } while (rc < 0 && errno == EINTR);
+    if (rc < 0) {
+        return errno;
+    }
+    return APR_SUCCESS;
+}
+
+static apr_status_t proc_mutex_sysv_perms_set(apr_proc_mutex_t *mutex,
+                                              apr_fileperms_t perms,
+                                              apr_uid_t uid,
+                                              apr_gid_t gid)
+{
+
+    union semun ick;
+    struct semid_ds buf;
+    buf.sem_perm.uid = uid;
+    buf.sem_perm.gid = gid;
+    buf.sem_perm.mode = apr_unix_perms2mode(perms);
+    ick.buf = &buf;
+    if (semctl(mutex->os.crossproc, 0, IPC_SET, ick) < 0) {
+        return errno;
+    }
+    return APR_SUCCESS;
+}
+
+static const apr_proc_mutex_unix_lock_methods_t mutex_sysv_methods =
+{
+#if APR_PROCESS_LOCK_IS_GLOBAL || !APR_HAS_THREADS || defined(SYSVSEM_IS_GLOBAL)
+    APR_PROCESS_LOCK_MECH_IS_GLOBAL,
+#else
+    0,
+#endif
+    proc_mutex_sysv_create,
+    proc_mutex_sysv_acquire,
+    proc_mutex_sysv_tryacquire,
+#if defined(HAVE_SEMTIMEDOP)
+    proc_mutex_sysv_timedacquire,
+#else
+    proc_mutex_spinsleep_timedacquire,
+#endif
+    proc_mutex_sysv_release,
+    proc_mutex_sysv_cleanup,
+    proc_mutex_no_child_init,
+    proc_mutex_sysv_perms_set,
+    APR_LOCK_SYSVSEM,
+    "sysvsem"
+};
+
+#endif /* SysV sem implementation */
+
+#if APR_HAS_PROC_PTHREAD_SERIALIZE
+
+#ifndef APR_USE_PROC_PTHREAD_MUTEX_COND
+#define APR_USE_PROC_PTHREAD_MUTEX_COND \
+            (defined(HAVE_PTHREAD_CONDATTR_SETPSHARED) \
+             && !defined(HAVE_PTHREAD_MUTEX_TIMEDLOCK))
+#endif
+
+/* The mmap()ed pthread_interproc is the native pthread_mutex_t followed
+ * by a refcounter to track children using it.  We want to avoid calling
+ * pthread_mutex_destroy() on the shared mutex area while it is in use by
+ * another process, because this may mark the shared pthread_mutex_t as
+ * invalid for everyone, including forked children (unlike "sysvsem" for
+ * example), causing unexpected errors or deadlocks (PR 49504).  So the
+ * last process (parent or child) referencing the mutex will effectively
+ * destroy it.
+ */
+typedef struct {
+#define proc_pthread_cast(m) \
+    ((proc_pthread_mutex_t *)(m)->os.pthread_interproc)
+    pthread_mutex_t mutex;
+#define proc_pthread_mutex(m) \
+    (proc_pthread_cast(m)->mutex)
+#if APR_USE_PROC_PTHREAD_MUTEX_COND
+    pthread_cond_t  cond;
+#define proc_pthread_mutex_cond(m) \
+    (proc_pthread_cast(m)->cond)
+    apr_int32_t     cond_locked;
+#define proc_pthread_mutex_cond_locked(m) \
+    (proc_pthread_cast(m)->cond_locked)
+    apr_uint32_t    cond_num_waiters;
+#define proc_pthread_mutex_cond_num_waiters(m) \
+    (proc_pthread_cast(m)->cond_num_waiters)
+#define proc_pthread_mutex_is_cond(m) \
+    ((m)->pthread_refcounting && proc_pthread_mutex_cond_locked(m) != -1)
+#endif /* APR_USE_PROC_PTHREAD_MUTEX_COND */
+    apr_uint32_t refcount;
+#define proc_pthread_mutex_refcount(m) \
+    (proc_pthread_cast(m)->refcount)
+} proc_pthread_mutex_t;
+
+
+static APR_INLINE int proc_pthread_mutex_inc(apr_proc_mutex_t *mutex)
+{
+    if (mutex->pthread_refcounting) {
+        apr_atomic_inc32(&proc_pthread_mutex_refcount(mutex));
+        return 1;
+    }
+    return 0;
+}
+
+static APR_INLINE int proc_pthread_mutex_dec(apr_proc_mutex_t *mutex)
+{
+    if (mutex->pthread_refcounting) {
+        return apr_atomic_dec32(&proc_pthread_mutex_refcount(mutex));
+    }
+    return 0;
+}
+
+static apr_status_t proc_pthread_mutex_unref(void *mutex_)
+{
+    apr_proc_mutex_t *mutex=mutex_;
+    apr_status_t rv;
+
+#if APR_USE_PROC_PTHREAD_MUTEX_COND
+    if (proc_pthread_mutex_is_cond(mutex)) {
+        mutex->curr_locked = 0;
+    }
+    else
+#endif /* APR_USE_PROC_PTHREAD_MUTEX_COND */
+    if (mutex->curr_locked == 1) {
+        if ((rv = pthread_mutex_unlock(&proc_pthread_mutex(mutex)))) {
+#ifdef HAVE_ZOS_PTHREADS
+            rv = errno;
+#endif
+            return rv;
+        }
+    }
+    if (!proc_pthread_mutex_dec(mutex)) {
+#if APR_USE_PROC_PTHREAD_MUTEX_COND
+        if (proc_pthread_mutex_is_cond(mutex) &&
+                (rv = pthread_cond_destroy(&proc_pthread_mutex_cond(mutex)))) {
+#ifdef HAVE_ZOS_PTHREADS
+            rv = errno;
+#endif
+            return rv;
+        }
+#endif /* APR_USE_PROC_PTHREAD_MUTEX_COND */
+
+        if ((rv = pthread_mutex_destroy(&proc_pthread_mutex(mutex)))) {
+#ifdef HAVE_ZOS_PTHREADS
+            rv = errno;
+#endif
+            return rv;
+        }
+    }
+    return APR_SUCCESS;
+}
+
+static apr_status_t proc_mutex_pthread_cleanup(void *mutex_)
+{
+    apr_proc_mutex_t *mutex=mutex_;
+    apr_status_t rv;
+
+    /* curr_locked is set to -1 until the mutex has been created */
+    if (mutex->curr_locked != -1) {
+        if ((rv = proc_pthread_mutex_unref(mutex))) {
+            return rv;
+        }
+    }
+    if (munmap(mutex->os.pthread_interproc, sizeof(proc_pthread_mutex_t))) {
+        return errno;
+    }
+    return APR_SUCCESS;
+}
+
+static apr_status_t proc_mutex_pthread_create(apr_proc_mutex_t *new_mutex,
+                                              const char *fname)
+{
+    apr_status_t rv;
+    int fd;
+    pthread_mutexattr_t mattr;
+
+    fd = open("/dev/zero", O_RDWR);
+    if (fd < 0) {
+        return errno;
+    }
+
+    new_mutex->os.pthread_interproc = mmap(NULL, sizeof(proc_pthread_mutex_t),
+                                           PROT_READ | PROT_WRITE, MAP_SHARED,
+                                           fd, 0); 
+    if (new_mutex->os.pthread_interproc == MAP_FAILED) {
+        new_mutex->os.pthread_interproc = NULL;
+        rv = errno;
+        close(fd);
+        return rv;
+    }
+    close(fd);
+
+    new_mutex->pthread_refcounting = 1;
+    new_mutex->curr_locked = -1; /* until the mutex has been created */
+#if APR_USE_PROC_PTHREAD_MUTEX_COND
+    proc_pthread_mutex_cond_locked(new_mutex) = -1;
+#endif
+
+    if ((rv = pthread_mutexattr_init(&mattr))) {
+#ifdef HAVE_ZOS_PTHREADS
+        rv = errno;
+#endif
+        proc_mutex_pthread_cleanup(new_mutex);
+        return rv;
+    }
+    if ((rv = pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED))) {
+#ifdef HAVE_ZOS_PTHREADS
+        rv = errno;
+#endif
+        proc_mutex_pthread_cleanup(new_mutex);
+        pthread_mutexattr_destroy(&mattr);
+        return rv;
+    }
+
+#ifdef HAVE_PTHREAD_MUTEX_ROBUST
+    if ((rv = pthread_mutexattr_setrobust_np(&mattr, 
+                                               PTHREAD_MUTEX_ROBUST_NP))) {
+#ifdef HAVE_ZOS_PTHREADS
+        rv = errno;
+#endif
+        proc_mutex_pthread_cleanup(new_mutex);
+        pthread_mutexattr_destroy(&mattr);
+        return rv;
+    }
+    if ((rv = pthread_mutexattr_setprotocol(&mattr, PTHREAD_PRIO_INHERIT))) {
+#ifdef HAVE_ZOS_PTHREADS
+        rv = errno;
+#endif
+        proc_mutex_pthread_cleanup(new_mutex);
+        pthread_mutexattr_destroy(&mattr);
+        return rv;
+    }
+#endif /* HAVE_PTHREAD_MUTEX_ROBUST */
+
+    if ((rv = pthread_mutex_init(&proc_pthread_mutex(new_mutex), &mattr))) {
+#ifdef HAVE_ZOS_PTHREADS
+        rv = errno;
+#endif
+        proc_mutex_pthread_cleanup(new_mutex);
+        pthread_mutexattr_destroy(&mattr);
+        return rv;
+    }
+
+    proc_pthread_mutex_refcount(new_mutex) = 1; /* first/parent reference */
+    new_mutex->curr_locked = 0; /* mutex created now */
+
+    if ((rv = pthread_mutexattr_destroy(&mattr))) {
+#ifdef HAVE_ZOS_PTHREADS
+        rv = errno;
+#endif
+        proc_mutex_pthread_cleanup(new_mutex);
+        return rv;
+    }
+
+    apr_pool_cleanup_register(new_mutex->pool,
+                              (void *)new_mutex,
+                              apr_proc_mutex_cleanup, 
+                              apr_pool_cleanup_null);
+    return APR_SUCCESS;
+}
+
+static apr_status_t proc_mutex_pthread_child_init(apr_proc_mutex_t **mutex,
+                                                  apr_pool_t *pool, 
+                                                  const char *fname)
+{
+    (*mutex)->curr_locked = 0;
+    if (proc_pthread_mutex_inc(*mutex)) {
+        apr_pool_cleanup_register(pool, *mutex, proc_pthread_mutex_unref, 
+                                  apr_pool_cleanup_null);
+    }
+    return APR_SUCCESS;
+}
+
+static apr_status_t proc_mutex_pthread_acquire_ex(apr_proc_mutex_t *mutex,
+                                                  apr_interval_time_t timeout)
+{
+    apr_status_t rv;
+
+#if APR_USE_PROC_PTHREAD_MUTEX_COND
+    if (proc_pthread_mutex_is_cond(mutex)) {
+        if ((rv = pthread_mutex_lock(&proc_pthread_mutex(mutex)))) {
+#ifdef HAVE_ZOS_PTHREADS 
+            rv = errno;
+#endif
+#ifdef HAVE_PTHREAD_MUTEX_ROBUST
+            /* Okay, our owner died.  Let's try to make it consistent again. */
+            if (rv == EOWNERDEAD) {
+                proc_pthread_mutex_dec(mutex);
+                pthread_mutex_consistent_np(&proc_pthread_mutex(mutex));
+            }
+            else
+#endif
+            return rv;
+        }
+
+        if (!proc_pthread_mutex_cond_locked(mutex)) {
+            rv = APR_SUCCESS;
+        }
+        else if (!timeout) {
+            rv = APR_TIMEUP;
+        }
+        else {
+            struct timespec abstime;
+
+            if (timeout > 0) {
+                timeout += apr_time_now();
+                abstime.tv_sec = apr_time_sec(timeout);
+                abstime.tv_nsec = apr_time_usec(timeout) * 1000; /* nanoseconds */
+            }
+
+            proc_pthread_mutex_cond_num_waiters(mutex)++;
+            do {
+                if (timeout < 0) {
+                    rv = pthread_cond_wait(&proc_pthread_mutex_cond(mutex),
+                                           &proc_pthread_mutex(mutex));
+                    if (rv) {
+#ifdef HAVE_ZOS_PTHREADS
+                        rv = errno;
+#endif
+                        break;
+                    }
+                }
+                else {
+                    rv = pthread_cond_timedwait(&proc_pthread_mutex_cond(mutex),
+                                                &proc_pthread_mutex(mutex),
+                                                &abstime);
+                    if (rv) {
+#ifdef HAVE_ZOS_PTHREADS
+                        rv = errno;
+#endif
+                        if (rv == ETIMEDOUT) {
+                            rv = APR_TIMEUP;
+                        }
+                        break;
+                    }
+                }
+            } while (proc_pthread_mutex_cond_locked(mutex));
+            proc_pthread_mutex_cond_num_waiters(mutex)--;
+        }
+        if (rv != APR_SUCCESS) {
+            pthread_mutex_unlock(&proc_pthread_mutex(mutex));
+            return rv;
+        }
+
+        proc_pthread_mutex_cond_locked(mutex) = 1;
+
+        rv = pthread_mutex_unlock(&proc_pthread_mutex(mutex));
+        if (rv) {
+#ifdef HAVE_ZOS_PTHREADS
+            rv = errno;
+#endif
+            return rv;
+        }
+    }
+    else
+#endif /* APR_USE_PROC_PTHREAD_MUTEX_COND */
+    {
+        if (timeout < 0) {
+            rv = pthread_mutex_lock(&proc_pthread_mutex(mutex));
+            if (rv) {
+#ifdef HAVE_ZOS_PTHREADS
+                rv = errno;
+#endif
+            }
+        }
+        else if (!timeout) {
+            rv = pthread_mutex_trylock(&proc_pthread_mutex(mutex));
+            if (rv) {
+#ifdef HAVE_ZOS_PTHREADS
+                rv = errno;
+#endif
+                if (rv == EBUSY) {
+                    return APR_TIMEUP;
+                }
+            }
+        }
+        else
+#if defined(HAVE_PTHREAD_MUTEX_TIMEDLOCK)
+        {
+            struct timespec abstime;
+
+            timeout += apr_time_now();
+            abstime.tv_sec = apr_time_sec(timeout);
+            abstime.tv_nsec = apr_time_usec(timeout) * 1000; /* nanoseconds */
+
+            rv = pthread_mutex_timedlock(&proc_pthread_mutex(mutex), &abstime);
+            if (rv) {
+#ifdef HAVE_ZOS_PTHREADS 
+                rv = errno;
+#endif
+                if (rv == ETIMEDOUT) {
+                    return APR_TIMEUP;
+                }
+            }
+        }
+        if (rv) {
+#ifdef HAVE_PTHREAD_MUTEX_ROBUST
+            /* Okay, our owner died.  Let's try to make it consistent again. */
+            if (rv == EOWNERDEAD) {
+                proc_pthread_mutex_dec(mutex);
+                pthread_mutex_consistent_np(&proc_pthread_mutex(mutex));
+            }
+            else
+#endif
+            return rv;
+        }
+#else /* !HAVE_PTHREAD_MUTEX_TIMEDLOCK */
+        return proc_mutex_spinsleep_timedacquire(mutex, timeout);
+#endif
+    }
+
+    mutex->curr_locked = 1;
+    return APR_SUCCESS;
+}
+
+static apr_status_t proc_mutex_pthread_acquire(apr_proc_mutex_t *mutex)
+{
+    return proc_mutex_pthread_acquire_ex(mutex, -1);
+}
+
+static apr_status_t proc_mutex_pthread_tryacquire(apr_proc_mutex_t *mutex)
+{
+    apr_status_t rv = proc_mutex_pthread_acquire_ex(mutex, 0);
+    return (rv == APR_TIMEUP) ? APR_EBUSY : rv;
+}
+
+static apr_status_t proc_mutex_pthread_timedacquire(apr_proc_mutex_t *mutex,
+                                                apr_interval_time_t timeout)
+{
+    return proc_mutex_pthread_acquire_ex(mutex, (timeout <= 0) ? 0 : timeout);
+}
+
+static apr_status_t proc_mutex_pthread_release(apr_proc_mutex_t *mutex)
+{
+    apr_status_t rv;
+
+#if APR_USE_PROC_PTHREAD_MUTEX_COND
+    if (proc_pthread_mutex_is_cond(mutex)) {
+        if ((rv = pthread_mutex_lock(&proc_pthread_mutex(mutex)))) {
+#ifdef HAVE_ZOS_PTHREADS 
+            rv = errno;
+#endif
+#ifdef HAVE_PTHREAD_MUTEX_ROBUST
+            /* Okay, our owner died.  Let's try to make it consistent again. */
+            if (rv == EOWNERDEAD) {
+                proc_pthread_mutex_dec(mutex);
+                pthread_mutex_consistent_np(&proc_pthread_mutex(mutex));
+            }
+            else
+#endif
+            return rv;
+        }
+
+        if (!proc_pthread_mutex_cond_locked(mutex)) {
+            rv = APR_EINVAL;
+        }
+        else if (!proc_pthread_mutex_cond_num_waiters(mutex)) {
+            rv = APR_SUCCESS;
+        }
+        else {
+            rv = pthread_cond_signal(&proc_pthread_mutex_cond(mutex));
+#ifdef HAVE_ZOS_PTHREADS
+            if (rv) {
+                rv = errno;
+            }
+#endif
+        }
+        if (rv != APR_SUCCESS) {
+            pthread_mutex_unlock(&proc_pthread_mutex(mutex));
+            return rv;
+        }
+
+        proc_pthread_mutex_cond_locked(mutex) = 0;
+    }
+#endif /* APR_USE_PROC_PTHREAD_MUTEX_COND */
+
+    mutex->curr_locked = 0;
+    if ((rv = pthread_mutex_unlock(&proc_pthread_mutex(mutex)))) {
+#ifdef HAVE_ZOS_PTHREADS
+        rv = errno;
+#endif
+        return rv;
+    }
+
+    return APR_SUCCESS;
+}
+
+static const apr_proc_mutex_unix_lock_methods_t mutex_proc_pthread_methods =
+{
+    APR_PROCESS_LOCK_MECH_IS_GLOBAL,
+    proc_mutex_pthread_create,
+    proc_mutex_pthread_acquire,
+    proc_mutex_pthread_tryacquire,
+    proc_mutex_pthread_timedacquire,
+    proc_mutex_pthread_release,
+    proc_mutex_pthread_cleanup,
+    proc_mutex_pthread_child_init,
+    proc_mutex_no_perms_set,
+    APR_LOCK_PROC_PTHREAD,
+    "pthread"
+};
+
+#if APR_USE_PROC_PTHREAD_MUTEX_COND
+static apr_status_t proc_mutex_pthread_cond_create(apr_proc_mutex_t *new_mutex,
+                                                   const char *fname)
+{
+    apr_status_t rv;
+    pthread_condattr_t cattr;
+
+    rv = proc_mutex_pthread_create(new_mutex, fname);
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
+    if ((rv = pthread_condattr_init(&cattr))) {
+#ifdef HAVE_ZOS_PTHREADS
+        rv = errno;
+#endif
+        apr_pool_cleanup_run(new_mutex->pool, new_mutex,
+                             apr_proc_mutex_cleanup); 
+        return rv;
+    }
+    if ((rv = pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_SHARED))) {
+#ifdef HAVE_ZOS_PTHREADS
+        rv = errno;
+#endif
+        pthread_condattr_destroy(&cattr);
+        apr_pool_cleanup_run(new_mutex->pool, new_mutex,
+                             apr_proc_mutex_cleanup); 
+        return rv;
+    }
+    if ((rv = pthread_cond_init(&proc_pthread_mutex_cond(new_mutex),
+                                &cattr))) {
+#ifdef HAVE_ZOS_PTHREADS
+        rv = errno;
+#endif
+        pthread_condattr_destroy(&cattr);
+        apr_pool_cleanup_run(new_mutex->pool, new_mutex,
+                             apr_proc_mutex_cleanup); 
+        return rv;
+    }
+    pthread_condattr_destroy(&cattr);
+
+    proc_pthread_mutex_cond_locked(new_mutex) = 0;
+    proc_pthread_mutex_cond_num_waiters(new_mutex) = 0;
+
+    return APR_SUCCESS;
+}
+
+static const apr_proc_mutex_unix_lock_methods_t mutex_proc_pthread_cond_methods =
+{
+    APR_PROCESS_LOCK_MECH_IS_GLOBAL,
+    proc_mutex_pthread_cond_create,
+    proc_mutex_pthread_acquire,
+    proc_mutex_pthread_tryacquire,
+    proc_mutex_pthread_timedacquire,
+    proc_mutex_pthread_release,
+    proc_mutex_pthread_cleanup,
+    proc_mutex_pthread_child_init,
+    proc_mutex_no_perms_set,
+    APR_LOCK_PROC_PTHREAD,
+    "pthread"
+};
+#endif
+
+#endif
+
+#if APR_HAS_FCNTL_SERIALIZE
+
+static struct flock proc_mutex_lock_it;
+static struct flock proc_mutex_unlock_it;
+
+static apr_status_t proc_mutex_fcntl_release(apr_proc_mutex_t *);
+
+static void proc_mutex_fcntl_setup(void)
+{
+    proc_mutex_lock_it.l_whence = SEEK_SET;   /* from current point */
+    proc_mutex_lock_it.l_start = 0;           /* -"- */
+    proc_mutex_lock_it.l_len = 0;             /* until end of file */
+    proc_mutex_lock_it.l_type = F_WRLCK;      /* set exclusive/write lock */
+    proc_mutex_lock_it.l_pid = 0;             /* pid not actually interesting */
+    proc_mutex_unlock_it.l_whence = SEEK_SET; /* from current point */
+    proc_mutex_unlock_it.l_start = 0;         /* -"- */
+    proc_mutex_unlock_it.l_len = 0;           /* until end of file */
+    proc_mutex_unlock_it.l_type = F_UNLCK;    /* set exclusive/write lock */
+    proc_mutex_unlock_it.l_pid = 0;           /* pid not actually interesting */
+}
+
+static apr_status_t proc_mutex_fcntl_cleanup(void *mutex_)
+{
+    apr_status_t status = APR_SUCCESS;
+    apr_proc_mutex_t *mutex=mutex_;
+
+    if (mutex->curr_locked == 1) {
+        status = proc_mutex_fcntl_release(mutex);
+        if (status != APR_SUCCESS)
+            return status;
+    }
+        
+    if (mutex->interproc) {
+        status = apr_file_close(mutex->interproc);
+    }
+    if (!mutex->interproc_closing
+            && mutex->os.crossproc != -1
+            && close(mutex->os.crossproc) == -1
+            && status == APR_SUCCESS) {
+        status = errno;
+    }
+    return status;
+}    
+
+static apr_status_t proc_mutex_fcntl_create(apr_proc_mutex_t *new_mutex,
+                                            const char *fname)
+{
+    int rv;
+ 
+    if (fname) {
+        new_mutex->fname = apr_pstrdup(new_mutex->pool, fname);
+        rv = apr_file_open(&new_mutex->interproc, new_mutex->fname,
+                           APR_FOPEN_CREATE | APR_FOPEN_WRITE | APR_FOPEN_EXCL,
+                           APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_GREAD | APR_FPROT_WREAD,
+                           new_mutex->pool);
+    }
+    else {
+        new_mutex->fname = apr_pstrdup(new_mutex->pool, "/tmp/aprXXXXXX");
+        rv = apr_file_mktemp(&new_mutex->interproc, new_mutex->fname,
+                             APR_FOPEN_CREATE | APR_FOPEN_WRITE | APR_FOPEN_EXCL,
+                             new_mutex->pool);
+    }
+ 
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
+    new_mutex->os.crossproc = new_mutex->interproc->filedes;
+    new_mutex->interproc_closing = 1;
+    new_mutex->curr_locked = 0;
+    unlink(new_mutex->fname);
+    apr_pool_cleanup_register(new_mutex->pool,
+                              (void*)new_mutex,
+                              apr_proc_mutex_cleanup, 
+                              apr_pool_cleanup_null);
+    return APR_SUCCESS; 
+}
+
+static apr_status_t proc_mutex_fcntl_acquire(apr_proc_mutex_t *mutex)
+{
+    int rc;
+
+    do {
+        rc = fcntl(mutex->os.crossproc, F_SETLKW, &proc_mutex_lock_it);
+    } while (rc < 0 && errno == EINTR);
+    if (rc < 0) {
+        return errno;
+    }
+    mutex->curr_locked=1;
+    return APR_SUCCESS;
+}
+
+static apr_status_t proc_mutex_fcntl_tryacquire(apr_proc_mutex_t *mutex)
+{
+    int rc;
+
+    do {
+        rc = fcntl(mutex->os.crossproc, F_SETLK, &proc_mutex_lock_it);
+    } while (rc < 0 && errno == EINTR);
+    if (rc < 0) {
+#if FCNTL_TRYACQUIRE_EACCES
+        if (errno == EACCES) {
+#else
+        if (errno == EAGAIN) {
+#endif
+            return APR_EBUSY;
+        }
+        return errno;
+    }
+    mutex->curr_locked = 1;
+    return APR_SUCCESS;
+}
+
+static apr_status_t proc_mutex_fcntl_release(apr_proc_mutex_t *mutex)
+{
+    int rc;
+
+    mutex->curr_locked=0;
+    do {
+        rc = fcntl(mutex->os.crossproc, F_SETLKW, &proc_mutex_unlock_it);
+    } while (rc < 0 && errno == EINTR);
+    if (rc < 0) {
+        return errno;
+    }
+    return APR_SUCCESS;
+}
+
+static apr_status_t proc_mutex_fcntl_perms_set(apr_proc_mutex_t *mutex,
+                                               apr_fileperms_t perms,
+                                               apr_uid_t uid,
+                                               apr_gid_t gid)
+{
+
+    if (mutex->fname) {
+        if (!(perms & APR_FPROT_GSETID))
+            gid = -1;
+        if (fchown(mutex->os.crossproc, uid, gid) < 0) {
+            return errno;
+        }
+    }
+    return APR_SUCCESS;
+}
+
+static const apr_proc_mutex_unix_lock_methods_t mutex_fcntl_methods =
+{
+#if APR_PROCESS_LOCK_IS_GLOBAL || !APR_HAS_THREADS || defined(FCNTL_IS_GLOBAL)
+    APR_PROCESS_LOCK_MECH_IS_GLOBAL,
+#else
+    0,
+#endif
+    proc_mutex_fcntl_create,
+    proc_mutex_fcntl_acquire,
+    proc_mutex_fcntl_tryacquire,
+    proc_mutex_spinsleep_timedacquire,
+    proc_mutex_fcntl_release,
+    proc_mutex_fcntl_cleanup,
+    proc_mutex_no_child_init,
+    proc_mutex_fcntl_perms_set,
+    APR_LOCK_FCNTL,
+    "fcntl"
+};
+
+#endif /* fcntl implementation */
+
+#if APR_HAS_FLOCK_SERIALIZE
+
+static apr_status_t proc_mutex_flock_release(apr_proc_mutex_t *);
+
+static apr_status_t proc_mutex_flock_cleanup(void *mutex_)
+{
+    apr_status_t status = APR_SUCCESS;
+    apr_proc_mutex_t *mutex=mutex_;
+
+    if (mutex->curr_locked == 1) {
+        status = proc_mutex_flock_release(mutex);
+        if (status != APR_SUCCESS)
+            return status;
+    }
+    if (mutex->interproc) { /* if it was opened properly */
+        status = apr_file_close(mutex->interproc);
+    }
+    if (!mutex->interproc_closing
+            && mutex->os.crossproc != -1
+            && close(mutex->os.crossproc) == -1
+            && status == APR_SUCCESS) {
+        status = errno;
+    }
+    if (mutex->fname) {
+        unlink(mutex->fname);
+    }
+    return status;
+}    
+
+static apr_status_t proc_mutex_flock_create(apr_proc_mutex_t *new_mutex,
+                                            const char *fname)
+{
+    int rv;
+ 
+    if (fname) {
+        new_mutex->fname = apr_pstrdup(new_mutex->pool, fname);
+        rv = apr_file_open(&new_mutex->interproc, new_mutex->fname,
+                           APR_FOPEN_CREATE | APR_FOPEN_WRITE | APR_FOPEN_EXCL,
+                           APR_FPROT_UREAD | APR_FPROT_UWRITE,
+                           new_mutex->pool);
+    }
+    else {
+        new_mutex->fname = apr_pstrdup(new_mutex->pool, "/tmp/aprXXXXXX");
+        rv = apr_file_mktemp(&new_mutex->interproc, new_mutex->fname,
+                             APR_FOPEN_CREATE | APR_FOPEN_WRITE | APR_FOPEN_EXCL,
+                             new_mutex->pool);
+    }
+ 
+    if (rv != APR_SUCCESS) {
+        proc_mutex_flock_cleanup(new_mutex);
+        return rv;
+    }
+
+    new_mutex->os.crossproc = new_mutex->interproc->filedes;
+    new_mutex->interproc_closing = 1;
+    new_mutex->curr_locked = 0;
+    apr_pool_cleanup_register(new_mutex->pool, (void *)new_mutex,
+                              apr_proc_mutex_cleanup,
+                              apr_pool_cleanup_null);
+    return APR_SUCCESS;
+}
+
+static apr_status_t proc_mutex_flock_acquire(apr_proc_mutex_t *mutex)
+{
+    int rc;
+
+    do {
+        rc = flock(mutex->os.crossproc, LOCK_EX);
+    } while (rc < 0 && errno == EINTR);
+    if (rc < 0) {
+        return errno;
+    }
+    mutex->curr_locked = 1;
+    return APR_SUCCESS;
+}
+
+static apr_status_t proc_mutex_flock_tryacquire(apr_proc_mutex_t *mutex)
+{
+    int rc;
+
+    do {
+        rc = flock(mutex->os.crossproc, LOCK_EX | LOCK_NB);
+    } while (rc < 0 && errno == EINTR);
+    if (rc < 0) {
+        if (errno == EWOULDBLOCK || errno == EAGAIN) {
+            return APR_EBUSY;
+        }
+        return errno;
+    }
+    mutex->curr_locked = 1;
+    return APR_SUCCESS;
+}
+
+static apr_status_t proc_mutex_flock_release(apr_proc_mutex_t *mutex)
+{
+    int rc;
+
+    mutex->curr_locked = 0;
+    do {
+        rc = flock(mutex->os.crossproc, LOCK_UN);
+    } while (rc < 0 && errno == EINTR);
+    if (rc < 0) {
+        return errno;
+    }
+    return APR_SUCCESS;
+}
+
+static apr_status_t proc_mutex_flock_child_init(apr_proc_mutex_t **mutex,
+                                                apr_pool_t *pool, 
+                                                const char *fname)
+{
+    apr_proc_mutex_t *new_mutex;
+    int rv;
+
+    if (!fname) {
+        fname = (*mutex)->fname;
+        if (!fname) {
+            return APR_SUCCESS;
+        }
+    }
+
+    new_mutex = (apr_proc_mutex_t *)apr_pmemdup(pool, *mutex,
+                                                sizeof(apr_proc_mutex_t));
+    new_mutex->pool = pool;
+    new_mutex->fname = apr_pstrdup(pool, fname);
+    rv = apr_file_open(&new_mutex->interproc, new_mutex->fname,
+                       APR_FOPEN_WRITE, 0, new_mutex->pool);
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+    new_mutex->os.crossproc = new_mutex->interproc->filedes;
+    new_mutex->interproc_closing = 1;
+
+    *mutex = new_mutex;
+    return APR_SUCCESS;
+}
+
+static apr_status_t proc_mutex_flock_perms_set(apr_proc_mutex_t *mutex,
+                                               apr_fileperms_t perms,
+                                               apr_uid_t uid,
+                                               apr_gid_t gid)
+{
+
+    if (mutex->fname) {
+        if (!(perms & APR_FPROT_GSETID))
+            gid = -1;
+        if (fchown(mutex->os.crossproc, uid, gid) < 0) {
+            return errno;
+        }
+    }
+    return APR_SUCCESS;
+}
+
+static const apr_proc_mutex_unix_lock_methods_t mutex_flock_methods =
+{
+#if APR_PROCESS_LOCK_IS_GLOBAL || !APR_HAS_THREADS || defined(FLOCK_IS_GLOBAL)
+    APR_PROCESS_LOCK_MECH_IS_GLOBAL,
+#else
+    0,
+#endif
+    proc_mutex_flock_create,
+    proc_mutex_flock_acquire,
+    proc_mutex_flock_tryacquire,
+    proc_mutex_spinsleep_timedacquire,
+    proc_mutex_flock_release,
+    proc_mutex_flock_cleanup,
+    proc_mutex_flock_child_init,
+    proc_mutex_flock_perms_set,
+    APR_LOCK_FLOCK,
+    "flock"
+};
+
+#endif /* flock implementation */
+
+void apr_proc_mutex_unix_setup_lock(void)
+{
+    /* setup only needed for sysvsem and fnctl */
+#if APR_HAS_SYSVSEM_SERIALIZE
+    proc_mutex_sysv_setup();
+#endif
+#if APR_HAS_FCNTL_SERIALIZE
+    proc_mutex_fcntl_setup();
+#endif
+}
+
+static apr_status_t proc_mutex_choose_method(apr_proc_mutex_t *new_mutex,
+                                             apr_lockmech_e mech,
+                                             apr_os_proc_mutex_t *ospmutex)
+{
+#if APR_HAS_PROC_PTHREAD_SERIALIZE
+    new_mutex->os.pthread_interproc = NULL;
+#endif
+#if APR_HAS_POSIXSEM_SERIALIZE
+    new_mutex->os.psem_interproc = NULL;
+#endif
+#if APR_HAS_SYSVSEM_SERIALIZE || APR_HAS_FCNTL_SERIALIZE || APR_HAS_FLOCK_SERIALIZE
+    new_mutex->os.crossproc = -1;
+
+#if APR_HAS_FCNTL_SERIALIZE || APR_HAS_FLOCK_SERIALIZE
+    new_mutex->interproc = NULL;
+    new_mutex->interproc_closing = 0;
+#endif
+#endif
+
+    switch (mech) {
+    case APR_LOCK_FCNTL:
+#if APR_HAS_FCNTL_SERIALIZE
+        new_mutex->meth = &mutex_fcntl_methods;
+        if (ospmutex) {
+            if (ospmutex->crossproc == -1) {
+                return APR_EINVAL;
+            }
+            new_mutex->os.crossproc = ospmutex->crossproc;
+        }
+#else
+        return APR_ENOTIMPL;
+#endif
+        break;
+    case APR_LOCK_FLOCK:
+#if APR_HAS_FLOCK_SERIALIZE
+        new_mutex->meth = &mutex_flock_methods;
+        if (ospmutex) {
+            if (ospmutex->crossproc == -1) {
+                return APR_EINVAL;
+            }
+            new_mutex->os.crossproc = ospmutex->crossproc;
+        }
+#else
+        return APR_ENOTIMPL;
+#endif
+        break;
+    case APR_LOCK_SYSVSEM:
+#if APR_HAS_SYSVSEM_SERIALIZE
+        new_mutex->meth = &mutex_sysv_methods;
+        if (ospmutex) {
+            if (ospmutex->crossproc == -1) {
+                return APR_EINVAL;
+            }
+            new_mutex->os.crossproc = ospmutex->crossproc;
+        }
+#else
+        return APR_ENOTIMPL;
+#endif
+        break;
+    case APR_LOCK_POSIXSEM:
+#if APR_HAS_POSIXSEM_SERIALIZE
+        new_mutex->meth = &mutex_posixsem_methods;
+        if (ospmutex) {
+            if (ospmutex->psem_interproc == NULL) {
+                return APR_EINVAL;
+            }
+            new_mutex->os.psem_interproc = ospmutex->psem_interproc;
+        }
+#else
+        return APR_ENOTIMPL;
+#endif
+        break;
+    case APR_LOCK_PROC_PTHREAD:
+#if APR_HAS_PROC_PTHREAD_SERIALIZE
+        new_mutex->meth = &mutex_proc_pthread_methods;
+        if (ospmutex) {
+            if (ospmutex->pthread_interproc == NULL) {
+                return APR_EINVAL;
+            }
+            new_mutex->os.pthread_interproc = ospmutex->pthread_interproc;
+        }
+#else
+        return APR_ENOTIMPL;
+#endif
+        break;
+    case APR_LOCK_DEFAULT_TIMED:
+#if APR_HAS_PROC_PTHREAD_SERIALIZE \
+        && (APR_USE_PROC_PTHREAD_MUTEX_COND \
+            || defined(HAVE_PTHREAD_MUTEX_TIMEDLOCK)) \
+        && defined(HAVE_PTHREAD_MUTEX_ROBUST)
+#if APR_USE_PROC_PTHREAD_MUTEX_COND
+        new_mutex->meth = &mutex_proc_pthread_cond_methods;
+#else
+        new_mutex->meth = &mutex_proc_pthread_methods;
+#endif
+        if (ospmutex) {
+            if (ospmutex->pthread_interproc == NULL) {
+                return APR_EINVAL;
+            }
+            new_mutex->os.pthread_interproc = ospmutex->pthread_interproc;
+        }
+        break;
+#elif APR_HAS_SYSVSEM_SERIALIZE && defined(HAVE_SEMTIMEDOP)
+        new_mutex->meth = &mutex_sysv_methods;
+        if (ospmutex) {
+            if (ospmutex->crossproc == -1) {
+                return APR_EINVAL;
+            }
+            new_mutex->os.crossproc = ospmutex->crossproc;
+        }
+        break;
+#elif APR_HAS_POSIXSEM_SERIALIZE && defined(HAVE_SEM_TIMEDWAIT)
+        new_mutex->meth = &mutex_posixsem_methods;
+        if (ospmutex) {
+            if (ospmutex->psem_interproc == NULL) {
+                return APR_EINVAL;
+            }
+            new_mutex->os.psem_interproc = ospmutex->psem_interproc;
+        }
+        break;
+#endif
+        /* fall trough */
+    case APR_LOCK_DEFAULT:
+#if APR_USE_FLOCK_SERIALIZE
+        new_mutex->meth = &mutex_flock_methods;
+        if (ospmutex) {
+            if (ospmutex->crossproc == -1) {
+                return APR_EINVAL;
+            }
+            new_mutex->os.crossproc = ospmutex->crossproc;
+        }
+#elif APR_USE_SYSVSEM_SERIALIZE
+        new_mutex->meth = &mutex_sysv_methods;
+        if (ospmutex) {
+            if (ospmutex->crossproc == -1) {
+                return APR_EINVAL;
+            }
+            new_mutex->os.crossproc = ospmutex->crossproc;
+        }
+#elif APR_USE_FCNTL_SERIALIZE
+        new_mutex->meth = &mutex_fcntl_methods;
+        if (ospmutex) {
+            if (ospmutex->crossproc == -1) {
+                return APR_EINVAL;
+            }
+            new_mutex->os.crossproc = ospmutex->crossproc;
+        }
+#elif APR_USE_PROC_PTHREAD_SERIALIZE
+        new_mutex->meth = &mutex_proc_pthread_methods;
+        if (ospmutex) {
+            if (ospmutex->pthread_interproc == NULL) {
+                return APR_EINVAL;
+            }
+            new_mutex->os.pthread_interproc = ospmutex->pthread_interproc;
+        }
+#elif APR_USE_POSIXSEM_SERIALIZE
+        new_mutex->meth = &mutex_posixsem_methods;
+        if (ospmutex) {
+            if (ospmutex->psem_interproc == NULL) {
+                return APR_EINVAL;
+            }
+            new_mutex->os.psem_interproc = ospmutex->psem_interproc;
+        }
+#else
+        return APR_ENOTIMPL;
+#endif
+        break;
+    default:
+        return APR_ENOTIMPL;
+    }
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(const char *) apr_proc_mutex_defname(void)
+{
+    apr_status_t rv;
+    apr_proc_mutex_t mutex;
+
+    if ((rv = proc_mutex_choose_method(&mutex, APR_LOCK_DEFAULT,
+                                       NULL)) != APR_SUCCESS) {
+        return "unknown";
+    }
+
+    return apr_proc_mutex_name(&mutex);
+}
+   
+static apr_status_t proc_mutex_create(apr_proc_mutex_t *new_mutex, apr_lockmech_e mech, const char *fname)
+{
+    apr_status_t rv;
+
+    if ((rv = proc_mutex_choose_method(new_mutex, mech,
+                                       NULL)) != APR_SUCCESS) {
+        return rv;
+    }
+
+    if ((rv = new_mutex->meth->create(new_mutex, fname)) != APR_SUCCESS) {
+        return rv;
+    }
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_proc_mutex_create(apr_proc_mutex_t **mutex,
+                                                const char *fname,
+                                                apr_lockmech_e mech,
+                                                apr_pool_t *pool)
+{
+    apr_proc_mutex_t *new_mutex;
+    apr_status_t rv;
+
+    new_mutex = apr_pcalloc(pool, sizeof(apr_proc_mutex_t));
+    new_mutex->pool = pool;
+
+    if ((rv = proc_mutex_create(new_mutex, mech, fname)) != APR_SUCCESS)
+        return rv;
+
+    *mutex = new_mutex;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_proc_mutex_child_init(apr_proc_mutex_t **mutex,
+                                                    const char *fname,
+                                                    apr_pool_t *pool)
+{
+    return (*mutex)->meth->child_init(mutex, pool, fname);
+}
+
+APR_DECLARE(apr_status_t) apr_proc_mutex_lock(apr_proc_mutex_t *mutex)
+{
+    return mutex->meth->acquire(mutex);
+}
+
+APR_DECLARE(apr_status_t) apr_proc_mutex_trylock(apr_proc_mutex_t *mutex)
+{
+    return mutex->meth->tryacquire(mutex);
+}
+
+APR_DECLARE(apr_status_t) apr_proc_mutex_timedlock(apr_proc_mutex_t *mutex,
+                                               apr_interval_time_t timeout)
+{
+    return mutex->meth->timedacquire(mutex, timeout);
+}
+
+APR_DECLARE(apr_status_t) apr_proc_mutex_unlock(apr_proc_mutex_t *mutex)
+{
+    return mutex->meth->release(mutex);
+}
+
+APR_DECLARE(apr_status_t) apr_proc_mutex_cleanup(void *mutex)
+{
+    return ((apr_proc_mutex_t *)mutex)->meth->cleanup(mutex);
+}
+
+APR_DECLARE(apr_lockmech_e) apr_proc_mutex_mech(apr_proc_mutex_t *mutex)
+{
+    return mutex->meth->mech;
+}
+
+APR_DECLARE(const char *) apr_proc_mutex_name(apr_proc_mutex_t *mutex)
+{
+    return mutex->meth->name;
+}
+
+APR_DECLARE(const char *) apr_proc_mutex_lockfile(apr_proc_mutex_t *mutex)
+{
+    /* POSIX sems use the fname field but don't use a file,
+     * so be careful. */
+#if APR_HAS_FLOCK_SERIALIZE
+    if (mutex->meth == &mutex_flock_methods) {
+        return mutex->fname;
+    }
+#endif
+#if APR_HAS_FCNTL_SERIALIZE
+    if (mutex->meth == &mutex_fcntl_methods) {
+        return mutex->fname;
+    }
+#endif
+    return NULL;
+}
+
+APR_PERMS_SET_IMPLEMENT(proc_mutex)
+{
+    apr_proc_mutex_t *mutex = (apr_proc_mutex_t *)theproc_mutex;
+    return mutex->meth->perms_set(mutex, perms, uid, gid);
+}
+
+APR_POOL_IMPLEMENT_ACCESSOR(proc_mutex)
+
+/* Implement OS-specific accessors defined in apr_portable.h */
+
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_get_ex(apr_os_proc_mutex_t *ospmutex, 
+                                                   apr_proc_mutex_t *pmutex,
+                                                   apr_lockmech_e *mech)
+{
+    *ospmutex = pmutex->os;
+    if (mech) {
+        *mech = pmutex->meth->mech;
+    }
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_get(apr_os_proc_mutex_t *ospmutex,
+                                                apr_proc_mutex_t *pmutex)
+{
+    return apr_os_proc_mutex_get_ex(ospmutex, pmutex, NULL);
+}
+
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_put_ex(apr_proc_mutex_t **pmutex,
+                                                apr_os_proc_mutex_t *ospmutex,
+                                                apr_lockmech_e mech,
+                                                int register_cleanup,
+                                                apr_pool_t *pool)
+{
+    apr_status_t rv;
+    if (pool == NULL) {
+        return APR_ENOPOOL;
+    }
+
+    if ((*pmutex) == NULL) {
+        (*pmutex) = (apr_proc_mutex_t *)apr_pcalloc(pool,
+                                                    sizeof(apr_proc_mutex_t));
+        (*pmutex)->pool = pool;
+    }
+    rv = proc_mutex_choose_method(*pmutex, mech, ospmutex);
+#if APR_HAS_FCNTL_SERIALIZE || APR_HAS_FLOCK_SERIALIZE
+    if (rv == APR_SUCCESS) {
+        rv = apr_os_file_put(&(*pmutex)->interproc, &(*pmutex)->os.crossproc,
+                             0, pool);
+    }
+#endif
+
+    if (rv == APR_SUCCESS && register_cleanup) {
+        apr_pool_cleanup_register(pool, *pmutex, apr_proc_mutex_cleanup, 
+                                  apr_pool_cleanup_null);
+    }
+    return rv;
+}
+
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_put(apr_proc_mutex_t **pmutex,
+                                                apr_os_proc_mutex_t *ospmutex,
+                                                apr_pool_t *pool)
+{
+    return apr_os_proc_mutex_put_ex(pmutex, ospmutex, APR_LOCK_DEFAULT,
+                                    0, pool);
+}
+
diff --git a/locks/unix/thread_cond.c b/locks/unix/thread_cond.c
new file mode 100644
index 00000000000..3c8e3170a0d
--- /dev/null
+++ b/locks/unix/thread_cond.c
@@ -0,0 +1,145 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+
+#if APR_HAS_THREADS
+
+#include "apr_arch_thread_mutex.h"
+#include "apr_arch_thread_cond.h"
+
+static apr_status_t thread_cond_cleanup(void *data)
+{
+    apr_thread_cond_t *cond = (apr_thread_cond_t *)data;
+    apr_status_t rv;
+
+    rv = pthread_cond_destroy(&cond->cond);
+#ifdef HAVE_ZOS_PTHREADS
+    if (rv) {
+        rv = errno;
+    }
+#endif
+    return rv;
+} 
+
+APR_DECLARE(apr_status_t) apr_thread_cond_create(apr_thread_cond_t **cond,
+                                                 apr_pool_t *pool)
+{
+    apr_thread_cond_t *new_cond;
+    apr_status_t rv;
+
+    new_cond = apr_palloc(pool, sizeof(apr_thread_cond_t));
+
+    new_cond->pool = pool;
+
+    if ((rv = pthread_cond_init(&new_cond->cond, NULL))) {
+#ifdef HAVE_ZOS_PTHREADS
+        rv = errno;
+#endif
+        return rv;
+    }
+
+    apr_pool_cleanup_register(new_cond->pool,
+                              (void *)new_cond, thread_cond_cleanup,
+                              apr_pool_cleanup_null);
+
+    *cond = new_cond;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_cond_wait(apr_thread_cond_t *cond,
+                                               apr_thread_mutex_t *mutex)
+{
+    apr_status_t rv;
+
+    rv = pthread_cond_wait(&cond->cond, &mutex->mutex);
+#ifdef HAVE_ZOS_PTHREADS
+    if (rv) {
+        rv = errno;
+    }
+#endif
+    return rv;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_cond_timedwait(apr_thread_cond_t *cond,
+                                                    apr_thread_mutex_t *mutex,
+                                                    apr_interval_time_t timeout)
+{
+    apr_status_t rv;
+    if (timeout < 0) {
+        rv = pthread_cond_wait(&cond->cond, &mutex->mutex);
+#ifdef HAVE_ZOS_PTHREADS
+        if (rv) {
+            rv = errno;
+        }
+#endif
+    }
+    else {
+        apr_time_t then;
+        struct timespec abstime;
+
+        then = apr_time_now() + timeout;
+        abstime.tv_sec = apr_time_sec(then);
+        abstime.tv_nsec = apr_time_usec(then) * 1000; /* nanoseconds */
+
+        rv = pthread_cond_timedwait(&cond->cond, &mutex->mutex, &abstime);
+#ifdef HAVE_ZOS_PTHREADS
+        if (rv) {
+            rv = errno;
+        }
+#endif
+        if (ETIMEDOUT == rv) {
+            return APR_TIMEUP;
+        }
+    }
+    return rv;
+}
+
+
+APR_DECLARE(apr_status_t) apr_thread_cond_signal(apr_thread_cond_t *cond)
+{
+    apr_status_t rv;
+
+    rv = pthread_cond_signal(&cond->cond);
+#ifdef HAVE_ZOS_PTHREADS
+    if (rv) {
+        rv = errno;
+    }
+#endif
+    return rv;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_cond_broadcast(apr_thread_cond_t *cond)
+{
+    apr_status_t rv;
+
+    rv = pthread_cond_broadcast(&cond->cond);
+#ifdef HAVE_ZOS_PTHREADS
+    if (rv) {
+        rv = errno;
+    }
+#endif
+    return rv;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_cond_destroy(apr_thread_cond_t *cond)
+{
+    return apr_pool_cleanup_run(cond->pool, cond, thread_cond_cleanup);
+}
+
+APR_POOL_IMPLEMENT_ACCESSOR(thread_cond)
+
+#endif /* APR_HAS_THREADS */
diff --git a/locks/unix/thread_mutex.c b/locks/unix/thread_mutex.c
new file mode 100644
index 00000000000..f027c791f2e
--- /dev/null
+++ b/locks/unix/thread_mutex.c
@@ -0,0 +1,332 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_arch_thread_mutex.h"
+#define APR_WANT_MEMFUNC
+#include "apr_want.h"
+
+#if APR_HAS_THREADS
+
+static apr_status_t thread_mutex_cleanup(void *data)
+{
+    apr_thread_mutex_t *mutex = data;
+    apr_status_t rv;
+
+    rv = pthread_mutex_destroy(&mutex->mutex);
+#ifdef HAVE_ZOS_PTHREADS
+    if (rv) {
+        rv = errno;
+    }
+#endif
+    return rv;
+} 
+
+APR_DECLARE(apr_status_t) apr_thread_mutex_create(apr_thread_mutex_t **mutex,
+                                                  unsigned int flags,
+                                                  apr_pool_t *pool)
+{
+    apr_thread_mutex_t *new_mutex;
+    apr_status_t rv;
+    
+#ifndef HAVE_PTHREAD_MUTEX_RECURSIVE
+    if (flags & APR_THREAD_MUTEX_NESTED) {
+        return APR_ENOTIMPL;
+    }
+#endif
+
+    new_mutex = apr_pcalloc(pool, sizeof(apr_thread_mutex_t));
+    new_mutex->pool = pool;
+
+#ifdef HAVE_PTHREAD_MUTEX_RECURSIVE
+    if (flags & APR_THREAD_MUTEX_NESTED) {
+        pthread_mutexattr_t mattr;
+        
+        rv = pthread_mutexattr_init(&mattr);
+        if (rv) return rv;
+        
+        rv = pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE);
+        if (rv) {
+            pthread_mutexattr_destroy(&mattr);
+            return rv;
+        }
+         
+        rv = pthread_mutex_init(&new_mutex->mutex, &mattr);
+        
+        pthread_mutexattr_destroy(&mattr);
+    } else
+#endif
+        rv = pthread_mutex_init(&new_mutex->mutex, NULL);
+
+    if (rv) {
+#ifdef HAVE_ZOS_PTHREADS
+        rv = errno;
+#endif
+        return rv;
+    }
+
+#ifndef HAVE_PTHREAD_MUTEX_TIMEDLOCK
+    if (flags & APR_THREAD_MUTEX_TIMED) {
+        rv = apr_thread_cond_create(&new_mutex->cond, pool);
+        if (rv) {
+#ifdef HAVE_ZOS_PTHREADS
+            rv = errno;
+#endif
+            pthread_mutex_destroy(&new_mutex->mutex);
+            return rv;
+        }
+    }
+#endif
+
+    apr_pool_cleanup_register(new_mutex->pool,
+                              new_mutex, thread_mutex_cleanup,
+                              apr_pool_cleanup_null);
+
+    *mutex = new_mutex;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_mutex_lock(apr_thread_mutex_t *mutex)
+{
+    apr_status_t rv;
+
+    if (mutex->cond) {
+        apr_status_t rv2;
+
+        rv = pthread_mutex_lock(&mutex->mutex);
+        if (rv) {
+#ifdef HAVE_ZOS_PTHREADS
+            rv = errno;
+#endif
+            return rv;
+        }
+
+        if (mutex->locked) {
+            mutex->num_waiters++;
+            rv = apr_thread_cond_wait(mutex->cond, mutex);
+            mutex->num_waiters--;
+        }
+        else {
+            mutex->locked = 1;
+        }
+
+        rv2 = pthread_mutex_unlock(&mutex->mutex);
+        if (rv2 && !rv) {
+#ifdef HAVE_ZOS_PTHREADS
+            rv = errno;
+#else
+            rv = rv2;
+#endif
+        }
+
+        return rv;
+    }
+
+    rv = pthread_mutex_lock(&mutex->mutex);
+#ifdef HAVE_ZOS_PTHREADS
+    if (rv) {
+        rv = errno;
+    }
+#endif
+
+    return rv;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_mutex_trylock(apr_thread_mutex_t *mutex)
+{
+    apr_status_t rv;
+
+    if (mutex->cond) {
+        apr_status_t rv2;
+
+        rv = pthread_mutex_lock(&mutex->mutex);
+        if (rv) {
+#ifdef HAVE_ZOS_PTHREADS
+            rv = errno;
+#endif
+            return rv;
+        }
+
+        if (mutex->locked) {
+            rv = APR_EBUSY;
+        }
+        else {
+            mutex->locked = 1;
+        }
+
+        rv2 = pthread_mutex_unlock(&mutex->mutex);
+        if (rv2) {
+#ifdef HAVE_ZOS_PTHREADS
+            rv = errno;
+#else
+            rv = rv2;
+#endif
+        }
+
+        return rv;
+    }
+
+    rv = pthread_mutex_trylock(&mutex->mutex);
+    if (rv) {
+#ifdef HAVE_ZOS_PTHREADS
+        rv = errno;
+#endif
+        return (rv == EBUSY) ? APR_EBUSY : rv;
+    }
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_mutex_timedlock(apr_thread_mutex_t *mutex,
+                                                 apr_interval_time_t timeout)
+{
+    apr_status_t rv = APR_ENOTIMPL;
+
+#ifdef HAVE_PTHREAD_MUTEX_TIMEDLOCK
+    if (timeout <= 0) {
+        rv = pthread_mutex_trylock(&mutex->mutex);
+        if (rv) {
+#ifdef HAVE_ZOS_PTHREADS
+            rv = errno;
+#endif
+            if (rv == EBUSY) {
+                rv = APR_TIMEUP;
+            }
+        }
+    }
+    else {
+        struct timespec abstime;
+
+        timeout += apr_time_now();
+        abstime.tv_sec = apr_time_sec(timeout);
+        abstime.tv_nsec = apr_time_usec(timeout) * 1000; /* nanoseconds */
+
+        rv = pthread_mutex_timedlock(&mutex->mutex, &abstime);
+        if (rv) {
+#ifdef HAVE_ZOS_PTHREADS
+            rv = errno;
+#endif
+            if (rv == ETIMEDOUT) {
+                rv = APR_TIMEUP;
+            }
+        }
+    }
+
+#else /* HAVE_PTHREAD_MUTEX_TIMEDLOCK */
+
+    if (mutex->cond) {
+        rv = pthread_mutex_lock(&mutex->mutex);
+        if (rv) {
+#ifdef HAVE_ZOS_PTHREADS
+            rv = errno;
+#endif
+            return rv;
+        }
+
+        if (mutex->locked) {
+            if (timeout <= 0) {
+                rv = APR_TIMEUP;
+            }
+            else {
+                mutex->num_waiters++;
+                do {
+                    rv = apr_thread_cond_timedwait(mutex->cond, mutex,
+                                                   timeout);
+                    if (rv) {
+#ifdef HAVE_ZOS_PTHREADS
+                        rv = errno;
+#endif
+                        break;
+                    }
+                } while (mutex->locked);
+                mutex->num_waiters--;
+            }
+            if (rv) {
+                pthread_mutex_unlock(&mutex->mutex);
+                return rv;
+            }
+        }
+
+        mutex->locked = 1;
+
+        rv = pthread_mutex_unlock(&mutex->mutex);
+        if (rv) {
+#ifdef HAVE_ZOS_PTHREADS
+            rv = errno;
+#endif
+            return rv;
+        }
+    }
+
+#endif /* HAVE_PTHREAD_MUTEX_TIMEDLOCK */
+
+    return rv;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_mutex_unlock(apr_thread_mutex_t *mutex)
+{
+    apr_status_t status;
+
+    if (mutex->cond) {
+        status = pthread_mutex_lock(&mutex->mutex);
+        if (status) {
+#ifdef HAVE_ZOS_PTHREADS
+            status = errno;
+#endif
+            return status;
+        }
+
+        if (!mutex->locked) {
+            status = APR_EINVAL;
+        }
+        else if (mutex->num_waiters) {
+            status = apr_thread_cond_signal(mutex->cond);
+        }
+        if (status) {
+            pthread_mutex_unlock(&mutex->mutex);
+            return status;
+        }
+
+        mutex->locked = 0;
+    }
+
+    status = pthread_mutex_unlock(&mutex->mutex);
+#ifdef HAVE_ZOS_PTHREADS
+    if (status) {
+        status = errno;
+    }
+#endif
+
+    return status;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_mutex_destroy(apr_thread_mutex_t *mutex)
+{
+    apr_status_t rv, rv2 = APR_SUCCESS;
+
+    if (mutex->cond) {
+        rv2 = apr_thread_cond_destroy(mutex->cond);
+    }
+    rv = apr_pool_cleanup_run(mutex->pool, mutex, thread_mutex_cleanup);
+    if (rv == APR_SUCCESS) {
+        rv = rv2;
+    }
+    
+    return rv;
+}
+
+APR_POOL_IMPLEMENT_ACCESSOR(thread_mutex)
+
+#endif /* APR_HAS_THREADS */
diff --git a/locks/unix/thread_rwlock.c b/locks/unix/thread_rwlock.c
new file mode 100644
index 00000000000..0f8b7a79ff7
--- /dev/null
+++ b/locks/unix/thread_rwlock.c
@@ -0,0 +1,181 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_arch_thread_rwlock.h"
+#include "apr_private.h"
+
+#if APR_HAS_THREADS
+
+#ifdef HAVE_PTHREAD_RWLOCKS
+
+/* The rwlock must be initialized but not locked by any thread when
+ * cleanup is called. */
+static apr_status_t thread_rwlock_cleanup(void *data)
+{
+    apr_thread_rwlock_t *rwlock = (apr_thread_rwlock_t *)data;
+    apr_status_t stat;
+
+    stat = pthread_rwlock_destroy(&rwlock->rwlock);
+#ifdef HAVE_ZOS_PTHREADS
+    if (stat) {
+        stat = errno;
+    }
+#endif
+    return stat;
+} 
+
+APR_DECLARE(apr_status_t) apr_thread_rwlock_create(apr_thread_rwlock_t **rwlock,
+                                                   apr_pool_t *pool)
+{
+    apr_thread_rwlock_t *new_rwlock;
+    apr_status_t stat;
+
+    new_rwlock = apr_palloc(pool, sizeof(apr_thread_rwlock_t));
+    new_rwlock->pool = pool;
+
+    if ((stat = pthread_rwlock_init(&new_rwlock->rwlock, NULL))) {
+#ifdef HAVE_ZOS_PTHREADS
+        stat = errno;
+#endif
+        return stat;
+    }
+
+    apr_pool_cleanup_register(new_rwlock->pool,
+                              (void *)new_rwlock, thread_rwlock_cleanup,
+                              apr_pool_cleanup_null);
+
+    *rwlock = new_rwlock;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_rwlock_rdlock(apr_thread_rwlock_t *rwlock)
+{
+    apr_status_t stat;
+
+    stat = pthread_rwlock_rdlock(&rwlock->rwlock);
+#ifdef HAVE_ZOS_PTHREADS
+    if (stat) {
+        stat = errno;
+    }
+#endif
+    return stat;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_rwlock_tryrdlock(apr_thread_rwlock_t *rwlock)
+{
+    apr_status_t stat;
+
+    stat = pthread_rwlock_tryrdlock(&rwlock->rwlock);
+#ifdef HAVE_ZOS_PTHREADS
+    if (stat) {
+        stat = errno;
+    }
+#endif
+    /* Normalize the return code. */
+    if (stat == EBUSY)
+        stat = APR_EBUSY;
+    return stat;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_rwlock_wrlock(apr_thread_rwlock_t *rwlock)
+{
+    apr_status_t stat;
+
+    stat = pthread_rwlock_wrlock(&rwlock->rwlock);
+#ifdef HAVE_ZOS_PTHREADS
+    if (stat) {
+        stat = errno;
+    }
+#endif
+    return stat;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_rwlock_trywrlock(apr_thread_rwlock_t *rwlock)
+{
+    apr_status_t stat;
+
+    stat = pthread_rwlock_trywrlock(&rwlock->rwlock);
+#ifdef HAVE_ZOS_PTHREADS
+    if (stat) {
+        stat = errno;
+    }
+#endif
+    /* Normalize the return code. */
+    if (stat == EBUSY)
+        stat = APR_EBUSY;
+    return stat;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_rwlock_unlock(apr_thread_rwlock_t *rwlock)
+{
+    apr_status_t stat;
+
+    stat = pthread_rwlock_unlock(&rwlock->rwlock);
+#ifdef HAVE_ZOS_PTHREADS
+    if (stat) {
+        stat = errno;
+    }
+#endif
+    return stat;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_rwlock_destroy(apr_thread_rwlock_t *rwlock)
+{
+    return apr_pool_cleanup_run(rwlock->pool, rwlock, thread_rwlock_cleanup);
+}
+
+#else  /* HAVE_PTHREAD_RWLOCKS */
+
+APR_DECLARE(apr_status_t) apr_thread_rwlock_create(apr_thread_rwlock_t **rwlock,
+                                                   apr_pool_t *pool)
+{
+    return APR_ENOTIMPL;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_rwlock_rdlock(apr_thread_rwlock_t *rwlock)
+{
+    return APR_ENOTIMPL;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_rwlock_tryrdlock(apr_thread_rwlock_t *rwlock)
+{
+    return APR_ENOTIMPL;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_rwlock_wrlock(apr_thread_rwlock_t *rwlock)
+{
+    return APR_ENOTIMPL;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_rwlock_trywrlock(apr_thread_rwlock_t *rwlock)
+{
+    return APR_ENOTIMPL;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_rwlock_unlock(apr_thread_rwlock_t *rwlock)
+{
+    return APR_ENOTIMPL;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_rwlock_destroy(apr_thread_rwlock_t *rwlock)
+{
+    return APR_ENOTIMPL;
+}
+
+#endif /* HAVE_PTHREAD_RWLOCKS */
+APR_POOL_IMPLEMENT_ACCESSOR(thread_rwlock)
+
+#endif /* APR_HAS_THREADS */
diff --git a/locks/win32/locks.c b/locks/win32/locks.c
deleted file mode 100644
index a9031a05d47..00000000000
--- a/locks/win32/locks.c
+++ /dev/null
@@ -1,201 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "apr_general.h"
-#include "apr_lib.h"
-#include "locks.h"
-#include "apr_portable.h"
-
-ap_status_t ap_create_lock(ap_lock_t **lock, ap_locktype_e type, 
-                           ap_lockscope_e scope, const char *fname, 
-                           ap_pool_t *cont)
-{
-    ap_lock_t *newlock;
-    SECURITY_ATTRIBUTES sec;
-
-    newlock = (ap_lock_t *)ap_palloc(cont, sizeof(ap_lock_t));
-
-    newlock->cntxt = cont;
-    /* ToDo:  How to handle the case when no context is available? 
-    *         How to cleanup the storage properly?
-    */
-    newlock->fname = ap_pstrdup(cont, fname);
-    newlock->type = type;
-    newlock->scope = scope;
-    sec.nLength = sizeof(SECURITY_ATTRIBUTES);
-    sec.lpSecurityDescriptor = NULL;
-
-    if (scope == APR_CROSS_PROCESS || scope == APR_LOCKALL) {
-        sec.bInheritHandle = TRUE;
-    }
-    else {
-        sec.bInheritHandle = FALSE;
-    }
-
-    if (scope == APR_INTRAPROCESS) {
-        InitializeCriticalSection(&newlock->section);
-    } else {
-        newlock->mutex = CreateMutex(&sec, FALSE, fname);
-    }
-    *lock = newlock;
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_child_init_lock(ap_lock_t **lock, const char *fname, 
-                               ap_pool_t *cont)
-{
-    /* This routine should not be called (and OpenMutex will fail if called) 
-     * on a INTRAPROCESS lock
-     */
-    (*lock) = (ap_lock_t *)ap_palloc(cont, sizeof(ap_lock_t));
-
-    if ((*lock) == NULL) {
-        return APR_ENOMEM;
-    }
-    (*lock)->fname = ap_pstrdup(cont, fname);
-    (*lock)->mutex = OpenMutex(MUTEX_ALL_ACCESS, TRUE, fname);
-    
-    if ((*lock)->mutex == NULL) {
-        return APR_EEXIST;
-    }
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_lock(ap_lock_t *lock)
-{
-    DWORD rv;
-    if (lock->scope == APR_INTRAPROCESS) {
-        EnterCriticalSection(&lock->section);
-        return APR_SUCCESS;
-    } else {
-        rv = WaitForSingleObject(lock->mutex, INFINITE);
-
-        if (rv == WAIT_OBJECT_0 || rv == WAIT_ABANDONED) {
-            return APR_SUCCESS;
-        }
-    }
-    return GetLastError();
-}
-
-ap_status_t ap_unlock(ap_lock_t *lock)
-{
-    if (lock->scope == APR_INTRAPROCESS) {
-        LeaveCriticalSection(&lock->section);
-        return APR_SUCCESS;
-    } else {
-        if (ReleaseMutex(lock->mutex) == 0) {
-            return APR_EEXIST;
-        }
-    }
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_destroy_lock(ap_lock_t *lock)
-{
-    if (lock->scope == APR_INTRAPROCESS) {
-        DeleteCriticalSection(&lock->section);
-        return APR_SUCCESS;
-    } else {
-        if (CloseHandle(lock->mutex) == 0) {
-            return APR_EEXIST;
-        }
-    }
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_get_lockdata(ap_lock_t *lock, char *key, void *data)
-{
-    if (lock != NULL) {
-        return ap_get_userdata(data, key, lock->cntxt);
-    }
-    else {
-        data = NULL;
-        return APR_ENOLOCK;
-    }
-}
-
-ap_status_t ap_set_lockdata(ap_lock_t *lock, void *data, char *key,
-                            ap_status_t (*cleanup) (void *))
-{
-    if (lock != NULL) {
-        return ap_set_userdata(data, key, cleanup, lock->cntxt);
-    }
-    else {
-        data = NULL;
-        return APR_ENOLOCK;
-    }
-}
-
-ap_status_t ap_get_os_lock(ap_os_lock_t *thelock, ap_lock_t *lock)
-{
-    if (lock == NULL) {
-        return APR_ENOFILE;
-    }
-    thelock = &(lock->mutex);
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_put_os_lock(ap_lock_t **lock, ap_os_lock_t *thelock, 
-                           ap_pool_t *cont)
-{
-    if (cont == NULL) {
-        return APR_ENOPOOL;
-    }
-    if ((*lock) == NULL) {
-        (*lock) = (ap_lock_t *)ap_palloc(cont, sizeof(ap_lock_t));
-        (*lock)->cntxt = cont;
-    }
-    (*lock)->mutex = *thelock;
-    return APR_SUCCESS;
-}    
diff --git a/locks/win32/locks.h b/locks/win32/locks.h
deleted file mode 100644
index 602c2eb673f..00000000000
--- a/locks/win32/locks.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef LOCKS_H
-#define LOCKS_H
-
-#include "apr_lock.h"
-
-struct ap_lock_t {
-    ap_pool_t *cntxt;
-    ap_locktype_e type;
-    ap_lockscope_e scope;
-    HANDLE mutex;
-    CRITICAL_SECTION section;
-    char *fname;
-};
-
-#endif  /* LOCKS_H */
-
diff --git a/locks/win32/proc_mutex.c b/locks/win32/proc_mutex.c
new file mode 100644
index 00000000000..e132e20a2e3
--- /dev/null
+++ b/locks/win32/proc_mutex.c
@@ -0,0 +1,301 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_private.h"
+#include "apr_general.h"
+#include "apr_strings.h"
+#include "apr_portable.h"
+#include "apr_arch_file_io.h"
+#include "apr_arch_proc_mutex.h"
+#include "apr_arch_misc.h"
+
+static apr_status_t proc_mutex_cleanup(void *mutex_)
+{
+    apr_proc_mutex_t *mutex = mutex_;
+
+    if (mutex->handle) {
+        if (CloseHandle(mutex->handle) == 0) {
+            return apr_get_os_error();
+        }
+    }
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_proc_mutex_create(apr_proc_mutex_t **mutex,
+                                                const char *fname,
+                                                apr_lockmech_e mech,
+                                                apr_pool_t *pool)
+{
+    HANDLE hMutex;
+    void *mutexkey;
+
+    if (mech != APR_LOCK_DEFAULT && mech != APR_LOCK_DEFAULT_TIMED) {
+        return APR_ENOTIMPL;
+    }
+
+    /* res_name_from_filename turns fname into a pseduo-name
+     * without slashes or backslashes, and prepends the \global
+     * prefix on Win2K and later
+     */
+    if (fname) {
+        mutexkey = res_name_from_filename(fname, 1, pool);
+    }
+    else {
+        mutexkey = NULL;
+    }
+
+#if APR_HAS_UNICODE_FS
+    IF_WIN_OS_IS_UNICODE
+    {
+        hMutex = CreateMutexW(NULL, FALSE, mutexkey);
+    }
+#endif
+#if APR_HAS_ANSI_FS
+    ELSE_WIN_OS_IS_ANSI
+    {
+        hMutex = CreateMutexA(NULL, FALSE, mutexkey);
+    }
+#endif
+
+    if (!hMutex) {
+        return apr_get_os_error();
+    }
+
+    *mutex = (apr_proc_mutex_t *)apr_palloc(pool, sizeof(apr_proc_mutex_t));
+    (*mutex)->pool = pool;
+    (*mutex)->handle = hMutex;
+    (*mutex)->fname = fname;
+    apr_pool_cleanup_register((*mutex)->pool, *mutex, 
+                              proc_mutex_cleanup, apr_pool_cleanup_null);
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_proc_mutex_child_init(apr_proc_mutex_t **mutex,
+                                                    const char *fname,
+                                                    apr_pool_t *pool)
+{
+    HANDLE hMutex;
+    void *mutexkey;
+
+    if (!fname) {
+        /* Reinitializing unnamed mutexes is a noop in the Unix code. */
+        return APR_SUCCESS;
+    }
+
+    /* res_name_from_filename turns file into a pseudo-name
+     * without slashes or backslashes, and prepends the \global
+     * prefix on Win2K and later
+     */
+    mutexkey = res_name_from_filename(fname, 1, pool);
+
+#if defined(_WIN32_WCE)
+    hMutex = CreateMutex(NULL, FALSE, mutexkey);
+    if (hMutex && ERROR_ALREADY_EXISTS != GetLastError()) {
+        CloseHandle(hMutex);
+        hMutex = NULL;
+        SetLastError(ERROR_FILE_NOT_FOUND);
+    }
+#else
+#if APR_HAS_UNICODE_FS
+    IF_WIN_OS_IS_UNICODE
+    {
+        hMutex = OpenMutexW(MUTEX_ALL_ACCESS, FALSE, mutexkey);
+    }
+#endif
+#if APR_HAS_ANSI_FS
+    ELSE_WIN_OS_IS_ANSI
+    {
+        hMutex = OpenMutexA(MUTEX_ALL_ACCESS, FALSE, mutexkey);
+    }
+#endif
+#endif
+
+    if (!hMutex) {
+        return apr_get_os_error();
+    }
+
+    *mutex = (apr_proc_mutex_t *)apr_palloc(pool, sizeof(apr_proc_mutex_t));
+    (*mutex)->pool = pool;
+    (*mutex)->handle = hMutex;
+    (*mutex)->fname = fname;
+    apr_pool_cleanup_register((*mutex)->pool, *mutex, 
+                              proc_mutex_cleanup, apr_pool_cleanup_null);
+    return APR_SUCCESS;
+}
+    
+APR_DECLARE(apr_status_t) apr_proc_mutex_lock(apr_proc_mutex_t *mutex)
+{
+    DWORD rv;
+
+    rv = WaitForSingleObject(mutex->handle, INFINITE);
+
+    if (rv == WAIT_OBJECT_0 || rv == WAIT_ABANDONED) {
+        return APR_SUCCESS;
+    }
+    return apr_get_os_error();
+}
+
+APR_DECLARE(apr_status_t) apr_proc_mutex_trylock(apr_proc_mutex_t *mutex)
+{
+    DWORD rv;
+
+    rv = WaitForSingleObject(mutex->handle, 0);
+
+    if (rv == WAIT_OBJECT_0 || rv == WAIT_ABANDONED) {
+        return APR_SUCCESS;
+    } 
+    else if (rv == WAIT_TIMEOUT) {
+        return APR_EBUSY;
+    }
+    return apr_get_os_error();
+}
+
+APR_DECLARE(apr_status_t) apr_proc_mutex_timedlock(apr_proc_mutex_t *mutex,
+                                               apr_interval_time_t timeout)
+{
+    DWORD rv, timeout_ms = 0;
+    apr_interval_time_t t = timeout;
+
+    do {
+        if (t > 0) {
+            /* Given timeout is 64bit usecs whereas Windows timeouts are
+             * 32bit msecs and below INFINITE (2^32 - 1), so we may need
+             * multiple timed out waits...
+             */
+            if (t > apr_time_from_msec(INFINITE - 1)) {
+                timeout_ms = INFINITE - 1;
+                t -= apr_time_from_msec(INFINITE - 1);
+            }
+            else {
+                timeout_ms = (DWORD)apr_time_as_msec(t);
+                t = 0;
+            }
+        }
+        rv = WaitForSingleObject(mutex->handle, timeout_ms);
+    } while (rv == WAIT_TIMEOUT && t > 0);
+
+    if (rv == WAIT_TIMEOUT) {
+        return APR_TIMEUP;
+    }
+    if (rv == WAIT_OBJECT_0 || rv == WAIT_ABANDONED) {
+        return APR_SUCCESS;
+    } 
+    return apr_get_os_error();
+}
+
+APR_DECLARE(apr_status_t) apr_proc_mutex_unlock(apr_proc_mutex_t *mutex)
+{
+    if (ReleaseMutex(mutex->handle) == 0) {
+        return apr_get_os_error();
+    }
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_proc_mutex_destroy(apr_proc_mutex_t *mutex)
+{
+    apr_status_t stat;
+
+    stat = proc_mutex_cleanup(mutex);
+    if (stat == APR_SUCCESS) {
+        apr_pool_cleanup_kill(mutex->pool, mutex, proc_mutex_cleanup);
+    }
+    return stat;
+}
+
+APR_DECLARE(apr_status_t) apr_proc_mutex_cleanup(void *mutex)
+{
+    return apr_proc_mutex_destroy((apr_proc_mutex_t *)mutex);
+}
+
+APR_DECLARE(const char *) apr_proc_mutex_lockfile(apr_proc_mutex_t *mutex)
+{
+    return mutex->fname;
+}
+
+APR_DECLARE(apr_lockmech_e) apr_proc_mutex_mech(apr_proc_mutex_t *mutex)
+{
+    return APR_LOCK_DEFAULT;
+}
+
+APR_DECLARE(const char *) apr_proc_mutex_name(apr_proc_mutex_t *mutex)
+{
+    return apr_proc_mutex_defname();
+}
+
+APR_DECLARE(const char *) apr_proc_mutex_defname(void)
+{
+    return "win32mutex";
+}
+
+APR_PERMS_SET_ENOTIMPL(proc_mutex)
+
+APR_POOL_IMPLEMENT_ACCESSOR(proc_mutex)
+
+/* Implement OS-specific accessors defined in apr_portable.h */
+
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_get_ex(apr_os_proc_mutex_t *ospmutex, 
+                                                   apr_proc_mutex_t *pmutex,
+                                                   apr_lockmech_e *mech)
+{
+    *ospmutex = pmutex->handle;
+    if (mech) {
+        *mech = APR_LOCK_DEFAULT;
+    }
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_get(apr_os_proc_mutex_t *ospmutex,
+                                                apr_proc_mutex_t *pmutex)
+{
+    return apr_os_proc_mutex_get_ex(ospmutex, pmutex, NULL);
+}
+
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_put_ex(apr_proc_mutex_t **pmutex,
+                                                apr_os_proc_mutex_t *ospmutex,
+                                                apr_lockmech_e mech,
+                                                int register_cleanup,
+                                                apr_pool_t *pool)
+{
+    if (pool == NULL) {
+        return APR_ENOPOOL;
+    }
+    if (mech != APR_LOCK_DEFAULT && mech != APR_LOCK_DEFAULT_TIMED) {
+        return APR_ENOTIMPL;
+    }
+
+    if ((*pmutex) == NULL) {
+        (*pmutex) = (apr_proc_mutex_t *)apr_palloc(pool,
+                                                   sizeof(apr_proc_mutex_t));
+        (*pmutex)->pool = pool;
+    }
+    (*pmutex)->handle = *ospmutex;
+
+    if (register_cleanup) {
+        apr_pool_cleanup_register(pool, *pmutex, proc_mutex_cleanup,
+                                  apr_pool_cleanup_null);
+    }
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_put(apr_proc_mutex_t **pmutex,
+                                                apr_os_proc_mutex_t *ospmutex,
+                                                apr_pool_t *pool)
+{
+    return apr_os_proc_mutex_put_ex(pmutex, ospmutex, APR_LOCK_DEFAULT,
+                                    0, pool);
+}
+
diff --git a/locks/win32/thread_cond.c b/locks/win32/thread_cond.c
new file mode 100644
index 00000000000..d22567a88e0
--- /dev/null
+++ b/locks/win32/thread_cond.c
@@ -0,0 +1,188 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_private.h"
+#include "apr_general.h"
+#include "apr_strings.h"
+#include "apr_arch_thread_mutex.h"
+#include "apr_arch_thread_cond.h"
+#include "apr_portable.h"
+
+#include <limits.h>
+
+static apr_status_t thread_cond_cleanup(void *data)
+{
+    apr_thread_cond_t *cond = data;
+    CloseHandle(cond->semaphore);
+    DeleteCriticalSection(&cond->csection);
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_cond_create(apr_thread_cond_t **cond,
+                                                 apr_pool_t *pool)
+{
+    apr_thread_cond_t *cv;
+
+    cv = apr_pcalloc(pool, sizeof(**cond));
+    if (cv == NULL) {
+        return APR_ENOMEM;
+    }
+
+    cv->semaphore = CreateSemaphore(NULL, 0, LONG_MAX, NULL);
+    if (cv->semaphore == NULL) {
+        return apr_get_os_error();
+    }
+
+    *cond = cv;
+    cv->pool = pool;
+    InitializeCriticalSection(&cv->csection);
+    apr_pool_cleanup_register(cv->pool, cv, thread_cond_cleanup,
+                              apr_pool_cleanup_null);
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_cond_destroy(apr_thread_cond_t *cond)
+{
+    return apr_pool_cleanup_run(cond->pool, cond, thread_cond_cleanup);
+}
+
+static APR_INLINE apr_status_t thread_cond_timedwait(apr_thread_cond_t *cond,
+                                                     apr_thread_mutex_t *mutex,
+                                                     apr_interval_time_t timeout)
+{
+    DWORD res;
+    apr_status_t rv;
+    unsigned int wake = 0;
+    unsigned long generation;
+    DWORD timeout_ms = 0;
+
+    EnterCriticalSection(&cond->csection);
+    cond->num_waiting++;
+    generation = cond->generation;
+    LeaveCriticalSection(&cond->csection);
+
+    apr_thread_mutex_unlock(mutex);
+
+    do {
+        apr_interval_time_t t = timeout;
+
+        do {
+            if (t < 0) {
+                timeout_ms = INFINITE;
+            }
+            else if (t > 0) {
+                /* Given timeout is 64bit usecs whereas Windows timeouts are
+                 * 32bit msecs and below INFINITE (2^32 - 1), so we may need
+                 * multiple timed out waits...
+                 */
+                if (t > apr_time_from_msec(INFINITE - 1)) {
+                    timeout_ms = INFINITE - 1;
+                    t -= apr_time_from_msec(INFINITE - 1);
+                }
+                else {
+                    timeout_ms = (DWORD)apr_time_as_msec(t);
+                    t = 0;
+                }
+            }
+            res = WaitForSingleObject(mutex->handle, timeout_ms);
+        } while (res == WAIT_TIMEOUT && t > 0);
+
+        EnterCriticalSection(&cond->csection);
+
+        if (cond->num_wake) {
+            if (cond->generation != generation) {
+                cond->num_wake--;
+                cond->num_waiting--;
+                rv = APR_SUCCESS;
+                break;
+            } else {
+                wake = 1;
+            }
+        }
+        else if (res != WAIT_OBJECT_0) {
+            cond->num_waiting--;
+            rv = APR_TIMEUP;
+            break;
+        }
+
+        LeaveCriticalSection(&cond->csection);
+
+        if (wake) {
+            wake = 0;
+            ReleaseSemaphore(cond->semaphore, 1, NULL);
+        }
+    } while (1);
+
+    LeaveCriticalSection(&cond->csection);
+    apr_thread_mutex_lock(mutex);
+
+    return rv;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_cond_wait(apr_thread_cond_t *cond,
+                                               apr_thread_mutex_t *mutex)
+{
+    return thread_cond_timedwait(cond, mutex, (apr_interval_time_t)-1);
+}
+
+APR_DECLARE(apr_status_t) apr_thread_cond_timedwait(apr_thread_cond_t *cond,
+                                                    apr_thread_mutex_t *mutex,
+                                                    apr_interval_time_t timeout)
+{
+    return thread_cond_timedwait(cond, mutex, timeout);
+}
+
+APR_DECLARE(apr_status_t) apr_thread_cond_signal(apr_thread_cond_t *cond)
+{
+    unsigned int wake = 0;
+
+    EnterCriticalSection(&cond->csection);
+    if (cond->num_waiting > cond->num_wake) {
+        wake = 1;
+        cond->num_wake++;
+        cond->generation++;
+    }
+    LeaveCriticalSection(&cond->csection);
+
+    if (wake) {
+        ReleaseSemaphore(cond->semaphore, 1, NULL);
+    }
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_cond_broadcast(apr_thread_cond_t *cond)
+{
+    unsigned long num_wake = 0;
+
+    EnterCriticalSection(&cond->csection);
+    if (cond->num_waiting > cond->num_wake) {
+        num_wake = cond->num_waiting - cond->num_wake;
+        cond->num_wake = cond->num_waiting;
+        cond->generation++;
+    }
+    LeaveCriticalSection(&cond->csection);
+
+    if (num_wake) {
+        ReleaseSemaphore(cond->semaphore, num_wake, NULL);
+    }
+
+    return APR_SUCCESS;
+}
+
+APR_POOL_IMPLEMENT_ACCESSOR(thread_cond)
diff --git a/locks/win32/thread_mutex.c b/locks/win32/thread_mutex.c
new file mode 100644
index 00000000000..f19152495f6
--- /dev/null
+++ b/locks/win32/thread_mutex.c
@@ -0,0 +1,175 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_private.h"
+#include "apr_general.h"
+#include "apr_strings.h"
+#include "apr_arch_thread_mutex.h"
+#include "apr_thread_mutex.h"
+#include "apr_portable.h"
+#include "apr_arch_misc.h"
+
+static apr_status_t thread_mutex_cleanup(void *data)
+{
+    apr_thread_mutex_t *lock = data;
+
+    if (lock->type == thread_mutex_critical_section) {
+        lock->type = -1;
+        DeleteCriticalSection(&lock->section);
+    }
+    else {
+        if (!CloseHandle(lock->handle)) {
+            return apr_get_os_error();
+        }
+    }
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_mutex_create(apr_thread_mutex_t **mutex,
+                                                  unsigned int flags,
+                                                  apr_pool_t *pool)
+{
+    (*mutex) = (apr_thread_mutex_t *)apr_palloc(pool, sizeof(**mutex));
+
+    (*mutex)->pool = pool;
+
+    if (flags & APR_THREAD_MUTEX_UNNESTED) {
+        /* Use an auto-reset signaled event, ready to accept one
+         * waiting thread.
+         */
+        (*mutex)->type = thread_mutex_unnested_event;
+        (*mutex)->handle = CreateEvent(NULL, FALSE, TRUE, NULL);
+    }
+    else if (flags & APR_THREAD_MUTEX_TIMED) {
+        (*mutex)->type = thread_mutex_nested_mutex;
+        (*mutex)->handle = CreateMutex(NULL, FALSE, NULL);
+    }
+    else {
+#if APR_HAS_UNICODE_FS
+        /* Critical Sections are terrific, performance-wise, on NT.
+         * On Win9x, we cannot 'try' on a critical section, so we 
+         * use a [slower] mutex object, instead.
+         */
+        IF_WIN_OS_IS_UNICODE {
+            InitializeCriticalSection(&(*mutex)->section);
+            (*mutex)->type = thread_mutex_critical_section;
+            (*mutex)->handle = NULL;
+        }
+#endif
+#if APR_HAS_ANSI_FS
+        ELSE_WIN_OS_IS_ANSI {
+            (*mutex)->type = thread_mutex_nested_mutex;
+            (*mutex)->handle = CreateMutex(NULL, FALSE, NULL);
+
+        }
+#endif
+    }
+
+    apr_pool_cleanup_register((*mutex)->pool, (*mutex), thread_mutex_cleanup,
+                              apr_pool_cleanup_null);
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_mutex_lock(apr_thread_mutex_t *mutex)
+{
+    if (mutex->type == thread_mutex_critical_section) {
+        EnterCriticalSection(&mutex->section);
+    }
+    else {
+        DWORD rv = WaitForSingleObject(mutex->handle, INFINITE);
+        if ((rv != WAIT_OBJECT_0) && (rv != WAIT_ABANDONED)) {
+            return (rv == WAIT_TIMEOUT) ? APR_EBUSY : apr_get_os_error();
+        }
+    }        
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_mutex_trylock(apr_thread_mutex_t *mutex)
+{
+    if (mutex->type == thread_mutex_critical_section) {
+        if (!TryEnterCriticalSection(&mutex->section)) {
+            return APR_EBUSY;
+        }
+    }
+    else {
+        DWORD rv = WaitForSingleObject(mutex->handle, 0);
+        if ((rv != WAIT_OBJECT_0) && (rv != WAIT_ABANDONED)) {
+            return (rv == WAIT_TIMEOUT) ? APR_EBUSY : apr_get_os_error();
+        }
+    }        
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_mutex_timedlock(apr_thread_mutex_t *mutex,
+                                                 apr_interval_time_t timeout)
+{
+    if (mutex->type != thread_mutex_critical_section) {
+        DWORD rv, timeout_ms = 0;
+        apr_interval_time_t t = timeout;
+
+        do {
+            if (t > 0) {
+                /* Given timeout is 64bit usecs whereas Windows timeouts are
+                 * 32bit msecs and below INFINITE (2^32 - 1), so we may need
+                 * multiple timed out waits...
+                 */
+                if (t > apr_time_from_msec(INFINITE - 1)) {
+                    timeout_ms = INFINITE - 1;
+                    t -= apr_time_from_msec(INFINITE - 1);
+                }
+                else {
+                    timeout_ms = (DWORD)apr_time_as_msec(t);
+                    t = 0;
+                }
+            }
+            rv = WaitForSingleObject(mutex->handle, timeout_ms);
+        } while (rv == WAIT_TIMEOUT && t > 0);
+
+        if ((rv != WAIT_OBJECT_0) && (rv != WAIT_ABANDONED)) {
+            return (rv == WAIT_TIMEOUT) ? APR_TIMEUP : apr_get_os_error();
+        }
+        return APR_SUCCESS;
+    }        
+
+    return APR_ENOTIMPL;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_mutex_unlock(apr_thread_mutex_t *mutex)
+{
+    if (mutex->type == thread_mutex_critical_section) {
+        LeaveCriticalSection(&mutex->section);
+    }
+    else if (mutex->type == thread_mutex_unnested_event) {
+        if (!SetEvent(mutex->handle)) {
+            return apr_get_os_error();
+        }
+    }
+    else if (mutex->type == thread_mutex_nested_mutex) {
+        if (!ReleaseMutex(mutex->handle)) {
+            return apr_get_os_error();
+        }
+    }
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_mutex_destroy(apr_thread_mutex_t *mutex)
+{
+    return apr_pool_cleanup_run(mutex->pool, mutex, thread_mutex_cleanup);
+}
+
+APR_POOL_IMPLEMENT_ACCESSOR(thread_mutex)
+
diff --git a/locks/win32/thread_rwlock.c b/locks/win32/thread_rwlock.c
new file mode 100644
index 00000000000..fd9d579f158
--- /dev/null
+++ b/locks/win32/thread_rwlock.c
@@ -0,0 +1,165 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_private.h"
+#include "apr_general.h"
+#include "apr_strings.h"
+#include "apr_arch_thread_rwlock.h"
+#include "apr_portable.h"
+
+static apr_status_t thread_rwlock_cleanup(void *data)
+{
+    apr_thread_rwlock_t *rwlock = data;
+    
+    if (! CloseHandle(rwlock->read_event))
+        return apr_get_os_error();
+
+    if (! CloseHandle(rwlock->write_mutex))
+        return apr_get_os_error();
+    
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t)apr_thread_rwlock_create(apr_thread_rwlock_t **rwlock,
+                                                  apr_pool_t *pool)
+{
+    *rwlock = apr_palloc(pool, sizeof(**rwlock));
+
+    (*rwlock)->pool        = pool;
+    (*rwlock)->readers     = 0;
+
+    if (! ((*rwlock)->read_event = CreateEvent(NULL, TRUE, FALSE, NULL))) {
+        *rwlock = NULL;
+        return apr_get_os_error();
+    }
+
+    if (! ((*rwlock)->write_mutex = CreateMutex(NULL, FALSE, NULL))) {
+        CloseHandle((*rwlock)->read_event);
+        *rwlock = NULL;
+        return apr_get_os_error();
+    }
+
+    apr_pool_cleanup_register(pool, *rwlock, thread_rwlock_cleanup,
+                              apr_pool_cleanup_null);
+
+    return APR_SUCCESS;
+}
+
+static apr_status_t apr_thread_rwlock_rdlock_core(apr_thread_rwlock_t *rwlock,
+                                                  DWORD  milliseconds)
+{
+    DWORD   code = WaitForSingleObject(rwlock->write_mutex, milliseconds);
+
+    if (code == WAIT_FAILED || code == WAIT_TIMEOUT)
+        return APR_FROM_OS_ERROR(code);
+
+    /* We've successfully acquired the writer mutex, we can't be locked
+     * for write, so it's OK to add the reader lock.  The writer mutex
+     * doubles as race condition protection for the readers counter.   
+     */
+    InterlockedIncrement(&rwlock->readers);
+    
+    if (! ResetEvent(rwlock->read_event))
+        return apr_get_os_error();
+    
+    if (! ReleaseMutex(rwlock->write_mutex))
+        return apr_get_os_error();
+    
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_rwlock_rdlock(apr_thread_rwlock_t *rwlock)
+{
+    return apr_thread_rwlock_rdlock_core(rwlock, INFINITE);
+}
+
+APR_DECLARE(apr_status_t) 
+apr_thread_rwlock_tryrdlock(apr_thread_rwlock_t *rwlock)
+{
+    return apr_thread_rwlock_rdlock_core(rwlock, 0);
+}
+
+static apr_status_t 
+apr_thread_rwlock_wrlock_core(apr_thread_rwlock_t *rwlock, DWORD milliseconds)
+{
+    DWORD   code = WaitForSingleObject(rwlock->write_mutex, milliseconds);
+
+    if (code == WAIT_FAILED || code == WAIT_TIMEOUT)
+        return APR_FROM_OS_ERROR(code);
+
+    /* We've got the writer lock but we have to wait for all readers to
+     * unlock before it's ok to use it.
+     */
+    if (rwlock->readers) {
+        /* Must wait for readers to finish before returning, unless this
+         * is an trywrlock (milliseconds == 0):
+         */
+        code = milliseconds
+          ? WaitForSingleObject(rwlock->read_event, milliseconds)
+          : WAIT_TIMEOUT;
+        
+        if (code == WAIT_FAILED || code == WAIT_TIMEOUT) {
+            /* Unable to wait for readers to finish, release write lock: */
+            if (! ReleaseMutex(rwlock->write_mutex))
+                return apr_get_os_error();
+            
+            return APR_FROM_OS_ERROR(code);
+        }
+    }
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_rwlock_wrlock(apr_thread_rwlock_t *rwlock)
+{
+    return apr_thread_rwlock_wrlock_core(rwlock, INFINITE);
+}
+
+APR_DECLARE(apr_status_t)apr_thread_rwlock_trywrlock(apr_thread_rwlock_t *rwlock)
+{
+    return apr_thread_rwlock_wrlock_core(rwlock, 0);
+}
+
+APR_DECLARE(apr_status_t) apr_thread_rwlock_unlock(apr_thread_rwlock_t *rwlock)
+{
+    apr_status_t rv = 0;
+
+    /* First, guess that we're unlocking a writer */
+    if (! ReleaseMutex(rwlock->write_mutex))
+        rv = apr_get_os_error();
+    
+    if (rv == APR_FROM_OS_ERROR(ERROR_NOT_OWNER)) {
+        /* Nope, we must have a read lock */
+        if (rwlock->readers &&
+            ! InterlockedDecrement(&rwlock->readers) &&
+            ! SetEvent(rwlock->read_event)) {
+            rv = apr_get_os_error();
+        }
+        else {
+            rv = 0;
+        }
+    }
+
+    return rv;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_rwlock_destroy(apr_thread_rwlock_t *rwlock)
+{
+    return apr_pool_cleanup_run(rwlock->pool, rwlock, thread_rwlock_cleanup);
+}
+
+APR_POOL_IMPLEMENT_ACCESSOR(thread_rwlock)
diff --git a/memcache/apr_memcache.c b/memcache/apr_memcache.c
new file mode 100644
index 00000000000..cfaf5db92d6
--- /dev/null
+++ b/memcache/apr_memcache.c
@@ -0,0 +1,1728 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_memcache.h"
+#include "apr_poll.h"
+#include "apr_version.h"
+#include <stdlib.h>
+
+#define BUFFER_SIZE 512
+struct apr_memcache_conn_t
+{
+    char *buffer;
+    apr_size_t blen;
+    apr_pool_t *p;
+    apr_pool_t *tp;
+    apr_socket_t *sock;
+    apr_bucket_brigade *bb;
+    apr_bucket_brigade *tb;
+    apr_memcache_server_t *ms;
+};                                                          
+
+/* Strings for Client Commands */
+
+#define MC_EOL "\r\n"
+#define MC_EOL_LEN (sizeof(MC_EOL)-1)
+
+#define MC_WS " "
+#define MC_WS_LEN (sizeof(MC_WS)-1)
+
+#define MC_GET "get "
+#define MC_GET_LEN (sizeof(MC_GET)-1)
+
+#define MC_SET "set "
+#define MC_SET_LEN (sizeof(MC_SET)-1)
+
+#define MC_ADD "add "
+#define MC_ADD_LEN (sizeof(MC_ADD)-1)
+
+#define MC_REPLACE "replace "
+#define MC_REPLACE_LEN (sizeof(MC_REPLACE)-1)
+
+#define MC_DELETE "delete "
+#define MC_DELETE_LEN (sizeof(MC_DELETE)-1)
+
+#define MC_INCR "incr "
+#define MC_INCR_LEN (sizeof(MC_INCR)-1)
+
+#define MC_DECR "decr "
+#define MC_DECR_LEN (sizeof(MC_DECR)-1)
+
+#define MC_VERSION "version"
+#define MC_VERSION_LEN (sizeof(MC_VERSION)-1)
+
+#define MC_STATS "stats"
+#define MC_STATS_LEN (sizeof(MC_STATS)-1)
+
+#define MC_QUIT "quit"
+#define MC_QUIT_LEN (sizeof(MC_QUIT)-1)
+
+/* Strings for Server Replies */
+
+#define MS_STORED "STORED"
+#define MS_STORED_LEN (sizeof(MS_STORED)-1)
+
+#define MS_NOT_STORED "NOT_STORED"
+#define MS_NOT_STORED_LEN (sizeof(MS_NOT_STORED)-1)
+
+#define MS_DELETED "DELETED"
+#define MS_DELETED_LEN (sizeof(MS_DELETED)-1)
+
+#define MS_NOT_FOUND "NOT_FOUND"
+#define MS_NOT_FOUND_LEN (sizeof(MS_NOT_FOUND)-1)
+
+#define MS_VALUE "VALUE"
+#define MS_VALUE_LEN (sizeof(MS_VALUE)-1)
+
+#define MS_ERROR "ERROR"
+#define MS_ERROR_LEN (sizeof(MS_ERROR)-1)
+
+#define MS_VERSION "VERSION"
+#define MS_VERSION_LEN (sizeof(MS_VERSION)-1)
+
+#define MS_STAT "STAT"
+#define MS_STAT_LEN (sizeof(MS_STAT)-1)
+
+#define MS_END "END"
+#define MS_END_LEN (sizeof(MS_END)-1)
+
+/** Server and Query Structure for a multiple get */
+struct cache_server_query_t {
+    apr_memcache_server_t* ms;
+    apr_memcache_conn_t* conn;
+    struct iovec* query_vec;
+    apr_int32_t query_vec_count;
+};
+
+#define MULT_GET_TIMEOUT 50000
+
+static apr_status_t make_server_dead(apr_memcache_t *mc, apr_memcache_server_t *ms)
+{
+#if APR_HAS_THREADS
+    apr_thread_mutex_lock(ms->lock);
+#endif
+    ms->status = APR_MC_SERVER_DEAD;
+    ms->btime = apr_time_now();
+#if APR_HAS_THREADS
+    apr_thread_mutex_unlock(ms->lock);
+#endif
+    return APR_SUCCESS;
+}
+
+static apr_status_t make_server_live(apr_memcache_t *mc, apr_memcache_server_t *ms)
+{
+    ms->status = APR_MC_SERVER_LIVE; 
+    return APR_SUCCESS;
+}
+
+
+APR_DECLARE(apr_status_t) apr_memcache_add_server(apr_memcache_t *mc, apr_memcache_server_t *ms)
+{
+    apr_status_t rv = APR_SUCCESS;
+
+    if(mc->ntotal >= mc->nalloc) {
+        return APR_ENOMEM;
+    }
+
+    mc->live_servers[mc->ntotal] = ms;
+    mc->ntotal++;
+    make_server_live(mc, ms);
+    return rv;
+}
+
+static apr_status_t mc_version_ping(apr_memcache_server_t *ms);
+
+APR_DECLARE(apr_memcache_server_t *) 
+apr_memcache_find_server_hash(apr_memcache_t *mc, const apr_uint32_t hash)
+{
+    if (mc->server_func) {
+        return mc->server_func(mc->server_baton, mc, hash);
+    }
+    else {
+        return apr_memcache_find_server_hash_default(NULL, mc, hash);
+    }
+}   
+
+APR_DECLARE(apr_memcache_server_t *) 
+apr_memcache_find_server_hash_default(void *baton, apr_memcache_t *mc,
+                                      const apr_uint32_t hash)
+{
+    apr_memcache_server_t *ms = NULL;
+    apr_uint32_t h = hash ? hash : 1;
+    apr_uint32_t i = 0;
+    apr_time_t curtime = 0;
+   
+    if(mc->ntotal == 0) {
+        return NULL;
+    }
+
+    do {
+        ms = mc->live_servers[h % mc->ntotal];
+        if(ms->status == APR_MC_SERVER_LIVE) {
+            break;
+        }
+        else {
+            if (curtime == 0) {
+                curtime = apr_time_now();
+            }
+#if APR_HAS_THREADS
+            apr_thread_mutex_lock(ms->lock);
+#endif
+            /* Try the dead server, every 5 seconds */
+            if (curtime - ms->btime >  apr_time_from_sec(5)) {
+                ms->btime = curtime;
+                if (mc_version_ping(ms) == APR_SUCCESS) {
+                    make_server_live(mc, ms);
+#if APR_HAS_THREADS
+                    apr_thread_mutex_unlock(ms->lock);
+#endif
+                    break;
+                }
+            }
+#if APR_HAS_THREADS
+            apr_thread_mutex_unlock(ms->lock);
+#endif
+        }
+        h++;
+        i++;
+    } while(i < mc->ntotal);
+
+    if (i == mc->ntotal) {
+        ms = NULL;
+    }
+
+    return ms;
+}
+
+APR_DECLARE(apr_memcache_server_t *) apr_memcache_find_server(apr_memcache_t *mc, const char *host, apr_port_t port)
+{
+    int i;
+
+    for (i = 0; i < mc->ntotal; i++) {
+        if (strcmp(mc->live_servers[i]->host, host) == 0
+            && mc->live_servers[i]->port == port) {
+
+            return mc->live_servers[i];
+        }
+    }
+
+    return NULL;
+}
+
+static apr_status_t ms_find_conn(apr_memcache_server_t *ms, apr_memcache_conn_t **conn) 
+{
+    apr_status_t rv;
+    apr_bucket_alloc_t *balloc;
+    apr_bucket *e;
+
+#if APR_HAS_THREADS
+    rv = apr_reslist_acquire(ms->conns, (void **)conn);
+#else
+    *conn = ms->conn;
+    rv = APR_SUCCESS;
+#endif
+
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
+    balloc = apr_bucket_alloc_create((*conn)->tp);
+    (*conn)->bb = apr_brigade_create((*conn)->tp, balloc);
+    (*conn)->tb = apr_brigade_create((*conn)->tp, balloc);
+
+    e = apr_bucket_socket_create((*conn)->sock, balloc);
+    APR_BRIGADE_INSERT_TAIL((*conn)->bb, e);
+
+    return rv;
+}
+
+static apr_status_t ms_bad_conn(apr_memcache_server_t *ms, apr_memcache_conn_t *conn) 
+{
+#if APR_HAS_THREADS
+    return apr_reslist_invalidate(ms->conns, conn);
+#else
+    return APR_SUCCESS;
+#endif
+}
+
+static apr_status_t ms_release_conn(apr_memcache_server_t *ms, apr_memcache_conn_t *conn) 
+{
+    apr_pool_clear(conn->tp);
+#if APR_HAS_THREADS
+    return apr_reslist_release(ms->conns, conn);
+#else
+    return APR_SUCCESS;
+#endif
+}
+
+APR_DECLARE(apr_status_t) apr_memcache_enable_server(apr_memcache_t *mc, apr_memcache_server_t *ms)
+{
+    apr_status_t rv = APR_SUCCESS;
+
+    if (ms->status == APR_MC_SERVER_LIVE) {
+        return rv;
+    }
+
+    rv = make_server_live(mc, ms);
+    return rv;
+}
+
+APR_DECLARE(apr_status_t) apr_memcache_disable_server(apr_memcache_t *mc, apr_memcache_server_t *ms)
+{
+    return make_server_dead(mc, ms);
+}
+
+static apr_status_t conn_connect(apr_memcache_conn_t *conn)
+{
+    apr_status_t rv = APR_SUCCESS;
+    apr_sockaddr_t *sa;
+#if APR_HAVE_SOCKADDR_UN
+    apr_int32_t family = conn->ms->host[0] != '/' ? APR_INET : APR_UNIX;
+#else
+    apr_int32_t family = APR_INET;
+#endif
+
+    rv = apr_sockaddr_info_get(&sa, conn->ms->host, family, conn->ms->port, 0, conn->p);
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
+    rv = apr_socket_timeout_set(conn->sock, 1 * APR_USEC_PER_SEC);
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
+    rv = apr_socket_connect(conn->sock, sa);
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
+    rv = apr_socket_timeout_set(conn->sock, -1);
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
+    return rv;
+}
+
+
+static apr_status_t
+mc_conn_construct(void **conn_, void *params, apr_pool_t *pool)
+{
+    apr_status_t rv = APR_SUCCESS;
+    apr_memcache_conn_t *conn;
+    apr_pool_t *np;
+    apr_pool_t *tp;
+    apr_memcache_server_t *ms = params;
+#if APR_HAVE_SOCKADDR_UN
+    apr_int32_t family = ms->host[0] != '/' ? APR_INET : APR_UNIX;
+#else
+    apr_int32_t family = APR_INET;
+#endif
+
+    rv = apr_pool_create(&np, pool);
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
+    rv = apr_pool_create(&tp, np);
+    if (rv != APR_SUCCESS) {
+        apr_pool_destroy(np);
+        return rv;
+    }
+
+    conn = apr_palloc(np, sizeof( apr_memcache_conn_t ));
+
+    conn->p = np;
+    conn->tp = tp;
+
+    rv = apr_socket_create(&conn->sock, family, SOCK_STREAM, 0, np);
+
+    if (rv != APR_SUCCESS) {
+        apr_pool_destroy(np);
+        return rv;
+    }
+
+    conn->buffer = apr_palloc(conn->p, BUFFER_SIZE + 1);
+    conn->blen = 0;
+    conn->ms = ms;
+
+    rv = conn_connect(conn);
+    if (rv != APR_SUCCESS) {
+        apr_pool_destroy(np);
+    }
+    else {
+        *conn_ = conn;
+    }
+    
+    return rv;
+}
+
+#if APR_HAS_THREADS
+static apr_status_t
+mc_conn_destruct(void *conn_, void *params, apr_pool_t *pool)
+{
+    apr_memcache_conn_t *conn = (apr_memcache_conn_t*)conn_;
+    struct iovec vec[2];
+    apr_size_t written;
+    
+    /* send a quit message to the memcached server to be nice about it. */
+    vec[0].iov_base = MC_QUIT;
+    vec[0].iov_len = MC_QUIT_LEN;
+
+    vec[1].iov_base = MC_EOL;
+    vec[1].iov_len = MC_EOL_LEN;
+    
+    /* Return values not checked, since we just want to make it go away. */
+    apr_socket_sendv(conn->sock, vec, 2, &written);
+    apr_socket_close(conn->sock);
+
+    apr_pool_destroy(conn->p);
+    
+    return APR_SUCCESS;
+}
+#endif
+
+APR_DECLARE(apr_status_t) apr_memcache_server_create(apr_pool_t *p, 
+                                                     const char *host, apr_port_t port, 
+                                                     apr_uint32_t min, apr_uint32_t smax,
+                                                     apr_uint32_t max, apr_uint32_t ttl,
+                                                     apr_memcache_server_t **ms)
+{
+    apr_status_t rv = APR_SUCCESS;
+    apr_memcache_server_t *server;
+    apr_pool_t *np;
+
+    rv = apr_pool_create(&np, p);
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
+    server = apr_palloc(np, sizeof(apr_memcache_server_t));
+
+    server->p = np;
+    server->host = apr_pstrdup(np, host);
+    server->port = port;
+    server->status = APR_MC_SERVER_DEAD;
+#if APR_HAS_THREADS
+    rv = apr_thread_mutex_create(&server->lock, APR_THREAD_MUTEX_DEFAULT, np);
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
+    rv = apr_reslist_create(&server->conns, 
+                               min,                     /* hard minimum */
+                               smax,                    /* soft maximum */
+                               max,                     /* hard maximum */
+                               ttl,                     /* Time to live */
+                               mc_conn_construct,       /* Make a New Connection */
+                               mc_conn_destruct,        /* Kill Old Connection */
+                               server, np);
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
+    apr_reslist_cleanup_order_set(server->conns, APR_RESLIST_CLEANUP_FIRST);
+#else
+    rv = mc_conn_construct((void**)&(server->conn), server, np);
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+#endif
+
+    *ms = server;
+
+    return rv;
+}
+
+APR_DECLARE(apr_status_t) apr_memcache_create(apr_pool_t *p,
+                                              apr_uint16_t max_servers, apr_uint32_t flags,
+                                              apr_memcache_t **memcache) 
+{
+    apr_status_t rv = APR_SUCCESS;
+    apr_memcache_t *mc;
+    
+    mc = apr_palloc(p, sizeof(apr_memcache_t));
+    mc->p = p;
+    mc->nalloc = max_servers;
+    mc->ntotal = 0;
+    mc->live_servers = apr_palloc(p, mc->nalloc * sizeof(struct apr_memcache_server_t *));
+    mc->hash_func = NULL;
+    mc->hash_baton = NULL;
+    mc->server_func = NULL;
+    mc->server_baton = NULL;
+    *memcache = mc;
+    return rv;
+}
+
+
+/* The crc32 functions and data was originally written by Spencer
+ * Garrett <srg@quick.com> and was gleaned from the PostgreSQL source
+ * tree via the files contrib/ltree/crc32.[ch] and from FreeBSD at
+ * src/usr.bin/cksum/crc32.c.
+ */ 
+
+static const apr_uint32_t crc32tab[256] = {
+  0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
+  0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+  0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+  0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+  0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+  0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+  0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+  0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+  0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+  0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+  0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
+  0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+  0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
+  0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+  0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+  0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+  0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
+  0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+  0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
+  0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+  0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+  0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+  0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
+  0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+  0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+  0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+  0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+  0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+  0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
+  0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+  0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
+  0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+  0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+  0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+  0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+  0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+  0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
+  0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+  0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+  0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+  0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
+  0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+  0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
+  0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+  0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+  0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+  0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
+  0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+  0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+  0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+  0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+  0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+  0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
+  0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+  0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+  0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+  0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+  0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+  0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
+  0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+  0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
+  0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+  0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+  0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
+};
+
+APR_DECLARE(apr_uint32_t) apr_memcache_hash_crc32(void *baton, 
+                                                  const char *data,
+                                                  const apr_size_t data_len)
+{
+    apr_uint32_t i;
+    apr_uint32_t crc;
+    crc = ~0;
+    
+    for (i = 0; i < data_len; i++)
+        crc = (crc >> 8) ^ crc32tab[(crc ^ (data[i])) & 0xff];
+    
+    return ~crc;
+}
+
+APR_DECLARE(apr_uint32_t) apr_memcache_hash_default(void *baton, 
+                                                    const char *data,
+                                                    const apr_size_t data_len)
+{
+    /* The default Perl Client doesn't actually use just crc32 -- it shifts it again
+     * like this....
+     */
+    return ((apr_memcache_hash_crc32(baton, data, data_len) >> 16) & 0x7fff);
+}
+
+APR_DECLARE(apr_uint32_t) apr_memcache_hash(apr_memcache_t *mc,
+                                            const char *data,
+                                            const apr_size_t data_len)
+{
+    if (mc->hash_func) {
+        return mc->hash_func(mc->hash_baton, data, data_len);
+    }
+    else {
+        return apr_memcache_hash_default(NULL, data, data_len);
+    }
+}
+
+static apr_status_t get_server_line(apr_memcache_conn_t *conn)
+{
+    apr_size_t bsize = BUFFER_SIZE;
+    apr_status_t rv = APR_SUCCESS;
+
+    rv = apr_brigade_split_line(conn->tb, conn->bb, APR_BLOCK_READ, BUFFER_SIZE);
+
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
+    rv = apr_brigade_flatten(conn->tb, conn->buffer, &bsize);
+
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
+    conn->blen = bsize;
+    conn->buffer[bsize] = '\0';
+
+    return apr_brigade_cleanup(conn->tb);
+}
+
+static apr_status_t storage_cmd_write(apr_memcache_t *mc,
+                                      char *cmd,
+                                      const apr_size_t cmd_size,
+                                      const char *key,
+                                      char *data,
+                                      const apr_size_t data_size,
+                                      apr_uint32_t timeout,
+                                      apr_uint16_t flags)
+{
+    apr_uint32_t hash;
+    apr_memcache_server_t *ms;
+    apr_memcache_conn_t *conn;
+    apr_status_t rv;
+    apr_size_t written;
+    struct iovec vec[5];
+    apr_size_t klen;
+
+    apr_size_t key_size = strlen(key);
+
+    hash = apr_memcache_hash(mc, key, key_size);
+
+    ms = apr_memcache_find_server_hash(mc, hash);
+
+    if (ms == NULL)
+        return APR_NOTFOUND;
+
+    rv = ms_find_conn(ms, &conn);
+
+    if (rv != APR_SUCCESS) {
+        apr_memcache_disable_server(mc, ms);
+        return rv;
+    }
+
+    /* <command name> <key> <flags> <exptime> <bytes>\r\n<data>\r\n */
+
+    vec[0].iov_base = cmd;
+    vec[0].iov_len  = cmd_size;
+
+    vec[1].iov_base = (void*)key;
+    vec[1].iov_len  = key_size;
+
+    klen = apr_snprintf(conn->buffer, BUFFER_SIZE, " %u %u %" APR_SIZE_T_FMT " " MC_EOL,
+                        flags, timeout, data_size);
+
+    vec[2].iov_base = conn->buffer;
+    vec[2].iov_len  = klen;
+
+    vec[3].iov_base = data;
+    vec[3].iov_len  = data_size;
+
+    vec[4].iov_base = MC_EOL;
+    vec[4].iov_len  = MC_EOL_LEN;
+
+    rv = apr_socket_sendv(conn->sock, vec, 5, &written);
+
+    if (rv != APR_SUCCESS) {
+        ms_bad_conn(ms, conn);
+        apr_memcache_disable_server(mc, ms);
+        return rv;
+    }
+
+    rv = get_server_line(conn);
+
+    if (rv != APR_SUCCESS) {
+        ms_bad_conn(ms, conn);
+        apr_memcache_disable_server(mc, ms);
+        return rv;
+    }
+
+    if (strcmp(conn->buffer, MS_STORED MC_EOL) == 0) {
+        rv = APR_SUCCESS;
+    }
+    else if (strcmp(conn->buffer, MS_NOT_STORED MC_EOL) == 0) {
+        rv = APR_EEXIST;
+    }
+    else {
+        rv = APR_EGENERAL;
+    }
+
+    ms_release_conn(ms, conn);
+
+    return rv;
+}
+
+APR_DECLARE(apr_status_t)
+apr_memcache_set(apr_memcache_t *mc,
+                 const char *key,
+                 char *data,
+                 const apr_size_t data_size,
+                 apr_uint32_t timeout,
+                 apr_uint16_t flags)
+{
+    return storage_cmd_write(mc,
+                           MC_SET, MC_SET_LEN,
+                           key,
+                           data, data_size,
+                           timeout, flags);
+}
+
+APR_DECLARE(apr_status_t)
+apr_memcache_add(apr_memcache_t *mc,
+                 const char *key,
+                 char *data,
+                 const apr_size_t data_size,
+                 apr_uint32_t timeout,
+                 apr_uint16_t flags)
+{
+    return storage_cmd_write(mc, 
+                           MC_ADD, MC_ADD_LEN,
+                           key,
+                           data, data_size,
+                           timeout, flags);
+}
+
+APR_DECLARE(apr_status_t)
+apr_memcache_replace(apr_memcache_t *mc,
+                 const char *key,
+                 char *data,
+                 const apr_size_t data_size,
+                 apr_uint32_t timeout,
+                 apr_uint16_t flags)
+{
+    return storage_cmd_write(mc,
+                           MC_REPLACE, MC_REPLACE_LEN,
+                           key,
+                           data, data_size,
+                           timeout, flags);
+
+}
+
+/*
+ * Parses a decimal size from size_str, returning the value in *size.
+ * Returns 1 if parsing was successful, 0 if parsing failed.
+ */
+static int parse_size(const char *size_str, apr_size_t *size)
+{
+    char *endptr;
+    long size_as_long;
+
+    errno = 0;
+    size_as_long = strtol(size_str, &endptr, 10);
+    if ((size_as_long < 0) || (errno != 0) || (endptr == size_str) ||
+        (endptr[0] != ' ' && (endptr[0] != '\r' || endptr[1] != '\n'))) {
+        return 0;
+    }
+
+    *size = (unsigned long)size_as_long;
+    return 1;
+}
+
+APR_DECLARE(apr_status_t)
+apr_memcache_getp(apr_memcache_t *mc,
+                  apr_pool_t *p,
+                  const char *key,
+                  char **baton,
+                  apr_size_t *new_length,
+                  apr_uint16_t *flags_)
+{
+    apr_status_t rv;
+    apr_memcache_server_t *ms;
+    apr_memcache_conn_t *conn;
+    apr_uint32_t hash;
+    apr_size_t written;
+    apr_size_t klen = strlen(key);
+    struct iovec vec[3];
+
+    hash = apr_memcache_hash(mc, key, klen);
+    ms = apr_memcache_find_server_hash(mc, hash);
+    if (ms == NULL)
+        return APR_NOTFOUND;
+    
+    rv = ms_find_conn(ms, &conn);
+
+    if (rv != APR_SUCCESS) {
+        apr_memcache_disable_server(mc, ms);
+        return rv;
+    }
+
+    /* get <key>[ <key>[...]]\r\n */
+    vec[0].iov_base = MC_GET;
+    vec[0].iov_len  = MC_GET_LEN;
+
+    vec[1].iov_base = (void*)key;
+    vec[1].iov_len  = klen;
+
+    vec[2].iov_base = MC_EOL;
+    vec[2].iov_len  = MC_EOL_LEN;
+
+    rv = apr_socket_sendv(conn->sock, vec, 3, &written);
+
+    if (rv != APR_SUCCESS) {
+        ms_bad_conn(ms, conn);
+        apr_memcache_disable_server(mc, ms);
+        return rv;
+    }
+
+    rv = get_server_line(conn);
+    if (rv != APR_SUCCESS) {
+        ms_bad_conn(ms, conn);
+        apr_memcache_disable_server(mc, ms);
+        return rv;
+    }
+
+    if (strncmp(MS_VALUE, conn->buffer, MS_VALUE_LEN) == 0) {
+        char *flags;
+        char *length;
+        char *last;
+        apr_size_t len = 0;
+
+        apr_strtok(conn->buffer, " ", &last);
+        apr_strtok(NULL, " ", &last);
+        flags = apr_strtok(NULL, " ", &last);
+
+        if (flags_) {
+            *flags_ = atoi(flags);
+        }
+
+        length = apr_strtok(NULL, " ", &last);
+        if (!length || !parse_size(length, &len)) {
+            ms_bad_conn(ms, conn);
+            apr_memcache_disable_server(mc, ms);
+            return APR_EGENERAL;
+        }
+        else {
+            apr_bucket_brigade *bbb;
+            apr_bucket *e;
+
+            /* eat the trailing \r\n */
+            rv = apr_brigade_partition(conn->bb, len+2, &e);
+            if (rv != APR_SUCCESS) {
+                ms_bad_conn(ms, conn);
+                apr_memcache_disable_server(mc, ms);
+                return rv;
+            }
+            
+            bbb = apr_brigade_split(conn->bb, e);
+
+            rv = apr_brigade_pflatten(conn->bb, baton, &len, p);
+            if (rv != APR_SUCCESS) {
+                ms_bad_conn(ms, conn);
+                return rv;
+            }
+
+            rv = apr_brigade_destroy(conn->bb);
+            if (rv != APR_SUCCESS) {
+                ms_bad_conn(ms, conn);
+                return rv;
+            }
+
+            conn->bb = bbb;
+
+            *new_length = len - 2;
+            (*baton)[*new_length] = '\0';
+        }
+        
+        rv = get_server_line(conn);
+        if (rv != APR_SUCCESS) {
+            ms_bad_conn(ms, conn);
+            apr_memcache_disable_server(mc, ms);
+            return rv;
+        }
+
+        if (strncmp(MS_END, conn->buffer, MS_END_LEN) != 0) {
+            ms_bad_conn(ms, conn);
+            apr_memcache_disable_server(mc, ms);
+            return APR_EGENERAL;
+        }
+    }
+    else if (strncmp(MS_END, conn->buffer, MS_END_LEN) == 0) {
+        rv = APR_NOTFOUND;
+    }
+    else {
+        ms_bad_conn(ms, conn);
+        apr_memcache_disable_server(mc, ms);
+        return APR_EGENERAL;
+    }
+
+    ms_release_conn(ms, conn);
+
+    return rv;
+}
+
+APR_DECLARE(apr_status_t)
+apr_memcache_delete(apr_memcache_t *mc,
+                    const char *key,
+                    apr_uint32_t timeout)
+{
+    apr_status_t rv;
+    apr_memcache_server_t *ms;
+    apr_memcache_conn_t *conn;
+    apr_uint32_t hash;
+    apr_size_t written;
+    struct iovec vec[3];
+    apr_size_t klen = strlen(key);
+
+    hash = apr_memcache_hash(mc, key, klen);
+    ms = apr_memcache_find_server_hash(mc, hash);
+    if (ms == NULL)
+        return APR_NOTFOUND;
+    
+    rv = ms_find_conn(ms, &conn);
+
+    if (rv != APR_SUCCESS) {
+        apr_memcache_disable_server(mc, ms);
+        return rv;
+    }
+
+    /* delete <key> <time>\r\n */
+    vec[0].iov_base = MC_DELETE;
+    vec[0].iov_len  = MC_DELETE_LEN;
+
+    vec[1].iov_base = (void*)key;
+    vec[1].iov_len  = klen;
+
+    klen = apr_snprintf(conn->buffer, BUFFER_SIZE, " %u" MC_EOL, timeout);
+
+    vec[2].iov_base = conn->buffer;
+    vec[2].iov_len  = klen;
+
+    rv = apr_socket_sendv(conn->sock, vec, 3, &written);
+
+    if (rv != APR_SUCCESS) {
+        ms_bad_conn(ms, conn);
+        apr_memcache_disable_server(mc, ms);
+        return rv;
+    }
+
+    rv = get_server_line(conn);
+    if (rv != APR_SUCCESS) {
+        ms_bad_conn(ms, conn);
+        apr_memcache_disable_server(mc, ms);
+        return rv;
+    }
+
+    if (strncmp(MS_DELETED, conn->buffer, MS_DELETED_LEN) == 0) {
+        rv = APR_SUCCESS;
+    }
+    else if (strncmp(MS_NOT_FOUND, conn->buffer, MS_NOT_FOUND_LEN) == 0) {
+        rv = APR_NOTFOUND;
+    }
+    else {
+        rv = APR_EGENERAL;
+    }
+
+    ms_release_conn(ms, conn);
+
+    return rv;
+}
+
+static apr_status_t num_cmd_write(apr_memcache_t *mc,
+                                      char *cmd,
+                                      const apr_uint32_t cmd_size,
+                                      const char *key,
+                                      const apr_int32_t inc,
+                                      apr_uint32_t *new_value)
+{
+    apr_status_t rv;
+    apr_memcache_server_t *ms;
+    apr_memcache_conn_t *conn;
+    apr_uint32_t hash;
+    apr_size_t written;
+    struct iovec vec[3];
+    apr_size_t klen = strlen(key);
+
+    hash = apr_memcache_hash(mc, key, klen);
+    ms = apr_memcache_find_server_hash(mc, hash);
+    if (ms == NULL)
+        return APR_NOTFOUND;
+    
+    rv = ms_find_conn(ms, &conn);
+
+    if (rv != APR_SUCCESS) {
+        apr_memcache_disable_server(mc, ms);
+        return rv;
+    }
+
+    /* <cmd> <key> <value>\r\n */
+    vec[0].iov_base = cmd;
+    vec[0].iov_len  = cmd_size;
+
+    vec[1].iov_base = (void*)key;
+    vec[1].iov_len  = klen;
+
+    klen = apr_snprintf(conn->buffer, BUFFER_SIZE, " %u" MC_EOL, inc);
+
+    vec[2].iov_base = conn->buffer;
+    vec[2].iov_len  = klen;
+
+    rv = apr_socket_sendv(conn->sock, vec, 3, &written);
+
+    if (rv != APR_SUCCESS) {
+        ms_bad_conn(ms, conn);
+        apr_memcache_disable_server(mc, ms);
+        return rv;
+    }
+
+    rv = get_server_line(conn);
+    if (rv != APR_SUCCESS) {
+        ms_bad_conn(ms, conn);
+        apr_memcache_disable_server(mc, ms);
+        return rv;
+    }
+
+    if (strncmp(MS_ERROR, conn->buffer, MS_ERROR_LEN) == 0) {
+        rv = APR_EGENERAL;
+    }
+    else if (strncmp(MS_NOT_FOUND, conn->buffer, MS_NOT_FOUND_LEN) == 0) {
+        rv = APR_NOTFOUND;
+    }
+    else {
+        if (new_value) {
+            *new_value = atoi(conn->buffer);
+        }
+        rv = APR_SUCCESS;
+    }
+
+    ms_release_conn(ms, conn);
+
+    return rv;
+}
+
+APR_DECLARE(apr_status_t)
+apr_memcache_incr(apr_memcache_t *mc,
+                    const char *key,
+                    apr_int32_t inc,
+                    apr_uint32_t *new_value)
+{
+    return num_cmd_write(mc,
+                         MC_INCR,
+                         MC_INCR_LEN,
+                         key,
+                         inc, 
+                         new_value);
+}
+
+
+APR_DECLARE(apr_status_t)
+apr_memcache_decr(apr_memcache_t *mc,
+                    const char *key,
+                    apr_int32_t inc,
+                    apr_uint32_t *new_value)
+{
+    return num_cmd_write(mc,
+                         MC_DECR,
+                         MC_DECR_LEN,
+                         key,
+                         inc, 
+                         new_value);
+}
+
+
+
+APR_DECLARE(apr_status_t)
+apr_memcache_version(apr_memcache_server_t *ms,
+                  apr_pool_t *p,
+                  char **baton)
+{
+    apr_status_t rv;
+    apr_memcache_conn_t *conn;
+    apr_size_t written;
+    struct iovec vec[2];
+
+    rv = ms_find_conn(ms, &conn);
+
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
+    /* version\r\n */
+    vec[0].iov_base = MC_VERSION;
+    vec[0].iov_len  = MC_VERSION_LEN;
+
+    vec[1].iov_base = MC_EOL;
+    vec[1].iov_len  = MC_EOL_LEN;
+
+    rv = apr_socket_sendv(conn->sock, vec, 2, &written);
+
+    if (rv != APR_SUCCESS) {
+        ms_bad_conn(ms, conn);
+        return rv;
+    }
+
+    rv = get_server_line(conn);
+    if (rv != APR_SUCCESS) {
+        ms_bad_conn(ms, conn);
+        return rv;
+    }
+
+    if (strncmp(MS_VERSION, conn->buffer, MS_VERSION_LEN) == 0) {
+        *baton = apr_pstrmemdup(p, conn->buffer+MS_VERSION_LEN+1, 
+                                conn->blen - MS_VERSION_LEN - 2);
+        rv = APR_SUCCESS;
+    }
+    else {
+        rv = APR_EGENERAL;
+    }
+
+    ms_release_conn(ms, conn);
+
+    return rv;
+}
+
+apr_status_t mc_version_ping(apr_memcache_server_t *ms)
+{
+    apr_status_t rv;
+    apr_size_t written;
+    struct iovec vec[2];
+    apr_memcache_conn_t *conn;
+
+    rv = ms_find_conn(ms, &conn);
+
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
+    /* version\r\n */
+    vec[0].iov_base = MC_VERSION;
+    vec[0].iov_len  = MC_VERSION_LEN;
+
+    vec[1].iov_base = MC_EOL;
+    vec[1].iov_len  = MC_EOL_LEN;
+
+    rv = apr_socket_sendv(conn->sock, vec, 2, &written);
+
+    if (rv != APR_SUCCESS) {
+        ms_bad_conn(ms, conn);
+        return rv;
+    }
+
+    rv = get_server_line(conn);
+    ms_release_conn(ms, conn);
+    return rv;
+}
+
+
+APR_DECLARE(void) 
+apr_memcache_add_multget_key(apr_pool_t *data_pool,
+                             const char* key,
+                             apr_hash_t **values)
+{
+    apr_memcache_value_t* value;
+    apr_size_t klen = strlen(key);
+
+    /* create the value hash if need be */
+    if (!*values) {
+        *values = apr_hash_make(data_pool);
+    }
+
+    /* init key and add it to the value hash */
+    value = apr_pcalloc(data_pool, sizeof(apr_memcache_value_t));
+
+    value->status = APR_NOTFOUND;
+    value->key = apr_pstrdup(data_pool, key);
+
+    apr_hash_set(*values, value->key, klen, value);
+}
+
+static void mget_conn_result(int serverup,
+                             int connup,
+                             apr_status_t rv,
+                             apr_memcache_t *mc,
+                             apr_memcache_server_t *ms,
+                             apr_memcache_conn_t *conn,
+                             struct cache_server_query_t *server_query,
+                             apr_hash_t *values,
+                             apr_hash_t *server_queries)
+{
+    apr_int32_t j;
+    apr_memcache_value_t* value;
+    
+    apr_hash_set(server_queries, &ms, sizeof(ms), NULL);
+
+    if (connup) {
+        ms_release_conn(ms, conn);
+    } else {
+        ms_bad_conn(ms, conn);
+
+        if (!serverup) {
+            apr_memcache_disable_server(mc, ms);
+        }
+    }
+    
+    for (j = 1; j < server_query->query_vec_count ; j+=2) {
+        if (server_query->query_vec[j].iov_base) {
+            value = apr_hash_get(values, server_query->query_vec[j].iov_base,
+                                 strlen(server_query->query_vec[j].iov_base));
+            
+            if (value->status == APR_NOTFOUND) {
+                value->status = rv;
+            }
+        }
+    }
+}
+
+APR_DECLARE(apr_status_t)
+apr_memcache_multgetp(apr_memcache_t *mc,
+                      apr_pool_t *temp_pool,
+                      apr_pool_t *data_pool,
+                      apr_hash_t *values)
+{
+    apr_status_t rv;
+    apr_memcache_server_t* ms;
+    apr_memcache_conn_t* conn;
+    apr_uint32_t hash;
+    apr_size_t written;
+    apr_size_t klen;
+
+    apr_memcache_value_t* value;
+    apr_hash_index_t* value_hash_index;
+
+    /* this is a little over aggresive, but beats multiple loops
+     * to figure out how long each vector needs to be per-server.
+     */
+    apr_int32_t veclen = 2 + 2 * apr_hash_count(values) - 1; /* get <key>[<space><key>...]\r\n */
+    apr_int32_t i, j;
+    apr_int32_t queries_sent;
+    apr_int32_t queries_recvd;
+
+    apr_hash_t * server_queries = apr_hash_make(temp_pool);
+    struct cache_server_query_t* server_query;
+    apr_hash_index_t * query_hash_index;
+
+    apr_pollset_t* pollset;
+    const apr_pollfd_t* activefds;
+    apr_pollfd_t* pollfds;
+
+
+    /* build all the queries */
+    value_hash_index = apr_hash_first(temp_pool, values);
+    while (value_hash_index) {
+        void *v;
+        apr_hash_this(value_hash_index, NULL, NULL, &v);
+        value = v;
+        value_hash_index = apr_hash_next(value_hash_index);
+        klen = strlen(value->key);
+
+        hash = apr_memcache_hash(mc, value->key, klen);
+        ms = apr_memcache_find_server_hash(mc, hash);
+        if (ms == NULL) {
+            continue;
+        }
+
+        server_query = apr_hash_get(server_queries, &ms, sizeof(ms));
+
+        if (!server_query) {
+            rv = ms_find_conn(ms, &conn);
+
+            if (rv != APR_SUCCESS) {
+                apr_memcache_disable_server(mc, ms);
+                value->status = rv;
+                continue;
+            }
+
+            server_query = apr_pcalloc(temp_pool,sizeof(struct cache_server_query_t));
+
+            apr_hash_set(server_queries, &ms, sizeof(ms), server_query);
+
+            server_query->ms = ms;
+            server_query->conn = conn;
+            server_query->query_vec = apr_pcalloc(temp_pool, sizeof(struct iovec)*veclen);
+
+            /* set up the first key */
+            server_query->query_vec[0].iov_base = MC_GET;
+            server_query->query_vec[0].iov_len  = MC_GET_LEN;
+
+            server_query->query_vec[1].iov_base = (void*)(value->key);
+            server_query->query_vec[1].iov_len  = klen;
+
+            server_query->query_vec[2].iov_base = MC_EOL;
+            server_query->query_vec[2].iov_len  = MC_EOL_LEN;
+
+            server_query->query_vec_count = 3;
+        }
+        else {
+            j = server_query->query_vec_count - 1;
+
+            server_query->query_vec[j].iov_base = MC_WS;
+            server_query->query_vec[j].iov_len  = MC_WS_LEN;
+            j++;
+
+            server_query->query_vec[j].iov_base = (void*)(value->key);
+            server_query->query_vec[j].iov_len  = klen;
+            j++;
+
+            server_query->query_vec[j].iov_base = MC_EOL;
+            server_query->query_vec[j].iov_len  = MC_EOL_LEN;
+            j++;
+
+           server_query->query_vec_count = j;
+        }
+    }
+
+    /* create polling structures */
+    pollfds = apr_pcalloc(temp_pool, apr_hash_count(server_queries) * sizeof(apr_pollfd_t));
+    
+    rv = apr_pollset_create(&pollset, apr_hash_count(server_queries), temp_pool,
+                            APR_POLLSET_NOCOPY);
+
+    if (rv != APR_SUCCESS) {
+        query_hash_index = apr_hash_first(temp_pool, server_queries);
+
+        while (query_hash_index) {
+            void *v;
+            apr_hash_this(query_hash_index, NULL, NULL, &v);
+            server_query = v;
+            query_hash_index = apr_hash_next(query_hash_index);
+
+            mget_conn_result(TRUE, TRUE, rv, mc, server_query->ms, server_query->conn,
+                             server_query, values, server_queries);
+        }
+
+        return rv;
+    }
+
+    /* send all the queries */
+    queries_sent = 0;
+    query_hash_index = apr_hash_first(temp_pool, server_queries);
+
+    while (query_hash_index) {
+        void *v;
+        apr_hash_this(query_hash_index, NULL, NULL, &v);
+        server_query = v;
+        query_hash_index = apr_hash_next(query_hash_index);
+
+        conn = server_query->conn;
+        ms = server_query->ms;
+
+        for (i = 0, rv = APR_SUCCESS; i < veclen && rv == APR_SUCCESS; i += APR_MAX_IOVEC_SIZE) {
+            rv = apr_socket_sendv(conn->sock, &(server_query->query_vec[i]),
+                                  veclen-i>APR_MAX_IOVEC_SIZE ? APR_MAX_IOVEC_SIZE : veclen-i , &written);
+        }
+
+        if (rv != APR_SUCCESS) {
+            mget_conn_result(FALSE, FALSE, rv, mc, ms, conn,
+                             server_query, values, server_queries);
+            continue;
+        }
+
+        pollfds[queries_sent].desc_type = APR_POLL_SOCKET;
+        pollfds[queries_sent].reqevents = APR_POLLIN;
+        pollfds[queries_sent].p = temp_pool;
+        pollfds[queries_sent].desc.s = conn->sock;
+        pollfds[queries_sent].client_data = (void *)server_query;
+        apr_pollset_add (pollset, &pollfds[queries_sent]);
+
+        queries_sent++;
+    }
+
+    while (queries_sent) {
+        rv = apr_pollset_poll(pollset, MULT_GET_TIMEOUT, &queries_recvd, &activefds);
+
+        if (rv != APR_SUCCESS) {
+            /* timeout */
+            queries_sent = 0;
+            continue;
+        }
+        for (i = 0; i < queries_recvd; i++) {
+            server_query = activefds[i].client_data;
+            conn = server_query->conn;
+            ms = server_query->ms;
+
+           rv = get_server_line(conn);
+
+           if (rv != APR_SUCCESS) {
+               apr_pollset_remove (pollset, &activefds[i]);
+               mget_conn_result(FALSE, FALSE, rv, mc, ms, conn,
+                                server_query, values, server_queries);
+               queries_sent--;
+               continue;
+           }
+
+           if (strncmp(MS_VALUE, conn->buffer, MS_VALUE_LEN) == 0) {
+               char *key;
+               char *flags;
+               char *length;
+               char *last;
+               char *data;
+               apr_size_t len = 0;
+               apr_bucket *e = NULL;
+
+               apr_strtok(conn->buffer, " ", &last); /* just the VALUE, ignore */
+               key = apr_strtok(NULL, " ", &last);
+               flags = apr_strtok(NULL, " ", &last);
+               length = apr_strtok(NULL, " ", &last);
+
+               if (!length || !parse_size(length, &len)) {
+                   rv = APR_EGENERAL;
+               }
+               else {
+                   /* eat the trailing \r\n */
+                   rv = apr_brigade_partition(conn->bb, len+2, &e);
+               }
+               if (rv != APR_SUCCESS) {
+                   apr_pollset_remove (pollset, &activefds[i]);
+                   mget_conn_result(TRUE, FALSE, rv, mc, ms, conn,
+                                    server_query, values, server_queries);
+                   queries_sent--;
+                   continue;
+               }
+
+               value = apr_hash_get(values, key, strlen(key));
+               if (value) {
+                   apr_bucket_brigade *bbb;
+
+                   bbb = apr_brigade_split(conn->bb, e);
+
+                   rv = apr_brigade_pflatten(conn->bb, &data, &len, data_pool);
+                   if (rv != APR_SUCCESS) {
+                       apr_pollset_remove (pollset, &activefds[i]);
+                       mget_conn_result(TRUE, FALSE, rv, mc, ms, conn,
+                                        server_query, values, server_queries);
+                       queries_sent--;
+                       continue;
+                   }
+
+                   rv = apr_brigade_destroy(conn->bb);
+                   if (rv != APR_SUCCESS) {
+                       apr_pollset_remove (pollset, &activefds[i]);
+                       mget_conn_result(TRUE, FALSE, rv, mc, ms, conn,
+                                        server_query, values, server_queries);
+                       queries_sent--;
+                       continue;
+                   }
+
+                   conn->bb = bbb;
+
+                   value->len = len - 2;
+                   data[value->len] = '\0';
+                   value->data = data;
+
+                   value->status = rv;
+                   value->flags = atoi(flags);
+
+                   /* stay on the server */
+                   i--;
+               }
+               else {
+                   /* Server Sent back a key I didn't ask for or my
+                    * hash is corrupt */
+                   rv = APR_EGENERAL;
+               }
+           }
+           else if (strncmp(MS_END, conn->buffer, MS_END_LEN) == 0) {
+               /* this connection is done */
+               apr_pollset_remove (pollset, &activefds[i]);
+               ms_release_conn(ms, conn);
+               apr_hash_set(server_queries, &ms, sizeof(ms), NULL);
+               queries_sent--;
+           }
+           else {
+               /* unknown reply? */
+               rv = APR_EGENERAL;
+           }
+           if (rv != APR_SUCCESS) {
+               apr_pollset_remove (pollset, &activefds[i]);
+               mget_conn_result(TRUE, FALSE, rv, mc, ms, conn,
+                                server_query, values, server_queries);
+               queries_sent--;
+           }
+        } /* /for */
+    } /* /while */
+    
+    query_hash_index = apr_hash_first(temp_pool, server_queries);
+    while (query_hash_index) {
+        void *v;
+        apr_hash_this(query_hash_index, NULL, NULL, &v);
+        server_query = v;
+        query_hash_index = apr_hash_next(query_hash_index);
+        
+        conn = server_query->conn;
+        ms = server_query->ms;
+        
+        mget_conn_result(TRUE, (rv == APR_SUCCESS), rv, mc, ms, conn,
+                         server_query, values, server_queries);
+        continue;
+    }
+    
+    apr_pollset_destroy(pollset);
+    apr_pool_clear(temp_pool);
+    return APR_SUCCESS;
+    
+}
+
+
+
+/**
+ * Define all of the strings for stats
+ */
+
+#define STAT_pid MS_STAT " pid "
+#define STAT_pid_LEN (sizeof(STAT_pid)-1)
+
+#define STAT_uptime MS_STAT " uptime "
+#define STAT_uptime_LEN (sizeof(STAT_uptime)-1)
+
+#define STAT_time MS_STAT " time "
+#define STAT_time_LEN (sizeof(STAT_time)-1)
+
+#define STAT_version MS_STAT " version "
+#define STAT_version_LEN (sizeof(STAT_version)-1)
+
+#define STAT_pointer_size MS_STAT " pointer_size "
+#define STAT_pointer_size_LEN (sizeof(STAT_pointer_size)-1)
+
+#define STAT_rusage_user MS_STAT " rusage_user "
+#define STAT_rusage_user_LEN (sizeof(STAT_rusage_user)-1)
+
+#define STAT_rusage_system MS_STAT " rusage_system "
+#define STAT_rusage_system_LEN (sizeof(STAT_rusage_system)-1)
+
+#define STAT_curr_items MS_STAT " curr_items "
+#define STAT_curr_items_LEN (sizeof(STAT_curr_items)-1)
+
+#define STAT_total_items MS_STAT " total_items "
+#define STAT_total_items_LEN (sizeof(STAT_total_items)-1)
+
+#define STAT_bytes MS_STAT " bytes "
+#define STAT_bytes_LEN (sizeof(STAT_bytes)-1)
+
+#define STAT_curr_connections MS_STAT " curr_connections "
+#define STAT_curr_connections_LEN (sizeof(STAT_curr_connections)-1)
+
+#define STAT_total_connections MS_STAT " total_connections "
+#define STAT_total_connections_LEN (sizeof(STAT_total_connections)-1)
+
+#define STAT_connection_structures MS_STAT " connection_structures "
+#define STAT_connection_structures_LEN (sizeof(STAT_connection_structures)-1)
+
+#define STAT_cmd_get MS_STAT " cmd_get "
+#define STAT_cmd_get_LEN (sizeof(STAT_cmd_get)-1)
+
+#define STAT_cmd_set MS_STAT " cmd_set "
+#define STAT_cmd_set_LEN (sizeof(STAT_cmd_set)-1)
+
+#define STAT_get_hits MS_STAT " get_hits "
+#define STAT_get_hits_LEN (sizeof(STAT_get_hits)-1)
+
+#define STAT_get_misses MS_STAT " get_misses "
+#define STAT_get_misses_LEN (sizeof(STAT_get_misses)-1)
+
+#define STAT_evictions MS_STAT " evictions "
+#define STAT_evictions_LEN (sizeof(STAT_evictions)-1)
+
+#define STAT_bytes_read MS_STAT " bytes_read "
+#define STAT_bytes_read_LEN (sizeof(STAT_bytes_read)-1)
+
+#define STAT_bytes_written MS_STAT " bytes_written "
+#define STAT_bytes_written_LEN (sizeof(STAT_bytes_written)-1)
+
+#define STAT_limit_maxbytes MS_STAT " limit_maxbytes "
+#define STAT_limit_maxbytes_LEN (sizeof(STAT_limit_maxbytes)-1)
+
+#define STAT_threads MS_STAT " threads "
+#define STAT_threads_LEN (sizeof(STAT_threads)-1)
+
+static const char *stat_read_string(apr_pool_t *p, char *buf, apr_size_t len)
+{
+    /* remove trailing \r\n and null char */
+    return apr_pstrmemdup(p, buf, len-2);
+}
+
+static apr_uint32_t stat_read_uint32(apr_pool_t *p, char *buf, apr_size_t  len)
+{
+    buf[len-2] = '\0';
+    return atoi(buf);
+}
+
+static apr_uint64_t stat_read_uint64(apr_pool_t *p, char *buf, apr_size_t  len)
+{
+    buf[len-2] = '\0';
+    return apr_atoi64(buf);
+}
+
+static apr_time_t stat_read_time(apr_pool_t *p, char *buf, apr_size_t  len)
+{
+    buf[len-2] = '\0';
+    return apr_time_from_sec(atoi(buf));
+}
+
+static apr_time_t stat_read_rtime(apr_pool_t *p, char *buf, apr_size_t  len)
+{
+    char *tok;
+    char *secs;
+    char *usecs;
+    const char *sep = ":.";
+
+    buf[len-2] = '\0';
+
+    secs = apr_strtok(buf, sep, &tok);
+    usecs = apr_strtok(NULL, sep, &tok);
+    if (secs && usecs) {
+        return apr_time_make(atoi(secs), atoi(usecs));
+    }
+    else {
+        return apr_time_make(0, 0);
+    }
+}
+
+/**
+ * I got tired of Typing. Meh. 
+ *
+ * TODO: Convert it to static tables to make it cooler.
+ */
+
+#define mc_stat_cmp(name) \
+    strncmp(STAT_ ## name, conn->buffer, STAT_ ## name ## _LEN) == 0
+
+#define mc_stat_str(name) \
+    stat_read_string(p, conn->buffer + name, \
+                     conn->blen - name)
+
+#define mc_stat_uint32(name) \
+    stat_read_uint32(p, conn->buffer + name, \
+                     conn->blen - name)
+
+#define mc_stat_uint64(name) \
+    stat_read_uint64(p, conn->buffer + name, \
+                     conn->blen - name)
+
+#define mc_stat_time(name) \
+    stat_read_time(p, conn->buffer + name, \
+                     conn->blen - name)
+
+#define mc_stat_rtime(name) \
+    stat_read_rtime(p, conn->buffer + name, \
+                     conn->blen - name)
+
+
+#define mc_do_stat(name, type) \
+    if (mc_stat_cmp(name)) { \
+        stats-> name = mc_stat_ ## type ((STAT_ ## name ## _LEN)); \
+    } 
+
+static void update_stats(apr_pool_t *p, apr_memcache_conn_t *conn, 
+                         apr_memcache_stats_t *stats)
+{
+
+    mc_do_stat(version, str)
+    else mc_do_stat(pid, uint32)
+    else mc_do_stat(uptime, uint32)
+    else mc_do_stat(pointer_size, uint32)
+    else mc_do_stat(time, time)
+    else mc_do_stat(rusage_user, rtime)
+    else mc_do_stat(rusage_system, rtime)
+    else mc_do_stat(curr_items, uint32)
+    else mc_do_stat(total_items, uint32)
+    else mc_do_stat(bytes, uint64)
+    else mc_do_stat(curr_connections, uint32)
+    else mc_do_stat(total_connections, uint32)
+    else mc_do_stat(connection_structures, uint32)
+    else mc_do_stat(cmd_get, uint32)
+    else mc_do_stat(cmd_set, uint32)
+    else mc_do_stat(get_hits, uint32)
+    else mc_do_stat(get_misses, uint32)
+    else mc_do_stat(evictions, uint64)
+    else mc_do_stat(bytes_read, uint64)
+    else mc_do_stat(bytes_written, uint64)
+    else mc_do_stat(limit_maxbytes, uint32)
+    else mc_do_stat(threads, uint32)
+}
+
+APR_DECLARE(apr_status_t)
+apr_memcache_stats(apr_memcache_server_t *ms,
+                  apr_pool_t *p,
+                  apr_memcache_stats_t **stats) 
+{
+    apr_memcache_stats_t *ret;
+    apr_status_t rv;
+    apr_memcache_conn_t *conn;
+    apr_size_t written;
+    struct iovec vec[2];
+
+    rv = ms_find_conn(ms, &conn);
+
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
+    /* version\r\n */
+    vec[0].iov_base = MC_STATS;
+    vec[0].iov_len  = MC_STATS_LEN;
+
+    vec[1].iov_base = MC_EOL;
+    vec[1].iov_len  = MC_EOL_LEN;
+
+    rv = apr_socket_sendv(conn->sock, vec, 2, &written);
+
+    if (rv != APR_SUCCESS) {
+        ms_bad_conn(ms, conn);
+        return rv;
+    }
+
+    ret = apr_pcalloc(p, sizeof(apr_memcache_stats_t));
+
+    do {
+        rv = get_server_line(conn);
+        if (rv != APR_SUCCESS) {
+            ms_bad_conn(ms, conn);
+            return rv;
+        }
+
+        if (strncmp(MS_END, conn->buffer, MS_END_LEN) == 0) {
+            rv = APR_SUCCESS;
+            break;
+        }
+        else if (strncmp(MS_STAT, conn->buffer, MS_STAT_LEN) == 0) {
+            update_stats(p, conn, ret);
+            continue;
+        }
+        else {
+            rv = APR_EGENERAL;
+            break;
+        }
+
+    } while(1);
+
+    ms_release_conn(ms, conn);
+
+    if (stats) {
+        *stats = ret;
+    }
+
+    return rv;
+}
+
diff --git a/memory/unix/apr_pools.c b/memory/unix/apr_pools.c
index 0d853a730ab..5fa7da1b5be 100644
--- a/memory/unix/apr_pools.c
+++ b/memory/unix/apr_pools.c
@@ -1,1280 +1,2746 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-/*
- * Resource allocation code... the code here is responsible for making
- * sure that nothing leaks.
- *
- * rst --- 4/95 --- 6/95
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
+#include "apr.h"
 #include "apr_private.h"
 
+#include "apr_atomic.h"
 #include "apr_portable.h" /* for get_os_proc */
+#include "apr_strings.h"
 #include "apr_general.h"
 #include "apr_pools.h"
+#include "apr_allocator.h"
 #include "apr_lib.h"
-#include "apr_lock.h"
-#include "misc.h"
-
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
+#include "apr_thread_mutex.h"
+#include "apr_hash.h"
+#include "apr_time.h"
+#include "apr_support.h"
+#define APR_WANT_MEMFUNC
+#include "apr_want.h"
+#include "apr_env.h"
+
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h>     /* for malloc, free and abort */
 #endif
-#ifdef HAVE_SYS_SIGNAL_H
-#include <sys/signal.h>
-#endif
-#ifdef HAVE_SIGNAL_H
-#include <signal.h>
-#endif
-#ifdef HAVE_SYS_WAIT_H
-#include <sys/wait.h>
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
+
+#if APR_HAVE_UNISTD_H
+#include <unistd.h>     /* for getpid and sysconf */
 #endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
+
+#if APR_ALLOCATOR_GUARD_PAGES && !APR_ALLOCATOR_USES_MMAP
+#define APR_ALLOCATOR_USES_MMAP   1
 #endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
+
+#if APR_ALLOCATOR_USES_MMAP
+#include <sys/mman.h>
 #endif
 
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
+#if HAVE_VALGRIND
+#define REDZONE APR_ALIGN_DEFAULT(8)
+int apr_running_on_valgrind = 0;
 #endif
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
+
+#if APR_POOL_CONCURRENCY_CHECK && !APR_HAS_THREADS
+#error pool-concurrency-check does not make sense without threads
 #endif
 
+
 /*
- * Debugging support: Define this to enable code which helps detect re-use
- * of freed memory and other such nonsense.
- *
- * The theory is simple.  The FILL_BYTE (0xa5) is written over all malloc'd
- * memory as we receive it, and is written over everything that we free up
- * during a clear_pool.  We check that blocks on the free list always
- * have the FILL_BYTE in them, and we check during palloc() that the bytes
- * still have FILL_BYTE in them.  If you ever see garbage URLs or whatnot
- * containing lots of 0xa5s then you know something used data that's been
- * freed or uninitialized.
+ * Magic numbers
  */
-/* #define ALLOC_DEBUG */
 
 /*
- * Debugging support: If defined all allocations will be done with
- * malloc and free()d appropriately at the end.  This is intended to be
- * used with something like Electric Fence or Purify to help detect
- * memory problems.  Note that if you're using efence then you should also
- * add in ALLOC_DEBUG.  But don't add in ALLOC_DEBUG if you're using Purify
- * because ALLOC_DEBUG would hide all the uninitialized read errors that
- * Purify can diagnose.
+ * Recycle up to MAX_INDEX in slots, larger indexes go to the
+ * sink slot at MAX_INDEX, and allocate at least MIN_ALLOC
+ * bytes (2^order boundaries/pages).
  */
-/* #define ALLOC_USE_MALLOC */
+#define MAX_INDEX   20
+#define MAX_ORDER   9
+static unsigned int min_order = 1;
+#define MIN_ALLOC   (BOUNDARY_SIZE << min_order)
 
 /*
- * Pool debugging support:  This is intended to detect cases where the
- * wrong pool is used when assigning data to an object in another pool.
- * In particular, it causes the table_{set,add,merge}n routines to check
- * that their arguments are safe for the ap_table_t they're being placed in.
- * It currently only works with the unix multiprocess model, but could
- * be extended to others.
+ * Determines the boundary/page size.
  */
-/* #define POOL_DEBUG */
+#if defined(_SC_PAGESIZE) || defined(WIN32)
+static unsigned int boundary_index;
+static unsigned int boundary_size;
+#define BOUNDARY_INDEX  boundary_index
+#define BOUNDARY_SIZE   boundary_size
+#else  /* Assume 4K pages */
+#define BOUNDARY_INDEX 12
+#define BOUNDARY_SIZE (1 << BOUNDARY_INDEX)
+#endif
 
-/*
- * Provide diagnostic information about make_table() calls which are
- * possibly too small.  This requires a recent gcc which supports
- * __builtin_return_address().  The error_log output will be a
- * message such as:
- *    table_push: ap_table_t created by 0x804d874 hit limit of 10
- * Use "l *0x804d874" to find the source that corresponds to.  It
- * indicates that a ap_table_t allocated by a call at that address has
- * possibly too small an initial ap_table_t size guess.
+#if APR_ALLOCATOR_GUARD_PAGES
+#if defined(_SC_PAGESIZE)
+#define GUARDPAGE_SIZE boundary_size
+#else
+#error Cannot determine page size
+#endif /* _SC_PAGESIZE */
+#else
+#define GUARDPAGE_SIZE 0
+#endif /* APR_ALLOCATOR_GUARD_PAGES */
+
+/* 
+ * Timing constants for killing subprocesses
+ * There is a total 3-second delay between sending a SIGINT 
+ * and sending of the final SIGKILL.
+ * TIMEOUT_INTERVAL should be set to TIMEOUT_USECS / 64
+ * for the exponetial timeout alogrithm.
  */
-/* #define MAKE_TABLE_PROFILE */
+#define TIMEOUT_USECS    3000000
+#define TIMEOUT_INTERVAL   46875
 
 /*
- * Provide some statistics on the cost of allocations.  It requires a
- * bit of an understanding of how alloc.c works.
+ * Allocator
+ *
+ * @note The max_free_index and current_free_index fields are not really
+ * indices, but quantities of BOUNDARY_SIZE big memory blocks.
  */
-/* #define ALLOC_STATS */
-
-#ifdef POOL_DEBUG
-#ifdef ALLOC_USE_MALLOC
-#error "sorry, no support for ALLOC_USE_MALLOC and POOL_DEBUG at the same time"
-#endif /* ALLOC_USE_MALLOC */
-
-#ifdef MULTITHREAD
-# error "sorry, no support for MULTITHREAD and POOL_DEBUG at the same time"
-#endif /* MULTITHREAD */
 
-#endif /* POOL_DEBUG */
-
-#ifdef ALLOC_USE_MALLOC
-#undef BLOCK_MINFREE
-#undef BLOCK_MINALLOC
-#define BLOCK_MINFREE	0
-#define BLOCK_MINALLOC	0
-#endif /* ALLOC_USE_MALLOC */
+struct apr_allocator_t {
+    /** largest used index into free[], always < MAX_INDEX */
+    apr_size_t        max_index;
+    /** Total size (in BOUNDARY_SIZE multiples) of unused memory before
+     * blocks are given back. @see apr_allocator_max_free_set().
+     * @note Initialized to APR_ALLOCATOR_MAX_FREE_UNLIMITED,
+     * which means to never give back blocks.
+     */
+    apr_size_t        max_free_index;
+    /**
+     * Memory size (in BOUNDARY_SIZE multiples) that currently must be freed
+     * before blocks are given back. Range: 0..max_free_index
+     */
+    apr_size_t        current_free_index;
+#if APR_HAS_THREADS
+    apr_thread_mutex_t *mutex;
+#endif /* APR_HAS_THREADS */
+    apr_pool_t         *owner;
+    /**
+     * Lists of free nodes. Slot MAX_INDEX is used for oversized nodes,
+     * and the slots 0..MAX_INDEX-1 contain nodes of sizes
+     * (i+1) * BOUNDARY_SIZE. Example for BOUNDARY_INDEX == 12:
+     * slot  0: size  4096
+     * slot  1: size  8192
+     * slot  2: size 12288
+     * ...
+     * slot 19: size 81920
+     * slot 20: nodes larger than 81920
+     */
+    apr_memnode_t      *free[MAX_INDEX + 1];
+};
 
-#define AP_SLACK_LOW    1
-#define AP_SLACK_HIGH   2
+#define SIZEOF_ALLOCATOR_T  APR_ALIGN_DEFAULT(sizeof(apr_allocator_t))
 
 
-/*****************************************************************
- *
- * Managing free storage blocks...
+/*
+ * Allocator
  */
 
-union align {
-    /*
-     * Types which are likely to have the longest RELEVANT alignment
-     * restrictions...
-     */
+static APR_INLINE
+void allocator_lock(apr_allocator_t *allocator)
+{
+#if APR_HAS_THREADS
+    if (allocator->mutex)
+        apr_thread_mutex_lock(allocator->mutex);
+#endif /* APR_HAS_THREADS */
+}
 
-    char *cp;
-    void (*f) (void);
-    long l;
-    FILE *fp;
-    double d;
-};
+static APR_INLINE
+void allocator_unlock(apr_allocator_t *allocator)
+{
+#if APR_HAS_THREADS
+    if (allocator->mutex)
+        apr_thread_mutex_unlock(allocator->mutex);
+#endif /* APR_HAS_THREADS */
+}
 
-#define CLICK_SZ (sizeof(union align))
+APR_DECLARE(apr_status_t) apr_allocator_create(apr_allocator_t **allocator)
+{
+    apr_allocator_t *new_allocator;
 
-union block_hdr {
-    union align a;
+    *allocator = NULL;
 
-    /* Actual header... */
+    if ((new_allocator = malloc(SIZEOF_ALLOCATOR_T)) == NULL)
+        return APR_ENOMEM;
 
-    struct {
-	char *endp;
-	union block_hdr *next;
-	char *first_avail;
-#ifdef POOL_DEBUG
-	union block_hdr *global_next;
-	ap_pool_t *owning_pool;
-#endif /* POOL_DEBUG */
-    } h;
-};
+    memset(new_allocator, 0, SIZEOF_ALLOCATOR_T);
+    new_allocator->max_free_index = APR_ALLOCATOR_MAX_FREE_UNLIMITED;
 
-#define APR_ABORT(conditional, retcode, func, str) \
-    if (conditional) { \
-        if ((func) == NULL) { \
-            return NULL; \
-        } \
-        else { \
-            fprintf(stderr, "%s", str); \
-            (*(func))(retcode); \
-        } \
-    }
+    *allocator = new_allocator;
 
-/*
- * Static cells for managing our internal synchronisation.
- */
-static union block_hdr *block_freelist = NULL;
+    return APR_SUCCESS;
+}
 
-#if APR_HAS_THREADS
-static ap_lock_t *alloc_mutex;
-static ap_lock_t *spawn_mutex;
+APR_DECLARE(void) apr_allocator_destroy(apr_allocator_t *allocator)
+{
+    apr_size_t index;
+    apr_memnode_t *node, **ref;
+
+    for (index = 0; index <= MAX_INDEX; index++) {
+        ref = &allocator->free[index];
+        while ((node = *ref) != NULL) {
+            *ref = node->next;
+#if APR_ALLOCATOR_USES_MMAP
+            munmap((char *)node - GUARDPAGE_SIZE,
+                   2 * GUARDPAGE_SIZE + ((node->index+1) << BOUNDARY_INDEX));
+#else
+            free(node);
 #endif
+        }
+    }
 
-#ifdef POOL_DEBUG
-static char *known_stack_point;
-static int stack_direction;
-static union block_hdr *global_block_list;
-#define FREE_POOL	((ap_pool_t *)(-1))
-#endif /* POOL_DEBUG */
-
-#ifdef ALLOC_STATS
-static unsigned long long num_free_blocks_calls;
-static unsigned long long num_blocks_freed;
-static unsigned max_blocks_in_one_free;
-static unsigned num_malloc_calls;
-static unsigned num_malloc_bytes;
-#endif /* ALLOC_STATS */
+    free(allocator);
+}
 
-#ifdef ALLOC_DEBUG
-#define FILL_BYTE	((char)(0xa5))
-#define debug_fill(ptr,size)	((void)memset((ptr), FILL_BYTE, (size)))
+#if APR_HAS_THREADS
+APR_DECLARE(void) apr_allocator_mutex_set(apr_allocator_t *allocator,
+                                          apr_thread_mutex_t *mutex)
+{
+    allocator->mutex = mutex;
+}
 
-static APR_INLINE void debug_verify_filled(const char *ptr, const char *endp,
-					   const char *error_msg)
+APR_DECLARE(apr_thread_mutex_t *) apr_allocator_mutex_get(
+                                      apr_allocator_t *allocator)
 {
-    for ( ; ptr < endp; ++ptr) {
-	if (*ptr != FILL_BYTE) {
-	    fputs(error_msg, stderr);
-	    abort();
-	    exit(1);
-	}
-    }
+    return allocator->mutex;
 }
+#endif /* APR_HAS_THREADS */
 
-#else /* ALLOC_DEBUG */
-#define debug_fill(a,b)
-#define debug_verify_filled(a,b,c)
-#endif /* ALLOC_DEBUG */
+APR_DECLARE(void) apr_allocator_owner_set(apr_allocator_t *allocator,
+                                          apr_pool_t *pool)
+{
+    allocator->owner = pool;
+}
 
-/*
- * Get a completely new block from the system pool. Note that we rely on
- * malloc() to provide aligned memory.
- */
+APR_DECLARE(apr_pool_t *) apr_allocator_owner_get(apr_allocator_t *allocator)
+{
+    return allocator->owner;
+}
 
-static union block_hdr *malloc_block(int size, int (*apr_abort)(int retcode))
+APR_DECLARE(void) apr_allocator_max_free_set(apr_allocator_t *allocator,
+                                             apr_size_t in_size)
 {
-    union block_hdr *blok;
+    apr_size_t max_free_index;
+    apr_size_t size = in_size;
 
-#ifdef ALLOC_DEBUG
-    /* make some room at the end which we'll fill and expect to be
-     * always filled
-     */
-    size += CLICK_SZ;
-#endif /* ALLOC_DEBUG */
+    allocator_lock(allocator);
 
-#ifdef ALLOC_STATS
-    ++num_malloc_calls;
-    num_malloc_bytes += size + sizeof(union block_hdr);
-#endif /* ALLOC_STATS */
+    max_free_index = APR_ALIGN(size, BOUNDARY_SIZE) >> BOUNDARY_INDEX;
+    allocator->current_free_index += max_free_index;
+    allocator->current_free_index -= allocator->max_free_index;
+    allocator->max_free_index = max_free_index;
+    if (allocator->current_free_index > max_free_index)
+        allocator->current_free_index = max_free_index;
 
-    blok = (union block_hdr *) malloc(size + sizeof(union block_hdr));
-    APR_ABORT(blok == NULL, APR_ENOMEM, apr_abort,
-              "Ouch!  malloc failed in malloc_block()\n");
-    debug_fill(blok, size + sizeof(union block_hdr));
-    blok->h.next = NULL;
-    blok->h.first_avail = (char *) (blok + 1);
-    blok->h.endp = size + blok->h.first_avail;
+    allocator_unlock(allocator);
+}
 
-#ifdef ALLOC_DEBUG
-    blok->h.endp -= CLICK_SZ;
-#endif /* ALLOC_DEBUG */
+static APR_INLINE
+apr_size_t allocator_align(apr_size_t in_size)
+{
+    apr_size_t size = in_size;
 
-#ifdef POOL_DEBUG
-    blok->h.global_next = global_block_list;
-    global_block_list = blok;
-    blok->h.owning_pool = NULL;
-#endif /* POOL_DEBUG */
+    /* Round up the block size to the next boundary, but always
+     * allocate at least a certain size (MIN_ALLOC).
+     */
+    size = APR_ALIGN(size + APR_MEMNODE_T_SIZE, BOUNDARY_SIZE);
+    if (size < in_size) {
+        return 0;
+    }
+    if (size < MIN_ALLOC) {
+        size = MIN_ALLOC;
+    }
 
-    return blok;
+    return size;
 }
 
-
-
-#if defined(ALLOC_DEBUG) && !defined(ALLOC_USE_MALLOC)
-static void chk_on_blk_list(union block_hdr *blok, union block_hdr *free_blk)
+APR_DECLARE(apr_size_t) apr_allocator_align(apr_allocator_t *allocator,
+                                            apr_size_t size)
 {
-    debug_verify_filled(blok->h.endp, blok->h.endp + CLICK_SZ,
-			"Ouch!  Someone trounced the padding "
-			"at the end of a block!\n");
-    while (free_blk) {
-	if (free_blk == blok) {
-            fprintf(stderr, "Ouch!  Freeing free block\n");
-	    abort();
-	    exit(1);
-	}
-	free_blk = free_blk->h.next;
-    }
+    (void)allocator;
+    return allocator_align(size);
 }
-#else /* defined(ALLOC_DEBUG) && !defined(ALLOC_USE_MALLOC) */
-#define chk_on_blk_list(_x, _y)
-#endif /* defined(ALLOC_DEBUG) && !defined(ALLOC_USE_MALLOC) */
-
-/* Free a chain of blocks --- must be called with alarms blocked. */
 
-static void free_blocks(union block_hdr *blok)
+static APR_INLINE
+apr_memnode_t *allocator_alloc(apr_allocator_t *allocator, apr_size_t in_size)
 {
-#ifdef ALLOC_USE_MALLOC
-    union block_hdr *next;
+    apr_memnode_t *node, **ref;
+    apr_size_t max_index, upper_index;
+    apr_size_t size, i, index;
 
-    for ( ; blok; blok = next) {
-	next = blok->h.next;
-	free(blok);
+    /* Round up the block size to the next boundary, but always
+     * allocate at least a certain size (MIN_ALLOC).
+     */
+    size = allocator_align(in_size);
+    if (!size) {
+        return NULL;
     }
-#else /* ALLOC_USE_MALLOC */
 
-#ifdef ALLOC_STATS
-    unsigned num_blocks;
-#endif /* ALLOC_STATS */
+    /* Find the index for this node size by
+     * dividing its size by the boundary size
+     */
+    index = (size >> BOUNDARY_INDEX) - 1;
+    
+    if (index > APR_UINT32_MAX) {
+        return NULL;
+    }
 
-    /*
-     * First, put new blocks at the head of the free list ---
-     * we'll eventually bash the 'next' pointer of the last block
-     * in the chain to point to the free blocks we already had.
+    /* First see if there are any nodes in the area we know
+     * our node will fit into.
      */
+    if (index <= allocator->max_index) {
+        allocator_lock(allocator);
+
+        /* Walk the free list to see if there are
+         * any nodes on it of the requested size
+         *
+         * If there is no exact match, look for nodes
+         * of up to twice the requested size, so we
+         * won't unnecessarily allocate more memory
+         * nor waste too much of what we have.
+         *
+         * NOTE: an optimization would be to check
+         * allocator->free[index] first and if no
+         * node is present, directly use
+         * allocator->free[max_index].  This seems
+         * like overkill though and could cause
+         * memory waste.
+         */
+        max_index = allocator->max_index;
+        upper_index = 2 * index < max_index ? 2 * index : max_index;
+        ref = &allocator->free[index];
+        i = index;
+        while (*ref == NULL && i < upper_index) {
+           ref++;
+           i++;
+        }
 
-    union block_hdr *old_free_list;
+        if ((node = *ref) != NULL) {
+            /* If we have found a node and it doesn't have any
+             * nodes waiting in line behind it _and_ we are on
+             * the highest available index, find the new highest
+             * available index
+             */
+            if ((*ref = node->next) == NULL && i >= max_index) {
+                do {
+                    ref--;
+                    max_index--;
+                }
+                while (*ref == NULL && max_index);
 
-    if (blok == NULL) {
-	return;			/* Sanity check --- freeing empty pool? */
-    }
+                allocator->max_index = max_index;
+            }
 
-#if APR_HAS_THREADS
-    ap_lock(alloc_mutex);
-#endif
-    old_free_list = block_freelist;
-    block_freelist = blok;
+            allocator->current_free_index += node->index + 1;
+            if (allocator->current_free_index > allocator->max_free_index)
+                allocator->current_free_index = allocator->max_free_index;
 
-    /*
-     * Next, adjust first_avail pointers of each block --- have to do it
-     * sooner or later, and it simplifies the search in new_block to do it
-     * now.
+            allocator_unlock(allocator);
+
+            goto have_node;
+        }
+
+        allocator_unlock(allocator);
+    }
+
+    /* If we found nothing, seek the sink (at index MAX_INDEX), if
+     * it is not empty.
      */
+    else if (allocator->free[MAX_INDEX]) {
+        allocator_lock(allocator);
 
-#ifdef ALLOC_STATS
-    num_blocks = 1;
-#endif /* ALLOC_STATS */
+        /* Walk the free list to see if there are
+         * any nodes on it of the requested size
+         */
+        ref = &allocator->free[MAX_INDEX];
+        while ((node = *ref) != NULL && index > node->index)
+            ref = &node->next;
 
-    while (blok->h.next != NULL) {
+        if (node) {
+            *ref = node->next;
 
-#ifdef ALLOC_STATS
-	++num_blocks;
-#endif /* ALLOC_STATS */
+            allocator->current_free_index += node->index + 1;
+            if (allocator->current_free_index > allocator->max_free_index)
+                allocator->current_free_index = allocator->max_free_index;
 
-	chk_on_blk_list(blok, old_free_list);
-	blok->h.first_avail = (char *) (blok + 1);
-	debug_fill(blok->h.first_avail, blok->h.endp - blok->h.first_avail);
-#ifdef POOL_DEBUG
-	blok->h.owning_pool = FREE_POOL;
-#endif /* POOL_DEBUG */
-	blok = blok->h.next;
-    }
+            allocator_unlock(allocator);
 
-    chk_on_blk_list(blok, old_free_list);
-    blok->h.first_avail = (char *) (blok + 1);
-    debug_fill(blok->h.first_avail, blok->h.endp - blok->h.first_avail);
-#ifdef POOL_DEBUG
-    blok->h.owning_pool = FREE_POOL;
-#endif /* POOL_DEBUG */
+            goto have_node;
+        }
 
-    /* Finally, reset next pointer to get the old free blocks back */
+        allocator_unlock(allocator);
+    }
 
-    blok->h.next = old_free_list;
+    /* If we haven't got a suitable node, malloc a new one
+     * and initialize it.
+     */
+#if APR_ALLOCATOR_GUARD_PAGES
+    if ((node = mmap(NULL, size + 2 * GUARDPAGE_SIZE, PROT_NONE,
+                     MAP_PRIVATE|MAP_ANON, -1, 0)) == MAP_FAILED)
+#elif APR_ALLOCATOR_USES_MMAP
+    if ((node = mmap(NULL, size, PROT_READ|PROT_WRITE,
+                     MAP_PRIVATE|MAP_ANON, -1, 0)) == MAP_FAILED)
+#else
+    if ((node = malloc(size)) == NULL)
+#endif
+        return NULL;
 
-#ifdef ALLOC_STATS
-    if (num_blocks > max_blocks_in_one_free) {
-	max_blocks_in_one_free = num_blocks;
+#if APR_ALLOCATOR_GUARD_PAGES
+    node = (apr_memnode_t *)((char *)node + GUARDPAGE_SIZE);
+    if (mprotect(node, size, PROT_READ|PROT_WRITE) != 0) {
+        munmap((char *)node - GUARDPAGE_SIZE, size + 2 * GUARDPAGE_SIZE);
+        return NULL;
     }
-    ++num_free_blocks_calls;
-    num_blocks_freed += num_blocks;
-#endif /* ALLOC_STATS */
+#endif
+    node->index = index;
+    node->endp = (char *)node + size;
 
-#if APR_HAS_THREADS
-    ap_unlock(alloc_mutex);
-#endif /* APR_HAS_THREADS */
-#endif /* ALLOC_USE_MALLOC */
-}
+have_node:
+    node->next = NULL;
+    node->first_avail = (char *)node + APR_MEMNODE_T_SIZE;
 
-/*
- * Get a new block, from our own free list if possible, from the system
- * if necessary.  Must be called with alarms blocked.
- */
+    APR_VALGRIND_UNDEFINED(node->first_avail, size - APR_MEMNODE_T_SIZE);
+
+    return node;
+}
 
-static union block_hdr *new_block(int min_size, int (*apr_abort)(int retcode))
+static APR_INLINE
+void allocator_free(apr_allocator_t *allocator, apr_memnode_t *node)
 {
-    union block_hdr **lastptr = &block_freelist;
-    union block_hdr *blok = block_freelist;
+    apr_memnode_t *next, *freelist = NULL;
+    apr_size_t index, max_index;
+    apr_size_t max_free_index, current_free_index;
+
+    allocator_lock(allocator);
 
-    /* First, see if we have anything of the required size
-     * on the free list...
+    max_index = allocator->max_index;
+    max_free_index = allocator->max_free_index;
+    current_free_index = allocator->current_free_index;
+
+    /* Walk the list of submitted nodes and free them one by one,
+     * shoving them in the right 'size' buckets as we go.
      */
+    do {
+        next = node->next;
+        index = node->index;
 
-    while (blok != NULL) {
-	if (min_size + BLOCK_MINFREE <= blok->h.endp - blok->h.first_avail) {
-	    *lastptr = blok->h.next;
-	    blok->h.next = NULL;
-	    debug_verify_filled(blok->h.first_avail, blok->h.endp,
-				"Ouch!  Someone trounced a block "
-				"on the free list!\n");
-	    return blok;
-	}
-	else {
-	    lastptr = &blok->h.next;
-	    blok = blok->h.next;
-	}
-    }
+        APR_VALGRIND_NOACCESS((char *)node + APR_MEMNODE_T_SIZE,
+                              (node->index+1) << BOUNDARY_INDEX);
+
+        if (max_free_index != APR_ALLOCATOR_MAX_FREE_UNLIMITED
+            && index + 1 > current_free_index) {
+            node->next = freelist;
+            freelist = node;
+        }
+        else if (index < MAX_INDEX) {
+            /* Add the node to the appropriate 'size' bucket.  Adjust
+             * the max_index when appropriate.
+             */
+            if ((node->next = allocator->free[index]) == NULL
+                && index > max_index) {
+                max_index = index;
+            }
+            allocator->free[index] = node;
+            if (current_free_index >= index + 1)
+                current_free_index -= index + 1;
+            else
+                current_free_index = 0;
+        }
+        else {
+            /* This node is too large to keep in a specific size bucket,
+             * just add it to the sink (at index MAX_INDEX).
+             */
+            node->next = allocator->free[MAX_INDEX];
+            allocator->free[MAX_INDEX] = node;
+            if (current_free_index >= index + 1)
+                current_free_index -= index + 1;
+            else
+                current_free_index = 0;
+        }
+    } while ((node = next) != NULL);
 
-    /* Nope. */
+    allocator->max_index = max_index;
+    allocator->current_free_index = current_free_index;
 
-    min_size += BLOCK_MINFREE;
-    blok = malloc_block((min_size > BLOCK_MINALLOC)
-			? min_size : BLOCK_MINALLOC, apr_abort);
-    return blok;
+    allocator_unlock(allocator);
+
+    while (freelist != NULL) {
+        node = freelist;
+        freelist = node->next;
+#if APR_ALLOCATOR_USES_MMAP
+        munmap((char *)node - GUARDPAGE_SIZE,
+               2 * GUARDPAGE_SIZE + ((node->index+1) << BOUNDARY_INDEX));
+#else
+        free(node);
+#endif
+    }
 }
 
+APR_DECLARE(apr_memnode_t *) apr_allocator_alloc(apr_allocator_t *allocator,
+                                                 apr_size_t size)
+{
+    return allocator_alloc(allocator, size);
+}
 
-/* Accounting */
+APR_DECLARE(void) apr_allocator_free(apr_allocator_t *allocator,
+                                     apr_memnode_t *node)
+{
+    allocator_free(allocator, node);
+}
 
-static long bytes_in_block_list(union block_hdr *blok)
+APR_DECLARE(apr_size_t) apr_allocator_page_size(void)
 {
-    long size = 0;
+    return boundary_size;
+}
 
-    while (blok) {
-	size += blok->h.endp - (char *) (blok + 1);
-	blok = blok->h.next;
+APR_DECLARE(apr_status_t) apr_allocator_min_order_set(unsigned int order)
+{
+    if (order > MAX_ORDER) {
+        return APR_EINVAL;
     }
-
-    return size;
+    min_order = order;
+    return APR_SUCCESS;
 }
 
 
-/*****************************************************************
- *
- * Pool internals and management...
- * NB that subprocesses are not handled by the generic cleanup code,
- * basically because we don't want cleanups for multiple subprocesses
- * to result in multiple three-second pauses.
+/*
+ * Debug level
  */
 
-struct process_chain;
-struct cleanup;
+#define APR_POOL_DEBUG_GENERAL  0x01
+#define APR_POOL_DEBUG_VERBOSE  0x02
+#define APR_POOL_DEBUG_LIFETIME 0x04
+#define APR_POOL_DEBUG_OWNER    0x08
+#define APR_POOL_DEBUG_VERBOSE_ALLOC 0x10
 
-static void run_cleanups(struct cleanup *c);
-static void free_proc_chain(struct process_chain *p);
+#define APR_POOL_DEBUG_VERBOSE_ALL (APR_POOL_DEBUG_VERBOSE \
+                                    | APR_POOL_DEBUG_VERBOSE_ALLOC)
 
-static ap_pool_t *permanent_pool;
 
-/* Each pool structure is allocated in the start of its own first block,
- * so we need to know how many bytes that is (once properly aligned...).
- * This also means that when a pool's sub-pool is destroyed, the storage
- * associated with it is *completely* gone, so we have to make sure it
- * gets taken off the parent's sub-pool list...
+/*
+ * Structures
  */
 
-#define POOL_HDR_CLICKS (1 + ((sizeof(struct ap_pool_t) - 1) / CLICK_SZ))
-#define POOL_HDR_BYTES (POOL_HDR_CLICKS * CLICK_SZ)
+typedef struct cleanup_t cleanup_t;
 
-API_EXPORT(ap_pool_t *) ap_make_sub_pool(ap_pool_t *p, int (*apr_abort)(int retcode))
-{
-    union block_hdr *blok;
-    ap_pool_t *new_pool;
+/** A list of processes */
+struct process_chain {
+    /** The process ID */
+    apr_proc_t *proc;
+    apr_kill_conditions_e kill_how;
+    /** The next process in the list */
+    struct process_chain *next;
+};
 
-    ap_block_alarms();
 
-#if APR_HAS_THREADS
-    ap_lock(alloc_mutex);
-#endif
+#if APR_POOL_DEBUG
 
-    blok = new_block(POOL_HDR_BYTES, apr_abort);
-    new_pool = (ap_pool_t *) blok->h.first_avail;
-    blok->h.first_avail += POOL_HDR_BYTES;
-#ifdef POOL_DEBUG
-    blok->h.owning_pool = new_pool;
-#endif
+typedef struct debug_node_t debug_node_t;
+
+struct debug_node_t {
+    debug_node_t *next;
+    apr_size_t    index;
+    void         *beginp[64];
+    void         *endp[64];
+};
 
-    memset((char *) new_pool, '\0', sizeof(struct ap_pool_t));
-    new_pool->free_first_avail = blok->h.first_avail;
-    new_pool->first = new_pool->last = blok;
+#define SIZEOF_DEBUG_NODE_T APR_ALIGN_DEFAULT(sizeof(debug_node_t))
 
-    if (p) {
-	new_pool->parent = p;
-	new_pool->sub_next = p->sub_pools;
-	if (new_pool->sub_next) {
-	    new_pool->sub_next->sub_prev = new_pool;
-	}
-	p->sub_pools = new_pool;
-    }
-    else {
-        permanent_pool = new_pool;
-    }
+#endif /* APR_POOL_DEBUG */
 
+/* The ref field in the apr_pool_t struct holds a
+ * pointer to the pointer referencing this pool.
+ * It is used for parent, child, sibling management.
+ * Look at apr_pool_create_ex() and apr_pool_destroy()
+ * to see how it is used.
+ */
+struct apr_pool_t {
+    apr_pool_t           *parent;
+    apr_pool_t           *child;
+    apr_pool_t           *sibling;
+    apr_pool_t          **ref;
+    cleanup_t            *cleanups;
+    cleanup_t            *free_cleanups;
+    apr_allocator_t      *allocator;
+    struct process_chain *subprocesses;
+    apr_abortfunc_t       abort_fn;
+    apr_hash_t           *user_data;
+    const char           *tag;
+
+#if !APR_POOL_DEBUG
+    apr_memnode_t        *active;
+    apr_memnode_t        *self; /* The node containing the pool itself */
+    char                 *self_first_avail;
+
+#else /* APR_POOL_DEBUG */
+    apr_pool_t           *joined; /* the caller has guaranteed that this pool
+                                   * will survive as long as ->joined */
+    debug_node_t         *nodes;
+    const char           *file_line;
+    apr_uint32_t          creation_flags;
+    unsigned int          stat_alloc;
+    unsigned int          stat_total_alloc;
+    unsigned int          stat_clear;
 #if APR_HAS_THREADS
-    ap_unlock(alloc_mutex);
-#endif
-    ap_unblock_alarms();
+    apr_os_thread_t       owner;
+    apr_thread_mutex_t   *mutex;
+#endif /* APR_HAS_THREADS */
+#endif /* APR_POOL_DEBUG */
+#ifdef NETWARE
+    apr_os_proc_t         owner_proc;
+#endif /* defined(NETWARE) */
+    cleanup_t            *pre_cleanups;
+#if APR_POOL_CONCURRENCY_CHECK
+
+#define                   IDLE        0
+#define                   IN_USE      1
+#define                   DESTROYED   2
+    volatile apr_uint32_t in_use;
+    apr_os_thread_t       in_use_by;
+#endif /* APR_POOL_CONCURRENCY_CHECK */
+};
 
-    return new_pool;
-}
+#define SIZEOF_POOL_T       APR_ALIGN_DEFAULT(sizeof(apr_pool_t))
 
-#ifdef POOL_DEBUG
-static void stack_var_init(char *s)
-{
-    char t;
 
-    if (s < &t) {
-	stack_direction = 1; /* stack grows up */
-    }
-    else {
-	stack_direction = -1; /* stack grows down */
-    }
-}
-#endif
+/*
+ * Variables
+ */
+
+static apr_byte_t   apr_pools_initialized = 0;
+static apr_pool_t  *global_pool = NULL;
 
-#ifdef ALLOC_STATS
-static void dump_stats(void)
+#if !APR_POOL_DEBUG
+static apr_allocator_t *global_allocator = NULL;
+#endif /* !APR_POOL_DEBUG */
+
+#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL)
+static apr_file_t *file_stderr = NULL;
+static apr_status_t apr_pool_cleanup_file_stderr(void *data)
 {
-    fprintf(stderr,
-	    "alloc_stats: [%d] #free_blocks %llu #blocks %llu max "
-	    "%u #malloc %u #bytes %u\n",
-	(int) getpid(),
-	num_free_blocks_calls,
-	num_blocks_freed,
-	max_blocks_in_one_free,
-	num_malloc_calls,
-	num_malloc_bytes);
+    file_stderr = NULL;
+    return APR_SUCCESS;
 }
-#endif
 
-/*****************************************************************
- *
- * Managing generic cleanups.  
+#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL) */
+
+/*
+ * Local functions
  */
 
-struct cleanup {
-    void *data;
-    ap_status_t (*plain_cleanup) (void *);
-    ap_status_t (*child_cleanup) (void *);
-    struct cleanup *next;
-};
+static void run_cleanups(cleanup_t **c);
+static void free_proc_chain(struct process_chain *procs);
+
+#if APR_POOL_DEBUG
+static void pool_destroy_debug(apr_pool_t *pool, const char *file_line);
+#endif
 
-static void * ap_pool_palloc(ap_pool_t *a, int reqsize, int (*apr_abort)(int retcode));
+#if !APR_POOL_DEBUG
+/*
+ * Initialization
+ */
 
-#if 0
-static void ap_register_pool_cleanup(struct ap_pool_t *p, void *data,
-				      ap_status_t (*plain_cleanup) (void *),
-				      ap_status_t (*child_cleanup) (void *))
+APR_DECLARE(apr_status_t) apr_pool_initialize(void)
 {
-    struct cleanup *c;
+    apr_status_t rv;
 
-    if (p != NULL) {
-        c = (struct cleanup *) ap_pool_palloc(p, sizeof(struct cleanup), NULL);
-        c->data = data;
-        c->plain_cleanup = plain_cleanup;
-        c->child_cleanup = child_cleanup;
-        c->next = p->cleanups;
-        p->cleanups = c;
+    if (apr_pools_initialized++)
+        return APR_SUCCESS;
+
+#if HAVE_VALGRIND
+    apr_running_on_valgrind = RUNNING_ON_VALGRIND;
+#endif
+
+#if defined(_SC_PAGESIZE)
+    boundary_size = sysconf(_SC_PAGESIZE);
+#elif defined(WIN32)
+    {
+        SYSTEM_INFO si;
+        GetSystemInfo(&si);
+        boundary_size = si.dwPageSize;
     }
-}
 #endif
+    boundary_index = 12;
+    while ( (1 << boundary_index) < boundary_size)
+        boundary_index++;
+    boundary_size = (1 << boundary_index);
+
+    if ((rv = apr_allocator_create(&global_allocator)) != APR_SUCCESS) {
+        apr_pools_initialized = 0;
+        return rv;
+    }
 
-API_EXPORT(void) ap_register_cleanup(ap_pool_t *p, void *data,
-				      ap_status_t (*plain_cleanup) (void *),
-				      ap_status_t (*child_cleanup) (void *))
-{
-    struct cleanup *c;
+    if ((rv = apr_pool_create_ex(&global_pool, NULL, NULL,
+                                 global_allocator)) != APR_SUCCESS) {
+        apr_allocator_destroy(global_allocator);
+        global_allocator = NULL;
+        apr_pools_initialized = 0;
+        return rv;
+    }
 
-    if (p != NULL) {
-        c = (struct cleanup *) ap_palloc(p, sizeof(struct cleanup));
-        c->data = data;
-        c->plain_cleanup = plain_cleanup;
-        c->child_cleanup = child_cleanup;
-        c->next = p->cleanups;
-        p->cleanups = c;
+    apr_pool_tag(global_pool, "apr_global_pool");
+
+    /* This has to happen here because mutexes might be backed by
+     * atomics.  It used to be snug and safe in apr_initialize().
+     *
+     * Warning: apr_atomic_init() must always be called, by any
+     * means possible, from apr_initialize().
+     */
+    if ((rv = apr_atomic_init(global_pool)) != APR_SUCCESS) {
+        return rv;
     }
-}
 
-API_EXPORT(void) ap_kill_cleanup(ap_pool_t *p, void *data,
-				  ap_status_t (*cleanup) (void *))
-{
-    struct cleanup *c;
-    struct cleanup **lastp;
+#if APR_HAS_THREADS
+    {
+        apr_thread_mutex_t *mutex;
 
-    if (p == NULL)
-        return;
-    c = p->cleanups;
-    lastp = &p->cleanups;
-    while (c) {
-        if (c->data == data && c->plain_cleanup == cleanup) {
-            *lastp = c->next;
-            break;
+        if ((rv = apr_thread_mutex_create(&mutex,
+                                          APR_THREAD_MUTEX_DEFAULT,
+                                          global_pool)) != APR_SUCCESS) {
+            return rv;
         }
 
-        lastp = &c->next;
-        c = c->next;
+        apr_allocator_mutex_set(global_allocator, mutex);
     }
-}
+#endif /* APR_HAS_THREADS */
 
-API_EXPORT(void) ap_run_cleanup(ap_pool_t *p, void *data,
-				 ap_status_t (*cleanup) (void *))
-{
-    ap_block_alarms();		/* Run cleanup only once! */
-    (*cleanup) (data);
-    ap_kill_cleanup(p, data, cleanup);
-    ap_unblock_alarms();
-}
+    apr_allocator_owner_set(global_allocator, global_pool);
 
-static void run_cleanups(struct cleanup *c)
-{
-    while (c) {
-	(*c->plain_cleanup) (c->data);
-	c = c->next;
-    }
+    return APR_SUCCESS;
 }
 
-static void run_child_cleanups(struct cleanup *c)
+APR_DECLARE(void) apr_pool_terminate(void)
 {
-    while (c) {
-	(*c->child_cleanup) (c->data);
-	c = c->next;
-    }
-}
+    if (!apr_pools_initialized)
+        return;
 
-static void cleanup_pool_for_exec(ap_pool_t *p)
-{
-    run_child_cleanups(p->cleanups);
-    p->cleanups = NULL;
+    if (--apr_pools_initialized)
+        return;
 
-    for (p = p->sub_pools; p; p = p->sub_next) {
-	cleanup_pool_for_exec(p);
-    }
-}
+    apr_pool_destroy(global_pool); /* This will also destroy the mutex */
+    global_pool = NULL;
 
-API_EXPORT(void) ap_cleanup_for_exec(void)
-{
-#if !defined(WIN32) && !defined(OS2)
-    /*
-     * Don't need to do anything on NT or OS/2, because I
-     * am actually going to spawn the new process - not
-     * exec it. All handles that are not inheritable, will
-     * be automajically closed. The only problem is with
-     * file handles that are open, but there isn't much
-     * I can do about that (except if the child decides
-     * to go out and close them
-     */
-    ap_block_alarms();
-    cleanup_pool_for_exec(permanent_pool);
-    ap_unblock_alarms();
-#endif /* ndef WIN32 */
+    global_allocator = NULL;
 }
 
-API_EXPORT_NONSTD(ap_status_t) ap_null_cleanup(void *data)
-{
-    /* do nothing cleanup routine */
-    return APR_SUCCESS;
-}
 
-ap_status_t ap_init_alloc(void)
-{
-#if APR_HAS_THREADS
-    ap_status_t status;
-#endif
-#ifdef POOL_DEBUG
-    char s;
+/* Node list management helper macros; list_insert() inserts 'node'
+ * before 'point'. */
+#define list_insert(node, point) do {           \
+    node->ref = point->ref;                     \
+    *node->ref = node;                          \
+    node->next = point;                         \
+    point->ref = &node->next;                   \
+} while (0)
 
-    known_stack_point = &s;
-    stack_var_init(&s);
-#endif
-#if APR_HAS_THREADS
-    status = ap_create_lock(&alloc_mutex, APR_MUTEX, APR_INTRAPROCESS,
-                   NULL, NULL);
-    if (status != APR_SUCCESS) {
-        ap_destroy_lock(alloc_mutex); 
-        return status;
-    }
-    status = ap_create_lock(&spawn_mutex, APR_MUTEX, APR_INTRAPROCESS,
-                   NULL, NULL);
-    if (status != APR_SUCCESS) {
-        ap_destroy_lock(spawn_mutex); 
-        return status;
-    }
-#endif
+/* list_remove() removes 'node' from its list. */
+#define list_remove(node) do {                  \
+    *node->ref = node->next;                    \
+    node->next->ref = node->ref;                \
+} while (0)
 
-#ifdef ALLOC_STATS
-    atexit(dump_stats);
-#endif
+/* Returns the amount of free space in the given node. */
+#define node_free_space(node_) ((apr_size_t)(node_->endp - node_->first_avail))
 
-    return APR_SUCCESS;
-}
+/*
+ * Helpers to mark pool as in-use/free. Used for finding thread-unsafe
+ * concurrent accesses from different threads.
+ */
+#if APR_POOL_CONCURRENCY_CHECK
 
-void ap_term_alloc(void)
+static const char * const in_use_string[] = { "idle", "in use", "destroyed" };
+
+static void pool_concurrency_abort(apr_pool_t *pool, apr_uint32_t new, apr_uint32_t old)
 {
-#if APR_HAS_THREADS
-    ap_destroy_lock(alloc_mutex);
-    ap_destroy_lock(spawn_mutex);
-#endif
+    fprintf(stderr, "pool concurrency check: pool %p(%s), thread cur %lx "
+                    "in use by %lx, state %s -> %s \n",
+                    pool, pool->tag, (unsigned long)apr_os_thread_current(),
+                    (unsigned long)pool->in_use_by,
+                    in_use_string[old], in_use_string[new]);
+    abort();
 }
 
-/* We only want to lock the mutex if we are being called from ap_clear_pool.
- * This is because if we also call this function from ap_destroy_real_pool,
- * which also locks the same mutex, and recursive locks aren't portable.  
- * This way, we are garaunteed that we only lock this mutex once when calling
- * either one of these functions.
- */
-API_EXPORT(void) ap_clear_pool(ap_pool_t *a)
+static APR_INLINE void pool_concurrency_set_used(apr_pool_t *pool)
 {
-    ap_block_alarms();
+    apr_uint32_t old;
 
-    while (a->sub_pools) {
-	ap_destroy_pool(a->sub_pools);
-    }
-    /*
-     * Don't hold the mutex during cleanups.
-     */
-    run_cleanups(a->cleanups);
-    a->cleanups = NULL;
-    free_proc_chain(a->subprocesses);
-    a->subprocesses = NULL;
-    free_blocks(a->first->h.next);
-    a->first->h.next = NULL;
-
-    a->last = a->first;
-    a->first->h.first_avail = a->free_first_avail;
-    debug_fill(a->first->h.first_avail,
-	       a->first->h.endp - a->first->h.first_avail);
-
-#ifdef ALLOC_USE_MALLOC
-    {
-	void *c, *n;
+    old = apr_atomic_cas32(&pool->in_use, IN_USE, IDLE);
 
-	for (c = a->allocation_list; c; c = n) {
-	    n = *(void **)c;
-	    free(c);
-	}
-	a->allocation_list = NULL;
-    }
-#endif
+    if (old != IDLE)
+        pool_concurrency_abort(pool, IN_USE, old);
 
-    ap_unblock_alarms();
+    pool->in_use_by = apr_os_thread_current();
 }
 
-API_EXPORT(void) ap_destroy_pool(ap_pool_t *a)
+static APR_INLINE void pool_concurrency_set_idle(apr_pool_t *pool)
 {
-    ap_block_alarms();
-    ap_clear_pool(a);
-#if APR_HAS_THREADS
-    ap_lock(alloc_mutex);
-#endif
+    apr_uint32_t old;
 
-    if (a->parent) {
-	if (a->parent->sub_pools == a) {
-	    a->parent->sub_pools = a->sub_next;
-	}
-	if (a->sub_prev) {
-	    a->sub_prev->sub_next = a->sub_next;
-	}
-	if (a->sub_next) {
-	    a->sub_next->sub_prev = a->sub_prev;
-	}
-    }
-#if APR_HAS_THREADS
-    ap_unlock(alloc_mutex);
-#endif
-    free_blocks(a->first);
-    ap_unblock_alarms();
+    old = apr_atomic_cas32(&pool->in_use, IDLE, IN_USE);
+
+    if (old != IN_USE)
+        pool_concurrency_abort(pool, IDLE, old);
 }
 
-API_EXPORT(long) ap_bytes_in_pool(ap_pool_t *p)
+static APR_INLINE void pool_concurrency_init(apr_pool_t *pool)
 {
-    return bytes_in_block_list(p->first);
+    pool->in_use = IDLE;
 }
-API_EXPORT(long) ap_bytes_in_free_blocks(void)
+
+static APR_INLINE void pool_concurrency_set_destroyed(apr_pool_t *pool)
+{
+    apr_uint32_t old;
+
+    old = apr_atomic_cas32(&pool->in_use, DESTROYED, IDLE);
+
+    if (old != IDLE)
+        pool_concurrency_abort(pool, DESTROYED, old);
+    pool->in_use_by = apr_os_thread_current();
+}
+#else
+static APR_INLINE void pool_concurrency_init(apr_pool_t *pool)          { }
+static APR_INLINE void pool_concurrency_set_used(apr_pool_t *pool)      { }
+static APR_INLINE void pool_concurrency_set_idle(apr_pool_t *pool)      { }
+static APR_INLINE void pool_concurrency_set_destroyed(apr_pool_t *pool) { }
+#endif /* APR_POOL_CONCURRENCY_CHECK */
+
+/*
+ * Memory allocation
+ */
+
+APR_DECLARE(void *) apr_palloc(apr_pool_t *pool, apr_size_t in_size)
+{
+    apr_memnode_t *active, *node;
+    void *mem;
+    apr_size_t size, free_index;
+
+    pool_concurrency_set_used(pool);
+    size = APR_ALIGN_DEFAULT(in_size);
+#if HAVE_VALGRIND
+    if (apr_running_on_valgrind)
+        size += 2 * REDZONE;
+#endif
+    if (size < in_size) {
+        pool_concurrency_set_idle(pool);
+        if (pool->abort_fn)
+            pool->abort_fn(APR_ENOMEM);
+
+        return NULL;
+    }
+    active = pool->active;
+
+    /* If the active node has enough bytes left, use it. */
+    if (size <= node_free_space(active)) {
+        mem = active->first_avail;
+        active->first_avail += size;
+        goto have_mem;
+    }
+
+    node = active->next;
+    if (size <= node_free_space(node)) {
+        list_remove(node);
+    }
+    else {
+        if ((node = allocator_alloc(pool->allocator, size)) == NULL) {
+            pool_concurrency_set_idle(pool);
+            if (pool->abort_fn)
+                pool->abort_fn(APR_ENOMEM);
+
+            return NULL;
+        }
+    }
+
+    node->free_index = 0;
+
+    mem = node->first_avail;
+    node->first_avail += size;
+
+    list_insert(node, active);
+
+    pool->active = node;
+
+    free_index = (APR_ALIGN(active->endp - active->first_avail + 1,
+                            BOUNDARY_SIZE) - BOUNDARY_SIZE) >> BOUNDARY_INDEX;
+
+    active->free_index = free_index;
+    node = active->next;
+    if (free_index >= node->free_index)
+        goto have_mem;
+
+    do {
+        node = node->next;
+    }
+    while (free_index < node->free_index);
+
+    list_remove(active);
+    list_insert(active, node);
+
+have_mem:
+#if HAVE_VALGRIND
+    if (!apr_running_on_valgrind) {
+        pool_concurrency_set_idle(pool);
+        return mem;
+    }
+    else {
+        mem = (char *)mem + REDZONE;
+        VALGRIND_MEMPOOL_ALLOC(pool, mem, in_size);
+        pool_concurrency_set_idle(pool);
+        return mem;
+    }
+#else
+    pool_concurrency_set_idle(pool);
+    return mem;
+#endif
+}
+
+/* Provide an implementation of apr_pcalloc for backward compatibility
+ * with code built before apr_pcalloc was a macro
+ */
+
+#ifdef apr_pcalloc
+#undef apr_pcalloc
+#endif
+
+APR_DECLARE(void *) apr_pcalloc(apr_pool_t *pool, apr_size_t size);
+APR_DECLARE(void *) apr_pcalloc(apr_pool_t *pool, apr_size_t size)
+{
+    void *mem;
+
+    if ((mem = apr_palloc(pool, size)) != NULL) {
+        memset(mem, 0, size);
+    }
+
+    return mem;
+}
+
+
+/*
+ * Pool creation/destruction
+ */
+
+APR_DECLARE(void) apr_pool_clear(apr_pool_t *pool)
+{
+    apr_memnode_t *active;
+
+    /* Run pre destroy cleanups */
+    run_cleanups(&pool->pre_cleanups);
+
+    pool_concurrency_set_used(pool);
+    pool->pre_cleanups = NULL;
+    pool_concurrency_set_idle(pool);
+
+    /* Destroy the subpools.  The subpools will detach themselves from
+     * this pool thus this loop is safe and easy.
+     */
+    while (pool->child)
+        apr_pool_destroy(pool->child);
+
+    /* Run cleanups */
+    run_cleanups(&pool->cleanups);
+
+    pool_concurrency_set_used(pool);
+    pool->cleanups = NULL;
+    pool->free_cleanups = NULL;
+
+    /* Free subprocesses */
+    free_proc_chain(pool->subprocesses);
+    pool->subprocesses = NULL;
+
+    /* Clear the user data. */
+    pool->user_data = NULL;
+
+    /* Find the node attached to the pool structure, reset it, make
+     * it the active node and free the rest of the nodes.
+     */
+    active = pool->active = pool->self;
+    active->first_avail = pool->self_first_avail;
+
+    APR_IF_VALGRIND(VALGRIND_MEMPOOL_TRIM(pool, pool, 1));
+
+    if (active->next == active) {
+        pool_concurrency_set_idle(pool);
+        return;
+    }
+
+    *active->ref = NULL;
+    allocator_free(pool->allocator, active->next);
+    active->next = active;
+    active->ref = &active->next;
+
+    pool_concurrency_set_idle(pool);
+}
+
+APR_DECLARE(void) apr_pool_destroy(apr_pool_t *pool)
+{
+    apr_memnode_t *active;
+    apr_allocator_t *allocator;
+
+    /* Run pre destroy cleanups */
+    run_cleanups(&pool->pre_cleanups);
+
+    pool_concurrency_set_used(pool);
+    pool->pre_cleanups = NULL;
+    pool_concurrency_set_idle(pool);
+
+    /* Destroy the subpools.  The subpools will detach themselve from
+     * this pool thus this loop is safe and easy.
+     */
+    while (pool->child)
+        apr_pool_destroy(pool->child);
+
+    /* Run cleanups */
+    run_cleanups(&pool->cleanups);
+    pool_concurrency_set_destroyed(pool);
+
+    /* Free subprocesses */
+    free_proc_chain(pool->subprocesses);
+
+    /* Remove the pool from the parents child list */
+    if (pool->parent) {
+#if APR_HAS_THREADS
+        apr_thread_mutex_t *mutex;
+
+        if ((mutex = apr_allocator_mutex_get(pool->parent->allocator)) != NULL)
+            apr_thread_mutex_lock(mutex);
+#endif /* APR_HAS_THREADS */
+
+        if ((*pool->ref = pool->sibling) != NULL)
+            pool->sibling->ref = pool->ref;
+
+#if APR_HAS_THREADS
+        if (mutex)
+            apr_thread_mutex_unlock(mutex);
+#endif /* APR_HAS_THREADS */
+    }
+
+    /* Find the block attached to the pool structure.  Save a copy of the
+     * allocator pointer, because the pool struct soon will be no more.
+     */
+    allocator = pool->allocator;
+    active = pool->self;
+    *active->ref = NULL;
+
+#if APR_HAS_THREADS
+    if (apr_allocator_owner_get(allocator) == pool) {
+        /* Make sure to remove the lock, since it is highly likely to
+         * be invalid now.
+         */
+        apr_allocator_mutex_set(allocator, NULL);
+    }
+#endif /* APR_HAS_THREADS */
+
+    /* Free all the nodes in the pool (including the node holding the
+     * pool struct), by giving them back to the allocator.
+     */
+    allocator_free(allocator, active);
+
+    /* If this pool happens to be the owner of the allocator, free
+     * everything in the allocator (that includes the pool struct
+     * and the allocator).  Don't worry about destroying the optional mutex
+     * in the allocator, it will have been destroyed by the cleanup function.
+     */
+    if (apr_allocator_owner_get(allocator) == pool) {
+        apr_allocator_destroy(allocator);
+    }
+    APR_IF_VALGRIND(VALGRIND_DESTROY_MEMPOOL(pool));
+}
+
+APR_DECLARE(apr_status_t) apr_pool_create_ex(apr_pool_t **newpool,
+                                             apr_pool_t *parent,
+                                             apr_abortfunc_t abort_fn,
+                                             apr_allocator_t *allocator)
+{
+    apr_pool_t *pool;
+    apr_memnode_t *node;
+
+    *newpool = NULL;
+
+    if (!parent)
+        parent = global_pool;
+
+    /* parent will always be non-NULL here except the first time a
+     * pool is created, in which case allocator is guaranteed to be
+     * non-NULL. */
+
+    if (!abort_fn && parent)
+        abort_fn = parent->abort_fn;
+
+    if (allocator == NULL)
+        allocator = parent->allocator;
+
+    if ((node = allocator_alloc(allocator,
+                                MIN_ALLOC - APR_MEMNODE_T_SIZE)) == NULL) {
+        if (abort_fn)
+            abort_fn(APR_ENOMEM);
+
+        return APR_ENOMEM;
+    }
+
+    node->next = node;
+    node->ref = &node->next;
+
+#if HAVE_VALGRIND
+    if (!apr_running_on_valgrind) {
+        pool = (apr_pool_t *)node->first_avail;
+        pool->self_first_avail = (char *)pool + SIZEOF_POOL_T;
+    }
+    else {
+        pool = (apr_pool_t *)(node->first_avail + REDZONE);
+        pool->self_first_avail = (char *)pool + SIZEOF_POOL_T + 2 * REDZONE;
+        VALGRIND_MAKE_MEM_NOACCESS(pool->self_first_avail,
+                                   node->endp - pool->self_first_avail);
+        VALGRIND_CREATE_MEMPOOL(pool, REDZONE, 0);
+    }
+#else
+    pool = (apr_pool_t *)node->first_avail;
+    pool->self_first_avail = (char *)pool + SIZEOF_POOL_T;
+#endif
+    node->first_avail = pool->self_first_avail;
+
+    pool->allocator = allocator;
+    pool->active = pool->self = node;
+    pool->abort_fn = abort_fn;
+    pool->child = NULL;
+    pool->cleanups = NULL;
+    pool->free_cleanups = NULL;
+    pool->pre_cleanups = NULL;
+    pool->subprocesses = NULL;
+    pool->user_data = NULL;
+    pool->tag = NULL;
+
+#ifdef NETWARE
+    pool->owner_proc = (apr_os_proc_t)getnlmhandle();
+#endif /* defined(NETWARE) */
+
+    if ((pool->parent = parent) != NULL) {
+#if APR_HAS_THREADS
+        apr_thread_mutex_t *mutex;
+
+        if ((mutex = apr_allocator_mutex_get(parent->allocator)) != NULL)
+            apr_thread_mutex_lock(mutex);
+#endif /* APR_HAS_THREADS */
+
+        if ((pool->sibling = parent->child) != NULL)
+            pool->sibling->ref = &pool->sibling;
+
+        parent->child = pool;
+        pool->ref = &parent->child;
+
+#if APR_HAS_THREADS
+        if (mutex)
+            apr_thread_mutex_unlock(mutex);
+#endif /* APR_HAS_THREADS */
+    }
+    else {
+        pool->sibling = NULL;
+        pool->ref = NULL;
+    }
+
+    pool_concurrency_init(pool);
+
+    *newpool = pool;
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_pool_create_unmanaged_ex(apr_pool_t **newpool,
+                                                  apr_abortfunc_t abort_fn,
+                                                  apr_allocator_t *allocator)
+{
+    apr_pool_t *pool;
+    apr_memnode_t *node;
+    apr_allocator_t *pool_allocator;
+
+    *newpool = NULL;
+
+    if (!apr_pools_initialized)
+        return APR_ENOPOOL;
+    if ((pool_allocator = allocator) == NULL) {
+        if (apr_allocator_create(&pool_allocator) != APR_SUCCESS) {
+            if (abort_fn)
+                abort_fn(APR_ENOMEM);
+
+            return APR_ENOMEM;
+        }
+        if ((node = allocator_alloc(pool_allocator,
+                                    MIN_ALLOC - APR_MEMNODE_T_SIZE)) == NULL) {
+            if (abort_fn)
+                abort_fn(APR_ENOMEM);
+
+            return APR_ENOMEM;
+        }
+    }
+    else if ((node = allocator_alloc(pool_allocator,
+                                     MIN_ALLOC - APR_MEMNODE_T_SIZE)) == NULL) {
+        if (abort_fn)
+            abort_fn(APR_ENOMEM);
+
+        return APR_ENOMEM;
+    }
+
+    node->next = node;
+    node->ref = &node->next;
+
+    pool = (apr_pool_t *)node->first_avail;
+    node->first_avail = pool->self_first_avail = (char *)pool + SIZEOF_POOL_T;
+
+    pool->allocator = pool_allocator;
+    pool->active = pool->self = node;
+    pool->abort_fn = abort_fn;
+    pool->child = NULL;
+    pool->cleanups = NULL;
+    pool->free_cleanups = NULL;
+    pool->pre_cleanups = NULL;
+    pool->subprocesses = NULL;
+    pool->user_data = NULL;
+    pool->tag = NULL;
+    pool->parent = NULL;
+    pool->sibling = NULL;
+    pool->ref = NULL;
+
+#ifdef NETWARE
+    pool->owner_proc = (apr_os_proc_t)getnlmhandle();
+#endif /* defined(NETWARE) */
+    if (!allocator)
+        pool_allocator->owner = pool;
+
+    pool_concurrency_init(pool);
+    *newpool = pool;
+
+    return APR_SUCCESS;
+}
+
+/*
+ * "Print" functions
+ */
+
+/*
+ * apr_psprintf is implemented by writing directly into the current
+ * block of the pool, starting right at first_avail.  If there's
+ * insufficient room, then a new block is allocated and the earlier
+ * output is copied over.  The new block isn't linked into the pool
+ * until all the output is done.
+ *
+ * Note that this is completely safe because nothing else can
+ * allocate in this apr_pool_t while apr_psprintf is running.  alarms are
+ * blocked, and the only thing outside of apr_pools.c that's invoked
+ * is apr_vformatter -- which was purposefully written to be
+ * self-contained with no callouts.
+ */
+
+struct psprintf_data {
+    apr_vformatter_buff_t vbuff;
+    apr_memnode_t   *node;
+    apr_pool_t      *pool;
+    apr_byte_t       got_a_new_node;
+    apr_memnode_t   *free;
+};
+
+#define APR_PSPRINTF_MIN_STRINGSIZE 32
+
+static int psprintf_flush(apr_vformatter_buff_t *vbuff)
+{
+    struct psprintf_data *ps = (struct psprintf_data *)vbuff;
+    apr_memnode_t *node, *active;
+    apr_size_t cur_len, size;
+    char *strp;
+    apr_pool_t *pool;
+    apr_size_t free_index;
+
+    pool = ps->pool;
+    active = ps->node;
+    strp = ps->vbuff.curpos;
+    cur_len = strp - active->first_avail;
+    size = cur_len << 1;
+
+    /* Make sure that we don't try to use a block that has less
+     * than APR_PSPRINTF_MIN_STRINGSIZE bytes left in it.  This
+     * also catches the case where size == 0, which would result
+     * in reusing a block that can't even hold the NUL byte.
+     */
+    if (size < APR_PSPRINTF_MIN_STRINGSIZE)
+        size = APR_PSPRINTF_MIN_STRINGSIZE;
+
+    node = active->next;
+    if (!ps->got_a_new_node && size <= node_free_space(node)) {
+
+        list_remove(node);
+        list_insert(node, active);
+
+        node->free_index = 0;
+
+        pool->active = node;
+
+        free_index = (APR_ALIGN(active->endp - active->first_avail + 1,
+                                BOUNDARY_SIZE) - BOUNDARY_SIZE) >> BOUNDARY_INDEX;
+
+        active->free_index = free_index;
+        node = active->next;
+        if (free_index < node->free_index) {
+            do {
+                node = node->next;
+            }
+            while (free_index < node->free_index);
+
+            list_remove(active);
+            list_insert(active, node);
+        }
+
+        node = pool->active;
+    }
+    else {
+        if ((node = allocator_alloc(pool->allocator, size)) == NULL)
+            return -1;
+
+        if (ps->got_a_new_node) {
+            active->next = ps->free;
+            ps->free = active;
+        }
+
+        ps->got_a_new_node = 1;
+    }
+
+    APR_VALGRIND_UNDEFINED(node->first_avail,
+                           node->endp - node->first_avail);
+    memcpy(node->first_avail, active->first_avail, cur_len);
+    APR_VALGRIND_NOACCESS(active->first_avail,
+                          active->endp - active->first_avail);
+
+    ps->node = node;
+    ps->vbuff.curpos = node->first_avail + cur_len;
+    ps->vbuff.endpos = node->endp - 1; /* Save a byte for NUL terminator */
+
+    return 0;
+}
+
+#if HAVE_VALGRIND
+static int add_redzone(int (*flush_func)(apr_vformatter_buff_t *b),
+                       struct psprintf_data *ps)
+{
+    apr_size_t len = ps->vbuff.curpos - ps->node->first_avail + REDZONE;
+
+    while (ps->vbuff.curpos - ps->node->first_avail < len) {
+        if (ps->vbuff.endpos - ps->node->first_avail >= len)
+            ps->vbuff.curpos = ps->node->first_avail + len;
+        else
+            ps->vbuff.curpos = ps->vbuff.endpos;
+
+        /*
+         * Prevent valgrind from complaining when psprintf_flush()
+         * does a memcpy(). The VALGRIND_MEMPOOL_ALLOC() will reset
+         * the redzone to NOACCESS.
+         */
+        if (ps->vbuff.curpos != ps->node->first_avail)
+            VALGRIND_MAKE_MEM_DEFINED(ps->node->first_avail,
+                                      ps->vbuff.curpos - ps->node->first_avail);
+        if (ps->vbuff.curpos == ps->vbuff.endpos) {
+            if (psprintf_flush(&ps->vbuff) == -1)
+                return -1;
+        }
+    }
+    return 0;
+}
+#endif
+
+APR_DECLARE(char *) apr_pvsprintf(apr_pool_t *pool, const char *fmt, va_list ap)
+{
+    struct psprintf_data ps;
+    char *strp;
+    apr_size_t size;
+    apr_memnode_t *active, *node;
+    apr_size_t free_index;
+
+    pool_concurrency_set_used(pool);
+    ps.node = active = pool->active;
+    ps.pool = pool;
+    ps.vbuff.curpos  = ps.node->first_avail;
+
+    /* Save a byte for the NUL terminator */
+    ps.vbuff.endpos = ps.node->endp - 1;
+    ps.got_a_new_node = 0;
+    ps.free = NULL;
+
+    /* Make sure that the first node passed to apr_vformatter has at least
+     * room to hold the NUL terminator.
+     */
+    if (ps.node->first_avail == ps.node->endp) {
+        if (psprintf_flush(&ps.vbuff) == -1)
+            goto error;
+    }
+#if HAVE_VALGRIND
+    if (apr_running_on_valgrind) {
+        if (add_redzone(psprintf_flush, &ps) == -1)
+            goto error;
+        if (!ps.got_a_new_node) {
+            /* psprintf_flush() has not been called, allow access to our node */
+            VALGRIND_MAKE_MEM_UNDEFINED(ps.vbuff.curpos,
+                                        ps.node->endp - ps.vbuff.curpos);
+        }
+    }
+#endif /* HAVE_VALGRIND */
+
+    if (apr_vformatter(psprintf_flush, &ps.vbuff, fmt, ap) == -1)
+        goto error;
+
+    *ps.vbuff.curpos++ = '\0';
+
+#if HAVE_VALGRIND
+    if (!apr_running_on_valgrind) {
+        strp = ps.node->first_avail;
+    }
+    else {
+        if (add_redzone(psprintf_flush, &ps) == -1)
+            goto error;
+        if (ps.node->endp != ps.vbuff.curpos)
+            APR_VALGRIND_NOACCESS(ps.vbuff.curpos,
+                                  ps.node->endp - ps.vbuff.curpos);
+        strp = ps.node->first_avail + REDZONE;
+        size = ps.vbuff.curpos - strp;
+        VALGRIND_MEMPOOL_ALLOC(pool, strp, size);
+        VALGRIND_MAKE_MEM_DEFINED(strp, size);
+    }
+#else
+    strp = ps.node->first_avail;
+#endif
+
+    size = ps.vbuff.curpos - ps.node->first_avail;
+    size = APR_ALIGN_DEFAULT(size);
+    ps.node->first_avail += size;
+
+    if (ps.free)
+        allocator_free(pool->allocator, ps.free);
+
+    /*
+     * Link the node in if it's a new one
+     */
+    if (!ps.got_a_new_node) {
+        pool_concurrency_set_idle(pool);
+        return strp;
+    }
+
+    active = pool->active;
+    node = ps.node;
+
+    node->free_index = 0;
+
+    list_insert(node, active);
+
+    pool->active = node;
+
+    free_index = (APR_ALIGN(active->endp - active->first_avail + 1,
+                            BOUNDARY_SIZE) - BOUNDARY_SIZE) >> BOUNDARY_INDEX;
+
+    active->free_index = free_index;
+    node = active->next;
+
+    if (free_index >= node->free_index) {
+        pool_concurrency_set_idle(pool);
+        return strp;
+    }
+
+    do {
+        node = node->next;
+    }
+    while (free_index < node->free_index);
+
+    list_remove(active);
+    list_insert(active, node);
+
+    pool_concurrency_set_idle(pool);
+    return strp;
+
+error:
+    pool_concurrency_set_idle(pool);
+    if (pool->abort_fn)
+        pool->abort_fn(APR_ENOMEM);
+    if (ps.got_a_new_node) {
+        ps.node->next = ps.free;
+        allocator_free(pool->allocator, ps.node);
+    }
+    APR_VALGRIND_NOACCESS(pool->active->first_avail,
+                          pool->active->endp - pool->active->first_avail);
+    return NULL;
+}
+
+
+#else /* APR_POOL_DEBUG */
+/*
+ * Debug helper functions
+ */
+
+
+/*
+ * Walk the pool tree rooted at pool, depth first.  When fn returns
+ * anything other than 0, abort the traversal and return the value
+ * returned by fn.
+ */
+static int apr_pool_walk_tree(apr_pool_t *pool,
+                              int (*fn)(apr_pool_t *pool, void *data),
+                              void *data)
+{
+    int rv;
+    apr_pool_t *child;
+
+    rv = fn(pool, data);
+    if (rv)
+        return rv;
+
+#if APR_HAS_THREADS
+    if (pool->mutex) {
+        apr_thread_mutex_lock(pool->mutex);
+                        }
+#endif /* APR_HAS_THREADS */
+
+    child = pool->child;
+    while (child) {
+        rv = apr_pool_walk_tree(child, fn, data);
+        if (rv)
+            break;
+
+        child = child->sibling;
+    }
+
+#if APR_HAS_THREADS
+    if (pool->mutex) {
+        apr_thread_mutex_unlock(pool->mutex);
+    }
+#endif /* APR_HAS_THREADS */
+
+    return rv;
+}
+
+#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL)
+static void apr_pool_log_event(apr_pool_t *pool, const char *event,
+                               const char *file_line, int deref)
+{
+    if (file_stderr) {
+        if (deref) {
+            apr_file_printf(file_stderr,
+                "POOL DEBUG: "
+                "[%lu"
+#if APR_HAS_THREADS
+                "/%lu"
+#endif /* APR_HAS_THREADS */
+                "] "
+                "%7s "
+                "(%10lu/%10lu/%10lu) "
+                "0x%pp \"%s\" "
+                "<%s> "
+                "0x%pp "
+                "(%u/%u/%u) "
+                "\n",
+                (unsigned long)getpid(),
+#if APR_HAS_THREADS
+                (unsigned long)apr_os_thread_current(),
+#endif /* APR_HAS_THREADS */
+                event,
+                (unsigned long)apr_pool_num_bytes(pool, 0),
+                (unsigned long)apr_pool_num_bytes(pool, 1),
+                (unsigned long)apr_pool_num_bytes(global_pool, 1),
+                pool, pool->tag,
+                file_line,
+                pool->parent,
+                pool->stat_alloc, pool->stat_total_alloc, pool->stat_clear);
+        }
+        else {
+            apr_file_printf(file_stderr,
+                "POOL DEBUG: "
+                "[%lu"
+#if APR_HAS_THREADS
+                "/%lu"
+#endif /* APR_HAS_THREADS */
+                "] "
+                "%7s "
+                "                                   "
+                "0x%pp "
+                "<%s> "
+                "\n",
+                (unsigned long)getpid(),
+#if APR_HAS_THREADS
+                (unsigned long)apr_os_thread_current(),
+#endif /* APR_HAS_THREADS */
+                event,
+                pool,
+                file_line);
+        }
+    }
+}
+#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL) */
+
+#if (APR_POOL_DEBUG & APR_POOL_DEBUG_LIFETIME)
+static int pool_is_child_of(apr_pool_t *parent, void *data)
+{
+    apr_pool_t *pool = (apr_pool_t *)data;
+
+    return (pool == parent);
+}
+
+static int apr_pool_is_child_of(apr_pool_t *pool, apr_pool_t *parent)
+{
+    if (parent == NULL)
+        return 0;
+
+    return apr_pool_walk_tree(parent, pool_is_child_of, pool);
+}
+#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_LIFETIME) */
+
+static void apr_pool_check_lifetime(apr_pool_t *pool)
+{
+    /* Rule of thumb: use of the global pool is always
+     * ok, since the only user is apr_pools.c.  Unless
+     * people have searched for the top level parent and
+     * started to use that...
+     */
+    if (pool == global_pool || global_pool == NULL)
+        return;
+
+    /* Lifetime
+     * This basically checks to see if the pool being used is still
+     * a relative to the global pool.  If not it was previously
+     * destroyed, in which case we abort().
+     */
+#if (APR_POOL_DEBUG & APR_POOL_DEBUG_LIFETIME)
+    if (!apr_pool_is_child_of(pool, global_pool)) {
+#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL)
+        apr_pool_log_event(pool, "LIFE",
+                           __FILE__ ":apr_pool_integrity check [lifetime]", 0);
+#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL) */
+        abort();
+    }
+#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_LIFETIME) */
+}
+
+static void apr_pool_check_owner(apr_pool_t *pool)
+{
+#if (APR_POOL_DEBUG & APR_POOL_DEBUG_OWNER)
+#if APR_HAS_THREADS
+    if (!apr_os_thread_equal(pool->owner, apr_os_thread_current())) {
+#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL)
+        apr_pool_log_event(pool, "THREAD",
+                           __FILE__ ":apr_pool_integrity check [owner]", 0);
+#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL) */
+        abort();
+    }
+#endif /* APR_HAS_THREADS */
+#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_OWNER) */
+}
+
+static void apr_pool_check_integrity(apr_pool_t *pool)
+{
+    apr_pool_check_lifetime(pool);
+    apr_pool_check_owner(pool);
+}
+
+APR_DECLARE(void) apr_pool_owner_set(apr_pool_t *pool, apr_uint32_t flags)
+{
+#if APR_HAS_THREADS && (APR_POOL_DEBUG & APR_POOL_DEBUG_OWNER)
+    pool->owner = apr_os_thread_current();
+#endif
+}
+
+/*
+ * Initialization (debug)
+ */
+
+APR_DECLARE(apr_status_t) apr_pool_initialize(void)
+{
+    apr_status_t rv;
+#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL)
+    char *logpath;
+    apr_file_t *debug_log = NULL;
+#endif
+
+    if (apr_pools_initialized++)
+        return APR_SUCCESS;
+
+#if defined(_SC_PAGESIZE)
+    boundary_size = sysconf(_SC_PAGESIZE);
+#elif defined(WIN32)
+    {
+        SYSTEM_INFO si;
+        GetSystemInfo(&si);
+        boundary_size = si.dwPageSize;
+    }
+#endif
+    boundary_index = 12;
+    while ( (1 << boundary_index) < boundary_size)
+        boundary_index++;
+    boundary_size = (1 << boundary_index);
+
+    /* Since the debug code works a bit differently then the
+     * regular pools code, we ask for a lock here.  The regular
+     * pools code has got this lock embedded in the global
+     * allocator, a concept unknown to debug mode.
+     */
+    if ((rv = apr_pool_create_ex(&global_pool, NULL, NULL,
+                                 NULL)) != APR_SUCCESS) {
+        return rv;
+    }
+
+    apr_pool_tag(global_pool, "APR global pool");
+
+    apr_pools_initialized = 1;
+
+    /* This has to happen here because mutexes might be backed by
+     * atomics.  It used to be snug and safe in apr_initialize().
+     */
+    if ((rv = apr_atomic_init(global_pool)) != APR_SUCCESS) {
+        return rv;
+    }
+
+#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL)
+    rv = apr_env_get(&logpath, "APR_POOL_DEBUG_LOG", global_pool);
+
+    /* Don't pass file_stderr directly to apr_file_open() here, since
+     * apr_file_open() can call back to apr_pool_log_event() and that
+     * may attempt to use then then non-NULL but partially set up file
+     * object. */
+    if (rv == APR_SUCCESS) {
+        apr_file_open(&debug_log, logpath,
+                      APR_FOPEN_APPEND|APR_FOPEN_WRITE|APR_FOPEN_CREATE,
+                      APR_FPROT_OS_DEFAULT, global_pool);
+    }
+    else {
+        apr_file_open_stderr(&debug_log, global_pool);
+    }
+
+    /* debug_log is now a file handle. */
+    file_stderr = debug_log;
+
+    if (file_stderr) {
+        apr_file_printf(file_stderr,
+            "POOL DEBUG: [PID"
+#if APR_HAS_THREADS
+            "/TID"
+#endif /* APR_HAS_THREADS */
+            "] ACTION  (SIZE      /POOL SIZE /TOTAL SIZE) "
+            "POOL       \"TAG\" <__FILE__:__LINE__> PARENT     (ALLOCS/TOTAL ALLOCS/CLEARS)\n");
+
+        apr_pool_log_event(global_pool, "GLOBAL", __FILE__ ":apr_pool_initialize", 0);
+
+        /* Add a cleanup handler that sets the debug log file handle
+         * to NULL, otherwise we'll try to log the global pool
+         * destruction event with predictably disastrous results. */
+        apr_pool_cleanup_register(global_pool, NULL,
+                                  apr_pool_cleanup_file_stderr,
+                                  apr_pool_cleanup_null);
+    }
+#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL) */
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(void) apr_pool_terminate(void)
+{
+    if (!apr_pools_initialized)
+        return;
+
+    if (--apr_pools_initialized)
+        return;
+
+    apr_pool_destroy(global_pool); /* This will also destroy the mutex */
+    global_pool = NULL;
+
+#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL)
+    file_stderr = NULL;
+#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL) */
+}
+
+
+/*
+ * Memory allocation (debug)
+ */
+
+static void *pool_alloc(apr_pool_t *pool, apr_size_t size)
+{
+    debug_node_t *node;
+    void *mem;
+
+    if ((mem = malloc(size)) == NULL) {
+        if (pool->abort_fn)
+            pool->abort_fn(APR_ENOMEM);
+
+        return NULL;
+    }
+
+    node = pool->nodes;
+    if (node == NULL || node->index == 64) {
+        if ((node = malloc(SIZEOF_DEBUG_NODE_T)) == NULL) {
+            free(mem);
+            if (pool->abort_fn)
+                pool->abort_fn(APR_ENOMEM);
+
+            return NULL;
+        }
+
+        memset(node, 0, SIZEOF_DEBUG_NODE_T);
+
+        node->next = pool->nodes;
+        pool->nodes = node;
+        node->index = 0;
+    }
+
+    node->beginp[node->index] = mem;
+    node->endp[node->index] = (char *)mem + size;
+    node->index++;
+
+    pool->stat_alloc++;
+    pool->stat_total_alloc++;
+
+    return mem;
+}
+
+APR_DECLARE(void *) apr_palloc_debug(apr_pool_t *pool, apr_size_t size,
+                                     const char *file_line)
+{
+    void *mem;
+
+    apr_pool_check_integrity(pool);
+
+    mem = pool_alloc(pool, size);
+
+#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALLOC)
+    apr_pool_log_event(pool, "PALLOC", file_line, 1);
+#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALLOC) */
+
+    return mem;
+}
+
+APR_DECLARE(void *) apr_pcalloc_debug(apr_pool_t *pool, apr_size_t size,
+                                      const char *file_line)
+{
+    void *mem;
+
+    apr_pool_check_integrity(pool);
+
+    mem = pool_alloc(pool, size);
+    memset(mem, 0, size);
+
+#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALLOC)
+    apr_pool_log_event(pool, "PCALLOC", file_line, 1);
+#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALLOC) */
+
+    return mem;
+}
+
+
+/*
+ * Pool creation/destruction (debug)
+ */
+
+#define POOL_POISON_BYTE 'A'
+
+static void pool_clear_debug(apr_pool_t *pool, const char *file_line)
+{
+    debug_node_t *node;
+    apr_size_t index;
+
+    /* Run pre destroy cleanups */
+    run_cleanups(&pool->pre_cleanups);
+    pool->pre_cleanups = NULL;
+
+    /*
+     * Now that we have given the pre cleanups the chance to kill of any
+     * threads using the pool, the owner must be correct.
+     */
+    apr_pool_check_owner(pool);
+
+    /* Destroy the subpools.  The subpools will detach themselves from
+     * this pool thus this loop is safe and easy.
+     */
+    while (pool->child)
+        pool_destroy_debug(pool->child, file_line);
+
+    /* Run cleanups */
+    run_cleanups(&pool->cleanups);
+    pool->free_cleanups = NULL;
+    pool->cleanups = NULL;
+
+    /* If new child pools showed up, this is a reason to raise a flag */
+    if (pool->child)
+        abort();
+
+    /* Free subprocesses */
+    free_proc_chain(pool->subprocesses);
+    pool->subprocesses = NULL;
+
+    /* Clear the user data. */
+    pool->user_data = NULL;
+
+    /* Free the blocks, scribbling over them first to help highlight
+     * use-after-free issues. */
+    while ((node = pool->nodes) != NULL) {
+        pool->nodes = node->next;
+
+        for (index = 0; index < node->index; index++) {
+            memset(node->beginp[index], POOL_POISON_BYTE,
+                   (char *)node->endp[index] - (char *)node->beginp[index]);
+            free(node->beginp[index]);
+        }
+
+        memset(node, POOL_POISON_BYTE, SIZEOF_DEBUG_NODE_T);
+        free(node);
+    }
+
+    pool->stat_alloc = 0;
+    pool->stat_clear++;
+}
+
+APR_DECLARE(void) apr_pool_clear_debug(apr_pool_t *pool,
+                                       const char *file_line)
+{
+#if APR_HAS_THREADS
+    apr_thread_mutex_t *mutex = NULL;
+#endif
+
+    apr_pool_check_lifetime(pool);
+
+#if APR_HAS_THREADS
+    if (pool->parent != NULL)
+        mutex = pool->parent->mutex;
+
+    /* Lock the parent mutex before clearing so that if we have our
+     * own mutex it won't be accessed by apr_pool_walk_tree after
+     * it has been destroyed.
+     */
+    if (mutex != NULL && mutex != pool->mutex) {
+        apr_thread_mutex_lock(mutex);
+    }
+#endif
+
+    pool_clear_debug(pool, file_line);
+
+#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE)
+    apr_pool_log_event(pool, "CLEAR", file_line, 1);
+#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE) */
+
+#if APR_HAS_THREADS
+    /* If we had our own mutex, it will have been destroyed by
+     * the registered cleanups.  Recreate the mutex.  Unlock
+     * the mutex we obtained above.
+     */
+    if (mutex != pool->mutex) {
+        /*
+         * Prevent apr_palloc() in apr_thread_mutex_create() from trying to
+         * use the destroyed mutex.
+         */
+        pool->mutex = NULL;
+        (void)apr_thread_mutex_create(&pool->mutex,
+                                      APR_THREAD_MUTEX_NESTED, pool);
+
+        if (mutex != NULL)
+            (void)apr_thread_mutex_unlock(mutex);
+    }
+#endif /* APR_HAS_THREADS */
+}
+
+static void pool_destroy_debug(apr_pool_t *pool, const char *file_line)
+{
+    apr_pool_check_lifetime(pool);
+
+    pool_clear_debug(pool, file_line);
+
+#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE)
+    apr_pool_log_event(pool, "DESTROY", file_line, 1);
+#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE) */
+
+    /* Remove the pool from the parents child list */
+    if (pool->parent) {
+#if APR_HAS_THREADS
+        apr_thread_mutex_t *mutex;
+
+        if ((mutex = pool->parent->mutex) != NULL)
+            apr_thread_mutex_lock(mutex);
+#endif /* APR_HAS_THREADS */
+
+        if ((*pool->ref = pool->sibling) != NULL)
+            pool->sibling->ref = pool->ref;
+
+#if APR_HAS_THREADS
+        if (mutex)
+            apr_thread_mutex_unlock(mutex);
+#endif /* APR_HAS_THREADS */
+    }
+
+    if (pool->allocator != NULL
+        && apr_allocator_owner_get(pool->allocator) == pool) {
+        apr_allocator_destroy(pool->allocator);
+    }
+
+    /* Free the pool itself */
+    free(pool);
+}
+
+APR_DECLARE(void) apr_pool_destroy_debug(apr_pool_t *pool,
+                                         const char *file_line)
+{
+    if (pool->joined) {
+        /* Joined pools must not be explicitly destroyed; the caller
+         * has broken the guarantee. */
+#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL)
+        apr_pool_log_event(pool, "LIFE",
+                           __FILE__ ":apr_pool_destroy abort on joined", 0);
+#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL) */
+
+        abort();
+    }
+    pool_destroy_debug(pool, file_line);
+}
+
+APR_DECLARE(apr_status_t) apr_pool_create_ex_debug(apr_pool_t **newpool,
+                                                   apr_pool_t *parent,
+                                                   apr_abortfunc_t abort_fn,
+                                                   apr_allocator_t *allocator,
+                                                   const char *file_line)
+{
+    apr_pool_t *pool;
+
+    *newpool = NULL;
+
+    if (!parent) {
+        parent = global_pool;
+    }
+    else {
+       apr_pool_check_lifetime(parent);
+
+       if (!allocator)
+           allocator = parent->allocator;
+    }
+
+    if (!abort_fn && parent)
+        abort_fn = parent->abort_fn;
+
+    if ((pool = malloc(SIZEOF_POOL_T)) == NULL) {
+        if (abort_fn)
+            abort_fn(APR_ENOMEM);
+
+         return APR_ENOMEM;
+    }
+
+    memset(pool, 0, SIZEOF_POOL_T);
+
+    pool->allocator = allocator;
+    pool->abort_fn = abort_fn;
+    pool->tag = file_line;
+    pool->file_line = file_line;
+
+    if ((pool->parent = parent) != NULL) {
+#if APR_HAS_THREADS
+        if (parent->mutex)
+            apr_thread_mutex_lock(parent->mutex);
+#endif /* APR_HAS_THREADS */
+        if ((pool->sibling = parent->child) != NULL)
+            pool->sibling->ref = &pool->sibling;
+
+        parent->child = pool;
+        pool->ref = &parent->child;
+
+#if APR_HAS_THREADS
+        if (parent->mutex)
+            apr_thread_mutex_unlock(parent->mutex);
+#endif /* APR_HAS_THREADS */
+    }
+    else {
+        pool->sibling = NULL;
+        pool->ref = NULL;
+    }
+
+#if APR_HAS_THREADS
+    pool->owner = apr_os_thread_current();
+#endif /* APR_HAS_THREADS */
+#ifdef NETWARE
+    pool->owner_proc = (apr_os_proc_t)getnlmhandle();
+#endif /* defined(NETWARE) */
+
+#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE)
+    apr_pool_log_event(pool, "CREATE", file_line, 1);
+#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE) */
+
+    if (parent == NULL || parent->allocator != allocator) {
+#if APR_HAS_THREADS
+        apr_status_t rv;
+
+        /* No matter what the creation flags say, always create
+         * a lock.  Without it integrity_check and apr_pool_num_bytes
+         * blow up (because they traverse pools child lists that
+         * possibly belong to another thread, in combination with
+         * the pool having no lock).  However, this might actually
+         * hide problems like creating a child pool of a pool
+         * belonging to another thread.
+         */
+        if ((rv = apr_thread_mutex_create(&pool->mutex,
+                APR_THREAD_MUTEX_NESTED, pool)) != APR_SUCCESS) {
+            free(pool);
+            return rv;
+        }
+#endif /* APR_HAS_THREADS */
+    }
+    else {
+#if APR_HAS_THREADS
+        if (parent)
+            pool->mutex = parent->mutex;
+#endif /* APR_HAS_THREADS */
+    }
+
+    *newpool = pool;
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_pool_create_unmanaged_ex_debug(apr_pool_t **newpool,
+                                                   apr_abortfunc_t abort_fn,
+                                                   apr_allocator_t *allocator,
+                                                   const char *file_line)
+{
+    apr_pool_t *pool;
+    apr_allocator_t *pool_allocator;
+
+    *newpool = NULL;
+
+    if ((pool = malloc(SIZEOF_POOL_T)) == NULL) {
+        if (abort_fn)
+            abort_fn(APR_ENOMEM);
+
+         return APR_ENOMEM;
+    }
+
+    memset(pool, 0, SIZEOF_POOL_T);
+
+    pool->abort_fn = abort_fn;
+    pool->tag = file_line;
+    pool->file_line = file_line;
+
+#if APR_HAS_THREADS
+    pool->owner = apr_os_thread_current();
+#endif /* APR_HAS_THREADS */
+#ifdef NETWARE
+    pool->owner_proc = (apr_os_proc_t)getnlmhandle();
+#endif /* defined(NETWARE) */
+
+    if ((pool_allocator = allocator) == NULL) {
+        apr_status_t rv;
+        if ((rv = apr_allocator_create(&pool_allocator)) != APR_SUCCESS) {
+            if (abort_fn)
+                abort_fn(rv);
+            return rv;
+        }
+        pool_allocator->owner = pool;
+    }
+    pool->allocator = pool_allocator;
+
+#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE)
+    apr_pool_log_event(pool, "CREATEU", file_line, 1);
+#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE) */
+
+    if (pool->allocator != allocator) {
+#if APR_HAS_THREADS
+        apr_status_t rv;
+
+        /* No matter what the creation flags say, always create
+         * a lock.  Without it integrity_check and apr_pool_num_bytes
+         * blow up (because they traverse pools child lists that
+         * possibly belong to another thread, in combination with
+         * the pool having no lock).  However, this might actually
+         * hide problems like creating a child pool of a pool
+         * belonging to another thread.
+         */
+        if ((rv = apr_thread_mutex_create(&pool->mutex,
+                APR_THREAD_MUTEX_NESTED, pool)) != APR_SUCCESS) {
+            free(pool);
+            return rv;
+        }
+#endif /* APR_HAS_THREADS */
+    }
+
+    *newpool = pool;
+
+    return APR_SUCCESS;
+}
+
+/*
+ * "Print" functions (debug)
+ */
+
+struct psprintf_data {
+    apr_vformatter_buff_t vbuff;
+    char      *mem;
+    apr_size_t size;
+};
+
+static int psprintf_flush(apr_vformatter_buff_t *vbuff)
+{
+    struct psprintf_data *ps = (struct psprintf_data *)vbuff;
+    apr_size_t size;
+
+    size = ps->vbuff.curpos - ps->mem;
+
+    ps->size <<= 1;
+    if ((ps->mem = realloc(ps->mem, ps->size)) == NULL)
+        return -1;
+
+    ps->vbuff.curpos = ps->mem + size;
+    ps->vbuff.endpos = ps->mem + ps->size - 1;
+
+    return 0;
+}
+
+APR_DECLARE(char *) apr_pvsprintf(apr_pool_t *pool, const char *fmt, va_list ap)
+{
+    struct psprintf_data ps;
+    debug_node_t *node;
+
+    apr_pool_check_integrity(pool);
+
+    ps.size = 64;
+    ps.mem = malloc(ps.size);
+    ps.vbuff.curpos  = ps.mem;
+
+    /* Save a byte for the NUL terminator */
+    ps.vbuff.endpos = ps.mem + ps.size - 1;
+
+    if (apr_vformatter(psprintf_flush, &ps.vbuff, fmt, ap) == -1) {
+        if (pool->abort_fn)
+            pool->abort_fn(APR_ENOMEM);
+
+        return NULL;
+    }
+
+    *ps.vbuff.curpos++ = '\0';
+
+    /*
+     * Link the node in
+     */
+    node = pool->nodes;
+    if (node == NULL || node->index == 64) {
+        if ((node = malloc(SIZEOF_DEBUG_NODE_T)) == NULL) {
+            if (pool->abort_fn)
+                pool->abort_fn(APR_ENOMEM);
+
+            return NULL;
+        }
+
+        node->next = pool->nodes;
+        pool->nodes = node;
+        node->index = 0;
+    }
+
+    node->beginp[node->index] = ps.mem;
+    node->endp[node->index] = ps.mem + ps.size;
+    node->index++;
+
+    return ps.mem;
+}
+
+
+/*
+ * Debug functions
+ */
+
+APR_DECLARE(void) apr_pool_join(apr_pool_t *p, apr_pool_t *sub)
+{
+#if APR_POOL_DEBUG
+    if (sub->parent != p) {
+        abort();
+    }
+    sub->joined = p;
+#endif
+}
+
+static int pool_find(apr_pool_t *pool, void *data)
+{
+    void **pmem = (void **)data;
+    debug_node_t *node;
+    apr_size_t index;
+
+    node = pool->nodes;
+
+    while (node) {
+        for (index = 0; index < node->index; index++) {
+             if (node->beginp[index] <= *pmem
+                 && node->endp[index] > *pmem) {
+                 *pmem = pool;
+                 return 1;
+             }
+        }
+
+        node = node->next;
+    }
+
+    return 0;
+}
+
+APR_DECLARE(apr_pool_t *) apr_pool_find(const void *mem)
+{
+    void *pool = (void *)mem;
+
+    if (apr_pool_walk_tree(global_pool, pool_find, &pool))
+        return pool;
+
+    return NULL;
+}
+
+static int pool_num_bytes(apr_pool_t *pool, void *data)
+{
+    apr_size_t *psize = (apr_size_t *)data;
+    debug_node_t *node;
+    apr_size_t index;
+
+    node = pool->nodes;
+
+    while (node) {
+        for (index = 0; index < node->index; index++) {
+            *psize += (char *)node->endp[index] - (char *)node->beginp[index];
+        }
+
+        node = node->next;
+    }
+
+    return 0;
+}
+
+APR_DECLARE(apr_size_t) apr_pool_num_bytes(apr_pool_t *pool, int recurse)
+{
+    apr_size_t size = 0;
+
+    if (!recurse) {
+        pool_num_bytes(pool, &size);
+
+        return size;
+    }
+
+    apr_pool_walk_tree(pool, pool_num_bytes, &size);
+
+    return size;
+}
+
+APR_DECLARE(void) apr_pool_lock(apr_pool_t *pool, int flag)
 {
-    return bytes_in_block_list(block_freelist);
 }
 
-/*****************************************************************
- * POOL_DEBUG support
- */
-#ifdef POOL_DEBUG
+#endif /* !APR_POOL_DEBUG */
+
+#ifdef NETWARE
+void netware_pool_proc_cleanup ()
+{
+    apr_pool_t *pool = global_pool->child;
+    apr_os_proc_t owner_proc = (apr_os_proc_t)getnlmhandle();
+
+    while (pool) {
+        if (pool->owner_proc == owner_proc) {
+            apr_pool_destroy (pool);
+            pool = global_pool->child;
+        }
+        else {
+            pool = pool->sibling;
+        }
+    }
+    return;
+}
+#endif /* defined(NETWARE) */
+
 
-/* the unix linker defines this symbol as the last byte + 1 of
- * the executable... so it includes TEXT, BSS, and DATA
+/*
+ * "Print" functions (common)
  */
-extern char _end;
 
-/* is ptr in the range [lo,hi) */
-#define is_ptr_in_range(ptr, lo, hi) \
-    (((unsigned long)(ptr) - (unsigned long)(lo)) \
-     < (unsigned long)(hi) - (unsigned long)(lo))
+APR_DECLARE_NONSTD(char *) apr_psprintf(apr_pool_t *p, const char *fmt, ...)
+{
+    va_list ap;
+    char *res;
+
+    va_start(ap, fmt);
+    res = apr_pvsprintf(p, fmt, ap);
+    va_end(ap);
+    return res;
+}
 
-/* Find the pool that ts belongs to, return NULL if it doesn't
- * belong to any pool.
+/*
+ * Pool Properties
  */
-API_EXPORT(ap_pool_t *) ap_find_pool(const void *ts, int (apr_abort)(int retcode))
+
+APR_DECLARE(void) apr_pool_abort_set(apr_abortfunc_t abort_fn,
+                                     apr_pool_t *pool)
 {
-    const char *s = ts;
-    union block_hdr **pb;
-    union block_hdr *b;
+    pool->abort_fn = abort_fn;
+}
 
-    /* short-circuit stuff which is in TEXT, BSS, or DATA */
-    if (is_ptr_in_range(s, 0, &_end)) {
-	return NULL;
-    }
-    /* consider stuff on the stack to also be in the NULL pool...
-     * XXX: there's cases where we don't want to assume this
-     */
-    APR_ABORT((stack_direction == -1 && 
-              is_ptr_in_range(s, &ts, known_stack_point)) || 
-              (stack_direction == 1 &&    
-              is_ptr_in_range(s, known_stack_point, &ts)), 1, apr_abort,
-              "Ouch!  find_pool() called on pointer in a free block\n");
-    ap_block_alarms();
-    /* search the global_block_list */
-    for (pb = &global_block_list; *pb; pb = &b->h.global_next) {
-	b = *pb;
-	if (is_ptr_in_range(s, b, b->h.endp)) {
-	    if (b->h.owning_pool == FREE_POOL) {
-		abort();
-		exit(1);
-	    }
-	    if (b != global_block_list) {
-		/*
-		 * promote b to front of list, this is a hack to speed
-		 * up the lookup
-		 */
-		*pb = b->h.global_next;
-		b->h.global_next = global_block_list;
-		global_block_list = b;
-	    }
-	    ap_unblock_alarms();
-	    return b->h.owning_pool;
-	}
-    }
-    ap_unblock_alarms();
-    return NULL;
+APR_DECLARE(apr_abortfunc_t) apr_pool_abort_get(apr_pool_t *pool)
+{
+    return pool->abort_fn;
+}
+
+APR_DECLARE(apr_pool_t *) apr_pool_parent_get(apr_pool_t *pool)
+{
+#ifdef NETWARE
+    /* On NetWare, don't return the global_pool, return the application pool 
+       as the top most pool */
+    if (pool->parent == global_pool)
+        return pool;
+    else
+#endif
+    return pool->parent;
+}
+
+APR_DECLARE(apr_allocator_t *) apr_pool_allocator_get(apr_pool_t *pool)
+{
+    return pool->allocator;
 }
 
-/* return TRUE iff a is an ancestor of b
+/* return TRUE if a is an ancestor of b
  * NULL is considered an ancestor of all pools
  */
-API_EXPORT(int) ap_pool_is_ancestor(ap_pool_t *a, ap_pool_t *b)
+APR_DECLARE(int) apr_pool_is_ancestor(apr_pool_t *a, apr_pool_t *b)
 {
-    if (a == NULL) {
-	return 1;
-    }
+    if (a == NULL)
+        return 1;
+
+#if APR_POOL_DEBUG
+    /* Find the pool with the longest lifetime guaranteed by the
+     * caller: */
     while (a->joined) {
-	a = a->joined;
+        a = a->joined;
     }
+#endif
+
     while (b) {
-	if (a == b) {
-	    return 1;
-	}
-	b = b->parent;
+        if (a == b)
+            return 1;
+
+        b = b->parent;
     }
+
     return 0;
 }
 
-/*
- * All blocks belonging to sub will be changed to point to p
- * instead.  This is a guarantee by the caller that sub will not
- * be destroyed before p is.
- */
-API_EXPORT(void) ap_pool_join(ap_pool_t *p, ap_pool_t *sub, 
-                              int (*apr_abort)(int retcode))
+APR_DECLARE(void) apr_pool_tag(apr_pool_t *pool, const char *tag)
 {
-    union block_hdr *b;
+    pool->tag = tag;
+}
 
-    /* We could handle more general cases... but this is it for now. */
-    APR_ABORT(sub->parent != p, 1, apr_abort,
-              "pool_join: p is not a parent of sub\n");
-    ap_block_alarms();
-    while (p->joined) {
-	p = p->joined;
-    }
-    sub->joined = p;
-    for (b = global_block_list; b; b = b->h.global_next) {
-	if (b->h.owning_pool == sub) {
-	    b->h.owning_pool = p;
-	}
-    }
-    ap_unblock_alarms();
+APR_DECLARE(const char *) apr_pool_get_tag(apr_pool_t *pool)
+{
+    return pool->tag;
 }
-#endif
 
-/*****************************************************************
- *
- * Allocating stuff...
+/*
+ * User data management
  */
 
-void * ap_palloc(ap_pool_t *a, int reqsize)
+APR_DECLARE(apr_status_t) apr_pool_userdata_set(const void *data, const char *key,
+                                                apr_status_t (*cleanup) (void *),
+                                                apr_pool_t *pool)
 {
-#ifdef ALLOC_USE_MALLOC
-    int size = reqsize + CLICK_SZ;
-    void *ptr;
+#if APR_POOL_DEBUG
+    apr_pool_check_integrity(pool);
+#endif /* APR_POOL_DEBUG */
 
-    if (a == NULL) {
-        return malloc(reqsize);
-    }
-    ap_block_alarms();
-    if (c == NULL) {
-        return malloc(reqsize);
+    if (pool->user_data == NULL)
+        pool->user_data = apr_hash_make(pool);
+
+    if (apr_hash_get(pool->user_data, key, APR_HASH_KEY_STRING) == NULL) {
+        char *new_key = apr_pstrdup(pool, key);
+        apr_hash_set(pool->user_data, new_key, APR_HASH_KEY_STRING, data);
     }
-    ptr = malloc(size);
-    if (ptr == NULL) {
-	fputs("Ouch!  Out of memory!\n", stderr);
-	exit(1);
+    else {
+        apr_hash_set(pool->user_data, key, APR_HASH_KEY_STRING, data);
     }
-    debug_fill(ptr, size); /* might as well get uninitialized protection */
-    *(void **)ptr = a->allocation_list;
-    a->allocation_list = ptr;
-    ap_unblock_alarms();
-    return (char *)ptr + CLICK_SZ;
-#else
-
-    /*
-     * Round up requested size to an even number of alignment units
-     * (core clicks)
-     */
-    int nclicks;
-    int size;
 
-    /* First, see if we have space in the block most recently
-     * allocated to this pool
-     */
+    if (cleanup)
+        apr_pool_cleanup_register(pool, data, cleanup, cleanup);
 
-    union block_hdr *blok;
-    char *first_avail;
-    char *new_first_avail;
+    return APR_SUCCESS;
+}
 
-    if (a == NULL) {
-        return malloc(reqsize);
-    }
+APR_DECLARE(apr_status_t) apr_pool_userdata_setn(const void *data,
+                              const char *key,
+                              apr_status_t (*cleanup)(void *),
+                              apr_pool_t *pool)
+{
+#if APR_POOL_DEBUG
+    apr_pool_check_integrity(pool);
+#endif /* APR_POOL_DEBUG */
 
-    nclicks = 1 + ((reqsize - 1) / CLICK_SZ);
-    size = nclicks * CLICK_SZ;
+    if (pool->user_data == NULL)
+        pool->user_data = apr_hash_make(pool);
 
-    /* First, see if we have space in the block most recently
-     * allocated to this pool
-     */
+    apr_hash_set(pool->user_data, key, APR_HASH_KEY_STRING, data);
 
-    blok = a->last;
-    first_avail = blok->h.first_avail;
+    if (cleanup)
+        apr_pool_cleanup_register(pool, data, cleanup, cleanup);
 
-    if (reqsize <= 0) {
-	return NULL;
-    }
+    return APR_SUCCESS;
+}
 
-    new_first_avail = first_avail + size;
+APR_DECLARE(apr_status_t) apr_pool_userdata_get(void **data, const char *key,
+                                                apr_pool_t *pool)
+{
+#if APR_POOL_DEBUG
+    apr_pool_check_integrity(pool);
+#endif /* APR_POOL_DEBUG */
 
-    if (new_first_avail <= blok->h.endp) {
-	debug_verify_filled(first_avail, blok->h.endp,
-			    "Ouch!  Someone trounced past the end "
-			    "of their allocation!\n");
-	blok->h.first_avail = new_first_avail;
-	return (void *) first_avail;
+    if (pool->user_data == NULL) {
+        *data = NULL;
+    }
+    else {
+        *data = apr_hash_get(pool->user_data, key, APR_HASH_KEY_STRING);
     }
 
-    /* Nope --- get a new one that's guaranteed to be big enough */
+    return APR_SUCCESS;
+}
 
-    ap_block_alarms();
 
-#if APR_HAS_THREADS
-    ap_lock(alloc_mutex);
-#endif
+/*
+ * Cleanup
+ */
 
-    blok = new_block(size, a->apr_abort);
-    a->last->h.next = blok;
-    a->last = blok;
-#ifdef POOL_DEBUG
-    blok->h.owning_pool = a;
-#endif
+struct cleanup_t {
+    struct cleanup_t *next;
+    const void *data;
+    apr_status_t (*plain_cleanup_fn)(void *data);
+    apr_status_t (*child_cleanup_fn)(void *data);
+};
 
-#if APR_HAS_THREADS
-    ap_unlock(alloc_mutex);
-#endif
+APR_DECLARE(void) apr_pool_cleanup_register(apr_pool_t *p, const void *data,
+                      apr_status_t (*plain_cleanup_fn)(void *data),
+                      apr_status_t (*child_cleanup_fn)(void *data))
+{
+    cleanup_t *c;
 
-    ap_unblock_alarms();
+#if APR_POOL_DEBUG
+    apr_pool_check_integrity(p);
 
-    first_avail = blok->h.first_avail;
-    blok->h.first_avail += size;
+    if (!p || !plain_cleanup_fn || !child_cleanup_fn) {
+        abort();
+    }
+#endif /* APR_POOL_DEBUG */
 
-    return (void *) first_avail;
-#endif
+    if (p != NULL) {
+        if (p->free_cleanups) {
+            /* reuse a cleanup structure */
+            c = p->free_cleanups;
+            p->free_cleanups = c->next;
+        } else {
+            c = apr_palloc(p, sizeof(cleanup_t));
+        }
+        c->data = data;
+        c->plain_cleanup_fn = plain_cleanup_fn;
+        c->child_cleanup_fn = child_cleanup_fn;
+        c->next = p->cleanups;
+        p->cleanups = c;
+    }
 }
 
-API_EXPORT(void *) ap_pcalloc(ap_pool_t *a, int size)
+APR_DECLARE(void) apr_pool_pre_cleanup_register(apr_pool_t *p, const void *data,
+                      apr_status_t (*plain_cleanup_fn)(void *data))
 {
-    void *res = ap_palloc(a, size);
-    memset(res, '\0', size);
-    return res;
-}
+    cleanup_t *c;
 
-API_EXPORT(char *) ap_pstrdup(ap_pool_t *a, const char *s)
-{
-    char *res;
-    size_t len;
+#if APR_POOL_DEBUG
+    apr_pool_check_integrity(p);
+#endif /* APR_POOL_DEBUG */
 
-    if (s == NULL) {
-	return NULL;
+    if (p != NULL) {
+        if (p->free_cleanups) {
+            /* reuse a cleanup structure */
+            c = p->free_cleanups;
+            p->free_cleanups = c->next;
+        } else {
+            c = apr_palloc(p, sizeof(cleanup_t));
+        }
+        c->data = data;
+        c->plain_cleanup_fn = plain_cleanup_fn;
+        c->next = p->pre_cleanups;
+        p->pre_cleanups = c;
     }
-    len = strlen(s) + 1;
-    res = ap_palloc(a, len);
-    memcpy(res, s, len);
-    return res;
 }
 
-API_EXPORT(char *) ap_pstrndup(ap_pool_t *a, const char *s, int n)
+APR_DECLARE(void) apr_pool_cleanup_kill(apr_pool_t *p, const void *data,
+                      apr_status_t (*cleanup_fn)(void *))
 {
-    char *res;
+    cleanup_t *c, **lastp;
 
-    if (s == NULL) {
-	return NULL;
-    }
-    res = ap_palloc(a, n + 1);
-    memcpy(res, s, n);
-    res[n] = '\0';
-    return res;
-}
+#if APR_POOL_DEBUG
+    apr_pool_check_integrity(p);
+#endif /* APR_POOL_DEBUG */
 
-API_EXPORT_NONSTD(char *) ap_pstrcat(ap_pool_t *a, ...)
-{
-    char *cp, *argp, *res;
+    if (p == NULL)
+        return;
+
+    c = p->cleanups;
+    lastp = &p->cleanups;
+    while (c) {
+#if APR_POOL_DEBUG
+        /* Some cheap loop detection to catch a corrupt list: */
+        if (c == c->next
+            || (c->next && c == c->next->next)
+            || (c->next && c->next->next && c == c->next->next->next)) {
+            abort();
+        }
+#endif
+
+        if (c->data == data && c->plain_cleanup_fn == cleanup_fn) {
+            *lastp = c->next;
+            /* move to freelist */
+            c->next = p->free_cleanups;
+            p->free_cleanups = c;
+            break;
+        }
 
-    /* Pass one --- find length of required string */
+        lastp = &c->next;
+        c = c->next;
+    }
 
-    int len = 0;
-    va_list adummy;
+    /* Remove any pre-cleanup as well */
+    c = p->pre_cleanups;
+    lastp = &p->pre_cleanups;
+    while (c) {
+#if APR_POOL_DEBUG
+        /* Some cheap loop detection to catch a corrupt list: */
+        if (c == c->next
+            || (c->next && c == c->next->next)
+            || (c->next && c->next->next && c == c->next->next->next)) {
+            abort();
+        }
+#endif
 
-    va_start(adummy, a);
+        if (c->data == data && c->plain_cleanup_fn == cleanup_fn) {
+            *lastp = c->next;
+            /* move to freelist */
+            c->next = p->free_cleanups;
+            p->free_cleanups = c;
+            break;
+        }
 
-    while ((cp = va_arg(adummy, char *)) != NULL) {
-	len += strlen(cp);
+        lastp = &c->next;
+        c = c->next;
     }
 
-    va_end(adummy);
+}
 
-    /* Allocate the required string */
+APR_DECLARE(void) apr_pool_child_cleanup_set(apr_pool_t *p, const void *data,
+                      apr_status_t (*plain_cleanup_fn)(void *),
+                      apr_status_t (*child_cleanup_fn)(void *))
+{
+    cleanup_t *c;
 
-    res = (char *) ap_palloc(a, len + 1);
-    cp = res;
-    *cp = '\0';
+#if APR_POOL_DEBUG
+    apr_pool_check_integrity(p);
+#endif /* APR_POOL_DEBUG */
 
-    /* Pass two --- copy the argument strings into the result space */
+    if (p == NULL)
+        return;
 
-    va_start(adummy, a);
+    c = p->cleanups;
+    while (c) {
+        if (c->data == data && c->plain_cleanup_fn == plain_cleanup_fn) {
+            c->child_cleanup_fn = child_cleanup_fn;
+            break;
+        }
 
-    while ((argp = va_arg(adummy, char *)) != NULL) {
-	strcpy(cp, argp);
-	cp += strlen(argp);
+        c = c->next;
     }
+}
 
-    va_end(adummy);
+APR_DECLARE(apr_status_t) apr_pool_cleanup_run(apr_pool_t *p, void *data,
+                              apr_status_t (*cleanup_fn)(void *))
+{
+    apr_pool_cleanup_kill(p, data, cleanup_fn);
+    return (*cleanup_fn)(data);
+}
 
-    /* Return the result string */
+static void run_cleanups(cleanup_t **cref)
+{
+    cleanup_t *c = *cref;
 
-    return res;
+    while (c) {
+        *cref = c->next;
+        (*c->plain_cleanup_fn)((void *)c->data);
+        c = *cref;
+    }
 }
 
-/*
- * ap_psprintf is implemented by writing directly into the current
- * block of the pool, starting right at first_avail.  If there's
- * insufficient room, then a new block is allocated and the earlier
- * output is copied over.  The new block isn't linked into the pool
- * until all the output is done.
- *
- * Note that this is completely safe because nothing else can
- * allocate in this ap_pool_t while ap_psprintf is running.  alarms are
- * blocked, and the only thing outside of alloc.c that's invoked
- * is ap_vformatter -- which was purposefully written to be
- * self-contained with no callouts.
- */
-
-struct psprintf_data {
-    ap_vformatter_buff_t vbuff;
-#ifdef ALLOC_USE_MALLOC
-    char *base;
-#else
-    union block_hdr *blok;
-    int got_a_new_block;
-#endif
-};
+#if !defined(WIN32) && !defined(OS2)
 
-static int psprintf_flush(ap_vformatter_buff_t *vbuff)
+static void run_child_cleanups(cleanup_t **cref)
 {
-    struct psprintf_data *ps = (struct psprintf_data *)vbuff;
-#ifdef ALLOC_USE_MALLOC
-    int size;
-    char *ptr;
-
-    size = (char *)ps->vbuff.curpos - ps->base;
-    ptr = realloc(ps->base, 2*size);
-    if (ptr == NULL) {
-	fputs("Ouch!  Out of memory!\n", stderr);
-	exit(1);
-    }
-    ps->base = ptr;
-    ps->vbuff.curpos = ptr + size;
-    ps->vbuff.endpos = ptr + 2*size - 1;
-    return 0;
-#else
-    union block_hdr *blok;
-    union block_hdr *nblok;
-    size_t cur_len;
-    char *strp;
-
-    blok = ps->blok;
-    strp = ps->vbuff.curpos;
-    cur_len = strp - blok->h.first_avail;
+    cleanup_t *c = *cref;
 
-    /* must try another blok */
-#if APR_HAS_THREADS
-    ap_lock(alloc_mutex);
-#endif
-    nblok = new_block(2 * cur_len, NULL);
-#if APR_HAS_THREADS
-    ap_unlock(alloc_mutex);
-#endif
-    memcpy(nblok->h.first_avail, blok->h.first_avail, cur_len);
-    ps->vbuff.curpos = nblok->h.first_avail + cur_len;
-    /* save a byte for the NUL terminator */
-    ps->vbuff.endpos = nblok->h.endp - 1;
-
-    /* did we allocate the current blok? if so free it up */
-    if (ps->got_a_new_block) {
-	debug_fill(blok->h.first_avail, blok->h.endp - blok->h.first_avail);
-#if APR_HAS_THREADS
-        ap_lock(alloc_mutex);
-#endif
-	blok->h.next = block_freelist;
-	block_freelist = blok;
-#if APR_HAS_THREADS
-        ap_unlock(alloc_mutex);
-#endif
+    while (c) {
+        *cref = c->next;
+        (*c->child_cleanup_fn)((void *)c->data);
+        c = *cref;
     }
-    ps->blok = nblok;
-    ps->got_a_new_block = 1;
-    /* note that we've deliberately not linked the new block onto
-     * the pool yet... because we may need to flush again later, and
-     * we'd have to spend more effort trying to unlink the block.
-     */
-    return 0;
-#endif
 }
 
-API_EXPORT(char *) ap_pvsprintf(ap_pool_t *p, const char *fmt, va_list ap)
+static void cleanup_pool_for_exec(apr_pool_t *p)
 {
-#ifdef ALLOC_USE_MALLOC
-    struct psprintf_data ps;
-    void *ptr;
-
-    ap_block_alarms();
-    ps.base = malloc(512);
-    if (ps.base == NULL) {
-	fputs("Ouch!  Out of memory!\n", stderr);
-	exit(1);
-    }
-    /* need room at beginning for allocation_list */
-    ps.vbuff.curpos = ps.base + CLICK_SZ;
-    ps.vbuff.endpos = ps.base + 511;
-    ap_vformatter(psprintf_flush, &ps.vbuff, fmt, ap);
-    *ps.vbuff.curpos++ = '\0';
-    ptr = ps.base;
-    /* shrink */
-    ptr = realloc(ptr, (char *)ps.vbuff.curpos - (char *)ptr);
-    if (ptr == NULL) {
-	fputs("Ouch!  Out of memory!\n", stderr);
-	exit(1);
-    }
-    *(void **)ptr = p->allocation_list;
-    p->allocation_list = ptr;
-    ap_unblock_alarms();
-    return (char *)ptr + CLICK_SZ;
-#else
-    struct psprintf_data ps;
-    char *strp;
-    int size;
-
-    ap_block_alarms();
-    ps.blok = p->last;
-    ps.vbuff.curpos = ps.blok->h.first_avail;
-    ps.vbuff.endpos = ps.blok->h.endp - 1;	/* save one for NUL */
-    ps.got_a_new_block = 0;
-
-    ap_vformatter(psprintf_flush, &ps.vbuff, fmt, ap);
-
-    strp = ps.vbuff.curpos;
-    *strp++ = '\0';
-
-    size = strp - ps.blok->h.first_avail;
-    size = (1 + ((size - 1) / CLICK_SZ)) * CLICK_SZ;
-    strp = ps.blok->h.first_avail;	/* save away result pointer */
-    ps.blok->h.first_avail += size;
-
-    /* have to link the block in if it's a new one */
-    if (ps.got_a_new_block) {
-	p->last->h.next = ps.blok;
-	p->last = ps.blok;
-#ifdef POOL_DEBUG
-	ps.blok->h.owning_pool = p;
-#endif
-    }
-    ap_unblock_alarms();
+    run_child_cleanups(&p->cleanups);
 
-    return strp;
-#endif
+    for (p = p->child; p; p = p->sibling)
+        cleanup_pool_for_exec(p);
 }
 
-API_EXPORT_NONSTD(char *) ap_psprintf(ap_pool_t *p, const char *fmt, ...)
+APR_DECLARE(void) apr_pool_cleanup_for_exec(void)
 {
-    va_list ap;
-    char *res;
+    cleanup_pool_for_exec(global_pool);
+}
 
-    va_start(ap, fmt);
-    res = ap_pvsprintf(p, fmt, ap);
-    va_end(ap);
-    return res;
+#else /* !defined(WIN32) && !defined(OS2) */
+
+APR_DECLARE(void) apr_pool_cleanup_for_exec(void)
+{
+    /*
+     * Don't need to do anything on NT or OS/2, because 
+     * these platforms will spawn the new process - not
+     * fork for exec. All handles that are not inheritable,
+     * will be automajically closed. The only problem is
+     * with file handles that are open, but there isn't
+     * much that can be done about that (except if the
+     * child decides to go out and close them, or the
+     * developer quits opening them shared)
+     */
+    return;
 }
 
+#endif /* !defined(WIN32) && !defined(OS2) */
 
-/*****************************************************************
- *
- * More grotty system stuff... subprocesses.  Frump.  These don't use
- * the generic cleanup interface because I don't want multiple
- * subprocesses to result in multiple three-second pauses; the
- * subprocesses have to be "freed" all at once.  If someone comes
- * along with another resource they want to allocate which has the
- * same property, we might want to fold support for that into the
- * generic interface, but for now, it's a special case
- */
+APR_DECLARE_NONSTD(apr_status_t) apr_pool_cleanup_null(void *data)
+{
+    /* do nothing cleanup routine */
+    return APR_SUCCESS;
+}
 
-API_EXPORT(void) ap_note_subprocess(ap_pool_t *a, ap_proc_t *pid,
-				     enum kill_conditions how)
+/* Subprocesses don't use the generic cleanup interface because
+ * we don't want multiple subprocesses to result in multiple
+ * three-second pauses; the subprocesses have to be "freed" all
+ * at once.  If other resources are introduced with the same property,
+ * we might want to fold support for that into the generic interface.
+ * For now, it's a special case.
+ */
+APR_DECLARE(void) apr_pool_note_subprocess(apr_pool_t *pool, apr_proc_t *proc,
+                                           apr_kill_conditions_e how)
 {
-    struct process_chain *new =
-    (struct process_chain *) ap_palloc(a, sizeof(struct process_chain));
+    struct process_chain *pc = apr_palloc(pool, sizeof(struct process_chain));
 
-    new->pid = pid;
-    new->kill_how = how;
-    new->next = a->subprocesses;
-    a->subprocesses = new;
+    pc->proc = proc;
+    pc->kill_how = how;
+    pc->next = pool->subprocesses;
+    pool->subprocesses = pc;
 }
 
 static void free_proc_chain(struct process_chain *procs)
@@ -1283,12 +2749,12 @@ static void free_proc_chain(struct process_chain *procs)
      * whatever it was we're cleaning up now.  This may involve killing
      * some of them off...
      */
-    struct process_chain *p;
+    struct process_chain *pc;
     int need_timeout = 0;
+    apr_time_t timeout_interval;
 
-    if (procs == NULL) {
-	return;			/* No work.  Whew! */
-    }
+    if (!procs)
+        return; /* No work.  Whew! */
 
     /* First, check to see if we need to do the SIGTERM, sleep, SIGKILL
      * dance with any of the processes we're cleaning up.  If we've got
@@ -1299,66 +2765,190 @@ static void free_proc_chain(struct process_chain *procs)
 
 #ifndef NEED_WAITPID
     /* Pick up all defunct processes */
-    for (p = procs; p; p = p->next) {
-        if (ap_wait_proc(p->pid, APR_NOWAIT) == APR_CHILD_DONE) {
-            p->kill_how = kill_never;
-        }
+    for (pc = procs; pc; pc = pc->next) {
+        if (apr_proc_wait(pc->proc, NULL, NULL, APR_NOWAIT) != APR_CHILD_NOTDONE)
+            pc->kill_how = APR_KILL_NEVER;
     }
-#endif
+#endif /* !defined(NEED_WAITPID) */
 
-    for (p = procs; p; p = p->next) {
-        if ((p->kill_how == kill_after_timeout)
-            || (p->kill_how == kill_only_once)) {
+    for (pc = procs; pc; pc = pc->next) {
+#ifndef WIN32
+        if ((pc->kill_how == APR_KILL_AFTER_TIMEOUT)
+            || (pc->kill_how == APR_KILL_ONLY_ONCE)) {
             /*
              * Subprocess may be dead already.  Only need the timeout if not.
-             * Note: ap_kill on Windows is TerminateProcess(), which is 
+             * Note: apr_proc_kill on Windows is TerminateProcess(), which is
              * similar to a SIGKILL, so always give the process a timeout
              * under Windows before killing it.
              */
-#ifdef WIN32
+            if (apr_proc_kill(pc->proc, SIGTERM) == APR_SUCCESS)
+                need_timeout = 1;
+        }
+        else if (pc->kill_how == APR_KILL_ALWAYS) {
+#else /* WIN32 knows only one fast, clean method of killing processes today */
+        if (pc->kill_how != APR_KILL_NEVER) {
             need_timeout = 1;
-#else
-	    if (ap_kill(p->pid, APR_SIGTERM) == APR_SUCCESS) {
-		need_timeout = 1;
-	    }
+            pc->kill_how = APR_KILL_ALWAYS;
 #endif
-	}
-	else if (p->kill_how == kill_always) {
-	    ap_kill(p->pid, APR_SIGKILL);
-	}
+            apr_proc_kill(pc->proc, SIGKILL);
+        }
     }
 
-    /* Sleep only if we have to... */
+    /* Sleep only if we have to. The sleep algorithm grows
+     * by a factor of two on each iteration. TIMEOUT_INTERVAL
+     * is equal to TIMEOUT_USECS / 64.
+     */
     if (need_timeout) {
-	sleep(3);
+        timeout_interval = TIMEOUT_INTERVAL;
+        apr_sleep(timeout_interval);
+
+        do {
+            /* check the status of the subprocesses */
+            need_timeout = 0;
+            for (pc = procs; pc; pc = pc->next) {
+                if (pc->kill_how == APR_KILL_AFTER_TIMEOUT) {
+                    if (apr_proc_wait(pc->proc, NULL, NULL, APR_NOWAIT)
+                            == APR_CHILD_NOTDONE)
+                        need_timeout = 1;		/* subprocess is still active */
+                    else
+                        pc->kill_how = APR_KILL_NEVER;	/* subprocess has exited */
+                }
+            }
+            if (need_timeout) {
+                if (timeout_interval >= TIMEOUT_USECS) {
+                    break;
+                }
+                apr_sleep(timeout_interval);
+                timeout_interval *= 2;
+            }
+        } while (need_timeout);
     }
 
     /* OK, the scripts we just timed out for have had a chance to clean up
      * --- now, just get rid of them, and also clean up the system accounting
      * goop...
      */
-    for (p = procs; p; p = p->next) {
-	if (p->kill_how == kill_after_timeout) {
-	    ap_kill(p->pid, APR_SIGKILL);
-	}
-    }
-#ifdef WIN32
-    /* 
-     * Do we need an APR function to clean-up a proc_t?
-     */
-    {
-        PROCESS_INFORMATION pi;
-        for (p = procs; p; p = p->next) {
-            ap_get_os_proc(&pi, p->pid);
-            CloseHandle(pi.hProcess);
-        }
+    for (pc = procs; pc; pc = pc->next) {
+        if (pc->kill_how == APR_KILL_AFTER_TIMEOUT)
+            apr_proc_kill(pc->proc, SIGKILL);
     }
-#endif /* WIN32 */
 
     /* Now wait for all the signaled processes to die */
-    for (p = procs; p; p = p->next) {
-	if (p->kill_how != kill_never) {
-	    (void) ap_wait_proc(p->pid, APR_WAIT);
-	}
+    for (pc = procs; pc; pc = pc->next) {
+        if (pc->kill_how != APR_KILL_NEVER)
+            (void)apr_proc_wait(pc->proc, NULL, NULL, APR_WAIT);
     }
 }
+
+
+/*
+ * Pool creation/destruction stubs, for people who are running
+ * mixed release/debug enviroments.
+ */
+
+#if !APR_POOL_DEBUG
+APR_DECLARE(void *) apr_palloc_debug(apr_pool_t *pool, apr_size_t size,
+                                     const char *file_line)
+{
+    return apr_palloc(pool, size);
+}
+
+APR_DECLARE(void *) apr_pcalloc_debug(apr_pool_t *pool, apr_size_t size,
+                                      const char *file_line)
+{
+    return apr_pcalloc(pool, size);
+}
+
+APR_DECLARE(void) apr_pool_clear_debug(apr_pool_t *pool,
+                                       const char *file_line)
+{
+    apr_pool_clear(pool);
+}
+
+APR_DECLARE(void) apr_pool_destroy_debug(apr_pool_t *pool,
+                                         const char *file_line)
+{
+    apr_pool_destroy(pool);
+}
+
+APR_DECLARE(apr_status_t) apr_pool_create_ex_debug(apr_pool_t **newpool,
+                                                   apr_pool_t *parent,
+                                                   apr_abortfunc_t abort_fn,
+                                                   apr_allocator_t *allocator,
+                                                   const char *file_line)
+{
+    return apr_pool_create_ex(newpool, parent, abort_fn, allocator);
+}
+
+APR_DECLARE(apr_status_t) apr_pool_create_unmanaged_ex_debug(apr_pool_t **newpool,
+                                                   apr_abortfunc_t abort_fn,
+                                                   apr_allocator_t *allocator,
+                                                   const char *file_line)
+{
+    return apr_pool_create_unmanaged_ex(newpool, abort_fn, allocator);
+}
+
+#else /* APR_POOL_DEBUG */
+
+#undef apr_palloc
+APR_DECLARE(void *) apr_palloc(apr_pool_t *pool, apr_size_t size);
+
+APR_DECLARE(void *) apr_palloc(apr_pool_t *pool, apr_size_t size)
+{
+    return apr_palloc_debug(pool, size, "undefined");
+}
+
+#undef apr_pcalloc
+APR_DECLARE(void *) apr_pcalloc(apr_pool_t *pool, apr_size_t size);
+
+APR_DECLARE(void *) apr_pcalloc(apr_pool_t *pool, apr_size_t size)
+{
+    return apr_pcalloc_debug(pool, size, "undefined");
+}
+
+#undef apr_pool_clear
+APR_DECLARE(void) apr_pool_clear(apr_pool_t *pool);
+
+APR_DECLARE(void) apr_pool_clear(apr_pool_t *pool)
+{
+    apr_pool_clear_debug(pool, "undefined");
+}
+
+#undef apr_pool_destroy
+APR_DECLARE(void) apr_pool_destroy(apr_pool_t *pool);
+
+APR_DECLARE(void) apr_pool_destroy(apr_pool_t *pool)
+{
+    apr_pool_destroy_debug(pool, "undefined");
+}
+
+#undef apr_pool_create_ex
+APR_DECLARE(apr_status_t) apr_pool_create_ex(apr_pool_t **newpool,
+                                             apr_pool_t *parent,
+                                             apr_abortfunc_t abort_fn,
+                                             apr_allocator_t *allocator);
+
+APR_DECLARE(apr_status_t) apr_pool_create_ex(apr_pool_t **newpool,
+                                             apr_pool_t *parent,
+                                             apr_abortfunc_t abort_fn,
+                                             apr_allocator_t *allocator)
+{
+    return apr_pool_create_ex_debug(newpool, parent,
+                                    abort_fn, allocator,
+                                    "undefined");
+}
+
+#undef apr_pool_create_unmanaged_ex
+APR_DECLARE(apr_status_t) apr_pool_create_unmanaged_ex(apr_pool_t **newpool,
+                                                  apr_abortfunc_t abort_fn,
+                                                  apr_allocator_t *allocator);
+
+APR_DECLARE(apr_status_t) apr_pool_create_unmanaged_ex(apr_pool_t **newpool,
+                                                  apr_abortfunc_t abort_fn,
+                                                  apr_allocator_t *allocator)
+{
+    return apr_pool_create_unmanaged_ex_debug(newpool, abort_fn,
+                                         allocator, "undefined");
+}
+
+#endif /* APR_POOL_DEBUG */
diff --git a/misc/beos/Makefile.in b/misc/beos/Makefile.in
deleted file mode 100644
index 6ba04bef4d8..00000000000
--- a/misc/beos/Makefile.in
+++ /dev/null
@@ -1,62 +0,0 @@
-#CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
-#LIBS=$(EXTRA_LIBS) $(LIBS1)
-#INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
-#LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
-
-CC=@CC@
-RANLIB=@RANLIB@
-CFLAGS=@CFLAGS@ @OPTIM@
-LIBS=@LIBS@
-LDFLAGS=@LDFLAGS@ $(LIBS)
-INCDIR=../../include
-INCDIR1=../../file_io/unix -I../../locks/beos -I../../threadproc/beos
-
-INCLUDES=-I$(INCDIR) -I$(INCDIR1) -I.
-
-LIB=libmisc.a
-
-OBJS=misc_common.o
-
-.c.o:
-	$(CC) $(CFLAGS) -c $(INCLUDES) $<
-
-all: $(LIB)
-
-clean:
-	$(RM) -f *.o *.a *.so
-
-distclean: clean
-	-$(RM) -f Makefile
-
-$(OBJS): Makefile
-
-$(LIB): $(OBJS)
-	$(RM) -f $@
-	$(AR) cr $@ $(OBJS)
-	$(RANLIB) $@
-
-#
-# We really don't expect end users to use this rule.  It works only with
-# gcc, and rebuilds Makefile.tmpl.  You have to re-run Configure after
-# using it.
-#
-depend:
-	cp Makefile.in Makefile.in.bak \
-	    && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.in > Makefile.new \
-	    && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \
-	    && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
-	           -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
-		> Makefile.in \
-	    && rm Makefile.new
-
-# DO NOT REMOVE
-getopt.o: getopt.c misc.h ../../include/apr_private.h \
- ../../include/apr_general.h ../../include/apr.h \
- ../../include/apr_errno.h ../../include/apr_pools.h \
- ../../include/apr_lib.h ../../include/apr_file_io.h \
- ../../include/apr_getopt.h
-start.o: start.c misc.h ../../include/apr_private.h \
- ../../include/apr_general.h ../../include/apr.h \
- ../../include/apr_errno.h ../../include/apr_pools.h \
- ../../include/apr_lib.h ../../include/apr_file_io.h \
- ../../include/apr_getopt.h
diff --git a/misc/beos/misc.h b/misc/beos/misc.h
deleted file mode 100644
index 7c99c206a83..00000000000
--- a/misc/beos/misc.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef MISC_H
-#define MISC_H
-
-#include "apr_private.h"
-#include "apr_general.h"
-#include "apr_pools.h"
-#include "apr_getopt.h"
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STDIO_H
-#include <stdio.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_SIGNAL_H
-#include <signal.h>
-#endif
-
-#include <kernel/OS.h>
-
-typedef struct datastruct {
-    void *data;
-    char *key;
-    struct datastruct *next;
-    struct datastruct *prev;
-} datastruct;
-
-struct ap_other_child_rec_t {
-    struct ap_other_child_rec_t *next;
-    thread_id pid; /* this is actually a thread_id, but in order to
-                      restrict the amount of code duplication we'll use
-                      pid so that the Unix code won't have too many #ifdef's
-                   */
-    void (*maintenance) (int, void *);
-    void *data;
-    int write_fd;
-};
-
-
-#endif  /* ! MISC_H */
-
diff --git a/misc/beos/misc_common.c b/misc/beos/misc_common.c
deleted file mode 100644
index 86a11c4cfc2..00000000000
--- a/misc/beos/misc_common.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-/* BeOS uses identical code so let's not have 2 copies... */
-
-#include "../unix/start.c"
-
-#include "../unix/getopt.c"
-
-#include "../unix/otherchild.c"
-
-#include "../unix/canonerr.c"
-#include "../unix/errorcodes.c"
diff --git a/misc/beos/otherchild.c b/misc/beos/otherchild.c
deleted file mode 100644
index 1239eedbc69..00000000000
--- a/misc/beos/otherchild.c
+++ /dev/null
@@ -1,180 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "misc.h"
-#include "../../threadproc/beos/threadproc.h"
-
-static ap_other_child_rec_t *other_children = NULL;
-
-API_EXPORT(void) ap_register_other_child(ap_proc_t *pid,
-                     void (*maintenance) (int reason, void *),
-                     void *data, int write_fd, ap_pool_t *p)
-{
-    ap_other_child_rec_t *ocr;
-
-    ocr = ap_palloc(p, sizeof(*ocr));
-    ocr->tid = pid->tid;
-    ocr->maintenance = maintenance;
-    ocr->data = data;
-    ocr->write_fd = write_fd;
-    ocr->next = other_children;
-    other_children = ocr;
-}
-
-API_EXPORT(void) ap_unregister_other_child(void *data)
-{
-    ap_other_child_rec_t **pocr, *nocr;
-
-    for (pocr = &other_children; *pocr; pocr = &(*pocr)->next) {
-        if ((*pocr)->data == data) {
-            nocr = (*pocr)->next;
-            (*(*pocr)->maintenance) (APR_OC_REASON_UNREGISTER, (*pocr)->data);
-            *pocr = nocr;
-            /* XXX: um, well we've just wasted some space in pconf ? */
-            return;
-        }
-    }
-}
-
-/* test to ensure that the write_fds are all still writable, otherwise
- * invoke the maintenance functions as appropriate */
-static void probe_writable_fds(void)
-{
-    fd_set writable_fds;
-    int fd_max;
-    ap_other_child_rec_t *ocr, *nocr; 
-    struct timeval tv; 
-    int rc;
-
-    if (other_children == NULL)
-        return;
-
-    fd_max = 0;
-    FD_ZERO(&writable_fds);
-    do {
-        for (ocr = other_children; ocr; ocr = ocr->next) {
-            if (ocr->write_fd == -1)
-                continue;
-            FD_SET(ocr->write_fd, &writable_fds);
-            if (ocr->write_fd > fd_max) {
-                fd_max = ocr->write_fd;
-            }
-        }
-        if (fd_max == 0)
-            return;
-
-        tv.tv_sec = 0;
-        tv.tv_usec = 0;
-        rc = select(fd_max + 1, NULL, &writable_fds, NULL, &tv);
-    } while (rc == -1 && errno == EINTR);
-
-    if (rc == -1) {
-        /* XXX: uhh this could be really bad, we could have a bad file
-         * descriptor due to a bug in one of the maintenance routines */
-        return;
-    }
-    if (rc == 0)
-        return;
-
-    for (ocr = other_children; ocr; ocr = nocr) {
-        nocr = ocr->next;
-        if (ocr->write_fd == -1)
-            continue;
-        if (FD_ISSET(ocr->write_fd, &writable_fds))
-            continue;
-        (*ocr->maintenance) (APR_OC_REASON_UNWRITABLE, ocr->data);
-    }
-}
-
-API_EXPORT(ap_status_t) reap_other_child(ap_proc_t *pid)
-{
-    ap_other_child_rec_t *ocr, *nocr;
-
-    for (ocr = other_children; ocr; ocr = nocr) {
-        nocr = ocr->next;
-        if (ocr->tid != pid->tid)
-            continue;
-        ocr->tid = -1;
-        (*ocr->maintenance) (APR_OC_REASON_DEATH, ocr->data);
-        return 0;
-    }
-    return APR_CHILD_NOTDONE;
-}
-
-API_EXPORT(void) check_other_child(void)
-{
-    ap_other_child_rec_t *ocr, *nocr;
-    pid_t waitret;    
-
-    for (ocr = other_children; ocr; ocr = nocr) {
-        nocr = ocr->next;
-        if (ocr->tid == -1)
-            continue;
-
-        waitret = waitpid(ocr->tid, NULL, WNOHANG);
-        if (waitret == ocr->tid) {
-            ocr->tid = -1;
-            (*ocr->maintenance) (APR_OC_REASON_DEATH, ocr->data);
-        }
-        else if (waitret == 0) {
-            (*ocr->maintenance) (APR_OC_REASON_RESTART, ocr->data);
-        }
-        else if (waitret == -1) {
-            /* uh what the heck? they didn't call unregister? */
-            ocr->tid = -1;
-            (*ocr->maintenance) (APR_OC_REASON_LOST, ocr->data);
-        }
-    }
-}
-
diff --git a/misc/beos/start.c b/misc/beos/start.c
deleted file mode 100644
index f46f1bfe53b..00000000000
--- a/misc/beos/start.c
+++ /dev/null
@@ -1,153 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "misc.h"
-
-ap_status_t ap_create_pool(ap_pool_t **newcont, ap_pool_t *cont)
-{
-    ap_pool_t *new;
-    ap_pool_t *pool;
-
-    if (cont) {
-        pool = ap_make_sub_pool(cont->pool, cont->apr_abort);
-    }
-    else {
-        pool = ap_make_sub_pool(NULL, NULL);
-    }
-        
-    if (pool == NULL) {
-        return APR_ENOPOOL;
-    }
-    
-    new = (ap_pool_t *)ap_palloc(cont, sizeof(ap_pool_t));
-    
-    new->pool = pool;
-    new->prog_data = NULL;
- 
-    *newcont = new;
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_destroy_context(ap_pool_t *cont)
-{
-    ap_destroy_pool(cont);
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_set_userdata(void *data, char *key,
-                            ap_status_t (*cleanup) (void *),
-                            ap_pool_t *cont)
-{
-    datastruct *dptr = NULL, *dptr2 = NULL;
-    if (cont) { 
-        dptr = cont->prog_data;
-        while (dptr) {
-            if (!strcmp(dptr->key, key))
-                break;
-            dptr2 = dptr;
-            dptr = dptr->next;
-        }
-        if (dptr == NULL) {
-            dptr = ap_palloc(cont, sizeof(datastruct));
-            dptr->next = dptr->prev = NULL;
-            dptr->key = ap_pstrdup(cont, key);
-            if (dptr2) {
-                dptr2->next = dptr;
-                dptr->prev = dptr2;
-            }
-            else {
-                cont->prog_data = dptr;
-            }
-        }
-        dptr->data = data;
-        ap_register_cleanup(cont, dptr->data, cleanup, cleanup);
-        return APR_SUCCESS;
-    }
-    return APR_ENOPOOL;
-}
-
-ap_status_t ap_get_userdata(void **data, char *key, ap_pool_t *cont)
-{
-    datastruct *dptr = NULL;
-    if (cont) { 
-        dptr = cont->prog_data;
-        while (dptr) {
-            if (!strcmp(dptr->key, key)) {
-                break;
-            }
-            dptr = dptr->next;
-        }
-        if (dptr) {
-            (*data) = dptr->data;
-        }
-        else {
-            (*data) = NULL;
-        }
-        return APR_SUCCESS;
-    }
-    return APR_ENOPOOL;
-}
-
-ap_status_t ap_initialize(void)
-{
-    ap_status_t status;
-    status = ap_init_alloc();
-    return status;
-}
-
-void ap_terminate(void)
-{
-    ap_term_alloc();
-}
-
diff --git a/misc/netware/apr.xdc b/misc/netware/apr.xdc
new file mode 100644
index 00000000000..12a7f6ba2df
Binary files /dev/null and b/misc/netware/apr.xdc differ
diff --git a/misc/netware/charset.c b/misc/netware/charset.c
new file mode 100644
index 00000000000..b79add10b55
--- /dev/null
+++ b/misc/netware/charset.c
@@ -0,0 +1,34 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_strings.h"
+#include "apr_portable.h"
+
+/* static struct utsname sysinfo; */
+
+/* XXX This needs to be fixed to produce the correct system language */
+
+APR_DECLARE(const char*) apr_os_default_encoding (apr_pool_t *pool)
+{
+    return apr_pstrdup(pool, "CP1252");
+}
+
+
+APR_DECLARE(const char*) apr_os_locale_encoding (apr_pool_t *pool)
+{
+    return apr_os_default_encoding(pool);
+}
diff --git a/misc/netware/libprews.c b/misc/netware/libprews.c
new file mode 100644
index 00000000000..9f9db5c9c76
--- /dev/null
+++ b/misc/netware/libprews.c
@@ -0,0 +1,187 @@
+/* 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 <netware.h>
+#include <library.h>
+#include <nks/synch.h>
+
+#include "apr_pools.h"
+#include "apr_private.h"
+#include "apr_arch_internal_time.h"
+
+
+/* library-private data...*/
+int          gLibId = -1;
+void         *gLibHandle = (void *) NULL;
+NXMutex_t    *gLibLock = (NXMutex_t *) NULL;
+
+/* internal library function prototypes...*/
+int DisposeLibraryData(void *);
+
+int _NonAppStart
+(
+    void        *NLMHandle,
+    void        *errorScreen,
+    const char  *cmdLine,
+    const char  *loadDirPath,
+    size_t      uninitializedDataLength,
+    void        *NLMFileHandle,
+    int         (*readRoutineP)( int conn, void *fileHandle, size_t offset,
+                    size_t nbytes, size_t *bytesRead, void *buffer ),
+    size_t      customDataOffset,
+    size_t      customDataSize,
+    int         messageCount,
+    const char  **messages
+)
+{
+#ifdef __MWERKS__
+#pragma unused(cmdLine)
+#pragma unused(loadDirPath)
+#pragma unused(uninitializedDataLength)
+#pragma unused(NLMFileHandle)
+#pragma unused(readRoutineP)
+#pragma unused(customDataOffset)
+#pragma unused(customDataSize)
+#pragma unused(messageCount)
+#pragma unused(messages)
+#endif
+#ifdef USE_WINSOCK
+    WSADATA wsaData;
+#endif
+    apr_status_t status;
+    
+    NX_LOCK_INFO_ALLOC(liblock, "Per-Application Data Lock", 0);
+
+    gLibId = register_library(DisposeLibraryData);
+
+    if (gLibId < -1)
+    {
+        OutputToScreen(errorScreen, "Unable to register library with kernel.\n");
+        return -1;
+    }
+
+    gLibHandle = NLMHandle;
+
+    gLibLock = NXMutexAlloc(0, 0, &liblock);
+
+    if (!gLibLock)
+    {
+        OutputToScreen(errorScreen, "Unable to allocate library data lock.\n");
+        return -1;
+    }
+
+    apr_netware_setup_time();
+
+    if ((status = apr_pool_initialize()) != APR_SUCCESS)
+        return status;
+
+#ifdef USE_WINSOCK
+    return WSAStartup((WORD) MAKEWORD(2, 0), &wsaData);
+#else
+    return 0;
+#endif
+}
+
+void _NonAppStop( void )
+{
+    apr_pool_terminate();
+
+#ifdef USE_WINSOCK
+    WSACleanup();
+#endif
+
+    unregister_library(gLibId);
+    NXMutexFree(gLibLock);
+}
+
+int  _NonAppCheckUnload( void )
+{
+    return 0;
+}
+
+int register_NLM(void *NLMHandle)
+{
+    APP_DATA *app_data = (APP_DATA*) get_app_data(gLibId);
+
+    NXLock(gLibLock);
+    if (!app_data) {
+        app_data = (APP_DATA*)library_malloc(gLibHandle, sizeof(APP_DATA));
+
+        if (app_data) {
+            memset (app_data, 0, sizeof(APP_DATA));
+            set_app_data(gLibId, app_data);
+            app_data->gs_nlmhandle = NLMHandle;
+        }
+    }
+
+    if (app_data && (!app_data->initialized)) {
+        app_data->initialized = 1;
+        NXUnlock(gLibLock);
+        return 0;
+    }
+
+    NXUnlock(gLibLock);
+    return 1;
+}
+
+int unregister_NLM(void *NLMHandle)
+{
+    APP_DATA *app_data = (APP_DATA*) get_app_data(gLibId);
+
+    NXLock(gLibLock);
+    if (app_data) {
+        app_data->initialized = 0;
+        NXUnlock(gLibLock);
+        return 0;
+    }
+    NXUnlock(gLibLock);
+    return 1;
+}
+
+int DisposeLibraryData(void *data)
+{
+    if (data)
+    {
+        library_free(data);
+    }
+
+    return 0;
+}
+
+int setGlobalPool(void *data)
+{
+    APP_DATA *app_data = (APP_DATA*) get_app_data(gLibId);
+
+    NXLock(gLibLock);
+
+    if (app_data && !app_data->gPool) {
+        app_data->gPool = data;
+    }
+
+    NXUnlock(gLibLock);
+    return 1;
+}
+
+void* getGlobalPool()
+{
+    APP_DATA *app_data = (APP_DATA*) get_app_data(gLibId);
+
+    if (app_data) {
+        return app_data->gPool;
+    }
+
+    return NULL;
+}
+
diff --git a/misc/netware/rand.c b/misc/netware/rand.c
new file mode 100644
index 00000000000..a2baae7ecd3
--- /dev/null
+++ b/misc/netware/rand.c
@@ -0,0 +1,70 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define APR_WANT_MEMFUNC
+#include "apr_want.h"
+#include "apr_general.h"
+#include "apr_private.h"
+
+#if APR_HAS_RANDOM
+
+#include <nks/plat.h>
+
+static int NXSeedRandomInternal( size_t width, void *seed )
+{
+    static int init = 0;
+    int                        *s = (int *) seed;
+    union { int x; char y[4]; } u;
+
+    if (!init) {
+        srand(NXGetSystemTick());
+        init = 1;
+    }
+ 
+    if (width > 3)
+    {
+        do
+        {
+            *s++ = rand();
+        }
+        while ((width -= 4) > 3);
+    }
+ 
+    if (width > 0)
+    {
+        char *p = (char *) s;
+
+        u.x = rand();
+ 
+        while (width > 0)
+           *p++ = u.y[width--];
+    }
+ 
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_generate_random_bytes(unsigned char *buf, 
+                                                    apr_size_t length)
+{
+    if (NXSeedRandom(length, buf) != 0) {
+        return NXSeedRandomInternal (length, buf);
+    }
+    return APR_SUCCESS;
+}
+
+
+
+#endif /* APR_HAS_RANDOM */
diff --git a/misc/netware/start.c b/misc/netware/start.c
new file mode 100644
index 00000000000..e044a102283
--- /dev/null
+++ b/misc/netware/start.c
@@ -0,0 +1,199 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_general.h"
+#include "apr_pools.h"
+#include "apr_signal.h"
+
+#include "apr_arch_misc.h"       /* for WSAHighByte / WSALowByte */
+#include "apr_arch_proc_mutex.h" /* for apr_proc_mutex_unix_setup_lock() */
+#include "apr_arch_internal_time.h"
+
+#ifdef USE_WINSOCK
+/* Prototypes missing from older NDKs */
+int WSAStartupRTags(WORD wVersionRequested,
+                    LPWSADATA lpWSAData,
+                    rtag_t WSAStartupRTag,
+                    rtag_t WSPSKTRTag,
+                    rtag_t lookUpServiceBeginRTag,
+                    rtag_t WSAEventRTag,
+                    rtag_t WSPCPRTag);
+
+int WSACleanupRTag(rtag_t rTag);
+
+/*
+** Resource tag signatures for using NetWare WinSock 2. These will no longer
+** be needed by anyone once the new WSAStartupWithNlmHandle() is available
+** since WinSock will make the calls to AllocateResourceTag().
+*/
+#define WS_LOAD_ENTRY_SIGNATURE     (*(unsigned long *) "WLDE")
+#define WS_SKT_SIGNATURE            (*(unsigned long *) "WSKT")
+#define WS_LOOKUP_SERVICE_SIGNATURE (*(unsigned long *) "WLUP")
+#define WS_WSAEVENT_SIGNATURE       (*(unsigned long *) "WEVT")
+#define WS_CPORT_SIGNATURE          (*(unsigned long *) "WCPT")
+
+
+int (*WSAStartupWithNLMHandle)( WORD version, LPWSADATA data, void *handle ) = NULL;
+int (*WSACleanupWithNLMHandle)( void *handle ) = NULL;
+
+static int wsa_startup_with_handle (WORD wVersionRequested, LPWSADATA data, void *handle)
+{
+    APP_DATA *app_data;
+    
+    if (!(app_data = (APP_DATA*) get_app_data(gLibId)))
+        return APR_EGENERAL;
+
+    app_data->gs_startup_rtag = AllocateResourceTag(handle, "WinSock Start-up", WS_LOAD_ENTRY_SIGNATURE);
+    app_data->gs_socket_rtag  = AllocateResourceTag(handle, "WinSock socket()", WS_SKT_SIGNATURE);
+    app_data->gs_lookup_rtag  = AllocateResourceTag(handle, "WinSock Look-up", WS_LOOKUP_SERVICE_SIGNATURE);
+    app_data->gs_event_rtag   = AllocateResourceTag(handle, "WinSock Event", WS_WSAEVENT_SIGNATURE);
+    app_data->gs_pcp_rtag     = AllocateResourceTag(handle, "WinSock C-Port", WS_CPORT_SIGNATURE);
+
+    return WSAStartupRTags(wVersionRequested, data, 
+                           app_data->gs_startup_rtag, 
+                           app_data->gs_socket_rtag, 
+                           app_data->gs_lookup_rtag, 
+                           app_data->gs_event_rtag, 
+                           app_data->gs_pcp_rtag);
+}
+
+static int wsa_cleanup_with_handle (void *handle)
+{
+    APP_DATA *app_data;
+    
+    if (!(app_data = (APP_DATA*) get_app_data(gLibId)))
+        return APR_EGENERAL;
+
+    return WSACleanupRTag(app_data->gs_startup_rtag);
+}
+
+static int UnregisterAppWithWinSock (void *nlm_handle)
+{
+    if (!WSACleanupWithNLMHandle)
+    {
+        if (!(WSACleanupWithNLMHandle = ImportPublicObject(gLibHandle, "WSACleanupWithNLMHandle")))
+            WSACleanupWithNLMHandle = wsa_cleanup_with_handle;
+    }
+
+    return (*WSACleanupWithNLMHandle)(nlm_handle);
+}
+
+static int RegisterAppWithWinSock (void *nlm_handle)
+{
+    int err;
+    WSADATA wsaData;
+    WORD wVersionRequested = MAKEWORD(WSAHighByte, WSALowByte);
+
+    if (!WSAStartupWithNLMHandle)
+    {
+        if (!(WSAStartupWithNLMHandle = ImportPublicObject(gLibHandle, "WSAStartupWithNLMHandle")))
+            WSAStartupWithNLMHandle = wsa_startup_with_handle;
+    }
+
+    err = (*WSAStartupWithNLMHandle)(wVersionRequested, &wsaData, nlm_handle);
+
+    if (LOBYTE(wsaData.wVersion) != WSAHighByte ||
+        HIBYTE(wsaData.wVersion) != WSALowByte) {
+        
+        UnregisterAppWithWinSock (nlm_handle);
+        return APR_EEXIST;
+    }
+
+    return err;
+}
+#endif
+
+
+
+APR_DECLARE(apr_status_t) apr_app_initialize(int *argc, 
+                                             const char * const * *argv, 
+                                             const char * const * *env)
+{
+    /* An absolute noop.  At present, only Win32 requires this stub, but it's
+     * required in order to move command arguments passed through the service
+     * control manager into the process, and it's required to fix the char*
+     * data passed in from win32 unicode into utf-8, win32's apr internal fmt.
+     */
+    return apr_initialize();
+}
+
+APR_DECLARE(apr_status_t) apr_initialize(void)
+{
+    apr_pool_t *pool;
+    void *nlmhandle = getnlmhandle();
+
+    /* Register the NLM as using APR. If it is already
+        registered then just return. */
+    if (register_NLM(nlmhandle) != 0) {
+        return APR_SUCCESS;
+    }
+
+    /* apr_pool_initialize() is being called from the library
+        startup code since all of the memory resources belong 
+        to the library rather than the application. */
+    
+    if (apr_pool_create(&pool, NULL) != APR_SUCCESS) {
+        return APR_ENOPOOL;
+    }
+
+    apr_pool_tag(pool, "apr_initilialize");
+
+#ifdef USE_WINSOCK
+    {
+        int err;
+        if ((err = RegisterAppWithWinSock (nlmhandle))) {
+            return err;
+        }
+    }
+#endif
+
+    apr_signal_init(pool);
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE_NONSTD(void) apr_terminate(void)
+{
+    APP_DATA *app_data;
+
+    /* Get our instance data for shutting down. */
+    if (!(app_data = (APP_DATA*) get_app_data(gLibId)))
+        return;
+
+    /* Unregister the NLM. If it is not registered
+        then just return. */
+    if (unregister_NLM(app_data->gs_nlmhandle) != 0) {
+        return;
+    }
+
+    /* apr_pool_terminate() is being called from the 
+        library shutdown code since the memory resources
+        belong to the library rather than the application */
+
+    /* Just clean up the memory for the app that is going
+        away. */
+    netware_pool_proc_cleanup ();
+
+#ifdef USE_WINSOCK
+    UnregisterAppWithWinSock (app_data->gs_nlmhandle);
+#endif
+}
+
+APR_DECLARE(void) apr_terminate2(void)
+{
+    apr_terminate();
+}
diff --git a/misc/os2/.cvsignore b/misc/os2/.cvsignore
deleted file mode 100644
index f3c7a7c5da6..00000000000
--- a/misc/os2/.cvsignore
+++ /dev/null
@@ -1 +0,0 @@
-Makefile
diff --git a/misc/os2/misc.h b/misc/os2/misc.h
deleted file mode 100644
index f6b0e4833f4..00000000000
--- a/misc/os2/misc.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "../unix/misc.h"
diff --git a/misc/unix/.cvsignore b/misc/unix/.cvsignore
deleted file mode 100644
index f3c7a7c5da6..00000000000
--- a/misc/unix/.cvsignore
+++ /dev/null
@@ -1 +0,0 @@
-Makefile
diff --git a/misc/unix/Makefile.in b/misc/unix/Makefile.in
deleted file mode 100644
index 23c3d6c96eb..00000000000
--- a/misc/unix/Makefile.in
+++ /dev/null
@@ -1,91 +0,0 @@
-#CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
-#LIBS=$(EXTRA_LIBS) $(LIBS1)
-#INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
-#LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
-
-RM=@RM@
-CC=@CC@
-RANLIB=@RANLIB@
-CFLAGS=@CFLAGS@ @OPTIM@
-LIBS=@LIBS@
-LDFLAGS=@LDFLAGS@ $(LIBS)
-INCDIR1=../../include
-INCDIR2=../../file_io/@OSDIR@
-INCDIR3=../../locks/@OSDIR@
-INCDIR4=../../threadproc/@OSDIR@
-INCLUDES=-I$(INCDIR1) -I$(INCDIR2) -I$(INCDIR3) -I$(INCDIR4) -I.
-
-#LIB=libmisc.a
-
-OBJS=start.o getopt.o otherchild.o errorcodes.o rand.o canonerr.o
-
-.c.o:
-	$(CC) $(CFLAGS) -c $(INCLUDES) $<
-
-all: $(OBJS)
-
-clean:
-	$(RM) -f *.o *.a *.so
-
-distclean: clean
-	-$(RM) -f Makefile
-
-$(OBJS): Makefile
-
-#$(LIB): $(OBJS)
-#	$(RM) -f $@
-#	$(AR) cr $@ $(OBJS)
-#	$(RANLIB) $@
-
-#
-# We really don't expect end users to use this rule.  It works only with
-# gcc, and rebuilds Makefile.tmpl.  You have to re-run Configure after
-# using it.
-#
-depend:
-	cp Makefile.in Makefile.in.bak \
-	    && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.in > Makefile.new \
-	    && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \
-	    && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
-	           -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
-		> Makefile.in \
-	    && rm Makefile.new
-
-# DO NOT REMOVE
-canonerr.o: canonerr.c misc.h ../../include/apr.h \
- ../../include/apr_private.h ../../include/apr_general.h \
- ../../include/apr_errno.h ../../include/apr_pools.h \
- ../../include/apr_lib.h ../../include/apr_file_io.h \
- ../../include/apr_time.h ../../include/apr_thread_proc.h \
- ../../include/apr_getopt.h
-errorcodes.o: errorcodes.c misc.h ../../include/apr.h \
- ../../include/apr_private.h ../../include/apr_general.h \
- ../../include/apr_errno.h ../../include/apr_pools.h \
- ../../include/apr_lib.h ../../include/apr_file_io.h \
- ../../include/apr_time.h ../../include/apr_thread_proc.h \
- ../../include/apr_getopt.h
-getopt.o: getopt.c misc.h ../../include/apr.h \
- ../../include/apr_private.h ../../include/apr_general.h \
- ../../include/apr_errno.h ../../include/apr_pools.h \
- ../../include/apr_lib.h ../../include/apr_file_io.h \
- ../../include/apr_time.h ../../include/apr_thread_proc.h \
- ../../include/apr_getopt.h
-otherchild.o: otherchild.c misc.h ../../include/apr.h \
- ../../include/apr_private.h ../../include/apr_general.h \
- ../../include/apr_errno.h ../../include/apr_pools.h \
- ../../include/apr_lib.h ../../include/apr_file_io.h \
- ../../include/apr_time.h ../../include/apr_thread_proc.h \
- ../../include/apr_getopt.h ../../threadproc/unix/threadproc.h \
- ../../file_io/unix/fileio.h
-rand.o: rand.c misc.h ../../include/apr.h ../../include/apr_private.h \
- ../../include/apr_general.h ../../include/apr_errno.h \
- ../../include/apr_pools.h ../../include/apr_lib.h \
- ../../include/apr_file_io.h ../../include/apr_time.h \
- ../../include/apr_thread_proc.h ../../include/apr_getopt.h
-start.o: start.c misc.h ../../include/apr.h \
- ../../include/apr_private.h ../../include/apr_general.h \
- ../../include/apr_errno.h ../../include/apr_pools.h \
- ../../include/apr_lib.h ../../include/apr_file_io.h \
- ../../include/apr_time.h ../../include/apr_thread_proc.h \
- ../../include/apr_getopt.h ../../locks/unix/locks.h \
- ../../include/apr_lock.h
diff --git a/misc/unix/canonerr.c b/misc/unix/canonerr.c
deleted file mode 100644
index 6fee3e34deb..00000000000
--- a/misc/unix/canonerr.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "misc.h"
-
-#ifndef OS2
-
-int ap_canonical_error(ap_status_t errcode)
-{
-#if defined(EAGAIN) && defined(EWOULDBLOCK) && (EAGAIN != EWOULDBLOCK)
-    if (errcode == EWOULDBLOCK) {
-        errcode = EAGAIN;
-    }
-#endif
-    return errcode;
-}
-
-#endif
diff --git a/misc/unix/charset.c b/misc/unix/charset.c
new file mode 100644
index 00000000000..a16310cd0c9
--- /dev/null
+++ b/misc/unix/charset.c
@@ -0,0 +1,83 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_private.h"
+#include "apr_strings.h"
+#include "apr_portable.h"
+
+#ifdef HAVE_LANGINFO_H
+#include <langinfo.h>
+#endif
+
+/*
+ * simple heuristic to determine codepage of source code so that
+ * literal strings (e.g., "GET /\r\n") in source code can be translated
+ * properly
+ *
+ * If appropriate, a symbol can be set at configure time to determine
+ * this.  On EBCDIC platforms, it will be important how the code was
+ * unpacked.
+ */
+
+APR_DECLARE(const char*) apr_os_default_encoding (apr_pool_t *pool)
+{
+#ifdef __MVS__
+#    ifdef __CODESET__
+        return __CODESET__;
+#    else
+        return "IBM-1047";
+#    endif
+#endif
+
+    if ('}' == 0xD0) {
+        return "IBM-1047";
+    }
+
+    if ('{' == 0xFB) {
+        return "EDF04";
+    }
+
+    if ('A' == 0xC1) {
+        return "EBCDIC"; /* not useful */
+    }
+
+    if ('A' == 0x41) {
+        return "ISO-8859-1"; /* not necessarily true */
+    }
+
+    return "unknown";
+}
+
+
+APR_DECLARE(const char*) apr_os_locale_encoding (apr_pool_t *pool)
+{
+#if defined(HAVE_NL_LANGINFO) && defined(CODESET)
+    const char *charset;
+
+    charset = nl_langinfo(CODESET);
+    if (charset && *charset) {
+#ifdef _OSD_POSIX /* Bug workaround - delete as soon as fixed in OSD_POSIX */
+        /* Some versions of OSD_POSIX return nl_langinfo(CODESET)="^[nN]" */
+        /* Ignore the bogus information and use apr_os_default_encoding() */
+        if (charset[0] != '^')
+#endif
+        return apr_pstrdup(pool, charset);
+    }
+#endif
+
+    return apr_os_default_encoding(pool);
+}
diff --git a/misc/unix/env.c b/misc/unix/env.c
new file mode 100644
index 00000000000..b41f8f17b52
--- /dev/null
+++ b/misc/unix/env.c
@@ -0,0 +1,88 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define APR_WANT_STRFUNC
+#include "apr_want.h"
+#include "apr.h"
+#include "apr_private.h"
+#include "apr_env.h"
+#include "apr_strings.h"
+
+#if APR_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+APR_DECLARE(apr_status_t) apr_env_get(char **value,
+                                      const char *envvar,
+                                      apr_pool_t *pool)
+{
+#ifdef HAVE_GETENV
+
+    char *val = getenv(envvar);
+    if (!val)
+        return APR_ENOENT;
+    *value = val;
+    return APR_SUCCESS;
+
+#else
+    return APR_ENOTIMPL;
+#endif
+}
+
+
+APR_DECLARE(apr_status_t) apr_env_set(const char *envvar,
+                                      const char *value,
+                                      apr_pool_t *pool)
+{
+#if defined(HAVE_SETENV)
+
+    if (0 > setenv(envvar, value, 1))
+        return APR_ENOMEM;
+    return APR_SUCCESS;
+
+#elif defined(HAVE_PUTENV)
+
+    if (0 > putenv(apr_pstrcat(pool, envvar, "=", value, NULL)))
+        return APR_ENOMEM;
+    return APR_SUCCESS;
+
+#else
+    return APR_ENOTIMPL;
+#endif
+}
+
+
+APR_DECLARE(apr_status_t) apr_env_delete(const char *envvar, apr_pool_t *pool)
+{
+#ifdef HAVE_UNSETENV
+
+    unsetenv(envvar);
+    return APR_SUCCESS;
+
+#else
+    /* hint: some platforms allow envvars to be unset via
+     *       putenv("varname")...  that isn't Single Unix spec,
+     *       but if your platform doesn't have unsetenv() it is
+     *       worth investigating and potentially adding a
+     *       configure check to decide when to use that form of
+     *       putenv() here
+     */
+    return APR_ENOTIMPL;
+#endif
+}
diff --git a/misc/unix/errorcodes.c b/misc/unix/errorcodes.c
index 7d1e4cd4469..4f9b1d92474 100644
--- a/misc/unix/errorcodes.c
+++ b/misc/unix/errorcodes.c
@@ -1,81 +1,50 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "misc.h"
+#include "apr_arch_misc.h"
+#include "apr_strings.h"
+#include "apr_lib.h"
+#include "apr_dso.h"
+
+#include "apu_errno.h"
+
+#if APR_HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
 
 /*
- * stuffbuffer - Stuff contents of string 's' into buffer 'buf' 
- * w/o overflowing 'buf' then NULL terminate.
+ * stuffbuffer - like apr_cpystrn() but returns the address of the
+ * dest buffer instead of the address of the terminating '\0'
  */
-static char *stuffbuffer(char *buf, ap_size_t bufsize, const char *s)
+static char *stuffbuffer(char *buf, apr_size_t bufsize, const char *s)
 {
-    ap_size_t len = strlen(s);
-    if (len > bufsize)
-        len = bufsize;
-    memcpy(buf, s, len);
-    if (len)
-        buf[len-1] = '\0';
+    apr_cpystrn(buf,s,bufsize);
     return buf;
 }
 
-static char *apr_error_string(ap_status_t statcode)
+static char *apr_error_string(apr_status_t statcode)
 {
     switch (statcode) {
+    case APR_ENOSTAT:
+        return "Could not perform a stat on the file.";
     case APR_ENOPOOL:
         return "A new pool could not be created.";
-    case APR_ENOFILE:
-        return "No file was provided and one was required.";
     case APR_EBADDATE:
         return "An invalid date has been provided";
     case APR_EINVALSOCK:
@@ -99,7 +68,19 @@ static char *apr_error_string(ap_status_t statcode)
     case APR_ENOSHMAVAIL:
         return "No shared memory is currently available";
     case APR_EDSOOPEN:
-        return "Could not open the dso.";
+#if APR_HAS_DSO && defined(HAVE_LIBDL)
+        return dlerror();
+#else
+        return "DSO load failed";
+#endif /* HAVE_LIBDL */
+    case APR_EBADIP:
+        return "The specified IP address is invalid.";
+    case APR_EBADMASK:
+        return "The specified network mask is invalid.";
+    case APR_ESYMNOTFOUND:
+        return "Could not find the requested symbol.";
+    case APR_ENOTENOUGHENTROPY:
+        return "Not enough entropy to continue.";
     case APR_INCHILD:
         return
 	    "Your code just forked, and you are currently executing in the "
@@ -118,6 +99,8 @@ static char *apr_error_string(ap_status_t statcode)
         return "The specified child process is not done executing";
     case APR_TIMEUP:
         return "The timeout specified has expired";
+    case APR_INCOMPLETE:
+        return "Partial results are valid but processing is incomplete";
     case APR_BADCH:
         return "Bad character specified on command line";
     case APR_BADARG:
@@ -140,6 +123,33 @@ static char *apr_error_string(ap_status_t statcode)
         return "This function has not been implemented on this platform";
     case APR_EMISMATCH:
         return "passwords do not match";
+    case APR_EABSOLUTE:
+        return "The given path is absolute";
+    case APR_ERELATIVE:
+        return "The given path is relative";
+    case APR_EINCOMPLETE:
+        return "The given path is incomplete";
+    case APR_EABOVEROOT:
+        return "The given path was above the root path";
+    case APR_EBADPATH:
+        return "The given path is misformatted or contained invalid characters";
+    case APR_EPATHWILD:
+        return "The given path contained wildcard characters";
+    case APR_EBUSY:
+        return "The given lock was busy.";
+    case APR_EPROC_UNKNOWN:
+        return "The process is not recognized.";
+    case APR_EGENERAL:
+        return "Internal error (specific information not available)";
+
+/* APR Util error codes */
+    case APR_ECRYPT:
+        return "Internal error in the crypto subsystem (specific information not available)";
+    case APR_ENOENGINE:
+        return "No engine found for crypto subsystem";
+    case APR_EINITENGINE:
+        return "Failed to init engine for crypto subsystem";
+
     default:
         return "Error string not specified yet";
     }
@@ -147,11 +157,11 @@ static char *apr_error_string(ap_status_t statcode)
 
 
 #ifdef OS2
-#define INCL_DOS
-#include <os2.h>
 #include <ctype.h>
 
-static char *apr_os_strerror(char* buf, ap_size_t bufsize, int err)
+int apr_canonical_error(apr_status_t err);
+
+static char *apr_os_strerror(char* buf, apr_size_t bufsize, int err)
 {
   char result[200];
   unsigned char message[HUGE_STRING_LEN];
@@ -161,7 +171,7 @@ static char *apr_os_strerror(char* buf, ap_size_t bufsize, int err)
   
   if (err >= 10000 && err < 12000) {  /* socket error codes */
       return stuffbuffer(buf, bufsize,
-                         strerror(ap_canonical_error(err+APR_OS_START_SYSERR)));
+                         strerror(apr_canonical_error(err+APR_OS_START_SYSERR)));
   } 
   else if (DosGetMessage(NULL, 0, message, HUGE_STRING_LEN, err,
 			 "OSO001.MSG", &len) == 0) {
@@ -170,13 +180,13 @@ static char *apr_os_strerror(char* buf, ap_size_t bufsize, int err)
       pos = result;
   
       if (len >= sizeof(result))
-        len = sizeof(result-1);
+        len = sizeof(result) - 1;
 
       for (c=0; c<len; c++) {
 	  /* skip multiple whitespace */
-          while (ap_isspace(message[c]) && ap_isspace(message[c+1]))
+          while (apr_isspace(message[c]) && apr_isspace(message[c+1]))
               c++;
-          *(pos++) = ap_isspace(message[c]) ? ' ' : message[c];
+          *(pos++) = apr_isspace(message[c]) ? ' ' : message[c];
       }
   
       *pos = 0;
@@ -190,26 +200,255 @@ static char *apr_os_strerror(char* buf, ap_size_t bufsize, int err)
    */
   return stuffbuffer(buf, bufsize, result);  
 }
+
+#elif defined(WIN32) || (defined(NETWARE) && defined(USE_WINSOCK))
+
+static const struct {
+    apr_status_t code;
+    const char *msg;
+} gaErrorList[] = {
+    {WSAEINTR,           "Interrupted system call"},
+    {WSAEBADF,           "Bad file number"},
+    {WSAEACCES,          "Permission denied"},
+    {WSAEFAULT,          "Bad address"},
+    {WSAEINVAL,          "Invalid argument"},
+    {WSAEMFILE,          "Too many open sockets"},
+    {WSAEWOULDBLOCK,     "Operation would block"},
+    {WSAEINPROGRESS,     "Operation now in progress"},
+    {WSAEALREADY,        "Operation already in progress"},
+    {WSAENOTSOCK,        "Socket operation on non-socket"},
+    {WSAEDESTADDRREQ,    "Destination address required"},
+    {WSAEMSGSIZE,        "Message too long"},
+    {WSAEPROTOTYPE,      "Protocol wrong type for socket"},
+    {WSAENOPROTOOPT,     "Bad protocol option"},
+    {WSAEPROTONOSUPPORT, "Protocol not supported"},
+    {WSAESOCKTNOSUPPORT, "Socket type not supported"},
+    {WSAEOPNOTSUPP,      "Operation not supported on socket"},
+    {WSAEPFNOSUPPORT,    "Protocol family not supported"},
+    {WSAEAFNOSUPPORT,    "Address family not supported"},
+    {WSAEADDRINUSE,      "Address already in use"},
+    {WSAEADDRNOTAVAIL,   "Can't assign requested address"},
+    {WSAENETDOWN,        "Network is down"},
+    {WSAENETUNREACH,     "Network is unreachable"},
+    {WSAENETRESET,       "Net connection reset"},
+    {WSAECONNABORTED,    "Software caused connection abort"},
+    {WSAECONNRESET,      "Connection reset by peer"},
+    {WSAENOBUFS,         "No buffer space available"},
+    {WSAEISCONN,         "Socket is already connected"},
+    {WSAENOTCONN,        "Socket is not connected"},
+    {WSAESHUTDOWN,       "Can't send after socket shutdown"},
+    {WSAETOOMANYREFS,    "Too many references, can't splice"},
+    {WSAETIMEDOUT,       "Connection timed out"},
+    {WSAECONNREFUSED,    "Connection refused"},
+    {WSAELOOP,           "Too many levels of symbolic links"},
+    {WSAENAMETOOLONG,    "File name too long"},
+    {WSAEHOSTDOWN,       "Host is down"},
+    {WSAEHOSTUNREACH,    "No route to host"},
+    {WSAENOTEMPTY,       "Directory not empty"},
+    {WSAEPROCLIM,        "Too many processes"},
+    {WSAEUSERS,          "Too many users"},
+    {WSAEDQUOT,          "Disc quota exceeded"},
+    {WSAESTALE,          "Stale NFS file handle"},
+    {WSAEREMOTE,         "Too many levels of remote in path"},
+    {WSASYSNOTREADY,     "Network system is unavailable"},
+    {WSAVERNOTSUPPORTED, "Winsock version out of range"},
+    {WSANOTINITIALISED,  "WSAStartup not yet called"},
+    {WSAEDISCON,         "Graceful shutdown in progress"},
+    {WSAHOST_NOT_FOUND,  "Host not found"},
+    {WSANO_DATA,         "No host data of that type was found"},
+    {0,                  NULL}
+};
+
+
+static char *apr_os_strerror(char *buf, apr_size_t bufsize, apr_status_t errcode)
+{
+    apr_size_t len=0, i;
+
+#ifndef NETWARE
+#ifndef _WIN32_WCE
+    len = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM 
+                      | FORMAT_MESSAGE_IGNORE_INSERTS,
+                        NULL,
+                        errcode,
+                        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
+                        buf,
+                        (DWORD)bufsize,
+                        NULL);
+#else /* _WIN32_WCE speaks unicode */
+     LPTSTR msg = (LPTSTR) buf;
+     len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM 
+                       | FORMAT_MESSAGE_IGNORE_INSERTS,
+                         NULL,
+                         errcode,
+                         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
+                         msg,
+                         (DWORD) (bufsize/sizeof(TCHAR)),
+                         NULL);
+     /* in-place convert to US-ASCII, substituting '?' for non ASCII   */
+     for(i = 0; i <= len; i++) {
+        if (msg[i] < 0x80 && msg[i] >= 0) {
+            buf[i] = (char) msg[i];
+        } else {
+            buf[i] = '?';
+        }
+    }
+#endif
+#endif
+
+    if (!len) {
+        for (i = 0; gaErrorList[i].msg; ++i) {
+            if (gaErrorList[i].code == errcode) {
+                apr_cpystrn(buf, gaErrorList[i].msg, bufsize);
+                len = strlen(buf);
+                break;
+            }
+        }
+    }
+
+    if (len) {
+        /* FormatMessage put the message in the buffer, but it may
+         * have embedded a newline (\r\n), and possible more than one.
+         * Remove the newlines replacing them with a space. This is not
+         * as visually perfect as moving all the remaining message over,
+         * but more efficient.
+         */
+        i = len;
+        while (i) {
+            i--;
+            if ((buf[i] == '\r') || (buf[i] == '\n'))
+                buf[i] = ' ';
+        }
+    }
+    else {
+        /* Windows didn't provide us with a message.  Even stuff like                    * WSAECONNREFUSED won't get a message.
+         */
+        apr_snprintf(buf, bufsize, "Unrecognized Win32 error code %d", errcode);
+    }
+
+    return buf;
+}
+
+#else
+/* On Unix, apr_os_strerror() handles error codes from the resolver 
+ * (h_errno). 
+ */
+static char *apr_os_strerror(char* buf, apr_size_t bufsize, int err) 
+{
+#ifdef HAVE_HSTRERROR
+    return stuffbuffer(buf, bufsize, hstrerror(err));
+#else /* HAVE_HSTRERROR */
+    const char *msg;
+
+    switch(err) {
+    case HOST_NOT_FOUND:
+        msg = "Unknown host";
+        break;
+#if defined(NO_DATA)
+    case NO_DATA:
+#if defined(NO_ADDRESS) && (NO_DATA != NO_ADDRESS)
+    case NO_ADDRESS:
+#endif
+        msg = "No address for host";
+        break;
+#elif defined(NO_ADDRESS)
+    case NO_ADDRESS:
+        msg = "No address for host";
+        break;
+#endif /* NO_DATA */
+    default:
+        msg = "Unrecognized resolver error";
+    }
+    return stuffbuffer(buf, bufsize, msg);
+#endif /* HAVE_STRERROR */
+}
+#endif
+
+#if defined(HAVE_STRERROR_R) && defined(STRERROR_R_RC_INT) && !defined(BEOS)
+/* AIX and Tru64 style */
+static char *native_strerror(apr_status_t statcode, char *buf,
+                             apr_size_t bufsize)
+{
+    if (strerror_r(statcode, buf, bufsize) < 0) {
+        return stuffbuffer(buf, bufsize, 
+                           "APR does not understand this error code");
+    }
+    else {
+        return buf;
+    }
+}
+#elif defined(HAVE_STRERROR_R)
+/* glibc style */
+
+/* BeOS has the function available, but it doesn't provide
+ * the prototype publically (doh!), so to avoid a build warning
+ * we add a suitable prototype here.
+ */
+#if defined(BEOS)
+const char *strerror_r(apr_status_t, char *, apr_size_t);
+#endif
+
+static char *native_strerror(apr_status_t statcode, char *buf,
+                             apr_size_t bufsize)
+{
+    const char *msg;
+
+    buf[0] = '\0';
+    msg = strerror_r(statcode, buf, bufsize);
+    if (buf[0] == '\0') { /* libc didn't use our buffer */
+        return stuffbuffer(buf, bufsize, msg);
+    }
+    else {
+        return buf;
+    }
+}
 #else
-static char *apr_os_strerror(char* buf, ap_size_t bufsize, int err) 
+/* plain old strerror(); 
+ * thread-safe on some platforms (e.g., Solaris, OS/390)
+ */
+static char *native_strerror(apr_status_t statcode, char *buf,
+                             apr_size_t bufsize)
 {
-    	return stuffbuffer(buf, bufsize,strerror(err));
+#ifdef _WIN32_WCE
+    static char err[32];
+    sprintf(err, "Native Error #%d", statcode);
+    return stuffbuffer(buf, bufsize, err);
+#else
+    const char *err = strerror(statcode);
+    if (err) {
+        return stuffbuffer(buf, bufsize, err);
+    } else {
+        return stuffbuffer(buf, bufsize, 
+                           "APR does not understand this error code");
+    }
+#endif
 }
 #endif
 
-char *ap_strerror(ap_status_t statcode, char *buf, ap_size_t bufsize)
+APR_DECLARE(char *) apr_strerror(apr_status_t statcode, char *buf,
+                                 apr_size_t bufsize)
 {
     if (statcode < APR_OS_START_ERROR) {
-        return stuffbuffer(buf, bufsize, strerror(statcode));
+        return native_strerror(statcode, buf, bufsize);
     }
-    else if (statcode < APR_OS_START_USEERR) {
+    else if (statcode < APR_OS_START_USERERR) {
         return stuffbuffer(buf, bufsize, apr_error_string(statcode));
     }
+    else if (statcode < APR_OS_START_EAIERR) {
+        return stuffbuffer(buf, bufsize, "APR does not understand this error code");
+    }
     else if (statcode < APR_OS_START_SYSERR) {
+#if defined(HAVE_GAI_STRERROR)
+        statcode -= APR_OS_START_EAIERR;
+#if defined(NEGATIVE_EAI)
+        statcode = -statcode;
+#endif
+        return stuffbuffer(buf, bufsize, gai_strerror(statcode));
+#else
         return stuffbuffer(buf, bufsize, "APR does not understand this error code");
+#endif
     }
     else {
-	return apr_os_strerror(buf, bufsize, statcode - APR_OS_START_SYSERR);
+        return apr_os_strerror(buf, bufsize, statcode - APR_OS_START_SYSERR);
     }
 }
 
diff --git a/misc/unix/getopt.c b/misc/unix/getopt.c
index 940e5b61217..24be3c82f89 100644
--- a/misc/unix/getopt.c
+++ b/misc/unix/getopt.c
@@ -31,94 +31,279 @@
  * SUCH DAMAGE.
  */
 
-#include "misc.h"
-
-int ap_opterr = 1,                      /* if error message should be printed */
-    ap_optind = 1,                      /* index into parent argv vector */
-    ap_optopt,                          /* character checked for validity */
-    ap_optreset;                        /* reset getopt */
-char *ap_optarg = "";                   /* argument associated with option */
+#include "apr_arch_misc.h"
+#include "apr_strings.h"
+#include "apr_lib.h"
 
 #define EMSG    ""
 
-ap_status_t ap_getopt(ap_int32_t nargc, char *const *nargv, const char *ostr, ap_int32_t *rv, ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_getopt_init(apr_getopt_t **os, apr_pool_t *cont,
+                                      int argc, const char *const *argv)
+{
+    void *argv_buff;
+
+    *os = apr_palloc(cont, sizeof(apr_getopt_t));
+    (*os)->cont = cont;
+    (*os)->reset = 0;
+    (*os)->errfn = (apr_getopt_err_fn_t*)(fprintf);
+    (*os)->errarg = (void*)(stderr);
+
+    (*os)->place = EMSG;
+    (*os)->argc = argc;
+
+    /* The argv parameter must be compatible with main()'s argv, since
+       that's the primary purpose of this function.  But people might
+       want to use this function with arrays other than the main argv,
+       and we shouldn't touch the caller's data.  So we copy. */
+    argv_buff = apr_palloc(cont, (argc + 1) * sizeof(const char *));
+    memcpy(argv_buff, argv, argc * sizeof(const char *));
+    (*os)->argv = argv_buff;
+    (*os)->argv[argc] = NULL;
+
+    (*os)->interleave = 0;
+    (*os)->ind = 1;
+    (*os)->skip_start = 1;
+    (*os)->skip_end = 1;
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_getopt(apr_getopt_t *os, const char *opts, 
+                                     char *optch, const char **optarg)
 {
-    char *p;
-    static char *place = EMSG;   /* option letter processing */
-    char *oli;                   /* option letter list index */
-
-    if (ap_optreset || !*place) {   /* update scanning pointer */
-        ap_optreset = 0;
-        if (ap_optind >= nargc || *(place = nargv[ap_optind]) != '-') {
-            place = EMSG;
-            *rv = ap_optopt;
+    const char *oli;  /* option letter list index */
+
+    if (os->reset || !*os->place) {   /* update scanning pointer */
+        os->reset = 0;
+        if (os->ind >= os->argc || *(os->place = os->argv[os->ind]) != '-') {
+            os->place = EMSG;
+            *optch = os->opt;
             return (APR_EOF);
         }
-        if (place[1] && *++place == '-') {        /* found "--" */
-            ++ap_optind;
-            place = EMSG;
-            *rv = ap_optopt;
+        if (os->place[1] && *++os->place == '-') {        /* found "--" */
+            ++os->ind;
+            os->place = EMSG;
+            *optch = os->opt;
             return (APR_EOF);
         }
     }                                /* option letter okay? */
-    if ((ap_optopt = (int) *place++) == (int) ':' ||
-        !(oli = strchr(ostr, ap_optopt))) {
+    if ((os->opt = (int) *os->place++) == (int) ':' ||
+        !(oli = strchr(opts, os->opt))) {
         /*
          * if the user didn't specify '-' as an option,
          * assume it means -1.
          */
-        if (ap_optopt == (int) '-')
-        {
-            *rv = ap_optopt;
+        if (os->opt == (int) '-') {
+            *optch = os->opt;
             return (APR_EOF);
         }
-        if (!*place)
-            ++ap_optind;
-        if (ap_opterr && *ostr != ':') {
-            if (!(p = strrchr(*nargv, '/')))
-                p = *nargv;
-            else
-                ++p;
-            (void) fprintf(stderr,
-                           "%s: illegal option -- %c\n", p, ap_optopt);
+        if (!*os->place)
+            ++os->ind;
+        if (os->errfn && *opts != ':') {
+            (os->errfn)(os->errarg, "%s: illegal option -- %c\n",
+                        apr_filepath_name_get(*os->argv), os->opt);
         }
-        *rv = ap_optopt;
-        return APR_BADCH;
+        *optch = os->opt;
+        return (APR_BADCH);
     }
     if (*++oli != ':') {        /* don't need argument */
-        ap_optarg = NULL;
-        if (!*place)
-            ++ap_optind;
+        *optarg = NULL;
+        if (!*os->place)
+            ++os->ind;
     }
     else {                        /* need an argument */
-        if (*place)                /* no white space */
-            ap_optarg = place;
-        else if (nargc <= ++ap_optind) {        /* no arg */
-            place = EMSG;
-            if (*ostr == ':')
-            {
-                *rv = ap_optopt;
+        if (*os->place)                /* no white space */
+            *optarg = os->place;
+        else if (os->argc <= ++os->ind) {        /* no arg */
+            os->place = EMSG;
+            if (*opts == ':') {
+                *optch = os->opt;
                 return (APR_BADARG);
             }
-            if (ap_opterr) {
-                if (!(p = strrchr(*nargv, '/')))
-                    p = *nargv;
-                else
-                    ++p;
-                (void) fprintf(stderr,
-                               "%s: option requires an argument -- %c\n",
-                               p, ap_optopt);
+            if (os->errfn) {
+                (os->errfn)(os->errarg, 
+                            "%s: option requires an argument -- %c\n",
+                            apr_filepath_name_get(*os->argv), os->opt);
             }
-            *rv = ap_optopt;
+            *optch = os->opt;
             return (APR_BADCH);
         }
         else                        /* white space */
-            ap_optarg = nargv[ap_optind];
-        place = EMSG;
-        ++ap_optind;
+            *optarg = os->argv[os->ind];
+        os->place = EMSG;
+        ++os->ind;
     }
-    *rv = ap_optopt;
+    *optch = os->opt;
     return APR_SUCCESS;
 }
 
+/* Reverse the sequence argv[start..start+len-1]. */
+static void reverse(const char **argv, int start, int len)
+{
+    const char *temp;
+
+    for (; len >= 2; start++, len -= 2) {
+        temp = argv[start];
+        argv[start] = argv[start + len - 1];
+        argv[start + len - 1] = temp;
+    }
+}
+
+/*
+ * Permute os->argv with the goal that non-option arguments will all
+ * appear at the end.  os->skip_start is where we started skipping
+ * non-option arguments, os->skip_end is where we stopped, and os->ind
+ * is where we are now.
+ */
+static void permute(apr_getopt_t *os)
+{
+    int len1 = os->skip_end - os->skip_start;
+    int len2 = os->ind - os->skip_end;
+
+    if (os->interleave) {
+        /*
+         * Exchange the sequences argv[os->skip_start..os->skip_end-1] and
+         * argv[os->skip_end..os->ind-1].  The easiest way to do that is
+         * to reverse the entire range and then reverse the two
+         * sub-ranges.
+         */
+        reverse(os->argv, os->skip_start, len1 + len2);
+        reverse(os->argv, os->skip_start, len2);
+        reverse(os->argv, os->skip_start + len2, len1);
+    }
+
+    /* Reset skip range to the new location of the non-option sequence. */
+    os->skip_start += len2;
+    os->skip_end += len2;
+}
+
+/* Helper function to print out an error involving a long option */
+static apr_status_t serr(apr_getopt_t *os, const char *err, const char *str,
+                         apr_status_t status)
+{
+    if (os->errfn)
+        (os->errfn)(os->errarg, "%s: %s: %s\n", 
+                    apr_filepath_name_get(*os->argv), err, str);
+    return status;
+}
 
+/* Helper function to print out an error involving a short option */
+static apr_status_t cerr(apr_getopt_t *os, const char *err, int ch,
+                         apr_status_t status)
+{
+    if (os->errfn)
+        (os->errfn)(os->errarg, "%s: %s: %c\n", 
+                    apr_filepath_name_get(*os->argv), err, ch);
+    return status;
+}
+
+APR_DECLARE(apr_status_t) apr_getopt_long(apr_getopt_t *os,
+                                          const apr_getopt_option_t *opts,
+                                          int *optch, const char **optarg)
+{
+    const char *p;
+    int i;
+
+    /* Let the calling program reset option processing. */
+    if (os->reset) {
+        os->place = EMSG;
+        os->ind = 1;
+        os->reset = 0;
+    }
+
+    /*
+     * We can be in one of two states: in the middle of processing a
+     * run of short options, or about to process a new argument.
+     * Since the second case can lead to the first one, handle that
+     * one first.  */
+    p = os->place;
+    if (*p == '\0') {
+        /* If we are interleaving, skip non-option arguments. */
+        if (os->interleave) {
+            while (os->ind < os->argc && *os->argv[os->ind] != '-')
+                os->ind++;
+            os->skip_end = os->ind;
+        }
+        if (os->ind >= os->argc || *os->argv[os->ind] != '-') {
+            os->ind = os->skip_start;
+            return APR_EOF;
+        }
+
+        p = os->argv[os->ind++] + 1;
+        if (*p == '-' && p[1] != '\0') {        /* Long option */
+            /* Search for the long option name in the caller's table. */
+            apr_size_t len = 0;
+
+            p++;
+            for (i = 0; ; i++) {
+                if (opts[i].optch == 0)             /* No match */
+                    return serr(os, "invalid option", p - 2, APR_BADCH);
+
+                if (opts[i].name) {
+                    len = strlen(opts[i].name);
+                    if (strncmp(p, opts[i].name, len) == 0
+                        && (p[len] == '\0' || p[len] == '='))
+                        break;
+                }
+            }
+            *optch = opts[i].optch;
+
+            if (opts[i].has_arg) {
+                if (p[len] == '=')             /* Argument inline */
+                    *optarg = p + len + 1;
+                else { 
+                    if (os->ind >= os->argc)   /* Argument missing */
+                        return serr(os, "missing argument", p - 2, APR_BADARG);
+                    else                       /* Argument in next arg */
+                        *optarg = os->argv[os->ind++];
+                }
+            } else {
+                *optarg = NULL;
+                if (p[len] == '=')
+                    return serr(os, "erroneous argument", p - 2, APR_BADARG);
+            }
+            permute(os);
+            return APR_SUCCESS;
+        } else {
+            if (*p == '-') {                 /* Bare "--"; we're done */
+                permute(os);
+                os->ind = os->skip_start;
+                return APR_EOF;
+            }
+            else 
+                if (*p == '\0')                    /* Bare "-" is illegal */
+                    return serr(os, "invalid option", p, APR_BADCH);
+        }
+    }
+
+    /*
+     * Now we're in a run of short options, and *p is the next one.
+     * Look for it in the caller's table.
+     */
+    for (i = 0; ; i++) {
+        if (opts[i].optch == 0)                     /* No match */
+            return cerr(os, "invalid option character", *p, APR_BADCH);
+
+        if (*p == opts[i].optch)
+            break;
+    }
+    *optch = *p++;
+
+    if (opts[i].has_arg) {
+        if (*p != '\0')                         /* Argument inline */
+            *optarg = p;
+        else { 
+            if (os->ind >= os->argc)           /* Argument missing */
+                return cerr(os, "missing argument", *optch, APR_BADARG);
+            else                               /* Argument in next arg */
+                *optarg = os->argv[os->ind++];
+        }
+        os->place = EMSG;
+    } else {
+        *optarg = NULL;
+        os->place = p;
+    }
+
+    permute(os);
+    return APR_SUCCESS;
+}
diff --git a/misc/unix/misc.h b/misc/unix/misc.h
deleted file mode 100644
index bb754bbf62e..00000000000
--- a/misc/unix/misc.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef MISC_H
-#define MISC_H
-
-#include "apr.h"
-#include "apr_private.h"
-#include "apr_general.h"
-#include "apr_pools.h"
-#include "apr_getopt.h"
-#include "apr_thread_proc.h"
-#include "apr_errno.h"
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STDIO_H
-#include <stdio.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_SIGNAL_H
-#include <signal.h>
-#endif
-#ifdef HAVE_PTHREAD_H
-#include <pthread.h>
-#endif
- 
-typedef struct datastruct {
-    void *data;
-    char *key;
-    struct datastruct *next;
-    struct datastruct *prev;
-} datastruct;
-
-struct ap_other_child_rec_t {
-    struct ap_other_child_rec_t *next;
-    int pid;
-    void (*maintenance) (int, void *, int);
-    void *data;
-    int write_fd;
-};
-
-
-#endif  /* ! MISC_H */
-
diff --git a/misc/unix/otherchild.c b/misc/unix/otherchild.c
index dd2368685ad..a2fef19acad 100644
--- a/misc/unix/otherchild.c
+++ b/misc/unix/otherchild.c
@@ -1,89 +1,44 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "misc.h"
-#include "threadproc.h"
+#include "apr.h"
+#include "apr_arch_misc.h"
+#include "apr_arch_threadproc.h"
+#include "apr_arch_file_io.h"
+
+#if APR_HAS_OTHER_CHILD
+
 #ifdef HAVE_TIME_H
 #include <sys/time.h>
 #endif
 #ifdef HAVE_SYS_SELECT_H
 #include <sys/select.h>
 #endif
-#ifdef HAVE_SYS_WAIT_H
+#if APR_HAVE_SYS_WAIT_H
 #include <sys/wait.h>
 #endif
+#ifdef BEOS
+#include <sys/socket.h> /* for fd_set definition! */
+#endif
 
-static ap_other_child_rec_t *other_children = NULL;
-
-API_EXPORT(void) ap_register_other_child(ap_proc_t *pid,
-                     void (*maintenance) (int reason, void *, int status),
-                     void *data, int write_fd, ap_pool_t *p)
-{
-    ap_other_child_rec_t *ocr;
-
-    ocr = ap_palloc(p, sizeof(*ocr));
-    ocr->pid = pid->pid;
-    ocr->maintenance = maintenance;
-    ocr->data = data;
-    ocr->write_fd = write_fd;
-    ocr->next = other_children;
-    other_children = ocr;
-}
+static apr_other_child_rec_t *other_children = NULL;
 
-API_EXPORT(void) ap_unregister_other_child(void *data)
+static apr_status_t other_child_cleanup(void *data)
 {
-    ap_other_child_rec_t **pocr, *nocr;
+    apr_other_child_rec_t **pocr, *nocr;
 
     for (pocr = &other_children; *pocr; pocr = &(*pocr)->next) {
         if ((*pocr)->data == data) {
@@ -91,100 +46,190 @@ API_EXPORT(void) ap_unregister_other_child(void *data)
             (*(*pocr)->maintenance) (APR_OC_REASON_UNREGISTER, (*pocr)->data, -1);
             *pocr = nocr;
             /* XXX: um, well we've just wasted some space in pconf ? */
-            return;
+            return APR_SUCCESS;
         }
     }
+    return APR_SUCCESS;
 }
 
-/* test to ensure that the write_fds are all still writable, otherwise
- * invoke the maintenance functions as appropriate */
-static void probe_writable_fds(void)
+APR_DECLARE(void) apr_proc_other_child_register(apr_proc_t *proc,
+                     void (*maintenance) (int reason, void *, int status),
+                     void *data, apr_file_t *write_fd, apr_pool_t *p)
 {
-    fd_set writable_fds;
-    int fd_max;
-    ap_other_child_rec_t *ocr, *nocr; 
-    struct timeval tv; 
-    int rc;
+    apr_other_child_rec_t *ocr;
 
-    if (other_children == NULL)
-        return;
+    ocr = apr_palloc(p, sizeof(*ocr));
+    ocr->p = p;
+    ocr->proc = proc;
+    ocr->maintenance = maintenance;
+    ocr->data = data;
+    ocr->next = other_children;
+    other_children = ocr;
+    apr_pool_cleanup_register(p, ocr->data, other_child_cleanup, 
+                              apr_pool_cleanup_null);
+}
+
+APR_DECLARE(void) apr_proc_other_child_unregister(void *data)
+{
+    apr_other_child_rec_t *cur;
 
-    fd_max = 0;
-    FD_ZERO(&writable_fds);
-    do {
-        for (ocr = other_children; ocr; ocr = ocr->next) {
-            if (ocr->write_fd == -1)
-                continue;
-            FD_SET(ocr->write_fd, &writable_fds);
-            if (ocr->write_fd > fd_max) {
-                fd_max = ocr->write_fd;
-            }
+    cur = other_children;
+    while (cur) {
+        if (cur->data == data) {
+            break;
         }
-        if (fd_max == 0)
-            return;
+        cur = cur->next;
+    }
 
-        tv.tv_sec = 0;
-        tv.tv_usec = 0;
-        rc = select(fd_max + 1, NULL, &writable_fds, NULL, &tv);
-    } while (rc == -1 && errno == EINTR);
+    /* segfault if this function called with invalid parm */
+    apr_pool_cleanup_kill(cur->p, cur->data, other_child_cleanup);
+    other_child_cleanup(data);
+}
 
-    if (rc == -1) {
-        /* XXX: uhh this could be really bad, we could have a bad file
-         * descriptor due to a bug in one of the maintenance routines */
-        return;
-    }
-    if (rc == 0)
-        return;
+APR_DECLARE(apr_status_t) apr_proc_other_child_alert(apr_proc_t *proc,
+                                                     int reason,
+                                                     int status)
+{
+    apr_other_child_rec_t *ocr, *nocr;
 
     for (ocr = other_children; ocr; ocr = nocr) {
         nocr = ocr->next;
-        if (ocr->write_fd == -1)
+        if (ocr->proc->pid != proc->pid)
             continue;
-        if (FD_ISSET(ocr->write_fd, &writable_fds))
-            continue;
-        (*ocr->maintenance) (APR_OC_REASON_UNWRITABLE, ocr->data, -1);
+
+        ocr->proc = NULL;
+        (*ocr->maintenance) (reason, ocr->data, status);
+        return APR_SUCCESS;
     }
+    return APR_EPROC_UNKNOWN;
 }
 
-API_EXPORT(ap_status_t) ap_reap_other_child(ap_proc_t *pid, int status)
+APR_DECLARE(void) apr_proc_other_child_refresh(apr_other_child_rec_t *ocr,
+                                               int reason)
 {
-    ap_other_child_rec_t *ocr, *nocr;
+    /* Todo: 
+     * Implement code to detect if pipes are still alive.
+     */
+#ifdef WIN32
+    DWORD status;
 
-    for (ocr = other_children; ocr; ocr = nocr) {
-        nocr = ocr->next;
-        if (ocr->pid != pid->pid)
-            continue;
+    if (ocr->proc == NULL)
+        return;
 
-        ocr->pid = -1;
+    if (!ocr->proc->hproc) {
+        /* Already mopped up, perhaps we apr_proc_kill'ed it,
+         * they should have already unregistered!
+         */
+        ocr->proc = NULL;
+        (*ocr->maintenance) (APR_OC_REASON_LOST, ocr->data, -1);
+    }
+    else if (!GetExitCodeProcess(ocr->proc->hproc, &status)) {
+        CloseHandle(ocr->proc->hproc);
+        ocr->proc->hproc = NULL;
+        ocr->proc = NULL;
+        (*ocr->maintenance) (APR_OC_REASON_LOST, ocr->data, -1);
+    }
+    else if (status == STILL_ACTIVE) {
+        (*ocr->maintenance) (reason, ocr->data, -1);
+    }
+    else {
+        CloseHandle(ocr->proc->hproc);
+        ocr->proc->hproc = NULL;
+        ocr->proc = NULL;
         (*ocr->maintenance) (APR_OC_REASON_DEATH, ocr->data, status);
-        return 0;
     }
-    return APR_CHILD_NOTDONE;
-}
 
-API_EXPORT(void) ap_check_other_child(void)
-{
-    ap_other_child_rec_t *ocr, *nocr;
+#elif defined(OS2)
+    int rc;
+    int status;
+    RESULTCODES proc_rc;
+    PID ended_pid;
+
+    if (ocr->proc == NULL) {
+        return;
+    }
+
+    rc = DosWaitChild(DCWA_PROCESS, DCWW_NOWAIT, &proc_rc, &ended_pid, ocr->proc->pid);
+
+    switch (rc) {
+    case 0:
+        ocr->proc = NULL;
+        status = (proc_rc.codeResult << 8) | proc_rc.codeTerminate;
+        (*ocr->maintenance) (APR_OC_REASON_DEATH, ocr->data, status);
+        break;
+
+    case ERROR_CHILD_NOT_COMPLETE:
+        (*ocr->maintenance) (reason, ocr->data, -1);
+        break;
+
+    default:
+        ocr->proc = NULL;
+        (*ocr->maintenance) (APR_OC_REASON_LOST, ocr->data, -1);
+        break;
+    }
+#else /* ndef Win32 */
     pid_t waitret; 
     int status;
 
-    for (ocr = other_children; ocr; ocr = nocr) {
-        nocr = ocr->next;
-        if (ocr->pid == -1)
-            continue;
+    if (ocr->proc == NULL)
+        return;
 
-        waitret = waitpid(ocr->pid, &status, WNOHANG);
-        if (waitret == ocr->pid) {
-            ocr->pid = -1;
-            (*ocr->maintenance) (APR_OC_REASON_DEATH, ocr->data, status);
-        }
-        else if (waitret == 0) {
-            (*ocr->maintenance) (APR_OC_REASON_RESTART, ocr->data, -1);
-        }
-        else if (waitret == -1) {
-            /* uh what the heck? they didn't call unregister? */
-            ocr->pid = -1;
-            (*ocr->maintenance) (APR_OC_REASON_LOST, ocr->data, -1);
-        }
+    waitret = waitpid(ocr->proc->pid, &status, WNOHANG);
+    if (waitret == ocr->proc->pid) {
+        ocr->proc = NULL;
+        (*ocr->maintenance) (APR_OC_REASON_DEATH, ocr->data, status);
+    }
+    else if (waitret == 0) {
+        (*ocr->maintenance) (reason, ocr->data, -1);
+    }
+    else if (waitret == -1) {
+        /* uh what the heck? they didn't call unregister? */
+        ocr->proc = NULL;
+        (*ocr->maintenance) (APR_OC_REASON_LOST, ocr->data, -1);
     }
+#endif
 }
+
+APR_DECLARE(void) apr_proc_other_child_refresh_all(int reason)
+{
+    apr_other_child_rec_t *ocr, *next_ocr;
+
+    for (ocr = other_children; ocr; ocr = next_ocr) {
+        next_ocr = ocr->next;
+        apr_proc_other_child_refresh(ocr, reason);
+    }
+}
+
+#else /* !APR_HAS_OTHER_CHILD */
+
+APR_DECLARE(void) apr_proc_other_child_register(apr_proc_t *proc,
+                     void (*maintenance) (int reason, void *, int status),
+                     void *data, apr_file_t *write_fd, apr_pool_t *p)
+{
+    return;
+}
+
+APR_DECLARE(void) apr_proc_other_child_unregister(void *data)
+{
+    return;
+}
+
+APR_DECLARE(apr_status_t) apr_proc_other_child_alert(apr_proc_t *proc,
+                                                     int reason,
+                                                     int status)
+{
+    return APR_ENOTIMPL;
+}
+
+APR_DECLARE(void) apr_proc_other_child_refresh(apr_other_child_rec_t *ocr,
+                                               int reason)
+{
+    return;
+}
+
+APR_DECLARE(void) apr_proc_other_child_refresh_all(int reason)
+{
+    return;
+}
+
+#endif /* APR_HAS_OTHER_CHILD */
diff --git a/misc/unix/rand.c b/misc/unix/rand.c
index aebd1d2f261..5e235990196 100644
--- a/misc/unix/rand.c
+++ b/misc/unix/rand.c
@@ -1,87 +1,277 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "misc.h"
-#include <sys/types.h>
+#define APR_WANT_MEMFUNC
+#include "apr_want.h"
+#include "apr_general.h"
+
+#include "apr_arch_misc.h"
 #include <sys/stat.h>
+#if APR_HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#if APR_HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#if APR_HAVE_FCNTL_H
 #include <fcntl.h>
-#ifdef HAVE_UNISTD_H
+#endif
+#if APR_HAVE_UNISTD_H
 #include <unistd.h>
 #endif
+#if APR_HAVE_SYS_UN_H
+#include <sys/un.h>
+#endif
+#if defined(HAVE_UUID_H)
+#include <uuid.h>
+#elif defined(HAVE_UUID_UUID_H)
+#include <uuid/uuid.h>
+#elif defined(HAVE_SYS_UUID_H)
+#include <sys/uuid.h>
+#endif
 
-#if APR_HAS_RANDOM
+#if defined(HAVE_SYS_RANDOM_H) && \
+    defined(HAVE_GETRANDOM)
+
+#include <sys/random.h>
+#define USE_GETRANDOM
+
+#elif defined(HAVE_SYS_SYSCALL_H) && \
+      defined(HAVE_LINUX_RANDOM_H) && \
+      defined(HAVE_DECL_SYS_GETRANDOM) && \
+      HAVE_DECL_SYS_GETRANDOM
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <linux/random.h>
+
+#define getrandom(buf, buflen, flags) \
+    syscall(SYS_getrandom, (buf), (buflen), (flags))
+#define USE_GETRANDOM
+
+#endif /* HAVE_SYS_RANDOM_H */
+
+#ifndef SHUT_RDWR
+#define SHUT_RDWR 2
+#endif
+
+#if APR_HAS_OS_UUID
+
+#if defined(HAVE_UUID_CREATE)
+
+APR_DECLARE(apr_status_t) apr_os_uuid_get(unsigned char *uuid_data)
+{
+    uint32_t rv;
+    uuid_t g;
+
+    uuid_create(&g, &rv);
+
+    if (rv != uuid_s_ok)
+        return APR_EGENERAL;
+
+    memcpy(uuid_data, &g, sizeof(uuid_t));
+
+    return APR_SUCCESS;
+}
+
+#elif defined(HAVE_UUID_GENERATE)
+
+APR_DECLARE(apr_status_t) apr_os_uuid_get(unsigned char *uuid_data)
+{
+    uuid_t g;
+
+    uuid_generate(g);
+
+    memcpy(uuid_data, g, sizeof(uuid_t));
+
+    return APR_SUCCESS;
+}
+#endif 
+
+#endif /* APR_HAS_OS_UUID */
 
-#define	XSTR(x)	#x
-#define	STR(x)	XSTR(x)
+#if APR_HAS_RANDOM
 
-ap_status_t ap_generate_random_bytes(unsigned char * buf, int length) 
+APR_DECLARE(apr_status_t) apr_generate_random_bytes(unsigned char *buf, 
+                                                    apr_size_t length)
 {
-#ifdef	DEV_RANDOM
+#if defined(HAVE_EGD)
+    /* use EGD-compatible socket daemon (such as EGD or PRNGd).
+     * message format:
+     * 0x00 (get entropy level)
+     *   0xMM (msb) 0xmm 0xll 0xLL (lsb)
+     * 0x01 (read entropy nonblocking) 0xNN (bytes requested)
+     *   0xMM (bytes granted) MM bytes
+     * 0x02 (read entropy blocking) 0xNN (bytes desired)
+     *   [block] NN bytes
+     * 0x03 (write entropy) 0xMM 0xLL (bits of entropy) 0xNN (bytes of data) 
+     *      NN bytes
+     * (no response - write only) 
+     * 0x04 (report PID)
+     *   0xMM (length of PID string, not null-terminated) MM chars
+     */
+    static const char *egd_sockets[] = { EGD_DEFAULT_SOCKET, NULL };
+    const char **egdsockname = NULL;
+
+    int egd_socket, egd_path_len, rv, bad_errno;
+    struct sockaddr_un addr;
+    apr_socklen_t egd_addr_len;
+    apr_size_t resp_expected;
+    unsigned char req[2], resp[255];
+    unsigned char *curbuf = buf;
+
+    for (egdsockname = egd_sockets; *egdsockname && length > 0; egdsockname++) {
+        egd_path_len = strlen(*egdsockname);
+        
+        if (egd_path_len > sizeof(addr.sun_path)) {
+            return APR_EINVAL;
+        }
+
+        memset(&addr, 0, sizeof(struct sockaddr_un));
+        addr.sun_family = AF_UNIX;
+        memcpy(addr.sun_path, *egdsockname, egd_path_len);
+        egd_addr_len = APR_OFFSETOF(struct sockaddr_un, sun_path) + 
+          egd_path_len; 
+
+        egd_socket = socket(PF_UNIX, SOCK_STREAM, 0);
+
+        if (egd_socket == -1) {
+            return errno;
+        }
+
+        rv = connect(egd_socket, (struct sockaddr*)&addr, egd_addr_len);
+
+        if (rv == -1) {
+            bad_errno = errno;
+            continue;
+        }
+
+        /* EGD can only return 255 bytes of data at a time.  Silly.  */ 
+        while (length > 0) {
+            apr_ssize_t srv;
+            req[0] = 2; /* We'll block for now. */
+            req[1] = length > 255 ? 255: length;
+
+            srv = write(egd_socket, req, 2);
+            if (srv == -1) {
+                bad_errno = errno;
+                shutdown(egd_socket, SHUT_RDWR);
+                close(egd_socket);
+                break;
+            }
+
+            if (srv != 2) {
+                shutdown(egd_socket, SHUT_RDWR);
+                close(egd_socket);
+                return APR_EGENERAL;
+            }
+            
+            resp_expected = req[1];
+            srv = read(egd_socket, resp, resp_expected);
+            if (srv == -1) {
+                bad_errno = errno;
+                shutdown(egd_socket, SHUT_RDWR);
+                close(egd_socket);
+                return bad_errno;
+            }
+            
+            memcpy(curbuf, resp, srv);
+            curbuf += srv;
+            length -= srv;
+        }
+        
+        shutdown(egd_socket, SHUT_RDWR);
+        close(egd_socket);
+    }
 
-    int rnd;
-    size_t got, tot;
+    if (length > 0) {
+        /* We must have iterated through the list of sockets,
+         * and no go. Return the errno.
+         */
+        return bad_errno;
+    }
 
-    if ((rnd = open(STR(DEV_RANDOM), O_RDONLY)) == -1) 
-	return errno;
+#elif defined(USE_GETRANDOM)
 
-    for (tot=0; tot<length; tot += got)
-	if ((got = read(rnd, buf+tot, length-tot)) < 0) 
-	    return errno;
+    do {
+        int rc;
 
-    close(rnd);
+        rc = getrandom(buf, length, GRND_NONBLOCK);
+        if (rc == -1) {
+            if (errno == EINTR) {
+                continue;
+            }
+            return errno;
+        }
 
-#else  /* use truerand */
+        buf += rc;
+        length -= rc;
+    } while (length > 0);
+
+#elif defined(HAVE_ARC4RANDOM_BUF)
+
+    arc4random_buf(buf, length);
+
+#elif defined(DEV_RANDOM)
+
+    int fd = -1;
+
+    /* On BSD/OS 4.1, /dev/random gives out 8 bytes at a time, then
+     * gives EOF, so reading 'length' bytes may require opening the
+     * device several times. */
+    do {
+        apr_ssize_t rc;
+
+        if (fd == -1)
+            if ((fd = open(DEV_RANDOM, O_RDONLY)) == -1)
+                return errno;
+        
+        do {
+            rc = read(fd, buf, length);
+        } while (rc == -1 && errno == EINTR);
+
+        if (rc < 0) {
+            int errnum = errno;
+            close(fd);
+            return errnum;
+        }
+        else if (rc == 0) {
+            close(fd);
+            fd = -1; /* force open() again */
+        }
+        else {
+            buf += rc;
+            length -= rc;
+        }
+    } while (length > 0);
+    
+    close(fd);
+
+#elif defined(OS2)
+
+    static UCHAR randbyte();
+    unsigned int idx;
+
+    for (idx=0; idx<length; idx++)
+	buf[idx] = randbyte();
+
+#elif defined(HAVE_TRUERAND) /* use truerand */
 
     extern int randbyte(void);	/* from the truerand library */
     unsigned int idx;
@@ -92,6 +282,10 @@ ap_status_t ap_generate_random_bytes(unsigned char * buf, int length)
     for (idx=0; idx<length; idx++)
 	buf[idx] = (unsigned char) randbyte();
 
+#else
+
+#error APR_HAS_RANDOM defined with no implementation
+
 #endif	/* DEV_RANDOM */
 
     return APR_SUCCESS;
@@ -99,4 +293,9 @@ ap_status_t ap_generate_random_bytes(unsigned char * buf, int length)
 
 #undef	STR
 #undef	XSTR
+
+#ifdef OS2
+#include "randbyte_os2.inc"
+#endif
+
 #endif /* APR_HAS_RANDOM */
diff --git a/misc/unix/randbyte_os2.inc b/misc/unix/randbyte_os2.inc
new file mode 100644
index 00000000000..4020e31fea2
--- /dev/null
+++ b/misc/unix/randbyte_os2.inc
@@ -0,0 +1,123 @@
+/* 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.
+ */
+
+/* The high resolution timer API provides access to the hardware timer 
+ * running at around 1.1MHz. The amount this changes in a time slice is
+ * varies randomly due to system events, hardware interrupts etc
+ */
+static UCHAR randbyte_hrtimer()
+{
+    QWORD t1, t2;
+    UCHAR byte;
+
+    DosTmrQueryTime(&t1);
+    DosSleep(5);
+    DosTmrQueryTime(&t2);
+
+    byte = (t2.ulLo - t1.ulLo) & 0xFF;
+    byte ^= (t2.ulLo - t1.ulLo) >> 8;
+    return byte;
+}
+
+
+
+/* A bunch of system information like memory & process stats.
+ * Not highly random but every bit helps....
+ */
+static UCHAR randbyte_sysinfo()
+{
+    UCHAR byte = 0;
+    UCHAR SysVars[100];
+    int b;
+
+    DosQuerySysInfo(1, QSV_FOREGROUND_PROCESS, SysVars, sizeof(SysVars));
+
+    for (b = 0; b < 100; b++) {
+        byte ^= SysVars[b];
+    }
+
+    return byte;
+}
+
+
+
+/* Similar in concept to randbyte_hrtimer() but accesses the CPU's internal
+ * counters which run at the CPU's MHz speed. We get separate 
+ * idle / busy / interrupt cycle counts which should provide very good 
+ * randomness due to interference of hardware events.
+ * This only works on newer CPUs (at least PPro or K6) and newer OS/2 versions
+ * which is why it's run-time linked.
+ */
+
+static APIRET APIENTRY(*DosPerfSysCall) (ULONG ulCommand, ULONG ulParm1,
+                                         ULONG ulParm2, ULONG ulParm3) = NULL;
+static HMODULE hDoscalls = 0;
+#define   CMD_KI_RDCNT    (0x63)
+
+typedef struct _CPUUTIL {
+    ULONG ulTimeLow;            /* Low 32 bits of time stamp      */
+    ULONG ulTimeHigh;           /* High 32 bits of time stamp     */
+    ULONG ulIdleLow;            /* Low 32 bits of idle time       */
+    ULONG ulIdleHigh;           /* High 32 bits of idle time      */
+    ULONG ulBusyLow;            /* Low 32 bits of busy time       */
+    ULONG ulBusyHigh;           /* High 32 bits of busy time      */
+    ULONG ulIntrLow;            /* Low 32 bits of interrupt time  */
+    ULONG ulIntrHigh;           /* High 32 bits of interrupt time */
+} CPUUTIL;
+
+
+static UCHAR randbyte_perf()
+{
+    UCHAR byte = 0;
+    CPUUTIL util;
+    int c;
+
+    if (hDoscalls == 0) {
+        char failed_module[20];
+        ULONG rc;
+
+        rc = DosLoadModule(failed_module, sizeof(failed_module), "DOSCALLS",
+                           &hDoscalls);
+
+        if (rc == 0) {
+            rc = DosQueryProcAddr(hDoscalls, 976, NULL, (PFN *)&DosPerfSysCall);
+
+            if (rc) {
+                DosPerfSysCall = NULL;
+            }
+        }
+    }
+
+    if (DosPerfSysCall) {
+        if (DosPerfSysCall(CMD_KI_RDCNT, (ULONG)&util, 0, 0) == 0) {
+            for (c = 0; c < sizeof(util); c++) {
+                byte ^= ((UCHAR *)&util)[c];
+            }
+        }
+        else {
+            DosPerfSysCall = NULL;
+        }
+    }
+
+    return byte;
+}
+
+
+
+static UCHAR randbyte()
+{
+    return randbyte_hrtimer() ^ randbyte_sysinfo() ^ randbyte_perf();
+}
diff --git a/misc/unix/start.c b/misc/unix/start.c
index fad86b50757..8dcc1d9897e 100644
--- a/misc/unix/start.c
+++ b/misc/unix/start.c
@@ -1,165 +1,89 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "misc.h"
-#include "locks.h"
-
-ap_status_t ap_create_pool(ap_pool_t **newcont, ap_pool_t *cont)
-{
-    ap_pool_t *new;
+#include "apr.h"
+#include "apr_general.h"
+#include "apr_pools.h"
+#include "apr_signal.h"
+#include "apr_atomic.h"
 
-    if (cont) {
-        new = ap_make_sub_pool(cont, cont->apr_abort);
-    }
-    else {
-        new = ap_make_sub_pool(NULL, NULL);
-    }
-        
-    if (new == NULL) {
-        return APR_ENOPOOL;
-    }   
+#include "apr_arch_proc_mutex.h" /* for apr_proc_mutex_unix_setup_lock() */
+#include "apr_arch_internal_time.h"
 
-    new->prog_data = NULL;
-    new->apr_abort = NULL;
- 
-    *newcont = new;
-    return APR_SUCCESS;
-}
 
-ap_status_t ap_destroy_context(ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_app_initialize(int *argc, 
+                                             const char * const * *argv, 
+                                             const char * const * *env)
 {
-    ap_destroy_pool(cont);
-    return APR_SUCCESS;
+    /* An absolute noop.  At present, only Win32 requires this stub, but it's
+     * required in order to move command arguments passed through the service
+     * control manager into the process, and it's required to fix the char*
+     * data passed in from win32 unicode into utf-8, win32's apr internal fmt.
+     */
+    return apr_initialize();
 }
 
-ap_status_t ap_set_userdata(void *data, char *key,
-                            ap_status_t (*cleanup) (void *),
-                            ap_pool_t *cont)
-{
-    datastruct *dptr = NULL, *dptr2 = NULL;
-    if (cont) { 
-        dptr = cont->prog_data;
-        while (dptr) {
-            if (!strcmp(dptr->key, key))
-                break;
-            dptr2 = dptr;
-            dptr = dptr->next;
-        }
-        if (dptr == NULL) {
-            dptr = ap_palloc(cont, sizeof(datastruct));
-            dptr->next = dptr->prev = NULL;
-            dptr->key = ap_pstrdup(cont, key);
-            if (dptr2) {
-                dptr2->next = dptr;
-                dptr->prev = dptr2;
-            }
-            else {
-                cont->prog_data = dptr;
-            }
-        }
-        dptr->data = data;
-        ap_register_cleanup(cont, dptr->data, cleanup, cleanup);
-        return APR_SUCCESS;
-    }
-    return APR_ENOPOOL;
-}
+static int initialized = 0;
 
-ap_status_t ap_get_userdata(void **data, char *key, ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_initialize(void)
 {
-    datastruct *dptr = NULL;
-    if (cont) { 
-        dptr = cont->prog_data;
-        while (dptr) {
-            if (!strcmp(dptr->key, key)) {
-                break;
-            }
-            dptr = dptr->next;
-        }
-        if (dptr) {
-            (*data) = dptr->data;
-        }
-        else {
-            (*data) = NULL;
-        }
+    apr_pool_t *pool;
+    apr_status_t status;
+
+    if (initialized++) {
         return APR_SUCCESS;
     }
-    return APR_ENOPOOL;
-}
 
-ap_status_t ap_initialize(void)
-{
-    ap_status_t status;
 #if !defined(BEOS) && !defined(OS2)
-    ap_unix_setup_lock();
+    apr_proc_mutex_unix_setup_lock();
+    apr_unix_setup_time();
 #endif
-    status = ap_init_alloc();
-    return status;
+
+    if ((status = apr_pool_initialize()) != APR_SUCCESS)
+        return status;
+    
+    if (apr_pool_create(&pool, NULL) != APR_SUCCESS) {
+        return APR_ENOPOOL;
+    }
+
+    apr_pool_tag(pool, "apr_initialize");
+
+    /* apr_atomic_init() used to be called from here as well.
+     * Pools rely on mutexes though, which can be backed by
+     * atomics.  Due to this circular dependency
+     * apr_pool_initialize() is taking care of calling
+     * apr_atomic_init() at the correct time.
+     */
+
+    apr_signal_init(pool);
+
+    return APR_SUCCESS;
 }
 
-void ap_terminate(void)
+APR_DECLARE_NONSTD(void) apr_terminate(void)
 {
-    ap_term_alloc();
+    initialized--;
+    if (initialized) {
+        return;
+    }
+    apr_pool_terminate();
+    
 }
 
-ap_status_t ap_set_abort(int (*apr_abort)(int retcode), ap_pool_t *cont)
+APR_DECLARE(void) apr_terminate2(void)
 {
-    if (cont == NULL) {
-        return APR_ENOPOOL;
-    }
-    else {
-        cont->apr_abort = apr_abort;
-        return APR_SUCCESS;
-    }
+    apr_terminate();
 }
- 
diff --git a/misc/unix/version.c b/misc/unix/version.c
new file mode 100644
index 00000000000..2f111bf9dc0
--- /dev/null
+++ b/misc/unix/version.c
@@ -0,0 +1,35 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_version.h"
+#include "apr_general.h" /* for APR_STRINGIFY */
+
+APR_DECLARE(void) apr_version(apr_version_t *pvsn)
+{
+    pvsn->major = APR_MAJOR_VERSION;
+    pvsn->minor = APR_MINOR_VERSION;
+    pvsn->patch = APR_PATCH_VERSION;
+#ifdef APR_IS_DEV_VERSION
+    pvsn->is_dev = 1;
+#else
+    pvsn->is_dev = 0;
+#endif
+}
+
+APR_DECLARE(const char *) apr_version_string(void)
+{
+    return APR_VERSION_STRING;
+}
diff --git a/misc/win32/apr_app.c b/misc/win32/apr_app.c
new file mode 100644
index 00000000000..4e08e33d756
--- /dev/null
+++ b/misc/win32/apr_app.c
@@ -0,0 +1,80 @@
+/* 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.
+ */
+
+/* Usage Notes:
+ *
+ *   this module, and the misc/win32/utf8.c modules must be
+ *   compiled APR_EXPORT_STATIC and linked to an application with
+ *   the /entry:wmainCRTStartup flag (which this module kindly
+ *   provides to the developer who links to libaprapp-1.lib).
+ *   This module becomes the true wmain entry point, and passes
+ *   utf-8 reformatted argv and env arrays to the application's
+ *   main() function as if nothing happened.
+ *
+ *   This module is only compatible with Unicode operating systems.
+ *   Mixed (Win9x backwards compatible) binaries should refer instead
+ *   to the apr_startup.c module.
+ *
+ *   _dbg_malloc/realloc is used in place of the usual API, in order
+ *   to convince the MSVCRT that it created these entities.  If we
+ *   do not create them as _CRT_BLOCK entities, the crt will fault
+ *   on an assert.  We are not worrying about the crt's locks here, 
+ *   since we are single threaded [so far].
+ */
+
+#include "apr_general.h"
+#include "ShellAPI.h"
+#include "wchar.h"
+#include "apr_arch_file_io.h"
+#include "assert.h"
+#include "apr_private.h"
+#include "apr_arch_misc.h"
+
+#pragma comment(linker,"/ENTRY:wmainCRTStartup")
+
+extern int main(int argc, const char **argv, const char **env);
+
+int wmain(int argc, const wchar_t **wargv, const wchar_t **wenv)
+{
+    char **argv;
+    char **env;
+    int dupenv;
+
+    (void)apr_wastrtoastr(&argv, wargv, argc);
+
+    dupenv = apr_wastrtoastr(&env, wenv, -1);
+
+    _environ = apr_malloc_dbg((dupenv + 1) * sizeof (char *),
+                              __FILE__, __LINE__ );
+    memcpy(_environ, env, (dupenv + 1) * sizeof (char *));
+
+    /* MSVCRT will attempt to maintain the wide environment calls
+     * on _putenv(), which is bogus if we've passed a non-ascii
+     * string to _putenv(), since they use MultiByteToWideChar
+     * and breaking the implicit utf-8 assumption we've built.
+     *
+     * Reset _wenviron for good measure.
+     */
+    if (_wenviron) {
+        wenv = _wenviron;
+        _wenviron = NULL;
+        free((wchar_t **)wenv);
+    }
+
+    apr_app_init_complete = 1;
+
+    return main(argc, argv, env);
+}
diff --git a/misc/win32/aprlib.c b/misc/win32/aprlib.c
deleted file mode 100644
index b54667430e0..00000000000
--- a/misc/win32/aprlib.c
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * Placeholder to force aprlib.dll creation with no LNK4001 error
- *
- * However, this isn't a bad place to store dynamic-only functions 
- * that determine which version of apr the application has loaded.
- * These functions are of (less?) importance to static-bound apps.
- */
diff --git a/misc/win32/canonerr.c b/misc/win32/canonerr.c
deleted file mode 100644
index aff1e0fc438..00000000000
--- a/misc/win32/canonerr.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "misc.h"
-
-/*
- * Map Windows system errors to APR specific error codes.
- * This routine should only be called when it is necessary to 
- * selectively react to errors returned by APR functions.
- * 
- * hack alert:
- * Certain Windows APR routines already canonicalize their 
- * return codes in most (and maybe all) cases that are
- * interesting to Apache. For now, canonicalization 
- * on Windows is a no-op.
- */
-int ap_canonical_error(ap_status_t code)
-{
-    return code;
-}
diff --git a/misc/win32/charset.c b/misc/win32/charset.c
new file mode 100644
index 00000000000..41135b25d90
--- /dev/null
+++ b/misc/win32/charset.c
@@ -0,0 +1,55 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_strings.h"
+#include "apr_portable.h"
+
+
+APR_DECLARE(const char*) apr_os_default_encoding (apr_pool_t *pool)
+{
+    return apr_psprintf(pool, "CP%u", (unsigned) GetACP());
+}
+
+
+APR_DECLARE(const char*) apr_os_locale_encoding (apr_pool_t *pool)
+{
+#ifdef _UNICODE
+    int i;
+#endif
+#if defined(_WIN32_WCE)
+    LCID locale = GetUserDefaultLCID();
+#else
+    LCID locale = GetThreadLocale();
+#endif
+    int len = GetLocaleInfo(locale, LOCALE_IDEFAULTANSICODEPAGE, NULL, 0);
+    char *cp = apr_palloc(pool, (len * sizeof(TCHAR)) + 2);
+    if (0 < GetLocaleInfo(locale, LOCALE_IDEFAULTANSICODEPAGE, (TCHAR*) (cp + 2), len))
+    {
+        /* Fix up the returned number to make a valid codepage name of
+          the form "CPnnnn". */
+        cp[0] = 'C';
+        cp[1] = 'P';
+#ifdef _UNICODE
+        for(i = 0; i < len; i++) {
+            cp[i + 2] = (char) ((TCHAR*) (cp + 2))[i];
+        }
+#endif
+        return cp;
+    }
+
+    return apr_os_default_encoding(pool);
+}
diff --git a/misc/win32/env.c b/misc/win32/env.c
new file mode 100644
index 00000000000..644f59b8801
--- /dev/null
+++ b/misc/win32/env.c
@@ -0,0 +1,192 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define APR_WANT_STRFUNC
+#include "apr_want.h"
+#include "apr.h"
+#include "apr_arch_misc.h"
+#include "apr_arch_utf8.h"
+#include "apr_env.h"
+#include "apr_errno.h"
+#include "apr_pools.h"
+#include "apr_strings.h"
+
+#if APR_HAS_UNICODE_FS && !defined(_WIN32_WCE)
+static apr_status_t widen_envvar_name (apr_wchar_t *buffer,
+                                       apr_size_t bufflen,
+                                       const char *envvar)
+{
+    apr_size_t inchars;
+    apr_status_t status;
+
+    inchars = strlen(envvar) + 1;
+    status = apr_conv_utf8_to_ucs2(envvar, &inchars, buffer, &bufflen);
+    if (status == APR_INCOMPLETE)
+        status = APR_ENAMETOOLONG;
+
+    return status;
+}
+#endif
+
+
+APR_DECLARE(apr_status_t) apr_env_get(char **value,
+                                      const char *envvar,
+                                      apr_pool_t *pool)
+{
+#if defined(_WIN32_WCE)
+    return APR_ENOTIMPL;
+#else
+    char *val = NULL;
+    DWORD size;
+
+#if APR_HAS_UNICODE_FS
+    IF_WIN_OS_IS_UNICODE
+    {
+        apr_wchar_t wenvvar[APR_PATH_MAX];
+        apr_size_t inchars, outchars;
+        apr_wchar_t *wvalue, dummy;
+        apr_status_t status;
+
+        status = widen_envvar_name(wenvvar, APR_PATH_MAX, envvar);
+        if (status)
+            return status;
+
+        SetLastError(0);
+        size = GetEnvironmentVariableW(wenvvar, &dummy, 0);
+        if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
+            /* The environment variable doesn't exist. */
+            return APR_ENOENT;
+
+        if (size == 0) {
+            /* The environment value exists, but is zero-length. */
+            *value = apr_pstrdup(pool, "");
+            return APR_SUCCESS;
+        }
+
+        wvalue = apr_palloc(pool, size * sizeof(*wvalue));
+        size = GetEnvironmentVariableW(wenvvar, wvalue, size);
+
+        inchars = wcslen(wvalue) + 1;
+        outchars = 3 * inchars; /* Enough for any UTF-8 representation */
+        val = apr_palloc(pool, outchars);
+        status = apr_conv_ucs2_to_utf8(wvalue, &inchars, val, &outchars);
+        if (status)
+            return status;
+    }
+#endif
+#if APR_HAS_ANSI_FS
+    ELSE_WIN_OS_IS_ANSI
+    {
+        char dummy;
+
+        SetLastError(0);
+        size = GetEnvironmentVariableA(envvar, &dummy, 0);
+        if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
+            /* The environment variable doesn't exist. */
+            return APR_ENOENT;
+
+        if (size == 0) {
+            /* The environment value exists, but is zero-length. */
+            *value = apr_pstrdup(pool, "");
+            return APR_SUCCESS;
+        }
+
+        val = apr_palloc(pool, size);
+        size = GetEnvironmentVariableA(envvar, val, size);
+        if (size == 0)
+            /* Mid-air collision?. Somebody must've changed the env. var. */
+            return APR_INCOMPLETE;
+    }
+#endif
+
+    *value = val;
+    return APR_SUCCESS;
+#endif
+}
+
+
+APR_DECLARE(apr_status_t) apr_env_set(const char *envvar,
+                                      const char *value,
+                                      apr_pool_t *pool)
+{
+#if defined(_WIN32_WCE)
+    return APR_ENOTIMPL;
+#else
+#if APR_HAS_UNICODE_FS
+    IF_WIN_OS_IS_UNICODE
+    {
+        apr_wchar_t wenvvar[APR_PATH_MAX];
+        apr_wchar_t *wvalue;
+        apr_size_t inchars, outchars;
+        apr_status_t status;
+
+        status = widen_envvar_name(wenvvar, APR_PATH_MAX, envvar);
+        if (status)
+            return status;
+
+        outchars = inchars = strlen(value) + 1;
+        wvalue = apr_palloc(pool, outchars * sizeof(*wvalue));
+        status = apr_conv_utf8_to_ucs2(value, &inchars, wvalue, &outchars);
+        if (status)
+            return status;
+
+        if (!SetEnvironmentVariableW(wenvvar, wvalue))
+            return apr_get_os_error();
+    }
+#endif
+#if APR_HAS_ANSI_FS
+    ELSE_WIN_OS_IS_ANSI
+    {
+        if (!SetEnvironmentVariableA(envvar, value))
+            return apr_get_os_error();
+    }
+#endif
+
+    return APR_SUCCESS;
+#endif
+}
+
+
+APR_DECLARE(apr_status_t) apr_env_delete(const char *envvar, apr_pool_t *pool)
+{
+#if defined(_WIN32_WCE)
+    return APR_ENOTIMPL;
+#else
+#if APR_HAS_UNICODE_FS
+    IF_WIN_OS_IS_UNICODE
+    {
+        apr_wchar_t wenvvar[APR_PATH_MAX];
+        apr_status_t status;
+
+        status = widen_envvar_name(wenvvar, APR_PATH_MAX, envvar);
+        if (status)
+            return status;
+
+        if (!SetEnvironmentVariableW(wenvvar, NULL))
+            return apr_get_os_error();
+    }
+#endif
+#if APR_HAS_ANSI_FS
+    ELSE_WIN_OS_IS_ANSI
+    {
+        if (!SetEnvironmentVariableA(envvar, NULL))
+            return apr_get_os_error();
+    }
+#endif
+
+    return APR_SUCCESS;
+#endif
+}
diff --git a/misc/win32/errorcodes.c b/misc/win32/errorcodes.c
deleted file mode 100644
index bd725273f8c..00000000000
--- a/misc/win32/errorcodes.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "apr_lib.h"
-#include "misc.h"
-
-/* Todo: Merge this code with the code in the misc/unix directory.
- * Most of it is common
- */
-
-/*
- * stuffbuffer - Stuff contents of string 's' into buffer 'buf' 
- * w/o overflowing 'buf' then NULL terminate.
- */
-static char *stuffbuffer(char *buf, ap_size_t bufsize, const char *s)
-{
-    ap_size_t len = strlen(s);
-    if (len > bufsize)
-        len = bufsize;
-    memcpy(buf, s, len);
-    if (len)
-        buf[len-1] = '\0';
-    return buf;
-}
-
-static char *apr_error_string(ap_status_t statcode)
-{
-    switch (statcode) {
-    case APR_ENOPOOL:
-        return "A new pool could not be created.";
-    case APR_ENOFILE:
-        return "No file was provided and one was required.";
-    case APR_EBADDATE:
-        return "An invalid date has been provided";
-    case APR_EINVALSOCK:
-        return "An invalid socket was returned";
-    case APR_ENOPROC:
-        return "No process was provided and one was required.";
-    case APR_ENOTIME:
-        return "No time was provided and one was required.";
-    case APR_ENODIR:
-        return "No directory was provided and one was required.";
-    case APR_ENOLOCK:
-        return "No lock was provided and one was required.";
-    case APR_ENOPOLL:
-        return "No poll structure was provided and one was required.";
-    case APR_ENOSOCKET:
-        return "No socket was provided and one was required.";
-    case APR_ENOTHREAD:
-        return "No thread was provided and one was required.";
-    case APR_ENOTHDKEY:
-        return "No thread key structure was provided and one was required.";
-    case APR_ENOSHMAVAIL:
-        return "No shared memory is currently available";
-    case APR_EDSOOPEN:
-        return "Could not open the dso.";
-    case APR_INCHILD:
-        return
-	    "Your code just forked, and you are currently executing in the "
-	    "child process";
-    case APR_INPARENT:
-        return
-	    "Your code just forked, and you are currently executing in the "
-	    "parent process";
-    case APR_DETACH:
-        return "The specified thread is detached";
-    case APR_NOTDETACH:
-        return "The specified thread is not detached";
-    case APR_CHILD_DONE:
-        return "The specified child process is done executing";
-    case APR_CHILD_NOTDONE:
-        return "The specified child process is not done executing";
-    case APR_TIMEUP:
-        return "The timeout specified has expired";
-    case APR_BADCH:
-        return "Bad character specified on command line";
-    case APR_BADARG:
-        return "Missing parameter for the specified command line option";
-    case APR_EOF:
-        return "End of file found";
-    case APR_NOTFOUND:
-        return "Could not find specified socket in poll list.";
-    case APR_ANONYMOUS:
-        return "Shared memory is implemented anonymously";
-    case APR_FILEBASED:
-        return "Shared memory is implemented using files";
-    case APR_KEYBASED:
-        return "Shared memory is implemented using a key system";
-    case APR_EINIT:
-        return "There is no error, this value signifies an initialized "
-              "error code";
-    case APR_ENOTIMPL:
-        return "This function has not been implemented on this platform";
-    case APR_EMISMATCH:
-        return "passwords do not match";
-    default:
-        return "Error string not specified yet";
-    }
-}
-
-static char *apr_os_strerror(char *buf, ap_size_t bufsize, ap_status_t errcode)
-{
-    DWORD len;
-    DWORD i;
-
-    buf = "";
-
-    len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
-                        NULL,
-                        errcode,
-                        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
-                        (LPTSTR) buf,
-                        bufsize,
-                        NULL);
-
-    /* FormatMessage put the message in the buffer, but it may
-     * have embedded a newline (\r\n), and possible more than one.
-     * Remove the newlines replacing them with a space. This is not 
-     * as visually perfect as moving all the remaining message over, 
-     * but more efficient.
-     */
-    i = len;
-    while (i) {
-        i--;
-        if ((buf[i] == '\r') || (buf[i] == '\n'))
-            buf[i] = ' ';
-    }
-    return buf;
-}
-
-char *ap_strerror(ap_status_t statcode, char* buf, ap_size_t bufsize)
-{
-    if (statcode < APR_OS_START_ERROR) {
-        return apr_os_strerror(buf, bufsize, statcode);
-    }
-    else if (statcode < APR_OS_START_USEERR) {
-        return stuffbuffer(buf, bufsize, apr_error_string(statcode));
-    }
-    else if (statcode < APR_OS_START_SYSERR) {
-        return stuffbuffer(buf, bufsize, "APR does not understand this error code");
-    }
-    else {
-	return apr_os_strerror(buf, bufsize, statcode - APR_OS_START_SYSERR);
-    }
-}
diff --git a/misc/win32/getopt.c b/misc/win32/getopt.c
deleted file mode 100644
index bae5406a0f2..00000000000
--- a/misc/win32/getopt.c
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (c) 1987, 1993, 1994
- *      The Regents of the University of California.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by the University of
- *      California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "misc.h"
-
-int ap_opterr = 1,                      /* if error message should be printed */
-    ap_optind = 1,                      /* index into parent argv vector */
-    ap_optopt,                          /* character checked for validity */
-    ap_optreset;                        /* reset getopt */
-char *ap_optarg = "";                   /* argument associated with option */
-
-#define EMSG    ""
-
-ap_status_t ap_getopt(ap_int32_t nargc, char *const *nargv, const char *ostr, ap_int32_t *rv, ap_pool_t *cont)
-{
-    char *p;
-    static char *place = EMSG;   /* option letter processing */
-    char *oli;                   /* option letter list index */
-
-    if (ap_optreset || !*place) {   /* update scanning pointer */
-        ap_optreset = 0;
-        if (ap_optind >= nargc || *(place = nargv[ap_optind]) != '-') {
-            place = EMSG;
-            *rv = ap_optopt;
-            return (APR_EOF);
-        }
-        if (place[1] && *++place == '-') {        /* found "--" */
-            ++ap_optind;
-            place = EMSG;
-            *rv = ap_optopt;
-            return (APR_EOF);
-        }
-    }                                /* option letter okay? */
-    if ((ap_optopt = (int) *place++) == (int) ':' ||
-        !(oli = strchr(ostr, ap_optopt))) {
-        /*
-         * if the user didn't specify '-' as an option,
-         * assume it means -1.
-         */
-        if (ap_optopt == (int) '-')
-            *rv = ap_optopt;
-            return (APR_EOF);
-        if (!*place)
-            ++ap_optind;
-        if (ap_opterr && *ostr != ':') {
-            if (!(p = strrchr(*nargv, '/')))
-                p = *nargv;
-            else
-                ++p;
-            (void) fprintf(stderr,
-                           "%s: illegal option -- %c\n", p, ap_optopt);
-        }
-        *rv = ap_optopt;
-        return APR_BADCH;
-    }
-    if (*++oli != ':') {        /* don't need argument */
-        ap_optarg = NULL;
-        if (!*place)
-            ++ap_optind;
-    }
-    else {                        /* need an argument */
-        if (*place)                /* no white space */
-            ap_optarg = place;
-        else if (nargc <= ++ap_optind) {        /* no arg */
-            place = EMSG;
-            if (*ostr == ':')
-                *rv = ap_optopt;
-                return (APR_BADARG);
-            if (ap_opterr) {
-                if (!(p = strrchr(*nargv, '/')))
-                    p = *nargv;
-                else
-                    ++p;
-                (void) fprintf(stderr,
-                               "%s: option requires an argument -- %c\n",
-                               p, ap_optopt);
-            }
-            *rv = ap_optopt;
-            return (APR_BADCH);
-        }
-        else                        /* white space */
-            ap_optarg = nargv[ap_optind];
-        place = EMSG;
-        ++ap_optind;
-    }
-    *rv = ap_optopt;
-    return APR_SUCCESS;
-}
-
-
diff --git a/misc/win32/internal.c b/misc/win32/internal.c
new file mode 100644
index 00000000000..03362cf5982
--- /dev/null
+++ b/misc/win32/internal.c
@@ -0,0 +1,101 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_private.h"
+
+#include "apr_arch_misc.h"
+#include "apr_arch_file_io.h"
+#include <assert.h>
+
+/* This module is the source of -static- helper functions that are
+ * entirely internal to apr.  If the fn is exported - it does not
+ * belong here.
+ *
+ * Namespace decoration is still required to protect us from symbol
+ * clashes in static linkages.
+ */
+
+
+/* Shared by apr_app.c and start.c 
+ *
+ * An internal apr function to convert an array of strings (either
+ * a counted or NULL terminated list, such as an argv[argc] or env[]
+ * list respectively) from wide Unicode strings to narrow utf-8 strings.
+ * These are allocated from the MSVCRT's _CRT_BLOCK to trick the system
+ * into trusting our store.
+ */
+int apr_wastrtoastr(char const * const * *retarr, 
+                    wchar_t const * const *arr, int args)
+{
+    apr_size_t elesize = 0;
+    char **newarr;
+    char *elements;
+    char *ele;
+    int arg;
+
+    if (args < 0) {
+        for (args = 0; arr[args]; ++args)
+            ;
+    }
+
+    newarr = apr_malloc_dbg((args + 1) * sizeof(char *),
+                            __FILE__, __LINE__);
+
+    for (arg = 0; arg < args; ++arg) {
+        newarr[arg] = (void*)(wcslen(arr[arg]) + 1);
+        elesize += (apr_size_t)newarr[arg];
+    }
+
+    /* This is a safe max allocation, we will realloc after
+     * processing and return the excess to the free store.
+     * 3 ucs bytes hold any single wchar_t value (16 bits)
+     * 4 ucs bytes will hold a wchar_t pair value (20 bits)
+     */
+    elesize = elesize * 3 + 1;
+    ele = elements = apr_malloc_dbg(elesize * sizeof(char),
+                                    __FILE__, __LINE__);
+
+    for (arg = 0; arg < args; ++arg) {
+        apr_size_t len = (apr_size_t)newarr[arg];
+        apr_size_t newlen = elesize;
+
+        newarr[arg] = ele;
+        (void)apr_conv_ucs2_to_utf8(arr[arg], &len,
+                                    newarr[arg], &elesize);
+
+        newlen -= elesize;
+        ele += newlen;
+        assert(elesize && (len == 0));
+    }
+
+    newarr[arg] = NULL;
+    *(ele++) = '\0';
+
+    /* Return to the free store if the heap realloc is the least bit optimized
+     */
+    ele = apr_realloc_dbg(elements, ele - elements,
+                          __FILE__, __LINE__);
+
+    if (ele != elements) {
+        apr_size_t diff = ele - elements;
+        for (arg = 0; arg < args; ++arg) {
+            newarr[arg] += diff;
+        }
+    }
+
+    *retarr = (char const * const *)newarr;
+    return args;
+}
diff --git a/misc/win32/libapr.c b/misc/win32/libapr.c
deleted file mode 100644
index b54667430e0..00000000000
--- a/misc/win32/libapr.c
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * Placeholder to force aprlib.dll creation with no LNK4001 error
- *
- * However, this isn't a bad place to store dynamic-only functions 
- * that determine which version of apr the application has loaded.
- * These functions are of (less?) importance to static-bound apps.
- */
diff --git a/misc/win32/misc.c b/misc/win32/misc.c
new file mode 100644
index 00000000000..337739ca128
--- /dev/null
+++ b/misc/win32/misc.c
@@ -0,0 +1,241 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_private.h"
+#include "apr_arch_misc.h"
+#include "apr_arch_file_io.h"
+#include "assert.h"
+#include "apr_lib.h"
+#include "tchar.h"
+
+APR_DECLARE_DATA apr_oslevel_e apr_os_level = APR_WIN_UNK;
+
+apr_status_t apr_get_oslevel(apr_oslevel_e *level)
+{
+    if (apr_os_level == APR_WIN_UNK) 
+    {
+        static OSVERSIONINFO oslev;
+        oslev.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+        GetVersionEx(&oslev);
+
+        if (oslev.dwPlatformId == VER_PLATFORM_WIN32_NT) 
+        {
+            static unsigned int servpack = 0;
+            TCHAR *pservpack;
+            if ((pservpack = oslev.szCSDVersion)) {
+                while (*pservpack && !apr_isdigit(*pservpack)) {
+                    pservpack++;
+                }
+                if (*pservpack)
+#ifdef _UNICODE
+                    servpack = _wtoi(pservpack);
+#else
+                    servpack = atoi(pservpack);
+#endif
+            }
+
+            if (oslev.dwMajorVersion < 3) {
+                apr_os_level = APR_WIN_UNSUP;
+            }
+            else if (oslev.dwMajorVersion == 3) {
+                if (oslev.dwMajorVersion < 50) {
+                    apr_os_level = APR_WIN_UNSUP;
+                }
+                else if (oslev.dwMajorVersion == 50) {
+                    apr_os_level = APR_WIN_NT_3_5;
+                }
+                else {
+                    apr_os_level = APR_WIN_NT_3_51;
+                }
+            }
+            else if (oslev.dwMajorVersion == 4) {
+                if (servpack < 2)
+                    apr_os_level = APR_WIN_NT_4;
+                else if (servpack <= 2)
+                    apr_os_level = APR_WIN_NT_4_SP2;
+                else if (servpack <= 3)
+                    apr_os_level = APR_WIN_NT_4_SP3;
+                else if (servpack <= 4)
+                    apr_os_level = APR_WIN_NT_4_SP4;
+                else if (servpack <= 5)
+                    apr_os_level = APR_WIN_NT_4_SP5;
+                else 
+                    apr_os_level = APR_WIN_NT_4_SP6;
+            }
+            else if (oslev.dwMajorVersion == 5) {
+                if (oslev.dwMinorVersion == 0) {
+                    if (servpack == 0)
+                        apr_os_level = APR_WIN_2000;
+                    else if (servpack == 1)
+                        apr_os_level = APR_WIN_2000_SP1;
+                    else
+                        apr_os_level = APR_WIN_2000_SP2;
+                }
+                else if (oslev.dwMinorVersion == 2) {
+                    apr_os_level = APR_WIN_2003;
+                }
+                else {
+                    if (servpack < 1)
+                        apr_os_level = APR_WIN_XP;
+                    else if (servpack == 1)
+                        apr_os_level = APR_WIN_XP_SP1;
+                    else
+                        apr_os_level = APR_WIN_XP_SP2;
+                }
+            }
+            else if (oslev.dwMajorVersion == 6) {
+                if (oslev.dwMinorVersion == 0)
+                    apr_os_level = APR_WIN_VISTA;
+                else if (oslev.dwMinorVersion == 1)
+                    apr_os_level = APR_WIN_7;
+                else
+                    apr_os_level = APR_WIN_8;
+            }
+            else {
+                apr_os_level = APR_WIN_XP;
+            }
+        }
+#ifdef _WIN32_WCE
+        else if (oslev.dwPlatformId == VER_PLATFORM_WIN32_CE) 
+        {
+            if (oslev.dwMajorVersion < 3) {
+                apr_os_level = APR_WIN_UNSUP;
+            }
+            else {
+                apr_os_level = APR_WIN_CE_3;
+            }
+        }
+#endif
+        else {
+            apr_os_level = APR_WIN_UNSUP;
+        }
+    }
+
+    *level = apr_os_level;
+
+    if (apr_os_level < APR_WIN_UNSUP) {
+        return APR_EGENERAL;
+    }
+
+    return APR_SUCCESS;
+}
+
+
+/* This is the helper code to resolve late bound entry points 
+ * missing from one or more releases of the Win32 API
+ */
+
+static const char* const lateDllName[DLL_defined] = {
+    "kernel32", "advapi32", "mswsock",  "ws2_32", "shell32", "ntdll.dll"  };
+static HMODULE lateDllHandle[DLL_defined] = {
+     NULL,       NULL,       NULL,       NULL,     NULL,       NULL       };
+
+FARPROC apr_load_dll_func(apr_dlltoken_e fnLib, char* fnName, int ordinal)
+{
+    if (!lateDllHandle[fnLib]) { 
+        lateDllHandle[fnLib] = LoadLibraryA(lateDllName[fnLib]);
+        if (!lateDllHandle[fnLib])
+            return NULL;
+    }
+#if defined(_WIN32_WCE)
+    if (ordinal)
+        return GetProcAddressA(lateDllHandle[fnLib], (const char *)
+                                                     (apr_ssize_t)ordinal);
+    else
+        return GetProcAddressA(lateDllHandle[fnLib], fnName);
+#else
+    if (ordinal)
+        return GetProcAddress(lateDllHandle[fnLib], (const char *)
+                                                    (apr_ssize_t)ordinal);
+    else
+        return GetProcAddress(lateDllHandle[fnLib], fnName);
+#endif
+}
+
+/* Declared in include/arch/win32/apr_dbg_win32_handles.h
+ */
+APR_DECLARE_NONSTD(HANDLE) apr_dbg_log(char* fn, HANDLE ha, char* fl, int ln, 
+                                       int nh, /* HANDLE hv, char *dsc */...)
+{
+    static DWORD tlsid = 0xFFFFFFFF;
+    static HANDLE fh = NULL;
+    static long ctr = 0;
+    static CRITICAL_SECTION cs;
+    long seq;
+    DWORD wrote;
+    char *sbuf;
+    
+    seq = (InterlockedIncrement)(&ctr);
+
+    if (tlsid == 0xFFFFFFFF) {
+        tlsid = (TlsAlloc)();
+    }
+
+    sbuf = (TlsGetValue)(tlsid);
+    if (!fh || !sbuf) {
+        sbuf = (malloc)(1024);
+        (TlsSetValue)(tlsid, sbuf);
+        sbuf[1023] = '\0';
+        if (!fh) {
+            (GetModuleFileNameA)(NULL, sbuf, 250);
+            sprintf(strchr(sbuf, '\0'), ".%u",
+                    (unsigned int)(GetCurrentProcessId)());
+            fh = (CreateFileA)(sbuf, GENERIC_WRITE, 0, NULL, 
+                            CREATE_ALWAYS, 0, NULL);
+            (InitializeCriticalSection)(&cs);
+        }
+    }
+
+    if (!nh) {
+        (sprintf)(sbuf, "%p %08x %08x %s() %s:%d\n",
+                  ha, (unsigned int)seq, (unsigned int)GetCurrentThreadId(),
+                  fn, fl, ln);
+        (EnterCriticalSection)(&cs);
+        (WriteFile)(fh, sbuf, (DWORD)strlen(sbuf), &wrote, NULL);
+        (LeaveCriticalSection)(&cs);
+    } 
+    else {
+        va_list a;
+        va_start(a,nh);
+        (EnterCriticalSection)(&cs);
+        do {
+            HANDLE *hv = va_arg(a, HANDLE*);
+            char *dsc = va_arg(a, char*);
+            if (strcmp(dsc, "Signaled") == 0) {
+                if ((apr_ssize_t)ha >= STATUS_WAIT_0 
+                       && (apr_ssize_t)ha < STATUS_ABANDONED_WAIT_0) {
+                    hv += (apr_ssize_t)ha;
+                }
+                else if ((apr_ssize_t)ha >= STATUS_ABANDONED_WAIT_0
+                            && (apr_ssize_t)ha < STATUS_USER_APC) {
+                    hv += (apr_ssize_t)ha - STATUS_ABANDONED_WAIT_0;
+                    dsc = "Abandoned";
+                }
+                else if ((apr_ssize_t)ha == WAIT_TIMEOUT) {
+                    dsc = "Timed Out";
+                }
+            }
+            (sprintf)(sbuf, "%p %08x %08x %s(%s) %s:%d\n",
+                      *hv, (unsigned int)seq,
+                      (unsigned int)GetCurrentThreadId(), 
+                      fn, dsc, fl, ln);
+            (WriteFile)(fh, sbuf, (DWORD)strlen(sbuf), &wrote, NULL);
+        } while (--nh);
+        (LeaveCriticalSection)(&cs);
+        va_end(a);
+    }
+    return ha;
+}
diff --git a/misc/win32/misc.h b/misc/win32/misc.h
deleted file mode 100644
index a1acdbccb44..00000000000
--- a/misc/win32/misc.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef MISC_H
-#define MISC_H
-
-#include "apr_general.h"
-#include "apr_file_io.h"
-#include "apr_errno.h"
-#include "apr_getopt.h"
-
-typedef struct datastruct {
-    void *data;
-    char *key;
-    struct datastruct *next;
-    struct datastruct *prev;
-} datastruct;
-
-#define WSAHighByte 2
-#define WSALowByte 0
-/* Platform specific designation of run time os version.
- * Gaps allow for specific service pack levels that 
- * export new kernel or winsock functions or behavior.
- */
-typedef enum {
-	APR_WIN_95 = 0, 
-	APR_WIN_98 = 4, 
-	APR_WIN_NT = 8,
-	APR_WIN_NT_4 = 12,
-	APR_WIN_NT_4_SP2 = 14,
-	APR_WIN_NT_4_SP3 = 15,
-	APR_WIN_NT_4_SP4 = 16,
-	APR_WIN_NT_4_SP6 = 18,
-	APR_WIN_2000 = 24
-} ap_oslevel_e;
-
-
-typedef enum {
-    DLL_WINBASEAPI = 0,    // kernel32 From WinBase.h
-    DLL_WINADVAPI = 1,     // advapi32 From WinBase.h
-    DLL_WINSOCKAPI = 2,    // mswsock  From WinSock.h
-    DLL_WINSOCK2API = 3,   // ws2_32   From WinSock2.h
-    DLL_defined = 4        // must define as last idx_ + 1
-} ap_dlltoken_e;
-
-FARPROC LoadLateDllFunc(ap_dlltoken_e fnLib, char *fnName, int ordinal);
-
-/* The LateFunctionName call WILL fault if the function cannot be loaded */
-
-#define DECLARE_LATE_DLL_FUNC(lib, rettype, calltype, fn, ord, args, names) \
-    typedef rettype (calltype *fpt##fn) args; \
-    static fpt##fn pfn##fn = NULL; \
-    __inline rettype Late##fn args \
-    {   if (!pfn##fn) \
-            pfn##fn = (fpt##fn) LoadLateDllFunc(lib, #fn, ord); \
-        return (*(pfn##fn)) names; }; \
-
-/* Provide late bound declarations of every API function missing from 
- * one or more supported releases of the Win32 API
- * 
- * lib is the enumerated token from ap_dlltoken_e, and must correspond 
- * to the string table entry in start.c used by the LoadLateDllFunc().
- * Token names (attempt to) follow Windows.h declarations prefixed by DLL_
- * in order to facilitate comparison.  Use the exact declaration syntax
- * and names from Windows.h to prevent ambigutity and bugs.
- * 
- * rettype and calltype follow the original declaration in Windows.h
- * fn is the true function name - beware Ansi/Unicode #defined macros
- * ord is the ordinal within the library, use 0 if it varies between versions
- * args is the parameter list following the original declaration, in parens
- * names is the parameter list sans data types, enclosed in parens
- *
- * #undef/re#define the Ansi/Unicode generic name to abate confusion
- * In the case of non-text functions, simply #define the original name
- */
-
-DECLARE_LATE_DLL_FUNC(DLL_WINBASEAPI, BOOL, WINAPI, GetFileAttributesExA, 0, (
-    IN LPCSTR lpFileName,
-    IN GET_FILEEX_INFO_LEVELS fInfoLevelId,
-    OUT LPVOID lpFileInformation),
-    (lpFileName, fInfoLevelId, lpFileInformation));
-#undef GetFileAttributesEx
-#define GetFileAttributesEx LateGetFileAttributesExA
-
-ap_status_t ap_get_oslevel(struct ap_pool_t *, ap_oslevel_e *);
-
-#endif  /* ! MISC_H */
-
diff --git a/misc/win32/names.c b/misc/win32/names.c
deleted file mode 100644
index d831842c929..00000000000
--- a/misc/win32/names.c
+++ /dev/null
@@ -1,316 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "apr_private.h"
-#include "apr_file_io.h"
-#include "apr_general.h"
-#include "apr_lib.h"
-#include <errno.h>
-#include <string.h>
-#include <sys/stat.h>
-
-/* Returns TRUE if the input string is a string
- * of one or more '.' characters.
- */
-static BOOL OnlyDots(char *pString)
-{
-    char *c;
-
-    if (*pString == '\0')
-        return FALSE;
-
-    for (c = pString;*c;c++)
-        if (*c != '.')
-            return FALSE;
-
-    return TRUE;
-}
-
-/* Accepts as input a pathname, and tries to match it to an 
- * existing path and return the pathname in the case that
- * is present on the existing path.  This routine also
- * converts alias names to long names.
- */
-API_EXPORT(char *) ap_os_systemcase_filename(ap_pool_t *pCont, 
-                                             const char *szFile)
-{
-    char buf[HUGE_STRING_LEN];
-    char *pInputName;
-    char *p, *q;
-    BOOL bDone = FALSE;
-    BOOL bFileExists = TRUE;
-    HANDLE hFind;
-    WIN32_FIND_DATA wfd;
-
-    if (!szFile || strlen(szFile) == 0 || strlen(szFile) >= sizeof(buf))
-        return ap_pstrdup(pCont, "");
-
-    buf[0] = '\0';
-    pInputName = ap_pstrdup(pCont, szFile);
-
-    /* First convert all slashes to \ so Win32 calls work OK */
-    for (p = pInputName; *p; p++) {
-        if (*p == '/')
-            *p = '\\';
-    }
-    
-    p = pInputName;
-    /* If there is drive information, copy it over. */ 
-    if (pInputName[1] == ':') {
-        buf[0] = tolower(*p++);
-        buf[1] = *p++;
-        buf[2] = '\0';
-
-        /* If all we have is a drive letter, then we are done */
-        if (strlen(pInputName) == 2)
-            bDone = TRUE;
-    }
-    
-    q = p;
-    if (*p == '\\') {
-        p++;
-        if (*p == '\\')  /* Possible UNC name */
-        {
-            p++;
-            /* Get past the machine name.  FindFirstFile */
-            /* will not find a machine name only */
-            p = strchr(p, '\\'); 
-            if (p)
-            {
-                p++;
-                /* Get past the share name.  FindFirstFile */
-                /* will not find a \\machine\share name only */
-                p = strchr(p, '\\'); 
-                if (p) {
-                    strncat(buf,q,p-q);
-                    q = p;
-                    p++;
-                }
-            }
-
-            if (!p)
-                p = q;
-        }
-    }
-
-    p = strchr(p, '\\');
-
-    while (!bDone) {
-        if (p)
-            *p = '\0';
-
-        if (strchr(q, '*') || strchr(q, '?'))
-            bFileExists = FALSE;
-
-        /* If the path exists so far, call FindFirstFile
-         * again.  However, if this portion of the path contains
-         * only '.' charaters, skip the call to FindFirstFile
-         * since it will convert '.' and '..' to actual names.
-         * Note: in the call to OnlyDots, we may have to skip
-         *       a leading slash.
-         */
-        if (bFileExists && !OnlyDots((*q == '.' ? q : q+1))) {            
-            hFind = FindFirstFile(pInputName, &wfd);
-            
-            if (hFind == INVALID_HANDLE_VALUE) {
-                bFileExists = FALSE;
-            }
-            else {
-                FindClose(hFind);
-
-                if (*q == '\\')
-                    strcat(buf,"\\");
-                strcat(buf, wfd.cFileName);
-            }
-        }
-        
-        if (!bFileExists || OnlyDots((*q == '.' ? q : q+1))) {
-            strcat(buf, q);
-        }
-        
-        if (p) {
-            q = p;
-            *p++ = '\\';
-            p = strchr(p, '\\');
-        }
-        else {
-            bDone = TRUE;
-        }
-    }
-    
-    /* First convert all slashes to / so server code handles it ok */
-    for (p = buf; *p; p++) {
-        if (*p == '\\')
-            *p = '/';
-    }
-
-    return ap_pstrdup(pCont, buf);
-}
- 
-/*  Perform canonicalization with the exception that the
- *  input case is preserved.
- */
-char * canonical_filename(ap_pool_t *pCont, const char *szFile)
-{
-    char *pNewStr;
-    char *s;
-    char *p; 
-    char *q;
-
-    if (szFile == NULL || strlen(szFile) == 0)
-        return ap_pstrdup(pCont, "");
-
-    pNewStr = ap_pstrdup(pCont, szFile);
-
-    /*  Change all '\' characters to '/' characters.
-     *  While doing this, remove any trailing '.'.
-     *  Also, blow away any directories with 3 or
-     *  more '.'
-     */
-    for (p = pNewStr,s = pNewStr; *s; s++,p++) {
-        if (*s == '\\' || *s == '/') {
-
-            q = p;
-            while (p > pNewStr && *(p-1) == '.')
-                p--;
-
-            if (p == pNewStr && q-p <= 2 && *p == '.')
-                p = q;
-            else if (p > pNewStr && p < q && *(p-1) == '/') {
-                if (q-p > 2)
-                    p--;
-                else
-                    p = q;
-            }
-
-            *p = '/';
-        }
-        else {
-            *p = *s;
-        }
-    }
-    *p = '\0';
-
-    /*  Blow away any final trailing '.' since on Win32
-     *  foo.bat == foo.bat. == foo.bat... etc.
-     *  Also blow away any trailing spaces since
-     *  "filename" == "filename "
-     */
-    q = p;
-    while (p > pNewStr && (*(p-1) == '.' || *(p-1) == ' '))
-        p--;
-    if ((p > pNewStr) ||
-        (p == pNewStr && q-p > 2))
-        *p = '\0';
-        
-
-    /*  One more security issue to deal with.  Win32 allows
-     *  you to create long filenames.  However, alias filenames
-     *  are always created so that the filename will
-     *  conform to 8.3 rules.  According to the Microsoft
-     *  Developer's network CD (1/98) 
-     *  "Automatically generated aliases are composed of the 
-     *   first six characters of the filename plus ~n 
-     *   (where n is a number) and the first three characters 
-     *   after the last period."
-     *  Here, we attempt to detect and decode these names.
-     */
-    p = strchr(pNewStr, '~');
-    if (p != NULL) {
-        char *pConvertedName, *pQstr, *pPstr;
-        char buf[HUGE_STRING_LEN];
-        /* We potentially have a short name.  Call 
-         * ap_os_systemcase_filename to examine the filesystem
-         * and possibly extract the long name.
-         */
-        pConvertedName = ap_os_systemcase_filename(pCont, pNewStr);
-
-        /* Since we want to preserve the incoming case as much
-         * as we can, compare for differences in the string and
-         * only substitute in the path names that changed.
-         */
-        if (stricmp(pNewStr, pConvertedName)) {
-            buf[0] = '\0';
-
-            q = pQstr = pConvertedName;
-            p = pPstr = pNewStr;
-            do {
-                q = strchr(q,'/');
-                p = strchr(p,'/');
-
-                if (p != NULL) {
-                    *q = '\0';
-                    *p = '\0';
-                }
-
-                if (stricmp(pQstr, pPstr)) 
-                    strcat(buf, pQstr);   /* Converted name */
-                else 
-                    strcat(buf, pPstr);   /* Original name  */
-
-
-                if (p != NULL) {
-                    pQstr = q;
-                    pPstr = p;
-                    *q++ = '/';
-                    *p++ = '/';
-                }
-
-            } while (p != NULL); 
-			
-            pNewStr = ap_pstrdup(pCont, buf);
-        }
-    }
-    return pNewStr;
-}
diff --git a/misc/win32/rand.c b/misc/win32/rand.c
index 1f6770e6275..cb5a6537fb7 100644
--- a/misc/win32/rand.c
+++ b/misc/win32/rand.c
@@ -1,78 +1,69 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
+#include "apr.h"
+#include <rpc.h>
+#include <wincrypt.h>
 #include "apr_private.h"
 #include "apr_general.h"
-#include <wincrypt.h>
+#include "apr_portable.h"
+#include "apr_arch_misc.h"
+
 
-ap_status_t ap_generate_random_bytes(unsigned char * buf, int length) 
+APR_DECLARE(apr_status_t) apr_generate_random_bytes(unsigned char * buf,
+                                                    apr_size_t length)
 {
     HCRYPTPROV hProv;
+    apr_status_t res = APR_SUCCESS;
 
-    if (!CryptAcquireContext(&hProv,NULL,NULL,PROV_RSA_FULL,0)) {
-	/*        ap_log_error(APLOG_MARK, APLOG_CRIT, 0, s, 
-                     "Digest: Error acquiring context. Errno = %d",
-                     GetLastError());
-		     exit(EXIT_FAILURE);*/
-	return 1;
+    /* 0x40 bit = CRYPT_SILENT, only introduced in more recent PSDKs 
+     * and will only work for Win2K and later.
+     */
+    DWORD flags = CRYPT_VERIFYCONTEXT
+                | ((apr_os_level >= APR_WIN_2000) ? 0x40 : 0);
+
+    if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, flags)) {
+	return apr_get_os_error();
+    }
+    /* XXX: An ugly hack for Win64, randomness is such that noone should
+     * ever expect > 2^31 bytes of data at once without the prng
+     * coming to a complete halt.
+     */
+    if (!CryptGenRandom(hProv, (DWORD)length, buf)) {
+    	res = apr_get_os_error();
     }
-    if (!CryptGenRandom(hProv,length,buf)) {
-	/*        ap_log_error(APLOG_MARK, APLOG_CRIT, 0, s, 
-                     "Digest: Error generating secret. Errno = %d",
-                     GetLastError());
-		     exit(EXIT_FAILURE);*/
-	return 1;
+    CryptReleaseContext(hProv, 0);
+    return res;
+}
+
+
+APR_DECLARE(apr_status_t) apr_os_uuid_get(unsigned char *uuid_data)
+{
+    /* Note: this call doesn't actually require CoInitialize() first 
+     *
+     * XXX: we should scramble the bytes or some such to eliminate the
+     * possible misuse/abuse since uuid is based on the NIC address, and
+     * is therefore not only a uniqifier, but an identity (which might not
+     * be appropriate in all cases.
+     *
+     * Note that Win2000, XP and later no longer suffer from this problem,
+     * a scrambling fix is only needed for (apr_os_level < APR_WIN_2000)
+     */
+    if (FAILED(UuidCreate((UUID *)uuid_data))) {
+        return APR_EGENERAL;
     }
     return APR_SUCCESS;
 }
diff --git a/misc/win32/start.c b/misc/win32/start.c
index 95fa14d960e..eb77d4a4ddd 100644
--- a/misc/win32/start.c
+++ b/misc/win32/start.c
@@ -1,258 +1,206 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
 #include "apr_private.h"
-#include "misc.h"
 #include "apr_general.h"
-#include "apr_errno.h"
 #include "apr_pools.h"
-#include "apr_lib.h"
-#include <string.h>
-#include <process.h>
-#include <stdlib.h>
+#include "apr_signal.h"
+#include "shellapi.h"
 
-ap_status_t clean_cont(void *data)
-{
-    return APR_SUCCESS;
-}
-    
+#include "apr_arch_misc.h"       /* for WSAHighByte / WSALowByte */
+#include "wchar.h"
+#include "apr_arch_file_io.h"    /* bring in unicode-ness */
+#include "apr_arch_threadproc.h" /* bring in apr_threadproc_init */
+#include "assert.h"
 
-ap_status_t ap_create_pool(ap_pool_t **newcont, ap_pool_t *cont)
-{
-    ap_pool_t *new;
+/* This symbol is _private_, although it must be exported.
+ */
+int APR_DECLARE_DATA apr_app_init_complete = 0;
 
-    if (cont) {
-        new = ap_make_sub_pool(cont, cont->apr_abort);
-    }
-    else {
-        new = ap_make_sub_pool(NULL, NULL);
+#if !defined(_WIN32_WCE)
+/* Used by apr_app_initialize to reprocess the environment
+ *
+ * An internal apr function to convert a double-null terminated set
+ * of single-null terminated strings from wide Unicode to narrow utf-8
+ * as a list of strings.  These are allocated from the MSVCRT's
+ * _CRT_BLOCK to trick the system into trusting our store.
+ */
+static int warrsztoastr(const char * const * *retarr,
+                        const wchar_t * arrsz, int args)
+{
+    const apr_wchar_t *wch;
+    apr_size_t totlen;
+    apr_size_t newlen;
+    apr_size_t wsize;
+    char **env;
+    char *pstrs;
+    char *strs;
+    int arg;
+
+    if (args < 0) {
+        for (args = 1, wch = arrsz; wch[0] || wch[1]; ++wch)
+            if (!*wch)
+                ++args;
     }
-        
-    if (new == NULL) {
-        return APR_ENOPOOL;
+    wsize = 1 + wch - arrsz;
+
+    /* This is a safe max allocation, we will alloc each
+     * string exactly after processing and return this
+     * temporary buffer to the free store.
+     * 3 ucs bytes hold any single wchar_t value (16 bits)
+     * 4 ucs bytes will hold a wchar_t pair value (20 bits)
+     */
+    newlen = totlen = wsize * 3 + 1;
+    pstrs = strs = apr_malloc_dbg(newlen * sizeof(char),
+                                  __FILE__, __LINE__);
+
+    (void)apr_conv_ucs2_to_utf8(arrsz, &wsize, strs, &newlen);
+
+    assert(newlen && !wsize);
+
+    *retarr = env = apr_malloc_dbg((args + 1) * sizeof(char*),
+                                   __FILE__, __LINE__);
+    for (arg = 0; arg < args; ++arg) {
+        char* p = pstrs;
+        int len = 0;
+        while (*p++)
+            ++len;
+        len += 1;
+
+        *env = apr_malloc_dbg(len * sizeof(char),
+                              __FILE__, __LINE__);
+        memcpy(*env, pstrs, len * sizeof(char));
+
+        pstrs += len;
+        ++env;
     }
-    
-    new->prog_data = NULL;
-    new->apr_abort = NULL;
 
-    *newcont = new;
-    return APR_SUCCESS;
-}
+    *env = NULL;
+    free(strs);
 
-ap_status_t ap_destroy_context(ap_pool_t *cont)
-{
-    ap_destroy_pool(cont);
-    return APR_SUCCESS;
+    return args;
 }
+#endif
 
-ap_status_t ap_get_oslevel(ap_pool_t *cont, ap_oslevel_e *level)
+/* Reprocess the arguments to main() for a completely apr-ized application
+ */
+
+APR_DECLARE(apr_status_t) apr_app_initialize(int *argc,
+                                             const char * const * *argv,
+                                             const char * const * *env)
 {
-    static OSVERSIONINFO oslev;
-    static unsigned int servpack = 0;
-    static BOOL first = TRUE;
-    char *pservpack;
-
-    if (first) {
-        first = FALSE;
-        oslev.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
-        GetVersionEx(&oslev);
-        if (oslev.dwPlatformId == VER_PLATFORM_WIN32_NT) {
-            for (pservpack = oslev.szCSDVersion; 
-                 *pservpack && !isdigit(*pservpack); pservpack++)
-                ;
-            if (*pservpack)
-                servpack = atoi(pservpack);
-        }
-    }
-    if (oslev.dwPlatformId == VER_PLATFORM_WIN32_NT) {
-        if (oslev.dwMajorVersion == 5) {
-            (*level) = APR_WIN_2000;
-        }
-        else if (oslev.dwMajorVersion == 4) {
-            if (servpack >= 6) {
-                (*level) = APR_WIN_NT_4_SP6;
-            }
-            else if (servpack >= 4) {
-                (*level) = APR_WIN_NT_4_SP4;
-            }
-            else if (servpack >= 3) {
-                (*level) = APR_WIN_NT_4_SP3;
-            }
-            else if (servpack >= 2) {
-                (*level) = APR_WIN_NT_4_SP2;
-            }
-            else {
-                (*level) = APR_WIN_NT_4;
-            }
-        }
-        else {
-            (*level) = APR_WIN_NT;
-        }
-        return APR_SUCCESS;
-    }
-    else if (oslev.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
-        if (oslev.dwMinorVersion == 0) {
-            (*level) = APR_WIN_95;
-            return APR_SUCCESS;
-        }
-        else if (oslev.dwMinorVersion > 0) {
-            (*level) = APR_WIN_98;
-            return APR_SUCCESS;
-        }
+    apr_status_t rv = apr_initialize();
+
+    if (rv != APR_SUCCESS) {
+        return rv;
     }
-    return APR_EEXIST;
-}
 
-ap_status_t ap_set_userdata(void *data, char *key,
-                            ap_status_t (*cleanup) (void *),
-                            ap_pool_t *cont)
-{
-    datastruct *dptr = NULL, *dptr2 = NULL;
-    if (cont) { 
-        dptr = cont->prog_data;
-        while (dptr) {
-            if (!strcmp(dptr->key, key))
-                break;
-            dptr2 = dptr;
-            dptr = dptr->next;
-        }
-        if (dptr == NULL) {
-            dptr = ap_palloc(cont, sizeof(datastruct));
-            dptr->next = dptr->prev = NULL;
-            dptr->key = ap_pstrdup(cont, key);
-            if (dptr2) {
-                dptr2->next = dptr;
-                dptr->prev = dptr2;
-            }
-            else {
-                cont->prog_data = dptr;
-            }
+#if defined(_WIN32_WCE)
+    apr_app_init_complete = 1;
+#elif APR_HAS_UNICODE_FS
+    IF_WIN_OS_IS_UNICODE
+    {
+        apr_wchar_t **wstrs;
+        apr_wchar_t *sysstr;
+        int wstrc;
+        int dupenv;
+
+        if (apr_app_init_complete) {
+            return rv;
         }
-        dptr->data = data;
-        ap_register_cleanup(cont, dptr->data, cleanup, cleanup);
-        return APR_SUCCESS;
-    }
-    return APR_ENOPOOL;
-}
 
-ap_status_t ap_get_userdata(void **data, char *key, ap_pool_t *cont)
-{
-    datastruct *dptr = NULL;
-    if (cont) { 
-        dptr = cont->prog_data;
-        while (dptr) {
-            if (!strcmp(dptr->key, key)) {
-                break;
+        apr_app_init_complete = 1;
+
+        sysstr = GetCommandLineW();
+        if (sysstr) {
+            wstrs = CommandLineToArgvW(sysstr, &wstrc);
+            if (wstrs) {
+                *argc = apr_wastrtoastr(argv, wstrs, wstrc);
+                GlobalFree(wstrs);
             }
-            dptr = dptr->next;
         }
-        if (dptr) {
-            (*data) = dptr->data;
+
+        sysstr = GetEnvironmentStringsW();
+        dupenv = warrsztoastr(&_environ, sysstr, -1);
+
+        if (env) {
+            *env = apr_malloc_dbg((dupenv + 1) * sizeof (char *),
+                                  __FILE__, __LINE__ );
+            memcpy((void*)*env, _environ, (dupenv + 1) * sizeof (char *));
         }
         else {
-            (*data) = NULL;
         }
-        return APR_SUCCESS;
-    }
-    return APR_ENOPOOL;
-}
 
-/* This is the helper code to resolve late bound entry points 
- * missing from one or more releases of the Win32 API
- */
-
-static const char* const lateDllName[DLL_defined] = {
-    "kernel32", "advapi32", "mswsock",  "ws2_32"  };
-static HMODULE lateDllHandle[DLL_defined] = {
-    NULL,       NULL,       NULL,       NULL      };
+        FreeEnvironmentStringsW(sysstr);
+
+        /* MSVCRT will attempt to maintain the wide environment calls
+         * on _putenv(), which is bogus if we've passed a non-ascii
+         * string to _putenv(), since they use MultiByteToWideChar
+         * and breaking the implicit utf-8 assumption we've built.
+         *
+         * Reset _wenviron for good measure.
+         */
+        if (_wenviron) {
+            apr_wchar_t **wenv = _wenviron;
+            _wenviron = NULL;
+            free(wenv);
+        }
 
-FARPROC LoadLateDllFunc(ap_dlltoken_e fnLib, char* fnName, int ordinal)
-{
-    if (!lateDllHandle[fnLib]) { 
-        lateDllHandle[fnLib] = LoadLibrary(lateDllName[fnLib]);
-        if (!lateDllHandle[fnLib])
-            return NULL;
     }
-    if (ordinal)
-        return GetProcAddress(lateDllHandle[fnLib], (char *) ordinal);
-    else
-        return GetProcAddress(lateDllHandle[fnLib], fnName);
+#endif
+    return rv;
 }
 
-/* This puts one thread in a Listen for signals mode */
-ap_status_t ap_initialize(void)
+static int initialized = 0;
+
+/* Provide to win32/thread.c */
+extern DWORD tls_apr_thread;
+
+APR_DECLARE(apr_status_t) apr_initialize(void)
 {
-    ap_status_t status;
+    apr_pool_t *pool;
+    apr_status_t status;
     int iVersionRequested;
     WSADATA wsaData;
     int err;
-#if 0
-    unsigned tid;
+    apr_oslevel_e osver;
+
+    if (initialized++) {
+        return APR_SUCCESS;
+    }
 
-    if (_beginthreadex(NULL, 0, SignalHandling, NULL, 0, &tid) == 0) {
+    /* Initialize apr_os_level global */
+    if (apr_get_oslevel(&osver) != APR_SUCCESS) {
         return APR_EEXIST;
     }
 
-    while (thread_ready() != 1) {
-        sleep(1);
+    tls_apr_thread = TlsAlloc();
+    if ((status = apr_pool_initialize()) != APR_SUCCESS)
+        return status;
+
+    if (apr_pool_create(&pool, NULL) != APR_SUCCESS) {
+        return APR_ENOPOOL;
     }
-#endif
+
+    apr_pool_tag(pool, "apr_initialize");
 
     iVersionRequested = MAKEWORD(WSAHighByte, WSALowByte);
     err = WSAStartup((WORD) iVersionRequested, &wsaData);
     if (err) {
-        return APR_EEXIST;
+        return err;
     }
     if (LOBYTE(wsaData.wVersion) != WSAHighByte ||
         HIBYTE(wsaData.wVersion) != WSALowByte) {
@@ -260,12 +208,27 @@ ap_status_t ap_initialize(void)
         return APR_EEXIST;
     }
 
-    status = ap_init_alloc();
-    return status;
+    apr_signal_init(pool);
+
+    apr_threadproc_init(pool);
+
+    return APR_SUCCESS;
 }
 
-void ap_terminate(void)
+APR_DECLARE_NONSTD(void) apr_terminate(void)
 {
+    initialized--;
+    if (initialized) {
+        return;
+    }
+    apr_pool_terminate();
+
     WSACleanup();
-    ap_term_alloc();
+
+    TlsFree(tls_apr_thread);
+}
+
+APR_DECLARE(void) apr_terminate2(void)
+{
+    apr_terminate();
 }
diff --git a/misc/win32/utf8.c b/misc/win32/utf8.c
new file mode 100644
index 00000000000..280f4064720
--- /dev/null
+++ b/misc/win32/utf8.c
@@ -0,0 +1,259 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_private.h"
+#include "apr_errno.h"
+#include "apr_arch_utf8.h"
+
+/* Implementation of RFC 3629, "UTF-8, a transformation format of ISO 10646"
+ * with particular attention to canonical translation forms (see section 10
+ * "Security Considerations" of the RFC for more info).
+ *
+ * Since several architectures including Windows support unicode, with UCS2
+ * used as the actual storage conventions by that archicture, these functions
+ * exist to transform or validate UCS2 strings into APR's 'char' type
+ * convention.  It is left up to the operating system to determine the
+ * validitity of the string, e.g. normative forms, in the context of 
+ * its native language support.  Other file systems which support filename 
+ * characters of 0x80-0xff but have no explicit requirement for Unicode
+ * will find this function useful only for validating the character sequences 
+ * and rejecting poorly encoded UTF8 sequences.
+ *
+ * Len UCS-4 range (hex) UTF-8 octet sequence (binary)
+ * 1:2 00000000-0000007F 0xxxxxxx
+ * 2:2 00000080-000007FF 110XXXXx 10xxxxxx
+ * 3:2 00000800-0000FFFF 1110XXXX 10Xxxxxx 10xxxxxx
+ * 4:4 00010000-001FFFFF 11110XXX 10XXxxxx 10xxxxxx 10xxxxxx
+ *     00200000-03FFFFFF 111110XX 10XXXxxx 10xxxxxx 10xxxxxx 10xxxxxx
+ *     04000000-7FFFFFFF 1111110X 10XXXXxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
+ *
+ * One of the X bits must be 1 to avoid overlong representation of ucs2 values. 
+ *
+ * For conversion into ucs2, the 4th form is limited in range to 0010 FFFF,
+ * and the final two forms are used only by full ucs4, per RFC 3629;
+ *
+ *   "Pairs of UCS-2 values between D800 and DFFF (surrogate pairs in 
+ *   Unicode parlance), being actually UCS-4 characters transformed 
+ *   through UTF-16, need special treatment: the UTF-16 transformation 
+ *   must be undone, yielding a UCS-4 character that is then transformed 
+ *   as above."
+ *
+ * From RFC2781 UTF-16: the compressed ISO 10646 encoding bitmask
+ *
+ *  U' = U - 0x10000
+ *  U' = 00000000 0000yyyy yyyyyyxx xxxxxxxx
+ *                    W1 = 110110yy yyyyyyyy
+ *                    W2 = 110111xx xxxxxxxx
+ *  Max U' = 0000 00001111 11111111 11111111
+ *  Max U  = 0000 00010000 11111111 11111111
+ *
+ * Len is the table above is a mapping of bytes used for utf8:ucs2 values,
+ * which results in these conclusions of maximum allocations;
+ *
+ *  apr_conv_utf8_to_ucs2 out bytes:sizeof(in) * 1 <= Req <= sizeof(in) * 2
+ *  apr_conv_ucs2_to_utf8 out words:sizeof(in) / 2 <= Req <= sizeof(in) * 3 / 2
+ */
+
+APR_DECLARE(apr_status_t) apr_conv_utf8_to_ucs2(const char *in, 
+                                                apr_size_t *inbytes,
+                                                apr_wchar_t *out, 
+                                                apr_size_t *outwords)
+{
+    apr_int64_t newch, mask;
+    apr_size_t expect, eating;
+    int ch;
+    
+    while (*inbytes && *outwords) 
+    {
+        ch = (unsigned char)(*in++);
+        if (!(ch & 0200)) {
+            /* US-ASCII-7 plain text
+             */
+            --*inbytes;
+            --*outwords;
+            *(out++) = ch;
+        }
+        else
+        {
+            if ((ch & 0300) != 0300) { 
+                /* Multibyte Continuation is out of place
+                 */
+                return APR_EINVAL;
+            }
+            else
+            {
+                /* Multibyte Sequence Lead Character
+                 *
+                 * Compute the expected bytes while adjusting
+                 * or lead byte and leading zeros mask.
+                 */
+                mask = 0340;
+                expect = 1;
+                while ((ch & mask) == mask) {
+                    mask |= mask >> 1;
+                    if (++expect > 3) /* (truly 5 for ucs-4) */
+                        return APR_EINVAL;
+                }
+                newch = ch & ~mask;
+                eating = expect + 1;
+                if (*inbytes <= expect)
+                    return APR_INCOMPLETE;
+                /* Reject values of excessive leading 0 bits
+                 * utf-8 _demands_ the shortest possible byte length
+                 */
+                if (expect == 1) {
+                    if (!(newch & 0036))
+                        return APR_EINVAL;
+                }
+                else {
+                    /* Reject values of excessive leading 0 bits
+                     */
+                    if (!newch && !((unsigned char)*in & 0077 & (mask << 1)))
+                        return APR_EINVAL;
+                    if (expect == 2) {
+                        /* Reject values D800-DFFF when not utf16 encoded
+                         * (may not be an appropriate restriction for ucs-4)
+                         */
+                        if (newch == 0015 && ((unsigned char)*in & 0040))
+                            return APR_EINVAL;
+                    }
+                    else if (expect == 3) {
+                        /* Short circuit values > 110000
+                         */
+                        if (newch > 4)
+                            return APR_EINVAL;
+                        if (newch == 4 && ((unsigned char)*in & 0060))
+                            return APR_EINVAL;
+                    }
+                }
+                /* Where the boolean (expect > 2) is true, we will need
+                 * an extra word for the output.
+                 */
+                if (*outwords < (apr_size_t)(expect > 2) + 1) 
+                    break; /* buffer full */
+                while (expect--)
+                {
+                    /* Multibyte Continuation must be legal */
+                    if (((ch = (unsigned char)*(in++)) & 0300) != 0200)
+                        return APR_EINVAL;
+                    newch <<= 6;
+                    newch |= (ch & 0077);
+                }
+                *inbytes -= eating;
+                /* newch is now a true ucs-4 character
+                 *
+                 * now we need to fold to ucs-2
+                 */
+                if (newch < 0x10000) 
+                {
+                    --*outwords;
+                    *(out++) = (apr_wchar_t) newch;
+                }
+                else 
+                {
+                    *outwords -= 2;
+                    newch -= 0x10000;
+                    *(out++) = (apr_wchar_t) (0xD800 | (newch >> 10));
+                    *(out++) = (apr_wchar_t) (0xDC00 | (newch & 0x03FF));                    
+                }
+            }
+        }
+    }
+    /* Buffer full 'errors' aren't errors, the client must inspect both
+     * the inbytes and outwords values
+     */
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_conv_ucs2_to_utf8(const apr_wchar_t *in, 
+                                                apr_size_t *inwords,
+                                                char *out, 
+                                                apr_size_t *outbytes)
+{
+    apr_int64_t newch, require;
+    apr_size_t need;
+    char *invout;
+    int ch;
+    
+    while (*inwords && *outbytes) 
+    {
+        ch = (unsigned short)(*in++);
+        if (ch < 0x80)
+        {
+            --*inwords;
+            --*outbytes;
+            *(out++) = (unsigned char) ch;
+        }
+        else 
+        {
+            if ((ch & 0xFC00) == 0xDC00) {
+                /* Invalid Leading ucs-2 Multiword Continuation Character
+                 */
+                return APR_EINVAL;
+            }
+            if ((ch & 0xFC00) == 0xD800) {
+                /* Leading ucs-2 Multiword Character
+                 */
+                if (*inwords < 2) {
+                    /* Missing ucs-2 Multiword Continuation Character
+                     */
+                    return APR_INCOMPLETE;
+                }
+                if (((unsigned short)(*in) & 0xFC00) != 0xDC00) {
+                    /* Invalid ucs-2 Multiword Continuation Character
+                     */
+                    return APR_EINVAL;
+                }
+                newch = (ch & 0x03FF) << 10 | ((unsigned short)(*in++) & 0x03FF);
+                newch += 0x10000;
+            }
+            else {
+                /* ucs-2 Single Word Character
+                 */
+                newch = ch;
+            }
+            /* Determine the absolute minimum utf-8 bytes required
+             */
+            require = newch >> 11;
+            need = 1;
+            while (require)
+                require >>= 5, ++need;
+            if (need >= *outbytes)
+                break; /* Insufficient buffer */
+            *inwords -= (need > 2) + 1;
+            *outbytes -= need + 1;
+            /* Compute the utf-8 characters in last to first order,
+             * calculating the lead character length bits along the way.
+             */
+            ch = 0200;
+            out += need + 1;
+            invout = out;
+            while (need--) {
+                ch |= ch >> 1;
+                *(--invout) = (unsigned char)(0200 | (newch & 0077));
+                newch >>= 6;
+            }
+            /* Compute the lead utf-8 character and move the dest offset
+             */
+            *(--invout) = (unsigned char)(ch | newch);
+        }
+    }
+    /* Buffer full 'errors' aren't errors, the client must inspect both
+     * the inwords and outbytes values
+     */
+    return APR_SUCCESS;    
+}
diff --git a/mmap/beos/Makefile.in b/mmap/beos/Makefile.in
deleted file mode 100644
index eac4bf5dd97..00000000000
--- a/mmap/beos/Makefile.in
+++ /dev/null
@@ -1,64 +0,0 @@
-#CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
-#LIBS=$(EXTRA_LIBS) $(LIBS1)
-#INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
-#LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
-
-RM=@RM@
-CC=@CC@
-RANLIB=@RANLIB@
-CFLAGS=@CFLAGS@ @OPTIM@
-LIBS=@LIBS@
-LDFLAGS=@LDFLAGS@ $(LIBS)
-INCDIR=../../include -I../../file_io/unix
-INCLUDES=-I$(INCDIR) -I.
-
-LIB=libmmap.a
-
-OBJS=mmap.o mmap_common.o
-
-.c.o:
-	$(CC) $(CFLAGS) -c $(INCLUDES) $<
-
-all: $(LIB)
-
-clean:
-	$(RM) -f *.o *.a *.so
-
-distclean: clean
-	-$(RM) -f Makefile
-
-$(OBJS): Makefile
-
-$(LIB): $(OBJS)
-	$(RM) -f $@
-	$(AR) cr $@ $(OBJS)
-	$(RANLIB) $@
-
-#
-# We really don't expect end users to use this rule.  It works only with
-# gcc, and rebuilds Makefile.tmpl.  You have to re-run Configure after
-# using it.
-#
-depend:
-	cp Makefile.in Makefile.in.bak \
-	    && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.in > Makefile.new \
-	    && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \
-	    && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
-	           -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
-		> Makefile.in \
-	    && rm Makefile.new
-
-# DO NOT REMOVE
-mmap.o: mmap.c mmap_h.h ../../include/apr_general.h \
- ../../include/apr.h ../../include/apr_errno.h \
- ../../include/apr_mmap.h ../../include/apr_network_io.h \
- ../../include/apr_file_io.h ../../include/apr_portable.h \
- ../../include/apr_thread_proc.h ../../include/apr_lock.h \
- ../../include/apr_time.h ../../include/apr_lib.h \
- ../../file_io/unix/fileio.h ../../include/apr_private.h
-mmap_common.o: mmap_common.c ../unix/common.c ../unix/../beos/mmap_h.h \
- ../../include/apr_general.h ../../include/apr.h \
- ../../include/apr_errno.h ../../include/apr_mmap.h \
- ../../include/apr_network_io.h ../../include/apr_file_io.h \
- ../../include/apr_portable.h ../../include/apr_thread_proc.h \
- ../../include/apr_lock.h ../../include/apr_time.h
diff --git a/mmap/beos/mmap.c b/mmap/beos/mmap.c
deleted file mode 100644
index f7d97c4579b..00000000000
--- a/mmap/beos/mmap.c
+++ /dev/null
@@ -1,122 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "mmap_h.h"
-
-static ap_status_t mmap_cleanup(void *themmap)
-{
-    ap_mmap_t *mm = themmap;
-    int rv;
-    rv = delete_area(mm->area);
-
-    if (rv == 0) {
-        mm->mm = 0;
-        mm->area = -1;
-        return APR_SUCCESS;
-    }
-    else
-        return errno;
-}
-
-ap_status_t ap_mmap_create(ap_mmap_t **new, ap_file_t *file, ap_off_t offset, ap_size_t size,
-                ap_pool_t *cont)
-{
-    void *mm;
-    area_id aid = -1;
-    char *areaname = "apr_mmap\0";
-    uint32 pages = 0;
-
-    if (file == NULL || file->buffered || file->filedes == -1)
-        return APR_EBADF;
-    (*new) = (ap_mmap_t *)ap_palloc(cont, sizeof(ap_mmap_t));
-    
-    pages = ((size -1) / B_PAGE_SIZE) + 1;
-
-    ap_seek(file, APR_SET, &offset);
-     
-    aid = create_area(areaname, &mm , B_ANY_ADDRESS, pages * B_PAGE_SIZE, 
-        B_FULL_LOCK, B_READ_AREA|B_WRITE_AREA);
-
-    if (aid < B_NO_ERROR) {
-        /* we failed to get an mmap'd file... */
-        return APR_ENOMEM;
-    }
-      
-    if (aid >= B_NO_ERROR)
-        read(file->filedes, mm, size);    
-
-    (*new)->mm = mm;
-    (*new)->size = size;
-    (*new)->area = aid;
-    (*new)->cntxt = cont;
-               
-    /* register the cleanup... */ 
-    ap_register_cleanup((*new)->cntxt, (void*)(*new), mmap_cleanup,
-             ap_null_cleanup);
-
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_mmap_delete(ap_mmap_t *mmap)
-{
-    ap_status_t rv;
-    if (mmap->area == -1)
-        return APR_ENOENT;
-         
-    if ((rv = mmap_cleanup(mmap)) == APR_SUCCESS) {
-        ap_kill_cleanup(mmap->cntxt, mmap, mmap_cleanup);
-        return APR_SUCCESS;
-    }
-    return rv;
-}
diff --git a/mmap/beos/mmap_common.c b/mmap/beos/mmap_common.c
deleted file mode 100644
index 7742d0f9a77..00000000000
--- a/mmap/beos/mmap_common.c
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "../unix/common.c"
-
diff --git a/mmap/beos/mmap_h.h b/mmap/beos/mmap_h.h
deleted file mode 100644
index 89895377122..00000000000
--- a/mmap/beos/mmap_h.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef MMAP_H_H
-#define MMAP_H_H
-
-#include "apr_general.h"
-#include "apr_mmap.h"
-#include "apr_errno.h"
-#include "apr_general.h"
-#include "apr_portable.h"
-#include "apr_lib.h"
-#include "fileio.h"
-#include <sys/stat.h>
-#include <kernel/OS.h>
-#include <errno.h>
-#include <string.h>
-#include <stdio.h>
-
-struct ap_mmap_t {
-    ap_pool_t *cntxt;
-    area_id area;
-    void *mm;
-    size_t size;
-};
-
-#endif  /* ! FILE_IO_H */
-
diff --git a/mmap/unix/.cvsignore b/mmap/unix/.cvsignore
deleted file mode 100644
index f3c7a7c5da6..00000000000
--- a/mmap/unix/.cvsignore
+++ /dev/null
@@ -1 +0,0 @@
-Makefile
diff --git a/mmap/unix/Makefile.in b/mmap/unix/Makefile.in
deleted file mode 100644
index e24de80e4d5..00000000000
--- a/mmap/unix/Makefile.in
+++ /dev/null
@@ -1,66 +0,0 @@
-#CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
-#LIBS=$(EXTRA_LIBS) $(LIBS1)
-#INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
-#LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
-
-RM=@RM@
-CC=@CC@
-RANLIB=@RANLIB@
-CFLAGS=@CFLAGS@ @OPTIM@
-LIBS=@LIBS@
-LDFLAGS=@LDFLAGS@ $(LIBS)
-INCDIR=../../include 
-INCDIR1=../../file_io/@OSDIR@
-INCLUDES=-I$(INCDIR) -I$(INCDIR1) -I.
-
-LIB=libmmap.a
-
-OBJS=mmap.o common.o
-
-.c.o:
-	$(CC) $(CFLAGS) -c $(INCLUDES) $<
-
-all: $(OBJS)
-
-clean:
-	$(RM) -f *.o *.a *.so
-
-distclean: clean
-	-$(RM) -f Makefile
-
-$(OBJS): Makefile
-
-#$(LIB): $(OBJS)
-#	$(RM) -f $@
-#	$(AR) cr $@ $(OBJS)
-#	$(RANLIB) $@
-
-#
-# We really don't expect end users to use this rule.  It works only with
-# gcc, and rebuilds Makefile.tmpl.  You have to re-run Configure after
-# using it.
-#
-depend:
-	cp Makefile.in Makefile.in.bak \
-	    && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.in > Makefile.new \
-	    && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \
-	    && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
-	           -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
-		> Makefile.in \
-	    && rm Makefile.new
-
-# DO NOT REMOVE
-common.o: common.c mmap_h.h ../../include/apr_private.h \
- ../../include/apr_general.h ../../include/apr.h \
- ../../include/apr_errno.h ../../include/apr_mmap.h \
- ../../include/apr_network_io.h ../../include/apr_file_io.h \
- ../../include/apr_time.h ../../include/apr_portable.h \
- ../../include/apr_thread_proc.h ../../include/apr_lock.h \
- ../../file_io/unix/fileio.h ../../include/apr_lib.h
-mmap.o: mmap.c mmap_h.h ../../include/apr_private.h \
- ../../include/apr_general.h ../../include/apr.h \
- ../../include/apr_errno.h ../../include/apr_mmap.h \
- ../../include/apr_network_io.h ../../include/apr_file_io.h \
- ../../include/apr_time.h ../../include/apr_portable.h \
- ../../include/apr_thread_proc.h ../../include/apr_lock.h \
- ../../file_io/unix/fileio.h ../../include/apr_lib.h
diff --git a/mmap/unix/common.c b/mmap/unix/common.c
index 34eb8fe929f..1172f3c89b9 100644
--- a/mmap/unix/common.c
+++ b/mmap/unix/common.c
@@ -1,55 +1,17 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+/* 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.
  */
 
 /* common .c
@@ -61,17 +23,17 @@
  *
  */
 
-#ifdef BEOS
-#include "../beos/mmap_h.h"
-#else
-#include "mmap_h.h"
-#endif
+#include "apr.h"
+#include "apr_private.h"
+#include "apr_mmap.h"
+#include "apr_errno.h"
 
-#if HAVE_MMAP
+#if APR_HAS_MMAP || defined(BEOS)
 
-ap_status_t ap_mmap_offset(void **addr, ap_mmap_t *mmap, ap_off_t offset)
-{  
-    if (offset < 0 || offset > mmap->size)
+APR_DECLARE(apr_status_t) apr_mmap_offset(void **addr, apr_mmap_t *mmap,
+                                          apr_off_t offset)
+{
+    if (offset < 0 || (apr_size_t)offset > mmap->size)
         return APR_EINVAL;
     
     (*addr) = (char *) mmap->mm + offset;
diff --git a/mmap/unix/mmap.c b/mmap/unix/mmap.c
index 5e5b571f7d1..67195709674 100644
--- a/mmap/unix/mmap.c
+++ b/mmap/unix/mmap.c
@@ -1,120 +1,172 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
+#include "apr.h"
+#include "apr_private.h"
+#include "apr_general.h"
+#include "apr_strings.h"
+#include "apr_mmap.h"
+#include "apr_errno.h"
+#include "apr_arch_file_io.h"
+#include "apr_portable.h"
+
+/* System headers required for the mmap library */
 #ifdef BEOS
-#include "../beos/mmap_h.h"
-#else
-#include "mmap_h.h"
+#include <kernel/OS.h>
+#endif
+#if APR_HAVE_STRING_H
+#include <string.h>
+#endif
+#if APR_HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
 #endif
 
-#include "apr_portable.h"
-
-#if HAVE_MMAP
+#if APR_HAS_MMAP || defined(BEOS)
 
-static ap_status_t mmap_cleanup(void *themmap)
+static apr_status_t mmap_cleanup(void *themmap)
 {
-    ap_mmap_t *mm = themmap;
-    int rv;
+    apr_mmap_t *mm = themmap;
+    apr_mmap_t *next = APR_RING_NEXT(mm,link);
+    int rv = 0;
+
+    /* we no longer refer to the mmaped region */
+    APR_RING_REMOVE(mm,link);
+    APR_RING_NEXT(mm,link) = NULL;
+    APR_RING_PREV(mm,link) = NULL;
+
+    if (next != mm) {
+        /* more references exist, so we're done */
+        return APR_SUCCESS;
+    }
+
+#ifdef BEOS
+    rv = delete_area(mm->area);
+#else
     rv = munmap(mm->mm, mm->size);
+#endif
+    mm->mm = (void *)-1;
 
     if (rv == 0) {
-        mm->mm = (caddr_t)-1;
         return APR_SUCCESS;
     }
-    else
-        return errno;
+    return errno;
 }
 
-ap_status_t ap_mmap_create(ap_mmap_t **new, ap_file_t *file, ap_off_t offset, 
-       ap_size_t size, ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_mmap_create(apr_mmap_t **new, 
+                                          apr_file_t *file, apr_off_t offset, 
+                                          apr_size_t size, apr_int32_t flag, 
+                                          apr_pool_t *cont)
 {
-    caddr_t mm;
-   
-    if (file == NULL || file->filedes == -1)
+    void *mm;
+#ifdef BEOS
+    area_id aid = -1;
+    uint32 pages = 0;
+#else
+    apr_int32_t native_flags = 0;
+#endif
+
+#if APR_HAS_LARGE_FILES && defined(HAVE_MMAP64)
+#define mmap mmap64
+#elif APR_HAS_LARGE_FILES && SIZEOF_OFF_T == 4
+    /* LFS but no mmap64: check for overflow */
+    if ((apr_int64_t)offset + size > INT_MAX)
+        return APR_EINVAL;
+#endif
+
+    if (size == 0)
+        return APR_EINVAL;
+    
+    if (file == NULL || file->filedes == -1 || file->buffered)
         return APR_EBADF;
+    (*new) = (apr_mmap_t *)apr_pcalloc(cont, sizeof(apr_mmap_t));
+    
+#ifdef BEOS
+    /* XXX: mmap shouldn't really change the seek offset */
+    apr_file_seek(file, APR_SET, &offset);
 
-    (*new) = (ap_mmap_t *)ap_palloc(cont, sizeof(ap_mmap_t));
+    /* There seems to be some strange interactions that mean our area must
+     * be set as READ & WRITE or writev will fail!  Go figure...
+     * So we ignore the value in flags and always ask for both READ and WRITE
+     */
+    pages = (size + B_PAGE_SIZE -1) / B_PAGE_SIZE;
+    aid = create_area("apr_mmap", &mm , B_ANY_ADDRESS, pages * B_PAGE_SIZE,
+        B_NO_LOCK, B_WRITE_AREA|B_READ_AREA);
+
+    if (aid < B_NO_ERROR) {
+        /* we failed to get an area we can use... */
+        *new = NULL;
+        return APR_ENOMEM;
+    }
+
+    if (aid >= B_NO_ERROR)
+        read(file->filedes, mm, size);
     
-    ap_seek(file, APR_SET, &offset);
-    mm = mmap(NULL, size, PROT_READ, MAP_SHARED, file->filedes ,0);
+    (*new)->area = aid;
+#else
 
-    if (mm == (caddr_t)-1) {
+    if (flag & APR_MMAP_WRITE) {
+        native_flags |= PROT_WRITE;
+    }
+    if (flag & APR_MMAP_READ) {
+        native_flags |= PROT_READ;
+    }
+
+    mm = mmap(NULL, size, native_flags, MAP_SHARED, file->filedes, offset);
+
+    if (mm == (void *)-1) {
         /* we failed to get an mmap'd file... */
-        return APR_ENOMEM;
+        *new = NULL;
+        return errno;
     }
+#endif
+
     (*new)->mm = mm;
     (*new)->size = size;
     (*new)->cntxt = cont;
+    APR_RING_ELEM_INIT(*new, link);
 
     /* register the cleanup... */
-    ap_register_cleanup((*new)->cntxt, (void*)(*new), mmap_cleanup,
-             ap_null_cleanup);
+    apr_pool_cleanup_register((*new)->cntxt, (void*)(*new), mmap_cleanup,
+             apr_pool_cleanup_null);
     return APR_SUCCESS;
 }
 
-ap_status_t ap_mmap_delete(ap_mmap_t *mmap)
+APR_DECLARE(apr_status_t) apr_mmap_dup(apr_mmap_t **new_mmap,
+                                       apr_mmap_t *old_mmap,
+                                       apr_pool_t *p)
 {
-    ap_status_t rv;
+    *new_mmap = (apr_mmap_t *)apr_pmemdup(p, old_mmap, sizeof(apr_mmap_t));
+    (*new_mmap)->cntxt = p;
 
-    if (mmap->mm == (caddr_t) -1)
-        return APR_ENOENT;
-      
-    if ((rv = mmap_cleanup(mmap)) == APR_SUCCESS) {
-        ap_kill_cleanup(mmap->cntxt, mmap, mmap_cleanup);
-        return APR_SUCCESS;
-    }
-    return rv;
+    APR_RING_INSERT_AFTER(old_mmap, *new_mmap, link);
+
+    apr_pool_cleanup_register(p, *new_mmap, mmap_cleanup,
+                              apr_pool_cleanup_null);
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_mmap_delete(apr_mmap_t *mm)
+{
+    return apr_pool_cleanup_run(mm->cntxt, mm, mmap_cleanup);
 }
 
 #endif
diff --git a/mmap/unix/mmap_h.h b/mmap/unix/mmap_h.h
deleted file mode 100644
index fbb42b63d6f..00000000000
--- a/mmap/unix/mmap_h.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef MMAP_H_H
-#define MMAP_H_H
-
-#include "apr_private.h"
-#include "apr_general.h"
-#include "apr_mmap.h"
-#include "apr_errno.h"
-#include "fileio.h"
-#ifdef BEOS
-#include "../beos/mmap_h.h"
-#else
-#include "mmap_h.h"
-#endif
-
-/* System headers required for the mmap library */
-#ifdef BEOS
-#include <kernel/OS.h>
-#endif
-#if HAVE_STRING_H
-#include <string.h>
-#endif
-#if HAVE_STDIO_H
-#include <stdio.h>
-#endif
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_MMAN_H
-#include <sys/mman.h>
-#endif
-/* End System Headers */
-
-struct ap_mmap_t {
-    ap_pool_t *cntxt;
-    void *mm;
-    size_t size;
-};
-
-#endif  /* ! MMAP_H_H */
-
diff --git a/mmap/win32/mmap.c b/mmap/win32/mmap.c
new file mode 100644
index 00000000000..8fbb2f25bb0
--- /dev/null
+++ b/mmap/win32/mmap.c
@@ -0,0 +1,173 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_private.h"
+#include "apr_general.h"
+#include "apr_mmap.h"
+#include "apr_errno.h"
+#include "apr_arch_file_io.h"
+#include "apr_portable.h"
+#include "apr_strings.h"
+
+#if APR_HAS_MMAP
+
+static apr_status_t mmap_cleanup(void *themmap)
+{
+    apr_mmap_t *mm = themmap;
+    apr_mmap_t *next = APR_RING_NEXT(mm,link);
+
+    /* we no longer refer to the mmaped region */
+    APR_RING_REMOVE(mm,link);
+    APR_RING_NEXT(mm,link) = NULL;
+    APR_RING_PREV(mm,link) = NULL;
+
+    if (next != mm) {
+        /* more references exist, so we're done */
+        return APR_SUCCESS;
+    }
+
+    if (mm->mv) {
+        if (!UnmapViewOfFile(mm->mv))
+        {
+            apr_status_t rv = apr_get_os_error();
+            CloseHandle(mm->mhandle);
+            mm->mv = NULL;
+            mm->mhandle = NULL;
+            return rv;
+        }
+        mm->mv = NULL;
+    }
+    if (mm->mhandle) 
+    {
+        if (!CloseHandle(mm->mhandle))
+        {
+            apr_status_t rv = apr_get_os_error();
+            CloseHandle(mm->mhandle);
+            mm->mhandle = NULL;
+            return rv;
+        }
+        mm->mhandle = NULL;
+    }
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_mmap_create(apr_mmap_t **new, apr_file_t *file,
+                                          apr_off_t offset, apr_size_t size,
+                                          apr_int32_t flag, apr_pool_t *cont)
+{
+    static DWORD memblock = 0;
+    DWORD fmaccess = 0;
+    DWORD mvaccess = 0;
+    DWORD offlo;
+    DWORD offhi;
+
+    if (size == 0)
+        return APR_EINVAL;
+    
+    if (flag & APR_MMAP_WRITE)
+        fmaccess |= PAGE_READWRITE;
+    else if (flag & APR_MMAP_READ)
+        fmaccess |= PAGE_READONLY;
+
+    if (flag & APR_MMAP_READ)
+        mvaccess |= FILE_MAP_READ;
+    if (flag & APR_MMAP_WRITE)
+        mvaccess |= FILE_MAP_WRITE;
+
+    if (!file || !file->filehand || file->filehand == INVALID_HANDLE_VALUE
+        || file->buffered)
+        return APR_EBADF;
+
+    if (!memblock)
+    {
+        SYSTEM_INFO si;
+        GetSystemInfo(&si);
+        memblock = si.dwAllocationGranularity;
+    }   
+    
+    *new = apr_pcalloc(cont, sizeof(apr_mmap_t));
+    (*new)->pstart = (offset / memblock) * memblock;
+    (*new)->poffset = offset - (*new)->pstart;
+    (*new)->psize = (apr_size_t)((*new)->poffset) + size;
+    /* The size of the CreateFileMapping object is the current size
+     * of the size of the mmap object (e.g. file size), not the size 
+     * of the mapped region!
+     */
+
+#if APR_HAS_UNICODE_FS
+    IF_WIN_OS_IS_UNICODE
+    {
+        (*new)->mhandle = CreateFileMappingW(file->filehand, NULL, fmaccess,
+                                             0, 0, NULL);
+    }
+#endif
+#if APR_HAS_ANSI_FS
+    ELSE_WIN_OS_IS_ANSI
+    {
+        (*new)->mhandle = CreateFileMappingA(file->filehand, NULL, fmaccess,
+                                             0, 0, NULL);
+    }
+#endif
+    if (!(*new)->mhandle || (*new)->mhandle == INVALID_HANDLE_VALUE)
+    {
+        *new = NULL;
+        return apr_get_os_error();
+    }
+
+    offlo = (DWORD)(*new)->pstart;
+    offhi = (DWORD)((*new)->pstart >> 32);
+    (*new)->mv = MapViewOfFile((*new)->mhandle, mvaccess, offhi,
+                               offlo, (*new)->psize);
+    if (!(*new)->mv)
+    {
+        apr_status_t rv = apr_get_os_error();
+        CloseHandle((*new)->mhandle);
+        *new = NULL;
+        return rv;
+    }
+
+    (*new)->mm = (char*)((*new)->mv) + (*new)->poffset;
+    (*new)->size = size;
+    (*new)->cntxt = cont;
+    APR_RING_ELEM_INIT(*new, link);
+
+    /* register the cleanup... */
+    apr_pool_cleanup_register((*new)->cntxt, (void*)(*new), mmap_cleanup,
+                         apr_pool_cleanup_null);
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_mmap_dup(apr_mmap_t **new_mmap,
+                                       apr_mmap_t *old_mmap,
+                                       apr_pool_t *p)
+{
+    *new_mmap = (apr_mmap_t *)apr_pmemdup(p, old_mmap, sizeof(apr_mmap_t));
+    (*new_mmap)->cntxt = p;
+
+    APR_RING_INSERT_AFTER(old_mmap, *new_mmap, link);
+
+    apr_pool_cleanup_register(p, *new_mmap, mmap_cleanup,
+                              apr_pool_cleanup_null);
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_mmap_delete(apr_mmap_t *mm)
+{
+    return apr_pool_cleanup_run(mm->cntxt, mm, mmap_cleanup);
+}
+
+#endif
diff --git a/network_io/beos/Makefile.in b/network_io/beos/Makefile.in
deleted file mode 100644
index a8b094ef698..00000000000
--- a/network_io/beos/Makefile.in
+++ /dev/null
@@ -1,97 +0,0 @@
-#CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
-#LIBS=$(EXTRA_LIBS) $(LIBS1)
-#INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
-#LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
-
-CC=@CC@
-RANLIB=@RANLIB@
-CFLAGS=@CFLAGS@ @OPTIM@
-LIBS=@LIBS@
-LDFLAGS=@LDFLAGS@ $(LIBS)
-INCDIR=../../include -I../../file_io/unix
-INCLUDES=-I$(INCDIR) -I.
-
-LIB=libnetwork.a
-
-OBJS=poll.o \
-	sendrecv.o \
-	sockets.o \
-	sockopt.o \
-        inet_aton.o \
-        sockaddr.o
-
-.c.o:
-	$(CC) $(CFLAGS) -c $(INCLUDES) $<
-
-all: $(LIB)
-
-clean:
-	$(RM) -f *.o *.a *.so
-
-distclean: clean
-	-$(RM) -f Makefile
-
-$(OBJS): Makefile
-
-$(LIB): $(OBJS)
-	$(RM) -f $@
-	$(AR) cr $@ $(OBJS)
-	$(RANLIB) $@
-
-#
-# We really don't expect end users to use this rule.  It works only with
-# gcc, and rebuilds Makefile.tmpl.  You have to re-run Configure after
-# using it.
-#
-depend:
-	cp Makefile.in Makefile.in.bak \
-	    && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.in > Makefile.new \
-	    && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \
-	    && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
-	           -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
-		> Makefile.in \
-	    && rm Makefile.new
-
-# DO NOT REMOVE
-inet_aton.o: inet_aton.c networkio.h ../../include/apr_network_io.h \
- ../../include/apr_general.h ../../include/apr.h \
- ../../include/apr_errno.h ../../include/apr_file_io.h \
- ../../include/apr_time.h ../../include/apr_portable.h \
- ../../include/apr_thread_proc.h ../../include/apr_lock.h \
- ../../include/apr_lib.h ../../file_io/unix/fileio.h \
- ../../include/apr_private.h
-poll.o: poll.c networkio.h ../../include/apr_network_io.h \
- ../../include/apr_general.h ../../include/apr.h \
- ../../include/apr_errno.h ../../include/apr_file_io.h \
- ../../include/apr_time.h ../../include/apr_portable.h \
- ../../include/apr_thread_proc.h ../../include/apr_lock.h \
- ../../include/apr_lib.h ../../file_io/unix/fileio.h \
- ../../include/apr_private.h
-sendrecv.o: sendrecv.c networkio.h ../../include/apr_network_io.h \
- ../../include/apr_general.h ../../include/apr.h \
- ../../include/apr_errno.h ../../include/apr_file_io.h \
- ../../include/apr_time.h ../../include/apr_portable.h \
- ../../include/apr_thread_proc.h ../../include/apr_lock.h \
- ../../include/apr_lib.h ../../file_io/unix/fileio.h \
- ../../include/apr_private.h
-sockaddr.o: sockaddr.c networkio.h ../../include/apr_network_io.h \
- ../../include/apr_general.h ../../include/apr.h \
- ../../include/apr_errno.h ../../include/apr_file_io.h \
- ../../include/apr_time.h ../../include/apr_portable.h \
- ../../include/apr_thread_proc.h ../../include/apr_lock.h \
- ../../include/apr_lib.h ../../file_io/unix/fileio.h \
- ../../include/apr_private.h
-sockets.o: sockets.c networkio.h ../../include/apr_network_io.h \
- ../../include/apr_general.h ../../include/apr.h \
- ../../include/apr_errno.h ../../include/apr_file_io.h \
- ../../include/apr_time.h ../../include/apr_portable.h \
- ../../include/apr_thread_proc.h ../../include/apr_lock.h \
- ../../include/apr_lib.h ../../file_io/unix/fileio.h \
- ../../include/apr_private.h
-sockopt.o: sockopt.c networkio.h ../../include/apr_network_io.h \
- ../../include/apr_general.h ../../include/apr.h \
- ../../include/apr_errno.h ../../include/apr_file_io.h \
- ../../include/apr_time.h ../../include/apr_portable.h \
- ../../include/apr_thread_proc.h ../../include/apr_lock.h \
- ../../include/apr_lib.h ../../file_io/unix/fileio.h \
- ../../include/apr_private.h
diff --git a/network_io/beos/inet_aton.c b/network_io/beos/inet_aton.c
deleted file mode 100644
index 732019c1177..00000000000
--- a/network_io/beos/inet_aton.c
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright (c) 1983, 1990, 1993
- *    The Regents of the University of California.  All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- * 	This product includes software developed by the University of
- * 	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*
- * Portions Copyright (c) 1993 by Digital Equipment Corporation.
- * 
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies, and that
- * the name of Digital Equipment Corporation not be used in advertising or
- * publicity pertaining to distribution of the document or software without
- * specific, written prior permission.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
- * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
- * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
- * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- */
-
-/*
- * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
- * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
- * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
- * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- */
-
-#include "networkio.h"
-
-/* BeOS doesn't yet have it's own inet_aton and Bind won't be ported
- * until R5, so this is from a Bind 8 distribution.  It's currently untested.
- */
-
-int inet_aton(const char *cp, struct in_addr *addr) {
-	u_long val;
-	int base, n;
-	char c;
-	short parts[4];
-	short *pp = parts;
-	int digit;
-
-	c = *cp;
-	for (;;) {
-		/*
-		 * Collect number up to ``.''.
-		 * Values are specified as for C:
-		 * 0x=hex, 0=octal, isdigit=decimal.
-		 */
-		if (!isdigit(c))
-			return (0);
-		val = 0; base = 10; digit = 0;
-		if (c == '0') {
-			c = *++cp;
-			if (c == 'x' || c == 'X')
-				base = 16, c = *++cp;
-			else {
-				base = 8;
-				digit = 1 ;
-			}
-		}
-		for (;;) {
-			if (isascii(c) && isdigit(c)) {
-				if (base == 8 && (c == '8' || c == '9'))
-					return (0);
-				val = (val * base) + (c - '0');
-				c = *++cp;
-				digit = 1;
-			} else if (base == 16 && isascii(c) && isxdigit(c)) {
-				val = (val << 4) |
-					(c + 10 - (islower(c) ? 'a' : 'A'));
-				c = *++cp;
-				digit = 1;
-			} else
-				break;
-		}
-		if (c == '.') {
-			/*
-			 * Internet format:
-			 *	a.b.c.d
-			 *	a.b.c	(with c treated as 16 bits)
-			 *	a.b	(with b treated as 24 bits)
-			 */
-			if (pp >= parts + 3 || val > 0xff)
-				return (0);
-			*pp++ = val;
-			c = *++cp;
-		} else
-			break;
-	}
-	/*
-	 * Check for trailing characters.
-	 */
-	if (c != '\0' && (!isascii(c) || !isspace(c)))
-		return (0);
-	/*
-	 * Did we get a valid digit?
-	 */
-	if (!digit)
-		return (0);
-	/*
-	 * Concoct the address according to
-	 * the number of parts specified.
-	 */
-	n = pp - parts + 1;
-	switch (n) {
-	case 1:				/* a -- 32 bits */
-		break;
-
-	case 2:				/* a.b -- 8.24 bits */
-		if (val > 0xffffff)
-			return (0);
-		val |= parts[0] << 24;
-		break;
-
-	case 3:				/* a.b.c -- 8.8.16 bits */
-		if (val > 0xffff)
-			return (0);
-		val |= (parts[0] << 24) | (parts[1] << 16);
-		break;
-
-	case 4:				/* a.b.c.d -- 8.8.8.8 bits */
-		if (val > 0xff)
-			return (0);
-		val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
-		break;
-	}
-	if (addr != NULL)
-		addr->s_addr = htonl(val);
-	return (1);
-}
diff --git a/network_io/beos/networkio.h b/network_io/beos/networkio.h
deleted file mode 100644
index 3966acf433b..00000000000
--- a/network_io/beos/networkio.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef NETWORK_IO_H
-#define NETWORK_IO_H
-
-#include <socket.h>
-#include <netdb.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-#include <sys/time.h>
-#include "apr_network_io.h"
-#include "apr_general.h"
-#include "apr_portable.h"
-#include "apr_lib.h"
-#include "fileio.h"
-#include "apr_errno.h"
-
-/* The definition of isascii was missed from the PowerPC ctype.h
- *
- * It will be included in the next release, but until then... */
-#if __POWERPC__
-#define isascii(c) (((c) & ~0x7f)==0)
-#endif
-
-#include "apr_general.h"
-#include <ByteOrder.h> /* for the ntohs definition */
-
-#define POLLIN	 1
-#define POLLPRI  2
-#define POLLOUT  4
-#define POLLERR  8
-#define POLLHUP  16
-#define POLLNVAL 32
-
-struct ap_socket_t {
-    ap_pool_t *cntxt;
-    int socketdes;
-    struct sockaddr_in *local_addr;
-    struct sockaddr_in *remote_addr;
-    int addr_len;
-    ap_interval_time_t timeout;
-    int connected;
-};
-
-struct ap_pollfd_t {
-    ap_pool_t *cntxt;
-    struct ap_socket_t *sock;
-    fd_set *read;
-    fd_set *write;
-    fd_set *except;
-    int highsock;
-};
-
-ap_int16_t get_event(ap_int16_t);
-
-int inet_aton(const char *cp, struct in_addr *addr);
-
-#endif  /* ! NETWORK_IO_H */
-
diff --git a/network_io/beos/poll.c b/network_io/beos/poll.c
deleted file mode 100644
index 82e011ceac8..00000000000
--- a/network_io/beos/poll.c
+++ /dev/null
@@ -1,218 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "networkio.h"
-
-/*  BeOS R4 doesn't have a poll function, but R5 will have */
-/*  so for the time being we try our best with an implementaion that */
-/*  uses select.  However, select on beos isn't that hot either, so */
-/*  until R5 we have to live with a less than perfect implementation */
-
-/*  Apparently those sneaky people at Be included support for write in */
-/*  select for R4.5 of BeOS.  So here we use code that uses the write */
-/*  bits. */
-    
-ap_status_t ap_setup_poll(ap_pollfd_t **new, ap_int32_t num, ap_pool_t *cont)
-{
-    (*new) = (ap_pollfd_t *)ap_palloc(cont, sizeof(ap_pollfd_t) * num);
-    if ((*new) == NULL) {
-        return APR_ENOMEM;
-    }
-    (*new)->cntxt = cont;
-    (*new)->read = (fd_set *)ap_palloc(cont, sizeof(fd_set));
-    (*new)->write = (fd_set *)ap_palloc(cont, sizeof(fd_set));
-    (*new)->except = (fd_set *)ap_palloc(cont, sizeof(fd_set));
-    FD_ZERO((*new)->read);
-    FD_ZERO((*new)->write);
-    FD_ZERO((*new)->except);
-    (*new)->highsock = -1;
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_add_poll_socket(ap_pollfd_t *aprset,
-                               ap_socket_t *sock, ap_int16_t event)
-{
-    if (event & APR_POLLIN) {
-        FD_SET(sock->socketdes, aprset->read);
-    }
-    if (event & APR_POLLPRI) {
-        FD_SET(sock->socketdes, aprset->read);
-    }
-    if (event & APR_POLLOUT) {
-        FD_SET(sock->socketdes, aprset->write);
-    }
-    if (sock->socketdes > aprset->highsock) {
-        aprset->highsock = sock->socketdes;
-    }
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_poll(ap_pollfd_t *aprset, ap_int32_t *nsds, 
-		    ap_interval_time_t timeout)
-{
-    int rv;
-    struct timeval tv, *tvptr;
-
-    if (timeout < 0) {
-        tvptr = NULL;
-    }
-    else {
-        tv.tv_sec = timeout / AP_USEC_PER_SEC;
-        tv.tv_usec = timeout % AP_USEC_PER_SEC;
-	tvptr = &tv;
-    }
-
-    rv = select(aprset->highsock + 1, aprset->read, aprset->write, 
-                    NULL, tvptr);
-
-    (*nsds) = rv;
-    if ((*nsds) == 0) {
-        return APR_TIMEUP;
-    }
-    if ((*nsds) < 0) {
-        return APR_EEXIST;
-    }
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_get_revents(ap_int16_t *event, ap_socket_t *sock, ap_pollfd_t *aprset)
-{
-    ap_int16_t revents = 0;
-    char data[256];
-    int dummy = 256;
-
-    if (FD_ISSET(sock->socketdes, aprset->read)) {
-        revents |= APR_POLLIN;
-        if (recv(sock->socketdes, &data, 0, 0) == -1) {
-            switch (errno) {
-                case ECONNRESET:
-                case ECONNABORTED:
-                case ESHUTDOWN:
-                case ENETRESET: {
-                    revents ^= APR_POLLIN;
-                    revents |= APR_POLLHUP;
-                    break;
-                }
-                case ENOTSOCK: {
-                    revents ^= APR_POLLIN;
-                    revents |= APR_POLLNVAL;
-                }
-                default: {
-                    revents ^= APR_POLLIN;
-                    revents |= APR_POLLERR;
-                }
-            }
-        }
-    }
-    if (FD_ISSET(sock->socketdes, aprset->write)) {
-        revents |= APR_POLLOUT;
-    }
-
-    /* Still no support for execpt bits in BeOS R4.5 so for the time being */
-    /* we can't check this.  Hopefully the error checking above will allow */
-    /* sufficient errors to be recognised to cover this. */
-
-    /*if (FD_ISSET(sock->socketdes, aprset->except)) {
-        revents |= APR_POLLPRI;
-    }*/
-
-    (*event) = revents;
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_remove_poll_socket(ap_pollfd_t *aprset, ap_socket_t *sock)
-{
-    FD_CLR(sock->socketdes, aprset->read);
-    FD_CLR(sock->socketdes, aprset->read);
-    FD_CLR(sock->socketdes, aprset->write);
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_clear_poll_sockets(ap_pollfd_t *aprset, ap_int16_t event)
-{
-    if (event & APR_POLLIN) {
-        FD_ZERO(aprset->read);
-    }
-    if (event & APR_POLLPRI) {
-        FD_ZERO(aprset->read);
-    }
-    if (event & APR_POLLOUT) {
-        FD_ZERO(aprset->write);
-    }
-    aprset->highsock = 0;
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_get_polldata(ap_pollfd_t *pollfd, char *key, void *data)
-{
-    if (pollfd != NULL) {
-        return ap_get_userdata(data, key, pollfd->cntxt);
-    }
-    else {
-        data = NULL;
-        return APR_ENOFILE;
-    }
-}
-
-ap_status_t ap_set_polldata(ap_pollfd_t *pollfd, void *data, char *key,
-                            ap_status_t (*cleanup) (void *))
-{
-    if (pollfd != NULL) {
-        return ap_set_userdata(data, key, cleanup, pollfd->cntxt);
-    }
-    else {
-        data = NULL;
-        return APR_ENOFILE;
-    }
-}
diff --git a/network_io/beos/sendrecv.c b/network_io/beos/sendrecv.c
index 2cccb0b9b7e..201abf89c89 100644
--- a/network_io/beos/sendrecv.c
+++ b/network_io/beos/sendrecv.c
@@ -1,60 +1,27 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "networkio.h"
+#include "apr_private.h"
+#if BEOS_BONE /* BONE uses the unix code - woohoo */
+#include "../unix/sendrecv.c"
+#else
+#include "apr_arch_networkio.h"
+#include "apr_time.h"
 
-static ap_status_t wait_for_io_or_timeout(ap_socket_t *sock, int for_read)
+static apr_status_t wait_for_io_or_timeout(apr_socket_t *sock, int for_read)
 {
     struct timeval tv, *tvptr;
     fd_set fdset;
@@ -67,8 +34,8 @@ static ap_status_t wait_for_io_or_timeout(ap_socket_t *sock, int for_read)
             tvptr = NULL;
         }
         else {
-            tv.tv_sec = sock->timeout / AP_USEC_PER_SEC;
-            tv.tv_usec = sock->timeout % AP_USEC_PER_SEC;
+            tv.tv_sec = sock->timeout / APR_USEC_PER_SEC;
+            tv.tv_usec = sock->timeout % APR_USEC_PER_SEC;
             tvptr = &tv;
         }
         srv = select(sock->socketdes + 1,
@@ -88,59 +55,162 @@ static ap_status_t wait_for_io_or_timeout(ap_socket_t *sock, int for_read)
     return APR_SUCCESS;
 }
 
-ap_status_t ap_send(ap_socket_t *sock, const char *buf, ap_ssize_t *len)
+#define SEND_WAIT APR_USEC_PER_SEC / 10
+
+APR_DECLARE(apr_status_t) apr_socket_send(apr_socket_t *sock, const char *buf,
+                                          apr_size_t *len)
 {
-    ssize_t rv;
+    apr_ssize_t rv;
 	
     do {
         rv = send(sock->socketdes, buf, (*len), 0);
     } while (rv == -1 && errno == EINTR);
 
     if (rv == -1 && errno == EWOULDBLOCK && sock->timeout > 0) {
-        ap_status_t arv = wait_for_io_or_timeout(sock, 0);
+        apr_int32_t snooze_val = SEND_WAIT;
+        apr_int32_t zzz = 0;  
+        
+        do {
+            rv = send(sock->socketdes, buf, (*len), 0);
+            if (rv == -1 && errno == EWOULDBLOCK){
+                apr_sleep (snooze_val);
+                zzz += snooze_val;
+                snooze_val += SEND_WAIT;
+                /* have we passed our timeout value */
+                if (zzz > (sock->timeout * APR_USEC_PER_SEC))
+                    break;
+            }
+        } while (rv == -1 && (errno == EINTR || errno == EWOULDBLOCK));
+    }
+    if (rv == -1) {
+        *len = 0;
+        return errno;
+    }
+    (*len) = rv;
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_socket_recv(apr_socket_t *sock, char *buf, 
+                                          apr_size_t *len)
+{
+    apr_ssize_t rv;
+   
+    do {
+        rv = recv(sock->socketdes, buf, (*len), 0);
+    } while (rv == -1 && errno == EINTR);
+
+    if (rv == -1 && errno == EWOULDBLOCK && sock->timeout > 0) {
+        apr_status_t arv = wait_for_io_or_timeout(sock, 1);
         if (arv != APR_SUCCESS) {
             *len = 0;
             return arv;
         }
         else {
             do {
-                rv = send(sock->socketdes, buf, (*len), 0);
+                rv = recv(sock->socketdes, buf, (*len), 0);
             } while (rv == -1 && errno == EINTR);
         }
     }
     if (rv == -1) {
-        *len = 0;
+        (*len) = 0;
         return errno;
     }
     (*len) = rv;
+    if (rv == 0)
+        return APR_EOF;
     return APR_SUCCESS;
 }
 
-ap_status_t ap_recv(ap_socket_t *sock, char *buf, ap_ssize_t *len)
+/* BeOS doesn't have writev for sockets so we use the following instead...
+ */
+APR_DECLARE(apr_status_t) apr_socket_sendv(apr_socket_t * sock, 
+                                           const struct iovec *vec,
+                                           apr_int32_t nvec, apr_size_t *len)
 {
-    ap_ssize_t rv;
-   
+    *len = vec[0].iov_len;
+    return apr_socket_send(sock, vec[0].iov_base, len);
+}
+
+APR_DECLARE(apr_status_t) apr_socket_sendto(apr_socket_t *sock, 
+                                            apr_sockaddr_t *where,
+                                            apr_int32_t flags, const char *buf,
+                                            apr_size_t *len)
+{
+    apr_ssize_t rv;
+
     do {
-        rv = recv(sock->socketdes, buf, (*len), 0);
+        rv = sendto(sock->socketdes, buf, (*len), flags,
+                    (const struct sockaddr*)&where->sa,
+                    where->salen);
     } while (rv == -1 && errno == EINTR);
 
-    if (rv == -1 && errno == EWOULDBLOCK && sock->timeout > 0) {
-        ap_status_t arv = wait_for_io_or_timeout(sock, 1);
+    if (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)
+        && sock->timeout != 0) {
+        apr_status_t arv = wait_for_io_or_timeout(sock, 0);
         if (arv != APR_SUCCESS) {
             *len = 0;
             return arv;
-        }
-        else {
+        } else {
             do {
-                rv = recv(sock->socketdes, buf, (*len), 0);
+                rv = sendto(sock->socketdes, buf, (*len), flags,
+                            (const struct sockaddr*)&where->sa,
+                            where->salen);
             } while (rv == -1 && errno == EINTR);
         }
     }
+    if (rv == -1) {
+        *len = 0;
+        return errno;
+    }
+    *len = rv;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_socket_recvfrom(apr_sockaddr_t *from,
+                                              apr_socket_t *sock,
+                                              apr_int32_t flags, char *buf,
+                                              apr_size_t *len)
+{
+    apr_ssize_t rv;
+
+    if (from == NULL){
+        return APR_ENOMEM;
+        /* Not sure if this is correct.  Maybe we should just allocate
+           the memory??
+         */
+    }
+
+    do {
+        rv = recvfrom(sock->socketdes, buf, (*len), flags,
+                      (struct sockaddr*)&from->sa, &from->salen);
+    } while (rv == -1 && errno == EINTR);
+
+    if (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) &&
+        sock->timeout != 0) {
+        apr_status_t arv = wait_for_io_or_timeout(sock, 1);
+        if (arv != APR_SUCCESS) {
+            *len = 0;
+            return arv;
+        } else {
+            do {
+                rv = recvfrom(sock->socketdes, buf, (*len), flags,
+                              (struct sockaddr*)&from->sa, &from->salen);
+                } while (rv == -1 && errno == EINTR);
+        }
+    }
     if (rv == -1) {
         (*len) = 0;
         return errno;
     }
+	
+    from->port = ntohs(from->sa.sin.sin_port);
+	
     (*len) = rv;
+    if (rv == 0)
+        return APR_EOF;
+
     return APR_SUCCESS;
 }
 
+#endif /* ! BEOS_BONE */
diff --git a/network_io/beos/sockaddr.c b/network_io/beos/sockaddr.c
deleted file mode 100644
index e880fc364e1..00000000000
--- a/network_io/beos/sockaddr.c
+++ /dev/null
@@ -1,178 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "networkio.h"
-
-ap_status_t ap_set_local_port(ap_socket_t *sock, ap_uint32_t port)
-{
-    if (!sock) {
-        return APR_EBADF;
-    }
-    sock->local_addr->sin_port = htons((short)port);
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_set_remote_port(ap_socket_t *sock, ap_uint32_t port)
-{
-    if (!sock) {
-        return APR_EBADF;
-    }
-    sock->remote_addr->sin_port = htons((short)port);
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_get_local_port(ap_uint32_t *port, ap_socket_t *sock)
-{
-    if (!sock) {
-        return APR_EBADF;
-    }
-    *port = ntohs(sock->local_addr->sin_port);
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_get_remote_port(ap_uint32_t *port, ap_socket_t *sock)
-{
-    if (!sock) {
-        return APR_EBADF;
-    }
-    *port = ntohs(sock->remote_addr->sin_port);
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_set_local_ipaddr(ap_socket_t *sock, const char *addr)
-{
-    u_long ipaddr;
-
-    if (!sock) {
-        return APR_EBADF;
-    }
-    
-    if (!strcmp(addr, APR_ANYADDR)) {
-        sock->local_addr->sin_addr.s_addr = htonl(INADDR_ANY);
-        return APR_SUCCESS;
-    }
-    
-    ipaddr = inet_addr(addr);
-    
-    if (ipaddr == -1) {
-        return errno;
-    }
-    
-    sock->local_addr->sin_addr.s_addr = ipaddr;
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_set_remote_ipaddr(ap_socket_t *sock, const char *addr)
-{
-    u_long ipaddr;
-
-    if (!sock) {
-        return APR_EBADF;
-    }
-    
-    if (!strcmp(addr, APR_ANYADDR)) {
-        sock->remote_addr->sin_addr.s_addr = htonl(INADDR_ANY);
-        return APR_SUCCESS;
-    }
-    
-    ipaddr = inet_addr(addr);
-    
-    if (ipaddr == (u_long)-1) {
-        return errno;
-    }
-    
-    sock->remote_addr->sin_addr.s_addr = ipaddr;
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_get_local_ipaddr(char **addr, const ap_socket_t *sock)
-{
-    if (!sock) {
-        return APR_EBADF;
-    }
-
-    *addr = ap_pstrdup(sock->cntxt, inet_ntoa(sock->local_addr->sin_addr));
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_get_remote_ipaddr(char **addr, const ap_socket_t *sock)
-{
-    if (!sock) {
-        return APR_EBADF;
-    }
-
-    *addr = ap_pstrdup(sock->cntxt, inet_ntoa(sock->remote_addr->sin_addr));
-    return APR_SUCCESS;
-}
-
-
-ap_status_t ap_get_local_name(struct sockaddr_in **name, const ap_socket_t *sock)
-{
-    if (!sock) {
-        return APR_EBADF;
-    }
-
-    *name = sock->local_addr;
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_get_remote_name(struct sockaddr_in **name, const ap_socket_t *sock)
-{
-    if (!sock) {
-        return APR_EBADF;
-    }
-
-    *name = sock->remote_addr;
-    return APR_SUCCESS;
-}
diff --git a/network_io/beos/socketcommon.c b/network_io/beos/socketcommon.c
new file mode 100644
index 00000000000..b9f594bbe0d
--- /dev/null
+++ b/network_io/beos/socketcommon.c
@@ -0,0 +1,6 @@
+#include "../unix/inet_ntop.c"
+#include "../unix/inet_pton.c"
+#include "../unix/sockets.c"
+#include "../unix/sockaddr.c"
+#include "../unix/sockopt.c"
+#include "../unix/socket_util.c"
diff --git a/network_io/beos/sockets.c b/network_io/beos/sockets.c
deleted file mode 100644
index 5a8afa6257e..00000000000
--- a/network_io/beos/sockets.c
+++ /dev/null
@@ -1,233 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "networkio.h"
-
-ap_status_t socket_cleanup(void *sock)
-{
-    ap_socket_t *thesocket = sock;
-    if (closesocket(thesocket->socketdes) == 0) {
-        thesocket->socketdes = -1;
-        return APR_SUCCESS;
-    }
-    else {
-        return errno;
-    }
-}
-
-ap_status_t ap_create_tcp_socket(ap_socket_t **new, ap_pool_t *cont)
-{
-    (*new) = (ap_socket_t *)ap_palloc(cont,sizeof(ap_socket_t));
-    
-    if ((*new) == NULL){
-        return APR_ENOMEM;
-    }
-    
-    (*new)->cntxt = cont;
-	(*new)->local_addr = (struct sockaddr_in *) ap_palloc((*new)->cntxt,
-	                    sizeof (struct sockaddr_in));
-	(*new)->remote_addr = (struct sockaddr_in *) ap_palloc((*new)->cntxt,
-	                    sizeof (struct sockaddr_in));
-    if ((*new)->local_addr == NULL || (*new)->remote_addr==NULL){
-        return APR_ENOMEM;
-    }
-    
-    (*new)->socketdes = socket(AF_INET ,SOCK_STREAM, 0);
-	(*new)->local_addr->sin_family = AF_INET; 
-	(*new)->remote_addr->sin_family = AF_INET; 
-    (*new)->addr_len = sizeof(*(*new)->local_addr);
-	memset(&(*new)->local_addr->sin_zero, 0, sizeof((*new)->local_addr->sin_zero));
-	memset(&(*new)->remote_addr->sin_zero, 0, sizeof((*new)->remote_addr->sin_zero));
-
-    if ((*new)->socketdes < 0) {
-        return errno;
-    }
-
-    (*new)->timeout = -1;
-    ap_register_cleanup((*new)->cntxt, (void *)(*new),
-                            socket_cleanup, ap_null_cleanup);
-    return APR_SUCCESS;
-} 
-
-ap_status_t ap_shutdown(ap_socket_t *thesocket, ap_shutdown_how_e how)
-{
-    return shutdown(thesocket->socketdes, how);
-}
-
-ap_status_t ap_close_socket(ap_socket_t *thesocket)
-{
-    ap_kill_cleanup(thesocket->cntxt,thesocket,socket_cleanup);
-    return socket_cleanup(thesocket);
-}
-
-ap_status_t ap_bind(ap_socket_t *sock) 
-{ 
-    if (bind(sock->socketdes, (struct sockaddr *)sock->local_addr, sock->addr_len) == -1) 
-        return errno; 
-    else 
-        return APR_SUCCESS; 
-} 
- 
-ap_status_t ap_listen(ap_socket_t *sock, ap_int32_t backlog) 
-{ 
-    if (listen(sock->socketdes, backlog) == -1) 
-        return errno; 
-    else 
-        return APR_SUCCESS; 
-} 
-
-ap_status_t ap_accept(ap_socket_t **new, const ap_socket_t *sock, ap_pool_t *connection_context) 
-{ 
-	(*new) = (ap_socket_t *)ap_palloc(connection_context,
-	                        sizeof(ap_socket_t)); 
-
-    (*new)->cntxt = connection_context;
-    (*new)->local_addr = (struct sockaddr_in *)ap_palloc((*new)->cntxt, 
-                 sizeof(struct sockaddr_in));
-
-    (*new)->remote_addr = (struct sockaddr_in *)ap_palloc((*new)->cntxt, 
-                 sizeof(struct sockaddr_in));
-    (*new)->addr_len = sizeof(struct sockaddr_in);
-    (*new)->connected = 1;
-    
-    (*new)->socketdes = accept(sock->socketdes, (struct sockaddr *)(*new)->remote_addr,
-                        &(*new)->addr_len);
-
-    if (getsockname((*new)->socketdes, (struct sockaddr *)(*new)->local_addr,
-         &((*new)->addr_len)) < 0) {
-        return errno;
-    }
-	if ((*new)->socketdes <0){
-		return errno;
-	}
-
-    ap_register_cleanup((*new)->cntxt, (void *)new, 
-                        socket_cleanup, ap_null_cleanup);
-    return APR_SUCCESS;
-} 
- 
-ap_status_t ap_connect(ap_socket_t *sock, char *hostname) 
-{ 
-    struct hostent *hp; 
-
-    hp = gethostbyname(hostname); 
-    if ((sock->socketdes < 0) || (!sock->remote_addr)) { 
-        return APR_ENOTSOCK; 
-    } 
-
-	memcpy((char *)&sock->remote_addr->sin_addr, hp->h_addr , hp->h_length);
-
-    sock->remote_addr->sin_family = AF_INET;
-     
-    memset(sock->remote_addr->sin_zero, 0, sizeof(sock->remote_addr->sin_zero));
-    
-    sock->addr_len = sizeof(sock->remote_addr);
-    
-    if ((connect(sock->socketdes, (const struct sockaddr *)sock->remote_addr, sock->addr_len) < 0) 
-      && (errno != EINPROGRESS)) {
-            return errno; 
-    } else {
-        int namelen = sizeof(*sock->local_addr);
-        getsockname(sock->socketdes, (struct sockaddr *)sock->local_addr, &namelen);
-        sock->connected = 1;
-    }
-     
-    return APR_SUCCESS; 
-} 
-
-ap_status_t ap_get_socketdata(void **data, char *key, ap_socket_t *sock)
-{
-    if (socket != NULL) {
-        return ap_get_userdata(data, key, sock->cntxt);
-    }
-    else {
-        data = NULL;
-        return APR_ENOSOCKET;
-    }
-}
-
-ap_status_t ap_set_socketdata(ap_socket_t *sock, void *data, char *key,
-                              ap_status_t (*cleanup) (void *))
-{
-    if (sock != NULL) {
-        return ap_set_userdata(data, key, cleanup, sock->cntxt);
-    }
-    else {
-        data = NULL;
-        return APR_ENOSOCKET;
-    }
-}
-
-ap_status_t ap_get_os_sock(ap_os_sock_t *thesock, ap_socket_t *sock)
-{
-    if (sock == NULL) {
-        return APR_ENOSOCKET;
-    }
-    *thesock = sock->socketdes;
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_put_os_sock(ap_socket_t **sock, ap_os_sock_t *thesock, 
-                           ap_pool_t *cont)
-{
-    if (cont == NULL) {
-        return APR_ENOPOOL;
-    }
-    if ((*sock) == NULL) {
-        (*sock) = (ap_socket_t *)ap_palloc(cont, sizeof(ap_socket_t));
-        (*sock)->cntxt = cont;
-    }
-    (*sock)->socketdes = *thesock;
-    return APR_SUCCESS;
-}
diff --git a/network_io/beos/sockopt.c b/network_io/beos/sockopt.c
deleted file mode 100644
index 6472fe4eed7..00000000000
--- a/network_io/beos/sockopt.c
+++ /dev/null
@@ -1,112 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "networkio.h"
-
-ap_status_t ap_setsocketopt(ap_socket_t *sock, ap_int32_t opt, ap_int32_t on)
-{
-    int one;
-    if (on){
-        one = 1;
-    }else {
-        one = 0;
-	}
-	if (opt & APR_SO_SNDBUF) 
-	    return APR_ENOTIMPL;
-
-    if (opt & APR_SO_DEBUG) {
-        if (setsockopt(sock->socketdes, SOL_SOCKET, SO_DEBUG, &one, sizeof(one)) == -1) {
-            return errno;
-        }
-    }
-    if (opt & APR_SO_REUSEADDR) {
-        if (setsockopt(sock->socketdes, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) == -1) {
-            return errno;
-        }
-    }
-    if (opt & APR_SO_NONBLOCK) {
-    	if (setsockopt(sock->socketdes, SOL_SOCKET, SO_NONBLOCK, &one, sizeof(one)) == -1){
-    		return errno;
-    	}
-    } 
-    return APR_SUCCESS;
-}         
-
-ap_status_t ap_gethostname(char * buf, int len, ap_pool_t *cont)
-{
-	if (gethostname(buf, len) == -1){
-		return errno;
-	} else {
-		return APR_SUCCESS;
-	}
-}
-
-ap_status_t ap_get_remote_hostname(char **name, ap_socket_t *sock)
-{
-    struct hostent *hptr;
-    
-    hptr = gethostbyaddr((char *)&(sock->remote_addr->sin_addr), 
-                         sizeof(struct in_addr), AF_INET);
-    if (hptr != NULL) {
-        *name = ap_pstrdup(sock->cntxt, hptr->h_name);
-        if (*name) {
-            return APR_SUCCESS;
-        }
-        return APR_ENOMEM;
-    }
-
-    /* XXX - Is this threadsafe? - manoj */
-    /* on BeOS h_errno is a global... */
-    return h_errno;
-}
diff --git a/network_io/os2/.cvsignore b/network_io/os2/.cvsignore
deleted file mode 100644
index f3c7a7c5da6..00000000000
--- a/network_io/os2/.cvsignore
+++ /dev/null
@@ -1 +0,0 @@
-Makefile
diff --git a/network_io/os2/Makefile.in b/network_io/os2/Makefile.in
deleted file mode 100644
index 54dfb7d331a..00000000000
--- a/network_io/os2/Makefile.in
+++ /dev/null
@@ -1,91 +0,0 @@
-#CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
-#LIBS=$(EXTRA_LIBS) $(LIBS1)
-#INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
-#LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
-
-CC=@CC@
-RANLIB=@RANLIB@
-CFLAGS=@CFLAGS@ @OPTIM@
-LIBS=@LIBS@
-LDFLAGS=@LDFLAGS@ $(LIBS)
-INCDIR=../../inc
-INCDIR1=../../include
-INCLUDES=-I$(INCDIR) -I$(INCDIR1) -I.
-
-LIB=network.a
-
-OBJS=poll.o \
-	sendrecv.o \
-	sockets.o \
-	sockopt.o \
-	sockaddr.o \
-	os2calls.o
-
-.c.o:
-	$(CC) $(CFLAGS) -c $(INCLUDES) $<
-
-all: $(LIB)
-
-clean:
-	$(RM) -f *.o *.a *.so
-
-distclean: clean
-	-$(RM) -f Makefile
-
-$(OBJS): Makefile
-
-$(LIB): $(OBJS)
-	$(RM) -f $@
-	$(AR) cr $@ $(OBJS)
-	$(RANLIB) $@
-
-#
-# We really don't expect end users to use this rule.  It works only with
-# gcc, and rebuilds Makefile.tmpl.  You have to re-run Configure after
-# using it.
-#
-depend:
-	cp Makefile.in Makefile.in.bak \
-	    && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.in > Makefile.new \
-	    && gcc -MM $(INCLUDES) $(CFLAGS) *.c | sed -e "s%\\\\\(.\)%/\\1%g" >> Makefile.new \
-	    && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
-                   -e '1,$$s: $(INCDIR1)/: $$(INCDIR1)/:g' \
-	           -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
-		> Makefile.in \
-	    && rm Makefile.new
-
-# DO NOT REMOVE
-os2calls.o: os2calls.c networkio.h $(INCDIR1)/apr_network_io.h \
- $(INCDIR1)/apr_general.h $(INCDIR1)/apr.h \
- $(INCDIR1)/apr_errno.h $(INCDIR1)/apr_file_io.h \
- $(INCDIR1)/apr_time.h os2calls.h $(INCDIR1)/apr_portable.h \
- $(INCDIR1)/apr_thread_proc.h $(INCDIR1)/apr_lock.h \
- $(INCDIR1)/apr_lib.h
-poll.o: poll.c networkio.h $(INCDIR1)/apr_network_io.h \
- $(INCDIR1)/apr_general.h $(INCDIR1)/apr.h \
- $(INCDIR1)/apr_errno.h $(INCDIR1)/apr_file_io.h \
- $(INCDIR1)/apr_time.h os2calls.h $(INCDIR1)/apr_portable.h \
- $(INCDIR1)/apr_thread_proc.h $(INCDIR1)/apr_lock.h \
- $(INCDIR1)/apr_lib.h
-sendrecv.o: sendrecv.c networkio.h $(INCDIR1)/apr_network_io.h \
- $(INCDIR1)/apr_general.h $(INCDIR1)/apr.h \
- $(INCDIR1)/apr_errno.h $(INCDIR1)/apr_file_io.h \
- $(INCDIR1)/apr_time.h os2calls.h $(INCDIR1)/apr_lib.h \
- $(INCDIR1)/apr_thread_proc.h
-sockaddr.o: sockaddr.c ../unix/sockaddr.c ../unix/networkio.h \
- $(INCDIR1)/apr_private.h $(INCDIR1)/apr_network_io.h \
- $(INCDIR1)/apr_general.h $(INCDIR1)/apr.h \
- $(INCDIR1)/apr_errno.h $(INCDIR1)/apr_file_io.h \
- $(INCDIR1)/apr_time.h $(INCDIR1)/apr_lib.h \
- $(INCDIR1)/apr_thread_proc.h
-sockets.o: sockets.c networkio.h $(INCDIR1)/apr_network_io.h \
- $(INCDIR1)/apr_general.h $(INCDIR1)/apr.h \
- $(INCDIR1)/apr_errno.h $(INCDIR1)/apr_file_io.h \
- $(INCDIR1)/apr_time.h os2calls.h $(INCDIR1)/apr_portable.h \
- $(INCDIR1)/apr_thread_proc.h $(INCDIR1)/apr_lock.h \
- $(INCDIR1)/apr_lib.h
-sockopt.o: sockopt.c networkio.h $(INCDIR1)/apr_network_io.h \
- $(INCDIR1)/apr_general.h $(INCDIR1)/apr.h \
- $(INCDIR1)/apr_errno.h $(INCDIR1)/apr_file_io.h \
- $(INCDIR1)/apr_time.h os2calls.h $(INCDIR1)/apr_lib.h \
- $(INCDIR1)/apr_thread_proc.h
diff --git a/network_io/os2/inet_ntop.c b/network_io/os2/inet_ntop.c
new file mode 100644
index 00000000000..f1f79d49489
--- /dev/null
+++ b/network_io/os2/inet_ntop.c
@@ -0,0 +1 @@
+#include "../unix/inet_ntop.c"
diff --git a/network_io/os2/inet_pton.c b/network_io/os2/inet_pton.c
new file mode 100644
index 00000000000..dbd3ac454b0
--- /dev/null
+++ b/network_io/os2/inet_pton.c
@@ -0,0 +1 @@
+#include "../unix/inet_pton.c"
diff --git a/network_io/os2/multicast.c b/network_io/os2/multicast.c
new file mode 100644
index 00000000000..f1ab4990e22
--- /dev/null
+++ b/network_io/os2/multicast.c
@@ -0,0 +1 @@
+#include "../unix/multicast.c"
diff --git a/network_io/os2/networkio.h b/network_io/os2/networkio.h
deleted file mode 100644
index 63424de6a74..00000000000
--- a/network_io/os2/networkio.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef NETWORK_IO_H
-#define NETWORK_IO_H
-
-#include "apr_network_io.h"
-#include "apr_general.h"
-#include "os2calls.h"
-
-struct ap_socket_t {
-    ap_pool_t *cntxt;
-    int socketdes;
-    struct sockaddr_in *local_addr;
-    struct sockaddr_in *remote_addr;
-    int addr_len;
-    ap_interval_time_t timeout;
-    int nonblock;
-};
-
-struct ap_pollfd_t {
-    ap_pool_t *cntxt;
-    int *socket_list;
-    int *r_socket_list;
-    int num_read;
-    int num_write;
-    int num_except;
-    int num_total;
-};
-
-/* Error codes returned from sock_errno() */
-#define SOCBASEERR              10000
-#define SOCEPERM                (SOCBASEERR+1)             /* Not owner */
-#define SOCESRCH                (SOCBASEERR+3)             /* No such process */
-#define SOCEINTR                (SOCBASEERR+4)             /* Interrupted system call */
-#define SOCENXIO                (SOCBASEERR+6)             /* No such device or address */
-#define SOCEBADF                (SOCBASEERR+9)             /* Bad file number */
-#define SOCEACCES               (SOCBASEERR+13)            /* Permission denied */
-#define SOCEFAULT               (SOCBASEERR+14)            /* Bad address */
-#define SOCEINVAL               (SOCBASEERR+22)            /* Invalid argument */
-#define SOCEMFILE               (SOCBASEERR+24)            /* Too many open files */
-#define SOCEPIPE                (SOCBASEERR+32)            /* Broken pipe */
-#define SOCEOS2ERR              (SOCBASEERR+100)            /* OS/2 Error */
-
-#endif  /* ! NETWORK_IO_H */
-
diff --git a/network_io/os2/os2calls.c b/network_io/os2/os2calls.c
index 586ab0a8eaa..c0aec855afe 100644
--- a/network_io/os2/os2calls.c
+++ b/network_io/os2/os2calls.c
@@ -1,64 +1,24 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "networkio.h"
+#include "apr_arch_networkio.h"
 #include "apr_network_io.h"
 #include "apr_portable.h"
 #include "apr_general.h"
 #include "apr_lib.h"
-#define INCL_DOS
-#include <os2.h>
 
 static int os2_socket_init(int, int ,int);
 
@@ -79,6 +39,8 @@ int (*apr_os2_setsockopt)(int, int, int, char *, int) = NULL;
 int (*apr_os2_shutdown)(int, int) = NULL;
 int (*apr_os2_soclose)(int) = NULL;
 int (*apr_os2_writev)(int, struct iovec *, int) = NULL;
+int (*apr_os2_sendto)(int, const char *, int, int, const struct sockaddr *, int);
+int (*apr_os2_recvfrom)(int, char *, int, int, struct sockaddr *, int *);
 
 static HMODULE hSO32DLL;
 
@@ -93,7 +55,7 @@ static int os2_fn_link()
         rc = DosLoadModule(errorstr, sizeof(errorstr), "SO32DLL", &hSO32DLL);
 
         if (rc)
-            return APR_OS2_STATUS(rc);
+            return APR_FROM_OS_ERROR(rc);
 
         rc = DosQueryProcAddr(hSO32DLL, 0, "SOCKET", &apr_os2_socket);
 
@@ -145,8 +107,14 @@ static int os2_fn_link()
         if (!rc)
             rc = DosQueryProcAddr(hSO32DLL, 0, "WRITEV", &apr_os2_writev);
 
+        if (!rc)
+            rc = DosQueryProcAddr(hSO32DLL, 0, "SENDTO", &apr_os2_sendto);
+
+        if (!rc)
+            rc = DosQueryProcAddr(hSO32DLL, 0, "RECVFROM", &apr_os2_recvfrom);
+
         if (rc)
-            return APR_OS2_STATUS(rc);
+            return APR_FROM_OS_ERROR(rc);
     }
 
     DosExitCritSec();
diff --git a/network_io/os2/os2calls.h b/network_io/os2/os2calls.h
deleted file mode 100644
index 40d54ee6e68..00000000000
--- a/network_io/os2/os2calls.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-
-extern int (*apr_os2_socket)(int, int, int);
-extern int (*apr_os2_select)(int *, int, int, int, long);
-extern int (*apr_os2_sock_errno)();
-extern int (*apr_os2_accept)(int, struct sockaddr *, int *);
-extern int (*apr_os2_bind)(int, struct sockaddr *, int);
-extern int (*apr_os2_connect)(int, struct sockaddr *, int);
-extern int (*apr_os2_getpeername)(int, struct sockaddr *, int *);
-extern int (*apr_os2_getsockname)(int, struct sockaddr *, int *);
-extern int (*apr_os2_getsockopt)(int, int, int, char *, int *);
-extern int (*apr_os2_ioctl)(int, int, caddr_t, int);
-extern int (*apr_os2_listen)(int, int);
-extern int (*apr_os2_recv)(int, char *, int, int);
-extern int (*apr_os2_send)(int, const char *, int, int);
-extern int (*apr_os2_setsockopt)(int, int, int, char *, int);
-extern int (*apr_os2_shutdown)(int, int);
-extern int (*apr_os2_soclose)(int);
-extern int (*apr_os2_writev)(int, struct iovec *, int);
-
-#define socket apr_os2_socket
-#define select apr_os2_select
-#define sock_errno apr_os2_sock_errno
-#define accept apr_os2_accept
-#define bind apr_os2_bind
-#define connect apr_os2_connect
-#define getpeername apr_os2_getpeername
-#define getsockname apr_os2_getsockname
-#define getsockopt apr_os2_getsockopt
-#define ioctl apr_os2_ioctl
-#define listen apr_os2_listen
-#define recv apr_os2_recv
-#define send apr_os2_send
-#define setsockopt apr_os2_setsockopt
-#define shutdown apr_os2_shutdown
-#define soclose apr_os2_soclose
-#define writev apr_os2_writev
-
-
-/* Error codes returned by above calls */
-#define SOCBASEERR              10000
-
-#define SOCEPERM                (SOCBASEERR+1)             /* Not owner */
-#define SOCESRCH                (SOCBASEERR+3)             /* No such process */
-#define SOCEINTR                (SOCBASEERR+4)             /* Interrupted system call */
-#define SOCENXIO                (SOCBASEERR+6)             /* No such device or address */
-#define SOCEBADF                (SOCBASEERR+9)             /* Bad file number */
-#define SOCEACCES               (SOCBASEERR+13)            /* Permission denied */
-#define SOCEFAULT               (SOCBASEERR+14)            /* Bad address */
-#define SOCEINVAL               (SOCBASEERR+22)            /* Invalid argument */
-#define SOCEMFILE               (SOCBASEERR+24)            /* Too many open files */
-#define SOCEPIPE                (SOCBASEERR+32)            /* Broken pipe */
-#define SOCEOS2ERR              (SOCBASEERR+100)           /* OS/2 Error */
-#define SOCEWOULDBLOCK          (SOCBASEERR+35)            /* Operation would block */
-#define SOCEINPROGRESS          (SOCBASEERR+36)            /* Operation now in progress */
-#define SOCEALREADY             (SOCBASEERR+37)            /* Operation already in progress */
-#define SOCENOTSOCK             (SOCBASEERR+38)            /* Socket operation on non-socket */
-#define SOCEDESTADDRREQ         (SOCBASEERR+39)            /* Destination address required */
-#define SOCEMSGSIZE             (SOCBASEERR+40)            /* Message too long */
-#define SOCEPROTOTYPE           (SOCBASEERR+41)            /* Protocol wrong type for socket */
-#define SOCENOPROTOOPT          (SOCBASEERR+42)            /* Protocol not available */
-#define SOCEPROTONOSUPPORT      (SOCBASEERR+43)            /* Protocol not supported */
-#define SOCESOCKTNOSUPPORT      (SOCBASEERR+44)            /* Socket type not supported */
-#define SOCEOPNOTSUPP           (SOCBASEERR+45)            /* Operation not supported on socket */
-#define SOCEPFNOSUPPORT         (SOCBASEERR+46)            /* Protocol family not supported */
-#define SOCEAFNOSUPPORT         (SOCBASEERR+47)            /* Address family not supported by protocol family */
-#define SOCEADDRINUSE           (SOCBASEERR+48)            /* Address already in use */
-#define SOCEADDRNOTAVAIL        (SOCBASEERR+49)            /* Can't assign requested address */
-#define SOCENETDOWN             (SOCBASEERR+50)            /* Network is down */
-#define SOCENETUNREACH          (SOCBASEERR+51)            /* Network is unreachable */
-#define SOCENETRESET            (SOCBASEERR+52)            /* Network dropped connection on reset */
-#define SOCECONNABORTED         (SOCBASEERR+53)            /* Software caused connection abort */
-#define SOCECONNRESET           (SOCBASEERR+54)            /* Connection reset by peer */
-#define SOCENOBUFS              (SOCBASEERR+55)            /* No buffer space available */
-#define SOCEISCONN              (SOCBASEERR+56)            /* Socket is already connected */
-#define SOCENOTCONN             (SOCBASEERR+57)            /* Socket is not connected */
-#define SOCESHUTDOWN            (SOCBASEERR+58)            /* Can't send after socket shutdown */
-#define SOCETOOMANYREFS         (SOCBASEERR+59)            /* Too many references: can't splice */
-#define SOCETIMEDOUT            (SOCBASEERR+60)            /* Connection timed out */
-#define SOCECONNREFUSED         (SOCBASEERR+61)            /* Connection refused */
-#define SOCELOOP                (SOCBASEERR+62)            /* Too many levels of symbolic links */
-#define SOCENAMETOOLONG         (SOCBASEERR+63)            /* File name too long */
-#define SOCEHOSTDOWN            (SOCBASEERR+64)            /* Host is down */
-#define SOCEHOSTUNREACH         (SOCBASEERR+65)            /* No route to host */
-#define SOCENOTEMPTY            (SOCBASEERR+66)            /* Directory not empty */
diff --git a/network_io/os2/poll.c b/network_io/os2/poll.c
deleted file mode 100644
index a36854ff018..00000000000
--- a/network_io/os2/poll.c
+++ /dev/null
@@ -1,233 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "networkio.h"
-#include "apr_network_io.h"
-#include "apr_general.h"
-#include "apr_portable.h"
-#include "apr_lib.h"
-#include <sys/time.h>
-#include <stdlib.h>
-#define INCL_DOS
-#include <os2.h>
-
-/*  OS/2 doesn't have a poll function, implement using OS/2 style select */
- 
-ap_status_t ap_setup_poll(ap_pollfd_t **new, ap_int32_t num, ap_pool_t *cont)
-{
-    *new = (ap_pollfd_t *)ap_palloc(cont, sizeof(ap_pollfd_t));
-
-    if (*new == NULL) {
-        return APR_ENOMEM;
-    }
-
-    (*new)->socket_list = ap_palloc(cont, sizeof(int) * num);
-    
-    if ((*new)->socket_list == NULL) {
-        return APR_ENOMEM;
-    }
-    
-    (*new)->r_socket_list = ap_palloc(cont, sizeof(int) * num);
-    
-    if ((*new)->r_socket_list == NULL) {
-        return APR_ENOMEM;
-    }
-    
-    (*new)->cntxt = cont;
-    (*new)->num_total = 0;
-    (*new)->num_read = 0;
-    (*new)->num_write = 0;
-    (*new)->num_except = 0;
-    
-    return APR_SUCCESS;
-}
-
-
-
-ap_status_t ap_add_poll_socket(ap_pollfd_t *aprset, 
-			       ap_socket_t *sock, ap_int16_t events)
-{
-    int i;
-    
-    if (events & APR_POLLIN) {
-        for (i=aprset->num_total; i>aprset->num_read; i--)
-            aprset->socket_list[i] = aprset->socket_list[i-1];
-        aprset->socket_list[i] = sock->socketdes;
-        aprset->num_read++;
-        aprset->num_total++;
-    }
-            
-    if (events & APR_POLLOUT) {
-        for (i=aprset->num_total; i>aprset->num_read + aprset->num_write; i--)
-            aprset->socket_list[i] = aprset->socket_list[i-1];
-        aprset->socket_list[i] = sock->socketdes;
-        aprset->num_write++;
-        aprset->num_total++;
-    }            
-        
-    if (events &APR_POLLPRI) {
-        aprset->socket_list[aprset->num_total] = sock->socketdes;
-        aprset->num_except++;
-        aprset->num_total++;
-    }
-    return APR_SUCCESS;
-}
-
-
-
-ap_status_t ap_poll(ap_pollfd_t *pollfdset, ap_int32_t *nsds, 
-                    ap_interval_time_t timeout)
-{
-    int i;
-    int rv = 0;
-    time_t starttime;
-    struct timeval tv;
-
-    timeout /= AP_USEC_PER_SEC; /* TODO: rework for microseconds and axe this */
-
-    tv.tv_sec = timeout;
-    tv.tv_usec = 0;
-    time(&starttime);
-
-    do {
-        for (i=0; i<pollfdset->num_total; i++) {
-            pollfdset->r_socket_list[i] = pollfdset->socket_list[i];
-        }
-        
-        rv = select(pollfdset->r_socket_list, 
-                    pollfdset->num_read, 
-                    pollfdset->num_write, 
-                    pollfdset->num_except, 
-                    timeout >= 0 ? timeout * 1000 : -1);
-
-        if (rv < 0 && sock_errno() == SOCEINTR && timeout >= 0 ) {
-            time_t elapsed = time(NULL) - starttime;
-
-            if (timeout <= elapsed)
-                break;
-
-            timeout -= elapsed;
-        }
-    } while ( rv < 0 && sock_errno() == SOCEINTR );
-
-    (*nsds) = rv;
-    return rv < 0 ? APR_OS2_STATUS(sock_errno()) : APR_SUCCESS;
-}
-
-
-
-ap_status_t ap_get_revents(ap_int16_t *event, ap_socket_t *sock, ap_pollfd_t *aprset)
-{
-    int i;
-    
-    *event = 0;
-    
-    for (i=0; i < aprset->num_total; i++) {
-        if (aprset->socket_list[i] == sock->socketdes && aprset->r_socket_list[i] > 0) {
-            if (i < aprset->num_read)
-                *event |= APR_POLLIN;
-            else if (i < aprset->num_read + aprset->num_write)
-                *event |= APR_POLLOUT;
-            else
-                *event |= APR_POLLPRI;
-        }
-    }
-
-    return APR_SUCCESS;
-}
-
-
-
-ap_status_t ap_mask_poll_socket(ap_pollfd_t *aprset, 
-                                ap_socket_t *sock, ap_int16_t events)
-{
-    int start, *count, pos;
-
-    while (events) {
-        if (events & APR_POLLIN) {
-            start = 0;
-            count = &aprset->num_read;
-            events -= APR_POLLIN;
-        } else if (events & APR_POLLOUT) {
-            start = aprset->num_read;
-            count = &aprset->num_write;
-            events -= APR_POLLOUT;
-        } else if (events & APR_POLLPRI) {
-            start = aprset->num_read + aprset->num_write;
-            count = &aprset->num_except;
-            events -= APR_POLLPRI;
-        } else
-            break;
-
-        for (pos=start; pos < start+(*count) && aprset->socket_list[pos] != sock->socketdes; pos++);
-
-        if (pos < start+(*count)) {
-            aprset->num_total--;
-            (*count)--;
-
-            for (;pos<aprset->num_total; pos++) {
-                aprset->socket_list[pos] = aprset->socket_list[pos+1];
-            }
-        }
-    }
-
-    return APR_SUCCESS;
-}
-
-
-
-ap_status_t ap_remove_poll_socket(ap_pollfd_t *aprset, ap_socket_t *sock)
-{
-    return ap_mask_poll_socket(aprset, sock, APR_POLLIN|APR_POLLOUT|APR_POLLPRI);
-}
diff --git a/network_io/os2/sendrecv.c b/network_io/os2/sendrecv.c
index a2bf144295e..4f67b3b312d 100644
--- a/network_io/os2/sendrecv.c
+++ b/network_io/os2/sendrecv.c
@@ -1,69 +1,36 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "networkio.h"
+#include "apr_arch_networkio.h"
 #include "apr_errno.h"
 #include "apr_general.h"
 #include "apr_network_io.h"
 #include "apr_lib.h"
 #include <sys/time.h>
 
-ap_status_t ap_send(ap_socket_t *sock, const char *buf, ap_ssize_t *len)
+APR_DECLARE(apr_status_t) apr_socket_send(apr_socket_t *sock, const char *buf,
+                                          apr_size_t *len)
 {
-    ssize_t rv;
+    apr_ssize_t rv;
     int fds, err = 0;
 
+    if (*len > 65536) {
+        *len = 65536;
+    }
+
     do {
         if (!sock->nonblock || err == SOCEWOULDBLOCK) {
             fds = sock->socketdes;
@@ -79,7 +46,7 @@ ap_status_t ap_send(ap_socket_t *sock, const char *buf, ap_ssize_t *len)
                 if (err == SOCEINTR)
                     continue;
 
-                return APR_OS2_STATUS(err);
+                return APR_FROM_OS_ERROR(err);
             }
         }
 
@@ -89,7 +56,7 @@ ap_status_t ap_send(ap_socket_t *sock, const char *buf, ap_ssize_t *len)
 
     if (err) {
         *len = 0;
-        return APR_OS2_STATUS(err);
+        return APR_FROM_OS_ERROR(err);
     }
 
     (*len) = rv;
@@ -98,13 +65,14 @@ ap_status_t ap_send(ap_socket_t *sock, const char *buf, ap_ssize_t *len)
 
 
 
-ap_status_t ap_recv(ap_socket_t *sock, char *buf, ap_ssize_t *len)
+APR_DECLARE(apr_status_t) apr_socket_recv(apr_socket_t *sock, char *buf,
+                                          apr_size_t *len)
 {
-    ssize_t rv;
+    apr_ssize_t rv;
     int fds, err = 0;
 
     do {
-        if (!sock->nonblock || err == SOCEWOULDBLOCK) {
+        if (!sock->nonblock || (err == SOCEWOULDBLOCK && sock->timeout != 0)) {
             fds = sock->socketdes;
             rv = select(&fds, 1, 0, 0, sock->timeout >= 0 ? sock->timeout/1000 : -1);
 
@@ -118,33 +86,41 @@ ap_status_t ap_recv(ap_socket_t *sock, char *buf, ap_ssize_t *len)
                 if (err == SOCEINTR)
                     continue;
 
-                return APR_OS2_STATUS(err);
+                return APR_FROM_OS_ERROR(err);
             }
         }
 
         rv = recv(sock->socketdes, buf, (*len), 0);
         err = rv < 0 ? sock_errno() : 0;
-    } while (err == SOCEINTR || err == SOCEWOULDBLOCK);
+    } while (err == SOCEINTR || (err == SOCEWOULDBLOCK && sock->timeout != 0));
 
     if (err) {
         *len = 0;
-        return APR_OS2_STATUS(err);
+        return APR_FROM_OS_ERROR(err);
     }
 
     (*len) = rv;
-    return APR_SUCCESS;
+    return rv == 0 ? APR_EOF : APR_SUCCESS;
 }
 
 
 
-ap_status_t ap_sendv(ap_socket_t *sock, const struct iovec *vec, ap_int32_t nvec, ap_int32_t *len)
+APR_DECLARE(apr_status_t) apr_socket_sendv(apr_socket_t *sock, 
+                                           const struct iovec *vec, 
+                                           apr_int32_t nvec, apr_size_t *len)
 {
-    ap_status_t rv;
+    apr_status_t rv;
     struct iovec *tmpvec;
     int fds, err = 0;
+    int nv_tosend, total = 0;
 
-    tmpvec = alloca(sizeof(struct iovec) * nvec);
-    memcpy(tmpvec, vec, sizeof(struct iovec) * nvec);
+    /* Make sure writev() only gets fed 64k at a time */
+    for ( nv_tosend = 0; nv_tosend < nvec && total + vec[nv_tosend].iov_len < 65536; nv_tosend++ ) {
+        total += vec[nv_tosend].iov_len;
+    }
+
+    tmpvec = alloca(sizeof(struct iovec) * nv_tosend);
+    memcpy(tmpvec, vec, sizeof(struct iovec) * nv_tosend);
 
     do {
         if (!sock->nonblock || err == SOCEWOULDBLOCK) {
@@ -161,19 +137,37 @@ ap_status_t ap_sendv(ap_socket_t *sock, const struct iovec *vec, ap_int32_t nvec
                 if (err == SOCEINTR)
                     continue;
 
-                return APR_OS2_STATUS(err);
+                return APR_FROM_OS_ERROR(err);
             }
         }
 
-        rv = writev(sock->socketdes, tmpvec, nvec);
+        rv = writev(sock->socketdes, tmpvec, nv_tosend);
         err = rv < 0 ? sock_errno() : 0;
     } while (err == SOCEINTR || err == SOCEWOULDBLOCK);
 
     if (err) {
         *len = 0;
-        return APR_OS2_STATUS(err);
+        return APR_FROM_OS_ERROR(err);
     }
 
     *len = rv;
     return APR_SUCCESS;
 }
+
+
+
+APR_DECLARE(apr_status_t) apr_socket_wait(apr_socket_t *sock, apr_wait_type_t direction)
+{
+    int pollsocket = sock->socketdes;
+    int wait_rc = select(&pollsocket, direction == APR_WAIT_READ, 
+                         direction == APR_WAIT_WRITE, 0, sock->timeout / 1000);
+
+    if (wait_rc == 0) {
+        return APR_TIMEUP;
+    }
+    else if (wait_rc < 0) {
+        return APR_FROM_OS_ERROR(sock_errno());
+    }
+
+    return APR_SUCCESS;
+}
diff --git a/network_io/os2/sendrecv_udp.c b/network_io/os2/sendrecv_udp.c
new file mode 100644
index 00000000000..1aea02c2591
--- /dev/null
+++ b/network_io/os2/sendrecv_udp.c
@@ -0,0 +1,116 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_arch_networkio.h"
+#include "apr_errno.h"
+#include "apr_general.h"
+#include "apr_network_io.h"
+#include "apr_support.h"
+#include "apr_lib.h"
+#include <sys/time.h>
+
+static apr_status_t wait_socket_ready(apr_socket_t *sock, int readwrite)
+{
+    int pollsocket = sock->socketdes;
+    int wait_rc = select(&pollsocket, readwrite == 0, readwrite == 1, 0, sock->timeout / 1000);
+
+    if (wait_rc == 0) {
+        return APR_TIMEUP;
+    }
+    else if (wait_rc < 0) {
+        return APR_FROM_OS_ERROR(sock_errno());
+    }
+
+    return APR_SUCCESS;
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_socket_sendto(apr_socket_t *sock,
+                                            apr_sockaddr_t *where,
+                                            apr_int32_t flags, const char *buf,
+                                            apr_size_t *len)
+{
+    apr_ssize_t rv;
+    int serrno;
+
+    do {
+        rv = sendto(sock->socketdes, buf, (*len), flags, 
+                    (struct sockaddr*)&where->sa,
+                    where->salen);
+
+        if (rv == -1) {
+            serrno = sock_errno();
+
+            if (serrno == SOCEWOULDBLOCK && sock->timeout != 0) {
+                apr_status_t wait_status = wait_socket_ready(sock, 1);
+
+                if (wait_status != APR_SUCCESS) {
+                    *len = 0;
+                    return wait_status;
+                }
+            }
+            else if (serrno != SOCEINTR) {
+                *len = 0;
+                return APR_FROM_OS_ERROR(serrno);
+            }
+        }
+        else {
+            *len = rv;
+            return APR_SUCCESS;
+        }
+    } while (1);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_socket_recvfrom(apr_sockaddr_t *from,
+                                              apr_socket_t *sock,
+                                              apr_int32_t flags, char *buf,
+                                              apr_size_t *len)
+{
+    apr_ssize_t rv;
+    int serrno;
+
+    do {
+        from->salen = sizeof(from->sa);
+        rv = recvfrom(sock->socketdes, buf, (*len), flags,
+                      (struct sockaddr*)&from->sa,
+                      &from->salen);
+
+        if (rv == -1) {
+            serrno = sock_errno();
+
+            if (serrno == SOCEWOULDBLOCK && sock->timeout != 0) {
+                apr_status_t wait_status = wait_socket_ready(sock, 0);
+
+                if (wait_status != APR_SUCCESS) {
+                    *len = 0;
+                    return wait_status;
+                }
+            }
+            else if (serrno != SOCEINTR) {
+                *len = 0;
+                return APR_FROM_OS_ERROR(serrno);
+            }
+        }
+        else {
+            *len = rv;
+            apr_sockaddr_vars_set(from, from->sa.sin.sin_family, ntohs(from->sa.sin.sin_port));
+            return (rv == 0 && sock->type == SOCK_STREAM) ? APR_EOF : APR_SUCCESS;
+        }
+    } while (1);
+}
diff --git a/network_io/os2/socket_util.c b/network_io/os2/socket_util.c
new file mode 100644
index 00000000000..cdc1cea8940
--- /dev/null
+++ b/network_io/os2/socket_util.c
@@ -0,0 +1 @@
+#include "../unix/socket_util.c"
diff --git a/network_io/os2/sockets.c b/network_io/os2/sockets.c
index 737af928b10..89d987603bb 100644
--- a/network_io/os2/sockets.c
+++ b/network_io/os2/sockets.c
@@ -1,62 +1,26 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "networkio.h"
+#include "apr_arch_networkio.h"
+#include "apr_arch_inherit.h"
 #include "apr_network_io.h"
 #include "apr_general.h"
 #include "apr_portable.h"
 #include "apr_lib.h"
+#include "apr_strings.h"
 #include <errno.h>
 #include <string.h>
 #include <sys/socket.h>
@@ -64,194 +28,295 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <netdb.h>
-#include "os2calls.h"
+#include "apr_arch_os2calls.h"
 
-static ap_status_t socket_cleanup(void *sock)
+static apr_status_t socket_cleanup(void *sock)
 {
-    ap_socket_t *thesocket = sock;
+    apr_socket_t *thesocket = sock;
+
+    if (thesocket->socketdes < 0) {
+        return APR_EINVALSOCK;
+    }
+
     if (soclose(thesocket->socketdes) == 0) {
         thesocket->socketdes = -1;
         return APR_SUCCESS;
     }
     else {
-        return APR_OS2_STATUS(sock_errno());
+        return APR_FROM_OS_ERROR(sock_errno());
     }
 }
 
-ap_status_t ap_create_tcp_socket(ap_socket_t **new, ap_pool_t *cont)
+static void set_socket_vars(apr_socket_t *sock, int family, int type, int protocol)
 {
-    (*new) = (ap_socket_t *)ap_palloc(cont, sizeof(ap_socket_t));
+    sock->type = type;
+    sock->protocol = protocol;
+    apr_sockaddr_vars_set(sock->local_addr, family, 0);
+    apr_sockaddr_vars_set(sock->remote_addr, family, 0);
+}
+
+static void alloc_socket(apr_socket_t **new, apr_pool_t *p)
+{
+    *new = (apr_socket_t *)apr_pcalloc(p, sizeof(apr_socket_t));
+    (*new)->pool = p;
+    (*new)->local_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->pool,
+                                                       sizeof(apr_sockaddr_t));
+    (*new)->local_addr->pool = p;
+
+    (*new)->remote_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->pool,
+                                                        sizeof(apr_sockaddr_t));
+    (*new)->remote_addr->pool = p;
+    (*new)->remote_addr_unknown = 1;
+
+    /* Create a pollset with room for one descriptor. */
+    /* ### check return codes */
+    (void) apr_pollset_create(&(*new)->pollset, 1, p, 0);
+}
+
+APR_DECLARE(apr_status_t) apr_socket_protocol_get(apr_socket_t *sock, int *protocol)
+{
+    *protocol = sock->protocol;
+    return APR_SUCCESS;
+}
 
-    if ((*new) == NULL) {
-        return APR_ENOMEM;
+APR_DECLARE(apr_status_t) apr_socket_create(apr_socket_t **new, int family, int type,
+                                            int protocol, apr_pool_t *cont)
+{
+    int downgrade = (family == AF_UNSPEC);
+    apr_pollfd_t pfd;
+    int oprotocol = protocol;
+
+    if (family == AF_UNSPEC) {
+#if APR_HAVE_IPV6
+        family = AF_INET6;
+#else
+        family = AF_INET;
+#endif
     }
-    (*new)->cntxt = cont; 
-    (*new)->local_addr = (struct sockaddr_in *)ap_palloc((*new)->cntxt,
-                         sizeof(struct sockaddr_in));
-    (*new)->remote_addr = (struct sockaddr_in *)ap_palloc((*new)->cntxt,
-                         sizeof(struct sockaddr_in));
-
-    if ((*new)->local_addr == NULL || (*new)->remote_addr == NULL) {
-        return APR_ENOMEM;
+
+    if (family == APR_UNIX) {
+        protocol = 0;
     }
- 
-    (*new)->socketdes = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
 
-    (*new)->local_addr->sin_family = AF_INET;
-    (*new)->remote_addr->sin_family = AF_INET;
+    alloc_socket(new, cont);
+
+    (*new)->socketdes = socket(family, type, protocol);
+#if APR_HAVE_IPV6
+    if ((*new)->socketdes < 0 && downgrade) {
+        family = AF_INET;
+        (*new)->socketdes = socket(family, type, protocol);
+    }
+#endif
 
-    (*new)->addr_len = sizeof(*(*new)->local_addr);
-    
     if ((*new)->socketdes < 0) {
-        return APR_OS2_STATUS(sock_errno());
+        return APR_FROM_OS_ERROR(sock_errno());
     }
+    set_socket_vars(*new, family, type, oprotocol);
+
     (*new)->timeout = -1;
     (*new)->nonblock = FALSE;
-    ap_register_cleanup((*new)->cntxt, (void *)(*new), 
-                        socket_cleanup, ap_null_cleanup);
+    apr_pool_cleanup_register((*new)->pool, (void *)(*new), 
+                        socket_cleanup, apr_pool_cleanup_null);
+
     return APR_SUCCESS;
 } 
 
-ap_status_t ap_shutdown(ap_socket_t *thesocket, ap_shutdown_how_e how)
+APR_DECLARE(apr_status_t) apr_socket_shutdown(apr_socket_t *thesocket, 
+                                              apr_shutdown_how_e how)
 {
     if (shutdown(thesocket->socketdes, how) == 0) {
         return APR_SUCCESS;
     }
     else {
-        return APR_OS2_STATUS(sock_errno());
+        return APR_FROM_OS_ERROR(sock_errno());
     }
 }
 
-ap_status_t ap_close_socket(ap_socket_t *thesocket)
+APR_DECLARE(apr_status_t) apr_socket_close(apr_socket_t *thesocket)
 {
-    ap_kill_cleanup(thesocket->cntxt, thesocket, socket_cleanup);
+    apr_pool_cleanup_kill(thesocket->pool, thesocket, socket_cleanup);
     return socket_cleanup(thesocket);
 }
 
-
-
-
-ap_status_t ap_bind(ap_socket_t *sock)
+APR_DECLARE(apr_status_t) apr_socket_bind(apr_socket_t *sock,
+                                          apr_sockaddr_t *sa)
 {
-    if (bind(sock->socketdes, (struct sockaddr *)sock->local_addr, sock->addr_len) == -1)
-        return APR_OS2_STATUS(sock_errno());
-    else
+    if (bind(sock->socketdes, 
+             (struct sockaddr *)&sa->sa,
+             sa->salen) == -1)
+        return APR_FROM_OS_ERROR(sock_errno());
+    else {
+        sock->local_addr = sa;
+        /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */
+        if (sock->local_addr->sa.sin.sin_port == 0) { /* no need for ntohs() when comparing w/ 0 */
+            sock->local_port_unknown = 1; /* kernel got us an ephemeral port */
+        }
         return APR_SUCCESS;
+    }
 }
 
-ap_status_t ap_listen(ap_socket_t *sock, ap_int32_t backlog)
+APR_DECLARE(apr_status_t) apr_socket_listen(apr_socket_t *sock, 
+                                            apr_int32_t backlog)
 {
     if (listen(sock->socketdes, backlog) == -1)
-        return APR_OS2_STATUS(sock_errno());
+        return APR_FROM_OS_ERROR(sock_errno());
     else
         return APR_SUCCESS;
 }
 
-ap_status_t ap_accept(ap_socket_t **new, const ap_socket_t *sock, ap_pool_t *connection_context)
+APR_DECLARE(apr_status_t) apr_socket_accept(apr_socket_t **new, 
+                                            apr_socket_t *sock,
+                                            apr_pool_t *connection_context)
 {
-    (*new) = (ap_socket_t *)ap_palloc(connection_context, 
-                            sizeof(ap_socket_t));
-
-    (*new)->cntxt = connection_context;
-    (*new)->remote_addr = (struct sockaddr_in *)ap_palloc((*new)->cntxt,
-                          sizeof(struct sockaddr_in));
-    (*new)->local_addr = sock->local_addr;
-    (*new)->addr_len = sizeof(struct sockaddr_in);
+    alloc_socket(new, connection_context);
+    set_socket_vars(*new, sock->local_addr->sa.sin.sin_family, SOCK_STREAM, sock->protocol);
+
     (*new)->timeout = -1;
     (*new)->nonblock = FALSE;
 
-    (*new)->socketdes = accept(sock->socketdes, (struct sockaddr *)(*new)->remote_addr,
-                        &(*new)->addr_len);
+    (*new)->socketdes = accept(sock->socketdes, 
+                               (struct sockaddr *)&(*new)->remote_addr->sa,
+                               &(*new)->remote_addr->salen);
 
     if ((*new)->socketdes < 0) {
-        return APR_OS2_STATUS(sock_errno());
+        return APR_FROM_OS_ERROR(sock_errno());
     }
 
-    ap_register_cleanup((*new)->cntxt, (void *)(*new), 
-                        socket_cleanup, ap_null_cleanup);
+    *(*new)->local_addr = *sock->local_addr;
+    (*new)->local_addr->pool = connection_context;
+    (*new)->remote_addr->port = ntohs((*new)->remote_addr->sa.sin.sin_port);
+
+    /* fix up any pointers which are no longer valid */
+    if (sock->local_addr->sa.sin.sin_family == AF_INET) {
+        (*new)->local_addr->ipaddr_ptr = &(*new)->local_addr->sa.sin.sin_addr;
+    }
+
+    apr_pool_cleanup_register((*new)->pool, (void *)(*new), 
+                        socket_cleanup, apr_pool_cleanup_null);
     return APR_SUCCESS;
 }
 
-ap_status_t ap_connect(ap_socket_t *sock, char *hostname)
+APR_DECLARE(apr_status_t) apr_socket_connect(apr_socket_t *sock,
+                                             apr_sockaddr_t *sa)
 {
-    struct hostent *hp;
-
-    if (hostname != NULL) {
-        hp = gethostbyname(hostname);
-
-        if ((sock->socketdes < 0) || (!sock->remote_addr)) {
-            return APR_ENOTSOCK;
-        }
-        if (!hp)  {
-            if (h_errno == TRY_AGAIN) {
-                return EAGAIN;
-            }
-            return h_errno;
-        }
-    
-        memcpy((char *)&sock->remote_addr->sin_addr, hp->h_addr_list[0], hp->h_length);
-        sock->addr_len = sizeof(*sock->remote_addr);
-    }
-
-    if ((connect(sock->socketdes, (struct sockaddr *)sock->remote_addr, sock->addr_len) < 0) &&
+    if ((connect(sock->socketdes, (struct sockaddr *)&sa->sa.sin, 
+                 sa->salen) < 0) &&
         (sock_errno() != SOCEINPROGRESS)) {
-        return APR_OS2_STATUS(sock_errno());
+        return APR_FROM_OS_ERROR(sock_errno());
     }
     else {
-        int namelen = sizeof(*sock->local_addr);
-        getsockname(sock->socketdes, (struct sockaddr *)sock->local_addr, &namelen);
+        int namelen = sizeof(sock->local_addr->sa.sin);
+        getsockname(sock->socketdes, (struct sockaddr *)&sock->local_addr->sa.sin, 
+                    &namelen);
+        sock->remote_addr = sa;
         return APR_SUCCESS;
     }
 }
 
+APR_DECLARE(apr_status_t) apr_socket_type_get(apr_socket_t *sock, int *type)
+{
+    *type = sock->type;
+    return APR_SUCCESS;
+}
 
-
-ap_status_t ap_get_socketdata(void **data, char *key, ap_socket_t *socket)
+APR_DECLARE(apr_status_t) apr_socket_data_get(void **data, const char *key,
+                                     apr_socket_t *sock)
 {
-    if (socket != NULL) {
-        return ap_get_userdata(data, key, socket->cntxt);
-    }
-    else {
-        data = NULL;
-        return APR_ENOSOCKET;
+    sock_userdata_t *cur = sock->userdata;
+
+    *data = NULL;
+
+    while (cur) {
+        if (!strcmp(cur->key, key)) {
+            *data = cur->data;
+            break;
+        }
+        cur = cur->next;
     }
+
+    return APR_SUCCESS;
 }
 
 
 
-ap_status_t ap_set_socketdata(ap_socket_t *socket, void *data, char *key,
-                              ap_status_t (*cleanup) (void *))
+APR_DECLARE(apr_status_t) apr_socket_data_set(apr_socket_t *sock, void *data, const char *key,
+                                     apr_status_t (*cleanup) (void *))
 {
-    if (socket != NULL) {
-        return ap_set_userdata(data, key, cleanup, socket->cntxt);
-    }
-    else {
-        data = NULL;
-        return APR_ENOSOCKET;
+    sock_userdata_t *new = apr_palloc(sock->pool, sizeof(sock_userdata_t));
+
+    new->key = apr_pstrdup(sock->pool, key);
+    new->data = data;
+    new->next = sock->userdata;
+    sock->userdata = new;
+
+    if (cleanup) {
+        apr_pool_cleanup_register(sock->pool, data, cleanup, cleanup);
     }
+
+    return APR_SUCCESS;
 }
 
-ap_status_t ap_get_os_sock(ap_os_sock_t *thesock, ap_socket_t *sock)
+APR_DECLARE(apr_status_t) apr_os_sock_get(apr_os_sock_t *thesock, apr_socket_t *sock)
 {
-    if (sock == NULL) {
-        return APR_ENOSOCKET;
-    }
     *thesock = sock->socketdes;
     return APR_SUCCESS;
 }
 
+APR_DECLARE(apr_status_t) apr_os_sock_make(apr_socket_t **apr_sock, 
+                                           apr_os_sock_info_t *os_sock_info, 
+                                           apr_pool_t *cont)
+{
+    alloc_socket(apr_sock, cont);
+    set_socket_vars(*apr_sock, os_sock_info->family, os_sock_info->type, os_sock_info->protocol);
+    (*apr_sock)->timeout = -1;
+    (*apr_sock)->socketdes = *os_sock_info->os_sock;
+    if (os_sock_info->local) {
+        memcpy(&(*apr_sock)->local_addr->sa.sin, 
+               os_sock_info->local, 
+               (*apr_sock)->local_addr->salen);
+        /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */
+        (*apr_sock)->local_addr->port = ntohs((*apr_sock)->local_addr->sa.sin.sin_port);
+    }
+    else {
+        (*apr_sock)->local_port_unknown = (*apr_sock)->local_interface_unknown = 1;
+    }
+    if (os_sock_info->remote) {
+        memcpy(&(*apr_sock)->remote_addr->sa.sin, 
+               os_sock_info->remote,
+               (*apr_sock)->remote_addr->salen);
+        /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */
+        (*apr_sock)->remote_addr->port = ntohs((*apr_sock)->remote_addr->sa.sin.sin_port);
+    }
+    else {
+        (*apr_sock)->remote_addr_unknown = 1;
+    }
+        
+    apr_pool_cleanup_register((*apr_sock)->pool, (void *)(*apr_sock), 
+                        socket_cleanup, apr_pool_cleanup_null);
 
+    return APR_SUCCESS;
+}
 
-ap_status_t ap_put_os_sock(ap_socket_t **sock, ap_os_sock_t *thesock, ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_os_sock_put(apr_socket_t **sock, apr_os_sock_t *thesock, apr_pool_t *cont)
 {
     if (cont == NULL) {
         return APR_ENOPOOL;
     }
     if ((*sock) == NULL) {
-        (*sock) = (ap_socket_t *)ap_palloc(cont, sizeof(ap_socket_t));
-        (*sock)->cntxt = cont;
+        alloc_socket(sock, cont);
+        set_socket_vars(*sock, AF_INET, SOCK_STREAM, 0);
+        (*sock)->timeout = -1;
     }
+
+    (*sock)->local_port_unknown = (*sock)->local_interface_unknown = 1;
+    (*sock)->remote_addr_unknown = 1;
     (*sock)->socketdes = *thesock;
     return APR_SUCCESS;
 }
 
+APR_POOL_IMPLEMENT_ACCESSOR(socket);
+
+APR_IMPLEMENT_INHERIT_SET(socket, inherit, pool, socket_cleanup)
+
+APR_IMPLEMENT_INHERIT_UNSET(socket, inherit, pool, socket_cleanup)
+
diff --git a/network_io/os2/sockopt.c b/network_io/os2/sockopt.c
index 1da0c6bf6df..2ada4fc4760 100644
--- a/network_io/os2/sockopt.c
+++ b/network_io/os2/sockopt.c
@@ -1,61 +1,24 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "networkio.h"
+#include "apr_arch_networkio.h"
 #include "apr_network_io.h"
 #include "apr_general.h"
 #include "apr_lib.h"
+#include "apr_strings.h"
 #include <errno.h>
 #include <string.h>
 #include <sys/socket.h>
@@ -66,7 +29,16 @@
 #include <sys/so_ioctl.h>
 
 
-ap_status_t ap_setsocketopt(ap_socket_t *sock, ap_int32_t opt, ap_int32_t on)
+APR_DECLARE(apr_status_t) apr_socket_timeout_set(apr_socket_t *sock, 
+                                                 apr_interval_time_t t)
+{
+    sock->timeout = t;
+    return APR_SUCCESS;
+}
+
+
+APR_DECLARE(apr_status_t) apr_socket_opt_set(apr_socket_t *sock, 
+                                             apr_int32_t opt, apr_int32_t on)
 {
     int one;
     struct linger li;
@@ -78,72 +50,95 @@ ap_status_t ap_setsocketopt(ap_socket_t *sock, ap_int32_t opt, ap_int32_t on)
 
     if (opt & APR_SO_KEEPALIVE) {
         if (setsockopt(sock->socketdes, SOL_SOCKET, SO_KEEPALIVE, (void *)&one, sizeof(int)) == -1) {
-            return APR_OS2_STATUS(sock_errno());
+            return APR_FROM_OS_ERROR(sock_errno());
         }
     }
     if (opt & APR_SO_DEBUG) {
         if (setsockopt(sock->socketdes, SOL_SOCKET, SO_DEBUG, (void *)&one, sizeof(int)) == -1) {
-            return APR_OS2_STATUS(sock_errno());
+            return APR_FROM_OS_ERROR(sock_errno());
+        }
+    }
+    if (opt & APR_SO_BROADCAST) {
+        if (setsockopt(sock->socketdes, SOL_SOCKET, SO_BROADCAST, (void *)&one, sizeof(int)) == -1) {
+            return APR_FROM_OS_ERROR(sock_errno());
         }
     }
     if (opt & APR_SO_REUSEADDR) {
         if (setsockopt(sock->socketdes, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(int)) == -1) {
-            return APR_OS2_STATUS(sock_errno());
+            return APR_FROM_OS_ERROR(sock_errno());
         }
     }
     if (opt & APR_SO_SNDBUF) {
         if (setsockopt(sock->socketdes, SOL_SOCKET, SO_SNDBUF, (void *)&on, sizeof(int)) == -1) {
-            return APR_OS2_STATUS(sock_errno());
+            return APR_FROM_OS_ERROR(sock_errno());
         }
     }
     if (opt & APR_SO_NONBLOCK) {
         if (ioctl(sock->socketdes, FIONBIO, (caddr_t)&one, sizeof(one)) == -1) {
-            return APR_OS2_STATUS(sock_errno());
+            return APR_FROM_OS_ERROR(sock_errno());
         } else {
             sock->nonblock = one;
         }
     }
     if (opt & APR_SO_LINGER) {
         li.l_onoff = on;
-        li.l_linger = MAX_SECS_TO_LINGER;
+        li.l_linger = APR_MAX_SECS_TO_LINGER;
         if (setsockopt(sock->socketdes, SOL_SOCKET, SO_LINGER, (char *) &li, sizeof(struct linger)) == -1) {
-            return APR_OS2_STATUS(sock_errno());
+            return APR_FROM_OS_ERROR(sock_errno());
         }
     }
-    if (opt & APR_SO_TIMEOUT) {
-        sock->timeout = on;
+    if (opt & APR_TCP_NODELAY) {
+        if (setsockopt(sock->socketdes, IPPROTO_TCP, TCP_NODELAY, (void *)&on, sizeof(int)) == -1) {
+            return APR_FROM_OS_ERROR(sock_errno());
+        }
     }
     return APR_SUCCESS;
 }
 
 
-
-ap_status_t ap_gethostname(char *buf, ap_int32_t len, ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_socket_timeout_get(apr_socket_t *sock, 
+                                                 apr_interval_time_t *t)
 {
-    if (gethostname(buf, len) == -1)
-        return APR_OS2_STATUS(sock_errno());
-    else
-        return APR_SUCCESS;
+    *t = sock->timeout;
+    return APR_SUCCESS;
 }
 
 
+APR_DECLARE(apr_status_t) apr_socket_opt_get(apr_socket_t *sock, 
+                                             apr_int32_t opt, apr_int32_t *on)
+{
+    switch(opt) {
+    default:
+        return APR_EINVAL;
+    }
+    return APR_SUCCESS;
+}
+
 
-ap_status_t ap_get_remote_hostname(char **name, ap_socket_t *sock)
+APR_DECLARE(apr_status_t) apr_socket_atmark(apr_socket_t *sock, int *atmark)
 {
-    struct hostent *hptr;
-
-    hptr = gethostbyaddr((char *)&(sock->remote_addr->sin_addr),
-                         sizeof(struct in_addr), AF_INET);
-    if (hptr != NULL) {
-        *name = ap_pstrdup(sock->cntxt, hptr->h_name);
-        if (*name) {
-            return APR_SUCCESS;
-        }
-        return APR_ENOMEM;
+    int oobmark;
+
+    if (ioctl(sock->socketdes, SIOCATMARK, (void*)&oobmark, sizeof(oobmark)) < 0) {
+        return APR_FROM_OS_ERROR(sock_errno());
     }
 
-    /* XXX - Is this threadsafe? */
-    return h_errno;
+    *atmark = (oobmark != 0);
+
+    return APR_SUCCESS;
 }
 
 
+APR_DECLARE(apr_status_t) apr_gethostname(char *buf, apr_int32_t len, 
+                                          apr_pool_t *cont)
+{
+    if (gethostname(buf, len) == -1) {
+        buf[0] = '\0';
+        return APR_FROM_OS_ERROR(sock_errno());
+    }
+    else if (!memchr(buf, '\0', len)) { /* buffer too small */
+        buf[0] = '\0';
+        return APR_ENAMETOOLONG;
+    }
+    return APR_SUCCESS;
+}
diff --git a/network_io/unix/.cvsignore b/network_io/unix/.cvsignore
deleted file mode 100644
index f3c7a7c5da6..00000000000
--- a/network_io/unix/.cvsignore
+++ /dev/null
@@ -1 +0,0 @@
-Makefile
diff --git a/network_io/unix/Makefile.in b/network_io/unix/Makefile.in
deleted file mode 100644
index ee0bc8bf6f4..00000000000
--- a/network_io/unix/Makefile.in
+++ /dev/null
@@ -1,82 +0,0 @@
-#CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
-#LIBS=$(EXTRA_LIBS) $(LIBS1)
-#INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
-#LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
-
-RM=@RM@
-CC=@CC@
-RANLIB=@RANLIB@
-CFLAGS=@CFLAGS@ @OPTIM@
-LIBS=@LIBS@
-LDFLAGS=@LDFLAGS@ $(LIBS)
-INCDIR=../../include
-INCLUDES=-I$(INCDIR) -I.
-
-LIB=libnetwork.a
-
-OBJS=poll.o \
-	sendrecv.o \
-	sockets.o \
-	sockopt.o \
-	sockaddr.o
-
-.c.o:
-	$(CC) $(CFLAGS) -c $(INCLUDES) $<
-
-all: $(OBJS)
-
-clean:
-	$(RM) -f *.o *.a *.so
-
-distclean: clean
-	-$(RM) -f Makefile
-
-$(OBJS): Makefile
-
-#$(LIB): $(OBJS)
-#	$(RM) -f $@
-#	$(AR) cr $@ $(OBJS)
-#	$(RANLIB) $@
-
-#
-# We really don't expect end users to use this rule.  It works only with
-# gcc, and rebuilds Makefile.tmpl.  You have to re-run Configure after
-# using it.
-#
-depend:
-	cp Makefile.in Makefile.in.bak \
-	    && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.in > Makefile.new \
-	    && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \
-	    && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
-	           -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
-		> Makefile.in \
-	    && rm Makefile.new
-
-# DO NOT REMOVE
-poll.o: poll.c networkio.h $(INCDIR)/apr_private.h \
- $(INCDIR)/apr_network_io.h $(INCDIR)/apr_general.h \
- $(INCDIR)/apr.h $(INCDIR)/apr_errno.h \
- $(INCDIR)/apr_file_io.h $(INCDIR)/apr_time.h \
- $(INCDIR)/apr_lib.h $(INCDIR)/apr_thread_proc.h
-sendrecv.o: sendrecv.c networkio.h $(INCDIR)/apr_private.h \
- $(INCDIR)/apr_network_io.h $(INCDIR)/apr_general.h \
- $(INCDIR)/apr.h $(INCDIR)/apr_errno.h \
- $(INCDIR)/apr_file_io.h $(INCDIR)/apr_time.h \
- $(INCDIR)/apr_lib.h $(INCDIR)/apr_thread_proc.h \
- ../../file_io/unix/fileio.h
-sockaddr.o: sockaddr.c networkio.h $(INCDIR)/apr_private.h \
- $(INCDIR)/apr_network_io.h $(INCDIR)/apr_general.h \
- $(INCDIR)/apr.h $(INCDIR)/apr_errno.h \
- $(INCDIR)/apr_file_io.h $(INCDIR)/apr_time.h \
- $(INCDIR)/apr_lib.h $(INCDIR)/apr_thread_proc.h
-sockets.o: sockets.c networkio.h $(INCDIR)/apr_private.h \
- $(INCDIR)/apr_network_io.h $(INCDIR)/apr_general.h \
- $(INCDIR)/apr.h $(INCDIR)/apr_errno.h \
- $(INCDIR)/apr_file_io.h $(INCDIR)/apr_time.h \
- $(INCDIR)/apr_lib.h $(INCDIR)/apr_thread_proc.h \
- $(INCDIR)/apr_portable.h $(INCDIR)/apr_lock.h
-sockopt.o: sockopt.c networkio.h $(INCDIR)/apr_private.h \
- $(INCDIR)/apr_network_io.h $(INCDIR)/apr_general.h \
- $(INCDIR)/apr.h $(INCDIR)/apr_errno.h \
- $(INCDIR)/apr_file_io.h $(INCDIR)/apr_time.h \
- $(INCDIR)/apr_lib.h $(INCDIR)/apr_thread_proc.h
diff --git a/network_io/unix/inet_ntop.c b/network_io/unix/inet_ntop.c
new file mode 100644
index 00000000000..78dd3baae53
--- /dev/null
+++ b/network_io/unix/inet_ntop.c
@@ -0,0 +1,243 @@
+/* Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#include "apr_private.h"
+#include "apr_arch_networkio.h"
+#include "apr_strings.h"
+
+#if APR_HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#if APR_HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#if APR_HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#if APR_HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#include <string.h>
+#if APR_HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <stdio.h>
+
+#ifndef IN6ADDRSZ
+#define IN6ADDRSZ   16
+#endif
+
+#ifndef INT16SZ
+#define INT16SZ sizeof(apr_int16_t)
+#endif
+
+#ifndef __P
+#define __P(x) x
+#endif
+
+#if !defined(EAFNOSUPPORT) && defined(WSAEAFNOSUPPORT)
+#define EAFNOSUPPORT WSAEAFNOSUPPORT
+#endif
+
+/*
+ * WARNING: Don't even consider trying to compile this on a system where
+ * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
+ */
+
+static const char *inet_ntop4 __P((const unsigned char *src, char *dst, apr_size_t size));
+#if APR_HAVE_IPV6
+static const char *inet_ntop6 __P((const unsigned char *src, char *dst, apr_size_t size));
+#endif
+
+/* char *
+ * inet_ntop(af, src, dst, size)
+ *	convert a network format address to presentation format.
+ * return:
+ *	pointer to presentation format address (`dst'), or NULL (see errno).
+ * author:
+ *	Paul Vixie, 1996.
+ */
+const char *
+apr_inet_ntop(int af, const void *src, char *dst, apr_size_t size)
+{
+	switch (af) {
+	case AF_INET:
+		return (inet_ntop4(src, dst, size));
+#if APR_HAVE_IPV6
+	case AF_INET6:
+		return (inet_ntop6(src, dst, size));
+#endif
+	default:
+		errno = EAFNOSUPPORT;
+		return (NULL);
+	}
+	/* NOTREACHED */
+}
+
+/* const char *
+ * inet_ntop4(src, dst, size)
+ *	format an IPv4 address, more or less like inet_ntoa()
+ * return:
+ *	`dst' (as a const)
+ * notes:
+ *	(1) uses no statics
+ *	(2) takes a u_char* not an in_addr as input
+ * author:
+ *	Paul Vixie, 1996.
+ */
+static const char *
+inet_ntop4(const unsigned char *src, char *dst, apr_size_t size)
+{
+	const apr_size_t MIN_SIZE = 16; /* space for 255.255.255.255\0 */
+	int n = 0;
+	char *next = dst;
+
+	if (size < MIN_SIZE) {
+	    errno = ENOSPC;
+	    return NULL;
+	}
+	do {
+	    unsigned char u = *src++;
+	    if (u > 99) {
+		*next++ = '0' + u/100;
+		u %= 100;
+		*next++ = '0' + u/10;
+		u %= 10;
+	    }
+	    else if (u > 9) {
+		*next++ = '0' + u/10;
+		u %= 10;
+	    }
+	    *next++ = '0' + u;
+	    *next++ = '.';
+	    n++;
+	} while (n < 4);
+	*--next = 0;
+	return dst;
+}
+
+#if APR_HAVE_IPV6
+/* const char *
+ * inet_ntop6(src, dst, size)
+ *	convert IPv6 binary address into presentation (printable) format
+ * author:
+ *	Paul Vixie, 1996.
+ */
+static const char *
+inet_ntop6(const unsigned char *src, char *dst, apr_size_t size)
+{
+    /*
+     * Note that int32_t and int16_t need only be "at least" large enough
+     * to contain a value of the specified size.  On some systems, like
+     * Crays, there is no such thing as an integer variable with 16 bits.
+     * Keep this in mind if you think this function should have been coded
+     * to use pointer overlays.  All the world's not a VAX.
+     */
+    char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
+    struct { int base, len; } best = {-1, 0}, cur = {-1, 0};
+    unsigned int words[IN6ADDRSZ / INT16SZ];
+    int i;
+    const unsigned char *next_src, *src_end;
+    unsigned int *next_dest;
+
+    /*
+     * Preprocess:
+     *	Copy the input (bytewise) array into a wordwise array.
+     *	Find the longest run of 0x00's in src[] for :: shorthanding.
+     */
+    next_src = src;
+    src_end = src + IN6ADDRSZ;
+    next_dest = words;
+    i = 0;
+    do {
+        unsigned int next_word = (unsigned int)*next_src++;
+        next_word <<= 8;
+        next_word |= (unsigned int)*next_src++;
+        *next_dest++ = next_word;
+
+        if (next_word == 0) {
+            if (cur.base == -1) {
+                cur.base = i;
+                cur.len = 1;
+            }
+            else {
+                cur.len++;
+            }
+        } else {
+            if (cur.base != -1) {
+                if (best.base == -1 || cur.len > best.len) {
+                    best = cur;
+                }
+                cur.base = -1;
+            }
+        }
+
+        i++;
+    } while (next_src < src_end);
+
+    if (cur.base != -1) {
+        if (best.base == -1 || cur.len > best.len) {
+            best = cur;
+        }
+    }
+    if (best.base != -1 && best.len < 2) {
+        best.base = -1;
+    }
+
+    /*
+     * Format the result.
+     */
+    tp = tmp;
+    for (i = 0; i < (IN6ADDRSZ / INT16SZ);) {
+        /* Are we inside the best run of 0x00's? */
+        if (i == best.base) {
+            *tp++ = ':';
+            i += best.len;
+            continue;
+        }
+        /* Are we following an initial run of 0x00s or any real hex? */
+        if (i != 0) {
+            *tp++ = ':';
+        }
+        /* Is this address an encapsulated IPv4? */
+        if (i == 6 && best.base == 0 &&
+            (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
+            if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp))) {
+                return (NULL);
+            }
+            tp += strlen(tp);
+            break;
+        }
+        tp += apr_snprintf(tp, sizeof tmp - (tp - tmp), "%x", words[i]);
+        i++;
+    }
+    /* Was it a trailing run of 0x00's? */
+    if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) {
+        *tp++ = ':';
+    }
+    *tp++ = '\0';
+
+    /*
+     * Check for overflow, copy, and we're done.
+     */
+    if ((apr_size_t)(tp - tmp) > size) {
+        errno = ENOSPC;
+        return (NULL);
+    }
+    strcpy(dst, tmp);
+    return (dst);
+}
+#endif
diff --git a/network_io/unix/inet_pton.c b/network_io/unix/inet_pton.c
new file mode 100644
index 00000000000..d41f74965ab
--- /dev/null
+++ b/network_io/unix/inet_pton.c
@@ -0,0 +1,240 @@
+/* Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#include "apr_private.h"
+#include "apr_arch_networkio.h"
+
+#if APR_HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#if APR_HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#if APR_HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#if APR_HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#include <string.h>
+#if APR_HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#ifndef IN6ADDRSZ
+#define IN6ADDRSZ   16
+#endif
+
+#ifndef INT16SZ
+#define INT16SZ sizeof(apr_int16_t)
+#endif
+
+#ifndef INADDRSZ
+#define INADDRSZ    4
+#endif
+
+#ifndef __P
+#define __P(x) x
+#endif
+
+#if !defined(EAFNOSUPPORT) && defined(WSAEAFNOSUPPORT)
+#define EAFNOSUPPORT WSAEAFNOSUPPORT
+#endif
+
+/*
+ * WARNING: Don't even consider trying to compile this on a system where
+ * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
+ */
+
+static int	inet_pton4 __P((const char *src, unsigned char *dst));
+#if APR_HAVE_IPV6
+static int	inet_pton6 __P((const char *src, unsigned char *dst));
+#endif
+
+/* int
+ * inet_pton(af, src, dst)
+ *	convert from presentation format (which usually means ASCII printable)
+ *	to network format (which is usually some kind of binary format).
+ * return:
+ *	1 if the address was valid for the specified address family
+ *	0 if the address wasn't valid (`dst' is untouched in this case)
+ *	-1 if some other error occurred (`dst' is untouched in this case, too)
+ * author:
+ *	Paul Vixie, 1996.
+ */
+int
+apr_inet_pton(int af, const char *src, void *dst)
+{
+	switch (af) {
+	case AF_INET:
+		return (inet_pton4(src, dst));
+#if APR_HAVE_IPV6
+	case AF_INET6:
+		return (inet_pton6(src, dst));
+#endif
+	default:
+		errno = EAFNOSUPPORT;
+		return (-1);
+	}
+	/* NOTREACHED */
+}
+
+/* int
+ * inet_pton4(src, dst)
+ *	like inet_aton() but without all the hexadecimal and shorthand.
+ * return:
+ *	1 if `src' is a valid dotted quad, else 0.
+ * notice:
+ *	does not touch `dst' unless it's returning 1.
+ * author:
+ *	Paul Vixie, 1996.
+ */
+static int
+inet_pton4(const char *src, unsigned char *dst)
+{
+    static const char digits[] = "0123456789";
+    int saw_digit, octets, ch;
+    unsigned char tmp[INADDRSZ], *tp;
+
+    saw_digit = 0;
+    octets = 0;
+    *(tp = tmp) = 0;
+    while ((ch = *src++) != '\0') {
+	const char *pch;
+
+	if ((pch = strchr(digits, ch)) != NULL) {
+	    unsigned int new = *tp * 10 + (unsigned int)(pch - digits);
+
+	    if (new > 255)
+		return (0);
+	    *tp = new;
+	    if (! saw_digit) {
+		if (++octets > 4)
+		    return (0);
+		saw_digit = 1;
+	    }
+	} else if (ch == '.' && saw_digit) {
+	    if (octets == 4)
+		return (0);
+	    *++tp = 0;
+	    saw_digit = 0;
+	} else
+		return (0);
+    }
+    if (octets < 4)
+	return (0);
+
+    memcpy(dst, tmp, INADDRSZ);
+    return (1);
+}
+
+#if APR_HAVE_IPV6
+/* int
+ * inet_pton6(src, dst)
+ *	convert presentation level address to network order binary form.
+ * return:
+ *	1 if `src' is a valid [RFC1884 2.2] address, else 0.
+ * notice:
+ *	(1) does not touch `dst' unless it's returning 1.
+ *	(2) :: in a full address is silently ignored.
+ * credit:
+ *	inspired by Mark Andrews.
+ * author:
+ *	Paul Vixie, 1996.
+ */
+static int
+inet_pton6(const char *src, unsigned char *dst)
+{
+	static const char xdigits_l[] = "0123456789abcdef",
+			  xdigits_u[] = "0123456789ABCDEF";
+	unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
+	const char *xdigits, *curtok;
+	int ch, saw_xdigit;
+	unsigned int val;
+
+	memset((tp = tmp), '\0', IN6ADDRSZ);
+	endp = tp + IN6ADDRSZ;
+	colonp = NULL;
+	/* Leading :: requires some special handling. */
+	if (*src == ':')
+		if (*++src != ':')
+			return (0);
+	curtok = src;
+	saw_xdigit = 0;
+	val = 0;
+	while ((ch = *src++) != '\0') {
+		const char *pch;
+
+		if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
+			pch = strchr((xdigits = xdigits_u), ch);
+		if (pch != NULL) {
+			val <<= 4;
+			val |= (pch - xdigits);
+			if (val > 0xffff)
+				return (0);
+			saw_xdigit = 1;
+			continue;
+		}
+		if (ch == ':') {
+			curtok = src;
+			if (!saw_xdigit) {
+				if (colonp)
+					return (0);
+				colonp = tp;
+				continue;
+			}
+			if (tp + INT16SZ > endp)
+				return (0);
+			*tp++ = (unsigned char) (val >> 8) & 0xff;
+			*tp++ = (unsigned char) val & 0xff;
+			saw_xdigit = 0;
+			val = 0;
+			continue;
+		}
+		if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
+		    inet_pton4(curtok, tp) > 0) {
+			tp += INADDRSZ;
+			saw_xdigit = 0;
+			break;	/* '\0' was seen by inet_pton4(). */
+		}
+		return (0);
+	}
+	if (saw_xdigit) {
+		if (tp + INT16SZ > endp)
+			return (0);
+		*tp++ = (unsigned char) (val >> 8) & 0xff;
+		*tp++ = (unsigned char) val & 0xff;
+	}
+	if (colonp != NULL) {
+		/*
+		 * Since some memmove()'s erroneously fail to handle
+		 * overlapping regions, we'll do the shift by hand.
+		 */
+		const apr_ssize_t n = tp - colonp;
+		apr_ssize_t i;
+
+		for (i = 1; i <= n; i++) {
+			endp[- i] = colonp[n - i];
+			colonp[n - i] = 0;
+		}
+		tp = endp;
+	}
+	if (tp != endp)
+		return (0);
+	memcpy(dst, tmp, IN6ADDRSZ);
+	return (1);
+}
+#endif
diff --git a/network_io/unix/multicast.c b/network_io/unix/multicast.c
new file mode 100644
index 00000000000..a8c85ce69ec
--- /dev/null
+++ b/network_io/unix/multicast.c
@@ -0,0 +1,316 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_arch_networkio.h"
+#include "apr_network_io.h"
+#include "apr_support.h"
+#include "apr_portable.h"
+#include "apr_arch_inherit.h"
+
+#ifdef HAVE_GETIFADDRS
+#include <net/if.h>
+#if APR_HAVE_IFADDRS_H
+#include <ifaddrs.h>
+#endif
+#endif
+
+#ifdef HAVE_STRUCT_IPMREQ
+static void fill_mip_v4(struct ip_mreq *mip, apr_sockaddr_t *mcast,
+                        apr_sockaddr_t *iface)
+{
+    mip->imr_multiaddr = mcast->sa.sin.sin_addr;
+    if (iface == NULL) {
+        mip->imr_interface.s_addr = INADDR_ANY;
+    }
+    else {
+        mip->imr_interface = iface->sa.sin.sin_addr;
+    }
+}
+
+/* This function is only interested in AF_INET6 sockets, so a noop
+ * "return 0" implementation for the !APR_HAVE_IPV6 build is
+ * sufficient. */
+static unsigned int find_if_index(const apr_sockaddr_t *iface)
+{
+    unsigned int index = 0;
+#if defined(HAVE_GETIFADDRS) && APR_HAVE_IFADDRS_H && APR_HAVE_IPV6 
+    struct ifaddrs *ifp, *ifs;
+
+    /**
+     * TODO: getifaddrs is only portable to *BSD and OS X. Using ioctl 
+     *       and SIOCGIFCONF is needed for Linux/Solaris support.
+     *       
+     *       There is a wrapper that takes the messy ioctl interface into 
+     *       getifaddrs. The license is acceptable, but, It is a fairly large 
+     *       chunk of code.
+     */
+    if (getifaddrs(&ifs) != 0) {
+        return 0;
+    }
+
+    for (ifp = ifs; ifp; ifp = ifp->ifa_next) {
+        if (ifp->ifa_addr != NULL && ifp->ifa_addr->sa_family == AF_INET6) {
+            if (memcmp(&iface->sa.sin6.sin6_addr,
+                       &((struct sockaddr_in6*)ifp->ifa_addr)->sin6_addr,
+                       sizeof(iface->sa.sin6.sin6_addr)) == 0) {
+                index = if_nametoindex(ifp->ifa_name);
+                break;
+            }
+        }
+    }
+
+    freeifaddrs(ifs);
+#endif
+    return index;
+}
+
+#if APR_HAVE_IPV6
+static void fill_mip_v6(struct ipv6_mreq *mip, const apr_sockaddr_t *mcast,
+                        const apr_sockaddr_t *iface)
+{
+    memcpy(&mip->ipv6mr_multiaddr, mcast->ipaddr_ptr,
+           sizeof(mip->ipv6mr_multiaddr));
+
+    if (iface == NULL) {
+        mip->ipv6mr_interface = 0;
+    }
+    else {
+        mip->ipv6mr_interface = find_if_index(iface);
+    }
+}
+
+#endif
+
+static int sock_is_ipv4(apr_socket_t *sock)
+{
+    if (sock->local_addr->family == APR_INET)
+        return 1;
+    return 0;
+}
+
+#if APR_HAVE_IPV6
+static int sock_is_ipv6(apr_socket_t *sock)
+{
+    if (sock->local_addr->family == APR_INET6)
+        return 1;
+    return 0;
+}
+#endif
+
+static apr_status_t do_mcast(int type, apr_socket_t *sock,
+                             apr_sockaddr_t *mcast, apr_sockaddr_t *iface,
+                             apr_sockaddr_t *source)
+{
+    struct ip_mreq mip4;
+    apr_status_t rv = APR_SUCCESS;
+#if APR_HAVE_IPV6
+    struct ipv6_mreq mip6;
+#endif
+#ifdef GROUP_FILTER_SIZE
+    struct group_source_req mip;
+    int ip_proto;
+#endif
+
+    if (source != NULL) {
+#ifdef GROUP_FILTER_SIZE
+        if (sock_is_ipv4(sock)) {
+            ip_proto = IPPROTO_IP;
+        } 
+#if APR_HAVE_IPV6
+        else if (sock_is_ipv6(sock)) {
+            ip_proto = IPPROTO_IPV6;
+        }
+#endif
+        else {
+            return APR_ENOTIMPL;
+        }
+
+        if (type == IP_ADD_MEMBERSHIP)
+            type = MCAST_JOIN_SOURCE_GROUP;
+        else if (type == IP_DROP_MEMBERSHIP)
+            type = MCAST_LEAVE_SOURCE_GROUP;
+        else
+            return APR_ENOTIMPL;
+
+        mip.gsr_interface = find_if_index(iface);
+        memcpy(&mip.gsr_group, mcast->ipaddr_ptr, sizeof(mip.gsr_group));
+        memcpy(&mip.gsr_source, source->ipaddr_ptr, sizeof(mip.gsr_source));
+
+        if (setsockopt(sock->socketdes, ip_proto, type, (const void *) &mip,
+                       sizeof(mip)) == -1) {
+            rv = errno;
+        }
+#else
+        /* We do not support Source-Specific Multicast. */
+        return APR_ENOTIMPL;
+#endif
+    }
+    else {
+        if (sock_is_ipv4(sock)) {
+
+            fill_mip_v4(&mip4, mcast, iface);
+
+            if (setsockopt(sock->socketdes, IPPROTO_IP, type,
+                           (const void *) &mip4, sizeof(mip4)) == -1) {
+                rv = errno;
+            }
+        }
+#if APR_HAVE_IPV6 && defined(IPV6_JOIN_GROUP) && defined(IPV6_LEAVE_GROUP)
+        else if (sock_is_ipv6(sock)) {
+            if (type == IP_ADD_MEMBERSHIP) {
+                type = IPV6_JOIN_GROUP;
+            }
+            else if (type == IP_DROP_MEMBERSHIP) {
+                type = IPV6_LEAVE_GROUP;
+            }
+            else {
+                return APR_ENOTIMPL;
+            }
+
+            fill_mip_v6(&mip6, mcast, iface);
+
+            if (setsockopt(sock->socketdes, IPPROTO_IPV6, type,
+                           (const void *) &mip6, sizeof(mip6)) == -1) {
+                rv = errno;
+            }
+        }
+#endif
+        else {
+            rv = APR_ENOTIMPL;
+        }
+    }
+    return rv;
+}
+
+/* Set the IP_MULTICAST_TTL or IP_MULTICAST_LOOP option, or IPv6
+ * equivalents, for the socket, to the given value.  Note that this
+ * function *only works* for those particular option types. */
+static apr_status_t do_mcast_opt(int type, apr_socket_t *sock,
+                                 apr_byte_t value)
+{
+    apr_status_t rv = APR_SUCCESS;
+
+    if (sock_is_ipv4(sock)) {
+        /* For the IP_MULTICAST_* options, this must be a (char *)
+         * pointer. */
+        if (setsockopt(sock->socketdes, IPPROTO_IP, type,
+                       (const void *) &value, sizeof(value)) == -1) {
+            rv = errno;
+        }
+    }
+#if APR_HAVE_IPV6
+    else if (sock_is_ipv6(sock)) {
+        /* For the IPV6_* options, an (int *) pointer must be used. */
+        int ivalue = value;
+
+        if (type == IP_MULTICAST_TTL) {
+            type = IPV6_MULTICAST_HOPS;
+        }
+        else if (type == IP_MULTICAST_LOOP) {
+            type = IPV6_MULTICAST_LOOP;
+        }
+        else {
+            return APR_ENOTIMPL;
+        }
+
+        if (setsockopt(sock->socketdes, IPPROTO_IPV6, type,
+                       (const void *) &ivalue, sizeof(ivalue)) == -1) {
+            rv = errno;
+        }
+    }
+#endif
+    else {
+        rv = APR_ENOTIMPL;
+    }
+
+    return rv;
+}
+#endif
+
+APR_DECLARE(apr_status_t) apr_mcast_join(apr_socket_t *sock,
+                                         apr_sockaddr_t *join,
+                                         apr_sockaddr_t *iface,
+                                         apr_sockaddr_t *source)
+{
+#if defined(IP_ADD_MEMBERSHIP) && defined(HAVE_STRUCT_IPMREQ)
+    return do_mcast(IP_ADD_MEMBERSHIP, sock, join, iface, source);
+#else
+    return APR_ENOTIMPL;
+#endif
+}
+
+APR_DECLARE(apr_status_t) apr_mcast_leave(apr_socket_t *sock,
+                                          apr_sockaddr_t *addr,
+                                          apr_sockaddr_t *iface,
+                                          apr_sockaddr_t *source)
+{
+#if defined(IP_DROP_MEMBERSHIP) && defined(HAVE_STRUCT_IPMREQ)
+    return do_mcast(IP_DROP_MEMBERSHIP, sock, addr, iface, source);
+#else
+    return APR_ENOTIMPL;
+#endif
+}
+
+APR_DECLARE(apr_status_t) apr_mcast_hops(apr_socket_t *sock, apr_byte_t ttl)
+{
+#if defined(IP_MULTICAST_TTL) && defined(HAVE_STRUCT_IPMREQ)
+    return do_mcast_opt(IP_MULTICAST_TTL, sock, ttl);
+#else
+    return APR_ENOTIMPL;
+#endif
+}
+
+APR_DECLARE(apr_status_t) apr_mcast_loopback(apr_socket_t *sock,
+                                             apr_byte_t opt)
+{
+#if defined(IP_MULTICAST_LOOP) && defined(HAVE_STRUCT_IPMREQ)
+    return do_mcast_opt(IP_MULTICAST_LOOP, sock, opt);
+#else
+    return APR_ENOTIMPL;
+#endif
+}
+
+APR_DECLARE(apr_status_t) apr_mcast_interface(apr_socket_t *sock,
+                                              apr_sockaddr_t *iface)
+{
+#if defined(IP_MULTICAST_IF) && defined(HAVE_STRUCT_IPMREQ)
+    apr_status_t rv = APR_SUCCESS;
+
+    if (sock_is_ipv4(sock)) {
+        if (setsockopt(sock->socketdes, IPPROTO_IP, IP_MULTICAST_IF,
+                       (const void *) &iface->sa.sin.sin_addr,
+                       sizeof(iface->sa.sin.sin_addr)) == -1) {
+            rv = errno;
+        }
+    }
+#if APR_HAVE_IPV6
+    else if (sock_is_ipv6(sock)) {
+        unsigned int idx = find_if_index(iface);
+        if (setsockopt(sock->socketdes, IPPROTO_IPV6, IPV6_MULTICAST_IF,
+                       (const void *) &idx, sizeof(idx)) == -1) {
+            rv = errno;
+        }
+    }
+#endif
+    else {
+        rv = APR_ENOTIMPL;
+    }
+    return rv;
+#else
+    return APR_ENOTIMPL;
+#endif
+}
diff --git a/network_io/unix/networkio.h b/network_io/unix/networkio.h
deleted file mode 100644
index 9880b04318d..00000000000
--- a/network_io/unix/networkio.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef NETWORK_IO_H
-#define NETWORK_IO_H
-
-#include "apr_private.h"
-#include "apr_network_io.h"
-#include "apr_errno.h"
-#include "apr_general.h"
-#include "apr_lib.h"
-
-/* System headers the network I/O library needs */
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#if HAVE_SYS_UIO_H
-#include <sys/uio.h>
-#endif
-#if HAVE_POLL_H
-#include <poll.h>
-#endif
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#if HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_STRING_H
-#include <string.h>
-#endif
-#if HAVE_NETINET_TCP_H
-#include <netinet/tcp.h>
-#endif
-#if HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-#if HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-#if HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#if HAVE_NETDB_H
-#include <netdb.h>
-#endif
-#if HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#if HAVE_SYS_SENDFILE_H
-#include <sys/sendfile.h>
-#endif
-/* End System Headers */
-
-struct ap_socket_t {
-    ap_pool_t *cntxt;
-    int socketdes;
-    struct sockaddr_in *local_addr;
-    struct sockaddr_in *remote_addr;
-    socklen_t addr_len;
-    ap_interval_time_t timeout; 
-#ifndef HAVE_POLL
-    int connected;
-#endif
-};
-
-struct ap_pollfd_t {
-    ap_pool_t *cntxt;
-#ifdef HAVE_POLL
-    struct pollfd *pollset;
-    int num;
-    int curpos;
-#else
-    fd_set *read;
-    fd_set *write;
-    fd_set *except;
-    int highsock;
-#endif
-    ap_int16_t *events;
-    ap_int16_t *revents;
-
-};
-
-#endif  /* ! NETWORK_IO_H */
-
diff --git a/network_io/unix/poll.c b/network_io/unix/poll.c
deleted file mode 100644
index df1cfba97ce..00000000000
--- a/network_io/unix/poll.c
+++ /dev/null
@@ -1,381 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "networkio.h"
-
-#ifdef HAVE_POLL    /* We can just use poll to do our socket polling. */
-
-ap_status_t ap_setup_poll(ap_pollfd_t **new, ap_int32_t num, ap_pool_t *cont)
-{
-    (*new) = (ap_pollfd_t *)ap_palloc(cont, sizeof(ap_pollfd_t));
-    if ((*new) == NULL) {
-        return APR_ENOMEM;
-    }
-    (*new)->pollset = (struct pollfd *)ap_palloc(cont, 
-                                         sizeof(struct pollfd) * num);
-
-    if ((*new)->pollset == NULL) {
-        return APR_ENOMEM;
-    }
-    (*new)->num = num;
-    (*new)->cntxt = cont;
-    (*new)->curpos = 0;
-    return APR_SUCCESS;
-}
-
-static ap_int16_t get_event(ap_int16_t event)
-{
-    ap_int16_t rv = 0;
-
-    if (event & APR_POLLIN)
-        rv |= POLLIN;        
-    if (event & APR_POLLPRI)
-        rv |= POLLPRI;        
-    if (event & APR_POLLOUT)
-        rv |= POLLOUT;       
-    if (event & APR_POLLERR)
-        rv |= POLLERR;        
-    if (event & APR_POLLHUP)
-        rv |= POLLHUP;        
-    if (event & APR_POLLNVAL)
-        rv |= POLLNVAL;        
-
-    return rv;
-}
-
-static ap_int16_t get_revent(ap_int16_t event)
-{
-    ap_int16_t rv = 0;
-
-    if (event & POLLIN)
-        rv |= APR_POLLIN;
-    if (event & POLLPRI)
-        rv |= APR_POLLPRI;
-    if (event & POLLOUT)
-        rv |= APR_POLLOUT;
-    if (event & POLLERR)
-        rv |= APR_POLLERR;
-    if (event & POLLHUP)
-        rv |= APR_POLLHUP;
-    if (event & POLLNVAL)
-        rv |= APR_POLLNVAL;
-
-    return rv;
-}        
-
-ap_status_t ap_add_poll_socket(ap_pollfd_t *aprset, 
-			       ap_socket_t *sock, ap_int16_t event)
-{
-    int i = 0;
-    
-    while (i < aprset->curpos && aprset->pollset[i].fd != sock->socketdes) {
-        i++;
-    }
-    if (i >= aprset->curpos) {
-        if(aprset->curpos == aprset->num) {
-            return APR_ENOMEM;
-        }
-        aprset->curpos++;
-    } 
-    aprset->pollset[i].fd = sock->socketdes;
-    aprset->pollset[i].events = get_event(event);
-
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_poll(ap_pollfd_t *aprset, ap_int32_t *nsds, 
-		    ap_interval_time_t timeout)
-{
-    int rv;
-
-    if (timeout > 0) {
-        timeout /= 1000; /* convert microseconds to milliseconds */
-    }
-
-    rv = poll(aprset->pollset, aprset->curpos, timeout);
-    (*nsds) = rv;
-    
-    if ((*nsds) < 0) {
-        return errno;
-    }
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_get_revents(ap_int16_t *event, ap_socket_t *sock, ap_pollfd_t *aprset)
-{
-    int i = 0;
-    
-    while (i < aprset->curpos && aprset->pollset[i].fd != sock->socketdes) {
-        i++;
-    }
-    if (i >= aprset->curpos) {
-        return APR_EINVALSOCK;
-    } 
-    (*event) = get_revent(aprset->pollset[i].revents);
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_mask_poll_socket(ap_pollfd_t *aprset, 
-                                  ap_socket_t *sock, ap_int16_t events)
-{
-    ap_int16_t newevents;
-    int i = 0;
-    
-    while (i < aprset->curpos && aprset->pollset[i].fd != sock->socketdes) {
-        i++;
-    }
-    if (i >= aprset->curpos) {
-        return APR_NOTFOUND;
-    } 
-    newevents = get_event(events);
-    if (aprset->events[i] & newevents) {
-        aprset->events[i] ^= newevents;
-    }
-
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_remove_poll_socket(ap_pollfd_t *aprset, ap_socket_t *sock)
-{
-    int i = 0;
-    while(i < aprset->curpos && aprset->pollset[i].fd != sock->socketdes) {
-	i++;
-    }
-    if(i >= aprset->curpos) {
-	return APR_NOTFOUND;
-    }
-    while(++i < aprset->curpos) {
-	aprset->pollset[i-1].fd = aprset->pollset[i].fd;
-	aprset->pollset[i-1].events = aprset->pollset[i].events;
-    }
-    --aprset->curpos;
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_clear_poll_sockets(ap_pollfd_t *aprset, ap_int16_t events)
-{
-    int i = 0;
-    ap_int16_t newevents;
-
-    newevents = get_event(events);
-
-    while (i < aprset->curpos) {
-        if (aprset->events[i] & newevents) {
-            aprset->events[i] ^= newevents;
-        }
-        i++;
-    }
-    return APR_SUCCESS;
-}
-
-#else    /* Use select to mimic poll */
-
-ap_status_t ap_setup_poll(ap_pollfd_t **new, ap_int32_t num, ap_pool_t *cont)
-{
-    (*new) = (ap_pollfd_t *)ap_palloc(cont, sizeof(ap_pollfd_t) * num);
-    if ((*new) == NULL) {
-        return APR_ENOMEM;
-    }
-    (*new)->cntxt = cont;
-    (*new)->read = (fd_set *)ap_palloc(cont, sizeof(fd_set));
-    (*new)->write = (fd_set *)ap_palloc(cont, sizeof(fd_set));
-    (*new)->except = (fd_set *)ap_palloc(cont, sizeof(fd_set));
-    FD_ZERO((*new)->read);
-    FD_ZERO((*new)->write);
-    FD_ZERO((*new)->except);
-    (*new)->highsock = -1;
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_add_poll_socket(ap_pollfd_t *aprset,
-                               ap_socket_t *sock, ap_int16_t event)
-{
-    if (event & APR_POLLIN) {
-        FD_SET(sock->socketdes, aprset->read);
-    }
-    if (event & APR_POLLPRI) {
-        FD_SET(sock->socketdes, aprset->read);
-    }
-    if (event & APR_POLLOUT) {
-        FD_SET(sock->socketdes, aprset->write);
-    }
-    if (sock->socketdes > aprset->highsock) {
-        aprset->highsock = sock->socketdes;
-    }
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_poll(ap_pollfd_t *aprset, ap_int32_t *nsds, 
-		    ap_interval_time_t timeout)
-{
-    int rv;
-    struct timeval tv, *tvptr;
-
-    if (timeout < 0) {
-        tvptr = NULL;
-    }
-    else {
-        tv.tv_sec = timeout / AP_USEC_PER_SEC;
-        tv.tv_usec = timeout % AP_USEC_PER_SEC;
-        tvptr = &tv;
-    }
-
-    rv = select(aprset->highsock + 1, aprset->read, aprset->write, 
-                    aprset->except, tvptr);
-    
-    (*nsds) = rv;
-    if ((*nsds) == 0) {
-        return APR_TIMEUP;
-    }
-    if ((*nsds) < 0) {
-        return APR_EEXIST;
-    }
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_get_revents(ap_int16_t *event, ap_socket_t *sock, ap_pollfd_t *aprset)
-{
-    ap_int16_t revents = 0;
-    char data[1];
-    int flags = MSG_PEEK;
-
-    /* We just want to PEEK at the data, so I am setting up a dummy WSABUF
-     * variable here.
-     */
-    if (FD_ISSET(sock->socketdes, aprset->read)) {
-        revents |= APR_POLLIN;
-        if (sock->connected
-	    && recv(sock->socketdes, data, sizeof data, flags) == -1) {
-            switch (errno) {
-                case ECONNRESET:
-                case ECONNABORTED:
-                case ESHUTDOWN:
-                case ENETRESET:
-                    revents ^= APR_POLLIN;
-                    revents |= APR_POLLHUP;
-                    break;
-                case ENOTSOCK:
-                    revents ^= APR_POLLIN;
-                    revents |= APR_POLLNVAL;
-		    break;
-                default:
-                    revents ^= APR_POLLIN;
-                    revents |= APR_POLLERR;
-		    break;
-            }
-        }
-    }
-    if (FD_ISSET(sock->socketdes, aprset->write)) {
-        revents |= APR_POLLOUT;
-    }
-    /* I am assuming that the except is for out of band data, not a failed
-     * connection on a non-blocking socket.  Might be a bad assumption, but
-     * it works for now. rbb.
-     */
-    if (FD_ISSET(sock->socketdes, aprset->except)) {
-        revents |= APR_POLLPRI;
-    }
-
-    (*event) = revents;
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_remove_poll_socket(ap_pollfd_t *aprset, ap_socket_t *sock)
-{
-    FD_CLR(sock->socketdes, aprset->read);
-    FD_CLR(sock->socketdes, aprset->read);
-    FD_CLR(sock->socketdes, aprset->write);
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_clear_poll_sockets(ap_pollfd_t *aprset, ap_int16_t event)
-{
-    if (event & APR_POLLIN) {
-        FD_ZERO(aprset->read);
-    }
-    if (event & APR_POLLPRI) {
-        FD_ZERO(aprset->read);
-    }
-    if (event & APR_POLLOUT) {
-        FD_ZERO(aprset->write);
-    }
-    aprset->highsock = 0;
-    return APR_SUCCESS;
-}
-
-#endif 
-
-ap_status_t ap_get_polldata(ap_pollfd_t *pollfd, char *key, void *data)
-{
-    if (pollfd != NULL) {
-        return ap_get_userdata(data, key, pollfd->cntxt);
-    }
-    else {
-        data = NULL;
-        return APR_ENOFILE;
-    }
-}
-
-ap_status_t ap_set_polldata(ap_pollfd_t *pollfd, void *data, char *key,
-                            ap_status_t (*cleanup) (void *))
-{
-    if (pollfd != NULL) {
-        return ap_set_userdata(data, key, cleanup, pollfd->cntxt);
-    }
-    else {
-        data = NULL;
-        return APR_ENOFILE;
-    }
-}
-
diff --git a/network_io/unix/sendrecv.c b/network_io/unix/sendrecv.c
index be163461a57..b9e580b1b01 100644
--- a/network_io/unix/sendrecv.c
+++ b/network_io/unix/sendrecv.c
@@ -1,155 +1,171 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "networkio.h"
+#include "apr_arch_networkio.h"
+#include "apr_support.h"
 
-#ifdef HAVE_SENDFILE
-/* This file is needed to allow us access to the ap_file_t internals. */
-#include "../../file_io/unix/fileio.h"
+#if APR_HAS_SENDFILE
+/* This file is needed to allow us access to the apr_file_t internals. */
+#include "apr_arch_file_io.h"
+#endif /* APR_HAS_SENDFILE */
 
-/* Glibc2.1.1 fails to define TCP_CORK.  This is a bug that will be 
- *fixed in the next release.  It should be 3
- */
-#if !defined(TCP_CORK) && defined(__linux__)
-#define TCP_CORK 3
+/* osreldate.h is only needed on FreeBSD for sendfile detection */
+#if defined(__FreeBSD__)
+#include <osreldate.h>
 #endif
 
-#endif /* HAVE_SENDFILE */
-
-static ap_status_t wait_for_io_or_timeout(ap_socket_t *sock, int for_read)
+apr_status_t apr_socket_send(apr_socket_t *sock, const char *buf, 
+                             apr_size_t *len)
 {
-    struct timeval tv, *tvptr;
-    fd_set fdset;
-    int srv;
+    apr_ssize_t rv;
+    
+    if (sock->options & APR_INCOMPLETE_WRITE) {
+        sock->options &= ~APR_INCOMPLETE_WRITE;
+        goto do_select;
+    }
 
     do {
-	FD_ZERO(&fdset);
-	FD_SET(sock->socketdes, &fdset);
-        if (sock->timeout < 0) {
-            tvptr = NULL;
+        rv = write(sock->socketdes, buf, (*len));
+    } while (rv == -1 && errno == EINTR);
+
+    while (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) 
+                    && (sock->timeout > 0)) {
+        apr_status_t arv;
+do_select:
+        arv = apr_wait_for_io_or_timeout(NULL, sock, 0);
+        if (arv != APR_SUCCESS) {
+            *len = 0;
+            return arv;
         }
         else {
-            tv.tv_sec = sock->timeout / AP_USEC_PER_SEC;
-            tv.tv_usec = sock->timeout % AP_USEC_PER_SEC;
-            tvptr = &tv;
+            do {
+                rv = write(sock->socketdes, buf, (*len));
+            } while (rv == -1 && errno == EINTR);
         }
-	srv = select(sock->socketdes + 1,
-	    for_read ? &fdset : NULL,
-	    for_read ? NULL : &fdset,
-	    NULL,
-	    tvptr);
-        /* TODO - timeout should be smaller on repeats of this loop */
-    } while (srv == -1 && errno == EINTR);
-
-    if (srv == 0) {
-	return APR_TIMEUP;
     }
-    else if (srv < 0) {
-	return errno;
+    if (rv == -1) {
+        *len = 0;
+        return errno;
     }
+    if ((sock->timeout > 0) && (rv < *len)) {
+        sock->options |= APR_INCOMPLETE_WRITE;
+    }
+    (*len) = rv;
     return APR_SUCCESS;
 }
 
-ap_status_t ap_send(ap_socket_t *sock, const char *buf, ap_ssize_t *len)
+apr_status_t apr_socket_recv(apr_socket_t *sock, char *buf, apr_size_t *len)
 {
-    ssize_t rv;
-    
+    apr_ssize_t rv;
+    apr_status_t arv;
+
+    if (sock->options & APR_INCOMPLETE_READ) {
+        sock->options &= ~APR_INCOMPLETE_READ;
+        goto do_select;
+    }
+
     do {
-        rv = write(sock->socketdes, buf, (*len));
+        rv = read(sock->socketdes, buf, (*len));
     } while (rv == -1 && errno == EINTR);
 
-    if (rv == -1 && 
-        (errno == EAGAIN || errno == EWOULDBLOCK) && 
-        sock->timeout != 0) {
-	ap_status_t arv = wait_for_io_or_timeout(sock, 0);
-	if (arv != APR_SUCCESS) {
-	    *len = 0;
-	    return arv;
-	}
+    while ((rv == -1) && (errno == EAGAIN || errno == EWOULDBLOCK)
+                      && (sock->timeout > 0)) {
+do_select:
+        arv = apr_wait_for_io_or_timeout(NULL, sock, 1);
+        if (arv != APR_SUCCESS) {
+            *len = 0;
+            return arv;
+        }
         else {
             do {
-                rv = write(sock->socketdes, buf, (*len));
+                rv = read(sock->socketdes, buf, (*len));
             } while (rv == -1 && errno == EINTR);
         }
     }
     if (rv == -1) {
-	*len = 0;
-	return errno;
+        (*len) = 0;
+        return errno;
+    }
+    if ((sock->timeout > 0) && (rv < *len)) {
+        sock->options |= APR_INCOMPLETE_READ;
     }
     (*len) = rv;
+    if (rv == 0) {
+        return APR_EOF;
+    }
+    return APR_SUCCESS;
+}
+
+apr_status_t apr_socket_sendto(apr_socket_t *sock, apr_sockaddr_t *where,
+                               apr_int32_t flags, const char *buf,
+                               apr_size_t *len)
+{
+    apr_ssize_t rv;
+
+    do {
+        rv = sendto(sock->socketdes, buf, (*len), flags, 
+                    (const struct sockaddr*)&where->sa, 
+                    where->salen);
+    } while (rv == -1 && errno == EINTR);
+
+    while ((rv == -1) && (errno == EAGAIN || errno == EWOULDBLOCK)
+                      && (sock->timeout > 0)) {
+        apr_status_t arv = apr_wait_for_io_or_timeout(NULL, sock, 0);
+        if (arv != APR_SUCCESS) {
+            *len = 0;
+            return arv;
+        } else {
+            do {
+                rv = sendto(sock->socketdes, buf, (*len), flags,
+                            (const struct sockaddr*)&where->sa,
+                            where->salen);
+            } while (rv == -1 && errno == EINTR);
+        }
+    }
+    if (rv == -1) {
+        *len = 0;
+        return errno;
+    }
+    *len = rv;
     return APR_SUCCESS;
 }
 
-ap_status_t ap_recv(ap_socket_t *sock, char *buf, ap_ssize_t *len)
+apr_status_t apr_socket_recvfrom(apr_sockaddr_t *from, apr_socket_t *sock,
+                                 apr_int32_t flags, char *buf, 
+                                 apr_size_t *len)
 {
-    ssize_t rv;
+    apr_ssize_t rv;
     
+    from->salen = sizeof(from->sa);
+
     do {
-        rv = read(sock->socketdes, buf, (*len));
+        rv = recvfrom(sock->socketdes, buf, (*len), flags, 
+                      (struct sockaddr*)&from->sa, &from->salen);
     } while (rv == -1 && errno == EINTR);
 
-    if (rv == -1 && 
-        (errno == EAGAIN || errno == EWOULDBLOCK) && 
-        sock->timeout != 0) {
-	ap_status_t arv = wait_for_io_or_timeout(sock, 1);
-	if (arv != APR_SUCCESS) {
-	    *len = 0;
-	    return arv;
-	}
-        else {
+    while ((rv == -1) && (errno == EAGAIN || errno == EWOULDBLOCK)
+                      && (sock->timeout > 0)) {
+        apr_status_t arv = apr_wait_for_io_or_timeout(NULL, sock, 1);
+        if (arv != APR_SUCCESS) {
+            *len = 0;
+            return arv;
+        } else {
             do {
-                rv = read(sock->socketdes, buf, (*len));
+                rv = recvfrom(sock->socketdes, buf, (*len), flags,
+                              (struct sockaddr*)&from->sa, &from->salen);
             } while (rv == -1 && errno == EINTR);
         }
     }
@@ -157,290 +173,949 @@ ap_status_t ap_recv(ap_socket_t *sock, char *buf, ap_ssize_t *len)
         (*len) = 0;
         return errno;
     }
+
+    /*
+     * Check if we have a valid address. recvfrom() with MSG_PEEK may return
+     * success without filling in the address.
+     */
+    if (from->salen > APR_OFFSETOF(struct sockaddr_in, sin_port)) {
+        apr_sockaddr_vars_set(from, from->sa.sin.sin_family,
+                              ntohs(from->sa.sin.sin_port));
+    }
+
     (*len) = rv;
+    if (rv == 0 && sock->type == SOCK_STREAM) {
+        return APR_EOF;
+    }
+
     return APR_SUCCESS;
 }
 
-ap_status_t ap_sendv(ap_socket_t * sock, const struct iovec *vec,
-                     ap_int32_t nvec, ap_int32_t *len)
+apr_status_t apr_socket_sendv(apr_socket_t * sock, const struct iovec *vec,
+                              apr_int32_t nvec, apr_size_t *len)
 {
-    ssize_t rv;
+#ifdef HAVE_WRITEV
+    apr_ssize_t rv;
+    apr_size_t requested_len = 0;
+    apr_int32_t i;
+
+    for (i = 0; i < nvec; i++) {
+        requested_len += vec[i].iov_len;
+    }
+
+    if (sock->options & APR_INCOMPLETE_WRITE) {
+        sock->options &= ~APR_INCOMPLETE_WRITE;
+        goto do_select;
+    }
 
     do {
         rv = writev(sock->socketdes, vec, nvec);
     } while (rv == -1 && errno == EINTR);
 
-    if (rv == -1 && 
-        (errno == EAGAIN || errno == EWOULDBLOCK) && 
-        sock->timeout != 0) {
-	ap_status_t arv = wait_for_io_or_timeout(sock, 0);
-	if (arv != APR_SUCCESS) {
-	    *len = 0;
-	    return arv;
-	}
+    while ((rv == -1) && (errno == EAGAIN || errno == EWOULDBLOCK) 
+                      && (sock->timeout > 0)) {
+        apr_status_t arv;
+do_select:
+        arv = apr_wait_for_io_or_timeout(NULL, sock, 0);
+        if (arv != APR_SUCCESS) {
+            *len = 0;
+            return arv;
+        }
         else {
             do {
-        	rv = writev(sock->socketdes, vec, nvec);
+                rv = writev(sock->socketdes, vec, nvec);
             } while (rv == -1 && errno == EINTR);
         }
     }
     if (rv == -1) {
-	*len = 0;
-	return errno;
+        *len = 0;
+        return errno;
+    }
+    if ((sock->timeout > 0) && (rv < requested_len)) {
+        sock->options |= APR_INCOMPLETE_WRITE;
     }
     (*len) = rv;
     return APR_SUCCESS;
+#else
+    *len = vec[0].iov_len;
+    return apr_socket_send(sock, vec[0].iov_base, len);
+#endif
 }
 
-#if defined(HAVE_SENDFILE)
+apr_status_t apr_socket_wait(apr_socket_t *sock, apr_wait_type_t direction)
+{
+    return apr_wait_for_io_or_timeout(NULL, sock, direction == APR_WAIT_READ);
+}
+
+#if APR_HAS_SENDFILE
+
+/* TODO: Verify that all platforms handle the fd the same way,
+ * i.e. that they don't move the file pointer.
+ */
+/* TODO: what should flags be?  int_32? */
+
+/* Define a structure to pass in when we have a NULL header value */
+static apr_hdtr_t no_hdtr;
 
- /* TODO: Verify that all platforms handle the fd the same way 
-  *     (i.e. not moving current file pointer)
-  *     - Should flags be an int_32 or what?
-  */
+#if (defined(__linux__) || defined(__GNU__)) && defined(HAVE_WRITEV)
 
-#if defined(__linux__) && defined(HAVE_WRITEV)
-ap_status_t ap_sendfile(ap_socket_t *sock, ap_file_t *file,
-        		ap_hdtr_t *hdtr, ap_off_t *offset, ap_size_t *len,
-        		ap_int32_t flags)
+apr_status_t apr_socket_sendfile(apr_socket_t *sock, apr_file_t *file,
+                                 apr_hdtr_t *hdtr, apr_off_t *offset,
+                                 apr_size_t *len, apr_int32_t flags)
 {
+    int nopush_set = 0, rv, i;
+    apr_size_t bytes_to_send = *len;
+    apr_status_t arv;
+    apr_size_t n;
+
+#if APR_HAS_LARGE_FILES && defined(HAVE_SENDFILE64)
+    apr_off_t off = *offset;
+#define sendfile sendfile64
+
+#elif APR_HAS_LARGE_FILES && SIZEOF_OFF_T == 4
+    /* 64-bit apr_off_t but no sendfile64(): fail if trying to send
+     * past the 2Gb limit. */
+    off_t off;
+    
+    if ((apr_int64_t)*offset + bytes_to_send > INT_MAX) {
+        *len = 0;
+        return EINVAL;
+    }
+    
+    off = *offset;
+
+#else
     off_t off = *offset;
-    int corkflag = 1;
-    int rv, nbytes = 0;
-    ap_status_t arv;
 
-    /* TCP_CORK keeps us from sending partial frames when we shouldn't */
-    rv = setsockopt(sock->socketdes, SOL_TCP, TCP_CORK,
-        	    (const void *) &corkflag, sizeof(corkflag));
-    if (rv == -1) {
-	*len = 0;
-        return errno;
+    /* Multiple reports have shown sendfile failing with EINVAL if
+     * passed a >=2Gb count value on some 64-bit kernels.  It won't
+     * noticably hurt performance to limit each call to <2Gb at a
+     * time, so avoid that issue here: */
+    if (sizeof(off_t) == 8 && bytes_to_send > INT_MAX) {
+        bytes_to_send = INT_MAX;
+    }
+#endif
+
+    /* Until further notice. */
+    *len = 0;
+
+    if (!hdtr) {
+        hdtr = &no_hdtr;
+    }
+    else if ((hdtr->numheaders > 0 || hdtr->numtrailers > 0)
+             && !apr_is_option_set(sock, APR_TCP_NOPUSH)) {
+        /* cork before writing headers */
+        rv = apr_socket_opt_set(sock, APR_TCP_NOPUSH, 1);
+        if (rv != APR_SUCCESS) {
+            return rv;
+        }
+        nopush_set = 1;
     }
 
-    /* Now write the headers */
     if (hdtr->numheaders > 0) {
-        ap_int32_t hdrbytes;
-        arv = ap_sendv(sock, hdtr->headers, hdtr->numheaders, &hdrbytes);
+        apr_size_t total_hdrbytes;
+
+        /* Now write the headers */
+        arv = apr_socket_sendv(sock, hdtr->headers, hdtr->numheaders, &n);
+        *len += n;
         if (arv != APR_SUCCESS) {
-	    *len = 0;
-            return errno;
+            return arv;
+        }
+
+        /* If this was a partial write and we aren't doing timeouts, 
+         * return now with the partial byte count; this is a non-blocking 
+         * socket.
+         */
+        total_hdrbytes = 0;
+        for (i = 0; i < hdtr->numheaders; i++) {
+            total_hdrbytes += hdtr->headers[i].iov_len;
+        }
+        if (n < total_hdrbytes) {
+            if (nopush_set) {
+                return apr_socket_opt_set(sock, APR_TCP_NOPUSH, 0);
+            }
+            return APR_SUCCESS;
         }
-        nbytes += hdrbytes;
+    }
+
+    if (sock->options & APR_INCOMPLETE_WRITE) {
+        sock->options &= ~APR_INCOMPLETE_WRITE;
+        goto do_select;
     }
 
     do {
-        rv = sendfile(sock->socketdes,	/* socket */
-        	      file->filedes,	/* open file descriptor of the file to be sent */
-        	      &off,	/* where in the file to start */
-        	      *len	/* number of bytes to send */
-            );
+        rv = sendfile(sock->socketdes,    /* socket */
+                      file->filedes, /* open file descriptor of the file to be sent */
+                      &off,    /* where in the file to start */
+                      bytes_to_send);   /* number of bytes to send */
     } while (rv == -1 && errno == EINTR);
 
-    if (rv == -1 && 
-        (errno == EAGAIN || errno == EWOULDBLOCK) && 
-        sock->timeout != 0) {
-	arv = wait_for_io_or_timeout(sock, 0);
-	if (arv != APR_SUCCESS) {
-	    *len = 0;
-	    return arv;
-	}
+    while ((rv == -1) && (errno == EAGAIN || errno == EWOULDBLOCK) 
+                      && (sock->timeout > 0)) {
+do_select:
+        arv = apr_wait_for_io_or_timeout(NULL, sock, 0);
+        if (arv != APR_SUCCESS) {
+            return arv;
+        }
         else {
             do {
-        	rv = sendfile(sock->socketdes,	/* socket */
-        		      file->filedes,	/* open file descriptor of the file to be sent */
-        		      &off,	/* where in the file to start */
-        		      *len);	/* number of bytes to send */
+                rv = sendfile(sock->socketdes,    /* socket */
+                              file->filedes, /* open file descriptor of the file to be sent */
+                              &off,    /* where in the file to start */
+                              bytes_to_send);    /* number of bytes to send */
             } while (rv == -1 && errno == EINTR);
         }
     }
 
     if (rv == -1) {
-	*len = nbytes;
-        return errno;
+        arv = errno;
+        if (nopush_set) {
+            apr_socket_opt_set(sock, APR_TCP_NOPUSH, 0);
+        }
+        return arv;
     }
 
-    nbytes += rv;
+    *len += rv;
+
+    if ((apr_size_t)rv < bytes_to_send) {
+        if (nopush_set) {
+            arv = apr_socket_opt_set(sock, APR_TCP_NOPUSH, 0);
+        }
+        else {
+            arv = APR_SUCCESS;
+        }
+        if (rv > 0) {
+                
+            /* If this was a partial write, return now with the 
+             * partial byte count;  this is a non-blocking socket.
+             */
+
+            if (sock->timeout > 0) {
+                sock->options |= APR_INCOMPLETE_WRITE;
+            }
+            return arv;
+        }
+        else {
+            /* If the file got smaller mid-request, eventually the offset
+             * becomes equal to the new file size and the kernel returns 0.  
+             * Make this an error so the caller knows to log something and
+             * exit.
+             */
+            return APR_EOF;
+        }
+    }
 
     /* Now write the footers */
     if (hdtr->numtrailers > 0) {
-        ap_int32_t trbytes;
-        arv = ap_sendv(sock, hdtr->trailers, hdtr->numtrailers, &trbytes);
-        nbytes += trbytes;
+        arv = apr_socket_sendv(sock, hdtr->trailers, hdtr->numtrailers, &n);
+        *len += n;
+        if (nopush_set) {
+            apr_socket_opt_set(sock, APR_TCP_NOPUSH, 0);
+        }
         if (arv != APR_SUCCESS) {
-	    *len = nbytes;
-            return errno;
+            return arv;
         }
     }
 
-    /* Uncork to send queued frames */
-    corkflag = 0;
-    rv = setsockopt(sock->socketdes, SOL_TCP, TCP_CORK,
-                    (const void *) &corkflag, sizeof(corkflag));
-
-    (*len) = nbytes;
-    return rv < 0 ? errno : APR_SUCCESS;
+    return APR_SUCCESS;
 }
 
-/* These are just demos of how the code for the other OSes.
- * I haven't tested these, but they're right in terms of interface.
- * I just wanted to see what types of vars would be required from other OSes. 
- */
+#elif defined(DARWIN)
+
+/* OS/X Release 10.5 or greater */
+apr_status_t apr_socket_sendfile(apr_socket_t *sock, apr_file_t *file,
+                                 apr_hdtr_t *hdtr, apr_off_t *offset,
+                                 apr_size_t *len, apr_int32_t flags)
+{
+    apr_off_t nbytes = 0;
+    apr_size_t bytes_to_send = *len;
+    apr_status_t arv;
+    apr_size_t n;
+    int rv = 0;
+
+    /* Until further notice. */
+    *len = 0;
+
+    /* Ignore flags for now. */
+    flags = 0;
+
+    if (!hdtr) {
+        hdtr = &no_hdtr;
+    }
+
+    /* OS X can send the headers/footers as part of the system call, 
+     * but how it counts bytes isn't documented properly. We use 
+     * apr_socket_sendv() instead.
+     */
+     if (hdtr->numheaders > 0) {
+        apr_size_t total_hdrbytes;
+        int i;
+
+        /* Now write the headers */
+        arv = apr_socket_sendv(sock, hdtr->headers, hdtr->numheaders, &n);
+        *len += n;
+        if (arv != APR_SUCCESS) {
+            return arv;
+        }
+
+        total_hdrbytes = 0;
+        for (i = 0; i < hdtr->numheaders; i++) {
+            total_hdrbytes += hdtr->headers[i].iov_len;
+        }
+        if (n < total_hdrbytes) {
+            return APR_SUCCESS;
+        }
+    }
+
+    do {
+        if (!bytes_to_send) {
+            break;
+        }
+        if (sock->options & APR_INCOMPLETE_WRITE) {
+            apr_status_t arv;
+            sock->options &= ~APR_INCOMPLETE_WRITE;
+            arv = apr_wait_for_io_or_timeout(NULL, sock, 0);
+            if (arv != APR_SUCCESS) {
+                return arv;
+            }
+        }
 
-#elif defined(__FreeBSD__)
+        nbytes = bytes_to_send;
+        rv = sendfile(file->filedes, /* file to be sent */
+                      sock->socketdes, /* socket */
+                      *offset,       /* where in the file to start */
+                      &nbytes,       /* number of bytes to write/written */
+                      NULL,          /* Headers/footers */
+                      flags);        /* undefined, set to 0 */
+
+        if (rv == -1) {
+            if (errno == EAGAIN) {
+                if (sock->timeout > 0) {
+                    sock->options |= APR_INCOMPLETE_WRITE;
+                }
+                /* BSD's sendfile can return -1/EAGAIN even if it
+                 * sent bytes.  Sanitize the result so we get normal EAGAIN
+                 * semantics w.r.t. bytes sent.
+                 */
+                if (nbytes) {
+                    *len += nbytes;
+                    /* normal exit for a big file & non-blocking io */
+                    return APR_SUCCESS;
+                }
+                if (sock->timeout <= 0) {
+                    /* normal exit for a non-blocking io which would block */
+                    break;
+                }
+            }
+        }
+        else {       /* rv == 0 (or the kernel is broken) */
+            if (nbytes == 0) {
+                /* Most likely the file got smaller after the stat.
+                 * Return an error so the caller can do the Right Thing.
+                 */
+                return APR_EOF;
+            }
+            *len += nbytes;
+        }
+    } while (rv == -1 && (errno == EINTR || errno == EAGAIN));
+
+    if (rv == -1) {
+        return errno;
+    }
+
+    /* Now write the footers */
+    if (hdtr->numtrailers > 0) {
+        arv = apr_socket_sendv(sock, hdtr->trailers, hdtr->numtrailers, &n);
+        *len += n;
+        if (arv != APR_SUCCESS) {
+            return arv;
+        }
+    }
+
+    return APR_SUCCESS;
+}
+
+#elif defined(__FreeBSD__) || defined(__DragonFly__)
 
 /* Release 3.1 or greater */
-ap_status_t ap_sendfile(ap_socket_t * sock, ap_file_t * file,
-        		ap_hdtr_t * hdtr, ap_off_t * offset, ap_size_t * len,
-        		ap_int32_t flags)
+apr_status_t apr_socket_sendfile(apr_socket_t * sock, apr_file_t * file,
+                                 apr_hdtr_t * hdtr, apr_off_t * offset,
+                                 apr_size_t * len, apr_int32_t flags)
 {
-    off_t nbytes;
+    off_t nbytes = 0;
     int rv;
+#if defined(__FreeBSD_version) && __FreeBSD_version < 460001
+    int i;
+#endif
     struct sf_hdtr headerstruct;
+    apr_size_t bytes_to_send = *len;
+    apr_status_t arv;
+
+    /* Until further notice. */
+    *len = 0;
+
+    /* Ignore flags for now. */
+    flags = 0;
+
+    if (!hdtr) {
+        hdtr = &no_hdtr;
+    }
+
+#if defined(__FreeBSD_version) && __FreeBSD_version < 460001
+    else if (hdtr->numheaders) {
+
+        /* On early versions of FreeBSD sendfile, the number of bytes to send 
+         * must include the length of the headers.  Don't look at the man page 
+         * for this :(  Instead, look at the logic in 
+         * src/sys/kern/uipc_syscalls::sendfile().
+         *
+         * This was fixed in the middle of 4.6-STABLE
+         */
+        for (i = 0; i < hdtr->numheaders; i++) {
+            bytes_to_send += hdtr->headers[i].iov_len;
+        }
+    }
+#endif
 
     headerstruct.headers = hdtr->headers;
     headerstruct.hdr_cnt = hdtr->numheaders;
     headerstruct.trailers = hdtr->trailers;
     headerstruct.trl_cnt = hdtr->numtrailers;
 
-
     /* FreeBSD can send the headers/footers as part of the system call */
     do {
-        rv = sendfile(file->filedes,	/* open file descriptor of the file to be sent */
-        	      sock->socketdes,	/* socket */
-        	      *offset,	/* where in the file to start */
-        	      (size_t) * len,	/* number of bytes to send */
-        	      &headerstruct,	/* Headers/footers */
-        	      &nbytes,	/* number of bytes written */
-        	      flags	/* undefined, set to 0 */
-            );
-    } while (rv == -1 && errno == EINTR);
+        if (sock->options & APR_INCOMPLETE_WRITE) {
+            sock->options &= ~APR_INCOMPLETE_WRITE;
+            arv = apr_wait_for_io_or_timeout(NULL, sock, 0);
+            if (arv != APR_SUCCESS) {
+                return arv;
+            }
+        }
+        if (bytes_to_send) {
+            /* We won't dare call sendfile() if we don't have
+             * header or file bytes to send because bytes_to_send == 0
+             * means send the whole file.
+             */
+            rv = sendfile(file->filedes, /* file to be sent */
+                          sock->socketdes, /* socket */
+                          *offset,       /* where in the file to start */
+                          bytes_to_send, /* number of bytes to send */
+                          &headerstruct, /* Headers/footers */
+                          &nbytes,       /* number of bytes written */
+                          flags);        /* undefined, set to 0 */
 
-    if (rv == -1 && 
-        (errno == EAGAIN || errno == EWOULDBLOCK) && 
-        sock->timeout != 0) {
-	ap_status_t arv = wait_for_io_or_timeout(sock, 0);
-	if (arv != APR_SUCCESS) {
-	    *len = 0;
-	    return arv;
-	}
+            if (rv == -1) {
+                if (errno == EAGAIN) {
+                    if (sock->timeout > 0) {
+                        sock->options |= APR_INCOMPLETE_WRITE;
+                    }
+                    /* FreeBSD's sendfile can return -1/EAGAIN even if it
+                     * sent bytes.  Sanitize the result so we get normal EAGAIN
+                     * semantics w.r.t. bytes sent.
+                     */
+                    if (nbytes) {
+                        *len += nbytes;
+                        /* normal exit for a big file & non-blocking io */
+                        return APR_SUCCESS;
+                    }
+                    if (sock->timeout <= 0) {
+                        /* normal exit for a non-blocking io which would block */
+                        break;
+                    }
+                }
+            }
+            else {       /* rv == 0 (or the kernel is broken) */
+                if (nbytes == 0) {
+                    /* Most likely the file got smaller after the stat.
+                     * Return an error so the caller can do the Right Thing.
+                     */
+                    return APR_EOF;
+                }
+                *len += nbytes;
+            }
+        }    
         else {
-            do {
-        	rv = sendfile(file->filedes,	/* open file descriptor of the file to be sent */
-        		      sock->socketdes,	/* socket */
-        		      *offset,	/* where in the file to start */
-        		      (size_t) * len,	/* number of bytes to send */
-        		      &headerstruct,	/* Headers/footers */
-        		      &nbytes,	/* number of bytes written */
-        		      flags	/* undefined, set to 0 */
-        	    );
-            } while (rv == -1 && errno == EINTR);
+            /* just trailer bytes... use writev()
+             */
+            rv = writev(sock->socketdes,
+                        hdtr->trailers,
+                        hdtr->numtrailers);
+            if (rv > 0) {
+                *len += rv;
+            }
+            else if (rv == -1 && errno == EAGAIN) {
+                if (sock->timeout > 0) {
+                    sock->options |= APR_INCOMPLETE_WRITE;
+                }
+                else {
+                    break;
+                }
+            }
         }
-    }
+    } while (rv == -1 && (errno == EINTR || errno == EAGAIN));
 
-    (*len) = nbytes;
     if (rv == -1) {
         return errno;
     }
     return APR_SUCCESS;
 }
 
-#elif defined(__HPUX__)
+#elif defined(__hpux) || defined(__hpux__)
+
+/* HP cc in ANSI mode defines __hpux; gcc defines __hpux__ */
 
-#error "there's no way this ap_sendfile implementation works -djg"
+/* HP-UX Version 10.30 or greater
+ * (no worries, because we only get here if autoconfiguration found sendfile)
+ */
 
-/* HP-UX Version 10.30 or greater */
-ap_status_t ap_sendfile(ap_socket_t * sock, ap_file_t * file,
-        		ap_hdtr_t * hdtr, ap_off_t * offset, ap_size_t * len,
-        		ap_int32_t flags)
+/* ssize_t sendfile(int s, int fd, off_t offset, size_t nbytes,
+ *                  const struct iovec *hdtrl, int flags);
+ *
+ * nbytes is the number of bytes to send just from the file; as with FreeBSD, 
+ * if nbytes == 0, the rest of the file (from offset) is sent
+ */
+
+apr_status_t apr_socket_sendfile(apr_socket_t *sock, apr_file_t *file,
+                                 apr_hdtr_t *hdtr, apr_off_t *offset,
+                                 apr_size_t *len, apr_int32_t flags)
 {
-    int i, ptr = 0;
-    size_t nbytes = 0, headerlen = 0, trailerlen = 0;
-    struct sf_hdtr headerstruct;
+    int i;
+    apr_ssize_t rc;
+    apr_size_t nbytes = *len, headerlen, trailerlen;
     struct iovec hdtrarray[2];
-    void *headerbuf, *trailerbuf;
+    char *headerbuf, *trailerbuf;
 
+#if APR_HAS_LARGE_FILES && defined(HAVE_SENDFILE64)
+    /* later HP-UXes have a sendfile64() */
+#define sendfile sendfile64
+    apr_off_t off = *offset;
 
-    /* HP-UX can only send one header iovec and one footer iovec */
+#elif APR_HAS_LARGE_FILES && SIZEOF_OFF_T == 4
+    /* HP-UX 11.00 doesn't have a sendfile64(): fail if trying to send
+     * past the 2Gb limit */
+    off_t off;
 
-    for (i = 0; i < hdtr->numheaders; i++) {
-        headerlen += hdtr->headers[i].iov_len;
+    if ((apr_int64_t)*offset + *len > INT_MAX) {
+        return EINVAL;
     }
+    off = *offset;
+#else
+    apr_off_t off = *offset;
+#endif
+
+    if (!hdtr) {
+        hdtr = &no_hdtr;
+    }
+
+    /* Ignore flags for now. */
+    flags = 0;
+
+    /* HP-UX can only send one header iovec and one footer iovec; try to
+     * only allocate storage to combine input iovecs when we really have to
+     */
 
-    /* XXX:  BUHHH? wow, what a memory leak! */
-    headerbuf = ap_palloc(sock->cntxt, headerlen);
+    switch(hdtr->numheaders) {
+    case 0:
+        hdtrarray[0].iov_base = NULL;
+        hdtrarray[0].iov_len = 0;
+        break;
+    case 1:
+        hdtrarray[0] = hdtr->headers[0];
+        break;
+    default:
+        headerlen = 0;
+        for (i = 0; i < hdtr->numheaders; i++) {
+            headerlen += hdtr->headers[i].iov_len;
+        }  
 
-    for (i = 0; i < hdtr->numheaders; i++) {
-        memcpy(headerbuf + ptr, hdtr->headers[i].iov_base,
-               hdtr->headers[i].iov_len);
-        ptr += hdtr->headers[i].iov_len;
+        /* XXX:  BUHHH? wow, what a memory leak! */
+        headerbuf = hdtrarray[0].iov_base = apr_palloc(sock->pool, headerlen);
+        hdtrarray[0].iov_len = headerlen;
+
+        for (i = 0; i < hdtr->numheaders; i++) {
+            memcpy(headerbuf, hdtr->headers[i].iov_base,
+                   hdtr->headers[i].iov_len);
+            headerbuf += hdtr->headers[i].iov_len;
+        }
     }
 
-    for (i = 0; i < hdtr->numtrailers; i++) {
-        trailerlen += hdtr->headers[i].iov_len;
+    switch(hdtr->numtrailers) {
+    case 0:
+        hdtrarray[1].iov_base = NULL;
+        hdtrarray[1].iov_len = 0;
+        break;
+    case 1:
+        hdtrarray[1] = hdtr->trailers[0];
+        break;
+    default:
+        trailerlen = 0;
+        for (i = 0; i < hdtr->numtrailers; i++) {
+            trailerlen += hdtr->trailers[i].iov_len;
+        }
+
+        /* XXX:  BUHHH? wow, what a memory leak! */
+        trailerbuf = hdtrarray[1].iov_base = apr_palloc(sock->pool, trailerlen);
+        hdtrarray[1].iov_len = trailerlen;
+
+        for (i = 0; i < hdtr->numtrailers; i++) {
+            memcpy(trailerbuf, hdtr->trailers[i].iov_base,
+                   hdtr->trailers[i].iov_len);
+            trailerbuf += hdtr->trailers[i].iov_len;
+        }
     }
 
-    /* XXX:  BUHHH? wow, what a memory leak! */
-    trailerbuf = ap_palloc(sock->cntxt, trailerlen);
+    do {
+        if (nbytes) {       /* any bytes to send from the file? */
+            rc = sendfile(sock->socketdes,      /* socket  */
+                          file->filedes,        /* file descriptor to send */
+                          off,                  /* where in the file to start */
+                          nbytes,               /* number of bytes to send from file */
+                          hdtrarray,            /* Headers/footers */
+                          flags);               /* undefined, set to 0 */
+        }
+        else {              /* we can't call sendfile() with no bytes to send from the file */
+            rc = writev(sock->socketdes, hdtrarray, 2);
+        }
+    } while (rc == -1 && errno == EINTR);
+
+    while ((rc == -1) && (errno == EAGAIN || errno == EWOULDBLOCK) 
+                      && (sock->timeout > 0)) {
+        apr_status_t arv = apr_wait_for_io_or_timeout(NULL, sock, 0);
+
+        if (arv != APR_SUCCESS) {
+            *len = 0;
+            return arv;
+        }
+        else {
+            do {
+                if (nbytes) {
+                    rc = sendfile(sock->socketdes,    /* socket  */
+                                  file->filedes,      /* file descriptor to send */
+                                  off,                /* where in the file to start */
+                                  nbytes,             /* number of bytes to send from file */
+                                  hdtrarray,          /* Headers/footers */
+                                  flags);             /* undefined, set to 0 */
+                }
+                else {      /* we can't call sendfile() with no bytes to send from the file */
+                    rc = writev(sock->socketdes, hdtrarray, 2);
+                }
+            } while (rc == -1 && errno == EINTR);
+        }
+    }
 
-    for (i = 0; i < hdtr->numtrailers; i++) {
-        memcpy(trailerbuf + ptr, hdtr->trailers[i].iov_base,
-               hdtr->trailers[i].iov_len);
-        ptr += hdtr->trailers[i].iov_len;
+    if (rc == -1) {
+        *len = 0;
+        return errno;
     }
 
-    hdtrarray[0].iov_base = headerbuf;
-    hdtrarray[0].iov_len = headerlen;
-    hdtrarray[1].iov_base = trailerbuf;
-    hdtrarray[1].iov_len = trailerlen;
+    /* Set len to the number of bytes written */
+    *len = rc;
+    return APR_SUCCESS;
+}
+#elif defined(_AIX) || defined(__MVS__)
+/* AIX and OS/390 have the same send_file() interface.
+ *
+ * subtle differences:
+ *   AIX doesn't update the file ptr but OS/390 does
+ *
+ * availability (correctly determined by autoconf):
+ *
+ * AIX -  version 4.3.2 with APAR IX85388, or version 4.3.3 and above
+ * OS/390 - V2R7 and above
+ */
+apr_status_t apr_socket_sendfile(apr_socket_t * sock, apr_file_t * file,
+                                 apr_hdtr_t * hdtr, apr_off_t * offset,
+                                 apr_size_t * len, apr_int32_t flags)
+{
+    int i, ptr, rv = 0;
+    void * hbuf=NULL, * tbuf=NULL;
+    apr_status_t arv;
+    struct sf_parms parms;
+
+    if (!hdtr) {
+        hdtr = &no_hdtr;
+    }
+
+    /* Ignore flags for now. */
+    flags = 0;
+
+    /* word to the wise: by default, AIX stores files sent by send_file()
+     * in the network buffer cache...  there are supposedly scenarios
+     * where the most recent copy of the file won't be sent, but I can't
+     * recreate the potential problem, perhaps because of the way we
+     * use send_file()...  if you suspect such a problem, try turning
+     * on the SF_SYNC_CACHE flag
+     */
+
+    /* AIX can also send the headers/footers as part of the system call */
+    parms.header_length = 0;
+    if (hdtr && hdtr->numheaders) {
+        if (hdtr->numheaders == 1) {
+            parms.header_data = hdtr->headers[0].iov_base;
+            parms.header_length = hdtr->headers[0].iov_len;
+        }
+        else {
+            for (i = 0; i < hdtr->numheaders; i++) {
+                parms.header_length += hdtr->headers[i].iov_len;
+            }
+#if 0
+            /* Keepalives make apr_palloc a bad idea */
+            hbuf = malloc(parms.header_length);
+#else
+            /* but headers are small, so maybe we can hold on to the
+             * memory for the life of the socket...
+             */
+            hbuf = apr_palloc(sock->pool, parms.header_length);
+#endif
+            ptr = 0;
+            for (i = 0; i < hdtr->numheaders; i++) {
+                memcpy((char *)hbuf + ptr, hdtr->headers[i].iov_base,
+                       hdtr->headers[i].iov_len);
+                ptr += hdtr->headers[i].iov_len;
+            }
+            parms.header_data = hbuf;
+        }
+    }
+    else parms.header_data = NULL;
+    parms.trailer_length = 0;
+    if (hdtr && hdtr->numtrailers) {
+        if (hdtr->numtrailers == 1) {
+            parms.trailer_data = hdtr->trailers[0].iov_base;
+            parms.trailer_length = hdtr->trailers[0].iov_len;
+        }
+        else {
+            for (i = 0; i < hdtr->numtrailers; i++) {
+                parms.trailer_length += hdtr->trailers[i].iov_len;
+            }
+#if 0
+            /* Keepalives make apr_palloc a bad idea */
+            tbuf = malloc(parms.trailer_length);
+#else
+            tbuf = apr_palloc(sock->pool, parms.trailer_length);
+#endif
+            ptr = 0;
+            for (i = 0; i < hdtr->numtrailers; i++) {
+                memcpy((char *)tbuf + ptr, hdtr->trailers[i].iov_base,
+                       hdtr->trailers[i].iov_len);
+                ptr += hdtr->trailers[i].iov_len;
+            }
+            parms.trailer_data = tbuf;
+        }
+    }
+    else {
+        parms.trailer_data = NULL;
+    }
+
+    /* Whew! Headers and trailers set up. Now for the file data */
+
+    parms.file_descriptor = file->filedes;
+    parms.file_offset = *offset;
+    parms.file_bytes = *len;
+
+    /* O.K. All set up now. Let's go to town */
+
+    if (sock->options & APR_INCOMPLETE_WRITE) {
+        sock->options &= ~APR_INCOMPLETE_WRITE;
+        goto do_select;
+    }
 
     do {
-        rv = sendfile(sock->socketdes,	/* socket  */
-        	      file->filedes,	/* file descriptor to send */
-        	      *offset,	/* where in the file to start */
-		      /* XXX: as far as i can see, nbytes == 0 always here -djg */
-        	      nbytes,	/* number of bytes to send */
-        	      hdtrarray,	/* Headers/footers */
-        	      flags	/* undefined, set to 0 */
-            );
+        rv = send_file(&(sock->socketdes), /* socket */
+                       &(parms),           /* all data */
+                       flags);             /* flags */
     } while (rv == -1 && errno == EINTR);
 
-    if (rv == -1 && 
-        (errno == EAGAIN || errno == EWOULDBLOCK) && 
-        sock->timeout != 0) {
-        ap_status_t arv = wait_for_io_or_timeout(sock, 0);
-
+    while ((rv == -1) && (errno == EAGAIN || errno == EWOULDBLOCK) 
+                      && (sock->timeout > 0)) {
+do_select:
+        arv = apr_wait_for_io_or_timeout(NULL, sock, 0);
         if (arv != APR_SUCCESS) {
-            /* jlt: not tested, but this matches other sendfile logic */
-            (*len) = 0;
+            *len = 0;
             return arv;
         }
         else {
             do {
-        	rv = sendfile(sock->socketdes,	/* socket  */
-        		      file->filedes,	/* file descriptor to send */
-        		      *offset,	/* where in the file to start */
-				/* XXX: as far as i can see, nbytes == 0 always here -djg */
-        		      nbytes,	/* number of bytes to send */
-        		      hdtrarray,	/* Headers/footers */
-        		      flags	/* undefined, set to 0 */
-        	    );
+                rv = send_file(&(sock->socketdes), /* socket */
+                               &(parms),           /* all data */
+                               flags);             /* flags */
             } while (rv == -1 && errno == EINTR);
         }
     }
 
+    (*len) = parms.bytes_sent;
+
+#if 0
+    /* Clean up after ourselves */
+    if(hbuf) free(hbuf);
+    if(tbuf) free(tbuf);
+#endif
 
     if (rv == -1) {
-	*len = 0;
         return errno;
     }
 
+    if ((sock->timeout > 0)
+          && (parms.bytes_sent 
+                < (parms.file_bytes + parms.header_length + parms.trailer_length))) {
+        sock->options |= APR_INCOMPLETE_WRITE;
+    }
+
+    return APR_SUCCESS;
+}
+#elif defined(__osf__) && defined (__alpha)
+/* Tru64's sendfile implementation doesn't work, and we need to make sure that
+ * we don't use it until it is fixed.  If it is used as it is now, it will
+ * hang the machine and the only way to fix it is a reboot.
+ */
+#elif defined(HAVE_SENDFILEV)
+/* Solaris 8's sendfilev() interface 
+ *
+ * SFV_FD_SELF refers to our memory space.
+ *
+ * Required Sparc patches (or newer):
+ * 111297-01, 108528-09, 109472-06, 109234-03, 108995-02, 111295-01, 109025-03,
+ * 108991-13
+ * Required x86 patches (or newer):
+ * 111298-01, 108529-09, 109473-06, 109235-04, 108996-02, 111296-01, 109026-04,
+ * 108992-13
+ */
 
-    /* Set len to the number of bytes written */
-    (*len) = rv;
+#if APR_HAS_LARGE_FILES && defined(HAVE_SENDFILEV64)
+#define sendfilevec_t sendfilevec64_t
+#define sendfilev sendfilev64
+#endif
+
+apr_status_t apr_socket_sendfile(apr_socket_t *sock, apr_file_t *file,
+                                 apr_hdtr_t *hdtr, apr_off_t *offset,
+                                 apr_size_t *len, apr_int32_t flags)
+{
+    apr_status_t rv, arv;
+    apr_size_t nbytes;
+    sendfilevec_t *sfv;
+    int vecs, curvec, i, repeat;
+    apr_size_t requested_len = 0;
+
+    if (!hdtr) {
+        hdtr = &no_hdtr;
+    }
+
+    /* Ignore flags for now. */
+    flags = 0;
+
+    /* Calculate how much space we need. */
+    vecs = hdtr->numheaders + hdtr->numtrailers + 1;
+    sfv = apr_palloc(sock->pool, sizeof(sendfilevec_t) * vecs);
+
+    curvec = 0;
+
+    /* Add the headers */
+    for (i = 0; i < hdtr->numheaders; i++, curvec++) {
+        sfv[curvec].sfv_fd = SFV_FD_SELF;
+        sfv[curvec].sfv_flag = 0;
+        /* Cast to unsigned long to prevent sign extension of the
+         * pointer value for the LFS case; see PR 39463. */
+        sfv[curvec].sfv_off = (unsigned long)hdtr->headers[i].iov_base;
+        sfv[curvec].sfv_len = hdtr->headers[i].iov_len;
+        requested_len += sfv[curvec].sfv_len;
+    }
+
+    /* If the len is 0, we skip the file. */
+    if (*len)
+    {
+        sfv[curvec].sfv_fd = file->filedes;
+        sfv[curvec].sfv_flag = 0;
+        sfv[curvec].sfv_off = *offset;
+        sfv[curvec].sfv_len = *len; 
+        requested_len += sfv[curvec].sfv_len;
+
+        curvec++;
+    }
+    else {
+        vecs--;
+    }
+
+    /* Add the footers */
+    for (i = 0; i < hdtr->numtrailers; i++, curvec++) {
+        sfv[curvec].sfv_fd = SFV_FD_SELF;
+        sfv[curvec].sfv_flag = 0;
+        sfv[curvec].sfv_off = (unsigned long)hdtr->trailers[i].iov_base;
+        sfv[curvec].sfv_len = hdtr->trailers[i].iov_len;
+        requested_len += sfv[curvec].sfv_len;
+    }
+
+    /* If the last write couldn't send all the requested data,
+     * wait for the socket to become writable before proceeding
+     */
+    if (sock->options & APR_INCOMPLETE_WRITE) {
+        sock->options &= ~APR_INCOMPLETE_WRITE;
+        arv = apr_wait_for_io_or_timeout(NULL, sock, 0);
+        if (arv != APR_SUCCESS) {
+            *len = 0;
+            return arv;
+        }
+    }
+ 
+    /* Actually do the sendfilev
+     *
+     * Solaris may return -1/EAGAIN even if it sent bytes on a non-block sock.
+     *
+     * If no bytes were originally sent (nbytes == 0) and we are on a TIMEOUT 
+     * socket (which as far as the OS is concerned is a non-blocking socket), 
+     * we want to retry after waiting for the other side to read the data (as 
+     * determined by poll).  Once it is clear to send, we want to retry
+     * sending the sendfilevec_t once more.
+     */
+    arv = 0;
+    do {
+        /* Clear out the repeat */
+        repeat = 0;
+
+        /* socket, vecs, number of vecs, bytes written */
+        rv = sendfilev(sock->socketdes, sfv, vecs, &nbytes);
+
+        if (rv == -1 && errno == EAGAIN) {
+            if (nbytes) {
+                rv = 0;
+            }
+            else if (!arv && (sock->timeout > 0)) {
+                apr_status_t t = apr_wait_for_io_or_timeout(NULL, sock, 0);
+
+                if (t != APR_SUCCESS) {
+                    *len = 0;
+                    return t;
+                }
+
+                arv = 1; 
+                repeat = 1;
+            }
+        }
+    } while ((rv == -1 && errno == EINTR) || repeat);
+
+    if (rv == -1) {
+        *len = 0;
+        return errno;
+    }
+
+    /* Update how much we sent */
+    *len = nbytes;
+
+    if (nbytes == 0) {
+        /* Most likely the file got smaller after the stat.
+         * Return an error so the caller can do the Right Thing.
+         */
+        return APR_EOF;
+    }
+
+    if ((sock->timeout > 0) && (*len < requested_len)) {
+        sock->options |= APR_INCOMPLETE_WRITE;
+    }
     return APR_SUCCESS;
 }
 #else
-/* TODO: Add AIX support */
-#endif /* __linux__, __FreeBSD__, __HPUX__ */
-#endif /* HAVE_SENDFILE */
+#error APR has detected sendfile on your system, but nobody has written a
+#error version of it for APR yet.  To get past this, either write 
+#error apr_socket_sendfile or change APR_HAS_SENDFILE in apr.h to 0.
+#endif /* __linux__, __FreeBSD__, __DragonFly__, __HPUX__, _AIX, __MVS__,
+	  Tru64/OSF1 */
 
+#endif /* APR_HAS_SENDFILE */
diff --git a/network_io/unix/sockaddr.c b/network_io/unix/sockaddr.c
index a95fa8f0333..8e4bde3e3b4 100644
--- a/network_io/unix/sockaddr.c
+++ b/network_io/unix/sockaddr.c
@@ -1,161 +1,1279 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "networkio.h"
+#include "apr_arch_networkio.h"
+#include "apr_strings.h"
+#include "apr.h"
+#include "apr_lib.h"
+#include "apr_strings.h"
+#include "apr_private.h"
+
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef HAVE_NET_IF_H
+#include <net/if.h>
+#endif
+
+#define APR_WANT_STRFUNC
+#include "apr_want.h"
+
+struct apr_ipsubnet_t {
+    int family;
+#if APR_HAVE_IPV6
+    apr_uint32_t sub[4]; /* big enough for IPv4 and IPv6 addresses */
+    apr_uint32_t mask[4];
+#else
+    apr_uint32_t sub[1];
+    apr_uint32_t mask[1];
+#endif
+};
 
-ap_status_t ap_set_local_port(ap_socket_t *sock, ap_uint32_t port)
+#if !defined(NETWARE) && !defined(WIN32)
+#ifdef HAVE_SET_H_ERRNO
+#define SET_H_ERRNO(newval) set_h_errno(newval)
+#else
+#define SET_H_ERRNO(newval) h_errno = (newval)
+#endif
+#else
+#define SET_H_ERRNO(newval)
+#endif
+
+#if APR_HAS_THREADS && !defined(GETHOSTBYNAME_IS_THREAD_SAFE) && \
+    defined(HAVE_GETHOSTBYNAME_R)
+/* This is the maximum size that may be returned from the reentrant
+ * gethostbyname_r function.  If the system tries to use more, it
+ * should return ERANGE.
+ */
+#define GETHOSTBYNAME_BUFLEN 512
+#endif
+
+#ifdef _AIX
+/* Some levels of AIX getaddrinfo() don't like servname = "0", so
+ * set servname to "1" when port is 0 and fix it up later.
+ */
+#define AIX_SERVNAME_HACK 1
+#else
+#define AIX_SERVNAME_HACK 0
+#endif
+
+#ifdef _WIN32_WCE
+/* XXX: BS solution.  Need an HAVE_GETSERVBYNAME and actually
+ * do something here, to provide the obvious proto mappings.
+ */
+static void *getservbyname(const char *name, const char *proto)
 {
-    sock->local_addr->sin_port = htons((short)port);
-    return APR_SUCCESS;
+    return NULL;
 }
+#endif
 
+static apr_status_t get_local_addr(apr_socket_t *sock)
+{
+    sock->local_addr->salen = sizeof(sock->local_addr->sa);
+    if (getsockname(sock->socketdes, (struct sockaddr *)&sock->local_addr->sa,
+                    &sock->local_addr->salen) < 0) {
+        return apr_get_netos_error();
+    }
+    else {
+        sock->local_port_unknown = sock->local_interface_unknown = 0;
+        /* XXX assumes sin_port and sin6_port at same offset */
+        sock->local_addr->port = ntohs(sock->local_addr->sa.sin.sin_port);
+        return APR_SUCCESS;
+    }
+}
 
+static apr_status_t get_remote_addr(apr_socket_t *sock)
+{
+    sock->remote_addr->salen = sizeof(sock->remote_addr->sa);
+    if (getpeername(sock->socketdes, (struct sockaddr *)&sock->remote_addr->sa,
+                    &sock->remote_addr->salen) < 0) {
+        return apr_get_netos_error();
+    }
+    else {
+        sock->remote_addr_unknown = 0;
+        /* XXX assumes sin_port and sin6_port at same offset */
+        sock->remote_addr->port = ntohs(sock->remote_addr->sa.sin.sin_port);
+        return APR_SUCCESS;
+    }
+}
 
-ap_status_t ap_set_remote_port(ap_socket_t *sock, ap_uint32_t port)
+APR_DECLARE(apr_status_t) apr_sockaddr_ip_getbuf(char *buf, apr_size_t buflen,
+                                                 apr_sockaddr_t *sockaddr)
 {
-    sock->remote_addr->sin_port = htons((short)port);
+    if (!apr_inet_ntop(sockaddr->family, sockaddr->ipaddr_ptr, buf, buflen)) {
+        return APR_ENOSPC;
+    }
+
+#if APR_HAVE_IPV6
+    if (sockaddr->family == AF_INET6 
+        && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)sockaddr->ipaddr_ptr)
+        && buflen > strlen("::ffff:")) {
+        /* This is an IPv4-mapped IPv6 address; drop the leading
+         * part of the address string so we're left with the familiar
+         * IPv4 format.
+         */
+        memmove(buf, buf + strlen("::ffff:"),
+                strlen(buf + strlen("::ffff:"))+1);
+    }
+
+    /* ensure NUL termination if the buffer is too short */
+    buf[buflen-1] = '\0';
+
+#ifdef HAVE_IF_INDEXTONAME
+    /* Append scope name for link-local addresses. */
+    if (sockaddr->family == AF_INET6
+        && IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)sockaddr->ipaddr_ptr)) {
+        char scbuf[IF_NAMESIZE], *p = buf + strlen(buf);
+
+        if (if_indextoname(sockaddr->sa.sin6.sin6_scope_id, scbuf) == scbuf) {
+            /* Space check, need room for buf + '%' + scope + '\0'.
+             * Assert: buflen >= strlen(buf) + strlen(scbuf) + 2
+             * Equiv:  buflen >= (p-buf) + strlen(buf) + 2
+             * Thus, fail in inverse condition: */
+            if (buflen < strlen(scbuf) + (p - buf) + 2) {
+                return APR_ENOSPC;
+            }
+            *p++ = '%';
+            memcpy(p, scbuf, strlen(scbuf) + 1);
+        }
+    }    
+#endif /* HAVE_IF_INDEXTONAME */
+#endif /* APR_HAVE_IPV6 */
+
     return APR_SUCCESS;
 }
 
+APR_DECLARE(apr_status_t) apr_sockaddr_ip_get(char **addr,
+                                              apr_sockaddr_t *sockaddr)
+{
+    *addr = apr_palloc(sockaddr->pool, sockaddr->addr_str_len);
+    return apr_sockaddr_ip_getbuf(*addr, sockaddr->addr_str_len, sockaddr);
+}
 
+void apr_sockaddr_vars_set(apr_sockaddr_t *addr, int family, apr_port_t port)
+{
+    addr->family = family;
+    addr->sa.sin.sin_family = family;
+    if (port) {
+        /* XXX IPv6: assumes sin_port and sin6_port at same offset */
+        addr->sa.sin.sin_port = htons(port);
+        addr->port = port;
+    }
+#if AIX_SERVNAME_HACK
+    else {
+        addr->sa.sin.sin_port = htons(port);
+    }
+#endif
 
-ap_status_t ap_get_local_port(ap_uint32_t *port, ap_socket_t *sock)
+    if (family == APR_INET) {
+        addr->salen = sizeof(struct sockaddr_in);
+        addr->addr_str_len = 16;
+        addr->ipaddr_ptr = &(addr->sa.sin.sin_addr);
+        addr->ipaddr_len = sizeof(struct in_addr);
+    }
+#if APR_HAVE_IPV6
+    else if (family == APR_INET6) {
+        addr->salen = sizeof(struct sockaddr_in6);
+        addr->addr_str_len = 46;
+        addr->ipaddr_ptr = &(addr->sa.sin6.sin6_addr);
+        addr->ipaddr_len = sizeof(struct in6_addr);
+    }
+#endif
+#if APR_HAVE_SOCKADDR_UN
+    else if (family == APR_UNIX) {
+        addr->salen = sizeof(struct sockaddr_un);
+        addr->addr_str_len = sizeof(addr->sa.unx.sun_path);;
+        addr->ipaddr_ptr = &(addr->sa.unx.sun_path);
+        addr->ipaddr_len = addr->addr_str_len;
+    }
+#endif
+}
+
+APR_DECLARE(apr_status_t) apr_socket_addr_get(apr_sockaddr_t **sa,
+                                           apr_interface_e which,
+                                           apr_socket_t *sock)
 {
-    *port = ntohs(sock->local_addr->sin_port);
+    if (which == APR_LOCAL) {
+        if (sock->local_interface_unknown || sock->local_port_unknown) {
+            apr_status_t rv = get_local_addr(sock);
+
+            if (rv != APR_SUCCESS) {
+                return rv;
+            }
+        }
+        *sa = sock->local_addr;
+    }
+    else if (which == APR_REMOTE) {
+        if (sock->remote_addr_unknown) {
+            apr_status_t rv = get_remote_addr(sock);
+
+            if (rv != APR_SUCCESS) {
+                return rv;
+            }
+        }
+        *sa = sock->remote_addr;
+    }
+    else {
+        *sa = NULL;
+        return APR_EINVAL;
+    }
     return APR_SUCCESS;
 }
 
+APR_DECLARE(apr_status_t) apr_parse_addr_port(char **addr,
+                                              char **scope_id,
+                                              apr_port_t *port,
+                                              const char *str,
+                                              apr_pool_t *p)
+{
+    const char *ch, *lastchar;
+    int big_port;
+    apr_size_t addrlen;
+
+    *addr = NULL;         /* assume not specified */
+    *scope_id = NULL;     /* assume not specified */
+    *port = 0;            /* assume not specified */
+
+    /* First handle the optional port number.  That may be all that
+     * is specified in the string.
+     */
+    ch = lastchar = str + strlen(str) - 1;
+    while (ch >= str && apr_isdigit(*ch)) {
+        --ch;
+    }
+
+    if (ch < str) {       /* Entire string is the port. */
+        big_port = atoi(str);
+        if (big_port < 1 || big_port > 65535) {
+            return APR_EINVAL;
+        }
+        *port = big_port;
+        return APR_SUCCESS;
+    }
+
+    if (*ch == ':' && ch < lastchar) { /* host and port number specified */
+        if (ch == str) {               /* string starts with ':' -- bad */
+            return APR_EINVAL;
+        }
+        big_port = atoi(ch + 1);
+        if (big_port < 1 || big_port > 65535) {
+            return APR_EINVAL;
+        }
+        *port = big_port;
+        lastchar = ch - 1;
+    }
+
+    /* now handle the hostname */
+    addrlen = lastchar - str + 1;
+
+/* XXX we don't really have to require APR_HAVE_IPV6 for this; 
+ * just pass char[] for ipaddr (so we don't depend on struct in6_addr)
+ * and always define APR_INET6 
+ */
+#if APR_HAVE_IPV6
+    if (*str == '[') {
+        const char *end_bracket = memchr(str, ']', addrlen);
+        struct in6_addr ipaddr;
+        const char *scope_delim;
+
+        if (!end_bracket || end_bracket != lastchar) {
+            *port = 0;
+            return APR_EINVAL;
+        }
+
+        /* handle scope id; this is the only context where it is allowed */
+        scope_delim = memchr(str, '%', addrlen);
+        if (scope_delim) {
+            if (scope_delim == end_bracket - 1) { /* '%' without scope id */
+                *port = 0;
+                return APR_EINVAL;
+            }
+            addrlen = scope_delim - str - 1;
+            *scope_id = apr_pstrmemdup(p, scope_delim + 1, end_bracket - scope_delim - 1);
+        }
+        else {
+            addrlen = addrlen - 2; /* minus 2 for '[' and ']' */
+        }
+
+        *addr = apr_pstrmemdup(p, str + 1, addrlen);
+        if (apr_inet_pton(AF_INET6, *addr, &ipaddr) != 1) {
+            *addr = NULL;
+            *scope_id = NULL;
+            *port = 0;
+            return APR_EINVAL;
+        }
+    }
+    else 
+#endif
+    {
+        /* XXX If '%' is not a valid char in a DNS name, we *could* check 
+         *     for bogus scope ids first.
+         */
+        *addr = apr_pstrmemdup(p, str, addrlen);
+    }
+    return APR_SUCCESS;
+}
 
+#if defined(HAVE_GETADDRINFO)
 
-ap_status_t ap_get_remote_port(ap_uint32_t *port, ap_socket_t *sock)
+static apr_status_t call_resolver(apr_sockaddr_t **sa,
+                                  const char *hostname, apr_int32_t family,
+                                  apr_port_t port, apr_int32_t flags, 
+                                  apr_pool_t *p)
 {
-    *port = ntohs(sock->remote_addr->sin_port);
+    struct addrinfo hints, *ai, *ai_list;
+    apr_sockaddr_t *prev_sa;
+    int error;
+    char *servname = NULL; 
+
+    memset(&hints, 0, sizeof(hints));
+    hints.ai_family = family;
+    hints.ai_socktype = SOCK_STREAM;
+#ifdef HAVE_GAI_ADDRCONFIG
+    if (family == APR_UNSPEC) {
+        /* By default, only look up addresses using address types for
+         * which a local interface is configured, i.e. no IPv6 if no
+         * IPv6 interfaces configured. */
+        hints.ai_flags = AI_ADDRCONFIG;
+    }
+#endif
+
+#ifdef __MVS__
+    /* z/OS will not return IPv4 address under AF_UNSPEC if any IPv6 results 
+     * are returned, w/o AI_ALL. 
+     */
+    if (family == APR_UNSPEC) { 
+       hints.ai_flags |= AI_ALL;
+    }
+#endif
+
+    if(hostname == NULL) {
+#ifdef AI_PASSIVE 
+        /* If hostname is NULL, assume we are trying to bind to all
+         * interfaces. */
+        hints.ai_flags |= AI_PASSIVE;
+#endif
+        /* getaddrinfo according to RFC 2553 must have either hostname
+         * or servname non-NULL.
+         */
+#ifdef OSF1
+        /* The Tru64 5.0 getaddrinfo() can only resolve services given
+         * by the name listed in /etc/services; a numeric or unknown
+         * servname gets an EAI_SERVICE error.  So just resolve the
+         * appropriate anyaddr and fill in the port later. */
+        hostname = family == AF_INET6 ? "::" : "0.0.0.0";
+        servname = NULL;
+#ifdef AI_NUMERICHOST
+        hints.ai_flags |= AI_NUMERICHOST;
+#endif
+#else
+#if AIX_SERVNAME_HACK
+        if (!port) {
+            servname = "1";
+        }
+        else
+#endif /* AIX_SERVNAME_HACK */
+        servname = apr_itoa(p, port);
+#endif /* OSF1 */
+    }
+    error = getaddrinfo(hostname, servname, &hints, &ai_list);
+#ifdef HAVE_GAI_ADDRCONFIG
+    /*
+     * Using AI_ADDRCONFIG involves some unfortunate guesswork because it
+     * does not consider loopback addresses when trying to determine if
+     * IPv4 or IPv6 is configured on a system (see RFC 3493).
+     * This is a problem if one actually wants to listen on or connect to
+     * the loopback address of a protocol family that is not otherwise
+     * configured on the system. See PR 52709.
+     * To work around some of the problems, retry without AI_ADDRCONFIG
+     * in case of EAI_ADDRFAMILY.
+     * XXX: apr_sockaddr_info_get() should really accept a flag to determine
+     * XXX: if AI_ADDRCONFIG's guesswork is wanted and if the address is
+     * XXX: to be used for listen() or connect().
+     *
+     * In case of EAI_BADFLAGS, AI_ADDRCONFIG is not supported.
+     */
+    if ((family == APR_UNSPEC) && (error == EAI_BADFLAGS
+#ifdef EAI_ADDRFAMILY
+                                   || error == EAI_ADDRFAMILY
+#endif
+                                                             )) {
+        hints.ai_flags &= ~AI_ADDRCONFIG;
+        error = getaddrinfo(hostname, servname, &hints, &ai_list);
+    }
+#endif
+    if (error) {
+#if defined(WIN32)
+        return apr_get_netos_error();
+#else
+        if (error == EAI_SYSTEM) {
+            return errno ? errno : APR_EGENERAL;
+        }
+        else 
+        {
+            /* issues with representing this with APR's error scheme:
+             * glibc uses negative values for these numbers, perhaps so 
+             * they don't conflict with h_errno values...  Tru64 uses 
+             * positive values which conflict with h_errno values
+             */
+#if defined(NEGATIVE_EAI)
+            error = -error;
+#endif
+            return error + APR_OS_START_EAIERR;
+        }
+#endif /* WIN32 */
+    }
+
+    prev_sa = NULL;
+    ai = ai_list;
+    while (ai) { /* while more addresses to report */
+        apr_sockaddr_t *new_sa;
+
+        /* Ignore anything bogus: getaddrinfo in some old versions of
+         * glibc will return AF_UNIX entries for APR_UNSPEC+AI_PASSIVE
+         * lookups. */
+#if APR_HAVE_IPV6
+        if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) {
+#else
+        if (ai->ai_family != AF_INET) {
+#endif
+            ai = ai->ai_next;
+            continue;
+        }
+
+        new_sa = apr_pcalloc(p, sizeof(apr_sockaddr_t));
+
+        new_sa->pool = p;
+        memcpy(&new_sa->sa, ai->ai_addr, ai->ai_addrlen);
+        apr_sockaddr_vars_set(new_sa, ai->ai_family, port);
+
+        if (!prev_sa) { /* first element in new list */
+            if (hostname) {
+                new_sa->hostname = apr_pstrdup(p, hostname);
+            }
+            *sa = new_sa;
+        }
+        else {
+            new_sa->hostname = prev_sa->hostname;
+            prev_sa->next = new_sa;
+        }
+
+        prev_sa = new_sa;
+        ai = ai->ai_next;
+    }
+    freeaddrinfo(ai_list);
+
+    if (prev_sa == NULL) {
+        /*
+         * getaddrinfo returned only useless entries and *sa is still empty.
+         * This should be treated as an error.
+         */
+        return APR_EGENERAL;
+    }
+
     return APR_SUCCESS;
 }
 
+static apr_status_t find_addresses(apr_sockaddr_t **sa, 
+                                   const char *hostname, apr_int32_t family,
+                                   apr_port_t port, apr_int32_t flags, 
+                                   apr_pool_t *p)
+{
+    if (flags & APR_IPV4_ADDR_OK) {
+        apr_status_t error = call_resolver(sa, hostname, AF_INET, port, flags, p);
+
+#if APR_HAVE_IPV6
+        if (error) {
+            family = AF_INET6; /* try again */
+        }
+        else
+#endif
+        return error;
+    }
+#if APR_HAVE_IPV6
+    else if (flags & APR_IPV6_ADDR_OK) {
+        apr_status_t error = call_resolver(sa, hostname, AF_INET6, port, flags, p);
+
+        if (error) {
+            family = AF_INET; /* try again */
+        }
+        else {
+            return APR_SUCCESS;
+        }
+    }
+#endif
+
+    return call_resolver(sa, hostname, family, port, flags, p);
+}
 
+#else /* end of HAVE_GETADDRINFO code */
 
-ap_status_t ap_set_local_ipaddr(ap_socket_t *sock, const char *addr)
+static apr_status_t find_addresses(apr_sockaddr_t **sa, 
+                                   const char *hostname, apr_int32_t family,
+                                   apr_port_t port, apr_int32_t flags, 
+                                   apr_pool_t *p)
 {
-    u_long ipaddr;
-    
-    if (!strcmp(addr, APR_ANYADDR)) {
-        sock->local_addr->sin_addr.s_addr = htonl(INADDR_ANY);
-        return APR_SUCCESS;
+    struct hostent *hp;
+    apr_sockaddr_t *prev_sa;
+    int curaddr;
+#if APR_HAS_THREADS && !defined(GETHOSTBYNAME_IS_THREAD_SAFE) && \
+    defined(HAVE_GETHOSTBYNAME_R) && !defined(BEOS)
+#ifdef GETHOSTBYNAME_R_HOSTENT_DATA
+    struct hostent_data hd;
+#else
+    /* If you see ERANGE, that means GETHOSBYNAME_BUFLEN needs to be
+     * bumped. */
+    char tmp[GETHOSTBYNAME_BUFLEN];
+#endif
+    int hosterror;
+#endif
+    struct hostent hs;
+    struct in_addr ipaddr;
+    char *addr_list[2];
+    const char *orig_hostname = hostname;
+
+    if (hostname == NULL) {
+        /* if we are given a NULL hostname, assume '0.0.0.0' */
+        hostname = "0.0.0.0";
     }
-    
-    ipaddr = inet_addr(addr);
-    
-    if (ipaddr == -1) {
-        return errno;
+
+    if (*hostname >= '0' && *hostname <= '9' &&
+        strspn(hostname, "0123456789.") == strlen(hostname)) {
+
+        ipaddr.s_addr = inet_addr(hostname);
+        addr_list[0] = (char *)&ipaddr;
+        addr_list[1] = NULL; /* just one IP in list */
+        hs.h_addr_list = (char **)addr_list;
+        hp = &hs;
     }
-    
-    sock->local_addr->sin_addr.s_addr = ipaddr;
+    else {
+#if APR_HAS_THREADS && !defined(GETHOSTBYNAME_IS_THREAD_SAFE) && \
+    defined(HAVE_GETHOSTBYNAME_R) && !defined(BEOS)
+#if defined(GETHOSTBYNAME_R_HOSTENT_DATA)
+        /* AIX, HP/UX, D/UX et alia */
+        gethostbyname_r(hostname, &hs, &hd);
+        hp = &hs;
+#else
+#if defined(GETHOSTBYNAME_R_GLIBC2)
+        /* Linux glibc2+ */
+        gethostbyname_r(hostname, &hs, tmp, GETHOSTBYNAME_BUFLEN - 1, 
+                        &hp, &hosterror);
+#else
+        /* Solaris, Irix et alia */
+        hp = gethostbyname_r(hostname, &hs, tmp, GETHOSTBYNAME_BUFLEN - 1,
+                             &hosterror);
+#endif /* !defined(GETHOSTBYNAME_R_GLIBC2) */
+        if (!hp) {
+            return (hosterror + APR_OS_START_SYSERR);
+        }
+#endif /* !defined(GETHOSTBYNAME_R_HOSTENT_DATA) */
+#else
+        hp = gethostbyname(hostname);
+#endif
+
+        if (!hp) {
+#ifdef WIN32
+            return apr_get_netos_error();
+#else
+            return (h_errno + APR_OS_START_SYSERR);
+#endif
+        }
+    }
+
+    prev_sa = NULL;
+    curaddr = 0;
+    while (hp->h_addr_list[curaddr]) {
+        apr_sockaddr_t *new_sa = apr_pcalloc(p, sizeof(apr_sockaddr_t));
+
+        new_sa->pool = p;
+        new_sa->sa.sin.sin_addr = *(struct in_addr *)hp->h_addr_list[curaddr];
+        apr_sockaddr_vars_set(new_sa, AF_INET, port);
+
+        if (!prev_sa) { /* first element in new list */
+            if (orig_hostname) {
+                new_sa->hostname = apr_pstrdup(p, orig_hostname);
+            }
+            *sa = new_sa;
+        }
+        else {
+            new_sa->hostname = prev_sa->hostname;
+            prev_sa->next = new_sa;
+        }
+
+        prev_sa = new_sa;
+        ++curaddr;
+    }
+
+    if (prev_sa == NULL) {
+        /* this should not happen but no result should be treated as error */
+        return APR_EGENERAL;
+    }
+
     return APR_SUCCESS;
 }
 
+#endif /* end of !HAVE_GETADDRINFO code */
 
+APR_DECLARE(apr_status_t) apr_sockaddr_info_get(apr_sockaddr_t **sa,
+                                                const char *hostname, 
+                                                apr_int32_t family, apr_port_t port,
+                                                apr_int32_t flags, apr_pool_t *p)
+{
+    apr_int32_t masked;
+    *sa = NULL;
 
-ap_status_t ap_set_remote_ipaddr(ap_socket_t *sock, const char *addr)
+    if ((masked = flags & (APR_IPV4_ADDR_OK | APR_IPV6_ADDR_OK))) {
+        if (!hostname ||
+            family != APR_UNSPEC ||
+            masked == (APR_IPV4_ADDR_OK | APR_IPV6_ADDR_OK)) {
+            return APR_EINVAL;
+        }
+#if !APR_HAVE_IPV6
+        if (flags & APR_IPV6_ADDR_OK) {
+            return APR_ENOTIMPL;
+        }
+#endif
+    }
+    if (family == APR_UNSPEC && hostname && *hostname == '/')
+        family = APR_UNIX;
+    if (family == APR_UNIX) {
+#if APR_HAVE_SOCKADDR_UN
+        if (hostname) {
+            *sa = apr_pcalloc(p, sizeof(apr_sockaddr_t));
+            (*sa)->pool = p;
+            apr_cpystrn((*sa)->sa.unx.sun_path, hostname,
+                        sizeof((*sa)->sa.unx.sun_path));
+            (*sa)->hostname = apr_pstrdup(p, hostname);
+            (*sa)->family = APR_UNIX;
+            (*sa)->sa.unx.sun_family = APR_UNIX;
+            (*sa)->salen = sizeof(struct sockaddr_un);
+            (*sa)->addr_str_len = sizeof((*sa)->sa.unx.sun_path);
+            (*sa)->ipaddr_ptr = &((*sa)->sa.unx.sun_path);
+            (*sa)->ipaddr_len = (*sa)->addr_str_len;
+
+            return APR_SUCCESS;
+        }
+        else
+#endif
+        {
+            *sa = NULL;
+            return APR_ENOTIMPL;
+        }
+    }
+#if !APR_HAVE_IPV6
+    /* What may happen is that APR is not IPv6-enabled, but we're still
+     * going to call getaddrinfo(), so we have to tell the OS we only
+     * want IPv4 addresses back since we won't know what to do with
+     * IPv6 addresses.
+     */
+    if (family == APR_UNSPEC) {
+        family = APR_INET;
+    }
+#endif
+
+    return find_addresses(sa, hostname, family, port, flags, p);
+}
+
+APR_DECLARE(apr_status_t) apr_sockaddr_info_copy(apr_sockaddr_t **dst,
+                                                 const apr_sockaddr_t *src,
+                                                 apr_pool_t *p)
 {
-    u_long ipaddr;
-    
-    if (!strcmp(addr, APR_ANYADDR)) {
-        sock->remote_addr->sin_addr.s_addr = htonl(INADDR_ANY);
+    apr_sockaddr_t *d;
+    const apr_sockaddr_t *s;
+
+    for (*dst = d = NULL, s = src; s; s = s->next) {
+        if (!d) {
+            *dst = d = apr_pmemdup(p, s, sizeof *s);
+        }
+        else {
+            d = d->next = apr_pmemdup(p, s, sizeof *s);
+        }
+        if (s->hostname) {
+            if (s == src || s->hostname != src->hostname) {
+                d->hostname = apr_pstrdup(p, s->hostname);
+            }
+            else {
+                d->hostname = (*dst)->hostname;
+            }
+        }
+        if (s->servname) {
+            if (s == src || s->servname != src->servname) {
+                d->servname = apr_pstrdup(p, s->servname);
+            }
+            else {
+                d->servname = (*dst)->servname;
+            }
+        }
+        d->pool = p;
+        apr_sockaddr_vars_set(d, s->family, s->port);
+    }
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_getnameinfo(char **hostname,
+                                          apr_sockaddr_t *sockaddr,
+                                          apr_int32_t flags)
+{
+#if defined(HAVE_GETNAMEINFO)
+    int rc;
+#if defined(NI_MAXHOST)
+    char tmphostname[NI_MAXHOST];
+#else
+    char tmphostname[256];
+#endif
+
+    /* don't know if it is portable for getnameinfo() to set h_errno;
+     * clear it then see if it was set */
+    SET_H_ERRNO(0);
+
+    /* default flags are NI_NAMREQD; otherwise, getnameinfo() will return
+     * a numeric address string if it fails to resolve the host name;
+     * that is *not* what we want here
+     *
+     * For IPv4-mapped IPv6 addresses, drop down to IPv4 before calling
+     * getnameinfo() to avoid getnameinfo bugs (MacOS X, glibc).
+     */
+#if APR_HAVE_IPV6
+    if (sockaddr->family == AF_INET6 &&
+        IN6_IS_ADDR_V4MAPPED(&sockaddr->sa.sin6.sin6_addr)) {
+        struct sockaddr_in tmpsa;
+        tmpsa.sin_family = AF_INET;
+        tmpsa.sin_port = 0;
+        tmpsa.sin_addr.s_addr = ((apr_uint32_t *)sockaddr->ipaddr_ptr)[3];
+#ifdef SIN6_LEN
+        tmpsa.sin_len = sizeof(tmpsa);
+#endif
+
+        rc = getnameinfo((const struct sockaddr *)&tmpsa, sizeof(tmpsa),
+                         tmphostname, sizeof(tmphostname), NULL, 0,
+                         flags != 0 ? flags : NI_NAMEREQD);
+    }
+#if APR_HAVE_SOCKADDR_UN
+    else if (sockaddr->family == APR_UNIX) {
+        *hostname = apr_pstrdup(sockaddr->pool, sockaddr->hostname);
         return APR_SUCCESS;
     }
-    
-    ipaddr = inet_addr(addr);
-    
-    if (ipaddr == (u_long)-1) {
-        return errno;
+#endif
+    else
+#endif
+    rc = getnameinfo((const struct sockaddr *)&sockaddr->sa, sockaddr->salen,
+                     tmphostname, sizeof(tmphostname), NULL, 0,
+                     flags != 0 ? flags : NI_NAMEREQD);
+    if (rc != 0) {
+        *hostname = NULL;
+
+#ifndef WIN32
+        /* something went wrong. Look at the EAI_ error code */
+        if (rc == EAI_SYSTEM) {
+            /* EAI_SYSTEM      System error returned in errno. */
+            /* IMHO, Implementations that set h_errno a simply broken. */
+            if (h_errno) { /* for broken implementations which set h_errno */
+                return h_errno + APR_OS_START_SYSERR;
+            }
+            else { /* "normal" case */
+                return errno + APR_OS_START_SYSERR;
+            }
+        }
+        else 
+#endif
+        {
+#if defined(NEGATIVE_EAI)
+            if (rc < 0) rc = -rc;
+#endif
+            return rc + APR_OS_START_EAIERR; /* return the EAI_ error */
+        }
     }
-    
-    sock->remote_addr->sin_addr.s_addr = ipaddr;
+    *hostname = sockaddr->hostname = apr_pstrdup(sockaddr->pool, 
+                                                 tmphostname);
     return APR_SUCCESS;
+#else
+#if APR_HAS_THREADS && !defined(GETHOSTBYADDR_IS_THREAD_SAFE) && \
+    defined(HAVE_GETHOSTBYADDR_R) && !defined(BEOS)
+#ifdef GETHOSTBYNAME_R_HOSTENT_DATA
+    struct hostent_data hd;
+#else
+    char tmp[GETHOSTBYNAME_BUFLEN];
+#endif
+    int hosterror;
+    struct hostent hs, *hptr;
+
+#if defined(GETHOSTBYNAME_R_HOSTENT_DATA)
+    /* AIX, HP/UX, D/UX et alia */
+    gethostbyaddr_r((char *)&sockaddr->sa.sin.sin_addr, 
+                  sizeof(struct in_addr), AF_INET, &hs, &hd);
+    hptr = &hs;
+#else
+#if defined(GETHOSTBYNAME_R_GLIBC2)
+    /* Linux glibc2+ */
+    gethostbyaddr_r((char *)&sockaddr->sa.sin.sin_addr, 
+                    sizeof(struct in_addr), AF_INET,
+                    &hs, tmp, GETHOSTBYNAME_BUFLEN - 1, &hptr, &hosterror);
+#else
+    /* Solaris, Irix et alia */
+    hptr = gethostbyaddr_r((char *)&sockaddr->sa.sin.sin_addr, 
+                           sizeof(struct in_addr), AF_INET,
+                           &hs, tmp, GETHOSTBYNAME_BUFLEN, &hosterror);
+#endif /* !defined(GETHOSTBYNAME_R_GLIBC2) */
+    if (!hptr) {
+        *hostname = NULL;
+        return hosterror + APR_OS_START_SYSERR;
+    }
+#endif /* !defined(GETHOSTBYNAME_R_HOSTENT_DATA) */
+#else
+    struct hostent *hptr;
+    hptr = gethostbyaddr((char *)&sockaddr->sa.sin.sin_addr, 
+                         sizeof(struct in_addr), AF_INET);
+#endif
+
+    if (hptr) {
+        *hostname = sockaddr->hostname = apr_pstrdup(sockaddr->pool, hptr->h_name);
+        return APR_SUCCESS;
+    }
+    *hostname = NULL;
+#if defined(WIN32)
+    return apr_get_netos_error();
+#elif defined(OS2)
+    return h_errno;
+#else
+    return h_errno + APR_OS_START_SYSERR;
+#endif
+#endif
 }
 
+APR_DECLARE(apr_status_t) apr_getservbyname(apr_sockaddr_t *sockaddr,
+                                            const char *servname)
+{
+#if APR_HAS_THREADS && !defined(GETSERVBYNAME_IS_THREAD_SAFE) && \
+    defined(HAVE_GETSERVBYNAME_R) && \
+    (defined(GETSERVBYNAME_R_GLIBC2) || defined(GETSERVBYNAME_R_SOLARIS) || \
+     defined(GETSERVBYNAME_R_OSF1))
+    struct servent se;
+#if defined(GETSERVBYNAME_R_OSF1)
+    struct servent_data sed;
+
+    memset(&sed, 0, sizeof(sed)); /* must zero fill before use */
+#else
+#if defined(GETSERVBYNAME_R_GLIBC2)
+    struct servent *res;
+#endif
+    char buf[1024];
+#endif
+#else
+    struct servent *se;
+#endif
 
+    if (servname == NULL)
+        return APR_EINVAL;
 
-ap_status_t ap_get_local_ipaddr(char **addr, const ap_socket_t *sock)
+#if APR_HAS_THREADS && !defined(GETSERVBYNAME_IS_THREAD_SAFE) && \
+    defined(HAVE_GETSERVBYNAME_R) && \
+    (defined(GETSERVBYNAME_R_GLIBC2) || defined(GETSERVBYNAME_R_SOLARIS) || \
+     defined(GETSERVBYNAME_R_OSF1))
+#if defined(GETSERVBYNAME_R_GLIBC2)
+    if (getservbyname_r(servname, NULL,
+                        &se, buf, sizeof(buf), &res) == 0 && res != NULL) {
+        sockaddr->port = ntohs(res->s_port);
+        sockaddr->servname = apr_pstrdup(sockaddr->pool, servname);
+        sockaddr->sa.sin.sin_port = res->s_port;
+        return APR_SUCCESS;
+    }
+#elif defined(GETSERVBYNAME_R_SOLARIS)
+    if (getservbyname_r(servname, NULL, &se, buf, sizeof(buf)) != NULL) {
+        sockaddr->port = ntohs(se.s_port);
+        sockaddr->servname = apr_pstrdup(sockaddr->pool, servname);
+        sockaddr->sa.sin.sin_port = se.s_port;
+        return APR_SUCCESS;
+    }
+#elif defined(GETSERVBYNAME_R_OSF1)
+    if (getservbyname_r(servname, NULL, &se, &sed) == 0) {
+        sockaddr->port = ntohs(se.s_port);
+        sockaddr->servname = apr_pstrdup(sockaddr->pool, servname);
+        sockaddr->sa.sin.sin_port = se.s_port;
+        return APR_SUCCESS;
+    }
+#endif
+#else
+    if ((se = getservbyname(servname, NULL)) != NULL){
+        sockaddr->port = ntohs(se->s_port);
+        sockaddr->servname = apr_pstrdup(sockaddr->pool, servname);
+        sockaddr->sa.sin.sin_port = se->s_port;
+        return APR_SUCCESS;
+    }
+#endif
+    return APR_ENOENT;
+}
+
+#define V4MAPPED_EQUAL(a,b)                                   \
+((a)->sa.sin.sin_family == AF_INET &&                         \
+ (b)->sa.sin.sin_family == AF_INET6 &&                        \
+ IN6_IS_ADDR_V4MAPPED((struct in6_addr *)(b)->ipaddr_ptr) &&  \
+ !memcmp((a)->ipaddr_ptr,                                     \
+         &((struct in6_addr *)(b)->ipaddr_ptr)->s6_addr[12],  \
+         (a)->ipaddr_len))
+
+#if APR_HAVE_IPV6
+#define SCOPE_OR_ZERO(sa_) ((sa_)->family != AF_INET6 ? 0 :   \
+                            ((sa_)->sa.sin6.sin6_scope_id))
+#else
+#define SCOPE_OR_ZERO(sa_) (0)
+#endif
+
+APR_DECLARE(int) apr_sockaddr_equal(const apr_sockaddr_t *addr1,
+                                    const apr_sockaddr_t *addr2)
 {
-    *addr = ap_pstrdup(sock->cntxt, inet_ntoa(sock->local_addr->sin_addr));
-    return APR_SUCCESS;
+    if (addr1->ipaddr_len == addr2->ipaddr_len
+        && !memcmp(addr1->ipaddr_ptr, addr2->ipaddr_ptr, addr1->ipaddr_len)
+        && SCOPE_OR_ZERO(addr1) == SCOPE_OR_ZERO(addr2)) {
+        return 1;
+    }
+#if APR_HAVE_IPV6
+    if (V4MAPPED_EQUAL(addr1, addr2)) {
+        return 1;
+    }
+    if (V4MAPPED_EQUAL(addr2, addr1)) {
+        return 1;
+    }
+#endif
+    return 0; /* not equal */
 }
 
+APR_DECLARE(int) apr_sockaddr_is_wildcard(const apr_sockaddr_t *addr)
+{
+    static const char inaddr_any[
+#if APR_HAVE_IPV6
+        sizeof(struct in6_addr)
+#else
+        sizeof(struct in_addr)
+#endif
+    ] = {0};
 
+    if (addr->ipaddr_ptr /* IP address initialized */
+        && addr->ipaddr_len <= sizeof inaddr_any) { /* else bug elsewhere? */
+        if (!memcmp(inaddr_any, addr->ipaddr_ptr, addr->ipaddr_len)) {
+            return 1;
+        }
+#if APR_HAVE_IPV6
+    if (addr->family == AF_INET6
+        && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)addr->ipaddr_ptr)) {
+        struct in_addr *v4 = (struct in_addr *)&((apr_uint32_t *)addr->ipaddr_ptr)[3];
 
-ap_status_t ap_get_remote_ipaddr(char **addr, const ap_socket_t *sock)
+        if (!memcmp(inaddr_any, v4, sizeof *v4)) {
+            return 1;
+        }
+    }
+#endif
+    }
+    return 0;
+}
+
+static apr_status_t parse_network(apr_ipsubnet_t *ipsub, const char *network)
 {
-    *addr = ap_pstrdup(sock->cntxt, inet_ntoa(sock->remote_addr->sin_addr));
+    /* legacy syntax for ip addrs: a.b.c. ==> a.b.c.0/24 for example */
+    int shift;
+    char *s, *t;
+    int octet;
+    char buf[sizeof "255.255.255.255"];
+
+    if (strlen(network) < sizeof buf) {
+        strcpy(buf, network);
+    }
+    else {
+        return APR_EBADIP;
+    }
+
+    /* parse components */
+    s = buf;
+    ipsub->sub[0] = 0;
+    ipsub->mask[0] = 0;
+    shift = 24;
+    while (*s) {
+        t = s;
+        if (!apr_isdigit(*t)) {
+            return APR_EBADIP;
+        }
+        while (apr_isdigit(*t)) {
+            ++t;
+        }
+        if (*t == '.') {
+            *t++ = 0;
+        }
+        else if (*t) {
+            return APR_EBADIP;
+        }
+        if (shift < 0) {
+            return APR_EBADIP;
+        }
+        octet = atoi(s);
+        if (octet < 0 || octet > 255) {
+            return APR_EBADIP;
+        }
+        ipsub->sub[0] |= octet << shift;
+        ipsub->mask[0] |= 0xFFUL << shift;
+        s = t;
+        shift -= 8;
+    }
+    ipsub->sub[0] = ntohl(ipsub->sub[0]);
+    ipsub->mask[0] = ntohl(ipsub->mask[0]);
+    ipsub->family = AF_INET;
     return APR_SUCCESS;
 }
 
+/* return values:
+ * APR_EINVAL     not an IP address; caller should see if it is something else
+ * APR_BADIP      IP address portion is is not valid
+ * APR_BADMASK    mask portion is not valid
+ */
 
-
-#if HAVE_NETINET_IN_H
-ap_status_t ap_get_local_name(struct sockaddr_in **name, const ap_socket_t *sock)
+static apr_status_t parse_ip(apr_ipsubnet_t *ipsub, const char *ipstr, int network_allowed)
 {
-    *name = sock->local_addr;
+    /* supported flavors of IP:
+     *
+     * . IPv6 numeric address string (e.g., "fe80::1")
+     * 
+     *   IMPORTANT: Don't store IPv4-mapped IPv6 address as an IPv6 address.
+     *
+     * . IPv4 numeric address string (e.g., "127.0.0.1")
+     *
+     * . IPv4 network string (e.g., "9.67")
+     *
+     *   IMPORTANT: This network form is only allowed if network_allowed is on.
+     */
+    int rc;
+
+#if APR_HAVE_IPV6
+    rc = apr_inet_pton(AF_INET6, ipstr, ipsub->sub);
+    if (rc == 1) {
+        if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ipsub->sub)) {
+            /* apr_ipsubnet_test() assumes that we don't create IPv4-mapped IPv6
+             * addresses; this of course forces the user to specify IPv4 addresses
+             * in a.b.c.d style instead of ::ffff:a.b.c.d style.
+             */
+            return APR_EBADIP;
+        }
+        ipsub->family = AF_INET6;
+    }
+    else
+#endif
+    {
+        rc = apr_inet_pton(AF_INET, ipstr, ipsub->sub);
+        if (rc == 1) {
+            ipsub->family = AF_INET;
+        }
+    }
+    if (rc != 1) {
+        if (network_allowed) {
+            return parse_network(ipsub, ipstr);
+        }
+        else {
+            return APR_EBADIP;
+        }
+    }
     return APR_SUCCESS;
 }
 
+static int looks_like_ip(const char *ipstr)
+{
+    if (strlen(ipstr) == 0) {
+        return 0;
+    }
+    
+    if (strchr(ipstr, ':')) {
+        /* definitely not a hostname; assume it is intended to be an IPv6 address */
+        return 1;
+    }
 
+    /* simple IPv4 address string check */
+    while ((*ipstr == '.') || apr_isdigit(*ipstr))
+        ipstr++;
+    return (*ipstr == '\0');
+}
 
-ap_status_t ap_get_remote_name(struct sockaddr_in **name, const ap_socket_t *sock)
+static void fix_subnet(apr_ipsubnet_t *ipsub)
 {
-    *name = sock->remote_addr;
+    /* in case caller specified more bits in network address than are
+     * valid according to the mask, turn off the extra bits
+     */
+    int i;
+
+    for (i = 0; i < sizeof ipsub->mask / sizeof(apr_int32_t); i++) {
+        ipsub->sub[i] &= ipsub->mask[i];
+    }
+}
+
+/* be sure not to store any IPv4 address as a v4-mapped IPv6 address */
+APR_DECLARE(apr_status_t) apr_ipsubnet_create(apr_ipsubnet_t **ipsub, const char *ipstr, 
+                                              const char *mask_or_numbits, apr_pool_t *p)
+{
+    apr_status_t rv;
+    char *endptr;
+    long bits, maxbits = 32;
+
+    /* filter out stuff which doesn't look remotely like an IP address; this helps 
+     * callers like mod_access which have a syntax allowing hostname or IP address;
+     * APR_EINVAL tells the caller that it was probably not intended to be an IP
+     * address
+     */
+    if (!looks_like_ip(ipstr)) {
+        return APR_EINVAL;
+    }
+
+    *ipsub = apr_pcalloc(p, sizeof(apr_ipsubnet_t));
+
+    /* assume ipstr is an individual IP address, not a subnet */
+    memset((*ipsub)->mask, 0xFF, sizeof (*ipsub)->mask);
+
+    rv = parse_ip(*ipsub, ipstr, mask_or_numbits == NULL);
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
+    if (mask_or_numbits) {
+#if APR_HAVE_IPV6
+        if ((*ipsub)->family == AF_INET6) {
+            maxbits = 128;
+        }
+#endif
+        bits = strtol(mask_or_numbits, &endptr, 10);
+        if (*endptr == '\0' && bits > 0 && bits <= maxbits) {
+            /* valid num-bits string; fill in mask appropriately */
+            int cur_entry = 0;
+            apr_int32_t cur_bit_value;
+
+            memset((*ipsub)->mask, 0, sizeof (*ipsub)->mask);
+            while (bits > 32) {
+                (*ipsub)->mask[cur_entry] = 0xFFFFFFFF; /* all 32 bits */
+                bits -= 32;
+                ++cur_entry;
+            }
+            cur_bit_value = 0x80000000;
+            while (bits) {
+                (*ipsub)->mask[cur_entry] |= cur_bit_value;
+                --bits;
+                cur_bit_value /= 2;
+            }
+            (*ipsub)->mask[cur_entry] = htonl((*ipsub)->mask[cur_entry]);
+        }
+        else if (apr_inet_pton(AF_INET, mask_or_numbits, (*ipsub)->mask) == 1 &&
+            (*ipsub)->family == AF_INET) {
+            /* valid IPv4 netmask */
+        }
+        else {
+            return APR_EBADMASK;
+        }
+    }
+
+    fix_subnet(*ipsub);
+
     return APR_SUCCESS;
 }
+
+APR_DECLARE(int) apr_ipsubnet_test(apr_ipsubnet_t *ipsub, apr_sockaddr_t *sa)
+{
+#if APR_HAVE_IPV6
+    /* XXX This line will segv on Win32 build with APR_HAVE_IPV6,
+     * but without the IPV6 drivers installed.
+     */
+    if (sa->family == AF_INET) {
+        if (ipsub->family == AF_INET &&
+            ((sa->sa.sin.sin_addr.s_addr & ipsub->mask[0]) == ipsub->sub[0])) {
+            return 1;
+        }
+    }
+    else if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)sa->ipaddr_ptr)) {
+        if (ipsub->family == AF_INET &&
+            (((apr_uint32_t *)sa->ipaddr_ptr)[3] & ipsub->mask[0]) == ipsub->sub[0]) {
+            return 1;
+        }
+    }
+    else if (sa->family == AF_INET6 && ipsub->family == AF_INET6) {
+        apr_uint32_t *addr = (apr_uint32_t *)sa->ipaddr_ptr;
+
+        if ((addr[0] & ipsub->mask[0]) == ipsub->sub[0] &&
+            (addr[1] & ipsub->mask[1]) == ipsub->sub[1] &&
+            (addr[2] & ipsub->mask[2]) == ipsub->sub[2] &&
+            (addr[3] & ipsub->mask[3]) == ipsub->sub[3]) {
+            return 1;
+        }
+    }
+#else
+    if ((sa->sa.sin.sin_addr.s_addr & ipsub->mask[0]) == ipsub->sub[0]) {
+        return 1;
+    }
+#endif /* APR_HAVE_IPV6 */
+    return 0; /* no match */
+}
+
+APR_DECLARE(apr_status_t) apr_sockaddr_zone_set(apr_sockaddr_t *sa,
+                                                const char *zone_id)
+{
+#if !APR_HAVE_IPV6 || !defined(HAVE_IF_NAMETOINDEX)
+    return APR_ENOTIMPL;
+#else
+    unsigned int idx;
+    
+    if (sa->family != APR_INET6
+        || !IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)sa->ipaddr_ptr)) {
+        return APR_EBADIP;
+    }
+
+    idx = if_nametoindex(zone_id);
+    if (idx) {
+        sa->sa.sin6.sin6_scope_id = idx;
+        return APR_SUCCESS;
+    }
+
+    if (errno != ENODEV) {
+        return errno;
+    }
+    else {
+        char *endptr;
+        apr_int64_t i = apr_strtoi64(zone_id, &endptr, 10);
+
+        if (*endptr != '\0' || errno || i < 1 || i > APR_INT16_MAX) {
+            return APR_EGENERAL;
+        }
+
+        sa->sa.sin6.sin6_scope_id = i;
+        return APR_SUCCESS;
+    }
+#endif
+}
+
+APR_DECLARE(apr_status_t) apr_sockaddr_zone_get(const apr_sockaddr_t *sa,
+                                                const char **name,
+                                                apr_uint32_t *id,
+                                                apr_pool_t *p)
+{
+#if !APR_HAVE_IPV6 || !defined(HAVE_IF_INDEXTONAME)
+    return APR_ENOTIMPL;
+#else
+    if (sa->family != APR_INET6 || !sa->sa.sin6.sin6_scope_id) {
+        return APR_EBADIP;
+    }        
+
+    if (name) {
+        char *buf = apr_palloc(p, IF_NAMESIZE);
+        if (if_indextoname(sa->sa.sin6.sin6_scope_id, buf) == NULL)
+            return errno;
+        *name = buf;
+    }
+
+    if (id) *id = sa->sa.sin6.sin6_scope_id;
+    
+    return APR_SUCCESS;
 #endif
+}
diff --git a/network_io/unix/socket_util.c b/network_io/unix/socket_util.c
new file mode 100644
index 00000000000..93fe25976ad
--- /dev/null
+++ b/network_io/unix/socket_util.c
@@ -0,0 +1,75 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_network_io.h"
+#include "apr_poll.h"
+
+APR_DECLARE(apr_status_t) apr_socket_atreadeof(apr_socket_t *sock, int *atreadeof)
+{
+    apr_pollfd_t pfds[1];
+    apr_status_t rv;
+    apr_int32_t  nfds;
+
+    /* The purpose here is to return APR_SUCCESS only in cases in
+     * which it can be unambiguously determined whether or not the
+     * socket will return EOF on next read.  In case of an unexpected
+     * error, return that. */
+
+    pfds[0].reqevents = APR_POLLIN;
+    pfds[0].desc_type = APR_POLL_SOCKET;
+    pfds[0].desc.s = sock;
+
+    do {
+        rv = apr_poll(&pfds[0], 1, &nfds, 0);
+    } while (APR_STATUS_IS_EINTR(rv));
+
+    if (APR_STATUS_IS_TIMEUP(rv)) {
+        /* Read buffer empty -> subsequent reads would block, so,
+         * definitely not at EOF. */
+        *atreadeof = 0;
+        return APR_SUCCESS;
+    }
+    else if (rv) {
+        /* Some other error -> unexpected error. */
+        return rv;
+    }
+    /* Many platforms return only APR_POLLIN; OS X returns APR_POLLHUP|APR_POLLIN */
+    else if (nfds == 1 && (pfds[0].rtnevents & APR_POLLIN)  == APR_POLLIN) {
+        apr_sockaddr_t unused;
+        apr_size_t len = 1;
+        char buf;
+
+        /* The socket is readable - peek to see whether it returns EOF
+         * without consuming bytes from the socket buffer. */
+        rv = apr_socket_recvfrom(&unused, sock, MSG_PEEK, &buf, &len);
+        if (rv == APR_EOF) {
+            *atreadeof = 1;
+            return APR_SUCCESS;
+        }
+        else if (rv) {
+            /* Read error -> unexpected error. */
+            return rv;
+        }
+        else {
+            *atreadeof = 0;
+            return APR_SUCCESS;
+        }
+    }
+
+    /* Should not fall through here. */
+    return APR_EGENERAL;
+}
+
diff --git a/network_io/unix/sockets.c b/network_io/unix/sockets.c
index a583c2ef783..e95ce2c7dde 100644
--- a/network_io/unix/sockets.c
+++ b/network_io/unix/sockets.c
@@ -1,63 +1,70 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "networkio.h"
+#include "apr_arch_networkio.h"
+#include "apr_network_io.h"
+#include "apr_strings.h"
+#include "apr_support.h"
 #include "apr_portable.h"
+#include "apr_arch_inherit.h"
+
+#ifdef BEOS_R5
+#undef close
+#define close closesocket
+#endif /* BEOS_R5 */
+
+#if APR_HAVE_SOCKADDR_UN
+#define GENERIC_INADDR_ANY_LEN  sizeof(struct sockaddr_un)
+#else
+#define GENERIC_INADDR_ANY_LEN  16
+#endif
+
+/* big enough for IPv4, IPv6 and optionally sun_path */
+static char generic_inaddr_any[GENERIC_INADDR_ANY_LEN] = {0};
+
+static apr_status_t socket_cleanup(void *sock)
+{
+    apr_socket_t *thesocket = sock;
+    int sd = thesocket->socketdes;
+
+    /* Set socket descriptor to -1 before close(), so that there is no
+     * chance of returning an already closed FD from apr_os_sock_get().
+     */
+    thesocket->socketdes = -1;
+
+#if APR_HAVE_SOCKADDR_UN
+    if (thesocket->bound && thesocket->local_addr->family == APR_UNIX) {
+        /* XXX: Check for return values ? */
+        unlink(thesocket->local_addr->hostname);
+    }
+#endif        
+    if (close(sd) == 0) {
+        return APR_SUCCESS;
+    }
+    else {
+        /* Restore, close() was not successful. */
+        thesocket->socketdes = sd;
+
+        return errno;
+    }
+}
 
-static ap_status_t socket_cleanup(void *sock)
+static apr_status_t socket_child_cleanup(void *sock)
 {
-    ap_socket_t *thesocket = sock;
+    apr_socket_t *thesocket = sock;
     if (close(thesocket->socketdes) == 0) {
         thesocket->socketdes = -1;
         return APR_SUCCESS;
@@ -67,64 +74,169 @@ static ap_status_t socket_cleanup(void *sock)
     }
 }
 
-ap_status_t ap_create_tcp_socket(ap_socket_t **new, ap_pool_t *cont)
+static void set_socket_vars(apr_socket_t *sock, int family, int type, int protocol)
+{
+    sock->type = type;
+    sock->protocol = protocol;
+    apr_sockaddr_vars_set(sock->local_addr, family, 0);
+    apr_sockaddr_vars_set(sock->remote_addr, family, 0);
+    sock->options = 0;
+#if defined(BEOS) && !defined(BEOS_BONE)
+    /* BeOS pre-BONE has TCP_NODELAY on by default and it can't be
+     * switched off!
+     */
+    sock->options |= APR_TCP_NODELAY;
+#endif
+}
+
+static void alloc_socket(apr_socket_t **new, apr_pool_t *p)
 {
-    (*new) = (ap_socket_t *)ap_palloc(cont, sizeof(ap_socket_t));
+    *new = (apr_socket_t *)apr_pcalloc(p, sizeof(apr_socket_t));
+    (*new)->pool = p;
+    (*new)->local_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->pool,
+                                                       sizeof(apr_sockaddr_t));
+    (*new)->local_addr->pool = p;
+    (*new)->remote_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->pool,
+                                                        sizeof(apr_sockaddr_t));
+    (*new)->remote_addr->pool = p;
+    (*new)->remote_addr_unknown = 1;
+#ifndef WAITIO_USES_POLL
+    /* Create a pollset with room for one descriptor. */
+    /* ### check return codes */
+    (void) apr_pollset_create(&(*new)->pollset, 1, p, 0);
+#endif
+}
+
+apr_status_t apr_socket_protocol_get(apr_socket_t *sock, int *protocol)
+{
+    *protocol = sock->protocol;
+    return APR_SUCCESS;
+}
+
+apr_status_t apr_socket_create(apr_socket_t **new, int ofamily, int type,
+                               int protocol, apr_pool_t *cont)
+{
+    int family = ofamily, flags = 0;
+    int oprotocol = protocol;
+
+#ifdef HAVE_SOCK_CLOEXEC
+    flags |= SOCK_CLOEXEC;
+#endif
 
-    if ((*new) == NULL) {
-        return APR_ENOMEM;
+    if (family == APR_UNSPEC) {
+#if APR_HAVE_IPV6
+        family = APR_INET6;
+#else
+        family = APR_INET;
+#endif
+    }
+#if APR_HAVE_SOCKADDR_UN
+    if (family == APR_UNIX) {
+        protocol = 0;
     }
-    (*new)->cntxt = cont; 
-    (*new)->local_addr = (struct sockaddr_in *)ap_palloc((*new)->cntxt,
-                         sizeof(struct sockaddr_in));
-    (*new)->remote_addr = (struct sockaddr_in *)ap_palloc((*new)->cntxt,
-                          sizeof(struct sockaddr_in));
+#endif
+    alloc_socket(new, cont);
 
-    if ((*new)->local_addr == NULL || (*new)->remote_addr == NULL) {
-        return APR_ENOMEM;
+#ifndef BEOS_R5
+    (*new)->socketdes = socket(family, type|flags, protocol);
+#else
+    /* For some reason BeOS R5 has an unconventional protocol numbering,
+     * so we need to translate here. */
+    switch (protocol) {
+    case 0:
+        (*new)->socketdes = socket(family, type|flags, 0);
+        break;
+    case APR_PROTO_TCP:
+        (*new)->socketdes = socket(family, type|flags, IPPROTO_TCP);
+        break;
+    case APR_PROTO_UDP:
+        (*new)->socketdes = socket(family, type|flags, IPPROTO_UDP);
+        break;
+    case APR_PROTO_SCTP:
+    default:
+        errno = EPROTONOSUPPORT;
+        (*new)->socketdes = -1;
+        break;
     }
- 
-    (*new)->socketdes = socket(AF_INET ,SOCK_STREAM, IPPROTO_TCP);
+#endif /* BEOS_R5 */
 
-    (*new)->local_addr->sin_family = AF_INET;
-    (*new)->remote_addr->sin_family = AF_INET;
+#if APR_HAVE_IPV6
+    if ((*new)->socketdes < 0 && ofamily == APR_UNSPEC) {
+        family = APR_INET;
+        (*new)->socketdes = socket(family, type|flags, protocol);
+    }
+#endif
 
-    (*new)->addr_len = sizeof(*(*new)->local_addr);
-    
     if ((*new)->socketdes < 0) {
         return errno;
     }
+    set_socket_vars(*new, family, type, oprotocol);
+
+#ifndef HAVE_SOCK_CLOEXEC
+    {
+        int flags;
+        apr_status_t rv;
+
+        if ((flags = fcntl((*new)->socketdes, F_GETFD)) == -1) {
+            rv = errno;
+            close((*new)->socketdes);
+            (*new)->socketdes = -1;
+            return rv;
+        }
+
+        flags |= FD_CLOEXEC;
+        if (fcntl((*new)->socketdes, F_SETFD, flags) == -1) {
+            rv = errno;
+            close((*new)->socketdes);
+            (*new)->socketdes = -1;
+            return rv;
+        }
+    }
+#endif
+
     (*new)->timeout = -1;
-    ap_register_cleanup((*new)->cntxt, (void *)(*new), 
-                        socket_cleanup, ap_null_cleanup);
+    (*new)->inherit = 0;
+    apr_pool_cleanup_register((*new)->pool, (void *)(*new), socket_cleanup,
+                              socket_child_cleanup);
+
     return APR_SUCCESS;
 } 
 
-ap_status_t ap_shutdown(ap_socket_t *thesocket, ap_shutdown_how_e how)
+apr_status_t apr_socket_shutdown(apr_socket_t *thesocket, 
+                                 apr_shutdown_how_e how)
 {
-    if (shutdown(thesocket->socketdes, how) == 0) {
-        return APR_SUCCESS;
-    }
-    else {
-        return errno;
-    }
+    return (shutdown(thesocket->socketdes, how) == -1) ? errno : APR_SUCCESS;
 }
 
-ap_status_t ap_close_socket(ap_socket_t *thesocket)
+apr_status_t apr_socket_close(apr_socket_t *thesocket)
 {
-    ap_kill_cleanup(thesocket->cntxt, thesocket, socket_cleanup);
-    return socket_cleanup(thesocket);
+    return apr_pool_cleanup_run(thesocket->pool, thesocket, socket_cleanup);
 }
 
-ap_status_t ap_bind(ap_socket_t *sock)
+apr_status_t apr_socket_bind(apr_socket_t *sock, apr_sockaddr_t *sa)
 {
-    if (bind(sock->socketdes, (struct sockaddr *)sock->local_addr, sock->addr_len) == -1)
+    if (bind(sock->socketdes, 
+             (struct sockaddr *)&sa->sa, sa->salen) == -1) {
         return errno;
-    else
+    }
+    else {
+        sock->local_addr = sa;
+        /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */
+#if APR_HAVE_SOCKADDR_UN
+        if (sock->local_addr->family == APR_UNIX) {
+            sock->bound = 1;
+            sock->local_port_unknown = 1;
+        }
+        else
+#endif
+        if (sock->local_addr->sa.sin.sin_port == 0) { /* no need for ntohs() when comparing w/ 0 */
+            sock->local_port_unknown = 1; /* kernel got us an ephemeral port */
+        }
         return APR_SUCCESS;
+    }
 }
 
-ap_status_t ap_listen(ap_socket_t *sock, ap_int32_t backlog)
+apr_status_t apr_socket_listen(apr_socket_t *sock, apr_int32_t backlog)
 {
     if (listen(sock->socketdes, backlog) == -1)
         return errno;
@@ -132,130 +244,329 @@ ap_status_t ap_listen(ap_socket_t *sock, ap_int32_t backlog)
         return APR_SUCCESS;
 }
 
-ap_status_t ap_accept(ap_socket_t **new, const ap_socket_t *sock, ap_pool_t *connection_context)
+apr_status_t apr_socket_accept(apr_socket_t **new, apr_socket_t *sock,
+                               apr_pool_t *connection_context)
 {
-    (*new) = (ap_socket_t *)ap_palloc(connection_context, 
-                            sizeof(ap_socket_t));
+    int s;
+    apr_sockaddr_t sa;
+
+    sa.salen = sizeof(sa.sa);
+
+#ifdef HAVE_ACCEPT4
+    {
+        int flags = SOCK_CLOEXEC;
+
+#if defined(SOCK_NONBLOCK) && APR_O_NONBLOCK_INHERITED
+        /* With FreeBSD accept4() (avail in 10+), O_NONBLOCK is not inherited
+         * (unlike Linux).  Mimic the accept() behavior here in a way that
+         * may help other platforms.
+         */
+        if (apr_is_option_set(sock, APR_SO_NONBLOCK) == 1) {
+            flags |= SOCK_NONBLOCK;
+        }
+#endif
+        s = accept4(sock->socketdes, (struct sockaddr *)&sa.sa, &sa.salen, flags);
+    }
+#else
+    s = accept(sock->socketdes, (struct sockaddr *)&sa.sa, &sa.salen);
+#endif
+
+    if (s < 0) {
+        return errno;
+    }
+#ifdef TPF
+    if (s == 0) { 
+        /* 0 is an invalid socket for TPF */
+        return APR_EINTR;
+    }
+#endif
+    alloc_socket(new, connection_context);
 
-    (*new)->cntxt = connection_context;
-    (*new)->local_addr = (struct sockaddr_in *)ap_palloc((*new)->cntxt, 
-                 sizeof(struct sockaddr_in));
+    /* Set up socket variables -- note that it may be possible for
+     * *new to be an AF_INET socket when sock is AF_INET6 in some
+     * dual-stack configurations, so ensure that the remote_/local_addr
+     * structures are adjusted for the family of the accepted
+     * socket: */
+    set_socket_vars(*new, sa.sa.sin.sin_family, SOCK_STREAM, sock->protocol);
 
-    (*new)->remote_addr = (struct sockaddr_in *)ap_palloc((*new)->cntxt, 
-                 sizeof(struct sockaddr_in));
-    (*new)->addr_len = sizeof(struct sockaddr_in);
 #ifndef HAVE_POLL
     (*new)->connected = 1;
 #endif
+    (*new)->timeout = -1;
 
-    (*new)->socketdes = accept(sock->socketdes, (struct sockaddr *)(*new)->remote_addr,
-                        &(*new)->addr_len);
+    (*new)->remote_addr_unknown = 0;
 
-    if ((*new)->socketdes < 0) {
-        return errno;
+    (*new)->socketdes = s;
+
+    /* Copy in peer's address. */
+    (*new)->remote_addr->sa = sa.sa;
+    (*new)->remote_addr->salen = sa.salen;
+
+    *(*new)->local_addr = *sock->local_addr;
+
+    /* The above assignment just overwrote the pool entry. Setting the local_addr 
+       pool for the accepted socket back to what it should be.  Otherwise all 
+       allocations for this socket will come from a server pool that is not
+       freed until the process goes down.*/
+    (*new)->local_addr->pool = connection_context;
+
+    /* fix up any pointers which are no longer valid */
+    if (sock->local_addr->sa.sin.sin_family == AF_INET) {
+        (*new)->local_addr->ipaddr_ptr = &(*new)->local_addr->sa.sin.sin_addr;
+    }
+#if APR_HAVE_IPV6
+    else if (sock->local_addr->sa.sin.sin_family == AF_INET6) {
+        (*new)->local_addr->ipaddr_ptr = &(*new)->local_addr->sa.sin6.sin6_addr;
+    }
+#endif
+#if APR_HAVE_SOCKADDR_UN
+    else if (sock->local_addr->sa.sin.sin_family == AF_UNIX) {
+        *(*new)->remote_addr = *sock->local_addr;
+        (*new)->local_addr->ipaddr_ptr = &((*new)->local_addr->sa.unx.sun_path);
+        (*new)->remote_addr->ipaddr_ptr = &((*new)->remote_addr->sa.unx.sun_path);
+    }
+    if (sock->local_addr->sa.sin.sin_family != AF_UNIX)
+#endif
+    (*new)->remote_addr->port = ntohs((*new)->remote_addr->sa.sin.sin_port);
+    if (sock->local_port_unknown) {
+        /* not likely for a listening socket, but theoretically possible :) */
+        (*new)->local_port_unknown = 1;
+    }
+
+#if APR_TCP_NODELAY_INHERITED
+    if (apr_is_option_set(sock, APR_TCP_NODELAY) == 1) {
+        apr_set_option(*new, APR_TCP_NODELAY, 1);
+    }
+#endif /* TCP_NODELAY_INHERITED */
+#if APR_O_NONBLOCK_INHERITED
+    if (apr_is_option_set(sock, APR_SO_NONBLOCK) == 1) {
+        apr_set_option(*new, APR_SO_NONBLOCK, 1);
     }
+#endif /* APR_O_NONBLOCK_INHERITED */
 
-    if (getsockname((*new)->socketdes, (struct sockaddr *)(*new)->local_addr, 
-                    &((*new)->addr_len)) < 0) {
-	return errno;
+    if (sock->local_interface_unknown ||
+        !memcmp(sock->local_addr->ipaddr_ptr,
+                generic_inaddr_any,
+                sock->local_addr->ipaddr_len)) {
+        /* If the interface address inside the listening socket's local_addr wasn't 
+         * up-to-date, we don't know local interface of the connected socket either.
+         *
+         * If the listening socket was not bound to a specific interface, we
+         * don't know the local_addr of the connected socket.
+         */
+        (*new)->local_interface_unknown = 1;
     }
 
-    ap_register_cleanup((*new)->cntxt, (void *)(*new), 
-                        socket_cleanup, ap_null_cleanup);
+#ifndef HAVE_ACCEPT4
+    {
+        int flags;
+        apr_status_t rv;
+
+        if ((flags = fcntl((*new)->socketdes, F_GETFD)) == -1) {
+            rv = errno;
+            close((*new)->socketdes);
+            (*new)->socketdes = -1;
+            return rv;
+        }
+
+        flags |= FD_CLOEXEC;
+        if (fcntl((*new)->socketdes, F_SETFD, flags) == -1) {
+            rv = errno;
+            close((*new)->socketdes);
+            (*new)->socketdes = -1;
+            return rv;
+        }
+    }
+#endif
+
+    (*new)->inherit = 0;
+    apr_pool_cleanup_register((*new)->pool, (void *)(*new), socket_cleanup,
+                              socket_cleanup);
     return APR_SUCCESS;
 }
 
-ap_status_t ap_connect(ap_socket_t *sock, char *hostname)
+apr_status_t apr_socket_connect(apr_socket_t *sock, apr_sockaddr_t *sa)
 {
-    struct hostent *hp;
+    int rc;        
 
-    if (hostname != NULL) {
-        hp = gethostbyname(hostname);
+    do {
+        rc = connect(sock->socketdes,
+                     (const struct sockaddr *)&sa->sa.sin,
+                     sa->salen);
+    } while (rc == -1 && errno == EINTR);
 
-        if ((sock->socketdes < 0) || (!sock->remote_addr)) {
-            return APR_ENOTSOCK;
+    /* we can see EINPROGRESS the first time connect is called on a non-blocking
+     * socket; if called again, we can see EALREADY
+     */
+    if ((rc == -1) && (errno == EINPROGRESS || errno == EALREADY)
+                   && (sock->timeout > 0)) {
+        rc = apr_wait_for_io_or_timeout(NULL, sock, 0);
+        if (rc != APR_SUCCESS) {
+            return rc;
         }
-        if (!hp)  {
-            return (h_errno + APR_OS_START_SYSERR);
+
+#ifdef SO_ERROR
+        {
+            int error;
+            apr_socklen_t len = sizeof(error);
+            if ((rc = getsockopt(sock->socketdes, SOL_SOCKET, SO_ERROR, 
+                                 (char *)&error, &len)) < 0) {
+                return errno;
+            }
+            if (error) {
+                return error;
+            }
         }
-    
-        memcpy((char *)&sock->remote_addr->sin_addr, hp->h_addr_list[0], hp->h_length);
+#endif /* SO_ERROR */
+    }
 
-        sock->addr_len = sizeof(*sock->remote_addr);
+    if (memcmp(sa->ipaddr_ptr, generic_inaddr_any, sa->ipaddr_len)) {
+        /* A real remote address was passed in.  If the unspecified
+         * address was used, the actual remote addr will have to be
+         * determined using getpeername() if required. */
+        sock->remote_addr_unknown = 0;
+
+        /* Copy the address structure details in. */
+        sock->remote_addr->sa = sa->sa;
+        sock->remote_addr->salen = sa->salen;
+        /* Adjust ipaddr_ptr et al. */
+        apr_sockaddr_vars_set(sock->remote_addr, sa->family, sa->port);
     }
 
-    if ((connect(sock->socketdes, (const struct sockaddr *)sock->remote_addr, sock->addr_len) < 0) &&
-        (errno != EINPROGRESS)) {
+    if (sock->local_addr->port == 0) {
+        /* connect() got us an ephemeral port */
+        sock->local_port_unknown = 1;
+    }
+#if APR_HAVE_SOCKADDR_UN
+    if (sock->local_addr->sa.sin.sin_family == AF_UNIX) {
+        /* Assign connect address as local. */
+        sock->local_addr = sa;
+    }
+    else
+#endif
+    if (!memcmp(sock->local_addr->ipaddr_ptr,
+                generic_inaddr_any,
+                sock->local_addr->ipaddr_len)) {
+        /* not bound to specific local interface; connect() had to assign
+         * one for the socket
+         */
+        sock->local_interface_unknown = 1;
+    }
+
+    if (rc == -1 && errno != EISCONN) {
         return errno;
     }
-    else {
-        socklen_t namelen = sizeof(*sock->local_addr);
-        getsockname(sock->socketdes, (struct sockaddr *)sock->local_addr, &namelen);
+
 #ifndef HAVE_POLL
-	sock->connected=1;
+    sock->connected=1;
 #endif
-        return APR_SUCCESS;
-    }
+    return APR_SUCCESS;
 }
 
-ap_status_t ap_get_socketdata(void **data, char *key, ap_socket_t *sock)
+apr_status_t apr_socket_type_get(apr_socket_t *sock, int *type)
 {
-    if (sock != NULL) {
-        return ap_get_userdata(data, key, sock->cntxt);
-    }
-    else {
-        data = NULL;
-        return APR_ENOSOCKET;
-    }
+    *type = sock->type;
+    return APR_SUCCESS;
 }
 
-ap_status_t ap_set_socketdata(ap_socket_t *sock, void *data, char *key,
-                              ap_status_t (*cleanup) (void *))
+apr_status_t apr_socket_data_get(void **data, const char *key, apr_socket_t *sock)
 {
-    if (sock != NULL) {
-        return ap_set_userdata(data, key, cleanup, sock->cntxt);
-    }
-    else {
-        data = NULL;
-        return APR_ENOSOCKET;
+    sock_userdata_t *cur = sock->userdata;
+
+    *data = NULL;
+
+    while (cur) {
+        if (!strcmp(cur->key, key)) {
+            *data = cur->data;
+            break;
+        }
+        cur = cur->next;
     }
+
+    return APR_SUCCESS;
 }
 
-ap_status_t ap_get_os_sock(ap_os_sock_t *thesock, ap_socket_t *sock)
+apr_status_t apr_socket_data_set(apr_socket_t *sock, void *data, const char *key,
+                                 apr_status_t (*cleanup) (void *))
 {
-    if (sock == NULL) {
-        return APR_ENOSOCKET;
+    sock_userdata_t *new = apr_palloc(sock->pool, sizeof(sock_userdata_t));
+
+    new->key = apr_pstrdup(sock->pool, key);
+    new->data = data;
+    new->next = sock->userdata;
+    sock->userdata = new;
+
+    if (cleanup) {
+        apr_pool_cleanup_register(sock->pool, data, cleanup, cleanup);
     }
+
+    return APR_SUCCESS;
+}
+
+apr_status_t apr_os_sock_get(apr_os_sock_t *thesock, apr_socket_t *sock)
+{
     *thesock = sock->socketdes;
     return APR_SUCCESS;
 }
 
-ap_status_t ap_put_os_sock(ap_socket_t **sock, ap_os_sock_t *thesock, 
-                           ap_pool_t *cont)
+apr_status_t apr_os_sock_make(apr_socket_t **apr_sock, 
+                              apr_os_sock_info_t *os_sock_info, 
+                              apr_pool_t *cont)
 {
-    if (cont == NULL) {
-        return APR_ENOPOOL;
+    alloc_socket(apr_sock, cont);
+    set_socket_vars(*apr_sock, os_sock_info->family, os_sock_info->type, os_sock_info->protocol);
+    (*apr_sock)->timeout = -1;
+    (*apr_sock)->socketdes = *os_sock_info->os_sock;
+    if (os_sock_info->local) {
+        memcpy(&(*apr_sock)->local_addr->sa.sin, 
+               os_sock_info->local, 
+               (*apr_sock)->local_addr->salen);
+        /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */
+        (*apr_sock)->local_addr->port = ntohs((*apr_sock)->local_addr->sa.sin.sin_port);
+    }
+    else {
+        (*apr_sock)->local_port_unknown = (*apr_sock)->local_interface_unknown = 1;
+    }
+    if (os_sock_info->remote) {
+#ifndef HAVE_POLL
+        (*apr_sock)->connected = 1;
+#endif
+        memcpy(&(*apr_sock)->remote_addr->sa.sin, 
+               os_sock_info->remote,
+               (*apr_sock)->remote_addr->salen);
+        /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */
+        (*apr_sock)->remote_addr->port = ntohs((*apr_sock)->remote_addr->sa.sin.sin_port);
+    }
+    else {
+        (*apr_sock)->remote_addr_unknown = 1;
     }
+        
+    (*apr_sock)->inherit = 0;
+    apr_pool_cleanup_register((*apr_sock)->pool, (void *)(*apr_sock), 
+                              socket_cleanup, socket_cleanup);
+    return APR_SUCCESS;
+}
+
+apr_status_t apr_os_sock_put(apr_socket_t **sock, apr_os_sock_t *thesock, 
+                           apr_pool_t *cont)
+{
+    /* XXX Bogus assumption that *sock points at anything legit */
     if ((*sock) == NULL) {
-        (*sock) = (ap_socket_t *)ap_palloc(cont, sizeof(ap_socket_t));
-        (*sock)->cntxt = cont;
-        (*sock)->local_addr = (struct sockaddr_in *)ap_palloc((*sock)->cntxt,
-                             sizeof(struct sockaddr_in));
-        (*sock)->remote_addr = (struct sockaddr_in *)ap_palloc((*sock)->cntxt,
-                              sizeof(struct sockaddr_in));
-
-        if ((*sock)->local_addr == NULL || (*sock)->remote_addr == NULL) {
-            return APR_ENOMEM;
-        }
-     
-        (*sock)->addr_len = sizeof(*(*sock)->local_addr);
+        alloc_socket(sock, cont);
+        /* XXX IPv6 figure out the family here! */
+        /* XXX figure out the actual socket type here */
+        /* *or* just decide that apr_os_sock_put() has to be told the family and type */
+        set_socket_vars(*sock, APR_INET, SOCK_STREAM, 0);
         (*sock)->timeout = -1;
-        if (getsockname(*thesock, (struct sockaddr *)(*sock)->local_addr, 
-                        &((*sock)->addr_len)) < 0) {
-            return errno;
-        }
     }
+    (*sock)->local_port_unknown = (*sock)->local_interface_unknown = 1;
+    (*sock)->remote_addr_unknown = 1;
     (*sock)->socketdes = *thesock;
     return APR_SUCCESS;
 }
 
+APR_POOL_IMPLEMENT_ACCESSOR(socket)
+
+APR_IMPLEMENT_INHERIT_SET(socket, inherit, pool, socket_cleanup)
+
+APR_IMPLEMENT_INHERIT_UNSET(socket, inherit, pool, socket_cleanup)
diff --git a/network_io/unix/sockopt.c b/network_io/unix/sockopt.c
index 45f64a5f5ef..c48ab06a540 100644
--- a/network_io/unix/sockopt.c
+++ b/network_io/unix/sockopt.c
@@ -1,61 +1,27 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "networkio.h"
+#include "apr_arch_networkio.h"
+#include "apr_strings.h"
 
-static ap_status_t soblock(int sd)
+
+static apr_status_t soblock(int sd)
 {
+/* BeOS uses setsockopt at present for non blocking... */
+#ifndef BEOS
     int fd_flags;
 
     fd_flags = fcntl(sd, F_GETFL, 0);
@@ -64,19 +30,24 @@ static ap_status_t soblock(int sd)
 #elif defined(O_NDELAY)
     fd_flags &= ~O_NDELAY;
 #elif defined(FNDELAY)
-    fd_flags &= ~O_FNDELAY;
+    fd_flags &= ~FNDELAY;
 #else
-    /* XXXX: this breaks things, but an alternative isn't obvious...*/
-    return -1;
+#error Please teach APR how to make sockets blocking on your platform.
 #endif
     if (fcntl(sd, F_SETFL, fd_flags) == -1) {
         return errno;
     }
+#else
+    int on = 0;
+    if (setsockopt(sd, SOL_SOCKET, SO_NONBLOCK, &on, sizeof(int)) < 0)
+        return errno;
+#endif /* BEOS */
     return APR_SUCCESS;
 }
 
-static ap_status_t sononblock(int sd)
+static apr_status_t sononblock(int sd)
 {
+#ifndef BEOS
     int fd_flags;
 
     fd_flags = fcntl(sd, F_GETFL, 0);
@@ -85,97 +56,406 @@ static ap_status_t sononblock(int sd)
 #elif defined(O_NDELAY)
     fd_flags |= O_NDELAY;
 #elif defined(FNDELAY)
-    fd_flags |= O_FNDELAY;
+    fd_flags |= FNDELAY;
 #else
-    /* XXXX: this breaks things, but an alternative isn't obvious...*/
-    return -1;
+#error Please teach APR how to make sockets non-blocking on your platform.
 #endif
     if (fcntl(sd, F_SETFL, fd_flags) == -1) {
         return errno;
     }
+#else
+    int on = 1;
+    if (setsockopt(sd, SOL_SOCKET, SO_NONBLOCK, &on, sizeof(int)) < 0)
+        return errno;
+#endif /* BEOS */
+    return APR_SUCCESS;
+}
+
+
+apr_status_t apr_socket_timeout_set(apr_socket_t *sock, apr_interval_time_t t)
+{
+    apr_status_t stat;
+
+    /* If our new timeout is non-negative and our old timeout was
+     * negative, then we need to ensure that we are non-blocking.
+     * Conversely, if our new timeout is negative and we had
+     * non-negative timeout, we must make sure our socket is blocking.
+     * We want to avoid calling fcntl more than necessary on the
+     * socket.
+     */
+    if (t >= 0 && sock->timeout < 0) {
+        if (apr_is_option_set(sock, APR_SO_NONBLOCK) != 1) {
+            if ((stat = sononblock(sock->socketdes)) != APR_SUCCESS) {
+                return stat;
+            }
+            apr_set_option(sock, APR_SO_NONBLOCK, 1);
+        }
+    } 
+    else if (t < 0 && sock->timeout >= 0) {
+        if (apr_is_option_set(sock, APR_SO_NONBLOCK) != 0) { 
+            if ((stat = soblock(sock->socketdes)) != APR_SUCCESS) { 
+                return stat; 
+            }
+            apr_set_option(sock, APR_SO_NONBLOCK, 0);
+        } 
+    }
+    /* must disable the incomplete read support if we disable
+     * a timeout
+     */
+    if (t <= 0) {
+        sock->options &= ~APR_INCOMPLETE_READ;
+    }
+    sock->timeout = t;
     return APR_SUCCESS;
 }
 
-ap_status_t ap_setsocketopt(ap_socket_t *sock, ap_int32_t opt, ap_int32_t on)
+
+apr_status_t apr_socket_opt_set(apr_socket_t *sock, 
+                                apr_int32_t opt, apr_int32_t on)
 {
     int one;
-    struct linger li;
-    ap_status_t stat;
+    apr_status_t rv;
 
     if (on)
         one = 1;
     else
         one = 0;
-
-    if (opt & APR_SO_KEEPALIVE) {
-        if (setsockopt(sock->socketdes, SOL_SOCKET, SO_KEEPALIVE, (void *)&one, sizeof(int)) == -1) {
-            return errno;
+    switch(opt) {
+    case APR_SO_KEEPALIVE:
+#ifdef SO_KEEPALIVE
+        if (on != apr_is_option_set(sock, APR_SO_KEEPALIVE)) {
+            if (setsockopt(sock->socketdes, SOL_SOCKET, SO_KEEPALIVE, (void *)&one, sizeof(int)) == -1) {
+                return errno;
+            }
+            apr_set_option(sock, APR_SO_KEEPALIVE, on);
         }
-    }
-    if (opt & APR_SO_DEBUG) {
-        if (setsockopt(sock->socketdes, SOL_SOCKET, SO_DEBUG, (void *)&one, sizeof(int)) == -1) {
-            return errno;
+#else
+        return APR_ENOTIMPL;
+#endif
+        break;
+    case APR_SO_DEBUG:
+        if (on != apr_is_option_set(sock, APR_SO_DEBUG)) {
+            if (setsockopt(sock->socketdes, SOL_SOCKET, SO_DEBUG, (void *)&one, sizeof(int)) == -1) {
+                return errno;
+            }
+            apr_set_option(sock, APR_SO_DEBUG, on);
         }
-    }
-    if (opt & APR_SO_REUSEADDR) {
-        if (setsockopt(sock->socketdes, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(int)) == -1) {
-            return errno;
+        break;
+    case APR_SO_BROADCAST:
+#ifdef SO_BROADCAST
+        if (on != apr_is_option_set(sock, APR_SO_BROADCAST)) {
+            if (setsockopt(sock->socketdes, SOL_SOCKET, SO_BROADCAST, (void *)&one, sizeof(int)) == -1) {
+                return errno;
+            }
+            apr_set_option(sock, APR_SO_BROADCAST, on);
         }
-    }
-    if (opt & APR_SO_SNDBUF) {
+#else
+        return APR_ENOTIMPL;
+#endif
+        break;
+    case APR_SO_REUSEADDR:
+        if (on != apr_is_option_set(sock, APR_SO_REUSEADDR)) {
+            if (setsockopt(sock->socketdes, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(int)) == -1) {
+                return errno;
+            }
+            apr_set_option(sock, APR_SO_REUSEADDR, on);
+        }
+        break;
+    case APR_SO_SNDBUF:
+#ifdef SO_SNDBUF
         if (setsockopt(sock->socketdes, SOL_SOCKET, SO_SNDBUF, (void *)&on, sizeof(int)) == -1) {
             return errno;
         }
-    }
-    if (opt & APR_SO_NONBLOCK) {
-        if (on) {
-            if ((stat = soblock(sock->socketdes)) != APR_SUCCESS) 
-                return stat;
+#else
+        return APR_ENOTIMPL;
+#endif
+        break;
+    case APR_SO_RCVBUF:
+#ifdef SO_RCVBUF
+        if (setsockopt(sock->socketdes, SOL_SOCKET, SO_RCVBUF, (void *)&on, sizeof(int)) == -1) {
+            return errno;
         }
-        else {
-            if ((stat = sononblock(sock->socketdes)) != APR_SUCCESS)
-                return stat;
+#else
+        return APR_ENOTIMPL;
+#endif
+        break;
+    case APR_SO_NONBLOCK:
+        if (apr_is_option_set(sock, APR_SO_NONBLOCK) != on) {
+            if (on) {
+                if ((rv = sononblock(sock->socketdes)) != APR_SUCCESS) 
+                    return rv;
+            }
+            else {
+                if ((rv = soblock(sock->socketdes)) != APR_SUCCESS)
+                    return rv;
+            }
+            apr_set_option(sock, APR_SO_NONBLOCK, on);
         }
-    }
-    if (opt & APR_SO_LINGER) {
-        li.l_onoff = on;
-        li.l_linger = MAX_SECS_TO_LINGER;
-        if (setsockopt(sock->socketdes, SOL_SOCKET, SO_LINGER, (char *) &li, sizeof(struct linger)) == -1) {
+        break;
+    case APR_SO_LINGER:
+#ifdef SO_LINGER
+        if (apr_is_option_set(sock, APR_SO_LINGER) != on) {
+            struct linger li;
+            li.l_onoff = on;
+            li.l_linger = APR_MAX_SECS_TO_LINGER;
+            if (setsockopt(sock->socketdes, SOL_SOCKET, SO_LINGER, (char *) &li, sizeof(struct linger)) == -1) {
+                return errno;
+            }
+            apr_set_option(sock, APR_SO_LINGER, on);
+        }
+#else
+        return APR_ENOTIMPL;
+#endif
+        break;
+    case APR_TCP_DEFER_ACCEPT:
+#if defined(TCP_DEFER_ACCEPT)
+        if (apr_is_option_set(sock, APR_TCP_DEFER_ACCEPT) != on) {
+            int optlevel = IPPROTO_TCP;
+            int optname = TCP_DEFER_ACCEPT;
+
+            if (setsockopt(sock->socketdes, optlevel, optname, 
+                           (void *)&on, sizeof(int)) == -1) {
+                return errno;
+            }
+            apr_set_option(sock, APR_TCP_DEFER_ACCEPT, on);
+        }
+#else
+        return APR_ENOTIMPL;
+#endif
+        break;
+    case APR_TCP_NODELAY:
+#if defined(TCP_NODELAY)
+        if (apr_is_option_set(sock, APR_TCP_NODELAY) != on) {
+            int optlevel = IPPROTO_TCP;
+            int optname = TCP_NODELAY;
+
+#if APR_HAVE_SCTP
+            if (sock->protocol == IPPROTO_SCTP) {
+                optlevel = IPPROTO_SCTP;
+                optname = SCTP_NODELAY;
+            }
+#endif
+            if (setsockopt(sock->socketdes, optlevel, optname, (void *)&on, sizeof(int)) == -1) {
+                return errno;
+            }
+            apr_set_option(sock, APR_TCP_NODELAY, on);
+        }
+#else
+        /* BeOS pre-BONE has TCP_NODELAY set by default.
+         * As it can't be turned off we might as well check if they're asking
+         * for it to be turned on!
+         */
+#ifdef BEOS
+        if (on == 1)
+            return APR_SUCCESS;
+        else
+#endif
+        return APR_ENOTIMPL;
+#endif
+        break;
+    case APR_TCP_NOPUSH:
+#if APR_TCP_NOPUSH_FLAG
+        /* TCP_NODELAY and TCP_CORK are mutually exclusive on Linux
+         * kernels < 2.6; on newer kernels they can be used together
+         * and TCP_CORK takes preference, which is the desired
+         * behaviour.  On older kernels, TCP_NODELAY must be toggled
+         * to "off" whilst TCP_CORK is in effect. */
+        if (apr_is_option_set(sock, APR_TCP_NOPUSH) != on) {
+#ifndef HAVE_TCP_NODELAY_WITH_CORK
+            int optlevel = IPPROTO_TCP;
+            int optname = TCP_NODELAY;
+
+#if APR_HAVE_SCTP
+            if (sock->protocol == IPPROTO_SCTP) {
+                optlevel = IPPROTO_SCTP;
+                optname = SCTP_NODELAY;
+            }
+#endif
+            /* OK we're going to change some settings here... */
+            if (apr_is_option_set(sock, APR_TCP_NODELAY) == 1 && on) {
+                /* Now toggle TCP_NODELAY to off, if TCP_CORK is being
+                 * turned on: */
+                int tmpflag = 0;
+                if (setsockopt(sock->socketdes, optlevel, optname,
+                               (void*)&tmpflag, sizeof(int)) == -1) {
+                    return errno;
+                }
+                apr_set_option(sock, APR_RESET_NODELAY, 1);
+                apr_set_option(sock, APR_TCP_NODELAY, 0);
+            } else if (on) {
+                apr_set_option(sock, APR_RESET_NODELAY, 0);
+            }
+#endif /* HAVE_TCP_NODELAY_WITH_CORK */
+
+            /* OK, now we can just set the TCP_NOPUSH flag accordingly...*/
+            if (setsockopt(sock->socketdes, IPPROTO_TCP, APR_TCP_NOPUSH_FLAG,
+                           (void*)&on, sizeof(int)) == -1) {
+                return errno;
+            }
+            apr_set_option(sock, APR_TCP_NOPUSH, on);
+#ifndef HAVE_TCP_NODELAY_WITH_CORK
+            if (!on && apr_is_option_set(sock, APR_RESET_NODELAY)) {
+                /* Now, if TCP_CORK was just turned off, turn
+                 * TCP_NODELAY back on again if it was earlier toggled
+                 * to off: */
+                int tmpflag = 1;
+                if (setsockopt(sock->socketdes, optlevel, optname,
+                               (void*)&tmpflag, sizeof(int)) == -1) {
+                    return errno;
+                }
+                apr_set_option(sock, APR_RESET_NODELAY,0);
+                apr_set_option(sock, APR_TCP_NODELAY, 1);
+            }
+#endif /* HAVE_TCP_NODELAY_WITH_CORK */
+        }
+#else
+        return APR_ENOTIMPL;
+#endif
+        break;
+    case APR_INCOMPLETE_READ:
+        apr_set_option(sock, APR_INCOMPLETE_READ, on);
+        break;
+    case APR_IPV6_V6ONLY:
+#if APR_HAVE_IPV6 && defined(IPV6_V6ONLY)
+        /* we don't know the initial setting of this option,
+         * so don't check sock->options since that optimization
+         * won't work
+         */
+        if (setsockopt(sock->socketdes, IPPROTO_IPV6, IPV6_V6ONLY,
+                       (void *)&on, sizeof(int)) == -1) {
             return errno;
         }
-    }
-    if (opt & APR_SO_TIMEOUT) {
-        sock->timeout = on;
-        if ((stat = sononblock(sock->socketdes)) != APR_SUCCESS) {
-            return stat;
+        apr_set_option(sock, APR_IPV6_V6ONLY, on);
+#else
+        return APR_ENOTIMPL;
+#endif
+        break;
+    case APR_SO_FREEBIND:
+#if defined(IP_FREEBIND)
+        if (setsockopt(sock->socketdes, SOL_IP, IP_FREEBIND,
+                       (void *)&one, sizeof(int)) == -1) {
+            return errno;
         }
+        apr_set_option(sock, APR_SO_FREEBIND, on);
+#elif 0 /* defined(IP_BINDANY) ... */
+        /* TODO: insert FreeBSD support here, note family specific
+         * options, IP_BINDANY vs IPV6_BINDANY */
+#else
+        return APR_ENOTIMPL;
+#endif
+        break;
+    default:
+        return APR_EINVAL;
     }
-    return APR_SUCCESS;
+
+    return APR_SUCCESS; 
 }         
 
-ap_status_t ap_gethostname(char *buf, ap_int32_t len, ap_pool_t *cont)
+
+apr_status_t apr_socket_timeout_get(apr_socket_t *sock, apr_interval_time_t *t)
+{
+    *t = sock->timeout;
+    return APR_SUCCESS;
+}
+
+
+apr_status_t apr_socket_opt_get(apr_socket_t *sock, 
+                                apr_int32_t opt, apr_int32_t *on)
+{
+    switch(opt) {
+        default:
+            *on = apr_is_option_set(sock, opt);
+    }
+    return APR_SUCCESS;
+}
+
+
+apr_status_t apr_socket_atmark(apr_socket_t *sock, int *atmark)
 {
-    if (gethostname(buf, len) == -1)
+#ifndef BEOS_R5
+    int oobmark;
+
+    if (ioctl(sock->socketdes, SIOCATMARK, (void*) &oobmark) < 0)
+        return apr_get_netos_error();
+
+    *atmark = (oobmark != 0);
+
+    return APR_SUCCESS;
+#else /* BEOS_R5 */
+    return APR_ENOTIMPL;
+#endif
+}
+
+apr_status_t apr_gethostname(char *buf, apr_int32_t len, apr_pool_t *cont)
+{
+#ifdef BEOS_R5
+    if (gethostname(buf, len) == 0) {
+#else
+    if (gethostname(buf, len) != 0) {
+#endif  
+        buf[0] = '\0';
         return errno;
-    else
-        return APR_SUCCESS;
+    }
+    else if (!memchr(buf, '\0', len)) { /* buffer too small */
+        /* note... most platforms just truncate in this condition
+         *         linux+glibc return an error
+         */
+        buf[0] = '\0';
+        return APR_ENAMETOOLONG;
+    }
+    return APR_SUCCESS;
 }
 
-ap_status_t ap_get_remote_hostname(char **name, ap_socket_t *sock)
+#if APR_HAS_SO_ACCEPTFILTER
+apr_status_t apr_socket_accept_filter(apr_socket_t *sock, const char *name,
+                                      const char *args)
 {
-    struct hostent *hptr;
-    
-    hptr = gethostbyaddr((char *)&(sock->remote_addr->sin_addr), 
-                         sizeof(struct in_addr), AF_INET);
-    if (hptr != NULL) {
-        *name = ap_pstrdup(sock->cntxt, hptr->h_name);
-        if (*name) {
+    struct accept_filter_arg af;
+    socklen_t optlen = sizeof(af);
+
+    /* FreeBSD returns an error if the filter is already set; ignore
+     * this call if we previously set it to the same value.
+     */
+    if ((getsockopt(sock->socketdes, SOL_SOCKET, SO_ACCEPTFILTER,
+                    &af, &optlen)) == 0) {
+        if (!strcmp(name, af.af_name) && !strcmp(args, af.af_arg)) {
             return APR_SUCCESS;
         }
-        return APR_ENOMEM;
     }
 
-    /* XXX - Is referencing h_errno threadsafe? */
-    return (h_errno + APR_OS_START_SYSERR);
+    /* Uhh, at least in FreeBSD 9 the fields are declared as arrays of
+     * these lengths; did sizeof not work in some ancient release?
+     *
+     * FreeBSD kernel sets the last byte to a '\0'.
+     */
+    apr_cpystrn(af.af_name, name, 16);
+    apr_cpystrn(af.af_arg, args, 256 - 16);
+
+    if ((setsockopt(sock->socketdes, SOL_SOCKET, SO_ACCEPTFILTER,
+          &af, sizeof(af))) < 0) {
+        return errno;
+    }
+    return APR_SUCCESS;
 }
+#endif
+
+APR_PERMS_SET_IMPLEMENT(socket)
+{
+#if APR_HAVE_SOCKADDR_UN
+    apr_status_t rv = APR_SUCCESS;
+    apr_socket_t *socket = (apr_socket_t *)thesocket;
 
+    if (socket->local_addr->family == APR_UNIX) {
+        if (!(perms & APR_FPROT_GSETID))
+            gid = -1;
+        if (fchown(socket->socketdes, uid, gid) < 0) {
+            rv = errno;
+        }
+    }
+    else
+        rv = APR_EINVAL;
+    return rv;
+#else
+    return APR_ENOTIMPL;
+#endif
+}
diff --git a/network_io/win32/networkio.h b/network_io/win32/networkio.h
deleted file mode 100644
index 58d82f8b126..00000000000
--- a/network_io/win32/networkio.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef NETWORK_IO_H
-#define NETWORK_IO_H
-
-#include "apr_network_io.h"
-#include "apr_general.h"
-
-struct ap_socket_t {
-    ap_pool_t *cntxt;
-    SOCKET sock;
-    struct sockaddr_in *local_addr;
-    struct sockaddr_in *remote_addr;
-    size_t addr_len;
-    ap_interval_time_t timeout;
-};
-
-struct ap_pollfd_t {
-    ap_pool_t *cntxt;
-    fd_set *read;
-    int numread;
-    fd_set *write;
-    int numwrite;
-    fd_set *except;
-    int numexcept;    
-};
-
-ap_status_t status_from_res_error(int);
-
-#endif  /* ! NETWORK_IO_H */
-
diff --git a/network_io/win32/poll.c b/network_io/win32/poll.c
deleted file mode 100644
index b7eb0603629..00000000000
--- a/network_io/win32/poll.c
+++ /dev/null
@@ -1,259 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "networkio.h"
-#include "apr_network_io.h"
-#include "apr_general.h"
-#include "apr_lib.h"
-#include <errno.h>
-#include <windows.h>
-#include <time.h>
-
-
-ap_status_t ap_setup_poll(ap_pollfd_t **new, ap_int32_t num, ap_pool_t *cont)
-{
-    (*new) = (ap_pollfd_t *)ap_palloc(cont, sizeof(ap_pollfd_t) * num);
-    if ((*new) == NULL) {
-        return APR_ENOMEM;
-    }
-    (*new)->cntxt = cont;
-    (*new)->read = (fd_set *)ap_palloc(cont, sizeof(fd_set));
-    (*new)->write = (fd_set *)ap_palloc(cont, sizeof(fd_set));
-    (*new)->except = (fd_set *)ap_palloc(cont, sizeof(fd_set));
-    FD_ZERO((*new)->read);
-    (*new)->numread = 0;
-    FD_ZERO((*new)->write);
-    (*new)->numwrite = 0;
-    FD_ZERO((*new)->except);
-    (*new)->numexcept = 0;
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_add_poll_socket(ap_pollfd_t *aprset, 
-			       ap_socket_t *sock, ap_int16_t event)
-{
-    if (event & APR_POLLIN) {
-        FD_SET(sock->sock, aprset->read);
-        aprset->numread++;
-    }
-    if (event & APR_POLLPRI) {
-        FD_SET(sock->sock, aprset->read);
-        aprset->numexcept++;
-    }
-    if (event & APR_POLLOUT) {
-        FD_SET(sock->sock, aprset->write);
-        aprset->numwrite++;
-    }
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_poll(ap_pollfd_t *aprset, ap_int32_t *nsds, 
-                    ap_interval_time_t timeout)
-{
-    int rv;
-    struct timeval tv, *tvptr;
-    fd_set *newread = NULL;
-    fd_set *newwrite = NULL;
-    fd_set *newexcept = NULL;
-
-    if (aprset->numread != 0) {
-        newread = aprset->read;
-    }
-    if (aprset->numwrite != 0) {
-        newwrite = aprset->write;
-    }
-    if (aprset->numexcept != 0) {
-        newexcept = aprset->except;
-    }
-
-    if (newread == NULL && newwrite == NULL && newexcept == NULL) {
-        Sleep(timeout / 1000); /* convert microseconds into milliseconds */
-        return APR_TIMEUP; /* TODO - get everybody in synch with Win32 ap_status_t */
-    }
-    else {
-        if (timeout < 0) {
-            tvptr = NULL;
-        }
-        else {
-            tv.tv_sec = (long)(timeout / AP_USEC_PER_SEC);
-            tv.tv_usec = (long)(timeout % AP_USEC_PER_SEC);
-            tvptr = &tv;
-        }
-        rv = select(500, /* ignored on Windows */
-                    newread, newwrite, newexcept, tvptr);
-    }
-
-    (*nsds) = rv;    
-    if ((*nsds) < 0) {
-        rv = GetLastError();
-        return APR_EEXIST;  /* TODO - get everybody in synch with Win32 ap_status_t */
-    }
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_get_revents(ap_int16_t *event, ap_socket_t *sock, ap_pollfd_t *aprset)
-{
-    ap_int16_t revents = 0;
-    WSABUF data;
-    int dummy;
-    int flags = MSG_PEEK;
-
-    /* We just want to PEEK at the data, so I am setting up a dummy WSABUF
-     * variable here.
-     */
-    data.len = 256;
-    data.buf = (char *)ap_palloc(aprset->cntxt, 256);
-
-    if (FD_ISSET(sock->sock, aprset->read)) {
-        revents |= APR_POLLIN;
-        if (WSARecv(sock->sock, &data, 1, &dummy, &flags, NULL, 
-                    NULL) == SOCKET_ERROR) {
-            dummy = WSAGetLastError();
-            switch (dummy) {
-                case WSAECONNRESET:
-                case WSAECONNABORTED:
-                case WSAESHUTDOWN:
-                case WSAENETRESET: {
-                    revents ^= APR_POLLIN;
-                    revents |= APR_POLLHUP;
-                    break;
-                }
-                case WSAENOTSOCK: {
-                    revents ^= APR_POLLIN;
-                    revents |= APR_POLLNVAL;
-                }
-                default: {
-                    revents ^= APR_POLLIN;
-                    revents |= APR_POLLERR;
-                }
-            }
-        }
-    }
-    if (FD_ISSET(sock->sock, aprset->write)) {
-        revents |= APR_POLLOUT;
-    }
-    /* I am assuming that the except is for out of band data, not a failed
-     * connection on a non-blocking socket.  Might be a bad assumption, but
-     * it works for now. rbb.
-     */
-    if (FD_ISSET(sock->sock, aprset->except)) {
-        revents |= APR_POLLPRI;
-    }
-
-    (*event) = revents;
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_get_polldata(ap_pollfd_t *pollfd, char *key, void *data)
-{
-    if (pollfd != NULL) {
-        return ap_get_userdata(data, key, pollfd->cntxt);
-    }
-    else {
-        data = NULL;
-        return APR_ENOFILE;
-    }
-}
-
-ap_status_t ap_set_polldata(ap_pollfd_t *pollfd, void *data, char *key,
-                            ap_status_t (*cleanup) (void *))
-{
-    if (pollfd != NULL) {
-        return ap_set_userdata(data, key, cleanup, pollfd->cntxt);
-    }
-    else {
-        data = NULL;
-        return APR_ENOFILE;
-    }
-}
-
-ap_status_t ap_mask_poll_socket(ap_pollfd_t *aprset, 
-                                ap_socket_t *sock, ap_int16_t events)
-{
-    if (events & APR_POLLIN) {
-        FD_CLR(sock->sock, aprset->read);
-        aprset->numread--;
-    }
-    if (events & APR_POLLPRI) {
-        FD_CLR(sock->sock, aprset->except);
-        aprset->numexcept--;
-    }
-    if (events & APR_POLLOUT) {
-        FD_CLR(sock->sock, aprset->write);
-        aprset->numwrite--;
-    }
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_remove_poll_socket(ap_pollfd_t *aprset, ap_socket_t *sock)
-{
-    return ap_mask_poll_socket(aprset, sock, ~0);
-}
-
-ap_status_t ap_clear_poll_sockets(ap_pollfd_t *aprset, ap_int16_t events)
-{
-    if (events & APR_POLLIN) {
-        FD_ZERO(aprset->read);
-        aprset->numread = 0;
-    }
-    if (events & APR_POLLPRI) {
-        FD_ZERO(aprset->read);
-        aprset->numexcept = 0;
-    }
-    if (events & APR_POLLOUT) {
-        FD_ZERO(aprset->write);
-        aprset->numwrite = 0;
-    }
-    return APR_SUCCESS;
-}
diff --git a/network_io/win32/sendrecv.c b/network_io/win32/sendrecv.c
index 33d39fb0713..61bc20746fe 100644
--- a/network_io/win32/sendrecv.c
+++ b/network_io/win32/sendrecv.c
@@ -1,78 +1,61 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "networkio.h"
+#include "apr_arch_networkio.h"
 #include "apr_errno.h"
 #include "apr_general.h"
 #include "apr_network_io.h"
 #include "apr_lib.h"
-#include "fileio.h"
+#include "apr_arch_file_io.h"
+#if APR_HAVE_TIME_H
 #include <time.h>
+#endif
 
-ap_status_t ap_send(ap_socket_t *sock, const char *buf, ap_ssize_t *len)
+/* MAX_SEGMENT_SIZE is the maximum amount of data that will be sent to a client
+ * in one call of TransmitFile. This number must be small enough to give the 
+ * slowest client time to receive the data before the socket timeout triggers.
+ * The same problem can exist with apr_socket_send(). In that case, we rely on
+ * the application to adjust socket timeouts and max send segment 
+ * sizes appropriately.
+ * For example, Apache will in most cases call apr_socket_send() with less
+ * than 8193 bytes.
+ */
+#define MAX_SEGMENT_SIZE 65536
+#define WSABUF_ON_STACK 50
+
+APR_DECLARE(apr_status_t) apr_socket_send(apr_socket_t *sock, const char *buf,
+                                          apr_size_t *len)
 {
-    ap_ssize_t rv;
+    apr_ssize_t rv;
     WSABUF wsaData;
     int lasterror;
     DWORD dwBytes = 0;
 
-    wsaData.len = *len;
+    wsaData.len = (u_long)*len;
     wsaData.buf = (char*) buf;
 
-    rv = WSASend(sock->sock, &wsaData, 1, &dwBytes, 0, NULL, NULL);
+#ifndef _WIN32_WCE
+    rv = WSASend(sock->socketdes, &wsaData, 1, &dwBytes, 0, NULL, NULL);
+#else
+    rv = send(sock->socketdes, wsaData.buf, wsaData.len, 0);
+    dwBytes = rv;
+#endif
     if (rv == SOCKET_ERROR) {
-        lasterror = WSAGetLastError();
+        lasterror = apr_get_netos_error();
+        *len = 0;
         return lasterror;
     }
 
@@ -81,183 +64,432 @@ ap_status_t ap_send(ap_socket_t *sock, const char *buf, ap_ssize_t *len)
     return APR_SUCCESS;
 }
 
-ap_status_t ap_recv(ap_socket_t *sock, char *buf, ap_ssize_t *len) 
+
+APR_DECLARE(apr_status_t) apr_socket_recv(apr_socket_t *sock, char *buf,
+                                          apr_size_t *len) 
 {
-    ap_ssize_t rv;
+    apr_ssize_t rv;
     WSABUF wsaData;
     int lasterror;
     DWORD dwBytes = 0;
     DWORD flags = 0;
 
-    wsaData.len = *len;
+    wsaData.len = (u_long)*len;
     wsaData.buf = (char*) buf;
 
-    rv = WSARecv(sock->sock, &wsaData, 1, &dwBytes, &flags, NULL, NULL);
+#ifndef _WIN32_WCE
+    rv = WSARecv(sock->socketdes, &wsaData, 1, &dwBytes, &flags, NULL, NULL);
+#else
+    rv = recv(sock->socketdes, wsaData.buf, wsaData.len, 0);
+    dwBytes = rv;
+#endif
     if (rv == SOCKET_ERROR) {
-        lasterror = WSAGetLastError();
+        lasterror = apr_get_netos_error();
+        *len = 0;
         return lasterror;
     }
 
     *len = dwBytes;
-    return APR_SUCCESS;
+    return dwBytes == 0 ? APR_EOF : APR_SUCCESS;
 }
 
-ap_status_t ap_sendv(ap_socket_t *sock, const struct iovec *vec,
-                     ap_int32_t nvec, ap_int32_t *nbytes)
+
+APR_DECLARE(apr_status_t) apr_socket_sendv(apr_socket_t *sock,
+                                           const struct iovec *vec,
+                                           apr_int32_t in_vec, apr_size_t *nbytes)
 {
-    ap_ssize_t rv;
-    int i;
-    int lasterror;
+    apr_status_t rc = APR_SUCCESS;
+    apr_ssize_t rv;
+    apr_size_t cur_len;
+    apr_int32_t nvec = 0;
+    int i, j = 0;
     DWORD dwBytes = 0;
+    WSABUF *pWsaBuf;
 
-    LPWSABUF pWsaData = (LPWSABUF) malloc(sizeof(WSABUF) * nvec);
+    for (i = 0; i < in_vec; i++) {
+        cur_len = vec[i].iov_len;
+        nvec++;
+        while (cur_len > APR_DWORD_MAX) {
+            nvec++;
+            cur_len -= APR_DWORD_MAX;
+        } 
+    }
 
-    if (!pWsaData)
+    pWsaBuf = (nvec <= WSABUF_ON_STACK) ? _alloca(sizeof(WSABUF) * (nvec))
+                                         : malloc(sizeof(WSABUF) * (nvec));
+    if (!pWsaBuf)
         return APR_ENOMEM;
 
+    for (i = 0; i < in_vec; i++) {
+        char * base = vec[i].iov_base;
+        cur_len = vec[i].iov_len;
+        
+        do {
+            if (cur_len > APR_DWORD_MAX) {
+                pWsaBuf[j].buf = base;
+                pWsaBuf[j].len = APR_DWORD_MAX;
+                cur_len -= APR_DWORD_MAX;
+                base += APR_DWORD_MAX;
+            }
+            else {
+                pWsaBuf[j].buf = base;
+                pWsaBuf[j].len = (DWORD)cur_len;
+                cur_len = 0;
+            }
+            j++;
+
+        } while (cur_len > 0);
+    }
+#ifndef _WIN32_WCE
+    rv = WSASend(sock->socketdes, pWsaBuf, nvec, &dwBytes, 0, NULL, NULL);
+    if (rv == SOCKET_ERROR) {
+        rc = apr_get_netos_error();
+    }
+#else
     for (i = 0; i < nvec; i++) {
-        pWsaData[i].buf = vec[i].iov_base;
-        pWsaData[i].len = vec[i].iov_len;
+        rv = send(sock->socketdes, pWsaBuf[i].buf, pWsaBuf[i].len, 0);
+        if (rv == SOCKET_ERROR) {
+            rc = apr_get_netos_error();
+            break;
+        }
+        dwBytes += rv;
+    }
+#endif
+    if (nvec > WSABUF_ON_STACK) 
+        free(pWsaBuf);
+
+    *nbytes = dwBytes;
+    return rc;
+}
+
+
+APR_DECLARE(apr_status_t) apr_socket_sendto(apr_socket_t *sock,
+                                            apr_sockaddr_t *where,
+                                            apr_int32_t flags, const char *buf, 
+                                            apr_size_t *len)
+{
+    apr_ssize_t rv;
+
+    rv = sendto(sock->socketdes, buf, (int)*len, flags, 
+                (const struct sockaddr*)&where->sa, 
+                where->salen);
+    if (rv == SOCKET_ERROR) {
+        *len = 0;
+        return apr_get_netos_error();
     }
 
-    rv = WSASend(sock->sock, pWsaData, nvec, &dwBytes, 0, NULL, NULL);
+    *len = rv;
+    return APR_SUCCESS;
+}
+
+
+APR_DECLARE(apr_status_t) apr_socket_recvfrom(apr_sockaddr_t *from, 
+                                              apr_socket_t *sock,
+                                              apr_int32_t flags, 
+                                              char *buf, apr_size_t *len)
+{
+    apr_ssize_t rv;
+
+    from->salen = sizeof(from->sa);
+
+    rv = recvfrom(sock->socketdes, buf, (int)*len, flags, 
+                  (struct sockaddr*)&from->sa, &from->salen);
     if (rv == SOCKET_ERROR) {
-        lasterror = WSAGetLastError();
-        free(pWsaData);
-        return lasterror;
+        (*len) = 0;
+        return apr_get_netos_error();
     }
 
-    free(pWsaData);
+    apr_sockaddr_vars_set(from, from->sa.sin.sin_family, 
+                          ntohs(from->sa.sin.sin_port));
 
-    *nbytes = dwBytes;
+    (*len) = rv;
+    if (rv == 0 && sock->type == SOCK_STREAM)
+        return APR_EOF;
+
+    return APR_SUCCESS;
+}
+
+
+#if APR_HAS_SENDFILE
+static apr_status_t collapse_iovec(char **off, apr_size_t *len, 
+                                   struct iovec *iovec, int numvec, 
+                                   char *buf, apr_size_t buflen)
+{
+    if (numvec == 1) {
+        *off = iovec[0].iov_base;
+        *len = iovec[0].iov_len;
+    }
+    else {
+        int i;
+        for (i = 0; i < numvec; i++) {
+            *len += iovec[i].iov_len;
+        }
+
+        if (*len > buflen) {
+            *len = 0;
+            return APR_INCOMPLETE;
+        }
+
+        *off = buf;
+
+        for (i = 0; i < numvec; i++) {
+            memcpy(buf, iovec[i].iov_base, iovec[i].iov_len);
+            buf += iovec[i].iov_len;
+        }
+    }
     return APR_SUCCESS;
 }
-#if defined(HAVE_SENDFILE)
+
+
 /*
- * ap_status_t ap_sendfile(ap_socket_t *, ap_file_t *, ap_hdtr_t *, 
- *                         ap_off_t *, ap_size_t *, ap_int32_t flags)
+ * apr_status_t apr_socket_sendfile(apr_socket_t *, apr_file_t *, apr_hdtr_t *, 
+ *                                 apr_off_t *, apr_size_t *, apr_int32_t flags)
  *    Send a file from an open file descriptor to a socket, along with 
  *    optional headers and trailers
  * arg 1) The socket to which we're writing
  * arg 2) The open file from which to read
  * arg 3) A structure containing the headers and trailers to send
  * arg 4) Offset into the file where we should begin writing
- * arg 5) Number of bytes to send 
- * arg 6) OS-specific flags to pass to sendfile()
+ * arg 5) Number of bytes to send out of the file
+ * arg 6) APR flags that are mapped to OS specific flags
  */
-ap_status_t ap_sendfile(ap_socket_t * sock, ap_file_t * file,
-        		ap_hdtr_t * hdtr, ap_off_t * offset, ap_size_t * len,
-        		ap_int32_t flags) 
+APR_DECLARE(apr_status_t) apr_socket_sendfile(apr_socket_t *sock, 
+                                              apr_file_t *file,
+                                              apr_hdtr_t *hdtr,
+                                              apr_off_t *offset,
+                                              apr_size_t *len,
+                                              apr_int32_t flags) 
 {
-/*
- *#define WAIT_FOR_EVENT
- * Note: Waiting for the socket directly is much faster than creating a seperate
- * wait event. There are a couple of dangerous aspects to waiting directly 
- * for the socket. First, we should not wait on the socket if concurrent threads
- * can wait-on/signal the same socket. This shouldn't be happening with Apache since 
- * a socket is uniquely tied to a thread. This will change when we begin using 
- * async I/O with completion ports on the socket. Second, I am not sure how the
- * socket timeout code will work. I am hoping the socket will be signaled if the
- * setsockopt timeout expires. Need to verify this...
- */
-    ap_ssize_t rv;
-    OVERLAPPED overlapped;
-    TRANSMIT_FILE_BUFFERS tfb, *ptfb = NULL;
-    int i, ptr = 0;
-    int lasterror = APR_SUCCESS;
+    apr_status_t status = APR_SUCCESS;
+    apr_status_t rv;
+    apr_off_t curoff = *offset;
     DWORD dwFlags = 0;
+    apr_size_t nbytes;
+    TRANSMIT_FILE_BUFFERS tfb, *ptfb = NULL;
+    apr_size_t bytes_to_send;   /* Bytes to send out of the file (not including headers) */
+    int disconnected = 0;
+    int sendv_trailers = 0;
+    char hdtrbuf[4096];
 
-#if 0
-    if (flags | APR_SENDFILE_KEEP_SOCKET)
-        dwFlags |= TF_REUSE_SOCKET;
-    if (flags | APR_SENDFILE_CLOSE_SOCKET)
-        dwFlags |= TF_DISCONNECT;
-#else
-    dwFlags = 0;
-#endif
+    if (apr_os_level < APR_WIN_NT) {
+        return APR_ENOTIMPL;
+    }
+
+    /* Use len to keep track of number of total bytes sent (including headers) */
+    bytes_to_send = *len;
+    *len = 0;
+
+    /* Handle the goofy case of sending headers/trailers and a zero byte file */
+    if (!bytes_to_send && hdtr) {
+        if (hdtr->numheaders) {
+            rv = apr_socket_sendv(sock, hdtr->headers, hdtr->numheaders, 
+                                  &nbytes);
+            if (rv != APR_SUCCESS)
+                return rv;
+            *len += nbytes;
+        }
+        if (hdtr->numtrailers) {
+            rv = apr_socket_sendv(sock, hdtr->trailers, hdtr->numtrailers,
+                                  &nbytes);
+            if (rv != APR_SUCCESS)
+                return rv;
+            *len += nbytes;
+        }
+        return APR_SUCCESS;
+    }
 
-    /* TransmitFile can only send one header and one footer */
     memset(&tfb, '\0', sizeof (tfb));
+
+    /* Collapse the headers into a single buffer */
     if (hdtr && hdtr->numheaders) {
+        apr_size_t head_length = tfb.HeadLength;
         ptfb = &tfb;
-        if (hdtr->numheaders == 1) {
-            ptfb->Head = hdtr->headers[0].iov_base;
-            ptfb->HeadLength = hdtr->headers[0].iov_len;
-        }
-        else {
-            /* Need to collapse all the header fragments into one buffer */
-            for (i = 0; i < hdtr->numheaders; i++) {
-                ptfb->HeadLength += hdtr->headers[i].iov_len;
-            }
-            ptfb->Head = ap_palloc(sock->cntxt, ptfb->HeadLength); /* Should this be a malloc? */
+        nbytes = 0;
+        rv = collapse_iovec((char **)&ptfb->Head, &head_length, 
+                            hdtr->headers, hdtr->numheaders, 
+                            hdtrbuf, sizeof(hdtrbuf));
 
-            for (i = 0; i < hdtr->numheaders; i++) {
-                memcpy((char*)ptfb->Head + ptr, hdtr->headers[i].iov_base,
-                       hdtr->headers[i].iov_len);
-                ptr += hdtr->headers[i].iov_len;
-            }
+        tfb.HeadLength = (DWORD)head_length;
+
+        /* If not enough buffer, punt to sendv */
+        if (rv == APR_INCOMPLETE) {
+            rv = apr_socket_sendv(sock, hdtr->headers, hdtr->numheaders, &nbytes);
+            if (rv != APR_SUCCESS)
+                return rv;
+            *len += nbytes;
+            ptfb = NULL;
         }
     }
-    if (hdtr && hdtr->numtrailers) {
-        ptfb = &tfb;
-        if (hdtr->numtrailers == 1) {
-            ptfb->Tail = hdtr->trailers[0].iov_base;
-            ptfb->TailLength = hdtr->trailers[0].iov_len;
+
+    /* Initialize the overlapped structure used on TransmitFile
+     */
+    if (!sock->overlapped) {
+        sock->overlapped = apr_pcalloc(sock->pool, sizeof(OVERLAPPED));
+        sock->overlapped->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+    }
+    while (bytes_to_send) {
+        DWORD xmitbytes;
+
+        if (bytes_to_send > MAX_SEGMENT_SIZE) {
+            xmitbytes = MAX_SEGMENT_SIZE;
         }
         else {
-            /* Need to collapse all the trailer fragments into one buffer */
-            for (i = 0; i < hdtr->numtrailers; i++) {
-                ptfb->TailLength += hdtr->headers[i].iov_len;
-            }
+            /* Last call to TransmitFile() */
+            xmitbytes = (DWORD)bytes_to_send;
+            /* Collapse the trailers into a single buffer */
+            if (hdtr && hdtr->numtrailers) {
+                apr_size_t tail_length = tfb.TailLength;
+                ptfb = &tfb;
+                rv = collapse_iovec((char**) &ptfb->Tail, &tail_length,
+                                    hdtr->trailers, hdtr->numtrailers,
+                                    hdtrbuf + ptfb->HeadLength,
+                                    sizeof(hdtrbuf) - ptfb->HeadLength);
 
-            ptfb->Tail = ap_palloc(sock->cntxt, ptfb->TailLength); /* Should this be a malloc? */
+                tfb.TailLength = (DWORD)tail_length;
 
-            for (i = 0; i < hdtr->numtrailers; i++) {
-                memcpy((char*)ptfb->Tail + ptr, hdtr->trailers[i].iov_base,
-                       hdtr->trailers[i].iov_len);
-                ptr += hdtr->trailers[i].iov_len;
+                if (rv == APR_INCOMPLETE) {
+                    /* If not enough buffer, punt to sendv, later */
+                    sendv_trailers = 1;
+                }
+            }
+            /* Disconnect the socket after last send */
+            if ((flags & APR_SENDFILE_DISCONNECT_SOCKET)
+                    && !sendv_trailers) {
+                dwFlags |= TF_REUSE_SOCKET;
+                dwFlags |= TF_DISCONNECT;
+                disconnected = 1;
             }
         }
+
+        sock->overlapped->Offset = (DWORD)(curoff);
+#if APR_HAS_LARGE_FILES
+        sock->overlapped->OffsetHigh = (DWORD)(curoff >> 32);
+#endif  
+        /* XXX BoundsChecker claims dwFlags must not be zero. */
+        rv = TransmitFile(sock->socketdes,  /* socket */
+                          file->filehand, /* open file descriptor of the file to be sent */
+                          xmitbytes,      /* number of bytes to send. 0=send all */
+                          0,              /* Number of bytes per send. 0=use default */
+                          sock->overlapped,    /* OVERLAPPED structure */
+                          ptfb,           /* header and trailer buffers */
+                          dwFlags);       /* flags to control various aspects of TransmitFile */
+        if (!rv) {
+            status = apr_get_netos_error();
+            if ((status == APR_FROM_OS_ERROR(ERROR_IO_PENDING)) ||
+                (status == APR_FROM_OS_ERROR(WSA_IO_PENDING))) 
+            {
+                rv = WaitForSingleObject(sock->overlapped->hEvent, 
+                                         (DWORD)(sock->timeout >= 0 
+                                                 ? sock->timeout_ms : INFINITE));
+                if (rv == WAIT_OBJECT_0) {
+                    status = APR_SUCCESS;
+                    if (!disconnected) {
+                        if (!WSAGetOverlappedResult(sock->socketdes,
+                                                    sock->overlapped,
+                                                    &xmitbytes,
+                                                    FALSE,
+                                                    &dwFlags)) {
+                            status = apr_get_netos_error();
+                        }
+                        /* Ugly code alert: WSAGetOverlappedResult returns
+                         * a count of all bytes sent. This loop only
+                         * tracks bytes sent out of the file.
+                         */
+                        else if (ptfb) {
+                            xmitbytes -= (ptfb->HeadLength + ptfb->TailLength);
+                        }
+                    }
+                }
+                else if (rv == WAIT_TIMEOUT) {
+                    status = APR_FROM_OS_ERROR(WAIT_TIMEOUT);
+                }
+                else if (rv == WAIT_ABANDONED) {
+                    /* Hummm... WAIT_ABANDONDED is not an error code. It is
+                     * a return specific to the Win32 WAIT functions that
+                     * indicates that a thread exited while holding a
+                     * mutex. Should consider triggering an assert
+                     * to detect the condition...
+                     */
+                    status = APR_FROM_OS_ERROR(WAIT_TIMEOUT);
+                }
+                else
+                    status = apr_get_os_error();
+            }
+        }
+        if (status != APR_SUCCESS)
+            break;
+
+        bytes_to_send -= xmitbytes;
+        curoff += xmitbytes;
+        *len += xmitbytes;
+        /* Adjust len for any headers/trailers sent */
+        if (ptfb) {
+            *len += (ptfb->HeadLength + ptfb->TailLength);
+            memset(&tfb, '\0', sizeof (tfb));
+            ptfb = NULL;
+        }
     }
-    /* Initialize the overlapped structure */
-    memset(&overlapped,'\0', sizeof(overlapped));
-    if (offset && *offset) {
-        overlapped.Offset = *offset;
-    }
-#ifdef WAIT_FOR_EVENT
-    overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
-#endif
- 
-    rv = TransmitFile(sock->sock,     /* socket */
-                      file->filehand, /* open file descriptor of the file to be sent */
-                      *len,           /* number of bytes to send. 0=send all */
-                      0,              /* Number of bytes per send. 0=use default */
-                      &overlapped,    /* OVERLAPPED structure */
-                      ptfb,           /* header and trailer buffers */
-                      dwFlags);       /* flags to control various aspects of TransmitFile */
-    if (!rv) {
-        lasterror = WSAGetLastError();
-        if (lasterror == ERROR_IO_PENDING) {
-#ifdef WAIT_FOR_EVENT
-            rv = WaitForSingleObject(overlapped.hEvent, 
-                                     sock->timeout >= 0 ? sock->timeout / 1000 : INFINITE);
-#else
-            rv = WaitForSingleObject((HANDLE) sock->sock, 
-                                     sock->timeout >= 0 ? sock->timeout / 1000 : INFINITE);
-#endif
-            if (rv == WAIT_OBJECT_0)
-                lasterror = APR_SUCCESS;
-            else if (rv == WAIT_TIMEOUT)
-                lasterror = WAIT_TIMEOUT;
-            else if (rv == WAIT_ABANDONED)
-                lasterror = WAIT_ABANDONED;
-            else
-                lasterror = GetLastError();
+
+    if (status == APR_SUCCESS) {
+        if (sendv_trailers) {
+            rv = apr_socket_sendv(sock, hdtr->trailers, hdtr->numtrailers, &nbytes);
+            if (rv != APR_SUCCESS)
+                return rv;
+            *len += nbytes;
+        }
+
+    
+        /* Mark the socket as disconnected, but do not close it.
+         * Note: The application must have stored the socket prior to making
+         * the call to apr_socket_sendfile in order to either reuse it 
+         * or close it.
+         */
+        if (disconnected) {
+            sock->disconnected = 1;
+            sock->socketdes = INVALID_SOCKET;
         }
     }
-#ifdef WAIT_FOR_EVENT
-    CloseHandle(overlapped.hEvent);
-#endif
-    return lasterror;
+
+    return status;
 }
+
 #endif
+
+APR_DECLARE(apr_status_t) apr_socket_wait(apr_socket_t *sock, apr_wait_type_t direction)
+{
+    fd_set fdset, *rptr, *wptr;
+    int rc;
+    struct timeval tv, *tvptr;
+
+    FD_ZERO(&fdset);
+    FD_SET(sock->socketdes, &fdset);
+
+    if (direction == APR_WAIT_READ) {
+        rptr = &fdset;
+        wptr = NULL;
+    }
+    else { /* APR_WAIT_WRITE */
+        rptr = NULL;
+        wptr = &fdset;
+    }
+
+    if (sock->timeout < 0) {
+        tvptr = NULL;
+    }
+    else {
+        /* casts for winsock/timeval definition */
+        tv.tv_sec =  (long)apr_time_sec(sock->timeout);
+        tv.tv_usec = (int)apr_time_usec(sock->timeout);
+        tvptr = &tv;
+    }
+    rc = select(/* ignored */ FD_SETSIZE+1, rptr, wptr, NULL, tvptr);
+    if (rc == SOCKET_ERROR) {
+        return apr_get_netos_error();
+    }
+    else if (!rc) {
+        return APR_FROM_OS_ERROR(WSAETIMEDOUT);
+    }
+
+    return APR_SUCCESS;
+}
+
diff --git a/network_io/win32/sockaddr.c b/network_io/win32/sockaddr.c
deleted file mode 100644
index 7010539fb76..00000000000
--- a/network_io/win32/sockaddr.c
+++ /dev/null
@@ -1,159 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "networkio.h"
-#include "apr_network_io.h"
-#include "apr_general.h"
-#include "apr_lib.h"
-#include <string.h>
-
-
-ap_status_t ap_set_local_port(ap_socket_t *sock, ap_uint32_t port)
-{
-    sock->local_addr->sin_port = htons((short)port);
-    return APR_SUCCESS;
-}
-
-
-
-ap_status_t ap_set_remote_port(ap_socket_t *sock, ap_uint32_t port)
-{
-    sock->remote_addr->sin_port = htons((short)port);
-    return APR_SUCCESS;
-}
-
-
-
-ap_status_t ap_get_local_port(ap_uint32_t *port, ap_socket_t *sock)
-{
-    *port = ntohs(sock->local_addr->sin_port);
-    return APR_SUCCESS;
-}
-
-
-
-ap_status_t ap_get_remote_port(ap_uint32_t *port, ap_socket_t *sock)
-{
-    *port = ntohs(sock->remote_addr->sin_port);
-    return APR_SUCCESS;
-}
-
-
-
-ap_status_t ap_set_local_ipaddr(ap_socket_t *sock, const char *addr)
-{
-    u_long ipaddr;
-    
-    if (!strcmp(addr, APR_ANYADDR)) {
-        sock->local_addr->sin_addr.s_addr = htonl(INADDR_ANY);
-        return APR_SUCCESS;
-    }
-    
-    ipaddr = inet_addr(addr);
-    
-    if (ipaddr == INADDR_NONE) {
-        return WSAEADDRNOTAVAIL;
-    }
-    
-    sock->local_addr->sin_addr.s_addr = ipaddr;
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_set_remote_ipaddr(ap_socket_t *sock, const char *addr)
-{
-    u_long ipaddr;
-    
-    if (!strcmp(addr, APR_ANYADDR)) {
-        sock->remote_addr->sin_addr.s_addr = htonl(INADDR_ANY);
-        return APR_SUCCESS;
-    }
-    
-    ipaddr = inet_addr(addr);
-    
-    if (ipaddr == INADDR_NONE) {
-        return WSAEADDRNOTAVAIL;
-    }
-    
-    sock->remote_addr->sin_addr.s_addr = ipaddr;
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_get_local_ipaddr(char **addr, const ap_socket_t *sock)
-{
-    *addr = ap_pstrdup(sock->cntxt, inet_ntoa(sock->local_addr->sin_addr));
-    return APR_SUCCESS;
-}
-
-
-
-ap_status_t ap_get_remote_ipaddr(char **addr, const ap_socket_t *sock)
-{
-    *addr = ap_pstrdup(sock->cntxt, inet_ntoa(sock->remote_addr->sin_addr));
-    return APR_SUCCESS;
-}
-
-
-ap_status_t ap_get_local_name(struct sockaddr_in **name, const ap_socket_t *sock)
-{
-    *name = sock->local_addr;
-    return APR_SUCCESS;
-}
-
-
-
-ap_status_t ap_get_remote_name(struct sockaddr_in **name, const ap_socket_t *sock)
-{
-    *name = sock->remote_addr;
-    return APR_SUCCESS;
-}
diff --git a/network_io/win32/sockets.c b/network_io/win32/sockets.c
index 02f243bdc55..9c30f70eb4d 100644
--- a/network_io/win32/sockets.c
+++ b/network_io/win32/sockets.c
@@ -1,118 +1,184 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "networkio.h"
+#include "apr_arch_networkio.h"
 #include "apr_network_io.h"
 #include "apr_general.h"
 #include "apr_lib.h"
 #include "apr_portable.h"
+#include "apr_strings.h"
 #include <string.h>
-#include <winsock2.h>
-#include <windows.h>
+#include "apr_arch_inherit.h"
+#include "apr_arch_misc.h"
 
+/* Borrow the definition of SOMAXCONN_HINT() from Windows SDK 8,
+ * in case the SDK we are building against doesn't have it.
+ */
+#ifndef SOMAXCONN_HINT
+#define SOMAXCONN_HINT(b) (-(b))
+#endif
 
-static ap_status_t socket_cleanup(void *sock)
+static char generic_inaddr_any[16] = {0}; /* big enough for IPv4 or IPv6 */
+
+static apr_status_t socket_cleanup(void *sock)
 {
-    ap_socket_t *thesocket = sock;
-    if (closesocket(thesocket->sock) != SOCKET_ERROR) {
-        thesocket->sock = INVALID_SOCKET;
-        return APR_SUCCESS;
+    apr_socket_t *thesocket = sock;
+
+    if (thesocket->socketdes != INVALID_SOCKET) {
+        if (closesocket(thesocket->socketdes) == SOCKET_ERROR) {
+            return apr_get_netos_error();
+        }
+        thesocket->socketdes = INVALID_SOCKET;
     }
-    else {
-        return APR_EEXIST;
+#if APR_HAS_SENDFILE
+    if (thesocket->overlapped) {
+        CloseHandle(thesocket->overlapped->hEvent);
+        thesocket->overlapped = NULL;
     }
+#endif
+    return APR_SUCCESS;
 }
 
-ap_status_t ap_create_tcp_socket(ap_socket_t **new, ap_pool_t *cont)
+static void set_socket_vars(apr_socket_t *sock, int family, int type, int protocol)
 {
-    (*new) = (ap_socket_t *)ap_palloc(cont, sizeof(ap_socket_t));
-
-    if ((*new) == NULL) {
-        return APR_ENOMEM;
+    sock->type = type;
+    sock->protocol = protocol;
+    apr_sockaddr_vars_set(sock->local_addr, family, 0);
+    apr_sockaddr_vars_set(sock->remote_addr, family, 0);
+#if APR_HAVE_IPV6
+    /* hard-coded behavior for older Windows IPv6 */
+    if (apr_os_level < APR_WIN_VISTA && family == AF_INET6) {
+        apr_set_option(sock, APR_IPV6_V6ONLY, 1);
     }
-    (*new)->cntxt = cont; 
-    (*new)->local_addr = (struct sockaddr_in *)ap_pcalloc((*new)->cntxt,
-                                                          sizeof(struct sockaddr_in));
-    (*new)->remote_addr = (struct sockaddr_in *)ap_palloc((*new)->cntxt,
-                          sizeof(struct sockaddr_in));
+#endif
+}                                                                                                  
+static void alloc_socket(apr_socket_t **new, apr_pool_t *p)
+{
+    *new = (apr_socket_t *)apr_pcalloc(p, sizeof(apr_socket_t));
+    (*new)->pool = p;
+    (*new)->local_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->pool,
+                                                       sizeof(apr_sockaddr_t));
+    (*new)->local_addr->pool = p;
+    
+    (*new)->remote_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->pool,
+                                                        sizeof(apr_sockaddr_t));
+    (*new)->remote_addr->pool = p;
+    (*new)->remote_addr_unknown = 1;
+
+    /* Create a pollset with room for one descriptor. */
+    /* ### check return codes */
+    (void) apr_pollset_create(&(*new)->pollset, 1, p, 0);
+}
+
+APR_DECLARE(apr_status_t) apr_socket_protocol_get(apr_socket_t *sock,
+                                                  int *protocol)
+{
+    *protocol = sock->protocol;
+    return APR_SUCCESS;
+}
 
-    if (((*new)->local_addr == NULL) || ((*new)->remote_addr == NULL)) {
-        return APR_ENOMEM;
+APR_DECLARE(apr_status_t) apr_socket_create(apr_socket_t **new, int family,
+                                            int type, int protocol, 
+                                            apr_pool_t *cont)
+{
+#if APR_HAVE_IPV6
+    int downgrade = (family == AF_UNSPEC);
+#endif
+
+    if (family == AF_UNSPEC) {
+#if APR_HAVE_IPV6
+        family = AF_INET6;
+#else
+        family = AF_INET;
+#endif
     }
+
+    alloc_socket(new, cont);
+
     /* For right now, we are not using socket groups.  We may later.
      * No flags to use when creating a socket, so use 0 for that parameter as well.
      */
-    (*new)->sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
-    if ((*new)->sock == INVALID_SOCKET) {
-        return WSAGetLastError();
+    (*new)->socketdes = socket(family, type, protocol);
+#if APR_HAVE_IPV6
+    if ((*new)->socketdes == INVALID_SOCKET && downgrade) {
+        family = AF_INET;
+        (*new)->socketdes = socket(family, type, protocol);
     }
+#endif
 
-    (*new)->local_addr->sin_family = AF_INET;
+    if ((*new)->socketdes == INVALID_SOCKET) {
+        return apr_get_netos_error();
+    }
 
-    (*new)->addr_len = sizeof(*(*new)->local_addr);
+#ifdef WIN32
+    /* Socket handles are never truly inheritable, there are too many
+     * bugs associated.  WSADuplicateSocket will copy them, but for our
+     * purposes, always transform the socket() created as a non-inherited
+     * handle
+     */
+#if APR_HAS_UNICODE_FS && !defined(_WIN32_WCE)
+    IF_WIN_OS_IS_UNICODE {
+        /* A different approach.  Many users report errors such as 
+         * (32538)An operation was attempted on something that is not 
+         * a socket.  : Parent: WSADuplicateSocket failed...
+         *
+         * This appears that the duplicated handle is no longer recognized
+         * as a socket handle.  SetHandleInformation should overcome that
+         * problem by not altering the handle identifier.  But this won't
+         * work on 9x - it's unsupported.
+         */
+        SetHandleInformation((HANDLE) (*new)->socketdes, 
+                             HANDLE_FLAG_INHERIT, 0);
+    }
+#if APR_HAS_ANSI_FS
+    /* only if APR_HAS_ANSI_FS && APR_HAS_UNICODE_FS */
+    ELSE_WIN_OS_IS_ANSI
+#endif
+#endif
+#if APR_HAS_ANSI_FS || defined(_WIN32_WCE)
+    {
+        HANDLE hProcess = GetCurrentProcess();
+        HANDLE dup;
+        if (DuplicateHandle(hProcess, (HANDLE) (*new)->socketdes, hProcess, 
+                            &dup, 0, FALSE, DUPLICATE_SAME_ACCESS)) {
+            closesocket((*new)->socketdes);
+            (*new)->socketdes = (SOCKET) dup;
+        }
+    }
+#endif
+
+#endif /* def WIN32 */
+
+    set_socket_vars(*new, family, type, protocol);
+
+    (*new)->timeout = -1;
+    (*new)->disconnected = 0;
+
+    apr_pool_cleanup_register((*new)->pool, (void *)(*new), 
+                        socket_cleanup, apr_pool_cleanup_null);
 
-    (*new)->local_addr->sin_port = 0;   
- 
-    ap_register_cleanup((*new)->cntxt, (void *)(*new), 
-                        socket_cleanup, ap_null_cleanup);
     return APR_SUCCESS;
 } 
 
-ap_status_t ap_shutdown(ap_socket_t *thesocket, ap_shutdown_how_e how)
+APR_DECLARE(apr_status_t) apr_socket_shutdown(apr_socket_t *thesocket,
+                                              apr_shutdown_how_e how)
 {
-    int winhow;
+    int winhow = 0;
 
+#ifdef SD_RECEIVE
     switch (how) {
         case APR_SHUTDOWN_READ: {
             winhow = SD_RECEIVE;
@@ -126,144 +192,369 @@ ap_status_t ap_shutdown(ap_socket_t *thesocket, ap_shutdown_how_e how)
             winhow = SD_BOTH;
             break;
         }
+        default:
+            return APR_BADARG;
     }
-    if (shutdown(thesocket->sock, winhow) == 0) {
+#endif
+    if (shutdown(thesocket->socketdes, winhow) == 0) {
         return APR_SUCCESS;
     }
     else {
-        return WSAGetLastError();
+        return apr_get_netos_error();
     }
 }
 
-ap_status_t ap_close_socket(ap_socket_t *thesocket)
+APR_DECLARE(apr_status_t) apr_socket_close(apr_socket_t *thesocket)
 {
-    ap_kill_cleanup(thesocket->cntxt, thesocket, socket_cleanup);
+    apr_pool_cleanup_kill(thesocket->pool, thesocket, socket_cleanup);
     return socket_cleanup(thesocket);
 }
 
-ap_status_t ap_bind(ap_socket_t *sock)
+APR_DECLARE(apr_status_t) apr_socket_bind(apr_socket_t *sock,
+                                          apr_sockaddr_t *sa)
 {
-    if (bind(sock->sock, (struct sockaddr *)sock->local_addr, sock->addr_len) == -1) {
-        return WSAGetLastError();
+    if (bind(sock->socketdes, 
+             (struct sockaddr *)&sa->sa, 
+             sa->salen) == -1) {
+        return apr_get_netos_error();
     }
-    else
+    else {
+        sock->local_addr = sa;
+        if (sock->local_addr->sa.sin.sin_port == 0) {
+            sock->local_port_unknown = 1; /* ephemeral port */
+        }
         return APR_SUCCESS;
+    }
 }
 
-ap_status_t ap_listen(ap_socket_t *sock, ap_int32_t backlog)
+APR_DECLARE(apr_status_t) apr_socket_listen(apr_socket_t *sock,
+                                            apr_int32_t backlog)
 {
-    if (listen(sock->sock, backlog) == SOCKET_ERROR)
-        return WSAGetLastError();
+    int backlog_val;
+
+    if (apr_os_level >= APR_WIN_8) {
+        /* Starting from Windows 8, listen() accepts a special SOMAXCONN_HINT()
+         * arg that allows setting the listen backlog value to a larger
+         * value than the predefined Winsock 2 limit (several hundred).
+         * https://blogs.msdn.microsoft.com/winsdk/2015/06/01/winsocks-listen-backlog-offers-more-flexibility-in-windows-8/
+         */
+        backlog_val = SOMAXCONN_HINT(backlog);
+    }
+    else {
+        backlog_val = backlog;
+    }
+
+    if (listen(sock->socketdes, backlog_val) == SOCKET_ERROR)
+        return apr_get_netos_error();
     else
         return APR_SUCCESS;
 }
 
-ap_status_t ap_accept(ap_socket_t **new, const ap_socket_t *sock, ap_pool_t *connection_context)
+APR_DECLARE(apr_status_t) apr_socket_accept(apr_socket_t **new, 
+                                            apr_socket_t *sock, apr_pool_t *p)
 {
-    (*new) = (ap_socket_t *)ap_palloc(connection_context, 
-                            sizeof(ap_socket_t));
+    SOCKET s;
+#if APR_HAVE_IPV6
+    struct sockaddr_storage sa;
+#else
+    struct sockaddr sa;
+#endif
+    int salen = sizeof(sock->remote_addr->sa);
 
-    (*new)->cntxt = connection_context;
-    (*new)->local_addr = (struct sockaddr_in *)ap_palloc((*new)->cntxt, 
-                 sizeof(struct sockaddr_in));
-    (*new)->remote_addr = (struct sockaddr_in *)ap_palloc((*new)->cntxt,
-                 sizeof(struct sockaddr_in));
-    memcpy((*new)->local_addr, sock->local_addr, sizeof(struct sockaddr_in));
+    /* Don't allocate the memory until after we call accept. This allows
+       us to work with nonblocking sockets. */
+    s = accept(sock->socketdes, (struct sockaddr *)&sa, &salen);
+    if (s == INVALID_SOCKET) {
+        return apr_get_netos_error();
+    }
+
+    alloc_socket(new, p);
+    set_socket_vars(*new, sock->local_addr->sa.sin.sin_family, SOCK_STREAM, 
+                    sock->protocol);
+
+    (*new)->timeout = -1;   
+    (*new)->disconnected = 0;
+
+    (*new)->socketdes = s;
+    /* XXX next line looks bogus w.r.t. AF_INET6 support */
+    (*new)->remote_addr->salen = sizeof((*new)->remote_addr->sa);
+    memcpy (&(*new)->remote_addr->sa, &sa, salen);
+    (*new)->remote_addr_unknown = 0;
 
-    (*new)->addr_len = sizeof(struct sockaddr_in);
+    *(*new)->local_addr = *sock->local_addr;
 
-    (*new)->sock = accept(sock->sock, (struct sockaddr *)(*new)->local_addr,
-                        &(*new)->addr_len);
+    /* The above assignment just overwrote the pool entry. Setting the local_addr 
+       pool for the accepted socket back to what it should be.  Otherwise all 
+       allocations for this socket will come from a server pool that is not
+       freed until the process goes down.*/
+    (*new)->local_addr->pool = p;
 
-    if ((*new)->sock == INVALID_SOCKET) {
-        return WSAGetLastError();
+    /* fix up any pointers which are no longer valid */
+    if (sock->local_addr->sa.sin.sin_family == AF_INET) {
+        (*new)->local_addr->ipaddr_ptr = &(*new)->local_addr->sa.sin.sin_addr;
     }
-    
-    ap_register_cleanup((*new)->cntxt, (void *)(*new), 
-                        socket_cleanup, ap_null_cleanup);
+#if APR_HAVE_IPV6
+    else if (sock->local_addr->sa.sin.sin_family == AF_INET6) {
+        (*new)->local_addr->ipaddr_ptr = &(*new)->local_addr->sa.sin6.sin6_addr;
+    }
+#endif
+    (*new)->remote_addr->port = ntohs((*new)->remote_addr->sa.sin.sin_port);
+    if (sock->local_port_unknown) {
+        /* not likely for a listening socket, but theoretically possible :) */
+        (*new)->local_port_unknown = 1;
+    }
+
+#if APR_TCP_NODELAY_INHERITED
+    if (apr_is_option_set(sock, APR_TCP_NODELAY) == 1) {
+        apr_set_option(*new, APR_TCP_NODELAY, 1);
+    }
+#endif /* TCP_NODELAY_INHERITED */
+#if APR_O_NONBLOCK_INHERITED
+    if (apr_is_option_set(sock, APR_SO_NONBLOCK) == 1) {
+        apr_set_option(*new, APR_SO_NONBLOCK, 1);
+    }
+#endif /* APR_O_NONBLOCK_INHERITED */
+
+    if (sock->local_interface_unknown ||
+        !memcmp(sock->local_addr->ipaddr_ptr,
+                generic_inaddr_any,
+                sock->local_addr->ipaddr_len)) {
+        /* If the interface address inside the listening socket's local_addr wasn't
+         * up-to-date, we don't know local interface of the connected socket either.
+         *
+         * If the listening socket was not bound to a specific interface, we
+         * don't know the local_addr of the connected socket.
+         */
+        (*new)->local_interface_unknown = 1;
+    }
+
+    apr_pool_cleanup_register((*new)->pool, (void *)(*new), 
+                        socket_cleanup, apr_pool_cleanup_null);
     return APR_SUCCESS;
 }
 
-ap_status_t ap_connect(ap_socket_t *sock, char *hostname)
+static apr_status_t wait_for_connect(apr_socket_t *sock)
 {
-    struct hostent *hp;
-    int lasterror;
-    fd_set temp;
+    int rc;
+    struct timeval tv, *tvptr;
+    fd_set wfdset, efdset;
 
-    if ((sock->sock == INVALID_SOCKET) || (!sock->local_addr)) {
-        return APR_ENOTSOCK;
-    }
+    /* wait for the connect to complete or timeout */
+    FD_ZERO(&wfdset);
+    FD_SET(sock->socketdes, &wfdset);
+    FD_ZERO(&efdset);
+    FD_SET(sock->socketdes, &efdset);
 
-    if (*hostname >= '0' && *hostname <= '9' && 
-        strspn(hostname, "0123456789.") == strlen(hostname)) {
-        sock->remote_addr->sin_addr.s_addr = inet_addr(hostname);
+    if (sock->timeout < 0) {
+        tvptr = NULL;
     }
     else {
-        hp = gethostbyname(hostname);
-        if (!hp)  {
-            return WSAGetLastError();
+        /* casts for winsock/timeval definition */
+        tv.tv_sec =  (long)apr_time_sec(sock->timeout);
+        tv.tv_usec = (int)apr_time_usec(sock->timeout);
+        tvptr = &tv;
+    }
+    rc = select(FD_SETSIZE+1, NULL, &wfdset, &efdset, tvptr);
+    if (rc == SOCKET_ERROR) {
+        return apr_get_netos_error();
+    }
+    else if (!rc) {
+        return APR_FROM_OS_ERROR(WSAETIMEDOUT);
+    }
+    /* Evaluate the efdset */
+    if (FD_ISSET(sock->socketdes, &efdset)) {
+        /* The connect failed. */
+        int rclen = sizeof(rc);
+        if (getsockopt(sock->socketdes, SOL_SOCKET, SO_ERROR, (char*) &rc, &rclen)) {
+            return apr_get_netos_error();
         }
-        memcpy((char *)&sock->remote_addr->sin_addr, hp->h_addr_list[0], hp->h_length);
-        sock->addr_len = sizeof(*sock->remote_addr);
+        return APR_FROM_OS_ERROR(rc);
     }
-    
-    sock->remote_addr->sin_family = AF_INET;
 
-    if (connect(sock->sock, (const struct sockaddr *)sock->remote_addr, 
-                sock->addr_len) == 0) {
-        return APR_SUCCESS;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_socket_connect(apr_socket_t *sock, 
+                                             apr_sockaddr_t *sa)
+{
+    apr_status_t rv;
+
+    if ((sock->socketdes == INVALID_SOCKET) || (!sock->local_addr)) {
+        return APR_ENOTSOCK;
+    }
+
+    if (connect(sock->socketdes, (const struct sockaddr *)&sa->sa.sin,
+                sa->salen) == SOCKET_ERROR) {
+        rv = apr_get_netos_error();
     }
     else {
-        lasterror = WSAGetLastError();
-        if (lasterror == WSAEWOULDBLOCK) {
-            FD_ZERO(&temp);
-            FD_SET(sock->sock, &temp);
-            if (select(sock->sock+1, NULL, &temp, NULL, NULL) == 1) {
-                return APR_SUCCESS;
+        rv = APR_SUCCESS;
+    }
+
+    if (rv == APR_FROM_OS_ERROR(WSAEWOULDBLOCK)) {
+        if (sock->timeout == 0) {
+            /* Tell the app that the connect is in progress...
+             * Gotta play some games here.  connect on Unix will return 
+             * EINPROGRESS under the same circumstances that Windows 
+             * returns WSAEWOULDBLOCK. Do some adhoc canonicalization...
+             */
+            rv = APR_FROM_OS_ERROR(WSAEINPROGRESS);
+        }
+        else {
+            rv = wait_for_connect(sock);
+            if (rv != APR_SUCCESS) {
+                return rv;
             }
         }
-        return lasterror;
     }
+
+    if (memcmp(sa->ipaddr_ptr, generic_inaddr_any, sa->ipaddr_len)) {
+        /* A real remote address was passed in.  If the unspecified
+         * address was used, the actual remote addr will have to be
+         * determined using getpeername() if required. */
+        sock->remote_addr_unknown = 0;
+
+        /* Copy the address structure details in. */
+        sock->remote_addr = sa;
+    }
+
+    if (sock->local_addr->sa.sin.sin_port == 0) {
+        /* connect() got us an ephemeral port */
+        sock->local_port_unknown = 1;
+    }
+    if (!memcmp(sock->local_addr->ipaddr_ptr,
+                generic_inaddr_any,
+                sock->local_addr->ipaddr_len)) {
+        /* not bound to specific local interface; connect() had to assign
+         * one for the socket
+         */
+        sock->local_interface_unknown = 1;
+    }
+
+    if (rv != APR_SUCCESS && rv != APR_FROM_OS_ERROR(WSAEISCONN)) {
+        return rv;
+    }
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_socket_type_get(apr_socket_t *sock, int *type)
+{
+    *type = sock->type;
+    return APR_SUCCESS;
 }
 
-ap_status_t ap_get_socketdata(void **data, char *key, ap_socket_t *socket)
+APR_DECLARE(apr_status_t) apr_socket_data_get(void **data, const char *key,
+                                             apr_socket_t *sock)
 {
-    return ap_get_userdata(data, key, socket->cntxt);
+    sock_userdata_t *cur = sock->userdata;
+
+    *data = NULL;
+
+    while (cur) {
+        if (!strcmp(cur->key, key)) {
+            *data = cur->data;
+            break;
+        }
+        cur = cur->next;
+    }
+
+    return APR_SUCCESS;
 }
 
-ap_status_t ap_set_socketdata(ap_socket_t *socket, void *data, char *key, 
-                              ap_status_t (*cleanup) (void *))
+APR_DECLARE(apr_status_t) apr_socket_data_set(apr_socket_t *sock, void *data,
+                                             const char *key,
+                                             apr_status_t (*cleanup)(void *))
 {
-    return ap_set_userdata(data, key, cleanup, socket->cntxt);
+    sock_userdata_t *new = apr_palloc(sock->pool, sizeof(sock_userdata_t));
+
+    new->key = apr_pstrdup(sock->pool, key);
+    new->data = data;
+    new->next = sock->userdata;
+    sock->userdata = new;
+
+    if (cleanup) {
+        apr_pool_cleanup_register(sock->pool, data, cleanup, cleanup);
+    }
+
+    return APR_SUCCESS;
 }
 
-ap_status_t ap_get_os_sock(ap_os_sock_t *thesock, ap_socket_t *sock)
+APR_DECLARE(apr_status_t) apr_os_sock_get(apr_os_sock_t *thesock,
+                                          apr_socket_t *sock)
 {
-    *thesock = sock->sock;
+    *thesock = sock->socketdes;
     return APR_SUCCESS;
 }
 
-ap_status_t ap_put_os_sock(ap_socket_t **sock, ap_os_sock_t *thesock, 
-                           ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_os_sock_make(apr_socket_t **apr_sock,
+                                           apr_os_sock_info_t *os_sock_info,
+                                           apr_pool_t *cont)
 {
-    if (cont == NULL) {
-        return APR_ENOPOOL;
+    alloc_socket(apr_sock, cont);
+    set_socket_vars(*apr_sock, os_sock_info->family, os_sock_info->type, os_sock_info->protocol);
+    (*apr_sock)->timeout = -1;
+    (*apr_sock)->disconnected = 0;
+    (*apr_sock)->socketdes = *os_sock_info->os_sock;
+    if (os_sock_info->local) {
+        memcpy(&(*apr_sock)->local_addr->sa.sin, 
+               os_sock_info->local, 
+               (*apr_sock)->local_addr->salen);
+        (*apr_sock)->local_addr->pool = cont;
+        /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */
+        (*apr_sock)->local_addr->port = ntohs((*apr_sock)->local_addr->sa.sin.sin_port);
     }
+    else {
+        (*apr_sock)->local_port_unknown = (*apr_sock)->local_interface_unknown = 1;
+    }
+    if (os_sock_info->remote) {
+        memcpy(&(*apr_sock)->remote_addr->sa.sin, 
+               os_sock_info->remote,
+               (*apr_sock)->remote_addr->salen);
+        (*apr_sock)->remote_addr->pool = cont;
+        /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */
+        (*apr_sock)->remote_addr->port = ntohs((*apr_sock)->remote_addr->sa.sin.sin_port);
+        (*apr_sock)->remote_addr_unknown = 0;
+    }
+        
+    apr_pool_cleanup_register((*apr_sock)->pool, (void *)(*apr_sock), 
+                        socket_cleanup, apr_pool_cleanup_null);
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_os_sock_put(apr_socket_t **sock,
+                                          apr_os_sock_t *thesock,
+                                          apr_pool_t *cont)
+{
     if ((*sock) == NULL) {
-        (*sock) = (ap_socket_t *)ap_palloc(cont, sizeof(ap_socket_t));
-        (*sock)->cntxt = cont;
-        (*sock)->local_addr = (struct sockaddr_in *)ap_palloc((*sock)->cntxt,
-                             sizeof(struct sockaddr_in));
-        (*sock)->remote_addr = (struct sockaddr_in *)ap_palloc((*sock)->cntxt,
-                              sizeof(struct sockaddr_in));
-
-        if ((*sock)->local_addr == NULL || (*sock)->remote_addr == NULL) {
-            return APR_ENOMEM;
-        }
-     
-        (*sock)->addr_len = sizeof(*(*sock)->local_addr);
+        alloc_socket(sock, cont);
+        /* XXX figure out the actual socket type here */
+        /* *or* just decide that apr_os_sock_put() has to be told the family and type */
+        set_socket_vars(*sock, AF_INET, SOCK_STREAM, 0);
         (*sock)->timeout = -1;
+        (*sock)->disconnected = 0;
     }
-    (*sock)->sock = *thesock;
+    (*sock)->local_port_unknown = (*sock)->local_interface_unknown = 1;
+    (*sock)->remote_addr_unknown = 1;
+    (*sock)->socketdes = *thesock;
     return APR_SUCCESS;
 }
+
+
+/* Sockets cannot be inherited through the standard sockets
+ * inheritence.  WSADuplicateSocket must be used.
+ * This is not trivial to implement.
+ */
+
+APR_DECLARE(apr_status_t) apr_socket_inherit_set(apr_socket_t *socket)    
+{    
+    return APR_ENOTIMPL;
+}    
+
+APR_DECLARE(apr_status_t) apr_socket_inherit_unset(apr_socket_t *socket)    
+{    
+    return APR_ENOTIMPL;
+}    
+
+APR_POOL_IMPLEMENT_ACCESSOR(socket);
diff --git a/network_io/win32/sockopt.c b/network_io/win32/sockopt.c
index d269b64e6a2..463eeebf55c 100644
--- a/network_io/win32/sockopt.c
+++ b/network_io/win32/sockopt.c
@@ -1,186 +1,302 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "networkio.h"
+#include "apr_arch_networkio.h"
+#include "apr_arch_misc.h" /* apr_os_level */
 #include "apr_network_io.h"
 #include "apr_general.h"
-#include "apr_lib.h"
+#include "apr_strings.h"
 #include <string.h>
-#include <winsock2.h>
 
-ap_status_t soblock(SOCKET sd)
+/* IPV6_V6ONLY is missing from pre-Windows 2008 SDK as well as MinGW
+ * (at least up through 1.0.16).
+ * Runtime support is a separate issue.
+ */
+#ifndef IPV6_V6ONLY
+#define IPV6_V6ONLY 27
+#endif
+
+static apr_status_t soblock(SOCKET sd)
 {
-    int one = 1;
+    u_long zero = 0;
 
-    if (ioctlsocket(sd, FIONBIO, &one) == SOCKET_ERROR) {
-        return APR_EEXIST;
+    if (ioctlsocket(sd, FIONBIO, &zero) == SOCKET_ERROR) {
+        return apr_get_netos_error();
     }
     return APR_SUCCESS;
 }
 
-ap_status_t sononblock(SOCKET sd)
+static apr_status_t sononblock(SOCKET sd)
 {
-    int zero = 0;
+    u_long one = 1;
 
-    if (ioctlsocket(sd, FIONBIO, &zero) == SOCKET_ERROR) {
-        return APR_EEXIST;
+    if (ioctlsocket(sd, FIONBIO, &one) == SOCKET_ERROR) {
+        return apr_get_netos_error();
     }
     return APR_SUCCESS;
 }
 
-ap_status_t ap_setsocketopt(ap_socket_t *sock, ap_int32_t opt, ap_int32_t on)
+
+APR_DECLARE(apr_status_t) apr_socket_timeout_set(apr_socket_t *sock, apr_interval_time_t t)
 {
-    int one;
-    struct linger li;
-    ap_status_t stat;
-
-    if (on)
-        one = 1;
-    else
-        one = 0;
-
-    if (opt & APR_SO_TIMEOUT) {
-        int timeout;
-        sock->timeout = on;
-        timeout = on / 1000; /* Windows needs timeout in mSeconds */
-        if (setsockopt(sock->sock, SOL_SOCKET, SO_RCVTIMEO, (char*) &timeout, 
-                       sizeof(timeout)) == SOCKET_ERROR) {
-            return WSAGetLastError();
-        }
-    }
-    if (opt & APR_SO_KEEPALIVE) {
-        if (setsockopt(sock->sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&one, sizeof(int)) == -1) {
-            return WSAGetLastError();
-        }
-    }
-    if (opt & APR_SO_DEBUG) {
-        if (setsockopt(sock->sock, SOL_SOCKET, SO_DEBUG, (void *)&one, sizeof(int)) == -1) {
-            return WSAGetLastError();
-        }
-    }
-    if (opt & APR_SO_REUSEADDR) {
-        if (setsockopt(sock->sock, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(int)) == -1) {
-            return WSAGetLastError();
+    apr_status_t stat;
+
+    if (t == 0) {
+        /* Set the socket non-blocking if it was previously blocking */
+        if (sock->timeout != 0) {
+            if ((stat = sononblock(sock->socketdes)) != APR_SUCCESS)
+                return stat;
         }
     }
-    if (opt & APR_SO_NONBLOCK) {
-        if (on) {
-            if ((stat = soblock(sock->sock)) != APR_SUCCESS) 
+    else if (t > 0) {
+        /* Set the socket to blocking if it was previously non-blocking */
+        if (sock->timeout == 0 || apr_is_option_set(sock, APR_SO_NONBLOCK)) {
+            if ((stat = soblock(sock->socketdes)) != APR_SUCCESS)
                 return stat;
+            apr_set_option(sock, APR_SO_NONBLOCK, 0);
         }
-        else {
-            if ((stat = sononblock(sock->sock)) != APR_SUCCESS)
-                return stat;
+        /* Reset socket timeouts if the new timeout differs from the old timeout */
+        if (sock->timeout != t) 
+        {
+            /* Win32 timeouts are in msec, represented as int */
+            sock->timeout_ms = (int)apr_time_as_msec(t);
+            setsockopt(sock->socketdes, SOL_SOCKET, SO_RCVTIMEO, 
+                       (char *) &sock->timeout_ms, 
+                       sizeof(sock->timeout_ms));
+            setsockopt(sock->socketdes, SOL_SOCKET, SO_SNDTIMEO, 
+                       (char *) &sock->timeout_ms, 
+                       sizeof(sock->timeout_ms));
         }
     }
-    if (opt & APR_SO_LINGER) {
-        li.l_onoff = on;
-        li.l_linger = MAX_SECS_TO_LINGER;
-        if (setsockopt(sock->sock, SOL_SOCKET, SO_LINGER, (char *) &li, sizeof(struct linger)) == -1) {
-            return APR_EEXIST;
-        }
+    else if (t < 0) {
+        int zero = 0;
+        /* Set the socket to blocking with infinite timeouts */
+        if ((stat = soblock(sock->socketdes)) != APR_SUCCESS)
+            return stat;
+        setsockopt(sock->socketdes, SOL_SOCKET, SO_RCVTIMEO, 
+                   (char *) &zero, sizeof(zero));
+        setsockopt(sock->socketdes, SOL_SOCKET, SO_SNDTIMEO, 
+                   (char *) &zero, sizeof(zero));
     }
+    sock->timeout = t;
     return APR_SUCCESS;
 }
 
-ap_status_t ap_gethostname(char *buf, int len, ap_pool_t *cont)
-{
-    if (gethostname(buf, len) == -1)
-        return APR_EEXIST;
-    else
-        return APR_SUCCESS;
-}
 
-ap_status_t ap_get_remote_hostname(char **name, ap_socket_t *sock)
+APR_DECLARE(apr_status_t) apr_socket_opt_set(apr_socket_t *sock,
+                                             apr_int32_t opt, apr_int32_t on)
 {
-    struct hostent *hptr;
+    int one;
+    apr_status_t stat;
 
-    hptr = gethostbyaddr((char *)&(sock->local_addr->sin_addr),
-                         sizeof(struct in_addr), AF_INET);
+    one = on ? 1 : 0;
 
-    if (hptr != NULL) {
-        *name = ap_pstrdup(sock->cntxt, hptr->h_name);
-        if (*name) {
-            return APR_SUCCESS;
+    switch (opt) {
+    case APR_SO_KEEPALIVE:
+        if (on != apr_is_option_set(sock, APR_SO_KEEPALIVE)) {
+            if (setsockopt(sock->socketdes, SOL_SOCKET, SO_KEEPALIVE, 
+                           (void *)&one, sizeof(int)) == -1) {
+                return apr_get_netos_error();
+            }
+            apr_set_option(sock, APR_SO_KEEPALIVE, on);
         }
-        return APR_ENOMEM;
+        break;
+    case APR_SO_DEBUG:
+        if (on != apr_is_option_set(sock, APR_SO_DEBUG)) {
+            if (setsockopt(sock->socketdes, SOL_SOCKET, SO_DEBUG, 
+                           (void *)&one, sizeof(int)) == -1) {
+                return apr_get_netos_error();
+            }
+            apr_set_option(sock, APR_SO_DEBUG, on);
+        }
+        break;
+    case APR_SO_SNDBUF:
+        if (setsockopt(sock->socketdes, SOL_SOCKET, SO_SNDBUF,
+                       (void *)&on, sizeof(int)) == -1) {
+            return apr_get_netos_error();
+        }
+        break;
+    case APR_SO_RCVBUF:
+        if (setsockopt(sock->socketdes, SOL_SOCKET, SO_RCVBUF,
+                       (void *)&on, sizeof(int)) == -1) {
+            return apr_get_netos_error();
+        }
+        break;
+    case APR_SO_BROADCAST:
+        if (on != apr_is_option_set(sock, APR_SO_BROADCAST)) {
+           if (setsockopt(sock->socketdes, SOL_SOCKET, SO_BROADCAST, 
+                           (void *)&one, sizeof(int)) == -1) {
+                return apr_get_netos_error();
+            }
+            apr_set_option(sock, APR_SO_BROADCAST, on);
+        }
+        break;
+    case APR_SO_REUSEADDR:
+        if (on != apr_is_option_set(sock, APR_SO_REUSEADDR)) {
+            if (setsockopt(sock->socketdes, SOL_SOCKET, SO_REUSEADDR, 
+                           (void *)&one, sizeof(int)) == -1) {
+                return apr_get_netos_error();
+            }
+            apr_set_option(sock, APR_SO_REUSEADDR, on);
+        }
+        break;
+    case APR_SO_NONBLOCK:
+        if (apr_is_option_set(sock, APR_SO_NONBLOCK) != on) {
+            if (on) {
+                if ((stat = sononblock(sock->socketdes)) != APR_SUCCESS) 
+                    return stat;
+            }
+            else {
+                if ((stat = soblock(sock->socketdes)) != APR_SUCCESS)
+                    return stat;
+            }
+            apr_set_option(sock, APR_SO_NONBLOCK, on);
+        }
+        break;
+    case APR_SO_LINGER:
+    {
+        if (apr_is_option_set(sock, APR_SO_LINGER) != on) {
+            struct linger li;
+            li.l_onoff = on;
+            li.l_linger = APR_MAX_SECS_TO_LINGER;
+            if (setsockopt(sock->socketdes, SOL_SOCKET, SO_LINGER, 
+                           (char *) &li, sizeof(struct linger)) == -1) {
+                return apr_get_netos_error();
+            }
+            apr_set_option(sock, APR_SO_LINGER, on);
+        }
+        break;
     }
+    case APR_TCP_DEFER_ACCEPT:
+#if defined(TCP_DEFER_ACCEPT)
+        if (apr_is_option_set(sock, APR_TCP_DEFER_ACCEPT) != on) {
+            int optlevel = IPPROTO_TCP;
+            int optname = TCP_DEFER_ACCEPT;
 
-    return (WSAGetLastError() + APR_OS_START_SYSERR);
-}
-#if 0
-ap_status_t status_from_res_error(int reserr)
-{
-    ap_status_t status;
-    switch(reserr) {
-    case WSAHOST_NOT_FOUND:
-        status = APR_EHOSTNOTFOUND;
+            if (setsockopt(sock->socketdes, optlevel, optname, 
+                           (void *)&on, sizeof(int)) == -1) {
+                return apr_get_netos_error();
+            }
+            apr_set_option(sock, APR_TCP_DEFER_ACCEPT, on);
+        }
+#else
+        return APR_ENOTIMPL;
+#endif
+    case APR_TCP_NODELAY:
+        if (apr_is_option_set(sock, APR_TCP_NODELAY) != on) {
+            int optlevel = IPPROTO_TCP;
+            int optname = TCP_NODELAY;
+
+#if APR_HAVE_SCTP
+            if (sock->protocol == IPPROTO_SCTP) {
+                optlevel = IPPROTO_SCTP;
+                optname = SCTP_NODELAY;
+            }
+#endif
+            if (setsockopt(sock->socketdes, optlevel, optname,
+                           (void *)&on, sizeof(int)) == -1) {
+                return apr_get_netos_error();
+            }
+            apr_set_option(sock, APR_TCP_NODELAY, on);
+        }
         break;
-    case WSATRY_AGAIN:
-        status = APR_EAGAIN;
+    case APR_IPV6_V6ONLY:
+#if APR_HAVE_IPV6
+        if (apr_os_level < APR_WIN_VISTA && 
+            sock->local_addr->family == AF_INET6) {
+            /* apr_set_option() called at socket creation */
+            if (on) {
+                return APR_SUCCESS;
+            }
+            else {
+                return APR_ENOTIMPL;
+            }
+        }
+        /* we don't know the initial setting of this option,
+         * so don't check sock->options since that optimization
+         * won't work
+         */
+        if (setsockopt(sock->socketdes, IPPROTO_IPV6, IPV6_V6ONLY,
+                       (void *)&on, sizeof(int)) == -1) {
+            return apr_get_netos_error();
+        }
+        apr_set_option(sock, APR_IPV6_V6ONLY, on);
+#else
+        return APR_ENOTIMPL;
+#endif
         break;
-    case WSANO_RECOVERY:
-        status = APR_ENORECOVERY;
+    default:
+        return APR_EINVAL;
         break;
-    case WSANO_DATA:
-        status = APR_ENODATA;
+    }
+    return APR_SUCCESS;
+}
+
+
+APR_DECLARE(apr_status_t) apr_socket_timeout_get(apr_socket_t *sock, apr_interval_time_t *t)
+{
+    *t = sock->timeout;
+    return APR_SUCCESS;
+}
+
+
+APR_DECLARE(apr_status_t) apr_socket_opt_get(apr_socket_t *sock,
+                                             apr_int32_t opt, apr_int32_t *on)
+{
+    switch (opt) {
+    case APR_SO_DISCONNECTED:
+        *on = sock->disconnected;
         break;
+    case APR_SO_KEEPALIVE:
+    case APR_SO_DEBUG:
+    case APR_SO_REUSEADDR:
+    case APR_SO_NONBLOCK:
+    case APR_SO_LINGER:
     default:
-        status = APR_ENORECOVERY;
+        *on = apr_is_option_set(sock, opt);
+        break;
     }
-    return status;
+    return APR_SUCCESS;
 }
-#endif
 
 
+APR_DECLARE(apr_status_t) apr_socket_atmark(apr_socket_t *sock, int *atmark)
+{
+    u_long oobmark;
+
+    if (ioctlsocket(sock->socketdes, SIOCATMARK, (void*) &oobmark) < 0)
+        return apr_get_netos_error();
+
+    *atmark = (oobmark != 0);
+
+    return APR_SUCCESS;
+}
+
+
+APR_DECLARE(apr_status_t) apr_gethostname(char *buf, int len,
+                                          apr_pool_t *cont)
+{
+    if (gethostname(buf, len) == -1) {
+        buf[0] = '\0';
+        return apr_get_netos_error();
+    }
+    else if (!memchr(buf, '\0', len)) { /* buffer too small */
+        buf[0] = '\0';
+        return APR_ENAMETOOLONG;
+    }
+    return APR_SUCCESS;
+}
+
diff --git a/passwd/apr_getpass.c b/passwd/apr_getpass.c
new file mode 100644
index 00000000000..6e4cbef3af8
--- /dev/null
+++ b/passwd/apr_getpass.c
@@ -0,0 +1,256 @@
+/* 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.
+ */
+
+/* apr_password_get.c: abstraction to provide for obtaining a password from the
+ * command line in whatever way the OS supports.  In the best case, it's a
+ * wrapper for the system library's getpass() routine; otherwise, we
+ * use one we define ourselves.
+ */
+#include "apr_private.h"
+#include "apr_strings.h"
+#include "apr_lib.h"
+#include "apr_errno.h"
+#if APR_HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#if APR_HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#if APR_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if APR_HAVE_CONIO_H
+#ifdef _MSC_VER
+#pragma warning(disable: 4032)
+#include <conio.h>
+#pragma warning(default: 4032)
+#else
+#include <conio.h>
+#endif
+#endif
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if APR_HAVE_STRING_H
+#include <string.h>
+#endif
+#if APR_HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#if APR_HAVE_STDIO_H
+#include <stdio.h>
+#endif
+
+/* Disable getpass() support when PASS_MAX is defined and is "small",
+ * for an arbitrary definition of "small".
+ * HP-UX truncates passwords (PR49496) so we disable getpass() for
+ * this platform too.
+ */
+#if defined(HAVE_GETPASS) && \
+    (defined(PASS_MAX) && PASS_MAX < 32) || defined(__hpux) || defined(__hpux__)
+#undef HAVE_GETPASS
+#endif
+
+#if defined(HAVE_TERMIOS_H) && !defined(HAVE_GETPASS)
+#include <termios.h>
+#endif
+
+#if !APR_CHARSET_EBCDIC
+#define LF 10
+#define CR 13
+#else /* APR_CHARSET_EBCDIC */
+#define LF '\n'
+#define CR '\r'
+#endif /* APR_CHARSET_EBCDIC */
+
+#define MAX_STRING_LEN 256
+
+#define ERR_OVERFLOW 5
+
+#if !defined(HAVE_GETPASS) && !defined(HAVE_GETPASSPHRASE) && !defined(HAVE_GETPASS_R)
+
+/* MPE, Win32, and BeOS all lack a native getpass() */
+
+#if !defined(HAVE_TERMIOS_H) && !defined(WIN32)
+/*
+ * MPE lacks getpass() and a way to suppress stdin echo.  So for now, just
+ * issue the prompt and read the results with echo.  (Ugh).
+ */
+
+static char *get_password(const char *prompt)
+{
+    static char password[MAX_STRING_LEN];
+
+    fputs(prompt, stderr);
+    fgets((char *) &password, sizeof(password), stdin);
+
+    return (char *) &password;
+}
+
+#elif defined(WIN32)
+
+/*
+ * Windows lacks getpass().  So we'll re-implement it here.
+ */
+
+static char *get_password(const char *prompt)
+{
+/* WCE lacks console. So the getpass is unsuported
+ * The only way is to use the GUI so the getpass should be implemented
+ * on per-application basis.
+ */ 
+#ifdef _WIN32_WCE
+    return NULL;
+#else
+    static char password[128];
+    int n = 0;
+    int ch;
+
+    fputs(prompt, stderr);
+    
+    while ((ch = _getch()) != '\r') {
+        if (ch == EOF) /* EOF */ {
+            fputs("[EOF]\n", stderr);
+            return NULL;
+        }
+        else if (ch == 0 || ch == 0xE0) {
+            /* FN Keys (0 or E0) are a sentinal for a FN code */ 
+            ch = (ch << 4) | _getch();
+            /* Catch {DELETE}, {<--}, Num{DEL} and Num{<--} */
+            if ((ch == 0xE53 || ch == 0xE4B || ch == 0x053 || ch == 0x04b) && n) {
+                password[--n] = '\0';
+                fputs("\b \b", stderr);
+            }
+            else {
+                fputc('\a', stderr);
+            }
+        }
+        else if ((ch == '\b' || ch == 127) && n) /* BS/DEL */ {
+            password[--n] = '\0';
+            fputs("\b \b", stderr);
+        }
+        else if (ch == 3) /* CTRL+C */ {
+            /* _getch() bypasses Ctrl+C but not Ctrl+Break detection! */
+            fputs("^C\n", stderr);
+            exit(-1);
+        }
+        else if (ch == 26) /* CTRL+Z */ {
+            fputs("^Z\n", stderr);
+            return NULL;
+        }
+        else if (ch == 27) /* ESC */ {
+            fputc('\n', stderr);
+            fputs(prompt, stderr);
+            n = 0;
+        }
+        else if ((n < sizeof(password) - 1) && !apr_iscntrl(ch)) {
+            password[n++] = ch;
+            fputc('*', stderr);
+        }
+        else {
+            fputc('\a', stderr);
+        }
+    }
+ 
+    fputc('\n', stderr);
+    password[n] = '\0';
+    return password;
+#endif
+}
+
+#elif defined (HAVE_TERMIOS_H)
+
+static char *get_password(const char *prompt)
+{
+    struct termios attr;
+    static char password[MAX_STRING_LEN];
+    int n=0;
+    fputs(prompt, stderr);
+    fflush(stderr);
+
+    if (tcgetattr(STDIN_FILENO, &attr) != 0)
+        return NULL;
+    attr.c_lflag &= ~(ECHO);
+
+    if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &attr) != 0)
+        return NULL;
+    while ((password[n] = getchar()) != '\n') {
+        if (n < sizeof(password) - 1 && password[n] >= ' ' && password[n] <= '~') {
+            n++;
+        } else {
+            fprintf(stderr,"\n");
+            fputs(prompt, stderr);
+            fflush(stderr);
+            n = 0;
+        }
+    }
+ 
+    password[n] = '\0';
+    printf("\n");
+    if (n > (MAX_STRING_LEN - 1)) {
+        password[MAX_STRING_LEN - 1] = '\0';
+    }
+
+    attr.c_lflag |= ECHO;
+    tcsetattr(STDIN_FILENO, TCSANOW, &attr);
+    return (char*) &password;
+}
+
+#endif /* no getchar or _getch */
+
+#endif /* no getpass or getpassphrase or getpass_r */
+
+/*
+ * Use the OS getpass() routine (or our own) to obtain a password from
+ * the input stream.
+ *
+ * Exit values:
+ *  0: Success
+ *  5: Partial success; entered text truncated to the size of the
+ *     destination buffer
+ *
+ * Restrictions: Truncation also occurs according to the host system's
+ * getpass() semantics, or at position 255 if our own version is used,
+ * but the caller is *not* made aware of it unless their own buffer is
+ * smaller than our own.
+ */
+
+APR_DECLARE(apr_status_t) apr_password_get(const char *prompt, char *pwbuf, apr_size_t *bufsiz)
+{
+    apr_status_t rv = APR_SUCCESS;
+#if defined(HAVE_GETPASS_R)
+    if (getpass_r(prompt, pwbuf, *bufsiz) == NULL)
+        return APR_EINVAL;
+#else
+#if defined(HAVE_GETPASSPHRASE)
+    char *pw_got = getpassphrase(prompt);
+#elif defined(HAVE_GETPASS)
+    char *pw_got = getpass(prompt);
+#else /* use the replacement implementation above */
+    char *pw_got = get_password(prompt);
+#endif
+
+    if (!pw_got)
+        return APR_EINVAL;
+    if (strlen(pw_got) >= *bufsiz) {
+        rv = APR_ENAMETOOLONG;
+    }
+    apr_cpystrn(pwbuf, pw_got, *bufsiz);
+    memset(pw_got, 0, strlen(pw_got));
+#endif /* HAVE_GETPASS_R */
+    return rv;
+}
diff --git a/poll/os2/poll.c b/poll/os2/poll.c
new file mode 100644
index 00000000000..3c36e5e688e
--- /dev/null
+++ b/poll/os2/poll.c
@@ -0,0 +1,105 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_poll.h"
+#include "apr_arch_networkio.h"
+
+APR_DECLARE(apr_status_t) apr_poll(apr_pollfd_t *aprset, apr_int32_t num,
+                      apr_int32_t *nsds, apr_interval_time_t timeout)
+{
+    int *pollset;
+    int i;
+    int num_read = 0, num_write = 0, num_except = 0, num_total;
+    int pos_read, pos_write, pos_except;
+
+    for (i = 0; i < num; i++) {
+        if (aprset[i].desc_type == APR_POLL_SOCKET) {
+            num_read += (aprset[i].reqevents & APR_POLLIN) != 0;
+            num_write += (aprset[i].reqevents & APR_POLLOUT) != 0;
+            num_except += (aprset[i].reqevents & APR_POLLPRI) != 0;
+        }
+    }
+
+    num_total = num_read + num_write + num_except;
+    pollset = alloca(sizeof(int) * num_total);
+    memset(pollset, 0, sizeof(int) * num_total);
+
+    pos_read = 0;
+    pos_write = num_read;
+    pos_except = pos_write + num_write;
+
+    for (i = 0; i < num; i++) {
+        if (aprset[i].desc_type == APR_POLL_SOCKET) {
+            if (aprset[i].reqevents & APR_POLLIN) {
+                pollset[pos_read++] = aprset[i].desc.s->socketdes;
+            }
+
+            if (aprset[i].reqevents & APR_POLLOUT) {
+                pollset[pos_write++] = aprset[i].desc.s->socketdes;
+            }
+
+            if (aprset[i].reqevents & APR_POLLPRI) {
+                pollset[pos_except++] = aprset[i].desc.s->socketdes;
+            }
+
+            aprset[i].rtnevents = 0;
+        }
+    }
+
+    if (timeout > 0) {
+        timeout /= 1000; /* convert microseconds to milliseconds */
+    }
+
+    i = select(pollset, num_read, num_write, num_except, timeout);
+    (*nsds) = i;
+
+    if ((*nsds) < 0) {
+        return APR_FROM_OS_ERROR(sock_errno());
+    }
+
+    if ((*nsds) == 0) {
+        return APR_TIMEUP;
+    }
+
+    pos_read = 0;
+    pos_write = num_read;
+    pos_except = pos_write + num_write;
+
+    for (i = 0; i < num; i++) {
+        if (aprset[i].desc_type == APR_POLL_SOCKET) {
+            if (aprset[i].reqevents & APR_POLLIN) {
+                if (pollset[pos_read++] > 0) {
+                    aprset[i].rtnevents |= APR_POLLIN;
+                }
+            }
+
+            if (aprset[i].reqevents & APR_POLLOUT) {
+                if (pollset[pos_write++] > 0) {
+                    aprset[i].rtnevents |= APR_POLLOUT;
+                }
+            }
+
+            if (aprset[i].reqevents & APR_POLLPRI) {
+                if (pollset[pos_except++] > 0) {
+                    aprset[i].rtnevents |= APR_POLLPRI;
+                }
+            }
+        }
+    }
+
+    return APR_SUCCESS;
+}
diff --git a/poll/os2/pollcb.c b/poll/os2/pollcb.c
new file mode 100644
index 00000000000..63b33cb169f
--- /dev/null
+++ b/poll/os2/pollcb.c
@@ -0,0 +1,96 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_poll.h"
+
+struct apr_pollcb_t {
+    apr_pool_t *pool;
+    apr_pollset_t *pollset;
+};
+
+
+
+APR_DECLARE(apr_status_t) apr_pollcb_create(apr_pollcb_t **pollcb,
+                                            apr_uint32_t size,
+                                            apr_pool_t *p,
+                                            apr_uint32_t flags)
+{
+    return apr_pollcb_create_ex(pollcb, size, p, flags, APR_POLLSET_DEFAULT);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_pollcb_create_ex(apr_pollcb_t **ret_pollcb,
+                                               apr_uint32_t size,
+                                               apr_pool_t *p,
+                                               apr_uint32_t flags,
+                                               apr_pollset_method_e method)
+{
+    apr_pollcb_t *pollcb = apr_palloc(p, sizeof(apr_pollcb_t));
+    pollcb->pool = p;
+    *ret_pollcb = pollcb;
+    return apr_pollset_create_ex(&pollcb->pollset, size, p, flags, method);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_pollcb_add(apr_pollcb_t *pollcb,
+                                         apr_pollfd_t *descriptor)
+{
+    return apr_pollset_add(pollcb->pollset, descriptor);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_pollcb_remove(apr_pollcb_t *pollcb,
+                                            apr_pollfd_t *descriptor)
+{
+    return apr_pollset_remove(pollcb->pollset, descriptor);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_pollcb_poll(apr_pollcb_t *pollcb,
+                                          apr_interval_time_t timeout,
+                                          apr_pollcb_cb_t func,
+                                          void *baton)
+{
+    int c;
+    int num_signaled = 0;
+    const apr_pollfd_t *signalled_descriptors;
+    apr_status_t rc = apr_pollset_poll(pollcb->pollset, timeout, &num_signaled, &signalled_descriptors);
+
+    for (c = 0; rc == APR_SUCCESS && c < num_signaled; c++) {
+        rc = func(baton, signalled_descriptors + c);
+    }
+
+    return rc;
+}
+
+
+
+APR_DECLARE(const char *) apr_pollcb_method_name(apr_pollcb_t *pollcb)
+{
+    return "poll";
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_pollcb_wakeup(apr_pollcb_t *pollcb)
+{
+    return apr_pollset_wakeup(pollcb->pollset);
+}
diff --git a/poll/os2/pollset.c b/poll/os2/pollset.c
new file mode 100644
index 00000000000..2ec848105be
--- /dev/null
+++ b/poll/os2/pollset.c
@@ -0,0 +1,321 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_poll.h"
+#include "apr_arch_networkio.h"
+
+#ifndef MSG_DONTWAIT
+#define MSG_DONTWAIT  0x100
+#endif
+
+struct apr_pollset_t {
+    apr_pool_t *pool;
+    apr_uint32_t nelts;
+    apr_uint32_t nalloc;
+    int *pollset;
+    int num_read;
+    int num_write;
+    int num_except;
+    int num_total;
+    apr_pollfd_t *query_set;
+    apr_pollfd_t *result_set;
+    apr_socket_t *wake_listen;
+    apr_socket_t *wake_sender;
+    apr_sockaddr_t *wake_address;
+};
+
+
+
+APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset,
+                                             apr_uint32_t size,
+                                             apr_pool_t *p,
+                                             apr_uint32_t flags)
+{
+    apr_status_t rc = APR_SUCCESS;
+
+    if (flags & APR_POLLSET_WAKEABLE) {
+        size++;
+    }
+
+    *pollset = apr_palloc(p, sizeof(**pollset));
+    (*pollset)->pool = p;
+    (*pollset)->nelts = 0;
+    (*pollset)->nalloc = size;
+    (*pollset)->pollset = apr_palloc(p, size * sizeof(int) * 3);
+    (*pollset)->query_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
+    (*pollset)->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
+    (*pollset)->num_read = -1;
+    (*pollset)->wake_listen = NULL;
+    (*pollset)->wake_sender = NULL;
+
+    if (flags & APR_POLLSET_WAKEABLE) {
+        rc = apr_socket_create(&(*pollset)->wake_listen, APR_UNIX, SOCK_DGRAM, 0, p);
+
+        if (rc == APR_SUCCESS) {
+            apr_sockaddr_t *listen_address;
+            apr_socket_timeout_set((*pollset)->wake_listen, 0);
+            apr_sockaddr_info_get(&listen_address, "", APR_UNIX, 0, 0, p);
+            rc = apr_socket_bind((*pollset)->wake_listen, listen_address);
+
+            if (rc == APR_SUCCESS) {
+                apr_pollfd_t wake_poll_fd;
+                wake_poll_fd.p = p;
+                wake_poll_fd.desc_type = APR_POLL_SOCKET;
+                wake_poll_fd.reqevents = APR_POLLIN;
+                wake_poll_fd.desc.s = (*pollset)->wake_listen;
+                wake_poll_fd.client_data = NULL;
+                apr_pollset_add(*pollset, &wake_poll_fd);
+                apr_socket_addr_get(&(*pollset)->wake_address, APR_LOCAL, (*pollset)->wake_listen);
+
+                rc = apr_socket_create(&(*pollset)->wake_sender, APR_UNIX, SOCK_DGRAM, 0, p);
+            }
+        }
+    }
+
+    return rc;
+}
+
+APR_DECLARE(apr_status_t) apr_pollset_create_ex(apr_pollset_t **pollset,
+                                                apr_uint32_t size,
+                                                apr_pool_t *p,
+                                                apr_uint32_t flags,
+                                                apr_pollset_method_e method)
+{
+    /* Only one method is supported */
+    if (flags & APR_POLLSET_NODEFAULT) {
+        if (method != APR_POLLSET_DEFAULT && method != APR_POLLSET_POLL) {
+            return APR_ENOTIMPL;
+        }
+    }
+
+    return apr_pollset_create(pollset, size, p, flags);
+}
+
+APR_DECLARE(apr_status_t) apr_pollset_destroy(apr_pollset_t *pollset)
+{
+    /* A no-op function for now.  If we later implement /dev/poll
+     * support, we'll need to close the /dev/poll fd here
+     */
+    return APR_SUCCESS;
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset,
+                                          const apr_pollfd_t *descriptor)
+{
+    if (pollset->nelts == pollset->nalloc) {
+        return APR_ENOMEM;
+    }
+
+    pollset->query_set[pollset->nelts] = *descriptor;
+
+    if (descriptor->desc_type != APR_POLL_SOCKET) {
+        return APR_EBADF;
+    }
+
+    pollset->nelts++;
+    pollset->num_read = -1;
+    return APR_SUCCESS;
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset,
+                                             const apr_pollfd_t *descriptor)
+{
+    apr_uint32_t i;
+
+    for (i = 0; i < pollset->nelts; i++) {
+        if (descriptor->desc.s == pollset->query_set[i].desc.s) {
+            /* Found an instance of the fd: remove this and any other copies */
+            apr_uint32_t dst = i;
+            apr_uint32_t old_nelts = pollset->nelts;
+            pollset->nelts--;
+
+            for (i++; i < old_nelts; i++) {
+                if (descriptor->desc.s == pollset->query_set[i].desc.s) {
+                    pollset->nelts--;
+                }
+                else {
+                    pollset->pollset[dst] = pollset->pollset[i];
+                    pollset->query_set[dst] = pollset->query_set[i];
+                    dst++;
+                }
+            }
+
+            pollset->num_read = -1;
+            return APR_SUCCESS;
+        }
+    }
+
+    return APR_NOTFOUND;
+}
+
+
+
+static void make_pollset(apr_pollset_t *pollset)
+{
+    int i;
+    int pos = 0;
+
+    pollset->num_read = 0;
+    pollset->num_write = 0;
+    pollset->num_except = 0;
+
+    for (i = 0; i < pollset->nelts; i++) {
+        if (pollset->query_set[i].reqevents & APR_POLLIN) {
+            pollset->pollset[pos++] = pollset->query_set[i].desc.s->socketdes;
+            pollset->num_read++;
+        }
+    }
+
+    for (i = 0; i < pollset->nelts; i++) {
+        if (pollset->query_set[i].reqevents & APR_POLLOUT) {
+            pollset->pollset[pos++] = pollset->query_set[i].desc.s->socketdes;
+            pollset->num_write++;
+        }
+    }
+
+    for (i = 0; i < pollset->nelts; i++) {
+        if (pollset->query_set[i].reqevents & APR_POLLPRI) {
+            pollset->pollset[pos++] = pollset->query_set[i].desc.s->socketdes;
+            pollset->num_except++;
+        }
+    }
+
+    pollset->num_total = pollset->num_read + pollset->num_write + pollset->num_except;
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset,
+                                           apr_interval_time_t timeout,
+                                           apr_int32_t *num,
+                                           const apr_pollfd_t **descriptors)
+{
+    int rv;
+    apr_uint32_t i;
+    int *pollresult;
+    int read_pos, write_pos, except_pos;
+    apr_status_t rc = APR_SUCCESS;
+
+    if (pollset->num_read < 0) {
+        make_pollset(pollset);
+    }
+
+    pollresult = alloca(sizeof(int) * pollset->num_total);
+    memcpy(pollresult, pollset->pollset, sizeof(int) * pollset->num_total);
+    (*num) = 0;
+
+    if (timeout > 0) {
+        timeout /= 1000;
+    }
+
+    rv = select(pollresult, pollset->num_read, pollset->num_write, pollset->num_except, timeout);
+
+    if (rv < 0) {
+        return APR_FROM_OS_ERROR(sock_errno());
+    }
+
+    if (rv == 0) {
+        return APR_TIMEUP;
+    }
+
+    read_pos = 0;
+    write_pos = pollset->num_read;
+    except_pos = pollset->num_read + pollset->num_write;
+
+    for (i = 0; i < pollset->nelts; i++) {
+        int rtnevents = 0;
+
+        if (pollset->query_set[i].reqevents & APR_POLLIN) {
+            if (pollresult[read_pos++] != -1) {
+                rtnevents |= APR_POLLIN;
+            }
+        }
+
+        if (pollset->query_set[i].reqevents & APR_POLLOUT) {
+            if (pollresult[write_pos++] != -1) {
+                rtnevents |= APR_POLLOUT;
+            }
+        }
+
+        if (pollset->query_set[i].reqevents & APR_POLLPRI) {
+            if (pollresult[except_pos++] != -1) {
+                rtnevents |= APR_POLLPRI;
+            }
+        }
+
+        if (rtnevents) {
+            if (i == 0 && pollset->wake_listen != NULL) {
+                struct apr_sockaddr_t from_addr;
+                char buffer[16];
+                apr_size_t buflen;
+                for (;;) {
+                    buflen = sizeof(buffer);
+                    rv = apr_socket_recvfrom(&from_addr, pollset->wake_listen,
+                                             MSG_DONTWAIT, buffer, &buflen);
+                    if (rv != APR_SUCCESS) {
+                        break;
+                    }
+                    /* Woken up, drain the pipe still. */
+                    rc = APR_EINTR;
+                }
+            }
+            else {
+                pollset->result_set[*num] = pollset->query_set[i];
+                pollset->result_set[*num].rtnevents = rtnevents;
+                /* Event(s) besides wakeup pipe. */
+                rc = APR_SUCCESS;
+                (*num)++;
+            }
+        }
+    }
+
+    if (descriptors) {
+        *descriptors = pollset->result_set;
+    }
+
+    return rc;
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_pollset_wakeup(apr_pollset_t *pollset)
+{
+    if (pollset->wake_sender) {
+        apr_size_t len = 1;
+        return apr_socket_sendto(pollset->wake_sender, pollset->wake_address, 0, "", &len);
+    }
+
+    return APR_EINIT;
+}
+
+
+
+APR_DECLARE(const char *) apr_poll_method_defname()
+{
+    return "select";
+}
+
+
+
+APR_DECLARE(const char *) apr_pollset_method_name(apr_pollset_t *pollset)
+{
+    return "select";
+}
diff --git a/poll/unix/epoll.c b/poll/unix/epoll.c
new file mode 100644
index 00000000000..4ab03f67ccc
--- /dev/null
+++ b/poll/unix/epoll.c
@@ -0,0 +1,490 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_poll.h"
+#include "apr_time.h"
+#include "apr_portable.h"
+#include "apr_arch_file_io.h"
+#include "apr_arch_networkio.h"
+#include "apr_arch_poll_private.h"
+#include "apr_arch_inherit.h"
+
+#if defined(HAVE_EPOLL)
+
+static apr_int16_t get_epoll_event(apr_int16_t event)
+{
+    apr_int16_t rv = 0;
+
+    if (event & APR_POLLIN)
+        rv |= EPOLLIN;
+    if (event & APR_POLLPRI)
+        rv |= EPOLLPRI;
+    if (event & APR_POLLOUT)
+        rv |= EPOLLOUT;
+    /* APR_POLLNVAL is not handled by epoll.  EPOLLERR and EPOLLHUP are return-only */
+
+    return rv;
+}
+
+static apr_int16_t get_epoll_revent(apr_int16_t event)
+{
+    apr_int16_t rv = 0;
+
+    if (event & EPOLLIN)
+        rv |= APR_POLLIN;
+    if (event & EPOLLPRI)
+        rv |= APR_POLLPRI;
+    if (event & EPOLLOUT)
+        rv |= APR_POLLOUT;
+    if (event & EPOLLERR)
+        rv |= APR_POLLERR;
+    if (event & EPOLLHUP)
+        rv |= APR_POLLHUP;
+    /* APR_POLLNVAL is not handled by epoll. */
+
+    return rv;
+}
+
+struct apr_pollset_private_t
+{
+    int epoll_fd;
+    struct epoll_event *pollset;
+    apr_pollfd_t *result_set;
+#if APR_HAS_THREADS
+    /* A thread mutex to protect operations on the rings */
+    apr_thread_mutex_t *ring_lock;
+#endif
+    /* A ring containing all of the pollfd_t that are active */
+    APR_RING_HEAD(pfd_query_ring_t, pfd_elem_t) query_ring;
+    /* A ring of pollfd_t that have been used, and then _remove()'d */
+    APR_RING_HEAD(pfd_free_ring_t, pfd_elem_t) free_ring;
+    /* A ring of pollfd_t where rings that have been _remove()`ed but
+        might still be inside a _poll() */
+    APR_RING_HEAD(pfd_dead_ring_t, pfd_elem_t) dead_ring;
+};
+
+static apr_status_t impl_pollset_cleanup(apr_pollset_t *pollset)
+{
+    close(pollset->p->epoll_fd);
+    return APR_SUCCESS;
+}
+
+
+static apr_status_t impl_pollset_create(apr_pollset_t *pollset,
+                                        apr_uint32_t size,
+                                        apr_pool_t *p,
+                                        apr_uint32_t flags)
+{
+    apr_status_t rv;
+    int fd;
+
+#ifdef HAVE_EPOLL_CREATE1
+    fd = epoll_create1(EPOLL_CLOEXEC);
+#else
+    fd = epoll_create(size);
+#endif
+    if (fd < 0) {
+        pollset->p = NULL;
+        return apr_get_netos_error();
+    }
+
+#ifndef HAVE_EPOLL_CREATE1
+    {
+        int fd_flags;
+
+        if ((fd_flags = fcntl(fd, F_GETFD)) == -1) {
+            rv = errno;
+            close(fd);
+            pollset->p = NULL;
+            return rv;
+        }
+
+        fd_flags |= FD_CLOEXEC;
+        if (fcntl(fd, F_SETFD, fd_flags) == -1) {
+            rv = errno;
+            close(fd);
+            pollset->p = NULL;
+            return rv;
+        }
+    }
+#endif
+
+    pollset->p = apr_palloc(p, sizeof(apr_pollset_private_t));
+#if APR_HAS_THREADS
+    if ((flags & APR_POLLSET_THREADSAFE) &&
+        !(flags & APR_POLLSET_NOCOPY) &&
+        ((rv = apr_thread_mutex_create(&pollset->p->ring_lock,
+                                       APR_THREAD_MUTEX_DEFAULT,
+                                       p)) != APR_SUCCESS)) {
+        close(fd);
+        pollset->p = NULL;
+        return rv;
+    }
+#else
+    if (flags & APR_POLLSET_THREADSAFE) {
+        close(fd);
+        pollset->p = NULL;
+        return APR_ENOTIMPL;
+    }
+#endif
+    pollset->p->epoll_fd = fd;
+    pollset->p->pollset = apr_palloc(p, size * sizeof(struct epoll_event));
+    pollset->p->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
+
+    if (!(flags & APR_POLLSET_NOCOPY)) {
+        APR_RING_INIT(&pollset->p->query_ring, pfd_elem_t, link);
+        APR_RING_INIT(&pollset->p->free_ring, pfd_elem_t, link);
+        APR_RING_INIT(&pollset->p->dead_ring, pfd_elem_t, link);
+    }
+    return APR_SUCCESS;
+}
+
+static apr_status_t impl_pollset_add(apr_pollset_t *pollset,
+                                     const apr_pollfd_t *descriptor)
+{
+    struct epoll_event ev = {0};
+    int ret;
+    pfd_elem_t *elem = NULL;
+    apr_status_t rv = APR_SUCCESS;
+
+    ev.events = get_epoll_event(descriptor->reqevents);
+
+    if (pollset->flags & APR_POLLSET_NOCOPY) {
+        ev.data.ptr = (void *)descriptor;
+    }
+    else {
+        pollset_lock_rings();
+
+        if (!APR_RING_EMPTY(&(pollset->p->free_ring), pfd_elem_t, link)) {
+            elem = APR_RING_FIRST(&(pollset->p->free_ring));
+            APR_RING_REMOVE(elem, link);
+        }
+        else {
+            elem = (pfd_elem_t *) apr_palloc(pollset->pool, sizeof(pfd_elem_t));
+            APR_RING_ELEM_INIT(elem, link);
+        }
+        elem->pfd = *descriptor;
+        ev.data.ptr = elem;
+    }
+    if (descriptor->desc_type == APR_POLL_SOCKET) {
+        ret = epoll_ctl(pollset->p->epoll_fd, EPOLL_CTL_ADD,
+                        descriptor->desc.s->socketdes, &ev);
+    }
+    else {
+        ret = epoll_ctl(pollset->p->epoll_fd, EPOLL_CTL_ADD,
+                        descriptor->desc.f->filedes, &ev);
+    }
+
+    if (0 != ret) {
+        rv = apr_get_netos_error();
+    }
+
+    if (!(pollset->flags & APR_POLLSET_NOCOPY)) {
+        if (rv != APR_SUCCESS) {
+            APR_RING_INSERT_TAIL(&(pollset->p->free_ring), elem, pfd_elem_t, link);
+        }
+        else {
+            APR_RING_INSERT_TAIL(&(pollset->p->query_ring), elem, pfd_elem_t, link);
+        }
+        pollset_unlock_rings();
+    }
+
+    return rv;
+}
+
+static apr_status_t impl_pollset_remove(apr_pollset_t *pollset,
+                                        const apr_pollfd_t *descriptor)
+{
+    pfd_elem_t *ep;
+    apr_status_t rv = APR_SUCCESS;
+    struct epoll_event ev = {0}; /* ignored, but must be passed with
+                                  * kernel < 2.6.9
+                                  */
+    int ret;
+
+    if (descriptor->desc_type == APR_POLL_SOCKET) {
+        ret = epoll_ctl(pollset->p->epoll_fd, EPOLL_CTL_DEL,
+                        descriptor->desc.s->socketdes, &ev);
+    }
+    else {
+        ret = epoll_ctl(pollset->p->epoll_fd, EPOLL_CTL_DEL,
+                        descriptor->desc.f->filedes, &ev);
+    }
+    if (ret < 0) {
+        rv = APR_NOTFOUND;
+    }
+
+    if (!(pollset->flags & APR_POLLSET_NOCOPY)) {
+        pollset_lock_rings();
+
+        for (ep = APR_RING_FIRST(&(pollset->p->query_ring));
+             ep != APR_RING_SENTINEL(&(pollset->p->query_ring),
+                                     pfd_elem_t, link);
+             ep = APR_RING_NEXT(ep, link)) {
+                
+            if (descriptor->desc.s == ep->pfd.desc.s) {
+                APR_RING_REMOVE(ep, link);
+                APR_RING_INSERT_TAIL(&(pollset->p->dead_ring),
+                                     ep, pfd_elem_t, link);
+                break;
+            }
+        }
+
+        pollset_unlock_rings();
+    }
+
+    return rv;
+}
+
+static apr_status_t impl_pollset_poll(apr_pollset_t *pollset,
+                                           apr_interval_time_t timeout,
+                                           apr_int32_t *num,
+                                           const apr_pollfd_t **descriptors)
+{
+    int ret;
+    apr_status_t rv = APR_SUCCESS;
+
+    *num = 0;
+
+    if (timeout > 0) {
+        timeout /= 1000;
+    }
+
+    ret = epoll_wait(pollset->p->epoll_fd, pollset->p->pollset, pollset->nalloc,
+                     timeout);
+    if (ret < 0) {
+        rv = apr_get_netos_error();
+    }
+    else if (ret == 0) {
+        rv = APR_TIMEUP;
+    }
+    else {
+        int i, j;
+        const apr_pollfd_t *fdptr;
+
+        for (i = 0, j = 0; i < ret; i++) {
+            if (pollset->flags & APR_POLLSET_NOCOPY) {
+                fdptr = (apr_pollfd_t *)(pollset->p->pollset[i].data.ptr);
+            }
+            else {
+                fdptr = &(((pfd_elem_t *) (pollset->p->pollset[i].data.ptr))->pfd);
+            }
+            /* Check if the polled descriptor is our
+             * wakeup pipe. In that case do not put it result set.
+             */
+            if ((pollset->flags & APR_POLLSET_WAKEABLE) &&
+                fdptr->desc_type == APR_POLL_FILE &&
+                fdptr->desc.f == pollset->wakeup_pipe[0]) {
+                apr_poll_drain_wakeup_pipe(pollset->wakeup_pipe);
+                rv = APR_EINTR;
+            }
+            else {
+                pollset->p->result_set[j] = *fdptr;
+                pollset->p->result_set[j].rtnevents =
+                    get_epoll_revent(pollset->p->pollset[i].events);
+                j++;
+            }
+        }
+        if (((*num) = j)) { /* any event besides wakeup pipe? */
+            rv = APR_SUCCESS;
+
+            if (descriptors) {
+                *descriptors = pollset->p->result_set;
+            }
+        }
+    }
+
+    if (!(pollset->flags & APR_POLLSET_NOCOPY)) {
+        pollset_lock_rings();
+
+        /* Shift all PFDs in the Dead Ring to the Free Ring */
+        APR_RING_CONCAT(&(pollset->p->free_ring), &(pollset->p->dead_ring), pfd_elem_t, link);
+
+        pollset_unlock_rings();
+    }
+
+    return rv;
+}
+
+static const apr_pollset_provider_t impl = {
+    impl_pollset_create,
+    impl_pollset_add,
+    impl_pollset_remove,
+    impl_pollset_poll,
+    impl_pollset_cleanup,
+    "epoll"
+};
+
+const apr_pollset_provider_t *const apr_pollset_provider_epoll = &impl;
+
+static apr_status_t impl_pollcb_cleanup(apr_pollcb_t *pollcb)
+{
+    close(pollcb->fd);
+    return APR_SUCCESS;
+}
+
+static apr_status_t impl_pollcb_create(apr_pollcb_t *pollcb,
+                                       apr_uint32_t size,
+                                       apr_pool_t *p,
+                                       apr_uint32_t flags)
+{
+    int fd;
+    
+#ifdef HAVE_EPOLL_CREATE1
+    fd = epoll_create1(EPOLL_CLOEXEC);
+#else
+    fd = epoll_create(size);
+#endif
+    
+    if (fd < 0) {
+        return apr_get_netos_error();
+    }
+
+#ifndef HAVE_EPOLL_CREATE1
+    {
+        int fd_flags;
+        apr_status_t rv;
+
+        if ((fd_flags = fcntl(fd, F_GETFD)) == -1) {
+            rv = errno;
+            close(fd);
+            pollcb->fd = -1;
+            return rv;
+        }
+
+        fd_flags |= FD_CLOEXEC;
+        if (fcntl(fd, F_SETFD, fd_flags) == -1) {
+            rv = errno;
+            close(fd);
+            pollcb->fd = -1;
+            return rv;
+        }
+    }
+#endif
+    
+    pollcb->fd = fd;
+    pollcb->pollset.epoll = apr_palloc(p, size * sizeof(struct epoll_event));
+
+    return APR_SUCCESS;
+}
+
+static apr_status_t impl_pollcb_add(apr_pollcb_t *pollcb,
+                                    apr_pollfd_t *descriptor)
+{
+    struct epoll_event ev = { 0 };
+    int ret;
+    
+    ev.events = get_epoll_event(descriptor->reqevents);
+    ev.data.ptr = (void *) descriptor;
+
+    if (descriptor->desc_type == APR_POLL_SOCKET) {
+        ret = epoll_ctl(pollcb->fd, EPOLL_CTL_ADD,
+                        descriptor->desc.s->socketdes, &ev);
+    }
+    else {
+        ret = epoll_ctl(pollcb->fd, EPOLL_CTL_ADD,
+                        descriptor->desc.f->filedes, &ev);
+    }
+    
+    if (ret == -1) {
+        return apr_get_netos_error();
+    }
+    
+    return APR_SUCCESS;
+}
+
+static apr_status_t impl_pollcb_remove(apr_pollcb_t *pollcb,
+                                       apr_pollfd_t *descriptor)
+{
+    apr_status_t rv = APR_SUCCESS;
+    struct epoll_event ev = {0}; /* ignored, but must be passed with
+                                  * kernel < 2.6.9
+                                  */
+    int ret;
+    
+    if (descriptor->desc_type == APR_POLL_SOCKET) {
+        ret = epoll_ctl(pollcb->fd, EPOLL_CTL_DEL,
+                        descriptor->desc.s->socketdes, &ev);
+    }
+    else {
+        ret = epoll_ctl(pollcb->fd, EPOLL_CTL_DEL,
+                        descriptor->desc.f->filedes, &ev);
+    }
+    
+    if (ret < 0) {
+        rv = APR_NOTFOUND;
+    }
+    
+    return rv;
+}
+
+
+static apr_status_t impl_pollcb_poll(apr_pollcb_t *pollcb,
+                                     apr_interval_time_t timeout,
+                                     apr_pollcb_cb_t func,
+                                     void *baton)
+{
+    int ret, i;
+    apr_status_t rv = APR_SUCCESS;
+    
+    if (timeout > 0) {
+        timeout /= 1000;
+    }
+    
+    ret = epoll_wait(pollcb->fd, pollcb->pollset.epoll, pollcb->nalloc,
+                     timeout);
+    if (ret < 0) {
+        rv = apr_get_netos_error();
+    }
+    else if (ret == 0) {
+        rv = APR_TIMEUP;
+    }
+    else {
+        for (i = 0; i < ret; i++) {
+            apr_pollfd_t *pollfd = (apr_pollfd_t *)(pollcb->pollset.epoll[i].data.ptr);
+
+            if ((pollcb->flags & APR_POLLSET_WAKEABLE) &&
+                pollfd->desc_type == APR_POLL_FILE &&
+                pollfd->desc.f == pollcb->wakeup_pipe[0]) {
+                apr_poll_drain_wakeup_pipe(pollcb->wakeup_pipe);
+                return APR_EINTR;
+            }
+
+            pollfd->rtnevents = get_epoll_revent(pollcb->pollset.epoll[i].events);
+
+            rv = func(baton, pollfd);
+            if (rv) {
+                return rv;
+            }
+        }
+    }
+    
+    return rv;
+}
+
+static const apr_pollcb_provider_t impl_cb = {
+    impl_pollcb_create,
+    impl_pollcb_add,
+    impl_pollcb_remove,
+    impl_pollcb_poll,
+    impl_pollcb_cleanup,
+    "epoll"
+};
+
+const apr_pollcb_provider_t *const apr_pollcb_provider_epoll = &impl_cb;
+
+#endif /* HAVE_EPOLL */
diff --git a/poll/unix/kqueue.c b/poll/unix/kqueue.c
new file mode 100644
index 00000000000..548464db148
--- /dev/null
+++ b/poll/unix/kqueue.c
@@ -0,0 +1,505 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_poll.h"
+#include "apr_time.h"
+#include "apr_portable.h"
+#include "apr_arch_file_io.h"
+#include "apr_arch_networkio.h"
+#include "apr_arch_poll_private.h"
+#include "apr_arch_inherit.h"
+
+#ifdef HAVE_KQUEUE
+
+static apr_int16_t get_kqueue_revent(apr_int16_t event, apr_int16_t flags)
+{
+    apr_int16_t rv = 0;
+
+    if (event == EVFILT_READ)
+        rv |= APR_POLLIN;
+    else if (event == EVFILT_WRITE)
+        rv |= APR_POLLOUT;
+    if (flags & EV_EOF)
+        rv |= APR_POLLHUP;
+    /* APR_POLLPRI, APR_POLLERR, and APR_POLLNVAL are not handled by this
+     * implementation.
+     * TODO: See if EV_ERROR + certain system errors in the returned data field
+     * should map to APR_POLLNVAL.
+     */
+    return rv;
+}
+
+struct apr_pollset_private_t
+{
+    int kqueue_fd;
+    struct kevent kevent;
+    apr_uint32_t setsize;
+    struct kevent *ke_set;
+    apr_pollfd_t *result_set;
+#if APR_HAS_THREADS
+    /* A thread mutex to protect operations on the rings */
+    apr_thread_mutex_t *ring_lock;
+#endif
+    /* A ring containing all of the pollfd_t that are active */
+    APR_RING_HEAD(pfd_query_ring_t, pfd_elem_t) query_ring;
+    /* A ring of pollfd_t that have been used, and then _remove'd */
+    APR_RING_HEAD(pfd_free_ring_t, pfd_elem_t) free_ring;
+    /* A ring of pollfd_t where rings that have been _remove'd but
+       might still be inside a _poll */
+    APR_RING_HEAD(pfd_dead_ring_t, pfd_elem_t) dead_ring;
+};
+
+static apr_status_t impl_pollset_cleanup(apr_pollset_t *pollset)
+{
+    close(pollset->p->kqueue_fd);
+    return APR_SUCCESS;
+}
+
+static apr_status_t impl_pollset_create(apr_pollset_t *pollset,
+                                        apr_uint32_t size,
+                                        apr_pool_t *p,
+                                        apr_uint32_t flags)
+{
+    apr_status_t rv;
+    pollset->p = apr_palloc(p, sizeof(apr_pollset_private_t));
+#if APR_HAS_THREADS
+    if (flags & APR_POLLSET_THREADSAFE &&
+        ((rv = apr_thread_mutex_create(&pollset->p->ring_lock,
+                                       APR_THREAD_MUTEX_DEFAULT,
+                                       p)) != APR_SUCCESS)) {
+        pollset->p = NULL;
+        return rv;
+    }
+#else
+    if (flags & APR_POLLSET_THREADSAFE) {
+        pollset->p = NULL;
+        return APR_ENOTIMPL;
+    }
+#endif
+
+    /* POLLIN and POLLOUT are represented in different returned
+     * events, so we need 2 entries per descriptor in the result set,
+     * both for what is returned by kevent() and what is returned to
+     * the caller of apr_pollset_poll() (since it doesn't spend the
+     * CPU to coalesce separate APR_POLLIN and APR_POLLOUT events
+     * for the same descriptor)
+     */
+    pollset->p->setsize = 2 * size;
+
+    pollset->p->ke_set =
+        (struct kevent *) apr_palloc(p, pollset->p->setsize * sizeof(struct kevent));
+
+    memset(pollset->p->ke_set, 0, pollset->p->setsize * sizeof(struct kevent));
+
+    pollset->p->kqueue_fd = kqueue();
+
+    if (pollset->p->kqueue_fd == -1) {
+        pollset->p = NULL;
+        return apr_get_netos_error();
+    }
+
+    {
+        int flags;
+
+        if ((flags = fcntl(pollset->p->kqueue_fd, F_GETFD)) == -1) {
+            rv = errno;
+            close(pollset->p->kqueue_fd);
+            pollset->p = NULL;
+            return rv;
+        }
+
+        flags |= FD_CLOEXEC;
+        if (fcntl(pollset->p->kqueue_fd, F_SETFD, flags) == -1) {
+            rv = errno;
+            close(pollset->p->kqueue_fd);
+            pollset->p = NULL;
+            return rv;
+        }
+    }
+
+    pollset->p->result_set = apr_palloc(p, pollset->p->setsize * sizeof(apr_pollfd_t));
+
+    APR_RING_INIT(&pollset->p->query_ring, pfd_elem_t, link);
+    APR_RING_INIT(&pollset->p->free_ring, pfd_elem_t, link);
+    APR_RING_INIT(&pollset->p->dead_ring, pfd_elem_t, link);
+
+    return APR_SUCCESS;
+}
+
+static apr_status_t impl_pollset_add(apr_pollset_t *pollset,
+                                     const apr_pollfd_t *descriptor)
+{
+    apr_os_sock_t fd;
+    pfd_elem_t *elem;
+    apr_status_t rv = APR_SUCCESS;
+
+    pollset_lock_rings();
+
+    if (!APR_RING_EMPTY(&(pollset->p->free_ring), pfd_elem_t, link)) {
+        elem = APR_RING_FIRST(&(pollset->p->free_ring));
+        APR_RING_REMOVE(elem, link);
+    }
+    else {
+        elem = (pfd_elem_t *) apr_palloc(pollset->pool, sizeof(pfd_elem_t));
+        APR_RING_ELEM_INIT(elem, link);
+    }
+    elem->pfd = *descriptor;
+
+    if (descriptor->desc_type == APR_POLL_SOCKET) {
+        fd = descriptor->desc.s->socketdes;
+    }
+    else {
+        fd = descriptor->desc.f->filedes;
+    }
+
+    if (descriptor->reqevents & APR_POLLIN) {
+        EV_SET(&pollset->p->kevent, fd, EVFILT_READ, EV_ADD, 0, 0, elem);
+
+        if (kevent(pollset->p->kqueue_fd, &pollset->p->kevent, 1, NULL, 0,
+                   NULL) == -1) {
+            rv = apr_get_netos_error();
+        }
+    }
+
+    if (descriptor->reqevents & APR_POLLOUT && rv == APR_SUCCESS) {
+        EV_SET(&pollset->p->kevent, fd, EVFILT_WRITE, EV_ADD, 0, 0, elem);
+
+        if (kevent(pollset->p->kqueue_fd, &pollset->p->kevent, 1, NULL, 0,
+                   NULL) == -1) {
+            rv = apr_get_netos_error();
+        }
+    }
+
+    if (rv == APR_SUCCESS) {
+        APR_RING_INSERT_TAIL(&(pollset->p->query_ring), elem, pfd_elem_t, link);
+    }
+    else {
+        APR_RING_INSERT_TAIL(&(pollset->p->free_ring), elem, pfd_elem_t, link);
+    }
+
+    pollset_unlock_rings();
+
+    return rv;
+}
+
+static apr_status_t impl_pollset_remove(apr_pollset_t *pollset,
+                                        const apr_pollfd_t *descriptor)
+{
+    pfd_elem_t *ep;
+    apr_status_t rv;
+    apr_os_sock_t fd;
+
+    pollset_lock_rings();
+
+    if (descriptor->desc_type == APR_POLL_SOCKET) {
+        fd = descriptor->desc.s->socketdes;
+    }
+    else {
+        fd = descriptor->desc.f->filedes;
+    }
+
+    rv = APR_NOTFOUND; /* unless at least one of the specified conditions is */
+    if (descriptor->reqevents & APR_POLLIN) {
+        EV_SET(&pollset->p->kevent, fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
+
+        if (kevent(pollset->p->kqueue_fd, &pollset->p->kevent, 1, NULL, 0,
+                   NULL) != -1) {
+            rv = APR_SUCCESS;
+        }
+    }
+
+    if (descriptor->reqevents & APR_POLLOUT) {
+        EV_SET(&pollset->p->kevent, fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
+
+        if (kevent(pollset->p->kqueue_fd, &pollset->p->kevent, 1, NULL, 0,
+                   NULL) != -1) {
+            rv = APR_SUCCESS;
+        }
+    }
+
+    for (ep = APR_RING_FIRST(&(pollset->p->query_ring));
+         ep != APR_RING_SENTINEL(&(pollset->p->query_ring),
+                                 pfd_elem_t, link);
+         ep = APR_RING_NEXT(ep, link)) {
+
+        if (descriptor->desc.s == ep->pfd.desc.s) {
+            APR_RING_REMOVE(ep, link);
+            APR_RING_INSERT_TAIL(&(pollset->p->dead_ring),
+                                 ep, pfd_elem_t, link);
+            break;
+        }
+    }
+
+    pollset_unlock_rings();
+
+    return rv;
+}
+
+static apr_status_t impl_pollset_poll(apr_pollset_t *pollset,
+                                      apr_interval_time_t timeout,
+                                      apr_int32_t *num,
+                                      const apr_pollfd_t **descriptors)
+{
+    int ret;
+    struct timespec tv, *tvptr;
+    apr_status_t rv = APR_SUCCESS;
+
+    *num = 0;
+
+    if (timeout < 0) {
+        tvptr = NULL;
+    }
+    else {
+        tv.tv_sec = (long) apr_time_sec(timeout);
+        tv.tv_nsec = (long) apr_time_usec(timeout) * 1000;
+        tvptr = &tv;
+    }
+
+    ret = kevent(pollset->p->kqueue_fd, NULL, 0, pollset->p->ke_set,
+                 pollset->p->setsize, tvptr);
+    if (ret < 0) {
+        rv = apr_get_netos_error();
+    }
+    else if (ret == 0) {
+        rv = APR_TIMEUP;
+    }
+    else {
+        int i, j;
+        const apr_pollfd_t *fd;
+
+        for (i = 0, j = 0; i < ret; i++) {
+            fd = &((pfd_elem_t *)pollset->p->ke_set[i].udata)->pfd;
+            if ((pollset->flags & APR_POLLSET_WAKEABLE) &&
+                fd->desc_type == APR_POLL_FILE &&
+                fd->desc.f == pollset->wakeup_pipe[0]) {
+                apr_poll_drain_wakeup_pipe(pollset->wakeup_pipe);
+                rv = APR_EINTR;
+            }
+            else {
+                pollset->p->result_set[j] = *fd;
+                pollset->p->result_set[j].rtnevents =
+                        get_kqueue_revent(pollset->p->ke_set[i].filter,
+                                          pollset->p->ke_set[i].flags);
+                j++;
+            }
+        }
+        if ((*num = j)) { /* any event besides wakeup pipe? */
+            rv = APR_SUCCESS;
+            if (descriptors) {
+                *descriptors = pollset->p->result_set;
+            }
+        }
+    }
+
+    pollset_lock_rings();
+
+    /* Shift all PFDs in the Dead Ring to the Free Ring */
+    APR_RING_CONCAT(&(pollset->p->free_ring), &(pollset->p->dead_ring),
+                    pfd_elem_t, link);
+
+    pollset_unlock_rings();
+
+    return rv;
+}
+
+static const apr_pollset_provider_t impl = {
+    impl_pollset_create,
+    impl_pollset_add,
+    impl_pollset_remove,
+    impl_pollset_poll,
+    impl_pollset_cleanup,
+    "kqueue"
+};
+
+const apr_pollset_provider_t *apr_pollset_provider_kqueue = &impl;
+
+static apr_status_t impl_pollcb_cleanup(apr_pollcb_t *pollcb)
+{
+    close(pollcb->fd);
+    return APR_SUCCESS;
+}
+
+static apr_status_t impl_pollcb_create(apr_pollcb_t *pollcb,
+                                       apr_uint32_t size,
+                                       apr_pool_t *p,
+                                       apr_uint32_t flags)
+{
+    int fd;
+    
+    fd = kqueue();
+    if (fd < 0) {
+        return apr_get_netos_error();
+    }
+
+    {
+        int flags;
+        apr_status_t rv;
+
+        if ((flags = fcntl(fd, F_GETFD)) == -1) {
+            rv = errno;
+            close(fd);
+            pollcb->fd = -1;
+            return rv;
+        }
+
+        flags |= FD_CLOEXEC;
+        if (fcntl(fd, F_SETFD, flags) == -1) {
+            rv = errno;
+            close(fd);
+            pollcb->fd = -1;
+            return rv;
+        }
+    }
+ 
+    pollcb->fd = fd;
+    pollcb->pollset.ke = (struct kevent *) apr_pcalloc(p, 2 * size * sizeof(struct kevent));
+    
+    return APR_SUCCESS;
+}
+
+static apr_status_t impl_pollcb_add(apr_pollcb_t *pollcb,
+                                    apr_pollfd_t *descriptor)
+{
+    apr_os_sock_t fd;
+    struct kevent ev;
+    apr_status_t rv = APR_SUCCESS;
+    
+    if (descriptor->desc_type == APR_POLL_SOCKET) {
+        fd = descriptor->desc.s->socketdes;
+    }
+    else {
+        fd = descriptor->desc.f->filedes;
+    }
+    
+    if (descriptor->reqevents & APR_POLLIN) {
+        EV_SET(&ev, fd, EVFILT_READ, EV_ADD, 0, 0, descriptor);
+        
+        if (kevent(pollcb->fd, &ev, 1, NULL, 0, NULL) == -1) {
+            rv = apr_get_netos_error();
+        }
+    }
+    
+    if (descriptor->reqevents & APR_POLLOUT && rv == APR_SUCCESS) {
+        EV_SET(&ev, fd, EVFILT_WRITE, EV_ADD, 0, 0, descriptor);
+        
+        if (kevent(pollcb->fd, &ev, 1, NULL, 0, NULL) == -1) {
+            rv = apr_get_netos_error();
+        }
+    }
+    
+    return rv;
+}
+
+static apr_status_t impl_pollcb_remove(apr_pollcb_t *pollcb,
+                                       apr_pollfd_t *descriptor)
+{
+    apr_status_t rv;
+    struct kevent ev;
+    apr_os_sock_t fd;
+    
+    if (descriptor->desc_type == APR_POLL_SOCKET) {
+        fd = descriptor->desc.s->socketdes;
+    }
+    else {
+        fd = descriptor->desc.f->filedes;
+    }
+
+    rv = APR_NOTFOUND; /* unless at least one of the specified conditions is */
+    if (descriptor->reqevents & APR_POLLIN) {
+        EV_SET(&ev, fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
+        
+        if (kevent(pollcb->fd, &ev, 1, NULL, 0, NULL) != -1) {
+            rv = APR_SUCCESS;
+        }
+    }
+    
+    if (descriptor->reqevents & APR_POLLOUT) {
+        EV_SET(&ev, fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
+        
+        if (kevent(pollcb->fd, &ev, 1, NULL, 0, NULL) != -1) {
+            rv = APR_SUCCESS;
+        }
+    }
+    
+    return rv;
+}
+
+
+static apr_status_t impl_pollcb_poll(apr_pollcb_t *pollcb,
+                                     apr_interval_time_t timeout,
+                                     apr_pollcb_cb_t func,
+                                     void *baton)
+{
+    int ret, i;
+    struct timespec tv, *tvptr;
+    apr_status_t rv = APR_SUCCESS;
+    
+    if (timeout < 0) {
+        tvptr = NULL;
+    }
+    else {
+        tv.tv_sec = (long) apr_time_sec(timeout);
+        tv.tv_nsec = (long) apr_time_usec(timeout) * 1000;
+        tvptr = &tv;
+    }
+    
+    ret = kevent(pollcb->fd, NULL, 0, pollcb->pollset.ke, 2 * pollcb->nalloc,
+                 tvptr);
+
+    if (ret < 0) {
+        rv = apr_get_netos_error();
+    }
+    else if (ret == 0) {
+        rv = APR_TIMEUP;
+    }
+    else {
+        for (i = 0; i < ret; i++) {
+            apr_pollfd_t *pollfd = (apr_pollfd_t *)(pollcb->pollset.ke[i].udata);
+
+            if ((pollcb->flags & APR_POLLSET_WAKEABLE) &&
+                pollfd->desc_type == APR_POLL_FILE &&
+                pollfd->desc.f == pollcb->wakeup_pipe[0]) {
+                apr_poll_drain_wakeup_pipe(pollcb->wakeup_pipe);
+                return APR_EINTR;
+            }
+
+            pollfd->rtnevents = get_kqueue_revent(pollcb->pollset.ke[i].filter,
+                                                  pollcb->pollset.ke[i].flags);
+            
+            rv = func(baton, pollfd);
+            
+            if (rv) {
+                return rv;
+            }
+        }
+    }
+
+    return rv;
+}
+
+static const apr_pollcb_provider_t impl_cb = {
+    impl_pollcb_create,
+    impl_pollcb_add,
+    impl_pollcb_remove,
+    impl_pollcb_poll,
+    impl_pollcb_cleanup,
+    "kqueue"
+};
+
+const apr_pollcb_provider_t *apr_pollcb_provider_kqueue = &impl_cb;
+
+#endif /* HAVE_KQUEUE */
diff --git a/poll/unix/poll.c b/poll/unix/poll.c
new file mode 100644
index 00000000000..f148f5e50d3
--- /dev/null
+++ b/poll/unix/poll.c
@@ -0,0 +1,460 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_poll.h"
+#include "apr_time.h"
+#include "apr_portable.h"
+#include "apr_arch_file_io.h"
+#include "apr_arch_networkio.h"
+#include "apr_arch_misc.h"
+#include "apr_arch_poll_private.h"
+
+#if defined(HAVE_POLL)
+
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#endif
+
+static apr_int16_t get_event(apr_int16_t event)
+{
+    apr_int16_t rv = 0;
+
+    if (event & APR_POLLIN)
+        rv |= POLLIN;
+    if (event & APR_POLLPRI)
+        rv |= POLLPRI;
+    if (event & APR_POLLOUT)
+        rv |= POLLOUT;
+    /* POLLERR, POLLHUP, and POLLNVAL aren't valid as requested events */
+
+    return rv;
+}
+
+static apr_int16_t get_revent(apr_int16_t event)
+{
+    apr_int16_t rv = 0;
+
+    if (event & POLLIN)
+        rv |= APR_POLLIN;
+    if (event & POLLPRI)
+        rv |= APR_POLLPRI;
+    if (event & POLLOUT)
+        rv |= APR_POLLOUT;
+    if (event & POLLERR)
+        rv |= APR_POLLERR;
+    if (event & POLLHUP)
+        rv |= APR_POLLHUP;
+    if (event & POLLNVAL)
+        rv |= APR_POLLNVAL;
+
+    return rv;
+}
+
+#ifdef POLL_USES_POLL
+
+#define SMALL_POLLSET_LIMIT  8
+
+APR_DECLARE(apr_status_t) apr_poll(apr_pollfd_t *aprset, apr_int32_t num,
+                                   apr_int32_t *nsds, 
+                                   apr_interval_time_t timeout)
+{
+    int i, num_to_poll;
+#ifdef HAVE_VLA
+    /* XXX: I trust that this is a segv when insufficient stack exists? */
+    struct pollfd pollset[num];
+#elif defined(HAVE_ALLOCA)
+    struct pollfd *pollset = alloca(sizeof(struct pollfd) * num);
+    if (!pollset)
+        return APR_ENOMEM;
+#else
+    struct pollfd tmp_pollset[SMALL_POLLSET_LIMIT];
+    struct pollfd *pollset;
+
+    if (num <= SMALL_POLLSET_LIMIT) {
+        pollset = tmp_pollset;
+    }
+    else {
+        /* This does require O(n) to copy the descriptors to the internal
+         * mapping.
+         */
+        pollset = malloc(sizeof(struct pollfd) * num);
+        /* The other option is adding an apr_pool_abort() fn to invoke
+         * the pool's out of memory handler
+         */
+        if (!pollset)
+            return APR_ENOMEM;
+    }
+#endif
+    for (i = 0; i < num; i++) {
+        if (aprset[i].desc_type == APR_POLL_SOCKET) {
+            pollset[i].fd = aprset[i].desc.s->socketdes;
+        }
+        else if (aprset[i].desc_type == APR_POLL_FILE) {
+            pollset[i].fd = aprset[i].desc.f->filedes;
+        }
+        else {
+            break;
+        }
+        pollset[i].events = get_event(aprset[i].reqevents);
+    }
+    num_to_poll = i;
+
+    if (timeout > 0) {
+        timeout /= 1000; /* convert microseconds to milliseconds */
+    }
+
+    i = poll(pollset, num_to_poll, timeout);
+    (*nsds) = i;
+
+    if (i > 0) { /* poll() sets revents only if an event was signalled;
+                  * we don't promise to set rtnevents unless an event
+                  * was signalled
+                  */
+        for (i = 0; i < num; i++) {
+            aprset[i].rtnevents = get_revent(pollset[i].revents);
+        }
+    }
+    
+#if !defined(HAVE_VLA) && !defined(HAVE_ALLOCA)
+    if (num > SMALL_POLLSET_LIMIT) {
+        free(pollset);
+    }
+#endif
+
+    if ((*nsds) < 0) {
+        return apr_get_netos_error();
+    }
+    if ((*nsds) == 0) {
+        return APR_TIMEUP;
+    }
+    return APR_SUCCESS;
+}
+
+
+#endif /* POLL_USES_POLL */
+
+struct apr_pollset_private_t
+{
+    struct pollfd *pollset;
+    apr_pollfd_t *query_set;
+    apr_pollfd_t *result_set;
+};
+
+static apr_status_t impl_pollset_create(apr_pollset_t *pollset,
+                                        apr_uint32_t size,
+                                        apr_pool_t *p,
+                                        apr_uint32_t flags)
+{
+    if (flags & APR_POLLSET_THREADSAFE) {                
+        return APR_ENOTIMPL;
+    }
+#ifdef WIN32
+    if (!APR_HAVE_LATE_DLL_FUNC(WSAPoll)) {
+        return APR_ENOTIMPL;
+    }
+#endif
+    pollset->p = apr_palloc(p, sizeof(apr_pollset_private_t));
+    pollset->p->pollset = apr_palloc(p, size * sizeof(struct pollfd));
+    pollset->p->query_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
+    pollset->p->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
+
+    return APR_SUCCESS;
+}
+
+static apr_status_t impl_pollset_add(apr_pollset_t *pollset,
+                                     const apr_pollfd_t *descriptor)
+{
+    if (pollset->nelts == pollset->nalloc) {
+        return APR_ENOMEM;
+    }
+
+    pollset->p->query_set[pollset->nelts] = *descriptor;
+
+    if (descriptor->desc_type == APR_POLL_SOCKET) {
+        pollset->p->pollset[pollset->nelts].fd = descriptor->desc.s->socketdes;
+    }
+    else {
+#if APR_FILES_AS_SOCKETS
+        pollset->p->pollset[pollset->nelts].fd = descriptor->desc.f->filedes;
+#else
+        if ((pollset->flags & APR_POLLSET_WAKEABLE) &&
+            descriptor->desc.f == pollset->wakeup_pipe[0])
+            pollset->p->pollset[pollset->nelts].fd = (SOCKET)descriptor->desc.f->filedes;
+        else
+            return APR_EBADF;
+#endif
+    }
+    pollset->p->pollset[pollset->nelts].events =
+        get_event(descriptor->reqevents);
+    pollset->nelts++;
+
+    return APR_SUCCESS;
+}
+
+static apr_status_t impl_pollset_remove(apr_pollset_t *pollset,
+                                        const apr_pollfd_t *descriptor)
+{
+    apr_uint32_t i;
+
+    for (i = 0; i < pollset->nelts; i++) {
+        if (descriptor->desc.s == pollset->p->query_set[i].desc.s) {
+            /* Found an instance of the fd: remove this and any other copies */
+            apr_uint32_t dst = i;
+            apr_uint32_t old_nelts = pollset->nelts;
+            pollset->nelts--;
+            for (i++; i < old_nelts; i++) {
+                if (descriptor->desc.s == pollset->p->query_set[i].desc.s) {
+                    pollset->nelts--;
+                }
+                else {
+                    pollset->p->pollset[dst] = pollset->p->pollset[i];
+                    pollset->p->query_set[dst] = pollset->p->query_set[i];
+                    dst++;
+                }
+            }
+            return APR_SUCCESS;
+        }
+    }
+
+    return APR_NOTFOUND;
+}
+
+static apr_status_t impl_pollset_poll(apr_pollset_t *pollset,
+                                      apr_interval_time_t timeout,
+                                      apr_int32_t *num,
+                                      const apr_pollfd_t **descriptors)
+{
+    int ret;
+    apr_status_t rv = APR_SUCCESS;
+
+    *num = 0;
+
+#ifdef WIN32
+    /* WSAPoll() requires at least one socket. */
+    if (pollset->nelts == 0) {
+        if (timeout > 0) {
+            apr_sleep(timeout);
+            return APR_TIMEUP;
+        }
+        return APR_SUCCESS;
+    }
+    if (timeout > 0) {
+        timeout /= 1000;
+    }
+    ret = WSAPoll(pollset->p->pollset, pollset->nelts, (int)timeout);
+#else
+    if (timeout > 0) {
+        timeout /= 1000;
+    }
+    ret = poll(pollset->p->pollset, pollset->nelts, timeout);
+#endif
+    if (ret < 0) {
+        return apr_get_netos_error();
+    }
+    else if (ret == 0) {
+        return APR_TIMEUP;
+    }
+    else {
+        apr_uint32_t i, j;
+
+        for (i = 0, j = 0; i < pollset->nelts; i++) {
+            if (pollset->p->pollset[i].revents != 0) {
+                /* Check if the polled descriptor is our
+                 * wakeup pipe. In that case do not put it result set.
+                 */
+                if ((pollset->flags & APR_POLLSET_WAKEABLE) &&
+                    pollset->p->query_set[i].desc_type == APR_POLL_FILE &&
+                    pollset->p->query_set[i].desc.f == pollset->wakeup_pipe[0]) {
+                    apr_poll_drain_wakeup_pipe(pollset->wakeup_pipe);
+                    rv = APR_EINTR;
+                }
+                else {
+                    pollset->p->result_set[j] = pollset->p->query_set[i];
+                    pollset->p->result_set[j].rtnevents =
+                        get_revent(pollset->p->pollset[i].revents);
+                    j++;
+                }
+            }
+        }
+        if ((*num = j)) { /* any event besides wakeup pipe? */
+            rv = APR_SUCCESS;
+        }
+    }
+    if (descriptors && (*num))
+        *descriptors = pollset->p->result_set;
+    return rv;
+}
+
+static const apr_pollset_provider_t impl = {
+    impl_pollset_create,
+    impl_pollset_add,
+    impl_pollset_remove,
+    impl_pollset_poll,
+    NULL,
+    "poll"
+};
+
+const apr_pollset_provider_t *apr_pollset_provider_poll = &impl;
+
+/* Poll method pollcb.
+ * This is probably usable only for WIN32 having WSAPoll
+ */
+static apr_status_t impl_pollcb_create(apr_pollcb_t *pollcb,
+                                       apr_uint32_t size,
+                                       apr_pool_t *p,
+                                       apr_uint32_t flags)
+{
+#if APR_HAS_THREADS
+    return APR_ENOTIMPL;
+#else
+    pollcb->fd = -1;
+#ifdef WIN32
+    if (!APR_HAVE_LATE_DLL_FUNC(WSAPoll)) {
+        return APR_ENOTIMPL;
+    }
+#endif
+
+    pollcb->pollset.ps = apr_palloc(p, size * sizeof(struct pollfd));
+    pollcb->copyset = apr_palloc(p, size * sizeof(apr_pollfd_t *));
+
+    return APR_SUCCESS;
+#endif
+}
+
+static apr_status_t impl_pollcb_add(apr_pollcb_t *pollcb,
+                                    apr_pollfd_t *descriptor)
+{
+    if (pollcb->nelts == pollcb->nalloc) {
+        return APR_ENOMEM;
+    }
+
+    if (descriptor->desc_type == APR_POLL_SOCKET) {
+        pollcb->pollset.ps[pollcb->nelts].fd = descriptor->desc.s->socketdes;
+    }
+    else {
+#if APR_FILES_AS_SOCKETS
+        pollcb->pollset.ps[pollcb->nelts].fd = descriptor->desc.f->filedes;
+#else
+        return APR_EBADF;
+#endif
+    }
+
+    pollcb->pollset.ps[pollcb->nelts].events =
+        get_event(descriptor->reqevents);
+    pollcb->copyset[pollcb->nelts] = descriptor;
+    pollcb->nelts++;
+    
+    return APR_SUCCESS;
+}
+
+static apr_status_t impl_pollcb_remove(apr_pollcb_t *pollcb,
+                                       apr_pollfd_t *descriptor)
+{
+    apr_uint32_t i;
+
+    for (i = 0; i < pollcb->nelts; i++) {
+        if (descriptor->desc.s == pollcb->copyset[i]->desc.s) {
+            /* Found an instance of the fd: remove this and any other copies */
+            apr_uint32_t dst = i;
+            apr_uint32_t old_nelts = pollcb->nelts;
+            pollcb->nelts--;
+            for (i++; i < old_nelts; i++) {
+                if (descriptor->desc.s == pollcb->copyset[i]->desc.s) {
+                    pollcb->nelts--;
+                }
+                else {
+                    pollcb->pollset.ps[dst] = pollcb->pollset.ps[i];
+                    pollcb->copyset[dst] = pollcb->copyset[i];
+                    dst++;
+                }
+            }
+            return APR_SUCCESS;
+        }
+    }
+
+    return APR_NOTFOUND;
+}
+
+static apr_status_t impl_pollcb_poll(apr_pollcb_t *pollcb,
+                                     apr_interval_time_t timeout,
+                                     apr_pollcb_cb_t func,
+                                     void *baton)
+{
+    int ret;
+    apr_status_t rv = APR_SUCCESS;
+    apr_uint32_t i;
+
+#ifdef WIN32
+    /* WSAPoll() requires at least one socket. */
+    if (pollcb->nelts == 0) {
+        if (timeout > 0) {
+            apr_sleep(timeout);
+            return APR_TIMEUP;
+        }
+        return APR_SUCCESS;
+    }
+    if (timeout > 0) {
+        timeout /= 1000;
+    }
+    ret = WSAPoll(pollcb->pollset.ps, pollcb->nelts, (int)timeout);
+#else
+    if (timeout > 0) {
+        timeout /= 1000;
+    }
+    ret = poll(pollcb->pollset.ps, pollcb->nelts, timeout);
+#endif
+    if (ret < 0) {
+        return apr_get_netos_error();
+    }
+    else if (ret == 0) {
+        return APR_TIMEUP;
+    }
+    else {
+        for (i = 0; i < pollcb->nelts; i++) {
+            if (pollcb->pollset.ps[i].revents != 0) {
+                apr_pollfd_t *pollfd = pollcb->copyset[i];
+
+                if ((pollcb->flags & APR_POLLSET_WAKEABLE) &&
+                    pollfd->desc_type == APR_POLL_FILE &&
+                    pollfd->desc.f == pollcb->wakeup_pipe[0]) {
+                    apr_poll_drain_wakeup_pipe(pollcb->wakeup_pipe);
+                    return APR_EINTR;
+                }
+
+                pollfd->rtnevents = get_revent(pollcb->pollset.ps[i].revents);                    
+                rv = func(baton, pollfd);
+                if (rv) {
+                    return rv;
+                }
+            }
+        }
+    }
+    return rv;
+}
+
+static const apr_pollcb_provider_t impl_cb = {
+    impl_pollcb_create,
+    impl_pollcb_add,
+    impl_pollcb_remove,
+    impl_pollcb_poll,
+    NULL,
+    "poll"
+};
+
+const apr_pollcb_provider_t *apr_pollcb_provider_poll = &impl_cb;
+
+#endif /* HAVE_POLL */
diff --git a/poll/unix/pollcb.c b/poll/unix/pollcb.c
new file mode 100644
index 00000000000..a63ad5c9cad
--- /dev/null
+++ b/poll/unix/pollcb.c
@@ -0,0 +1,224 @@
+/* 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.
+ */
+
+#ifdef WIN32
+/* POSIX defines 1024 for the FD_SETSIZE */
+#define FD_SETSIZE 1024
+#endif
+
+#include "apr.h"
+#include "apr_poll.h"
+#include "apr_time.h"
+#include "apr_portable.h"
+#include "apr_arch_file_io.h"
+#include "apr_arch_networkio.h"
+#include "apr_arch_poll_private.h"
+
+static apr_pollset_method_e pollset_default_method = POLLSET_DEFAULT_METHOD;
+#if defined(HAVE_KQUEUE)
+extern const apr_pollcb_provider_t *apr_pollcb_provider_kqueue;
+#endif
+#if defined(HAVE_PORT_CREATE)
+extern const apr_pollcb_provider_t *apr_pollcb_provider_port;
+#endif
+#if defined(HAVE_EPOLL)
+extern const apr_pollcb_provider_t *apr_pollcb_provider_epoll;
+#endif
+#if defined(HAVE_POLL)
+extern const apr_pollcb_provider_t *apr_pollcb_provider_poll;
+#endif
+
+static const apr_pollcb_provider_t *pollcb_provider(apr_pollset_method_e method)
+{
+    const apr_pollcb_provider_t *provider = NULL;
+    switch (method) {
+        case APR_POLLSET_KQUEUE:
+#if defined(HAVE_KQUEUE)
+            provider = apr_pollcb_provider_kqueue;
+#endif
+        break;
+        case APR_POLLSET_PORT:
+#if defined(HAVE_PORT_CREATE)
+            provider = apr_pollcb_provider_port;
+#endif
+        break;
+        case APR_POLLSET_EPOLL:
+#if defined(HAVE_EPOLL)
+            provider = apr_pollcb_provider_epoll;
+#endif
+        break;
+        case APR_POLLSET_POLL:
+#if defined(HAVE_POLL)
+            provider = apr_pollcb_provider_poll;
+#endif
+        break;
+        case APR_POLLSET_SELECT:
+        case APR_POLLSET_AIO_MSGQ:
+        case APR_POLLSET_DEFAULT:
+        break;
+    }
+    return provider;
+}
+
+static apr_status_t pollcb_cleanup(void *p)
+{
+    apr_pollcb_t *pollcb = (apr_pollcb_t *) p;
+
+    if (pollcb->provider->cleanup) {
+        (*pollcb->provider->cleanup)(pollcb);
+    }
+    if (pollcb->flags & APR_POLLSET_WAKEABLE) {
+        apr_poll_close_wakeup_pipe(pollcb->wakeup_pipe);
+    }
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_pollcb_create_ex(apr_pollcb_t **ret_pollcb,
+                                               apr_uint32_t size,
+                                               apr_pool_t *p,
+                                               apr_uint32_t flags,
+                                               apr_pollset_method_e method)
+{
+    apr_status_t rv;
+    apr_pollcb_t *pollcb;
+    const apr_pollcb_provider_t *provider = NULL;
+
+    *ret_pollcb = NULL;
+
+ #ifdef WIN32
+    /* This will work only if ws2_32.dll has WSAPoll funtion.
+     * We could check the presence of the function here,
+     * but someone might implement other pollcb method in
+     * the future.
+     */
+    if (method == APR_POLLSET_DEFAULT) {
+        method = APR_POLLSET_POLL;
+    }
+ #endif
+
+    if (method == APR_POLLSET_DEFAULT)
+        method = pollset_default_method;
+    while (provider == NULL) {
+        provider = pollcb_provider(method);
+        if (!provider) {
+            if ((flags & APR_POLLSET_NODEFAULT) == APR_POLLSET_NODEFAULT)
+                return APR_ENOTIMPL;
+            if (method == pollset_default_method)
+                return APR_ENOTIMPL;
+            method = pollset_default_method;
+        }
+    }
+
+    if (flags & APR_POLLSET_WAKEABLE) {
+        /* Add room for wakeup descriptor */
+        size++;
+    }
+
+    pollcb = apr_palloc(p, sizeof(*pollcb));
+    pollcb->nelts = 0;
+    pollcb->nalloc = size;
+    pollcb->flags = flags;
+    pollcb->pool = p;
+    pollcb->provider = provider;
+
+    rv = (*provider->create)(pollcb, size, p, flags);
+    if (rv == APR_ENOTIMPL) {
+        if (method == pollset_default_method) {
+            return rv;
+        }
+
+        if ((flags & APR_POLLSET_NODEFAULT) == APR_POLLSET_NODEFAULT) {
+            return rv;
+        }
+
+        /* Try with default provider */
+        provider = pollcb_provider(pollset_default_method);
+        if (!provider) {
+            return APR_ENOTIMPL;
+        }
+        rv = (*provider->create)(pollcb, size, p, flags);
+        if (rv != APR_SUCCESS) {
+            return rv;
+        }
+        pollcb->provider = provider;
+    }
+    else if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
+    if (flags & APR_POLLSET_WAKEABLE) {
+        /* Create wakeup pipe */
+        if ((rv = apr_poll_create_wakeup_pipe(pollcb->pool, &pollcb->wakeup_pfd,
+                                              pollcb->wakeup_pipe)) 
+                != APR_SUCCESS) {
+            return rv;
+        }
+
+        if ((rv = apr_pollcb_add(pollcb, &pollcb->wakeup_pfd)) != APR_SUCCESS) {
+            return rv;
+        }
+    }
+    if ((flags & APR_POLLSET_WAKEABLE) || provider->cleanup)
+        apr_pool_cleanup_register(p, pollcb, pollcb_cleanup,
+                                  apr_pool_cleanup_null);
+
+    *ret_pollcb = pollcb;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_pollcb_create(apr_pollcb_t **pollcb,
+                                            apr_uint32_t size,
+                                            apr_pool_t *p,
+                                            apr_uint32_t flags)
+{
+    apr_pollset_method_e method = APR_POLLSET_DEFAULT;
+    return apr_pollcb_create_ex(pollcb, size, p, flags, method);
+}
+
+APR_DECLARE(apr_status_t) apr_pollcb_add(apr_pollcb_t *pollcb,
+                                         apr_pollfd_t *descriptor)
+{
+    return (*pollcb->provider->add)(pollcb, descriptor);
+}
+
+APR_DECLARE(apr_status_t) apr_pollcb_remove(apr_pollcb_t *pollcb,
+                                            apr_pollfd_t *descriptor)
+{
+    return (*pollcb->provider->remove)(pollcb, descriptor);
+}
+
+
+APR_DECLARE(apr_status_t) apr_pollcb_poll(apr_pollcb_t *pollcb,
+                                          apr_interval_time_t timeout,
+                                          apr_pollcb_cb_t func,
+                                          void *baton)
+{
+    return (*pollcb->provider->poll)(pollcb, timeout, func, baton);
+}
+
+APR_DECLARE(apr_status_t) apr_pollcb_wakeup(apr_pollcb_t *pollcb)
+{
+    if (pollcb->flags & APR_POLLSET_WAKEABLE)
+        return apr_file_putc(1, pollcb->wakeup_pipe[1]);
+    else
+        return APR_EINIT;
+}
+
+APR_DECLARE(const char *) apr_pollcb_method_name(apr_pollcb_t *pollcb)
+{
+    return pollcb->provider->name;
+}
diff --git a/poll/unix/pollset.c b/poll/unix/pollset.c
new file mode 100644
index 00000000000..8fa817330f6
--- /dev/null
+++ b/poll/unix/pollset.c
@@ -0,0 +1,247 @@
+/* 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.
+ */
+
+#ifdef WIN32
+/* POSIX defines 1024 for the FD_SETSIZE */
+#define FD_SETSIZE 1024
+#endif
+
+#include "apr.h"
+#include "apr_poll.h"
+#include "apr_time.h"
+#include "apr_portable.h"
+#include "apr_arch_file_io.h"
+#include "apr_arch_networkio.h"
+#include "apr_arch_poll_private.h"
+#include "apr_arch_inherit.h"
+
+static apr_pollset_method_e pollset_default_method = POLLSET_DEFAULT_METHOD;
+
+static apr_status_t pollset_cleanup(void *p)
+{
+    apr_pollset_t *pollset = (apr_pollset_t *) p;
+    if (pollset->provider->cleanup) {
+        (*pollset->provider->cleanup)(pollset);
+    }
+    if (pollset->flags & APR_POLLSET_WAKEABLE) {
+        apr_poll_close_wakeup_pipe(pollset->wakeup_pipe);
+    }
+
+    return APR_SUCCESS;
+}
+
+#if defined(HAVE_KQUEUE)
+extern const apr_pollset_provider_t *apr_pollset_provider_kqueue;
+#endif
+#if defined(HAVE_PORT_CREATE)
+extern const apr_pollset_provider_t *apr_pollset_provider_port;
+#endif
+#if defined(HAVE_EPOLL)
+extern const apr_pollset_provider_t *apr_pollset_provider_epoll;
+#endif
+#if defined(HAVE_AIO_MSGQ)
+extern const apr_pollset_provider_t *apr_pollset_provider_aio_msgq;
+#endif
+#if defined(HAVE_POLL)
+extern const apr_pollset_provider_t *apr_pollset_provider_poll;
+#endif
+extern const apr_pollset_provider_t *apr_pollset_provider_select;
+
+static const apr_pollset_provider_t *pollset_provider(apr_pollset_method_e method)
+{
+    const apr_pollset_provider_t *provider = NULL;
+    switch (method) {
+        case APR_POLLSET_KQUEUE:
+#if defined(HAVE_KQUEUE)
+            provider = apr_pollset_provider_kqueue;
+#endif
+        break;
+        case APR_POLLSET_PORT:
+#if defined(HAVE_PORT_CREATE)
+            provider = apr_pollset_provider_port;
+#endif
+        break;
+        case APR_POLLSET_EPOLL:
+#if defined(HAVE_EPOLL)
+            provider = apr_pollset_provider_epoll;
+#endif
+        break;
+        case APR_POLLSET_AIO_MSGQ:
+#if defined(HAVE_AIO_MSGQ)
+            provider = apr_pollset_provider_aio_msgq;
+#endif
+        break;
+        case APR_POLLSET_POLL:
+#if defined(HAVE_POLL)
+            provider = apr_pollset_provider_poll;
+#endif
+        break;
+        case APR_POLLSET_SELECT:
+            provider = apr_pollset_provider_select;
+        break;
+        case APR_POLLSET_DEFAULT:
+        break;
+    }
+    return provider;
+}
+
+APR_DECLARE(apr_status_t) apr_pollset_create_ex(apr_pollset_t **ret_pollset,
+                                                apr_uint32_t size,
+                                                apr_pool_t *p,
+                                                apr_uint32_t flags,
+                                                apr_pollset_method_e method)
+{
+    apr_status_t rv;
+    apr_pollset_t *pollset;
+    const apr_pollset_provider_t *provider = NULL;
+
+    *ret_pollset = NULL;
+
+ #ifdef WIN32
+    /* Favor WSAPoll if supported.
+     * This will work only if ws2_32.dll has WSAPoll funtion.
+     * In other cases it will fall back to select() method unless
+     * the APR_POLLSET_NODEFAULT is added to the flags.
+     */
+    if (method == APR_POLLSET_DEFAULT) {
+        method = APR_POLLSET_POLL;
+    }
+ #endif
+
+    if (method == APR_POLLSET_DEFAULT)
+        method = pollset_default_method;
+    while (provider == NULL) {
+        provider = pollset_provider(method);
+        if (!provider) {
+            if ((flags & APR_POLLSET_NODEFAULT) == APR_POLLSET_NODEFAULT)
+                return APR_ENOTIMPL;
+            if (method == pollset_default_method)
+                return APR_ENOTIMPL;
+            method = pollset_default_method;
+        }
+    }
+    if (flags & APR_POLLSET_WAKEABLE) {
+        /* Add room for wakeup descriptor */
+        size++;
+    }
+
+    pollset = apr_palloc(p, sizeof(*pollset));
+    pollset->nelts = 0;
+    pollset->nalloc = size;
+    pollset->pool = p;
+    pollset->flags = flags;
+    pollset->provider = provider;
+
+    rv = (*provider->create)(pollset, size, p, flags);
+    if (rv == APR_ENOTIMPL) {
+        if (method == pollset_default_method) {
+            return rv;
+        }
+        provider = pollset_provider(pollset_default_method);
+        if (!provider) {
+            return APR_ENOTIMPL;
+        }
+        rv = (*provider->create)(pollset, size, p, flags);
+        if (rv != APR_SUCCESS) {
+            return rv;
+        }
+        pollset->provider = provider;
+    }
+    else if (rv != APR_SUCCESS) {
+        return rv;
+    }
+    if (flags & APR_POLLSET_WAKEABLE) {
+        /* Create wakeup pipe */
+        if ((rv = apr_poll_create_wakeup_pipe(pollset->pool, &pollset->wakeup_pfd,
+                                              pollset->wakeup_pipe))
+                != APR_SUCCESS) {
+            return rv;
+        }
+
+        if ((rv = apr_pollset_add(pollset, &pollset->wakeup_pfd)) != APR_SUCCESS) {
+            return rv;
+        }
+    }
+    if ((flags & APR_POLLSET_WAKEABLE) || provider->cleanup)
+        apr_pool_cleanup_register(p, pollset, pollset_cleanup,
+                                  apr_pool_cleanup_null);
+
+    *ret_pollset = pollset;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(const char *) apr_pollset_method_name(apr_pollset_t *pollset)
+{
+    return pollset->provider->name;
+}
+
+APR_DECLARE(const char *) apr_poll_method_defname()
+{
+    const apr_pollset_provider_t *provider = NULL;
+
+    provider = pollset_provider(pollset_default_method);
+    if (provider)
+        return provider->name;
+    else
+        return "unknown";
+}
+
+APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset,
+                                             apr_uint32_t size,
+                                             apr_pool_t *p,
+                                             apr_uint32_t flags)
+{
+    apr_pollset_method_e method = APR_POLLSET_DEFAULT;
+    return apr_pollset_create_ex(pollset, size, p, flags, method);
+}
+
+APR_DECLARE(apr_status_t) apr_pollset_destroy(apr_pollset_t * pollset)
+{
+    if (pollset->flags & APR_POLLSET_WAKEABLE ||
+        pollset->provider->cleanup)
+        return apr_pool_cleanup_run(pollset->pool, pollset,
+                                    pollset_cleanup);
+    else
+        return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_pollset_wakeup(apr_pollset_t *pollset)
+{
+    if (pollset->flags & APR_POLLSET_WAKEABLE)
+        return apr_file_putc(1, pollset->wakeup_pipe[1]);
+    else
+        return APR_EINIT;
+}
+
+APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset,
+                                          const apr_pollfd_t *descriptor)
+{
+    return (*pollset->provider->add)(pollset, descriptor);
+}
+
+APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset,
+                                             const apr_pollfd_t *descriptor)
+{
+    return (*pollset->provider->remove)(pollset, descriptor);
+}
+
+APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset,
+                                           apr_interval_time_t timeout,
+                                           apr_int32_t *num,
+                                           const apr_pollfd_t **descriptors)
+{
+    return (*pollset->provider->poll)(pollset, timeout, num, descriptors);
+}
diff --git a/poll/unix/port.c b/poll/unix/port.c
new file mode 100644
index 00000000000..c1e599412ec
--- /dev/null
+++ b/poll/unix/port.c
@@ -0,0 +1,594 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_poll.h"
+#include "apr_time.h"
+#include "apr_portable.h"
+#include "apr_atomic.h"
+#include "apr_arch_file_io.h"
+#include "apr_arch_networkio.h"
+#include "apr_arch_poll_private.h"
+#include "apr_arch_inherit.h"
+
+#if defined(HAVE_PORT_CREATE)
+
+static apr_int16_t get_event(apr_int16_t event)
+{
+    apr_int16_t rv = 0;
+
+    if (event & APR_POLLIN)
+        rv |= POLLIN;
+    if (event & APR_POLLPRI)
+        rv |= POLLPRI;
+    if (event & APR_POLLOUT)
+        rv |= POLLOUT;
+    /* POLLERR, POLLHUP, and POLLNVAL aren't valid as requested events */
+
+    return rv;
+}
+
+static apr_int16_t get_revent(apr_int16_t event)
+{
+    apr_int16_t rv = 0;
+
+    if (event & POLLIN)
+        rv |= APR_POLLIN;
+    if (event & POLLPRI)
+        rv |= APR_POLLPRI;
+    if (event & POLLOUT)
+        rv |= APR_POLLOUT;
+    if (event & POLLERR)
+        rv |= APR_POLLERR;
+    if (event & POLLHUP)
+        rv |= APR_POLLHUP;
+    if (event & POLLNVAL)
+        rv |= APR_POLLNVAL;
+
+    return rv;
+}
+
+
+struct apr_pollset_private_t
+{
+    int port_fd;
+    port_event_t *port_set;
+    apr_pollfd_t *result_set;
+#if APR_HAS_THREADS
+    /* A thread mutex to protect operations on the rings */
+    apr_thread_mutex_t *ring_lock;
+#endif
+    /* A ring containing all of the pollfd_t that are active */
+    APR_RING_HEAD(pfd_query_ring_t, pfd_elem_t) query_ring;
+    /* A ring containing the pollfd_t that will be added on the
+     * next call to apr_pollset_poll().
+     */
+    APR_RING_HEAD(pfd_add_ring_t, pfd_elem_t) add_ring;
+    /* A ring of pollfd_t that have been used, and then _remove'd */
+    APR_RING_HEAD(pfd_free_ring_t, pfd_elem_t) free_ring;
+    /* A ring of pollfd_t where rings that have been _remove'd but
+       might still be inside a _poll */
+    APR_RING_HEAD(pfd_dead_ring_t, pfd_elem_t) dead_ring;
+    /* number of threads in poll */
+    volatile apr_uint32_t waiting;
+};
+
+static apr_status_t call_port_getn(int port, port_event_t list[], 
+                                   unsigned int max, unsigned int *nget,
+                                   apr_interval_time_t timeout)
+{
+    struct timespec tv, *tvptr;
+    int ret;
+    apr_status_t rv = APR_SUCCESS;
+
+    if (timeout < 0) {
+        tvptr = NULL;
+    }
+    else {
+        tv.tv_sec = (long) apr_time_sec(timeout);
+        tv.tv_nsec = (long) apr_time_usec(timeout) * 1000;
+        tvptr = &tv;
+    }
+
+    list[0].portev_user = (void *)-1; /* so we can double check that an
+                                       * event was returned
+                                       */
+
+    ret = port_getn(port, list, max, nget, tvptr);
+    /* Note: 32-bit port_getn() on Solaris 10 x86 returns large negative 
+     * values instead of 0 when returning immediately.
+     */
+
+    if (ret == -1) {
+        rv = apr_get_netos_error();
+
+        switch(rv) {
+        case EINTR:
+        case ETIME:
+            if (*nget > 0 && list[0].portev_user != (void *)-1) {
+                /* This confusing API can return an event at the same time
+                 * that it reports EINTR or ETIME.  If that occurs, just
+                 * report the event.  With EINTR, nget can be > 0 without
+                 * any event, so check that portev_user was filled in.
+                 *
+                 * (Maybe it will be simplified; see thread
+                 *   http://mail.opensolaris.org
+                 *   /pipermail/networking-discuss/2009-August/011979.html
+                 *  This code will still work afterwards.)
+                 */
+                rv = APR_SUCCESS;
+                break;
+            }
+            if (rv == ETIME) {
+                rv = APR_TIMEUP;
+            }
+        /* fall-through */
+        default:
+            *nget = 0;
+        }
+    }
+    else if (*nget == 0) {
+        rv = APR_TIMEUP;
+    }
+
+    return rv;
+}
+
+static apr_status_t impl_pollset_cleanup(apr_pollset_t *pollset)
+{
+    close(pollset->p->port_fd);
+    return APR_SUCCESS;
+}
+
+static apr_status_t impl_pollset_create(apr_pollset_t *pollset,
+                                             apr_uint32_t size,
+                                             apr_pool_t *p,
+                                             apr_uint32_t flags)
+{
+    apr_status_t rv = APR_SUCCESS;
+    pollset->p = apr_palloc(p, sizeof(apr_pollset_private_t));
+#if APR_HAS_THREADS
+    if (flags & APR_POLLSET_THREADSAFE &&
+        ((rv = apr_thread_mutex_create(&pollset->p->ring_lock,
+                                       APR_THREAD_MUTEX_DEFAULT,
+                                       p)) != APR_SUCCESS)) {
+        pollset->p = NULL;
+        return rv;
+    }
+#else
+    if (flags & APR_POLLSET_THREADSAFE) {
+        pollset->p = NULL;
+        return APR_ENOTIMPL;
+    }
+#endif
+    pollset->p->waiting = 0;
+
+    pollset->p->port_set = apr_palloc(p, size * sizeof(port_event_t));
+
+    pollset->p->port_fd = port_create();
+
+    if (pollset->p->port_fd < 0) {
+        pollset->p = NULL;
+        return apr_get_netos_error();
+    }
+
+    {
+        int flags;
+
+        if ((flags = fcntl(pollset->p->port_fd, F_GETFD)) == -1) {
+            rv = errno;
+            close(pollset->p->port_fd);
+            pollset->p = NULL;
+            return rv;
+        }
+
+        flags |= FD_CLOEXEC;
+        if (fcntl(pollset->p->port_fd, F_SETFD, flags) == -1) {
+            rv = errno;
+            close(pollset->p->port_fd);
+            pollset->p = NULL;
+            return rv;
+        }
+    }
+
+    pollset->p->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
+
+    APR_RING_INIT(&pollset->p->query_ring, pfd_elem_t, link);
+    APR_RING_INIT(&pollset->p->add_ring, pfd_elem_t, link);
+    APR_RING_INIT(&pollset->p->free_ring, pfd_elem_t, link);
+    APR_RING_INIT(&pollset->p->dead_ring, pfd_elem_t, link);
+
+    return rv;
+}
+
+static apr_status_t impl_pollset_add(apr_pollset_t *pollset,
+                                     const apr_pollfd_t *descriptor)
+{
+    apr_os_sock_t fd;
+    pfd_elem_t *elem;
+    int res;
+    apr_status_t rv = APR_SUCCESS;
+
+    pollset_lock_rings();
+
+    if (!APR_RING_EMPTY(&(pollset->p->free_ring), pfd_elem_t, link)) {
+        elem = APR_RING_FIRST(&(pollset->p->free_ring));
+        APR_RING_REMOVE(elem, link);
+    }
+    else {
+        elem = (pfd_elem_t *) apr_palloc(pollset->pool, sizeof(pfd_elem_t));
+        APR_RING_ELEM_INIT(elem, link);
+        elem->on_query_ring = 0;
+    }
+    elem->pfd = *descriptor;
+
+    if (descriptor->desc_type == APR_POLL_SOCKET) {
+        fd = descriptor->desc.s->socketdes;
+    }
+    else {
+        fd = descriptor->desc.f->filedes;
+    }
+
+    /* If another thread is polling, notify the kernel immediately; otherwise,
+     * wait until the next call to apr_pollset_poll().
+     */
+    if (apr_atomic_read32(&pollset->p->waiting)) {
+        res = port_associate(pollset->p->port_fd, PORT_SOURCE_FD, fd, 
+                             get_event(descriptor->reqevents), (void *)elem);
+
+        if (res < 0) {
+            rv = apr_get_netos_error();
+            APR_RING_INSERT_TAIL(&(pollset->p->free_ring), elem, pfd_elem_t, link);
+        }
+        else {
+            elem->on_query_ring = 1;
+            APR_RING_INSERT_TAIL(&(pollset->p->query_ring), elem, pfd_elem_t, link);
+        }
+    } 
+    else {
+        APR_RING_INSERT_TAIL(&(pollset->p->add_ring), elem, pfd_elem_t, link);
+    }
+
+    pollset_unlock_rings();
+
+    return rv;
+}
+
+static apr_status_t impl_pollset_remove(apr_pollset_t *pollset,
+                                        const apr_pollfd_t *descriptor)
+{
+    apr_os_sock_t fd;
+    pfd_elem_t *ep;
+    apr_status_t rv = APR_SUCCESS;
+    int res;
+    int err = 0;
+    int found;
+
+    pollset_lock_rings();
+
+    if (descriptor->desc_type == APR_POLL_SOCKET) {
+        fd = descriptor->desc.s->socketdes;
+    }
+    else {
+        fd = descriptor->desc.f->filedes;
+    }
+
+    /* Search the add ring first.  This ring is often shorter,
+     * and it often contains the descriptor being removed.  
+     * (For the common scenario where apr_pollset_poll() 
+     * returns activity for the descriptor and the descriptor
+     * is then removed from the pollset, it will have just 
+     * been moved to the add ring by apr_pollset_poll().)
+     *
+     * If it is on the add ring, it isn't associated with the
+     * event port yet/anymore.
+     */
+    found = 0;
+    for (ep = APR_RING_FIRST(&(pollset->p->add_ring));
+         ep != APR_RING_SENTINEL(&(pollset->p->add_ring),
+                                 pfd_elem_t, link);
+         ep = APR_RING_NEXT(ep, link)) {
+
+        if (descriptor->desc.s == ep->pfd.desc.s) {
+            found = 1;
+            APR_RING_REMOVE(ep, link);
+            APR_RING_INSERT_TAIL(&(pollset->p->free_ring),
+                                 ep, pfd_elem_t, link);
+            break;
+        }
+    }
+
+    if (!found) {
+        res = port_dissociate(pollset->p->port_fd, PORT_SOURCE_FD, fd);
+
+        if (res < 0) {
+            /* The expected case for this failure is that another
+             * thread's call to port_getn() returned this fd and
+             * disassociated the fd from the event port, and 
+             * impl_pollset_poll() is blocked on the ring lock,
+             * which this thread holds.
+             */
+            err = errno;
+            rv = APR_NOTFOUND;
+        }
+
+        for (ep = APR_RING_FIRST(&(pollset->p->query_ring));
+             ep != APR_RING_SENTINEL(&(pollset->p->query_ring),
+                                     pfd_elem_t, link);
+             ep = APR_RING_NEXT(ep, link)) {
+
+            if (descriptor->desc.s == ep->pfd.desc.s) {
+                APR_RING_REMOVE(ep, link);
+                ep->on_query_ring = 0;
+                APR_RING_INSERT_TAIL(&(pollset->p->dead_ring),
+                                     ep, pfd_elem_t, link);
+                if (ENOENT == err) {
+                    rv = APR_SUCCESS;
+                }
+                break;
+            }
+        }
+    }
+
+    pollset_unlock_rings();
+
+    return rv;
+}
+
+static apr_status_t impl_pollset_poll(apr_pollset_t *pollset,
+                                      apr_interval_time_t timeout,
+                                      apr_int32_t *num,
+                                      const apr_pollfd_t **descriptors)
+{
+    apr_os_sock_t fd;
+    int ret;
+    unsigned int nget, i;
+    apr_int32_t j;
+    pfd_elem_t *ep;
+    apr_status_t rv = APR_SUCCESS;
+
+    *num = 0;
+    nget = 1;
+
+    pollset_lock_rings();
+
+    apr_atomic_inc32(&pollset->p->waiting);
+
+    while (!APR_RING_EMPTY(&(pollset->p->add_ring), pfd_elem_t, link)) {
+        ep = APR_RING_FIRST(&(pollset->p->add_ring));
+        APR_RING_REMOVE(ep, link);
+
+        if (ep->pfd.desc_type == APR_POLL_SOCKET) {
+            fd = ep->pfd.desc.s->socketdes;
+        }
+        else {
+            fd = ep->pfd.desc.f->filedes;
+        }
+
+        ret = port_associate(pollset->p->port_fd, PORT_SOURCE_FD, 
+                             fd, get_event(ep->pfd.reqevents), ep);
+        if (ret < 0) {
+            rv = apr_get_netos_error();
+            APR_RING_INSERT_TAIL(&(pollset->p->free_ring), ep, pfd_elem_t, link);
+            break;
+        }
+
+        ep->on_query_ring = 1;
+        APR_RING_INSERT_TAIL(&(pollset->p->query_ring), ep, pfd_elem_t, link);
+    }
+
+    pollset_unlock_rings();
+
+    if (rv != APR_SUCCESS) {
+        apr_atomic_dec32(&pollset->p->waiting);
+        return rv;
+    }
+
+    rv = call_port_getn(pollset->p->port_fd, pollset->p->port_set, 
+                        pollset->nalloc, &nget, timeout);
+
+    /* decrease the waiting ASAP to reduce the window for calling 
+       port_associate within apr_pollset_add() */
+    apr_atomic_dec32(&pollset->p->waiting);
+
+    pollset_lock_rings();
+
+    for (i = 0, j = 0; i < nget; i++) {
+        ep = (pfd_elem_t *)pollset->p->port_set[i].portev_user;
+        if ((pollset->flags & APR_POLLSET_WAKEABLE) &&
+            ep->pfd.desc_type == APR_POLL_FILE &&
+            ep->pfd.desc.f == pollset->wakeup_pipe[0]) {
+            apr_poll_drain_wakeup_pipe(pollset->wakeup_pipe);
+            rv = APR_EINTR;
+        }
+        else {
+            pollset->p->result_set[j] = ep->pfd;
+            pollset->p->result_set[j].rtnevents =
+                get_revent(pollset->p->port_set[i].portev_events);
+            j++;
+        }
+        /* If the ring element is still on the query ring, move it
+         * to the add ring for re-association with the event port
+         * later.  (It may have already been moved to the dead ring
+         * by a call to pollset_remove on another thread.)
+         */
+        if (ep->on_query_ring) {
+            APR_RING_REMOVE(ep, link);
+            ep->on_query_ring = 0;
+            APR_RING_INSERT_TAIL(&(pollset->p->add_ring), ep,
+                                 pfd_elem_t, link);
+        }
+    }
+    if ((*num = j)) { /* any event besides wakeup pipe? */
+        rv = APR_SUCCESS;
+        if (descriptors) {
+            *descriptors = pollset->p->result_set;
+        }
+    }
+
+    /* Shift all PFDs in the Dead Ring to the Free Ring */
+    APR_RING_CONCAT(&(pollset->p->free_ring), &(pollset->p->dead_ring), pfd_elem_t, link);
+
+    pollset_unlock_rings();
+
+    return rv;
+}
+
+static const apr_pollset_provider_t impl = {
+    impl_pollset_create,
+    impl_pollset_add,
+    impl_pollset_remove,
+    impl_pollset_poll,
+    impl_pollset_cleanup,
+    "port"
+};
+
+const apr_pollset_provider_t *apr_pollset_provider_port = &impl;
+
+static apr_status_t impl_pollcb_cleanup(apr_pollcb_t *pollcb)
+{
+    close(pollcb->fd);
+    return APR_SUCCESS;
+}
+
+static apr_status_t impl_pollcb_create(apr_pollcb_t *pollcb,
+                                       apr_uint32_t size,
+                                       apr_pool_t *p,
+                                       apr_uint32_t flags)
+{
+    pollcb->fd = port_create();
+
+    if (pollcb->fd < 0) {
+        return apr_get_netos_error();
+    }
+
+    {
+        int flags;
+        apr_status_t rv;
+
+        if ((flags = fcntl(pollcb->fd, F_GETFD)) == -1) {
+            rv = errno;
+            close(pollcb->fd);
+            pollcb->fd = -1;
+            return rv;
+        }
+
+        flags |= FD_CLOEXEC;
+        if (fcntl(pollcb->fd, F_SETFD, flags) == -1) {
+            rv = errno;
+            close(pollcb->fd);
+            pollcb->fd = -1;
+            return rv;
+        }
+    }
+
+    pollcb->pollset.port = apr_palloc(p, size * sizeof(port_event_t));
+
+    return APR_SUCCESS;
+}
+
+static apr_status_t impl_pollcb_add(apr_pollcb_t *pollcb,
+                                    apr_pollfd_t *descriptor)
+{
+    int ret, fd;
+
+    if (descriptor->desc_type == APR_POLL_SOCKET) {
+        fd = descriptor->desc.s->socketdes;
+    }
+    else {
+        fd = descriptor->desc.f->filedes;
+    }
+
+    ret = port_associate(pollcb->fd, PORT_SOURCE_FD, fd,
+                         get_event(descriptor->reqevents), descriptor);
+
+    if (ret == -1) {
+        return apr_get_netos_error();
+    }
+
+    return APR_SUCCESS;
+}
+
+static apr_status_t impl_pollcb_remove(apr_pollcb_t *pollcb,
+                                       apr_pollfd_t *descriptor)
+{
+    int fd, ret;
+
+    if (descriptor->desc_type == APR_POLL_SOCKET) {
+        fd = descriptor->desc.s->socketdes;
+    }
+    else {
+        fd = descriptor->desc.f->filedes;
+    }
+
+    ret = port_dissociate(pollcb->fd, PORT_SOURCE_FD, fd);
+
+    if (ret < 0) {
+        return APR_NOTFOUND;
+    }
+
+    return APR_SUCCESS;
+}
+
+static apr_status_t impl_pollcb_poll(apr_pollcb_t *pollcb,
+                                     apr_interval_time_t timeout,
+                                     apr_pollcb_cb_t func,
+                                     void *baton)
+{
+    apr_status_t rv;
+    unsigned int nget = 1;
+
+    rv = call_port_getn(pollcb->fd, pollcb->pollset.port, pollcb->nalloc,
+                        &nget, timeout);
+
+    if (nget) {
+        unsigned int i;
+
+        for (i = 0; i < nget; i++) {
+            apr_pollfd_t *pollfd = (apr_pollfd_t *)(pollcb->pollset.port[i].portev_user);
+
+            if ((pollcb->flags & APR_POLLSET_WAKEABLE) &&
+                pollfd->desc_type == APR_POLL_FILE &&
+                pollfd->desc.f == pollcb->wakeup_pipe[0]) {
+                apr_poll_drain_wakeup_pipe(pollcb->wakeup_pipe);
+                return APR_EINTR;
+            }
+
+            pollfd->rtnevents = get_revent(pollcb->pollset.port[i].portev_events);
+
+            rv = func(baton, pollfd);
+            if (rv) {
+                return rv;
+            }
+            rv = apr_pollcb_add(pollcb, pollfd);
+        }
+    }
+
+    return rv;
+}
+
+static const apr_pollcb_provider_t impl_cb = {
+    impl_pollcb_create,
+    impl_pollcb_add,
+    impl_pollcb_remove,
+    impl_pollcb_poll,
+    impl_pollcb_cleanup,
+    "port"
+};
+
+const apr_pollcb_provider_t *apr_pollcb_provider_port = &impl_cb;
+
+#endif /* HAVE_PORT_CREATE */
diff --git a/poll/unix/select.c b/poll/unix/select.c
new file mode 100644
index 00000000000..51be3c1cd5f
--- /dev/null
+++ b/poll/unix/select.c
@@ -0,0 +1,449 @@
+/* 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.
+ */
+
+#ifdef WIN32
+/* POSIX defines 1024 for the FD_SETSIZE */
+#define FD_SETSIZE 1024
+#endif
+
+#include "apr.h"
+#include "apr_poll.h"
+#include "apr_time.h"
+#include "apr_portable.h"
+#include "apr_arch_file_io.h"
+#include "apr_arch_networkio.h"
+#include "apr_arch_poll_private.h"
+
+#ifdef POLL_USES_SELECT
+
+APR_DECLARE(apr_status_t) apr_poll(apr_pollfd_t *aprset, int num,
+                                   apr_int32_t *nsds,
+                                   apr_interval_time_t timeout)
+{
+    fd_set readset, writeset, exceptset;
+    int rv, i;
+    int maxfd = -1;
+    struct timeval tv, *tvptr;
+#ifdef NETWARE
+    apr_datatype_e set_type = APR_NO_DESC;
+#endif
+
+#ifdef WIN32
+    /* On Win32, select() must be presented with at least one socket to
+     * poll on, or select() will return WSAEINVAL.  So, we'll just
+     * short-circuit and bail now.
+     */
+    if (num == 0) {
+        (*nsds) = 0;
+        if (timeout > 0) {
+            apr_sleep(timeout);
+            return APR_TIMEUP;
+        }
+        return APR_SUCCESS;
+    }
+#endif
+
+    if (timeout < 0) {
+        tvptr = NULL;
+    }
+    else {
+        tv.tv_sec = (long) apr_time_sec(timeout);
+        tv.tv_usec = (long) apr_time_usec(timeout);
+        tvptr = &tv;
+    }
+
+    FD_ZERO(&readset);
+    FD_ZERO(&writeset);
+    FD_ZERO(&exceptset);
+
+    for (i = 0; i < num; i++) {
+        apr_os_sock_t fd;
+
+        aprset[i].rtnevents = 0;
+
+        if (aprset[i].desc_type == APR_POLL_SOCKET) {
+#ifdef NETWARE
+            if (HAS_PIPES(set_type)) {
+                return APR_EBADF;
+            }
+            else {
+                set_type = APR_POLL_SOCKET;
+            }
+#endif
+            fd = aprset[i].desc.s->socketdes;
+        }
+        else if (aprset[i].desc_type == APR_POLL_FILE) {
+#if !APR_FILES_AS_SOCKETS
+            return APR_EBADF;
+#else
+#ifdef NETWARE
+            if (aprset[i].desc.f->is_pipe && !HAS_SOCKETS(set_type)) {
+                set_type = APR_POLL_FILE;
+            }
+            else
+                return APR_EBADF;
+#endif /* NETWARE */
+
+            fd = aprset[i].desc.f->filedes;
+
+#endif /* APR_FILES_AS_SOCKETS */
+        }
+        else {
+            break;
+        }
+#if !defined(WIN32) && !defined(NETWARE)        /* socket sets handled with array of handles */
+        if (fd >= FD_SETSIZE) {
+            /* XXX invent new error code so application has a clue */
+            return APR_EBADF;
+        }
+#endif
+        if (aprset[i].reqevents & APR_POLLIN) {
+            FD_SET(fd, &readset);
+        }
+        if (aprset[i].reqevents & APR_POLLOUT) {
+            FD_SET(fd, &writeset);
+        }
+        if (aprset[i].reqevents &
+            (APR_POLLPRI | APR_POLLERR | APR_POLLHUP | APR_POLLNVAL)) {
+            FD_SET(fd, &exceptset);
+        }
+        if ((int) fd > maxfd) {
+            maxfd = (int) fd;
+        }
+    }
+
+#ifdef NETWARE
+    if (HAS_PIPES(set_type)) {
+        rv = pipe_select(maxfd + 1, &readset, &writeset, &exceptset, tvptr);
+    }
+    else {
+#endif
+
+        rv = select(maxfd + 1, &readset, &writeset, &exceptset, tvptr);
+
+#ifdef NETWARE
+    }
+#endif
+
+    (*nsds) = rv;
+    if ((*nsds) == 0) {
+        return APR_TIMEUP;
+    }
+    if ((*nsds) < 0) {
+        return apr_get_netos_error();
+    }
+
+    (*nsds) = 0;
+    for (i = 0; i < num; i++) {
+        apr_os_sock_t fd;
+
+        if (aprset[i].desc_type == APR_POLL_SOCKET) {
+            fd = aprset[i].desc.s->socketdes;
+        }
+        else if (aprset[i].desc_type == APR_POLL_FILE) {
+#if !APR_FILES_AS_SOCKETS
+            return APR_EBADF;
+#else
+            fd = aprset[i].desc.f->filedes;
+#endif
+        }
+        else {
+            break;
+        }
+        if (FD_ISSET(fd, &readset)) {
+            aprset[i].rtnevents |= APR_POLLIN;
+        }
+        if (FD_ISSET(fd, &writeset)) {
+            aprset[i].rtnevents |= APR_POLLOUT;
+        }
+        if (FD_ISSET(fd, &exceptset)) {
+            aprset[i].rtnevents |= APR_POLLERR;
+        }
+        if (aprset[i].rtnevents) {
+            (*nsds)++;
+        }
+    }
+
+    return APR_SUCCESS;
+}
+
+#endif /* POLL_USES_SELECT */
+
+struct apr_pollset_private_t
+{
+    fd_set readset, writeset, exceptset;
+    int maxfd;
+    apr_pollfd_t *query_set;
+    apr_pollfd_t *result_set;
+    apr_uint32_t flags;
+#ifdef NETWARE
+    int set_type;
+#endif
+};
+
+static apr_status_t impl_pollset_create(apr_pollset_t *pollset,
+                                        apr_uint32_t size,
+                                        apr_pool_t *p,
+                                        apr_uint32_t flags)
+{
+    if (flags & APR_POLLSET_THREADSAFE) {                
+        pollset->p = NULL;
+        return APR_ENOTIMPL;
+    }
+#ifdef FD_SETSIZE
+    if (size > FD_SETSIZE) {
+        pollset->p = NULL;
+        return APR_EINVAL;
+    }
+#endif
+    pollset->p = apr_palloc(p, sizeof(apr_pollset_private_t));
+    FD_ZERO(&(pollset->p->readset));
+    FD_ZERO(&(pollset->p->writeset));
+    FD_ZERO(&(pollset->p->exceptset));
+    pollset->p->maxfd = 0;
+#ifdef NETWARE
+    pollset->p->set_type = APR_NO_DESC;
+#endif
+    pollset->p->query_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
+    pollset->p->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
+
+    return APR_SUCCESS;
+}
+
+static apr_status_t impl_pollset_add(apr_pollset_t *pollset,
+                                     const apr_pollfd_t *descriptor)
+{
+    apr_os_sock_t fd;
+
+    if (pollset->nelts == pollset->nalloc) {
+        return APR_ENOMEM;
+    }
+
+    pollset->p->query_set[pollset->nelts] = *descriptor;
+
+    if (descriptor->desc_type == APR_POLL_SOCKET) {
+#ifdef NETWARE
+        /* NetWare can't handle mixed descriptor types in select() */
+        if (HAS_PIPES(pollset->p->set_type)) {
+            return APR_EBADF;
+        }
+        else {
+            pollset->p->set_type = APR_POLL_SOCKET;
+        }
+#endif
+        fd = descriptor->desc.s->socketdes;
+    }
+    else {
+#if !APR_FILES_AS_SOCKETS
+        if ((pollset->flags & APR_POLLSET_WAKEABLE) &&
+            descriptor->desc.f == pollset->wakeup_pipe[0])
+            fd = (apr_os_sock_t)descriptor->desc.f->filedes;
+        else
+            return APR_EBADF;
+#else
+#ifdef NETWARE
+        /* NetWare can't handle mixed descriptor types in select() */
+        if (descriptor->desc.f->is_pipe && !HAS_SOCKETS(pollset->p->set_type)) {
+            pollset->p->set_type = APR_POLL_FILE;
+            fd = descriptor->desc.f->filedes;
+        }
+        else {
+            return APR_EBADF;
+        }
+#else
+        fd = descriptor->desc.f->filedes;
+#endif
+#endif
+    }
+#if !defined(WIN32) && !defined(NETWARE)        /* socket sets handled with array of handles */
+    if (fd >= FD_SETSIZE) {
+        /* XXX invent new error code so application has a clue */
+        return APR_EBADF;
+    }
+#endif
+    if (descriptor->reqevents & APR_POLLIN) {
+        FD_SET(fd, &(pollset->p->readset));
+    }
+    if (descriptor->reqevents & APR_POLLOUT) {
+        FD_SET(fd, &(pollset->p->writeset));
+    }
+    if (descriptor->reqevents &
+        (APR_POLLPRI | APR_POLLERR | APR_POLLHUP | APR_POLLNVAL)) {
+        FD_SET(fd, &(pollset->p->exceptset));
+    }
+    if ((int) fd > pollset->p->maxfd) {
+        pollset->p->maxfd = (int) fd;
+    }
+    pollset->nelts++;
+    return APR_SUCCESS;
+}
+
+static apr_status_t impl_pollset_remove(apr_pollset_t * pollset,
+                                        const apr_pollfd_t * descriptor)
+{
+    apr_uint32_t i;
+    apr_os_sock_t fd;
+
+    if (descriptor->desc_type == APR_POLL_SOCKET) {
+        fd = descriptor->desc.s->socketdes;
+    }
+    else {
+#if !APR_FILES_AS_SOCKETS
+        return APR_EBADF;
+#else
+        fd = descriptor->desc.f->filedes;
+#endif
+    }
+
+    for (i = 0; i < pollset->nelts; i++) {
+        if (descriptor->desc.s == pollset->p->query_set[i].desc.s) {
+            /* Found an instance of the fd: remove this and any other copies */
+            apr_uint32_t dst = i;
+            apr_uint32_t old_nelts = pollset->nelts;
+            pollset->nelts--;
+            for (i++; i < old_nelts; i++) {
+                if (descriptor->desc.s == pollset->p->query_set[i].desc.s) {
+                    pollset->nelts--;
+                }
+                else {
+                    pollset->p->query_set[dst] = pollset->p->query_set[i];
+                    dst++;
+                }
+            }
+            FD_CLR(fd, &(pollset->p->readset));
+            FD_CLR(fd, &(pollset->p->writeset));
+            FD_CLR(fd, &(pollset->p->exceptset));
+            if (((int) fd == pollset->p->maxfd) && (pollset->p->maxfd > 0)) {
+                pollset->p->maxfd--;
+            }
+            return APR_SUCCESS;
+        }
+    }
+
+    return APR_NOTFOUND;
+}
+
+static apr_status_t impl_pollset_poll(apr_pollset_t *pollset,
+                                      apr_interval_time_t timeout,
+                                      apr_int32_t *num,
+                                      const apr_pollfd_t **descriptors)
+{
+    int rs;
+    apr_uint32_t i, j;
+    struct timeval tv, *tvptr;
+    fd_set readset, writeset, exceptset;
+    apr_status_t rv = APR_SUCCESS;
+
+    *num = 0;
+
+#ifdef WIN32
+    /* On Win32, select() must be presented with at least one socket to
+     * poll on, or select() will return WSAEINVAL.  So, we'll just
+     * short-circuit and bail now.
+     */
+    if (pollset->nelts == 0) {
+        if (timeout > 0) {
+            apr_sleep(timeout);
+            return APR_TIMEUP;
+        }
+        return APR_SUCCESS;
+    }
+#endif
+
+    if (timeout < 0) {
+        tvptr = NULL;
+    }
+    else {
+        tv.tv_sec = (long) apr_time_sec(timeout);
+        tv.tv_usec = (long) apr_time_usec(timeout);
+        tvptr = &tv;
+    }
+
+    memcpy(&readset, &(pollset->p->readset), sizeof(fd_set));
+    memcpy(&writeset, &(pollset->p->writeset), sizeof(fd_set));
+    memcpy(&exceptset, &(pollset->p->exceptset), sizeof(fd_set));
+
+#ifdef NETWARE
+    if (HAS_PIPES(pollset->p->set_type)) {
+        rs = pipe_select(pollset->p->maxfd + 1, &readset, &writeset, &exceptset,
+                         tvptr);
+    }
+    else
+#endif
+        rs = select(pollset->p->maxfd + 1, &readset, &writeset, &exceptset,
+                    tvptr);
+
+    if (rs < 0) {
+        return apr_get_netos_error();
+    }
+    if (rs == 0) {
+        return APR_TIMEUP;
+    }
+    j = 0;
+    for (i = 0; i < pollset->nelts; i++) {
+        apr_os_sock_t fd;
+        if (pollset->p->query_set[i].desc_type == APR_POLL_SOCKET) {
+            fd = pollset->p->query_set[i].desc.s->socketdes;
+        }
+        else {
+            if ((pollset->flags & APR_POLLSET_WAKEABLE) &&
+                pollset->p->query_set[i].desc.f == pollset->wakeup_pipe[0]) {
+                apr_poll_drain_wakeup_pipe(pollset->wakeup_pipe);
+                rv = APR_EINTR;
+                continue;
+            }
+            else {
+#if !APR_FILES_AS_SOCKETS
+                return APR_EBADF;
+#else
+                fd = pollset->p->query_set[i].desc.f->filedes;
+#endif
+            }
+        }
+        if (FD_ISSET(fd, &readset) || FD_ISSET(fd, &writeset) ||
+            FD_ISSET(fd, &exceptset)) {
+            pollset->p->result_set[j] = pollset->p->query_set[i];
+            pollset->p->result_set[j].rtnevents = 0;
+            if (FD_ISSET(fd, &readset)) {
+                pollset->p->result_set[j].rtnevents |= APR_POLLIN;
+            }
+            if (FD_ISSET(fd, &writeset)) {
+                pollset->p->result_set[j].rtnevents |= APR_POLLOUT;
+            }
+            if (FD_ISSET(fd, &exceptset)) {
+                pollset->p->result_set[j].rtnevents |= APR_POLLERR;
+            }
+            j++;
+        }
+    }
+    if (((*num) = j) != 0)
+        rv = APR_SUCCESS;
+
+    if (descriptors)
+        *descriptors = pollset->p->result_set;
+    return rv;
+}
+
+static const apr_pollset_provider_t impl = {
+    impl_pollset_create,
+    impl_pollset_add,
+    impl_pollset_remove,
+    impl_pollset_poll,
+    NULL,
+    "select"
+};
+
+const apr_pollset_provider_t *apr_pollset_provider_select = &impl;
diff --git a/poll/unix/wakeup.c b/poll/unix/wakeup.c
new file mode 100644
index 00000000000..f8ea0604842
--- /dev/null
+++ b/poll/unix/wakeup.c
@@ -0,0 +1,151 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_poll.h"
+#include "apr_time.h"
+#include "apr_portable.h"
+#include "apr_arch_file_io.h"
+#include "apr_arch_networkio.h"
+#include "apr_arch_poll_private.h"
+#include "apr_arch_inherit.h"
+
+#if !APR_FILES_AS_SOCKETS
+
+#ifdef WIN32
+
+apr_status_t apr_poll_create_wakeup_pipe(apr_pool_t *pool, apr_pollfd_t *pfd,
+                                         apr_file_t **wakeup_pipe)
+{
+    apr_status_t rv;
+
+    if ((rv = file_socket_pipe_create(&wakeup_pipe[0], &wakeup_pipe[1],
+                                      pool)) != APR_SUCCESS)
+        return rv;
+
+    pfd->reqevents = APR_POLLIN;
+    pfd->desc_type = APR_POLL_FILE;
+    pfd->desc.f = wakeup_pipe[0];
+    return APR_SUCCESS;
+}
+
+apr_status_t apr_poll_close_wakeup_pipe(apr_file_t **wakeup_pipe)
+{
+    apr_status_t rv0 = APR_SUCCESS;
+    apr_status_t rv1 = APR_SUCCESS;
+
+    /* Close both sides of the wakeup pipe */
+    if (wakeup_pipe[0]) {
+        rv0 = file_socket_pipe_close(wakeup_pipe[0]);
+        wakeup_pipe[0] = NULL;
+    }
+    if (wakeup_pipe[1]) {
+        rv1 = file_socket_pipe_close(wakeup_pipe[1]);
+        wakeup_pipe[1] = NULL;
+    }
+    return rv0 ? rv0 : rv1;
+}
+
+#else /* !WIN32 */
+
+apr_status_t apr_poll_create_wakeup_pipe(apr_pollfd_t *pfd, apr_file_t **wakeup_pipe)
+{
+    return APR_ENOTIMPL;
+}
+
+apr_status_t apr_poll_close_wakeup_pipe(apr_file_t **wakeup_pipe)
+{
+    return APR_ENOTIMPL;
+}
+
+#endif /* !WIN32 */
+
+#else  /* APR_FILES_AS_SOCKETS */
+
+apr_status_t apr_poll_create_wakeup_pipe(apr_pool_t *pool, apr_pollfd_t *pfd,
+                                         apr_file_t **wakeup_pipe)
+{
+    apr_status_t rv;
+
+    if ((rv = apr_file_pipe_create(&wakeup_pipe[0], &wakeup_pipe[1],
+                                   pool)) != APR_SUCCESS)
+        return rv;
+
+    pfd->p = pool;
+    pfd->reqevents = APR_POLLIN;
+    pfd->desc_type = APR_POLL_FILE;
+    pfd->desc.f = wakeup_pipe[0];
+
+    {
+        int flags;
+
+        if ((flags = fcntl(wakeup_pipe[0]->filedes, F_GETFD)) == -1)
+            return errno;
+
+        flags |= FD_CLOEXEC;
+        if (fcntl(wakeup_pipe[0]->filedes, F_SETFD, flags) == -1)
+            return errno;
+    }
+    {
+        int flags;
+
+        if ((flags = fcntl(wakeup_pipe[1]->filedes, F_GETFD)) == -1)
+            return errno;
+
+        flags |= FD_CLOEXEC;
+        if (fcntl(wakeup_pipe[1]->filedes, F_SETFD, flags) == -1)
+            return errno;
+    }
+
+    return APR_SUCCESS;
+}
+
+apr_status_t apr_poll_close_wakeup_pipe(apr_file_t **wakeup_pipe)
+{
+    apr_status_t rv0 = APR_SUCCESS;
+    apr_status_t rv1 = APR_SUCCESS;
+
+    /* Close both sides of the wakeup pipe */
+    if (wakeup_pipe[0]) {
+        rv0 = apr_file_close(wakeup_pipe[0]);
+        wakeup_pipe[0] = NULL;
+    }
+    if (wakeup_pipe[1]) {
+        rv1 = apr_file_close(wakeup_pipe[1]);
+        wakeup_pipe[1] = NULL;
+    }
+    return rv0 ? rv0 : rv1;
+}
+
+#endif /* APR_FILES_AS_SOCKETS */
+
+/* Read and discard whatever is in the wakeup pipe.
+ */
+void apr_poll_drain_wakeup_pipe(apr_file_t **wakeup_pipe)
+{
+    char rb[512];
+    apr_size_t nr = sizeof(rb);
+
+    while (apr_file_read(wakeup_pipe[0], rb, &nr) == APR_SUCCESS) {
+        /* Although we write just one byte to the other end of the pipe
+         * during wakeup, multiple threads could call the wakeup.
+         * So simply drain out from the input side of the pipe all
+         * the data.
+         */
+        if (nr != sizeof(rb))
+            break;
+    }
+}
diff --git a/poll/unix/z_asio.c b/poll/unix/z_asio.c
new file mode 100644
index 00000000000..48b531cc8c7
--- /dev/null
+++ b/poll/unix/z_asio.c
@@ -0,0 +1,782 @@
+/* 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 implementation is based on a design by John Brooks (IBM Pok) which uses
+ * the z/OS sockets async i/o facility.  When a
+ * socket is added to the pollset, an async poll is issued for that individual
+ * socket.  It specifies that the kernel should send an IPC message when the
+ * socket becomes ready.  The IPC messages are sent to a single message queue
+ * that is part of the pollset.  apr_pollset_poll waits on the arrival of IPC
+ * messages or the specified timeout.
+ *
+ * Since z/OS does not support async i/o for pipes or files at present, this
+ * implementation falls back to using ordinary poll() when
+ * APR_POLLSET_THREADSAFE is unset.
+ *
+ * Greg Ames
+ * April 2012
+ */
+
+#include "apr.h"
+#include "apr_hash.h"
+#include "apr_poll.h"
+#include "apr_time.h"
+#include "apr_portable.h"
+#include "apr_arch_inherit.h"
+#include "apr_arch_file_io.h"
+#include "apr_arch_networkio.h"
+#include "apr_arch_poll_private.h"
+
+#ifdef HAVE_AIO_MSGQ
+
+#include <sys/msg.h>  	/* msgget etc   */
+#include <time.h>     	/* timestruct   */
+#include <poll.h>     	/* pollfd       */
+#include <limits.h>     /* MAX_INT      */
+
+struct apr_pollset_private_t
+{
+    int             msg_q;              /* IPC message queue. The z/OS kernel sends messages
+                                         * to this queue when our async polls on individual
+                                         * file descriptors complete
+                                         */
+    apr_pollfd_t    *result_set;
+    apr_uint32_t    size;
+
+#if APR_HAS_THREADS
+    /* A thread mutex to protect operations on the rings and the hash */
+    apr_thread_mutex_t *ring_lock;
+#endif
+
+    /* A hash of all active elements used for O(1) _remove operations */
+    apr_hash_t      *elems;
+
+    APR_RING_HEAD(ready_ring_t,       asio_elem_t)      ready_ring;
+    APR_RING_HEAD(prior_ready_ring_t, asio_elem_t)      prior_ready_ring;
+    APR_RING_HEAD(free_ring_t,        asio_elem_t)      free_ring;
+
+    /* for pipes etc with no asio */
+    struct pollfd   *pollset;
+    apr_pollfd_t    *query_set;
+};
+
+typedef enum {
+    ASIO_INIT = 0,
+    ASIO_REMOVED,
+    ASIO_COMPLETE
+} asio_state_e;
+
+typedef struct asio_elem_t asio_elem_t;
+
+struct asio_msgbuf_t {
+    long         msg_type;       /* must be > 0 */
+    asio_elem_t *msg_elem;
+};
+
+struct asio_elem_t
+{
+    APR_RING_ENTRY(asio_elem_t) link;
+    apr_pollfd_t                pfd;
+    struct pollfd               os_pfd;
+    struct aiocb                a;
+    asio_state_e                state;
+    struct asio_msgbuf_t        msg;
+};
+
+#define DEBUG 0
+
+/* DEBUG settings: 0 - no debug messages at all,
+ *                 1 - should not occur messages,
+ *                 2 - apr_pollset_* entry and exit messages,
+ *                 3 - state changes, memory usage,
+ *                 4 - z/OS, APR, and internal calls,
+ *                 5 - everything else except the timer pop path,
+ *                 6 - everything, including the Event 1 sec timer pop path
+ *
+ *  each DEBUG level includes all messages produced by lower numbered levels
+ */
+
+#if DEBUG
+
+#include <assert.h>
+#include <unistd.h>	/* getpid       */
+
+#define DBG_BUFF char dbg_msg_buff[256];
+
+#define DBG_TEST(lvl) if (lvl <= DEBUG) {
+
+#define DBG_CORE(msg)               sprintf(dbg_msg_buff, "% 8d " __FUNCTION__ \
+                                        " "  msg, getpid()),                   \
+                                    fprintf(stderr, "%s", dbg_msg_buff);
+#define DBG_CORE1(msg, var1)        sprintf(dbg_msg_buff, "% 8d " __FUNCTION__ \
+                                        " " msg, getpid(), var1),              \
+                                    fprintf(stderr, "%s", dbg_msg_buff);
+#define DBG_CORE2(msg, var1, var2)  sprintf(dbg_msg_buff, "% 8d " __FUNCTION__ \
+                                        " " msg, getpid(), var1, var2),        \
+                                    fprintf(stderr, "%s", dbg_msg_buff);
+#define DBG_CORE3(msg, var1, var2, var3)                                       \
+                                    sprintf(dbg_msg_buff, "% 8d " __FUNCTION__ \
+                                        " " msg, getpid(), var1, var2, var3),  \
+                                    fprintf(stderr, "%s", dbg_msg_buff);
+#define DBG_CORE4(msg, var1, var2, var3, var4)                                 \
+                                    sprintf(dbg_msg_buff, "% 8d " __FUNCTION__ \
+                                        " " msg, getpid(), var1, var2, var3, var4),\
+                                    fprintf(stderr, "%s", dbg_msg_buff);
+
+#define DBG_END }
+
+#define DBG(lvl, msg)   DBG_TEST(lvl)   \
+                        DBG_CORE(msg)   \
+                        DBG_END
+
+#define DBG1(lvl, msg, var1)    DBG_TEST(lvl)           \
+                                DBG_CORE1(msg, var1)    \
+                                DBG_END
+
+#define DBG2(lvl, msg, var1, var2)      DBG_TEST(lvl)               \
+                                        DBG_CORE2(msg, var1, var2)  \
+                                        DBG_END
+
+#define DBG3(lvl, msg, var1, var2, var3)                        \
+                        DBG_TEST(lvl)                           \
+                        DBG_CORE3(msg, var1, var2, var3)        \
+                        DBG_END
+
+#define DBG4(lvl, msg, var1, var2, var3, var4)                  \
+                        DBG_TEST(lvl)                           \
+                        DBG_CORE4(msg, var1, var2, var3, var4)  \
+                        DBG_END
+
+#else  /* DEBUG is 0 */
+#define DBG_BUFF
+#define DBG(lvl, msg)                            ((void)0)
+#define DBG1(lvl, msg, var1)                     ((void)0)
+#define DBG2(lvl, msg, var1, var2)               ((void)0)
+#define DBG3(lvl, msg, var1, var2, var3)         ((void)0)
+#define DBG4(lvl, msg, var1, var2, var3, var4)   ((void)0)
+
+#endif /* DEBUG */
+
+static int asyncio(struct aiocb *a)
+{
+    DBG_BUFF
+    int rv;
+
+#ifdef _LP64
+#define AIO BPX4AIO
+#else
+#define AIO BPX1AIO
+#endif
+
+    AIO(sizeof(struct aiocb), a, &rv, &errno, __err2ad());
+    DBG2(4, "BPX4AIO aiocb %p rv %d\n",
+             a, rv);
+#ifdef DEBUG
+    if (rv < 0) {
+        DBG2(4, "errno %d errnojr %08x\n",
+                 errno, *__err2ad());
+    }
+#endif
+    return rv;
+}
+
+static apr_int16_t get_event(apr_int16_t event)
+{
+    DBG_BUFF
+    apr_int16_t rv = 0;
+    DBG(4, "entered\n");
+
+    if (event & APR_POLLIN)
+        rv |= POLLIN;
+    if (event & APR_POLLPRI)
+        rv |= POLLPRI;
+    if (event & APR_POLLOUT)
+        rv |= POLLOUT;
+    if (event & APR_POLLERR)
+        rv |= POLLERR;
+    if (event & APR_POLLHUP)
+        rv |= POLLHUP;
+    if (event & APR_POLLNVAL)
+        rv |= POLLNVAL;
+
+    DBG(4, "exiting\n");
+    return rv;
+}
+
+static apr_int16_t get_revent(apr_int16_t event)
+{
+    DBG_BUFF
+    apr_int16_t rv = 0;
+    DBG(4, "entered\n");
+
+    if (event & POLLIN)
+        rv |= APR_POLLIN;
+    if (event & POLLPRI)
+        rv |= APR_POLLPRI;
+    if (event & POLLOUT)
+        rv |= APR_POLLOUT;
+    if (event & POLLERR)
+        rv |= APR_POLLERR;
+    if (event & POLLHUP)
+        rv |= APR_POLLHUP;
+    if (event & POLLNVAL)
+        rv |= APR_POLLNVAL;
+
+    DBG(4, "exiting\n");
+    return rv;
+}
+
+static apr_status_t asio_pollset_cleanup(apr_pollset_t *pollset)
+{
+    DBG_BUFF
+    int rv;
+
+    DBG(4, "entered\n");
+    if (pollset->flags & APR_POLLSET_THREADSAFE) { 
+        rv = msgctl(pollset->p->msg_q, IPC_RMID, NULL);
+        DBG1(4, "asio_pollset_cleanup: msgctl(IPC_RMID) returned %d\n", rv);
+    }
+
+    return rv;
+}
+
+static apr_status_t asio_pollset_create(apr_pollset_t *pollset,
+                                        apr_uint32_t size,
+                                        apr_pool_t *p,
+                                        apr_uint32_t flags)
+{
+    DBG_BUFF
+    apr_status_t rv;
+    apr_pollset_private_t *priv;
+
+    DBG1(2, "entered, flags: %x\n", flags);
+
+    priv = pollset->p = apr_pcalloc(p, sizeof(*priv));
+
+    if (flags & APR_POLLSET_THREADSAFE) {
+#if APR_HAS_THREADS
+        if ((rv = apr_thread_mutex_create(&(priv->ring_lock),
+                                           APR_THREAD_MUTEX_DEFAULT,
+                                           p)) != APR_SUCCESS) {
+            DBG1(1, "apr_thread_mutex_create returned %d\n", rv);
+            pollset->p = NULL;
+            return rv;
+        }
+        rv = msgget(IPC_PRIVATE, S_IWUSR+S_IRUSR); /* user r/w perms */
+        if (rv < 0) {
+#if DEBUG
+            perror(__FUNCTION__ " msgget returned < 0 ");
+#endif
+            pollset->p = NULL;
+            return rv;
+        }
+
+        DBG2(4, "pollset %p msgget was OK, rv=%d\n", pollset, rv);
+        priv->msg_q = rv;
+        priv->elems   = apr_hash_make(p);
+
+        APR_RING_INIT(&priv->free_ring, asio_elem_t, link);
+        APR_RING_INIT(&priv->prior_ready_ring, asio_elem_t, link);
+
+#else  /* APR doesn't have threads but caller wants a threadsafe pollset */
+        pollset->p = NULL;
+        return APR_ENOTIMPL;
+#endif
+
+    } else {  /* APR_POLLSET_THREADSAFE not set, i.e. no async i/o,
+               * init fields only needed in old style pollset
+               */
+
+        priv->pollset = apr_palloc(p, size * sizeof(struct pollfd));
+        priv->query_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
+
+        if ((!priv->pollset) || (!priv->query_set)) {
+            pollset->p = NULL;
+            return APR_ENOMEM;
+        }
+    }
+
+    pollset->nelts   = 0;
+    pollset->flags   = flags;
+    pollset->pool    = p;
+    priv->size    = size;
+    priv->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
+    if (!priv->result_set) {
+        if (flags & APR_POLLSET_THREADSAFE) {
+            msgctl(priv->msg_q, IPC_RMID, NULL);
+        }
+        pollset->p = NULL;
+        return APR_ENOMEM;
+    }
+
+    DBG2(2, "exiting, pollset: %p, type: %s\n",
+             pollset,
+             flags & APR_POLLSET_THREADSAFE ? "async" : "POSIX");
+
+
+    return APR_SUCCESS;
+
+} /* end of asio_pollset_create */
+
+static apr_status_t posix_add(apr_pollset_t      *pollset,
+                              const apr_pollfd_t *descriptor)
+{
+    DBG_BUFF
+    int fd;
+    apr_pool_t  *p = pollset->pool;
+    apr_pollset_private_t *priv = pollset->p;
+
+    DBG(4, "entered\n");
+
+    if (pollset->nelts == priv->size) {
+        return APR_ENOMEM;
+    }
+
+    priv->query_set[pollset->nelts] = *descriptor;
+    if (descriptor->desc_type == APR_POLL_SOCKET) {
+        fd = descriptor->desc.s->socketdes;
+    }
+    else {
+        fd = descriptor->desc.f->filedes;
+    }
+
+    priv->pollset[pollset->nelts].fd = fd;
+
+    priv->pollset[pollset->nelts].events =
+        get_event(descriptor->reqevents);
+
+    pollset->nelts++;
+
+    DBG2(4, "exiting, fd %d added to pollset %p\n", fd, pollset);
+
+    return APR_SUCCESS;
+}   /* end of posix_add */
+
+
+static apr_status_t asio_pollset_add(apr_pollset_t *pollset,
+                                     const apr_pollfd_t *descriptor)
+{
+    DBG_BUFF
+    asio_elem_t *elem;
+    apr_status_t rv = APR_SUCCESS;
+    apr_pollset_private_t *priv = pollset->p;
+
+    pollset_lock_rings();
+    DBG(2, "entered\n");
+
+    if (pollset->flags & APR_POLLSET_THREADSAFE) {
+
+        if (!APR_RING_EMPTY(&(priv->free_ring), asio_elem_t, link)) {
+            elem = APR_RING_FIRST(&(priv->free_ring));
+            APR_RING_REMOVE(elem, link);
+            DBG1(3, "used recycled memory at %08p\n", elem);
+            elem->state = ASIO_INIT;
+            elem->a.aio_cflags = 0;
+        }
+        else {
+            elem = (asio_elem_t *) apr_pcalloc(pollset->pool, sizeof(asio_elem_t));
+            DBG1(3, "alloced new memory at %08p\n", elem);
+
+            elem->a.aio_notifytype = AIO_MSGQ;
+            elem->a.aio_msgev_qid  = priv->msg_q;
+            DBG1(5, "aio_msgev_quid = %d \n", elem->a.aio_msgev_qid);
+            elem->a.aio_msgev_size = sizeof(asio_elem_t *);
+            elem->a.aio_msgev_flag = 0;     /* wait if queue is full */
+            elem->a.aio_msgev_addr = &(elem->msg);
+            elem->a.aio_buf        = &(elem->os_pfd);
+            elem->a.aio_nbytes     = 1;     /* number of pfds to poll */
+            elem->msg.msg_type     = 1;
+            elem->msg.msg_elem     = elem;
+        }
+
+        /* z/OS only supports async I/O for sockets for now */
+        elem->os_pfd.fd = descriptor->desc.s->socketdes;
+
+        APR_RING_ELEM_INIT(elem, link);
+        elem->a.aio_cmd       = AIO_SELPOLL;
+        elem->a.aio_cflags    &= ~AIO_OK2COMPIMD; /* not OK to complete inline*/
+        elem->pfd             = *descriptor;
+        elem->os_pfd.events   = get_event(descriptor->reqevents);
+
+        if (0 != asyncio(&elem->a)) {
+            rv = errno;
+            DBG3(4, "pollset %p asio failed fd %d, errno %p\n",
+                     pollset, elem->os_pfd.fd, rv);
+#if DEBUG
+            perror(__FUNCTION__ " asio failure");
+#endif
+        }
+        else {
+            DBG2(4, "good asio call, adding fd %d to pollset %p\n",
+                     elem->os_pfd.fd, pollset);
+
+            pollset->nelts++;
+            apr_hash_set(priv->elems, &(elem->os_pfd.fd), sizeof(int), elem);
+        }
+    }
+    else {
+        /* APR_POLLSET_THREADSAFE isn't set.  use POSIX poll in case
+         * pipes or files are used with this pollset
+         */
+
+        rv = posix_add(pollset, descriptor);
+    }
+
+    DBG1(2, "exiting, rv = %d\n", rv);
+
+    pollset_unlock_rings();
+    return rv;
+} /* end of asio_pollset_add */
+
+static posix_remove(apr_pollset_t *pollset, const apr_pollfd_t *descriptor)
+{
+    DBG_BUFF
+    apr_uint32_t i;
+    apr_pollset_private_t *priv = pollset->p;
+
+    DBG(4, "entered\n");
+    for (i = 0; i < pollset->nelts; i++) {
+        if (descriptor->desc.s == priv->query_set[i].desc.s) {
+            /* Found an instance of the fd: remove this and any other copies */
+            apr_uint32_t dst = i;
+            apr_uint32_t old_nelts = pollset->nelts;
+            pollset->nelts--;
+            for (i++; i < old_nelts; i++) {
+                if (descriptor->desc.s == priv->query_set[i].desc.s) {
+                    pollset->nelts--;
+                }
+                else {
+                    priv->pollset[dst] = priv->pollset[i];
+                    priv->query_set[dst] = priv->query_set[i];
+                    dst++;
+                }
+            }
+            DBG(4, "returning OK\n");
+            return APR_SUCCESS;
+        }
+    }
+
+    DBG(1, "returning APR_NOTFOUND\n");
+    return APR_NOTFOUND;
+
+}   /* end of posix_remove */
+
+static apr_status_t asio_pollset_remove(apr_pollset_t *pollset,
+                                        const apr_pollfd_t *descriptor)
+{
+    DBG_BUFF
+    asio_elem_t *elem;
+    apr_status_t rv = APR_SUCCESS;
+    apr_pollset_private_t *priv = pollset->p;
+    /* AIO_CANCEL is synchronous, so autodata works fine.  */
+    struct aiocb cancel_a = {0};   
+
+    int fd;
+
+    DBG(2, "entered\n");
+
+    if (!(pollset->flags & APR_POLLSET_THREADSAFE)) {
+        return posix_remove(pollset, descriptor);
+    }
+
+    pollset_lock_rings();
+
+#if DEBUG
+    assert(descriptor->desc_type == APR_POLL_SOCKET);
+#endif
+    /* zOS 1.12 doesn't support files for async i/o */
+    fd = descriptor->desc.s->socketdes;
+
+    elem = apr_hash_get(priv->elems, &(fd), sizeof(int));
+    if (elem == NULL) {
+        DBG1(1, "couldn't find fd %d\n", fd);
+        rv = APR_NOTFOUND;
+    } else {
+        DBG1(5, "hash found fd %d\n", fd);
+        /* delete this fd from the hash */
+        apr_hash_set(priv->elems, &(fd), sizeof(int), NULL);
+
+        if (elem->state == ASIO_INIT) {
+            /* asyncio call to cancel */
+            cancel_a.aio_cmd = AIO_CANCEL;
+            cancel_a.aio_buf = &elem->a;   /* point to original aiocb */
+
+            cancel_a.aio_cflags  = 0;
+            cancel_a.aio_cflags2 = 0;
+
+            /* we want the original aiocb to show up on the pollset message queue 
+             * before recycling its memory to eliminate race conditions
+             */
+
+            rv = asyncio(&cancel_a);
+            DBG1(4, "asyncio returned %d\n", rv);
+
+#if DEBUG
+            assert(rv == 1);
+#endif
+        }
+        elem->state = ASIO_REMOVED;
+        rv = APR_SUCCESS;
+    }
+
+    DBG1(2, "exiting, rv: %d\n", rv);
+
+    pollset_unlock_rings();
+
+    return rv;
+}   /* end of asio_pollset_remove */
+
+static posix_poll(apr_pollset_t *pollset,
+                  apr_interval_time_t timeout,
+                  apr_int32_t *num,
+                  const apr_pollfd_t **descriptors)
+{
+    DBG_BUFF
+    int rv;
+    apr_uint32_t i, j;
+    apr_pollset_private_t *priv = pollset->p;
+
+    DBG(4, "entered\n");
+
+    if (timeout > 0) {
+        timeout /= 1000;
+    }
+    rv = poll(priv->pollset, pollset->nelts, timeout);
+    (*num) = rv;
+    if (rv < 0) {
+        return apr_get_netos_error();
+    }
+    if (rv == 0) {
+        return APR_TIMEUP;
+    }
+    j = 0;
+    for (i = 0; i < pollset->nelts; i++) {
+        if (priv->pollset[i].revents != 0) {
+            priv->result_set[j] = priv->query_set[i];
+            priv->result_set[j].rtnevents =
+                get_revent(priv->pollset[i].revents);
+            j++;
+        }
+    }
+    if (descriptors)
+        *descriptors = priv->result_set;
+
+    DBG(4, "exiting ok\n");
+    return APR_SUCCESS;
+
+}   /* end of posix_poll */
+
+static process_msg(apr_pollset_t *pollset, struct asio_msgbuf_t *msg)
+{
+    DBG_BUFF
+    asio_elem_t *elem = msg->msg_elem;
+
+    switch(elem->state) {
+    case ASIO_REMOVED:
+        DBG2(5, "for cancelled elem, recycling memory - elem %08p, fd %d\n",
+                elem, elem->os_pfd.fd);
+        APR_RING_INSERT_TAIL(&(pollset->p->free_ring), elem,
+                             asio_elem_t, link);
+        break;
+    case ASIO_INIT:
+        DBG2(4, "adding to ready ring: elem %08p, fd %d\n",
+                elem, elem->os_pfd.fd);
+        elem->state = ASIO_COMPLETE;
+        APR_RING_INSERT_TAIL(&(pollset->p->ready_ring), elem,
+                             asio_elem_t, link);
+        break;
+    default:
+        DBG3(1, "unexpected state: elem %08p, fd %d, state %d\n",
+            elem, elem->os_pfd.fd, elem->state);
+#if DEBUG
+        assert(0);
+#endif
+    }
+}
+
+static apr_status_t asio_pollset_poll(apr_pollset_t *pollset,
+                                      apr_interval_time_t timeout,
+                                      apr_int32_t *num,
+                                      const apr_pollfd_t **descriptors)
+{
+    DBG_BUFF
+    int i, ret;
+    asio_elem_t *elem, *next_elem;
+    struct asio_msgbuf_t msg_buff;
+    struct timespec tv;
+    apr_status_t rv = APR_SUCCESS;
+    apr_pollset_private_t *priv = pollset->p;
+
+    DBG(6, "entered\n"); /* chatty - traces every second w/Event */
+
+    if ((pollset->flags & APR_POLLSET_THREADSAFE) == 0 ) {
+        return posix_poll(pollset, timeout, num, descriptors);
+    }
+
+    pollset_lock_rings();
+    APR_RING_INIT(&(priv->ready_ring), asio_elem_t, link);
+
+    while (!APR_RING_EMPTY(&(priv->prior_ready_ring), asio_elem_t, link)) {
+        elem = APR_RING_FIRST(&(priv->prior_ready_ring));
+        DBG3(5, "pollset %p elem %p fd %d on prior ready ring\n",
+                pollset,
+                elem,
+                elem->os_pfd.fd);
+
+        APR_RING_REMOVE(elem, link);
+
+        /*
+         * since USS does not remember what's in our pollset, we have
+         * to re-add fds which have not been apr_pollset_remove'd
+         *
+         * there may have been too many ready fd's to return in the
+         * result set last time. re-poll inline for both cases
+         */
+
+        if (elem->state == ASIO_REMOVED) {
+
+            /* 
+             * async i/o is done since it was found on prior_ready
+             * the state says the caller is done with it too 
+             * so recycle the elem 
+             */
+             
+            APR_RING_INSERT_TAIL(&(priv->free_ring), elem,
+                                 asio_elem_t, link);
+            continue;  /* do not re-add if it has been _removed */
+        }
+
+        elem->state = ASIO_INIT;
+        elem->a.aio_cflags     = AIO_OK2COMPIMD;
+
+        if (0 != (ret = asyncio(&elem->a))) {
+            if (ret == 1) {
+                DBG(4, "asyncio() completed inline\n");
+                /* it's ready now */
+                elem->state = ASIO_COMPLETE;
+                APR_RING_INSERT_TAIL(&(priv->ready_ring), elem, asio_elem_t,
+                                     link);
+            }
+            else {
+                DBG2(1, "asyncio() failed, ret: %d, errno: %d\n",
+                        ret, errno);
+                pollset_unlock_rings();
+                return errno;
+            }
+        }
+        DBG1(4, "asyncio() completed rc %d\n", ret);
+    }
+
+    DBG(6, "after prior ready loop\n"); /* chatty w/timeouts, hence 6 */
+
+    /* Gather async poll completions that have occurred since the last call */
+    while (0 < msgrcv(priv->msg_q, &msg_buff, sizeof(asio_elem_t *), 0,
+                      IPC_NOWAIT)) {
+        process_msg(pollset, &msg_buff);
+    }
+
+    /* Suspend if nothing is ready yet. */
+    if (APR_RING_EMPTY(&(priv->ready_ring), asio_elem_t, link)) {
+
+        if (timeout >= 0) {
+            tv.tv_sec  = apr_time_sec(timeout);
+            tv.tv_nsec = apr_time_usec(timeout) * 1000;
+        } else {
+            tv.tv_sec = INT_MAX;  /* block until something is ready */
+        }
+
+        DBG2(6, "nothing on the ready ring "
+                "- blocking for %d seconds %d ns\n",
+                tv.tv_sec, tv.tv_nsec);
+
+        pollset_unlock_rings();   /* allow other apr_pollset_* calls while blocked */
+
+        if (0 >= (ret = __msgrcv_timed(priv->msg_q, &msg_buff,
+                                       sizeof(asio_elem_t *), 0, NULL, &tv))) {
+#if DEBUG
+            if (errno == EAGAIN) {
+                DBG(6, "__msgrcv_timed timed out\n"); /* timeout path, so 6 */
+            }
+            else {
+                DBG(1, "__msgrcv_timed failed!\n");
+            }
+#endif
+            return (errno == EAGAIN) ? APR_TIMEUP : errno;
+        }
+
+        pollset_lock_rings();
+
+        process_msg(pollset, &msg_buff);
+    }
+
+    APR_RING_INIT(&priv->prior_ready_ring, asio_elem_t, link);
+
+    (*num) = 0;
+    elem = APR_RING_FIRST(&(priv->ready_ring));
+
+    for (i = 0;
+
+        i < priv->size
+                && elem != APR_RING_SENTINEL(&(priv->ready_ring), asio_elem_t, link);
+        i++) {
+             DBG2(5, "ready ring: elem %08p, fd %d\n", elem, elem->os_pfd.fd);
+
+             priv->result_set[i] = elem->pfd;
+             priv->result_set[i].rtnevents
+                                    = get_revent(elem->os_pfd.revents);
+             (*num)++;
+
+             elem = APR_RING_NEXT(elem, link);
+
+#if DEBUG
+             if (elem == APR_RING_SENTINEL(&(priv->ready_ring), asio_elem_t, link)) {
+                 DBG(5, "end of ready ring reached\n");
+             }
+#endif
+    }
+
+    if (descriptors) {
+        *descriptors = priv->result_set;
+    }
+
+    /* if the result size is too small, remember which descriptors
+     * haven't had results reported yet.  we will look
+     * at these descriptors on the next apr_pollset_poll call
+     */
+
+    APR_RING_CONCAT(&priv->prior_ready_ring, &(priv->ready_ring), asio_elem_t, link);
+
+    DBG1(2, "exiting, rv = %d\n", rv);
+
+    pollset_unlock_rings();
+
+    return rv;
+}  /* end of asio_pollset_poll */
+
+static const apr_pollset_provider_t impl = {
+    asio_pollset_create,
+    asio_pollset_add,
+    asio_pollset_remove,
+    asio_pollset_poll,
+    asio_pollset_cleanup,
+    "asio"
+};
+
+const apr_pollset_provider_t *apr_pollset_provider_aio_msgq = &impl;
+
+#endif /* HAVE_AIO_MSGQ */
diff --git a/random/unix/apr_random.c b/random/unix/apr_random.c
new file mode 100644
index 00000000000..b042b66bdf5
--- /dev/null
+++ b/random/unix/apr_random.c
@@ -0,0 +1,326 @@
+/* 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.
+ */
+/*
+ * See the paper "On Randomness" by Ben Laurie for an explanation of this PRNG.
+ * http://www.apache-ssl.org/randomness.pdf
+ * XXX: Is there a formal proof of this PRNG? Couldn't we use the more popular
+ * Mersenne Twister PRNG (and BSD licensed)?
+ */
+
+#include "apr.h"
+#include "apr_pools.h"
+#include "apr_random.h"
+#include "apr_thread_proc.h"
+#include <assert.h>
+
+#ifdef min
+#undef min
+#endif
+#define min(a,b) ((a) < (b) ? (a) : (b))
+
+#define APR_RANDOM_DEFAULT_POOLS 32
+#define APR_RANDOM_DEFAULT_REHASH_SIZE 1024
+#define APR_RANDOM_DEFAULT_RESEED_SIZE 32
+#define APR_RANDOM_DEFAULT_HASH_SECRET_SIZE 32
+#define APR_RANDOM_DEFAULT_G_FOR_INSECURE 32
+#define APR_RANDOM_DEFAULT_G_FOR_SECURE 320
+
+typedef struct apr_random_pool_t {
+    unsigned char *pool;
+    unsigned int bytes;
+    unsigned int pool_size;
+} apr_random_pool_t;
+
+#define hash_init(h)            (h)->init(h)
+#define hash_add(h,b,n)         (h)->add(h,b,n)
+#define hash_finish(h,r)        (h)->finish(h,r)
+
+#define hash(h,r,b,n)           hash_init(h),hash_add(h,b,n),hash_finish(h,r)
+
+#define crypt_setkey(c,k)       (c)->set_key((c)->data,k)
+#define crypt_crypt(c,out,in)   (c)->crypt((c)->date,out,in)
+
+struct apr_random_t {
+    apr_pool_t *apr_pool;
+    apr_crypto_hash_t *pool_hash;
+    unsigned int npools;
+    apr_random_pool_t *pools;
+    unsigned int next_pool;
+    unsigned int generation;
+    apr_size_t rehash_size;
+    apr_size_t reseed_size;
+    apr_crypto_hash_t *key_hash;
+#define K_size(g) ((g)->key_hash->size)
+    apr_crypto_hash_t *prng_hash;
+#define B_size(g) ((g)->prng_hash->size)
+
+    unsigned char *H;
+    unsigned char *H_waiting;
+#define H_size(g) (B_size(g)+K_size(g))
+#define H_current(g) (((g)->insecure_started && !(g)->secure_started) \
+                      ? (g)->H_waiting : (g)->H)
+
+    unsigned char *randomness;
+    apr_size_t random_bytes;
+    unsigned int g_for_insecure;
+    unsigned int g_for_secure;
+    unsigned int secure_base;
+    unsigned int insecure_started:1;
+    unsigned int secure_started:1;
+
+    apr_random_t *next;
+};
+
+static apr_random_t *all_random;
+
+static apr_status_t random_cleanup(void *data)
+{
+    apr_random_t *remove_this = data,
+                 *cur = all_random,
+                 **prev_ptr = &all_random;
+    while (cur) {
+        if (cur == remove_this) {
+            *prev_ptr = cur->next;
+            break;
+        }
+        prev_ptr = &cur->next;
+        cur = cur->next;
+    }
+    return APR_SUCCESS;
+}
+
+
+APR_DECLARE(void) apr_random_init(apr_random_t *g,apr_pool_t *p,
+                                  apr_crypto_hash_t *pool_hash,
+                                  apr_crypto_hash_t *key_hash,
+                                  apr_crypto_hash_t *prng_hash)
+{
+    unsigned int n;
+
+    g->apr_pool = p;
+
+    g->pool_hash = pool_hash;
+    g->key_hash = key_hash;
+    g->prng_hash = prng_hash;
+
+    g->npools = APR_RANDOM_DEFAULT_POOLS;
+    g->pools = apr_palloc(p,g->npools*sizeof *g->pools);
+    for (n = 0; n < g->npools; ++n) {
+        g->pools[n].bytes = g->pools[n].pool_size = 0;
+        g->pools[n].pool = NULL;
+    }
+    g->next_pool = 0;
+
+    g->generation = 0;
+
+    g->rehash_size = APR_RANDOM_DEFAULT_REHASH_SIZE;
+    /* Ensure that the rehash size is twice the size of the pool hasher */
+    g->rehash_size = ((g->rehash_size+2*g->pool_hash->size-1)/g->pool_hash->size
+                    /2)*g->pool_hash->size*2;
+    g->reseed_size = APR_RANDOM_DEFAULT_RESEED_SIZE;
+
+    g->H = apr_pcalloc(p,H_size(g));
+    g->H_waiting = apr_pcalloc(p,H_size(g));
+
+    g->randomness = apr_palloc(p,B_size(g));
+    g->random_bytes = 0;
+
+    g->g_for_insecure = APR_RANDOM_DEFAULT_G_FOR_INSECURE;
+    g->secure_base = 0;
+    g->g_for_secure = APR_RANDOM_DEFAULT_G_FOR_SECURE;
+    g->secure_started = g->insecure_started = 0;
+
+    g->next = all_random;
+    all_random = g;
+    apr_pool_cleanup_register(p, g, random_cleanup, apr_pool_cleanup_null);
+}
+
+static void mix_pid(apr_random_t *g,unsigned char *H,pid_t pid)
+{
+    hash_init(g->key_hash);
+    hash_add(g->key_hash,H,H_size(g));
+    hash_add(g->key_hash,&pid,sizeof pid);
+    hash_finish(g->key_hash,H);
+}
+
+static void mixer(apr_random_t *g,pid_t pid)
+{
+    unsigned char *H = H_current(g);
+
+    /* mix the PID into the current H */
+    mix_pid(g,H,pid);
+    /* if we are in waiting, then also mix into main H */
+    if (H != g->H)
+        mix_pid(g,g->H,pid);
+    /* change order of pool mixing for good measure - note that going
+       backwards is much better than going forwards */
+    --g->generation;
+    /* blow away any lingering randomness */
+    g->random_bytes = 0;
+}
+
+APR_DECLARE(void) apr_random_after_fork(apr_proc_t *proc)
+{
+    apr_random_t *r;
+
+    for (r = all_random; r; r = r->next)
+        /* 
+         * XXX Note: the pid does not provide sufficient entropy to 
+         * actually call this secure.  See Ben's paper referenced at 
+         * the top of this file. 
+         */
+        mixer(r,proc->pid);
+}
+
+APR_DECLARE(apr_random_t *) apr_random_standard_new(apr_pool_t *p)
+{
+    apr_random_t *r = apr_palloc(p,sizeof *r);
+    
+    apr_random_init(r,p,apr_crypto_sha256_new(p),apr_crypto_sha256_new(p),
+                    apr_crypto_sha256_new(p));
+    return r;
+}
+
+static void rekey(apr_random_t *g)
+{
+    unsigned int n;
+    unsigned char *H = H_current(g);
+
+    hash_init(g->key_hash);
+    hash_add(g->key_hash,H,H_size(g));
+    for (n = 0 ; n < g->npools && (n == 0 || g->generation&(1 << (n-1)))
+            ; ++n) {
+        hash_add(g->key_hash,g->pools[n].pool,g->pools[n].bytes);
+        g->pools[n].bytes = 0;
+    }
+    hash_finish(g->key_hash,H+B_size(g));
+
+    ++g->generation;
+    if (!g->insecure_started && g->generation > g->g_for_insecure) {
+        g->insecure_started = 1;
+        if (!g->secure_started) {
+            memcpy(g->H_waiting,g->H,H_size(g));
+            g->secure_base = g->generation;
+        }
+    }
+
+    if (!g->secure_started && g->generation > g->secure_base+g->g_for_secure) {
+        g->secure_started = 1;
+        memcpy(g->H,g->H_waiting,H_size(g));
+    }
+}
+
+APR_DECLARE(void) apr_random_add_entropy(apr_random_t *g,const void *entropy_,
+                                         apr_size_t bytes)
+{
+    unsigned int n;
+    const unsigned char *entropy = entropy_;
+
+    for (n = 0; n < bytes; ++n) {
+        apr_random_pool_t *p = &g->pools[g->next_pool];
+
+        if (++g->next_pool == g->npools)
+            g->next_pool = 0;
+
+        if (p->pool_size < p->bytes+1) {
+            unsigned char *np = apr_palloc(g->apr_pool,(p->bytes+1)*2);
+
+            memcpy(np,p->pool,p->bytes);
+            p->pool = np;
+            p->pool_size = (p->bytes+1)*2;
+        }
+        p->pool[p->bytes++] = entropy[n];
+
+        if (p->bytes == g->rehash_size) {
+            apr_size_t r;
+
+            for (r = 0; r < p->bytes/2; r+=g->pool_hash->size)
+                hash(g->pool_hash,p->pool+r,p->pool+r*2,g->pool_hash->size*2);
+            p->bytes/=2;
+        }
+        assert(p->bytes < g->rehash_size);
+    }
+
+    if (g->pools[0].bytes >= g->reseed_size)
+        rekey(g);
+}
+
+/* This will give g->B_size bytes of randomness */
+static void apr_random_block(apr_random_t *g,unsigned char *random)
+{
+    /* FIXME: in principle, these are different hashes */
+    hash(g->prng_hash,g->H,g->H,H_size(g));
+    hash(g->prng_hash,random,g->H,B_size(g));
+}
+
+static void apr_random_bytes(apr_random_t *g,unsigned char *random,
+                             apr_size_t bytes)
+{
+    apr_size_t n;
+
+    for (n = 0; n < bytes; ) {
+        apr_size_t l;
+
+        if (g->random_bytes == 0) {
+            apr_random_block(g,g->randomness);
+            g->random_bytes = B_size(g);
+        }
+        l = min(bytes-n,g->random_bytes);
+        memcpy(&random[n],g->randomness+B_size(g)-g->random_bytes,l);
+        g->random_bytes-=l;
+        n+=l;
+    }
+}
+
+APR_DECLARE(apr_status_t) apr_random_secure_bytes(apr_random_t *g,
+                                                  void *random,
+                                                  apr_size_t bytes)
+{
+    if (!g->secure_started)
+        return APR_ENOTENOUGHENTROPY;
+    apr_random_bytes(g,random,bytes);
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_random_insecure_bytes(apr_random_t *g,
+                                                    void *random,
+                                                    apr_size_t bytes)
+{
+    if (!g->insecure_started)
+        return APR_ENOTENOUGHENTROPY;
+    apr_random_bytes(g,random,bytes);
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(void) apr_random_barrier(apr_random_t *g)
+{
+    g->secure_started = 0;
+    g->secure_base = g->generation;
+}
+
+APR_DECLARE(apr_status_t) apr_random_secure_ready(apr_random_t *r)
+{
+    if (!r->secure_started)
+        return APR_ENOTENOUGHENTROPY;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_random_insecure_ready(apr_random_t *r)
+{
+    if (!r->insecure_started)
+        return APR_ENOTENOUGHENTROPY;
+    return APR_SUCCESS;
+}
diff --git a/random/unix/sha2.c b/random/unix/sha2.c
new file mode 100644
index 00000000000..12c257d1fa1
--- /dev/null
+++ b/random/unix/sha2.c
@@ -0,0 +1,528 @@
+/* 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:        sha2.c
+ * AUTHOR:      Aaron D. Gifford <me@aarongifford.com>
+ *
+ * A licence was granted to the ASF by Aaron on 4 November 2003.
+ */
+
+#include <string.h>     /* memcpy()/memset() or bcopy()/bzero() */
+#include <assert.h>     /* assert() */
+#include "sha2.h"
+
+/*
+ * ASSERT NOTE:
+ * Some sanity checking code is included using assert().  On my FreeBSD
+ * system, this additional code can be removed by compiling with NDEBUG
+ * defined.  Check your own systems manpage on assert() to see how to
+ * compile WITHOUT the sanity checking code on your system.
+ *
+ * UNROLLED TRANSFORM LOOP NOTE:
+ * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform
+ * loop version for the hash transform rounds (defined using macros
+ * later in this file).  Either define on the command line, for example:
+ *
+ *   cc -DSHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c
+ *
+ * or define below:
+ *
+ *   #define SHA2_UNROLL_TRANSFORM
+ *
+ */
+
+/*** SHA-256/384/512 Machine Architecture Definitions *****************/
+typedef apr_byte_t   sha2_byte;         /* Exactly 1 byte */
+typedef apr_uint32_t sha2_word32;       /* Exactly 4 bytes */
+typedef apr_uint64_t sha2_word64;       /* Exactly 8 bytes */
+
+/*** SHA-256/384/512 Various Length Definitions ***********************/
+/* NOTE: Most of these are in sha2.h */
+#define SHA256_SHORT_BLOCK_LENGTH       (SHA256_BLOCK_LENGTH - 8)
+
+
+/*** ENDIAN REVERSAL MACROS *******************************************/
+#if !APR_IS_BIGENDIAN
+#define REVERSE32(w,x)  { \
+        sha2_word32 tmp = (w); \
+        tmp = (tmp >> 16) | (tmp << 16); \
+        (x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \
+}
+#define REVERSE64(w,x)  { \
+        sha2_word64 tmp = (w); \
+        tmp = (tmp >> 32) | (tmp << 32); \
+        tmp = ((tmp & APR_UINT64_C(0xff00ff00ff00ff00)) >> 8) | \
+              ((tmp & APR_UINT64_C(0x00ff00ff00ff00ff)) << 8); \
+        (x) = ((tmp & APR_UINT64_C(0xffff0000ffff0000)) >> 16) | \
+              ((tmp & APR_UINT64_C(0x0000ffff0000ffff)) << 16); \
+}
+#endif /* !APR_IS_BIGENDIAN */
+
+/*
+ * Macro for incrementally adding the unsigned 64-bit integer n to the
+ * unsigned 128-bit integer (represented using a two-element array of
+ * 64-bit words):
+ */
+#define ADDINC128(w,n)  { \
+        (w)[0] += (sha2_word64)(n); \
+        if ((w)[0] < (n)) { \
+                (w)[1]++; \
+        } \
+}
+
+/*
+ * Macros for copying blocks of memory and for zeroing out ranges
+ * of memory.  Using these macros makes it easy to switch from
+ * using memset()/memcpy() and using bzero()/bcopy().
+ *
+ * Please define either SHA2_USE_MEMSET_MEMCPY or define
+ * SHA2_USE_BZERO_BCOPY depending on which function set you
+ * choose to use:
+ */
+#if !defined(SHA2_USE_MEMSET_MEMCPY) && !defined(SHA2_USE_BZERO_BCOPY)
+/* Default to memset()/memcpy() if no option is specified */
+#define SHA2_USE_MEMSET_MEMCPY  1
+#endif
+#if defined(SHA2_USE_MEMSET_MEMCPY) && defined(SHA2_USE_BZERO_BCOPY)
+/* Abort with an error if BOTH options are defined */
+#error Define either SHA2_USE_MEMSET_MEMCPY or SHA2_USE_BZERO_BCOPY, not both!
+#endif
+
+#ifdef SHA2_USE_MEMSET_MEMCPY
+#define MEMSET_BZERO(p,l)       memset((p), 0, (l))
+#define MEMCPY_BCOPY(d,s,l)     memcpy((d), (s), (l))
+#endif
+#ifdef SHA2_USE_BZERO_BCOPY
+#define MEMSET_BZERO(p,l)       bzero((p), (l))
+#define MEMCPY_BCOPY(d,s,l)     bcopy((s), (d), (l))
+#endif
+
+
+/*** THE SIX LOGICAL FUNCTIONS ****************************************/
+/*
+ * Bit shifting and rotation (used by the six SHA-XYZ logical functions:
+ *
+ *   NOTE:  The naming of R and S appears backwards here (R is a SHIFT and
+ *   S is a ROTATION) because the SHA-256/384/512 description document
+ *   (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this
+ *   same "backwards" definition.
+ */
+/* Shift-right (used in SHA-256, SHA-384, and SHA-512): */
+#define R(b,x)          ((x) >> (b))
+/* 32-bit Rotate-right (used in SHA-256): */
+#define S32(b,x)        (((x) >> (b)) | ((x) << (32 - (b))))
+/* 64-bit Rotate-right (used in SHA-384 and SHA-512): */
+#define S64(b,x)        (((x) >> (b)) | ((x) << (64 - (b))))
+
+/* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */
+#define Ch(x,y,z)       (((x) & (y)) ^ ((~(x)) & (z)))
+#define Maj(x,y,z)      (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
+
+/* Four of six logical functions used in SHA-256: */
+#define Sigma0_256(x)   (S32(2,  (x)) ^ S32(13, (x)) ^ S32(22, (x)))
+#define Sigma1_256(x)   (S32(6,  (x)) ^ S32(11, (x)) ^ S32(25, (x)))
+#define sigma0_256(x)   (S32(7,  (x)) ^ S32(18, (x)) ^ R(3 ,   (x)))
+#define sigma1_256(x)   (S32(17, (x)) ^ S32(19, (x)) ^ R(10,   (x)))
+
+/* Four of six logical functions used in SHA-384 and SHA-512: */
+#define Sigma0_512(x)   (S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x)))
+#define Sigma1_512(x)   (S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x)))
+#define sigma0_512(x)   (S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7,   (x)))
+#define sigma1_512(x)   (S64(19, (x)) ^ S64(61, (x)) ^ R( 6,   (x)))
+
+/*** INTERNAL FUNCTION PROTOTYPES *************************************/
+/* NOTE: These should not be accessed directly from outside this
+ * library -- they are intended for private internal visibility/use
+ * only.
+ */
+void apr__SHA256_Transform(SHA256_CTX*, const sha2_word32*);
+
+
+/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/
+/* Hash constant words K for SHA-256: */
+static const sha2_word32 K256[64] = {
+        0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
+        0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
+        0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
+        0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
+        0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
+        0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
+        0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,
+        0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
+        0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
+        0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
+        0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,
+        0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
+        0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,
+        0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
+        0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
+        0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
+};
+
+/* Initial hash value H for SHA-256: */
+static const sha2_word32 sha256_initial_hash_value[8] = {
+        0x6a09e667UL,
+        0xbb67ae85UL,
+        0x3c6ef372UL,
+        0xa54ff53aUL,
+        0x510e527fUL,
+        0x9b05688cUL,
+        0x1f83d9abUL,
+        0x5be0cd19UL
+};
+
+/*
+ * Constant used by SHA256/384/512_End() functions for converting the
+ * digest to a readable hexadecimal character string:
+ */
+static const char *sha2_hex_digits = "0123456789abcdef";
+
+
+/*** SHA-256: *********************************************************/
+void apr__SHA256_Init(SHA256_CTX* context) {
+        if (context == (SHA256_CTX*)0) {
+                return;
+        }
+        MEMCPY_BCOPY(context->state, sha256_initial_hash_value, SHA256_DIGEST_LENGTH);
+        MEMSET_BZERO(context->buffer, SHA256_BLOCK_LENGTH);
+        context->bitcount = 0;
+}
+
+#ifdef SHA2_UNROLL_TRANSFORM
+
+/* Unrolled SHA-256 round macros: */
+
+#if !APR_IS_BIGENDIAN
+
+#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h)       \
+        REVERSE32(*data++, W256[j]); \
+        T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \
+             K256[j] + W256[j]; \
+        (d) += T1; \
+        (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
+        j++
+
+
+#else /* APR_IS_BIGENDIAN */
+
+#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h)       \
+        T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \
+             K256[j] + (W256[j] = *data++); \
+        (d) += T1; \
+        (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
+        j++
+
+#endif /* APR_IS_BIGENDIAN */
+
+#define ROUND256(a,b,c,d,e,f,g,h)       \
+        s0 = W256[(j+1)&0x0f]; \
+        s0 = sigma0_256(s0); \
+        s1 = W256[(j+14)&0x0f]; \
+        s1 = sigma1_256(s1); \
+        T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + K256[j] + \
+             (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \
+        (d) += T1; \
+        (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
+        j++
+
+void apr__SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) {
+        sha2_word32     a, b, c, d, e, f, g, h, s0, s1;
+        sha2_word32     T1, *W256;
+        int             j;
+
+        W256 = (sha2_word32*)context->buffer;
+
+        /* Initialize registers with the prev. intermediate value */
+        a = context->state[0];
+        b = context->state[1];
+        c = context->state[2];
+        d = context->state[3];
+        e = context->state[4];
+        f = context->state[5];
+        g = context->state[6];
+        h = context->state[7];
+
+        j = 0;
+        do {
+                /* Rounds 0 to 15 (unrolled): */
+                ROUND256_0_TO_15(a,b,c,d,e,f,g,h);
+                ROUND256_0_TO_15(h,a,b,c,d,e,f,g);
+                ROUND256_0_TO_15(g,h,a,b,c,d,e,f);
+                ROUND256_0_TO_15(f,g,h,a,b,c,d,e);
+                ROUND256_0_TO_15(e,f,g,h,a,b,c,d);
+                ROUND256_0_TO_15(d,e,f,g,h,a,b,c);
+                ROUND256_0_TO_15(c,d,e,f,g,h,a,b);
+                ROUND256_0_TO_15(b,c,d,e,f,g,h,a);
+        } while (j < 16);
+
+        /* Now for the remaining rounds to 64: */
+        do {
+                ROUND256(a,b,c,d,e,f,g,h);
+                ROUND256(h,a,b,c,d,e,f,g);
+                ROUND256(g,h,a,b,c,d,e,f);
+                ROUND256(f,g,h,a,b,c,d,e);
+                ROUND256(e,f,g,h,a,b,c,d);
+                ROUND256(d,e,f,g,h,a,b,c);
+                ROUND256(c,d,e,f,g,h,a,b);
+                ROUND256(b,c,d,e,f,g,h,a);
+        } while (j < 64);
+
+        /* Compute the current intermediate hash value */
+        context->state[0] += a;
+        context->state[1] += b;
+        context->state[2] += c;
+        context->state[3] += d;
+        context->state[4] += e;
+        context->state[5] += f;
+        context->state[6] += g;
+        context->state[7] += h;
+
+        /* Clean up */
+        a = b = c = d = e = f = g = h = T1 = 0;
+}
+
+#else /* SHA2_UNROLL_TRANSFORM */
+
+void apr__SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) {
+        sha2_word32     a, b, c, d, e, f, g, h, s0, s1;
+        sha2_word32     T1, T2, *W256;
+        int             j;
+
+        W256 = (sha2_word32*)context->buffer;
+
+        /* Initialize registers with the prev. intermediate value */
+        a = context->state[0];
+        b = context->state[1];
+        c = context->state[2];
+        d = context->state[3];
+        e = context->state[4];
+        f = context->state[5];
+        g = context->state[6];
+        h = context->state[7];
+
+        j = 0;
+        do {
+#if !APR_IS_BIGENDIAN
+                /* Copy data while converting to host byte order */
+                REVERSE32(*data++,W256[j]);
+                /* Apply the SHA-256 compression function to update a..h */
+                T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j];
+#else /* APR_IS_BIGENDIAN */
+                /* Apply the SHA-256 compression function to update a..h with copy */
+                T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j] = *data++);
+#endif /* APR_IS_BIGENDIAN */
+                T2 = Sigma0_256(a) + Maj(a, b, c);
+                h = g;
+                g = f;
+                f = e;
+                e = d + T1;
+                d = c;
+                c = b;
+                b = a;
+                a = T1 + T2;
+
+                j++;
+        } while (j < 16);
+
+        do {
+                /* Part of the message block expansion: */
+                s0 = W256[(j+1)&0x0f];
+                s0 = sigma0_256(s0);
+                s1 = W256[(j+14)&0x0f]; 
+                s1 = sigma1_256(s1);
+
+                /* Apply the SHA-256 compression function to update a..h */
+                T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + 
+                     (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0);
+                T2 = Sigma0_256(a) + Maj(a, b, c);
+                h = g;
+                g = f;
+                f = e;
+                e = d + T1;
+                d = c;
+                c = b;
+                b = a;
+                a = T1 + T2;
+
+                j++;
+        } while (j < 64);
+
+        /* Compute the current intermediate hash value */
+        context->state[0] += a;
+        context->state[1] += b;
+        context->state[2] += c;
+        context->state[3] += d;
+        context->state[4] += e;
+        context->state[5] += f;
+        context->state[6] += g;
+        context->state[7] += h;
+
+        /* Clean up */
+        a = b = c = d = e = f = g = h = T1 = T2 = 0;
+}
+
+#endif /* SHA2_UNROLL_TRANSFORM */
+
+void apr__SHA256_Update(SHA256_CTX* context, const sha2_byte *data, size_t len) {
+        unsigned int    freespace, usedspace;
+
+        if (len == 0) {
+                /* Calling with no data is valid - we do nothing */
+                return;
+        }
+
+        /* Sanity check: */
+        assert(context != (SHA256_CTX*)0 && data != (sha2_byte*)0);
+
+        usedspace = (unsigned int)((context->bitcount >> 3) 
+                                 % SHA256_BLOCK_LENGTH);
+        if (usedspace > 0) {
+                /* Calculate how much free space is available in the buffer */
+                freespace = SHA256_BLOCK_LENGTH - usedspace;
+
+                if (len >= freespace) {
+                        /* Fill the buffer completely and process it */
+                        MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace);
+                        context->bitcount += freespace << 3;
+                        len -= freespace;
+                        data += freespace;
+                        apr__SHA256_Transform(context, (sha2_word32*)context->buffer);
+                } else {
+                        /* The buffer is not yet full */
+                        MEMCPY_BCOPY(&context->buffer[usedspace], data, len);
+                        context->bitcount += len << 3;
+                        /* Clean up: */
+                        usedspace = freespace = 0;
+                        return;
+                }
+        }
+        while (len >= SHA256_BLOCK_LENGTH) {
+                /* Process as many complete blocks as we can */
+                apr__SHA256_Transform(context, (sha2_word32*)data);
+                context->bitcount += SHA256_BLOCK_LENGTH << 3;
+                len -= SHA256_BLOCK_LENGTH;
+                data += SHA256_BLOCK_LENGTH;
+        }
+        if (len > 0) {
+                /* There's left-overs, so save 'em */
+                MEMCPY_BCOPY(context->buffer, data, len);
+                context->bitcount += len << 3;
+        }
+        /* Clean up: */
+        usedspace = freespace = 0;
+}
+
+void apr__SHA256_Final(sha2_byte digest[], SHA256_CTX* context) {
+        sha2_word32     *d = (sha2_word32*)digest;
+        unsigned int    usedspace;
+
+        /* Sanity check: */
+        assert(context != (SHA256_CTX*)0);
+
+        /* If no digest buffer is passed, we don't bother doing this: */
+        if (digest != (sha2_byte*)0) {
+                usedspace = (unsigned int)((context->bitcount >> 3) 
+                                         % SHA256_BLOCK_LENGTH);
+#if !APR_IS_BIGENDIAN
+                /* Convert FROM host byte order */
+                REVERSE64(context->bitcount,context->bitcount);
+#endif
+                if (usedspace > 0) {
+                        /* Begin padding with a 1 bit: */
+                        context->buffer[usedspace++] = 0x80;
+
+                        if (usedspace <= SHA256_SHORT_BLOCK_LENGTH) {
+                                /* Set-up for the last transform: */
+                                MEMSET_BZERO(&context->buffer[usedspace], SHA256_SHORT_BLOCK_LENGTH - usedspace);
+                        } else {
+                                if (usedspace < SHA256_BLOCK_LENGTH) {
+                                        MEMSET_BZERO(&context->buffer[usedspace], SHA256_BLOCK_LENGTH - usedspace);
+                                }
+                                /* Do second-to-last transform: */
+                                apr__SHA256_Transform(context, (sha2_word32*)context->buffer);
+
+                                /* And set-up for the last transform: */
+                                MEMSET_BZERO(context->buffer, SHA256_SHORT_BLOCK_LENGTH);
+                        }
+                } else {
+                        /* Set-up for the last transform: */
+                        MEMSET_BZERO(context->buffer, SHA256_SHORT_BLOCK_LENGTH);
+
+                        /* Begin padding with a 1 bit: */
+                        *context->buffer = 0x80;
+                }
+                /* Set the bit count: */
+                {
+                        union dummy {
+                                apr_uint64_t bitcount;
+                                apr_byte_t bytes[8];
+                        } bitcount;
+                        bitcount.bitcount = context->bitcount;
+                        MEMCPY_BCOPY(&context->buffer[SHA256_SHORT_BLOCK_LENGTH], bitcount.bytes, 8);
+                }
+
+                /* Final transform: */
+                apr__SHA256_Transform(context, (sha2_word32*)context->buffer);
+
+#if !APR_IS_BIGENDIAN
+                {
+                        /* Convert TO host byte order */
+                        int     j;
+                        for (j = 0; j < 8; j++) {
+                                REVERSE32(context->state[j],context->state[j]);
+                                *d++ = context->state[j];
+                        }
+                }
+#else
+                MEMCPY_BCOPY(d, context->state, SHA256_DIGEST_LENGTH);
+#endif
+        }
+
+        /* Clean up state data: */
+        MEMSET_BZERO(context, sizeof(*context));
+        usedspace = 0;
+}
+
+char *apr__SHA256_End(SHA256_CTX* context, char buffer[]) {
+        sha2_byte       digest[SHA256_DIGEST_LENGTH], *d = digest;
+        int             i;
+
+        /* Sanity check: */
+        assert(context != (SHA256_CTX*)0);
+
+        if (buffer != (char*)0) {
+                apr__SHA256_Final(digest, context);
+
+                for (i = 0; i < SHA256_DIGEST_LENGTH; i++) {
+                        *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
+                        *buffer++ = sha2_hex_digits[*d & 0x0f];
+                        d++;
+                }
+                *buffer = (char)0;
+        } else {
+                MEMSET_BZERO(context, sizeof(*context));
+        }
+        MEMSET_BZERO(digest, SHA256_DIGEST_LENGTH);
+        return buffer;
+}
+
+char* apr__SHA256_Data(const sha2_byte* data, size_t len, char digest[SHA256_DIGEST_STRING_LENGTH]) {
+        SHA256_CTX      context;
+
+        apr__SHA256_Init(&context);
+        apr__SHA256_Update(&context, data, len);
+        return apr__SHA256_End(&context, digest);
+}
diff --git a/random/unix/sha2.h b/random/unix/sha2.h
new file mode 100644
index 00000000000..0a030d7dbae
--- /dev/null
+++ b/random/unix/sha2.h
@@ -0,0 +1,59 @@
+/* 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:        sha2.h
+ * AUTHOR:      Aaron D. Gifford <me@aarongifford.com>
+ * 
+ * A licence was granted to the ASF by Aaron on 4 November 2003.
+ */
+
+#ifndef __SHA2_H__
+#define __SHA2_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "apr.h"
+
+/*** SHA-256 Various Length Definitions ***********************/
+#define SHA256_BLOCK_LENGTH             64
+#define SHA256_DIGEST_LENGTH            32
+#define SHA256_DIGEST_STRING_LENGTH     (SHA256_DIGEST_LENGTH * 2 + 1)
+
+
+/*** SHA-256/384/512 Context Structures *******************************/
+typedef struct _SHA256_CTX {
+        apr_uint32_t    state[8];
+        apr_uint64_t    bitcount;
+        apr_byte_t      buffer[SHA256_BLOCK_LENGTH];
+} SHA256_CTX;
+
+
+/*** SHA-256/384/512 Function Prototypes ******************************/
+void apr__SHA256_Init(SHA256_CTX *);
+void apr__SHA256_Update(SHA256_CTX *, const apr_byte_t *, size_t);
+void apr__SHA256_Final(apr_byte_t [SHA256_DIGEST_LENGTH], SHA256_CTX *);
+char* apr__SHA256_End(SHA256_CTX *, char [SHA256_DIGEST_STRING_LENGTH]);
+char* apr__SHA256_Data(const apr_byte_t *, size_t,
+                  char [SHA256_DIGEST_STRING_LENGTH]);
+                  
+#ifdef  __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __SHA2_H__ */
+
diff --git a/random/unix/sha2_glue.c b/random/unix/sha2_glue.c
new file mode 100644
index 00000000000..cb6e897802f
--- /dev/null
+++ b/random/unix/sha2_glue.c
@@ -0,0 +1,49 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <apr.h>
+#include <apr_random.h>
+#include <apr_pools.h>
+#include "sha2.h"
+
+static void sha256_init(apr_crypto_hash_t *h)
+{
+    apr__SHA256_Init(h->data);
+}
+
+static void sha256_add(apr_crypto_hash_t *h,const void *data,
+                       apr_size_t bytes)
+{
+    apr__SHA256_Update(h->data,data,bytes);
+}
+
+static void sha256_finish(apr_crypto_hash_t *h,unsigned char *result)
+{
+    apr__SHA256_Final(result,h->data);
+}
+
+APR_DECLARE(apr_crypto_hash_t *) apr_crypto_sha256_new(apr_pool_t *p)
+{
+    apr_crypto_hash_t *h=apr_palloc(p,sizeof *h);
+
+    h->data=apr_palloc(p,sizeof(SHA256_CTX));
+    h->init=sha256_init;
+    h->add=sha256_add;
+    h->finish=sha256_finish;
+    h->size=256/8;
+
+    return h;
+}
diff --git a/redis/apr_redis.c b/redis/apr_redis.c
new file mode 100644
index 00000000000..77692736619
--- /dev/null
+++ b/redis/apr_redis.c
@@ -0,0 +1,1548 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_redis.h"
+#include "apr_poll.h"
+#include "apr_version.h"
+#include <stdlib.h>
+#include <string.h>
+
+#define BUFFER_SIZE  512
+#define LILBUFF_SIZE 64
+struct apr_redis_conn_t
+{
+    char *buffer;
+    apr_size_t blen;
+    apr_pool_t *p;
+    apr_pool_t *tp;
+    apr_socket_t *sock;
+    apr_bucket_brigade *bb;
+    apr_bucket_brigade *tb;
+    apr_redis_server_t *rs;
+};
+
+/* Strings for Client Commands */
+
+#define RC_EOL "\r\n"
+#define RC_EOL_LEN (sizeof(RC_EOL)-1)
+
+#define RC_WS " "
+#define RC_WS_LEN (sizeof(RC_WS)-1)
+
+#define RC_RESP_1 "*1\r\n"
+#define RC_RESP_1_LEN (sizeof(RC_RESP_1)-1)
+
+#define RC_RESP_2 "*2\r\n"
+#define RC_RESP_2_LEN (sizeof(RC_RESP_2)-1)
+
+#define RC_RESP_3 "*3\r\n"
+#define RC_RESP_3_LEN (sizeof(RC_RESP_3)-1)
+
+#define RC_RESP_4 "*4\r\n"
+#define RC_RESP_4_LEN (sizeof(RC_RESP_4)-1)
+
+#define RC_GET "GET\r\n"
+#define RC_GET_LEN (sizeof(RC_GET)-1)
+
+#define RC_GET_SIZE "$3\r\n"
+#define RC_GET_SIZE_LEN (sizeof(RC_GET_SIZE)-1)
+
+#define RC_SET "SET\r\n"
+#define RC_SET_LEN (sizeof(RC_SET)-1)
+
+#define RC_SET_SIZE "$3\r\n"
+#define RC_SET_SIZE_LEN (sizeof(RC_SET_SIZE)-1)
+
+#define RC_SETEX "SETEX\r\n"
+#define RC_SETEX_LEN (sizeof(RC_SETEX)-1)
+
+#define RC_SETEX_SIZE "$5\r\n"
+#define RC_SETEX_SIZE_LEN (sizeof(RC_SETEX_SIZE)-1)
+
+#define RC_DEL "DEL\r\n"
+#define RC_DEL_LEN (sizeof(RC_DEL)-1)
+
+#define RC_DEL_SIZE "$3\r\n"
+#define RC_DEL_SIZE_LEN (sizeof(RC_DEL_SIZE)-1)
+
+#define RC_QUIT "QUIT\r\n"
+#define RC_QUIT_LEN (sizeof(RC_QUIT)-1)
+
+#define RC_QUIT_SIZE "$4\r\n"
+#define RC_QUIT_SIZE_LEN (sizeof(RC_QUIT_SIZE)-1)
+
+#define RC_PING "PING\r\n"
+#define RC_PING_LEN (sizeof(RC_PING)-1)
+
+#define RC_PING_SIZE "$4\r\n"
+#define RC_PING_SIZE_LEN (sizeof(RC_PING_SIZE)-1)
+
+#define RC_INFO "INFO\r\n"
+#define RC_INFO_LEN (sizeof(RC_INFO)-1)
+
+#define RC_INFO_SIZE "$4\r\n"
+#define RC_INFO_SIZE_LEN (sizeof(RC_INFO_SIZE)-1)
+
+/* Strings for Server Replies */
+
+#define RS_STORED "+OK"
+#define RS_STORED_LEN (sizeof(RS_STORED)-1)
+
+#define RS_NOT_STORED "$-1"
+#define RS_NOT_STORED_LEN (sizeof(RS_NOT_STORED)-1)
+
+#define RS_DELETED ":1"
+#define RS_DELETED_LEN (sizeof(RS_DELETED)-1)
+
+#define RS_NOT_FOUND_GET "$-1"
+#define RS_NOT_FOUND_GET_LEN (sizeof(RS_NOT_FOUND_GET)-1)
+
+#define RS_NOT_FOUND_DEL ":0"
+#define RS_NOT_FOUND_DEL_LEN (sizeof(RS_NOT_FOUND_DEL)-1)
+
+#define RS_TYPE_STRING "$"
+#define RS_TYPE_STRING_LEN (sizeof(RS_TYPE_STRING)-1)
+
+#define RS_END "\r\n"
+#define RS_END_LEN (sizeof(RS_END)-1)
+
+static apr_status_t make_server_dead(apr_redis_t *rc,
+                                     apr_redis_server_t *rs)
+{
+#if APR_HAS_THREADS
+    apr_thread_mutex_lock(rs->lock);
+#endif
+    rs->status = APR_RC_SERVER_DEAD;
+    rs->btime = apr_time_now();
+#if APR_HAS_THREADS
+    apr_thread_mutex_unlock(rs->lock);
+#endif
+    return APR_SUCCESS;
+}
+
+static apr_status_t make_server_live(apr_redis_t *rc,
+                                     apr_redis_server_t *rs)
+{
+    rs->status = APR_RC_SERVER_LIVE;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_redis_add_server(apr_redis_t *rc,
+                                               apr_redis_server_t *rs)
+{
+    apr_status_t rv = APR_SUCCESS;
+
+    if (rc->ntotal >= rc->nalloc) {
+        return APR_ENOMEM;
+    }
+    rc->live_servers[rc->ntotal] = rs;
+    rc->ntotal++;
+    make_server_live(rc, rs);
+    return rv;
+}
+
+APR_DECLARE(apr_redis_server_t *)
+apr_redis_find_server_hash(apr_redis_t *rc, const apr_uint32_t hash)
+{
+    if (rc->server_func) {
+        return rc->server_func(rc->server_baton, rc, hash);
+    }
+    else {
+        return apr_redis_find_server_hash_default(NULL, rc, hash);
+    }
+}
+
+APR_DECLARE(apr_redis_server_t *)
+apr_redis_find_server_hash_default(void *baton, apr_redis_t *rc,
+                                   const apr_uint32_t hash)
+{
+    apr_redis_server_t *rs = NULL;
+    apr_uint32_t h = hash ? hash : 1;
+    apr_uint32_t i = 0;
+    apr_time_t curtime = 0;
+
+    if (rc->ntotal == 0) {
+        return NULL;
+    }
+
+    do {
+        rs = rc->live_servers[h % rc->ntotal];
+        if (rs->status == APR_RC_SERVER_LIVE) {
+            break;
+        }
+        else {
+            if (curtime == 0) {
+                curtime = apr_time_now();
+            }
+#if APR_HAS_THREADS
+            apr_thread_mutex_lock(rs->lock);
+#endif
+            /* Try the dead server, every 5 seconds */
+            if (curtime - rs->btime > apr_time_from_sec(5)) {
+                rs->btime = curtime;
+                if (apr_redis_ping(rs) == APR_SUCCESS) {
+                    make_server_live(rc, rs);
+#if APR_HAS_THREADS
+                    apr_thread_mutex_unlock(rs->lock);
+#endif
+                    break;
+                }
+            }
+#if APR_HAS_THREADS
+            apr_thread_mutex_unlock(rs->lock);
+#endif
+        }
+        h++;
+        i++;
+    } while (i < rc->ntotal);
+
+    if (i == rc->ntotal) {
+        rs = NULL;
+    }
+
+    return rs;
+}
+
+APR_DECLARE(apr_redis_server_t *) apr_redis_find_server(apr_redis_t *rc,
+                                                        const char *host,
+                                                        apr_port_t port)
+{
+    int i;
+
+    for (i = 0; i < rc->ntotal; i++) {
+        if (strcmp(rc->live_servers[i]->host, host) == 0
+            && rc->live_servers[i]->port == port) {
+
+            return rc->live_servers[i];
+        }
+    }
+
+    return NULL;
+}
+
+static apr_status_t rs_find_conn(apr_redis_server_t *rs,
+                                 apr_redis_conn_t ** conn)
+{
+    apr_status_t rv;
+    apr_bucket_alloc_t *balloc;
+    apr_bucket *e;
+
+#if APR_HAS_THREADS
+    rv = apr_reslist_acquire(rs->conns, (void **) conn);
+#else
+    *conn = rs->conn;
+    rv = APR_SUCCESS;
+#endif
+
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
+    balloc = apr_bucket_alloc_create((*conn)->tp);
+    (*conn)->bb = apr_brigade_create((*conn)->tp, balloc);
+    (*conn)->tb = apr_brigade_create((*conn)->tp, balloc);
+
+    e = apr_bucket_socket_create((*conn)->sock, balloc);
+    APR_BRIGADE_INSERT_TAIL((*conn)->bb, e);
+
+    return rv;
+}
+
+static apr_status_t rs_bad_conn(apr_redis_server_t *rs,
+                                apr_redis_conn_t *conn)
+{
+#if APR_HAS_THREADS
+    return apr_reslist_invalidate(rs->conns, conn);
+#else
+    return APR_SUCCESS;
+#endif
+}
+
+static apr_status_t rs_release_conn(apr_redis_server_t *rs,
+                                    apr_redis_conn_t *conn)
+{
+    apr_pool_clear(conn->tp);
+#if APR_HAS_THREADS
+    return apr_reslist_release(rs->conns, conn);
+#else
+    return APR_SUCCESS;
+#endif
+}
+
+APR_DECLARE(apr_status_t) apr_redis_enable_server(apr_redis_t *rc,
+                                                  apr_redis_server_t *rs)
+{
+    apr_status_t rv = APR_SUCCESS;
+
+    if (rs->status == APR_RC_SERVER_LIVE) {
+        return rv;
+    }
+    rv = make_server_live(rc, rs);
+    return rv;
+}
+
+APR_DECLARE(apr_status_t) apr_redis_disable_server(apr_redis_t *rc,
+                                                   apr_redis_server_t *rs)
+{
+    return make_server_dead(rc, rs);
+}
+
+static apr_status_t conn_connect(apr_redis_conn_t *conn)
+{
+    apr_status_t rv = APR_SUCCESS;
+    apr_sockaddr_t *sa;
+#if APR_HAVE_SOCKADDR_UN
+    apr_int32_t family = conn->rs->host[0] != '/' ? APR_INET : APR_UNIX;
+#else
+    apr_int32_t family = APR_INET;
+#endif
+
+    rv = apr_sockaddr_info_get(&sa, conn->rs->host, family, conn->rs->port, 0,
+                               conn->p);
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
+    rv = apr_socket_timeout_set(conn->sock, 1 * APR_USEC_PER_SEC);
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
+    rv = apr_socket_connect(conn->sock, sa);
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
+    rv = apr_socket_timeout_set(conn->sock,
+                                conn->rs->rwto * APR_USEC_PER_SEC);
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
+    return rv;
+}
+
+static apr_status_t
+rc_conn_construct(void **conn_, void *params, apr_pool_t *pool)
+{
+    apr_status_t rv = APR_SUCCESS;
+    apr_redis_conn_t *conn;
+    apr_pool_t *np;
+    apr_pool_t *tp;
+    apr_redis_server_t *rs = params;
+#if APR_HAVE_SOCKADDR_UN
+    apr_int32_t family = rs->host[0] != '/' ? APR_INET : APR_UNIX;
+#else
+    apr_int32_t family = APR_INET;
+#endif
+
+    rv = apr_pool_create(&np, pool);
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
+    rv = apr_pool_create(&tp, np);
+    if (rv != APR_SUCCESS) {
+        apr_pool_destroy(np);
+        return rv;
+    }
+
+    conn = apr_palloc(np, sizeof(apr_redis_conn_t));
+
+    conn->p = np;
+    conn->tp = tp;
+
+    rv = apr_socket_create(&conn->sock, family, SOCK_STREAM, 0, np);
+
+    if (rv != APR_SUCCESS) {
+        apr_pool_destroy(np);
+        return rv;
+    }
+
+    conn->buffer = apr_palloc(conn->p, BUFFER_SIZE + 1);
+    conn->blen = 0;
+    conn->rs = rs;
+
+    rv = conn_connect(conn);
+    if (rv != APR_SUCCESS) {
+        apr_pool_destroy(np);
+    }
+    else {
+        *conn_ = conn;
+    }
+
+    return rv;
+}
+
+#if APR_HAS_THREADS
+static apr_status_t
+rc_conn_destruct(void *conn_, void *params, apr_pool_t *pool)
+{
+    apr_redis_conn_t *conn = (apr_redis_conn_t *) conn_;
+    struct iovec vec[3];
+    apr_size_t written;
+
+    /* send a quit message to the Redis server to be nice about it. */
+
+    /*
+     * RESP Command:
+     *   *1
+     *   $4
+     *   QUIT
+     */
+    vec[0].iov_base = RC_RESP_1;
+    vec[0].iov_len = RC_RESP_1_LEN;
+
+    vec[1].iov_base = RC_QUIT_SIZE;
+    vec[1].iov_len = RC_QUIT_SIZE_LEN;
+
+    vec[2].iov_base = RC_QUIT;
+    vec[2].iov_len = RC_QUIT_LEN;
+
+    /* Return values not checked, since we just want to make it go away. */
+    apr_socket_sendv(conn->sock, vec, 3, &written);
+    apr_socket_close(conn->sock);
+
+    apr_pool_destroy(conn->p);
+
+    return APR_SUCCESS;
+}
+#endif
+
+APR_DECLARE(apr_status_t) apr_redis_server_create(apr_pool_t *p,
+                                                  const char *host,
+                                                  apr_port_t port,
+                                                  apr_uint32_t min,
+                                                  apr_uint32_t smax,
+                                                  apr_uint32_t max,
+                                                  apr_uint32_t ttl,
+                                                  apr_uint32_t rwto,
+                                                  apr_redis_server_t **rs)
+{
+    apr_status_t rv = APR_SUCCESS;
+    apr_redis_server_t *server;
+    apr_pool_t *np;
+
+    rv = apr_pool_create(&np, p);
+
+    server = apr_palloc(np, sizeof(apr_redis_server_t));
+
+    server->p = np;
+    server->host = apr_pstrdup(np, host);
+    server->port = port;
+    server->status = APR_RC_SERVER_DEAD;
+    server->rwto = rwto;
+    server->version.major = 0;
+    server->version.minor = 0;
+    server->version.patch = 0;
+
+#if APR_HAS_THREADS
+    rv = apr_thread_mutex_create(&server->lock, APR_THREAD_MUTEX_DEFAULT, np);
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
+    rv = apr_reslist_create(&server->conns,
+                            min,        /* hard minimum */
+                            smax,       /* soft maximum */
+                            max,        /* hard maximum */
+                            ttl,        /* Time to live */
+                            rc_conn_construct,  /* Make a New Connection */
+                            rc_conn_destruct,   /* Kill Old Connection */
+                            server, np);
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
+    apr_reslist_cleanup_order_set(server->conns, APR_RESLIST_CLEANUP_FIRST);
+#else
+    rv = rc_conn_construct((void **) &(server->conn), server, np);
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+#endif
+
+    *rs = server;
+
+    return rv;
+}
+
+APR_DECLARE(apr_status_t) apr_redis_create(apr_pool_t *p,
+                                           apr_uint16_t max_servers,
+                                           apr_uint32_t flags,
+                                           apr_redis_t **redis)
+{
+    apr_status_t rv = APR_SUCCESS;
+    apr_redis_t *rc;
+
+    rc = apr_palloc(p, sizeof(apr_redis_t));
+    rc->p = p;
+    rc->nalloc = max_servers;
+    rc->ntotal = 0;
+    rc->live_servers =
+        apr_palloc(p, rc->nalloc * sizeof(struct apr_redis_server_t *));
+    rc->hash_func = NULL;
+    rc->hash_baton = NULL;
+    rc->server_func = NULL;
+    rc->server_baton = NULL;
+    *redis = rc;
+    return rv;
+}
+
+
+/* The crc32 functions and data was originally written by Spencer
+ * Garrett <srg@quick.com> and was gleaned from the PostgreSQL source
+ * tree via the files contrib/ltree/crc32.[ch] and from FreeBSD at
+ * src/usr.bin/cksum/crc32.c.
+ */
+
+static const apr_uint32_t crc32tab[256] = {
+    0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
+    0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+    0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+    0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+    0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+    0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+    0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+    0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+    0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+    0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+    0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
+    0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+    0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
+    0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+    0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+    0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+    0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
+    0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+    0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
+    0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+    0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+    0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+    0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
+    0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+    0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+    0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+    0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+    0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+    0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
+    0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+    0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
+    0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+    0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+    0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+    0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+    0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+    0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
+    0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+    0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+    0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+    0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
+    0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+    0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
+    0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+    0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+    0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+    0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
+    0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+    0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+    0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+    0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+    0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+    0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
+    0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+    0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+    0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+    0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+    0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+    0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
+    0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+    0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
+    0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+    0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+    0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
+};
+
+APR_DECLARE(apr_uint32_t) apr_redis_hash_crc32(void *baton,
+                                               const char *data,
+                                               const apr_size_t data_len)
+{
+    apr_uint32_t i;
+    apr_uint32_t crc;
+    crc = ~0;
+
+    for (i = 0; i < data_len; i++)
+        crc = (crc >> 8) ^ crc32tab[(crc ^ (data[i])) & 0xff];
+
+    return ~crc;
+}
+
+APR_DECLARE(apr_uint32_t) apr_redis_hash_default(void *baton,
+                                                 const char *data,
+                                                 const apr_size_t data_len)
+{
+    /* The default Perl Client doesn't actually use just crc32 -- it shifts it again
+     * like this....
+     */
+    return ((apr_redis_hash_crc32(baton, data, data_len) >> 16) & 0x7fff);
+}
+
+APR_DECLARE(apr_uint32_t) apr_redis_hash(apr_redis_t *rc,
+                                         const char *data,
+                                         const apr_size_t data_len)
+{
+    if (rc->hash_func) {
+        return rc->hash_func(rc->hash_baton, data, data_len);
+    }
+    else {
+        return apr_redis_hash_default(NULL, data, data_len);
+    }
+}
+
+static apr_status_t get_server_line(apr_redis_conn_t *conn)
+{
+    apr_size_t bsize = BUFFER_SIZE;
+    apr_status_t rv = APR_SUCCESS;
+
+    rv = apr_brigade_split_line(conn->tb, conn->bb, APR_BLOCK_READ,
+            BUFFER_SIZE);
+
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
+    rv = apr_brigade_flatten(conn->tb, conn->buffer, &bsize);
+
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
+    conn->blen = bsize;
+    conn->buffer[bsize] = '\0';
+
+    return apr_brigade_cleanup(conn->tb);
+}
+
+APR_DECLARE(apr_status_t) apr_redis_set(apr_redis_t *rc,
+                                        const char *key,
+                                        char *data,
+                                        const apr_size_t data_size,
+                                        apr_uint16_t flags)
+{
+    apr_uint32_t hash;
+    apr_redis_server_t *rs;
+    apr_redis_conn_t *conn;
+    apr_status_t rv;
+    apr_size_t written;
+    struct iovec vec[9];
+    char keysize_str[LILBUFF_SIZE];
+    char datasize_str[LILBUFF_SIZE];
+    apr_size_t len, klen;
+
+    klen = strlen(key);
+    hash = apr_redis_hash(rc, key, klen);
+
+    rs = apr_redis_find_server_hash(rc, hash);
+
+    if (rs == NULL)
+        return APR_NOTFOUND;
+
+    rv = rs_find_conn(rs, &conn);
+
+    if (rv != APR_SUCCESS) {
+        apr_redis_disable_server(rc, rs);
+        return rv;
+    }
+
+    /*
+     * RESP Command:
+     *   *3
+     *   $3
+     *   SET
+     *   $<keylen>
+     *   key
+     *   $<datalen>
+     *   data
+     */
+
+    vec[0].iov_base = RC_RESP_3;
+    vec[0].iov_len = RC_RESP_3_LEN;
+
+    vec[1].iov_base = RC_SET_SIZE;
+    vec[1].iov_len = RC_SET_SIZE_LEN;
+
+    vec[2].iov_base = RC_SET;
+    vec[2].iov_len = RC_SET_LEN;
+
+    len = apr_snprintf(keysize_str, LILBUFF_SIZE, "$%" APR_SIZE_T_FMT "\r\n", klen);
+    vec[3].iov_base = keysize_str;
+    vec[3].iov_len = len;
+
+    vec[4].iov_base = (void *) key;
+    vec[4].iov_len = klen;
+
+    vec[5].iov_base = RC_EOL;
+    vec[5].iov_len = RC_EOL_LEN;
+
+    len = apr_snprintf(datasize_str, LILBUFF_SIZE, "$%" APR_SIZE_T_FMT "\r\n",
+                     data_size);
+    vec[6].iov_base = datasize_str;
+    vec[6].iov_len = len;
+
+    vec[7].iov_base = data;
+    vec[7].iov_len = data_size;
+
+    vec[8].iov_base = RC_EOL;
+    vec[8].iov_len = RC_EOL_LEN;
+
+    rv = apr_socket_sendv(conn->sock, vec, 9, &written);
+
+    if (rv != APR_SUCCESS) {
+        rs_bad_conn(rs, conn);
+        apr_redis_disable_server(rc, rs);
+        return rv;
+    }
+
+    rv = get_server_line(conn);
+    if (rv != APR_SUCCESS) {
+        rs_bad_conn(rs, conn);
+        apr_redis_disable_server(rc, rs);
+        return rv;
+    }
+
+    if (strcmp(conn->buffer, RS_STORED RC_EOL) == 0) {
+        rv = APR_SUCCESS;
+    }
+    else if (strcmp(conn->buffer, RS_NOT_STORED RC_EOL) == 0) {
+        rv = APR_EEXIST;
+    }
+    else {
+        rv = APR_EGENERAL;
+    }
+
+    rs_release_conn(rs, conn);
+    return rv;
+}
+
+APR_DECLARE(apr_status_t) apr_redis_setex(apr_redis_t *rc,
+                                          const char *key,
+                                          char *data,
+                                          const apr_size_t data_size,
+                                          apr_uint32_t timeout,
+                                          apr_uint16_t flags)
+{
+    apr_uint32_t hash;
+    apr_redis_server_t *rs;
+    apr_redis_conn_t *conn;
+    apr_status_t rv;
+    apr_size_t written;
+    struct iovec vec[11];
+    char keysize_str[LILBUFF_SIZE];
+    char expire_str[LILBUFF_SIZE];
+    char expiresize_str[LILBUFF_SIZE];
+    char datasize_str[LILBUFF_SIZE];
+    apr_size_t len, klen, expire_len;
+
+
+    klen = strlen(key);
+    hash = apr_redis_hash(rc, key, klen);
+
+    rs = apr_redis_find_server_hash(rc, hash);
+
+    if (rs == NULL)
+        return APR_NOTFOUND;
+
+    rv = rs_find_conn(rs, &conn);
+
+    if (rv != APR_SUCCESS) {
+        apr_redis_disable_server(rc, rs);
+        return rv;
+    }
+
+    /*
+     * RESP Command:
+     *   *4
+     *   $5
+     *   SETEX
+     *   $<keylen>
+     *   key
+     *   $<expirelen>
+     *   expirey
+     *   $<datalen>
+     *   data
+     */
+
+    vec[0].iov_base = RC_RESP_4;
+    vec[0].iov_len = RC_RESP_4_LEN;
+
+    vec[1].iov_base = RC_SETEX_SIZE;
+    vec[1].iov_len = RC_SETEX_SIZE_LEN;
+
+    vec[2].iov_base = RC_SETEX;
+    vec[2].iov_len = RC_SETEX_LEN;
+
+    len = apr_snprintf(keysize_str, LILBUFF_SIZE, "$%" APR_SIZE_T_FMT "\r\n", klen);
+    vec[3].iov_base = keysize_str;
+    vec[3].iov_len = len;
+
+    vec[4].iov_base = (void *) key;
+    vec[4].iov_len = klen;
+
+    vec[5].iov_base = RC_EOL;
+    vec[5].iov_len = RC_EOL_LEN;
+
+    expire_len = apr_snprintf(expire_str, LILBUFF_SIZE, "%u\r\n", timeout);
+    len = apr_snprintf(expiresize_str, LILBUFF_SIZE, "$%" APR_SIZE_T_FMT "\r\n",
+                     expire_len - 2);
+    vec[6].iov_base = (void *) expiresize_str;
+    vec[6].iov_len = len;
+
+    vec[7].iov_base = (void *) expire_str;
+    vec[7].iov_len = expire_len;
+
+    len = apr_snprintf(datasize_str, LILBUFF_SIZE, "$%" APR_SIZE_T_FMT "\r\n",
+                     data_size);
+    vec[8].iov_base = datasize_str;
+    vec[8].iov_len = len;
+
+    vec[9].iov_base = data;
+    vec[9].iov_len = data_size;
+
+    vec[10].iov_base = RC_EOL;
+    vec[10].iov_len = RC_EOL_LEN;
+
+    rv = apr_socket_sendv(conn->sock, vec, 11, &written);
+
+    if (rv != APR_SUCCESS) {
+        rs_bad_conn(rs, conn);
+        apr_redis_disable_server(rc, rs);
+        return rv;
+    }
+
+    rv = get_server_line(conn);
+    if (rv != APR_SUCCESS) {
+        rs_bad_conn(rs, conn);
+        apr_redis_disable_server(rc, rs);
+        return rv;
+    }
+
+    if (strcmp(conn->buffer, RS_STORED RC_EOL) == 0) {
+        rv = APR_SUCCESS;
+    }
+    else if (strcmp(conn->buffer, RS_NOT_STORED RC_EOL) == 0) {
+        rv = APR_EEXIST;
+    }
+    else {
+        rv = APR_EGENERAL;
+    }
+
+    rs_release_conn(rs, conn);
+    return rv;
+}
+
+static apr_status_t grab_bulk_resp(apr_redis_server_t *rs, apr_redis_t *rc,
+                                   apr_redis_conn_t *conn, apr_pool_t *p,
+                                   char **baton, apr_size_t *new_length)
+{
+    char *length;
+    char *last;
+    apr_status_t rv;
+    apr_size_t len = 0;
+    *new_length = 0;
+
+    length = apr_strtok(conn->buffer + 1, " ", &last);
+    if (length) {
+        len = strtol(length, (char **) NULL, 10);
+    }
+
+    if (len == 0) {
+        *new_length = 0;
+        *baton = NULL;
+    }
+    else {
+        apr_bucket_brigade *bbb;
+        apr_bucket *e;
+
+        /* eat the trailing \r\n */
+        rv = apr_brigade_partition(conn->bb, len + 2, &e);
+
+        if (rv != APR_SUCCESS) {
+            rs_bad_conn(rs, conn);
+            if (rc)
+                apr_redis_disable_server(rc, rs);
+            return rv;
+        }
+
+        bbb = apr_brigade_split(conn->bb, e);
+
+        rv = apr_brigade_pflatten(conn->bb, baton, &len, p);
+
+        if (rv != APR_SUCCESS) {
+            rs_bad_conn(rs, conn);
+            if (rc)
+                apr_redis_disable_server(rc, rs);
+            return rv;
+        }
+
+        rv = apr_brigade_destroy(conn->bb);
+        if (rv != APR_SUCCESS) {
+            rs_bad_conn(rs, conn);
+            if (rc)
+                apr_redis_disable_server(rc, rs);
+            return rv;
+        }
+
+        conn->bb = bbb;
+
+        *new_length = len - 2;
+        (*baton)[*new_length] = '\0';
+    }
+    return APR_SUCCESS;
+
+}
+
+APR_DECLARE(apr_status_t) apr_redis_getp(apr_redis_t *rc,
+                                         apr_pool_t *p,
+                                         const char *key,
+                                         char **baton,
+                                         apr_size_t *new_length,
+                                         apr_uint16_t *flags)
+{
+    apr_status_t rv;
+    apr_redis_server_t *rs;
+    apr_redis_conn_t *conn;
+    apr_uint32_t hash;
+    apr_size_t written;
+    apr_size_t len, klen;
+    struct iovec vec[6];
+    char keysize_str[LILBUFF_SIZE];
+
+    klen = strlen(key);
+    hash = apr_redis_hash(rc, key, klen);
+    rs = apr_redis_find_server_hash(rc, hash);
+
+    if (rs == NULL)
+        return APR_NOTFOUND;
+
+    rv = rs_find_conn(rs, &conn);
+
+    if (rv != APR_SUCCESS) {
+        apr_redis_disable_server(rc, rs);
+        return rv;
+    }
+
+    /*
+     * RESP Command:
+     *   *2
+     *   $3
+     *   GET
+     *   $<keylen>
+     *   key
+     */
+    vec[0].iov_base = RC_RESP_2;
+    vec[0].iov_len = RC_RESP_2_LEN;
+
+    vec[1].iov_base = RC_GET_SIZE;
+    vec[1].iov_len = RC_GET_SIZE_LEN;
+
+    vec[2].iov_base = RC_GET;
+    vec[2].iov_len = RC_GET_LEN;
+
+    len = apr_snprintf(keysize_str, LILBUFF_SIZE, "$%" APR_SIZE_T_FMT "\r\n",
+                     klen);
+    vec[3].iov_base = keysize_str;
+    vec[3].iov_len = len;
+
+    vec[4].iov_base = (void *) key;
+    vec[4].iov_len = klen;
+
+    vec[5].iov_base = RC_EOL;
+    vec[5].iov_len = RC_EOL_LEN;
+
+    rv = apr_socket_sendv(conn->sock, vec, 6, &written);
+
+
+    if (rv != APR_SUCCESS) {
+        rs_bad_conn(rs, conn);
+        apr_redis_disable_server(rc, rs);
+        return rv;
+    }
+
+    rv = get_server_line(conn);
+    if (rv != APR_SUCCESS) {
+        rs_bad_conn(rs, conn);
+        apr_redis_disable_server(rc, rs);
+        return rv;
+    }
+    if (strncmp(RS_NOT_FOUND_GET, conn->buffer, RS_NOT_FOUND_GET_LEN) == 0) {
+        rv = APR_NOTFOUND;
+    }
+    else if (strncmp(RS_TYPE_STRING, conn->buffer, RS_TYPE_STRING_LEN) == 0) {
+        rv = grab_bulk_resp(rs, rc, conn, p, baton, new_length);
+    }
+    else {
+        rv = APR_EGENERAL;
+    }
+
+    rs_release_conn(rs, conn);
+    return rv;
+}
+
+APR_DECLARE(apr_status_t)
+    apr_redis_delete(apr_redis_t *rc, const char *key, apr_uint32_t timeout)
+{
+    apr_status_t rv;
+    apr_redis_server_t *rs;
+    apr_redis_conn_t *conn;
+    apr_uint32_t hash;
+    apr_size_t written;
+    struct iovec vec[6];
+    apr_size_t len, klen;
+    char keysize_str[LILBUFF_SIZE];
+
+    klen = strlen(key);
+    hash = apr_redis_hash(rc, key, klen);
+    rs = apr_redis_find_server_hash(rc, hash);
+    if (rs == NULL)
+        return APR_NOTFOUND;
+
+    rv = rs_find_conn(rs, &conn);
+
+    if (rv != APR_SUCCESS) {
+        apr_redis_disable_server(rc, rs);
+        return rv;
+    }
+
+    /*
+     * RESP Command:
+     *   *2
+     *   $3
+     *   DEL
+     *   $<keylen>
+     *   key
+     */
+    vec[0].iov_base = RC_RESP_2;
+    vec[0].iov_len = RC_RESP_2_LEN;
+
+    vec[1].iov_base = RC_DEL_SIZE;
+    vec[1].iov_len = RC_DEL_SIZE_LEN;
+
+    vec[2].iov_base = RC_DEL;
+    vec[2].iov_len = RC_DEL_LEN;
+
+    len = apr_snprintf(keysize_str, LILBUFF_SIZE, "$%" APR_SIZE_T_FMT "\r\n",
+                     klen);
+    vec[3].iov_base = keysize_str;
+    vec[3].iov_len = len;
+
+    vec[4].iov_base = (void *) key;
+    vec[4].iov_len = klen;
+
+    vec[5].iov_base = RC_EOL;
+    vec[5].iov_len = RC_EOL_LEN;
+
+    rv = apr_socket_sendv(conn->sock, vec, 6, &written);
+
+    if (rv != APR_SUCCESS) {
+        rs_bad_conn(rs, conn);
+        apr_redis_disable_server(rc, rs);
+        return rv;
+    }
+
+    rv = get_server_line(conn);
+    if (rv != APR_SUCCESS) {
+        rs_bad_conn(rs, conn);
+        apr_redis_disable_server(rc, rs);
+        return rv;
+    }
+
+    if (strncmp(RS_DELETED, conn->buffer, RS_DELETED_LEN) == 0) {
+        rv = APR_SUCCESS;
+    }
+    else if (strncmp(RS_NOT_FOUND_DEL, conn->buffer, RS_NOT_FOUND_DEL_LEN) == 0) {
+        rv = APR_NOTFOUND;
+    }
+    else {
+        rv = APR_EGENERAL;
+    }
+
+    rs_release_conn(rs, conn);
+    return rv;
+}
+
+APR_DECLARE(apr_status_t)
+apr_redis_ping(apr_redis_server_t *rs)
+{
+    apr_status_t rv;
+    apr_size_t written;
+    struct iovec vec[3];
+    apr_redis_conn_t *conn;
+
+    rv = rs_find_conn(rs, &conn);
+
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
+    /*
+     * RESP Command:
+     *   *1
+     *   $4
+     *   PING
+     */
+    vec[0].iov_base = RC_RESP_1;
+    vec[0].iov_len = RC_RESP_1_LEN;
+
+    vec[1].iov_base = RC_PING_SIZE;
+    vec[1].iov_len = RC_PING_SIZE_LEN;
+
+    vec[2].iov_base = RC_PING;
+    vec[2].iov_len = RC_PING_LEN;
+
+    rv = apr_socket_sendv(conn->sock, vec, 3, &written);
+
+    if (rv != APR_SUCCESS) {
+        rs_bad_conn(rs, conn);
+        return rv;
+    }
+
+    rv = get_server_line(conn);
+    if (rv == APR_SUCCESS) {
+        /* we got *something*. Was it Redis? */
+        if (strncmp(conn->buffer, "+PONG", sizeof("+PONG")-1) != 0) {
+            rv = APR_EGENERAL;
+        }
+    }
+    rs_release_conn(rs, conn);
+    return rv;
+}
+
+APR_DECLARE(apr_status_t)
+apr_redis_info(apr_redis_server_t *rs, apr_pool_t *p, char **baton)
+{
+    apr_status_t rv;
+    apr_redis_conn_t *conn;
+    apr_size_t written;
+    struct iovec vec[3];
+
+    rv = rs_find_conn(rs, &conn);
+
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
+    /*
+     * RESP Command:
+     *   *1
+     *   $4
+     *   INFO
+     */
+    vec[0].iov_base = RC_RESP_1;
+    vec[0].iov_len = RC_RESP_1_LEN;
+
+    vec[1].iov_base = RC_INFO_SIZE;
+    vec[1].iov_len = RC_INFO_SIZE_LEN;
+
+    vec[2].iov_base = RC_INFO;
+    vec[2].iov_len = RC_INFO_LEN;
+
+    rv = apr_socket_sendv(conn->sock, vec, 3, &written);
+
+    if (rv != APR_SUCCESS) {
+        rs_bad_conn(rs, conn);
+        return rv;
+    }
+
+    rv = get_server_line(conn);
+    if (rv != APR_SUCCESS) {
+        rs_bad_conn(rs, conn);
+        return rv;
+    }
+
+    if (strncmp(RS_TYPE_STRING, conn->buffer, RS_TYPE_STRING_LEN) == 0) {
+        apr_size_t nl;
+        rv = grab_bulk_resp(rs, NULL, conn, p, baton, &nl);
+    } else {
+        rs_bad_conn(rs, conn);
+        rv = APR_EGENERAL;
+    }
+
+    rs_release_conn(rs, conn);
+    return rv;
+}
+
+#define RV_FIELD "redis_version:"
+APR_DECLARE(apr_status_t)
+apr_redis_version(apr_redis_server_t *rs, apr_pool_t *p, char **baton)
+{
+    apr_status_t rv;
+    char *ptr, *eptr;
+    apr_pool_t *subpool;
+
+    /* Have we already obtained the version number? */
+    if (rs->version.minor != 0) {
+        if (baton)
+            *baton = apr_pstrdup(p, rs->version.number);
+        return APR_SUCCESS;
+    }
+    if (apr_pool_create(&subpool, p) != APR_SUCCESS) {
+        /* well, we tried */
+        subpool = p;
+    }
+    rv = apr_redis_info(rs, subpool, baton);
+
+    if (rv != APR_SUCCESS) {
+        if (subpool != p) {
+            apr_pool_destroy(subpool);
+        }
+        return rv;
+    }
+
+    ptr = strstr(*baton, RV_FIELD);
+    if (ptr) {
+        rs->version.major = strtol(ptr + sizeof(RV_FIELD) - 1, &eptr, 10);
+        ptr = eptr + 1;
+        rs->version.minor = strtol(ptr, &eptr, 10);
+        ptr = eptr + 1;
+        rs->version.patch = strtol(ptr, &eptr, 10);
+        rs->version.number = apr_psprintf(rs->p, "%d.%d.%d",
+                rs->version.major, rs->version.minor,
+                rs->version.patch);
+    }
+    if (baton)
+        *baton = apr_pstrdup(p, rs->version.number);
+    if (subpool != p) {
+        apr_pool_destroy(subpool);
+    }
+    return APR_SUCCESS;
+}
+
+static apr_status_t plus_minus(apr_redis_t *rc,
+                    int incr,
+                    const char *key,
+                    apr_int32_t inc,
+                    apr_uint32_t *new_value)
+{
+    apr_status_t rv;
+    apr_redis_server_t *rs;
+    apr_redis_conn_t *conn;
+    apr_uint32_t hash;
+    apr_size_t written;
+    apr_size_t len, klen;
+    struct iovec vec[12];
+    char keysize_str[LILBUFF_SIZE];
+    char inc_str[LILBUFF_SIZE];
+    char inc_str_len[LILBUFF_SIZE];
+    int i = 0;
+
+    klen = strlen(key);
+    hash = apr_redis_hash(rc, key, klen);
+    rs = apr_redis_find_server_hash(rc, hash);
+    if (rs == NULL)
+        return APR_NOTFOUND;
+
+    rv = rs_find_conn(rs, &conn);
+
+    if (rv != APR_SUCCESS) {
+        apr_redis_disable_server(rc, rs);
+        return rv;
+    }
+
+    /*
+     * RESP Command:
+     *   *2|*3
+     *   $4|$6
+     *   INCR/DECR|INCRBY/DECRBY
+     *   $<keylen>
+     *   key
+     *   <:inc>
+     */
+    if (inc == 1) {
+        vec[i].iov_base = RC_RESP_2;
+        vec[i].iov_len = RC_RESP_2_LEN;
+        i++;
+
+        vec[i].iov_base = "$4\r\n";
+        vec[i].iov_len = sizeof("$4\r\n")-1;
+        i++;
+
+        if (incr)
+            vec[i].iov_base = "INCR\r\n";
+        else
+            vec[i].iov_base = "DECR\r\n";
+        vec[i].iov_len = sizeof("INCR\r\n")-1;
+        i++;
+    }
+    else {
+        vec[i].iov_base = RC_RESP_3;
+        vec[i].iov_len = RC_RESP_3_LEN;
+        i++;
+
+        vec[i].iov_base = "$6\r\n";
+        vec[i].iov_len = sizeof("$6\r\n")-1;
+        i++;
+
+       if (incr)
+            vec[i].iov_base = "INCRBY\r\n";
+        else
+            vec[i].iov_base = "DECRBY\r\n";
+        vec[i].iov_len = sizeof("INCRBY\r\n")-1;
+        i++;
+    }
+
+    len = apr_snprintf(keysize_str, LILBUFF_SIZE, "$%" APR_SIZE_T_FMT "\r\n",
+                     klen);
+    vec[i].iov_base = keysize_str;
+    vec[i].iov_len = len;
+    i++;
+
+    vec[i].iov_base = (void *) key;
+    vec[i].iov_len = klen;
+    i++;
+
+    vec[i].iov_base = RC_EOL;
+    vec[i].iov_len = RC_EOL_LEN;
+    i++;
+
+    if (inc != 1) {
+        len = apr_snprintf(inc_str, LILBUFF_SIZE, "%d\r\n", inc);
+        klen = apr_snprintf(inc_str_len, LILBUFF_SIZE, "$%d\r\n", (int)(len-2));
+        vec[i].iov_base = inc_str_len;
+        vec[i].iov_len = klen;
+        i++;
+
+        vec[i].iov_base = inc_str;
+        vec[i].iov_len = len;
+        i++;
+
+        vec[i].iov_base = RC_EOL;
+        vec[i].iov_len = RC_EOL_LEN;
+        i++;
+    }
+
+    rv = apr_socket_sendv(conn->sock, vec, i, &written);
+
+    if (rv != APR_SUCCESS) {
+        rs_bad_conn(rs, conn);
+        apr_redis_disable_server(rc, rs);
+        return rv;
+    }
+
+    rv = get_server_line(conn);
+    if (rv != APR_SUCCESS) {
+        rs_bad_conn(rs, conn);
+        apr_redis_disable_server(rc, rs);
+        return rv;
+    }
+    if (strncmp(RS_NOT_FOUND_GET, conn->buffer, RS_NOT_FOUND_GET_LEN) == 0) {
+        rv = APR_NOTFOUND;
+    }
+    else if (*conn->buffer == ':') {
+        *new_value = atoi((const char *)(conn->buffer + 1));
+        rv = APR_SUCCESS;
+    }
+    else {
+        rv = APR_EGENERAL;
+    }
+    rs_release_conn(rs, conn);
+    return rv;
+}
+
+APR_DECLARE(apr_status_t)
+apr_redis_incr(apr_redis_t *rc, const char *key, apr_int32_t inc, apr_uint32_t *new_value)
+{
+    return plus_minus(rc, 1, key, inc, new_value);
+}
+
+APR_DECLARE(apr_status_t)
+apr_redis_decr(apr_redis_t *rc, const char *key, apr_int32_t inc, apr_uint32_t *new_value)
+{
+    return plus_minus(rc, 0, key, inc, new_value);
+}
+
+APR_DECLARE(apr_status_t)
+apr_redis_multgetp(apr_redis_t *rc,
+                   apr_pool_t *temp_pool,
+                   apr_pool_t *data_pool,
+                   apr_hash_t *values)
+{
+    return APR_ENOTIMPL;
+}
+
+/**
+ * Define all of the strings for stats
+ */
+
+#define STAT_process_id "process_id:"
+#define STAT_process_id_LEN (sizeof(STAT_process_id)-1)
+
+#define STAT_uptime_in_seconds "uptime_in_seconds:"
+#define STAT_uptime_in_seconds_LEN (sizeof(STAT_uptime_in_seconds)-1)
+
+#define STAT_arch_bits "arch_bits:"
+#define STAT_arch_bits_LEN (sizeof(STAT_arch_bits)-1)
+
+#define STAT_connected_clients "connected_clients:"
+#define STAT_connected_clients_LEN (sizeof(STAT_connected_clients)-1)
+
+#define STAT_blocked_clients "blocked_clients:"
+#define STAT_blocked_clients_LEN (sizeof(STAT_blocked_clients)-1)
+
+#define STAT_maxmemory "maxmemory:"
+#define STAT_maxmemory_LEN (sizeof(STAT_maxmemory)-1)
+
+#define STAT_used_memory "used_memory:"
+#define STAT_used_memory_LEN (sizeof(STAT_used_memory)-1)
+
+#define STAT_total_system_memory "total_system_memory:"
+#define STAT_total_system_memory_LEN (sizeof(STAT_total_system_memory)-1)
+
+#define STAT_total_connections_received "total_connections_received:"
+#define STAT_total_connections_received_LEN (sizeof(STAT_total_connections_received)-1)
+
+#define STAT_total_commands_processed "total_commands_processed:"
+#define STAT_total_commands_processed_LEN (sizeof(STAT_total_commands_processed)-1)
+
+#define STAT_rejected_connections "rejected_connections:"
+#define STAT_rejected_connections_LEN (sizeof(STAT_rejected_connections)-1)
+
+#define STAT_total_net_input_bytes "total_net_input_bytes:"
+#define STAT_total_net_input_bytes_LEN (sizeof(STAT_total_net_input_bytes)-1)
+
+#define STAT_total_net_output_bytes "total_net_output_bytes:"
+#define STAT_total_net_output_bytes_LEN (sizeof(STAT_total_net_output_bytes)-1)
+
+#define STAT_keyspace_hits "keyspace_hits:"
+#define STAT_keyspace_hits_LEN (sizeof(STAT_keyspace_hits)-1)
+
+#define STAT_keyspace_misses "keyspace_misses:"
+#define STAT_keyspace_misses_LEN (sizeof(STAT_keyspace_misses)-1)
+
+#define STAT_connected_slaves "connected_slaves:"
+#define STAT_connected_slaves_LEN (sizeof(STAT_connected_slaves)-1)
+
+#define STAT_used_cpu_sys "used_cpu_sys:"
+#define STAT_used_cpu_sys_LEN (sizeof(STAT_used_cpu_sys)-1)
+
+#define STAT_used_cpu_user "used_cpu_user:"
+#define STAT_used_cpu_user_LEN (sizeof(STAT_used_cpu_user)-1)
+
+#define STAT_cluster_enabled "cluster_enabled:"
+#define STAT_cluster_enabled_LEN (sizeof(STAT_cluster_enabled)-1)
+
+static apr_uint32_t stat_read_uint32( char *buf)
+{
+    return atoi(buf);
+}
+
+static apr_uint64_t stat_read_uint64(char *buf)
+{
+    return apr_atoi64(buf);
+}
+
+#define rc_do_stat(name, type) \
+    if ((ptr = strstr(info , STAT_ ## name )) != NULL ) { \
+        char *str = ptr + (STAT_ ## name ## _LEN ); \
+        stats-> name = stat_read_ ## type (str); \
+    }
+
+static void update_stats(char *info, apr_redis_stats_t *stats)
+{
+    char *ptr;
+
+    rc_do_stat(process_id, uint32);
+    rc_do_stat(uptime_in_seconds, uint32);
+    rc_do_stat(arch_bits, uint32);
+    rc_do_stat(connected_clients, uint32);
+    rc_do_stat(blocked_clients, uint32);
+    rc_do_stat(maxmemory, uint64);
+    rc_do_stat(used_memory, uint64);
+    rc_do_stat(total_system_memory, uint64);
+    rc_do_stat(total_connections_received, uint64);
+    rc_do_stat(total_commands_processed, uint64);
+    rc_do_stat(rejected_connections, uint64);
+    rc_do_stat(total_net_input_bytes, uint64);
+    rc_do_stat(total_net_output_bytes, uint64);
+    rc_do_stat(keyspace_hits, uint64);
+    rc_do_stat(keyspace_misses, uint64);
+    rc_do_stat(connected_slaves, uint32);
+    rc_do_stat(used_cpu_sys, uint32);
+    rc_do_stat(used_cpu_user, uint32);
+    rc_do_stat(cluster_enabled, uint32);
+}
+
+APR_DECLARE(apr_status_t)
+apr_redis_stats(apr_redis_server_t *rs,
+                apr_pool_t *p,
+                apr_redis_stats_t **stats)
+{
+    apr_status_t rv;
+    char *info;
+    apr_pool_t *subpool;
+    apr_redis_stats_t *ret;
+    char *ptr;
+
+    if (apr_pool_create(&subpool, p) != APR_SUCCESS) {
+        /* well, we tried */
+        subpool = p;
+    }
+    rv = apr_redis_info(rs, subpool, &info);
+
+    if (rv != APR_SUCCESS) {
+        if (subpool != p) {
+            apr_pool_destroy(subpool);
+        }
+        return rv;
+    }
+    ret = apr_pcalloc(p, sizeof(apr_redis_stats_t));
+    /* Get the bulk of the stats */
+    update_stats(info, ret);
+
+    /* Now the version number */
+    if (rs->version.major != 0) {
+        ret->major = rs->version.major;
+        ret->minor = rs->version.minor;
+        ret->patch = rs->version.patch;
+    }
+    else {
+        char *eptr;
+        ptr = strstr(info, RV_FIELD);
+        if (ptr) {
+            ret->major = rs->version.major = strtol(ptr + sizeof(RV_FIELD) - 1, &eptr, 10);
+            ptr = eptr + 1;
+            ret->minor = rs->version.minor = strtol(ptr, &eptr, 10);
+            ptr = eptr + 1;
+            ret->patch = rs->version.patch = strtol(ptr, &eptr, 10);
+        }
+    }
+
+    /* Finally, the role */
+    ptr = strstr(info, "role:");
+    if (!ptr) {
+        ret->role = APR_RS_SERVER_UNKNOWN;
+    }
+    else if (!strncmp("master", ptr + sizeof("role:") - 1, sizeof("master")-1)) {
+        ret->role = APR_RS_SERVER_MASTER;
+    }
+    else {
+        ret->role = APR_RS_SERVER_SLAVE;
+    }
+    if (stats) {
+        *stats = ret;
+    }
+
+    return APR_SUCCESS;
+}
diff --git a/shmem/beos/shm.c b/shmem/beos/shm.c
new file mode 100644
index 00000000000..fcd7c84d1e6
--- /dev/null
+++ b/shmem/beos/shm.c
@@ -0,0 +1,195 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_general.h"
+#include "apr_shm.h"
+#include "apr_errno.h"
+#include "apr_lib.h"
+#include "apr_strings.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <kernel/OS.h>
+#include "apr_portable.h"
+
+struct apr_shm_t {
+    apr_pool_t *pool;
+    void *memblock;
+    void *ptr;
+    apr_size_t reqsize;
+    apr_size_t avail;
+    area_id aid;
+};
+
+APR_DECLARE(apr_status_t) apr_shm_create(apr_shm_t **m, 
+                                         apr_size_t reqsize, 
+                                         const char *filename, 
+                                         apr_pool_t *p)
+{
+    apr_size_t pagesize;
+    area_id newid;
+    char *addr;
+    char shname[B_OS_NAME_LENGTH];
+    
+    (*m) = (apr_shm_t *)apr_pcalloc(p, sizeof(apr_shm_t));
+    /* we MUST allocate in pages, so calculate how big an area we need... */
+    pagesize = ((reqsize + B_PAGE_SIZE - 1) / B_PAGE_SIZE) * B_PAGE_SIZE;
+     
+    if (!filename) {
+        int num = 0;
+        snprintf(shname, B_OS_NAME_LENGTH, "apr_shmem_%ld", find_thread(NULL));
+        while (find_area(shname) >= 0)
+            snprintf(shname, B_OS_NAME_LENGTH, "apr_shmem_%ld_%d",
+                     find_thread(NULL), num++);
+    }
+    newid = create_area(filename ? filename : shname, 
+                        (void*)&addr, B_ANY_ADDRESS,
+                        pagesize, B_LAZY_LOCK, B_READ_AREA|B_WRITE_AREA);
+
+    if (newid < 0)
+        return errno;
+
+    (*m)->pool = p;
+    (*m)->aid = newid;
+    (*m)->memblock = addr;
+    (*m)->ptr = (void*)addr;
+    (*m)->avail = pagesize; /* record how big an area we actually created... */
+    (*m)->reqsize = reqsize;
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_shm_create_ex(apr_shm_t **m, 
+                                            apr_size_t reqsize, 
+                                            const char *filename, 
+                                            apr_pool_t *p,
+                                            apr_int32_t flags)
+{
+    return apr_shm_create(m, reqsize, filename, p);
+}
+
+APR_DECLARE(apr_status_t) apr_shm_destroy(apr_shm_t *m)
+{
+    delete_area(m->aid);
+    m->avail = 0;
+    m->memblock = NULL;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_shm_remove(const char *filename,
+                                         apr_pool_t *pool)
+{
+    area_id deleteme = find_area(filename);
+    
+    if (deleteme == B_NAME_NOT_FOUND)
+        return APR_EINVAL;
+
+    delete_area(deleteme);
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_shm_delete(apr_shm_t *m)
+{
+    if (m->filename) {
+        return apr_shm_remove(m->filename, m->pool);
+    }
+    else {
+        return APR_ENOTIMPL;
+    }
+} 
+
+APR_DECLARE(apr_status_t) apr_shm_attach(apr_shm_t **m,
+                                         const char *filename,
+                                         apr_pool_t *pool)
+{
+    area_info ai;
+    thread_info ti;
+    apr_shm_t *new_m;
+    area_id deleteme = find_area(filename);
+
+    if (deleteme == B_NAME_NOT_FOUND)
+        return APR_EINVAL;
+
+    new_m = (apr_shm_t*)apr_palloc(pool, sizeof(apr_shm_t*));
+    if (new_m == NULL)
+        return APR_ENOMEM;
+    new_m->pool = pool;
+
+    get_area_info(deleteme, &ai);
+    get_thread_info(find_thread(NULL), &ti);
+
+    if (ti.team != ai.team) {
+        area_id narea;
+        
+        narea = clone_area(ai.name, &(ai.address), B_CLONE_ADDRESS,
+                           B_READ_AREA|B_WRITE_AREA, ai.area);
+
+        if (narea < B_OK)
+            return narea;
+            
+        get_area_info(narea, &ai);
+        new_m->aid = narea;
+        new_m->memblock = ai.address;
+        new_m->ptr = (void*)ai.address;
+        new_m->avail = ai.size;
+        new_m->reqsize = ai.size;
+    }
+
+    (*m) = new_m;
+    
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_shm_attach_ex(apr_shm_t **m,
+                                            const char *filename,
+                                            apr_pool_t *pool,
+                                            apr_int32_t flags)
+{
+    return apr_shm_attach(m, filename, pool);
+}
+
+APR_DECLARE(apr_status_t) apr_shm_detach(apr_shm_t *m)
+{
+    delete_area(m->aid);
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(void *) apr_shm_baseaddr_get(const apr_shm_t *m)
+{
+    return m->memblock;
+}
+
+APR_DECLARE(apr_size_t) apr_shm_size_get(const apr_shm_t *m)
+{
+    return m->reqsize;
+}
+
+APR_PERMS_SET_ENOTIMPL(shm)
+
+APR_POOL_IMPLEMENT_ACCESSOR(shm)
+
+APR_DECLARE(apr_status_t) apr_os_shm_get(apr_os_shm_t *osshm,
+                                         apr_shm_t *shm)
+{
+    return APR_ENOTIMPL;
+}
+
+APR_DECLARE(apr_status_t) apr_os_shm_put(apr_shm_t **m,
+                                         apr_os_shm_t *osshm,
+                                         apr_pool_t *pool)
+{
+    return APR_ENOTIMPL;
+}    
+
diff --git a/shmem/os2/.cvsignore b/shmem/os2/.cvsignore
deleted file mode 100644
index f3c7a7c5da6..00000000000
--- a/shmem/os2/.cvsignore
+++ /dev/null
@@ -1 +0,0 @@
-Makefile
diff --git a/shmem/os2/Makefile.in b/shmem/os2/Makefile.in
deleted file mode 100644
index 5e25e40384e..00000000000
--- a/shmem/os2/Makefile.in
+++ /dev/null
@@ -1,58 +0,0 @@
-#CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
-#LIBS=$(EXTRA_LIBS) $(LIBS1)
-#INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
-#LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
-
-CC=@CC@
-RANLIB=@RANLIB@
-CFLAGS=@CFLAGS@ @OPTIM@
-LIBS=@LIBS@
-LDFLAGS=@LDFLAGS@ $(LIBS)
-INCDIR=../../inc
-INCDIR1=../../include
-INCDIR2=../../file_io/os2
-INCLUDES=-I$(INCDIR) -I$(INCDIR1) -I$(INCDIR2) -I.
-
-LIB=shmem.a
-
-OBJS=shmem.o
-
-.c.o:
-	$(CC) $(CFLAGS) -c $(INCLUDES) $<
-
-all: $(LIB)
-
-clean:
-	$(RM) -f *.o *.a *.so
-
-distclean: clean
-	-$(RM) -f Makefile
-
-$(OBJS): Makefile
-
-$(LIB): $(OBJS)
-	$(RM) -f $@
-	$(AR) cr $@ $(OBJS)
-	$(RANLIB) $@
-
-#
-# We really don't expect end users to use this rule.  It works only with
-# gcc, and rebuilds Makefile.tmpl.  You have to re-run Configure after
-# using it.
-#
-depend:
-	cp Makefile.in Makefile.in.bak \
-	    && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.in > Makefile.new \
-	    && gcc -MM $(INCLUDES) $(CFLAGS) *.c | sed -e "s%\\\\\(.\)%/\\1%g" >> Makefile.new \
-	    && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
-                   -e '1,$$s: $(INCDIR1)/: $$(INCDIR1)/:g' \
-                   -e '1,$$s: $(INCDIR2)/: $$(INCDIR2)/:g' \
-	           -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
-		> Makefile.in \
-	    && rm Makefile.new
-
-# DO NOT REMOVE
-shmem.o: shmem.c $(INCDIR1)/apr_general.h $(INCDIR1)/apr.h \
- $(INCDIR1)/apr_errno.h $(INCDIR1)/apr_shmem.h \
- $(INCDIR1)/apr_lib.h $(INCDIR1)/apr_file_io.h \
- $(INCDIR1)/apr_time.h $(INCDIR1)/apr_thread_proc.h
diff --git a/shmem/os2/shm.c b/shmem/os2/shm.c
new file mode 100644
index 00000000000..b6ef7811aea
--- /dev/null
+++ b/shmem/os2/shm.c
@@ -0,0 +1,168 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_general.h"
+#include "apr_shm.h"
+#include "apr_errno.h"
+#include "apr_lib.h"
+#include "apr_strings.h"
+#include "apr_portable.h"
+
+struct apr_shm_t {
+    apr_pool_t *pool;
+    void *memblock;
+};
+
+APR_DECLARE(apr_status_t) apr_shm_create(apr_shm_t **m,
+                                         apr_size_t reqsize,
+                                         const char *filename,
+                                         apr_pool_t *pool)
+{
+    int rc;
+    apr_shm_t *newm = (apr_shm_t *)apr_palloc(pool, sizeof(apr_shm_t));
+    char *name = NULL;
+    ULONG flags = PAG_COMMIT|PAG_READ|PAG_WRITE;
+
+    newm->pool = pool;
+
+    if (filename) {
+        name = apr_pstrcat(pool, "\\SHAREMEM\\", filename, NULL);
+    }
+
+    if (name == NULL) {
+        flags |= OBJ_GETTABLE;
+    }
+
+    rc = DosAllocSharedMem(&(newm->memblock), name, reqsize, flags);
+
+    if (rc) {
+        return APR_FROM_OS_ERROR(rc);
+    }
+
+    *m = newm;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_shm_create_ex(apr_shm_t **m, 
+                                            apr_size_t reqsize, 
+                                            const char *filename, 
+                                            apr_pool_t *p,
+                                            apr_int32_t flags)
+{
+    return apr_shm_create(m, reqsize, filename, p);
+}
+
+APR_DECLARE(apr_status_t) apr_shm_destroy(apr_shm_t *m)
+{
+    DosFreeMem(m->memblock);
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_shm_remove(const char *filename,
+                                         apr_pool_t *pool)
+{
+    return APR_ENOTIMPL;
+}
+
+APR_DECLARE(apr_status_t) apr_shm_delete(apr_shm_t *m)
+{
+    return APR_ENOTIMPL;
+} 
+
+APR_DECLARE(apr_status_t) apr_shm_attach(apr_shm_t **m,
+                                         const char *filename,
+                                         apr_pool_t *pool)
+{
+    int rc;
+    apr_shm_t *newm = (apr_shm_t *)apr_palloc(pool, sizeof(apr_shm_t));
+    char *name = NULL;
+    ULONG flags = PAG_READ|PAG_WRITE;
+
+    newm->pool = pool;
+    name = apr_pstrcat(pool, "\\SHAREMEM\\", filename, NULL);
+
+    rc = DosGetNamedSharedMem(&(newm->memblock), name, flags);
+
+    if (rc) {
+        return APR_FROM_OS_ERROR(rc);
+    }
+
+    *m = newm;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_shm_attach_ex(apr_shm_t **m,
+                                            const char *filename,
+                                            apr_pool_t *pool,
+                                            apr_int32_t flags)
+{
+    return apr_shm_attach(m, filename, pool);
+}
+
+APR_DECLARE(apr_status_t) apr_shm_detach(apr_shm_t *m)
+{
+    int rc = 0;
+
+    if (m->memblock) {
+        rc = DosFreeMem(m->memblock);
+    }
+
+    return APR_FROM_OS_ERROR(rc);
+}
+
+APR_DECLARE(void *) apr_shm_baseaddr_get(const apr_shm_t *m)
+{
+    return m->memblock;
+}
+
+APR_DECLARE(apr_size_t) apr_shm_size_get(const apr_shm_t *m)
+{
+    ULONG flags, size = 0x1000000;
+    DosQueryMem(m->memblock, &size, &flags);
+    return size;
+}
+
+APR_PERMS_SET_ENOTIMPL(shm)
+
+APR_POOL_IMPLEMENT_ACCESSOR(shm)
+
+APR_DECLARE(apr_status_t) apr_os_shm_get(apr_os_shm_t *osshm,
+                                         apr_shm_t *shm)
+{
+    *osshm = shm->memblock;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_os_shm_put(apr_shm_t **m,
+                                         apr_os_shm_t *osshm,
+                                         apr_pool_t *pool)
+{
+    int rc;
+    apr_shm_t *newm = (apr_shm_t *)apr_palloc(pool, sizeof(apr_shm_t));
+    ULONG flags = PAG_COMMIT|PAG_READ|PAG_WRITE;
+
+    newm->pool = pool;
+
+    rc = DosGetSharedMem(&(newm->memblock), flags);
+
+    if (rc) {
+        return APR_FROM_OS_ERROR(rc);
+    }
+
+    *m = newm;
+    return APR_SUCCESS;
+}    
+
diff --git a/shmem/os2/shmem.c b/shmem/os2/shmem.c
deleted file mode 100644
index 364f1941501..00000000000
--- a/shmem/os2/shmem.c
+++ /dev/null
@@ -1,158 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "apr_general.h"
-#include "apr_shmem.h"
-#include "apr_errno.h"
-#include "apr_lib.h"
-#include <umalloc.h>
-#include <stdlib.h>
-#define INCL_DOS
-#include <os2.h>
-
-struct shmem_t {
-    void *memblock;
-    Heap_t heap;
-};
-
-
-
-ap_status_t ap_shm_init(struct shmem_t **m, ap_size_t reqsize, const char *file, ap_pool_t *cont)
-{
-    int rc;
-    struct shmem_t *newm = (struct shmem_t *)ap_palloc(cont, sizeof(struct shmem_t));
-    char *name = NULL;
-
-    if (file)
-        name = ap_pstrcat(cont, "\\SHAREMEM\\", file, NULL);
-
-    rc = DosAllocSharedMem(&(newm->memblock), name, reqsize, PAG_COMMIT|OBJ_GETTABLE|PAG_READ|PAG_WRITE);
-
-    if (rc)
-        return APR_OS2_STATUS(rc);
-
-    newm->heap = _ucreate(newm->memblock, reqsize, !_BLOCK_CLEAN, _HEAP_REGULAR|_HEAP_SHARED, NULL, NULL);
-    _uopen(newm->heap);
-    *m = newm;
-    return APR_SUCCESS;
-}
-
-
-
-ap_status_t ap_shm_destroy(struct shmem_t *m)
-{
-    _uclose(m->heap);
-    _udestroy(m->heap, _FORCE);
-    DosFreeMem(m->memblock);
-    return APR_SUCCESS;
-}
-
-
-
-void *ap_shm_malloc(struct shmem_t *m, ap_size_t reqsize)
-{
-    return _umalloc(m->heap, reqsize);
-}
-
-
-
-void *ap_shm_calloc(struct shmem_t *m, ap_size_t size)
-{
-    return _ucalloc(m->heap, size, 1);
-}
-
-
-
-ap_status_t ap_shm_free(struct shmem_t *m, void *entity)
-{
-    free(entity);
-    return APR_SUCCESS;
-}
-
-
-
-ap_status_t ap_get_shm_name(ap_shmem_t *c, ap_shm_name_t **name)
-{
-    return APR_ANONYMOUS;
-}
-
-
-
-ap_status_t ap_set_shm_name(ap_shmem_t *c, ap_shm_name_t *name)
-{
-    return APR_ANONYMOUS;
-}
-
-
-
-ap_status_t ap_open_shmem(struct shmem_t *m)
-{
-    int rc;
-
-    rc = DosGetSharedMem(m->memblock, PAG_READ|PAG_WRITE);
-
-    if (rc)
-        return APR_OS2_STATUS(rc);
-
-    _uopen(m->heap);
-    return APR_SUCCESS;
-}
-
-
-
-ap_status_t ap_shm_avail(struct shmem_t *c, ap_size_t *size)
-{
-
-    return APR_ENOTIMPL;
-}
diff --git a/shmem/unix/.cvsignore b/shmem/unix/.cvsignore
deleted file mode 100644
index f3c7a7c5da6..00000000000
--- a/shmem/unix/.cvsignore
+++ /dev/null
@@ -1 +0,0 @@
-Makefile
diff --git a/shmem/unix/Makefile.in b/shmem/unix/Makefile.in
deleted file mode 100644
index 085863ddb8c..00000000000
--- a/shmem/unix/Makefile.in
+++ /dev/null
@@ -1,60 +0,0 @@
-#CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
-#LIBS=$(EXTRA_LIBS) $(LIBS1)
-#INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
-#LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
-
-RM=@RM@
-CC=@CC@
-RANLIB=@RANLIB@
-CFLAGS=@CFLAGS@ @OPTIM@
-LIBS=@LIBS@
-LDFLAGS=@LDFLAGS@ $(LIBS)
-INCDIR=../../inc
-INCDIR1=../../include
-INCDIR2=../../misc/@OSDIR@
-INCLUDES=-I$(INCDIR) -I$(INCDIR1) -I$(INCDIR2) -Imm -I.
-
-LIB=libshmem.a
-
-OBJS=shmem.o
-
-.c.o:
-	$(CC) $(CFLAGS) -c $(INCLUDES) $<
-
-all: $(LIB)
-
-clean:
-	$(RM) -f *.o *.a *.so
-	cd mm; make clean; cd ..
-
-distclean: clean
-	-$(RM) -f Makefile
-	cd mm; make distclean; cd ..
-
-$(OBJS): Makefile
-
-$(LIB): $(OBJS)
-	$(RM) -f $@
-	cd mm; make; cd ..
-	cp mm/mm_global.o mm/mm_alloc.o mm/mm_core.o mm/mm_lib.o mm/mm_vers.o .
-	$(AR) cr $@ $(OBJS)
-	$(RANLIB) $@
-
-#
-# We really don't expect end users to use this rule.  It works only with
-# gcc, and rebuilds Makefile.tmpl.  You have to re-run Configure after
-# using it.
-#
-depend:
-	cp Makefile.in Makefile.in.bak \
-	    && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.in > Makefile.new \
-	    && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \
-	    && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
-	           -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
-		> Makefile.in \
-	    && rm Makefile.new
-
-# DO NOT REMOVE
-shmem.o: shmem.c mm/mm.h ../../include/apr_general.h \
- ../../include/apr.h ../../include/apr_errno.h \
- ../../include/apr_shmem.h
diff --git a/shmem/unix/mm/.cvsignore b/shmem/unix/mm/.cvsignore
deleted file mode 100644
index c147a43f370..00000000000
--- a/shmem/unix/mm/.cvsignore
+++ /dev/null
@@ -1,11 +0,0 @@
-config.log
-mm_conf.h
-libtool
-config.status
-.libs
-Makefile
-mm-config
-*.lo
-*.la
-mm_test
-configure
diff --git a/shmem/unix/mm/CHANGES b/shmem/unix/mm/CHANGES
deleted file mode 100644
index 4048a223cb2..00000000000
--- a/shmem/unix/mm/CHANGES
+++ /dev/null
@@ -1,162 +0,0 @@
-
- MM CHANGES
- ==========
-
- Changes between 1.0.10 and 1.0.11 (27-Aug-1999 to 06-Sep-1999)
-
-  *) Cleaned up various file permission in source tree
-  *) Enhanced mm-config.in: new --all option and less newlines
-  *) Added support --silent to libtool glue code in aclocal.m4
-  *) Upgraded to GNU Pth's more recent config.{guess,sub}
-  *) Upgraded to GNU shtool 1.4.6
-  *) Fixed --section for mm-config in Makefile.in
-  *) Added `void *' casts to MAP_FAILED (= -1) values to avoid
-     warnings under some platforms.
-  *) Fixed a few typos in mm.pod
-
- Changes between 1.0.9 and 1.0.10 (02-Jul-1999 to 27-Aug-1999)
-
-  *) Changed "make dist" and "make snap" to use "shtool tarball"
-  *) Added #define KERNEL for SunOS to get SHM_R und SHM_W values.
-  *) Upgraded to GNU libtool 1.3.3
-  *) Upgraded to GNU shtool 1.4.5
-  *) Downgraded required Autoconf version to 2.12
-  *) Added MM version number to test report
-  *) Added --enable-batch
-  *) Moved mm_lock_mode in mm.h to top to avoid warnings
-
- Changes between 1.0.8 and 1.0.9 (24-Jun-1999 to 02-Jul-1999)
-
-  *) Fixed a nasty bug related to {MM,mm}_[un]lock():
-     an additional semicolon broke the semantics.
-  *) Upgraded to released shtool 1.4.0
-  *) Fixed `make test'
-
- Changes between 1.0.7 and 1.0.8 (22-Jun-1999 to 24-Jun-1999)
-  
-  *) Added important MAP_FAILED fallback also to Autoconf stuff
-  *) Upgraded to latest shtool 1.3.0-dev to fix two Awk problems
-
- Changes between 1.0.6 and 1.0.7 (06-Jun-1999 to 22-Jun-1999)
-
-  *) Upgraded to latest shtool 1.3.0-dev
-  *) Avoid -g under non-debugging situation
-  *) Complain with a fatal error message when MM_SHM_MAXSEGSIZE
-     couldn't be determined.
-  *) Updated config.guess/config.sub
-  *) Fixed a nasty permission bug for the lock files:
-     they were opened write-only, but at least fcntl()
-     requires them to be opened read-write.
-  *) Check return value of mm_core_lock() in mm_alloc.c
-
- Changes between 1.0.5 and 1.0.6 (02-Jun-1999 to 06-Jun-1999)
-
-  *) Fixed mm_malloc() function: it returned the wrong pointer when a chunk
-     was reused and forgot to lock/unlock the data structures.
-  *) Fixed internal best-fit algorithm for finding a free memory chunk: 
-     - things got inserted out of order in the list
-     - when chunk is found which matches size exactly it stops immediately
-     - lowered chunk splitting threshold to MIN(2*size,128)
-  *) Moved internal definitions in mm.h to private section
-
- Changes between 1.0.4 and 1.0.5 (21-May-1999 to 02-Jun-1999)
-
-  *) Fixed output of mm-config.in
-  *) Fixed output of configure --help
-  *) Upgraded to GNU libtool 1.3.2
-  *) Upgraded to shtool 1.2.9
-  *) Made libtool calls visible but use --quiet 
-  *) Hint user to send feedback only on errors or for new platform
-  *) Removed unnecessary "elf" hint for FreeBSD from config.guess
-
- Changes between 1.0.3 and 1.0.4 (15-May-1999 to 21-May-1999)
-
-  *) Fixed maximum memory size determination and internal handling
-  *) Documented the mm_lib_xxx() functions.
-
- Changes between 1.0.2 and 1.0.3 (26-Apr-1999 to 15-May-1999)
-
-  *) Added {MM,mm,mm_core}_permission() function
-  *) Fixed version information and mod_ssl URL in manual page
-  *) Upgraded config.{guess,sub} from libtool 1.3 distribution
-  *) Upgraded to GNU libtool 1.3
-  *) Upgraded to shtool 1.2.7
-  *) Fixed public includes for xx_t types
-  *) Fixed mm_vers.c and shtool type inside CVS
-
- Changes between 1.0.1 and 1.0.2 (18-Apr-1999 to 26-Apr-1999)
-
-  *) Upgraded to GNU libtool 1.2f
-  *) Upgraded to shtool 1.1.0
-
- Changes between 1.0.0 and 1.0.1 (18-Mar-1999 to 18-Apr-1999)
-
-  *) Fixed "dist" Makefile target to not distribute CVS stuff
-  *) Upgraded lshtool to the latest version
-  *) Const'ification of the API
-
- Changes between 1.0b6 and 1.0.0 (18-Mar-1999 to 28-Mar-1999)
-
-  *) Finally cleaned up and polished the mm.pod manual page.
-  *) Fixed mm-config program
-
- Changes between 1.0b5 and 1.0b6 (18-Mar-1999 to 18-Mar-1999)
-
-  *) Added {MM,mm}_maxsize() to manual page
-  *) Changed MM_create() signature to match mm_create()
-
- Changes between 1.0b4 and 1.0b5 (15-Mar-1999 to 18-Mar-1999)
-
-  *) Make sure the maximum allocateable size takes
-     the overhead of the memory pool into account.
-  *) Fixed lshtool and this way hex version string
-  *) Fixed Makefile for mm_test target dependecies
-  *) Added {MM,mm}_maxsize() function to let one
-     determine in advance the maximum allocateable pool
-
- Changes between 1.0b3 and 1.0b4 (15-Mar-1999 to 15-Mar-1999)
-
-  *) Added mm-config.pod manpage
-  *) Split mm-config --ldflags into --ldflags and --libs
-  *) Removed TODO and fulltest files
-
- Changes between 1.0b2 and 1.0b3 (13-Mar-1999 to 15-Mar-1999)
-
-  *) Added Autoconf check for determining max shared mem segment size
-  *) Changed -1 to MAP_FAILED when available
-  *) Replaced 8KB default shared memory segment size with max size
-  *) Added mm_core_maxsegsize() function
-  *) Use a remembered offset for mmap() on temporary files
-  *) Imported source tree into CVS
-  *) Added read-only locking support
-  *) Fixed MMFILE and MMZERO variants
-
- Changes between 1.0b1 and 1.0b2 (12-Mar-1999 to 13-Mar-1999)
-
-  *) Updated the mm.pod manual page.
-  *) Split README into README and LICENSE files
-  *) Fixed becho problems
-  *) Added a test suite summary
-  *) Added INSTALL file
-  *) Reduced mm_test's memory size from 1MB to 512KB
-  *) Fixed unsigned long and %X related warnings
-
- Changes between 1.0b0 and 1.0b1 (11-Mar-1999 to 12-Mar-1999)
-
-  *) Enhanced mm_test
-  *) Added {MM,mm}_available() function
-  *) Fixed MMZERO
-  *) Fixed IPC Semaphore initialization
-  *) Added --with-{sem,shm}=TYPE options
-  *) Fixed "make test" and mm_memory_display() function
-  *) Added mm_lib.c source with mm_lib_xx() functions
-
- Changes between 0.9.0 and 1.0b0 (10-Mar-1999 to 11-Mar-1999)
-
-  *) Switched to GNU Autoconf and GNU Libtool
-
- Changes between GENESIS and 0.9.0 (Jan-1999 to 10-Mar-1999)
-
-  *) Created initial version on FreeBSD
-  *) Ported to Linux and Solaris
-
diff --git a/shmem/unix/mm/INSTALL b/shmem/unix/mm/INSTALL
deleted file mode 100644
index 1f42c1d4abd..00000000000
--- a/shmem/unix/mm/INSTALL
+++ /dev/null
@@ -1,19 +0,0 @@
-   __  __ __  __ 
-  |  \/  |  \/  |
-  | |\/| | |\/| |
-  | |  | | |  | |
-  |_|  |_|_|  |_|
-                 
-  MM - Shared Memory Library
-
-  To install the MM library into /path/to/mm/{bin,lib,include,man}/ perform
-  the following steps in your shell:
-      
-    $ ./configure --prefix=/path/to/mm
-    $ make
-    $ make test
-    $ make install
-
-  This installs at least a static variant of the MM library and when your
-  platforms support it, also a shared library variant of the MM library.
-
diff --git a/shmem/unix/mm/LICENSE b/shmem/unix/mm/LICENSE
deleted file mode 100644
index 3bd1c3d4131..00000000000
--- a/shmem/unix/mm/LICENSE
+++ /dev/null
@@ -1,40 +0,0 @@
-
-  ====================================================================
-  Copyright (c) 1999 Ralf S. Engelschall. All rights reserved.
- 
-  Redistribution and use in source and binary forms, with or without
-  modification, are permitted provided that the following conditions
-  are met:
- 
-  1. Redistributions of source code must retain the above copyright
-     notice, this list of conditions and the following disclaimer. 
- 
-  2. Redistributions in binary form must reproduce the above copyright
-     notice, this list of conditions and the following disclaimer in
-     the documentation and/or other materials provided with the
-     distribution.
- 
-  3. All advertising materials mentioning features or use of this
-     software must display the following acknowledgment:
-     "This product includes software developed by
-      Ralf S. Engelschall <rse@engelschall.com>."
- 
-  4. Redistributions of any form whatsoever must retain the following
-     acknowledgment:
-     "This product includes software developed by
-      Ralf S. Engelschall <rse@engelschall.com>."
- 
-  THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
-  EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-  PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL RALF S. ENGELSCHALL OR
-  ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
-  OF THE POSSIBILITY OF SUCH DAMAGE.
-  ====================================================================
-
diff --git a/shmem/unix/mm/Makefile.in b/shmem/unix/mm/Makefile.in
deleted file mode 100644
index 206580d2c05..00000000000
--- a/shmem/unix/mm/Makefile.in
+++ /dev/null
@@ -1,222 +0,0 @@
-## ====================================================================
-## Copyright (c) 1999 Ralf S. Engelschall. All rights reserved.
-##
-## Redistribution and use in source and binary forms, with or without
-## modification, are permitted provided that the following conditions
-## are met:
-##
-## 1. Redistributions of source code must retain the above copyright
-##    notice, this list of conditions and the following disclaimer. 
-##
-## 2. Redistributions in binary form must reproduce the above copyright
-##    notice, this list of conditions and the following disclaimer in
-##    the documentation and/or other materials provided with the
-##    distribution.
-##
-## 3. All advertising materials mentioning features or use of this
-##    software must display the following acknowledgment:
-##    "This product includes software developed by
-##     Ralf S. Engelschall <rse@engelschall.com>."
-##
-## 4. Redistributions of any form whatsoever must retain the following
-##    acknowledgment:
-##    "This product includes software developed by
-##     Ralf S. Engelschall <rse@engelschall.com>."
-##
-## THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
-## EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-## PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL RALF S. ENGELSCHALL OR
-## ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-## NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-## LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-## HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-## STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-## ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
-## OF THE POSSIBILITY OF SUCH DAMAGE.
-## ====================================================================
-
-##
-##  Makefile
-##
-
-@SET_MAKE@
-
-TOP         = .
-prefix      = @prefix@
-exec_prefix = @exec_prefix@
-bindir      = @bindir@
-libdir      = @libdir@
-includedir  = @includedir@
-mandir      = @mandir@
-
-SHELL       = /bin/sh
-CC          = @CC@
-CFLAGS      = @CFLAGS@
-LDFLAGS     = @LDFLAGS@
-LIBS        = @LIBS@
-RM          = rm -f
-LIBTOOL     = @LIBTOOL@
-SHTOOL      = @SHTOOL@
-
-MAN         = mm.3 mm-config.1
-OBJ         = mm_global.o  mm_alloc.o  mm_core.o  mm_lib.o  mm_vers.o
-LOBJ        = mm_global.lo mm_alloc.lo mm_core.lo mm_lib.lo mm_vers.lo
-
-_VERSION_FILE = \
-    mm_vers.c
-_VERSION = \
-	$(SHTOOL) version -l c -n MM -p MM $$OPT $(_VERSION_FILE);\
-	V=`$(SHTOOL) version -l c -d long $(_VERSION_FILE)`;\
-	sed -e "s/Version .*(.*)/Version $$V/g" <README >README.n && mv README.n README
-
-.SUFFIXES: .o .lo
-
-.c.o:
-	$(LIBTOOL) --quiet --mode=compile \
-		$(CC) -c $(CFLAGS) $<
-
-.c.lo:
-	$(LIBTOOL) --quiet --mode=compile \
-		$(CC) -c $(CFLAGS) $<
-
-all: libmm.la $(MAN) mm_test
-
-libmm.la: $(OBJ) $(LOBJ)
-	$(LIBTOOL) --quiet --mode=link  \
-		$(CC) -o libmm.la $(LOBJ) \
-	    -rpath $(libdir) -version-info `$(SHTOOL) version -l c -d libtool mm_vers.c`
-
-mm_alloc.c mm_core.c mm_global.c: mm_conf.h mm.h mm_vers.c
-
-test: mm_test
-	-@./mm_test; \
-	if [ $$? -eq 0 ]; then \
-		PLATFORM=`$(SHELL) ./config.guess`; \
-		PLATFORM=`$(SHELL) ./config.sub $$PLATFORM`; \
-		if [ ".`grep $$PLATFORM README`" = . ]; then \
-	        echo "Please send the following summary via Email to the author"; \
-	        echo "Ralf S. Engelschall <rse@engelschall.com> for inclusion into"; \
-	        echo "the list of successfully tested platforms (see README file):"; \
-	        echo ""; \
-	        echo "Ok" >.fbtool; \
-	        $(SHELL) ./fbtool -d; \
-	    fi; \
-	else \
-	    echo "Please send the following summary together with as much other"; \
-	    echo "details about the configuration, build and test steps to the author"; \
-	    echo "Ralf S. Engelschall <rse@engelschall.com> to help him in tracking"; \
-	    echo "down your platform problem."; \
-	    echo ""; \
-	    echo "Failed" >.fbtool; \
-	    $(SHELL) ./fbtool -d; \
-	fi; \
-	exit 0
-
-debug: mm_test
-	@$(LIBTOOL) --mode=execute gdb mm_test
-
-mm_test: mm_test.lo libmm.la
-	$(LIBTOOL) --quiet --mode=link \
-		$(CC) -o $@ mm_test.lo libmm.la
-
-mm.3: mm.pod
-	V1=`$(SHTOOL) version -l c -d short $(_VERSION_FILE)`; \
-	V2=`$(SHTOOL) version -l c -d long $(_VERSION_FILE)`; \
-	D=`$(SHTOOL) version -l c -d long $(_VERSION_FILE) | sed -e 's;.*(;;' -e 's;).*;;'`; \
-	pod2man --section=3 --center="Shared Memory Library" --release="$$D" --date="MM $$V1" mm.pod |\
-	perl -p -e 's;^(\\\&\s+.+?)([Mm][Mm]_[a-zA-Z0-9_]+)(\(.+?)$$;$$1\\fB$$2\\fR$$3;' |\
-	sed -e "s;MM_VERSION_STR;$$V2;" >mm.3
-
-mm-config.1: mm-config.pod
-	V1=`$(SHTOOL) version -l c -d short $(_VERSION_FILE)`; \
-	V2=`$(SHTOOL) version -l c -d long $(_VERSION_FILE)`; \
-	D=`$(SHTOOL) version -l c -d long $(_VERSION_FILE) | sed -e 's;.*(;;' -e 's;).*;;'`; \
-	pod2man --section=1 --center="Shared Memory Library" --release="$$D" --date="MM $$V1" mm-config.pod |\
-	perl -p -e 's;^(\\\&\s+.+?)([Mm][Mm]_[a-zA-Z0-9_]+)(\(.+?)$$;$$1\\fB$$2\\fR$$3;' |\
-	sed -e "s;MM_VERSION_STR;$$V2;" >mm-config.1
-
-update:
-	@$(RM) ltmain.sh ltconfig shtool
-	@$(MAKE) $(MFLAGS) ltmain.sh ltconfig configure shtool
-
-configure: configure.in aclocal.m4
-	$(RM) configure
-	autoconf
-
-ltmain.sh:
-	@F=`libtoolize -n -c -f | grep 'cp.*ltmain.sh' |\
-	    sed -e 's;[^/]*;;' -e 's; .*;;'`; \
-	echo "ltmain.sh <-- $$F"; cat $$F |\
-	sed -e 's:/bin/sh; then:/bin/sh || test "$$nonopt" = ./shtool;then:' \
-	    -e 's:exec \$$SHELL \$$0 --finish:exit 0 #:' >ltmain.sh
-
-ltconfig:
-	@F=`libtoolize -n -c -f | grep 'cp.*ltconfig' | sed -e 's;[^/]*;;' -e 's; .*;;'`; \
-	echo "ltconfig <-- $$F"; cp $$F .
-
-shtool:
-	shtoolize -o shtool all
-
-install: all
-	$(SHTOOL) mkdir -f -p -m 755 $(bindir)
-	$(SHTOOL) mkdir -f -p -m 755 $(includedir)
-	$(SHTOOL) mkdir -f -p -m 755 $(libdir)
-	$(SHTOOL) mkdir -f -p -m 755 $(mandir)/man1
-	$(SHTOOL) mkdir -f -p -m 755 $(mandir)/man3
-	$(SHTOOL) install -c -m 755 mm-config $(bindir)/mm-config
-	$(SHTOOL) install -c -m 644 mm-config.1 $(mandir)/man1/mm-config.1
-	$(SHTOOL) install -c -m 644 mm.3 $(mandir)/man3/mm.3
-	$(SHTOOL) install -c -m 644 mm.h $(includedir)/mm.h
-	@$(LIBTOOL) --mode=install $(SHTOOL) install -c -m 644 libmm.la $(libdir)/libmm.la
-
-clean:
-	$(RM) mm_test mm_test.o mm_test.lo
-	$(RM) core *.core *.bak *~
-	$(RM) $(LOBJ)
-	$(RM) $(OBJ) 
-	$(RM) libmm.la
-	$(RM) -r .libs
-
-distclean: clean
-	$(RM) Makefile
-	$(RM) mm-config mm_conf.h
-	$(RM) config.h config.cache config.status config.log
-	$(RM) libtool
-	$(RM) .fbtool
-
-realclean: distclean
-	$(RM) $(MAN)
-
-dist: distclean
-	@$(SHTOOL) fixperm -v *; \
-	V=`$(SHTOOL) version -l c -d short $(_VERSION_FILE)`; \
-	$(SHTOOL) tarball -o mm-$${V}.tar.gz -d mm-$${V} -u rse -g mm \
-	                  -e 'CVS,\.cvsignore,\.[ao],^\.' -c 'gzip --best' .; \
-	ls -l mm-$${V}.tar.gz
-
-snap: distclean
-	@$(SHTOOL) fixperm *; \
-	V=`$(SHTOOL) version -l c -d short $(_VERSION_FILE)`; \
-	$(SHTOOL) tarball -o mm-$${V}-SNAP.tar.gz -d mm-$${V}-SNAP -u rse -g mm \
-	                  -e 'CVS,\.cvsignore,\.[ao],^\.' -c 'gzip --best' .; \
-	ls -l mm-$${V}-SNAP.tar.gz
-
-new-version:
-	OPT='-i v' && $(_VERSION)
-new-revision:
-	OPT='-i r' && $(_VERSION)
-new-patchlevel:
-	OPT='-i P' && $(_VERSION)
-new-betalevel:
-	OPT='-i b' && $(_VERSION)
-new-alphalevel:
-	OPT='-i a' && $(_VERSION)
-new-snaplevel:
-	OPT='-i s' && $(_VERSION)
-new-release:
-	OPT='-s $(R)' && $(_VERSION)
-update-version:
-	OPT="-s `$(SHTOOL) version -l c -d short $(_VERSION_FILE)`" && $(_VERSION)
-
diff --git a/shmem/unix/mm/README b/shmem/unix/mm/README
deleted file mode 100644
index 5a19d6c08ad..00000000000
--- a/shmem/unix/mm/README
+++ /dev/null
@@ -1,87 +0,0 @@
-   __  __ __  __ 
-  |  \/  |  \/  |
-  | |\/| | |\/| |
-  | |  | | |  | |
-  |_|  |_|_|  |_|
-                 
-  MM - Shared Memory Library
-  Copyright (c) 1999 Ralf S. Engelschall, All rights reserved.
-  Version 1.0.8 (24-Jun-1999)
-
-  The MM library is a 2-layer abstraction library which simplifies the usage
-  of shared memory between forked (and this way strongly related) processes
-  under Unix platforms. On the first (lower) layer it hides all platform
-  dependent implementation details (allocation and locking) when dealing with
-  shared memory segments and on the second (higher) layer it provides a
-  high-level malloc(3)-style API for a convenient and well known way to work
-  with data-structures inside those shared memory segments. 
-
-  This library was successfully tested on the following platforms (and
-  should automatically adjust to other platforms, of course):
-
-    o  i386-unknown-freebsd3.1     FreeBSD 3.1         
-    o  i386-unknown-freebsd3.2     FreeBSD 3.2
-    o  i386-unknown-freebsd2.2.7   FreeBSD 2.2.7
-    o  i386-unknown-freebsd2.2.8   FreeBSD 2.2.8
-    o  i386-unknown-freebsd2.2.2   FreeBSD 2.2.2
-    o  i386-unknown-openbsd2.5     OpenBSD 2.5
-    o  i386-pc-bsdi4.0.1           BSDI 4.0.1
-    o  i586-pc-linux-gnu           RedHat 5.2
-    o  i586-pc-linux-gnu           RedHat 5.0
-    o  i686-pc-linux-gnu           Redhat 6.0
-    o  i486-pc-linux-gnulibc1      Linux
-    o  i686-pc-linux-gnulibc1      Slackware 4.0
-    o  i586-pc-linux-gnulibc1      Slackware 4.0
-    o  sparc-sun-solaris2.6        Solaris 2.6
-    o  sparc-sun-solaris2.7        Solaris 2.7
-    o  i386-pc-solaris2.7          Solaris 2.7
-    o  alphaev56-dec-osf4.0d       Digital Unix v4.0D
-    o  alphaev56-dec-osf4.0c       Digital Unix v4.0C
-    o  powerpc-ibm-aix4.2.0.0      AIX 4.2
-    o  powerpc-ibm-aix4.3.1.0      AIX 4.2
-    o  alphaev56-unknown-linux-gnu Linux/Alpha
-    o  powerpc-unknown-linux-gnu   LinuxPPC 4
-    o  m68k-apple-aux3.1.1         A/UX 3.1.1         
-    o  hppa1.1-hp-hpux10.10        HP-UX 10.10
-    o  hppa1.1-hp-hpux10.20        HP-UX 10.20
-    o  hppa2.0-hp-hpux10.20        HP-UX 10.20
-    o  arm-unknown-linux-gnu       Corel Netwinder SA110
-    o  mips-sni-sysv4              SIEMENS ReliantUNIX
-    o  mips-sgi-irix6.2            IRIX 6.2
-    o  mips-sgi-irix6.3            IRIX 6.3
-    o  mips-sgi-irix6.4            IRIX 6.4
-    o  mips-sgi-irix6.5            IRIX 6.5.4
-
-  Credit has to be given to the following people who contributed ideas,
-  bugfixes, hints, gave platform feedback, etc. (in alphabetical order):
-
-    o  Ronald Appelfelder          <ra@intraregio.net>
-    o  Robert Belleman             <robbel@wins.uva.nl>
-    o  Jeff Clark                  <hotwire@hoser.com>
-    o  Eric Cholet                 <cholet@logilune.com>
-    o  Dean Gaudet                 <dgaudet@arctic.org>
-    o  Ask Bjoern Hansen           <ask@netcetera.dk>
-    o  Jim Jagielski               <jim@jagunet.com>
-    o  Mats Josefsson              <matjos@rsv.se>
-    o  Sergey Kachanovsky          <ranger@tversu.ru>
-    o  Martin Kraemer              <martin.kraemer@mch.sni.de>
-    o  Rasmus Lerdorf              <rasmus@lerdorf.on.ca>
-    o  Dave Malhotra               <davem@glue.umd.edu>
-    o  Christophe Massiot          <massiot@via.ecp.fr>
-    o  Patrick                     <puzzled@symplex.net>
-    o  Charles Randall             <crandall@matchlogic.com> 
-    o  David Rees                  <drees@ucsd.edu>
-    o  Christian Reiber            <chrei@en.muc.de>
-    o  Dan Sullivan                <sullivan@epa.gov>
-    o  Tom Vaughan                 <tvaughan@aventail.com>
-    o  Rick Watson                 <rick@akbar.cc.utexas.edu>
-    o  Mark Wilkie                 <mark@exceptionmedia.com>
-    o  Cliff Woolley               <jwoolley@wlu.edu>
-
-  The documentation and latest release can be found on
-  http://www.engelschall.com/sw/mm/
-
-                                       Ralf S. Engelschall
-                                       rse@engelschall.com
-                                       www.engelschall.com
-
diff --git a/shmem/unix/mm/aclocal.m4 b/shmem/unix/mm/aclocal.m4
deleted file mode 100644
index ad9f0147d07..00000000000
--- a/shmem/unix/mm/aclocal.m4
+++ /dev/null
@@ -1,362 +0,0 @@
-dnl ##
-dnl ##
-dnl ##
-define(AC_PROG_LIBTOOL,[dnl
-AC_ARG_ENABLE(static,dnl
-[  --enable-static         build static libraries (default=yes)],
-enable_static="$enableval",
-enable_static=yes
-)dnl
-AC_ARG_ENABLE(shared,dnl
-[  --enable-shared         build shared libraries (default=yes)],
-enable_shared="$enableval",
-enable_shared=yes
-)dnl
-libtool_flags=''
-test ".$silent"            = .yes && libtool_flags="$libtool_flags --silent"
-test ".$enable_static"     = .no  && libtool_flags="$libtool_flags --disable-static"
-test ".$enable_shared"     = .no  && libtool_flags="$libtool_flags --disable-shared"
-test ".$ac_cv_prog_gcc"    = .yes && libtool_flags="$libtool_flags --with-gcc"
-test ".$ac_cv_prog_gnu_ld" = .yes && libtool_flags="$libtool_flags --with-gnu-ld"
-CC="$CC" CFLAGS="$CFLAGS" CPPFLAGS="$CPPFLAGS" LD="$LD" \
-${CONFIG_SHELL-/bin/sh} ltconfig --no-reexec \
-$libtool_flags --no-verify ltmain.sh $PLATFORM ||\
-AC_MSG_ERROR([libtool configuration failed])
-LIBTOOL="\$(TOP)/libtool"
-AC_SUBST(LIBTOOL)
-])dnl
-dnl ##
-dnl ##
-dnl ##
-define(AC_CHECK_DEBUGGING,[dnl
-AC_MSG_CHECKING(for compilation debug mode)
-AC_ARG_ENABLE(debug,dnl
-[  --enable-debug          build for debugging (default=no)],
-[dnl
-if test ".$ac_cv_prog_gcc" = ".yes"; then
-    case "$CFLAGS" in
-        *-O2* ) ;;
-            * ) CFLAGS="$CFLAGS -O2" ;;
-    esac
-    case "$CFLAGS" in
-        *-g* ) ;;
-           * ) CFLAGS="$CFLAGS -g" ;;
-    esac
-    CFLAGS="$CFLAGS -ggdb3"
-    CFLAGS="$CFLAGS -Wall -Wshadow -Wpointer-arith -Wcast-align"
-    CFLAGS="$CFLAGS -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -Winline"
-else
-    case "$CFLAGS" in
-        *-g* ) ;;
-           * ) CFLAGS="$CFLAGS -g" ;;
-    esac
-fi
-msg="enabled"
-AC_DEFINE(MM_DEBUG)
-],[
-case "$CFLAGS" in
-    *-g* ) CFLAGS=`echo "$CFLAGS" |\
-                   sed -e 's/ -g //g' -e 's/ -g$//' -e 's/^-g //g' -e 's/^-g$//'` ;;
-esac
-msg=disabled
-])dnl
-AC_MSG_RESULT([$msg])
-])
-dnl ##
-dnl ##
-dnl ##
-define(AC_CONFIGURE_PART,[dnl
-AC_MSG_RESULT()
-AC_MSG_RESULT(${T_MD}$1:${T_ME})
-])dnl
-dnl ##
-dnl ##
-dnl ##
-define(AC_CHECK_DEFINE,[dnl
-AC_CACHE_CHECK(for $1 in $2, ac_cv_define_$1,
-AC_EGREP_CPP([YES_IS_DEFINED], [
-#include <$2>
-#ifdef $1
-YES_IS_DEFINED
-#endif
-], ac_cv_define_$1=yes; AC_DEFINE(HAVE_$1), ac_cv_define_$1=no)
-)])dnl
-dnl ##
-dnl ##
-dnl ##
-define(AC_IFALLYES,[dnl
-ac_rc=yes
-for ac_spec in $1; do
-    ac_type=`echo "$ac_spec" | sed -e 's/:.*$//'`
-    ac_item=`echo "$ac_spec" | sed -e 's/^.*://'`
-    case $ac_type in
-        header )
-            ac_item=`echo "$ac_item" | sed 'y%./+-%__p_%'`
-            ac_var="ac_cv_header_$ac_item"
-            ;;
-        file )
-            ac_item=`echo "$ac_item" | sed 'y%./+-%__p_%'`
-            ac_var="ac_cv_file_$ac_item"
-            ;;
-        func )   ac_var="ac_cv_func_$ac_item"   ;;
-        define ) ac_var="ac_cv_define_$ac_item" ;;
-        custom ) ac_var="$ac_item" ;;
-    esac
-    eval "ac_val=\$$ac_var"
-    if test ".$ac_val" != .yes; then
-        ac_rc=no
-        break
-    fi
-done
-if test ".$ac_rc" = .yes; then
-    :
-    $2
-else
-    :
-    $3
-fi
-])dnl
-dnl ##
-dnl ##
-dnl ##
-define(AC_BEGIN_DECISION,[dnl
-ac_decision_item='$1'
-ac_decision_msg='FAILED'
-ac_decision=''
-])dnl
-define(AC_DECIDE,[dnl
-ac_decision='$1'
-ac_decision_msg='$2'
-ac_decision_$1=yes
-ac_decision_$1_msg='$2'
-])dnl
-define(AC_DECISION_OVERRIDE,[dnl
-    ac_decision=''
-    for ac_item in $1; do
-         eval "ac_decision_this=\$ac_decision_${ac_item}"
-         if test ".$ac_decision_this" = .yes; then
-             ac_decision=$ac_item
-             eval "ac_decision_msg=\$ac_decision_${ac_item}_msg"
-         fi
-    done
-])dnl
-define(AC_DECISION_FORCE,[dnl
-ac_decision="$1"
-eval "ac_decision_msg=\"\$ac_decision_${ac_decision}_msg\""
-])dnl
-define(AC_END_DECISION,[dnl
-if test ".$ac_decision" = .; then
-    echo "[$]0:Error: decision on $ac_decision_item failed" 1>&2
-    exit 1
-else
-    if test ".$ac_decision_msg" = .; then
-        ac_decision_msg="$ac_decision"
-    fi
-    AC_MSG_RESULT([decision on $ac_decision_item... $ac_decision_msg])
-fi
-])dnl
-dnl ##
-dnl ##
-dnl ##
-AC_DEFUN(AC_TEST_FILE,
-[AC_REQUIRE([AC_PROG_CC])
-ac_safe=`echo "$1" | sed 'y%./+-%__p_%'`
-AC_MSG_CHECKING([for $1])
-AC_CACHE_VAL(ac_cv_file_$ac_safe, [
-  if test -r $1; then
-    eval "ac_cv_file_$ac_safe=yes"
-  else
-    eval "ac_cv_file_$ac_safe=no"
-  fi
-])dnl
-if eval "test \"`echo '$ac_cv_file_'$ac_safe`\" = yes"; then
-  AC_MSG_RESULT(yes)
-  ifelse([$2], , :, [$2])
-else
-  AC_MSG_RESULT(no)
-ifelse([$3], , , [$3])
-fi
-])
-dnl ##
-dnl ##  AC_PROG_NM - find the path to a BSD-compatible name lister
-dnl ##
-AC_DEFUN(AC_PROG_NM,
-[AC_MSG_CHECKING([for BSD-compatible nm])
-AC_CACHE_VAL(ac_cv_path_NM,
-[if test -n "$NM"; then
-  # Let the user override the test.
-  ac_cv_path_NM="$NM"
-else
-  IFS="${IFS=   }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
-  for ac_dir in /usr/ucb /usr/ccs/bin $PATH /bin; do
-    test -z "$ac_dir" && ac_dir=.
-    if test -f $ac_dir/nm; then
-      # Check to see if the nm accepts a BSD-compat flag.
-      # Adding the `sed 1q' prevents false positives on HP-UX, which says:
-      #   nm: unknown option "B" ignored
-      if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
-        ac_cv_path_NM="$ac_dir/nm -B"
-      elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
-        ac_cv_path_NM="$ac_dir/nm -p"
-      else
-        ac_cv_path_NM="$ac_dir/nm"
-      fi
-      break
-    fi
-  done
-  IFS="$ac_save_ifs"
-  test -z "$ac_cv_path_NM" && ac_cv_path_NM=nm
-fi])
-NM="$ac_cv_path_NM"
-AC_MSG_RESULT([$NM])
-AC_SUBST(NM)
-])
-dnl #
-dnl #
-dnl #
-define(AC_CHECK_MAXSEGSIZE,[dnl
-AC_MSG_CHECKING(for shared memory maximum segment size)
-OCFLAGS="$CFLAGS"
-case "$1" in
-    MM_SHMT_MM*    ) CFLAGS="-DTEST_MMAP   $CFLAGS" ;;
-    MM_SHMT_IPCSHM ) CFLAGS="-DTEST_SHMGET $CFLAGS" ;;
-esac
-cross_compile=no
-AC_TRY_RUN(
-changequote(<<, >>)dnl
-<<
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/file.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#ifdef TEST_MMAP
-#include <sys/mman.h>
-#endif
-#ifdef TEST_SHMGET
-#include <sys/ipc.h>
-#ifndef _OSD_POSIX
-#include <sys/shm.h>
-#else
-#define _KMEMUSER 1 /* BS2000 needs this to enable SHM_[RW] */
-#include <sys/shm.h>
-#undef  _KMEMUSER
-#endif
-#endif
-#if !defined(MAP_FAILED)
-#define MAP_FAILED ((void *)-1)
-#endif
-
-int testit(int size)
-{
-    int fd;
-    void *segment;
-#ifdef TEST_MMAP
-    char file[] = "./ac_test.tmp";
-    unlink(file);
-    if ((fd = open(file, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR)) == -1)
-        return 0;
-    if (ftruncate(fd, size) == -1)
-        return 0;
-    if ((segment = (void *)mmap(NULL, size, PROT_READ|PROT_WRITE, 
-                                MAP_SHARED, fd, 0)) == MAP_FAILED) {
-        close(fd);
-        return 0;
-    }
-    munmap((caddr_t)segment, size);
-    close(fd);
-    unlink(file);
-#endif
-#ifdef TEST_SHMGET
-    if ((fd = shmget(IPC_PRIVATE, size, SHM_R|SHM_W|IPC_CREAT)) == -1)
-        return 0;
-    if ((segment = (void *)shmat(fd, NULL, 0)) == ((void *)-1)) {
-        shmctl(fd, IPC_RMID, NULL);
-        return 0;
-    }
-    shmdt(segment);
-    shmctl(fd, IPC_RMID, NULL);
-#endif
-    return 1;
-}
-
-#define ABS(n) ((n) >= 0 ? (n) : (-(n)))
-
-int main(int argc, char *argv[]) 
-{
-    int t, m, b;
-    int d;
-    int rc;
-    FILE *f;
-
-    /*
-     * Find maximum possible allocation size by performing a
-     * binary search starting with a search space between 0 and
-     * 64MB of memory.
-     */
-    t = 1024*1024*64 /* = 67108864 */;
-    if (testit(t))
-        m = t;
-    else {
-        m = 1024*1024*32;
-        b = 0;
-        for (;;) {
-            /* fprintf(stderr, "t=%d, m=%d, b=%d\n", t, m, b); */
-            rc = testit(m);
-            if (rc) {
-                d = ((t-m)/2);
-                b = m;
-            }
-            else {
-                d = -((m-b)/2);
-                t = m;
-            }
-            if (ABS(d) < 1024*1) {
-                if (!rc)
-                    m = b;
-                break;
-            }
-            if (m < 1024*8)
-                break;
-            m += d;
-        }
-        if (m < 1024*8)
-            m = 0;
-    }
-    if ((f = fopen("conftestval", "w")) == NULL)
-        exit(1);
-    fprintf(f, "%d\n", m);
-    fclose(f);
-    exit(0);
-}
->>
-changequote([, ])dnl
-,[
-MM_SHM_MAXSEGSIZE="`cat conftestval`"
-msg="$MM_SHM_MAXSEGSIZE"
-if test $msg -eq 67108864; then
-    msg="64MB (soft limit)"
-elif test $msg -gt 1048576; then
-    msg="`expr $msg / 1024`"
-    msg="`expr $msg / 1024`"
-    msg="${msg}MB"
-elif test $msg -gt 1024; then
-    msg="`expr $msg / 1024`"
-    msg="${msg}KB"
-else
-    MM_SHM_MAXSEGSIZE=0
-    msg=unknown
-fi
-],
-MM_SHM_MAXSEGSIZE=0
-msg=unknown
-,
-MM_SHM_MAXSEGSIZE=0
-msg=unknown
-)dnl
-CFLAGS="$OCFLAGS"
-test ".$msg" = .unknown && AC_MSG_ERROR([Unable to determine maximum shared memory segment size])
-AC_MSG_RESULT([$msg])
-AC_DEFINE_UNQUOTED(MM_SHM_MAXSEGSIZE, $MM_SHM_MAXSEGSIZE)
-])
diff --git a/shmem/unix/mm/config.guess b/shmem/unix/mm/config.guess
deleted file mode 100755
index 16942ccf63b..00000000000
--- a/shmem/unix/mm/config.guess
+++ /dev/null
@@ -1,1103 +0,0 @@
-#! /bin/sh
-# Attempt to guess a canonical system name.
-#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999
-#   Free Software Foundation, Inc.
-#
-# This file is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-# Written by Per Bothner <bothner@cygnus.com>.
-# The master version of this file is at the FSF in /home/gd/gnu/lib.
-# Please send patches to the Autoconf mailing list <autoconf@gnu.org>.
-#
-# This script attempts to guess a canonical system name similar to
-# config.sub.  If it succeeds, it prints the system name on stdout, and
-# exits with 0.  Otherwise, it exits with 1.
-#
-# The plan is that this can be called by configure scripts if you
-# don't specify an explicit system type (host/target name).
-#
-# Only a few systems have been added to this list; please add others
-# (but try to keep the structure clean).
-#
-
-# Use $HOST_CC if defined. $CC may point to a cross-compiler
-if test x"$CC_FOR_BUILD" = x; then
-  if test x"$HOST_CC" != x; then
-    CC_FOR_BUILD="$HOST_CC"
-  else
-    if test x"$CC" != x; then
-      CC_FOR_BUILD="$CC"
-    else
-      CC_FOR_BUILD=cc
-    fi
-  fi
-fi
-
-
-# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
-# (ghazi@noc.rutgers.edu 8/24/94.)
-if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
-	PATH=$PATH:/.attbin ; export PATH
-fi
-
-UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
-UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
-UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
-UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
-
-dummy=dummy-$$
-trap 'rm -f $dummy.c $dummy.o $dummy; exit 1' 1 2 15
-
-# Note: order is significant - the case branches are not exclusive.
-
-case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
-    alpha:OSF1:*:*)
-	if test $UNAME_RELEASE = "V4.0"; then
-		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
-	fi
-	# A Vn.n version is a released version.
-	# A Tn.n version is a released field test version.
-	# A Xn.n version is an unreleased experimental baselevel.
-	# 1.2 uses "1.2" for uname -r.
-	cat <<EOF >$dummy.s
-	.globl main
-	.ent main
-main:
-	.frame \$30,0,\$26,0
-	.prologue 0
-	.long 0x47e03d80 # implver $0
-	lda \$2,259
-	.long 0x47e20c21 # amask $2,$1
-	srl \$1,8,\$2
-	sll \$2,2,\$2
-	sll \$0,3,\$0
-	addl \$1,\$0,\$0
-	addl \$2,\$0,\$0
-	ret \$31,(\$26),1
-	.end main
-EOF
-	$CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null
-	if test "$?" = 0 ; then
-		./$dummy
-		case "$?" in
-			7)
-				UNAME_MACHINE="alpha"
-				;;
-			15)
-				UNAME_MACHINE="alphaev5"
-				;;
-			14)
-				UNAME_MACHINE="alphaev56"
-				;;
-			10)
-				UNAME_MACHINE="alphapca56"
-				;;
-			16)
-				UNAME_MACHINE="alphaev6"
-				;;
-		esac
-	fi
-	rm -f $dummy.s $dummy
-	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
-	exit 0 ;;
-    Alpha\ *:Windows_NT*:*)
-	# How do we know it's Interix rather than the generic POSIX subsystem?
-	# Should we change UNAME_MACHINE based on the output of uname instead
-	# of the specific Alpha model?
-	echo alpha-pc-interix
-	exit 0 ;;
-    21064:Windows_NT:50:3)
-	echo alpha-dec-winnt3.5
-	exit 0 ;;
-    Amiga*:UNIX_System_V:4.0:*)
-	echo m68k-cbm-sysv4
-	exit 0;;
-    amiga:NetBSD:*:*)
-      echo m68k-cbm-netbsd${UNAME_RELEASE}
-      exit 0 ;;
-    amiga:OpenBSD:*:*)
-	echo m68k-unknown-openbsd${UNAME_RELEASE}
-	exit 0 ;;
-    *:[Aa]miga[Oo][Ss]:*:*)
-	echo ${UNAME_MACHINE}-unknown-amigaos
-	exit 0 ;;
-    arc64:OpenBSD:*:*)
-	echo mips64el-unknown-openbsd${UNAME_RELEASE}
-	exit 0 ;;
-    arc:OpenBSD:*:*)
-	echo mipsel-unknown-openbsd${UNAME_RELEASE}
-	exit 0 ;;
-    hkmips:OpenBSD:*:*)
-	echo mips-unknown-openbsd${UNAME_RELEASE}
-	exit 0 ;;
-    pmax:OpenBSD:*:*)
-	echo mipsel-unknown-openbsd${UNAME_RELEASE}
-	exit 0 ;;
-    sgi:OpenBSD:*:*)
-	echo mips-unknown-openbsd${UNAME_RELEASE}
-	exit 0 ;;
-    wgrisc:OpenBSD:*:*)
-	echo mipsel-unknown-openbsd${UNAME_RELEASE}
-	exit 0 ;;
-    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
-	echo arm-acorn-riscix${UNAME_RELEASE}
-	exit 0;;
-    arm32:NetBSD:*:*)
-	echo arm-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
-	exit 0 ;;
-    SR2?01:HI-UX/MPP:*:*)
-	echo hppa1.1-hitachi-hiuxmpp
-	exit 0;;
-    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
-	# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
-	if test "`(/bin/universe) 2>/dev/null`" = att ; then
-		echo pyramid-pyramid-sysv3
-	else
-		echo pyramid-pyramid-bsd
-	fi
-	exit 0 ;;
-    NILE*:*:*:dcosx)
-	echo pyramid-pyramid-svr4
-	exit 0 ;;
-    sun4H:SunOS:5.*:*)
-	echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
-	exit 0 ;;
-    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
-	echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
-	exit 0 ;;
-    i86pc:SunOS:5.*:*)
-	echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
-	exit 0 ;;
-    sun4*:SunOS:6*:*)
-	# According to config.sub, this is the proper way to canonicalize
-	# SunOS6.  Hard to guess exactly what SunOS6 will be like, but
-	# it's likely to be more like Solaris than SunOS4.
-	echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
-	exit 0 ;;
-    sun4*:SunOS:*:*)
-	case "`/usr/bin/arch -k`" in
-	    Series*|S4*)
-		UNAME_RELEASE=`uname -v`
-		;;
-	esac
-	# Japanese Language versions have a version number like `4.1.3-JL'.
-	echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
-	exit 0 ;;
-    sun3*:SunOS:*:*)
-	echo m68k-sun-sunos${UNAME_RELEASE}
-	exit 0 ;;
-    sun*:*:4.2BSD:*)
-	UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
-	test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
-	case "`/bin/arch`" in
-	    sun3)
-		echo m68k-sun-sunos${UNAME_RELEASE}
-		;;
-	    sun4)
-		echo sparc-sun-sunos${UNAME_RELEASE}
-		;;
-	esac
-	exit 0 ;;
-    aushp:SunOS:*:*)
-	echo sparc-auspex-sunos${UNAME_RELEASE}
-	exit 0 ;;
-    atari*:NetBSD:*:*)
-	echo m68k-atari-netbsd${UNAME_RELEASE}
-	exit 0 ;;
-    atari*:OpenBSD:*:*)
-	echo m68k-unknown-openbsd${UNAME_RELEASE}
-	exit 0 ;;
-    # The situation for MiNT is a little confusing.  The machine name
-    # can be virtually everything (everything which is not
-    # "atarist" or "atariste" at least should have a processor 
-    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
-    # to the lowercase version "mint" (or "freemint").  Finally
-    # the system name "TOS" denotes a system which is actually not
-    # MiNT.  But MiNT is downward compatible to TOS, so this should
-    # be no problem.
-    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
-        echo m68k-atari-mint${UNAME_RELEASE}
-	exit 0 ;;
-    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
-	echo m68k-atari-mint${UNAME_RELEASE}
-        exit 0 ;;
-    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
-        echo m68k-atari-mint${UNAME_RELEASE}
-	exit 0 ;;
-    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
-        echo m68k-milan-mint${UNAME_RELEASE}
-        exit 0 ;;
-    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
-        echo m68k-hades-mint${UNAME_RELEASE}
-        exit 0 ;;
-    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
-        echo m68k-unknown-mint${UNAME_RELEASE}
-        exit 0 ;;
-    sun3*:NetBSD:*:*)
-	echo m68k-sun-netbsd${UNAME_RELEASE}
-	exit 0 ;;
-    sun3*:OpenBSD:*:*)
-	echo m68k-unknown-openbsd${UNAME_RELEASE}
-	exit 0 ;;
-    mac68k:NetBSD:*:*)
-	echo m68k-apple-netbsd${UNAME_RELEASE}
-	exit 0 ;;
-    mac68k:OpenBSD:*:*)
-	echo m68k-unknown-openbsd${UNAME_RELEASE}
-	exit 0 ;;
-    mvme68k:OpenBSD:*:*)
-	echo m68k-unknown-openbsd${UNAME_RELEASE}
-	exit 0 ;;
-    mvme88k:OpenBSD:*:*)
-	echo m88k-unknown-openbsd${UNAME_RELEASE}
-	exit 0 ;;
-    powerpc:machten:*:*)
-	echo powerpc-apple-machten${UNAME_RELEASE}
-	exit 0 ;;
-    macppc:NetBSD:*:*)
-        echo powerpc-apple-netbsd${UNAME_RELEASE}
-        exit 0 ;;
-    RISC*:Mach:*:*)
-	echo mips-dec-mach_bsd4.3
-	exit 0 ;;
-    RISC*:ULTRIX:*:*)
-	echo mips-dec-ultrix${UNAME_RELEASE}
-	exit 0 ;;
-    VAX*:ULTRIX*:*:*)
-	echo vax-dec-ultrix${UNAME_RELEASE}
-	exit 0 ;;
-    2020:CLIX:*:* | 2430:CLIX:*:*)
-	echo clipper-intergraph-clix${UNAME_RELEASE}
-	exit 0 ;;
-    mips:*:*:UMIPS | mips:*:*:RISCos)
-	sed 's/^	//' << EOF >$dummy.c
-#ifdef __cplusplus
-	int main (int argc, char *argv[]) {
-#else
-	int main (argc, argv) int argc; char *argv[]; {
-#endif
-	#if defined (host_mips) && defined (MIPSEB)
-	#if defined (SYSTYPE_SYSV)
-	  printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
-	#endif
-	#if defined (SYSTYPE_SVR4)
-	  printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
-	#endif
-	#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
-	  printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
-	#endif
-	#endif
-	  exit (-1);
-	}
-EOF
-	$CC_FOR_BUILD $dummy.c -o $dummy \
-	  && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
-	  && rm $dummy.c $dummy && exit 0
-	rm -f $dummy.c $dummy
-	echo mips-mips-riscos${UNAME_RELEASE}
-	exit 0 ;;
-    Night_Hawk:Power_UNIX:*:*)
-	echo powerpc-harris-powerunix
-	exit 0 ;;
-    m88k:CX/UX:7*:*)
-	echo m88k-harris-cxux7
-	exit 0 ;;
-    m88k:*:4*:R4*)
-	echo m88k-motorola-sysv4
-	exit 0 ;;
-    m88k:*:3*:R3*)
-	echo m88k-motorola-sysv3
-	exit 0 ;;
-    AViiON:dgux:*:*)
-        # DG/UX returns AViiON for all architectures
-        UNAME_PROCESSOR=`/usr/bin/uname -p`
-        if [ $UNAME_PROCESSOR = mc88100 -o $UNAME_PROCESSOR = mc88110 ] ; then
-	if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \
-	     -o ${TARGET_BINARY_INTERFACE}x = x ] ; then
-		echo m88k-dg-dgux${UNAME_RELEASE}
-	else
-		echo m88k-dg-dguxbcs${UNAME_RELEASE}
-	fi
-        else echo i586-dg-dgux${UNAME_RELEASE}
-        fi
- 	exit 0 ;;
-    M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
-	echo m88k-dolphin-sysv3
-	exit 0 ;;
-    M88*:*:R3*:*)
-	# Delta 88k system running SVR3
-	echo m88k-motorola-sysv3
-	exit 0 ;;
-    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
-	echo m88k-tektronix-sysv3
-	exit 0 ;;
-    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
-	echo m68k-tektronix-bsd
-	exit 0 ;;
-    *:IRIX*:*:*)
-	echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
-	exit 0 ;;
-    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
-	echo romp-ibm-aix      # uname -m gives an 8 hex-code CPU id
-	exit 0 ;;              # Note that: echo "'`uname -s`'" gives 'AIX '
-    i?86:AIX:*:*)
-	echo i386-ibm-aix
-	exit 0 ;;
-    *:AIX:2:3)
-	if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
-		sed 's/^		//' << EOF >$dummy.c
-		#include <sys/systemcfg.h>
-
-		main()
-			{
-			if (!__power_pc())
-				exit(1);
-			puts("powerpc-ibm-aix3.2.5");
-			exit(0);
-			}
-EOF
-		$CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm $dummy.c $dummy && exit 0
-		rm -f $dummy.c $dummy
-		echo rs6000-ibm-aix3.2.5
-	elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
-		echo rs6000-ibm-aix3.2.4
-	else
-		echo rs6000-ibm-aix3.2
-	fi
-	exit 0 ;;
-    *:AIX:*:4)
-	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'`
-	if /usr/sbin/lsattr -EHl ${IBM_CPU_ID} | grep POWER >/dev/null 2>&1; then
-		IBM_ARCH=rs6000
-	else
-		IBM_ARCH=powerpc
-	fi
-	if [ -x /usr/bin/oslevel ] ; then
-		IBM_REV=`/usr/bin/oslevel`
-	else
-		IBM_REV=4.${UNAME_RELEASE}
-	fi
-	echo ${IBM_ARCH}-ibm-aix${IBM_REV}
-	exit 0 ;;
-    *:AIX:*:*)
-	echo rs6000-ibm-aix
-	exit 0 ;;
-    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
-	echo romp-ibm-bsd4.4
-	exit 0 ;;
-    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC NetBSD and
-	echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
-	exit 0 ;;                           # report: romp-ibm BSD 4.3
-    *:BOSX:*:*)
-	echo rs6000-bull-bosx
-	exit 0 ;;
-    DPX/2?00:B.O.S.:*:*)
-	echo m68k-bull-sysv3
-	exit 0 ;;
-    9000/[34]??:4.3bsd:1.*:*)
-	echo m68k-hp-bsd
-	exit 0 ;;
-    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
-	echo m68k-hp-bsd4.4
-	exit 0 ;;
-    9000/[34678]??:HP-UX:*:*)
-	case "${UNAME_MACHINE}" in
-	    9000/31? )            HP_ARCH=m68000 ;;
-	    9000/[34]?? )         HP_ARCH=m68k ;;
-	    9000/[678][0-9][0-9])
-              sed 's/^              //' << EOF >$dummy.c
-              #include <stdlib.h>
-              #include <unistd.h>
-
-              int main ()
-              {
-              #if defined(_SC_KERNEL_BITS)
-                  long bits = sysconf(_SC_KERNEL_BITS);
-              #endif
-                  long cpu  = sysconf (_SC_CPU_VERSION);
-
-                  switch (cpu)
-              	{
-              	case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
-              	case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
-              	case CPU_PA_RISC2_0:
-              #if defined(_SC_KERNEL_BITS)
-              	    switch (bits)
-              		{
-              		case 64: puts ("hppa2.0w"); break;
-              		case 32: puts ("hppa2.0n"); break;
-              		default: puts ("hppa2.0"); break;
-              		} break;
-              #else  /* !defined(_SC_KERNEL_BITS) */
-              	    puts ("hppa2.0"); break;
-              #endif
-              	default: puts ("hppa1.0"); break;
-              	}
-                  exit (0);
-              }
-EOF
-	($CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null ) && HP_ARCH=`./$dummy`
-	rm -f $dummy.c $dummy
-	esac
-	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
-	echo ${HP_ARCH}-hp-hpux${HPUX_REV}
-	exit 0 ;;
-    3050*:HI-UX:*:*)
-	sed 's/^	//' << EOF >$dummy.c
-	#include <unistd.h>
-	int
-	main ()
-	{
-	  long cpu = sysconf (_SC_CPU_VERSION);
-	  /* The order matters, because CPU_IS_HP_MC68K erroneously returns
-	     true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
-	     results, however.  */
-	  if (CPU_IS_PA_RISC (cpu))
-	    {
-	      switch (cpu)
-		{
-		  case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
-		  case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
-		  case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
-		  default: puts ("hppa-hitachi-hiuxwe2"); break;
-		}
-	    }
-	  else if (CPU_IS_HP_MC68K (cpu))
-	    puts ("m68k-hitachi-hiuxwe2");
-	  else puts ("unknown-hitachi-hiuxwe2");
-	  exit (0);
-	}
-EOF
-	$CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm $dummy.c $dummy && exit 0
-	rm -f $dummy.c $dummy
-	echo unknown-hitachi-hiuxwe2
-	exit 0 ;;
-    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
-	echo hppa1.1-hp-bsd
-	exit 0 ;;
-    9000/8??:4.3bsd:*:*)
-	echo hppa1.0-hp-bsd
-	exit 0 ;;
-    *9??*:MPE/iX:*:*)
-	echo hppa1.0-hp-mpeix
-	exit 0 ;;
-    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
-	echo hppa1.1-hp-osf
-	exit 0 ;;
-    hp8??:OSF1:*:*)
-	echo hppa1.0-hp-osf
-	exit 0 ;;
-    i?86:OSF1:*:*)
-	if [ -x /usr/sbin/sysversion ] ; then
-	    echo ${UNAME_MACHINE}-unknown-osf1mk
-	else
-	    echo ${UNAME_MACHINE}-unknown-osf1
-	fi
-	exit 0 ;;
-    parisc*:Lites*:*:*)
-	echo hppa1.1-hp-lites
-	exit 0 ;;
-    hppa*:OpenBSD:*:*)
-	echo hppa-unknown-openbsd
-	exit 0 ;;
-    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
-	echo c1-convex-bsd
-        exit 0 ;;
-    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
-	if getsysinfo -f scalar_acc
-	then echo c32-convex-bsd
-	else echo c2-convex-bsd
-	fi
-        exit 0 ;;
-    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
-	echo c34-convex-bsd
-        exit 0 ;;
-    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
-	echo c38-convex-bsd
-        exit 0 ;;
-    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
-	echo c4-convex-bsd
-        exit 0 ;;
-    CRAY*X-MP:*:*:*)
-	echo xmp-cray-unicos
-        exit 0 ;;
-    CRAY*Y-MP:*:*:*)
-	echo ymp-cray-unicos${UNAME_RELEASE}
-	exit 0 ;;
-    CRAY*[A-Z]90:*:*:*)
-	echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
-	| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
-	      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
-	exit 0 ;;
-    CRAY*TS:*:*:*)
-	echo t90-cray-unicos${UNAME_RELEASE}
-	exit 0 ;;
-    CRAY*T3E:*:*:*)
-	echo t3e-cray-unicosmk${UNAME_RELEASE}
-	exit 0 ;;
-    CRAY-2:*:*:*)
-	echo cray2-cray-unicos
-        exit 0 ;;
-    F300:UNIX_System_V:*:*)
-        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
-        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
-        echo "f300-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
-        exit 0 ;;
-    F301:UNIX_System_V:*:*)
-       echo f301-fujitsu-uxpv`echo $UNAME_RELEASE | sed 's/ .*//'`
-       exit 0 ;;
-    hp3[0-9][05]:NetBSD:*:*)
-	echo m68k-hp-netbsd${UNAME_RELEASE}
-	exit 0 ;;
-    hp300:OpenBSD:*:*)
-	echo m68k-unknown-openbsd${UNAME_RELEASE}
-	exit 0 ;;
-    i?86:BSD/386:*:* | i?86:BSD/OS:*:*)
-	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
-	exit 0 ;;
-    sparc*:BSD/OS:*:*)
-	echo sparc-unknown-bsdi${UNAME_RELEASE}
-	exit 0 ;;
-    *:BSD/OS:*:*)
-	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
-	exit 0 ;;
-    *:FreeBSD:*:*)
-	# echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
-        VERS=`echo ${UNAME_RELEASE} | sed -e 's/[-(].*//'`
-        MACH=`sysctl -n hw.model`
-        ARCH='unknown'
-        case ${MACH} in
-           *386*       ) MACH="i386" ;;
-           *486*       ) MACH="i486" ;;
-           Pentium\ II*) MACH="i686" ;;
-           Pentium*    ) MACH="i586" ;;
-           Alpha*      ) MACH="alpha" ;;
-           *           ) MACH="$UNAME_MACHINE" ;;
-        esac
-        case ${MACH} in
-           i[0-9]86 ) ARCH="pc" ;;
-        esac
-        echo "${MACH}-${ARCH}-freebsd${VERS}"
-	exit 0 ;;
-    *:NetBSD:*:*)
-	echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
-	exit 0 ;;
-    *:OpenBSD:*:*)
-	echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
-	exit 0 ;;
-    i*:CYGWIN*:*)
-	echo ${UNAME_MACHINE}-pc-cygwin
-	exit 0 ;;
-    i*:MINGW*:*)
-	echo ${UNAME_MACHINE}-pc-mingw32
-	exit 0 ;;
-    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
-	# How do we know it's Interix rather than the generic POSIX subsystem?
-	# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
-	# UNAME_MACHINE based on the output of uname instead of i386?
-	echo i386-pc-interix
-	exit 0 ;;
-    i*:UWIN*:*)
-	echo ${UNAME_MACHINE}-pc-uwin
-	exit 0 ;;
-    p*:CYGWIN*:*)
-	echo powerpcle-unknown-cygwin
-	exit 0 ;;
-    prep*:SunOS:5.*:*)
-	echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
-	exit 0 ;;
-    *:GNU:*:*)
-	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
-	exit 0 ;;
-    *:Linux:*:*)
-	# uname on the ARM produces all sorts of strangeness, and we need to
-	# filter it out.
-	case "$UNAME_MACHINE" in
-	  armv*)		      UNAME_MACHINE=$UNAME_MACHINE ;;
-	  arm* | sa110*)	      UNAME_MACHINE="arm" ;;
-	esac
-
-	# The BFD linker knows what the default object file format is, so
-	# first see if it will tell us. cd to the root directory to prevent
-	# problems with other programs or directories called `ld' in the path.
-	ld_help_string=`cd /; ld --help 2>&1`
-	ld_supported_emulations=`echo $ld_help_string \
-			 | sed -ne '/supported emulations:/!d
-				    s/[ 	][ 	]*/ /g
-				    s/.*supported emulations: *//
-				    s/ .*//
-				    p'`
-        case "$ld_supported_emulations" in
-	  *ia64)      echo "${UNAME_MACHINE}-unknown-linux"         ; exit 0 ;;
-	  i?86linux)  echo "${UNAME_MACHINE}-pc-linux-gnuaout"      ; exit 0 ;;
-	  i?86coff)   echo "${UNAME_MACHINE}-pc-linux-gnucoff"      ; exit 0 ;;
-	  sparclinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;;
-	  armlinux)   echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;;
-	  m68klinux)  echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;;
-	  elf32ppc | elf32ppclinux)
-		# Determine Lib Version
-		cat >$dummy.c <<EOF
-#include <features.h>
-#if defined(__GLIBC__)
-extern char __libc_version[];
-extern char __libc_release[];
-#endif
-main(argc, argv)
-     int argc;
-     char *argv[];
-{
-#if defined(__GLIBC__)
-  printf("%s %s\n", __libc_version, __libc_release);
-#else
-  printf("unkown\n");
-#endif
-  return 0;
-}
-EOF
-		LIBC=""
-		$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null
-		if test "$?" = 0 ; then
-			./$dummy | grep 1\.99 > /dev/null
-			if test "$?" = 0 ; then
-				LIBC="libc1"
-			fi
-		fi	
-		rm -f $dummy.c $dummy
-		echo powerpc-unknown-linux-gnu${LIBC} ; exit 0 ;;
-	esac
-
-	if test "${UNAME_MACHINE}" = "alpha" ; then
-		sed 's/^	//'  <<EOF >$dummy.s
-		.globl main
-		.ent main
-	main:
-		.frame \$30,0,\$26,0
-		.prologue 0
-		.long 0x47e03d80 # implver $0
-		lda \$2,259
-		.long 0x47e20c21 # amask $2,$1
-		srl \$1,8,\$2
-		sll \$2,2,\$2
-		sll \$0,3,\$0
-		addl \$1,\$0,\$0
-		addl \$2,\$0,\$0
-		ret \$31,(\$26),1
-		.end main
-EOF
-		LIBC=""
-		$CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null
-		if test "$?" = 0 ; then
-			./$dummy
-			case "$?" in
-			7)
-				UNAME_MACHINE="alpha"
-				;;
-			15)
-				UNAME_MACHINE="alphaev5"
-				;;
-			14)
-				UNAME_MACHINE="alphaev56"
-				;;
-			10)
-				UNAME_MACHINE="alphapca56"
-				;;
-			16)
-				UNAME_MACHINE="alphaev6"
-				;;
-			esac
-
-			objdump --private-headers $dummy | \
-			  grep ld.so.1 > /dev/null
-			if test "$?" = 0 ; then
-				LIBC="libc1"
-			fi
-		fi
-		rm -f $dummy.s $dummy
-		echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} ; exit 0
-	elif test "${UNAME_MACHINE}" = "mips" ; then
-	  cat >$dummy.c <<EOF
-#ifdef __cplusplus
-	int main (int argc, char *argv[]) {
-#else
-	int main (argc, argv) int argc; char *argv[]; {
-#endif
-#ifdef __MIPSEB__
-  printf ("%s-unknown-linux-gnu\n", argv[1]);
-#endif
-#ifdef __MIPSEL__
-  printf ("%sel-unknown-linux-gnu\n", argv[1]);
-#endif
-  return 0;
-}
-EOF
-	  $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm $dummy.c $dummy && exit 0
-	  rm -f $dummy.c $dummy
-	else
-	  # Either a pre-BFD a.out linker (linux-gnuoldld)
-	  # or one that does not give us useful --help.
-	  # GCC wants to distinguish between linux-gnuoldld and linux-gnuaout.
-	  # If ld does not provide *any* "supported emulations:"
-	  # that means it is gnuoldld.
-	  echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations:"
-	  test $? != 0 && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0
-
-	  case "${UNAME_MACHINE}" in
-	  i?86)
-	    VENDOR=pc;
-	    ;;
-	  *)
-	    VENDOR=unknown;
-	    ;;
-	  esac
-	  # Determine whether the default compiler is a.out or elf
-	  cat >$dummy.c <<EOF
-#include <features.h>
-#ifdef __cplusplus
-	int main (int argc, char *argv[]) {
-#else
-	int main (argc, argv) int argc; char *argv[]; {
-#endif
-#ifdef __ELF__
-# ifdef __GLIBC__
-#  if __GLIBC__ >= 2
-    printf ("%s-${VENDOR}-linux-gnu\n", argv[1]);
-#  else
-    printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]);
-#  endif
-# else
-   printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]);
-# endif
-#else
-  printf ("%s-${VENDOR}-linux-gnuaout\n", argv[1]);
-#endif
-  return 0;
-}
-EOF
-	  $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm $dummy.c $dummy && exit 0
-	  rm -f $dummy.c $dummy
-	fi ;;
-# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.  earlier versions
-# are messed up and put the nodename in both sysname and nodename.
-    i?86:DYNIX/ptx:4*:*)
-	echo i386-sequent-sysv4
-	exit 0 ;;
-    i?86:UnixWare:*:* )
-        echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE}uw${UNAME_VERSION}
-        exit 0 ;;
-    i?86:UNIX_SV:4.2MP:2.*)
-        # Unixware is an offshoot of SVR4, but it has its own version
-        # number series starting with 2...
-        # I am not positive that other SVR4 systems won't match this,
-	# I just have to hope.  -- rms.
-        # Use sysv4.2uw... so that sysv4* matches it.
-	echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
-	exit 0 ;;
-    i?86:*:4.*:* | i?86:SYSTEM_V:4.*:*)
-	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
-		echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE}
-	else
-		echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE}
-	fi
-	exit 0 ;;
-    i?86:*:5:7*)
-	UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
-	(/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
-	(/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) && UNAME_MACHINE=i586
-	(/bin/uname -X|egrep '^Machine.*Pent.*II' >/dev/null) && UNAME_MACHINE=i686
-	(/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) && UNAME_MACHINE=i585
-	echo ${UNAME_MACHINE}-${UNAME_SYSTEM}${UNAME_VERSION}-sysv${UNAME_RELEASE}
-	exit 0 ;;
-    i?86:*:3.2:*)
-	if test -f /usr/options/cb.name; then
-		UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
-		echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
-	elif /bin/uname -X 2>/dev/null >/dev/null ; then
-		UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
-		(/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
-		(/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
-			&& UNAME_MACHINE=i586
-		(/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \
-			&& UNAME_MACHINE=i686
-		(/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \
-			&& UNAME_MACHINE=i686
-		echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
-	else
-		echo ${UNAME_MACHINE}-pc-sysv32
-	fi
-	exit 0 ;;
-    pc:*:*:*)
-        # uname -m prints for DJGPP always 'pc', but it prints nothing about
-        # the processor, so we play safe by assuming i386.
-	echo i386-pc-msdosdjgpp
-        exit 0 ;;
-    Intel:Mach:3*:*)
-	echo i386-pc-mach3
-	exit 0 ;;
-    paragon:*:*:*)
-	echo i860-intel-osf1
-	exit 0 ;;
-    i860:*:4.*:*) # i860-SVR4
-	if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
-	  echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
-	else # Add other i860-SVR4 vendors below as they are discovered.
-	  echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
-	fi
-	exit 0 ;;
-    mini*:CTIX:SYS*5:*)
-	# "miniframe"
-	echo m68010-convergent-sysv
-	exit 0 ;;
-    M68*:*:R3V[567]*:*)
-	test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
-    3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0)
-	OS_REL=''
-	test -r /etc/.relid \
-	&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
-	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
-	  && echo i486-ncr-sysv4.3${OS_REL} && exit 0
-	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
-	  && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
-    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
-        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
-          && echo i486-ncr-sysv4 && exit 0 ;;
-    m68*:LynxOS:2.*:*)
-	echo m68k-unknown-lynxos${UNAME_RELEASE}
-	exit 0 ;;
-    mc68030:UNIX_System_V:4.*:*)
-	echo m68k-atari-sysv4
-	exit 0 ;;
-    i?86:LynxOS:2.*:* | i?86:LynxOS:3.[01]*:*)
-	echo i386-unknown-lynxos${UNAME_RELEASE}
-	exit 0 ;;
-    TSUNAMI:LynxOS:2.*:*)
-	echo sparc-unknown-lynxos${UNAME_RELEASE}
-	exit 0 ;;
-    rs6000:LynxOS:2.*:* | PowerPC:LynxOS:2.*:*)
-	echo rs6000-unknown-lynxos${UNAME_RELEASE}
-	exit 0 ;;
-    SM[BE]S:UNIX_SV:*:*)
-	echo mips-dde-sysv${UNAME_RELEASE}
-	exit 0 ;;
-    BS2000:POSIX-BC:*:*)
-	echo bs2000-siemens-sysv4
-	exit 0 ;;
-    RM*:ReliantUNIX-*:*:*)
-	echo mips-sni-sysv4
-	exit 0 ;;
-    RM*:SINIX-*:*:*)
-	echo mips-sni-sysv4
-	exit 0 ;;
-    *:SINIX-*:*:*)
-	if uname -p 2>/dev/null >/dev/null ; then
-		UNAME_MACHINE=`(uname -p) 2>/dev/null`
-		echo ${UNAME_MACHINE}-sni-sysv4
-	else
-		echo ns32k-sni-sysv
-	fi
-	exit 0 ;;
-    PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
-                           # says <Richard.M.Bartel@ccMail.Census.GOV>
-        echo i586-unisys-sysv4
-        exit 0 ;;
-    *:UNIX_System_V:4*:FTX*)
-	# From Gerald Hewes <hewes@openmarket.com>.
-	# How about differentiating between stratus architectures? -djm
-	echo hppa1.1-stratus-sysv4
-	exit 0 ;;
-    *:*:*:FTX*)
-	# From seanf@swdc.stratus.com.
-	echo i860-stratus-sysv4
-	exit 0 ;;
-    mc68*:A/UX:*:*)
-	echo m68k-apple-aux${UNAME_RELEASE}
-	exit 0 ;;
-    news*:NEWS-OS:*:6*)
-	echo mips-sony-newsos6
-	exit 0 ;;
-    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
-	if [ -d /usr/nec ]; then
-	        echo mips-nec-sysv${UNAME_RELEASE}
-	else
-	        echo mips-unknown-sysv${UNAME_RELEASE}
-	fi
-        exit 0 ;;
-    BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
-	echo powerpc-be-beos
-	exit 0 ;;
-    BeMac:BeOS:*:*)	# BeOS running on Mac or Mac clone, PPC only.
-	echo powerpc-apple-beos
-	exit 0 ;;
-    BePC:BeOS:*:*)	# BeOS running on Intel PC compatible.
-	echo i586-pc-beos
-	exit 0 ;;
-    SX-4:SUPER-UX:*:*)
-	echo sx4-nec-superux${UNAME_RELEASE}
-	exit 0 ;;
-    SX-5:SUPER-UX:*:*)
-	echo sx5-nec-superux${UNAME_RELEASE}
-	exit 0 ;;
-    Power*:Rhapsody:*:*)
-	echo powerpc-apple-rhapsody${UNAME_RELEASE}
-	exit 0 ;;
-    *:Rhapsody:*:*)
-	echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
-	exit 0 ;;
-esac
-
-#echo '(No uname command or uname output not recognized.)' 1>&2
-#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
-
-cat >$dummy.c <<EOF
-#ifdef _SEQUENT_
-# include <sys/types.h>
-# include <sys/utsname.h>
-#endif
-main ()
-{
-#if defined (sony)
-#if defined (MIPSEB)
-  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
-     I don't know....  */
-  printf ("mips-sony-bsd\n"); exit (0);
-#else
-#include <sys/param.h>
-  printf ("m68k-sony-newsos%s\n",
-#ifdef NEWSOS4
-          "4"
-#else
-	  ""
-#endif
-         ); exit (0);
-#endif
-#endif
-
-#if defined (__arm) && defined (__acorn) && defined (__unix)
-  printf ("arm-acorn-riscix"); exit (0);
-#endif
-
-#if defined (hp300) && !defined (hpux)
-  printf ("m68k-hp-bsd\n"); exit (0);
-#endif
-
-#if defined (NeXT)
-#if !defined (__ARCHITECTURE__)
-#define __ARCHITECTURE__ "m68k"
-#endif
-  int version;
-  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
-  if (version < 4)
-    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
-  else
-    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
-  exit (0);
-#endif
-
-#if defined (MULTIMAX) || defined (n16)
-#if defined (UMAXV)
-  printf ("ns32k-encore-sysv\n"); exit (0);
-#else
-#if defined (CMU)
-  printf ("ns32k-encore-mach\n"); exit (0);
-#else
-  printf ("ns32k-encore-bsd\n"); exit (0);
-#endif
-#endif
-#endif
-
-#if defined (__386BSD__)
-  printf ("i386-pc-bsd\n"); exit (0);
-#endif
-
-#if defined (sequent)
-#if defined (i386)
-  printf ("i386-sequent-dynix\n"); exit (0);
-#endif
-#if defined (ns32000)
-  printf ("ns32k-sequent-dynix\n"); exit (0);
-#endif
-#endif
-
-#if defined (_SEQUENT_)
-    struct utsname un;
-
-    uname(&un);
-
-    if (strncmp(un.version, "V2", 2) == 0) {
-	printf ("i386-sequent-ptx2\n"); exit (0);
-    }
-    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
-	printf ("i386-sequent-ptx1\n"); exit (0);
-    }
-    printf ("i386-sequent-ptx\n"); exit (0);
-
-#endif
-
-#if defined (vax)
-#if !defined (ultrix)
-  printf ("vax-dec-bsd\n"); exit (0);
-#else
-  printf ("vax-dec-ultrix\n"); exit (0);
-#endif
-#endif
-
-#if defined (alliant) && defined (i860)
-  printf ("i860-alliant-bsd\n"); exit (0);
-#endif
-
-  exit (1);
-}
-EOF
-
-$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm $dummy.c $dummy && exit 0
-rm -f $dummy.c $dummy
-
-# Apollos put the system type in the environment.
-
-test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
-
-# Convex versions that predate uname can use getsysinfo(1)
-
-if [ -x /usr/convex/getsysinfo ]
-then
-    case `getsysinfo -f cpu_type` in
-    c1*)
-	echo c1-convex-bsd
-	exit 0 ;;
-    c2*)
-	if getsysinfo -f scalar_acc
-	then echo c32-convex-bsd
-	else echo c2-convex-bsd
-	fi
-	exit 0 ;;
-    c34*)
-	echo c34-convex-bsd
-	exit 0 ;;
-    c38*)
-	echo c38-convex-bsd
-	exit 0 ;;
-    c4*)
-	echo c4-convex-bsd
-	exit 0 ;;
-    esac
-fi
-
-#echo '(Unable to guess system type)' 1>&2
-
-exit 1
diff --git a/shmem/unix/mm/config.sub b/shmem/unix/mm/config.sub
deleted file mode 100755
index 0fd1ade4a9c..00000000000
--- a/shmem/unix/mm/config.sub
+++ /dev/null
@@ -1,1219 +0,0 @@
-#! /bin/sh
-# Configuration validation subroutine script, version 1.1.
-#   Copyright (C) 1991, 92-97, 1998, 1999 Free Software Foundation, Inc.
-# This file is (in principle) common to ALL GNU software.
-# The presence of a machine in this file suggests that SOME GNU software
-# can handle that machine.  It does not imply ALL GNU software can.
-#
-# This file is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-# Configuration subroutine to validate and canonicalize a configuration type.
-# Supply the specified configuration type as an argument.
-# If it is invalid, we print an error message on stderr and exit with code 1.
-# Otherwise, we print the canonical config type on stdout and succeed.
-
-# This file is supposed to be the same for all GNU packages
-# and recognize all the CPU types, system types and aliases
-# that are meaningful with *any* GNU software.
-# Each package is responsible for reporting which valid configurations
-# it does not support.  The user should be able to distinguish
-# a failure to support a valid configuration from a meaningless
-# configuration.
-
-# The goal of this file is to map all the various variations of a given
-# machine specification into a single specification in the form:
-#	CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
-# or in some cases, the newer four-part form:
-#	CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
-# It is wrong to echo any other type of specification.
-
-if [ x$1 = x ]
-then
-	echo Configuration name missing. 1>&2
-	echo "Usage: $0 CPU-MFR-OPSYS" 1>&2
-	echo "or     $0 ALIAS" 1>&2
-	echo where ALIAS is a recognized configuration type. 1>&2
-	exit 1
-fi
-
-# First pass through any local machine types.
-case $1 in
-	*local*)
-		echo $1
-		exit 0
-		;;
-	*)
-	;;
-esac
-
-# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
-# Here we must recognize all the valid KERNEL-OS combinations.
-maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
-case $maybe_os in
-  linux-gnu*)
-    os=-$maybe_os
-    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
-    ;;
-  *)
-    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
-    if [ $basic_machine != $1 ]
-    then os=`echo $1 | sed 's/.*-/-/'`
-    else os=; fi
-    ;;
-esac
-
-### Let's recognize common machines as not being operating systems so
-### that things like config.sub decstation-3100 work.  We also
-### recognize some manufacturers as not being operating systems, so we
-### can provide default operating systems below.
-case $os in
-	-sun*os*)
-		# Prevent following clause from handling this invalid input.
-		;;
-	-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
-	-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
-	-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
-	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
-	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
-	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
-	-apple)
-		os=
-		basic_machine=$1
-		;;
-	-sim | -cisco | -oki | -wec | -winbond)
-		os=
-		basic_machine=$1
-		;;
-	-scout)
-		;;
-	-wrs)
-		os=vxworks
-		basic_machine=$1
-		;;
-	-hiux*)
-		os=-hiuxwe2
-		;;
-	-sco5)
-		os=-sco3.2v5
-		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
-		;;
-	-sco4)
-		os=-sco3.2v4
-		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
-		;;
-	-sco3.2.[4-9]*)
-		os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
-		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
-		;;
-	-sco3.2v[4-9]*)
-		# Don't forget version if it is 3.2v4 or newer.
-		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
-		;;
-	-sco*)
-		os=-sco3.2v2
-		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
-		;;
-	-udk*)
-		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
-		;;
-	-isc)
-		os=-isc2.2
-		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
-		;;
-	-clix*)
-		basic_machine=clipper-intergraph
-		;;
-	-isc*)
-		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
-		;;
-	-lynx*)
-		os=-lynxos
-		;;
-	-ptx*)
-		basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
-		;;
-	-windowsnt*)
-		os=`echo $os | sed -e 's/windowsnt/winnt/'`
-		;;
-	-psos*)
-		os=-psos
-		;;
-esac
-
-# Decode aliases for certain CPU-COMPANY combinations.
-case $basic_machine in
-	# Recognize the basic CPU types without company name.
-	# Some are omitted here because they have special meanings below.
-	tahoe | i860 | ia64 | m32r | m68k | m68000 | m88k | ns32k | arc | arm \
-		| arme[lb] | pyramid | mn10200 | mn10300 | tron | a29k \
-		| 580 | i960 | h8300 \
-		| hppa | hppa1.0 | hppa1.1 | hppa2.0 | hppa2.0w | hppa2.0n \
-		| alpha | alphaev[4-7] | alphaev56 | alphapca5[67] \
-		| we32k | ns16k | clipper | i370 | sh | powerpc | powerpcle \
-		| 1750a | dsp16xx | pdp11 | mips16 | mips64 | mipsel | mips64el \
-		| mips64orion | mips64orionel | mipstx39 | mipstx39el \
-		| mips64vr4300 | mips64vr4300el | mips64vr4100 | mips64vr4100el \
-		| mips64vr5000 | miprs64vr5000el | mcore \
-		| sparc | sparclet | sparclite | sparc64 | sparcv9 | v850 | c4x \
-		| thumb | d10v)
-		basic_machine=$basic_machine-unknown
-		;;
-	m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | z8k | v70 | h8500 | w65)
-		;;
-
-	# We use `pc' rather than `unknown'
-	# because (1) that's what they normally are, and
-	# (2) the word "unknown" tends to confuse beginning users.
-	i[34567]86)
-	  basic_machine=$basic_machine-pc
-	  ;;
-	# Object if more than one company name word.
-	*-*-*)
-		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
-		exit 1
-		;;
-	# Recognize the basic CPU types with company name.
-	# FIXME: clean up the formatting here.
-	vax-* | tahoe-* | i[34567]86-* | i860-* | ia64-* | m32r-* | m68k-* | m68000-* \
-	      | m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | arm-* | c[123]* \
-	      | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \
-	      | power-* | none-* | 580-* | cray2-* | h8300-* | h8500-* | i960-* \
-	      | xmp-* | ymp-* \
-	      | hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* | hppa2.0w-* | hppa2.0n-* \
-	      | alpha-* | alphaev[4-7]-* | alphaev56-* | alphapca5[67]-* \
-	      | we32k-* | cydra-* | ns16k-* | pn-* | np1-* | xps100-* \
-	      | clipper-* | orion-* \
-	      | sparclite-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \
-	      | sparc64-* | sparcv9-* | sparc86x-* | mips16-* | mips64-* | mipsel-* \
-	      | mips64el-* | mips64orion-* | mips64orionel-* \
-	      | mips64vr4100-* | mips64vr4100el-* | mips64vr4300-* | mips64vr4300el-* \
-	      | mipstx39-* | mipstx39el-* | mcore-* \
-	      | f301-* | armv*-* | t3e-* \
-	      | m88110-* | m680[01234]0-* | m683?2-* | m68360-* | z8k-* | d10v-* \
-	      | thumb-* | v850-* | d30v-* | tic30-* | c30-* )
-		;;
-	# Recognize the various machine names and aliases which stand
-	# for a CPU type and a company and sometimes even an OS.
-	386bsd)
-		basic_machine=i386-unknown
-		os=-bsd
-		;;
-	3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
-		basic_machine=m68000-att
-		;;
-	3b*)
-		basic_machine=we32k-att
-		;;
-	a29khif)
-		basic_machine=a29k-amd
-		os=-udi
-		;;
-	adobe68k)
-		basic_machine=m68010-adobe
-		os=-scout
-		;;
-	alliant | fx80)
-		basic_machine=fx80-alliant
-		;;
-	altos | altos3068)
-		basic_machine=m68k-altos
-		;;
-	am29k)
-		basic_machine=a29k-none
-		os=-bsd
-		;;
-	amdahl)
-		basic_machine=580-amdahl
-		os=-sysv
-		;;
-	amiga | amiga-*)
-		basic_machine=m68k-cbm
-		;;
-	amigaos | amigados)
-		basic_machine=m68k-cbm
-		os=-amigaos
-		;;
-	amigaunix | amix)
-		basic_machine=m68k-cbm
-		os=-sysv4
-		;;
-	apollo68)
-		basic_machine=m68k-apollo
-		os=-sysv
-		;;
-	apollo68bsd)
-		basic_machine=m68k-apollo
-		os=-bsd
-		;;
-	aux)
-		basic_machine=m68k-apple
-		os=-aux
-		;;
-	balance)
-		basic_machine=ns32k-sequent
-		os=-dynix
-		;;
-	convex-c1)
-		basic_machine=c1-convex
-		os=-bsd
-		;;
-	convex-c2)
-		basic_machine=c2-convex
-		os=-bsd
-		;;
-	convex-c32)
-		basic_machine=c32-convex
-		os=-bsd
-		;;
-	convex-c34)
-		basic_machine=c34-convex
-		os=-bsd
-		;;
-	convex-c38)
-		basic_machine=c38-convex
-		os=-bsd
-		;;
-	cray | ymp)
-		basic_machine=ymp-cray
-		os=-unicos
-		;;
-	cray2)
-		basic_machine=cray2-cray
-		os=-unicos
-		;;
-	[ctj]90-cray)
-		basic_machine=c90-cray
-		os=-unicos
-		;;
-	crds | unos)
-		basic_machine=m68k-crds
-		;;
-	da30 | da30-*)
-		basic_machine=m68k-da30
-		;;
-	decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
-		basic_machine=mips-dec
-		;;
-	delta | 3300 | motorola-3300 | motorola-delta \
-	      | 3300-motorola | delta-motorola)
-		basic_machine=m68k-motorola
-		;;
-	delta88)
-		basic_machine=m88k-motorola
-		os=-sysv3
-		;;
-	dpx20 | dpx20-*)
-		basic_machine=rs6000-bull
-		os=-bosx
-		;;
-	dpx2* | dpx2*-bull)
-		basic_machine=m68k-bull
-		os=-sysv3
-		;;
-	ebmon29k)
-		basic_machine=a29k-amd
-		os=-ebmon
-		;;
-	elxsi)
-		basic_machine=elxsi-elxsi
-		os=-bsd
-		;;
-	encore | umax | mmax)
-		basic_machine=ns32k-encore
-		;;
-	es1800 | OSE68k | ose68k | ose | OSE)
-		basic_machine=m68k-ericsson
-		os=-ose
-		;;
-	fx2800)
-		basic_machine=i860-alliant
-		;;
-	genix)
-		basic_machine=ns32k-ns
-		;;
-	gmicro)
-		basic_machine=tron-gmicro
-		os=-sysv
-		;;
-	h3050r* | hiux*)
-		basic_machine=hppa1.1-hitachi
-		os=-hiuxwe2
-		;;
-	h8300hms)
-		basic_machine=h8300-hitachi
-		os=-hms
-		;;
-	h8300xray)
-		basic_machine=h8300-hitachi
-		os=-xray
-		;;
-	h8500hms)
-		basic_machine=h8500-hitachi
-		os=-hms
-		;;
-	harris)
-		basic_machine=m88k-harris
-		os=-sysv3
-		;;
-	hp300-*)
-		basic_machine=m68k-hp
-		;;
-	hp300bsd)
-		basic_machine=m68k-hp
-		os=-bsd
-		;;
-	hp300hpux)
-		basic_machine=m68k-hp
-		os=-hpux
-		;;
-	hp3k9[0-9][0-9] | hp9[0-9][0-9])
-		basic_machine=hppa1.0-hp
-		;;
-	hp9k2[0-9][0-9] | hp9k31[0-9])
-		basic_machine=m68000-hp
-		;;
-	hp9k3[2-9][0-9])
-		basic_machine=m68k-hp
-		;;
-	hp9k6[0-9][0-9] | hp6[0-9][0-9])
-		basic_machine=hppa1.0-hp
-		;;
-	hp9k7[0-79][0-9] | hp7[0-79][0-9])
-		basic_machine=hppa1.1-hp
-		;;
-	hp9k78[0-9] | hp78[0-9])
-		# FIXME: really hppa2.0-hp
-		basic_machine=hppa1.1-hp
-		;;
-	hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
-		# FIXME: really hppa2.0-hp
-		basic_machine=hppa1.1-hp
-		;;
-	hp9k8[0-9][13679] | hp8[0-9][13679])
-		basic_machine=hppa1.1-hp
-		;;
-	hp9k8[0-9][0-9] | hp8[0-9][0-9])
-		basic_machine=hppa1.0-hp
-		;;
-	hppa-next)
-		os=-nextstep3
-		;;
-	hppaosf)
-		basic_machine=hppa1.1-hp
-		os=-osf
-		;;
-	hppro)
-		basic_machine=hppa1.1-hp
-		os=-proelf
-		;;
-	i370-ibm* | ibm*)
-		basic_machine=i370-ibm
-		os=-mvs
-		;;
-# I'm not sure what "Sysv32" means.  Should this be sysv3.2?
-	i[34567]86v32)
-		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
-		os=-sysv32
-		;;
-	i[34567]86v4*)
-		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
-		os=-sysv4
-		;;
-	i[34567]86v)
-		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
-		os=-sysv
-		;;
-	i[34567]86sol2)
-		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
-		os=-solaris2
-		;;
-	i386mach)
-		basic_machine=i386-mach
-		os=-mach
-		;;
-	i386-vsta | vsta)
-		basic_machine=i386-unknown
-		os=-vsta
-		;;
-	i386-go32 | go32)
-		basic_machine=i386-unknown
-		os=-go32
-		;;
-	i386-mingw32 | mingw32)
-		basic_machine=i386-unknown
-		os=-mingw32
-		;;
-	iris | iris4d)
-		basic_machine=mips-sgi
-		case $os in
-		    -irix*)
-			;;
-		    *)
-			os=-irix4
-			;;
-		esac
-		;;
-	isi68 | isi)
-		basic_machine=m68k-isi
-		os=-sysv
-		;;
-	m88k-omron*)
-		basic_machine=m88k-omron
-		;;
-	magnum | m3230)
-		basic_machine=mips-mips
-		os=-sysv
-		;;
-	merlin)
-		basic_machine=ns32k-utek
-		os=-sysv
-		;;
-	miniframe)
-		basic_machine=m68000-convergent
-		;;
-	*mint | *MiNT)
-		basic_machine=m68k-atari
-		os=-mint
-		;;
-	mipsel*-linux*)
-		basic_machine=mipsel-unknown
-		os=-linux-gnu
-		;;
-	mips*-linux*)
-		basic_machine=mips-unknown
-		os=-linux-gnu
-		;;
-	mips3*-*)
-		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
-		;;
-	mips3*)
-		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
-		;;
-	monitor)
-		basic_machine=m68k-rom68k
-		os=-coff
-		;;
-	msdos)
-		basic_machine=i386-unknown
-		os=-msdos
-		;;
-	ncr3000)
-		basic_machine=i486-ncr
-		os=-sysv4
-		;;
-	netbsd386)
-		basic_machine=i386-unknown
-		os=-netbsd
-		;;
-	netwinder)
-		basic_machine=armv4l-corel
-		os=-linux
-		;;
-	news | news700 | news800 | news900)
-		basic_machine=m68k-sony
-		os=-newsos
-		;;
-	news1000)
-		basic_machine=m68030-sony
-		os=-newsos
-		;;
-	news-3600 | risc-news)
-		basic_machine=mips-sony
-		os=-newsos
-		;;
-	necv70)
-		basic_machine=v70-nec
-		os=-sysv
-		;;
-	next | m*-next )
-		basic_machine=m68k-next
-		case $os in
-		    -nextstep* )
-			;;
-		    -ns2*)
-		      os=-nextstep2
-			;;
-		    *)
-		      os=-nextstep3
-			;;
-		esac
-		;;
-	nh3000)
-		basic_machine=m68k-harris
-		os=-cxux
-		;;
-	nh[45]000)
-		basic_machine=m88k-harris
-		os=-cxux
-		;;
-	nindy960)
-		basic_machine=i960-intel
-		os=-nindy
-		;;
-	mon960)
-		basic_machine=i960-intel
-		os=-mon960
-		;;
-	np1)
-		basic_machine=np1-gould
-		;;
-	op50n-* | op60c-*)
-		basic_machine=hppa1.1-oki
-		os=-proelf
-		;;
-	OSE68000 | ose68000)
-		basic_machine=m68000-ericsson
-		os=-ose
-		;;
-	os68k)
-		basic_machine=m68k-none
-		os=-os68k
-		;;
-	pa-hitachi)
-		basic_machine=hppa1.1-hitachi
-		os=-hiuxwe2
-		;;
-	paragon)
-		basic_machine=i860-intel
-		os=-osf
-		;;
-	pbd)
-		basic_machine=sparc-tti
-		;;
-	pbb)
-		basic_machine=m68k-tti
-		;;
-        pc532 | pc532-*)
-		basic_machine=ns32k-pc532
-		;;
-	pentium | p5 | k5 | k6 | nexen)
-		basic_machine=i586-pc
-		;;
-	pentiumpro | p6 | 6x86)
-		basic_machine=i686-pc
-		;;
-	pentiumii | pentium2)
-		basic_machine=i786-pc
-		;;
-	pentium-* | p5-* | k5-* | k6-* | nexen-*)
-		basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
-		;;
-	pentiumpro-* | p6-* | 6x86-*)
-		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
-		;;
-	pentiumii-* | pentium2-*)
-		basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
-		;;
-	pn)
-		basic_machine=pn-gould
-		;;
-	power)	basic_machine=rs6000-ibm
-		;;
-	ppc)	basic_machine=powerpc-unknown
-	        ;;
-	ppc-*)	basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
-		;;
-	ppcle | powerpclittle | ppc-le | powerpc-little)
-		basic_machine=powerpcle-unknown
-	        ;;
-	ppcle-* | powerpclittle-*)
-		basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
-		;;
-	ps2)
-		basic_machine=i386-ibm
-		;;
-	rom68k)
-		basic_machine=m68k-rom68k
-		os=-coff
-		;;
-	rm[46]00)
-		basic_machine=mips-siemens
-		;;
-	rtpc | rtpc-*)
-		basic_machine=romp-ibm
-		;;
-	sa29200)
-		basic_machine=a29k-amd
-		os=-udi
-		;;
-	sequent)
-		basic_machine=i386-sequent
-		;;
-	sh)
-		basic_machine=sh-hitachi
-		os=-hms
-		;;
-	sparclite-wrs)
-		basic_machine=sparclite-wrs
-		os=-vxworks
-		;;
-	sps7)
-		basic_machine=m68k-bull
-		os=-sysv2
-		;;
-	spur)
-		basic_machine=spur-unknown
-		;;
-	st2000)
-		basic_machine=m68k-tandem
-		;;
-	stratus)
-		basic_machine=i860-stratus
-		os=-sysv4
-		;;
-	sun2)
-		basic_machine=m68000-sun
-		;;
-	sun2os3)
-		basic_machine=m68000-sun
-		os=-sunos3
-		;;
-	sun2os4)
-		basic_machine=m68000-sun
-		os=-sunos4
-		;;
-	sun3os3)
-		basic_machine=m68k-sun
-		os=-sunos3
-		;;
-	sun3os4)
-		basic_machine=m68k-sun
-		os=-sunos4
-		;;
-	sun4os3)
-		basic_machine=sparc-sun
-		os=-sunos3
-		;;
-	sun4os4)
-		basic_machine=sparc-sun
-		os=-sunos4
-		;;
-	sun4sol2)
-		basic_machine=sparc-sun
-		os=-solaris2
-		;;
-	sun3 | sun3-*)
-		basic_machine=m68k-sun
-		;;
-	sun4)
-		basic_machine=sparc-sun
-		;;
-	sun386 | sun386i | roadrunner)
-		basic_machine=i386-sun
-		;;
-	symmetry)
-		basic_machine=i386-sequent
-		os=-dynix
-		;;
-	t3e)
-		basic_machine=t3e-cray
-		os=-unicos
-		;;
-	tx39)
-		basic_machine=mipstx39-unknown
-		;;
-	tx39el)
-		basic_machine=mipstx39el-unknown
-		;;
-	tower | tower-32)
-		basic_machine=m68k-ncr
-		;;
-	udi29k)
-		basic_machine=a29k-amd
-		os=-udi
-		;;
-	ultra3)
-		basic_machine=a29k-nyu
-		os=-sym1
-		;;
-	v810 | necv810)
-		basic_machine=v810-nec
-		os=-none
-		;;
-	vaxv)
-		basic_machine=vax-dec
-		os=-sysv
-		;;
-	vms)
-		basic_machine=vax-dec
-		os=-vms
-		;;
-	vpp*|vx|vx-*)
-               basic_machine=f301-fujitsu
-               ;;
-	vxworks960)
-		basic_machine=i960-wrs
-		os=-vxworks
-		;;
-	vxworks68)
-		basic_machine=m68k-wrs
-		os=-vxworks
-		;;
-	vxworks29k)
-		basic_machine=a29k-wrs
-		os=-vxworks
-		;;
-	w65*)
-		basic_machine=w65-wdc
-		os=-none
-		;;
-	w89k-*)
-		basic_machine=hppa1.1-winbond
-		os=-proelf
-		;;
-	xmp)
-		basic_machine=xmp-cray
-		os=-unicos
-		;;
-        xps | xps100)
-		basic_machine=xps100-honeywell
-		;;
-	z8k-*-coff)
-		basic_machine=z8k-unknown
-		os=-sim
-		;;
-	none)
-		basic_machine=none-none
-		os=-none
-		;;
-
-# Here we handle the default manufacturer of certain CPU types.  It is in
-# some cases the only manufacturer, in others, it is the most popular.
-	w89k)
-		basic_machine=hppa1.1-winbond
-		;;
-	op50n)
-		basic_machine=hppa1.1-oki
-		;;
-	op60c)
-		basic_machine=hppa1.1-oki
-		;;
-	mips)
-		if [ x$os = x-linux-gnu ]; then
-			basic_machine=mips-unknown
-		else
-			basic_machine=mips-mips
-		fi
-		;;
-	romp)
-		basic_machine=romp-ibm
-		;;
-	rs6000)
-		basic_machine=rs6000-ibm
-		;;
-	vax)
-		basic_machine=vax-dec
-		;;
-	pdp11)
-		basic_machine=pdp11-dec
-		;;
-	we32k)
-		basic_machine=we32k-att
-		;;
-	sparc | sparcv9)
-		basic_machine=sparc-sun
-		;;
-        cydra)
-		basic_machine=cydra-cydrome
-		;;
-	orion)
-		basic_machine=orion-highlevel
-		;;
-	orion105)
-		basic_machine=clipper-highlevel
-		;;
-	mac | mpw | mac-mpw)
-		basic_machine=m68k-apple
-		;;
-	pmac | pmac-mpw)
-		basic_machine=powerpc-apple
-		;;
-	c4x*)
-		basic_machine=c4x-none
-		os=-coff
-		;;
-	bs2000-siemens)
-		;;
-	*)
-		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
-		exit 1
-		;;
-esac
-
-# Here we canonicalize certain aliases for manufacturers.
-case $basic_machine in
-	*-digital*)
-		basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
-		;;
-	*-commodore*)
-		basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
-		;;
-	*)
-		;;
-esac
-
-# Decode manufacturer-specific aliases for certain operating systems.
-
-if [ x"$os" != x"" ]
-then
-case $os in
-        # First match some system type aliases
-        # that might get confused with valid system types.
-	# -solaris* is a basic system type, with this one exception.
-	-solaris1 | -solaris1.*)
-		os=`echo $os | sed -e 's|solaris1|sunos4|'`
-		;;
-	-solaris)
-		os=-solaris2
-		;;
-	-svr4*)
-		os=-sysv4
-		;;
-	-unixware*)
-		os=-sysv4.2uw
-		;;
-	-gnu/linux*)
-		os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
-		;;
-	# First accept the basic system types.
-	# The portable systems comes first.
-	# Each alternative MUST END IN A *, to match a version number.
-	# -sysv* is not here because it comes later, after sysvr4.
-	-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
-	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
-	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
-	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
-	      | -aos* \
-	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
-	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
-	      | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
-	      | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
-	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
-	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
-	      | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
-	      | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
-	      | -interix* | -uwin* | -rhapsody* | -openstep* | -oskit*)
-	# Remember, each alternative MUST END IN *, to match a version number.
-		;;
-	-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
-	      | -windows* | -osx | -abug | -netware* | -os9* | -beos* \
-	      | -macos* | -mpw* | -magic* | -mon960* | -lnews*)
-		;;
-	-mac*)
-		os=`echo $os | sed -e 's|mac|macos|'`
-		;;
-	-linux*)
-		os=`echo $os | sed -e 's|linux|linux-gnu|'`
-		;;
-	-sunos5*)
-		os=`echo $os | sed -e 's|sunos5|solaris2|'`
-		;;
-	-sunos6*)
-		os=`echo $os | sed -e 's|sunos6|solaris3|'`
-		;;
-	-osfrose*)
-		os=-osfrose
-		;;
-	-osf*)
-		os=-osf
-		;;
-	-utek*)
-		os=-bsd
-		;;
-	-dynix*)
-		os=-bsd
-		;;
-	-acis*)
-		os=-aos
-		;;
-	-386bsd)
-		os=-bsd
-		;;
-	-ctix* | -uts*)
-		os=-sysv
-		;;
-	-ns2 )
-	        os=-nextstep2
-		;;
-	# Preserve the version number of sinix5.
-	-sinix5.*)
-		os=`echo $os | sed -e 's|sinix|sysv|'`
-		;;
-	-sinix*)
-		os=-sysv4
-		;;
-	-triton*)
-		os=-sysv3
-		;;
-	-oss*)
-		os=-sysv3
-		;;
-	-svr4)
-		os=-sysv4
-		;;
-	-svr3)
-		os=-sysv3
-		;;
-	-sysvr4)
-		os=-sysv4
-		;;
-	# This must come after -sysvr4.
-	-sysv*)
-		;;
-	-ose*)
-		os=-ose
-		;;
-	-es1800*)
-		os=-ose
-		;;
-	-xenix)
-		os=-xenix
-		;;
-        -*mint | -*MiNT)
-	        os=-mint
-		;;
-	-none)
-		;;
-	*)
-		# Get rid of the `-' at the beginning of $os.
-		os=`echo $os | sed 's/[^-]*-//'`
-		echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
-		exit 1
-		;;
-esac
-else
-
-# Here we handle the default operating systems that come with various machines.
-# The value should be what the vendor currently ships out the door with their
-# machine or put another way, the most popular os provided with the machine.
-
-# Note that if you're going to try to match "-MANUFACTURER" here (say,
-# "-sun"), then you have to tell the case statement up towards the top
-# that MANUFACTURER isn't an operating system.  Otherwise, code above
-# will signal an error saying that MANUFACTURER isn't an operating
-# system, and we'll never get to this point.
-
-case $basic_machine in
-	*-acorn)
-		os=-riscix1.2
-		;;
-	arm*-corel)
-		os=-linux
-		;;
-	arm*-semi)
-		os=-aout
-		;;
-        pdp11-*)
-		os=-none
-		;;
-	*-dec | vax-*)
-		os=-ultrix4.2
-		;;
-	m68*-apollo)
-		os=-domain
-		;;
-	i386-sun)
-		os=-sunos4.0.2
-		;;
-	m68000-sun)
-		os=-sunos3
-		# This also exists in the configure program, but was not the
-		# default.
-		# os=-sunos4
-		;;
-	m68*-cisco)
-		os=-aout
-		;;
-	mips*-cisco)
-		os=-elf
-		;;
-	mips*-*)
-		os=-elf
-		;;
-	*-tti)	# must be before sparc entry or we get the wrong os.
-		os=-sysv3
-		;;
-	sparc-* | *-sun)
-		os=-sunos4.1.1
-		;;
-	*-be)
-		os=-beos
-		;;
-	*-ibm)
-		os=-aix
-		;;
-	*-wec)
-		os=-proelf
-		;;
-	*-winbond)
-		os=-proelf
-		;;
-	*-oki)
-		os=-proelf
-		;;
-	*-hp)
-		os=-hpux
-		;;
-	*-hitachi)
-		os=-hiux
-		;;
-	i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
-		os=-sysv
-		;;
-	*-cbm)
-		os=-amigaos
-		;;
-	*-dg)
-		os=-dgux
-		;;
-	*-dolphin)
-		os=-sysv3
-		;;
-	m68k-ccur)
-		os=-rtu
-		;;
-	m88k-omron*)
-		os=-luna
-		;;
-	*-next )
-		os=-nextstep
-		;;
-	*-sequent)
-		os=-ptx
-		;;
-	*-crds)
-		os=-unos
-		;;
-	*-ns)
-		os=-genix
-		;;
-	i370-*)
-		os=-mvs
-		;;
-	*-next)
-		os=-nextstep3
-		;;
-        *-gould)
-		os=-sysv
-		;;
-        *-highlevel)
-		os=-bsd
-		;;
-	*-encore)
-		os=-bsd
-		;;
-        *-sgi)
-		os=-irix
-		;;
-        *-siemens)
-		os=-sysv4
-		;;
-	*-masscomp)
-		os=-rtu
-		;;
-	f301-fujitsu)
-		os=-uxpv
-		;;
-	*-rom68k)
-		os=-coff
-		;;
-	*-*bug)
-		os=-coff
-		;;
-	*-apple)
-		os=-macos
-		;;
-	*-atari*)
-		os=-mint
-		;;
-	*)
-		os=-none
-		;;
-esac
-fi
-
-# Here we handle the case where we know the os, and the CPU type, but not the
-# manufacturer.  We pick the logical manufacturer.
-vendor=unknown
-case $basic_machine in
-	*-unknown)
-		case $os in
-			-riscix*)
-				vendor=acorn
-				;;
-			-sunos*)
-				vendor=sun
-				;;
-			-aix*)
-				vendor=ibm
-				;;
-			-beos*)
-				vendor=be
-				;;
-			-hpux*)
-				vendor=hp
-				;;
-			-mpeix*)
-				vendor=hp
-				;;
-			-hiux*)
-				vendor=hitachi
-				;;
-			-unos*)
-				vendor=crds
-				;;
-			-dgux*)
-				vendor=dg
-				;;
-			-luna*)
-				vendor=omron
-				;;
-			-genix*)
-				vendor=ns
-				;;
-			-mvs*)
-				vendor=ibm
-				;;
-			-ptx*)
-				vendor=sequent
-				;;
-			-vxsim* | -vxworks*)
-				vendor=wrs
-				;;
-			-aux*)
-				vendor=apple
-				;;
-			-hms*)
-				vendor=hitachi
-				;;
-			-mpw* | -macos*)
-				vendor=apple
-				;;
-			-*mint | -*MiNT)
-				vendor=atari
-				;;
-		esac
-		basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
-		;;
-esac
-
-echo $basic_machine$os
-exit 0
diff --git a/shmem/unix/mm/configure.in b/shmem/unix/mm/configure.in
deleted file mode 100644
index e7de4dd965c..00000000000
--- a/shmem/unix/mm/configure.in
+++ /dev/null
@@ -1,219 +0,0 @@
-dnl ##
-dnl ##   Autoconf specification for MM library
-dnl ##
-
-dnl #
-dnl #   standard Autoconf prolog
-dnl #
-
-AC_PREREQ(2.12)dnl
-AC_REVISION(1.0)dnl
-
-dnl #   shtool bootstrap
-SHTOOL="\$(TOP)/shtool"
-AC_SUBST(SHTOOL)
-ac_shtool="./shtool"
-T_MD=`$ac_shtool echo -n -e %B`
-T_ME=`$ac_shtool echo -n -e %b`
-PLATFORM=`${CONFIG_SHELL-/bin/sh} ./config.guess`
-PLATFORM=`${CONFIG_SHELL-/bin/sh} ./config.sub $PLATFORM`
-MM_VERSION_STR="`$ac_shtool version -l c -d long mm_vers.c`"
-AC_SUBST(MM_VERSION_STR)
-
-dnl #   friendly header ;-)
-echo "Configuring ${T_MD}MM${T_ME} (Shared Memory Library), Version ${T_MD}${MM_VERSION_STR}${T_ME}"
-echo "Copyright (c) 1999 Ralf S. Engelschall, All Rights Reserved."
-echo "Platform: ${T_MD}${PLATFORM}${T_ME}"
-
-dnl #   autoconf initialization
-AC_INIT(README)
-AC_CONFIG_HEADER(mm_conf.h)dnl
-AC_PREFIX_DEFAULT(/usr/local)
-
-dnl #   determine build mode
-AC_ARG_ENABLE(batch,dnl
-[  --enable-batch          build in batch mode (default=no)],
-enable_batch="$enableval",
-if test ".$enable_batch" = .; then
-    enable_batch=no
-fi
-)dnl
-
-dnl #
-dnl #   determine build tools and parameters
-dnl #
-
-AC_CONFIGURE_PART(Build Tools)
-AC_PROG_CC
-AC_PROG_CPP
-AC_CHECK_DEBUGGING
-AC_SET_MAKE
-AC_PROG_LIBTOOL
-
-dnl #   support for some special platform/compiler options
-case "$PLATFORM:$CC" in
-    *-hp-hpux*:cc ) CFLAGS="$CFLAGS -Ae +DAportable" ;;
-esac
-
-dnl #
-dnl #   determine system parameters
-dnl #
-
-AC_CONFIGURE_PART(Platform Environment)
-
-AC_HAVE_HEADERS(stdio.h stdlib.h string.h dnl 
-                errno.h limits.h unistd.h fcntl.h dnl
-                sys/stat.h sys/types.h)
-AC_BEGIN_DECISION([mandatory system headers])
-AC_IFALLYES(header:stdio.h header:stdlib.h header:string.h dnl
-            header:errno.h header:limits.h header:unistd.h header:fcntl.h dnl
-            header:sys/stat.h header:sys/types.h,
-            AC_DECIDE(fine, [all fine]))
-AC_END_DECISION
-
-AC_HAVE_HEADERS(memory.h)
-AC_CHECK_FUNCS(memcpy memset bcopy)
-AC_CHECK_DEFINE(_POSIX_PATH_MAX, limits.h)
-AC_CHECK_DEFINE(PATH_MAX, limits.h)
-AC_CHECK_DEFINE(MAXPATHLEN, sys/param.h)
-AC_CHECK_DEFINE(_POSIX_CHILD_MAX, limits.h)
-AC_CHECK_DEFINE(CHILD_MAX, limits.h)
-
-dnl #   some special defines for brain dead platforms
-case $PLATFORM in
-   *-*-sunos* ) AC_DEFINE(MM_OS_SUNOS) ;;
-esac
-
-dnl #
-dnl #   method to determine virtual memory page size
-dnl #
-
-AC_CONFIGURE_PART(Virtual Memory Page Size)
-
-AC_HAVE_HEADERS(unistd.h)
-AC_HAVE_FUNCS(getpagesize sysconf)
-AC_CHECK_DEFINE(_SC_PAGESIZE, unistd.h)
-AC_HAVE_HEADERS(kernel/OS.h)
-AC_CHECK_DEFINE(B_PAGE_SIZE, kernel/OS.h)
-
-AC_BEGIN_DECISION([memory page size determination])
-AC_IFALLYES(header:unistd.h func:getpagesize, 
-            AC_DECIDE(MM_VMPS_GETPAGESIZE, [4.2BSD getpagesize()]))
-AC_IFALLYES(header:unistd.h func:sysconf define:_SC_PAGESIZE, 
-            AC_DECIDE(MM_VMPS_SYSCONF, [POSIX.1 sysconf(_SC_PAGESIZE)]))
-AC_IFALLYES(header:kernel/OS.h define:B_PAGE_SIZE,
-            AC_DECIDE(MM_VMPS_BEOS, [BeOS B_PAGE_SIZE])) 
-AC_END_DECISION
-AC_DEFINE_UNQUOTED($ac_decision)
-
-dnl #
-dnl #   Shared Memory
-dnl #
-
-AC_CONFIGURE_PART(Shared Memory Implementation)
-
-AC_HAVE_HEADERS(sys/mman.h)
-AC_CHECK_DEFINE(MAP_ANON, sys/mman.h)
-AC_HAVE_FUNCS(mmap munmap shm_open shm_unlink)
-AC_TEST_FILE(/dev/zero)
-AC_HAVE_HEADERS(sys/ipc.h sys/shm.h sys/file.h)
-AC_HAVE_FUNCS(shmget shmat shmdt shmctl)
-AC_HAVE_HEADERS(kernel/OS.h)
-AC_HAVE_FUNCS(create_area)
-
-AC_BEGIN_DECISION([shared memory allocation method])
-AC_IFALLYES(header:sys/mman.h func:mmap func:munmap, 
-            AC_DECIDE(MM_SHMT_MMFILE, [Classical mmap() on temporary file]))
-AC_IFALLYES(header:sys/mman.h func:mmap func:munmap func:shm_open func:shm_unlink, 
-            AC_DECIDE(MM_SHMT_MMPOSX, [mmap() via POSIX.1 shm_open() on temporary file]))
-AC_IFALLYES(header:sys/mman.h func:mmap func:munmap file:/dev/zero, 
-            AC_DECIDE(MM_SHMT_MMZERO, [SVR4-style mmap() on /dev/zero]))
-AC_IFALLYES(header:sys/ipc.h header:sys/shm.h header:sys/file.h dnl
-            func:shmget func:shmat func:shmdt func:shmctl,
-            AC_DECIDE(MM_SHMT_IPCSHM, [SysV IPC shmget()]))
-AC_IFALLYES(header:sys/mman.h func:mmap func:munmap define:MAP_ANON, 
-            AC_DECIDE(MM_SHMT_MMANON, [4.4BSD-style mmap() via MAP_ANON]))
-AC_IFALLYES(header:kernel/OS.h func:create_area,
-           AC_DECIDE(MM_SHMT_BEOS, [BeOS areas]))
-case $PLATFORM in
-    *-*-linux* ) 
-        #   Linux has problems with MM_SHMT_MMANON
-        AC_DECISION_OVERRIDE(MM_SHMT_MMANON MM_SHMT_MMFILE MM_SHMT_MMZERO dnl
-                             MM_SHMT_MMPOSX MM_SHMT_IPCSHM)
-        ;;
-esac
-AC_ARG_WITH(shm,dnl
-[  --with-shm=TYPE         force shared memory type: MMFILE MMZERO MMPOSX MMANON IPCSHM],
-AC_DECISION_FORCE(MM_SHMT_$withval)
-)dnl
-AC_END_DECISION
-AC_DEFINE_UNQUOTED($ac_decision)
-
-AC_CHECK_MAXSEGSIZE($ac_decision)
-
-dnl #
-dnl #   Mutex
-dnl #
-
-AC_CONFIGURE_PART(Mutual Exclusion Implementation)
-
-AC_HAVE_HEADERS(sys/ipc.h sys/sem.h sys/file.h)
-AC_HAVE_FUNCS(semget semctl)
-AC_CHECK_DEFINE(LOCK_EX, sys/file.h)
-AC_CHECK_DEFINE(F_SETLK, fcntl.h)
-AC_CHECK_DEFINE(IPC_PRIVATE, sys/ipc.h)
-AC_CHECK_DEFINE(SEM_UNDO, sys/sem.h)
-AC_HAVE_HEADERS(kernel/OS.h)
-AC_CHECK_FUNCS(create_sem, kernel/OS.h)
-
-AC_MSG_CHECKING(whether union semun is defined in sys/sem.h)
-AC_TRY_COMPILE([
-#include <sys/types.h>
-#include <sys/ipc.h>
-#include <sys/sem.h>
-],[
-union semun arg;
-semctl(0, 0, 0, arg);
-],
-AC_DEFINE(HAVE_UNION_SEMUN)
-msg=yes,dnl
-msg=no)
-AC_MSG_RESULT([$msg])
-
-AC_BEGIN_DECISION([mutex implementation method])
-AC_IFALLYES(header:sys/file.h define:LOCK_EX, 
-            AC_DECIDE(MM_SEMT_FLOCK, [4.2BSD-style flock() on temporary file]))
-AC_IFALLYES(header:sys/ipc.h header:sys/sem.h header:sys/file.h dnl
-            func:semget func:semctl,
-            AC_DECIDE(MM_SEMT_IPCSEM, [SysV IPC semget()]))
-AC_IFALLYES(header:fcntl.h define:F_SETLK, 
-            AC_DECIDE(MM_SEMT_FCNTL, [SVR4-style fcntl() on temporary file]))
-AC_IFALLYES(header:kernel/OS.h func:create_sem,
-            AC_DECIDE(MM_SEMT_BEOS, [BeOS semaphores/benaphores]))
-AC_ARG_WITH(sem,dnl
-[  --with-sem=TYPE         force semaphore type: FLOCK FCNTL IPCSEM],
-AC_DECISION_FORCE(MM_SEMT_$withval)
-)dnl
-AC_END_DECISION
-AC_DEFINE_UNQUOTED($ac_decision)
-
-dnl #
-dnl #   finally: source file substitution...
-dnl #
-
-AC_CONFIGURE_PART(Output Substitution)
-
-AC_OUTPUT(dnl
-Makefile dnl
-mm-config dnl
-,dnl
-chmod a+x mm-config
-)dnl
-
-if test ".$enable_batch" != .yes; then
-    echo ""
-    echo "Now please type \`${T_MD}make${T_ME}' to compile. Good luck."
-    echo ""
-fi
-
-dnl ##EOF##
diff --git a/shmem/unix/mm/fbtool b/shmem/unix/mm/fbtool
deleted file mode 100755
index 5b6b2231896..00000000000
--- a/shmem/unix/mm/fbtool
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/bin/sh
-##
-##  fbtool -- MM library feedback tool
-##  Copyright (c) 1999 Ralf S. Engelschall, All Rights Reserved. 
-##
-
-if [ ! -f .fbtool ]; then
-    echo "fbtool:Error: still no results known";
-    exit 1
-fi
-result=`cat .fbtool`
-
-VERSION=`./shtool version -l c -d long mm_vers.c`
-
-PLATFORM=`/bin/sh ./config.guess`
-PLATFORM=`/bin/sh ./config.sub $PLATFORM`
-
-VMPS=`grep MM_VMPS_ mm_conf.h | grep define | sed -e 's;.*MM_;MM_;' -e 's; .*;;'`; \
-SHMT=`grep MM_SHMT_ mm_conf.h | grep define | sed -e 's;.*MM_;MM_;' -e 's; .*;;'`; \
-SEMT=`grep MM_SEMT_ mm_conf.h | grep define | sed -e 's;.*MM_;MM_;' -e 's; .*;;'`; \
-SEGS=`grep MM_SHM_MAXSEGSIZE mm_conf.h | grep define | sed -e 's;.*SIZE *;;' -e 's; .*;;'`; \
-
-TMP=".fbsummary"
-rm -f $TMP >/dev/null 2>&1
-touch $TMP
-echo "+-MM-Library-Test-Suite-Summary---------------------------" >>$TMP
-echo "| Library Version       : MM $VERSION" >>$TMP
-echo "| Platform              : $PLATFORM" >>$TMP
-echo "| Memory Page Size Type : $VMPS" >>$TMP
-echo "| Shared Memory Type    : $SHMT" >>$TMP
-echo "| Semaphore Type        : $SEMT" >>$TMP
-echo "| Maximum Segment Size  : $SEGS" >>$TMP
-echo "| Test Suite            : $result" >>$TMP
-echo "+---------------------------------------------------------" >>$TMP
-
-case $1 in
-    -d ) cat $TMP ;;
-    -s ) ;;
-esac
-
-rm -f $TMP >/dev/null 2>&1
-
diff --git a/shmem/unix/mm/ltconfig b/shmem/unix/mm/ltconfig
deleted file mode 100755
index 65ec6f65d0f..00000000000
--- a/shmem/unix/mm/ltconfig
+++ /dev/null
@@ -1,3017 +0,0 @@
-#! /bin/sh
-
-# ltconfig - Create a system-specific libtool.
-# Copyright (C) 1996-1999 Free Software Foundation, Inc.
-# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
-#
-# This file is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-# A lot of this script is taken from autoconf-2.10.
-
-# Check that we are running under the correct shell.
-SHELL=${CONFIG_SHELL-/bin/sh}
-echo=echo
-if test "X$1" = X--no-reexec; then
-  # Discard the --no-reexec flag, and continue.
-  shift
-elif test "X$1" = X--fallback-echo; then
-  # Avoid inline document here, it may be left over
-  :
-elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
-  # Yippee, $echo works!
-  :
-else
-  # Restart under the correct shell.
-  exec "$SHELL" "$0" --no-reexec ${1+"$@"}
-fi
-
-if test "X$1" = X--fallback-echo; then
-  # used as fallback echo
-  shift
-  cat <<EOF
-$*
-EOF
-  exit 0
-fi
-
-# Find the correct PATH separator.  Usually this is `:', but
-# DJGPP uses `;' like DOS.
-if test "X${PATH_SEPARATOR+set}" != "Xset"; then
-  UNAME=${UNAME-`uname 2>/dev/null`}
-  case X$UNAME in
-    *-DOS) PATH_SEPARATOR=';' ;;
-    *)     PATH_SEPARATOR=':' ;;
-  esac
-fi
-
-# The HP-UX ksh and POSIX shell print the target directory to stdout
-# if CDPATH is set.
-if test "${CDPATH+set}" = set; then CDPATH=; export CDPATH; fi
-
-if test "X${echo_test_string+set}" != "Xset"; then
-  # find a string as large as possible, as long as the shell can cope with it
-  for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do
-    # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
-    if (echo_test_string="`eval $cmd`") 2>/dev/null &&
-       echo_test_string="`eval $cmd`" &&
-       (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null; then
-      break
-    fi
-  done
-fi
-
-if test "X`($echo '\t') 2>/dev/null`" != 'X\t' ||
-   test "X`($echo "$echo_test_string") 2>/dev/null`" != X"$echo_test_string"; then
-  # The Solaris, AIX, and Digital Unix default echo programs unquote
-  # backslashes.  This makes it impossible to quote backslashes using
-  #   echo "$something" | sed 's/\\/\\\\/g'
-  #
-  # So, first we look for a working echo in the user's PATH.
-
-  IFS="${IFS= 	}"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
-  for dir in $PATH /usr/ucb; do
-    if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
-       test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
-       test "X`($dir/echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
-      echo="$dir/echo"
-      break
-    fi
-  done
-  IFS="$save_ifs"
-
-  if test "X$echo" = Xecho; then
-    # We didn't find a better echo, so look for alternatives.
-    if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' &&
-       test "X`(print -r "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
-      # This shell has a builtin print -r that does the trick.
-      echo='print -r'
-    elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) &&
-	 test "X$CONFIG_SHELL" != X/bin/ksh; then
-      # If we have ksh, try running ltconfig again with it.
-      ORIGINAL_CONFIG_SHELL="${CONFIG_SHELL-/bin/sh}"
-      export ORIGINAL_CONFIG_SHELL
-      CONFIG_SHELL=/bin/ksh
-      export CONFIG_SHELL
-      exec "$CONFIG_SHELL" "$0" --no-reexec ${1+"$@"}
-    else
-      # Try using printf.
-      echo='printf "%s\n"'
-      if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
-	 test "X`($echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
-	# Cool, printf works
-	:
-      elif test "X`("$ORIGINAL_CONFIG_SHELL" "$0" --fallback-echo '\t') 2>/dev/null`" = 'X\t' &&
-	   test "X`("$ORIGINAL_CONFIG_SHELL" "$0" --fallback-echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
-	CONFIG_SHELL="$ORIGINAL_CONFIG_SHELL"
-	export CONFIG_SHELL
-	SHELL="$CONFIG_SHELL"
-	export SHELL
-	echo="$CONFIG_SHELL $0 --fallback-echo"
-      elif test "X`("$CONFIG_SHELL" "$0" --fallback-echo '\t') 2>/dev/null`" = 'X\t' &&
-	   test "X`("$CONFIG_SHELL" "$0" --fallback-echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
-	echo="$CONFIG_SHELL $0 --fallback-echo"
-      else
-	# maybe with a smaller string...
-	prev=:
-
-	for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do
-	  if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null; then
-	    break
-	  fi
-	  prev="$cmd"
-	done
-
-	if test "$prev" != 'sed 50q "$0"'; then
-	  echo_test_string=`eval $prev`
-	  export echo_test_string
-	  exec "${ORIGINAL_CONFIG_SHELL}" "$0" ${1+"$@"}
-	else
-	  # Oops.  We lost completely, so just stick with echo.
-	  echo=echo
-	fi
-      fi
-    fi
-  fi
-fi
-
-# Sed substitution that helps us do robust quoting.  It backslashifies
-# metacharacters that are still active within double-quoted strings.
-Xsed='sed -e s/^X//'
-sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'
-
-# Same as above, but do not quote variable references.
-double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g'
-
-# Sed substitution to delay expansion of an escaped shell variable in a
-# double_quote_subst'ed string.
-delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
-
-# The name of this program.
-progname=`$echo "X$0" | $Xsed -e 's%^.*/%%'`
-
-# Constants:
-PROGRAM=ltconfig
-PACKAGE=libtool
-VERSION=1.3.3
-TIMESTAMP=" (1.385.2.181 1999/07/02 15:49:11)"
-ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.c 1>&5'
-ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.c $LIBS 1>&5'
-rm="rm -f"
-
-help="Try \`$progname --help' for more information."
-
-# Global variables:
-default_ofile=libtool
-can_build_shared=yes
-enable_shared=yes
-# All known linkers require a `.a' archive for static linking (except M$VC,
-# which needs '.lib').
-enable_static=yes
-enable_fast_install=yes
-enable_dlopen=unknown
-enable_win32_dll=no
-ltmain=
-silent=
-srcdir=
-ac_config_guess=
-ac_config_sub=
-host=
-nonopt=
-ofile="$default_ofile"
-verify_host=yes
-with_gcc=no
-with_gnu_ld=no
-need_locks=yes
-ac_ext=c
-objext=o
-libext=a
-exeext=
-cache_file=
-
-old_AR="$AR"
-old_CC="$CC"
-old_CFLAGS="$CFLAGS"
-old_CPPFLAGS="$CPPFLAGS"
-old_LDFLAGS="$LDFLAGS"
-old_LD="$LD"
-old_LN_S="$LN_S"
-old_LIBS="$LIBS"
-old_NM="$NM"
-old_RANLIB="$RANLIB"
-old_DLLTOOL="$DLLTOOL"
-old_OBJDUMP="$OBJDUMP"
-old_AS="$AS"
-
-# Parse the command line options.
-args=
-prev=
-for option
-do
-  case "$option" in
-  -*=*) optarg=`echo "$option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
-  *) optarg= ;;
-  esac
-
-  # If the previous option needs an argument, assign it.
-  if test -n "$prev"; then
-    eval "$prev=\$option"
-    prev=
-    continue
-  fi
-
-  case "$option" in
-  --help) cat <<EOM
-Usage: $progname [OPTION]... [HOST [LTMAIN]]
-
-Generate a system-specific libtool script.
-
-    --debug                enable verbose shell tracing
-    --disable-shared       do not build shared libraries
-    --disable-static       do not build static libraries
-    --disable-fast-install do not optimize for fast installation
-    --enable-dlopen        enable dlopen support
-    --enable-win32-dll     enable building dlls on win32 hosts
-    --help                 display this help and exit
-    --no-verify            do not verify that HOST is a valid host type
--o, --output=FILE          specify the output file [default=$default_ofile]
-    --quiet                same as \`--silent'
-    --silent               do not print informational messages
-    --srcdir=DIR           find \`config.guess' in DIR
-    --version              output version information and exit
-    --with-gcc             assume that the GNU C compiler will be used
-    --with-gnu-ld          assume that the C compiler uses the GNU linker
-    --disable-lock         disable file locking
-    --cache-file=FILE      configure cache file
-
-LTMAIN is the \`ltmain.sh' shell script fragment or \`ltmain.c' program
-that provides basic libtool functionality.
-
-HOST is the canonical host system name [default=guessed].
-EOM
-  exit 0
-  ;;
-
-  --debug)
-    echo "$progname: enabling shell trace mode"
-    set -x
-    ;;
-
-  --disable-shared) enable_shared=no ;;
-
-  --disable-static) enable_static=no ;;
-
-  --disable-fast-install) enable_fast_install=no ;;
-
-  --enable-dlopen) enable_dlopen=yes ;;
-
-  --enable-win32-dll) enable_win32_dll=yes ;;
-
-  --quiet | --silent) silent=yes ;;
-
-  --srcdir) prev=srcdir ;;
-  --srcdir=*) srcdir="$optarg" ;;
-
-  --no-verify) verify_host=no ;;
-
-  --output | -o) prev=ofile ;;
-  --output=*) ofile="$optarg" ;;
-
-  --version) echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP"; exit 0 ;;
-
-  --with-gcc) with_gcc=yes ;;
-  --with-gnu-ld) with_gnu_ld=yes ;;
-
-  --disable-lock) need_locks=no ;;
-
-  --cache-file=*) cache_file="$optarg" ;;
-
-  -*)
-    echo "$progname: unrecognized option \`$option'" 1>&2
-    echo "$help" 1>&2
-    exit 1
-    ;;
-
-  *)
-    if test -z "$ltmain"; then
-      ltmain="$option"
-    elif test -z "$host"; then
-# This generates an unnecessary warning for sparc-sun-solaris4.1.3_U1
-#      if test -n "`echo $option| sed 's/[-a-z0-9.]//g'`"; then
-#        echo "$progname: warning \`$option' is not a valid host type" 1>&2
-#      fi
-      host="$option"
-    else
-      echo "$progname: too many arguments" 1>&2
-      echo "$help" 1>&2
-      exit 1
-    fi ;;
-  esac
-done
-
-if test -z "$ltmain"; then
-  echo "$progname: you must specify a LTMAIN file" 1>&2
-  echo "$help" 1>&2
-  exit 1
-fi
-
-if test ! -f "$ltmain"; then
-  echo "$progname: \`$ltmain' does not exist" 1>&2
-  echo "$help" 1>&2
-  exit 1
-fi
-
-# Quote any args containing shell metacharacters.
-ltconfig_args=
-for arg
-do
-  case "$arg" in
-  *" "*|*"	"*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
-  ltconfig_args="$ltconfig_args '$arg'" ;;
-  *) ltconfig_args="$ltconfig_args $arg" ;;
-  esac
-done
-
-# A relevant subset of AC_INIT.
-
-# File descriptor usage:
-# 0 standard input
-# 1 file creation
-# 2 errors and warnings
-# 3 some systems may open it to /dev/tty
-# 4 used on the Kubota Titan
-# 5 compiler messages saved in config.log
-# 6 checking for... messages and results
-if test "$silent" = yes; then
-  exec 6>/dev/null
-else
-  exec 6>&1
-fi
-exec 5>>./config.log
-
-# NLS nuisances.
-# Only set LANG and LC_ALL to C if already set.
-# These must not be set unconditionally because not all systems understand
-# e.g. LANG=C (notably SCO).
-if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
-if test "${LANG+set}"   = set; then LANG=C;   export LANG;   fi
-
-if test -n "$cache_file" && test -r "$cache_file"; then
-  echo "loading cache $cache_file within ltconfig"
-  . $cache_file
-fi
-
-if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
-  # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
-  if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
-    ac_n= ac_c='
-' ac_t='	'
-  else
-    ac_n=-n ac_c= ac_t=
-  fi
-else
-  ac_n= ac_c='\c' ac_t=
-fi
-
-if test -z "$srcdir"; then
-  # Assume the source directory is the same one as the path to LTMAIN.
-  srcdir=`$echo "X$ltmain" | $Xsed -e 's%/[^/]*$%%'`
-  test "$srcdir" = "$ltmain" && srcdir=.
-fi
-
-trap "$rm conftest*; exit 1" 1 2 15
-if test "$verify_host" = yes; then
-  # Check for config.guess and config.sub.
-  ac_aux_dir=
-  for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
-    if test -f $ac_dir/config.guess; then
-      ac_aux_dir=$ac_dir
-      break
-    fi
-  done
-  if test -z "$ac_aux_dir"; then
-    echo "$progname: cannot find config.guess in $srcdir $srcdir/.. $srcdir/../.." 1>&2
-    echo "$help" 1>&2
-    exit 1
-  fi
-  ac_config_guess=$ac_aux_dir/config.guess
-  ac_config_sub=$ac_aux_dir/config.sub
-
-  # Make sure we can run config.sub.
-  if $SHELL $ac_config_sub sun4 >/dev/null 2>&1; then :
-  else
-    echo "$progname: cannot run $ac_config_sub" 1>&2
-    echo "$help" 1>&2
-    exit 1
-  fi
-
-  echo $ac_n "checking host system type""... $ac_c" 1>&6
-
-  host_alias=$host
-  case "$host_alias" in
-  "")
-    if host_alias=`$SHELL $ac_config_guess`; then :
-    else
-      echo "$progname: cannot guess host type; you must specify one" 1>&2
-      echo "$help" 1>&2
-      exit 1
-    fi ;;
-  esac
-  host=`$SHELL $ac_config_sub $host_alias`
-  echo "$ac_t$host" 1>&6
-
-  # Make sure the host verified.
-  test -z "$host" && exit 1
-
-elif test -z "$host"; then
-  echo "$progname: you must specify a host type if you use \`--no-verify'" 1>&2
-  echo "$help" 1>&2
-  exit 1
-else
-  host_alias=$host
-fi
-
-# Transform linux* to *-*-linux-gnu*, to support old configure scripts.
-case "$host_os" in
-linux-gnu*) ;;
-linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'`
-esac
-
-host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
-host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
-host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
-
-case "$host_os" in
-aix3*)
-  # AIX sometimes has problems with the GCC collect2 program.  For some
-  # reason, if we set the COLLECT_NAMES environment variable, the problems
-  # vanish in a puff of smoke.
-  if test "${COLLECT_NAMES+set}" != set; then
-    COLLECT_NAMES=
-    export COLLECT_NAMES
-  fi
-  ;;
-esac
-
-# Determine commands to create old-style static archives.
-old_archive_cmds='$AR cru $oldlib$oldobjs'
-old_postinstall_cmds='chmod 644 $oldlib'
-old_postuninstall_cmds=
-
-# Set a sane default for `AR'.
-test -z "$AR" && AR=ar
-
-# Set a sane default for `OBJDUMP'.
-test -z "$OBJDUMP" && OBJDUMP=objdump
-
-# If RANLIB is not set, then run the test.
-if test "${RANLIB+set}" != "set"; then
-  result=no
-
-  echo $ac_n "checking for ranlib... $ac_c" 1>&6
-  IFS="${IFS= 	}"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
-  for dir in $PATH; do
-    test -z "$dir" && dir=.
-    if test -f $dir/ranlib || test -f $dir/ranlib$ac_exeext; then
-      RANLIB="ranlib"
-      result="ranlib"
-      break
-    fi
-  done
-  IFS="$save_ifs"
-
-  echo "$ac_t$result" 1>&6
-fi
-
-if test -n "$RANLIB"; then
-  old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
-  old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds"
-fi
-
-# Set sane defaults for `DLLTOOL', `OBJDUMP', and `AS', used on cygwin.
-test -z "$DLLTOOL" && DLLTOOL=dlltool
-test -z "$OBJDUMP" && OBJDUMP=objdump
-test -z "$AS" && AS=as
-
-# Check to see if we are using GCC.
-if test "$with_gcc" != yes || test -z "$CC"; then
-  # If CC is not set, then try to find GCC or a usable CC.
-  if test -z "$CC"; then
-    echo $ac_n "checking for gcc... $ac_c" 1>&6
-    IFS="${IFS= 	}"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
-    for dir in $PATH; do
-      test -z "$dir" && dir=.
-      if test -f $dir/gcc || test -f $dir/gcc$ac_exeext; then
-	CC="gcc"
-	break
-      fi
-    done
-    IFS="$save_ifs"
-
-    if test -n "$CC"; then
-      echo "$ac_t$CC" 1>&6
-    else
-      echo "$ac_t"no 1>&6
-    fi
-  fi
-
-  # Not "gcc", so try "cc", rejecting "/usr/ucb/cc".
-  if test -z "$CC"; then
-    echo $ac_n "checking for cc... $ac_c" 1>&6
-    IFS="${IFS= 	}"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
-    cc_rejected=no
-    for dir in $PATH; do
-      test -z "$dir" && dir=.
-      if test -f $dir/cc || test -f $dir/cc$ac_exeext; then
-	if test "$dir/cc" = "/usr/ucb/cc"; then
-	  cc_rejected=yes
-	  continue
-	fi
-	CC="cc"
-	break
-      fi
-    done
-    IFS="$save_ifs"
-    if test $cc_rejected = yes; then
-      # We found a bogon in the path, so make sure we never use it.
-      set dummy $CC
-      shift
-      if test $# -gt 0; then
-	# We chose a different compiler from the bogus one.
-	# However, it has the same name, so the bogon will be chosen
-	# first if we set CC to just the name; use the full file name.
-	shift
-	set dummy "$dir/cc" "$@"
-	shift
-	CC="$@"
-      fi
-    fi
-
-    if test -n "$CC"; then
-      echo "$ac_t$CC" 1>&6
-    else
-      echo "$ac_t"no 1>&6
-    fi
-
-    if test -z "$CC"; then
-      echo "$progname: error: no acceptable cc found in \$PATH" 1>&2
-      exit 1
-    fi
-  fi
-
-  # Now see if the compiler is really GCC.
-  with_gcc=no
-  echo $ac_n "checking whether we are using GNU C... $ac_c" 1>&6
-  echo "$progname:581: checking whether we are using GNU C" >&5
-
-  $rm conftest.c
-  cat > conftest.c <<EOF
-#ifdef __GNUC__
-  yes;
-#endif
-EOF
-  if { ac_try='${CC-cc} -E conftest.c'; { (eval echo $progname:589: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
-    with_gcc=yes
-  fi
-  $rm conftest.c
-  echo "$ac_t$with_gcc" 1>&6
-fi
-
-# Allow CC to be a program name with arguments.
-set dummy $CC
-compiler="$2"
-
-echo $ac_n "checking for object suffix... $ac_c" 1>&6
-$rm conftest*
-echo 'int i = 1;' > conftest.c
-echo "$progname:603: checking for object suffix" >& 5
-if { (eval echo $progname:604: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; }; then
-  # Append any warnings to the config.log.
-  cat conftest.err 1>&5
-
-  for ac_file in conftest.*; do
-    case $ac_file in
-    *.c) ;;
-    *) objext=`echo $ac_file | sed -e s/conftest.//` ;;
-    esac
-  done
-else
-  cat conftest.err 1>&5
-  echo "$progname: failed program was:" >&5
-  cat conftest.c >&5
-fi
-$rm conftest*
-echo "$ac_t$objext" 1>&6
-
-echo $ac_n "checking for executable suffix... $ac_c" 1>&6
-if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then
-  echo $ac_n "(cached) $ac_c" 1>&6
-else
-  ac_cv_exeext="no"
-  $rm conftest*
-  echo 'main () { return 0; }' > conftest.c
-  echo "$progname:629: checking for executable suffix" >& 5
-  if { (eval echo $progname:630: \"$ac_link\") 1>&5; (eval $ac_link) 2>conftest.err; }; then
-    # Append any warnings to the config.log.
-    cat conftest.err 1>&5
-
-    for ac_file in conftest.*; do
-      case $ac_file in
-      *.c | *.err | *.$objext ) ;;
-      *) ac_cv_exeext=.`echo $ac_file | sed -e s/conftest.//` ;;
-      esac
-    done
-  else
-    cat conftest.err 1>&5
-    echo "$progname: failed program was:" >&5
-    cat conftest.c >&5
-  fi
-  $rm conftest*
-fi
-if test "X$ac_cv_exeext" = Xno; then
-  exeext=""
-else
-  exeext="$ac_cv_exeext"
-fi
-echo "$ac_t$ac_cv_exeext" 1>&6
-
-echo $ac_n "checking for $compiler option to produce PIC... $ac_c" 1>&6
-pic_flag=
-special_shlib_compile_flags=
-wl=
-link_static_flag=
-no_builtin_flag=
-
-if test "$with_gcc" = yes; then
-  wl='-Wl,'
-  link_static_flag='-static'
-
-  case "$host_os" in
-  beos* | irix5* | irix6* | osf3* | osf4*)
-    # PIC is the default for these OSes.
-    ;;
-  aix*)
-    # Below there is a dirty hack to force normal static linking with -ldl
-    # The problem is because libdl dynamically linked with both libc and
-    # libC (AIX C++ library), which obviously doesn't included in libraries
-    # list by gcc. This cause undefined symbols with -static flags.
-    # This hack allows C programs to be linked with "-static -ldl", but
-    # we not sure about C++ programs.
-    link_static_flag="$link_static_flag ${wl}-lC"
-    ;;
-  cygwin* | mingw* | os2*)
-    # We can build DLLs from non-PIC.
-    ;;
-  amigaos*)
-    # FIXME: we need at least 68020 code to build shared libraries, but
-    # adding the `-m68020' flag to GCC prevents building anything better,
-    # like `-m68040'.
-    pic_flag='-m68020 -resident32 -malways-restore-a4'
-    ;;
-  sysv4*MP*)
-    if test -d /usr/nec; then
-       pic_flag=-Kconform_pic
-    fi
-    ;;
-  *)
-    pic_flag='-fPIC'
-    ;;
-  esac
-else
-  # PORTME Check for PIC flags for the system compiler.
-  case "$host_os" in
-  aix3* | aix4*)
-    # All AIX code is PIC.
-    link_static_flag='-bnso -bI:/lib/syscalls.exp'
-    ;;
-
-  hpux9* | hpux10* | hpux11*)
-    # Is there a better link_static_flag that works with the bundled CC?
-    wl='-Wl,'
-    link_static_flag="${wl}-a ${wl}archive"
-    pic_flag='+Z'
-    ;;
-
-  irix5* | irix6*)
-    wl='-Wl,'
-    link_static_flag='-non_shared'
-    # PIC (with -KPIC) is the default.
-    ;;
-
-  cygwin* | mingw* | os2*)
-    # We can build DLLs from non-PIC.
-    ;;
-
-  osf3* | osf4*)
-    # All OSF/1 code is PIC.
-    wl='-Wl,'
-    link_static_flag='-non_shared'
-    ;;
-
-  sco3.2v5*)
-    pic_flag='-Kpic'
-    link_static_flag='-dn'
-    special_shlib_compile_flags='-belf'
-    ;;
-
-  solaris*)
-    pic_flag='-KPIC'
-    link_static_flag='-Bstatic'
-    wl='-Wl,'
-    ;;
-
-  sunos4*)
-    pic_flag='-PIC'
-    link_static_flag='-Bstatic'
-    wl='-Qoption ld '
-    ;;
-
-  sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
-    pic_flag='-KPIC'
-    link_static_flag='-Bstatic'
-    wl='-Wl,'
-    ;;
-
-  uts4*)
-    pic_flag='-pic'
-    link_static_flag='-Bstatic'
-    ;;
-  sysv4*MP*)
-    if test -d /usr/nec ;then
-      pic_flag='-Kconform_pic'
-      link_static_flag='-Bstatic'
-    fi
-    ;;
-  *)
-    can_build_shared=no
-    ;;
-  esac
-fi
-
-if test -n "$pic_flag"; then
-  echo "$ac_t$pic_flag" 1>&6
-
-  # Check to make sure the pic_flag actually works.
-  echo $ac_n "checking if $compiler PIC flag $pic_flag works... $ac_c" 1>&6
-  $rm conftest*
-  echo "int some_variable = 0;" > conftest.c
-  save_CFLAGS="$CFLAGS"
-  CFLAGS="$CFLAGS $pic_flag -DPIC"
-  echo "$progname:776: checking if $compiler PIC flag $pic_flag works" >&5
-  if { (eval echo $progname:777: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.$objext; then
-    # Append any warnings to the config.log.
-    cat conftest.err 1>&5
-    
-    case "$host_os" in
-    hpux9* | hpux10* | hpux11*)
-      # On HP-UX, both CC and GCC only warn that PIC is supported... then they
-      # create non-PIC objects.  So, if there were any warnings, we assume that
-      # PIC is not supported.
-      if test -s conftest.err; then
-	echo "$ac_t"no 1>&6
-	can_build_shared=no
-	pic_flag=
-      else
-	echo "$ac_t"yes 1>&6
-	pic_flag=" $pic_flag"
-      fi
-      ;;
-    *)
-      echo "$ac_t"yes 1>&6
-      pic_flag=" $pic_flag"
-      ;;
-    esac
-  else
-    # Append any errors to the config.log.
-    cat conftest.err 1>&5
-    can_build_shared=no
-    pic_flag=
-    echo "$ac_t"no 1>&6
-  fi
-  CFLAGS="$save_CFLAGS"
-  $rm conftest*
-else
-  echo "$ac_t"none 1>&6
-fi
-
-# Check to see if options -o and -c are simultaneously supported by compiler
-echo $ac_n "checking if $compiler supports -c -o file.o... $ac_c" 1>&6
-$rm -r conftest 2>/dev/null
-mkdir conftest
-cd conftest
-$rm conftest*
-echo "int some_variable = 0;" > conftest.c
-mkdir out
-# According to Tom Tromey, Ian Lance Taylor reported there are C compilers
-# that will create temporary files in the current directory regardless of
-# the output directory.  Thus, making CWD read-only will cause this test
-# to fail, enabling locking or at least warning the user not to do parallel
-# builds.
-chmod -w .
-save_CFLAGS="$CFLAGS"
-CFLAGS="$CFLAGS -o out/conftest2.o"
-echo "$progname:829: checking if $compiler supports -c -o file.o" >&5
-if { (eval echo $progname:830: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.o; then
-
-  # The compiler can only warn and ignore the option if not recognized
-  # So say no if there are warnings
-    if test -s out/conftest.err; then
-      echo "$ac_t"no 1>&6
-      compiler_c_o=no
-    else
-      echo "$ac_t"yes 1>&6
-      compiler_c_o=yes
-    fi
-else
-  # Append any errors to the config.log.
-  cat out/conftest.err 1>&5
-  compiler_c_o=no
-  echo "$ac_t"no 1>&6
-fi
-CFLAGS="$save_CFLAGS"
-chmod u+w .
-$rm conftest* out/*
-rmdir out
-cd ..
-rmdir conftest
-$rm -r conftest 2>/dev/null
-
-if test x"$compiler_c_o" = x"yes"; then
-  # Check to see if we can write to a .lo
-  echo $ac_n "checking if $compiler supports -c -o file.lo... $ac_c" 1>&6
-  $rm conftest*
-  echo "int some_variable = 0;" > conftest.c
-  save_CFLAGS="$CFLAGS"
-  CFLAGS="$CFLAGS -c -o conftest.lo"
-  echo "$progname:862: checking if $compiler supports -c -o file.lo" >&5
-if { (eval echo $progname:863: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.lo; then
-
-    # The compiler can only warn and ignore the option if not recognized
-    # So say no if there are warnings
-      if test -s conftest.err; then
-	echo "$ac_t"no 1>&6
-	compiler_o_lo=no
-      else
-	echo "$ac_t"yes 1>&6
-	compiler_o_lo=yes
-      fi
-  else
-    # Append any errors to the config.log.
-    cat conftest.err 1>&5
-    compiler_o_lo=no
-    echo "$ac_t"no 1>&6
-  fi
-  CFLAGS="$save_CFLAGS"
-  $rm conftest*
-else
-  compiler_o_lo=no
-fi
-
-# Check to see if we can do hard links to lock some files if needed
-hard_links="nottested"
-if test "$compiler_c_o" = no && test "$need_locks" != no; then
-  # do not overwrite the value of need_locks provided by the user
-  echo $ac_n "checking if we can lock with hard links... $ac_c" 1>&6
-  hard_links=yes
-  $rm conftest*
-  ln conftest.a conftest.b 2>/dev/null && hard_links=no
-  touch conftest.a
-  ln conftest.a conftest.b 2>&5 || hard_links=no
-  ln conftest.a conftest.b 2>/dev/null && hard_links=no
-  echo "$ac_t$hard_links" 1>&6
-  $rm conftest*
-  if test "$hard_links" = no; then
-    echo "*** WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2
-    need_locks=warn
-  fi
-else
-  need_locks=no
-fi
-
-if test "$with_gcc" = yes; then
-  # Check to see if options -fno-rtti -fno-exceptions are supported by compiler
-  echo $ac_n "checking if $compiler supports -fno-rtti -fno-exceptions ... $ac_c" 1>&6
-  $rm conftest*
-  echo "int some_variable = 0;" > conftest.c
-  save_CFLAGS="$CFLAGS"
-  CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -c conftest.c"
-  echo "$progname:914: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
-  if { (eval echo $progname:915: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.o; then
-
-    # The compiler can only warn and ignore the option if not recognized
-    # So say no if there are warnings
-      if test -s conftest.err; then
-	echo "$ac_t"no 1>&6
-	compiler_rtti_exceptions=no
-      else
-	echo "$ac_t"yes 1>&6
-	compiler_rtti_exceptions=yes
-      fi
-  else
-    # Append any errors to the config.log.
-    cat conftest.err 1>&5
-    compiler_rtti_exceptions=no
-    echo "$ac_t"no 1>&6
-  fi
-  CFLAGS="$save_CFLAGS"
-  $rm conftest*
-
-  if test "$compiler_rtti_exceptions" = "yes"; then
-    no_builtin_flag=' -fno-builtin -fno-rtti -fno-exceptions'
-  else
-    no_builtin_flag=' -fno-builtin'
-  fi
-  
-fi
-
-# Check for any special shared library compilation flags.
-if test -n "$special_shlib_compile_flags"; then
-  echo "$progname: warning: \`$CC' requires \`$special_shlib_compile_flags' to build shared libraries" 1>&2
-  if echo "$old_CC $old_CFLAGS " | egrep -e "[ 	]$special_shlib_compile_flags[ 	]" >/dev/null; then :
-  else
-    echo "$progname: add \`$special_shlib_compile_flags' to the CC or CFLAGS env variable and reconfigure" 1>&2
-    can_build_shared=no
-  fi
-fi
-
-echo $ac_n "checking if $compiler static flag $link_static_flag works... $ac_c" 1>&6
-$rm conftest*
-echo 'main(){return(0);}' > conftest.c
-save_LDFLAGS="$LDFLAGS"
-LDFLAGS="$LDFLAGS $link_static_flag"
-echo "$progname:958: checking if $compiler static flag $link_static_flag works" >&5
-if { (eval echo $progname:959: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
-  echo "$ac_t$link_static_flag" 1>&6
-else
-  echo "$ac_t"none 1>&6
-  link_static_flag=
-fi
-LDFLAGS="$save_LDFLAGS"
-$rm conftest*
-
-if test -z "$LN_S"; then
-  # Check to see if we can use ln -s, or we need hard links.
-  echo $ac_n "checking whether ln -s works... $ac_c" 1>&6
-  $rm conftest.dat
-  if ln -s X conftest.dat 2>/dev/null; then
-    $rm conftest.dat
-    LN_S="ln -s"
-  else
-    LN_S=ln
-  fi
-  if test "$LN_S" = "ln -s"; then
-    echo "$ac_t"yes 1>&6
-  else
-    echo "$ac_t"no 1>&6
-  fi
-fi
-
-# Make sure LD is an absolute path.
-if test -z "$LD"; then
-  ac_prog=ld
-  if test "$with_gcc" = yes; then
-    # Check if gcc -print-prog-name=ld gives a path.
-    echo $ac_n "checking for ld used by GCC... $ac_c" 1>&6
-    echo "$progname:991: checking for ld used by GCC" >&5
-    ac_prog=`($CC -print-prog-name=ld) 2>&5`
-    case "$ac_prog" in
-    # Accept absolute paths.
-    [\\/]* | [A-Za-z]:[\\/]*)
-      re_direlt='/[^/][^/]*/\.\./'
-      # Canonicalize the path of ld
-      ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
-      while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
-	ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
-      done
-      test -z "$LD" && LD="$ac_prog"
-      ;;
-    "")
-      # If it fails, then pretend we are not using GCC.
-      ac_prog=ld
-      ;;
-    *)
-      # If it is relative, then search for the first ld in PATH.
-      with_gnu_ld=unknown
-      ;;
-    esac
-  elif test "$with_gnu_ld" = yes; then
-    echo $ac_n "checking for GNU ld... $ac_c" 1>&6
-    echo "$progname:1015: checking for GNU ld" >&5
-  else
-    echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6
-    echo "$progname:1018: checking for non-GNU ld" >&5
-  fi
-
-  if test -z "$LD"; then
-    IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
-    for ac_dir in $PATH; do
-      test -z "$ac_dir" && ac_dir=.
-      if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
-	LD="$ac_dir/$ac_prog"
-	# Check to see if the program is GNU ld.  I'd rather use --version,
-	# but apparently some GNU ld's only accept -v.
-	# Break only if it was the GNU/non-GNU ld that we prefer.
-	if "$LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
-	  test "$with_gnu_ld" != no && break
-	else
-	  test "$with_gnu_ld" != yes && break
-	fi
-      fi
-    done
-    IFS="$ac_save_ifs"
-  fi
-
-  if test -n "$LD"; then
-    echo "$ac_t$LD" 1>&6
-  else
-    echo "$ac_t"no 1>&6
-  fi
-
-  if test -z "$LD"; then
-    echo "$progname: error: no acceptable ld found in \$PATH" 1>&2
-    exit 1
-  fi
-fi
-
-# Check to see if it really is or is not GNU ld.
-echo $ac_n "checking if the linker ($LD) is GNU ld... $ac_c" 1>&6
-# I'd rather use --version here, but apparently some GNU ld's only accept -v.
-if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
-  with_gnu_ld=yes
-else
-  with_gnu_ld=no
-fi
-echo "$ac_t$with_gnu_ld" 1>&6
-
-# See if the linker supports building shared libraries.
-echo $ac_n "checking whether the linker ($LD) supports shared libraries... $ac_c" 1>&6
-
-allow_undefined_flag=
-no_undefined_flag=
-need_lib_prefix=unknown
-need_version=unknown
-# when you set need_version to no, make sure it does not cause -set_version
-# flags to be left without arguments
-archive_cmds=
-archive_expsym_cmds=
-old_archive_from_new_cmds=
-export_dynamic_flag_spec=
-whole_archive_flag_spec=
-thread_safe_flag_spec=
-hardcode_libdir_flag_spec=
-hardcode_libdir_separator=
-hardcode_direct=no
-hardcode_minus_L=no
-hardcode_shlibpath_var=unsupported
-runpath_var=
-always_export_symbols=no
-export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | sed '\''s/.* //'\'' | sort | uniq > $export_symbols'
-# include_expsyms should be a list of space-separated symbols to be *always*
-# included in the symbol list
-include_expsyms=
-# exclude_expsyms can be an egrep regular expression of symbols to exclude
-# it will be wrapped by ` (' and `)$', so one must not match beginning or
-# end of line.  Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
-# as well as any symbol that contains `d'.
-exclude_expsyms="_GLOBAL_OFFSET_TABLE_"
-# Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
-# platforms (ab)use it in PIC code, but their linkers get confused if
-# the symbol is explicitly referenced.  Since portable code cannot
-# rely on this symbol name, it's probably fine to never include it in
-# preloaded symbol tables.
-
-case "$host_os" in
-cygwin* | mingw*)
-  # FIXME: the MSVC++ port hasn't been tested in a loooong time
-  # When not using gcc, we currently assume that we are using
-  # Microsoft Visual C++.
-  if test "$with_gcc" != yes; then
-    with_gnu_ld=no
-  fi
-  ;;
-
-esac
-
-ld_shlibs=yes
-if test "$with_gnu_ld" = yes; then
-  # If archive_cmds runs LD, not CC, wlarc should be empty
-  wlarc='${wl}'
-
-  # See if GNU ld supports shared libraries.
-  case "$host_os" in
-  aix3* | aix4*)
-    # On AIX, the GNU linker is very broken
-    ld_shlibs=no
-    cat <<EOF 1>&2
-
-*** Warning: the GNU linker, at least up to release 2.9.1, is reported
-*** to be unable to reliably create shared libraries on AIX.
-*** Therefore, libtool is disabling shared libraries support.  If you
-*** really care for shared libraries, you may want to modify your PATH
-*** so that a non-GNU linker is found, and then restart.
-
-EOF
-    ;;
-
-  amigaos*)
-    archive_cmds='$rm $objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $objdir/a2ixlibrary.data~$AR cru $lib $libobjs~$RANLIB $lib~(cd $objdir && a2ixlibrary -32)'
-    hardcode_libdir_flag_spec='-L$libdir'
-    hardcode_minus_L=yes
-
-    # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
-    # that the semantics of dynamic libraries on AmigaOS, at least up
-    # to version 4, is to share data among multiple programs linked
-    # with the same dynamic library.  Since this doesn't match the
-    # behavior of shared libraries on other platforms, we can use
-    # them.
-    ld_shlibs=no
-    ;;
-
-  beos*)
-    if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
-      allow_undefined_flag=unsupported
-      # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
-      # support --undefined.  This deserves some investigation.  FIXME
-      archive_cmds='$CC -nostart $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib'
-    else
-      ld_shlibs=no
-    fi
-    ;;
-
-  cygwin* | mingw*)
-    # hardcode_libdir_flag_spec is actually meaningless, as there is
-    # no search path for DLLs.
-    hardcode_libdir_flag_spec='-L$libdir'
-    allow_undefined_flag=unsupported
-    always_export_symbols=yes
-
-    # Extract the symbol export list from an `--export-all' def file,
-    # then regenerate the def file from the symbol export list, so that
-    # the compiled dll only exports the symbol export list.
-    export_symbols_cmds='test -f $objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $0 > $objdir/$soname-ltdll.c~
-      test -f $objdir/$soname-ltdll.$objext || (cd $objdir && $CC -c $soname-ltdll.c)~
-      $DLLTOOL --export-all --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --output-def $objdir/$soname-def  $objdir/$soname-ltdll.$objext $libobjs $convenience~
-      sed -e "1,/EXPORTS/d" -e "s/ @ [0-9]* ; *//" < $objdir/$soname-def > $export_symbols'
-
-    archive_expsym_cmds='echo EXPORTS > $objdir/$soname-def~
-      _lt_hint=1;
-      for symbol in `cat $export_symbols`; do
-	echo "	\$symbol @ \$_lt_hint ; " >> $objdir/$soname-def;
-	_lt_hint=`expr 1 + \$_lt_hint`;
-      done~
-      test -f $objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $0 > $objdir/$soname-ltdll.c~
-      test -f $objdir/$soname-ltdll.$objext || (cd $objdir && $CC -c $soname-ltdll.c)~
-      $CC -Wl,--base-file,$objdir/$soname-base -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts~
-      $DLLTOOL --as=$AS --dllname $soname --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --def $objdir/$soname-def --base-file $objdir/$soname-base --output-exp $objdir/$soname-exp~
-      $CC -Wl,--base-file,$objdir/$soname-base $objdir/$soname-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts~
-      $DLLTOOL --as=$AS --dllname $soname --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --def $objdir/$soname-def --base-file $objdir/$soname-base --output-exp $objdir/$soname-exp~
-      $CC $objdir/$soname-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts'
-
-      old_archive_from_new_cmds='$DLLTOOL --as=$AS --dllname $soname --def $objdir/$soname-def --output-lib $objdir/$libname.a' 
-    ;;
-
-  netbsd*)
-    if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
-      archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib'
-      archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
-    else
-      archive_cmds='$LD -Bshareable $libobjs $deplibs $linkopts -o $lib'
-      # can we support soname and/or expsyms with a.out? -oliva
-    fi
-    ;;
-
-  solaris*)
-    if $LD -v 2>&1 | egrep 'BFD 2\.8' > /dev/null; then
-      ld_shlibs=no
-      cat <<EOF 1>&2
-
-*** Warning: The releases 2.8.* of the GNU linker cannot reliably
-*** create shared libraries on Solaris systems.  Therefore, libtool
-*** is disabling shared libraries support.  We urge you to upgrade GNU
-*** binutils to release 2.9.1 or newer.  Another option is to modify
-*** your PATH or compiler configuration so that the native linker is
-*** used, and then restart.
-
-EOF
-    elif $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
-      archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib'
-      archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
-    else
-      ld_shlibs=no
-    fi
-    ;;      
-
-  sunos4*)
-    archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linkopts'
-    wlarc=
-    hardcode_direct=yes
-    hardcode_shlibpath_var=no
-    ;;
-
-  *)
-    if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
-      archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib'
-      archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
-    else
-      ld_shlibs=no
-    fi
-    ;;
-  esac
-
-  if test "$ld_shlibs" = yes; then
-    runpath_var=LD_RUN_PATH
-    hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir'
-    export_dynamic_flag_spec='${wl}--export-dynamic'
-    case $host_os in
-    cygwin* | mingw*)
-      # dlltool doesn't understand --whole-archive et. al.
-      whole_archive_flag_spec=
-      ;;
-    *)
-      whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
-      ;;
-    esac
-  fi
-else
-  # PORTME fill in a description of your system's linker (not GNU ld)
-  case "$host_os" in
-  aix3*)
-    allow_undefined_flag=unsupported
-    always_export_symbols=yes
-    archive_expsym_cmds='$LD -o $objdir/$soname $libobjs $deplibs $linkopts -bE:$export_symbols -T512 -H512 -bM:SRE~$AR cru $lib $objdir/$soname'
-    # Note: this linker hardcodes the directories in LIBPATH if there
-    # are no directories specified by -L.
-    hardcode_minus_L=yes
-    if test "$with_gcc" = yes && test -z "$link_static_flag"; then
-      # Neither direct hardcoding nor static linking is supported with a
-      # broken collect2.
-      hardcode_direct=unsupported
-    fi
-    ;;
-
-  aix4*)
-    hardcode_libdir_flag_spec='${wl}-b ${wl}nolibpath ${wl}-b ${wl}libpath:$libdir:/usr/lib:/lib'
-    hardcode_libdir_separator=':'
-    if test "$with_gcc" = yes; then
-      collect2name=`${CC} -print-prog-name=collect2`
-      if test -f "$collect2name" && \
-	 strings "$collect2name" | grep resolve_lib_name >/dev/null
-      then
-	# We have reworked collect2
-	hardcode_direct=yes
-      else
-	# We have old collect2
-	hardcode_direct=unsupported
-	# It fails to find uninstalled libraries when the uninstalled
-	# path is not listed in the libpath.  Setting hardcode_minus_L
-	# to unsupported forces relinking
-	hardcode_minus_L=yes
-	hardcode_libdir_flag_spec='-L$libdir'
-	hardcode_libdir_separator=
-      fi
-      shared_flag='-shared'
-    else
-      shared_flag='${wl}-bM:SRE'
-      hardcode_direct=yes
-    fi
-    allow_undefined_flag=' ${wl}-berok'
-    archive_cmds="\$CC $shared_flag"' -o $objdir/$soname $libobjs $deplibs $linkopts ${wl}-bexpall ${wl}-bnoentry${allow_undefined_flag}'
-    archive_expsym_cmds="\$CC $shared_flag"' -o $objdir/$soname $libobjs $deplibs $linkopts ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}'
-    case "$host_os" in aix4.[01]|aix4.[01].*)
-      # According to Greg Wooledge, -bexpall is only supported from AIX 4.2 on
-      always_export_symbols=yes ;;
-    esac
-   ;;
-
-  amigaos*)
-    archive_cmds='$rm $objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $objdir/a2ixlibrary.data~$AR cru $lib $libobjs~$RANLIB $lib~(cd $objdir && a2ixlibrary -32)'
-    hardcode_libdir_flag_spec='-L$libdir'
-    hardcode_minus_L=yes
-    # see comment about different semantics on the GNU ld section
-    ld_shlibs=no
-    ;;
-
-  cygwin* | mingw*)
-    # When not using gcc, we currently assume that we are using
-    # Microsoft Visual C++.
-    # hardcode_libdir_flag_spec is actually meaningless, as there is
-    # no search path for DLLs.
-    hardcode_libdir_flag_spec=' '
-    allow_undefined_flag=unsupported
-    # Tell ltmain to make .lib files, not .a files.
-    libext=lib
-    # FIXME: Setting linknames here is a bad hack.
-    archive_cmds='$CC -o $lib $libobjs $linkopts `echo "$deplibs" | sed -e '\''s/ -lc$//'\''` -link -dll~linknames='
-    # The linker will automatically build a .lib file if we build a DLL.
-    old_archive_from_new_cmds='true'
-    # FIXME: Should let the user specify the lib program.
-    old_archive_cmds='lib /OUT:$oldlib$oldobjs'
-    fix_srcfile_path='`cygpath -w $srcfile`'
-    ;;
-
-  freebsd1*)
-    ld_shlibs=no
-    ;;
-
-  # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
-  # support.  Future versions do this automatically, but an explicit c++rt0.o
-  # does not break anything, and helps significantly (at the cost of a little
-  # extra space).
-  freebsd2.2*)
-    archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts /usr/lib/c++rt0.o'
-    hardcode_libdir_flag_spec='-R$libdir'
-    hardcode_direct=yes
-    hardcode_shlibpath_var=no
-    ;;
-
-  # Unfortunately, older versions of FreeBSD 2 do not have this feature.
-  freebsd2*)
-    archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts'
-    hardcode_direct=yes
-    hardcode_minus_L=yes
-    hardcode_shlibpath_var=no
-    ;;
-
-  # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
-  freebsd*)
-    archive_cmds='$CC -shared -o $lib $libobjs $deplibs $linkopts'
-    hardcode_libdir_flag_spec='-R$libdir'
-    hardcode_direct=yes
-    hardcode_shlibpath_var=no
-    ;;
-
-  hpux9* | hpux10* | hpux11*)
-    case "$host_os" in
-    hpux9*) archive_cmds='$rm $objdir/$soname~$LD -b +b $install_libdir -o $objdir/$soname $libobjs $deplibs $linkopts~test $objdir/$soname = $lib || mv $objdir/$soname $lib' ;;
-    *) archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linkopts' ;;
-    esac
-    hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
-    hardcode_libdir_separator=:
-    hardcode_direct=yes
-    hardcode_minus_L=yes # Not in the search PATH, but as the default
-			 # location of the library.
-    export_dynamic_flag_spec='${wl}-E'
-    ;;
-
-  irix5* | irix6*)
-    if test "$with_gcc" = yes; then
-      archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib'
-    else
-      archive_cmds='$LD -shared $libobjs $deplibs $linkopts -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib'
-    fi
-    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
-    hardcode_libdir_separator=:
-    ;;
-
-  netbsd*)
-    if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
-      archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts'  # a.out
-    else
-      archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linkopts'      # ELF
-    fi
-    hardcode_libdir_flag_spec='${wl}-R$libdir'
-    hardcode_direct=yes
-    hardcode_shlibpath_var=no
-    ;;
-
-  openbsd*)
-    archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts'
-    hardcode_libdir_flag_spec='-R$libdir'
-    hardcode_direct=yes
-    hardcode_shlibpath_var=no
-    ;;
-
-  os2*)
-    hardcode_libdir_flag_spec='-L$libdir'
-    hardcode_minus_L=yes
-    allow_undefined_flag=unsupported
-    archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $objdir/$libname.def~$echo DATA >> $objdir/$libname.def~$echo " SINGLE NONSHARED" >> $objdir/$libname.def~$echo EXPORTS >> $objdir/$libname.def~emxexp $libobjs >> $objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $linkopts $objdir/$libname.def'
-    old_archive_from_new_cmds='emximp -o $objdir/$libname.a $objdir/$libname.def'
-    ;;
-
-  osf3* | osf4*)
-    if test "$with_gcc" = yes; then
-      allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
-      archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $linkopts ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib'
-    else
-      allow_undefined_flag=' -expect_unresolved \*'
-      archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linkopts -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib'
-    fi
-    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
-    hardcode_libdir_separator=:
-    ;;
-
-  sco3.2v5*)
-    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
-    hardcode_shlibpath_var=no
-    runpath_var=LD_RUN_PATH
-    hardcode_runpath_var=yes
-    ;;
-
-  solaris*)
-    no_undefined_flag=' -z text'
-    # $CC -shared without GNU ld will not create a library from C++
-    # object files and a static libstdc++, better avoid it by now
-    archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linkopts'
-    archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
-		$LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linkopts~$rm $lib.exp'
-    hardcode_libdir_flag_spec='-R$libdir'
-    hardcode_shlibpath_var=no
-    case "$host_os" in
-    solaris2.[0-5] | solaris2.[0-5].*) ;;
-    *) # Supported since Solaris 2.6 (maybe 2.5.1?)
-      whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;;
-    esac
-    ;;
-
-  sunos4*)
-    archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linkopts'
-    hardcode_libdir_flag_spec='-L$libdir'
-    hardcode_direct=yes
-    hardcode_minus_L=yes
-    hardcode_shlibpath_var=no
-    ;;
-
-  sysv4)
-    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
-    runpath_var='LD_RUN_PATH'
-    hardcode_shlibpath_var=no
-    hardcode_direct=no #Motorola manual says yes, but my tests say they lie 
-    ;;  
-
-  sysv4.3*)
-    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
-    hardcode_shlibpath_var=no
-    export_dynamic_flag_spec='-Bexport'
-    ;;
-
-  uts4*)
-    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
-    hardcode_libdir_flag_spec='-L$libdir'
-    hardcode_shlibpath_var=no
-    ;;
-
-  dgux*)
-    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
-    hardcode_libdir_flag_spec='-L$libdir'
-    hardcode_shlibpath_var=no
-    ;;
-
-  sysv4*MP*)
-    if test -d /usr/nec ;then
-    # archive_cmds='$LD -G -z text -h $soname -o $lib$libobjs$deplibs'
-    archive_cmds='$LD -G -h $soname -o $lib$libobjs$deplibs'
-    hardcode_shlibpath_var=no
-    runpath_var=LD_RUN_PATH
-    hardcode_runpath_var=yes
-    ld_shlibs=yes
-    fi
-    ;;
-
-  *)
-    ld_shlibs=no
-    ;;
-  esac
-fi
-echo "$ac_t$ld_shlibs" 1>&6
-test "$ld_shlibs" = no && can_build_shared=no
-
-if test -z "$NM"; then
-  echo $ac_n "checking for BSD-compatible nm... $ac_c" 1>&6
-  case "$NM" in
-  [\\/]* | [A-Za-z]:[\\/]*) ;; # Let the user override the test with a path.
-  *)
-    IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
-    for ac_dir in $PATH /usr/ucb /usr/ccs/bin /bin; do
-      test -z "$ac_dir" && ac_dir=.
-      if test -f $ac_dir/nm || test -f $ac_dir/nm$ac_exeext; then
-	# Check to see if the nm accepts a BSD-compat flag.
-	# Adding the `sed 1q' prevents false positives on HP-UX, which says:
-	#   nm: unknown option "B" ignored
-	if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
-	  NM="$ac_dir/nm -B"
-	  break
-	elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
-	  NM="$ac_dir/nm -p"
-	  break
-	else
-	  NM=${NM="$ac_dir/nm"} # keep the first match, but
-	  continue # so that we can try to find one that supports BSD flags
-	fi
-      fi
-    done
-    IFS="$ac_save_ifs"
-    test -z "$NM" && NM=nm
-    ;;
-  esac
-  echo "$ac_t$NM" 1>&6
-fi
-
-# Check for command to grab the raw symbol name followed by C symbol from nm.
-echo $ac_n "checking command to parse $NM output... $ac_c" 1>&6
-
-# These are sane defaults that work on at least a few old systems.
-# [They come from Ultrix.  What could be older than Ultrix?!! ;)]
-
-# Character class describing NM global symbol codes.
-symcode='[BCDEGRST]'
-
-# Regexp to match symbols that can be accessed directly from C.
-sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
-
-# Transform the above into a raw symbol and a C symbol.
-symxfrm='\1 \2\3 \3'
-
-# Transform an extracted symbol line into a proper C declaration
-global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'"
-
-# Define system-specific variables.
-case "$host_os" in
-aix*)
-  symcode='[BCDT]'
-  ;;
-cygwin* | mingw*)
-  symcode='[ABCDGISTW]'
-  ;;
-hpux*) # Its linker distinguishes data from code symbols
-  global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^. .* \(.*\)$/extern char \1;/p'"
-  ;;
-irix*)
-  symcode='[BCDEGRST]'
-  ;;
-solaris*)
-  symcode='[BDT]'
-  ;;
-sysv4)
-  symcode='[DFNSTU]'
-  ;;
-esac
-
-# If we're using GNU nm, then use its standard symbol codes.
-if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then
-  symcode='[ABCDGISTW]'
-fi
-
-# Try without a prefix undercore, then with it.
-for ac_symprfx in "" "_"; do
-
-  # Write the raw and C identifiers.
-  global_symbol_pipe="sed -n -e 's/^.*[ 	]\($symcode\)[ 	][ 	]*\($ac_symprfx\)$sympat$/$symxfrm/p'"
-
-  # Check to see that the pipe works correctly.
-  pipe_works=no
-  $rm conftest*
-  cat > conftest.c <<EOF
-#ifdef __cplusplus
-extern "C" {
-#endif
-char nm_test_var;
-void nm_test_func(){}
-#ifdef __cplusplus
-}
-#endif
-main(){nm_test_var='a';nm_test_func();return(0);}
-EOF
-
-  echo "$progname:1592: checking if global_symbol_pipe works" >&5
-  if { (eval echo $progname:1593: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; } && test -s conftest.$objext; then
-    # Now try to grab the symbols.
-    nlist=conftest.nm
-    if { echo "$progname:1596: eval \"$NM conftest.$objext | $global_symbol_pipe > $nlist\"" >&5; eval "$NM conftest.$objext | $global_symbol_pipe > $nlist 2>&5"; } && test -s "$nlist"; then
-
-      # Try sorting and uniquifying the output.
-      if sort "$nlist" | uniq > "$nlist"T; then
-	mv -f "$nlist"T "$nlist"
-      else
-	rm -f "$nlist"T
-      fi
-
-      # Make sure that we snagged all the symbols we need.
-      if egrep ' nm_test_var$' "$nlist" >/dev/null; then
-	if egrep ' nm_test_func$' "$nlist" >/dev/null; then
-	  cat <<EOF > conftest.c
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-EOF
-	  # Now generate the symbol file.
-	  eval "$global_symbol_to_cdecl"' < "$nlist" >> conftest.c'
-
-	  cat <<EOF >> conftest.c
-#if defined (__STDC__) && __STDC__
-# define lt_ptr_t void *
-#else
-# define lt_ptr_t char *
-# define const
-#endif
-
-/* The mapping between symbol names and symbols. */
-const struct {
-  const char *name;
-  lt_ptr_t address;
-}
-lt_preloaded_symbols[] =
-{
-EOF
-	  sed 's/^. \(.*\) \(.*\)$/  {"\2", (lt_ptr_t) \&\2},/' < "$nlist" >> conftest.c
-	  cat <<\EOF >> conftest.c
-  {0, (lt_ptr_t) 0}
-};
-
-#ifdef __cplusplus
-}
-#endif
-EOF
-	  # Now try linking the two files.
-	  mv conftest.$objext conftstm.$objext
-	  save_LIBS="$LIBS"
-	  save_CFLAGS="$CFLAGS"
-	  LIBS="conftstm.$objext"
-	  CFLAGS="$CFLAGS$no_builtin_flag"
-	  if { (eval echo $progname:1648: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
-	    pipe_works=yes
-	  else
-	    echo "$progname: failed program was:" >&5
-	    cat conftest.c >&5
-	  fi
-	  LIBS="$save_LIBS"
-	else
-	  echo "cannot find nm_test_func in $nlist" >&5
-	fi
-      else
-	echo "cannot find nm_test_var in $nlist" >&5
-      fi
-    else
-      echo "cannot run $global_symbol_pipe" >&5
-    fi
-  else
-    echo "$progname: failed program was:" >&5
-    cat conftest.c >&5
-  fi
-  $rm conftest* conftst*
-
-  # Do not use the global_symbol_pipe unless it works.
-  if test "$pipe_works" = yes; then
-    break
-  else
-    global_symbol_pipe=
-  fi
-done
-if test "$pipe_works" = yes; then
-  echo "${ac_t}ok" 1>&6
-else
-  echo "${ac_t}failed" 1>&6
-fi
-
-if test -z "$global_symbol_pipe"; then
-  global_symbol_to_cdecl=
-fi
-
-# Check hardcoding attributes.
-echo $ac_n "checking how to hardcode library paths into programs... $ac_c" 1>&6
-hardcode_action=
-if test -n "$hardcode_libdir_flag_spec" || \
-   test -n "$runpath_var"; then
-
-  # We can hardcode non-existant directories.
-  if test "$hardcode_direct" != no &&
-     # If the only mechanism to avoid hardcoding is shlibpath_var, we
-     # have to relink, otherwise we might link with an installed library
-     # when we should be linking with a yet-to-be-installed one
-     ## test "$hardcode_shlibpath_var" != no &&
-     test "$hardcode_minus_L" != no; then
-    # Linking always hardcodes the temporary library directory.
-    hardcode_action=relink
-  else
-    # We can link without hardcoding, and we can hardcode nonexisting dirs.
-    hardcode_action=immediate
-  fi
-else
-  # We cannot hardcode anything, or else we can only hardcode existing
-  # directories.
-  hardcode_action=unsupported
-fi
-echo "$ac_t$hardcode_action" 1>&6
-
-
-reload_flag=
-reload_cmds='$LD$reload_flag -o $output$reload_objs'
-echo $ac_n "checking for $LD option to reload object files... $ac_c" 1>&6
-# PORTME Some linkers may need a different reload flag.
-reload_flag='-r'
-echo "$ac_t$reload_flag" 1>&6
-test -n "$reload_flag" && reload_flag=" $reload_flag"
-
-# PORTME Fill in your ld.so characteristics
-library_names_spec=
-libname_spec='lib$name'
-soname_spec=
-postinstall_cmds=
-postuninstall_cmds=
-finish_cmds=
-finish_eval=
-shlibpath_var=
-shlibpath_overrides_runpath=unknown
-version_type=none
-dynamic_linker="$host_os ld.so"
-sys_lib_dlsearch_path_spec="/lib /usr/lib"
-sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
-file_magic_cmd=
-file_magic_test_file=
-deplibs_check_method='unknown'
-# Need to set the preceding variable on all platforms that support
-# interlibrary dependencies.
-# 'none' -- dependencies not supported.
-# `unknown' -- same as none, but documents that we really don't know.
-# 'pass_all' -- all dependencies passed with no checks.
-# 'test_compile' -- check by making test program.
-# 'file_magic [regex]' -- check by looking for files in library path
-# which responds to the $file_magic_cmd with a given egrep regex.
-# If you have `file' or equivalent on your system and you're not sure
-# whether `pass_all' will *always* work, you probably want this one.
-echo $ac_n "checking dynamic linker characteristics... $ac_c" 1>&6
-case "$host_os" in
-aix3*)
-  version_type=linux
-  library_names_spec='${libname}${release}.so$versuffix $libname.a'
-  shlibpath_var=LIBPATH
-
-  # AIX has no versioning support, so we append a major version to the name.
-  soname_spec='${libname}${release}.so$major'
-  ;;
-
-aix4*)
-  version_type=linux
-  # AIX has no versioning support, so currently we can not hardcode correct
-  # soname into executable. Probably we can add versioning support to
-  # collect2, so additional links can be useful in future.
-  # We preserve .a as extension for shared libraries though AIX4.2
-  # and later linker supports .so
-  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.a'
-  shlibpath_var=LIBPATH
-  deplibs_check_method=pass_all
-  ;;
-
-amigaos*)
-  library_names_spec='$libname.ixlibrary $libname.a'
-  # Create ${libname}_ixlibrary.a entries in /sys/libs.
-  finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done'
-  ;;
-
-beos*)
-  library_names_spec='${libname}.so'
-  dynamic_linker="$host_os ld.so"
-  shlibpath_var=LIBRARY_PATH
-  deplibs_check_method=pass_all
-  lt_cv_dlopen="load_add_on"
-  lt_cv_dlopen_libs=
-  lt_cv_dlopen_self=yes
-  ;;
-
-bsdi4*)
-  version_type=linux
-  library_names_spec='${libname}.so$major ${libname}.so'
-  soname_spec='${libname}.so'
-  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
-  shlibpath_var=LD_LIBRARY_PATH
-  deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
-  file_magic_cmd=/usr/bin/file
-  file_magic_test_file=/shlib/libc.so
-  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
-  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
-  # the default ld.so.conf also contains /usr/contrib/lib and
-  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
-  # libtool to hard-code these into programs
-  ;;
-
-cygwin* | mingw*)
-  version_type=windows
-  need_version=no
-  need_lib_prefix=no
-  if test "$with_gcc" = yes; then
-    library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.a'
-  else
-    library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.lib'
-  fi
-  dynamic_linker='Win32 ld.exe'
-  deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
-  file_magic_cmd='${OBJDUMP} -f'
-  # FIXME: first we should search . and the directory the executable is in
-  shlibpath_var=PATH
-  lt_cv_dlopen="LoadLibrary"
-  lt_cv_dlopen_libs=
-  ;;
-
-freebsd1*)
-  dynamic_linker=no
-  ;;
-  
-freebsd*)
-  objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout`
-  version_type=freebsd-$objformat
-  case "$version_type" in
-    freebsd-elf*)
-      deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB shared object'
-      file_magic_cmd=/usr/bin/file
-      file_magic_test_file=`echo /usr/lib/libc.so*`
-      library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so'
-      need_version=no
-      need_lib_prefix=no
-      ;;
-    freebsd-*)
-      deplibs_check_method=unknown
-      library_names_spec='${libname}${release}.so$versuffix $libname.so$versuffix'
-      need_version=yes
-      ;;
-  esac
-  finish_cmds='PATH="\$PATH:/sbin" OBJFORMAT="'"$objformat"'" ldconfig -m $libdir'
-  shlibpath_var=LD_LIBRARY_PATH
-  case "$host_os" in
-  freebsd2* | freebsd3.[01]*)
-    shlibpath_overrides_runpath=yes
-    ;;
-  *) # from 3.2 on
-    shlibpath_overrides_runpath=no
-    ;;
-  esac
-  ;;
-
-gnu*)
-  version_type=linux
-  need_lib_prefix=no
-  need_version=no
-  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so${major} ${libname}.so'
-  soname_spec='${libname}${release}.so$major'
-  shlibpath_var=LD_LIBRARY_PATH
-  ;;
-
-hpux9* | hpux10* | hpux11*)
-  # Give a soname corresponding to the major version so that dld.sl refuses to
-  # link against other versions.
-  dynamic_linker="$host_os dld.sl"
-  version_type=sunos
-  need_lib_prefix=no
-  need_version=no
-  shlibpath_var=SHLIB_PATH
-  shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
-  library_names_spec='${libname}${release}.sl$versuffix ${libname}${release}.sl$major $libname.sl'
-  soname_spec='${libname}${release}.sl$major'
-  # HP-UX runs *really* slowly unless shared libraries are mode 555.
-  postinstall_cmds='chmod 555 $lib'
-  ;;
-
-irix5* | irix6*)
-  version_type=irix
-  need_lib_prefix=no
-  need_version=no
-  soname_spec='${libname}${release}.so.$major'
-  library_names_spec='${libname}${release}.so.$versuffix ${libname}${release}.so.$major ${libname}${release}.so $libname.so'
-  case "$host_os" in
-  irix5*)
-    libsuff= shlibsuff=
-    # this will be overridden with pass_all, but let us keep it just in case
-    deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1"
-    ;;
-  *)
-    case "$LD" in # libtool.m4 will add one of these switches to LD
-    *-32|*"-32 ") libsuff= shlibsuff= libmagic=32-bit;;
-    *-n32|*"-n32 ") libsuff=32 shlibsuff=N32 libmagic=N32;;
-    *-64|*"-64 ") libsuff=64 shlibsuff=64 libmagic=64-bit;;
-    *) libsuff= shlibsuff= libmagic=never-match;;
-    esac
-    # this will be overridden with pass_all, but let us keep it just in case
-    deplibs_check_method="file_magic ELF ${libmagic} MSB mips-[1234] dynamic lib MIPS - version 1"
-    ;;
-  esac
-  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
-  shlibpath_overrides_runpath=no
-  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
-  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
-  file_magic_cmd=/usr/bin/file
-  file_magic_test_file=`echo /lib${libsuff}/libc.so*`
-  deplibs_check_method='pass_all'
-  ;;
-
-# No shared lib support for Linux oldld, aout, or coff.
-linux-gnuoldld* | linux-gnuaout* | linux-gnucoff*)
-  dynamic_linker=no
-  ;;
-
-# This must be Linux ELF.
-linux-gnu*)
-  version_type=linux
-  need_lib_prefix=no
-  need_version=no
-  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
-  soname_spec='${libname}${release}.so$major'
-  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
-  shlibpath_var=LD_LIBRARY_PATH
-  shlibpath_overrides_runpath=no
-  deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
-  file_magic_cmd=/usr/bin/file
-  file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so`
-
-  if test -f /lib/ld.so.1; then
-    dynamic_linker='GNU ld.so'
-  else
-    # Only the GNU ld.so supports shared libraries on MkLinux.
-    case "$host_cpu" in
-    powerpc*) dynamic_linker=no ;;
-    *) dynamic_linker='Linux ld.so' ;;
-    esac
-  fi
-  ;;
-
-netbsd*)
-  version_type=sunos
-  if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
-    library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
-    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
-    dynamic_linker='NetBSD (a.out) ld.so'
-  else
-    library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so ${libname}.so'
-    soname_spec='${libname}${release}.so$major'
-    dynamic_linker='NetBSD ld.elf_so'
-  fi
-  shlibpath_var=LD_LIBRARY_PATH
-  ;;
-
-openbsd*)
-  version_type=sunos
-  if test "$with_gnu_ld" = yes; then
-    need_lib_prefix=no
-    need_version=no
-  fi
-  library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
-  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
-  shlibpath_var=LD_LIBRARY_PATH
-  ;;
-
-os2*)
-  libname_spec='$name'
-  need_lib_prefix=no
-  library_names_spec='$libname.dll $libname.a'
-  dynamic_linker='OS/2 ld.exe'
-  shlibpath_var=LIBPATH
-  ;;
-
-osf3* | osf4*)
-  version_type=osf
-  need_version=no
-  soname_spec='${libname}${release}.so'
-  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so'
-  shlibpath_var=LD_LIBRARY_PATH
-  # this will be overridden with pass_all, but let us keep it just in case
-  deplibs_check_method='file_magic COFF format alpha shared library'
-  file_magic_cmd=/usr/bin/file
-  file_magic_test_file=/shlib/libc.so
-  deplibs_check_method='pass_all'
-  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
-  sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
-  ;;
-
-sco3.2v5*)
-  version_type=osf
-  soname_spec='${libname}${release}.so$major'
-  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
-  shlibpath_var=LD_LIBRARY_PATH
-  ;;
-
-solaris*)
-  version_type=linux
-  need_lib_prefix=no
-  need_version=no
-  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
-  soname_spec='${libname}${release}.so$major'
-  shlibpath_var=LD_LIBRARY_PATH
-  shlibpath_overrides_runpath=yes
-  # ldd complains unless libraries are executable
-  postinstall_cmds='chmod +x $lib'
-  deplibs_check_method="file_magic ELF [0-9][0-9]-bit [LM]SB dynamic lib"
-  file_magic_cmd=/usr/bin/file
-  file_magic_test_file=/lib/libc.so
-  ;;
-
-sunos4*)
-  version_type=sunos
-  library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
-  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
-  shlibpath_var=LD_LIBRARY_PATH
-  shlibpath_overrides_runpath=yes
-  if test "$with_gnu_ld" = yes; then
-    need_lib_prefix=no
-  fi
-  need_version=yes
-  ;;
-
-sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
-  version_type=linux
-  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
-  soname_spec='${libname}${release}.so$major'
-  shlibpath_var=LD_LIBRARY_PATH
-  case "$host_vendor" in
-    ncr)
-      deplibs_check_method='pass_all'
-      ;;
-    motorola)
-      need_lib_prefix=no
-      need_version=no
-      shlibpath_overrides_runpath=no
-      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
-      deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'
-      file_magic_cmd=/usr/bin/file
-      file_magic_test_file=`echo /usr/lib/libc.so*`
-      ;;
-  esac
-  ;;
-
-uts4*)
-  version_type=linux
-  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
-  soname_spec='${libname}${release}.so$major'
-  shlibpath_var=LD_LIBRARY_PATH
-  ;;
-
-dgux*)
-  version_type=linux
-  need_lib_prefix=no
-  need_version=no
-  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
-  soname_spec='${libname}${release}.so$major'
-  shlibpath_var=LD_LIBRARY_PATH
-  ;;
-
-sysv4*MP*)
-  if test -d /usr/nec ;then
-    version_type=linux
-    library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so'
-    soname_spec='$libname.so.$major'
-    shlibpath_var=LD_LIBRARY_PATH
-  fi
-  ;;
-
-*)
-  dynamic_linker=no
-  ;;
-esac
-echo "$ac_t$dynamic_linker" 1>&6
-test "$dynamic_linker" = no && can_build_shared=no
-
-# Report the final consequences.
-echo "checking if libtool supports shared libraries... $can_build_shared" 1>&6
-
-# Only try to build win32 dlls if AC_LIBTOOL_WIN32_DLL was used in
-# configure.in, otherwise build static only libraries.
-case "$host_os" in
-cygwin* | mingw* | os2*)
-  if test x$can_build_shared = xyes; then
-    test x$enable_win32_dll = xno && can_build_shared=no
-    echo "checking if package supports dlls... $can_build_shared" 1>&6
-  fi
-;;
-esac
-
-if test -n "$file_magic_test_file" && test -n "$file_magic_cmd"; then
-  case "$deplibs_check_method" in
-  "file_magic "*)
-    file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`"
-    if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
-       egrep "$file_magic_regex" > /dev/null; then
-      :
-    else
-      cat <<EOF 1>&2
-
-*** Warning: the command libtool uses to detect shared libraries,
-*** $file_magic_cmd, produces output that libtool cannot recognize.
-*** The result is that libtool may fail to recognize shared libraries
-*** as such.  This will affect the creation of libtool libraries that
-*** depend on shared libraries, but programs linked with such libtool
-*** libraries will work regardless of this problem.  Nevertheless, you
-*** may want to report the problem to your system manager and/or to
-*** bug-libtool@gnu.org
-
-EOF
-    fi ;;
-  esac
-fi
-
-echo $ac_n "checking whether to build shared libraries... $ac_c" 1>&6
-test "$can_build_shared" = "no" && enable_shared=no
-
-# On AIX, shared libraries and static libraries use the same namespace, and
-# are all built from PIC.
-case "$host_os" in
-aix3*)
-  test "$enable_shared" = yes && enable_static=no
-  if test -n "$RANLIB"; then
-    archive_cmds="$archive_cmds~\$RANLIB \$lib"
-    postinstall_cmds='$RANLIB $lib'
-  fi
-  ;;
-
-aix4*)
-  test "$enable_shared" = yes && enable_static=no
-  ;;
-esac
-
-echo "$ac_t$enable_shared" 1>&6
-
-# Make sure either enable_shared or enable_static is yes.
-test "$enable_shared" = yes || enable_static=yes
-
-echo "checking whether to build static libraries... $enable_static" 1>&6
-
-if test "$hardcode_action" = relink; then
-  # Fast installation is not supported
-  enable_fast_install=no
-elif test "$shlibpath_overrides_runpath" = yes ||
-     test "$enable_shared" = no; then
-  # Fast installation is not necessary
-  enable_fast_install=needless
-fi
-
-echo $ac_n "checking for objdir... $ac_c" 1>&6
-rm -f .libs 2>/dev/null
-mkdir .libs 2>/dev/null
-if test -d .libs; then
-  objdir=.libs
-else
-  # MS-DOS does not allow filenames that begin with a dot.
-  objdir=_libs
-fi
-rmdir .libs 2>/dev/null
-echo "$ac_t$objdir" 1>&6
-
-if test "x$enable_dlopen" != xyes; then
-  enable_dlopen=unknown
-  enable_dlopen_self=unknown
-  enable_dlopen_self_static=unknown
-else
-if eval "test \"`echo '$''{'lt_cv_dlopen'+set}'`\" != set"; then
-  lt_cv_dlopen=no lt_cv_dlopen_libs=
-echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6
-echo "$progname:2170: checking for dlopen in -ldl" >&5
-ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
-  echo $ac_n "(cached) $ac_c" 1>&6
-else
-  ac_save_LIBS="$LIBS"
-LIBS="-ldl  $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 2178 "ltconfig"
-/* Override any gcc2 internal prototype to avoid an error.  */
-/* We use char because int might match the return type of a gcc2
-    builtin and then its argument prototype would still apply.  */
-char dlopen();
-
-int main() {
-dlopen()
-; return 0; }
-EOF
-if { (eval echo $progname:2188: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
-  rm -rf conftest*
-  eval "ac_cv_lib_$ac_lib_var=yes"
-else
-  echo "$progname: failed program was:" >&5
-  cat conftest.$ac_ext >&5
-  rm -rf conftest*
-  eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
-  echo "$ac_t""yes" 1>&6
-  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
-else
-  echo "$ac_t""no" 1>&6
-echo $ac_n "checking for dlopen""... $ac_c" 1>&6
-echo "$progname:2207: checking for dlopen" >&5
-if eval "test \"`echo '$''{'ac_cv_func_dlopen'+set}'`\" = set"; then
-  echo $ac_n "(cached) $ac_c" 1>&6
-else
-  cat > conftest.$ac_ext <<EOF
-#line 2212 "ltconfig"
-/* System header to define __stub macros and hopefully few prototypes,
-    which can conflict with char dlopen(); below.  */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error.  */
-/* We use char because int might match the return type of a gcc2
-    builtin and then its argument prototype would still apply.  */
-char dlopen();
-
-int main() {
-
-/* The GNU C library defines this for functions which it implements
-    to always fail with ENOSYS.  Some functions are actually named
-    something starting with __ and the normal name is an alias.  */
-#if defined (__stub_dlopen) || defined (__stub___dlopen)
-choke me
-#else
-dlopen();
-#endif
-
-; return 0; }
-EOF
-if { (eval echo $progname:2234: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
-  rm -rf conftest*
-  eval "ac_cv_func_dlopen=yes"
-else
-  echo "$progname: failed program was:" >&5
-  cat conftest.$ac_ext >&5
-  rm -rf conftest*
-  eval "ac_cv_func_dlopen=no"
-fi
-rm -f conftest*
-fi
-if eval "test \"`echo '$ac_cv_func_'dlopen`\" = yes"; then
-  echo "$ac_t""yes" 1>&6
-  lt_cv_dlopen="dlopen"
-else
-  echo "$ac_t""no" 1>&6
-echo $ac_n "checking for dld_link in -ldld""... $ac_c" 1>&6
-echo "$progname:2251: checking for dld_link in -ldld" >&5
-ac_lib_var=`echo dld'_'dld_link | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
-  echo $ac_n "(cached) $ac_c" 1>&6
-else
-  ac_save_LIBS="$LIBS"
-LIBS="-ldld  $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 2259 "ltconfig"
-/* Override any gcc2 internal prototype to avoid an error.  */
-/* We use char because int might match the return type of a gcc2
-    builtin and then its argument prototype would still apply.  */
-char dld_link();
-
-int main() {
-dld_link()
-; return 0; }
-EOF
-if { (eval echo $progname:2269: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
-  rm -rf conftest*
-  eval "ac_cv_lib_$ac_lib_var=yes"
-else
-  echo "$progname: failed program was:" >&5
-  cat conftest.$ac_ext >&5
-  rm -rf conftest*
-  eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
-  echo "$ac_t""yes" 1>&6
-  lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"
-else
-  echo "$ac_t""no" 1>&6
-echo $ac_n "checking for shl_load""... $ac_c" 1>&6
-echo "$progname:2288: checking for shl_load" >&5
-if eval "test \"`echo '$''{'ac_cv_func_shl_load'+set}'`\" = set"; then
-  echo $ac_n "(cached) $ac_c" 1>&6
-else
-  cat > conftest.$ac_ext <<EOF
-#line 2293 "ltconfig"
-/* System header to define __stub macros and hopefully few prototypes,
-    which can conflict with char shl_load(); below.  */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error.  */
-/* We use char because int might match the return type of a gcc2
-    builtin and then its argument prototype would still apply.  */
-char shl_load();
-
-int main() {
-
-/* The GNU C library defines this for functions which it implements
-    to always fail with ENOSYS.  Some functions are actually named
-    something starting with __ and the normal name is an alias.  */
-#if defined (__stub_shl_load) || defined (__stub___shl_load)
-choke me
-#else
-shl_load();
-#endif
-
-; return 0; }
-EOF
-if { (eval echo $progname:2315: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
-  rm -rf conftest*
-  eval "ac_cv_func_shl_load=yes"
-else
-  echo "$progname: failed program was:" >&5
-  cat conftest.$ac_ext >&5
-  rm -rf conftest*
-  eval "ac_cv_func_shl_load=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'shl_load`\" = yes"; then
-  echo "$ac_t""yes" 1>&6
-  lt_cv_dlopen="shl_load"
-else
-  echo "$ac_t""no" 1>&6
-echo $ac_n "checking for shl_load in -ldld""... $ac_c" 1>&6
-echo "$progname:2333: checking for shl_load in -ldld" >&5
-ac_lib_var=`echo dld'_'shl_load | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
-  echo $ac_n "(cached) $ac_c" 1>&6
-else
-  ac_save_LIBS="$LIBS"
-LIBS="-ldld  $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 2341 "ltconfig"
-#include "confdefs.h"
-/* Override any gcc2 internal prototype to avoid an error.  */
-/* We use char because int might match the return type of a gcc2
-    builtin and then its argument prototype would still apply.  */
-char shl_load();
-
-int main() {
-shl_load()
-; return 0; }
-EOF
-if { (eval echo $progname:2352: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
-  rm -rf conftest*
-  eval "ac_cv_lib_$ac_lib_var=yes"
-else
-  echo "$progname: failed program was:" >&5
-  cat conftest.$ac_ext >&5
-  rm -rf conftest*
-  eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
-  echo "$ac_t""yes" 1>&6
-  lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"
-else
-  echo "$ac_t""no" 1>&6
-fi
-
-
-fi
-
-    
-fi
-
-  
-fi
-
-
-fi
-
-fi
-
-  if test "x$lt_cv_dlopen" != xno; then
-    enable_dlopen=yes
-  fi
-
-  case "$lt_cv_dlopen" in
-  dlopen)
-for ac_hdr in dlfcn.h; do
-ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "$progname:2395: checking for $ac_hdr" >&5
-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
-  echo $ac_n "(cached) $ac_c" 1>&6
-else
-  cat > conftest.$ac_ext <<EOF
-#line 2400 "ltconfig"
-#include <$ac_hdr>
-int fnord = 0;
-EOF
-ac_try="$ac_compile conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo $progname:2405: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
-  rm -rf conftest*
-  eval "ac_cv_header_$ac_safe=yes"
-else
-  echo "$ac_err" >&5
-  echo "$progname: failed program was:" >&5
-  cat conftest.$ac_ext >&5
-  rm -rf conftest*
-  eval "ac_cv_header_$ac_safe=no"
-fi
-rm -f conftest*
-fi
-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
-  echo "$ac_t""yes" 1>&6
-else
-  echo "$ac_t""no" 1>&6
-fi
-done
-
-    if test "x$ac_cv_header_dlfcn_h" = xyes; then
-      CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
-    fi
-    eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
-    LIBS="$lt_cv_dlopen_libs $LIBS"
-
-  echo $ac_n "checking whether a program can dlopen itself""... $ac_c" 1>&6
-echo "$progname:2433: checking whether a program can dlopen itself" >&5
-if test "${lt_cv_dlopen_self+set}" = set; then
-  echo $ac_n "(cached) $ac_c" 1>&6
-else
-  if test "$cross_compiling" = yes; then
-    lt_cv_dlopen_self=cross
-  else
-    cat > conftest.c <<EOF
-#line 2441 "ltconfig"
-
-#if HAVE_DLFCN_H
-#include <dlfcn.h>
-#endif
-
-#include <stdio.h>
-
-#ifdef RTLD_GLOBAL
-# define LTDL_GLOBAL	RTLD_GLOBAL
-#else
-# ifdef DL_GLOBAL
-#  define LTDL_GLOBAL	DL_GLOBAL
-# else
-#  define LTDL_GLOBAL	0
-# endif
-#endif
-
-/* We may have to define LTDL_LAZY_OR_NOW in the command line if we
-   find out it does not work in some platform. */
-#ifndef LTDL_LAZY_OR_NOW
-# ifdef RTLD_LAZY
-#  define LTDL_LAZY_OR_NOW	RTLD_LAZY
-# else
-#  ifdef DL_LAZY
-#   define LTDL_LAZY_OR_NOW	DL_LAZY
-#  else
-#   ifdef RTLD_NOW
-#    define LTDL_LAZY_OR_NOW	RTLD_NOW
-#   else
-#    ifdef DL_NOW
-#     define LTDL_LAZY_OR_NOW	DL_NOW
-#    else
-#     define LTDL_LAZY_OR_NOW	0
-#    endif
-#   endif
-#  endif
-# endif
-#endif
-
-fnord() { int i=42;}
-main() { void *self, *ptr1, *ptr2; self=dlopen(0,LTDL_GLOBAL|LTDL_LAZY_OR_NOW);
-    if(self) { ptr1=dlsym(self,"fnord"); ptr2=dlsym(self,"_fnord");
-	       if(ptr1 || ptr2) { dlclose(self); exit(0); } } exit(1); } 
-
-EOF
-if { (eval echo $progname:2487: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
-then
-  lt_cv_dlopen_self=yes
-else
-  echo "$progname: failed program was:" >&5
-  cat conftest.$ac_ext >&5
-  rm -fr conftest*
-  lt_cv_dlopen_self=no
-fi
-rm -fr conftest*
-fi
-
-fi
-
-echo "$ac_t""$lt_cv_dlopen_self" 1>&6
-
-  if test "$lt_cv_dlopen_self" = yes; then
-    LDFLAGS="$LDFLAGS $link_static_flag"
-  echo $ac_n "checking whether a statically linked program can dlopen itself""... $ac_c" 1>&6
-echo "$progname:2506: checking whether a statically linked program can dlopen itself" >&5
-if test "${lt_cv_dlopen_self_static+set}" = set; then
-  echo $ac_n "(cached) $ac_c" 1>&6
-else
-  if test "$cross_compiling" = yes; then
-    lt_cv_dlopen_self_static=cross
-  else
-    cat > conftest.c <<EOF
-#line 2514 "ltconfig"
-
-#if HAVE_DLFCN_H
-#include <dlfcn.h>
-#endif
-
-#include <stdio.h>
-
-#ifdef RTLD_GLOBAL
-# define LTDL_GLOBAL	RTLD_GLOBAL
-#else
-# ifdef DL_GLOBAL
-#  define LTDL_GLOBAL	DL_GLOBAL
-# else
-#  define LTDL_GLOBAL	0
-# endif
-#endif
-
-/* We may have to define LTDL_LAZY_OR_NOW in the command line if we
-   find out it does not work in some platform. */
-#ifndef LTDL_LAZY_OR_NOW
-# ifdef RTLD_LAZY
-#  define LTDL_LAZY_OR_NOW	RTLD_LAZY
-# else
-#  ifdef DL_LAZY
-#   define LTDL_LAZY_OR_NOW	DL_LAZY
-#  else
-#   ifdef RTLD_NOW
-#    define LTDL_LAZY_OR_NOW	RTLD_NOW
-#   else
-#    ifdef DL_NOW
-#     define LTDL_LAZY_OR_NOW	DL_NOW
-#    else
-#     define LTDL_LAZY_OR_NOW	0
-#    endif
-#   endif
-#  endif
-# endif
-#endif
-
-fnord() { int i=42;}
-main() { void *self, *ptr1, *ptr2; self=dlopen(0,LTDL_GLOBAL|LTDL_LAZY_OR_NOW);
-    if(self) { ptr1=dlsym(self,"fnord"); ptr2=dlsym(self,"_fnord");
-    if(ptr1 || ptr2) { dlclose(self); exit(0); } } exit(1); } 
-
-EOF
-if { (eval echo $progname:2560: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
-then
-  lt_cv_dlopen_self_static=yes
-else
-  echo "$progname: failed program was:" >&5
-  cat conftest.$ac_ext >&5
-  rm -fr conftest*
-  lt_cv_dlopen_self_static=no
-fi
-rm -fr conftest*
-fi
-
-fi
-
-echo "$ac_t""$lt_cv_dlopen_self_static" 1>&6
-fi
-    ;;
-  esac
-
-  case "$lt_cv_dlopen_self" in
-  yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
-  *) enable_dlopen_self=unknown ;;
-  esac
-
-  case "$lt_cv_dlopen_self_static" in
-  yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
-  *) enable_dlopen_self_static=unknown ;;
-  esac
-fi
-
-# Copy echo and quote the copy, instead of the original, because it is
-# used later.
-ltecho="$echo"
-if test "X$ltecho" = "X$CONFIG_SHELL $0 --fallback-echo"; then
-   ltecho="$CONFIG_SHELL \$0 --fallback-echo"
-fi
-LTSHELL="$SHELL"
-
-LTCONFIG_VERSION="$VERSION"
-
-# Only quote variables if we're using ltmain.sh.
-case "$ltmain" in
-*.sh)
-  # Now quote all the things that may contain metacharacters.
-  for var in ltecho old_CC old_CFLAGS old_CPPFLAGS \
-    old_LD old_LDFLAGS old_LIBS \
-    old_NM old_RANLIB old_LN_S old_DLLTOOL old_OBJDUMP old_AS \
-    AR CC LD LN_S NM LTSHELL LTCONFIG_VERSION \
-    reload_flag reload_cmds wl \
-    pic_flag link_static_flag no_builtin_flag export_dynamic_flag_spec \
-    thread_safe_flag_spec whole_archive_flag_spec libname_spec \
-    library_names_spec soname_spec \
-    RANLIB old_archive_cmds old_archive_from_new_cmds old_postinstall_cmds \
-    old_postuninstall_cmds archive_cmds archive_expsym_cmds postinstall_cmds postuninstall_cmds \
-    file_magic_cmd export_symbols_cmds deplibs_check_method allow_undefined_flag no_undefined_flag \
-    finish_cmds finish_eval global_symbol_pipe global_symbol_to_cdecl \
-    hardcode_libdir_flag_spec hardcode_libdir_separator  \
-    sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
-    compiler_c_o compiler_o_lo need_locks exclude_expsyms include_expsyms; do
-
-    case "$var" in
-    reload_cmds | old_archive_cmds | old_archive_from_new_cmds | \
-    old_postinstall_cmds | old_postuninstall_cmds | \
-    export_symbols_cmds | archive_cmds | archive_expsym_cmds | \
-    postinstall_cmds | postuninstall_cmds | \
-    finish_cmds | sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
-      # Double-quote double-evaled strings.
-      eval "$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
-      ;;
-    *)
-      eval "$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
-      ;;
-    esac
-  done
-
-  case "$ltecho" in
-  *'\$0 --fallback-echo"')
-    ltecho=`$echo "X$ltecho" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
-    ;;
-  esac
-
-  trap "$rm \"$ofile\"; exit 1" 1 2 15
-  echo "creating $ofile"
-  $rm "$ofile"
-  cat <<EOF > "$ofile"
-#! $SHELL
-
-# `$echo "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
-# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
-# NOTE: Changes made to this file will be lost: look at ltconfig or ltmain.sh.
-#
-# Copyright (C) 1996-1999 Free Software Foundation, Inc.
-# Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-# Sed that helps us avoid accidentally triggering echo(1) options like -n.
-Xsed="sed -e s/^X//"
-
-# The HP-UX ksh and POSIX shell print the target directory to stdout
-# if CDPATH is set.
-if test "\${CDPATH+set}" = set; then CDPATH=; export CDPATH; fi
-
-### BEGIN LIBTOOL CONFIG
-EOF
-  cfgfile="$ofile"
-  ;;
-
-*)
-  # Double-quote the variables that need it (for aesthetics).
-  for var in old_CC old_CFLAGS old_CPPFLAGS \
-    old_LD old_LDFLAGS old_LIBS \
-    old_NM old_RANLIB old_LN_S old_DLLTOOL old_OBJDUMP old_AS; do
-    eval "$var=\\\"\$var\\\""
-  done
-
-  # Just create a config file.
-  cfgfile="$ofile.cfg"
-  trap "$rm \"$cfgfile\"; exit 1" 1 2 15
-  echo "creating $cfgfile"
-  $rm "$cfgfile"
-  cat <<EOF > "$cfgfile"
-# `$echo "$cfgfile" | sed 's%^.*/%%'` - Libtool configuration file.
-# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
-EOF
-  ;;
-esac
-
-cat <<EOF >> "$cfgfile"
-# Libtool was configured as follows, on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
-#
-# CC=$old_CC CFLAGS=$old_CFLAGS CPPFLAGS=$old_CPPFLAGS \\
-# LD=$old_LD LDFLAGS=$old_LDFLAGS LIBS=$old_LIBS \\
-# NM=$old_NM RANLIB=$old_RANLIB LN_S=$old_LN_S \\
-# DLLTOOL=$old_DLLTOOL OBJDUMP=$old_OBJDUMP AS=$old_AS \\
-#   $0$ltconfig_args
-#
-# Compiler and other test output produced by $progname, useful for
-# debugging $progname, is in ./config.log if it exists.
-
-# The version of $progname that generated this script.
-LTCONFIG_VERSION=$LTCONFIG_VERSION
-
-# Shell to use when invoking shell scripts.
-SHELL=$LTSHELL
-
-# Whether or not to build shared libraries.
-build_libtool_libs=$enable_shared
-
-# Whether or not to build static libraries.
-build_old_libs=$enable_static
-
-# Whether or not to optimize for fast installation.
-fast_install=$enable_fast_install
-
-# The host system.
-host_alias=$host_alias
-host=$host
-
-# An echo program that does not interpret backslashes.
-echo=$ltecho
-
-# The archiver.
-AR=$AR
-
-# The default C compiler.
-CC=$CC
-
-# The linker used to build libraries.
-LD=$LD
-
-# Whether we need hard or soft links.
-LN_S=$LN_S
-
-# A BSD-compatible nm program.
-NM=$NM
-
-# Used on cygwin: DLL creation program.
-DLLTOOL="$DLLTOOL"
-
-# Used on cygwin: object dumper.
-OBJDUMP="$OBJDUMP"
-
-# Used on cygwin: assembler.
-AS="$AS"
-
-# The name of the directory that contains temporary libtool files.
-objdir=$objdir
-
-# How to create reloadable object files.
-reload_flag=$reload_flag
-reload_cmds=$reload_cmds
-
-# How to pass a linker flag through the compiler.
-wl=$wl
-
-# Object file suffix (normally "o").
-objext="$objext"
-
-# Old archive suffix (normally "a").
-libext="$libext"
-
-# Executable file suffix (normally "").
-exeext="$exeext"
-
-# Additional compiler flags for building library objects.
-pic_flag=$pic_flag
-
-# Does compiler simultaneously support -c and -o options?
-compiler_c_o=$compiler_c_o
-
-# Can we write directly to a .lo ?
-compiler_o_lo=$compiler_o_lo
-
-# Must we lock files when doing compilation ?
-need_locks=$need_locks
-
-# Do we need the lib prefix for modules?
-need_lib_prefix=$need_lib_prefix
-
-# Do we need a version for libraries?
-need_version=$need_version
-
-# Whether dlopen is supported.
-dlopen=$enable_dlopen
-
-# Whether dlopen of programs is supported.
-dlopen_self=$enable_dlopen_self
-
-# Whether dlopen of statically linked programs is supported.
-dlopen_self_static=$enable_dlopen_self_static
-
-# Compiler flag to prevent dynamic linking.
-link_static_flag=$link_static_flag
-
-# Compiler flag to turn off builtin functions.
-no_builtin_flag=$no_builtin_flag
-
-# Compiler flag to allow reflexive dlopens.
-export_dynamic_flag_spec=$export_dynamic_flag_spec
-
-# Compiler flag to generate shared objects directly from archives.
-whole_archive_flag_spec=$whole_archive_flag_spec
-
-# Compiler flag to generate thread-safe objects.
-thread_safe_flag_spec=$thread_safe_flag_spec
-
-# Library versioning type.
-version_type=$version_type
-
-# Format of library name prefix.
-libname_spec=$libname_spec
-
-# List of archive names.  First name is the real one, the rest are links.
-# The last name is the one that the linker finds with -lNAME.
-library_names_spec=$library_names_spec
-
-# The coded name of the library, if different from the real name.
-soname_spec=$soname_spec
-
-# Commands used to build and install an old-style archive.
-RANLIB=$RANLIB
-old_archive_cmds=$old_archive_cmds
-old_postinstall_cmds=$old_postinstall_cmds
-old_postuninstall_cmds=$old_postuninstall_cmds
-
-# Create an old-style archive from a shared archive.
-old_archive_from_new_cmds=$old_archive_from_new_cmds
-
-# Commands used to build and install a shared archive.
-archive_cmds=$archive_cmds
-archive_expsym_cmds=$archive_expsym_cmds
-postinstall_cmds=$postinstall_cmds
-postuninstall_cmds=$postuninstall_cmds
-
-# Method to check whether dependent libraries are shared objects.
-deplibs_check_method=$deplibs_check_method
-
-# Command to use when deplibs_check_method == file_magic.
-file_magic_cmd=$file_magic_cmd
-
-# Flag that allows shared libraries with undefined symbols to be built.
-allow_undefined_flag=$allow_undefined_flag
-
-# Flag that forces no undefined symbols.
-no_undefined_flag=$no_undefined_flag
-
-# Commands used to finish a libtool library installation in a directory.
-finish_cmds=$finish_cmds
-
-# Same as above, but a single script fragment to be evaled but not shown.
-finish_eval=$finish_eval
-
-# Take the output of nm and produce a listing of raw symbols and C names.
-global_symbol_pipe=$global_symbol_pipe
-
-# Transform the output of nm in a proper C declaration
-global_symbol_to_cdecl=$global_symbol_to_cdecl
-
-# This is the shared library runtime path variable.
-runpath_var=$runpath_var
-
-# This is the shared library path variable.
-shlibpath_var=$shlibpath_var
-
-# Is shlibpath searched before the hard-coded library search path?
-shlibpath_overrides_runpath=$shlibpath_overrides_runpath
-
-# How to hardcode a shared library path into an executable.
-hardcode_action=$hardcode_action
-
-# Flag to hardcode \$libdir into a binary during linking.
-# This must work even if \$libdir does not exist.
-hardcode_libdir_flag_spec=$hardcode_libdir_flag_spec
-
-# Whether we need a single -rpath flag with a separated argument.
-hardcode_libdir_separator=$hardcode_libdir_separator
-
-# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the
-# resulting binary.
-hardcode_direct=$hardcode_direct
-
-# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
-# resulting binary.
-hardcode_minus_L=$hardcode_minus_L
-
-# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
-# the resulting binary.
-hardcode_shlibpath_var=$hardcode_shlibpath_var
-
-# Compile-time system search path for libraries
-sys_lib_search_path_spec=$sys_lib_search_path_spec
-
-# Run-time system search path for libraries
-sys_lib_dlsearch_path_spec=$sys_lib_dlsearch_path_spec
-
-# Fix the shell variable \$srcfile for the compiler.
-fix_srcfile_path="$fix_srcfile_path"
-
-# Set to yes if exported symbols are required.
-always_export_symbols=$always_export_symbols
-
-# The commands to list exported symbols.
-export_symbols_cmds=$export_symbols_cmds
-
-# Symbols that should not be listed in the preloaded symbols.
-exclude_expsyms=$exclude_expsyms
-
-# Symbols that must always be exported.
-include_expsyms=$include_expsyms
-
-EOF
-
-case "$ltmain" in
-*.sh)
-  echo '### END LIBTOOL CONFIG' >> "$ofile"
-  echo >> "$ofile"
-  case "$host_os" in
-  aix3*)
-    cat <<\EOF >> "$ofile"
-
-# AIX sometimes has problems with the GCC collect2 program.  For some
-# reason, if we set the COLLECT_NAMES environment variable, the problems
-# vanish in a puff of smoke.
-if test "${COLLECT_NAMES+set}" != set; then
-  COLLECT_NAMES=
-  export COLLECT_NAMES
-fi
-EOF
-    ;;
-  esac
-
-  # Append the ltmain.sh script.
-  sed '$q' "$ltmain" >> "$ofile" || (rm -f "$ofile"; exit 1)
-
-  chmod +x "$ofile"
-  ;;
-
-*)
-  # Compile the libtool program.
-  echo "FIXME: would compile $ltmain"
-  ;;
-esac
-
-test -n "$cache_file" || exit 0
-
-# AC_CACHE_SAVE
-trap '' 1 2 15
-cat > confcache <<\EOF
-# This file is a shell script that caches the results of configure
-# tests run on this system so they can be shared between configure
-# scripts and configure runs.  It is not useful on other systems.
-# If it contains results you don't want to keep, you may remove or edit it.
-#
-# By default, configure uses ./config.cache as the cache file,
-# creating it if it does not exist already.  You can give configure
-# the --cache-file=FILE option to use a different cache file; that is
-# what configure does when it calls configure scripts in
-# subdirectories, so they share the cache.
-# Giving --cache-file=/dev/null disables caching, for debugging configure.
-# config.status only pays attention to the cache file if you give it the
-# --recheck option to rerun configure.
-#
-EOF
-# The following way of writing the cache mishandles newlines in values,
-# but we know of no workaround that is simple, portable, and efficient.
-# So, don't put newlines in cache variables' values.
-# Ultrix sh set writes to stderr and can't be redirected directly,
-# and sets the high bit in the cache file unless we assign to the vars.
-(set) 2>&1 |
-  case `(ac_space=' '; set | grep ac_space) 2>&1` in
-  *ac_space=\ *)
-    # `set' does not quote correctly, so add quotes (double-quote substitution
-    # turns \\\\ into \\, and sed turns \\ into \).
-    sed -n \
-      -e "s/'/'\\\\''/g" \
-      -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
-    ;;
-  *)
-    # `set' quotes correctly as required by POSIX, so do not add quotes.
-    sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
-    ;;
-  esac >> confcache
-if cmp -s $cache_file confcache; then
-  :
-else
-  if test -w $cache_file; then
-    echo "updating cache $cache_file"
-    cat confcache > $cache_file
-  else
-    echo "not updating unwritable cache $cache_file"
-  fi
-fi
-rm -f confcache
-
-exit 0
-
-# Local Variables:
-# mode:shell-script
-# sh-indentation:2
-# End:
diff --git a/shmem/unix/mm/ltmain.sh b/shmem/unix/mm/ltmain.sh
deleted file mode 100644
index f479d1ef57f..00000000000
--- a/shmem/unix/mm/ltmain.sh
+++ /dev/null
@@ -1,3975 +0,0 @@
-# ltmain.sh - Provide generalized library-building support services.
-# NOTE: Changing this file will not affect anything until you rerun ltconfig.
-#
-# Copyright (C) 1996-1999 Free Software Foundation, Inc.
-# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-# Check that we have a working $echo.
-if test "X$1" = X--no-reexec; then
-  # Discard the --no-reexec flag, and continue.
-  shift
-elif test "X$1" = X--fallback-echo; then
-  # Avoid inline document here, it may be left over
-  :
-elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
-  # Yippee, $echo works!
-  :
-else
-  # Restart under the correct shell, and then maybe $echo will work.
-  exec $SHELL "$0" --no-reexec ${1+"$@"}
-fi
-
-if test "X$1" = X--fallback-echo; then
-  # used as fallback echo
-  shift
-  cat <<EOF
-$*
-EOF
-  exit 0
-fi
-
-# The name of this program.
-progname=`$echo "$0" | sed 's%^.*/%%'`
-modename="$progname"
-
-# Constants.
-PROGRAM=ltmain.sh
-PACKAGE=libtool
-VERSION=1.3.3
-TIMESTAMP=" (1.385.2.181 1999/07/02 15:49:11)"
-
-default_mode=
-help="Try \`$progname --help' for more information."
-magic="%%%MAGIC variable%%%"
-mkdir="mkdir"
-mv="mv -f"
-rm="rm -f"
-
-# Sed substitution that helps us do robust quoting.  It backslashifies
-# metacharacters that are still active within double-quoted strings.
-Xsed='sed -e 1s/^X//'
-sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g'
-SP2NL='tr \040 \012'
-NL2SP='tr \015\012 \040\040'
-
-# NLS nuisances.
-# Only set LANG and LC_ALL to C if already set.
-# These must not be set unconditionally because not all systems understand
-# e.g. LANG=C (notably SCO).
-# We save the old values to restore during execute mode.
-if test "${LC_ALL+set}" = set; then
-  save_LC_ALL="$LC_ALL"; LC_ALL=C; export LC_ALL
-fi
-if test "${LANG+set}" = set; then
-  save_LANG="$LANG"; LANG=C; export LANG
-fi
-
-if test "$LTCONFIG_VERSION" != "$VERSION"; then
-  echo "$modename: ltconfig version \`$LTCONFIG_VERSION' does not match $PROGRAM version \`$VERSION'" 1>&2
-  echo "Fatal configuration error.  See the $PACKAGE docs for more information." 1>&2
-  exit 1
-fi
-
-if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
-  echo "$modename: not configured to build any kind of library" 1>&2
-  echo "Fatal configuration error.  See the $PACKAGE docs for more information." 1>&2
-  exit 1
-fi
-
-# Global variables.
-mode=$default_mode
-nonopt=
-prev=
-prevopt=
-run=
-show="$echo"
-show_help=
-execute_dlfiles=
-lo2o="s/\\.lo\$/.${objext}/"
-o2lo="s/\\.${objext}\$/.lo/"
-
-# Parse our command line options once, thoroughly.
-while test $# -gt 0
-do
-  arg="$1"
-  shift
-
-  case "$arg" in
-  -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;;
-  *) optarg= ;;
-  esac
-
-  # If the previous option needs an argument, assign it.
-  if test -n "$prev"; then
-    case "$prev" in
-    execute_dlfiles)
-      eval "$prev=\"\$$prev \$arg\""
-      ;;
-    *)
-      eval "$prev=\$arg"
-      ;;
-    esac
-
-    prev=
-    prevopt=
-    continue
-  fi
-
-  # Have we seen a non-optional argument yet?
-  case "$arg" in
-  --help)
-    show_help=yes
-    ;;
-
-  --version)
-    echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP"
-    exit 0
-    ;;
-
-  --config)
-    sed -e '1,/^### BEGIN LIBTOOL CONFIG/d' -e '/^### END LIBTOOL CONFIG/,$d' $0
-    exit 0
-    ;;
-
-  --debug)
-    echo "$progname: enabling shell trace mode"
-    set -x
-    ;;
-
-  --dry-run | -n)
-    run=:
-    ;;
-
-  --features)
-    echo "host: $host"
-    if test "$build_libtool_libs" = yes; then
-      echo "enable shared libraries"
-    else
-      echo "disable shared libraries"
-    fi
-    if test "$build_old_libs" = yes; then
-      echo "enable static libraries"
-    else
-      echo "disable static libraries"
-    fi
-    exit 0
-    ;;
-
-  --finish) mode="finish" ;;
-
-  --mode) prevopt="--mode" prev=mode ;;
-  --mode=*) mode="$optarg" ;;
-
-  --quiet | --silent)
-    show=:
-    ;;
-
-  -dlopen)
-    prevopt="-dlopen"
-    prev=execute_dlfiles
-    ;;
-
-  -*)
-    $echo "$modename: unrecognized option \`$arg'" 1>&2
-    $echo "$help" 1>&2
-    exit 1
-    ;;
-
-  *)
-    nonopt="$arg"
-    break
-    ;;
-  esac
-done
-
-if test -n "$prevopt"; then
-  $echo "$modename: option \`$prevopt' requires an argument" 1>&2
-  $echo "$help" 1>&2
-  exit 1
-fi
-
-if test -z "$show_help"; then
-
-  # Infer the operation mode.
-  if test -z "$mode"; then
-    case "$nonopt" in
-    *cc | *++ | gcc* | *-gcc*)
-      mode=link
-      for arg
-      do
-	case "$arg" in
-	-c)
-	   mode=compile
-	   break
-	   ;;
-	esac
-      done
-      ;;
-    *db | *dbx | *strace | *truss)
-      mode=execute
-      ;;
-    *install*|cp|mv)
-      mode=install
-      ;;
-    *rm)
-      mode=uninstall
-      ;;
-    *)
-      # If we have no mode, but dlfiles were specified, then do execute mode.
-      test -n "$execute_dlfiles" && mode=execute
-
-      # Just use the default operation mode.
-      if test -z "$mode"; then
-	if test -n "$nonopt"; then
-	  $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2
-	else
-	  $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2
-	fi
-      fi
-      ;;
-    esac
-  fi
-
-  # Only execute mode is allowed to have -dlopen flags.
-  if test -n "$execute_dlfiles" && test "$mode" != execute; then
-    $echo "$modename: unrecognized option \`-dlopen'" 1>&2
-    $echo "$help" 1>&2
-    exit 1
-  fi
-
-  # Change the help message to a mode-specific one.
-  generic_help="$help"
-  help="Try \`$modename --help --mode=$mode' for more information."
-
-  # These modes are in order of execution frequency so that they run quickly.
-  case "$mode" in
-  # libtool compile mode
-  compile)
-    modename="$modename: compile"
-    # Get the compilation command and the source file.
-    base_compile=
-    lastarg=
-    srcfile="$nonopt"
-    suppress_output=
-
-    user_target=no
-    for arg
-    do
-      # Accept any command-line options.
-      case "$arg" in
-      -o)
-	if test "$user_target" != "no"; then
-	  $echo "$modename: you cannot specify \`-o' more than once" 1>&2
-	  exit 1
-	fi
-	user_target=next
-	;;
-
-      -static)
-	build_old_libs=yes
-	continue
-	;;
-      esac
-
-      case "$user_target" in
-      next)
-	# The next one is the -o target name
-	user_target=yes
-	continue
-	;;
-      yes)
-	# We got the output file
-	user_target=set
-	libobj="$arg"
-	continue
-	;;
-      esac
-
-      # Accept the current argument as the source file.
-      lastarg="$srcfile"
-      srcfile="$arg"
-
-      # Aesthetically quote the previous argument.
-
-      # Backslashify any backslashes, double quotes, and dollar signs.
-      # These are the only characters that are still specially
-      # interpreted inside of double-quoted scrings.
-      lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"`
-
-      # Double-quote args containing other shell metacharacters.
-      # Many Bourne shells cannot handle close brackets correctly in scan
-      # sets, so we specify it separately.
-      case "$lastarg" in
-      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*)
-	lastarg="\"$lastarg\""
-	;;
-      esac
-
-      # Add the previous argument to base_compile.
-      if test -z "$base_compile"; then
-	base_compile="$lastarg"
-      else
-	base_compile="$base_compile $lastarg"
-      fi
-    done
-
-    case "$user_target" in
-    set)
-      ;;
-    no)
-      # Get the name of the library object.
-      libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'`
-      ;;
-    *)
-      $echo "$modename: you must specify a target with \`-o'" 1>&2
-      exit 1
-      ;;
-    esac
-
-    # Recognize several different file suffixes.
-    # If the user specifies -o file.o, it is replaced with file.lo
-    xform='[cCFSfmso]'
-    case "$libobj" in
-    *.ada) xform=ada ;;
-    *.adb) xform=adb ;;
-    *.ads) xform=ads ;;
-    *.asm) xform=asm ;;
-    *.c++) xform=c++ ;;
-    *.cc) xform=cc ;;
-    *.cpp) xform=cpp ;;
-    *.cxx) xform=cxx ;;
-    *.f90) xform=f90 ;;
-    *.for) xform=for ;;
-    esac
-
-    libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"`
-
-    case "$libobj" in
-    *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;;
-    *)
-      $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2
-      exit 1
-      ;;
-    esac
-
-    if test -z "$base_compile"; then
-      $echo "$modename: you must specify a compilation command" 1>&2
-      $echo "$help" 1>&2
-      exit 1
-    fi
-
-    # Delete any leftover library objects.
-    if test "$build_old_libs" = yes; then
-      removelist="$obj $libobj"
-    else
-      removelist="$libobj"
-    fi
-
-    $run $rm $removelist
-    trap "$run $rm $removelist; exit 1" 1 2 15
-
-    # Calculate the filename of the output object if compiler does
-    # not support -o with -c
-    if test "$compiler_c_o" = no; then
-      output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\..*$%%'`.${objext}
-      lockfile="$output_obj.lock"
-      removelist="$removelist $output_obj $lockfile"
-      trap "$run $rm $removelist; exit 1" 1 2 15
-    else
-      need_locks=no
-      lockfile=
-    fi
-
-    # Lock this critical section if it is needed
-    # We use this script file to make the link, it avoids creating a new file
-    if test "$need_locks" = yes; then
-      until ln "$0" "$lockfile" 2>/dev/null; do
-	$show "Waiting for $lockfile to be removed"
-	sleep 2
-      done
-    elif test "$need_locks" = warn; then
-      if test -f "$lockfile"; then
-	echo "\
-*** ERROR, $lockfile exists and contains:
-`cat $lockfile 2>/dev/null`
-
-This indicates that another process is trying to use the same
-temporary object file, and libtool could not work around it because
-your compiler does not support \`-c' and \`-o' together.  If you
-repeat this compilation, it may succeed, by chance, but you had better
-avoid parallel builds (make -j) in this platform, or get a better
-compiler."
-
-	$run $rm $removelist
-	exit 1
-      fi
-      echo $srcfile > "$lockfile"
-    fi
-
-    if test -n "$fix_srcfile_path"; then
-      eval srcfile=\"$fix_srcfile_path\"
-    fi
-
-    # Only build a PIC object if we are building libtool libraries.
-    if test "$build_libtool_libs" = yes; then
-      # Without this assignment, base_compile gets emptied.
-      fbsd_hideous_sh_bug=$base_compile
-
-      # All platforms use -DPIC, to notify preprocessed assembler code.
-      command="$base_compile $pic_flag -DPIC $srcfile"
-      if test "$build_old_libs" = yes; then
-	lo_libobj="$libobj"
-	dir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'`
-	if test "X$dir" = "X$libobj"; then
-	  dir="$objdir"
-	else
-	  dir="$dir/$objdir"
-	fi
-	libobj="$dir/"`$echo "X$libobj" | $Xsed -e 's%^.*/%%'`
-
-	if test -d "$dir"; then
-	  $show "$rm $libobj"
-	  $run $rm $libobj
-	else
-	  $show "$mkdir $dir"
-	  $run $mkdir $dir
-	  status=$?
-	  if test $status -ne 0 && test ! -d $dir; then
-	    exit $status
-	  fi
-	fi
-      fi
-      if test "$compiler_o_lo" = yes; then
-	output_obj="$libobj"
-	command="$command -o $output_obj"
-      elif test "$compiler_c_o" = yes; then
-	output_obj="$obj"
-	command="$command -o $output_obj"
-      fi
-
-      $run $rm "$output_obj"
-      $show "$command"
-      if $run eval "$command"; then :
-      else
-	test -n "$output_obj" && $run $rm $removelist
-	exit 1
-      fi
-
-      if test "$need_locks" = warn &&
-	 test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then
-	echo "\
-*** ERROR, $lockfile contains:
-`cat $lockfile 2>/dev/null`
-
-but it should contain:
-$srcfile
-
-This indicates that another process is trying to use the same
-temporary object file, and libtool could not work around it because
-your compiler does not support \`-c' and \`-o' together.  If you
-repeat this compilation, it may succeed, by chance, but you had better
-avoid parallel builds (make -j) in this platform, or get a better
-compiler."
-
-	$run $rm $removelist
-	exit 1
-      fi
-
-      # Just move the object if needed, then go on to compile the next one
-      if test x"$output_obj" != x"$libobj"; then
-	$show "$mv $output_obj $libobj"
-	if $run $mv $output_obj $libobj; then :
-	else
-	  error=$?
-	  $run $rm $removelist
-	  exit $error
-	fi
-      fi
-
-      # If we have no pic_flag, then copy the object into place and finish.
-      if test -z "$pic_flag" && test "$build_old_libs" = yes; then
-	# Rename the .lo from within objdir to obj
-	if test -f $obj; then
-	  $show $rm $obj
-	  $run $rm $obj
-	fi
-
-	$show "$mv $libobj $obj"
-	if $run $mv $libobj $obj; then :
-	else
-	  error=$?
-	  $run $rm $removelist
-	  exit $error
-	fi
-
-	# Now arrange that obj and lo_libobj become the same file
-	$show "$LN_S $obj $lo_libobj"
-	if $run $LN_S $obj $lo_libobj; then
-	  exit 0
-	else
-	  error=$?
-	  $run $rm $removelist
-	  exit $error
-	fi
-      fi
-
-      # Allow error messages only from the first compilation.
-      suppress_output=' >/dev/null 2>&1'
-    fi
-
-    # Only build a position-dependent object if we build old libraries.
-    if test "$build_old_libs" = yes; then
-      command="$base_compile $srcfile"
-      if test "$compiler_c_o" = yes; then
-	command="$command -o $obj"
-	output_obj="$obj"
-      fi
-
-      # Suppress compiler output if we already did a PIC compilation.
-      command="$command$suppress_output"
-      $run $rm "$output_obj"
-      $show "$command"
-      if $run eval "$command"; then :
-      else
-	$run $rm $removelist
-	exit 1
-      fi
-
-      if test "$need_locks" = warn &&
-	 test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then
-	echo "\
-*** ERROR, $lockfile contains:
-`cat $lockfile 2>/dev/null`
-
-but it should contain:
-$srcfile
-
-This indicates that another process is trying to use the same
-temporary object file, and libtool could not work around it because
-your compiler does not support \`-c' and \`-o' together.  If you
-repeat this compilation, it may succeed, by chance, but you had better
-avoid parallel builds (make -j) in this platform, or get a better
-compiler."
-
-	$run $rm $removelist
-	exit 1
-      fi
-
-      # Just move the object if needed
-      if test x"$output_obj" != x"$obj"; then
-	$show "$mv $output_obj $obj"
-	if $run $mv $output_obj $obj; then :
-	else
-	  error=$?
-	  $run $rm $removelist
-	  exit $error
-	fi
-      fi
-
-      # Create an invalid libtool object if no PIC, so that we do not
-      # accidentally link it into a program.
-      if test "$build_libtool_libs" != yes; then
-	$show "echo timestamp > $libobj"
-	$run eval "echo timestamp > \$libobj" || exit $?
-      else
-	# Move the .lo from within objdir
-	$show "$mv $libobj $lo_libobj"
-	if $run $mv $libobj $lo_libobj; then :
-	else
-	  error=$?
-	  $run $rm $removelist
-	  exit $error
-	fi
-      fi
-    fi
-
-    # Unlock the critical section if it was locked
-    if test "$need_locks" != no; then
-      $rm "$lockfile"
-    fi
-
-    exit 0
-    ;;
-
-  # libtool link mode
-  link)
-    modename="$modename: link"
-    C_compiler="$CC" # save it, to compile generated C sources
-    CC="$nonopt"
-    case "$host" in
-    *-*-cygwin* | *-*-mingw* | *-*-os2*)
-      # It is impossible to link a dll without this setting, and
-      # we shouldn't force the makefile maintainer to figure out
-      # which system we are compiling for in order to pass an extra
-      # flag for every libtool invokation.
-      # allow_undefined=no
-
-      # FIXME: Unfortunately, there are problems with the above when trying
-      # to make a dll which has undefined symbols, in which case not
-      # even a static library is built.  For now, we need to specify
-      # -no-undefined on the libtool link line when we can be certain
-      # that all symbols are satisfied, otherwise we get a static library.
-      allow_undefined=yes
-
-      # This is a source program that is used to create dlls on Windows
-      # Don't remove nor modify the starting and closing comments
-# /* ltdll.c starts here */
-# #define WIN32_LEAN_AND_MEAN
-# #include <windows.h>
-# #undef WIN32_LEAN_AND_MEAN
-# #include <stdio.h>
-#
-# #ifndef __CYGWIN__
-# #  ifdef __CYGWIN32__
-# #    define __CYGWIN__ __CYGWIN32__
-# #  endif
-# #endif
-#
-# #ifdef __cplusplus
-# extern "C" {
-# #endif
-# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved);
-# #ifdef __cplusplus
-# }
-# #endif
-#
-# #ifdef __CYGWIN__
-# #include <cygwin/cygwin_dll.h>
-# DECLARE_CYGWIN_DLL( DllMain );
-# #endif
-# HINSTANCE __hDllInstance_base;
-#
-# BOOL APIENTRY
-# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved)
-# {
-#   __hDllInstance_base = hInst;
-#   return TRUE;
-# }
-# /* ltdll.c ends here */
-      # This is a source program that is used to create import libraries
-      # on Windows for dlls which lack them. Don't remove nor modify the
-      # starting and closing comments
-# /* impgen.c starts here */
-# /*   Copyright (C) 1999 Free Software Foundation, Inc.
-# 
-#  This file is part of GNU libtool.
-# 
-#  This program is free software; you can redistribute it and/or modify
-#  it under the terms of the GNU General Public License as published by
-#  the Free Software Foundation; either version 2 of the License, or
-#  (at your option) any later version.
-# 
-#  This program is distributed in the hope that it will be useful,
-#  but WITHOUT ANY WARRANTY; without even the implied warranty of
-#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#  GNU General Public License for more details.
-# 
-#  You should have received a copy of the GNU General Public License
-#  along with this program; if not, write to the Free Software
-#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#  */
-# 
-#  #include <stdio.h>		/* for printf() */
-#  #include <unistd.h>		/* for open(), lseek(), read() */
-#  #include <fcntl.h>		/* for O_RDONLY, O_BINARY */
-#  #include <string.h>		/* for strdup() */
-# 
-#  static unsigned int
-#  pe_get16 (fd, offset)
-#       int fd;
-#       int offset;
-#  {
-#    unsigned char b[2];
-#    lseek (fd, offset, SEEK_SET);
-#    read (fd, b, 2);
-#    return b[0] + (b[1]<<8);
-#  }
-# 
-#  static unsigned int
-#  pe_get32 (fd, offset)
-#      int fd;
-#      int offset;
-#  {
-#    unsigned char b[4];
-#    lseek (fd, offset, SEEK_SET);
-#    read (fd, b, 4);
-#    return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24);
-#  }
-# 
-#  static unsigned int
-#  pe_as32 (ptr)
-#       void *ptr;
-#  {
-#    unsigned char *b = ptr;
-#    return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24);
-#  }
-# 
-#  int
-#  main (argc, argv)
-#      int argc;
-#      char *argv[];
-#  {
-#      int dll;
-#      unsigned long pe_header_offset, opthdr_ofs, num_entries, i;
-#      unsigned long export_rva, export_size, nsections, secptr, expptr;
-#      unsigned long name_rvas, nexp;
-#      unsigned char *expdata, *erva;
-#      char *filename, *dll_name;
-# 
-#      filename = argv[1];
-# 
-#      dll = open(filename, O_RDONLY|O_BINARY);
-#      if (!dll)
-#  	return 1;
-# 
-#      dll_name = filename;
-#    
-#      for (i=0; filename[i]; i++)
-#  	if (filename[i] == '/' || filename[i] == '\\'  || filename[i] == ':')
-#  	    dll_name = filename + i +1;
-# 
-#      pe_header_offset = pe_get32 (dll, 0x3c);
-#      opthdr_ofs = pe_header_offset + 4 + 20;
-#      num_entries = pe_get32 (dll, opthdr_ofs + 92);
-# 
-#      if (num_entries < 1) /* no exports */
-#  	return 1;
-# 
-#      export_rva = pe_get32 (dll, opthdr_ofs + 96);
-#      export_size = pe_get32 (dll, opthdr_ofs + 100);
-#      nsections = pe_get16 (dll, pe_header_offset + 4 +2);
-#      secptr = (pe_header_offset + 4 + 20 +
-#  	      pe_get16 (dll, pe_header_offset + 4 + 16));
-# 
-#      expptr = 0;
-#      for (i = 0; i < nsections; i++)
-#      {
-#  	char sname[8];
-#  	unsigned long secptr1 = secptr + 40 * i;
-#  	unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
-#  	unsigned long vsize = pe_get32 (dll, secptr1 + 16);
-#  	unsigned long fptr = pe_get32 (dll, secptr1 + 20);
-#  	lseek(dll, secptr1, SEEK_SET);
-#  	read(dll, sname, 8);
-#  	if (vaddr <= export_rva && vaddr+vsize > export_rva)
-#  	{
-#  	    expptr = fptr + (export_rva - vaddr);
-#  	    if (export_rva + export_size > vaddr + vsize)
-#  		export_size = vsize - (export_rva - vaddr);
-#  	    break;
-#  	}
-#      }
-# 
-#      expdata = (unsigned char*)malloc(export_size);
-#      lseek (dll, expptr, SEEK_SET);
-#      read (dll, expdata, export_size);
-#      erva = expdata - export_rva;
-# 
-#      nexp = pe_as32 (expdata+24);
-#      name_rvas = pe_as32 (expdata+32);
-# 
-#      printf ("EXPORTS\n");
-#      for (i = 0; i<nexp; i++)
-#      {
-#  	unsigned long name_rva = pe_as32 (erva+name_rvas+i*4);
-#  	printf ("\t%s @ %ld ;\n", erva+name_rva, 1+ i);
-#      }
-# 
-#      return 0;
-#  }
-# /* impgen.c ends here */
-      ;;
-    *)
-      allow_undefined=yes
-      ;;
-    esac
-    compile_command="$CC"
-    finalize_command="$CC"
-
-    compile_rpath=
-    finalize_rpath=
-    compile_shlibpath=
-    finalize_shlibpath=
-    convenience=
-    old_convenience=
-    deplibs=
-    linkopts=
-
-    if test -n "$shlibpath_var"; then
-      # get the directories listed in $shlibpath_var
-      eval lib_search_path=\`\$echo \"X \${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\`
-    else
-      lib_search_path=
-    fi
-    # now prepend the system-specific ones
-    eval lib_search_path=\"$sys_lib_search_path_spec\$lib_search_path\"
-    eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\"
-    
-    avoid_version=no
-    dlfiles=
-    dlprefiles=
-    dlself=no
-    export_dynamic=no
-    export_symbols=
-    export_symbols_regex=
-    generated=
-    libobjs=
-    link_against_libtool_libs=
-    ltlibs=
-    module=no
-    objs=
-    prefer_static_libs=no
-    preload=no
-    prev=
-    prevarg=
-    release=
-    rpath=
-    xrpath=
-    perm_rpath=
-    temp_rpath=
-    thread_safe=no
-    vinfo=
-
-    # We need to know -static, to get the right output filenames.
-    for arg
-    do
-      case "$arg" in
-      -all-static | -static)
-	if test "X$arg" = "X-all-static"; then
-	  if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
-	    $echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2
-	  fi
-	  if test -n "$link_static_flag"; then
-	    dlopen_self=$dlopen_self_static
-	  fi
-	else
-	  if test -z "$pic_flag" && test -n "$link_static_flag"; then
-	    dlopen_self=$dlopen_self_static
-	  fi
-	fi
-	build_libtool_libs=no
-	build_old_libs=yes
-	prefer_static_libs=yes
-	break
-	;;
-      esac
-    done
-
-    # See if our shared archives depend on static archives.
-    test -n "$old_archive_from_new_cmds" && build_old_libs=yes
-
-    # Go through the arguments, transforming them on the way.
-    while test $# -gt 0; do
-      arg="$1"
-      shift
-
-      # If the previous option needs an argument, assign it.
-      if test -n "$prev"; then
-	case "$prev" in
-	output)
-	  compile_command="$compile_command @OUTPUT@"
-	  finalize_command="$finalize_command @OUTPUT@"
-	  ;;
-	esac
-
-	case "$prev" in
-	dlfiles|dlprefiles)
-	  if test "$preload" = no; then
-	    # Add the symbol object into the linking commands.
-	    compile_command="$compile_command @SYMFILE@"
-	    finalize_command="$finalize_command @SYMFILE@"
-	    preload=yes
-	  fi
-	  case "$arg" in
-	  *.la | *.lo) ;;  # We handle these cases below.
-	  force)
-	    if test "$dlself" = no; then
-	      dlself=needless
-	      export_dynamic=yes
-	    fi
-	    prev=
-	    continue
-	    ;;
-	  self)
-	    if test "$prev" = dlprefiles; then
-	      dlself=yes
-	    elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then
-	      dlself=yes
-	    else
-	      dlself=needless
-	      export_dynamic=yes
-	    fi
-	    prev=
-	    continue
-	    ;;
-	  *)
-	    if test "$prev" = dlfiles; then
-	      dlfiles="$dlfiles $arg"
-	    else
-	      dlprefiles="$dlprefiles $arg"
-	    fi
-	    prev=
-	    ;;
-	  esac
-	  ;;
-	expsyms)
-	  export_symbols="$arg"
-	  if test ! -f "$arg"; then
-	    $echo "$modename: symbol file \`$arg' does not exist"
-	    exit 1
-	  fi
-	  prev=
-	  continue
-	  ;;
-	expsyms_regex)
-	  export_symbols_regex="$arg"
-	  prev=
-	  continue
-	  ;;
-	release)
-	  release="-$arg"
-	  prev=
-	  continue
-	  ;;
-	rpath | xrpath)
-	  # We need an absolute path.
-	  case "$arg" in
-	  [\\/]* | [A-Za-z]:[\\/]*) ;;
-	  *)
-	    $echo "$modename: only absolute run-paths are allowed" 1>&2
-	    exit 1
-	    ;;
-	  esac
-	  if test "$prev" = rpath; then
-	    case "$rpath " in
-	    *" $arg "*) ;;
-	    *) rpath="$rpath $arg" ;;
-	    esac
-	  else
-	    case "$xrpath " in
-	    *" $arg "*) ;;
-	    *) xrpath="$xrpath $arg" ;;
-	    esac
-	  fi
-	  prev=
-	  continue
-	  ;;
-	*)
-	  eval "$prev=\"\$arg\""
-	  prev=
-	  continue
-	  ;;
-	esac
-      fi
-
-      prevarg="$arg"
-
-      case "$arg" in
-      -all-static)
-	if test -n "$link_static_flag"; then
-	  compile_command="$compile_command $link_static_flag"
-	  finalize_command="$finalize_command $link_static_flag"
-	fi
-	continue
-	;;
-
-      -allow-undefined)
-	# FIXME: remove this flag sometime in the future.
-	$echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2
-	continue
-	;;
-
-      -avoid-version)
-	avoid_version=yes
-	continue
-	;;
-
-      -dlopen)
-	prev=dlfiles
-	continue
-	;;
-
-      -dlpreopen)
-	prev=dlprefiles
-	continue
-	;;
-
-      -export-dynamic)
-	export_dynamic=yes
-	continue
-	;;
-
-      -export-symbols | -export-symbols-regex)
-	if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
-	  $echo "$modename: not more than one -exported-symbols argument allowed"
-	  exit 1
-	fi
-	if test "X$arg" = "X-export-symbols"; then
-	  prev=expsyms
-	else
-	  prev=expsyms_regex
-	fi
-	continue
-	;;
-
-      -L*)
-	dir=`$echo "X$arg" | $Xsed -e 's/^-L//'`
-	# We need an absolute path.
-	case "$dir" in
-	[\\/]* | [A-Za-z]:[\\/]*) ;;
-	*)
-	  absdir=`cd "$dir" && pwd`
-	  if test -z "$absdir"; then
-	    $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2
-	    $echo "$modename: passing it literally to the linker, although it might fail" 1>&2
-	    absdir="$dir"
-	  fi
-	  dir="$absdir"
-	  ;;
-	esac
-	case " $deplibs " in
-	*" $arg "*) ;;
-	*) deplibs="$deplibs $arg";;
-	esac
-	case " $lib_search_path " in
-	*" $dir "*) ;;
-	*) lib_search_path="$lib_search_path $dir";;
-	esac
-	case "$host" in
-	*-*-cygwin* | *-*-mingw* | *-*-os2*)
-	  dllsearchdir=`cd "$dir" && pwd || echo "$dir"`
-	  case ":$dllsearchpath:" in
-	  ::) dllsearchpath="$dllsearchdir";;
-	  *":$dllsearchdir:"*) ;;
-	  *) dllsearchpath="$dllsearchpath:$dllsearchdir";;
-	  esac
-	  ;;
-	esac
-	;;
-
-      -l*)
-	if test "$arg" = "-lc"; then
-	  case "$host" in
-	  *-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos*)
-	    # These systems don't actually have c library (as such)
-	    continue
-	    ;;
-	  esac
-	elif test "$arg" = "-lm"; then
-	  case "$host" in
-	  *-*-cygwin* | *-*-beos*)
-	    # These systems don't actually have math library (as such)
-	    continue
-	    ;;
-	  esac
-	fi
-	deplibs="$deplibs $arg"
-	;;
-
-      -module)
-	module=yes
-	continue
-	;;
-
-      -no-undefined)
-	allow_undefined=no
-	continue
-	;;
-
-      -o) prev=output ;;
-
-      -release)
-	prev=release
-	continue
-	;;
-
-      -rpath)
-	prev=rpath
-	continue
-	;;
-
-      -R)
-	prev=xrpath
-	continue
-	;;
-
-      -R*)
-	dir=`$echo "X$arg" | $Xsed -e 's/^-R//'`
-	# We need an absolute path.
-	case "$dir" in
-	[\\/]* | [A-Za-z]:[\\/]*) ;;
-	*)
-	  $echo "$modename: only absolute run-paths are allowed" 1>&2
-	  exit 1
-	  ;;
-	esac
-	case "$xrpath " in
-	*" $dir "*) ;;
-	*) xrpath="$xrpath $dir" ;;
-	esac
-	continue
-	;;
-
-      -static)
-	# If we have no pic_flag, then this is the same as -all-static.
-	if test -z "$pic_flag" && test -n "$link_static_flag"; then
-	  compile_command="$compile_command $link_static_flag"
-	  finalize_command="$finalize_command $link_static_flag"
-	fi
-	continue
-	;;
-
-      -thread-safe)
-	thread_safe=yes
-	continue
-	;;
-
-      -version-info)
-	prev=vinfo
-	continue
-	;;
-
-      # Some other compiler flag.
-      -* | +*)
-	# Unknown arguments in both finalize_command and compile_command need
-	# to be aesthetically quoted because they are evaled later.
-	arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
-	case "$arg" in
-	*[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*)
-	  arg="\"$arg\""
-	  ;;
-	esac
-	;;
-
-      *.o | *.obj | *.a | *.lib)
-	# A standard object.
-	objs="$objs $arg"
-	;;
-
-      *.lo)
-	# A library object.
-	if test "$prev" = dlfiles; then
-	  dlfiles="$dlfiles $arg"
-	  if test "$build_libtool_libs" = yes && test "$dlopen" = yes; then
-	    prev=
-	    continue
-	  else
-	    # If libtool objects are unsupported, then we need to preload.
-	    prev=dlprefiles
-	  fi
-	fi
-
-	if test "$prev" = dlprefiles; then
-	  # Preload the old-style object.
-	  dlprefiles="$dlprefiles "`$echo "X$arg" | $Xsed -e "$lo2o"`
-	  prev=
-	fi
-	libobjs="$libobjs $arg"
-	;;
-
-      *.la)
-	# A libtool-controlled library.
-
-	dlname=
-	libdir=
-	library_names=
-	old_library=
-
-	# Check to see that this really is a libtool archive.
-	if (sed -e '2q' $arg | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
-	else
-	  $echo "$modename: \`$arg' is not a valid libtool archive" 1>&2
-	  exit 1
-	fi
-
-	# If the library was installed with an old release of libtool,
-	# it will not redefine variable installed.
-	installed=yes
-
-	# Read the .la file
-	# If there is no directory component, then add one.
-	case "$arg" in
-	*/* | *\\*) . $arg ;;
-	*) . ./$arg ;;
-	esac
-
-	# Get the name of the library we link against.
-	linklib=
-	for l in $old_library $library_names; do
-	  linklib="$l"
-	done
-
-	if test -z "$linklib"; then
-	  $echo "$modename: cannot find name of link library for \`$arg'" 1>&2
-	  exit 1
-	fi
-
-	# Find the relevant object directory and library name.
-	name=`$echo "X$arg" | $Xsed -e 's%^.*/%%' -e 's/\.la$//' -e 's/^lib//'`
-
-	if test "X$installed" = Xyes; then
-	  dir="$libdir"
-	else
-	  dir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
-	  if test "X$dir" = "X$arg"; then
-	    dir="$objdir"
-	  else
-	    dir="$dir/$objdir"
-	  fi
-	fi
-
-	if test -n "$dependency_libs"; then
-	  # Extract -R and -L from dependency_libs
-	  temp_deplibs=
-	  for deplib in $dependency_libs; do
-	    case "$deplib" in
-	    -R*) temp_xrpath=`$echo "X$deplib" | $Xsed -e 's/^-R//'`
-		 case " $rpath $xrpath " in
-		 *" $temp_xrpath "*) ;;
-		 *) xrpath="$xrpath $temp_xrpath";;
-		 esac;;
-	    -L*) case "$compile_command $temp_deplibs " in
-		 *" $deplib "*) ;;
-		 *) temp_deplibs="$temp_deplibs $deplib";;
-		 esac
-		 temp_dir=`$echo "X$deplib" | $Xsed -e 's/^-L//'`
-		 case " $lib_search_path " in
-		 *" $temp_dir "*) ;;
-		 *) lib_search_path="$lib_search_path $temp_dir";;
-		 esac
-		 ;;
-	    *) temp_deplibs="$temp_deplibs $deplib";;
-	    esac
-	  done
-	  dependency_libs="$temp_deplibs"
-	fi
-
-	if test -z "$libdir"; then
-	  # It is a libtool convenience library, so add in its objects.
-	  convenience="$convenience $dir/$old_library"
-	  old_convenience="$old_convenience $dir/$old_library"
-	  deplibs="$deplibs$dependency_libs"
-	  compile_command="$compile_command $dir/$old_library$dependency_libs"
-	  finalize_command="$finalize_command $dir/$old_library$dependency_libs"
-	  continue
-	fi
-
-	# This library was specified with -dlopen.
-	if test "$prev" = dlfiles; then
-	  dlfiles="$dlfiles $arg"
-	  if test -z "$dlname" || test "$dlopen" != yes || test "$build_libtool_libs" = no; then
-	    # If there is no dlname, no dlopen support or we're linking statically,
-	    # we need to preload.
-	    prev=dlprefiles
-	  else
-	    # We should not create a dependency on this library, but we
-	    # may need any libraries it requires.
-	    compile_command="$compile_command$dependency_libs"
-	    finalize_command="$finalize_command$dependency_libs"
-	    prev=
-	    continue
-	  fi
-	fi
-
-	# The library was specified with -dlpreopen.
-	if test "$prev" = dlprefiles; then
-	  # Prefer using a static library (so that no silly _DYNAMIC symbols
-	  # are required to link).
-	  if test -n "$old_library"; then
-	    dlprefiles="$dlprefiles $dir/$old_library"
-	  else
-	    dlprefiles="$dlprefiles $dir/$linklib"
-	  fi
-	  prev=
-	fi
-
-	if test -n "$library_names" &&
-	   { test "$prefer_static_libs" = no || test -z "$old_library"; }; then
-	  link_against_libtool_libs="$link_against_libtool_libs $arg"
-	  if test -n "$shlibpath_var"; then
-	    # Make sure the rpath contains only unique directories.
-	    case "$temp_rpath " in
-	    *" $dir "*) ;;
-	    *) temp_rpath="$temp_rpath $dir" ;;
-	    esac
-	  fi
-
-	  # We need an absolute path.
-	  case "$dir" in
-	  [\\/] | [A-Za-z]:[\\/]*) absdir="$dir" ;;
-	  *)
-	    absdir=`cd "$dir" && pwd`
-	    if test -z "$absdir"; then
-	      $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2
-	      $echo "$modename: passing it literally to the linker, although it might fail" 1>&2
-	      absdir="$dir"
-	    fi
-	    ;;
-	  esac
-	  
-	  # This is the magic to use -rpath.
-	  # Skip directories that are in the system default run-time
-	  # search path, unless they have been requested with -R.
-	  case " $sys_lib_dlsearch_path " in
-	  *" $absdir "*) ;;
-	  *)
-	    case "$compile_rpath " in
-	    *" $absdir "*) ;;
-	    *) compile_rpath="$compile_rpath $absdir" 
-	    esac
-	    ;;
-	  esac
-
-	  case " $sys_lib_dlsearch_path " in
-	  *" $libdir "*) ;;
-	  *)
-	    case "$finalize_rpath " in
-	    *" $libdir "*) ;;
-	    *) finalize_rpath="$finalize_rpath $libdir"
-	    esac
-	    ;;
-	  esac
-
-	  lib_linked=yes
-	  case "$hardcode_action" in
-	  immediate | unsupported)
-	    if test "$hardcode_direct" = no; then
-	      compile_command="$compile_command $dir/$linklib"
-	      deplibs="$deplibs $dir/$linklib"
-	      case "$host" in
-	      *-*-cygwin* | *-*-mingw* | *-*-os2*)
-		dllsearchdir=`cd "$dir" && pwd || echo "$dir"`
-		if test -n "$dllsearchpath"; then
-		  dllsearchpath="$dllsearchpath:$dllsearchdir"
-		else
-		  dllsearchpath="$dllsearchdir"
-		fi
-		;;
-	      esac
-	    elif test "$hardcode_minus_L" = no; then
-	      case "$host" in
-	      *-*-sunos*)
-		compile_shlibpath="$compile_shlibpath$dir:"
-		;;
-	      esac
-	      case "$compile_command " in
-	      *" -L$dir "*) ;;
-	      *) compile_command="$compile_command -L$dir";;
-	      esac
-	      compile_command="$compile_command -l$name"
-	      deplibs="$deplibs -L$dir -l$name"
-	    elif test "$hardcode_shlibpath_var" = no; then
-	      case ":$compile_shlibpath:" in
-	      *":$dir:"*) ;;
-	      *) compile_shlibpath="$compile_shlibpath$dir:";;
-	      esac
-	      compile_command="$compile_command -l$name"
-	      deplibs="$deplibs -l$name"
-	    else
-	      lib_linked=no
-	    fi
-	    ;;
-
-	  relink)
-	    if test "$hardcode_direct" = yes; then
-	      compile_command="$compile_command $absdir/$linklib"
-	      deplibs="$deplibs $absdir/$linklib"
-	    elif test "$hardcode_minus_L" = yes; then
-	      case "$compile_command " in
-	      *" -L$absdir "*) ;;
-	      *) compile_command="$compile_command -L$absdir";;
-	      esac
-	      compile_command="$compile_command -l$name"
-	      deplibs="$deplibs -L$absdir -l$name"
-	    elif test "$hardcode_shlibpath_var" = yes; then
-	      case ":$compile_shlibpath:" in
-	      *":$absdir:"*) ;;
-	      *) compile_shlibpath="$compile_shlibpath$absdir:";;
-	      esac
-	      compile_command="$compile_command -l$name"
-	      deplibs="$deplibs -l$name"
-	    else
-	      lib_linked=no
-	    fi
-	    ;;
-
-	  *)
-	    lib_linked=no
-	    ;;
-	  esac
-
-	  if test "$lib_linked" != yes; then
-	    $echo "$modename: configuration error: unsupported hardcode properties"
-	    exit 1
-	  fi
-
-	  # Finalize command for both is simple: just hardcode it.
-	  if test "$hardcode_direct" = yes; then
-	    finalize_command="$finalize_command $libdir/$linklib"
-	  elif test "$hardcode_minus_L" = yes; then
-	    case "$finalize_command " in
-	    *" -L$libdir "*) ;;
-	    *) finalize_command="$finalize_command -L$libdir";;
-	    esac
-	    finalize_command="$finalize_command -l$name"
-	  elif test "$hardcode_shlibpath_var" = yes; then
-	    case ":$finalize_shlibpath:" in
-	    *":$libdir:"*) ;;
-	    *) finalize_shlibpath="$finalize_shlibpath$libdir:";;
-	    esac
-	    finalize_command="$finalize_command -l$name"
-	  else
-	    # We cannot seem to hardcode it, guess we'll fake it.
-	    case "$finalize_command " in
-	    *" -L$dir "*) ;;
-	    *) finalize_command="$finalize_command -L$libdir";;
-	    esac
-	    finalize_command="$finalize_command -l$name"
-	  fi
-	else
-	  # Transform directly to old archives if we don't build new libraries.
-	  if test -n "$pic_flag" && test -z "$old_library"; then
-	    $echo "$modename: cannot find static library for \`$arg'" 1>&2
-	    exit 1
-	  fi
-
-	  # Here we assume that one of hardcode_direct or hardcode_minus_L
-	  # is not unsupported.  This is valid on all known static and
-	  # shared platforms.
-	  if test "$hardcode_direct" != unsupported; then
-	    test -n "$old_library" && linklib="$old_library"
-	    compile_command="$compile_command $dir/$linklib"
-	    finalize_command="$finalize_command $dir/$linklib"
-	  else
-	    case "$compile_command " in
-	    *" -L$dir "*) ;;
-	    *) compile_command="$compile_command -L$dir";;
-	    esac
-	    compile_command="$compile_command -l$name"
-	    case "$finalize_command " in
-	    *" -L$dir "*) ;;
-	    *) finalize_command="$finalize_command -L$dir";;
-	    esac
-	    finalize_command="$finalize_command -l$name"
-	  fi
-	fi
-
-	# Add in any libraries that this one depends upon.
-	compile_command="$compile_command$dependency_libs"
-	finalize_command="$finalize_command$dependency_libs"
-	continue
-	;;
-
-      # Some other compiler argument.
-      *)
-	# Unknown arguments in both finalize_command and compile_command need
-	# to be aesthetically quoted because they are evaled later.
-	arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
-	case "$arg" in
-	*[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*)
-	  arg="\"$arg\""
-	  ;;
-	esac
-	;;
-      esac
-
-      # Now actually substitute the argument into the commands.
-      if test -n "$arg"; then
-	compile_command="$compile_command $arg"
-	finalize_command="$finalize_command $arg"
-      fi
-    done
-
-    if test -n "$prev"; then
-      $echo "$modename: the \`$prevarg' option requires an argument" 1>&2
-      $echo "$help" 1>&2
-      exit 1
-    fi
-
-    if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then
-      eval arg=\"$export_dynamic_flag_spec\"
-      compile_command="$compile_command $arg"
-      finalize_command="$finalize_command $arg"
-    fi
-
-    oldlibs=
-    # calculate the name of the file, without its directory
-    outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'`
-    libobjs_save="$libobjs"
-
-    case "$output" in
-    "")
-      $echo "$modename: you must specify an output file" 1>&2
-      $echo "$help" 1>&2
-      exit 1
-      ;;
-
-    *.a | *.lib)
-      if test -n "$link_against_libtool_libs"; then
-	$echo "$modename: error: cannot link libtool libraries into archives" 1>&2
-	exit 1
-      fi
-
-      if test -n "$deplibs"; then
-	$echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2
-      fi
-
-      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
-	$echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2
-      fi
-
-      if test -n "$rpath"; then
-	$echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2
-      fi
-
-      if test -n "$xrpath"; then
-	$echo "$modename: warning: \`-R' is ignored for archives" 1>&2
-      fi
-
-      if test -n "$vinfo"; then
-	$echo "$modename: warning: \`-version-info' is ignored for archives" 1>&2
-      fi
-
-      if test -n "$release"; then
-	$echo "$modename: warning: \`-release' is ignored for archives" 1>&2
-      fi
-
-      if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
-	$echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2
-      fi
-
-      # Now set the variables for building old libraries.
-      build_libtool_libs=no
-      oldlibs="$output"
-      ;;
-
-    *.la)
-      # Make sure we only generate libraries of the form `libNAME.la'.
-      case "$outputname" in
-      lib*)
-	name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
-	eval libname=\"$libname_spec\"
-	;;
-      *)
-	if test "$module" = no; then
-	  $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2
-	  $echo "$help" 1>&2
-	  exit 1
-	fi
-	if test "$need_lib_prefix" != no; then
-	  # Add the "lib" prefix for modules if required
-	  name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
-	  eval libname=\"$libname_spec\"
-	else
-	  libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
-	fi
-	;;
-      esac
-
-      output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'`
-      if test "X$output_objdir" = "X$output"; then
-	output_objdir="$objdir"
-      else
-	output_objdir="$output_objdir/$objdir"
-      fi
-
-      if test -n "$objs"; then
-	$echo "$modename: cannot build libtool library \`$output' from non-libtool objects:$objs" 2>&1
-	exit 1
-      fi
-
-      # How the heck are we supposed to write a wrapper for a shared library?
-      if test -n "$link_against_libtool_libs"; then
-	 $echo "$modename: error: cannot link shared libraries into libtool libraries" 1>&2
-	 exit 1
-      fi
-
-      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
-	$echo "$modename: warning: \`-dlopen' is ignored for libtool libraries" 1>&2
-      fi
-
-      set dummy $rpath
-      if test $# -gt 2; then
-	$echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2
-      fi
-      install_libdir="$2"
-
-      oldlibs=
-      if test -z "$rpath"; then
-	if test "$build_libtool_libs" = yes; then
-	  # Building a libtool convenience library.
-	  libext=al
-	  oldlibs="$output_objdir/$libname.$libext $oldlibs"
-	  build_libtool_libs=convenience
-	  build_old_libs=yes
-	fi
-	dependency_libs="$deplibs"
-
-	if test -n "$vinfo"; then
-	  $echo "$modename: warning: \`-version-info' is ignored for convenience libraries" 1>&2
-	fi
-
-	if test -n "$release"; then
-	  $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2
-	fi
-      else
-
-	# Parse the version information argument.
-	IFS="${IFS= 	}"; save_ifs="$IFS"; IFS=':'
-	set dummy $vinfo 0 0 0
-	IFS="$save_ifs"
-
-	if test -n "$8"; then
-	  $echo "$modename: too many parameters to \`-version-info'" 1>&2
-	  $echo "$help" 1>&2
-	  exit 1
-	fi
-
-	current="$2"
-	revision="$3"
-	age="$4"
-
-	# Check that each of the things are valid numbers.
-	case "$current" in
-	0 | [1-9] | [1-9][0-9]*) ;;
-	*)
-	  $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2
-	  $echo "$modename: \`$vinfo' is not valid version information" 1>&2
-	  exit 1
-	  ;;
-	esac
-
-	case "$revision" in
-	0 | [1-9] | [1-9][0-9]*) ;;
-	*)
-	  $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2
-	  $echo "$modename: \`$vinfo' is not valid version information" 1>&2
-	  exit 1
-	  ;;
-	esac
-
-	case "$age" in
-	0 | [1-9] | [1-9][0-9]*) ;;
-	*)
-	  $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2
-	  $echo "$modename: \`$vinfo' is not valid version information" 1>&2
-	  exit 1
-	  ;;
-	esac
-
-	if test $age -gt $current; then
-	  $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2
-	  $echo "$modename: \`$vinfo' is not valid version information" 1>&2
-	  exit 1
-	fi
-
-	# Calculate the version variables.
-	major=
-	versuffix=
-	verstring=
-	case "$version_type" in
-	none) ;;
-
-	irix)
-	  major=`expr $current - $age + 1`
-	  versuffix="$major.$revision"
-	  verstring="sgi$major.$revision"
-
-	  # Add in all the interfaces that we are compatible with.
-	  loop=$revision
-	  while test $loop != 0; do
-	    iface=`expr $revision - $loop`
-	    loop=`expr $loop - 1`
-	    verstring="sgi$major.$iface:$verstring"
-	  done
-	  ;;
-
-	linux)
-	  major=.`expr $current - $age`
-	  versuffix="$major.$age.$revision"
-	  ;;
-
-	osf)
-	  major=`expr $current - $age`
-	  versuffix=".$current.$age.$revision"
-	  verstring="$current.$age.$revision"
-
-	  # Add in all the interfaces that we are compatible with.
-	  loop=$age
-	  while test $loop != 0; do
-	    iface=`expr $current - $loop`
-	    loop=`expr $loop - 1`
-	    verstring="$verstring:${iface}.0"
-	  done
-
-	  # Make executables depend on our current version.
-	  verstring="$verstring:${current}.0"
-	  ;;
-
-	sunos)
-	  major=".$current"
-	  versuffix=".$current.$revision"
-	  ;;
-
-	freebsd-aout)
-	  major=".$current"
-	  versuffix=".$current.$revision";
-	  ;;
-
-	freebsd-elf)
-	  major=".$current"
-	  versuffix=".$current";
-	  ;;
-
-	windows)
-	  # Like Linux, but with '-' rather than '.', since we only
-	  # want one extension on Windows 95.
-	  major=`expr $current - $age`
-	  versuffix="-$major-$age-$revision"
-	  ;;
-
-	*)
-	  $echo "$modename: unknown library version type \`$version_type'" 1>&2
-	  echo "Fatal configuration error.  See the $PACKAGE docs for more information." 1>&2
-	  exit 1
-	  ;;
-	esac
-
-	# Clear the version info if we defaulted, and they specified a release.
-	if test -z "$vinfo" && test -n "$release"; then
-	  major=
-	  verstring="0.0"
-	  if test "$need_version" = no; then
-	    versuffix=
-	  else
-	    versuffix=".0.0"
-	  fi
-	fi
-
-	# Remove version info from name if versioning should be avoided
-	if test "$avoid_version" = yes && test "$need_version" = no; then
-	  major=
-	  versuffix=
-	  verstring=""
-	fi
-	
-	# Check to see if the archive will have undefined symbols.
-	if test "$allow_undefined" = yes; then
-	  if test "$allow_undefined_flag" = unsupported; then
-	    $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2
-	    build_libtool_libs=no
-	    build_old_libs=yes
-	  fi
-	else
-	  # Don't allow undefined symbols.
-	  allow_undefined_flag="$no_undefined_flag"
-	fi
-
-	dependency_libs="$deplibs"
-	case "$host" in
-	*-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos*)
-	  # these systems don't actually have a c library (as such)!
-	  ;;
-	*)
-	  # Add libc to deplibs on all other systems.
-	  deplibs="$deplibs -lc"
-	  ;;
-	esac
-      fi
-
-      # Create the output directory, or remove our outputs if we need to.
-      if test -d $output_objdir; then
-	$show "${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.*"
-	$run ${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.*
-      else
-	$show "$mkdir $output_objdir"
-	$run $mkdir $output_objdir
-	status=$?
-	if test $status -ne 0 && test ! -d $output_objdir; then
-	  exit $status
-	fi
-      fi
-
-      # Now set the variables for building old libraries.
-      if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then
-	oldlibs="$oldlibs $output_objdir/$libname.$libext"
-
-	# Transform .lo files to .o files.
-	oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP`
-      fi
-
-      if test "$build_libtool_libs" = yes; then
-	# Transform deplibs into only deplibs that can be linked in shared.
-	name_save=$name
-	libname_save=$libname
-	release_save=$release
-	versuffix_save=$versuffix
-	major_save=$major
-	# I'm not sure if I'm treating the release correctly.  I think
-	# release should show up in the -l (ie -lgmp5) so we don't want to
-	# add it in twice.  Is that correct?
-	release=""
-	versuffix=""
-	major=""
-	newdeplibs=
-	droppeddeps=no
-	case "$deplibs_check_method" in
-	pass_all)
-	  # Don't check for shared/static.  Everything works.
-	  # This might be a little naive.  We might want to check
-	  # whether the library exists or not.  But this is on
-	  # osf3 & osf4 and I'm not really sure... Just
-	  # implementing what was already the behaviour.
-	  newdeplibs=$deplibs
-	  ;;
-	test_compile)
-	  # This code stresses the "libraries are programs" paradigm to its
-	  # limits. Maybe even breaks it.  We compile a program, linking it
-	  # against the deplibs as a proxy for the library.  Then we can check
-	  # whether they linked in statically or dynamically with ldd.
-	  $rm conftest.c
-	  cat > conftest.c <<EOF
-	  int main() { return 0; }
-EOF
-	  $rm conftest
-	  $C_compiler -o conftest conftest.c $deplibs
-	  if test $? -eq 0 ; then
-	    ldd_output=`ldd conftest`
-	    for i in $deplibs; do
-	      name="`expr $i : '-l\(.*\)'`"
-	      # If $name is empty we are operating on a -L argument.
-	      if test "$name" != "" ; then
-		libname=`eval \\$echo \"$libname_spec\"`
-		deplib_matches=`eval \\$echo \"$library_names_spec\"`
-		set dummy $deplib_matches
-		deplib_match=$2
-		if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
-		  newdeplibs="$newdeplibs $i"
-		else
-		  droppeddeps=yes
-		  echo
-		  echo "*** Warning: This library needs some functionality provided by $i."
-		  echo "*** I have the capability to make that library automatically link in when"
-		  echo "*** you link to this library.  But I can only do this if you have a"
-		  echo "*** shared version of the library, which you do not appear to have."
-		fi
-	      else
-		newdeplibs="$newdeplibs $i"
-	      fi
-	    done
-	  else
-	    # Error occured in the first compile.  Let's try to salvage the situation:
-	    # Compile a seperate program for each library.
-	    for i in $deplibs; do
-	      name="`expr $i : '-l\(.*\)'`"
-	     # If $name is empty we are operating on a -L argument.
-	      if test "$name" != "" ; then
-		$rm conftest
-		$C_compiler -o conftest conftest.c $i
-		# Did it work?
-		if test $? -eq 0 ; then
-		  ldd_output=`ldd conftest`
-		  libname=`eval \\$echo \"$libname_spec\"`
-		  deplib_matches=`eval \\$echo \"$library_names_spec\"`
-		  set dummy $deplib_matches
-		  deplib_match=$2
-		  if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
-		    newdeplibs="$newdeplibs $i"
-		  else
-		    droppeddeps=yes
-		    echo
-		    echo "*** Warning: This library needs some functionality provided by $i."
-		    echo "*** I have the capability to make that library automatically link in when"
-		    echo "*** you link to this library.  But I can only do this if you have a"
-		    echo "*** shared version of the library, which you do not appear to have."
-		  fi
-		else
-		  droppeddeps=yes
-		  echo
-		  echo "*** Warning!  Library $i is needed by this library but I was not able to"
-		  echo "***  make it link in!  You will probably need to install it or some"
-		  echo "*** library that it depends on before this library will be fully"
-		  echo "*** functional.  Installing it before continuing would be even better."
-		fi
-	      else
-		newdeplibs="$newdeplibs $i"
-	      fi
-	    done
-	  fi
-	  ;;
-	file_magic*)
-	  set dummy $deplibs_check_method
-	  file_magic_regex="`expr \"$deplibs_check_method\" : \"$2 \(.*\)\"`"
-	  for a_deplib in $deplibs; do
-	    name="`expr $a_deplib : '-l\(.*\)'`"
-	    # If $name is empty we are operating on a -L argument.
-	    if test "$name" != "" ; then
-	      libname=`eval \\$echo \"$libname_spec\"`
-	      for i in $lib_search_path; do
-		    potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
-		    for potent_lib in $potential_libs; do
-		      # Follow soft links.
-		      if ls -lLd "$potent_lib" 2>/dev/null \
-			 | grep " -> " >/dev/null; then
-			continue 
-		      fi
-		      # The statement above tries to avoid entering an
-		      # endless loop below, in case of cyclic links.
-		      # We might still enter an endless loop, since a link
-		      # loop can be closed while we follow links,
-		      # but so what?
-		      potlib="$potent_lib"
-		      while test -h "$potlib" 2>/dev/null; do
-			potliblink=`ls -ld $potlib | sed 's/.* -> //'`
-			case "$potliblink" in
-			[\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";;
-			*) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";;
-			esac
-		      done
-		      if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \
-			 | sed 10q \
-			 | egrep "$file_magic_regex" > /dev/null; then
-			newdeplibs="$newdeplibs $a_deplib"
-			a_deplib=""
-			break 2
-		      fi
-		    done
-	      done
-	      if test -n "$a_deplib" ; then
-		droppeddeps=yes
-		echo
-		echo "*** Warning: This library needs some functionality provided by $a_deplib."
-		echo "*** I have the capability to make that library automatically link in when"
-		echo "*** you link to this library.  But I can only do this if you have a"
-		echo "*** shared version of the library, which you do not appear to have."
-	      fi
-	    else
-	      # Add a -L argument.
-	      newdeplibs="$newdeplibs $a_deplib"
-	    fi
-	  done # Gone through all deplibs.
-	  ;;
-	none | unknown | *)
-	  newdeplibs=""
-	  if $echo "X $deplibs" | $Xsed -e 's/ -lc$//' \
-	       -e 's/ -[LR][^ ]*//g' -e 's/[ 	]//g' |
-	     grep . >/dev/null; then
-	    echo
-	    if test "X$deplibs_check_method" = "Xnone"; then
-	      echo "*** Warning: inter-library dependencies are not supported in this platform."
-	    else
-	      echo "*** Warning: inter-library dependencies are not known to be supported."
-	    fi
-	    echo "*** All declared inter-library dependencies are being dropped."
-	    droppeddeps=yes
-	  fi
-	  ;;
-	esac
-	versuffix=$versuffix_save
-	major=$major_save
-	release=$release_save
-	libname=$libname_save
-	name=$name_save
-
-	if test "$droppeddeps" = yes; then
-	  if test "$module" = yes; then
-	    echo
-	    echo "*** Warning: libtool could not satisfy all declared inter-library"
-	    echo "*** dependencies of module $libname.  Therefore, libtool will create"
-	    echo "*** a static module, that should work as long as the dlopening"
-	    echo "*** application is linked with the -dlopen flag."
-	    if test -z "$global_symbol_pipe"; then
-	      echo
-	      echo "*** However, this would only work if libtool was able to extract symbol"
-	      echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
-	      echo "*** not find such a program.  So, this module is probably useless."
-	      echo "*** \`nm' from GNU binutils and a full rebuild may help."
-	    fi
-	    if test "$build_old_libs" = no; then
-	      oldlibs="$output_objdir/$libname.$libext"
-	      build_libtool_libs=module
-	      build_old_libs=yes
-	    else
-	      build_libtool_libs=no
-	    fi
-	  else
-	    echo "*** The inter-library dependencies that have been dropped here will be"
-	    echo "*** automatically added whenever a program is linked with this library"
-	    echo "*** or is declared to -dlopen it."
-	  fi
-	fi
-	# Done checking deplibs!
-	deplibs=$newdeplibs
-      fi
-
-      # All the library-specific variables (install_libdir is set above).
-      library_names=
-      old_library=
-      dlname=
-      
-      # Test again, we may have decided not to build it any more
-      if test "$build_libtool_libs" = yes; then
-	# Get the real and link names of the library.
-	eval library_names=\"$library_names_spec\"
-	set dummy $library_names
-	realname="$2"
-	shift; shift
-
-	if test -n "$soname_spec"; then
-	  eval soname=\"$soname_spec\"
-	else
-	  soname="$realname"
-	fi
-
-	lib="$output_objdir/$realname"
-	for link
-	do
-	  linknames="$linknames $link"
-	done
-
-	# Ensure that we have .o objects for linkers which dislike .lo
-	# (e.g. aix) incase we are running --disable-static
-	for obj in $libobjs; do
-	  oldobj=`$echo "X$obj" | $Xsed -e "$lo2o"`
-	  if test ! -f $oldobj; then
-	    $show "${LN_S} $obj $oldobj"
-	    $run ${LN_S} $obj $oldobj || exit $?
-	  fi
-	done
-
-	# Use standard objects if they are pic
-	test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
-
-	# Prepare the list of exported symbols
-	if test -z "$export_symbols"; then
-	  if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then
-	    $show "generating symbol list for \`$libname.la'"
-	    export_symbols="$output_objdir/$libname.exp"
-	    $run $rm $export_symbols
-	    eval cmds=\"$export_symbols_cmds\"
-	    IFS="${IFS= 	}"; save_ifs="$IFS"; IFS='~'
-	    for cmd in $cmds; do
-	      IFS="$save_ifs"
-	      $show "$cmd"
-	      $run eval "$cmd" || exit $?
-	    done
-	    IFS="$save_ifs"
-	    if test -n "$export_symbols_regex"; then
-	      $show "egrep -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\""
-	      $run eval 'egrep -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
-	      $show "$mv \"${export_symbols}T\" \"$export_symbols\""
-	      $run eval '$mv "${export_symbols}T" "$export_symbols"'
-	    fi
-	  fi
-	fi
-
-	if test -n "$export_symbols" && test -n "$include_expsyms"; then
-	  $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"'
-	fi
-
-	if test -n "$convenience"; then
-	  if test -n "$whole_archive_flag_spec"; then
-	    eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
-	  else
-	    gentop="$output_objdir/${outputname}x"
-	    $show "${rm}r $gentop"
-	    $run ${rm}r "$gentop"
-	    $show "mkdir $gentop"
-	    $run mkdir "$gentop"
-	    status=$?
-	    if test $status -ne 0 && test ! -d "$gentop"; then
-	      exit $status
-	    fi
-	    generated="$generated $gentop"
-
-	    for xlib in $convenience; do
-	      # Extract the objects.
-	      case "$xlib" in
-	      [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
-	      *) xabs=`pwd`"/$xlib" ;;
-	      esac
-	      xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
-	      xdir="$gentop/$xlib"
-
-	      $show "${rm}r $xdir"
-	      $run ${rm}r "$xdir"
-	      $show "mkdir $xdir"
-	      $run mkdir "$xdir"
-	      status=$?
-	      if test $status -ne 0 && test ! -d "$xdir"; then
-		exit $status
-	      fi
-	      $show "(cd $xdir && $AR x $xabs)"
-	      $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
-
-	      libobjs="$libobjs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP`
-	    done
-	  fi
-	fi
-
-	if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
-	  eval flag=\"$thread_safe_flag_spec\"
-	  linkopts="$linkopts $flag"
-	fi
-
-	# Do each of the archive commands.
-	if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
-	  eval cmds=\"$archive_expsym_cmds\"
-	else
-	  eval cmds=\"$archive_cmds\"
-	fi
-	IFS="${IFS= 	}"; save_ifs="$IFS"; IFS='~'
-	for cmd in $cmds; do
-	  IFS="$save_ifs"
-	  $show "$cmd"
-	  $run eval "$cmd" || exit $?
-	done
-	IFS="$save_ifs"
-
-	# Create links to the real library.
-	for linkname in $linknames; do
-	  if test "$realname" != "$linkname"; then
-	    $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)"
-	    $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $?
-	  fi
-	done
-
-	# If -module or -export-dynamic was specified, set the dlname.
-	if test "$module" = yes || test "$export_dynamic" = yes; then
-	  # On all known operating systems, these are identical.
-	  dlname="$soname"
-	fi
-      fi
-      ;;
-
-    *.lo | *.o | *.obj)
-      if test -n "$link_against_libtool_libs"; then
-	$echo "$modename: error: cannot link libtool libraries into objects" 1>&2
-	exit 1
-      fi
-
-      if test -n "$deplibs"; then
-	$echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2
-      fi
-
-      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
-	$echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2
-      fi
-
-      if test -n "$rpath"; then
-	$echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2
-      fi
-
-      if test -n "$xrpath"; then
-	$echo "$modename: warning: \`-R' is ignored for objects" 1>&2
-      fi
-
-      if test -n "$vinfo"; then
-	$echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2
-      fi
-
-      if test -n "$release"; then
-	$echo "$modename: warning: \`-release' is ignored for objects" 1>&2
-      fi
-
-      case "$output" in
-      *.lo)
-	if test -n "$objs"; then
-	  $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2
-	  exit 1
-	fi
-	libobj="$output"
-	obj=`$echo "X$output" | $Xsed -e "$lo2o"`
-	;;
-      *)
-	libobj=
-	obj="$output"
-	;;
-      esac
-
-      # Delete the old objects.
-      $run $rm $obj $libobj
-
-      # Objects from convenience libraries.  This assumes
-      # single-version convenience libraries.  Whenever we create
-      # different ones for PIC/non-PIC, this we'll have to duplicate
-      # the extraction.
-      reload_conv_objs=
-      gentop=
-      # reload_cmds runs $LD directly, so let us get rid of
-      # -Wl from whole_archive_flag_spec
-      wl= 
-
-      if test -n "$convenience"; then
-	if test -n "$whole_archive_flag_spec"; then
-	  eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\"
-	else
-	  gentop="$output_objdir/${obj}x"
-	  $show "${rm}r $gentop"
-	  $run ${rm}r "$gentop"
-	  $show "mkdir $gentop"
-	  $run mkdir "$gentop"
-	  status=$?
-	  if test $status -ne 0 && test ! -d "$gentop"; then
-	    exit $status
-	  fi
-	  generated="$generated $gentop"
-
-	  for xlib in $convenience; do
-	    # Extract the objects.
-	    case "$xlib" in
-	    [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
-	    *) xabs=`pwd`"/$xlib" ;;
-	    esac
-	    xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
-	    xdir="$gentop/$xlib"
-
-	    $show "${rm}r $xdir"
-	    $run ${rm}r "$xdir"
-	    $show "mkdir $xdir"
-	    $run mkdir "$xdir"
-	    status=$?
-	    if test $status -ne 0 && test ! -d "$xdir"; then
-	      exit $status
-	    fi
-	    $show "(cd $xdir && $AR x $xabs)"
-	    $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
-
-	    reload_conv_objs="$reload_objs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP`
-	  done
-	fi
-      fi
-
-      # Create the old-style object.
-      reload_objs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs"
-
-      output="$obj"
-      eval cmds=\"$reload_cmds\"
-      IFS="${IFS= 	}"; save_ifs="$IFS"; IFS='~'
-      for cmd in $cmds; do
-	IFS="$save_ifs"
-	$show "$cmd"
-	$run eval "$cmd" || exit $?
-      done
-      IFS="$save_ifs"
-
-      # Exit if we aren't doing a library object file.
-      if test -z "$libobj"; then
-	if test -n "$gentop"; then
-	  $show "${rm}r $gentop"
-	  $run ${rm}r $gentop
-	fi
-
-	exit 0
-      fi
-
-      if test "$build_libtool_libs" != yes; then
-	if test -n "$gentop"; then
-	  $show "${rm}r $gentop"
-	  $run ${rm}r $gentop
-	fi
-
-	# Create an invalid libtool object if no PIC, so that we don't
-	# accidentally link it into a program.
-	$show "echo timestamp > $libobj"
-	$run eval "echo timestamp > $libobj" || exit $?
-	exit 0
-      fi
-
-      if test -n "$pic_flag"; then
-	# Only do commands if we really have different PIC objects.
-	reload_objs="$libobjs $reload_conv_objs"
-	output="$libobj"
-	eval cmds=\"$reload_cmds\"
-	IFS="${IFS= 	}"; save_ifs="$IFS"; IFS='~'
-	for cmd in $cmds; do
-	  IFS="$save_ifs"
-	  $show "$cmd"
-	  $run eval "$cmd" || exit $?
-	done
-	IFS="$save_ifs"
-      else
-	# Just create a symlink.
-	$show $rm $libobj
-	$run $rm $libobj
-	$show "$LN_S $obj $libobj"
-	$run $LN_S $obj $libobj || exit $?
-      fi
-
-      if test -n "$gentop"; then
-	$show "${rm}r $gentop"
-	$run ${rm}r $gentop
-      fi
-
-      exit 0
-      ;;
-
-    # Anything else should be a program.
-    *)
-      if test -n "$vinfo"; then
-	$echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2
-      fi
-
-      if test -n "$release"; then
-	$echo "$modename: warning: \`-release' is ignored for programs" 1>&2
-      fi
-
-      if test "$preload" = yes; then
-	if test "$dlopen" = unknown && test "$dlopen_self" = unknown &&
-	   test "$dlopen_self_static" = unknown; then
-	  $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support."
-	fi 
-      fi
-    
-      if test -n "$rpath$xrpath"; then
-	# If the user specified any rpath flags, then add them.
-	for libdir in $rpath $xrpath; do
-	  # This is the magic to use -rpath.
-	  case "$compile_rpath " in
-	  *" $libdir "*) ;;
-	  *) compile_rpath="$compile_rpath $libdir" ;;
-	  esac
-	  case "$finalize_rpath " in
-	  *" $libdir "*) ;;
-	  *) finalize_rpath="$finalize_rpath $libdir" ;;
-	  esac
-	done
-      fi
-
-      # Now hardcode the library paths
-      rpath=
-      hardcode_libdirs=
-      for libdir in $compile_rpath $finalize_rpath; do
-	if test -n "$hardcode_libdir_flag_spec"; then
-	  if test -n "$hardcode_libdir_separator"; then
-	    if test -z "$hardcode_libdirs"; then
-	      hardcode_libdirs="$libdir"
-	    else
-	      # Just accumulate the unique libdirs.
-	      case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in
-	      *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
-		;;
-	      *)
-		hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
-		;;
-	      esac
-	    fi
-	  else
-	    eval flag=\"$hardcode_libdir_flag_spec\"
-	    rpath="$rpath $flag"
-	  fi
-	elif test -n "$runpath_var"; then
-	  case "$perm_rpath " in
-	  *" $libdir "*) ;;
-	  *) perm_rpath="$perm_rpath $libdir" ;;
-	  esac
-	fi
-      done
-      # Substitute the hardcoded libdirs into the rpath.
-      if test -n "$hardcode_libdir_separator" &&
-	 test -n "$hardcode_libdirs"; then
-	libdir="$hardcode_libdirs"
-	eval rpath=\" $hardcode_libdir_flag_spec\"
-      fi
-      compile_rpath="$rpath"
-
-      rpath=
-      hardcode_libdirs=
-      for libdir in $finalize_rpath; do
-	if test -n "$hardcode_libdir_flag_spec"; then
-	  if test -n "$hardcode_libdir_separator"; then
-	    if test -z "$hardcode_libdirs"; then
-	      hardcode_libdirs="$libdir"
-	    else
-	      # Just accumulate the unique libdirs.
-	      case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in
-	      *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
-		;;
-	      *)
-		hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
-		;;
-	      esac
-	    fi
-	  else
-	    eval flag=\"$hardcode_libdir_flag_spec\"
-	    rpath="$rpath $flag"
-	  fi
-	elif test -n "$runpath_var"; then
-	  case "$finalize_perm_rpath " in
-	  *" $libdir "*) ;;
-	  *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;;
-	  esac
-	fi
-      done
-      # Substitute the hardcoded libdirs into the rpath.
-      if test -n "$hardcode_libdir_separator" &&
-	 test -n "$hardcode_libdirs"; then
-	libdir="$hardcode_libdirs"
-	eval rpath=\" $hardcode_libdir_flag_spec\"
-      fi
-      finalize_rpath="$rpath"
-
-      output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'`
-      if test "X$output_objdir" = "X$output"; then
-	output_objdir="$objdir"
-      else
-	output_objdir="$output_objdir/$objdir"
-      fi
-
-      # Create the binary in the object directory, then wrap it.
-      if test ! -d $output_objdir; then
-	$show "$mkdir $output_objdir"
-	$run $mkdir $output_objdir
-	status=$?
-	if test $status -ne 0 && test ! -d $output_objdir; then
-	  exit $status
-	fi
-      fi
-
-      if test -n "$libobjs" && test "$build_old_libs" = yes; then
-	# Transform all the library objects into standard objects.
-	compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
-	finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
-      fi
-
-      dlsyms=
-      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
-	if test -n "$NM" && test -n "$global_symbol_pipe"; then
-	  dlsyms="${outputname}S.c"
-	else
-	  $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2
-	fi
-      fi
-
-      if test -n "$dlsyms"; then
-	case "$dlsyms" in
-	"") ;;
-	*.c)
-	  # Discover the nlist of each of the dlfiles.
-	  nlist="$output_objdir/${outputname}.nm"
-
-	  $show "$rm $nlist ${nlist}S ${nlist}T"
-	  $run $rm "$nlist" "${nlist}S" "${nlist}T"
-
-	  # Parse the name list into a source file.
-	  $show "creating $output_objdir/$dlsyms"
-
-	  test -z "$run" && $echo > "$output_objdir/$dlsyms" "\
-/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */
-/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */
-
-#ifdef __cplusplus
-extern \"C\" {
-#endif
-
-/* Prevent the only kind of declaration conflicts we can make. */
-#define lt_preloaded_symbols some_other_symbol
-
-/* External symbol declarations for the compiler. */\
-"
-
-	  if test "$dlself" = yes; then
-	    $show "generating symbol list for \`$output'"
-
-	    test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist"
-
-	    # Add our own program objects to the symbol list.
-	    progfiles=`$echo "X$objs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
-	    for arg in $progfiles; do
-	      $show "extracting global C symbols from \`$arg'"
-	      $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
-	    done
-
-	    if test -n "$exclude_expsyms"; then
-	      $run eval 'egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
-	      $run eval '$mv "$nlist"T "$nlist"'
-	    fi
-	    
-	    if test -n "$export_symbols_regex"; then
-	      $run eval 'egrep -e "$export_symbols_regex" "$nlist" > "$nlist"T'
-	      $run eval '$mv "$nlist"T "$nlist"'
-	    fi
-
-	    # Prepare the list of exported symbols
-	    if test -z "$export_symbols"; then
-	      export_symbols="$output_objdir/$output.exp"
-	      $run $rm $export_symbols
-	      $run eval "sed -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
-	    else
-	      $run eval "sed -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"'
-	      $run eval 'grep -f "$output_objdir/$output.exp" < "$nlist" > "$nlist"T'
-	      $run eval 'mv "$nlist"T "$nlist"'
-	    fi
-	  fi
-
-	  for arg in $dlprefiles; do
-	    $show "extracting global C symbols from \`$arg'"
-	    name=`echo "$arg" | sed -e 's%^.*/%%'`
-	    $run eval 'echo ": $name " >> "$nlist"'
-	    $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
-	  done
-
-	  if test -z "$run"; then
-	    # Make sure we have at least an empty file.
-	    test -f "$nlist" || : > "$nlist"
-
-	    if test -n "$exclude_expsyms"; then
-	      egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
-	      $mv "$nlist"T "$nlist"
-	    fi
-
-	    # Try sorting and uniquifying the output.
-	    if grep -v "^: " < "$nlist" | sort +2 | uniq > "$nlist"S; then
-	      :
-	    else
-	      grep -v "^: " < "$nlist" > "$nlist"S
-	    fi
-
-	    if test -f "$nlist"S; then
-	      eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"'
-	    else
-	      echo '/* NONE */' >> "$output_objdir/$dlsyms"
-	    fi
-
-	    $echo >> "$output_objdir/$dlsyms" "\
-
-#undef lt_preloaded_symbols
-
-#if defined (__STDC__) && __STDC__
-# define lt_ptr_t void *
-#else
-# define lt_ptr_t char *
-# define const
-#endif
-
-/* The mapping between symbol names and symbols. */
-const struct {
-  const char *name;
-  lt_ptr_t address;
-}
-lt_preloaded_symbols[] =
-{\
-"
-
-	    sed -n -e 's/^: \([^ ]*\) $/  {\"\1\", (lt_ptr_t) 0},/p' \
-		-e 's/^. \([^ ]*\) \([^ ]*\)$/  {"\2", (lt_ptr_t) \&\2},/p' \
-		  < "$nlist" >> "$output_objdir/$dlsyms"
-
-	    $echo >> "$output_objdir/$dlsyms" "\
-  {0, (lt_ptr_t) 0}
-};
-
-/* This works around a problem in FreeBSD linker */
-#ifdef FREEBSD_WORKAROUND
-static const void *lt_preloaded_setup() {
-  return lt_preloaded_symbols;
-}
-#endif
-
-#ifdef __cplusplus
-}
-#endif\
-"
-	  fi
-
-	  pic_flag_for_symtable=
-	  case "$host" in
-	  # compiling the symbol table file with pic_flag works around
-	  # a FreeBSD bug that causes programs to crash when -lm is
-	  # linked before any other PIC object.  But we must not use
-	  # pic_flag when linking with -static.  The problem exists in
-	  # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
-	  *-*-freebsd2*|*-*-freebsd3.0*)
-	    case "$compile_command " in
-	    *" -static "*) ;;
-	    *) pic_flag_for_symtable=" $pic_flag -DPIC -DFREEBSD_WORKAROUND";;
-	    esac
-	  esac
-
-	  # Now compile the dynamic symbol file.
-	  $show "(cd $output_objdir && $C_compiler -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")"
-	  $run eval '(cd $output_objdir && $C_compiler -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $?
-
-	  # Clean up the generated files.
-	  $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T"
-	  $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T"
-
-	  # Transform the symbol file into the correct name.
-	  compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
-	  finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
-	  ;;
-	*)
-	  $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2
-	  exit 1
-	  ;;
-	esac
-      else
-	# We keep going just in case the user didn't refer to
-	# lt_preloaded_symbols.  The linker will fail if global_symbol_pipe
-	# really was required.
-
-	# Nullify the symbol file.
-	compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"`
-	finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"`
-      fi
-
-      if test -z "$link_against_libtool_libs" || test "$build_libtool_libs" != yes; then
-	# Replace the output file specification.
-	compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
-	link_command="$compile_command$compile_rpath"
-
-	# We have no uninstalled library dependencies, so finalize right now.
-	$show "$link_command"
-	$run eval "$link_command"
-	status=$?
-	
-	# Delete the generated files.
-	if test -n "$dlsyms"; then
-	  $show "$rm $output_objdir/${outputname}S.${objext}"
-	  $run $rm "$output_objdir/${outputname}S.${objext}"
-	fi
-
-	exit $status
-      fi
-
-      if test -n "$shlibpath_var"; then
-	# We should set the shlibpath_var
-	rpath=
-	for dir in $temp_rpath; do
-	  case "$dir" in
-	  [\\/]* | [A-Za-z]:[\\/]*)
-	    # Absolute path.
-	    rpath="$rpath$dir:"
-	    ;;
-	  *)
-	    # Relative path: add a thisdir entry.
-	    rpath="$rpath\$thisdir/$dir:"
-	    ;;
-	  esac
-	done
-	temp_rpath="$rpath"
-      fi
-
-      if test -n "$compile_shlibpath$finalize_shlibpath"; then
-	compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
-      fi
-      if test -n "$finalize_shlibpath"; then
-	finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
-      fi
-
-      compile_var=
-      finalize_var=
-      if test -n "$runpath_var"; then
-	if test -n "$perm_rpath"; then
-	  # We should set the runpath_var.
-	  rpath=
-	  for dir in $perm_rpath; do
-	    rpath="$rpath$dir:"
-	  done
-	  compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
-	fi
-	if test -n "$finalize_perm_rpath"; then
-	  # We should set the runpath_var.
-	  rpath=
-	  for dir in $finalize_perm_rpath; do
-	    rpath="$rpath$dir:"
-	  done
-	  finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
-	fi
-      fi
-
-      if test "$hardcode_action" = relink; then
-	# Fast installation is not supported
-	link_command="$compile_var$compile_command$compile_rpath"
-	relink_command="$finalize_var$finalize_command$finalize_rpath"
-	
-	$echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2
-	$echo "$modename: \`$output' will be relinked during installation" 1>&2
-      else
-	if test "$fast_install" != no; then
-	  link_command="$finalize_var$compile_command$finalize_rpath"
-	  if test "$fast_install" = yes; then
-	    relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'`
-	  else
-	    # fast_install is set to needless
-	    relink_command=
-	  fi
-	else
-	  link_command="$compile_var$compile_command$compile_rpath"
-	  relink_command="$finalize_var$finalize_command$finalize_rpath"
-	fi
-      fi
-
-      # Replace the output file specification.
-      link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
-      
-      # Delete the old output files.
-      $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname
-
-      $show "$link_command"
-      $run eval "$link_command" || exit $?
-
-      # Now create the wrapper script.
-      $show "creating $output"
-
-      # Quote the relink command for shipping.
-      if test -n "$relink_command"; then
-	relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
-      fi
-
-      # Quote $echo for shipping.
-      if test "X$echo" = "X$SHELL $0 --fallback-echo"; then
-	case "$0" in
-	[\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $0 --fallback-echo";;
-	*) qecho="$SHELL `pwd`/$0 --fallback-echo";;
-	esac
-	qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"`
-      else
-	qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"`
-      fi
-
-      # Only actually do things if our run command is non-null.
-      if test -z "$run"; then
-	# win32 will think the script is a binary if it has
-	# a .exe suffix, so we strip it off here.
-	case $output in
-	  *.exe) output=`echo $output|sed 's,.exe$,,'` ;;
-	esac
-	$rm $output
-	trap "$rm $output; exit 1" 1 2 15
-
-	$echo > $output "\
-#! $SHELL
-
-# $output - temporary wrapper script for $objdir/$outputname
-# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
-#
-# The $output program cannot be directly executed until all the libtool
-# libraries that it depends on are installed.
-#
-# This wrapper script should never be moved out of the build directory.
-# If it is, it will not operate correctly.
-
-# Sed substitution that helps us do robust quoting.  It backslashifies
-# metacharacters that are still active within double-quoted strings.
-Xsed='sed -e 1s/^X//'
-sed_quote_subst='$sed_quote_subst'
-
-# The HP-UX ksh and POSIX shell print the target directory to stdout
-# if CDPATH is set.
-if test \"\${CDPATH+set}\" = set; then CDPATH=; export CDPATH; fi
-
-relink_command=\"$relink_command\"
-
-# This environment variable determines our operation mode.
-if test \"\$libtool_install_magic\" = \"$magic\"; then
-  # install mode needs the following variable:
-  link_against_libtool_libs='$link_against_libtool_libs'
-else
-  # When we are sourced in execute mode, \$file and \$echo are already set.
-  if test \"\$libtool_execute_magic\" != \"$magic\"; then
-    echo=\"$qecho\"
-    file=\"\$0\"
-    # Make sure echo works.
-    if test \"X\$1\" = X--no-reexec; then
-      # Discard the --no-reexec flag, and continue.
-      shift
-    elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then
-      # Yippee, \$echo works!
-      :
-    else
-      # Restart under the correct shell, and then maybe \$echo will work.
-      exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"}
-    fi
-  fi\
-"
-	$echo >> $output "\
-
-  # Find the directory that this script lives in.
-  thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\`
-  test \"x\$thisdir\" = \"x\$file\" && thisdir=.
-
-  # Follow symbolic links until we get to the real thisdir.
-  file=\`ls -ld \"\$file\" | sed -n 's/.*-> //p'\`
-  while test -n \"\$file\"; do
-    destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\`
-
-    # If there was a directory component, then change thisdir.
-    if test \"x\$destdir\" != \"x\$file\"; then
-      case \"\$destdir\" in
-      [\\/]* | [A-Za-z]:[\\/]*) thisdir=\"\$destdir\" ;;
-      *) thisdir=\"\$thisdir/\$destdir\" ;;
-      esac
-    fi
-
-    file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\`
-    file=\`ls -ld \"\$thisdir/\$file\" | sed -n 's/.*-> //p'\`
-  done
-
-  # Try to get the absolute directory name.
-  absdir=\`cd \"\$thisdir\" && pwd\`
-  test -n \"\$absdir\" && thisdir=\"\$absdir\"
-"
-
-	if test "$fast_install" = yes; then
-	  echo >> $output "\
-  program=lt-'$outputname'
-  progdir=\"\$thisdir/$objdir\"
-  
-  if test ! -f \"\$progdir/\$program\" || \\
-     { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | sed 1q\`; \\
-       test \"X\$file\" != \"X\$progdir/\$program\"; }; then
-
-    file=\"\$\$-\$program\"
-
-    if test ! -d \"\$progdir\"; then
-      $mkdir \"\$progdir\"
-    else
-      $rm \"\$progdir/\$file\"
-    fi"
-
-	  echo >> $output "\
-
-    # relink executable if necessary
-    if test -n \"\$relink_command\"; then
-      if (cd \"\$thisdir\" && eval \$relink_command); then :
-      else
-	$rm \"\$progdir/\$file\"
-	exit 1
-      fi
-    fi
-
-    $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
-    { $rm \"\$progdir/\$program\";
-      $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; }
-    $rm \"\$progdir/\$file\"
-  fi"
-	else
-	  echo >> $output "\
-  program='$outputname$exeext'
-  progdir=\"\$thisdir/$objdir\"
-"
-	fi
-
-	echo >> $output "\
-
-  if test -f \"\$progdir/\$program\"; then"
-
-	# Export our shlibpath_var if we have one.
-	if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
-	  $echo >> $output "\
-    # Add our own library path to $shlibpath_var
-    $shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
-
-    # Some systems cannot cope with colon-terminated $shlibpath_var
-    # The second colon is a workaround for a bug in BeOS R4 sed
-    $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\`
-
-    export $shlibpath_var
-"
-	fi
-
-	# fixup the dll searchpath if we need to.
-	if test -n "$dllsearchpath"; then
-	  $echo >> $output "\
-    # Add the dll search path components to the executable PATH
-    PATH=$dllsearchpath:\$PATH
-"
-	fi
-
-	$echo >> $output "\
-    if test \"\$libtool_execute_magic\" != \"$magic\"; then
-      # Run the actual program with our arguments.
-"
-	case $host in
-	*-*-cygwin* | *-*-mingw | *-*-os2*)
-	  # win32 systems need to use the prog path for dll
-	  # lookup to work
-	  $echo >> $output "\
-      exec \$progdir\\\\\$program \${1+\"\$@\"}
-"
-	  ;;
-	*)
-	  $echo >> $output "\
-      # Export the path to the program.
-      PATH=\"\$progdir:\$PATH\"
-      export PATH
-
-      exec \$program \${1+\"\$@\"}
-"
-	  ;;
-	esac
-	$echo >> $output "\
-      \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\"
-      exit 1
-    fi
-  else
-    # The program doesn't exist.
-    \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2
-    \$echo \"This script is just a wrapper for \$program.\" 1>&2
-    echo \"See the $PACKAGE documentation for more information.\" 1>&2
-    exit 1
-  fi
-fi\
-"
-	chmod +x $output
-      fi
-      exit 0
-      ;;
-    esac
-
-    # See if we need to build an old-fashioned archive.
-    for oldlib in $oldlibs; do
-
-      if test "$build_libtool_libs" = convenience; then
-	oldobjs="$libobjs_save"
-	addlibs="$convenience"
-	build_libtool_libs=no
-      else
-	if test "$build_libtool_libs" = module; then
-	  oldobjs="$libobjs_save"
-	  build_libtool_libs=no
-	else
-	  oldobjs="$objs "`$echo "X$libobjs_save" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`
-	fi
-	addlibs="$old_convenience"
-      fi
-
-      if test -n "$addlibs"; then
-	gentop="$output_objdir/${outputname}x"
-	$show "${rm}r $gentop"
-	$run ${rm}r "$gentop"
-	$show "mkdir $gentop"
-	$run mkdir "$gentop"
-	status=$?
-	if test $status -ne 0 && test ! -d "$gentop"; then
-	  exit $status
-	fi
-	generated="$generated $gentop"
-	  
-	# Add in members from convenience archives.
-	for xlib in $addlibs; do
-	  # Extract the objects.
-	  case "$xlib" in
-	  [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
-	  *) xabs=`pwd`"/$xlib" ;;
-	  esac
-	  xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
-	  xdir="$gentop/$xlib"
-
-	  $show "${rm}r $xdir"
-	  $run ${rm}r "$xdir"
-	  $show "mkdir $xdir"
-	  $run mkdir "$xdir"
-	  status=$?
-	  if test $status -ne 0 && test ! -d "$xdir"; then
-	    exit $status
-	  fi
-	  $show "(cd $xdir && $AR x $xabs)"
-	  $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
-
-	  oldobjs="$oldobjs "`find $xdir -name \*.${objext} -print -o -name \*.lo -print | $NL2SP`
-	done
-      fi
-
-      # Do each command in the archive commands.
-      if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
-	eval cmds=\"$old_archive_from_new_cmds\"
-      else
-	# Ensure that we have .o objects in place incase we decided
-	# not to build a shared library, and have fallen back to building
-	# static libs even though --disable-static was passed!
-	for oldobj in $oldobjs; do
-	  if test ! -f $oldobj; then
-	    obj=`$echo "X$oldobj" | $Xsed -e "$o2lo"`
-	    $show "${LN_S} $obj $oldobj"
-	    $run ${LN_S} $obj $oldobj || exit $?
-	  fi
-	done
-
-	eval cmds=\"$old_archive_cmds\"
-      fi
-      IFS="${IFS= 	}"; save_ifs="$IFS"; IFS='~'
-      for cmd in $cmds; do
-	IFS="$save_ifs"
-	$show "$cmd"
-	$run eval "$cmd" || exit $?
-      done
-      IFS="$save_ifs"
-    done
-
-    if test -n "$generated"; then
-      $show "${rm}r$generated"
-      $run ${rm}r$generated
-    fi
-
-    # Now create the libtool archive.
-    case "$output" in
-    *.la)
-      old_library=
-      test "$build_old_libs" = yes && old_library="$libname.$libext"
-      $show "creating $output"
-
-      if test -n "$xrpath"; then
-	temp_xrpath=
-	for libdir in $xrpath; do
-	  temp_xrpath="$temp_xrpath -R$libdir"
-	done
-	dependency_libs="$temp_xrpath $dependency_libs"
-      fi
-
-      # Only create the output if not a dry run.
-      if test -z "$run"; then
-	for installed in no yes; do
-	  if test "$installed" = yes; then
-	    if test -z "$install_libdir"; then
-	      break
-	    fi
-	    output="$output_objdir/$outputname"i
-	  fi
-	  $rm $output
-	  $echo > $output "\
-# $outputname - a libtool library file
-# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
-#
-# Please DO NOT delete this file!
-# It is necessary for linking the library.
-
-# The name that we can dlopen(3).
-dlname='$dlname'
-
-# Names of this library.
-library_names='$library_names'
-
-# The name of the static archive.
-old_library='$old_library'
-
-# Libraries that this one depends upon.
-dependency_libs='$dependency_libs'
-
-# Version information for $libname.
-current=$current
-age=$age
-revision=$revision
-
-# Is this an already installed library?
-installed=$installed
-
-# Directory that this library needs to be installed in:
-libdir='$install_libdir'\
-"
-	done
-      fi
-
-      # Do a symbolic link so that the libtool archive can be found in
-      # LD_LIBRARY_PATH before the program is installed.
-      $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)"
-      $run eval "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" || exit $?
-      ;;
-    esac
-    exit 0
-    ;;
-
-  # libtool install mode
-  install)
-    modename="$modename: install"
-
-    # There may be an optional sh(1) argument at the beginning of
-    # install_prog (especially on Windows NT).
-    if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || test "$nonopt" = ./shtool;then
-      # Aesthetically quote it.
-      arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"`
-      case "$arg" in
-      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*)
-	arg="\"$arg\""
-	;;
-      esac
-      install_prog="$arg "
-      arg="$1"
-      shift
-    else
-      install_prog=
-      arg="$nonopt"
-    fi
-
-    # The real first argument should be the name of the installation program.
-    # Aesthetically quote it.
-    arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
-    case "$arg" in
-    *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*)
-      arg="\"$arg\""
-      ;;
-    esac
-    install_prog="$install_prog$arg"
-
-    # We need to accept at least all the BSD install flags.
-    dest=
-    files=
-    opts=
-    prev=
-    install_type=
-    isdir=no
-    stripme=
-    for arg
-    do
-      if test -n "$dest"; then
-	files="$files $dest"
-	dest="$arg"
-	continue
-      fi
-
-      case "$arg" in
-      -d) isdir=yes ;;
-      -f) prev="-f" ;;
-      -g) prev="-g" ;;
-      -m) prev="-m" ;;
-      -o) prev="-o" ;;
-      -s)
-	stripme=" -s"
-	continue
-	;;
-      -*) ;;
-
-      *)
-	# If the previous option needed an argument, then skip it.
-	if test -n "$prev"; then
-	  prev=
-	else
-	  dest="$arg"
-	  continue
-	fi
-	;;
-      esac
-
-      # Aesthetically quote the argument.
-      arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
-      case "$arg" in
-      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*)
-	arg="\"$arg\""
-	;;
-      esac
-      install_prog="$install_prog $arg"
-    done
-
-    if test -z "$install_prog"; then
-      $echo "$modename: you must specify an install program" 1>&2
-      $echo "$help" 1>&2
-      exit 1
-    fi
-
-    if test -n "$prev"; then
-      $echo "$modename: the \`$prev' option requires an argument" 1>&2
-      $echo "$help" 1>&2
-      exit 1
-    fi
-
-    if test -z "$files"; then
-      if test -z "$dest"; then
-	$echo "$modename: no file or destination specified" 1>&2
-      else
-	$echo "$modename: you must specify a destination" 1>&2
-      fi
-      $echo "$help" 1>&2
-      exit 1
-    fi
-
-    # Strip any trailing slash from the destination.
-    dest=`$echo "X$dest" | $Xsed -e 's%/$%%'`
-
-    # Check to see that the destination is a directory.
-    test -d "$dest" && isdir=yes
-    if test "$isdir" = yes; then
-      destdir="$dest"
-      destname=
-    else
-      destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'`
-      test "X$destdir" = "X$dest" && destdir=.
-      destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'`
-
-      # Not a directory, so check to see that there is only one file specified.
-      set dummy $files
-      if test $# -gt 2; then
-	$echo "$modename: \`$dest' is not a directory" 1>&2
-	$echo "$help" 1>&2
-	exit 1
-      fi
-    fi
-    case "$destdir" in
-    [\\/]* | [A-Za-z]:[\\/]*) ;;
-    *)
-      for file in $files; do
-	case "$file" in
-	*.lo) ;;
-	*)
-	  $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2
-	  $echo "$help" 1>&2
-	  exit 1
-	  ;;
-	esac
-      done
-      ;;
-    esac
-
-    # This variable tells wrapper scripts just to set variables rather
-    # than running their programs.
-    libtool_install_magic="$magic"
-
-    staticlibs=
-    future_libdirs=
-    current_libdirs=
-    for file in $files; do
-
-      # Do each installation.
-      case "$file" in
-      *.a | *.lib)
-	# Do the static libraries later.
-	staticlibs="$staticlibs $file"
-	;;
-
-      *.la)
-	# Check to see that this really is a libtool archive.
-	if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
-	else
-	  $echo "$modename: \`$file' is not a valid libtool archive" 1>&2
-	  $echo "$help" 1>&2
-	  exit 1
-	fi
-
-	library_names=
-	old_library=
-	# If there is no directory component, then add one.
-	case "$file" in
-	*/* | *\\*) . $file ;;
-	*) . ./$file ;;
-	esac
-
-	# Add the libdir to current_libdirs if it is the destination.
-	if test "X$destdir" = "X$libdir"; then
-	  case "$current_libdirs " in
-	  *" $libdir "*) ;;
-	  *) current_libdirs="$current_libdirs $libdir" ;;
-	  esac
-	else
-	  # Note the libdir as a future libdir.
-	  case "$future_libdirs " in
-	  *" $libdir "*) ;;
-	  *) future_libdirs="$future_libdirs $libdir" ;;
-	  esac
-	fi
-
-	dir="`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/"
-	test "X$dir" = "X$file/" && dir=
-	dir="$dir$objdir"
-
-	# See the names of the shared library.
-	set dummy $library_names
-	if test -n "$2"; then
-	  realname="$2"
-	  shift
-	  shift
-
-	  # Install the shared library and build the symlinks.
-	  $show "$install_prog $dir/$realname $destdir/$realname"
-	  $run eval "$install_prog $dir/$realname $destdir/$realname" || exit $?
-
-	  if test $# -gt 0; then
-	    # Delete the old symlinks, and create new ones.
-	    for linkname
-	    do
-	      if test "$linkname" != "$realname"; then
-		$show "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)"
-		$run eval "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)"
-	      fi
-	    done
-	  fi
-
-	  # Do each command in the postinstall commands.
-	  lib="$destdir/$realname"
-	  eval cmds=\"$postinstall_cmds\"
-	  IFS="${IFS= 	}"; save_ifs="$IFS"; IFS='~'
-	  for cmd in $cmds; do
-	    IFS="$save_ifs"
-	    $show "$cmd"
-	    $run eval "$cmd" || exit $?
-	  done
-	  IFS="$save_ifs"
-	fi
-
-	# Install the pseudo-library for information purposes.
-	name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
-	instname="$dir/$name"i
-	$show "$install_prog $instname $destdir/$name"
-	$run eval "$install_prog $instname $destdir/$name" || exit $?
-
-	# Maybe install the static library, too.
-	test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library"
-	;;
-
-      *.lo)
-	# Install (i.e. copy) a libtool object.
-
-	# Figure out destination file name, if it wasn't already specified.
-	if test -n "$destname"; then
-	  destfile="$destdir/$destname"
-	else
-	  destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
-	  destfile="$destdir/$destfile"
-	fi
-
-	# Deduce the name of the destination old-style object file.
-	case "$destfile" in
-	*.lo)
-	  staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"`
-	  ;;
-	*.o | *.obj)
-	  staticdest="$destfile"
-	  destfile=
-	  ;;
-	*)
-	  $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2
-	  $echo "$help" 1>&2
-	  exit 1
-	  ;;
-	esac
-
-	# Install the libtool object if requested.
-	if test -n "$destfile"; then
-	  $show "$install_prog $file $destfile"
-	  $run eval "$install_prog $file $destfile" || exit $?
-	fi
-
-	# Install the old object if enabled.
-	if test "$build_old_libs" = yes; then
-	  # Deduce the name of the old-style object file.
-	  staticobj=`$echo "X$file" | $Xsed -e "$lo2o"`
-
-	  $show "$install_prog $staticobj $staticdest"
-	  $run eval "$install_prog \$staticobj \$staticdest" || exit $?
-	fi
-	exit 0
-	;;
-
-      *)
-	# Figure out destination file name, if it wasn't already specified.
-	if test -n "$destname"; then
-	  destfile="$destdir/$destname"
-	else
-	  destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
-	  destfile="$destdir/$destfile"
-	fi
-
-	# Do a test to see if this is really a libtool program.
-	if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
-	  link_against_libtool_libs=
-	  relink_command=
-
-	  # If there is no directory component, then add one.
-	  case "$file" in
-	  */* | *\\*) . $file ;;
-	  *) . ./$file ;;
-	  esac
-
-	  # Check the variables that should have been set.
-	  if test -z "$link_against_libtool_libs"; then
-	    $echo "$modename: invalid libtool wrapper script \`$file'" 1>&2
-	    exit 1
-	  fi
-
-	  finalize=yes
-	  for lib in $link_against_libtool_libs; do
-	    # Check to see that each library is installed.
-	    libdir=
-	    if test -f "$lib"; then
-	      # If there is no directory component, then add one.
-	      case "$lib" in
-	      */* | *\\*) . $lib ;;
-	      *) . ./$lib ;;
-	      esac
-	    fi
-	    libfile="$libdir/`$echo "X$lib" | $Xsed -e 's%^.*/%%g'`"
-	    if test -n "$libdir" && test ! -f "$libfile"; then
-	      $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2
-	      finalize=no
-	    fi
-	  done
-
-	  outputname=
-	  if test "$fast_install" = no && test -n "$relink_command"; then
-	    if test "$finalize" = yes && test -z "$run"; then
-	      tmpdir="/tmp"
-	      test -n "$TMPDIR" && tmpdir="$TMPDIR"
-	      tmpdir="$tmpdir/libtool-$$"
-	      if $mkdir -p "$tmpdir" && chmod 700 "$tmpdir"; then :
-	      else
-		$echo "$modename: error: cannot create temporary directory \`$tmpdir'" 1>&2
-		continue
-	      fi
-	      outputname="$tmpdir/$file"
-	      # Replace the output file specification.
-	      relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'`
-
-	      $show "$relink_command"
-	      if $run eval "$relink_command"; then :
-	      else
-		$echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
-		${rm}r "$tmpdir"
-		continue
-	      fi
-	      file="$outputname"
-	    else
-	      $echo "$modename: warning: cannot relink \`$file'" 1>&2
-	    fi
-	  else
-	    # Install the binary that we compiled earlier.
-	    file=`$echo "X$file" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"`
-	  fi
-	fi
-
-	$show "$install_prog$stripme $file $destfile"
-	$run eval "$install_prog\$stripme \$file \$destfile" || exit $?
-	test -n "$outputname" && ${rm}r "$tmpdir"
-	;;
-      esac
-    done
-
-    for file in $staticlibs; do
-      name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
-
-      # Set up the ranlib parameters.
-      oldlib="$destdir/$name"
-
-      $show "$install_prog $file $oldlib"
-      $run eval "$install_prog \$file \$oldlib" || exit $?
-
-      # Do each command in the postinstall commands.
-      eval cmds=\"$old_postinstall_cmds\"
-      IFS="${IFS= 	}"; save_ifs="$IFS"; IFS='~'
-      for cmd in $cmds; do
-	IFS="$save_ifs"
-	$show "$cmd"
-	$run eval "$cmd" || exit $?
-      done
-      IFS="$save_ifs"
-    done
-
-    if test -n "$future_libdirs"; then
-      $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2
-    fi
-
-    if test -n "$current_libdirs"; then
-      # Maybe just do a dry run.
-      test -n "$run" && current_libdirs=" -n$current_libdirs"
-      exit 0 #$current_libdirs
-      exit 1
-    fi
-
-    exit 0
-    ;;
-
-  # libtool finish mode
-  finish)
-    modename="$modename: finish"
-    libdirs="$nonopt"
-    admincmds=
-
-    if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
-      for dir
-      do
-	libdirs="$libdirs $dir"
-      done
-
-      for libdir in $libdirs; do
-	if test -n "$finish_cmds"; then
-	  # Do each command in the finish commands.
-	  eval cmds=\"$finish_cmds\"
-	  IFS="${IFS= 	}"; save_ifs="$IFS"; IFS='~'
-	  for cmd in $cmds; do
-	    IFS="$save_ifs"
-	    $show "$cmd"
-	    $run eval "$cmd" || admincmds="$admincmds
-       $cmd"
-	  done
-	  IFS="$save_ifs"
-	fi
-	if test -n "$finish_eval"; then
-	  # Do the single finish_eval.
-	  eval cmds=\"$finish_eval\"
-	  $run eval "$cmds" || admincmds="$admincmds
-       $cmds"
-	fi
-      done
-    fi
-
-    # Exit here if they wanted silent mode.
-    test "$show" = : && exit 0
-
-    echo "----------------------------------------------------------------------"
-    echo "Libraries have been installed in:"
-    for libdir in $libdirs; do
-      echo "   $libdir"
-    done
-    echo
-    echo "If you ever happen to want to link against installed libraries"
-    echo "in a given directory, LIBDIR, you must either use libtool, and"
-    echo "specify the full pathname of the library, or use \`-LLIBDIR'"
-    echo "flag during linking and do at least one of the following:"
-    if test -n "$shlibpath_var"; then
-      echo "   - add LIBDIR to the \`$shlibpath_var' environment variable"
-      echo "     during execution"
-    fi
-    if test -n "$runpath_var"; then
-      echo "   - add LIBDIR to the \`$runpath_var' environment variable"
-      echo "     during linking"
-    fi
-    if test -n "$hardcode_libdir_flag_spec"; then
-      libdir=LIBDIR
-      eval flag=\"$hardcode_libdir_flag_spec\"
-
-      echo "   - use the \`$flag' linker flag"
-    fi
-    if test -n "$admincmds"; then
-      echo "   - have your system administrator run these commands:$admincmds"
-    fi
-    if test -f /etc/ld.so.conf; then
-      echo "   - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
-    fi
-    echo
-    echo "See any operating system documentation about shared libraries for"
-    echo "more information, such as the ld(1) and ld.so(8) manual pages."
-    echo "----------------------------------------------------------------------"
-    exit 0
-    ;;
-
-  # libtool execute mode
-  execute)
-    modename="$modename: execute"
-
-    # The first argument is the command name.
-    cmd="$nonopt"
-    if test -z "$cmd"; then
-      $echo "$modename: you must specify a COMMAND" 1>&2
-      $echo "$help"
-      exit 1
-    fi
-
-    # Handle -dlopen flags immediately.
-    for file in $execute_dlfiles; do
-      if test ! -f "$file"; then
-	$echo "$modename: \`$file' is not a file" 1>&2
-	$echo "$help" 1>&2
-	exit 1
-      fi
-
-      dir=
-      case "$file" in
-      *.la)
-	# Check to see that this really is a libtool archive.
-	if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
-	else
-	  $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
-	  $echo "$help" 1>&2
-	  exit 1
-	fi
-
-	# Read the libtool library.
-	dlname=
-	library_names=
-
-	# If there is no directory component, then add one.
-	case "$file" in
-	*/* | *\\*) . $file ;;
-	*) . ./$file ;;
-	esac
-
-	# Skip this library if it cannot be dlopened.
-	if test -z "$dlname"; then
-	  # Warn if it was a shared library.
-	  test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'"
-	  continue
-	fi
-
-	dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
-	test "X$dir" = "X$file" && dir=.
-
-	if test -f "$dir/$objdir/$dlname"; then
-	  dir="$dir/$objdir"
-	else
-	  $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2
-	  exit 1
-	fi
-	;;
-
-      *.lo)
-	# Just add the directory containing the .lo file.
-	dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
-	test "X$dir" = "X$file" && dir=.
-	;;
-
-      *)
-	$echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2
-	continue
-	;;
-      esac
-
-      # Get the absolute pathname.
-      absdir=`cd "$dir" && pwd`
-      test -n "$absdir" && dir="$absdir"
-
-      # Now add the directory to shlibpath_var.
-      if eval "test -z \"\$$shlibpath_var\""; then
-	eval "$shlibpath_var=\"\$dir\""
-      else
-	eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
-      fi
-    done
-
-    # This variable tells wrapper scripts just to set shlibpath_var
-    # rather than running their programs.
-    libtool_execute_magic="$magic"
-
-    # Check if any of the arguments is a wrapper script.
-    args=
-    for file
-    do
-      case "$file" in
-      -*) ;;
-      *)
-	# Do a test to see if this is really a libtool program.
-	if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
-	  # If there is no directory component, then add one.
-	  case "$file" in
-	  */* | *\\*) . $file ;;
-	  *) . ./$file ;;
-	  esac
-
-	  # Transform arg to wrapped name.
-	  file="$progdir/$program"
-	fi
-	;;
-      esac
-      # Quote arguments (to preserve shell metacharacters).
-      file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"`
-      args="$args \"$file\""
-    done
-
-    if test -z "$run"; then
-      # Export the shlibpath_var.
-      eval "export $shlibpath_var"
-
-      # Restore saved enviroment variables
-      if test "${save_LC_ALL+set}" = set; then
-	LC_ALL="$save_LC_ALL"; export LC_ALL
-      fi
-      if test "${save_LANG+set}" = set; then
-	LANG="$save_LANG"; export LANG
-      fi
-
-      # Now actually exec the command.
-      eval "exec \$cmd$args"
-
-      $echo "$modename: cannot exec \$cmd$args"
-      exit 1
-    else
-      # Display what would be done.
-      eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\""
-      $echo "export $shlibpath_var"
-      $echo "$cmd$args"
-      exit 0
-    fi
-    ;;
-
-  # libtool uninstall mode
-  uninstall)
-    modename="$modename: uninstall"
-    rm="$nonopt"
-    files=
-
-    for arg
-    do
-      case "$arg" in
-      -*) rm="$rm $arg" ;;
-      *) files="$files $arg" ;;
-      esac
-    done
-
-    if test -z "$rm"; then
-      $echo "$modename: you must specify an RM program" 1>&2
-      $echo "$help" 1>&2
-      exit 1
-    fi
-
-    for file in $files; do
-      dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
-      test "X$dir" = "X$file" && dir=.
-      name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
-
-      rmfiles="$file"
-
-      case "$name" in
-      *.la)
-	# Possibly a libtool archive, so verify it.
-	if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
-	  . $dir/$name
-
-	  # Delete the libtool libraries and symlinks.
-	  for n in $library_names; do
-	    rmfiles="$rmfiles $dir/$n"
-	  done
-	  test -n "$old_library" && rmfiles="$rmfiles $dir/$old_library"
-
-	  $show "$rm $rmfiles"
-	  $run $rm $rmfiles
-
-	  if test -n "$library_names"; then
-	    # Do each command in the postuninstall commands.
-	    eval cmds=\"$postuninstall_cmds\"
-	    IFS="${IFS= 	}"; save_ifs="$IFS"; IFS='~'
-	    for cmd in $cmds; do
-	      IFS="$save_ifs"
-	      $show "$cmd"
-	      $run eval "$cmd"
-	    done
-	    IFS="$save_ifs"
-	  fi
-
-	  if test -n "$old_library"; then
-	    # Do each command in the old_postuninstall commands.
-	    eval cmds=\"$old_postuninstall_cmds\"
-	    IFS="${IFS= 	}"; save_ifs="$IFS"; IFS='~'
-	    for cmd in $cmds; do
-	      IFS="$save_ifs"
-	      $show "$cmd"
-	      $run eval "$cmd"
-	    done
-	    IFS="$save_ifs"
-	  fi
-
-	  # FIXME: should reinstall the best remaining shared library.
-	fi
-	;;
-
-      *.lo)
-	if test "$build_old_libs" = yes; then
-	  oldobj=`$echo "X$name" | $Xsed -e "$lo2o"`
-	  rmfiles="$rmfiles $dir/$oldobj"
-	fi
-	$show "$rm $rmfiles"
-	$run $rm $rmfiles
-	;;
-
-      *)
-	$show "$rm $rmfiles"
-	$run $rm $rmfiles
-	;;
-      esac
-    done
-    exit 0
-    ;;
-
-  "")
-    $echo "$modename: you must specify a MODE" 1>&2
-    $echo "$generic_help" 1>&2
-    exit 1
-    ;;
-  esac
-
-  $echo "$modename: invalid operation mode \`$mode'" 1>&2
-  $echo "$generic_help" 1>&2
-  exit 1
-fi # test -z "$show_help"
-
-# We need to display help for each of the modes.
-case "$mode" in
-"") $echo \
-"Usage: $modename [OPTION]... [MODE-ARG]...
-
-Provide generalized library-building support services.
-
-    --config          show all configuration variables
-    --debug           enable verbose shell tracing
--n, --dry-run         display commands without modifying any files
-    --features        display basic configuration information and exit
-    --finish          same as \`--mode=finish'
-    --help            display this help message and exit
-    --mode=MODE       use operation mode MODE [default=inferred from MODE-ARGS]
-    --quiet           same as \`--silent'
-    --silent          don't print informational messages
-    --version         print version information
-
-MODE must be one of the following:
-
-      compile         compile a source file into a libtool object
-      execute         automatically set library path, then run a program
-      finish          complete the installation of libtool libraries
-      install         install libraries or executables
-      link            create a library or an executable
-      uninstall       remove libraries from an installed directory
-
-MODE-ARGS vary depending on the MODE.  Try \`$modename --help --mode=MODE' for
-a more detailed description of MODE."
-  exit 0
-  ;;
-
-compile)
-  $echo \
-"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
-
-Compile a source file into a libtool library object.
-
-This mode accepts the following additional options:
-
-  -o OUTPUT-FILE    set the output file name to OUTPUT-FILE
-  -static           always build a \`.o' file suitable for static linking
-
-COMPILE-COMMAND is a command to be used in creating a \`standard' object file
-from the given SOURCEFILE.
-
-The output file name is determined by removing the directory component from
-SOURCEFILE, then substituting the C source code suffix \`.c' with the
-library object suffix, \`.lo'."
-  ;;
-
-execute)
-  $echo \
-"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]...
-
-Automatically set library path, then run a program.
-
-This mode accepts the following additional options:
-
-  -dlopen FILE      add the directory containing FILE to the library path
-
-This mode sets the library path environment variable according to \`-dlopen'
-flags.
-
-If any of the ARGS are libtool executable wrappers, then they are translated
-into their corresponding uninstalled binary, and any of their required library
-directories are added to the library path.
-
-Then, COMMAND is executed, with ARGS as arguments."
-  ;;
-
-finish)
-  $echo \
-"Usage: $modename [OPTION]... --mode=finish [LIBDIR]...
-
-Complete the installation of libtool libraries.
-
-Each LIBDIR is a directory that contains libtool libraries.
-
-The commands that this mode executes may require superuser privileges.  Use
-the \`--dry-run' option if you just want to see what would be executed."
-  ;;
-
-install)
-  $echo \
-"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND...
-
-Install executables or libraries.
-
-INSTALL-COMMAND is the installation command.  The first component should be
-either the \`install' or \`cp' program.
-
-The rest of the components are interpreted as arguments to that command (only
-BSD-compatible install options are recognized)."
-  ;;
-
-link)
-  $echo \
-"Usage: $modename [OPTION]... --mode=link LINK-COMMAND...
-
-Link object files or libraries together to form another library, or to
-create an executable program.
-
-LINK-COMMAND is a command using the C compiler that you would use to create
-a program from several object files.
-
-The following components of LINK-COMMAND are treated specially:
-
-  -all-static       do not do any dynamic linking at all
-  -avoid-version    do not add a version suffix if possible
-  -dlopen FILE      \`-dlpreopen' FILE if it cannot be dlopened at runtime
-  -dlpreopen FILE   link in FILE and add its symbols to lt_preloaded_symbols
-  -export-dynamic   allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
-  -export-symbols SYMFILE
-		    try to export only the symbols listed in SYMFILE
-  -export-symbols-regex REGEX
-		    try to export only the symbols matching REGEX
-  -LLIBDIR          search LIBDIR for required installed libraries
-  -lNAME            OUTPUT-FILE requires the installed library libNAME
-  -module           build a library that can dlopened
-  -no-undefined     declare that a library does not refer to external symbols
-  -o OUTPUT-FILE    create OUTPUT-FILE from the specified objects
-  -release RELEASE  specify package release information
-  -rpath LIBDIR     the created library will eventually be installed in LIBDIR
-  -R[ ]LIBDIR       add LIBDIR to the runtime path of programs and libraries
-  -static           do not do any dynamic linking of libtool libraries
-  -version-info CURRENT[:REVISION[:AGE]]
-		    specify library version info [each variable defaults to 0]
-
-All other options (arguments beginning with \`-') are ignored.
-
-Every other argument is treated as a filename.  Files ending in \`.la' are
-treated as uninstalled libtool libraries, other files are standard or library
-object files.
-
-If the OUTPUT-FILE ends in \`.la', then a libtool library is created,
-only library objects (\`.lo' files) may be specified, and \`-rpath' is
-required, except when creating a convenience library.
-
-If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created
-using \`ar' and \`ranlib', or on Windows using \`lib'.
-
-If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file
-is created, otherwise an executable program is created."
-  ;;
-
-uninstall)
-  $echo \
-"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
-
-Remove libraries from an installation directory.
-
-RM is the name of the program to use to delete files associated with each FILE
-(typically \`/bin/rm').  RM-OPTIONS are options (such as \`-f') to be passed
-to RM.
-
-If FILE is a libtool library, all the files associated with it are deleted.
-Otherwise, only FILE itself is deleted using RM."
-  ;;
-
-*)
-  $echo "$modename: invalid operation mode \`$mode'" 1>&2
-  $echo "$help" 1>&2
-  exit 1
-  ;;
-esac
-
-echo
-$echo "Try \`$modename --help' for more information about other modes."
-
-exit 0
-
-# Local Variables:
-# mode:shell-script
-# sh-indentation:2
-# End:
diff --git a/shmem/unix/mm/mm-config.1 b/shmem/unix/mm/mm-config.1
deleted file mode 100644
index 512f0d4e830..00000000000
--- a/shmem/unix/mm/mm-config.1
+++ /dev/null
@@ -1,283 +0,0 @@
-.rn '' }`
-''' $RCSfile: mm-config.1,v $$Revision: 1.2 $$Date: 1999/09/27 07:42:06 $
-'''
-''' $Log: mm-config.1,v $
-''' Revision 1.2  1999/09/27 07:42:06  rse
-''' Update the MM version APR contains to a more recent one.
-'''
-''' Revision 1.7  1999/09/06 11:32:17  rse
-''' *** empty log message ***
-'''
-'''
-.de Sh
-.br
-.if t .Sp
-.ne 5
-.PP
-\fB\\$1\fR
-.PP
-..
-.de Sp
-.if t .sp .5v
-.if n .sp
-..
-.de Ip
-.br
-.ie \\n(.$>=3 .ne \\$3
-.el .ne 3
-.IP "\\$1" \\$2
-..
-.de Vb
-.ft CW
-.nf
-.ne \\$1
-..
-.de Ve
-.ft R
-
-.fi
-..
-'''
-'''
-'''     Set up \*(-- to give an unbreakable dash;
-'''     string Tr holds user defined translation string.
-'''     Bell System Logo is used as a dummy character.
-'''
-.tr \(*W-|\(bv\*(Tr
-.ie n \{\
-.ds -- \(*W-
-.ds PI pi
-.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
-.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
-.ds L" ""
-.ds R" ""
-'''   \*(M", \*(S", \*(N" and \*(T" are the equivalent of
-'''   \*(L" and \*(R", except that they are used on ".xx" lines,
-'''   such as .IP and .SH, which do another additional levels of
-'''   double-quote interpretation
-.ds M" """
-.ds S" """
-.ds N" """""
-.ds T" """""
-.ds L' '
-.ds R' '
-.ds M' '
-.ds S' '
-.ds N' '
-.ds T' '
-'br\}
-.el\{\
-.ds -- \(em\|
-.tr \*(Tr
-.ds L" ``
-.ds R" ''
-.ds M" ``
-.ds S" ''
-.ds N" ``
-.ds T" ''
-.ds L' `
-.ds R' '
-.ds M' `
-.ds S' '
-.ds N' `
-.ds T' '
-.ds PI \(*p
-'br\}
-.\"	If the F register is turned on, we'll generate
-.\"	index entries out stderr for the following things:
-.\"		TH	Title 
-.\"		SH	Header
-.\"		Sh	Subsection 
-.\"		Ip	Item
-.\"		X<>	Xref  (embedded
-.\"	Of course, you have to process the output yourself
-.\"	in some meaninful fashion.
-.if \nF \{
-.de IX
-.tm Index:\\$1\t\\n%\t"\\$2"
-..
-.nr % 0
-.rr F
-.\}
-.TH MM-CONFIG 1 "06-Sep-1999" "MM 1.0.11" "Shared Memory Library"
-.UC
-.if n .hy 0
-.if n .na
-.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
-.de CQ          \" put $1 in typewriter font
-.ft CW
-'if n "\c
-'if t \\&\\$1\c
-'if n \\&\\$1\c
-'if n \&"
-\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7
-'.ft R
-..
-.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2
-.	\" AM - accent mark definitions
-.bd B 3
-.	\" fudge factors for nroff and troff
-.if n \{\
-.	ds #H 0
-.	ds #V .8m
-.	ds #F .3m
-.	ds #[ \f1
-.	ds #] \fP
-.\}
-.if t \{\
-.	ds #H ((1u-(\\\\n(.fu%2u))*.13m)
-.	ds #V .6m
-.	ds #F 0
-.	ds #[ \&
-.	ds #] \&
-.\}
-.	\" simple accents for nroff and troff
-.if n \{\
-.	ds ' \&
-.	ds ` \&
-.	ds ^ \&
-.	ds , \&
-.	ds ~ ~
-.	ds ? ?
-.	ds ! !
-.	ds /
-.	ds q
-.\}
-.if t \{\
-.	ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
-.	ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
-.	ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
-.	ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
-.	ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
-.	ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10'
-.	ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m'
-.	ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
-.	ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10'
-.\}
-.	\" troff and (daisy-wheel) nroff accents
-.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
-.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
-.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#]
-.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u'
-.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u'
-.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#]
-.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
-.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
-.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
-.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
-.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
-.ds ae a\h'-(\w'a'u*4/10)'e
-.ds Ae A\h'-(\w'A'u*4/10)'E
-.ds oe o\h'-(\w'o'u*4/10)'e
-.ds Oe O\h'-(\w'O'u*4/10)'E
-.	\" corrections for vroff
-.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
-.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
-.	\" for low resolution devices (crt and lpr)
-.if \n(.H>23 .if \n(.V>19 \
-\{\
-.	ds : e
-.	ds 8 ss
-.	ds v \h'-1'\o'\(aa\(ga'
-.	ds _ \h'-1'^
-.	ds . \h'-1'.
-.	ds 3 3
-.	ds o a
-.	ds d- d\h'-1'\(ga
-.	ds D- D\h'-1'\(hy
-.	ds th \o'bp'
-.	ds Th \o'LP'
-.	ds ae ae
-.	ds Ae AE
-.	ds oe oe
-.	ds Oe OE
-.\}
-.rm #[ #] #H #V #F C
-.SH "NAME"
-\fBmm-config\fR \- MM library configuration/build utility
-.SH "VERSION"
-MM 1.0.11 (06-Sep-1999)
-.SH "SYNOPSIS"
-\fBmm-config\fR 
-[\fB--help\fR]
-[\fB--version\fR]
-[\fB--cflags\fR]
-[\fB--ldflags\fR]
-[\fB--libs\fR]
-.SH "DESCRIPTION"
-The \fBmm-config\fR program is a little helper utility for easy configuring and
-building applications based on the \fImm\fR\|(3) library.  It can be used to query the
-C compiler and linker flags which are required to correctly compile and link
-the application against the \fImm\fR\|(3) library. 
-.SH "OPTIONS"
-\fBmm-config\fR accepts the following options:
-.Ip "\fB--help\fR" 4
-Prints the short usage information.
-.Ip "\fB--version\fR" 4
-Prints the version number and date of the installed \fImm\fR\|(3) library.
-.Ip "\fB--cflags\fR" 4
-Prints the C compiler flags which are needed to compile the \fImm\fR\|(3)\-based
-application. The output is usually added to the \f(CWCFLAGS\fR variable of the
-applications \f(CWMakefile\fR.
-.Ip "\fB--ldflags\fR" 4
-Prints the linker flags (\f(CW-L\fR) which are needed to link the application with
-the \fImm\fR\|(3) library. The output is usually added to the \f(CWLDFLAGS\fR variable of
-the applications \f(CWMakefile\fR.
-.Ip "\fB--libs\fR" 4
-Prints the library flags (\f(CW-l\fR) which are needed to link the application with
-the \fImm\fR\|(3) library. The output is usually added to the \f(CWLIBS\fR variable of the
-applications \f(CWMakefile\fR.
-.SH "EXAMPLE"
-.PP
-.Vb 10
-\& CC=cc
-\& CFLAGS=-O `mm-config --cflags`
-\& LDFLAGS=`mm-config --ldflags`
-\& LIBS=-lm `mm-config --libs`
-\& 
-\& all: foo
-\& foo: foo.o
-\&     $(CC) $(LDFLAGS) -o foo foo.o $(LIBS)
-\& foo.o: foo.c
-\&     $(CC) $(CFLAGS) -c foo.c
-.Ve
-.SH "SEE ALSO"
-\fImm\fR\|(3).
-.SH "AUTHOR"
-.PP
-.Vb 3
-\& Ralf S. Engelschall
-\& rse@engelschall.com
-\& www.engelschall.com
-.Ve
-
-.rn }` ''
-.IX Title "MM-CONFIG 1"
-.IX Name "B<mm-config> - MM library configuration/build utility"
-
-.IX Header "NAME"
-
-.IX Header "VERSION"
-
-.IX Header "SYNOPSIS"
-
-.IX Header "DESCRIPTION"
-
-.IX Header "OPTIONS"
-
-.IX Item "\fB--help\fR"
-
-.IX Item "\fB--version\fR"
-
-.IX Item "\fB--cflags\fR"
-
-.IX Item "\fB--ldflags\fR"
-
-.IX Item "\fB--libs\fR"
-
-.IX Header "EXAMPLE"
-
-.IX Header "SEE ALSO"
-
-.IX Header "AUTHOR"
-
diff --git a/shmem/unix/mm/mm-config.in b/shmem/unix/mm/mm-config.in
deleted file mode 100644
index 7e4e774cfbd..00000000000
--- a/shmem/unix/mm/mm-config.in
+++ /dev/null
@@ -1,127 +0,0 @@
-#!/bin/sh
-##
-## mm-config -- MM library build configuration utility
-##
-## ====================================================================
-## Copyright (c) 1999 Ralf S. Engelschall. All rights reserved.
-##
-## Redistribution and use in source and binary forms, with or without
-## modification, are permitted provided that the following conditions
-## are met:
-##
-## 1. Redistributions of source code must retain the above copyright
-##    notice, this list of conditions and the following disclaimer. 
-##
-## 2. Redistributions in binary form must reproduce the above copyright
-##    notice, this list of conditions and the following disclaimer in
-##    the documentation and/or other materials provided with the
-##    distribution.
-##
-## 3. All advertising materials mentioning features or use of this
-##    software must display the following acknowledgment:
-##    "This product includes software developed by
-##     Ralf S. Engelschall <rse@engelschall.com>."
-##
-## 4. Redistributions of any form whatsoever must retain the following
-##    acknowledgment:
-##    "This product includes software developed by
-##     Ralf S. Engelschall <rse@engelschall.com>."
-##
-## THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
-## EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-## PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL RALF S. ENGELSCHALL OR
-## ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-## NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-## LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-## HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-## STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-## ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
-## OF THE POSSIBILITY OF SUCH DAMAGE.
-## ====================================================================
-
-DIFS=' 	
-'
-
-prefix="@prefix@"
-exec_prefix="@exec_prefix@"
-
-mm_prefix="$prefix"
-mm_libdir="@libdir@"
-mm_includedir="@includedir@"
-mm_mandir="@mandir@"
-mm_cflags="@CFLAGS@"
-mm_ldflags="@LDFLAGS@"
-mm_libs="@LIBS@"
-mm_version="@MM_VERSION_STR@"
-
-help=no
-version=no
-
-usage="mm-config [--help] [--version] [--all] [--cflags] [--ldflags] [--libs]"
-if [ $# -eq 0 ]; then
-    echo "mm-config:Error: Invalid option" 1>&2
-    echo "mm-config:Usage: $usage" 1>&2
-    exit 1
-fi
-output=""
-output_extra=""
-all=no
-prev=''
-OIFS="$IFS" IFS="$DIFS"
-for option
-do
-    if [ ".$prev" != . ]; then
-        eval "$prev=\$option"
-        prev=""
-        continue
-    fi
-    case "$option" in
-        -*=*) optarg=`echo "$option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
-           *) optarg='' ;;
-    esac
-    case "$option" in
-        --help|-h) 
-            echo "Usage: $usage"
-            echo "Report bugs to rse@engelschall.com"
-            exit 0
-            ;;
-        --version|-v)
-            echo "MM $mm_version"
-            exit 0
-            ;;
-        --all)
-            all=yes
-            ;;
-        --cflags)
-            output="$output -I$mm_includedir"
-            output_extra="$output_extra $mm_cflags"
-            ;;
-        --ldflags)
-            output="$output -L$mm_libdir"
-            output_extra="$output_extra $mm_ldflags"
-            ;;
-        --libs)
-            output="$output -lmm"
-            output_extra="$output_extra $mm_libs"
-            ;;
-        * )             
-            echo "mm-config:Error: Invalid option" 1>&2
-            echo "mm-config:Usage: $usage" 1>&2
-            exit 1;
-            ;;
-    esac
-done
-IFS="$OIFS"
-if [ ".$prev" != . ]; then
-    echo "mm-config:Error: missing argument to --`echo $prev | sed 's/_/-/g'`" 1>&2
-    exit 1
-fi
-if [ ".$output" != . ]; then
-    if [ ".$all" = .yes ]; then
-        output="$output $output_extra"
-    fi
-    echo $output
-fi
-
diff --git a/shmem/unix/mm/mm-config.pod b/shmem/unix/mm/mm-config.pod
deleted file mode 100644
index 1891a62e802..00000000000
--- a/shmem/unix/mm/mm-config.pod
+++ /dev/null
@@ -1,128 +0,0 @@
-## ====================================================================
-## Copyright (c) 1999 Ralf S. Engelschall. All rights reserved.
-##
-## Redistribution and use in source and binary forms, with or without
-## modification, are permitted provided that the following conditions
-## are met:
-##
-## 1. Redistributions of source code must retain the above copyright
-##    notice, this list of conditions and the following disclaimer. 
-##
-## 2. Redistributions in binary form must reproduce the above copyright
-##    notice, this list of conditions and the following disclaimer in
-##    the documentation and/or other materials provided with the
-##    distribution.
-##
-## 3. All advertising materials mentioning features or use of this
-##    software must display the following acknowledgment:
-##    "This product includes software developed by
-##     Ralf S. Engelschall <rse@engelschall.com>."
-##
-## 4. Redistributions of any form whatsoever must retain the following
-##    acknowledgment:
-##    "This product includes software developed by
-##     Ralf S. Engelschall <rse@engelschall.com>."
-##
-## THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
-## EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-## PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL RALF S. ENGELSCHALL OR
-## ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-## NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-## LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-## HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-## STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-## ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
-## OF THE POSSIBILITY OF SUCH DAMAGE.
-## ====================================================================
-
-##
-## mm-config.pod -- Manpage
-##
-
-=pod
-
-=head1 NAME
-
-B<mm-config> - MM library configuration/build utility
-
-=head1 VERSION
-
-MM MM_VERSION_STR
-
-=head1 SYNOPSIS
-
-B<mm-config> 
-[B<--help>]
-[B<--version>]
-[B<--cflags>]
-[B<--ldflags>]
-[B<--libs>]
-
-=head1 DESCRIPTION
-
-The B<mm-config> program is a little helper utility for easy configuring and
-building applications based on the mm(3) library.  It can be used to query the
-C compiler and linker flags which are required to correctly compile and link
-the application against the mm(3) library. 
-
-=head1 OPTIONS
-
-B<mm-config> accepts the following options:
-
-=over 4
-
-=item B<--help>
-
-Prints the short usage information.
-
-=item B<--version>
-
-Prints the version number and date of the installed mm(3) library.
-
-=item B<--cflags>
-
-Prints the C compiler flags which are needed to compile the mm(3)-based
-application. The output is usually added to the C<CFLAGS> variable of the
-applications C<Makefile>.
-
-=item B<--ldflags>
-
-Prints the linker flags (C<-L>) which are needed to link the application with
-the mm(3) library. The output is usually added to the C<LDFLAGS> variable of
-the applications C<Makefile>.
-
-=item B<--libs>
-
-Prints the library flags (C<-l>) which are needed to link the application with
-the mm(3) library. The output is usually added to the C<LIBS> variable of the
-applications C<Makefile>.
-
-=back
-
-=head1 EXAMPLE
-
- CC=cc
- CFLAGS=-O `mm-config --cflags`
- LDFLAGS=`mm-config --ldflags`
- LIBS=-lm `mm-config --libs`
- 
- all: foo
- foo: foo.o
-     $(CC) $(LDFLAGS) -o foo foo.o $(LIBS)
- foo.o: foo.c
-     $(CC) $(CFLAGS) -c foo.c
-
-=head1 SEE ALSO
-
-mm(3).
-
-=head1 AUTHOR
-
- Ralf S. Engelschall
- rse@engelschall.com
- www.engelschall.com
-
-=cut
-
diff --git a/shmem/unix/mm/mm.3 b/shmem/unix/mm/mm.3
deleted file mode 100644
index 94ef391a31b..00000000000
--- a/shmem/unix/mm/mm.3
+++ /dev/null
@@ -1,762 +0,0 @@
-.rn '' }`
-''' $RCSfile: mm.3,v $$Revision: 1.3 $$Date: 2000/03/10 00:06:32 $
-'''
-''' $Log: mm.3,v $
-''' Revision 1.3  2000/03/10 00:06:32  rbb
-''' Fix all the License issues.  Including:
-''' s/Apache Group/Apache Software Foundation/
-''' s/1999/2000/
-''' s/Sascha's license/ASF license
-'''
-'''
-.de Sh
-.br
-.if t .Sp
-.ne 5
-.PP
-\fB\\$1\fR
-.PP
-..
-.de Sp
-.if t .sp .5v
-.if n .sp
-..
-.de Ip
-.br
-.ie \\n(.$>=3 .ne \\$3
-.el .ne 3
-.IP "\\$1" \\$2
-..
-.de Vb
-.ft CW
-.nf
-.ne \\$1
-..
-.de Ve
-.ft R
-
-.fi
-..
-'''
-'''
-'''     Set up \*(-- to give an unbreakable dash;
-'''     string Tr holds user defined translation string.
-'''     Bell System Logo is used as a dummy character.
-'''
-.tr \(*W-|\(bv\*(Tr
-.ie n \{\
-.ds -- \(*W-
-.ds PI pi
-.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
-.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
-.ds L" ""
-.ds R" ""
-'''   \*(M", \*(S", \*(N" and \*(T" are the equivalent of
-'''   \*(L" and \*(R", except that they are used on ".xx" lines,
-'''   such as .IP and .SH, which do another additional levels of
-'''   double-quote interpretation
-.ds M" """
-.ds S" """
-.ds N" """""
-.ds T" """""
-.ds L' '
-.ds R' '
-.ds M' '
-.ds S' '
-.ds N' '
-.ds T' '
-'br\}
-.el\{\
-.ds -- \(em\|
-.tr \*(Tr
-.ds L" ``
-.ds R" ''
-.ds M" ``
-.ds S" ''
-.ds N" ``
-.ds T" ''
-.ds L' `
-.ds R' '
-.ds M' `
-.ds S' '
-.ds N' `
-.ds T' '
-.ds PI \(*p
-'br\}
-.\"	If the F register is turned on, we'll generate
-.\"	index entries out stderr for the following things:
-.\"		TH	Title 
-.\"		SH	Header
-.\"		Sh	Subsection 
-.\"		Ip	Item
-.\"		X<>	Xref  (embedded
-.\"	Of course, you have to process the output yourself
-.\"	in some meaninful fashion.
-.if \nF \{
-.de IX
-.tm Index:\\$1\t\\n%\t"\\$2"
-..
-.nr % 0
-.rr F
-.\}
-.TH mm 3 "06-Sep-1999" "MM 1.0.11" "Shared Memory Library"
-.UC
-.if n .hy 0
-.if n .na
-.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
-.de CQ          \" put $1 in typewriter font
-.ft CW
-'if n "\c
-'if t \\&\\$1\c
-'if n \\&\\$1\c
-'if n \&"
-\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7
-'.ft R
-..
-.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2
-.	\" AM - accent mark definitions
-.bd B 3
-.	\" fudge factors for nroff and troff
-.if n \{\
-.	ds #H 0
-.	ds #V .8m
-.	ds #F .3m
-.	ds #[ \f1
-.	ds #] \fP
-.\}
-.if t \{\
-.	ds #H ((1u-(\\\\n(.fu%2u))*.13m)
-.	ds #V .6m
-.	ds #F 0
-.	ds #[ \&
-.	ds #] \&
-.\}
-.	\" simple accents for nroff and troff
-.if n \{\
-.	ds ' \&
-.	ds ` \&
-.	ds ^ \&
-.	ds , \&
-.	ds ~ ~
-.	ds ? ?
-.	ds ! !
-.	ds /
-.	ds q
-.\}
-.if t \{\
-.	ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
-.	ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
-.	ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
-.	ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
-.	ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
-.	ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10'
-.	ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m'
-.	ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
-.	ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10'
-.\}
-.	\" troff and (daisy-wheel) nroff accents
-.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
-.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
-.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#]
-.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u'
-.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u'
-.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#]
-.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
-.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
-.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
-.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
-.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
-.ds ae a\h'-(\w'a'u*4/10)'e
-.ds Ae A\h'-(\w'A'u*4/10)'E
-.ds oe o\h'-(\w'o'u*4/10)'e
-.ds Oe O\h'-(\w'O'u*4/10)'E
-.	\" corrections for vroff
-.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
-.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
-.	\" for low resolution devices (crt and lpr)
-.if \n(.H>23 .if \n(.V>19 \
-\{\
-.	ds : e
-.	ds 8 ss
-.	ds v \h'-1'\o'\(aa\(ga'
-.	ds _ \h'-1'^
-.	ds . \h'-1'.
-.	ds 3 3
-.	ds o a
-.	ds d- d\h'-1'\(ga
-.	ds D- D\h'-1'\(hy
-.	ds th \o'bp'
-.	ds Th \o'LP'
-.	ds ae ae
-.	ds Ae AE
-.	ds oe oe
-.	ds Oe OE
-.\}
-.rm #[ #] #H #V #F C
-.SH "NAME"
-\fBMM \- Shared Memory Library\fR
-.SH "VERSION"
-MM 1.0.11 (06-Sep-1999)
-.SH "SYNOPSIS"
-.PP
-.Vb 1
-\& #include "mm.h"
-.Ve
-\fB Global Malloc-Replacement API\fR
-.PP
-.Vb 14
-\& int     \fBMM_create\fR(size_t size, const char *file);
-\& int     \fBMM_permission\fR(mode_t mode, uid_t owner, gid_t group);
-\& void    \fBMM_destroy\fR(void);
-\& int     \fBMM_lock\fR(mm_lock_mode mode);
-\& int     \fBMM_unlock\fR(void);
-\& void   *\fBMM_malloc\fR(size_t size);
-\& void   *\fBMM_realloc\fR(void *ptr, size_t size);
-\& void    \fBMM_free\fR(void *ptr);
-\& void   *\fBMM_calloc\fR(size_t number, size_t size);
-\& char   *\fBMM_strdup\fR(const char *str);
-\& size_t  \fBMM_sizeof\fR(void *ptr);
-\& size_t  \fBMM_maxsize\fR(void);
-\& size_t  \fBMM_available\fR(void);
-\& char   *\fBMM_error\fR(void);
-.Ve
-\fB Standard Malloc-Style API\fR
-.PP
-.Vb 15
-\& MM     *\fBmm_create\fR(size_t size, char *file);
-\& int     \fBmm_permission\fR(MM *mm, mode_t mode, uid_t owner, gid_t group);
-\& void    \fBmm_destroy\fR(MM *mm);
-\& int     \fBmm_lock\fR(MM *mm, mm_lock_mode mode);
-\& int     \fBmm_unlock\fR(MM *mm);
-\& void   *\fBmm_malloc\fR(MM *mm, size_t size);
-\& void   *\fBmm_realloc\fR(MM *mm, void *ptr, size_t size);
-\& void    \fBmm_free\fR(MM *mm, void *ptr);
-\& void   *\fBmm_calloc\fR(MM *mm, size_t number, size_t size);
-\& char   *\fBmm_strdup\fR(MM *mm, const char *str);
-\& size_t  \fBmm_sizeof\fR(void *ptr);
-\& size_t  \fBmm_maxsize\fR(void);
-\& size_t  \fBmm_available\fR(MM *mm);
-\& char   *\fBmm_error\fR(void);
-\& void    \fBmm_display_info\fR(MM *mm);
-.Ve
-\fB Low-level Shared Memory API\fR
-.PP
-.Vb 9
-\& void   *\fBmm_core_create\fR(size_t size, char *file);
-\& int     \fBmm_core_permission\fR(void *core, mode_t mode, uid_t owner, gid_t group);
-\& void    \fBmm_core_delete\fR(void *core);
-\& int     \fBmm_core_lock\fR(void *core, mm_lock_mode mode);
-\& int     \fBmm_core_unlock\fR(void *core);
-\& size_t  \fBmm_core_size\fR(void *core);
-\& size_t  \fBmm_core_maxsegsize\fR(void);
-\& size_t  \fBmm_core_align2page\fR(size_t size);
-\& size_t  \fBmm_core_align2click\fR(size_t size);
-.Ve
-\fB Internal Library API\fR
-.PP
-.Vb 3
-\& void    \fBmm_lib_error_set\fR(unsigned int, const char *str);
-\& char   *\fBmm_lib_error_get\fR(void);
-\& int     \fBmm_lib_version\fR(void);
-.Ve
-.SH "DESCRIPTION"
-The \fBMM\fR library is a 2-layer abstraction library which simplifies the usage
-of shared memory between forked (and this way strongly related) processes
-under Unix platforms. On the first (lower) layer it hides all platform
-dependent implementation details (allocation and locking) when dealing with
-shared memory segments and on the second (higher) layer it provides a
-high-level \fImalloc\fR\|(3)\-style API for a convenient and well known way to work
-with data-structures inside those shared memory segments. 
-.PP
-The abbreviation \fBMM\fR is historically and originally comes from the phrase
-``\fImemory mapped\fR'\*(R' as used by the POSIX.1 \fImmap\fR\|(2) function. Because this
-facility is internally used by this library on most platforms to create the
-shared memory segments. 
-.Sh "\s-1LIBRARY\s0 \s-1STRUCTURE\s0"
-This library is structured into three main APIs which are internally based on
-each other:
-.Ip "\fBGlobal Malloc-Replacement \s-1API\s0\fR" 4
-This is the most high-level \s-1API\s0 which directly can be used as replacement \s-1API\s0
-for the \s-1POSIX\s0.1 memory allocation \s-1API\s0 (\fImalloc\fR\|(2) and friends). This is
-useful when converting \fIheap\fR based data structures to \fIshared memory\fR
-based data structures without the need to change the code dramatically.  All
-which is needed is to prefix the \s-1POSIX\s0.1 memory allocation functions with
-`\f(CWMM_\fR\*(R', i.e. `\f(CWmalloc\fR\*(R' becomes `\f(CWMM_malloc\fR\*(R', `\f(CWstrdup\fR\*(R' becomes
-`\f(CWMM_strdup\fR\*(R', etc. This \s-1API\s0 internally uses just a global `\f(CWMM *\fR\*(R' pool for
-calling the corresponding functions (with prefix `\f(CWmm_\fR') of the \fIStandard
-Malloc-Style \s-1API\s0\fR.
-.Ip "\fBStandard Malloc-Style \s-1API\s0\fR" 4
-This is the standard high-level memory allocation \s-1API\s0. Its interface is
-similar to the \fIGlobal Malloc-Replacement \s-1API\s0\fR but it uses an explicit `\f(CWMM *\fR\*(R'
-pool to operate on. That's why every function of this \s-1API\s0 has an argument of
-type `\f(CWMM *\fR\*(R' as the first argument.  This \s-1API\s0 provides a comfortable way to
-work with small dynamically allocated shared memory chunks inside large
-statically allocated shared memory segments. It's internally based on the
-\fILow-Level Shared Memory \s-1API\s0\fR for creating the underlaying shared memory
-segment.
-.Ip "\fBLow-Level Shared Memory \s-1API\s0\fR" 4
-This is the basis of the whole \fB\s-1MM\s0\fR library. It provides low-level functions
-for creating shared memory segments with mutual exclusion (in short: \fImutex\fR)
-capabilities in a portable way. Internally the shared memory and mutex
-facility is implemented in various platform-dependent ways. A list of
-implementation variants follows under the next topic.
-.Sh "\s-1SHARED\s0 \s-1MEMORY\s0 \s-1IMPLEMENTATION\s0"
-Internally the shared memory facility is implemented in various
-platform-dependent variants. Each has it's own advantages and disadvantages
-(in addition to the fact that some variants aren't available at all on some
-platforms). The \s-1MM\s0 libraries configuration procedure tried hard to make a good
-decision. The implemented variants are now given for overview and background
-reasons with their advantages and disadvantages and in an ascending order,
-i.e. the \s-1MM\s0 configuration mechanism chooses the last available one in the list
-as the preferred variant.
-.Ip "Classical mmap(2) on temporary file (\s-1MMFILE\s0)" 4
-\fIAdvantage:\fR maximum portable.
-\fIDisadvantage:\fR needs a temporary file on the filesystem
-.Ip "mmap(2) via \s-1POSIX\s0.1 shm_open(3) on temporary file (\s-1MMPOSX\s0)" 4
-\fIAdvantage:\fR standardized by \s-1POSIX\s0.1 and theoretically portable.
-\fIDisadvantage:\fR needs a temporary file on the filesystem and is
-is usually not available on existing Unix platform.
-.Ip "\s-1SVR4-\s0style mmap(2) on \f(CW/dev/zero\fR device (\s-1MMZERO\s0)" 4
-\fIAdvantage:\fR widely available on mostly portable on \s-1SVR4\s0 platforms.
-\fIDisadvantage:\fR needs the \f(CW/dev/zero/\fR device and an \fImmap\fR\|(2)
-which supports memory mapping through it.
-.Ip "4.4BSD\-style mmap(2) via \f(CWMAP_ANON\fR facility (\s-1MMANON\s0)" 4
-\fIAdvantage:\fR doesn't need a temporary file or external device
-\fIDisadvantage:\fR usually only available on \s-1BSD\s0 platforms and derivatives.
-.Ip "SysV \s-1IPC\s0 shmget(2) (\s-1IPCSHM\s0)" 4
-\fIAdvantage:\fR doesn't need a temporary file or external device
-\fIDisadvantage:\fR although available on mostly all modern Unix platforms it has
-hard restrictions like the maximum size of a single shared memory segment (can
-be as small as 100KB, but depends on the platform).
-.Sh "\s-1LOCKING\s0 \s-1IMPLEMENTATION\s0"
-As for the shared memory facility, internally the locking facility is
-implemented in various platform-dependent variants. A short overview of
-implemented variants is given:
-.Ip "4.2BSD\-style flock(2) on temporary file (\s-1FLOCK\s0)" 4
-\fIAdvantage:\fR exists on a lot of platforms, especially on older Unix
-derivates.  \fIDisadvantage:\fR needs a temporary file on the filesystem and has
-to reopen filedescriptors to it in \fIeach\fR\|(!) \fIfork\fR\|(2)ed child process.
-.Ip "SysV \s-1IPC\s0 semget(2) (\s-1IPCSEM\s0)" 4
-\fIAdvantage:\fR exists on a lot of platforms and doesn't need a temporary file.
-\fIDisadvantage:\fR an unmeant termination of the application leads to a
-semaphore leak because the facility doesn't allow an \*(L"remove in advance\*(R" trick
-(as the \s-1IPC\s0 shared memory facility does!) for safe cleanups.
-.Ip "\s-1SVR4-\s0style fcntl(2) on temporary file (\s-1FCNTL\s0)" 4
-\fIAdvantage:\fR exists on a lot of platforms and is also the most powerful
-variant (although not always the fastest one).  \fIDisadvantage:\fR needs a
-temporary file.
-.Sh "\s-1MEMORY\s0 \s-1ALLOCATION\s0 \s-1STRATEGY\s0"
-The memory allocation strategy the \fIStandard Malloc-Style \s-1API\s0\fR functions use
-internally is the following:
-.Ip "\fBAllocation\fR" 4
-When a chunk of memory has to be allocated, the internal list of free chunks
-is searched for a minimal-sized chunk which is larger or equal than the size
-of the to be allocated chunk (some sort of a \fIbest fit algorithm\fR). 
-.Sp
-When a chunk is found which matches this best-fit criteria, but is still a lot
-larger than the requested size, it is split into two chunks: One with exactly
-the requested size (which is the resulting chunk) and one with the remaining
-size (which is immediately re-inserted into the list of free chunks). 
-.Sp
-When no fitting chunk is found at all in the list of free chunks, a new one is
-created from the spare area of the shared memory segment until the segment is
-full (in which case an \fIout of memory\fR error occurs).
-.Ip "\fBDeallocation\fR" 4
-When a chunk of memory has to be deallocated, it is inserted in sorted manner
-into the internal list of free chunks.  The insertion operation automatically
-merges the chunk with a previous and/or next free chunk when possible, i.e.
-the free chunks stay physically seamless (one after another) in memory, to
-automatically form larger free chunks out of smaller ones. 
-.Sp
-This way the shared memory segment is automatically defragmented when memory
-is deallocated.
-.PP
-This strategy reduces memory waste and fragmentation caused by small and
-frequent allocations and deallocations to a minimum. 
-.PP
-The internal implementation of the list of free chunks is not specially
-optimized (for instance by using binary search trees or even splay trees,
-etc.), because it's assumed that the total amount of entries in the list of
-free chunks is always small (caused both by the fact that shared memory
-segments are usually a lot smaller than heaps and the fact that we always
-defragment by merging the free chunks when possible).
-.SH "API FUNCTIONS"
-In the following all API functions are described in detail.
-The order directly follows the one in the SYNOPSIS.
-.Sh "Global Malloc-Replacement \s-1API\s0"
-.Ip "int \fBMM_create\fR(size_t \fIsize\fR, const char *\fIfile\fR);" 4
-This initialized the global shared memory pool with \fIsize\fR and \fIfile\fR and
-has be called \fIbefore\fR any \fIfork\fR\|(2) operations are performed by the
-application.
-.Ip "int \fBMM_permission\fR(mode_t \fImode\fR, uid_t \fIowner\fR, gid_t \fIgroup\fR);" 4
-This sets the filesystem \fImode\fR, \fIowner\fR and \fIgroup\fR for the global shared
-memory pool (has effects only when the underlaying shared memory segment
-implementation is actually based on external auxiliary files).  The arguments
-are directly passed through to \fIchmod\fR\|(2) and \fIchown\fR\|(2).
-.Ip "void \fBMM_destroy\fR(void);" 4
-This destroys the global shared memory pool and should be called \fIafter\fR all
-child processes were killed.
-.Ip "int \fBMM_lock\fR(mm_lock_mode \fImode\fR);" 4
-This locks the global shared memory pool for the current process in order to
-perform either shared/read-only (\fImode\fR is \f(CWMM_LOCK_RD\fR) or
-exclusive/read-write (\fImode\fR is \f(CWMM_LOCK_RW\fR) operations inside the global
-shared memory pool.
-.Ip "int \fBMM_unlock\fR(void);" 4
-This unlocks the global shared memory pool for the current process after
-mutual exclusion operations were performed inside the global shared memory
-pool.
-.Ip "void *\fBMM_malloc\fR(size_t \fIsize\fR);" 4
-Identical to the \s-1POSIX\s0.1 \fImalloc\fR\|(3) function but instead of allocating
-memory from the \fIheap\fR it allocates it from the global shared memory pool.
-.Ip "void \fBMM_free\fR(void *\fIptr\fR);" 4
-Identical to the \s-1POSIX\s0.1 \fIfree\fR\|(3) function but instead of deallocating
-memory in the \fIheap\fR it deallocates it in the global shared memory pool.
-.Ip "void *\fBMM_realloc\fR(void *\fIptr\fR, size_t \fIsize\fR);" 4
-Identical to the \s-1POSIX\s0.1 \fIrealloc\fR\|(3) function but instead of reallocating
-memory in the \fIheap\fR it reallocates it inside the global shared memory pool.
-.Ip "void *\fBMM_calloc\fR(size_t \fInumber\fR, size_t \fIsize\fR);" 4
-Identical to the \s-1POSIX\s0.1 \fIcalloc\fR\|(3) function but instead of allocating and
-initializing memory from the \fIheap\fR it allocates and initializes it from the
-global shared memory pool.
-.Ip "char *\fBMM_strdup\fR(const char *\fIstr\fR);" 4
-Identical to the \s-1POSIX\s0.1 \fIstrdup\fR\|(3) function but instead of creating the
-string copy in the \fIheap\fR it creates it in the global shared memory pool.
-.Ip "size_t \fBMM_sizeof\fR(const void *\fIptr\fR);" 4
-This function returns the size in bytes of the chunk starting at \fIptr\fR when
-\fIptr\fR was previously allocated with \fIMM_malloc\fR\|(3). The result is undefined
-when \fIptr\fR was not previously allocated with \fIMM_malloc\fR\|(3).
-.Ip "size_t \fBMM_maxsize\fR(void);" 4
-This function returns the maximum size which is allowed
-as the first argument to the \fIMM_create\fR\|(3) function.
-.Ip "size_t \fBMM_available\fR(void);" 4
-Returns the amount in bytes of still available (free) memory in the global
-shared memory pool.
-.Ip "char *\fBMM_error\fR(void);" 4
-Returns the last error message which occurred inside the \fB\s-1MM\s0\fR library.
-.Sh "Standard Malloc-Style \s-1API\s0"
-.Ip "\s-1MM\s0 *\fBmm_create\fR(size_t \fIsize\fR, const char *\fIfile\fR);" 4
-This creates a shared memory pool which has space for approximately a total of
-\fIsize\fR bytes with the help of \fIfile\fR. Here \fIfile\fR is a filesystem path to a
-file which need not to exist (and perhaps is never created because this
-depends on the platform and chosen shared memory and mutex implementation).
-The return value is a pointer to an \f(CWMM\fR structure which should be treated as
-opaque by the application. It describes the internals of the created shared
-memory pool. In case of an error \f(CWNULL\fR is returned.  A \fIsize\fR of 0 means to
-allocate the maximum allowed size which is platform dependent and between a
-few \s-1KB\s0 and the soft limit of 64MB.
-.Ip "int \fBmm_permission\fR(\s-1MM\s0 *\fImm\fR, mode_t \fImode\fR, uid_t \fIowner\fR, gid_t \fIgroup\fR);" 4
-This sets the filesystem \fImode\fR, \fIowner\fR and \fIgroup\fR for the shared memory
-pool \fImm\fR (has effects only when the underlaying shared memory segment
-implementation is actually based on external auxiliary files).  The arguments
-are directly passed through to \fIchmod\fR\|(2) and \fIchown\fR\|(2).
-.Ip "void \fBmm_destroy\fR(\s-1MM\s0 *\fImm\fR);" 4
-This destroys the complete shared memory pool \fImm\fR and with it all chunks
-which were allocated in this pool. Additionally any created files on the
-filesystem corresponding the to shared memory pool are unlinked.
-.Ip "int \fBmm_lock\fR(\s-1MM\s0 *\fImm\fR, mm_lock_mode \fImode\fR);" 4
-This locks the shared memory pool \fImm\fR for the current process in order to
-perform either shared/read-only (\fImode\fR is \f(CWMM_LOCK_RD\fR) or
-exclusive/read-write (\fImode\fR is \f(CWMM_LOCK_RW\fR) operations inside the global
-shared memory pool.
-.Ip "int \fBmm_unlock\fR(\s-1MM\s0 *\fImm\fR);" 4
-This unlocks the shared memory pool \fImm\fR for the current process after mutual
-exclusion operations were performed inside the global shared memory pool.
-.Ip "void *\fBmm_malloc\fR(\s-1MM\s0 *\fImm\fR, size_t \fIsize\fR);" 4
-This function allocates \fIsize\fR bytes from the shared memory pool \fImm\fR and
-returns either a (virtual memory word aligned) pointer to it or \f(CWNULL\fR in
-case of an error (out of memory). It behaves like the \s-1POSIX\s0.1 \fImalloc\fR\|(3)
-function but instead of allocating memory from the \fIheap\fR it allocates it
-from the shared memory segment underlaying \fImm\fR.
-.Ip "void \fBmm_free\fR(\s-1MM\s0 *\fImm\fR, void *\fIptr\fR);" 4
-This deallocates the chunk starting at \fIptr\fR in the shared memory pool \fImm\fR.
-It behaves like the \s-1POSIX\s0.1 \fIfree\fR\|(3) function but instead of deallocating
-memory from the \fIheap\fR it deallocates it from the shared memory segment
-underlaying \fImm\fR.
-.Ip "void *\fBmm_realloc\fR(\s-1MM\s0 *\fImm\fR, void *\fIptr\fR, size_t \fIsize\fR);" 4
-This function reallocates the chunk starting at \fIptr\fR inside the shared
-memory pool \fImm\fR with the new size of \fIsize\fR bytes.  It behaves like the
-\s-1POSIX\s0.1 \fIrealloc\fR\|(3) function but instead of reallocating memory in the
-\fIheap\fR it reallocates it in the shared memory segment underlaying \fImm\fR.
-.Ip "void *\fBmm_calloc\fR(\s-1MM\s0 *\fImm\fR, size_t \fInumber\fR, size_t \fIsize\fR);" 4
-This is similar to \fImm_malloc\fR\|(3), but additionally clears the chunk. It behaves
-like the \s-1POSIX\s0.1 \fIcalloc\fR\|(3) function.  It allocates space for \fInumber\fR
-objects, each \fIsize\fR bytes in length from the shared memory pool \fImm\fR.  The
-result is identical to calling \fImm_malloc\fR\|(3) with an argument of ``\fInumber\fR *
-\fIsize\fR'\*(R', with the exception that the allocated memory is initialized to nul
-bytes.
-.Ip "char *\fBmm_strdup\fR(\s-1MM\s0 *\fImm\fR, const char *\fIstr\fR);" 4
-This function behaves like the \s-1POSIX\s0.1 \fIstrdup\fR\|(3) function.  It allocates
-sufficient memory inside the shared memory pool \fImm\fR for a copy of the string
-\fIstr\fR, does the copy, and returns a pointer to it.  The pointer may
-subsequently be used as an argument to the function \fImm_free\fR\|(3). If
-insufficient shared memory is available, \f(CWNULL\fR is returned.
-.Ip "size_t \fBmm_sizeof\fR(const void *\fIptr\fR);" 4
-This function returns the size in bytes of the chunk starting at \fIptr\fR when
-\fIptr\fR was previously allocated with \fImm_malloc\fR\|(3). The result is undefined
-when \fIptr\fR was not previously allocated with \fImm_malloc\fR\|(3).
-.Ip "size_t \fBmm_maxsize\fR(void);" 4
-This function returns the maximum size which is allowed as the first argument
-to the \fImm_create\fR\|(3) function.
-.Ip "size_t \fBmm_available\fR(\s-1MM\s0 *\fImm\fR);" 4
-Returns the amount in bytes of still available (free) memory in the 
-shared memory pool \fImm\fR.
-.Ip "char *\fBmm_error\fR(void);" 4
-Returns the last error message which occurred inside the \fB\s-1MM\s0\fR library.
-.Ip "void \fBmm_display_info\fR(\s-1MM\s0 *\fImm\fR);" 4
-This is debugging function which displays a summary page for the shared memory
-pool \fImm\fR describing various internal sizes and counters.
-.Sh "Low-Level Shared Memory \s-1API\s0"
-.Ip "void *\fBmm_core_create\fR(size_t \fIsize\fR, const char *\fIfile\fR);" 4
-This creates a shared memory area which is at least \fIsize\fR bytes in size with
-the help of \fIfile\fR. The value \fIsize\fR has to be greater than 0 and less or
-equal the value returned by \fImm_core_maxsegsize\fR\|(3). Here \fIfile\fR is a
-filesystem path to a file which need not to exist (and perhaps is never
-created because this depends on the platform and chosen shared memory and
-mutex implementation).  The return value is either a (virtual memory word
-aligned) pointer to the shared memory segment or \f(CWNULL\fR in case of an error.
-The application is guaranteed to be able to access the shared memory segment
-from byte 0 to byte \fIsize\fR\-1 starting at the returned address.
-.Ip "int \fBmm_core_permission\fR(void *\fIcore\fR, mode_t \fImode\fR, uid_t \fIowner\fR, gid_t \fIgroup\fR);" 4
-This sets the filesystem \fImode\fR, \fIowner\fR and \fIgroup\fR for the shared memory
-segment \fIcode\fR (has effects only when the underlaying shared memory segment
-implementation is actually based on external auxiliary files).  The arguments
-are directly passed through to \fIchmod\fR\|(2) and \fIchown\fR\|(2).
-.Ip "void \fBmm_core_delete\fR(void *\fIcore\fR);" 4
-This deletes a shared memory segment \fIcore\fR (as previously returned by a
-\fImm_core_create\fR\|(3) call). After this operation, accessing the segment starting
-at \fIcore\fR is no longer allowed and will usually lead to a segmentation fault.
-.Ip "int \fBmm_core_lock\fR(const void *\fIcore\fR, mm_lock_mode \fImode\fR);" 4
-This function acquires an advisory lock for the current process on the shared
-memory segment \fIcore\fR for either shared/read-only (\fImode\fR is \f(CWMM_LOCK_RD\fR)
-or exclusive/read-write (\fImode\fR is \f(CWMM_LOCK_RW\fR) operations between
-\fIfork\fR\|(2)'ed child processes.
-.Ip "int \fBmm_core_unlock\fR(const void *\fIcore\fR);" 4
-This function releases a previously acquired advisory lock for the current
-process on the shared memory segment \fIcore\fR.
-.Ip "size_t \fBmm_core_size\fR(const void *\fIcore\fR);" 4
-This returns the size in bytes of \fIcore\fR. This size is exactly the size which
-was used for creating the shared memory area via \fImm_core_create\fR\|(3). The
-function is provided just for convenience reasons to not require the
-application to remember the memory size behind \fIcore\fR itself. 
-.Ip "size_t \fBmm_core_maxsegsize\fR(void);" 4
-This returns the number of bytes of a maximum-size shared memory segment which
-is allowed to allocate via the \s-1MM\s0 library. It is between a few \s-1KB\s0 and the soft
-limit of 64MB.
-.Ip "size_t \fBmm_core_align2page\fR(size_t \fIsize\fR);" 4
-This is just a utility function which can be used to align the number \fIsize\fR
-to the next virtual memory \fIpage\fR boundary used by the underlaying platform.
-The memory page boundary under Unix platforms is usually somewhere between
-2048 and 16384 bytes. You don't have to align the \fIsize\fR arguments of other
-\fB\s-1MM\s0\fR library functions yourself, because this is already done internally.
-This function is exported by the \fB\s-1MM\s0\fR library just for convenience reasons in
-case an application wants to perform simular calculations for other purposes.
-.Ip "size_t \fBmm_core_align2word\fR(size_t \fIsize\fR);" 4
-This is another utility function which can be used to align the number \fIsize\fR
-to the next virtual memory \fIword\fR boundary used by the underlaying platform.
-The memory word boundary under Unix platforms is usually somewhere between 4
-and 16 bytes.  You don't have to align the \fIsize\fR arguments of other \fB\s-1MM\s0\fR
-library functions yourself, because this is already done internally.  This
-function is exported by the \fB\s-1MM\s0\fR library just for convenience reasons in case
-an application wants to perform simular calculations for other purposes.
-.Sh "Low-Level Shared Memory \s-1API\s0"
-.Ip "void \fBmm_lib_error_set\fR(unsigned int, const char *str);" 4
-This is a function which is used internally by the various \s-1MM\s0 function to set
-an error string. It's usually not called directly from applications.
-.Ip "char *\fBmm_lib_error_get\fR(void);" 4
-This is a function which is used internally by \fIMM_error\fR\|(3) and \fImm_error\fR\|(3)
-functions to get the current error string. It's usually not called directly
-from applications.
-.Ip "int \fBmm_lib_version\fR(void);" 4
-This function returns a hex-value ``0x\fIV\fR\fI\s-1RR\s0\fR\fIT\fR\fI\s-1LL\s0\fR'\*(R' which describes the
-current \s-1MM\s0 library version. \fIV\fR is the version, \fI\s-1RR\s0\fR the revisions, \fI\s-1LL\s0\fR
-the level and \fIT\fR the type of the level (alphalevel=0, betalevel=1,
-patchlevel=2, etc). For instance \s-1MM\s0 version 1.0.4 is encoded as 0x100204.  The
-reason for this unusual mapping is that this way the version number is
-steadily \fIincreasing\fR.
-.SH "RESTRICTIONS"
-The maximum size of a continuous shared memory segment one can allocate
-depends on the underlaying platform. This cannot be changed, of course.  But
-currently the high-level \fImalloc\fR\|(3)\-style API just uses a single shared memory
-segment as the underlaying data structure for an \f(CWMM\fR object which means that
-the maximum amount of memory a \f(CWMM\fR object represents also depends on the
-platform. 
-.PP
-This should be changed in later versions by allowing the high-level
-\fImalloc\fR\|(3)\-style API to internally use multiple shared memory segments to form
-the \f(CWMM\fR object. This way \f(CWMM\fR objects could have arbitrary sizes, although
-the maximum size of an allocatable chunk still is bounded by the maximum size
-of a shared memory segment.
-.SH "SEE ALSO"
-mm-\fIconfig\fR\|(1).
-.PP
-\fImalloc\fR\|(3), \fIcalloc\fR\|(3), \fIrealloc\fR\|(3), \fIstrdup\fR\|(3), \fIfree\fR\|(3), \fImmap\fR\|(2), \fIshmget\fR\|(2),
-\fIshmctl\fR\|(2), \fIflock\fR\|(2), \fIfcntl\fR\|(2), \fIsemget\fR\|(2), \fIsemctl\fR\|(2), \fIsemop\fR\|(2).
-.SH "HOME"
-http://www.engelschall.com/sw/mm/
-
-.SH "HISTORY"
-This library was originally written in January 1999 by \fIRalf S. Engelschall\fR
-<rse@engelschall.com> for use in the \fBExtended API\fR (EAPI) of the \fBApache\fR
-HTTP server project (see www.apache.org), which was originally invented for
-\fBmod_ssl\fR (see http://www.modssl.org/). 
-.PP
-Its base idea (a malloc-style API for handling shared memory) was originally
-derived from the non-publically available \fImm_malloc\fR library written in
-October 1997 by \fICharles Randall\fR <crandall@matchlogic.com> for MatchLogic,
-Inc.
-.SH "AUTHOR"
-.PP
-.Vb 3
-\& Ralf S. Engelschall
-\& rse@engelschall.com
-\& www.engelschall.com
-.Ve
-
-.rn }` ''
-.IX Title "mm 3"
-.IX Name "B<MM - Shared Memory Library>"
-
-.IX Header "NAME"
-
-.IX Header "VERSION"
-
-.IX Header "SYNOPSIS"
-
-.IX Header "DESCRIPTION"
-
-.IX Subsection "\s-1LIBRARY\s0 \s-1STRUCTURE\s0"
-
-.IX Item "\fBGlobal Malloc-Replacement \s-1API\s0\fR"
-
-.IX Item "\fBStandard Malloc-Style \s-1API\s0\fR"
-
-.IX Item "\fBLow-Level Shared Memory \s-1API\s0\fR"
-
-.IX Subsection "\s-1SHARED\s0 \s-1MEMORY\s0 \s-1IMPLEMENTATION\s0"
-
-.IX Item "Classical mmap(2) on temporary file (\s-1MMFILE\s0)"
-
-.IX Item "mmap(2) via \s-1POSIX\s0.1 shm_open(3) on temporary file (\s-1MMPOSX\s0)"
-
-.IX Item "\s-1SVR4-\s0style mmap(2) on \f(CW/dev/zero\fR device (\s-1MMZERO\s0)"
-
-.IX Item "4.4BSD\-style mmap(2) via \f(CWMAP_ANON\fR facility (\s-1MMANON\s0)"
-
-.IX Item "SysV \s-1IPC\s0 shmget(2) (\s-1IPCSHM\s0)"
-
-.IX Subsection "\s-1LOCKING\s0 \s-1IMPLEMENTATION\s0"
-
-.IX Item "4.2BSD\-style flock(2) on temporary file (\s-1FLOCK\s0)"
-
-.IX Item "SysV \s-1IPC\s0 semget(2) (\s-1IPCSEM\s0)"
-
-.IX Item "\s-1SVR4-\s0style fcntl(2) on temporary file (\s-1FCNTL\s0)"
-
-.IX Subsection "\s-1MEMORY\s0 \s-1ALLOCATION\s0 \s-1STRATEGY\s0"
-
-.IX Item "\fBAllocation\fR"
-
-.IX Item "\fBDeallocation\fR"
-
-.IX Header "API FUNCTIONS"
-
-.IX Subsection "Global Malloc-Replacement \s-1API\s0"
-
-.IX Item "int \fBMM_create\fR(size_t \fIsize\fR, const char *\fIfile\fR);"
-
-.IX Item "int \fBMM_permission\fR(mode_t \fImode\fR, uid_t \fIowner\fR, gid_t \fIgroup\fR);"
-
-.IX Item "void \fBMM_destroy\fR(void);"
-
-.IX Item "int \fBMM_lock\fR(mm_lock_mode \fImode\fR);"
-
-.IX Item "int \fBMM_unlock\fR(void);"
-
-.IX Item "void *\fBMM_malloc\fR(size_t \fIsize\fR);"
-
-.IX Item "void \fBMM_free\fR(void *\fIptr\fR);"
-
-.IX Item "void *\fBMM_realloc\fR(void *\fIptr\fR, size_t \fIsize\fR);"
-
-.IX Item "void *\fBMM_calloc\fR(size_t \fInumber\fR, size_t \fIsize\fR);"
-
-.IX Item "char *\fBMM_strdup\fR(const char *\fIstr\fR);"
-
-.IX Item "size_t \fBMM_sizeof\fR(const void *\fIptr\fR);"
-
-.IX Item "size_t \fBMM_maxsize\fR(void);"
-
-.IX Item "size_t \fBMM_available\fR(void);"
-
-.IX Item "char *\fBMM_error\fR(void);"
-
-.IX Subsection "Standard Malloc-Style \s-1API\s0"
-
-.IX Item "\s-1MM\s0 *\fBmm_create\fR(size_t \fIsize\fR, const char *\fIfile\fR);"
-
-.IX Item "int \fBmm_permission\fR(\s-1MM\s0 *\fImm\fR, mode_t \fImode\fR, uid_t \fIowner\fR, gid_t \fIgroup\fR);"
-
-.IX Item "void \fBmm_destroy\fR(\s-1MM\s0 *\fImm\fR);"
-
-.IX Item "int \fBmm_lock\fR(\s-1MM\s0 *\fImm\fR, mm_lock_mode \fImode\fR);"
-
-.IX Item "int \fBmm_unlock\fR(\s-1MM\s0 *\fImm\fR);"
-
-.IX Item "void *\fBmm_malloc\fR(\s-1MM\s0 *\fImm\fR, size_t \fIsize\fR);"
-
-.IX Item "void \fBmm_free\fR(\s-1MM\s0 *\fImm\fR, void *\fIptr\fR);"
-
-.IX Item "void *\fBmm_realloc\fR(\s-1MM\s0 *\fImm\fR, void *\fIptr\fR, size_t \fIsize\fR);"
-
-.IX Item "void *\fBmm_calloc\fR(\s-1MM\s0 *\fImm\fR, size_t \fInumber\fR, size_t \fIsize\fR);"
-
-.IX Item "char *\fBmm_strdup\fR(\s-1MM\s0 *\fImm\fR, const char *\fIstr\fR);"
-
-.IX Item "size_t \fBmm_sizeof\fR(const void *\fIptr\fR);"
-
-.IX Item "size_t \fBmm_maxsize\fR(void);"
-
-.IX Item "size_t \fBmm_available\fR(\s-1MM\s0 *\fImm\fR);"
-
-.IX Item "char *\fBmm_error\fR(void);"
-
-.IX Item "void \fBmm_display_info\fR(\s-1MM\s0 *\fImm\fR);"
-
-.IX Subsection "Low-Level Shared Memory \s-1API\s0"
-
-.IX Item "void *\fBmm_core_create\fR(size_t \fIsize\fR, const char *\fIfile\fR);"
-
-.IX Item "int \fBmm_core_permission\fR(void *\fIcore\fR, mode_t \fImode\fR, uid_t \fIowner\fR, gid_t \fIgroup\fR);"
-
-.IX Item "void \fBmm_core_delete\fR(void *\fIcore\fR);"
-
-.IX Item "int \fBmm_core_lock\fR(const void *\fIcore\fR, mm_lock_mode \fImode\fR);"
-
-.IX Item "int \fBmm_core_unlock\fR(const void *\fIcore\fR);"
-
-.IX Item "size_t \fBmm_core_size\fR(const void *\fIcore\fR);"
-
-.IX Item "size_t \fBmm_core_maxsegsize\fR(void);"
-
-.IX Item "size_t \fBmm_core_align2page\fR(size_t \fIsize\fR);"
-
-.IX Item "size_t \fBmm_core_align2word\fR(size_t \fIsize\fR);"
-
-.IX Subsection "Low-Level Shared Memory \s-1API\s0"
-
-.IX Item "void \fBmm_lib_error_set\fR(unsigned int, const char *str);"
-
-.IX Item "char *\fBmm_lib_error_get\fR(void);"
-
-.IX Item "int \fBmm_lib_version\fR(void);"
-
-.IX Header "RESTRICTIONS"
-
-.IX Header "SEE ALSO"
-
-.IX Header "HOME"
-
-.IX Header "HISTORY"
-
-.IX Header "AUTHOR"
-
diff --git a/shmem/unix/mm/mm.h b/shmem/unix/mm/mm.h
deleted file mode 100644
index 3c029e63061..00000000000
--- a/shmem/unix/mm/mm.h
+++ /dev/null
@@ -1,361 +0,0 @@
-/* ====================================================================
- * Copyright (c) 1999 Ralf S. Engelschall. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- *    software must display the following acknowledgment:
- *    "This product includes software developed by
- *     Ralf S. Engelschall <rse@engelschall.com>."
- *
- * 4. Redistributions of any form whatsoever must retain the following
- *    acknowledgment:
- *    "This product includes software developed by
- *     Ralf S. Engelschall <rse@engelschall.com>."
- *
- * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL RALF S. ENGELSCHALL OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- */
-
-/*
-**
-**  mm.h -- Shared Memory library API header
-**
-*/
-
-#ifndef MM_H 
-#define MM_H 1
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
-**  ____ Public Part (I) of the API ________________________
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-typedef enum { 
-    MM_LOCK_RD, MM_LOCK_RW
-} mm_lock_mode;
-
-/*
-**  ____ Private Part of the API ___________________________
-*/
-
-#if defined(MM_PRIVATE)
-
-#include "mm_conf.h"
-
-#include <errno.h>
-#include <limits.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#ifdef MM_OS_SUNOS
-#define KERNEL 1
-#include <memory.h>
-/* SunOS lacks prototypes */
-extern int   getpagesize(void);
-extern int   munmap(caddr_t, int);
-extern int   ftruncate(int, off_t);
-extern int   flock(int, int);
-extern char *strerror(int);
-#endif
-
-#if !defined(FALSE)
-#define FALSE 0
-#endif
-#if !defined(TRUE)
-#define TRUE !FALSE
-#endif
-#if !defined(NULL)
-#define NULL (void *)0
-#endif
-#if !defined(NUL)
-#define NUL '\0'
-#endif
-#if !defined(min_of)
-#define min_of(a,b) ((a) < (b) ? (a) : (b))
-#endif
-#if !defined(max_of)
-#define max_of(a,b) ((a) > (b) ? (a) : (b))
-#endif
-#if !defined(absof)
-#define abs_of(a) ((a) < 0 ? -(a) : (a))
-#endif
-#if !defined(offset_of)
-#define offset_of(type,member) ((size_t)(&((type *)0)->member))
-#endif
-
-#if !defined(HAVE_MEMCPY) 
-#if defined(HAVE_BCOPY)
-#define memcpy(to,from,len) bcopy(from,to,len)
-#else
-#define memcpy(to,from,len) \
-        { int i; for (i = 0; i < (len); i++) *((to)+i) = *((from)+i); }
-#endif
-#endif
-#if !defined(HAVE_MEMSET)
-#define memset(to,ch,len) \
-        { int i; for (i = 0; i < (len); i++) *((to)+i) = (ch); }
-#endif
-
-#define ERR(type,str)   mm_lib_error_set(type,str)
-#define FAIL(type,str)  { ERR(type,str); goto cus; }
-#define BEGIN_FAILURE   cus:
-#define END_FAILURE   
-
-#if defined(HAVE_PATH_MAX)
-#define MM_MAXPATH PATH_MAX
-#elif defined(HAVE__POSIX_PATH_MAX)
-#define MM_MAXPATH _POSIX_PATH_MAX
-#elif defined(HAVE_MAXPATHLEN)
-#define MM_MAXPATH MAXPATHLEN
-#else
-#define MM_MAXPATH 2048
-#endif
-
-#if defined(HAVE_CHILD_MAX)
-#define MM_MAXCHILD CHILD_MAX
-#elif defined(HAVE__POSIX_CHILD_MAX)
-#define MM_MAXCHILD _POSIX_CHILD_MAX
-#else
-#define MM_MAXCHILD 512
-#endif
-
-#if defined(MM_SHMT_MMANON) || defined(MM_SHMT_MMPOSX) ||\
-    defined(MM_SHMT_MMZERO) || defined(MM_SHMT_MMFILE)
-#include <sys/mman.h>
-#if !defined(MAP_ANON) && defined(MAP_ANONYMOUS)
-#define MAP_ANON MAP_ANONYMOUS
-#endif
-#if !defined(MAP_FAILED)
-#define MAP_FAILED ((void *)-1)
-#endif
-#endif
-
-#if defined(MM_SHMT_IPCSHM) || defined(MM_SEMT_IPCSEM)
-#include <sys/ipc.h>
-#endif
-
-#if defined(MM_SHMT_IPCSHM)
-#include <sys/shm.h>
-#endif
-
-#if defined(MM_SEMT_IPCSEM)
-#include <sys/sem.h>
-#ifndef HAVE_UNION_SEMUN
-union semun {
-    int val;
-    struct semid_ds *buf;
-    u_short *array;
-};
-#endif
-#endif
-
-#ifdef MM_SEMT_FLOCK
-#include <sys/file.h>
-#endif
-
-#ifdef MM_SHMT_BEOS
-#include <kernel/OS.h>
-#endif
-
-#define MM_ALLOC_MINSIZE         (1024*8) 
-#define MM_CORE_FILEMODE         (S_IRUSR|S_IWUSR)
-#define MM_CORE_DEFAULT_PAGESIZE (1024*8)
-#define MM_CORE_DEFAULT_FILE     "/tmp/mm.core.%d"  /* %d is PID */
-
-#define MM_ERR_ALLOC    1
-#define MM_ERR_CORE     2
-#define MM_ERR_SYSTEM   4
-
-/* 
- * Define a union with types which are likely to have the longest
- * *relevant* CPU-specific memory word alignment restrictions...
- */
-union mem_word {
-    void  *mw_vp;
-    void (*mw_fp)(void);
-    char  *mw_cp;
-    long   mw_l;
-    double mw_d;
-};
-typedef union mem_word mem_word;
-#define SIZEOF_mem_word (sizeof(mem_word))
-
-/*
- * Define the structure used for memory chunks
- */
-union mem_chunk_mc_u {
-    struct mem_chunk *mc_next; /* really used when it's free         */
-    mem_word          mc_base; /* virtually used when it's allocated */
-};
-struct mem_chunk {
-    size_t mc_size;      /* physical size   */
-    size_t mc_usize;     /* user known size */
-    union mem_chunk_mc_u mc_u;
-};
-typedef struct mem_chunk mem_chunk;
-#define SIZEOF_mem_chunk (sizeof(mem_chunk)-sizeof(union mem_chunk_mc_u))
-
-/*
- * Define the structure describing a memory pool
- */
-struct mem_pool {
-   size_t     mp_size;
-   size_t     mp_offset;
-   mem_chunk  mp_freechunks;
-   mem_word   mp_base;
-};
-typedef struct mem_pool mem_pool;
-#define SIZEOF_mem_pool (sizeof(mem_pool)-SIZEOF_mem_word)
-
-/*
- * Define the structure holding per-process filedescriptors
- */
-#if defined(MM_SEMT_FLOCK)
-struct mem_core_fd {
-    pid_t pid;
-    int fd;
-};
-typedef struct mem_core_fd mem_core_fd;
-#define SIZEOF_mem_core_fd (sizeof(mem_core_fd)
-#endif
-
-/*
- * Define the structure describing a shared memory core area
- * (the actual contents depends on the shared memory and
- * semaphore/mutex type and is stripped down to a minimum
- * required)
- */
-struct mem_core {
-   size_t       mc_size;
-   size_t       mc_usize;
-   pid_t        mc_pid;
-   int          mc_fdmem;
-#if defined(MM_SHMT_MMFILE)
-   char         mc_fnmem[MM_MAXPATH];
-#endif
-#if defined(MM_SHMT_BEOS)
-    area_id     mc_areaid;
-#endif
-#if defined(MM_SEMT_BEOS)
-    sem_id      mc_semid;
-    int32       mc_ben;
-#endif
-#if !defined(MM_SEMT_FLOCK)
-   int          mc_fdsem;
-#endif
-#if defined(MM_SEMT_FLOCK)
-   mem_core_fd  mc_fdsem[MM_MAXCHILD];
-#endif
-#if defined(MM_SEMT_IPCSEM)
-   int          mc_fdsem_rd;
-   int          mc_readers;
-   mm_lock_mode mc_lockmode;
-#endif
-#if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL)
-   char         mc_fnsem[MM_MAXPATH];
-#endif
-   mem_word     mc_base;
-};
-typedef struct mem_core mem_core;
-#define SIZEOF_mem_core (sizeof(mem_core)-SIZEOF_mem_word)
-
-#endif /* MM_PRIVATE */
-
-/*
-**  ____ Public Part (II) of the API _______________________
-*/
-
-#if defined(MM_PRIVATE)
-typedef mem_pool MM;
-#else
-typedef void MM;
-#endif
-
-/* Global Malloc-Replacement API */
-int     MM_create(size_t size, const char *file);
-int     MM_permission(mode_t mode, uid_t owner, gid_t group);
-void    MM_destroy(void);
-int     MM_lock(mm_lock_mode mode);
-int     MM_unlock(void);
-void   *MM_malloc(size_t size);
-void   *MM_realloc(void *ptr, size_t size);
-void    MM_free(void *ptr);
-void   *MM_calloc(size_t number, size_t size);
-char   *MM_strdup(const char *str);
-size_t  MM_sizeof(const void *ptr);
-size_t  MM_maxsize(void);
-size_t  MM_available(void);
-char   *MM_error(void);
-
-/* Standard Malloc-Style API */
-MM     *mm_create(size_t size, const char *file);
-int     mm_permission(MM *mm, mode_t mode, uid_t owner, gid_t group);
-void    mm_destroy(MM *mm);
-int     mm_lock(MM *mm, mm_lock_mode mode);
-int     mm_unlock(MM *mm);
-void   *mm_malloc(MM *mm, size_t size);
-void   *mm_realloc(MM *mm, void *ptr, size_t size);
-void    mm_free(MM *mm, void *ptr);
-void   *mm_calloc(MM *mm, size_t number, size_t size);
-char   *mm_strdup(MM *mm, const char *str);
-size_t  mm_sizeof(MM *mm, const void *ptr);
-size_t  mm_maxsize(void);
-size_t  mm_available(MM *mm);
-char   *mm_error(void);
-void    mm_display_info(MM *mm);
-
-/* Low-Level Shared Memory API */
-void   *mm_core_create(size_t size, const char *file);
-int     mm_core_permission(void *core, mode_t mode, uid_t owner, gid_t group);
-void    mm_core_delete(void *core);
-size_t  mm_core_size(const void *core);
-int     mm_core_lock(const void *core, mm_lock_mode mode);
-int     mm_core_unlock(const void *core);
-size_t  mm_core_maxsegsize(void);
-size_t  mm_core_align2page(size_t size);
-size_t  mm_core_align2word(size_t size);
-
-/* Internal Library API */
-void    mm_lib_error_set(unsigned int, const char *str);
-char   *mm_lib_error_get(void);
-int     mm_lib_version(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* MM_H */
diff --git a/shmem/unix/mm/mm.pod b/shmem/unix/mm/mm.pod
deleted file mode 100644
index 7746612b5d6..00000000000
--- a/shmem/unix/mm/mm.pod
+++ /dev/null
@@ -1,633 +0,0 @@
-## ====================================================================
-## Copyright (c) 1999 Ralf S. Engelschall. All rights reserved.
-##
-## Redistribution and use in source and binary forms, with or without
-## modification, are permitted provided that the following conditions
-## are met:
-##
-## 1. Redistributions of source code must retain the above copyright
-##    notice, this list of conditions and the following disclaimer. 
-##
-## 2. Redistributions in binary form must reproduce the above copyright
-##    notice, this list of conditions and the following disclaimer in
-##    the documentation and/or other materials provided with the
-##    distribution.
-##
-## 3. All advertising materials mentioning features or use of this
-##    software must display the following acknowledgment:
-##    "This product includes software developed by
-##     Ralf S. Engelschall <rse@engelschall.com>."
-##
-## 4. Redistributions of any form whatsoever must retain the following
-##    acknowledgment:
-##    "This product includes software developed by
-##     Ralf S. Engelschall <rse@engelschall.com>."
-##
-## THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
-## EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-## PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL RALF S. ENGELSCHALL OR
-## ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-## NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-## LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-## HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-## STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-## ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
-## OF THE POSSIBILITY OF SUCH DAMAGE.
-## ====================================================================
-
-##
-## mm.pod -- Manpage
-##
-
-=pod
-
-=head1 NAME
-
-B<MM - Shared Memory Library>
-
-=head1 VERSION
-
-MM MM_VERSION_STR
-
-=head1 SYNOPSIS
-
- #include "mm.h"
-
-B< Global Malloc-Replacement API>
-
- int     MM_create(size_t size, const char *file);
- int     MM_permission(mode_t mode, uid_t owner, gid_t group);
- void    MM_destroy(void);
- int     MM_lock(mm_lock_mode mode);
- int     MM_unlock(void);
- void   *MM_malloc(size_t size);
- void   *MM_realloc(void *ptr, size_t size);
- void    MM_free(void *ptr);
- void   *MM_calloc(size_t number, size_t size);
- char   *MM_strdup(const char *str);
- size_t  MM_sizeof(void *ptr);
- size_t  MM_maxsize(void);
- size_t  MM_available(void);
- char   *MM_error(void);
-
-B< Standard Malloc-Style API>
-
- MM     *mm_create(size_t size, char *file);
- int     mm_permission(MM *mm, mode_t mode, uid_t owner, gid_t group);
- void    mm_destroy(MM *mm);
- int     mm_lock(MM *mm, mm_lock_mode mode);
- int     mm_unlock(MM *mm);
- void   *mm_malloc(MM *mm, size_t size);
- void   *mm_realloc(MM *mm, void *ptr, size_t size);
- void    mm_free(MM *mm, void *ptr);
- void   *mm_calloc(MM *mm, size_t number, size_t size);
- char   *mm_strdup(MM *mm, const char *str);
- size_t  mm_sizeof(void *ptr);
- size_t  mm_maxsize(void);
- size_t  mm_available(MM *mm);
- char   *mm_error(void);
- void    mm_display_info(MM *mm);
-
-B< Low-level Shared Memory API>
-
- void   *mm_core_create(size_t size, char *file);
- int     mm_core_permission(void *core, mode_t mode, uid_t owner, gid_t group);
- void    mm_core_delete(void *core);
- int     mm_core_lock(void *core, mm_lock_mode mode);
- int     mm_core_unlock(void *core);
- size_t  mm_core_size(void *core);
- size_t  mm_core_maxsegsize(void);
- size_t  mm_core_align2page(size_t size);
- size_t  mm_core_align2click(size_t size);
-
-B< Internal Library API>
-
- void    mm_lib_error_set(unsigned int, const char *str);
- char   *mm_lib_error_get(void);
- int     mm_lib_version(void);
-
-=head1 DESCRIPTION
-
-The B<MM> library is a 2-layer abstraction library which simplifies the usage
-of shared memory between forked (and this way strongly related) processes
-under Unix platforms. On the first (lower) layer it hides all platform
-dependent implementation details (allocation and locking) when dealing with
-shared memory segments and on the second (higher) layer it provides a
-high-level malloc(3)-style API for a convenient and well known way to work
-with data-structures inside those shared memory segments. 
-
-The abbreviation B<MM> is historically and originally comes from the phrase
-``I<memory mapped>'' as used by the POSIX.1 mmap(2) function. Because this
-facility is internally used by this library on most platforms to create the
-shared memory segments. 
-
-=head2 LIBRARY STRUCTURE
-
-This library is structured into three main APIs which are internally based on
-each other:
-
-=over 4
-
-=item B<Global Malloc-Replacement API>
-
-This is the most high-level API which directly can be used as replacement API
-for the POSIX.1 memory allocation API (malloc(2) and friends). This is
-useful when converting I<heap> based data structures to I<shared memory>
-based data structures without the need to change the code dramatically.  All
-which is needed is to prefix the POSIX.1 memory allocation functions with
-`C<MM_>', i.e. `C<malloc>' becomes `C<MM_malloc>', `C<strdup>' becomes
-`C<MM_strdup>', etc. This API internally uses just a global `C<MM *>' pool for
-calling the corresponding functions (with prefix `C<mm_>') of the I<Standard
-Malloc-Style API>.
-
-=item B<Standard Malloc-Style API>
-
-This is the standard high-level memory allocation API. Its interface is
-similar to the I<Global Malloc-Replacement API> but it uses an explicit `C<MM *>'
-pool to operate on. That's why every function of this API has an argument of
-type `C<MM *>' as the first argument.  This API provides a comfortable way to
-work with small dynamically allocated shared memory chunks inside large
-statically allocated shared memory segments. It's internally based on the
-I<Low-Level Shared Memory API> for creating the underlaying shared memory
-segment.
-
-=item B<Low-Level Shared Memory API>
-
-This is the basis of the whole B<MM> library. It provides low-level functions
-for creating shared memory segments with mutual exclusion (in short: I<mutex>)
-capabilities in a portable way. Internally the shared memory and mutex
-facility is implemented in various platform-dependent ways. A list of
-implementation variants follows under the next topic.
-
-=back
-
-=head2 SHARED MEMORY IMPLEMENTATION
-
-Internally the shared memory facility is implemented in various
-platform-dependent variants. Each has it's own advantages and disadvantages
-(in addition to the fact that some variants aren't available at all on some
-platforms). The MM libraries configuration procedure tried hard to make a good
-decision. The implemented variants are now given for overview and background
-reasons with their advantages and disadvantages and in an ascending order,
-i.e. the MM configuration mechanism chooses the last available one in the list
-as the preferred variant.
-
-=over 4
-
-=item Classical mmap(2) on temporary file (MMFILE)
-
-I<Advantage:> maximum portable.
-I<Disadvantage:> needs a temporary file on the filesystem
-
-=item mmap(2) via POSIX.1 shm_open(3) on temporary file (MMPOSX)
-
-I<Advantage:> standardized by POSIX.1 and theoretically portable.
-I<Disadvantage:> needs a temporary file on the filesystem and is
-is usually not available on existing Unix platform.
-
-=item SVR4-style mmap(2) on C</dev/zero> device (MMZERO)
-
-I<Advantage:> widely available on mostly portable on SVR4 platforms.
-I<Disadvantage:> needs the C</dev/zero/> device and an mmap(2)
-which supports memory mapping through it.
-
-=item 4.4BSD-style mmap(2) via C<MAP_ANON> facility (MMANON)
-
-I<Advantage:> doesn't need a temporary file or external device
-I<Disadvantage:> usually only available on BSD platforms and derivatives.
-
-=item SysV IPC shmget(2) (IPCSHM)
-
-I<Advantage:> doesn't need a temporary file or external device
-I<Disadvantage:> although available on mostly all modern Unix platforms it has
-hard restrictions like the maximum size of a single shared memory segment (can
-be as small as 100KB, but depends on the platform).
-
-=back
-
-=head2 LOCKING IMPLEMENTATION
-
-As for the shared memory facility, internally the locking facility is
-implemented in various platform-dependent variants. A short overview of
-implemented variants is given:
-
-=over 4
-
-=item 4.2BSD-style flock(2) on temporary file (FLOCK)
-
-I<Advantage:> exists on a lot of platforms, especially on older Unix
-derivates.  I<Disadvantage:> needs a temporary file on the filesystem and has
-to reopen filedescriptors to it in each(!) fork(2)ed child process.
-
-=item SysV IPC semget(2) (IPCSEM)
-
-I<Advantage:> exists on a lot of platforms and doesn't need a temporary file.
-I<Disadvantage:> an unmeant termination of the application leads to a
-semaphore leak because the facility doesn't allow an "remove in advance" trick
-(as the IPC shared memory facility does!) for safe cleanups.
-
-=item SVR4-style fcntl(2) on temporary file (FCNTL)
-
-I<Advantage:> exists on a lot of platforms and is also the most powerful
-variant (although not always the fastest one).  I<Disadvantage:> needs a
-temporary file.
-
-=back
-
-=head2 MEMORY ALLOCATION STRATEGY
-
-The memory allocation strategy the I<Standard Malloc-Style API> functions use
-internally is the following:
-
-=over 4
-
-=item B<Allocation>
-
-When a chunk of memory has to be allocated, the internal list of free chunks
-is searched for a minimal-sized chunk which is larger or equal than the size
-of the to be allocated chunk (some sort of a I<best fit algorithm>). 
-
-When a chunk is found which matches this best-fit criteria, but is still a lot
-larger than the requested size, it is split into two chunks: One with exactly
-the requested size (which is the resulting chunk) and one with the remaining
-size (which is immediately re-inserted into the list of free chunks). 
-
-When no fitting chunk is found at all in the list of free chunks, a new one is
-created from the spare area of the shared memory segment until the segment is
-full (in which case an I<out of memory> error occurs).
-
-=item B<Deallocation>
-
-When a chunk of memory has to be deallocated, it is inserted in sorted manner
-into the internal list of free chunks.  The insertion operation automatically
-merges the chunk with a previous and/or next free chunk when possible, i.e.
-the free chunks stay physically seamless (one after another) in memory, to
-automatically form larger free chunks out of smaller ones. 
-
-This way the shared memory segment is automatically defragmented when memory
-is deallocated.
-
-=back
-
-This strategy reduces memory waste and fragmentation caused by small and
-frequent allocations and deallocations to a minimum. 
-
-The internal implementation of the list of free chunks is not specially
-optimized (for instance by using binary search trees or even splay trees,
-etc.), because it's assumed that the total amount of entries in the list of
-free chunks is always small (caused both by the fact that shared memory
-segments are usually a lot smaller than heaps and the fact that we always
-defragment by merging the free chunks when possible).
-
-=head1 API FUNCTIONS
-
-In the following all API functions are described in detail.
-The order directly follows the one in the SYNOPSIS.
-
-=head2 Global Malloc-Replacement API
-
-=over 4
-
-=item int B<MM_create>(size_t I<size>, const char *I<file>);
-
-This initialized the global shared memory pool with I<size> and I<file> and
-has be called I<before> any fork(2) operations are performed by the
-application.
-
-=item int B<MM_permission>(mode_t I<mode>, uid_t I<owner>, gid_t I<group>);
-
-This sets the filesystem I<mode>, I<owner> and I<group> for the global shared
-memory pool (has effects only when the underlaying shared memory segment
-implementation is actually based on external auxiliary files).  The arguments
-are directly passed through to chmod(2) and chown(2).
-
-=item void B<MM_destroy>(void);
-
-This destroys the global shared memory pool and should be called I<after> all
-child processes were killed.
-
-=item int B<MM_lock>(mm_lock_mode I<mode>);
-
-This locks the global shared memory pool for the current process in order to
-perform either shared/read-only (I<mode> is C<MM_LOCK_RD>) or
-exclusive/read-write (I<mode> is C<MM_LOCK_RW>) operations inside the global
-shared memory pool.
-
-=item int B<MM_unlock>(void);
-
-This unlocks the global shared memory pool for the current process after
-mutual exclusion operations were performed inside the global shared memory
-pool.
-
-=item void *B<MM_malloc>(size_t I<size>);
-
-Identical to the POSIX.1 malloc(3) function but instead of allocating
-memory from the I<heap> it allocates it from the global shared memory pool.
-
-=item void B<MM_free>(void *I<ptr>);
-
-Identical to the POSIX.1 free(3) function but instead of deallocating
-memory in the I<heap> it deallocates it in the global shared memory pool.
-
-=item void *B<MM_realloc>(void *I<ptr>, size_t I<size>);
-
-Identical to the POSIX.1 realloc(3) function but instead of reallocating
-memory in the I<heap> it reallocates it inside the global shared memory pool.
-
-=item void *B<MM_calloc>(size_t I<number>, size_t I<size>);
-
-Identical to the POSIX.1 calloc(3) function but instead of allocating and
-initializing memory from the I<heap> it allocates and initializes it from the
-global shared memory pool.
-
-=item char *B<MM_strdup>(const char *I<str>);
-
-Identical to the POSIX.1 strdup(3) function but instead of creating the
-string copy in the I<heap> it creates it in the global shared memory pool.
-
-=item size_t B<MM_sizeof>(const void *I<ptr>);
-
-This function returns the size in bytes of the chunk starting at I<ptr> when
-I<ptr> was previously allocated with MM_malloc(3). The result is undefined
-when I<ptr> was not previously allocated with MM_malloc(3).
-
-=item size_t B<MM_maxsize>(void);
-
-This function returns the maximum size which is allowed
-as the first argument to the MM_create(3) function.
-
-=item size_t B<MM_available>(void);
-
-Returns the amount in bytes of still available (free) memory in the global
-shared memory pool.
-
-=item char *B<MM_error>(void);
-
-Returns the last error message which occurred inside the B<MM> library.
-
-=back
-
-=head2 Standard Malloc-Style API
-
-=over 4
-
-=item MM *B<mm_create>(size_t I<size>, const char *I<file>);
-
-This creates a shared memory pool which has space for approximately a total of
-I<size> bytes with the help of I<file>. Here I<file> is a filesystem path to a
-file which need not to exist (and perhaps is never created because this
-depends on the platform and chosen shared memory and mutex implementation).
-The return value is a pointer to an C<MM> structure which should be treated as
-opaque by the application. It describes the internals of the created shared
-memory pool. In case of an error C<NULL> is returned.  A I<size> of 0 means to
-allocate the maximum allowed size which is platform dependent and between a
-few KB and the soft limit of 64MB.
-
-=item int B<mm_permission>(MM *I<mm>, mode_t I<mode>, uid_t I<owner>, gid_t I<group>);
-
-This sets the filesystem I<mode>, I<owner> and I<group> for the shared memory
-pool I<mm> (has effects only when the underlaying shared memory segment
-implementation is actually based on external auxiliary files).  The arguments
-are directly passed through to chmod(2) and chown(2).
-
-=item void B<mm_destroy>(MM *I<mm>);
-
-This destroys the complete shared memory pool I<mm> and with it all chunks
-which were allocated in this pool. Additionally any created files on the
-filesystem corresponding the to shared memory pool are unlinked.
-
-=item int B<mm_lock>(MM *I<mm>, mm_lock_mode I<mode>);
-
-This locks the shared memory pool I<mm> for the current process in order to
-perform either shared/read-only (I<mode> is C<MM_LOCK_RD>) or
-exclusive/read-write (I<mode> is C<MM_LOCK_RW>) operations inside the global
-shared memory pool.
-
-=item int B<mm_unlock>(MM *I<mm>);
-
-This unlocks the shared memory pool I<mm> for the current process after mutual
-exclusion operations were performed inside the global shared memory pool.
-
-=item void *B<mm_malloc>(MM *I<mm>, size_t I<size>);
-
-This function allocates I<size> bytes from the shared memory pool I<mm> and
-returns either a (virtual memory word aligned) pointer to it or C<NULL> in
-case of an error (out of memory). It behaves like the POSIX.1 malloc(3)
-function but instead of allocating memory from the I<heap> it allocates it
-from the shared memory segment underlaying I<mm>.
-
-=item void B<mm_free>(MM *I<mm>, void *I<ptr>);
-
-This deallocates the chunk starting at I<ptr> in the shared memory pool I<mm>.
-It behaves like the POSIX.1 free(3) function but instead of deallocating
-memory from the I<heap> it deallocates it from the shared memory segment
-underlaying I<mm>.
-
-=item void *B<mm_realloc>(MM *I<mm>, void *I<ptr>, size_t I<size>);
-
-This function reallocates the chunk starting at I<ptr> inside the shared
-memory pool I<mm> with the new size of I<size> bytes.  It behaves like the
-POSIX.1 realloc(3) function but instead of reallocating memory in the
-I<heap> it reallocates it in the shared memory segment underlaying I<mm>.
-
-=item void *B<mm_calloc>(MM *I<mm>, size_t I<number>, size_t I<size>);
-
-This is similar to mm_malloc(3), but additionally clears the chunk. It behaves
-like the POSIX.1 calloc(3) function.  It allocates space for I<number>
-objects, each I<size> bytes in length from the shared memory pool I<mm>.  The
-result is identical to calling mm_malloc(3) with an argument of ``I<number> *
-I<size>'', with the exception that the allocated memory is initialized to nul
-bytes.
-
-=item char *B<mm_strdup>(MM *I<mm>, const char *I<str>);
-
-This function behaves like the POSIX.1 strdup(3) function.  It allocates
-sufficient memory inside the shared memory pool I<mm> for a copy of the string
-I<str>, does the copy, and returns a pointer to it.  The pointer may
-subsequently be used as an argument to the function mm_free(3). If
-insufficient shared memory is available, C<NULL> is returned.
-
-=item size_t B<mm_sizeof>(const void *I<ptr>);
-
-This function returns the size in bytes of the chunk starting at I<ptr> when
-I<ptr> was previously allocated with mm_malloc(3). The result is undefined
-when I<ptr> was not previously allocated with mm_malloc(3).
-
-=item size_t B<mm_maxsize>(void);
-
-This function returns the maximum size which is allowed as the first argument
-to the mm_create(3) function.
-
-=item size_t B<mm_available>(MM *I<mm>);
-
-Returns the amount in bytes of still available (free) memory in the 
-shared memory pool I<mm>.
-
-=item char *B<mm_error>(void);
-
-Returns the last error message which occurred inside the B<MM> library.
-
-=item void B<mm_display_info>(MM *I<mm>);
-
-This is debugging function which displays a summary page for the shared memory
-pool I<mm> describing various internal sizes and counters.
-
-=back
-
-=head2 Low-Level Shared Memory API
-
-=over 4
-
-=item void *B<mm_core_create>(size_t I<size>, const char *I<file>);
-
-This creates a shared memory area which is at least I<size> bytes in size with
-the help of I<file>. The value I<size> has to be greater than 0 and less or
-equal the value returned by mm_core_maxsegsize(3). Here I<file> is a
-filesystem path to a file which need not to exist (and perhaps is never
-created because this depends on the platform and chosen shared memory and
-mutex implementation).  The return value is either a (virtual memory word
-aligned) pointer to the shared memory segment or C<NULL> in case of an error.
-The application is guaranteed to be able to access the shared memory segment
-from byte 0 to byte I<size>-1 starting at the returned address.
-
-=item int B<mm_core_permission>(void *I<core>, mode_t I<mode>, uid_t I<owner>, gid_t I<group>);
-
-This sets the filesystem I<mode>, I<owner> and I<group> for the shared memory
-segment I<code> (has effects only when the underlaying shared memory segment
-implementation is actually based on external auxiliary files).  The arguments
-are directly passed through to chmod(2) and chown(2).
-
-=item void B<mm_core_delete>(void *I<core>);
-
-This deletes a shared memory segment I<core> (as previously returned by a
-mm_core_create(3) call). After this operation, accessing the segment starting
-at I<core> is no longer allowed and will usually lead to a segmentation fault.
-
-=item int B<mm_core_lock>(const void *I<core>, mm_lock_mode I<mode>);
-
-This function acquires an advisory lock for the current process on the shared
-memory segment I<core> for either shared/read-only (I<mode> is C<MM_LOCK_RD>)
-or exclusive/read-write (I<mode> is C<MM_LOCK_RW>) operations between
-fork(2)'ed child processes.
-
-=item int B<mm_core_unlock>(const void *I<core>);
-
-This function releases a previously acquired advisory lock for the current
-process on the shared memory segment I<core>.
-
-=item size_t B<mm_core_size>(const void *I<core>);
-
-This returns the size in bytes of I<core>. This size is exactly the size which
-was used for creating the shared memory area via mm_core_create(3). The
-function is provided just for convenience reasons to not require the
-application to remember the memory size behind I<core> itself. 
-
-=item size_t B<mm_core_maxsegsize>(void);
-
-This returns the number of bytes of a maximum-size shared memory segment which
-is allowed to allocate via the MM library. It is between a few KB and the soft
-limit of 64MB.
-
-=item size_t B<mm_core_align2page>(size_t I<size>);
-
-This is just a utility function which can be used to align the number I<size>
-to the next virtual memory I<page> boundary used by the underlaying platform.
-The memory page boundary under Unix platforms is usually somewhere between
-2048 and 16384 bytes. You don't have to align the I<size> arguments of other
-B<MM> library functions yourself, because this is already done internally.
-This function is exported by the B<MM> library just for convenience reasons in
-case an application wants to perform simular calculations for other purposes.
-
-=item size_t B<mm_core_align2word>(size_t I<size>);
-
-This is another utility function which can be used to align the number I<size>
-to the next virtual memory I<word> boundary used by the underlaying platform.
-The memory word boundary under Unix platforms is usually somewhere between 4
-and 16 bytes.  You don't have to align the I<size> arguments of other B<MM>
-library functions yourself, because this is already done internally.  This
-function is exported by the B<MM> library just for convenience reasons in case
-an application wants to perform simular calculations for other purposes.
-
-=back
-
-=head2 Low-Level Shared Memory API
-
-=over 4
-
-=item void B<mm_lib_error_set>(unsigned int, const char *str);
-
-This is a function which is used internally by the various MM function to set
-an error string. It's usually not called directly from applications.
-
-=item char *B<mm_lib_error_get>(void);
-
-This is a function which is used internally by MM_error(3) and mm_error(3)
-functions to get the current error string. It's usually not called directly
-from applications.
-
-=item int B<mm_lib_version>(void);
-
-This function returns a hex-value ``0xI<V>I<RR>I<T>I<LL>'' which describes the
-current MM library version. I<V> is the version, I<RR> the revisions, I<LL>
-the level and I<T> the type of the level (alphalevel=0, betalevel=1,
-patchlevel=2, etc). For instance MM version 1.0.4 is encoded as 0x100204.  The
-reason for this unusual mapping is that this way the version number is
-steadily I<increasing>.
-
-=back
-
-=head1 RESTRICTIONS
-
-The maximum size of a continuous shared memory segment one can allocate
-depends on the underlaying platform. This cannot be changed, of course.  But
-currently the high-level malloc(3)-style API just uses a single shared memory
-segment as the underlaying data structure for an C<MM> object which means that
-the maximum amount of memory a C<MM> object represents also depends on the
-platform. 
-
-This should be changed in later versions by allowing the high-level
-malloc(3)-style API to internally use multiple shared memory segments to form
-the C<MM> object. This way C<MM> objects could have arbitrary sizes, although
-the maximum size of an allocatable chunk still is bounded by the maximum size
-of a shared memory segment.
-
-=head1 SEE ALSO
-
-mm-config(1).
-
-malloc(3), calloc(3), realloc(3), strdup(3), free(3), mmap(2), shmget(2),
-shmctl(2), flock(2), fcntl(2), semget(2), semctl(2), semop(2).
-
-=head1 HOME
-
-=for html 
-<a href="http://www.engelschall.com/sw/mm/">http://www.engelschall.com/sw/mm/</a>
-
-=for text 
-http://www.engelschall.com/sw/mm/
-
-=for man 
-http://www.engelschall.com/sw/mm/
-
-=head1 HISTORY
-
-This library was originally written in January 1999 by I<Ralf S. Engelschall>
-<rse@engelschall.com> for use in the B<Extended API> (EAPI) of the B<Apache>
-HTTP server project (see www.apache.org), which was originally invented for
-B<mod_ssl> (see http://www.modssl.org/). 
-
-Its base idea (a malloc-style API for handling shared memory) was originally
-derived from the non-publically available I<mm_malloc> library written in
-October 1997 by I<Charles Randall> <crandall@matchlogic.com> for MatchLogic,
-Inc.
-
-=head1 AUTHOR
-
- Ralf S. Engelschall
- rse@engelschall.com
- www.engelschall.com
-
-=cut
-
diff --git a/shmem/unix/mm/mm_alloc.c b/shmem/unix/mm/mm_alloc.c
deleted file mode 100644
index 049a4ab20f2..00000000000
--- a/shmem/unix/mm/mm_alloc.c
+++ /dev/null
@@ -1,446 +0,0 @@
-/* ====================================================================
- * Copyright (c) 1999 Ralf S. Engelschall. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- *    software must display the following acknowledgment:
- *    "This product includes software developed by
- *     Ralf S. Engelschall <rse@engelschall.com>."
- *
- * 4. Redistributions of any form whatsoever must retain the following
- *    acknowledgment:
- *    "This product includes software developed by
- *     Ralf S. Engelschall <rse@engelschall.com>."
- *
- * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL RALF S. ENGELSCHALL OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- */
-
-/*
-**
-**  mm_alloc.c -- Standard Malloc-Style API
-**
-*/
-
-#define MM_PRIVATE
-#include "mm.h"
-
-/*
- * Create a memory pool
- */
-MM *mm_create(size_t usize, const char *file)
-{
-    MM *mm = NULL;
-    void *core;
-    size_t size;
-    size_t maxsize;
-
-    /* defaults */
-    maxsize = mm_maxsize();
-    if (usize < 0) {
-        errno = EINVAL;
-        return NULL;
-    }
-    if (usize == 0)
-        usize = maxsize;
-    if (usize > maxsize)
-        usize = maxsize;
-    if (usize < MM_ALLOC_MINSIZE)
-        usize = MM_ALLOC_MINSIZE;
-
-    /* determine size */
-    size = usize+SIZEOF_mem_pool;
-
-    /* get a shared memory area */
-    if ((core = mm_core_create(size, file)) == NULL)
-        return NULL;
-
-    /* fill in the memory pool structure */
-    mm = (MM *)core;
-    mm->mp_size    = size;
-    mm->mp_offset  = SIZEOF_mem_pool;
-
-    /* first element of list of free chunks counts existing chunks */
-    mm->mp_freechunks.mc_size      = 0;
-    mm->mp_freechunks.mc_usize     = 0;
-    mm->mp_freechunks.mc_u.mc_next = NULL;
-
-    return mm;
-}
-
-/*
- * Set permissions on memory pools underlaying disk files
- */
-int mm_permission(MM *mm, mode_t mode, uid_t owner, gid_t group)
-{
-    if (mm == NULL)
-        return -1;
-    return mm_core_permission((void *)mm, mode, owner, group);
-}
-
-/*
- * Destroy a memory pool
- */
-void mm_destroy(MM *mm)
-{
-    if (mm == NULL)
-        return;
-    /* wipe out the whole area to be safe */
-    memset(mm, 0, mm->mp_size);
-    /* and delete the core area */
-    (void)mm_core_delete((void *)mm);
-    return;
-}
-
-/*
- * Lock a memory pool 
- */
-int mm_lock(MM *mm, mm_lock_mode mode)
-{
-    if (mm == NULL)
-        return FALSE;
-    return mm_core_lock((void *)mm, mode);
-}
-
-/*
- * Unlock a memory pool 
- */
-int mm_unlock(MM *mm)
-{
-    if (mm == NULL)
-        return FALSE;
-    return mm_core_unlock((void *)mm);
-}
-
-/*
- * Display debugging information
- */
-void mm_display_info(MM *mm)
-{
-    mem_chunk *mc;
-    int nFree;
-    int nAlloc;
-    int i;
-
-    if (!mm_core_lock((void *)mm, MM_LOCK_RD))
-        return;
-    mc = &(mm->mp_freechunks);
-    nFree   = 0;
-    while (mc->mc_u.mc_next != NULL) {
-        mc = mc->mc_u.mc_next;
-        nFree += mc->mc_size;
-    }
-    nAlloc = mm->mp_offset-SIZEOF_mem_pool-nFree;
-
-    fprintf(stderr, "Information for MM\n");
-    fprintf(stderr, "    memory area     = 0x%lx - 0x%lx\n", (unsigned long)mm, (unsigned long)(mm+mm->mp_size));
-    fprintf(stderr, "    memory size     = %d\n", mm->mp_size);
-    fprintf(stderr, "    memory offset   = %d\n", mm->mp_offset);
-    fprintf(stderr, "    bytes spare     = %d\n", mm->mp_size-mm->mp_offset);
-    fprintf(stderr, "    bytes free      = %d (%d chunk%s)\n", 
-            nFree, mm->mp_freechunks.mc_usize,
-            mm->mp_freechunks.mc_usize == 1 ? "" : "s");
-    fprintf(stderr, "    bytes allocated = %d\n", nAlloc);
-
-    fprintf(stderr, "    List of free chunks:\n");
-    if (mm->mp_freechunks.mc_usize > 0) {
-        mc = &(mm->mp_freechunks);
-        i = 1;
-        while (mc->mc_u.mc_next != NULL) {
-            mc = mc->mc_u.mc_next;
-            fprintf(stderr, "        chunk #%03d: 0x%lx-0x%lx (%d bytes)\n", 
-                    i++, (unsigned long)mc, (unsigned long)(mc+mc->mc_size), mc->mc_size);
-        }
-    }
-    else {
-        fprintf(stderr, "        <empty-list>\n");
-    }
-    mm_core_unlock((void *)mm);
-    return;
-}
-
-/*
- * Insert a chunk to the list of free chunks. Algorithm used is:
- * Insert in sorted manner to the list and merge with previous
- * and/or next chunk when possible to form larger chunks out of
- * smaller ones.
- */
-static void mm_insert_chunk(MM *mm, mem_chunk *mcInsert)
-{
-    mem_chunk *mc;
-    mem_chunk *mcPrev;
-    mem_chunk *mcNext;
-    
-    if (!mm_core_lock((void *)mm, MM_LOCK_RW))
-        return;
-    mc = &(mm->mp_freechunks);
-    while (mc->mc_u.mc_next != NULL && (char *)(mc->mc_u.mc_next) < (char *)mcInsert)
-        mc = mc->mc_u.mc_next;
-    mcPrev = mc;
-    mcNext = mc->mc_u.mc_next;
-    if ((char *)mcPrev+mcPrev->mc_size == (char *)mcInsert &&
-             (mcNext != NULL && (char *)mcInsert+mcInsert->mc_size == (char *)mcNext)) {
-        /* merge with previous and next chunk */
-        mcPrev->mc_size += mcInsert->mc_size + mcNext->mc_size;
-        mcPrev->mc_u.mc_next = mcNext->mc_u.mc_next;
-        mm->mp_freechunks.mc_usize -= 1;
-    }
-    else if ((char *)mcPrev+mcPrev->mc_size == (char *)mcInsert) {
-        /* merge with previous chunk */
-        mcPrev->mc_size += mcInsert->mc_size;
-    }
-    else if (mcNext != NULL && (char *)mcInsert+mcInsert->mc_size == (char *)mcNext) {
-        /* merge with next chunk */
-        mcInsert->mc_size += mcNext->mc_size;
-        mcInsert->mc_u.mc_next = mcNext->mc_u.mc_next;
-        mcPrev->mc_u.mc_next = mcInsert;
-    }
-    else {
-        /* no merging possible, so insert as new chunk */
-        mcInsert->mc_u.mc_next = mcNext;
-        mcPrev->mc_u.mc_next = mcInsert;
-        mm->mp_freechunks.mc_usize += 1;
-    }
-    mm_core_unlock((void *)mm);
-    return;
-}
-
-/*
- * Retrieve a chunk from the list of free chunks.  Algorithm used
- * is: Search for minimal-sized chunk which is larger or equal
- * than the request size. But when the retrieved chunk is still a
- * lot larger than the requested size, split out the requested
- * size to not waste memory.
- */
-static mem_chunk *mm_retrieve_chunk(MM *mm, size_t size)
-{
-    mem_chunk *mc;
-    mem_chunk **pmcMin;
-    mem_chunk *mcRes;
-    size_t sMin;
-    size_t s;
-
-    if (mm->mp_freechunks.mc_usize == 0)
-        return NULL;
-    if (!mm_core_lock((void *)mm, MM_LOCK_RW))
-        return NULL;
-    /* find best-fitting chunk */
-    pmcMin = NULL;
-    sMin = mm->mp_size; /* maximum possible */
-    mc = &(mm->mp_freechunks);
-    while (mc->mc_u.mc_next != NULL) {
-        s = mc->mc_u.mc_next->mc_size;
-        if (s >= size && s < sMin) {
-            pmcMin = &(mc->mc_u.mc_next);
-            sMin = s;
-            if (s == size)
-                break;
-        }
-        mc = mc->mc_u.mc_next;
-    }
-    /* create result chunk */
-    if (pmcMin == NULL)
-        mcRes = NULL;
-    else {
-        mcRes = *pmcMin;
-        if (mcRes->mc_size >= (size + min_of(2*size,128))) {
-            /* split out in part */
-            s = mcRes->mc_size - size;
-            mcRes->mc_size = size;
-            /* add back remaining chunk part as new chunk */
-            mc = (mem_chunk *)((char *)mcRes + size);
-            mc->mc_size = s;
-            mc->mc_u.mc_next = mcRes->mc_u.mc_next;
-            *pmcMin = mc;
-        }
-        else {
-            /* split out as a whole */
-            *pmcMin = mcRes->mc_u.mc_next;
-            mm->mp_freechunks.mc_usize--;
-        }
-    }
-    mm_core_unlock((void *)mm);
-    return mcRes;
-}
-
-/*
- * Allocate a chunk of memory
- */
-void *mm_malloc(MM *mm, size_t usize)
-{
-    mem_chunk *mc;
-    size_t size;
-    void *vp;
-
-    if (mm == NULL || usize == 0)
-        return NULL;
-    size = mm_core_align2word(SIZEOF_mem_chunk+usize);
-    if ((mc = mm_retrieve_chunk(mm, size)) != NULL) {
-        mc->mc_usize = usize;
-        return &(mc->mc_u.mc_base.mw_cp);
-    }
-    if (!mm_core_lock((void *)mm, MM_LOCK_RW))
-        return NULL;
-    if ((mm->mp_size - mm->mp_offset) < size) {
-        mm_core_unlock((void *)mm);
-        ERR(MM_ERR_ALLOC, "Out of memory");
-        errno = ENOMEM;
-        return NULL; 
-    }
-    mc = (mem_chunk *)((char *)mm + mm->mp_offset);
-    mc->mc_size  = size;
-    mc->mc_usize = usize;
-    vp = (void *)&(mc->mc_u.mc_base.mw_cp);
-    mm->mp_offset += size;
-    mm_core_unlock((void *)mm);
-    return vp;
-}
-
-/*
- * Reallocate a chunk of memory
- */
-void *mm_realloc(MM *mm, void *ptr, size_t usize)
-{
-    size_t size;
-    mem_chunk *mc;
-    void *vp;
-
-    if (mm == NULL || usize == 0)
-        return NULL;
-    if (ptr == NULL)
-        return mm_malloc(mm, usize); /* POSIX.1 semantics */
-    mc = (mem_chunk *)((char *)ptr - SIZEOF_mem_chunk);
-    if (usize <= mc->mc_usize) {
-        mc->mc_usize = usize;
-        return ptr;
-    }
-    size = mm_core_align2word(SIZEOF_mem_chunk+usize);
-    if (size <= mc->mc_size) {
-        mc->mc_usize = usize;
-        return ptr;
-    }
-    if ((vp = mm_malloc(mm, usize)) == NULL)
-        return NULL;
-    memcpy(vp, ptr, usize);
-    mm_free(mm, ptr);
-    return vp;
-}
-
-/*
- * Free a chunk of memory
- */
-void mm_free(MM *mm, void *ptr)
-{
-    mem_chunk *mc;
-
-    if (mm == NULL || ptr == NULL)
-        return;
-    mc = (mem_chunk *)((char *)ptr - SIZEOF_mem_chunk);
-    mm_insert_chunk(mm, mc);
-    return;
-}
-
-/*
- * Allocate and initialize a chunk of memory
- */
-void *mm_calloc(MM *mm, size_t number, size_t usize)
-{
-    void *vp;
-
-    if (mm == NULL || number*usize == 0)
-        return NULL;
-    if ((vp = mm_malloc(mm, number*usize)) == NULL)
-        return NULL;
-    memset(vp, 0, number*usize);
-    return vp;
-}
-
-/*
- * Duplicate a string
- */
-char *mm_strdup(MM *mm, const char *str)
-{
-    int n;
-    void *vp;
-
-    if (mm == NULL || str == NULL)
-        return NULL;
-    n = strlen(str);
-    if ((vp = mm_malloc(mm, n+1)) == NULL)
-        return NULL;
-    memcpy(vp, str, n+1);
-    return vp;
-}
-
-/*
- * Determine user size of a memory chunk
- */
-size_t mm_sizeof(MM *mm, const void *ptr)
-{
-    mem_chunk *mc;
-
-    if (mm == NULL || ptr == NULL)
-        return -1;
-    mc = (mem_chunk *)((char *)ptr - SIZEOF_mem_chunk);
-    return mc->mc_usize;
-}
-
-/*
- * Determine maximum size of an allocateable memory pool
- */
-size_t mm_maxsize(void)
-{
-    return (mm_core_maxsegsize()-SIZEOF_mem_pool);
-}
-
-/*
- * Determine available memory
- */
-size_t mm_available(MM *mm)
-{
-    mem_chunk *mc;
-    int nFree;
-
-    if (!mm_core_lock((void *)mm, MM_LOCK_RD))
-        return 0;
-    nFree = mm->mp_size-mm->mp_offset;
-    mc = &(mm->mp_freechunks);
-    while (mc->mc_u.mc_next != NULL) {
-        mc = mc->mc_u.mc_next;
-        nFree += mc->mc_size;
-    }
-    mm_core_unlock((void *)mm);
-    return nFree;
-}
-
-/*
- * Return last error string
- */
-char *mm_error(void)
-{
-    return mm_lib_error_get();
-}
-
-/*EOF*/
diff --git a/shmem/unix/mm/mm_conf.h.in b/shmem/unix/mm/mm_conf.h.in
deleted file mode 100644
index 5d6be09f06e..00000000000
--- a/shmem/unix/mm/mm_conf.h.in
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
-**  mm_conf.h
-*/
-
-#ifndef MM_CONF_HH
-#define MM_CONF_HH
-
-/* VM Page Size Determination */
-#undef MM_VMPS_GETPAGESIZE
-#undef MM_VMPS_SYSCONF
-#undef MM_VMPS_BEOS
-
-/* Shared Memory Type */
-#undef MM_SHMT_MMANON
-#undef MM_SHMT_MMPOSX
-#undef MM_SHMT_MMZERO
-#undef MM_SHMT_MMFILE
-#undef MM_SHMT_IPCSHM
-#undef MM_SHMT_BEOS
-
-/* Shared Memory Maximum Segment Size */
-#define MM_SHM_MAXSEGSIZE @MM_SHM_MAXSEGSIZE@
-
-/* Semaphore Type */
-#undef MM_SEMT_FLOCK
-#undef MM_SEMT_FCNTL
-#undef MM_SEMT_IPCSEM
-#undef MM_SEMT_BEOS
-
-/* Debugging */
-#undef MM_DEBUG
-
-/* Standard Autoconf stuff */
-#undef HAVE_MEMCPY
-#undef HAVE_MEMSET
-#undef HAVE_BCOPY
-#undef HAVE_MEMORY_H
-#undef MM_OS_SUNOS
-#undef HAVE_PATH_MAX
-#undef HAVE__POSIX_PATH_MAX
-#undef HAVE_MAXPATHLEN
-#undef HAVE_UNION_SEMUN
-
-#endif /* MM_CONF_HH */
diff --git a/shmem/unix/mm/mm_core.c b/shmem/unix/mm/mm_core.c
deleted file mode 100644
index 37d938ea0b1..00000000000
--- a/shmem/unix/mm/mm_core.c
+++ /dev/null
@@ -1,626 +0,0 @@
-/* ====================================================================
- * Copyright (c) 1999 Ralf S. Engelschall. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- *    software must display the following acknowledgment:
- *    "This product includes software developed by
- *     Ralf S. Engelschall <rse@engelschall.com>."
- *
- * 4. Redistributions of any form whatsoever must retain the following
- *    acknowledgment:
- *    "This product includes software developed by
- *     Ralf S. Engelschall <rse@engelschall.com>."
- *
- * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL RALF S. ENGELSCHALL OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- */
-
-/*
-**
-**  mm_core.c -- Low-level Shared Memory API
-**
-*/
-
-#define MM_PRIVATE
-#include "mm.h"
-
-/*
- * Some global variables
- */
-
-#if defined(MM_SEMT_FCNTL)
-/* lock/unlock structures for fcntl() */
-static struct flock mm_core_dolock_rd;
-static struct flock mm_core_dolock_rw;
-static struct flock mm_core_dounlock;
-#endif
-
-#if defined(MM_SEMT_IPCSEM)
-/* lock/unlock structures for semop() */
-static union  semun  mm_core_semctlarg;
-static struct sembuf mm_core_dolock[2];
-static struct sembuf mm_core_dounlock[1];
-#endif
-
-#if defined(MM_SHMT_MMFILE) || defined(MM_SHMT_MMPOSX)
-static size_t mm_core_mapoffset = 0;           /* we use own file */
-#elif defined(MM_SHMT_MMZERO)
-static size_t mm_core_mapoffset = 1024*1024*1; /* we share with other apps */
-#endif
-
-static void mm_core_init(void)
-{
-    static int initialized = FALSE;
-    if (!initialized) {
-#if defined(MM_SEMT_FCNTL)
-        mm_core_dolock_rd.l_whence   = SEEK_SET; /* from current point */
-        mm_core_dolock_rd.l_start    = 0;        /* -"- */
-        mm_core_dolock_rd.l_len      = 0;        /* until end of file */
-        mm_core_dolock_rd.l_type     = F_RDLCK;  /* set shard/read lock */
-        mm_core_dolock_rd.l_pid      = 0;        /* pid not actually interesting */
-        mm_core_dolock_rw.l_whence   = SEEK_SET; /* from current point */
-        mm_core_dolock_rw.l_start    = 0;        /* -"- */
-        mm_core_dolock_rw.l_len      = 0;        /* until end of file */
-        mm_core_dolock_rw.l_type     = F_WRLCK;  /* set exclusive/read-write lock */
-        mm_core_dolock_rw.l_pid      = 0;        /* pid not actually interesting */
-        mm_core_dounlock.l_whence    = SEEK_SET; /* from current point */
-        mm_core_dounlock.l_start     = 0;        /* -"- */
-        mm_core_dounlock.l_len       = 0;        /* until end of file */
-        mm_core_dounlock.l_type      = F_UNLCK;  /* unlock */
-        mm_core_dounlock.l_pid       = 0;        /* pid not actually interesting */
-#endif
-#if defined(MM_SEMT_IPCSEM)
-        mm_core_dolock[0].sem_num   = 0;
-        mm_core_dolock[0].sem_op    = 0;
-        mm_core_dolock[0].sem_flg   = 0;
-        mm_core_dolock[1].sem_num   = 0;
-        mm_core_dolock[1].sem_op    = 1;
-        mm_core_dolock[1].sem_flg   = SEM_UNDO;
-        mm_core_dounlock[0].sem_num = 0;
-        mm_core_dounlock[0].sem_op  = -1;
-        mm_core_dounlock[0].sem_flg = SEM_UNDO;
-#endif
-        initialized = TRUE;
-    }
-    return;
-}
-
-#if defined(MM_SEMT_FLOCK)
-/*
- * Determine per-process fd for semaphore
- * (needed only for flock() based semaphore)
- */
-static int mm_core_getfdsem(mem_core *mc)
-{
-    int fd = -1;
-    pid_t pid;
-    int i;
-    
-    pid = getpid();
-    for (i = 0; i < MM_MAXCHILD && 
-                mc->mc_fdsem[i].pid != 0 && 
-                mc->mc_fdsem[i].fd != -1; i++) {
-        if (mc->mc_fdsem[i].pid == pid) {
-            fd = mc->mc_fdsem[i].fd;
-            break;
-        }
-    }
-    if (fd == -1 && i < MM_MAXCHILD) {
-        fd = open(mc->mc_fnsem, O_WRONLY, MM_CORE_FILEMODE);
-        mc->mc_fdsem[i].pid = getpid();
-        mc->mc_fdsem[i].fd  = fd;
-    }
-    return fd;
-}
-#endif /* MM_SEMT_FLOCK */
-
-/*
- * Determine memory page size of OS
- */
-
-static size_t mm_core_pagesize(void)
-{
-    static int pagesize = 0;
-    if (pagesize == 0)
-#if defined(MM_VMPS_GETPAGESIZE)
-        pagesize = getpagesize();
-#elif defined(MM_VMPS_SYSCONF)
-        pagesize = sysconf(_SC_PAGESIZE);
-#elif defined(MM_VMPS_BEOS)
-        pagesize = B_PAGE_SIZE;
-#else
-        pagesize = MM_CORE_DEFAULT_PAGESIZE;
-#endif
-    return pagesize;
-}
-
-/*
- * Align a size to the next page or word boundary
- */
-
-size_t mm_core_align2page(size_t size)
-{
-    int psize = mm_core_pagesize();
-    return ((size)%(psize) > 0 ? ((size)/(psize)+1)*(psize) : (size));
-}
-
-size_t mm_core_align2word(size_t size)
-{
-    return ((1+((size-1) / SIZEOF_mem_word)) * SIZEOF_mem_word);
-}
-
-size_t mm_core_maxsegsize(void)
-{
-    return mm_core_align2page((MM_SHM_MAXSEGSIZE-SIZEOF_mem_core)-mm_core_pagesize());
-}
-
-/*
- * Create a shared memory area
- */
-
-void *mm_core_create(size_t usersize, const char *file)
-{
-    mem_core *mc;
-    void *area = ((void *)-1);
-    int fdmem = 0;
-    int fdsem = 0;
-#if defined(MM_SEMT_IPCSEM)
-    int fdsem_rd = 0;
-#endif
-#if defined(MM_SHMT_MMPOSX) || defined(MM_SHMT_MMFILE)
-    char *fnmem;
-#endif
-#if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL)
-    char *fnsem;
-#endif
-    size_t size;
-#if defined(MM_SHMT_MMZERO) || defined(MM_SHMT_MMPOSX) || defined(MM_SHMT_MMFILE)
-    int zero = 0;
-#endif
-#if defined(MM_SHMT_IPCSHM)
-    struct shmid_ds shmbuf;
-#endif
-#if defined(MM_SHMT_MMPOSX) || defined(MM_SHMT_MMFILE)
-    char shmfilename[MM_MAXPATH];
-#endif
-#if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL)
-    char semfilename[MM_MAXPATH];
-#endif
-#if defined(MM_SHMT_BEOS)
-    area_id temparea;
-#endif
-    char filename[MM_MAXPATH];
-
-    if (usersize <= 0 || usersize > mm_core_maxsegsize()) {
-        errno = EINVAL;
-        return NULL;
-    }
-    if (file == NULL) {
-        sprintf(filename, MM_CORE_DEFAULT_FILE, (int)getpid());
-        file = filename;
-    }
-
-    mm_core_init();
-    size = mm_core_align2page(usersize+SIZEOF_mem_core);
-
-#if defined(MM_SHMT_MMPOSX) || defined(MM_SHMT_MMFILE)
-    sprintf(shmfilename, "%s.mem", file);
-    fnmem = shmfilename;
-#endif
-#if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL)
-    sprintf(semfilename, "%s.sem", file);
-    fnsem = semfilename;
-#endif
-
-#if defined(MM_SHMT_MMANON)
-    if ((area = (void *)mmap(NULL, size, PROT_READ|PROT_WRITE, 
-                             MAP_ANON|MAP_SHARED, -1, 0)) == (void *)MAP_FAILED)
-        FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to memory map anonymous area");
-#endif /* MM_SHMT_MMANON */
-
-#if defined(MM_SHMT_BEOS)
-    if ((temparea = create_area("mm",(void*)&area, B_ANY_ADDRESS,
-                        size, B_LAZY_LOCK, B_READ_AREA | B_WRITE_AREA)) < 0)
-        FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to create the memory area");
-#endif /* MM_SHMT_BEOS */
-#if defined(MM_SHMT_MMPOSX)
-    shm_unlink(fnmem); /* Ok when it fails */
-    if ((fdmem = shm_open(fnmem, O_RDWR|O_CREAT, MM_CORE_FILEMODE)) == -1)
-        FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to open tempfile");
-    if (ftruncate(fdmem, mm_core_mapoffset+size) == -1)
-        FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to truncate tempfile");
-    write(fdmem, &zero, sizeof(zero));
-    if ((area = (void *)mmap(NULL, size, PROT_READ|PROT_WRITE, 
-                             MAP_SHARED, fdmem, mm_core_mapoffset)) == (void *)MAP_FAILED)
-        FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to memory map tempfile");
-    shm_unlink(fnmem);
-    mm_core_mapoffset += size;
-#endif /* MM_SHMT_MMPOSX */
-
-#if defined(MM_SHMT_MMZERO)
-    if ((fdmem = open("/dev/zero", O_RDWR, MM_CORE_FILEMODE)) == -1)
-        FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to open /dev/zero");
-    if (lseek(fdmem, mm_core_mapoffset+size, SEEK_SET) == -1)
-        FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to seek in /dev/zero");
-    write(fdmem, &zero, sizeof(zero));
-    if ((area = (void *)mmap(NULL, size, PROT_READ|PROT_WRITE, 
-                             MAP_SHARED, fdmem, mm_core_mapoffset)) == (void *)MAP_FAILED)
-        FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to memory map /dev/zero");
-    mm_core_mapoffset += size;
-#endif /* MM_SHMT_MMZERO */
-
-#if defined(MM_SHMT_MMFILE)
-    unlink(fnmem);
-    if ((fdmem = open(fnmem, O_RDWR|O_CREAT, MM_CORE_FILEMODE)) == -1)
-        FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to open memory file");
-    if (ftruncate(fdmem, mm_core_mapoffset+size) == -1)
-        FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to truncate memory file");
-    write(fdmem, &zero, sizeof(zero));
-    if ((area = (void *)mmap(NULL, size, PROT_READ|PROT_WRITE, 
-                             MAP_SHARED, fdmem, mm_core_mapoffset)) == (void *)MAP_FAILED)
-        FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to memory map memory file");
-    mm_core_mapoffset += size;
-#endif /* MM_SHMT_MMFILE */
-
-#if defined(MM_SHMT_IPCSHM)
-    if ((fdmem = shmget(IPC_PRIVATE, size, (SHM_R|SHM_W|IPC_CREAT))) == -1)
-        FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to acquire shared memory segment");
-    if ((area = (void *)shmat(fdmem, NULL, 0)) == ((void *)-1))
-        FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to attach shared memory");
-    if (shmctl(fdmem, IPC_STAT, &shmbuf) == -1)
-        FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to get status of shared memory");
-    shmbuf.shm_perm.uid = getuid();
-    shmbuf.shm_perm.gid = getgid();
-    if (shmctl(fdmem, IPC_SET, &shmbuf) == -1)
-        FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to set status of shared memory");
-    if (shmctl(fdmem, IPC_RMID, NULL) == -1)
-        FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to remove shared memory in advance");
-#endif /* MM_SHMT_IPCSHM */
-
-#if defined(MM_SEMT_FLOCK)
-    unlink(fnsem);
-    if ((fdsem = open(fnsem, O_RDWR|O_CREAT, MM_CORE_FILEMODE)) == -1)
-        FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to open semaphore file");
-#endif /* MM_SEMT_FLOCK */
-
-#if defined(MM_SEMT_FCNTL)
-    unlink(fnsem);
-    if ((fdsem = open(fnsem, O_RDWR|O_CREAT, MM_CORE_FILEMODE)) == -1)
-        FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to open semaphore file");
-#endif /* MM_SEMT_FCNTL */
-
-#if defined(MM_SEMT_IPCSEM)
-    fdsem = semget(IPC_PRIVATE, 1, IPC_CREAT|IPC_EXCL|S_IRUSR|S_IWUSR);
-    if (fdsem == -1 && errno == EEXIST)
-        fdsem = semget(IPC_PRIVATE, 1, IPC_EXCL|S_IRUSR|S_IWUSR);
-        if (fdsem == -1)
-            FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to acquire semaphore");
-    mm_core_semctlarg.val = 0;
-    semctl(fdsem, 0, SETVAL, mm_core_semctlarg);
-    fdsem_rd = semget(IPC_PRIVATE, 1, IPC_CREAT|IPC_EXCL|S_IRUSR|S_IWUSR);
-    if (fdsem_rd == -1 && errno == EEXIST)
-        fdsem_rd = semget(IPC_PRIVATE, 1, IPC_EXCL|S_IRUSR|S_IWUSR);
-        if (fdsem_rd == -1)
-            FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to acquire semaphore");
-    mm_core_semctlarg.val = 0;
-    semctl(fdsem_rd, 0, SETVAL, mm_core_semctlarg);
-#endif /* MM_SEMT_IPCSEM */
-
-    /*
-     * Configure the memory core parameters
-     */
-    mc = (mem_core *)area;
-    mc->mc_size     = size;
-    mc->mc_usize    = usersize;
-    mc->mc_pid      = getpid();
-    mc->mc_fdmem    = fdmem;
-#if defined(MM_SEMT_FLOCK)
-    mc->mc_fdsem[0].pid = getpid();
-    mc->mc_fdsem[0].fd  = fdsem;
-    mc->mc_fdsem[1].pid = 0;
-    mc->mc_fdsem[1].fd  = -1;
-#else
-    mc->mc_fdsem    = fdsem;
-#endif
-#if defined(MM_SEMT_BEOS)
-    mc->mc_semid = create_sem(0, "mm_semid");
-    mc->mc_ben=0;
-#endif
-#if defined(MM_SHMT_BEOS)
-    mc->mc_areaid = temparea;
-#endif
-#if defined(MM_SEMT_IPCSEM)
-    mc->mc_fdsem_rd = fdsem_rd;
-    mc->mc_readers  = 0;
-#endif
-#if defined(MM_SHMT_MMFILE)
-    memcpy(mc->mc_fnmem, fnmem, MM_MAXPATH);
-#endif
-#if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL)
-    memcpy(mc->mc_fnsem, fnsem, MM_MAXPATH);
-#endif
-
-    /*
-     * Return successfully established core
-     */
-    return ((void *)&(mc->mc_base.mw_cp));
-
-    /*
-     * clean-up sequence (CUS) for error situation
-     */
-    BEGIN_FAILURE
-#if defined(MM_SHMT_MMANON) || defined(MM_SHMT_MMZERO) || defined(MM_SHMT_MMPOSX) || defined(MM_SHMT_MMFILE)
-    if (area != ((void *)-1))
-        munmap((caddr_t)area, size);
-#endif
-#if defined(MM_SHMT_IPCSHM)
-    if (area != ((void *)-1))
-        shmdt(area);
-#endif
-#if defined(MM_SHMT_MMPOSX) || defined(MM_SHMT_MMFILE)
-    if (fdmem != -1)
-        close(fdmem);
-#endif
-#if defined(MM_SHMT_IPCSHM)
-    if (fdmem != -1)
-        shmctl(fdmem, IPC_RMID, NULL);
-#endif
-#if defined(MM_SHMT_BEOS)
-    delete_area(mc->mc_areaid);
-#endif
-#if defined(MM_SEMT_BEOS)
-    delete_sem(mc->mc_semid);
-#endif
-
-#if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL)
-    if (fdsem != -1)
-        close(fdsem);
-#endif
-#if defined(MM_SEMT_IPCSEM)
-    if (fdsem != -1)
-        semctl(fdsem, 0, IPC_RMID, 0);
-    if (fdsem_rd != -1)
-        semctl(fdsem_rd, 0, IPC_RMID, 0);
-#endif
-#if defined(MM_SHMT_MMFILE)
-    unlink(fnmem);
-#endif
-#if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL)
-    unlink(fnsem);
-#endif
-    return NULL;
-    END_FAILURE
-}
-
-int mm_core_permission(void *core, mode_t mode, uid_t owner, gid_t group)
-{
-    int rc;
-    mem_core *mc;
-
-    if (core == NULL)
-        return -1;
-    mc = (mem_core *)((char *)core-SIZEOF_mem_core);
-    rc = 0;
-#if defined(MM_SHMT_MMFILE)
-    if (rc == 0 && chmod(mc->mc_fnmem, mode) < 0)
-        rc = -1;
-    if (rc == 0 && chown(mc->mc_fnmem, owner, group) < 0)
-        rc = -1;
-#endif
-#if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL)
-    if (rc == 0 && chmod(mc->mc_fnsem, mode) < 0)
-        rc = -1;
-    if (rc == 0 && chown(mc->mc_fnsem, owner, group) < 0)
-        rc = -1;
-#endif
-    return rc;
-}
-
-void mm_core_delete(void *core)
-{
-    mem_core *mc;
-    int fdmem;
-    int fdsem;
-#if defined(MM_SEMT_IPCSEM)
-    int fdsem_rd;
-#endif
-    size_t size;
-#if defined(MM_SHMT_MMFILE)
-    char fnmem[MM_MAXPATH];
-#endif
-#if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL)
-    char fnsem[MM_MAXPATH];
-#endif
-
-    if (core == NULL)
-        return;
-    mc = (mem_core *)((char *)core-SIZEOF_mem_core);
-    size  = mc->mc_size;
-    fdmem = mc->mc_fdmem;
-#if !defined(MM_SEMT_FLOCK)
-    fdsem = mc->mc_fdsem;
-#endif
-#if defined(MM_SEMT_IPCSEM)
-    fdsem_rd = mc->mc_fdsem_rd;
-#endif
-#if defined(MM_SEMT_FLOCK)
-    fdsem = mm_core_getfdsem(mc);
-#endif
-#if defined(MM_SHMT_MMFILE)
-    memcpy(fnmem, mc->mc_fnmem, MM_MAXPATH);
-#endif
-#if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL)
-    memcpy(fnsem, mc->mc_fnsem, MM_MAXPATH);
-#endif
-
-#if defined(MM_SHMT_MMANON) || defined(MM_SHMT_MMPOSX) || defined(MM_SHMT_MMZERO) || defined(MM_SHMT_MMFILE)
-    munmap((caddr_t)mc, size);
-#endif
-#if defined(MM_SHMT_IPCSHM)
-    shmdt((void *)mc);
-    shmctl(fdmem, IPC_RMID, NULL);
-#endif
-#if defined(MM_SHMT_MMPOSX) || defined(MM_SHMT_MMZERO) || defined(MM_SHMT_MMFILE)
-    close(fdmem);
-#endif
-#if defined(MM_SHMT_MMFILE)
-    unlink(fnmem);
-#endif
-#if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL)
-    close(fdsem);
-#endif
-#if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL)
-    unlink(fnsem);
-#endif
-#if defined(MM_SEMT_IPCSEM)
-    semctl(fdsem, 0, IPC_RMID, 0);
-    semctl(fdsem_rd, 0, IPC_RMID, 0);
-#endif
-    return;
-}
-
-size_t mm_core_size(const void *core)
-{
-    mem_core *mc;
-
-    if (core == NULL)
-        return 0;
-    mc = (mem_core *)((char *)core-SIZEOF_mem_core);
-    return (mc->mc_usize);
-}
-
-int mm_core_lock(const void *core, mm_lock_mode mode)
-{
-    mem_core *mc;
-    int rc;
-    int fdsem;
-
-    if (core == NULL)
-        return FALSE;
-    mc = (mem_core *)((char *)core-SIZEOF_mem_core);
-#if !defined(MM_SEMT_FLOCK)
-    fdsem = mc->mc_fdsem;
-#endif
-#if defined(MM_SEMT_FLOCK)
-    fdsem = mm_core_getfdsem(mc);
-#endif
-
-#if defined(MM_SEMT_FCNTL)
-    if (mode == MM_LOCK_RD)
-        while (((rc = fcntl(fdsem, F_SETLKW, &mm_core_dolock_rd)) < 0) && (errno == EINTR)) ;
-    else
-        while (((rc = fcntl(fdsem, F_SETLKW, &mm_core_dolock_rw)) < 0) && (errno == EINTR)) ;
-#endif
-#if defined(MM_SEMT_FLOCK)
-    if (mode == MM_LOCK_RD)
-        while (((rc = flock(fdsem, LOCK_SH)) < 0) && (errno == EINTR)) ;
-    else
-        while (((rc = flock(fdsem, LOCK_EX)) < 0) && (errno == EINTR)) ;
-#endif
-#if defined(MM_SEMT_IPCSEM)
-    if (mode == MM_LOCK_RD) {
-        while (((rc = semop(mc->mc_fdsem_rd, mm_core_dolock, 2)) < 0) && (errno == EINTR)) ;
-        mc->mc_readers++;
-        if (mc->mc_readers == 1)
-            while (((rc = semop(fdsem, mm_core_dolock, 2)) < 0) && (errno == EINTR)) ;
-        while (((rc = semop(mc->mc_fdsem_rd, mm_core_dounlock, 1)) < 0) && (errno == EINTR)) ;
-    }
-    else {
-        while (((rc = semop(fdsem, mm_core_dolock, 2)) < 0) && (errno == EINTR)) ;
-    }
-    mc->mc_lockmode = mode;
-#endif
-#if defined(MM_SEMT_BEOS)
-	rc=0;
-	if (atomic_add (&mc->mc_ben, 1) > 0){
-		/* someone already in lock..acquire sem and wait */
-		if (acquire_sem(mc->mc_semid) != B_NO_ERROR){
-			atomic_add(&mc->mc_ben,-1);
-	        rc = -1;
-    	}
-    }
-#endif
-
-    if (rc < 0) {
-        ERR(MM_ERR_CORE|MM_ERR_SYSTEM, "Failed to lock");
-        rc = FALSE;
-    }
-    else
-        rc = TRUE;
-    return rc;
-}
-
-int mm_core_unlock(const void *core)
-{
-    mem_core *mc;
-    int rc;
-    int fdsem;
-
-    if (core == NULL)
-        return FALSE;
-    mc = (mem_core *)((char *)core-SIZEOF_mem_core);
-#if !defined(MM_SEMT_FLOCK)
-    fdsem = mc->mc_fdsem;
-#endif
-#if defined(MM_SEMT_FLOCK)
-    fdsem = mm_core_getfdsem(mc);
-#endif
-
-#if defined(MM_SEMT_FCNTL)
-    while (((rc = fcntl(fdsem, F_SETLKW, &mm_core_dounlock)) < 0) && (errno == EINTR)) ;
-#endif
-#if defined(MM_SEMT_FLOCK)
-    while (((rc = flock(fdsem, LOCK_UN)) < 0) && (errno == EINTR)) ;
-#endif
-#if defined(MM_SEMT_IPCSEM)
-    if (mc->mc_lockmode == MM_LOCK_RD) {
-        while (((rc = semop(mc->mc_fdsem_rd, mm_core_dolock, 2)) < 0) && (errno == EINTR)) ;
-        mc->mc_readers--;
-        if (mc->mc_readers == 0)
-            while (((rc = semop(fdsem, mm_core_dounlock, 1)) < 0) && (errno == EINTR)) ;
-        while (((rc = semop(mc->mc_fdsem_rd, mm_core_dounlock, 1)) < 0) && (errno == EINTR)) ;
-    }
-    else {
-        while (((rc = semop(fdsem, mm_core_dounlock, 1)) < 0) && (errno == EINTR)) ;
-    }
-#endif
-#if defined(MM_SEMT_BEOS)
-    rc=0;
-	if (atomic_add(&mc->mc_ben, -1) > 1){
-		release_sem(mc->mc_semid);
-    }
-#endif
-
-    if (rc < 0) {
-        ERR(MM_ERR_CORE|MM_ERR_SYSTEM, "Failed to unlock");
-        rc = FALSE;
-    }
-    else
-        rc = TRUE;
-    return rc;
-}
-
-/*EOF*/
diff --git a/shmem/unix/mm/mm_global.c b/shmem/unix/mm/mm_global.c
deleted file mode 100644
index 53efcca58c7..00000000000
--- a/shmem/unix/mm/mm_global.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/* ====================================================================
- * Copyright (c) 1999 Ralf S. Engelschall. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- *    software must display the following acknowledgment:
- *    "This product includes software developed by
- *     Ralf S. Engelschall <rse@engelschall.com>."
- *
- * 4. Redistributions of any form whatsoever must retain the following
- *    acknowledgment:
- *    "This product includes software developed by
- *     Ralf S. Engelschall <rse@engelschall.com>."
- *
- * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL RALF S. ENGELSCHALL OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- */
-
-/*
-**
-**  mm_global.c -- Global Malloc-Replacement API
-**
-*/
-
-#define MM_PRIVATE
-#include "mm.h"
-
-static MM *mm_global = NULL;
-
-int MM_create(size_t size, const char *file)
-{
-    if (mm_global != NULL)
-        return FALSE;
-    if ((mm_global = mm_create(size, file)) == NULL)
-        return FALSE;
-    return TRUE;
-}
-
-int MM_permission(mode_t mode, uid_t owner, gid_t group)
-{
-    if (mm_global != NULL)
-        return -1;
-    return mm_permission(mm_global, mode, owner, group);
-}
-
-void MM_destroy(void)
-{
-    if (mm_global == NULL)
-        return;
-    mm_destroy(mm_global);
-    mm_global = NULL;
-    return;
-}
-
-int MM_lock(mm_lock_mode mode)
-{
-    if (mm_global == NULL)
-        return FALSE;
-    return mm_lock(mm_global, mode);
-}
-
-int MM_unlock(void)
-{
-    if (mm_global == NULL)
-        return FALSE;
-    return mm_unlock(mm_global);
-}
-
-void *MM_malloc(size_t size)
-{
-    if (mm_global == NULL)
-        return NULL;
-    return mm_malloc(mm_global, size);
-}
-
-void *MM_realloc(void *ptr, size_t size)
-{
-    if (mm_global == NULL)
-        return NULL;
-    return mm_realloc(mm_global, ptr, size);
-}
-
-void MM_free(void *ptr)
-{
-    if (mm_global == NULL)
-        return;
-    mm_free(mm_global, ptr);
-    return;
-}
-
-void *MM_calloc(size_t number, size_t size)
-{
-    if (mm_global == NULL)
-        return NULL;
-    return mm_calloc(mm_global, number, size);
-}
-
-char *MM_strdup(const char *str)
-{
-    if (mm_global == NULL)
-        return NULL;
-    return mm_strdup(mm_global, str);
-}
-
-size_t MM_sizeof(const void *ptr)
-{
-    if (mm_global == NULL)
-        return -1;
-    return mm_sizeof(mm_global, ptr);
-}
-
-size_t MM_maxsize(void)
-{
-    return mm_maxsize();
-}
-
-size_t MM_available(void)
-{
-    if (mm_global == NULL)
-        return -1;
-    return mm_available(mm_global);
-}
-
-char *MM_error(void)
-{
-    return mm_lib_error_get();
-}
-
-/*EOF*/
diff --git a/shmem/unix/mm/mm_lib.c b/shmem/unix/mm/mm_lib.c
deleted file mode 100644
index 0e7c34e86c9..00000000000
--- a/shmem/unix/mm/mm_lib.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/* ====================================================================
- * Copyright (c) 1999 Ralf S. Engelschall. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- *    software must display the following acknowledgment:
- *    "This product includes software developed by
- *     Ralf S. Engelschall <rse@engelschall.com>."
- *
- * 4. Redistributions of any form whatsoever must retain the following
- *    acknowledgment:
- *    "This product includes software developed by
- *     Ralf S. Engelschall <rse@engelschall.com>."
- *
- * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL RALF S. ENGELSCHALL OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- */
-
-/*
-**
-** mm_lib.c -- Internal Library API
-**
-*/
-
-#define MM_PRIVATE
-#include "mm.h"
-
-/*
- * Error Handling
- */
-
-#define MM_LIB_ERROR_MAXLEN 1024
-static char mm_lib_error[MM_LIB_ERROR_MAXLEN+1] = { NUL };
-
-void mm_lib_error_set(unsigned int type, const char *str)
-{
-    int l, n;
-    char *cp;
-
-    if (str == NULL) {
-        mm_lib_error[0] = NUL;
-        return;
-    }
-    if (type & MM_ERR_ALLOC)
-        strcpy(mm_lib_error, "mm:alloc: ");
-    else if (type & MM_ERR_CORE)
-        strcpy(mm_lib_error, "mm:core: ");
-    l = strlen(mm_lib_error);
-    n = strlen(str);
-    if (n > MM_LIB_ERROR_MAXLEN-l)
-        n = MM_LIB_ERROR_MAXLEN-l;
-    memcpy(mm_lib_error+l, str, n+1);
-    l += n;
-    if (type & MM_ERR_SYSTEM && errno != 0) {
-        if (MM_LIB_ERROR_MAXLEN-l > 2) {
-            strcpy(mm_lib_error+l, " (");
-            l += 2;
-        }
-        cp = strerror(errno);
-        n = strlen(cp);
-        if (n > MM_LIB_ERROR_MAXLEN-l)
-            n = MM_LIB_ERROR_MAXLEN-l;
-        memcpy(mm_lib_error+l, cp, n+1);
-        l += n;
-        if (MM_LIB_ERROR_MAXLEN-l > 1) {
-            strcpy(mm_lib_error+l, ")");
-            l += 1;
-        }
-    }
-    *(mm_lib_error+l) = NUL;
-    return;
-}
-
-char *mm_lib_error_get(void)
-{
-    if (mm_lib_error[0] == NUL)
-        return NULL;
-    return mm_lib_error;
-}
-
-/*
- * Version Information
- */
-
-#define _AS_HEADER
-#include "mm_vers.c"
-
-int mm_lib_version(void)
-{
-    return MM_Version;
-}
-
diff --git a/shmem/unix/mm/mm_test.c b/shmem/unix/mm/mm_test.c
deleted file mode 100644
index 38e5570ec16..00000000000
--- a/shmem/unix/mm/mm_test.c
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
-**  mm_test.c -- Test Suite for MM Library
-*/
-
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <signal.h>
-
-#define MM_PRIVATE
-#include "mm.h"
-
-#define FAILED_IF(expr) \
-     if (expr) { \
-         char *e; \
-         e = mm_error(); \
-         fprintf(stderr, "%s\n", e != NULL ? e : "Unknown Error"); \
-         exit(1); \
-     }
-
-int main(int argc, char *argv[]) 
-{
-    char *core;
-    int i;
-    size_t s, s2;
-    pid_t pid;
-    int size;
-    MM *mm;
-    int n;
-    char *cp[1025];
-    int version;
-    struct count_test { int count; int prev; } *ct;
-    
-    setbuf(stderr, NULL);
-
-    /*
-    **
-    **  Test Global Library API
-    **
-    */
-
-    fprintf(stderr, "\n*** TESTING GLOBAL LIBRARY API ***\n\n");
-
-    fprintf(stderr, "Fetching library version\n");
-    version = mm_lib_version();
-    FAILED_IF(version == 0x0);
-    fprintf(stderr, "version = 0x%X\n", version);
-
-    /*
-    **
-    **  Test Low-Level Shared Memory API
-    **
-    */
-    
-    fprintf(stderr, "\n*** TESTING LOW-LEVEL SHARED MEMORY API ***\n");
-
-    fprintf(stderr, "\n=== Testing Memory Segment Access ===\n");
-
-    fprintf(stderr, "Creating 16KB shared memory core area\n");
-    core = mm_core_create(1024*16, NULL);
-    FAILED_IF(core == NULL);
-    s = mm_core_size(core);
-    FAILED_IF(s == 0);
-    fprintf(stderr, "actually allocated core size = %d\n", s);
-
-    fprintf(stderr, "Writing 0xF5 bytes to shared memory core area\n");
-    for (i = 0; i < s; i++) {
-        fprintf(stderr, "write to core[%06d]\r", i);
-        core[i] = 0xF5;
-    }
-    fprintf(stderr, "\n");
-
-    fprintf(stderr, "Reading back 0xF5 bytes from shared memory core area\n");
-    for (i = 0; i < s; i++) {
-        fprintf(stderr, "read from core[%06d]\r", i);
-        if (core[i] != (char)0xF5) {
-            fprintf(stderr, "Offset %d: 0xF5 not found (found 0x%X\n", i, core[i]);
-            exit(0);
-        }
-    }
-    fprintf(stderr, "\n");
-
-    fprintf(stderr, "Destroying shared memory core area\n");
-    mm_core_delete(core);
-
-    fprintf(stderr, "\n=== Testing Memory Locking ===\n");
-
-    fprintf(stderr, "Creating small shared memory core area\n");
-    ct = mm_core_create(sizeof(struct count_test), NULL);
-    FAILED_IF(ct == NULL);
-    s = mm_core_size(ct);
-    FAILED_IF(s == 0);
-    fprintf(stderr, "actually allocated core size = %d\n", s);
-    
-    ct->prev  = 0;
-    ct->count = 1;
-    if ((pid = fork()) == 0) {
-        /* child */
-        while (ct->count < 32768) {
-            if (!mm_core_lock(ct, MM_LOCK_RW)) {
-                fprintf(stderr, "locking failed (child)\n");
-                FAILED_IF(1);
-            }
-            if (ct->prev != (ct->count-1)) {
-                fprintf(stderr, "Failed, prev=%d != count=%d\n", ct->prev, ct->count);
-                exit(1);
-            }
-            ct->count += 1;
-            fprintf(stderr, "count=%06d (child )\r", ct->count);
-            ct->prev  += 1;
-            if (!mm_core_unlock(ct)) {
-                fprintf(stderr, "locking failed (child)\n");
-                FAILED_IF(1);
-            }
-        }
-        exit(0);
-    }
-    /* parent ... */
-    while (ct->count < 32768) {
-        if (!mm_core_lock(ct, MM_LOCK_RW)) {
-            fprintf(stderr, "locking failed (parent)\n");
-            FAILED_IF(1);
-        }
-        if (ct->prev != (ct->count-1)) {
-            fprintf(stderr, "Failed, prev=%d != count=%d\n", ct->prev, ct->count);
-            exit(1);
-        }
-        ct->count += 1;
-        fprintf(stderr, "count=%06d (parent)\r", ct->count);
-        ct->prev  += 1;
-        if (!mm_core_unlock(ct)) {
-            fprintf(stderr, "locking failed (parent)\n");
-            kill(pid, SIGTERM);
-            FAILED_IF(1);
-        }
-    }
-    waitpid(pid, NULL, 0);
-    fprintf(stderr, "\n");
-
-    fprintf(stderr, "Destroying shared memory core area\n");
-    mm_core_delete(ct);
-
-    /*
-    **
-    **  Test Standard Malloc-style API
-    **
-    */
-
-    fprintf(stderr, "\n*** TESTING STANDARD MALLOC-STYLE API ***\n");
-
-    fprintf(stderr, "\n=== Testing Allocation ===\n");
-
-    fprintf(stderr, "Creating MM object\n");
-    size = mm_maxsize();
-    if (size > 1024*1024*1)
-        size = 1024*1024*1;
-    mm = mm_create(size, NULL);
-    FAILED_IF(mm == NULL)
-    mm_display_info(mm);
-    s = mm_available(mm);
-    FAILED_IF(s == 0);
-    fprintf(stderr, "actually available bytes = %d\n", s);
-    
-    fprintf(stderr, "Allocating areas inside MM\n");
-    n = 0;
-    for (i = 0; i < 1024; i++) 
-        cp[i] = NULL;
-    for (i = 0; i < 1024; i++) {
-        fprintf(stderr, "total=%09d allocated=%09d add=%06d\r", s, n, (i+1)*(i+1));
-        s2 = mm_available(mm);
-        if ((i+1)*(i+1) > s2) {
-            cp[i] = mm_malloc(mm, (i+1)*(i+1));
-            if (cp[i] != NULL) {
-                fprintf(stderr, "\nExpected an out of memory situation. Hmmmmm\n");
-                FAILED_IF(1);
-            }
-            break;
-        }
-        cp[i] = mm_malloc(mm, (i+1)*(i+1));
-        n += (i+1)*(i+1);
-        FAILED_IF(cp[i] == NULL)
-        memset(cp[i], 0xF5, (i+1)*(i+1));
-    }
-    mm_display_info(mm);
-
-    fprintf(stderr, "\n=== Testing Defragmentation ===\n");
-
-    fprintf(stderr, "Fragmenting memory area by freeing some selected areas\n");
-    for (i = 0; i < 1024; i++) {
-        if (i % 2 == 0)
-            continue;
-        if (cp[i] != NULL)
-            mm_free(mm, cp[i]);
-        cp[i] = NULL;
-    }
-    mm_display_info(mm);
-
-    fprintf(stderr, "Freeing all areas\n");
-    for (i = 0; i < 1024; i++) {
-        mm_free(mm, cp[i]);
-    }
-    mm_display_info(mm);
-
-    fprintf(stderr, "Checking for memory leaks\n");
-    s2 = mm_available(mm);
-    if (s != s2) {
-        fprintf(stderr, "Something is leaking, we've lost %d bytes\n", s - s2);
-        FAILED_IF(1);
-    }
-    else {
-        fprintf(stderr, "Fine, we have again %d bytes available\n", s2);
-    }
-    
-    fprintf(stderr, "Destroying MM object\n");
-    mm_destroy(mm);
-    
-    /******/
-
-    fprintf(stderr, "\nOK - ALL TESTS SUCCESSFULLY PASSED.\n\n");
-    exit(0);
-}
-
diff --git a/shmem/unix/mm/mm_vers.c b/shmem/unix/mm/mm_vers.c
deleted file mode 100644
index ab61a88b199..00000000000
--- a/shmem/unix/mm/mm_vers.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
-**  mm_vers.c -- Version Information
-**  [automatically generated and maintained by shtool]
-*/
-
-#ifdef _AS_HEADER
-
-#ifndef _MM_VERS_C
-#define _MM_VERS_C
-#define MM_VERSION 0x100211
-extern const int  MM_Version;
-extern const char MM_VersionStr[];
-extern const char MM_Hello[];
-extern const char MM_GNUVersion[];
-extern const char MM_WhatID[];
-extern const char MM_RCSIdentID[];
-extern const char MM_WebID[];
-extern const char MM_PlainID[];
-#endif /* _MM_VERS_C */
-
-#else
-
-const int  MM_Version      = 0x100211;
-const char MM_VersionStr[] = "1.0.11 (06-Sep-1999)";
-const char MM_Hello[]      = "This is MM, Version 1.0.11 (06-Sep-1999)";
-const char MM_GNUVersion[] = "MM Version 1.0.11";
-const char MM_WhatID[]     = "@(#)MM Version 1.0.11 (06-Sep-1999)";
-const char MM_RCSIdentID[] = "$Id: mm_vers.c,v 1.2 1999/09/27 07:42:10 rse Exp $";
-const char MM_WebID[]      = "MM/1.0.11";
-const char MM_PlainID[]    = "1.0.11";
-
-#endif
diff --git a/shmem/unix/mm/shtool b/shmem/unix/mm/shtool
deleted file mode 100755
index cacca7eb67f..00000000000
--- a/shmem/unix/mm/shtool
+++ /dev/null
@@ -1,2721 +0,0 @@
-#!/bin/sh
-##
-##  GNU shtool -- The GNU Portable Shell Tool
-##  Copyright (c) 1994-1999 Ralf S. Engelschall <rse@engelschall.com>
-##
-##  See http://www.gnu.org/software/shtool/ for more information.
-##  See ftp://ftp.gnu.org/gnu/shtool/ for latest version.
-##
-##  Version 1.4.6 (05-Sep-1999)
-##  Ingredients: all available modules
-##
-
-##
-##  This program is free software; you can redistribute it and/or modify
-##  it under the terms of the GNU General Public License as published by
-##  the Free Software Foundation; either version 2 of the License, or
-##  (at your option) any later version.
-##
-##  This program is distributed in the hope that it will be useful,
-##  but WITHOUT ANY WARRANTY; without even the implied warranty of
-##  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-##  General Public License for more details.
-##
-##  You should have received a copy of the GNU General Public License
-##  along with this program; if not, write to the Free Software
-##  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
-##  USA, or contact Ralf S. Engelschall <rse@engelschall.com>.
-##
-##  Notice: Given that you include this file verbatim into your own
-##  source tree, you are justified in saying that it remains separate
-##  from your package, and that this way you are simply just using GNU
-##  shtool. So, in this situation, there is no requirement that your
-##  package itself is licensed under the GNU General Public License in
-##  order to take advantage of GNU shtool.
-##
-
-##
-##  Usage: shtool [<options>] [<cmd-name> [<cmd-options>] [<cmd-args>]]
-##
-##  Available commands:
-##    echo       Print string with optional construct expansion
-##    mdate      Pretty-print modification time of a file or dir
-##    table      Pretty print a field-separated list as a table
-##    prop       Display progress with a running propeller
-##    move       Move files with simultan substitution
-##    install    Install a program, script or datafile
-##    mkdir      Make one or more directories
-##    mkln       Make link with calculation of relative paths
-##    mkshadow   Make a shadow tree
-##    fixperm    Fix file permissions inside a source tree
-##    tarball    Roll distribution tarballs
-##    guessos    Simple OS/platform guesser
-##    arx        Extended archive command
-##    slo        Separate linker options by library class
-##    scpp       Sharing C Pre-Processor
-##    version    Generate and maintain a version information file
-##    path       Deal with program paths
-##
-
-if [ $# -eq 0 ]; then
-    echo "$0:Error: invalid command line" 1>&2
-    echo "$0:Hint:  run \`$0 -h' for usage" 1>&2
-    exit 1
-fi
-if [ ".$1" = ".-h" -o ".$1" = ".--help" ]; then
-    echo "This is GNU shtool, version 1.4.6 (05-Sep-1999)"
-    echo "Copyright (c) 1994-1999 Ralf S. Engelschall <rse@engelschall.com>"
-    echo "Report bugs to <bug-shtool@gnu.org>"
-    echo ''
-    echo "Usage: shtool [<options>] [<cmd-name> [<cmd-options>] [<cmd-args>]]" 
-    echo ''
-    echo 'Available global <options>:'
-    echo '  -v, --version   display shtool version information'
-    echo '  -h, --help      display shtool usage help page (this one)'
-    echo '  -d, --debug     display shell trace information'
-    echo ''
-    echo 'Available <cmd-name> [<cmd-options>] [<cmd-args>]:'
-    echo '  echo     [-n] [-e] [<str> ...]'
-    echo '  mdate    [-n] [-z] [-s] [-d] [-f<str>] [-o<spec>] <path>'
-    echo '  table    [-F<sep>] [-w<width>] [-c<cols>] [-s<strip>] <str><sep><str>...'
-    echo '  prop     [-p<str>]'
-    echo '  move     [-v] [-t] [-e] [-p] <src-file> <dst-file>'
-    echo '  install  [-v] [-t] [-c] [-C] [-s] [-m<mode>] [-o<owner>] [-g<group>]'
-    echo '           [-e<ext>] <file> <path>'
-    echo '  mkdir    [-t] [-f] [-p] [-m<mode>] <dir> [<dir> ...]'
-    echo '  mkln     [-t] [-f] [-s] <src-path> [<src-path> ...] <dst-path>'
-    echo '  mkshadow [-v] [-t] [-a] <src-dir> <dst-dir>'
-    echo '  fixperm  [-v] [-t] <path> [<path> ...]'
-    echo '  tarball  [-t] [-v] [-o <tarball>] [-c <prog>] [-d <dir>] [-u'
-    echo '           <user>] [-g <group>] [-e <pattern>] <path> [<path> ...]'
-    echo '  guessos  '
-    echo '  arx      [-t] [-C<cmd>] <op> <archive> [<file> ...]'
-    echo '  slo      -- -L<dir> -l<lib> [ -L<dir> -l<lib> ... ]'
-    echo '  scpp     [-v] [-p] [-o<ofile>] [-t<tfile>] [-M<mark>] [-D<dname>]'
-    echo '           [-C<cname>] <file> [<file> ...]'
-    echo '  version  [-l<lang>] [-n<name>] [-p<prefix>] [-s<version>] [-i<knob>]'
-    echo '           [-d<type>] <file>'
-    echo '  path     [-s] [-r] [-d] [-b] [-m] [-p<path>] <str> [<str> ...]'
-    echo ''
-    exit 0
-fi
-if [ ".$1" = ".-v" -o ".$1" = ."--version" ]; then
-    echo "GNU shtool 1.4.6 (05-Sep-1999)"
-    exit 0
-fi
-if [ ".$1" = ".-d" -o ".$1" = ."--debug" ]; then
-    shift
-    set -x
-fi
-name=`echo "$0" | sed -e 's;.*/\([^/]*\)$;\1;' -e 's;-sh$;;' -e 's;\.sh$;;'`
-case "$name" in
-    echo|mdate|table|prop|move|install|mkdir|mkln|mkshadow|fixperm|tarball|guessos|arx|slo|scpp|version|path )
-        #   implicit tool command selection
-        tool="$name"
-        ;;
-    * )
-        #   explicit tool command selection
-        tool="$1"
-        shift
-        ;;
-esac
-arg_spec=""
-opt_spec=""
-gen_tmpfile=no
-
-##
-##  DISPATCH INTO SCRIPT PROLOG
-##
-
-case $tool in
-    echo )
-        str_tool="echo"
-        str_usage="[-n] [-e] [<str> ...]"
-        arg_spec="0+"
-        opt_spec="ne"
-        ;;
-    mdate )
-        str_tool="mdate"
-        str_usage="[-n] [-z] [-s] [-d] [-f<str>] [-o<spec>] <path>"
-        arg_spec="1"
-        opt_spec="nzsdf:!o:!"
-        opt_f=" "
-        opt_o="dmy"
-        ;;
-    table )
-        str_tool="table"
-        str_usage="[-F<sep>] [-w<width>] [-c<cols>] [-s<strip>] <str><sep><str>..."
-        arg_spec="1+"
-        opt_spec="F:!w:!c:!s:!"
-        opt_F=":"
-        opt_w=15
-        opt_c=3
-        opt_s=79
-        ;;
-    prop )
-        str_tool="prop"
-        str_usage="[-p<str>]"
-        arg_spec="0"
-        opt_spec="p:"
-        ;;
-    move )
-        str_tool="move"
-        str_usage="[-v] [-t] [-e] [-p] <src-file> <dst-file>"
-        arg_spec="2"
-        opt_spec="vtep"
-        ;;
-    install )
-        str_tool="install"
-        str_usage="[-v] [-t] [-c] [-C] [-s] [-m<mode>] [-o<owner>] [-g<group>] [-e<ext>] <file> <path>"
-        arg_spec="2"
-        opt_spec="vtcCsm:o:g:e:"
-        ;;
-    mkdir )
-        str_tool="mkdir"
-        str_usage="[-t] [-f] [-p] [-m<mode>] <dir> [<dir> ...]"
-        arg_spec="1+"
-        opt_spec="tfpm:"
-        ;;
-    mkln )
-        str_tool="mkln"
-        str_usage="[-t] [-f] [-s] <src-path> [<src-path> ...] <dst-path>"
-        arg_spec="2+"
-        opt_spec="tfs"
-        ;;
-    mkshadow )
-        str_tool="mkshadow"
-        str_usage="[-v] [-t] [-a] <src-dir> <dst-dir>"
-        arg_spec="2"
-        opt_spec="vta"
-        ;;
-    fixperm )
-        str_tool="fixperm"
-        str_usage="[-v] [-t] <path> [<path> ...]"
-        gen_tmpfile=yes
-        arg_spec="1+"
-        opt_spec="vt"
-        ;;
-    tarball )
-        str_tool="tarball"
-        str_usage="[-t] [-v] [-o <tarball>] [-c <prog>] [-d <dir>] [-u <user>] [-g <group>] [-e <pattern>] <path> [<path> ...]"
-        gen_tmpfile=yes
-        arg_spec="1+"
-        opt_spec="tvo:c:d:u:g:e:!"
-        opt_e="CVS,\\.cvsignore,\\.[oa]\$"
-        ;;
-    guessos )
-        str_tool="guessos"
-        str_usage=""
-        arg_spec="0"
-        opt_spec=""
-        ;;
-    arx )
-        str_tool="arx"
-        str_usage="[-t] [-C<cmd>] <op> <archive> [<file> ...]"
-        arg_spec="2+"
-        opt_spec="tC:!"
-        opt_C="ar"
-        ;;
-    slo )
-        str_tool="slo"
-        str_usage="-- -L<dir> -l<lib> [ -L<dir> -l<lib> ... ]"
-        arg_spec="1+"
-        opt_spec=""
-        ;;
-    scpp )
-        str_tool="scpp"
-        str_usage="[-v] [-p] [-o<ofile>] [-t<tfile>] [-M<mark>] [-D<dname>] [-C<cname>] <file> [<file> ...]"
-        gen_tmpfile=yes
-        arg_spec="1+"
-        opt_spec="vpo:!t:!M:!D:!C:!"
-        opt_o="lib.h"
-        opt_t="lib.h.in"
-        opt_M="%%MARK%%"
-        opt_D="cpp"
-        opt_C="intern"
-        ;;
-    version )
-        str_tool="version"
-        str_usage="[-l<lang>] [-n<name>] [-p<prefix>] [-s<version>] [-i<knob>] [-d<type>] <file>"
-        arg_spec="1+"
-        opt_spec="l:!n:!p:!s:!i:!d:!"
-        opt_l="txt"
-        opt_n="unknown"
-        opt_p="unknown"
-        opt_s="unknown"
-        opt_i="P"
-        opt_d="NO"
-        gen_tmpfile=yes
-        ;;
-    path )
-        str_tool="path"
-        str_usage="[-s] [-r] [-d] [-b] [-m] [-p<path>] <str> [<str> ...]"
-        gen_tmpfile=yes
-        arg_spec="1+"
-        opt_spec="srdbmp:!"
-        opt_p="$PATH"
-        ;;
-    * )
-        echo "$0:Error: unknown command \`$tool'" 2>&1
-        echo "$0:Hint:  run \`$0 -h' for usage" 2>&1
-        exit 1
-        ;;
-esac
-
-##
-##  COMMON UTILITY CODE
-##
-
-#   determine name of tool
-if [ ".$tool" != . ]; then
-    #   inside shtool
-    toolcmd="$0 $tool"
-    toolcmdhelp="shtool $tool"
-    msgprefix="shtool:$tool"
-else
-    #   standalone
-    toolcmd="$0"
-    toolcmdhelp="sh.$tool"
-    msgprefix="$str_tool"
-fi
-
-#   parse argument specification string
-eval `echo $arg_spec | sed -e 's/^\([0-9]*\)\(.*\)/arg_NUMS="\1"; arg_MODE="\2"/'`
-test ".$arg_MODE" = . && arg_MODE="="
-
-#   parse option specification string
-for opt in `echo "h$opt_spec" | sed -e 's/\([a-zA-Z0-9][!:+]*\)/\1 /g'`; do
-    opt_MODE="."; opt_INIT="."
-    eval `echo $opt |\
-          sed -e 's/^\([a-zA-Z0-9]\)/opt_THIS="\1";/' \
-              -e 's/";\([:+]\)/"; opt_MODE="\1";/' \
-              -e 's/";\(!\)/"; opt_INIT="\1"/'`
-    eval "opt_MODE_${opt_THIS}=${opt_MODE}"
-    if [ ".$opt_INIT" != ".!" ]; then
-        case "$opt_MODE" in
-            "." )     eval "opt_${opt_THIS}=no"   ;;
-            ":"|"+" ) eval "opt_${opt_THIS}=\"\"" ;;
-        esac
-    fi
-done
-
-#   interate over argument line
-opt_PREV=''
-while [ $# -gt 0 ]; do
-    #   special option stops processing
-    if [ ".$1" = ".--" ]; then
-        shift
-        break
-    fi
-
-    #   determine option and argument
-    opt_ARG_OK=no
-    if [ ".$opt_PREV" != . ]; then
-        #   merge previous seen option with argument
-        opt_OPT="$opt_PREV"
-        opt_ARG="$1"
-        opt_ARG_OK=yes
-        opt_PREV=""
-    else
-        #   split argument into option and argument
-        case "$1" in
-            -[a-zA-Z0-9]*)
-                eval `echo "x$1" |\
-                      sed -e 's/^x-\([a-zA-Z0-9]\)/opt_OPT="\1";/' \
-                          -e 's/";\(.*\)$/"; opt_ARG="\1"/'`
-                ;;
-            -[a-zA-Z0-9])
-                opt_OPT=`awk 'BEGIN { printf("%s", substr(OPT, 2)); }' \
-                         "OPT=$1" </dev/null"`
-                opt_ARG=''
-                ;;
-            *)
-                break
-                ;;
-        esac
-    fi
-
-    #   eat up option
-    shift
-
-    #   determine whether option needs an argument
-    eval "opt_MODE=\$opt_MODE_${opt_OPT}"
-    if [ ".$opt_ARG" = . -a ".$opt_ARG_OK" != .yes ]; then
-        if [ ".$opt_MODE" = ".:" -o ".$opt_MODE" = ".+" ]; then
-            opt_PREV="$opt_OPT"
-            continue
-        fi
-    fi
-
-    #   process option
-    case $opt_MODE in
-        "." )
-            #   boolean option
-            eval "opt_${opt_OPT}=yes"
-            ;;
-        ":" )
-            #   option with argument (multiple occurances override)
-            eval "opt_${opt_OPT}=\"\$opt_ARG\""
-            ;;
-        "+" )
-            #   option with argument (multiple occurances append)
-            eval "opt_${opt_OPT}=\"\$opt_${opt_OPT} \$opt_ARG\""
-            ;;
-        * )
-            echo "$msgprefix:Error: unknown option: \`-$opt_OPT'" 1>&2
-            echo "$msgprefix:Hint:  run \`$toolcmdhelp -h' or \`man shtool' for details" 1>&2
-            exit 1
-            ;;
-    esac
-done
-if [ ".$opt_PREV" != . ]; then
-    echo "$msgprefix:Error: missing argument to option \`-$opt_PREV'" 1>&2
-    echo "$msgprefix:Hint:  run \`$toolcmdhelp -h' or \`man shtool' for details" 1>&2
-    exit 1
-fi
-
-#   process help option
-if [ ".$opt_h" = .yes ]; then
-    echo "Usage: $toolcmdhelp $str_usage"
-    exit 0
-fi
-
-#   complain about incorrect number of arguments
-case $arg_MODE in
-    "=" )
-        if [ $# -ne $arg_NUMS ]; then
-            echo "$msgprefix:Error: invalid number of arguments (exactly $arg_NUMS expected)" 1>&2
-            echo "$msgprefix:Hint:  run \`$toolcmd -h' or \`man shtool' for details" 1>&2
-            exit 1
-        fi
-        ;;
-    "+" )
-        if [ $# -lt $arg_NUMS ]; then
-            echo "$msgprefix:Error: invalid number of arguments (at least $arg_NUMS expected)" 1>&2
-            echo "$msgprefix:Hint:  run \`$toolcmd -h' or \`man shtool' for details" 1>&2
-            exit 1
-        fi
-        ;;
-esac
-
-#   establish a temporary file on request
-if [ ".$gen_tmpfile" = .yes ]; then
-    tmpdir="/tmp"
-    if [ ".$TMPDIR" != . ]; then
-        tmpdir="$TMPDIR"
-    else
-        if [ ".$TEMPDIR" != . ]; then
-            tmpdir="$TEMPDIR"
-        fi
-    fi
-    tmpfile="$tmpdir/.shtool.$$"
-    rm -f $tmpfile >/dev/null 2>&1
-    touch $tmpfile
-fi
-
-##
-##  DISPATCH INTO SCRIPT BODY
-##
-
-case $tool in
-
-echo )
-    ##
-    ##  echo -- Print string with optional construct expansion
-    ##  Copyright (c) 1998-1999 Ralf S. Engelschall <rse@engelschall.com>
-    ##  Originally written for WML as buildinfo
-    ##
-    
-    text="$*"
-    
-    #   check for broken escape sequence expansion
-    seo=''
-    bytes=`echo '\1' | wc -c | awk '{ printf("%s", $1); }'`
-    if [ ".$bytes" != .3 ]; then
-        bytes=`echo -E '\1' | wc -c | awk '{ printf("%s", $1); }'`
-        if [ ".$bytes" = .3 ]; then
-            seo='-E'
-        fi
-    fi
-    
-    #   check for existing -n option (to suppress newline)
-    minusn=''
-    bytes=`echo -n 123 2>/dev/null | wc -c | awk '{ printf("%s", $1); }'`
-    if [ ".$bytes" = .3 ]; then
-        minusn='-n'
-    fi
-    
-    #   determine terminal bold sequence
-    term_bold='' 
-    term_norm=''
-    if [ ".$opt_e" = .yes -a ".`echo $text | egrep '%[Bb]'`" != . ]; then
-        #   the most important terminals we directly know
-        case $TERM in
-            xterm|xterm*|vt220|vt220*)
-                term_bold=`awk 'BEGIN { printf("%c%c%c%c", 27, 91, 49, 109); }' </dev/null 2>/dev/null`
-                term_norm=`awk 'BEGIN { printf("%c%c%c", 27, 91, 109); }' </dev/null 2>/dev/null`
-                ;;
-            vt100|vt100*)
-                term_bold=`awk 'BEGIN { printf("%c%c%c%c%c%c", 27, 91, 49, 109, 0, 0); }' </dev/null 2>/dev/null`
-                term_norm=`awk 'BEGIN { printf("%c%c%c%c%c", 27, 91, 109, 0, 0); }' </dev/null 2>/dev/null`
-                ;;
-        esac
-        #   then try a possibly existing "tput" or "tcout" utility
-        paths=`echo $PATH | sed -e 's/:/ /g'`
-        for tool in tput tcout; do
-            for dir in $paths; do
-                if [ -r "$dir/$tool" ]; then
-                    for seq in bold md smso; do # smso is last
-                        bold="`$dir/$tool $seq 2>/dev/null`"
-                        if [ ".$bold" != . ]; then
-                            term_bold="$bold"
-                            break
-                        fi
-                    done
-                    if [ ".$term_bold" != . ]; then
-                        for seq in sgr0 me rmso reset; do # 'reset' is last
-                            norm="`$dir/$tool $seq 2>/dev/null`"
-                            if [ ".$norm" != . ]; then
-                                term_norm="$norm"
-                                break
-                            fi
-                        done
-                    fi
-                    break
-                fi
-            done
-            if [ ".$term_bold" != . -a ".$term_norm" != . ]; then
-                break;
-            fi
-        done
-        if [ ".$term_bold" = . -o ".$term_norm" = . ]; then
-            echo "$msgprefix:Warning: unable to determine terminal sequence for bold mode" 1>&2
-        fi
-    fi
-    
-    #   determine user name
-    username=''
-    if [ ".$opt_e" = .yes -a ".`echo $text | egrep '%[uU]'`" != . ]; then
-        username="$LOGNAME"
-        if [ ".$username" = . ]; then
-            username="$USER"
-            if [ ".$username" = . ]; then
-                username="`(whoami) 2>/dev/null |\
-                           awk '{ printf("%s", $1); }'`"
-                if [ ".$username" = . ]; then
-                    username="`(who am i) 2>/dev/null |\
-                               awk '{ printf("%s", $1); }'`"
-                    if [ ".$username" = . ]; then
-                        username='unknown'
-                    fi
-                fi
-            fi
-        fi
-    fi
-    
-    #   determine user id
-    userid=''
-    if [ ".$opt_e" = .yes -a ".`echo $text | egrep '%U'`" != . ]; then
-        userid="`(id -u) 2>/dev/null`"
-        if [ ".$userid" = . ]; then
-            str="`(id) 2>/dev/null`"
-            if [ ".`echo $str | grep '^uid[ 	]*=[ 	]*[0-9]*('`" != . ]; then
-                userid=`echo $str | sed -e 's/^uid[ 	]*=[ 	]*//' -e 's/(.*//'`
-            fi
-            if [ ".$userid" = . ]; then
-                userid=`egrep "^${username}:" /etc/passwd 2>/dev/null | \
-                        sed -e 's/[^:]*:[^:]*://' -e 's/:.*$//'`
-                if [ ".$userid" = . ]; then
-                    userid=`(ypcat passwd) 2>/dev/null |
-                            egrep "^${username}:" | \
-                            sed -e 's/[^:]*:[^:]*://' -e 's/:.*$//'`
-                    if [ ".$userid" = . ]; then
-                        userid='?'
-                    fi
-                fi
-            fi
-        fi
-    fi
-    
-    #   determine host name
-    hostname=''
-    if [ ".$opt_e" = .yes -a ".`echo $text | egrep '%h'`" != . ]; then
-        hostname="`(uname -n) 2>/dev/null |\
-                   awk '{ printf("%s", $1); }'`"
-        if [ ".$hostname" = . ]; then
-            hostname="`(hostname) 2>/dev/null |\
-                       awk '{ printf("%s", $1); }'`"
-            if [ ".$hostname" = . ]; then
-                hostname='unknown'
-            fi
-        fi
-        case $hostname in
-            *.* )
-                domainname=".`echo $hostname | cut -d. -f2-`"
-                hostname="`echo $hostname | cut -d. -f1`"
-                ;;
-        esac
-    fi
-    
-    #   determine domain name
-    domainname=''
-    if [ ".$opt_e" = .yes -a ".`echo $text | egrep '%d'`" != . ]; then
-        if [ ".$domainname" = . ]; then
-            if [ -f /etc/resolv.conf ]; then
-                domainname="`egrep '^[ 	]*domain' /etc/resolv.conf | head -1 |\
-                             sed -e 's/.*domain//' \
-                                 -e 's/^[ 	]*//' -e 's/^ *//' -e 's/^	*//' \
-                                 -e 's/^\.//' -e 's/^/./' |\
-                             awk '{ printf("%s", $1); }'`"
-                if [ ".$domainname" = . ]; then
-                    domainname="`egrep '^[ 	]*search' /etc/resolv.conf | head -1 |\
-                                 sed -e 's/.*search//' \
-                                     -e 's/^[ 	]*//' -e 's/^ *//' -e 's/^	*//' \
-                                     -e 's/ .*//' -e 's/	.*//' \
-                                     -e 's/^\.//' -e 's/^/./' |\
-                                 awk '{ printf("%s", $1); }'`"
-                fi
-            fi
-        fi
-    fi
-    
-    #   determine current time
-    time_day=''
-    time_month=''
-    time_year=''
-    time_monthname=''
-    if [ ".$opt_e" = .yes -a ".`echo $text | egrep '%[DMYm]'`" != . ]; then
-        time_day=`date '+%d'`
-        time_month=`date '+%m'`
-        time_year=`date '+%Y' 2>/dev/null`
-        if [ ".$time_year" = . ]; then
-            time_year=`date '+%y'`
-            case $time_year in
-                [5-9][0-9]) time_year="19$time_year" ;;
-                [0-4][0-9]) time_year="20$time_year" ;;
-            esac
-        fi
-        case $time_month in
-            1|01) time_monthname='Jan' ;;
-            2|02) time_monthname='Feb' ;;
-            3|03) time_monthname='Mar' ;;
-            4|04) time_monthname='Apr' ;;
-            5|05) time_monthname='May' ;;
-            6|06) time_monthname='Jun' ;;
-            7|07) time_monthname='Jul' ;;
-            8|08) time_monthname='Aug' ;;
-            9|09) time_monthname='Sep' ;;
-              10) time_monthname='Oct' ;;
-              11) time_monthname='Nov' ;;
-              12) time_monthname='Dec' ;;
-        esac
-    fi
-    
-    #   expand special ``%x'' constructs
-    if [ ".$opt_e" = .yes ]; then
-        text=`echo $seo "$text" |\
-              sed -e "s/%B/${term_bold}/g" \
-                  -e "s/%b/${term_norm}/g" \
-                  -e "s/%u/${username}/g" \
-                  -e "s/%U/${userid}/g" \
-                  -e "s/%h/${hostname}/g" \
-                  -e "s/%d/${domainname}/g" \
-                  -e "s/%D/${time_day}/g" \
-                  -e "s/%M/${time_month}/g" \
-                  -e "s/%Y/${time_year}/g" \
-                  -e "s/%m/${time_monthname}/g" 2>/dev/null`
-    fi
-    
-    #   create output
-    if [ .$opt_n = .no ]; then
-        echo $seo $text
-    else
-        #   the harder part: echo -n is best, because
-        #   awk complains about some \xx sequences.
-        if [ ".$minusn" != . ]; then
-            echo $seo $minusn $text
-        else
-            echo dummy | awk '{ printf("%s", TEXT); }' TEXT="$text"
-        fi
-    fi
-    ;;
-
-mdate )
-    ##
-    ##  mdate -- Pretty-print modification time of a file or dir
-    ##  Copyright (c) 1995-1997 Free Software Foundation, Inc.
-    ##  Originally idea and basis code by Ulrich Drepper
-    ##  Enhanced by Ralf S. Engelschall for shtool
-    ##
-    
-    fod="$1"
-    case "$opt_o" in
-        [dmy][dmy][dmy] )
-            ;;
-        * ) echo "$msgprefix:Error: invalid argument to option \`-o': $opt_o" 1>&2
-            exit 1
-            ;;
-    esac
-    if [ ! -r "$fod" ]; then
-        echo "$msgprefix:Error: file or directory not found: $fod" 1>&2
-        exit 1
-    fi
-    
-    #   prevent "date" giving response in another language
-    LANG=C;    export LANG
-    LC_ALL=C;  export LC_ALL
-    LC_TIME=C; export LC_TIME
-    
-    #   get the extended ls output of the file or directory.
-    if ls -L /dev/null >/dev/null 2>&1; then
-        set - x`ls -L -l -d $fod`
-    else
-        set - x`ls -l -d $fod`
-    fi
-    
-    #   The month is at least the fourth argument
-    #   (3 shifts here, the next inside the loop).
-    shift; shift; shift
-    
-    #   Find the month. Next argument is day, followed by the year or time.
-    month=""
-    while [ ".$month" = . ]; do
-        shift
-        case $1 in
-            Jan) month=January;   nummonth=1  ;;
-            Feb) month=February;  nummonth=2  ;;
-            Mar) month=March;     nummonth=3  ;;
-            Apr) month=April;     nummonth=4  ;;
-            May) month=May;       nummonth=5  ;;
-            Jun) month=June;      nummonth=6  ;;
-            Jul) month=July;      nummonth=7  ;;
-            Aug) month=August;    nummonth=8  ;;
-            Sep) month=September; nummonth=9  ;;
-            Oct) month=October;   nummonth=10 ;;
-            Nov) month=November;  nummonth=11 ;;
-            Dec) month=December;  nummonth=12 ;;
-        esac
-    done
-    day="$2"
-    year="$3"
-    
-    #   We finally have to deal with the problem that the "ls" output
-    #   gives either the time of the day or the year.
-    case $year in
-        *:*)
-            this_year=`date '+%Y' 2>/dev/null`
-            if [ ".$this_year" = . ]; then
-                this_year=`date '+%y'`
-                case $this_year in
-                    [5-9][0-9]) this_year="19$this_year" ;;
-                    [0-4][0-9]) this_year="20$this_year" ;;
-                esac
-            fi
-            #   for the following months of the last year the time notation
-            #   is usually also used for files modified in the last year.
-            this_month=`date '+%m'`
-            if (expr $nummonth \> $this_month) >/dev/null; then
-                this_year=`expr $this_year - 1`
-            fi
-            year="$this_year"
-            ;;
-    esac
-    
-    #   Optionally fill day and month with leeding zeros
-    if [ ".$opt_z" = .yes ]; then
-        case $day in
-            [0-9][0-9] ) ;;
-                 [0-9] ) day="0$day" ;;
-        esac
-        case $nummonth in
-            [0-9][0-9] ) ;;
-                 [0-9] ) nummonth="0$nummonth" ;;
-        esac
-    fi
-    
-    #   Optionally use digits for month
-    if [ ".$opt_d" = .yes ]; then
-        month="$nummonth"
-    fi
-    
-    #   Optionally shorten the month name to three characters
-    if [ ".$opt_s" = .yes ]; then
-        month=`echo $month | cut -c1-3`
-    fi
-    
-    #   Output the resulting date string
-    echo dummy | awk '{
-        for (i = 0; i < 3; i++) {
-            now = substr(order, 1, 1);
-            order = substr(order, 2);
-            if (now == "d")
-                out = day;
-            else if (now == "m")
-                out = month;
-            else if (now == "y")
-                out = year;
-            if (i < 2)
-                printf("%s%s", out, field);
-            else
-                printf("%s", out);
-        }
-        if (newline != "yes")
-            printf("\n");
-    }' "day=$day" "month=$month" "year=$year" \
-       "field=$opt_f" "order=$opt_o" "newline=$opt_n"
-    ;;
-
-table )
-    ##
-    ##  table -- Pretty print a field-separated list as a table
-    ##  Copyright (c) 1998-1999 Ralf S. Engelschall <rse@engelschall.com>
-    ##  Originally written for Apache
-    ##
-    
-    if [ $opt_c -gt 4 ]; then
-        echo "$msgprefix:Error: Invalid number of colums (1..4 allowed only)" 1>&2
-        exit 1
-    fi
-    case "x$opt_F" in
-        x? ) ;;
-        *  ) echo "$msgprefix:Error: Invalid separator (one char allowed only)" 1>&2; exit 1 ;;
-    esac
-    
-    #   split the list into a table
-    list=`
-        IFS="$opt_F"
-        for entry in $*; do
-            if [ ".$entry" != . ]; then
-                echo "$entry"
-            fi
-        done |\
-        awk "
-            BEGIN { list = \"\"; n = 0; }
-            {
-                list = list \\$1;
-                n = n + 1;
-                if (n < $opt_c) {
-                    list = list \":\";
-                }
-                if (n == $opt_c) {
-                    list = list \"\\n\";
-                    n = 0;
-                }
-            }
-            END { print list; }
-         "
-    `
-    
-    #   format table cells and make sure table
-    #   doesn't exceed maximum width
-    OIFS="$IFS"
-    IFS='
-'
-    for entry in $list; do
-        case $opt_c in
-            1 ) eval "echo \"\${entry}\" | awk -F: '{ printf(\"%-${opt_w}s\\n\", \$1); }'" ;;
-            2 ) eval "echo \"\${entry}\" | awk -F: '{ printf(\"%-${opt_w}s %-${opt_w}s\\n\", \$1, \$2); }'" ;;
-            3 ) eval "echo \"\${entry}\" | awk -F: '{ printf(\"%-${opt_w}s %-${opt_w}s %-${opt_w}s\\n\", \$1, \$2, \$3); }'" ;;
-            4 ) eval "echo \"\${entry}\" | awk -F: '{ printf(\"%-${opt_w}s %-${opt_w}s %-${opt_w}s %-${opt_w}s\\n\", \$1, \$2, \$3, \$4); }'" ;;
-        esac
-    done |\
-    awk "{
-        if (length(\$0) > $opt_s) {
-            printf(\"%s\\n\", substr(\$0, 0, $opt_s-1));
-        } else {
-            print \$0;
-        }
-    }"
-    IFS="$OIFS"
-    ;;
-
-prop )
-    ##
-    ##  prop -- Display progress with a running propeller
-    ##  Copyright (c) 1998-1999 Ralf S. Engelschall <rse@engelschall.com>
-    ##  Originally written for mod_ssl
-    ##
-    
-    perl=''
-    for dir in `echo $PATH | sed -e 's/:/ /g'` .; do
-        if [ -f "$dir/perl" ]; then
-            perl="$dir/perl"
-            break
-        fi
-    done
-    if [ ".$perl" != . ]; then
-        #   Perl is preferred because writing to STDERR in
-        #   Perl really writes immediately as one would expect
-        $perl -e '
-            @p = ("|","/","-","\\");
-            $i = 0;
-            while (<STDIN>) {
-                printf(STDERR "\r%s...%s\b", $ARGV[0], $p[$i++]);
-                $i = 0 if ($i > 3);
-            }
-            printf(STDERR "\r%s    \n", $ARGV[0]);
-        ' "$opt_p"
-    else
-        #   But when Perl doesn't exists we use Awk even
-        #   some Awk's buffer even the /dev/stderr writing :-(
-        awk '
-            BEGIN {
-                split("|#/#-#\\", p, "#");
-                i = 1;
-            }
-            {
-                printf("\r%s%c\b", prefix, p[i++]) > "/dev/stderr";
-                if (i > 4) { i = 1; }
-            }
-            END {
-                printf("\r%s    \n", prefix) > "/dev/stderr";
-            }
-        ' "prefix=$opt_p"
-    fi
-    ;;
-
-move )
-    ##
-    ##  move -- Move files with simultan substitution
-    ##  Copyright (c) 1999 Ralf S. Engelschall <rse@engelschall.com>
-    ##  Originally written for shtool
-    ##
-    
-    src="$1"
-    dst="$2"
-    
-    #   consistency checks
-    if [ ".$src" = . -o ".$dst" = . ]; then
-        echo "$msgprefix:Error: Invalid arguments" 1>&2
-        exit 1
-    fi
-    if [ ".$src" = ".$dst" ]; then
-        echo "$msgprefix:Error: Source and destination files are the same" 1>&2
-        exit 1
-    fi
-    expsrc="$src"
-    if [ ".$opt_e" = .yes ]; then
-        expsrc="`echo $expsrc`"
-    fi
-    if [ ".$opt_e" = .yes ]; then
-        if [ ".`echo "$src" | sed -e 's;^.*\\*.*$;;'`" = ".$src" ]; then
-            echo "$msgprefix:Error: Source doesn't contain wildcard ('*'): $dst" 1>&2
-            exit 1
-        fi
-        if [ ".`echo "$dst" | sed -e 's;^.*%[1-9].*$;;'`" = ".$dst" ]; then
-            echo "$msgprefix:Error: Destination doesn't contain substitution ('%N'): $dst" 1>&2
-            exit 1
-        fi
-        if [ ".$expsrc" = ".$src" ]; then
-            echo "$msgprefix:Error: Sources not found or no asterisk : $src" 1>&2
-            exit 1
-        fi
-    else
-        if [ ! -r "$src" ]; then
-            echo "$msgprefix:Error: Source not found: $src" 1>&2
-            exit 1
-        fi
-    fi
-    
-    #   determine substitution patterns
-    if [ ".$opt_e" = .yes ]; then
-        srcpat=`echo "$src" | sed -e 's/\\./\\\\./g' -e 's/;/\\;/g' -e 's;\\*;\\\\(.*\\\\);g'`
-        dstpat=`echo "$dst" | sed -e 's;%\([1-9]\);\\\\\1;g'`
-    fi
-    
-    #   iterate over source(s)
-    for onesrc in $expsrc; do
-        if [ .$opt_e = .yes ]; then
-            onedst=`echo $onesrc | sed -e "s;$srcpat;$dstpat;"`
-        else
-            onedst="$dst"
-        fi
-        errorstatus=0
-        if [ ".$opt_v" = .yes ]; then
-            echo "$onesrc -> $onedst"
-        fi
-        if [ ".$opt_p" = .yes ]; then
-            if [ -r $onedst ]; then
-                if cmp -s $onesrc $onedst; then
-                    if [ ".$opt_t" = .yes ]; then
-                        echo "rm -f $onesrc" 1>&2
-                    fi
-                    rm -f $onesrc || errorstatus=$?
-                else
-                    if [ ".$opt_t" = .yes ]; then
-                        echo "mv -f $onesrc $onedst" 1>&2
-                    fi
-                    mv -f $onesrc $onedst || errorstatus=$?
-                fi
-            else
-                if [ ".$opt_t" = .yes ]; then
-                    echo "mv -f $onesrc $onedst" 1>&2
-                fi
-                mv -f $onesrc $onedst || errorstatus=$?
-            fi
-        else
-            if [ ".$opt_t" = .yes ]; then
-                echo "mv -f $onesrc $onedst" 1>&2
-            fi
-            mv -f $onesrc $onedst || errorstatus=$?
-        fi
-        if [ $errorstatus -ne 0 ]; then
-            break;
-        fi
-    done
-    exit $errorstatus
-    ;;
-
-install )
-    ##
-    ##  install -- Install a program, script or datafile
-    ##  Copyright (c) 1997-1999 Ralf S. Engelschall <rse@engelschall.com>
-    ##  Originally written for shtool
-    ##
-    
-    src="$1"
-    dst="$2"
-    
-    #  If destination is a directory, append the input filename
-    if [ -d $dst ]; then
-        dst=`echo "$dst" | sed -e 's:/$::'`
-        dstfile=`echo "$src" | sed -e 's;.*/\([^/]*\)$;\1;'`
-        dst="$dst/$dstfile"
-    fi
-    
-    #  Add a possible extension to src and dst
-    if [ ".$opt_e" != . ]; then
-        src="$src$opt_e"
-        dst="$dst$opt_e"
-    fi
-    
-    #  Check for correct arguments
-    if [ ".$src" = ".$dst" ]; then
-        echo "$msgprefix:Error: source and destination are the same" 1>&2
-        exit 1
-    fi
-    
-    #  Make a temp file name in the destination directory
-    dstdir=`echo $dst | sed -e 's;[^/]*$;;' -e 's;\(.\)/$;\1;' -e 's;^$;.;'`
-    dsttmp="$dstdir/#INST@$$#"
-    
-    #  Verbosity
-    if [ ".$opt_v" = .yes ]; then
-        echo "$src -> $dst" 1>&2
-    fi
-    
-    #  Copy or move the file name to the temp name
-    #  (because we might be not allowed to change the source)
-    if [ ".$opt_C" = .yes ]; then
-        opt_c=yes
-    fi
-    if [ ".$opt_c" = .yes ]; then
-        if [ ".$opt_t" = .yes ]; then
-            echo "cp $src $dsttmp" 1>&2
-        fi
-        cp $src $dsttmp || exit $?
-    else
-        if [ ".$opt_t" = .yes ]; then
-            echo "mv $src $dsttmp" 1>&2
-        fi
-        mv $src $dsttmp || exit $?
-    fi
-    
-    #  Adjust the target file
-    #  (we do chmod last to preserve setuid bits)
-    if [ ".$opt_s" = .yes ]; then
-        if [ ".$opt_t" = .yes ]; then
-            echo "strip $dsttmp" 1>&2
-        fi
-        strip $dsttmp || exit $?
-    fi
-    if [ ".$opt_o" != . ]; then
-        if [ ".$opt_t" = .yes ]; then
-            echo "chown $opt_o $dsttmp" 1>&2
-        fi
-        chown $opt_o $dsttmp || exit $?
-    fi
-    if [ ".$opt_g" != . ]; then
-        if [ ".$opt_t" = .yes ]; then
-            echo "chgrp $opt_g $dsttmp" 1>&2
-        fi
-        chgrp $opt_g $dsttmp || exit $?
-    fi
-    if [ ".$opt_m" != . ]; then
-        if [ ".$opt_t" = .yes ]; then
-            echo "chmod $opt_m $dsttmp" 1>&2
-        fi
-        chmod $opt_m $dsttmp || exit $?
-    fi
-    
-    #   Determine whether to do a quick install
-    #   (has to be done _after_ the strip was already done)
-    quick=no
-    if [ ".$opt_C" = .yes ]; then
-        if [ -r $dst ]; then
-            if cmp -s $src $dst; then
-                quick=yes
-            fi
-        fi
-    fi
-    
-    #   Finally install the file to the real destination
-    if [ $quick = yes ]; then
-        if [ ".$opt_t" = .yes ]; then
-            echo "rm -f $dsttmp" 1>&2
-        fi
-        rm -f $dsttmp
-    else
-        if [ ".$opt_t" = .yes ]; then
-            echo "rm -f $dst && mv $dsttmp $dst" 1>&2
-        fi
-        rm -f $dst && mv $dsttmp $dst
-    fi
-    ;;
-
-mkdir )
-    ##
-    ##  mkdir -- Make one or more directories
-    ##  Copyright (c) 1996-1999 Ralf S. Engelschall <rse@engelschall.com>
-    ##  Originally written for public domain by Noah Friedman <friedman@prep.ai.mit.edu>
-    ##  Cleaned up and enhanced for shtool
-    ##
-    
-    errstatus=0
-    for p in ${1+"$@"}; do
-        #   when the directory already exists...
-        if [ -d "$p" ]; then
-            if [ ".$opt_f" = .no ]; then
-                echo "$msgprefix:Error: file exists: $p" 1>&2
-                errstatus=1
-                break
-            else
-                continue
-            fi
-        fi
-        #   when the directory has to be created
-        if [ ".$opt_p" = .no ]; then
-            if [ ".$opt_t" = .yes ]; then
-                echo "mkdir $p" 1>&2
-            fi
-            mkdir $p || errstatus=$?
-        else
-            #   the smart situation
-            set fnord `echo ":$p" |\
-                       sed -e 's/^:\//%/' \
-                           -e 's/^://' \
-                           -e 's/\// /g' \
-                           -e 's/^%/\//'`
-            shift
-            pathcomp=
-            for d in ${1+"$@"}; do
-                pathcomp="$pathcomp$d"
-                case "$pathcomp" in
-                    -* ) pathcomp="./$pathcomp" ;;
-                esac
-                if [ ! -d "$pathcomp" ]; then
-                    if [ ".$opt_t" = .yes ]; then
-                        echo "mkdir $pathcomp" 1>&2
-                    fi
-                    mkdir $pathcomp || errstatus=$?
-                    if [ ".$opt_m" != . ]; then
-                        if [ ".$opt_t" = .yes ]; then
-                            echo "chmod $opt_m $pathcomp" 1>&2
-                        fi
-                        chmod $opt_m $pathcomp || errstatus=$?
-                    fi
-                fi
-                pathcomp="$pathcomp/"
-            done
-        fi
-    done
-    exit $errstatus
-    ;;
-
-mkln )
-    ##
-    ##  mkln -- Make link with calculation of relative paths
-    ##  Copyright (c) 1999 Ralf S. Engelschall <rse@engelschall.com>
-    ##  Originally written for shtool
-    ##
-    
-    args=$?
-    srcs=""
-    while [ $# -gt 1 ]; do
-        srcs="$srcs $1"
-        shift
-    done
-    dst="$1"
-    if [ ! -d $dst ]; then
-        if [ $args -gt 2 ]; then
-            echo "$msgprefix:Error: multiple sources not allowed when target isn't a directory" 1>&2
-            exit 1
-        fi
-    fi
-    
-    #   determine link options
-    lnopt=""
-    if [ ".$opt_f" = .yes ]; then
-        lnopt="$lnopt -f"
-    fi
-    if [ ".$opt_s" = .yes ]; then
-        lnopt="$lnopt -s"
-    fi
-    
-    #   iterate over sources
-    for src in $srcs; do
-        #   determine if one of the paths is an absolute path,
-        #   because then we _have_ to use an absolute symlink
-        oneisabs=0
-        srcisabs=0
-        dstisabs=0
-        case $src in
-            /* ) oneisabs=1; srcisabs=1 ;;
-        esac
-        case $dst in
-            /* ) oneisabs=1; dstisabs=1 ;;
-        esac
-    
-        #   split source and destination into dir and base name
-        if [ -d $src ]; then
-            srcdir=`echo $src | sed -e 's;/*$;;'`
-            srcbase=""
-        else
-            srcdir=`echo  $src | sed -e 's;^[^/]*$;;' -e 's;^\(.*/\)[^/]*$;\1;' -e 's;\(.\)/$;\1;'`
-            srcbase=`echo $src | sed -e 's;.*/\([^/]*\)$;\1;'`
-        fi
-        if [ -d $dst ]; then
-            dstdir=`echo $dst | sed -e 's;/*$;;'`
-            dstbase=""
-        else
-            dstdir=`echo  $dst | sed -e 's;^[^/]*$;;' -e 's;^\(.*/\)[^/]*$;\1;' -e 's;\(.\)/$;\1;'`
-            dstbase=`echo $dst | sed -e 's;.*/\([^/]*\)$;\1;'`
-        fi
-    
-        #   consistency check
-        if [ ".$dstdir" != . ]; then
-            if [ ! -d $dstdir ]; then
-                echo "$msgprefix:Error: destination directory not found: $dstdir" 1>&2
-                exit 1
-            fi
-        fi
-    
-        #   make sure the source is reachable from the destination
-        if [ $dstisabs = 1 ]; then
-            if [ $srcisabs = 0 ]; then
-                if [ -d $srcdir ]; then
-                    srcdir="`cd $srcdir; pwd | sed -e 's;/*$;;'`"
-                    srcisabs=1
-                    oneisabs=1
-                fi
-            fi
-        fi
-    
-        #   split away a common prefix
-        prefix=""
-        if [ ".$srcdir" = ".$dstdir" ] && [ ".$srcdir" != . ]; then
-            prefix="$srcdir/"
-            srcdir=""
-            dstdir=""
-        else
-            while [ ".$srcdir" != . ] && [ ".$dstdir" != . ]; do
-                presrc=`echo $srcdir | sed -e 's;^\([^/]*\)/.*;\1;'`
-                predst=`echo $dstdir | sed -e 's;^\([^/]*\)/.*;\1;'`
-                if [ ".$presrc" != ".$predst" ]; then
-                    break
-                fi
-                prefix="$prefix$presrc/"
-                srcdir=`echo $srcdir | sed -e 's;^[^/]*/*;;'`
-                dstdir=`echo $dstdir | sed -e 's;^[^/]*/*;;'`
-            done
-        fi
-    
-        #   destination prefix is just the common prefix
-        dstpre="$prefix"
-    
-        #   determine source prefix which is the reverse directory
-        #   step-up corresponding to the destination directory
-        srcpre=""
-        if [ $oneisabs = 0 ] || [ ".$prefix" != . -a ".$prefix" != ./ ]; then
-            pl="$dstdir/"
-            OIFS="$IFS"; IFS='/'
-            for pe in $pl; do
-                [ ".$pe" = . ] && continue
-                srcpre="../$srcpre"
-            done
-            IFS="$OIFS"
-        else
-            if [ $srcisabs = 1 ]; then
-                srcpre="$prefix"
-            fi
-        fi
-    
-        #   determine destination symlink name
-        if [ ".$dstbase" = . ]; then
-            if [ ".$srcbase" != . ]; then
-                dstbase="$srcbase"
-            else
-                dstbase=`echo "$prefix$srcdir" | sed -e 's;/*$;;' -e 's;.*/\([^/]*\)$;\1;'`
-            fi
-        fi
-    
-        #   now finalize source and destination directory paths
-        srcdir=`echo $srcdir | sed -e 's;\([^/]\)$;\1/;'`
-        dstdir=`echo $dstdir | sed -e 's;\([^/]\)$;\1/;'`
-    
-        #   run the final link command
-        if [ ".$opt_t" = .yes ]; then
-            echo "ln$lnopt $srcpre$srcdir$srcbase $dstpre$dstdir$dstbase"
-        fi
-        eval ln$lnopt $srcpre$srcdir$srcbase $dstpre$dstdir$dstbase
-    done
-    ;;
-
-mkshadow )
-    ##
-    ##  mkshadow -- Make a shadow tree
-    ##  Copyright (c) 1998-1999 Ralf S. Engelschall <rse@engelschall.com>
-    ##  Originally written for Apache
-    ##
-    
-    #   source and destination directory
-    src=`echo "$1" | sed -e 's:/$::'`
-    dst=`echo "$2" | sed -e 's:/$::'`
-    
-    #   check whether source exists
-    if [ ! -d $src ]; then
-        echo "$msgprefix:Error: source directory not found: \`$src'" 1>&2
-        exit 1
-    fi
-    
-    #   determine if one of the paths is an absolute path,
-    #   because then we have to use an absolute symlink
-    oneisabs=0
-    case $src in
-        /* ) oneisabs=1 ;;
-    esac
-    case $dst in
-        /* ) oneisabs=1 ;;
-    esac
-    
-    #   determine reverse directory for destination directory
-    dstrevdir=''
-    if [ $oneisabs = 0 ]; then
-        #   (inlined fp2rp)
-        OIFS="$IFS"; IFS='/'
-        for pe in $dst; do
-            dstrevdir="../$dstrevdir"
-        done
-        IFS="$OIFS"
-    else
-        src="`cd $src; pwd`";
-    fi
-    
-    #   create directory tree at destination
-    if [ ! -d $dst ]; then
-        if [ ".$opt_t" = .yes ]; then
-            echo "mkdir $dst" 1>&2
-        fi
-        mkdir $dst
-    fi
-    if [ ".$opt_a" = .yes ]; then
-        DIRS=`cd $src; find . -type d -print |\
-              sed -e '/^\.$/d' -e 's:^\./::'`
-    else
-        DIRS=`cd $src; find . -type d -print |\
-              sed -e '/\/CVS/d' -e '/^\.$/d' -e 's:^\./::'`
-    fi
-    for dir in $DIRS; do
-        if [ ".$opt_t" = .yes ]; then
-            echo "mkdir $dst/$dir" 1>&2
-        fi
-        mkdir $dst/$dir
-    done
-    
-    #   fill directory tree with symlinks to files
-    if [ ".$opt_a" = .yes ]; then
-        FILES="`cd $src; find . -depth -print |\
-                sed -e 's/^\.\///'`"
-    else
-        FILES="`cd $src; find . -depth -print |\
-                sed -e '/\.o$/d' -e '/\.a$/d' -e '/\.so$/d' \
-                    -e '/\.cvsignore$/d' -e '/\/CVS/d' \
-                    -e '/\/\.#/d' -e '/\.orig$/d' \
-                    -e 's/^\.\///'`"
-    fi
-    for file in $FILES; do
-         #  don't use `-type f' above for find because of symlinks
-         if [ -d "$src/$file" ]; then
-             continue
-         fi
-         basename=`echo $file | sed -e 's:^.*/::'`
-         dir=`echo $file | sed -e 's:[^/]*$::' -e 's:/$::' -e 's:$:/:' -e 's:^/$::'`
-         from=`echo "$src/$file" | sed -e 's/^\.\///'`
-         to="$dst/$dir$basename"
-         if [ $oneisabs = 0 ]; then
-             if [ ".$dir" != . ]; then
-                 subdir=`echo $dir | sed -e 's:/$::'`
-                 #   (inlined fp2rp)
-                 revdir=''
-                 OIFS="$IFS"; IFS='/'
-                 for pe in $subdir; do
-                     revdir="../$revdir"
-                 done
-                 IFS="$OIFS"
-                 #   finalize from
-                 from="$revdir$from"
-             fi
-             from="$dstrevdir$from"
-         fi
-         if [ ".$opt_v" = .yes ]; then
-             echo "    $to" 1>&2
-         fi
-         if [ ".$opt_t" = .yes ]; then
-             echo "ln -s $from $to" 1>&2
-         fi
-         ln -s $from $to
-    done
-    ;;
-
-fixperm )
-    ##
-    ##  fixperm -- Fix file permissions inside a source tree
-    ##  Copyright (c) 1996-1999 Ralf S. Engelschall <rse@engelschall.com>
-    ##  Originally written for ePerl
-    ##
-    
-    paths="$*"
-    
-    #   check whether the test command supports the -x option
-    cat >$tmpfile <<EOT
-if [ -x / ] || [ -x /bin ] || [ -x /bin/ls ]; then
-    exit 0
-fi
-exit 1
-EOT
-    if sh $tmpfile 2>/dev/null; then
-        minusx="-x"
-    else
-        minusx="-r"
-    fi
-    rm -f $tmpfile
-    
-    #   iterate over paths
-    for p in $paths; do
-        for file in `find $p -depth -print`; do
-            if [ -f $file ]; then
-                if [ $minusx $file ]; then
-                    if [ ".$opt_v" = .yes ]; then
-                        echo "-rwxrwxr-x $file" 2>&1
-                    fi
-                    if [ ".$opt_t" = .yes ]; then
-                        echo "chmod 775 $file" 2>&1
-                    fi
-                    chmod 775 $file
-                else
-                    if [ ".$opt_v" = .yes ]; then
-                        echo "-rw-rw-r-- $file" 2>&1
-                    fi
-                    if [ ".$opt_t" = .yes ]; then
-                        echo "chmod 664 $file" 2>&1
-                    fi
-                    chmod 664 $file
-                fi
-                continue
-            fi
-            if [ -d $file ]; then
-                if [ ".$opt_v" = .yes ]; then
-                    echo "drwxrwxr-x $file" 2>&1
-                fi
-                if [ ".$opt_t" = .yes ]; then
-                    echo "chmod 775 $file" 2>&1
-                fi
-                chmod 775 $file
-                continue
-            fi
-            if [ ".$opt_v" = .yes ]; then
-                echo "?????????? $file" 2>&1
-            fi
-        done
-    done
-    ;;
-
-tarball )
-    ##
-    ##  tarball -- Roll distribution tarballs
-    ##  Copyright (c) 1999 Ralf S. Engelschall <rse@engelschall.com>
-    ##  Originally written for shtool
-    ##
-    
-    srcs="$*"
-    
-    #   check whether the test command supports the -x option
-    cat >$tmpfile <<EOT
-if [ -x / ] || [ -x /bin ] || [ -x /bin/ls ]; then
-    exit 0
-fi
-exit 1
-EOT
-    if sh $tmpfile 2>/dev/null; then
-        minusx="-x"
-    else
-        minusx="-r"
-    fi
-    rm -f $tmpfile
-    
-    #   find the tools
-    paths="`echo $PATH |\
-            sed -e 's%/*:%:%g' -e 's%/*$%%' \
-                -e 's/^:/.:/' -e 's/::/:.:/g' -e 's/:$/:./' \
-                -e 's/:/ /g'`"
-    for spec in find:gfind,find tar:gtar,tar tardy:tardy,tarcust; do
-        prg=`echo $spec | sed -e 's/:.*$//'`
-        tools=`echo $spec | sed -e 's/^.*://'`
-        eval "prg_${prg}=''"
-        #   iterate over tools
-        for tool in `echo $tools | sed -e 's/,/ /g'`; do
-            #   iterate over paths
-            for path in $paths; do
-                if [ $minusx "$path/$tool" ] && [ ! -d "$path/$tool" ]; then
-                    eval "prg_${prg}=\"$path/$tool\""
-                    break
-                fi
-            done
-            eval "val=\$prg_${prg}"
-            if [ ".$val" != . ]; then
-                break
-            fi
-        done
-    done
-    
-    #   expand source paths
-    exclude=''
-    for pat in `echo $opt_e | sed 's/,/ /g'`; do
-        exclude="$exclude | grep -v '$pat'"
-    done
-    if [ ".$opt_t" = .yes ]; then
-        echo "cp /dev/null $tmpfile.lst" 1>&2
-    fi
-    cp /dev/null $tmpfile.lst
-    for src in $srcs; do
-        if [ -d $src ]; then
-            if [ ".$opt_t" = .yes ]; then
-                echo "(cd $src && $prg_find . -type f -depth -print) | sed -e 's:^\\.\$::' -e 's:^\\./::' | cat $exclude >>$tmpfile.lst" 1>&2
-            fi
-            (cd $src && find . -type f -depth -print) |\
-            sed -e 's:^\.$::' -e 's:^\./::' | eval cat $exclude >>$tmpfile.lst
-        else
-            if [ ".$opt_t" = .yes ]; then
-                echo "echo $src >>$tmpfile.lst" 1>&2
-            fi
-            echo $src >>$tmpfile.lst
-        fi
-    done
-    sort <$tmpfile.lst >$tmpfile.lst.n
-    mv $tmpfile.lst.n $tmpfile.lst
-    if [ ".$opt_v" = .yes ]; then
-        cat $tmpfile.lst | sed -e 's/^/  /' 1>&2
-    fi
-    
-    #   determine tarball file and directory name
-    if [ ".$opt_o" != . ]; then
-        tarfile="$opt_o"
-        if [ ".$opt_d" != . ]; then
-            tarname="$opt_d"
-        else
-            tarname=`echo $tarfile | sed -e 's/\.tar.*$//' -e 's;.*/\([^/]*\)$;\1;'`
-        fi
-    else
-        if [ ".$opt_d" != . ]; then
-            tarname="$opt_d"
-        elif [ -d "$from" ]; then
-            tarname=`echo $from | sed -e 's;.*/\([^/]*\)$;\1;'`
-        else
-            tarname="out"
-        fi
-        tarfile="$tarname.tar"
-    fi
-    
-    #   roll the tarball
-    compress=''
-    if [ ".$opt_c" != . ]; then
-        compress="| $opt_c"
-    fi
-    if [ ".$prg_tardy" != . ]; then
-        #   the elegant hackers way
-        tardy_opt="--prefix=$tarname"
-        tardy_opt="$tardy_opt --user_number=0 --group_number=0" # security!
-        if [ ".$opt_u" != . ]; then
-            tardy_opt="$tardy_opt --user_name=$opt_u"
-        fi
-        if [ ".$opt_g" != . ]; then
-            tardy_opt="$tardy_opt --group_name=$opt_g"
-        fi
-        if [ ".$opt_t" = .yes ]; then
-            echo "cat $tmpfile.lst | xargs $prg_tar cf - | $prg_tardy $tardy_opt | cat $compress >$tmpfile.out" 1>&2
-        fi
-        cat $tmpfile.lst |\
-        xargs $prg_tar cf - |\
-        $prg_tardy $tardy_opt |\
-        eval cat $compress >$tmpfile.out
-        if [ ".$opt_t" = .yes ]; then
-            echo "cp $tmpfile.out $tarfile" 1>&2
-        fi
-        cp $tmpfile.out $tarfile
-    else
-        #  the portable standard way
-        if [ ".$opt_t" = .yes ]; then
-            echo "mkdir $tmpdir/$tarname" 1>&2
-        fi
-        mkdir $tmpdir/$tarname || exit 1
-        if [ ".$opt_t" = .yes ]; then
-            echo "cat $tmpfile.lst | xargs $prg_tar cf - | (cd $tmpdir/$tarname && $prg_tar xf -)" 1>&2
-        fi
-        cat $tmpfile.lst |\
-        xargs $prg_tar cf - |\
-        (cd $tmpdir/$tarname && $prg_tar xf -)
-        if [ ".$opt_u" != . ]; then
-            if [ ".$opt_t" = .yes ]; then
-                echo "chown -R $opt_u $tmpdir/$tarname >/dev/null 2>&1" 2>&1
-            fi
-            chown -R $opt_u $tmpdir/$tarname >/dev/null 2>&1 ||\
-            echo "$msgprefix:Warning: cannot set user name \`$opt_u' (need root priviledges)"
-        fi
-        if [ ".$opt_g" != . ]; then
-            if [ ".$opt_t" = .yes ]; then
-                echo "chgrp -R $opt_g $tmpdir/$tarname >/dev/null 2>&1" 2>&1
-            fi
-            chgrp -R $opt_g $tmpdir/$tarname >/dev/null 2>&1 ||\
-            echo "$msgprefix:Warning: cannot set group name \`$opt_g' (need root priviledges)"
-        fi
-        if [ ".$opt_t" = .yes ]; then
-            echo "(cd $tmpdir && $prg_find $tarname -type f -depth -print | sort | xargs $prg_tar cf -) | cat $compress >$tmpfile.out" 1>&2
-        fi
-        (cd $tmpdir && $prg_find $tarname -type f -depth -print | sort | xargs $prg_tar cf -) |\
-        eval cat $compress >$tmpfile.out
-        if [ ".$opt_t" = .yes ]; then
-            echo "cp $tmpfile.out $tarfile" 1>&2
-        fi
-        cp $tmpfile.out $tarfile
-        if [ ".$opt_t" = .yes ]; then
-            echo "rm -rf $tmpdir/$tarname" 1>&2
-        fi
-        rm -rf $tmpdir/$tarname
-    fi
-    
-    #   cleanup
-    if [ ".$opt_t" = .yes ]; then
-        echo "rm -f $tmpfile.lst $tmpfile.out" 1>&2
-    fi
-    rm -f $tmpfile.lst $tmpfile.out
-    ;;
-
-guessos )
-    ##
-    ##  guessos -- Simple OS/platform guesser
-    ##  Copyright (c) 1996-2000 The Apache Group, http://www.apache.org/
-    ##  The Apache license applies (see http://www.apache.org/docs/LICENSE)
-    ##  Originally written for Apache
-    ##
-    
-    MACHINE=`(uname -m) 2>/dev/null` || MACHINE="unknown"
-    RELEASE=`(uname -r) 2>/dev/null` || RELEASE="unknown"
-     SYSTEM=`(uname -s) 2>/dev/null` ||  SYSTEM="unknown"
-    VERSION=`(uname -v) 2>/dev/null` || VERSION="unknown"
-    
-    XREL=`(uname -X) 2>/dev/null | grep "^Release" | awk '{print $3}'`
-    if [ "x$XREL" != "x" ]; then
-        if [ -f /etc/kconfig ]; then
-            case "$XREL" in
-                4.0|4.1) echo "${MACHINE}-whatever-isc4"; exit 0 ;;
-            esac
-        else
-        case "$XREL" in
-            3.2v4.2)
-                echo "whatever-whatever-sco3"; exit 0
-                ;;
-            3.2v5.0*)
-                echo "whatever-whatever-sco5"; exit 0
-                ;;
-            4.2MP)
-                if [ "x$VERSION" = "x2.1.1" ]; then
-                    echo "${MACHINE}-whatever-unixware211"; exit 0
-                elif [ "x$VERSION" = "x2.1.2" ]; then
-                    echo "${MACHINE}-whatever-unixware212"; exit 0
-                else
-                    echo "${MACHINE}-whatever-unixware2"; exit 0
-                fi
-                ;;
-            4.2)
-                echo "whatever-whatever-unixware1"; exit 0
-                ;;
-            5)
-                case "$VERSION" in
-                    7*) echo "${MACHINE}-whatever-unixware7"; exit 0 ;;
-                esac
-                ;;
-        esac
-        fi
-    fi
-    case "${SYSTEM}:${RELEASE}:${VERSION}:${MACHINE}" in
-        MiNT:*)
-            echo "m68k-atari-mint"; exit 0
-            ;;
-        A/UX:*)
-            echo "m68k-apple-aux3"; exit 0
-            ;;
-        AIX:*)
-            MACH=`echo $MACHINE | sed -e 's;[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F];;'`
-            echo "${MACH}-ibm-aix${VERSION}.${RELEASE}"; exit 0
-            ;;
-        dgux:*)
-            echo "${MACHINE}-dg-dgux"; exit 0
-            ;;
-        HI-UX:*)
-            echo "${MACHINE}-hi-hiux"; exit 0
-            ;;
-        HP-UX:*)
-            HPUXVER=`echo ${RELEASE}|sed -e 's/[^.]*.[0B]*//'`
-            echo "${MACHINE}-hp-hpux${HPUXVER}"; exit 0
-            ;;
-        IRIX:*)
-            if [ -f /usr/lib32/mips4/libm.so ]; then
-                echo "${MACHINE}/32-sgi-irix${RELEASE}"; exit 0
-            else
-                echo "${MACHINE}-sgi-irix${RELEASE}"; exit 0
-            fi
-            ;;
-        IRIX64:*)
-            echo "${MACHINE}/64-sgi-irix${RELEASE}"; exit 0
-            ;;
-        Linux:*)
-            V='whatever'
-            case "$MACHINE" in
-                i?86) V='pc' ;;
-            esac
-            R=''
-            case "$RELEASE" in
-                [1-9].*) R=`echo $RELEASE | cut -c1` ;;
-            esac
-            echo "${MACHINE}-${V}-linux-gnu${R}"; exit 0
-            ;;
-        LynxOS:*)
-            echo "${MACHINE}-lynx-lynxos"; exit 0
-            ;;
-        BSD/386|BSD/OS:3.*)
-            echo "${MACHINE}-whatever-bsdi3"; exit 0
-            ;;
-        BSD/386:*:*:*486*|BSD/OS:*:*:*:*486*)
-            echo "i486-whatever-bsdi"; exit 0
-            ;;
-        BSD/386:*|BSD/OS:*)
-            echo "${MACHINE}-whatever-bsdi"; exit 0
-            ;;
-        FreeBSD:*)
-            VERS=`echo ${RELEASE} | sed -e 's/[-(].*//'`
-            MACH=`/sbin/sysctl -n hw.model`
-            ARCH='whatever'
-            case ${MACH} in
-               *386*       ) MACH="i386"     ;;
-               *486*       ) MACH="i486"     ;;
-               Pentium\ II*) MACH="i686"     ;;
-               Pentium*    ) MACH="i586"     ;;
-               Alpha*      ) MACH="alpha"    ;;
-               *           ) MACH="$MACHINE" ;;
-            esac
-            case ${MACH} in
-               i[0-9]86 ) ARCH="pc" ;;
-            esac
-            echo "${MACH}-${ARCH}-freebsd${VERS}"; exit 0
-            ;;
-        NetBSD:*:*:*486*)
-            echo "i486-whatever-netbsd${RELEASE}"; exit 0
-            ;;
-        NetBSD:*)
-            echo "${MACHINE}-whatever-netbsd${RELEASE}"; exit 0
-            ;;
-        OpenBSD:*)
-            echo "${MACHINE}-whatever-openbsd"; exit 0
-            ;;
-        OSF1:*:*:*alpha*)
-            VERS=`echo $RELEASE | sed -e 's;^V;;'`
-            echo "${MACHINE}-dec-osf${VERS}"; exit 0
-            ;;
-        QNX:*)
-            if [ "$VERSION" -gt 422 ]; then
-                echo "${MACHINE}-qssl-qnx32"
-            else
-                echo "${MACHINE}-qssl-qnx"
-            fi
-            exit 0
-            ;;
-        Paragon*:*:*:*)
-            echo "i860-intel-osf1"; exit 0
-            ;;
-        SunOS:5.*)
-            VERSION=`echo $RELEASE | sed -e 's;^5\.;;'`
-            echo "${MACHINE}-sun-solaris2.${VERSION}"; exit 0
-            ;;
-        SunOS:*)
-            echo "${MACHINE}-sun-sunos4"; exit 0
-            ;;
-        UNIX_System_V:4.*:*)
-            echo "${MACHINE}-whatever-sysv4"; exit 0
-            ;;
-        unix:3.0.9*:*:88k)
-            echo "${MACHINE}-encore-sysv4"; exit 0
-            ;;
-        *:4*:R4*:m88k)
-            echo "${MACHINE}-whatever-sysv4"; exit 0
-            ;;
-        UnixWare:5:99*:*)
-            # Gemini, beta release of next rev of unixware
-            echo "${MACHINE}-whatever-unixware212"; exit 0
-            ;;
-        DYNIX/ptx:4*:*)
-            echo "${MACHINE}-whatever-sysv4"; exit 0
-            ;;
-        *:4.0:3.0:[345][0-9]?? | *:4.0:3.0:3[34]??[/,]* | library:*)
-            echo "x86-ncr-sysv4"; exit 0
-            ;;
-        ULTRIX:*)
-            echo "${MACHINE}-unknown-ultrix"; exit 0
-            ;;
-        SINIX-?:* | ReliantUNIX-?:*)
-            echo "${MACHINE}-siemens-sysv4"; exit 0
-            ;;
-        POSIX*BS2000)
-            echo "${MACHINE}-siemens-sysv4"; exit 0
-            ;;
-        machten:*)
-           echo "${MACHINE}-tenon-${SYSTEM}"; exit 0;
-           ;;
-        ConvexOS:*:11.*:*)
-           echo "${MACHINE}-v11-${SYSTEM}"; exit 0;
-           ;;
-        UNIX_SV:*:*:maxion)
-           echo "${MACHINE}-ccur-sysv4"; exit 0;
-           ;;
-        PowerMAX_OS:*:*:Night_Hawk)
-           MACHINE=`uname -p`
-           echo "${MACHINE}-concurrent-powermax"; exit 0;
-           ;;
-        UNIX_SV:*)
-           if [ -d /usr/nec ];then
-               echo "mips-nec-sysv4"; exit 0;
-           fi
-           ;;
-        NonStop-UX:4.[02]*:[BC]*:*)
-           echo "${MACHINE}-tandem-sysv4"; exit 0;
-           ;;
-        Rhapsody:*:*:*)
-           case "${MACHINE}" in
-               "Power Macintosh") MACHINE=powerpc ;;
-           esac
-           echo "${MACHINE}-apple-rhapsody${RELEASE}"; exit 0
-           ;;
-        "Mac OS":*:*:*)
-           MACHINE=`uname -p`
-           echo "${MACHINE}-apple-macos${RELEASE}"; exit 0
-           ;;
-        "RISC iX":*)
-           echo "arm-whatever-riscix"; exit 0;
-           ;;
-        *:4.0:2:*)
-           echo "whatever-unisys-sysv4"; exit 0;
-           ;;
-        *:*:dcosx:NILE*)
-           echo "pyramid-pyramid-svr4"; exit 0;
-           ;;
-        *:*:*:"DRS 6000")
-           echo "drs6000-whatever-whatever"; exit 0;
-           ;;
-        AmigaOS:*:*:* )
-           echo "${MACHINE}-whatever-${SYSTEM}${RELEASE}"; exit 0
-           ;;
-    esac
-    
-    # Now NeXT
-    ISNEXT=`(hostinfo) 2>/dev/null`
-    case "$ISNEXT" in
-        *NeXT*)
-             # Swiped from a friendly uname clone for NEXT/OPEN Step.
-             NEXTOSVER="`hostinfo | sed -n 's/.*NeXT Mach \([0-9\.]*\).*/\1/p'`"
-             if [ "$NEXTOSVER" -gt 3.3 ]; then
-                 NEXTOS="openstep"
-             else
-                 NEXTOS="nextstep"
-             fi
-             NEXTREL="`hostinfo | sed -n 's/.*NeXT Mach \([0-9\.]*\).*/\1/p'`"
-             NEXTARCH=`arch`
-             echo "${NEXTARCH}-next-${NEXTOS}${NEXTREL}" ; exit 0
-             ;;
-    esac
-    
-    # Fallback
-    echo "${MACHINE}-whatever-${SYSTEM}/${RELEASE}/${VERSION}"
-    ;;
-
-arx )
-    ##
-    ##  arx -- Extended archive command
-    ##  Copyright (c) 1999 Ralf S. Engelschall <rse@engelschall.com>
-    ##  Originally written for shtool
-    ##
-    
-    ar_prg="$opt_C"
-    ar_cmd="$1"; shift
-    archive="$1"; shift
-    files="$*"
-    
-    #   walk through the file list and expand archives members
-    tmpdir=`echo $archive | sed -e 's;[^/]*$;.arx;'`
-    nfiles=''
-    if [ ".$files" != . ]; then
-        for file in $files; do
-            if [ ! -f $file ]; then
-                echo "$msgprefix:Error: input file not found: $file" 1>&2
-                exit 1
-            fi
-            case $file in
-                *.a )
-                    if [ ! -d $tmpdir ]; then
-                        if [ ".$opt_t" = .yes ]; then
-                            echo "mkdir $tmpdir" 1>&2
-                        fi
-                        mkdir $tmpdir
-                    fi
-                    case $tmpdir in
-                         .arx )
-                             from="../$file"
-                             ;;
-                         * )
-                             dir=`echo $file | sed -e 's;[^/]*$;;' -e 's;\(.\)/$;\1;' -e 's;^$;.;'`
-                             base=`echo $file | sed -e 's;.*/\([^/]*\)$;\1;'`
-                             from="`cd $dir; pwd`/$base"
-                             ;;
-                    esac
-                    if [ ".$opt_t" = .yes ]; then
-                        echo "(cd $tmpdir && $ar_prg x $from)" 1>&2
-                    fi
-                    (cd $tmpdir && eval $ar_prg x $from)
-                    if [ $? -ne 0 ]; then
-                        echo "$msgprefix:Error: member extraction failed for archive: $file" 1>&2
-                        exit 1
-                    fi
-                    for member in - `eval $ar_prg t $file`; do
-                        [ ".$member" = .- ] && continue
-                        nfiles="$nfiles $tmpdir/$member"
-                    done
-                    ;;
-                * )
-                    nfiles="$nfiles $file"
-                    ;;
-            esac
-        done
-    fi
-    
-    #   run the final archive command
-    if [ ".$opt_t" = .yes ]; then
-        echo "$ar_prg $ar_cmd $archive $nfiles" 1>&2
-    fi
-    eval $ar_prg $ar_cmd $archive $nfiles
-    if [ $? -ne 0 ]; then
-        echo "$msgprefix:Error: archive command failed" 1>&2
-        exit $?
-    fi
-    
-    #   cleanup and die gracefully
-    if [ -d $tmpdir ]; then
-        if [ ".$opt_t" = .yes ]; then
-            echo "rm -rf $tmpdir" 1>&2
-        fi
-        rm -rf $tmpdir
-    fi
-    ;;
-
-slo )
-    ##
-    ##  slo -- Separate linker options by library class
-    ##  Copyright (c) 1998-1999 Ralf S. Engelschall <rse@engelschall.com>
-    ##  Originally written for Apache
-    ##
-    
-    DIFS="$IFS"
-    
-    #   parse out -L and -l options from command line
-    DIRS=''
-    LIBS=''
-    ARGV=''
-    optprev=''
-    for opt
-    do
-        #   concatenate with previous option if exists
-        if [ ".$optprev" != . ]; then
-            opt="${optprev}${opt}";
-            optprev=''
-        fi
-        #   remember options for arg when used stand-alone
-        if [ ".$opt" = ".-L" -o ".$opt" = ".-l" ]; then
-            optprev="$opt"
-            continue;
-        fi
-        #   split argument into option plus option argument
-        arg="`echo $opt | cut -c3-`"
-        opt="`echo $opt | cut -c1-2`"
-        #   store into containers
-        case $opt in
-            -L) DIRS="$DIRS:$arg" ;;
-            -l) LIBS="$LIBS:$arg" ;;
-             *) ARGV="$ARGV $opt" ;;
-        esac
-    done
-    
-    #   set linker default directories
-    DIRS_DEFAULT='/lib:/usr/lib'
-    if [ ".$LD_LIBRARY_PATH" != . ]; then
-        DIRS_DEFAULT="$DIRS_DEFAULT:$LD_LIBRARY_PATH"
-    fi
-    
-    #   sort options by class
-    DIRS_OBJ=''
-    LIBS_OBJ=''
-    DIRS_PIC=''
-    LIBS_PIC=''
-    DIRS_DSO=''
-    LIBS_DSO=''
-    
-    #    for each library...
-    OIFS="$IFS" IFS=':'
-    for lib in $LIBS; do
-        [ ".$lib" = . ] && continue
-    
-        found='no'
-        found_indefdir='no'
-        found_type=''
-        found_dir=''
-    
-        #    for each directory...
-        OIFS2="$IFS" IFS=":$DIFS"
-        for dir in ${DIRS} switch-to-defdirs ${DIRS_DEFAULT}; do
-            [ ".$dir" = . ] && continue
-            [ ".$dir" = .switch-to-defdirs ] && found_indefdir=yes
-            [ ! -d $dir ] && continue
-    
-            #    search the file
-            OIFS3="$IFS" IFS="$DIFS"
-            for file in '' `cd $dir && ls lib${lib}.* 2>/dev/null`; do
-                 [ ".$file" = . ] && continue
-                 case $file in
-                     *.so|*.so.[0-9]*|*.sl|*.sl.[0-9]* )
-                          found=yes;
-                          found_type=DSO;
-                          break
-                          ;;
-                     *.lo|*.la )
-                          found=yes;
-                          found_type=PIC
-                          ;;
-                     *.a )
-                          if [ ".$found_type" = . ]; then
-                              found=yes
-                              found_type=OBJ
-                          fi
-                          ;;
-                 esac
-            done
-            IFS="$OIFS3"
-            if [ ".$found" = .yes ]; then
-                found_dir="$dir"
-                break
-            fi
-        done
-        IFS="$OIFS2"
-    
-        if [ ".$found" = .yes ]; then
-            if [ ".$found_indefdir" != .yes ]; then
-                eval "dirlist=\"\${DIRS_${found_type}}:\""
-                if [ ".`echo \"$dirlist\" | fgrep :$found_dir:`" = . ]; then
-                    eval "DIRS_${found_type}=\"\$DIRS_${found_type}:${found_dir}\""
-                fi
-                eval "LIBS_${found_type}=\"\$LIBS_${found_type}:$lib\""
-            else
-                eval "LIBS_${found_type}=\"\$LIBS_${found_type}:$lib\""
-            fi
-        else
-            LIBS_OBJ="$LIBS_OBJ:$lib"
-            #dirlist="`echo $DIRS $DIRS_DEFAULT | sed -e 's/:/ /g'`"
-            #echo "slo:Warning: library \"$lib\" not found in any of the following dirs:" 2>&1
-            #echo "slo:Warning: $dirlist" 1>&1
-        fi
-    done
-    IFS="$OIFS"
-    
-    #   also pass-through unused dirs even if it's useless
-    OIFS="$IFS" IFS=':'
-    for dir in $DIRS; do
-        dirlist="${DIRS_OBJ}:${DIRS_PIC}:${DIRS_DSO}:"
-        if [ ".`echo \"$dirlist\" | fgrep :$dir:`" = . ]; then
-            DIRS_OBJ="$DIRS_OBJ:$dir"
-        fi
-    done
-    IFS="$OIFS"
-    
-    #   reassemble the options but separated by type
-    for type in OBJ PIC DSO; do
-        OIFS="$IFS" IFS=':'
-        eval "libs=\"\$LIBS_${type}\""
-        opts=''
-        for lib in $libs; do
-            [ ".$lib" = . ] && continue
-            opts="$opts -l$lib"
-        done
-        eval "LIBS_${type}=\"$opts\""
-    
-        eval "dirs=\"\$DIRS_${type}\""
-        opts=''
-        for dir in $dirs; do
-            [ ".$dir" = . ] && continue
-            opts="$opts -L$dir"
-        done
-        eval "DIRS_${type}=\"$opts\""
-        IFS="$OIFS"
-    done
-    
-    #   give back results
-    for var in ARGV DIRS_OBJ LIBS_OBJ DIRS_PIC LIBS_PIC DIRS_DSO LIBS_DSO; do
-        eval "val=\"\$${var}\""
-        val="`echo $val | sed -e 's/^ *//'`"
-        echo "SLO_${var}=\"${val}\""
-    done
-    ;;
-
-scpp )
-    ##
-    ##  scpp -- Sharing C Pre-Processor
-    ##  Copyright (c) 1999 Ralf S. Engelschall <rse@engelschall.com>
-    ##  Originally written for GNU pth
-    ##
-    
-    srcs="$*"
-    output="${opt_o}.n"
-    
-    #   find a reasonable Awk
-    awk=''
-    paths=`echo $PATH |\
-           sed -e 's%/*:%:%g' -e 's%/$%%' \
-               -e 's/^:/.:/' -e 's/::/:.:/g' -e 's/:$/:./' \
-               -e 's/:/ /g'`
-    for name in gawk nawk awk; do
-        for path in $paths; do
-            if [ -r "$path/$name" ]; then
-                awk="$path/$name"
-                break
-            fi
-        done
-        if [ ".$awk" != . ]; then
-            break
-        fi
-    done
-    if [ ".$awk" = . ]; then
-        echo "$msgprefix:Error: cannot find a reasonable Awk" 1>&2
-        exit 1
-    fi
-    
-    #   parse source file(s)
-    if [ ".$opt_v" = .yes ]; then
-        echo "Parsing:" | $awk '{ printf("%s", $0); }' 1>&2
-    fi
-    for src in $srcs; do
-        if [ ".$opt_v" = .yes ]; then
-            echo $src | $awk '{ printf(" %s", $0); }' 1>&2
-        fi
-        $awk <$src '
-           BEGIN {
-               ln    = 0;
-               fln   = 0;
-               level = 0;
-               mode  = "";
-               store = "";
-           }
-           {
-               ln++;
-           }
-           /^#if.*/ {
-               level++;
-           }
-           /^#if [a-zA-Z_][a-zA-Z0-9_]* *$/ {
-               if ($2 == define) {
-                   mode = "D";
-                   printf("D:#line %d \"%s\"\n", ln, src);
-                   next;
-               }
-           }
-           /^#endif.*/ {
-               level--;
-               if (mode == "D" && level == 0) {
-                   mode = "";
-                   next;
-               }
-           }
-           /^[a-zA-Z_][a-zA-Z0-9_].*;.*/ {
-               if ($1 == class) {
-                   printf("V:#line %d \"%s\"\n", ln, src);
-                   printf("V:%s\n", $0);
-                   printf("J:%s\n", $0);
-                   next;
-               }
-           }
-           /^[a-zA-Z_][a-zA-Z0-9_].*=.*/ {
-               if ($1 == class) {
-                   printf("V:#line %d \"%s\"\n", ln, src);
-                   printf("V:%s\n", $0);
-                   printf("J:%s\n", $0);
-                   next;
-               }
-           }
-           /^[a-zA-Z_][a-zA-Z0-9_]*/ {
-               if ($1 == class) {
-                   fln = ln;
-                   store = $0;
-                   mode = "F";
-                   next;
-               }
-           }
-           /^\{ *$/ {
-               if (mode == "F") {
-                   printf("F:#line %d \"%s\"\n", fln, src);
-                   printf("F:%s;\n", store);
-                   printf("I:%s;\n", store);
-                   store = "";
-                   mode = "";
-                   next;
-               }
-           }
-           {
-               if (mode == "D")
-                   printf("D:%s\n", $0);
-               else if (mode == "F")
-                   store = store " " $0;
-           }
-        ' "src=$src" "define=$opt_D" "class=$opt_C" >>$tmpfile
-    done
-    if [ ".$opt_v" = .yes ]; then
-        echo "" 1>&2
-    fi
-    
-    #   start generating output header
-    echo "/* $opt_o -- autogenerated from $opt_t, DO NOT EDIT! */" >$output
-    echo "#line 1 \"$opt_t\"" >>$output
-    sed <$opt_t -e "1,/^${opt_M} *\$/p" -e 'd' |\
-    sed -e "/^${opt_M} *\$/d" >>$output
-    
-    #   merge in the define blocks
-    grep '^D:' $tmpfile | sed -e 's/^D://' >>$output
-    
-    #   generate standard prolog
-    echo "#line 1 \"_ON_THE_FLY_\"" >>$output
-    echo "" >>$output
-    echo "/* make sure the scpp source extensions are skipped */" >>$output
-    echo "#define $opt_D 0" >>$output
-    echo "#define $opt_C /**/" >>$output
-    
-    #   generate namespace hiding for variables
-    echo "" >>$output
-    echo "/* move intern variables to hidden namespace */" >>$output
-    grep '^J:' $tmpfile | sed >>$output \
-        -e 's/^J://' \
-        -e 's/  */ /g' \
-        -e 's/^[^=;]*[ *]\([a-zA-Z0-9_]*\)\[\];.*$/#define \1 __\1/' \
-        -e 's/^[^=;]*[ *]\([a-zA-Z0-9_]*\)\[\] =.*$/#define \1 __\1/' \
-        -e 's/^[^=;]*[ *]\([a-zA-Z0-9_]*\);.*$/#define \1 __\1/' \
-        -e 's/^[^=;]*[ *]\([a-zA-Z0-9_]*\) =.*$/#define \1 __\1/'
-    
-    #   generate namespace hiding for functions
-    echo "" >>$output
-    echo "/* move intern functions to hidden namespace */" >>$output
-    grep '^I:' $tmpfile | sed >>$output \
-        -e 's/^I://' \
-        -e 's/\([ (]\) */\1/g' \
-        -e 's/ *\([),]\)/\1/g' \
-        -e 's/^[^(]*[ *]\([a-zA-Z0-9_]*\)(.*$/#define \1 __\1/'
-    
-    #   generate prototypes for variables
-    echo "" >>$output
-    echo "/* prototypes for intern variables */" >>$output
-    grep '^V:' $tmpfile | sed >>$output \
-        -e 's/^V://' \
-        -e 's/  */ /g' \
-        -e 's/^\([^=;]*[ *][a-zA-Z0-9_]*\[\]\);.*$/\1;/' \
-        -e 's/^\([^=;]*[ *][a-zA-Z0-9_]*\[\]\) =.*$/\1;/' \
-        -e 's/^\([^=;]*[ *][a-zA-Z0-9_]*\);.*$/\1;/' \
-        -e 's/^\([^=;]*[ *][a-zA-Z0-9_]*\) =.*$/\1;/' \
-        -e 's/ ;/;/g' \
-        -e "s/^$opt_C /extern /"
-    
-    #   generate prototypes for functions
-    echo "" >>$output
-    echo "/* prototypes for intern functions */" >>$output
-    grep '^F:' $tmpfile | sed >>$output \
-        -e 's/^F://' \
-        -e 's/\([ (]\) */\1/g' \
-        -e 's/ *\([),]\)/\1/g' \
-        -e 's/\([* ]\)[a-zA-Z0-9_]*,/\1,/g' \
-        -e 's/\([* ]\)[a-zA-Z0-9_]*);/\1);/g' \
-        -e 's/(\*[a-zA-Z0-9_]*)(/(*)(/g' \
-        -e 's/\([ (]\) */\1/g' \
-        -e 's/ *\([),]\)/\1/g' \
-        -e "s/^$opt_C /extern /"
-    
-    #   finish generating output header
-    n=`(echo ''; sed <$opt_t -e "1,/^${opt_M} *\$/p" -e 'd') |\
-       wc -l | sed -e 's;^ *\([0-9]*\) *$;\1;'`
-    echo "#line $n \"$opt_t\"" >>$output
-    sed <$opt_t -e "/^${opt_M} *\$/,\$p" -e 'd' |\
-    sed -e "/^${opt_M} *\$/d" >>$output
-    
-    #   create final output file
-    if [ -f $opt_o ]; then
-        if [ ".$opt_p" = .yes ]; then
-            grep -v '^#line' $opt_o  >$tmpfile.o
-            grep -v '^#line' $output >$tmpfile.n
-            out_old="$tmpfile.o"
-            out_new="$tmpfile.n"
-        else
-            out_old="$opt_o"
-            out_new="$output"
-        fi
-        if cmp -s $out_old $out_new; then
-            :
-        else
-            cp $output $opt_o
-        fi
-    else
-        cp $output $opt_o
-    fi
-    rm -f $output
-    rm -f $tmpfile $tmpfile.* >/dev/null 2>&1
-    ;;
-
-version )
-    ##
-    ##  version -- Generate and maintain a version information file
-    ##  Copyright (c) 1994-1999 Ralf S. Engelschall <rse@engelschall.com>
-    ##  Originally written for ePerl
-    ##
-    
-    LANGUAGE="$opt_l"
-    NAME="$opt_n"
-    PREFIX="$opt_p"
-    FULLVERSION="$opt_s"
-    INCREASE="$opt_i"
-    REPORT="$opt_d"
-    FILE="$1"
-    
-    #   determine language
-    if [ ".$LANGUAGE" = .unknown ]; then
-        case $FILE in
-            *.txt )       LANGUAGE=txt  ;;
-            *.c )         LANGUAGE=c    ;;
-            *.pl | *.pm ) LANGUAGE=perl ;;
-            * )           echo "$tool:Error: unknown language type" 1>&2; exit 1 ;;
-        esac
-    fi
-    
-    #   determine prefix from name and vice versa
-    if [ ".$PREFIX" = . -o ".$PREFIX" = .unknown ]; then
-        if [ ".$NAME" != . -a ".$NAME" != .unknown ]; then
-            PREFIX="$NAME"
-        fi
-    fi
-    if [ ".$NAME" = . -o ".$NAME" = .unknown ]; then
-        if [ ".$PREFIX" != . -a ".$PREFIX" != .unknown ]; then
-            NAME="$PREFIX"
-        fi
-    fi
-    
-    #   determine version
-    date=unknown
-    version=0
-    revision=0
-    bplevel=0
-    if [ ".$FULLVERSION" = .unknown ]; then
-        if [ -r "$FILE" ]; then
-            #   grep out current information
-            id=`grep 'Version [0-9]*.[0-9]*[.abps][0-9]* ([0-9]*-[a-zA-Z]*-[0-9]*)' $FILE | \
-                head -1 | \
-                sed -e 's%.*Version \([0-9]*\)\.\([0-9]*\)\([.abps]\)\([0-9]*\) (\([0-9]*-[a-zA-Z]*-[0-9]*\)).*%\1:\2:\3:\4:\5%'`
-            version=`echo $id | awk -F: '{ print $1 }'`
-            revision=`echo $id | awk -F: '{ print $2 }'`
-            bptype=`echo $id | awk -F: '{ print $3 }'`
-            bplevel=`echo $id | awk -F: '{ print $4 }'`
-            date=`echo $id | awk -F: '{ print $5 }'`
-            if [ .$REPORT = .NO ]; then
-                case $INCREASE in
-                    b ) bplevel=`expr $bplevel + 1`
-                        bptype=b
-                        ;;
-                    a ) bplevel=`expr $bplevel + 1`
-                        bptype=a
-                        ;;
-                    s ) bplevel=`expr $bplevel + 1`
-                        bptype=s
-                        ;;
-                    P ) bplevel=`expr $bplevel + 1`
-                        bptype=.
-                        ;;
-                    p ) bplevel=`expr $bplevel + 1`
-                        bptype=p
-                        ;;
-                    r ) revision=`expr $revision + 1`
-                        bptype=.
-                        bplevel=0
-                        ;;
-                    v ) version=`expr $version + 1`
-                        revision=0
-                        bptype=.
-                        bplevel=0
-                        ;;
-                esac
-                date=calc
-            fi
-            FULLVERSION="$version.$revision$bptype$bplevel"
-        else
-            #   intialise to first version
-            version=0
-            revision=5
-            bptype=b
-            bplevel=0
-            date=calc
-        fi
-    else
-        #   take given version
-        V=`echo $FULLVERSION | sed -e 's%\([0-9]*\)\.\([0-9]*\)\([.abps]\)\([0-9]*\).*%\1:\2:\3:\4%'`
-        version=`echo $V | awk -F: '{ print $1 }'`
-        revision=`echo $V | awk -F: '{ print $2 }'`
-        bptype=`echo $V | awk -F: '{ print $3 }'`
-        bplevel=`echo $V | awk -F: '{ print $4 }'`
-        date=calc
-    fi
-    
-    #   determine hex value of version
-    case $FULLVERSION in
-        *.*a* )
-            HEX=`echo "$FULLVERSION" | sed -e 's/a.*//' | awk -F. '{ printf("%d%02d", $1, $2); }' &&
-                 echo "$FULLVERSION" | sed -e 's/.*a//' | awk '{ printf("0%02d", $1); }'`
-            ;;
-        *.*b* )
-            HEX=`echo "$FULLVERSION" | sed -e 's/b.*//' | awk -F. '{ printf("%d%02d", $1, $2); }' &&
-                 echo "$FULLVERSION" | sed -e 's/.*b//' | awk '{ printf("1%02d", $1); }'`
-            ;;
-        *.*.* )
-            HEX=`echo "$FULLVERSION" | awk -F. '{ printf("%d%02d2%02d", $1, $2, $3); }'`
-            ;;
-    esac
-    
-    #   determine libtool version
-    case $FULLVERSION in
-        *.*a* )
-            LTV=`echo "$FULLVERSION" | sed -e 's/a.*//' | awk -F. '{ printf("%d:0", $1*10+$2); }'`
-            ;;
-        *.*b* )
-            LTV=`echo "$FULLVERSION" | sed -e 's/b.*//' | awk -F. '{ printf("%d:0", $1*10+$2); }'`
-            ;;
-        *.*.* )
-            LTV=`echo "$FULLVERSION" | awk -F. '{ printf("%d:%d", $1*10+$2, $3); }'`
-            ;;
-    esac
-    
-    #   determine string out of filename
-    #   (don't try to optimize this in any way - portability!)
-    FILESTR=`echo "$FILE" |\
-             tr 'abcdefghijklmnopqrstuvwxyz./%+' \
-                'ABCDEFGHIJKLMNOPQRSTUVWXYZ____' | sed -e 's/-/_/g'`
-    
-    #   determine date
-    if [ ".$date" = .calc ]; then
-        day=`date '+%d'`
-        month=`date '+%m'`
-        year=`date '+%Y' 2>/dev/null`
-        if [ ".$time_year" = . ]; then
-            year=`date '+%y'`
-            case $year in
-                [5-9][0-9]) year="19$year" ;;
-                [0-4][0-9]) year="20$year" ;;
-            esac
-        fi
-        case $month in
-            1|01) month='Jan' ;;
-            2|02) month='Feb' ;;
-            3|03) month='Mar' ;;
-            4|04) month='Apr' ;;
-            5|05) month='May' ;;
-            6|06) month='Jun' ;;
-            7|07) month='Jul' ;;
-            8|08) month='Aug' ;;
-            9|09) month='Sep' ;;
-              10) month='Oct' ;;
-              11) month='Nov' ;;
-              12) month='Dec' ;;
-        esac
-        date="${day}-${month}-${year}"
-    fi
-    
-    if [ .$REPORT != .NO ]; then
-        case $REPORT in
-            long )
-                echo "$version.$revision$bptype$bplevel ($date)"
-                ;;
-            short )
-                echo "$version.$revision$bptype$bplevel"
-                ;;
-            libtool )
-                echo "$LTV"
-                ;;
-            hex )
-                echo "0x$HEX"
-                ;;
-        esac
-        rm -f $tmpfile >/dev/null 2>&1
-        exit 0
-    fi
-    
-    #   create the version file according the the selected language
-    echo "new version: $version.$revision$bptype$bplevel ($date)"
-    case $LANGUAGE in
-        txt )
-            cat >$tmpfile <<'EOT'
-    
-  This is @NAME@, Version @VERSION@.@REVISION@@BPTYPE@@BPLEVEL@ (@DAY@-@MONTH@-@YEAR@)
-EOT
-            ;;
-        c )
-            cat >$tmpfile <<'EOT'
-/*
-**  @FILE@ -- Version Information
-**  [automatically generated and maintained by shtool]
-*/
-
-#ifdef _AS_HEADER
-
-#ifndef _@FILESTR@
-#define _@FILESTR@
-#define @PREFIX@_VERSION 0x@HEX@
-extern const int  @PREFIX@_Version;
-extern const char @PREFIX@_VersionStr[];
-extern const char @PREFIX@_Hello[];
-extern const char @PREFIX@_GNUVersion[];
-extern const char @PREFIX@_WhatID[];
-extern const char @PREFIX@_RCSIdentID[];
-extern const char @PREFIX@_WebID[];
-extern const char @PREFIX@_PlainID[];
-#endif /* _@FILESTR@ */
-
-#else
-
-const int  @PREFIX@_Version      = 0x@HEX@;
-const char @PREFIX@_VersionStr[] = "@VERSION@.@REVISION@@BPTYPE@@BPLEVEL@ (@DAY@-@MONTH@-@YEAR@)";
-const char @PREFIX@_Hello[]      = "This is @NAME@, Version @VERSION@.@REVISION@@BPTYPE@@BPLEVEL@ (@DAY@-@MONTH@-@YEAR@)";
-const char @PREFIX@_GNUVersion[] = "@NAME@ Version @VERSION@.@REVISION@@BPTYPE@@BPLEVEL@";
-const char @PREFIX@_WhatID[]     = "@(#)@NAME@ Version @VERSION@.@REVISION@@BPTYPE@@BPLEVEL@ (@DAY@-@MONTH@-@YEAR@)";
-const char @PREFIX@_RCSIdentID[] = "$Id: shtool,v 1.4 2000/03/31 08:36:19 fielding Exp $";
-const char @PREFIX@_WebID[]      = "@NAME@/@VERSION@.@REVISION@@BPTYPE@@BPLEVEL@";
-const char @PREFIX@_PlainID[]    = "@VERSION@.@REVISION@@BPTYPE@@BPLEVEL@";
-
-#endif
-EOT
-            ;;
-        perl )
-            cat >$tmpfile <<'EOT'
-##
-##  @FILE@ -- Version Information
-##  [automatically generated and maintained by shtool]
-##
-
-$@PREFIX@_Version    = 0x@HEX@;
-$@PREFIX@_VersionStr = "@VERSION@.@REVISION@@BPTYPE@@BPLEVEL@ (@DAY@-@MONTH@-@YEAR@)";
-$@PREFIX@_Hello      = "This is @NAME@, Version @VERSION@.@REVISION@@BPTYPE@@BPLEVEL@ (@DAY@-@MONTH@-@YEAR@)";
-$@PREFIX@_GNUVersion = "@NAME@ Version @VERSION@.@REVISION@@BPTYPE@@BPLEVEL@";
-$@PREFIX@_WhatID     = "@(#)@NAME@ Version @VERSION@.@REVISION@@BPTYPE@@BPLEVEL@ (@DAY@-@MONTH@-@YEAR@)";
-$@PREFIX@_RCSIdentID = "\$Id: shtool,v 1.4 2000/03/31 08:36:19 fielding Exp $/";
-$@PREFIX@_WebID      = "@NAME@/@VERSION@.@REVISION@@BPTYPE@@BPLEVEL@";
-$@PREFIX@_PlainID    = "@VERSION@.@REVISION@@BPTYPE@@BPLEVEL@";
-
-1;
-EOT
-            ;;
-    esac
-    
-    #   now create the version file
-    rm -f $FILE >/dev/null 2>&1
-    sed \
-        -e "s|@FILE@|$FILE|g" \
-        -e "s|@FILESTR@|$FILESTR|g" \
-        -e "s|@PREFIX@|$PREFIX|g" \
-        -e "s|@NAME@|$NAME|g" \
-        -e "s|@HEX@|$HEX|g" \
-        -e "s|@VERSION@|$version|g" \
-        -e "s|@REVISION@|$revision|g" \
-        -e "s|@BPTYPE@|$bptype|g" \
-        -e "s|@BPLEVEL@|$bplevel|g" \
-        -e "s|@YEAR@|$year|g" \
-        -e "s|@MONTH@|$month|g" \
-        -e "s|@DAY@|$day|g" <$tmpfile >$FILE
-    rm -f $tmpfile >/dev/null 2>&1
-    exit 0
-    ;;
-
-path )
-    ##
-    ##  path -- Deal with program paths
-    ##  Copyright (c) 1998-1999 Ralf S. Engelschall <rse@engelschall.com>
-    ##  Originally written for Apache
-    ##
-    
-    namelist="$*"
-    
-    #   check whether the test command supports the -x option
-    cat >$tmpfile <<EOT
-if [ -x / ] || [ -x /bin ] || [ -x /bin/ls ]; then
-    exit 0
-fi
-exit 1
-EOT
-    if sh $tmpfile 2>/dev/null; then
-        minusx="-x"
-    else
-        minusx="-r"
-    fi
-    rm -f $tmpfile
-    
-    #   split path string
-    paths="`echo $opt_p |\
-            sed -e 's/^:/.:/' \
-                -e 's/::/:.:/g' \
-                -e 's/:$/:./' \
-                -e 's/:/ /g'`"
-    
-    #   SPECIAL REQUEST
-    #   translate forward to reverse path
-    if [ ".$opt_r" = .yes ]; then
-        if [ "x$namelist" = "x." ]; then
-            rp='.'
-        else
-            rp=''
-            for pe in `IFS="$IFS/"; echo $namelist`; do
-                rp="../$rp"
-            done
-        fi
-        echo $rp | sed -e 's:/$::'
-        exit 0
-    fi
-    
-    #   SPECIAL REQUEST
-    #   strip out directory or base name
-    if [ ".$opt_d" = .yes ]; then
-        echo "$namelist" |\
-        sed -e 's;[^/]*$;;' -e 's;\(.\)/$;\1;'
-        exit 0
-    fi
-    if [ ".$opt_b" = .yes ]; then
-        echo "$namelist" |\
-        sed -e 's;.*/\([^/]*\)$;\1;'
-        exit 0
-    fi
-    
-    #   MAGIC SITUATION
-    #   Perl Interpreter (perl)
-    if [ ".$opt_m" = .yes ] && [ ".$namelist" = .perl ]; then
-        rm -f $tmpfile
-        touch $tmpfile
-        c=0
-        found=0
-        for dir in $paths; do
-            dir=`echo $dir | sed -e 's;/*$;;'`
-            for perl in perl5 perl miniperl; do
-                 if [ $minusx "$dir/$perl" ] && [ ! -d "$dir/$perl" ]; then
-                     perl="$dir/$perl"
-                     version=`$perl -v | grep version |\
-                              sed -e 's/.* version //' -e 's/ built.*//' -e 's/ with.*//'`
-                     versionnum="`echo $version | sed -e 's/\.//g' -e 's/_//g'`"
-                     versionnum=`expr $versionnum - $c`
-                     echo "$versionnum $perl" >>$tmpfile
-                     found=1
-                 fi
-            done
-            c=`expr $c + 1`
-        done
-        if [ $found = 1 ]; then
-            perl="`cat $tmpfile | sort -u | tail -1 | cut '-d ' -f2`"
-            rm -f $tmpfile
-            echo "$perl"
-            exit 0
-        fi
-        exit 1
-    fi
-    
-    #   MAGIC SITUATION
-    #   C pre-processor (cpp)
-    if [ ".$opt_m" = .yes ] && [ ".$namelist" = .cpp ]; then
-        cat >$tmpfile.c <<EOT
-#include <assert.h>
-    Syntax Error
-EOT
-        #   1. try the standard cc -E approach
-        cpp="${CC-cc} -E"
-        (eval "$cpp $tmpfile.c >/dev/null") 2>$tmpfile.out
-        my_error=`grep -v '^ *+' $tmpfile.out`
-        if [ ".$my_error" != . ]; then
-            #   2. try the cc -E approach and GCC's -traditional-ccp option
-            cpp="${CC-cc} -E -traditional-cpp"
-            (eval "$cpp $tmpfile.c >/dev/null") 2>$tmpfile.out
-            my_error=`grep -v '^ *+' $tmpfile.out`
-            if [ ".$my_error" != . ]; then
-                #   3. try a standalone cpp command in path and lib dirs
-                for path in $paths /lib /usr/lib /usr/local/lib; do
-                    path=`echo $path | sed -e 's;/*$;;'`
-                    if [ $minusx "$path/cpp" ] && [ ! -d "$path/cpp" ]; then
-                        cpp="$path/cpp"
-                        break
-                    fi
-                done
-                if [ ".$cpp" != . ]; then
-                    (eval "$cpp $tmpfile.c >/dev/null") 2>$tmpfile.out
-                    my_error=`grep -v '^ *+' $tmpfile.out`
-                    if [ ".$my_error" != . ]; then
-                        #   ok, we gave up...
-                        cpp=''
-                    fi
-                fi
-            fi
-        fi
-        rm -f $tmpfile.c $tmpfile.out
-        if [ ".$cpp" != . ]; then
-            echo "$cpp"
-            exit 0
-        fi
-        exit 1
-    fi
-    
-    #   STANDARD SITUATION
-    #   iterate over names
-    for name in $namelist; do
-        #   iterate over paths
-        for path in $paths; do
-            path=`echo $path | sed -e 's;/*$;;'`
-            if [ $minusx "$path/$name" ] && [ ! -d "$path/$name" ]; then
-                if [ ".$opt_s" != .yes ]; then
-                    echo "$path/$name" 2>&1
-                fi
-                exit 0
-            fi
-        done
-    done
-    exit 1
-    ;;
-
-esac
-
-exit 0
-
-##EOF##
diff --git a/shmem/unix/shm.c b/shmem/unix/shm.c
new file mode 100644
index 00000000000..f93efb5fc44
--- /dev/null
+++ b/shmem/unix/shm.c
@@ -0,0 +1,731 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_arch_shm.h"
+#include "apr_arch_file_io.h"
+
+#include "apr_general.h"
+#include "apr_errno.h"
+#include "apr_user.h"
+#include "apr_strings.h"
+#include "apr_hash.h"
+
+#if APR_USE_SHMEM_MMAP_SHM
+/* 
+ *   For portable use, a shared memory object should be identified by a name of
+ *   the form /somename; that is, a null-terminated string of up to NAME_MAX
+ *   (i.e., 255) characters consisting of an initial slash, followed by one or
+ *   more characters, none of which are slashes.
+ */
+#ifndef NAME_MAX
+#define NAME_MAX 255
+#endif
+
+/* See proc_mutex.c and sem_open for the reason for all this! */
+static unsigned int rshash (const char *p) {
+    /* hash function from Robert Sedgwicks 'Algorithms in C' book */
+    unsigned int b    = 378551;
+    unsigned int a    = 63689;
+    unsigned int retval = 0;
+
+    for( ; *p; p++) {
+        retval = retval * a + (*p);
+        a *= b;
+    }
+
+    return retval;
+}
+
+static const char *make_shm_open_safe_name(const char *filename,
+                                           apr_pool_t *pool)
+{
+    apr_ssize_t flen;
+    unsigned int h1, h2;
+
+    if (filename == NULL) {
+        return NULL;
+    }
+
+    flen = strlen(filename);
+    h1 = (apr_hashfunc_default(filename, &flen) & 0xffffffff);
+    h2 = (rshash(filename) & 0xffffffff);
+    return apr_psprintf(pool, "/ShM.%xH%x", h1, h2);
+
+}
+#endif
+
+#if APR_USE_SHMEM_SHMGET
+static key_t our_ftok(const char *filename)
+{
+    /* to help avoid collisions while still using
+     * an easily recreated proj_id */
+    apr_ssize_t slen = strlen(filename);
+    return ftok(filename,
+                (int)apr_hashfunc_default(filename, &slen));
+}
+#endif
+
+static apr_status_t shm_cleanup_owner(void *m_)
+{
+    apr_shm_t *m = (apr_shm_t *)m_;
+
+    /* anonymous shared memory */
+    if (m->filename == NULL) {
+#if APR_USE_SHMEM_MMAP_ZERO || APR_USE_SHMEM_MMAP_ANON
+        if (munmap(m->base, m->realsize) == -1) {
+            return errno;
+        }
+        return APR_SUCCESS;
+#elif APR_USE_SHMEM_SHMGET_ANON
+        if (shmdt(m->base) == -1) {
+            return errno;
+        }
+        /* This segment will automatically remove itself after all
+         * references have detached. */
+        return APR_SUCCESS;
+#endif
+    }
+
+    /* name-based shared memory */
+    else {
+#if APR_USE_SHMEM_MMAP_TMP
+        if (munmap(m->base, m->realsize) == -1) {
+            return errno;
+        }
+        if (access(m->filename, F_OK)) {
+            return APR_SUCCESS;
+        }
+        else {
+            return apr_file_remove(m->filename, m->pool);
+        }
+#elif APR_USE_SHMEM_MMAP_SHM
+        if (munmap(m->base, m->realsize) == -1) {
+            return errno;
+        }
+        if (shm_unlink(make_shm_open_safe_name(m->filename, m->pool)) == -1 && errno != ENOENT) {
+            return errno;
+        }
+        return APR_SUCCESS;
+#elif APR_USE_SHMEM_SHMGET
+        /* Indicate that the segment is to be destroyed as soon
+         * as all processes have detached. This also disallows any
+         * new attachments to the segment. */
+        if (shmctl(m->shmid, IPC_RMID, NULL) == -1 && errno != EINVAL) {
+            return errno;
+        }
+        if (shmdt(m->base) == -1) {
+            return errno;
+        }
+        if (access(m->filename, F_OK)) {
+            return APR_SUCCESS;
+        }
+        else {
+            return apr_file_remove(m->filename, m->pool);
+        }
+#else
+        return APR_ENOTIMPL;
+#endif
+    }
+}
+
+APR_DECLARE(apr_status_t) apr_shm_create(apr_shm_t **m,
+                                         apr_size_t reqsize, 
+                                         const char *filename,
+                                         apr_pool_t *pool)
+{
+    apr_shm_t *new_m;
+    apr_status_t status;
+#if APR_USE_SHMEM_SHMGET || APR_USE_SHMEM_SHMGET_ANON
+    struct shmid_ds shmbuf;
+    apr_uid_t uid;
+    apr_gid_t gid;
+#endif
+#if APR_USE_SHMEM_MMAP_TMP || APR_USE_SHMEM_MMAP_SHM || \
+    APR_USE_SHMEM_MMAP_ZERO
+    int tmpfd;
+#endif
+#if APR_USE_SHMEM_SHMGET
+    apr_size_t nbytes;
+#endif
+#if APR_USE_SHMEM_MMAP_ZERO || APR_USE_SHMEM_SHMGET || \
+    APR_USE_SHMEM_MMAP_TMP || APR_USE_SHMEM_MMAP_SHM
+    apr_file_t *file;   /* file where metadata is stored */
+#endif
+
+    /* Check if they want anonymous or name-based shared memory */
+    if (filename == NULL) {
+#if APR_USE_SHMEM_MMAP_ZERO || APR_USE_SHMEM_MMAP_ANON
+        new_m = apr_palloc(pool, sizeof(apr_shm_t));
+        new_m->pool = pool;
+        new_m->reqsize = reqsize;
+        new_m->realsize = reqsize + 
+            APR_ALIGN_DEFAULT(sizeof(apr_size_t)); /* room for metadata */
+        new_m->filename = NULL;
+    
+#if APR_USE_SHMEM_MMAP_ZERO
+        status = apr_file_open(&file, "/dev/zero", APR_FOPEN_READ | APR_FOPEN_WRITE, 
+                               APR_FPROT_OS_DEFAULT, pool);
+        if (status != APR_SUCCESS) {
+            return status;
+        }
+        status = apr_os_file_get(&tmpfd, file);
+        if (status != APR_SUCCESS) {
+            return status;
+        }
+
+        new_m->base = mmap(NULL, new_m->realsize, PROT_READ|PROT_WRITE,
+                           MAP_SHARED, tmpfd, 0);
+        if (new_m->base == (void *)MAP_FAILED) {
+            return errno;
+        }
+
+        status = apr_file_close(file);
+        if (status != APR_SUCCESS) {
+            return status;
+        }
+
+        /* store the real size in the metadata */
+        *(apr_size_t*)(new_m->base) = new_m->realsize;
+        /* metadata isn't usable */
+        new_m->usable = (char *)new_m->base + APR_ALIGN_DEFAULT(sizeof(apr_size_t));
+
+        apr_pool_cleanup_register(new_m->pool, new_m, shm_cleanup_owner,
+                                  apr_pool_cleanup_null);
+        *m = new_m;
+        return APR_SUCCESS;
+
+#elif APR_USE_SHMEM_MMAP_ANON
+        new_m->base = mmap(NULL, new_m->realsize, PROT_READ|PROT_WRITE,
+                           MAP_ANON|MAP_SHARED, -1, 0);
+        if (new_m->base == (void *)MAP_FAILED) {
+            return errno;
+        }
+
+        /* store the real size in the metadata */
+        *(apr_size_t*)(new_m->base) = new_m->realsize;
+        /* metadata isn't usable */
+        new_m->usable = (char *)new_m->base + APR_ALIGN_DEFAULT(sizeof(apr_size_t));
+
+        apr_pool_cleanup_register(new_m->pool, new_m, shm_cleanup_owner,
+                                  apr_pool_cleanup_null);
+        *m = new_m;
+        return APR_SUCCESS;
+
+#endif /* APR_USE_SHMEM_MMAP_ZERO */
+#elif APR_USE_SHMEM_SHMGET_ANON
+        new_m = apr_palloc(pool, sizeof(apr_shm_t));
+        new_m->pool = pool;
+        new_m->reqsize = reqsize;
+        new_m->realsize = reqsize;
+        new_m->filename = NULL;
+        new_m->shmkey = IPC_PRIVATE;
+        if ((new_m->shmid = shmget(new_m->shmkey, new_m->realsize,
+                                   SHM_R | SHM_W | IPC_CREAT)) < 0) {
+            return errno;
+        }
+
+        if ((new_m->base = shmat(new_m->shmid, NULL, 0)) == (void *)-1) {
+            return errno;
+        }
+        new_m->usable = new_m->base;
+
+        if (shmctl(new_m->shmid, IPC_STAT, &shmbuf) == -1) {
+            return errno;
+        }
+        apr_uid_current(&uid, &gid, pool);
+        shmbuf.shm_perm.uid = uid;
+        shmbuf.shm_perm.gid = gid;
+        if (shmctl(new_m->shmid, IPC_SET, &shmbuf) == -1) {
+            return errno;
+        }
+
+        /* Remove the segment once use count hits zero.
+         * We will not attach to this segment again, since it is
+         * anonymous memory, so it is ok to mark it for deletion.
+         */
+        if (shmctl(new_m->shmid, IPC_RMID, NULL) == -1) {
+            return errno;
+        }
+
+        apr_pool_cleanup_register(new_m->pool, new_m, shm_cleanup_owner,
+                                  apr_pool_cleanup_null);
+        *m = new_m;
+        return APR_SUCCESS;
+#else
+        /* It is an error if they want anonymous memory but we don't have it. */
+        return APR_ENOTIMPL; /* requested anonymous but we don't have it */
+#endif
+    }
+
+    /* Name-based shared memory */
+    else {
+        new_m = apr_palloc(pool, sizeof(apr_shm_t));
+        new_m->pool = pool;
+        new_m->reqsize = reqsize;
+        new_m->filename = apr_pstrdup(pool, filename);
+#if APR_USE_SHMEM_MMAP_SHM
+        const char *shm_name = make_shm_open_safe_name(filename, pool);
+#endif
+#if APR_USE_SHMEM_MMAP_TMP || APR_USE_SHMEM_MMAP_SHM
+        new_m->realsize = reqsize + 
+            APR_ALIGN_DEFAULT(sizeof(apr_size_t)); /* room for metadata */
+        /* FIXME: Ignore error for now. *
+         * status = apr_file_remove(file, pool);*/
+        status = APR_SUCCESS;
+    
+#if APR_USE_SHMEM_MMAP_TMP
+        /* FIXME: Is APR_FPROT_OS_DEFAULT sufficient? */
+        status = apr_file_open(&file, filename, 
+                               APR_FOPEN_READ | APR_FOPEN_WRITE | APR_FOPEN_CREATE | APR_FOPEN_EXCL,
+                               APR_FPROT_OS_DEFAULT, pool);
+        if (status != APR_SUCCESS) {
+            return status;
+        }
+
+        status = apr_os_file_get(&tmpfd, file);
+        if (status != APR_SUCCESS) {
+            apr_file_close(file); /* ignore errors, we're failing */
+            apr_file_remove(new_m->filename, new_m->pool);
+            return status;
+        }
+
+        status = apr_file_trunc(file, new_m->realsize);
+        if (status != APR_SUCCESS && status != APR_ESPIPE) {
+            apr_file_close(file); /* ignore errors, we're failing */
+            apr_file_remove(new_m->filename, new_m->pool);
+            return status;
+        }
+
+        new_m->base = mmap(NULL, new_m->realsize, PROT_READ | PROT_WRITE,
+                           MAP_SHARED, tmpfd, 0);
+        /* FIXME: check for errors */
+
+        status = apr_file_close(file);
+        if (status != APR_SUCCESS) {
+            return status;
+        }
+#endif /* APR_USE_SHMEM_MMAP_TMP */
+#if APR_USE_SHMEM_MMAP_SHM
+        /* FIXME: SysV uses 0600... should we? */
+        tmpfd = shm_open(shm_name, O_RDWR | O_CREAT | O_EXCL, 0644);
+        if (tmpfd == -1) {
+            return errno;
+        }
+
+        status = apr_os_file_put(&file, &tmpfd,
+                                 APR_FOPEN_READ | APR_FOPEN_WRITE | APR_FOPEN_CREATE | APR_FOPEN_EXCL,
+                                 pool); 
+        if (status != APR_SUCCESS) {
+            return status;
+        }
+
+        status = apr_file_trunc(file, new_m->realsize);
+        if (status != APR_SUCCESS && status != APR_ESPIPE) {
+            shm_unlink(shm_name); /* we're failing, remove the object */
+            return status;
+        }
+        new_m->base = mmap(NULL, new_m->realsize, PROT_READ | PROT_WRITE,
+                           MAP_SHARED, tmpfd, 0);
+
+        /* FIXME: check for errors */
+
+        status = apr_file_close(file);
+        if (status != APR_SUCCESS) {
+            return status;
+        }
+#endif /* APR_USE_SHMEM_MMAP_SHM */
+
+        /* store the real size in the metadata */
+        *(apr_size_t*)(new_m->base) = new_m->realsize;
+        /* metadata isn't usable */
+        new_m->usable = (char *)new_m->base + APR_ALIGN_DEFAULT(sizeof(apr_size_t));
+
+        apr_pool_cleanup_register(new_m->pool, new_m, shm_cleanup_owner,
+                                  apr_pool_cleanup_null);
+        *m = new_m;
+        return APR_SUCCESS;
+
+#elif APR_USE_SHMEM_SHMGET
+        new_m->realsize = reqsize;
+
+        /* FIXME: APR_FPROT_OS_DEFAULT is too permissive, switch to 600 I think. */
+        status = apr_file_open(&file, filename, 
+                               APR_FOPEN_WRITE | APR_FOPEN_CREATE | APR_FOPEN_EXCL,
+                               APR_FPROT_OS_DEFAULT, pool);
+        if (status != APR_SUCCESS) {
+            return status;
+        }
+
+        /* ftok() (on solaris at least) requires that the file actually
+         * exist before calling ftok(). */
+        new_m->shmkey = our_ftok(filename);
+        if (new_m->shmkey == (key_t)-1) {
+            apr_file_close(file);
+            return errno;
+        }
+
+        if ((new_m->shmid = shmget(new_m->shmkey, new_m->realsize,
+                                   SHM_R | SHM_W | IPC_CREAT | IPC_EXCL)) < 0) {
+            apr_file_close(file);
+            return errno;
+        }
+
+        if ((new_m->base = shmat(new_m->shmid, NULL, 0)) == (void *)-1) {
+            apr_file_close(file);
+            return errno;
+        }
+        new_m->usable = new_m->base;
+
+        if (shmctl(new_m->shmid, IPC_STAT, &shmbuf) == -1) {
+            apr_file_close(file);
+            return errno;
+        }
+        apr_uid_current(&uid, &gid, pool);
+        shmbuf.shm_perm.uid = uid;
+        shmbuf.shm_perm.gid = gid;
+        if (shmctl(new_m->shmid, IPC_SET, &shmbuf) == -1) {
+            apr_file_close(file);
+            return errno;
+        }
+
+        nbytes = sizeof(reqsize);
+        status = apr_file_write(file, (const void *)&reqsize,
+                                &nbytes);
+        if (status != APR_SUCCESS) {
+            apr_file_close(file);
+            return status;
+        }
+        status = apr_file_close(file);
+        if (status != APR_SUCCESS) {
+            return status;
+        }
+
+        apr_pool_cleanup_register(new_m->pool, new_m, shm_cleanup_owner,
+                                  apr_pool_cleanup_null);
+        *m = new_m; 
+        return APR_SUCCESS;
+
+#else
+        return APR_ENOTIMPL;
+#endif
+    }
+}
+
+APR_DECLARE(apr_status_t) apr_shm_create_ex(apr_shm_t **m, 
+                                            apr_size_t reqsize, 
+                                            const char *filename, 
+                                            apr_pool_t *p,
+                                            apr_int32_t flags)
+{
+    return apr_shm_create(m, reqsize, filename, p);
+}
+
+APR_DECLARE(apr_status_t) apr_shm_remove(const char *filename,
+                                         apr_pool_t *pool)
+{
+#if APR_USE_SHMEM_SHMGET
+    apr_status_t status;
+    apr_file_t *file;  
+    key_t shmkey;
+    int shmid;
+#endif
+
+#if APR_USE_SHMEM_MMAP_TMP
+    return apr_file_remove(filename, pool);
+#elif APR_USE_SHMEM_MMAP_SHM
+    const char *shm_name = make_shm_open_safe_name(filename, pool);
+    if (shm_unlink(shm_name) == -1) {
+        return errno;
+    }
+    return APR_SUCCESS;
+#elif APR_USE_SHMEM_SHMGET
+    /* Presume that the file already exists; just open for writing */    
+    status = apr_file_open(&file, filename, APR_FOPEN_WRITE,
+                           APR_FPROT_OS_DEFAULT, pool);
+    if (status) {
+        return status;
+    }
+
+    /* ftok() (on solaris at least) requires that the file actually
+     * exist before calling ftok(). */
+    shmkey = our_ftok(filename);
+    if (shmkey == (key_t)-1) {
+        goto shm_remove_failed;
+    }
+
+    apr_file_close(file);
+
+    if ((shmid = shmget(shmkey, 0, SHM_R | SHM_W)) < 0) {
+        goto shm_remove_failed;
+    }
+
+    /* Indicate that the segment is to be destroyed as soon
+     * as all processes have detached. This also disallows any
+     * new attachments to the segment. */
+    if (shmctl(shmid, IPC_RMID, NULL) == -1) {
+        goto shm_remove_failed;
+    }
+    return apr_file_remove(filename, pool);
+
+shm_remove_failed:
+    status = errno;
+    /* ensure the file has been removed anyway. */
+    apr_file_remove(filename, pool);
+    return status;
+#else
+
+    /* No support for anonymous shm */
+    return APR_ENOTIMPL;
+#endif
+} 
+
+APR_DECLARE(apr_status_t) apr_shm_delete(apr_shm_t *m)
+{
+    if (m->filename) {
+        return apr_shm_remove(m->filename, m->pool);
+    }
+    else {
+        return APR_ENOTIMPL;
+    }
+} 
+
+APR_DECLARE(apr_status_t) apr_shm_destroy(apr_shm_t *m)
+{
+    return apr_pool_cleanup_run(m->pool, m, shm_cleanup_owner);
+}
+
+static apr_status_t shm_cleanup_attach(void *m_)
+{
+    apr_shm_t *m = (apr_shm_t *)m_;
+
+    if (m->filename == NULL) {
+        /* It doesn't make sense to detach from an anonymous memory segment. */
+        return APR_EINVAL;
+    }
+    else {
+#if APR_USE_SHMEM_MMAP_TMP || APR_USE_SHMEM_MMAP_SHM
+        if (munmap(m->base, m->realsize) == -1) {
+            return errno;
+        }
+        return APR_SUCCESS;
+#elif APR_USE_SHMEM_SHMGET
+        if (shmdt(m->base) == -1) {
+            return errno;
+        }
+        return APR_SUCCESS;
+#else
+        return APR_ENOTIMPL;
+#endif
+    }
+}
+
+APR_DECLARE(apr_status_t) apr_shm_attach(apr_shm_t **m,
+                                         const char *filename,
+                                         apr_pool_t *pool)
+{
+    if (filename == NULL) {
+        /* It doesn't make sense to attach to a segment if you don't know
+         * the filename. */
+        return APR_EINVAL;
+    }
+    else {
+#if APR_USE_SHMEM_MMAP_TMP || APR_USE_SHMEM_MMAP_SHM
+        apr_shm_t *new_m;
+        apr_status_t status;
+        int tmpfd;
+        apr_file_t *file;   /* file where metadata is stored */
+        apr_size_t nbytes;
+
+        new_m = apr_palloc(pool, sizeof(apr_shm_t));
+        new_m->pool = pool;
+        new_m->filename = apr_pstrdup(pool, filename);
+#if APR_USE_SHMEM_MMAP_SHM
+        const char *shm_name = make_shm_open_safe_name(filename, pool);
+
+        /* FIXME: SysV uses 0600... should we? */
+        tmpfd = shm_open(shm_name, O_RDWR, 0644);
+        if (tmpfd == -1) {
+            return errno;
+        }
+
+        status = apr_os_file_put(&file, &tmpfd,
+                                 APR_READ | APR_WRITE,
+                                 pool); 
+        if (status != APR_SUCCESS) {
+            return status;
+        }
+
+#elif APR_USE_SHMEM_MMAP_TMP
+        status = apr_file_open(&file, filename, 
+                               APR_FOPEN_READ | APR_FOPEN_WRITE,
+                               APR_FPROT_OS_DEFAULT, pool);
+        if (status != APR_SUCCESS) {
+            return status;
+        }
+        status = apr_os_file_get(&tmpfd, file);
+        if (status != APR_SUCCESS) {
+            return status;
+        }
+#else
+        return APR_ENOTIMPL;
+#endif
+
+        nbytes = sizeof(new_m->realsize);
+        status = apr_file_read(file, (void *)&(new_m->realsize),
+                               &nbytes);
+        if (status != APR_SUCCESS) {
+            return status;
+        }
+
+        status = apr_os_file_get(&tmpfd, file);
+        if (status != APR_SUCCESS) {
+            apr_file_close(file); /* ignore errors, we're failing */
+            apr_file_remove(new_m->filename, new_m->pool);
+            return status;
+        }
+
+        new_m->reqsize = new_m->realsize - sizeof(apr_size_t);
+
+        new_m->base = mmap(NULL, new_m->realsize, PROT_READ | PROT_WRITE,
+                           MAP_SHARED, tmpfd, 0);
+        /* FIXME: check for errors */
+        
+        status = apr_file_close(file);
+        if (status != APR_SUCCESS) {
+            return status;
+        }
+
+        /* metadata isn't part of the usable segment */
+        new_m->usable = (char *)new_m->base + APR_ALIGN_DEFAULT(sizeof(apr_size_t));
+
+        apr_pool_cleanup_register(new_m->pool, new_m, shm_cleanup_attach,
+                                  apr_pool_cleanup_null);
+        *m = new_m;
+        return APR_SUCCESS;
+
+#elif APR_USE_SHMEM_SHMGET
+        apr_shm_t *new_m;
+        apr_status_t status;
+        apr_file_t *file;   /* file where metadata is stored */
+        apr_size_t nbytes;
+
+        new_m = apr_palloc(pool, sizeof(apr_shm_t));
+
+        status = apr_file_open(&file, filename, 
+                               APR_FOPEN_READ, APR_FPROT_OS_DEFAULT, pool);
+        if (status != APR_SUCCESS) {
+            return status;
+        }
+
+        nbytes = sizeof(new_m->reqsize);
+        status = apr_file_read(file, (void *)&(new_m->reqsize),
+                               &nbytes);
+        if (status != APR_SUCCESS) {
+            return status;
+        }
+        status = apr_file_close(file);
+        if (status != APR_SUCCESS) {
+            return status;
+        }
+
+        new_m->filename = apr_pstrdup(pool, filename);
+        new_m->pool = pool;
+        new_m->shmkey = our_ftok(filename);
+        if (new_m->shmkey == (key_t)-1) {
+            return errno;
+        }
+        if ((new_m->shmid = shmget(new_m->shmkey, 0, SHM_R | SHM_W)) == -1) {
+            return errno;
+        }
+        if ((new_m->base = shmat(new_m->shmid, NULL, 0)) == (void *)-1) {
+            return errno;
+        }
+        new_m->usable = new_m->base;
+        new_m->realsize = new_m->reqsize;
+
+        apr_pool_cleanup_register(new_m->pool, new_m, shm_cleanup_attach,
+                                  apr_pool_cleanup_null);
+        *m = new_m;
+        return APR_SUCCESS;
+
+#else
+        return APR_ENOTIMPL;
+#endif
+    }
+}
+
+APR_DECLARE(apr_status_t) apr_shm_attach_ex(apr_shm_t **m,
+                                            const char *filename,
+                                            apr_pool_t *pool,
+                                            apr_int32_t flags)
+{
+    return apr_shm_attach(m, filename, pool);
+}
+
+APR_DECLARE(apr_status_t) apr_shm_detach(apr_shm_t *m)
+{
+    apr_status_t rv = shm_cleanup_attach(m);
+    apr_pool_cleanup_kill(m->pool, m, shm_cleanup_attach);
+    return rv;
+}
+
+APR_DECLARE(void *) apr_shm_baseaddr_get(const apr_shm_t *m)
+{
+    return m->usable;
+}
+
+APR_DECLARE(apr_size_t) apr_shm_size_get(const apr_shm_t *m)
+{
+    return m->reqsize;
+}
+
+APR_PERMS_SET_IMPLEMENT(shm)
+{
+#if APR_USE_SHMEM_SHMGET || APR_USE_SHMEM_SHMGET_ANON
+    struct shmid_ds shmbuf;
+    int shmid;
+    apr_shm_t *m = (apr_shm_t *)theshm;
+
+    if ((shmid = shmget(m->shmkey, 0, SHM_R | SHM_W)) == -1) {
+        return errno;
+    }
+    shmbuf.shm_perm.uid  = uid;
+    shmbuf.shm_perm.gid  = gid;
+    shmbuf.shm_perm.mode = apr_unix_perms2mode(perms);
+    if (shmctl(shmid, IPC_SET, &shmbuf) == -1) {
+        return errno;
+    }
+    return APR_SUCCESS;
+#else
+    return APR_ENOTIMPL;
+#endif
+}
+
+APR_POOL_IMPLEMENT_ACCESSOR(shm)
+
+APR_DECLARE(apr_status_t) apr_os_shm_get(apr_os_shm_t *osshm,
+                                         apr_shm_t *shm)
+{
+    return APR_ENOTIMPL;
+}
+
+APR_DECLARE(apr_status_t) apr_os_shm_put(apr_shm_t **m,
+                                         apr_os_shm_t *osshm,
+                                         apr_pool_t *pool)
+{
+    return APR_ENOTIMPL;
+}    
+
diff --git a/shmem/unix/shmem.c b/shmem/unix/shmem.c
deleted file mode 100644
index c728f550142..00000000000
--- a/shmem/unix/shmem.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "mm.h"
-#include "apr_general.h"
-#include "apr_shmem.h"
-#include "apr_errno.h"
-
-struct shmem_t {
-    MM *mm;
-};
-
-ap_status_t ap_shm_init(struct shmem_t **m, ap_size_t reqsize, const char *file, ap_pool_t *cont)
-{
-    MM *newmm = mm_create(reqsize, file);
-    if (newmm == NULL) {
-        return errno;
-    }
-    (*m) = mm_malloc(newmm, sizeof(struct shmem_t));
-    (*m)->mm = newmm;
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_shm_destroy(struct shmem_t *m)
-{
-    mm_destroy(m->mm);
-    return APR_SUCCESS;
-}
-
-void *ap_shm_malloc(struct shmem_t *c, ap_size_t reqsize)
-{
-    if (c->mm == NULL) {
-        return NULL;
-    }
-    return mm_malloc(c->mm, reqsize);
-}
-
-void *ap_shm_calloc(struct shmem_t *shared, ap_size_t size) 
-{
-    if (shared == NULL) {
-        return NULL;
-    }
-    return mm_calloc(shared->mm, 1, size);
-}
-
-ap_status_t ap_shm_free(struct shmem_t *shared, void *entity)
-{
-    mm_free(shared->mm, entity);
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_get_shm_name(ap_shmem_t *c, ap_shm_name_t **name)
-{
-#if APR_USES_ANONYMOUS_SHM
-    name = NULL;
-    return APR_ANONYMOUS;
-/* Currently, we are not supporting name based shared memory on Unix
- * systems.  This may change in the future however, so I will leave
- * this in here for now.  Plus, this gives other platforms a good idea
- * of how to proceed.
- */
-#elif APR_USES_FILEBASED_SHM
-#elif APR_USES_KEYBASED_SHM
-#endif
-}
-
-ap_status_t ap_set_shm_name(ap_shmem_t *c, ap_shm_name_t *name)
-{
-#if APR_USES_ANONYMOUS_SHM
-    return APR_ANONYMOUS;
-/* Currently, we are not supporting name based shared memory on Unix
- * systems.  This may change in the future however, so I will leave
- * this in here for now.  Plus, this gives other platforms a good idea
- * of how to proceed.
- */
-#elif APR_USES_FILEBASED_SHM
-#elif APR_USES_KEYBASED_SHM
-#endif
-}
-
-ap_status_t ap_open_shmem(struct shmem_t *c)
-{
-#if APR_USES_ANONYMOUS_SHM
-/* When using MM, we don't need to open shared memory segments in child
- * segments, so just return immediately.
- */
-    return APR_SUCCESS;
-/* Currently, we are not supporting name based shared memory on Unix
- * systems.  This may change in the future however, so I will leave
- * this in here for now.  Plus, this gives other platforms a good idea
- * of how to proceed.
- */
-#elif APR_USES_FILEBASED_SHM
-#elif APR_USES_KEYBASED_SHM
-#endif
-}
-
-ap_status_t ap_shm_avail(struct shmem_t *c, ap_size_t *size)
-{
-    *size = mm_available(c);
-    if (*size == 0) {
-        return APR_ENOSHMAVAIL;
-    }
-    return APR_SUCCESS;
-}
diff --git a/shmem/win32/shm.c b/shmem/win32/shm.c
new file mode 100644
index 00000000000..b01411ebd5e
--- /dev/null
+++ b/shmem/win32/shm.c
@@ -0,0 +1,452 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_general.h"
+#include "apr_errno.h"
+#include "apr_file_io.h"
+#include "apr_shm.h"
+#include "apr_strings.h"
+#include "apr_arch_file_io.h"
+#include "limits.h"
+
+typedef struct memblock_t {
+    apr_size_t size;
+    apr_size_t length;
+} memblock_t;
+
+struct apr_shm_t {
+    apr_pool_t *pool;
+    memblock_t *memblk;
+    void       *usrmem;
+    apr_size_t  size;
+    apr_size_t  length;
+    HANDLE      hMap;
+    const char *filename;
+};
+
+static apr_status_t shm_cleanup(void* shm)
+{
+    apr_status_t rv = APR_SUCCESS;
+    apr_shm_t *m = shm;
+    
+    if (!UnmapViewOfFile(m->memblk)) {
+        rv = apr_get_os_error();
+    }
+    if (!CloseHandle(m->hMap)) {
+        rv = rv != APR_SUCCESS ? rv : apr_get_os_error();
+    }
+    if (m->filename) {
+        /* Remove file if file backed */
+        apr_status_t rc = apr_file_remove(m->filename, m->pool);
+        rv = rv != APR_SUCCESS ? rv : rc;
+    }
+    return rv;
+}
+
+/* See if the caller is able to create a map in the global namespace by
+ * checking if the SE_CREATE_GLOBAL_NAME privilege is enabled.
+ *
+ * Prior to APR 1.5.0, named shared memory segments were always created
+ * in the global segment.  However, with recent versions of Windows this
+ * fails for unprivileged processes.  Thus, with older APR, named shared
+ * memory segments can't be created by unprivileged processes on newer
+ * Windows.
+ *
+ * By checking if the caller has the privilege, shm APIs can decide
+ * whether to use the Global or Local namespace.
+ *
+ * If running on an SDK without the required API definitions *OR*
+ * some processing failure occurs trying to check the privilege, fall
+ * back to earlier behavior -- always try to use the Global namespace.
+ */
+#ifdef SE_CREATE_GLOBAL_NAME
+static int can_create_global_maps(void)
+{
+    BOOL ok, has_priv;
+    LUID priv_id;
+    PRIVILEGE_SET privs;
+    HANDLE hToken;
+
+    ok = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &hToken);
+    if (!ok && GetLastError() == ERROR_NO_TOKEN) {
+        /* no thread-specific access token, so try to get process access token
+         */
+        ok = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken);
+    }
+
+    if (ok) {
+        ok = LookupPrivilegeValue(NULL, SE_CREATE_GLOBAL_NAME, &priv_id);
+    }
+
+    if (ok) {
+        privs.PrivilegeCount = 1;
+        privs.Control = PRIVILEGE_SET_ALL_NECESSARY;
+        privs.Privilege[0].Luid = priv_id;
+        privs.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED;
+        ok = PrivilegeCheck(hToken, &privs, &has_priv);
+    }
+
+    if (ok && !has_priv) {
+        return 0;
+    }
+    else {
+        return 1;
+    }
+}
+#else /* SE_CREATE_GLOBAL_NAME */
+/* SDK definitions missing */
+static int can_create_global_maps(void)
+{
+    return 1;
+}
+#endif /* SE_CREATE_GLOBAL_NAME */
+
+APR_DECLARE(apr_status_t) apr_shm_create_ex(apr_shm_t **m,
+                                            apr_size_t reqsize,
+                                            const char *file,
+                                            apr_pool_t *pool,
+                                            apr_int32_t flags)
+{
+    static apr_size_t memblock = 0;
+    HANDLE hMap, hFile;
+    apr_status_t rv;
+    apr_size_t size;
+    apr_file_t *f;
+    void *base;
+    void *mapkey;
+    DWORD err, sizelo, sizehi;
+
+    reqsize += sizeof(memblock_t);
+
+    if (!memblock)
+    {
+        SYSTEM_INFO si;
+        GetSystemInfo(&si);
+        memblock = si.dwAllocationGranularity;
+    }   
+
+    /* Compute the granualar multiple of the pagesize */
+    size = memblock * (1 + (reqsize - 1) / memblock);
+    sizelo = (DWORD)size;
+#ifdef _WIN64
+    sizehi = (DWORD)(size >> 32);
+#else
+    sizehi = 0;
+#endif
+
+    if (!file) {
+        /* Do Anonymous, which must be passed as a duplicated handle */
+#ifndef _WIN32_WCE
+        hFile = INVALID_HANDLE_VALUE;
+#endif
+        mapkey = NULL;
+    }
+    else {
+        int global;
+
+        /* Do file backed, which is not an inherited handle 
+         * While we could open APR_FOPEN_EXCL, it doesn't seem that Unix
+         * ever did.  Ignore that error here, but fail later when
+         * we discover we aren't the creator of the file map object.
+         */
+        rv = apr_file_open(&f, file,
+                           APR_FOPEN_READ | APR_FOPEN_WRITE | APR_FOPEN_BINARY | APR_FOPEN_CREATE,
+                           APR_FPROT_UREAD | APR_FPROT_UWRITE, pool);
+        if ((rv != APR_SUCCESS)
+                || ((rv = apr_os_file_get(&hFile, f)) != APR_SUCCESS)) {
+            return rv;
+        }
+        rv = apr_file_trunc(f, size);
+
+        /* res_name_from_filename turns file into a pseudo-name
+         * without slashes or backslashes, and prepends the \global
+         * or \local prefix on Win2K and later
+         */
+        if (flags & APR_SHM_NS_GLOBAL) {
+            global = 1;
+        }
+        else if (flags & APR_SHM_NS_LOCAL) {
+            global = 0;
+        }
+        else {
+            global = can_create_global_maps();
+        }
+        mapkey = res_name_from_filename(file, global, pool);
+    }
+
+#if APR_HAS_UNICODE_FS
+    IF_WIN_OS_IS_UNICODE
+    {
+        hMap = CreateFileMappingW(hFile, NULL, PAGE_READWRITE, 
+                                  sizehi, sizelo, mapkey);
+    }
+#endif
+#if APR_HAS_ANSI_FS
+    ELSE_WIN_OS_IS_ANSI
+    {
+        hMap = CreateFileMappingA(hFile, NULL, PAGE_READWRITE, 
+                                  sizehi, sizelo, mapkey);
+    }
+#endif
+    err = apr_get_os_error();
+
+    if (file) {
+        apr_file_close(f);
+    }
+
+    if (hMap && APR_STATUS_IS_EEXIST(err)) {
+        CloseHandle(hMap);
+        return APR_EEXIST;
+    }
+    if (!hMap) {
+        return err;
+    }
+    
+    base = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE,
+                         0, 0, size);
+    if (!base) {
+        CloseHandle(hMap);
+        return apr_get_os_error();
+    }
+    
+    *m = (apr_shm_t *) apr_palloc(pool, sizeof(apr_shm_t));
+    (*m)->pool = pool;
+    (*m)->hMap = hMap;
+    (*m)->memblk = base;
+    (*m)->size = size;
+
+    (*m)->usrmem = (char*)base + sizeof(memblock_t);
+    (*m)->length = reqsize - sizeof(memblock_t);;
+    
+    (*m)->memblk->length = (*m)->length;
+    (*m)->memblk->size = (*m)->size;
+    (*m)->filename = file ? apr_pstrdup(pool, file) : NULL;
+
+    apr_pool_cleanup_register((*m)->pool, *m, 
+                              shm_cleanup, apr_pool_cleanup_null);
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_shm_create(apr_shm_t **m,
+                                         apr_size_t reqsize,
+                                         const char *file,
+                                         apr_pool_t *pool)
+{
+    return apr_shm_create_ex(m, reqsize, file, pool, 0);
+}
+
+APR_DECLARE(apr_status_t) apr_shm_destroy(apr_shm_t *m) 
+{
+    apr_status_t rv = shm_cleanup(m);
+    apr_pool_cleanup_kill(m->pool, m, shm_cleanup);
+    return rv;
+}
+
+APR_DECLARE(apr_status_t) apr_shm_remove(const char *filename,
+                                         apr_pool_t *pool)
+{
+    return apr_file_remove(filename, pool);
+}
+
+APR_DECLARE(apr_status_t) apr_shm_delete(apr_shm_t *m)
+{
+    if (m->filename) {
+        return apr_shm_remove(m->filename, m->pool);
+    }
+    else {
+        return APR_ENOTIMPL;
+    }
+} 
+
+static apr_status_t shm_attach_internal(apr_shm_t **m,
+                                        const char *file,
+                                        apr_pool_t *pool,
+                                        int global)
+{
+    HANDLE hMap;
+    void *mapkey;
+    void *base;
+
+    /* res_name_from_filename turns file into a pseudo-name
+     * without slashes or backslashes, and prepends the \global
+     * or local prefix on Win2K and later
+     */
+    mapkey = res_name_from_filename(file, global, pool);
+
+#if APR_HAS_UNICODE_FS
+    IF_WIN_OS_IS_UNICODE
+    {
+#ifndef _WIN32_WCE
+        hMap = OpenFileMappingW(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, mapkey);
+#else
+        /* The WCE 3.0 lacks OpenFileMapping. So we emulate one with
+         * opening the existing shmem and reading its size from the header 
+         */
+        hMap = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, 
+                                  PAGE_READWRITE, 0, sizeof(apr_shm_t), mapkey);
+#endif
+    }
+#endif
+#if APR_HAS_ANSI_FS
+    ELSE_WIN_OS_IS_ANSI
+    {
+        hMap = OpenFileMappingA(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, mapkey);
+    }
+#endif
+
+    if (!hMap) {
+        return apr_get_os_error();
+    }
+    
+    base = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
+    if (!base) {
+        CloseHandle(hMap);
+        return apr_get_os_error();
+    }
+    
+    *m = (apr_shm_t *) apr_palloc(pool, sizeof(apr_shm_t));
+    (*m)->pool = pool;
+    (*m)->memblk = base;
+    /* Real (*m)->mem->size could be recovered with VirtualQuery */
+    (*m)->size = (*m)->memblk->size;
+#if _WIN32_WCE
+    /* Reopen with real size  */
+    UnmapViewOfFile(base);
+    CloseHandle(hMap);
+
+    hMap = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, 
+                              PAGE_READWRITE, 0, (*m)->size, mapkey);
+    if (!hMap) {
+        return apr_get_os_error();
+    }
+    base = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
+    if (!base) {
+        CloseHandle(hMap);
+        return apr_get_os_error();
+    }    
+#endif
+    (*m)->hMap = hMap;
+    (*m)->length = (*m)->memblk->length;
+    (*m)->usrmem = (char*)base + sizeof(memblock_t);
+    (*m)->filename = NULL;
+
+    apr_pool_cleanup_register((*m)->pool, *m, 
+                              shm_cleanup, apr_pool_cleanup_null);
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_shm_attach_ex(apr_shm_t **m,
+                                            const char *file,
+                                            apr_pool_t *pool,
+                                            apr_int32_t flags)
+{
+    apr_status_t rv;
+    int can_create_global;
+    int try_global_local[3] = {-1, -1, -1};
+    int cur;
+
+    if (!file) {
+        return APR_EINVAL;
+    }
+
+    if (flags & APR_SHM_NS_LOCAL) {
+        try_global_local[0] = 0; /* only search local */
+    }
+    else if (flags & APR_SHM_NS_GLOBAL) {
+        try_global_local[0] = 1; /* only search global */
+    }
+    else {
+        can_create_global = can_create_global_maps();
+        if (!can_create_global) { /* unprivileged process */
+            try_global_local[0] = 0; /* search local before global */
+            try_global_local[1] = 1;
+        }
+        else {
+            try_global_local[0] = 1; /* search global before local */
+            try_global_local[1] = 0;
+        }
+    }
+
+    for (cur = 0; try_global_local[cur] != -1; cur++) {
+        rv = shm_attach_internal(m, file, pool, try_global_local[cur]);
+        if (!APR_STATUS_IS_ENOENT(rv)) {
+            break;
+        }
+    }
+
+    return rv;
+}
+
+APR_DECLARE(apr_status_t) apr_shm_attach(apr_shm_t **m,
+                                         const char *file,
+                                         apr_pool_t *pool)
+{
+    return apr_shm_attach_ex(m, file, pool, 0);
+}
+
+APR_DECLARE(apr_status_t) apr_shm_detach(apr_shm_t *m)
+{
+    apr_status_t rv = shm_cleanup(m);
+    apr_pool_cleanup_kill(m->pool, m, shm_cleanup);
+    return rv;
+}
+
+APR_DECLARE(void *) apr_shm_baseaddr_get(const apr_shm_t *m)
+{
+    return m->usrmem;
+}
+
+APR_DECLARE(apr_size_t) apr_shm_size_get(const apr_shm_t *m)
+{
+    return m->length;
+}
+
+APR_PERMS_SET_ENOTIMPL(shm)
+
+APR_POOL_IMPLEMENT_ACCESSOR(shm)
+
+APR_DECLARE(apr_status_t) apr_os_shm_get(apr_os_shm_t *osshm,
+                                         apr_shm_t *shm)
+{
+    *osshm = shm->hMap;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_os_shm_put(apr_shm_t **m,
+                                         apr_os_shm_t *osshm,
+                                         apr_pool_t *pool)
+{
+    void* base;
+    base = MapViewOfFile(*osshm, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
+    if (!base) {
+        return apr_get_os_error();
+    }
+    
+    *m = (apr_shm_t *) apr_palloc(pool, sizeof(apr_shm_t));
+    (*m)->pool = pool;
+    (*m)->hMap = *osshm;
+    (*m)->memblk = base;
+    (*m)->usrmem = (char*)base + sizeof(memblock_t);
+    /* Real (*m)->mem->size could be recovered with VirtualQuery */
+    (*m)->size = (*m)->memblk->size;
+    (*m)->length = (*m)->memblk->length;
+    (*m)->filename = NULL;
+
+    apr_pool_cleanup_register((*m)->pool, *m, 
+                              shm_cleanup, apr_pool_cleanup_null);
+    return APR_SUCCESS;
+}    
+
diff --git a/strings/apr_cpystrn.c b/strings/apr_cpystrn.c
new file mode 100644
index 00000000000..fb96025a00a
--- /dev/null
+++ b/strings/apr_cpystrn.c
@@ -0,0 +1,315 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_strings.h"
+#include "apr_private.h"
+#include "apr_lib.h"
+
+#if APR_HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#if APR_HAVE_STRING_H
+#include <string.h>
+#endif
+#if APR_HAVE_CTYPE_H
+#include <ctype.h>
+#endif
+
+/*
+ * Apache's "replacement" for the strncpy() function. We roll our
+ * own to implement these specific changes:
+ *   (1) strncpy() doesn't always null terminate and we want it to.
+ *   (2) strncpy() null fills, which is bogus, esp. when copy 8byte
+ *       strings into 8k blocks.
+ *   (3) Instead of returning the pointer to the beginning of
+ *       the destination string, we return a pointer to the
+ *       terminating '\0' to allow us to "check" for truncation
+ *   (4) If src is NULL, null terminate dst (empty string copy)
+ *
+ * apr_cpystrn() follows the same call structure as strncpy().
+ */
+
+APR_DECLARE(char *) apr_cpystrn(char *dst, const char *src, apr_size_t dst_size)
+{
+
+    char *d = dst, *end;
+
+    if (dst_size == 0) {
+        return (dst);
+    }
+
+    if (src) {
+        end = dst + dst_size - 1;
+
+        for (; d < end; ++d, ++src) {
+            if (!(*d = *src)) {
+                return (d);
+            }
+        }
+    }
+
+    *d = '\0';	/* always null terminate */
+
+    return (d);
+}
+
+
+/*
+ * This function provides a way to parse a generic argument string
+ * into a standard argv[] form of argument list. It respects the 
+ * usual "whitespace" and quoteing rules. In the future this could
+ * be expanded to include support for the apr_call_exec command line
+ * string processing (including converting '+' to ' ' and doing the 
+ * url processing. It does not currently support this function.
+ *
+ *    token_context: Context from which pool allocations will occur.
+ *    arg_str:       Input argument string for conversion to argv[].
+ *    argv_out:      Output location. This is a pointer to an array
+ *                   of pointers to strings (ie. &(char *argv[]).
+ *                   This value will be allocated from the contexts
+ *                   pool and filled in with copies of the tokens
+ *                   found during parsing of the arg_str. 
+ */
+APR_DECLARE(apr_status_t) apr_tokenize_to_argv(const char *arg_str, 
+                                            char ***argv_out,
+                                            apr_pool_t *token_context)
+{
+    const char *cp;
+    const char *ct;
+    char *cleaned, *dirty;
+    int escaped;
+    int isquoted, numargs = 0, argnum;
+
+#define SKIP_WHITESPACE(cp) \
+    for ( ; *cp == ' ' || *cp == '\t'; ) { \
+        cp++; \
+    };
+
+#define CHECK_QUOTATION(cp,isquoted) \
+    isquoted = 0; \
+    if (*cp == '"') { \
+        isquoted = 1; \
+        cp++; \
+    } \
+    else if (*cp == '\'') { \
+        isquoted = 2; \
+        cp++; \
+    }
+
+/* DETERMINE_NEXTSTRING:
+ * At exit, cp will point to one of the following:  NULL, SPACE, TAB or QUOTE.
+ * NULL implies the argument string has been fully traversed.
+ */
+#define DETERMINE_NEXTSTRING(cp,isquoted) \
+    for ( ; *cp != '\0'; cp++) { \
+        if (   (*cp == '\\' && (*(cp+1) == ' ' || *(cp+1) == '\t' || \
+                                *(cp+1) == '"' || *(cp+1) == '\''))) { \
+            cp++; \
+            continue; \
+        } \
+        if (   (!isquoted && (*cp == ' ' || *cp == '\t')) \
+            || (isquoted == 1 && *cp == '"') \
+            || (isquoted == 2 && *cp == '\'')                 ) { \
+            break; \
+        } \
+    }
+ 
+/* REMOVE_ESCAPE_CHARS:
+ * Compresses the arg string to remove all of the '\' escape chars.
+ * The final argv strings should not have any extra escape chars in it.
+ */
+#define REMOVE_ESCAPE_CHARS(cleaned, dirty, escaped) \
+    escaped = 0; \
+    while(*dirty) { \
+        if (!escaped && *dirty == '\\') { \
+            escaped = 1; \
+        } \
+        else { \
+            escaped = 0; \
+            *cleaned++ = *dirty; \
+        } \
+        ++dirty; \
+    } \
+    *cleaned = 0;        /* last line of macro... */
+
+    cp = arg_str;
+    SKIP_WHITESPACE(cp);
+    ct = cp;
+
+    /* This is ugly and expensive, but if anyone wants to figure a
+     * way to support any number of args without counting and 
+     * allocating, please go ahead and change the code.
+     *
+     * Must account for the trailing NULL arg.
+     */
+    numargs = 1;
+    while (*ct != '\0') {
+        CHECK_QUOTATION(ct, isquoted);
+        DETERMINE_NEXTSTRING(ct, isquoted);
+        if (*ct != '\0') {
+            ct++;
+        }
+        numargs++;
+        SKIP_WHITESPACE(ct);
+    }
+    *argv_out = apr_palloc(token_context, numargs * sizeof(char*));
+
+    /*  determine first argument */
+    for (argnum = 0; argnum < (numargs-1); argnum++) {
+        SKIP_WHITESPACE(cp);
+        CHECK_QUOTATION(cp, isquoted);
+        ct = cp;
+        DETERMINE_NEXTSTRING(cp, isquoted);
+        cp++;
+        (*argv_out)[argnum] = apr_palloc(token_context, cp - ct);
+        apr_cpystrn((*argv_out)[argnum], ct, cp - ct);
+        cleaned = dirty = (*argv_out)[argnum];
+        REMOVE_ESCAPE_CHARS(cleaned, dirty, escaped);
+    }
+    (*argv_out)[argnum] = NULL;
+
+    return APR_SUCCESS;
+}
+
+/* Filepath_name_get returns the final element of the pathname.
+ * Using the current platform's filename syntax.
+ *   "/foo/bar/gum" -> "gum"
+ *   "/foo/bar/gum/" -> ""
+ *   "gum" -> "gum"
+ *   "wi\\n32\\stuff" -> "stuff
+ *
+ * Corrected Win32 to accept "a/b\\stuff", "a:stuff"
+ */
+
+APR_DECLARE(const char *) apr_filepath_name_get(const char *pathname)
+{
+    const char path_separator = '/';
+    const char *s = strrchr(pathname, path_separator);
+
+#ifdef WIN32
+    const char path_separator_win = '\\';
+    const char drive_separator_win = ':';
+    const char *s2 = strrchr(pathname, path_separator_win);
+
+    if (s2 > s) s = s2;
+
+    if (!s) s = strrchr(pathname, drive_separator_win);
+#endif
+
+    return s ? ++s : pathname;
+}
+
+/* length of dest assumed >= length of src
+ * collapse in place (src == dest) is legal.
+ * returns terminating null ptr to dest string.
+ */
+APR_DECLARE(char *) apr_collapse_spaces(char *dest, const char *src)
+{
+    while (*src) {
+        if (!apr_isspace(*src)) 
+            *dest++ = *src;
+        ++src;
+    }
+    *dest = 0;
+    return (dest);
+}
+
+#if !APR_HAVE_STRDUP
+char *strdup(const char *str)
+{
+    char *sdup;
+    size_t len = strlen(str) + 1;
+
+    sdup = (char *) malloc(len);
+    if (sdup == NULL)
+        return NULL;
+    memcpy(sdup, str, len);
+
+    return sdup;
+}
+#endif
+
+/* The following two routines were donated for SVR4 by Andreas Vogel */
+#if (!APR_HAVE_STRCASECMP && !APR_HAVE_STRICMP)
+int strcasecmp(const char *a, const char *b)
+{
+    const char *p = a;
+    const char *q = b;
+    for (p = a, q = b; *p && *q; p++, q++) {
+        int diff = apr_tolower(*p) - apr_tolower(*q);
+        if (diff)
+            return diff;
+    }
+    if (*p)
+        return 1;               /* p was longer than q */
+    if (*q)
+        return -1;              /* p was shorter than q */
+    return 0;                   /* Exact match */
+}
+
+#endif
+
+#if (!APR_HAVE_STRNCASECMP && !APR_HAVE_STRNICMP)
+int strncasecmp(const char *a, const char *b, size_t n)
+{
+    const char *p = a;
+    const char *q = b;
+
+    for (p = a, q = b; /*NOTHING */ ; p++, q++) {
+        int diff;
+        if (p == a + n)
+            return 0;           /*   Match up to n characters */
+        if (!(*p && *q))
+            return *p - *q;
+        diff = apr_tolower(*p) - apr_tolower(*q);
+        if (diff)
+            return diff;
+    }
+    /*NOTREACHED */
+}
+#endif
+
+/* The following routine was donated for UTS21 by dwd@bell-labs.com */
+#if (!APR_HAVE_STRSTR)
+char *strstr(char *s1, char *s2)
+{
+    char *p1, *p2;
+    if (*s2 == '\0') {
+        /* an empty s2 */
+        return(s1);
+    }
+    while((s1 = strchr(s1, *s2)) != NULL) {
+        /* found first character of s2, see if the rest matches */
+        p1 = s1;
+        p2 = s2;
+        while (*++p1 == *++p2) {
+            if (*p1 == '\0') {
+                /* both strings ended together */
+                return(s1);
+            }
+        }
+        if (*p2 == '\0') {
+            /* second string ended, a match */
+            break;
+        }
+        /* didn't find a match here, try starting at next character in s1 */
+        s1++;
+    }
+    return(s1);
+}
+#endif
+
diff --git a/strings/apr_cstr.c b/strings/apr_cstr.c
new file mode 100644
index 00000000000..7717c4406e7
--- /dev/null
+++ b/strings/apr_cstr.c
@@ -0,0 +1,408 @@
+/*    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ */
+
+#include "apr.h"
+#include "apr_lib.h"
+#include "apr_strings.h"
+#include "apr_fnmatch.h"
+#if 0
+#define APR_WANT_STDIO
+#define APR_WANT_STRFUNC
+#endif
+#include "apr_want.h"
+#include "apr_cstr.h"
+
+APR_DECLARE(void) apr_cstr_split_append(apr_array_header_t *array,
+                                        const char *input,
+                                        const char *sep_chars,
+                                        int chop_whitespace,
+                                        apr_pool_t *pool)
+{
+  char *pats;
+  char *p;
+
+  pats = apr_pstrdup(pool, input);  /* strtok wants non-const data */
+  p = apr_cstr_tokenize(sep_chars, &pats);
+
+  while (p)
+    {
+      if (chop_whitespace)
+        {
+          while (apr_isspace(*p))
+            p++;
+
+          {
+            char *e = p + (strlen(p) - 1);
+            while ((e >= p) && (apr_isspace(*e)))
+              e--;
+            *(++e) = '\0';
+          }
+        }
+
+      if (p[0] != '\0')
+        APR_ARRAY_PUSH(array, const char *) = p;
+
+      p = apr_cstr_tokenize(sep_chars, &pats);
+    }
+
+  return;
+}
+
+
+APR_DECLARE(apr_array_header_t *) apr_cstr_split(const char *input,
+                                                 const char *sep_chars,
+                                                 int chop_whitespace,
+                                                 apr_pool_t *pool)
+{
+  apr_array_header_t *a = apr_array_make(pool, 5, sizeof(input));
+  apr_cstr_split_append(a, input, sep_chars, chop_whitespace, pool);
+  return a;
+}
+
+
+APR_DECLARE(int) apr_cstr_match_glob_list(const char *str,
+                                          const apr_array_header_t *list)
+{
+  int i;
+
+  for (i = 0; i < list->nelts; i++)
+    {
+      const char *this_pattern = APR_ARRAY_IDX(list, i, char *);
+
+      if (apr_fnmatch(this_pattern, str, 0) == APR_SUCCESS)
+        return TRUE;
+    }
+
+  return FALSE;
+}
+
+APR_DECLARE(int) apr_cstr_match_list(const char *str,
+                                     const apr_array_header_t *list)
+{
+  int i;
+
+  for (i = 0; i < list->nelts; i++)
+    {
+      const char *this_str = APR_ARRAY_IDX(list, i, char *);
+
+      if (strcmp(this_str, str) == 0)
+        return TRUE;
+    }
+
+  return FALSE;
+}
+
+APR_DECLARE(char *) apr_cstr_tokenize(const char *sep, char **str)
+{
+    char *token;
+    char *next;
+    char csep;
+
+    /* check parameters */
+    if ((sep == NULL) || (str == NULL) || (*str == NULL))
+        return NULL;
+
+    /* let APR handle edge cases and multiple separators */
+    csep = *sep;
+    if (csep == '\0' || sep[1] != '\0')
+      return apr_strtok(NULL, sep, str);
+
+    /* skip characters in sep (will terminate at '\0') */
+    token = *str;
+    while (*token == csep)
+        ++token;
+
+    if (!*token)          /* no more tokens */
+        return NULL;
+
+    /* skip valid token characters to terminate token and
+     * prepare for the next call (will terminate at '\0)
+     */
+    next = strchr(token, csep);
+    if (next == NULL)
+      {
+        *str = token + strlen(token);
+      }
+    else
+      {
+        *next = '\0';
+        *str = next + 1;
+      }
+
+    return token;
+}
+
+APR_DECLARE(int) apr_cstr_count_newlines(const char *msg)
+{
+  int count = 0;
+  const char *p;
+
+  for (p = msg; *p; p++)
+    {
+      if (*p == '\n')
+        {
+          count++;
+          if (*(p + 1) == '\r')
+            p++;
+        }
+      else if (*p == '\r')
+        {
+          count++;
+          if (*(p + 1) == '\n')
+            p++;
+        }
+    }
+
+  return count;
+}
+
+#if 0 /* XXX: stringbuf logic is not present in APR */
+APR_DECLARE(char *) apr_cstr_join(const apr_array_header_t *strings,
+                                  const char *separator,
+                                  apr_pool_t *pool)
+{
+  svn_stringbuf_t *new_str = svn_stringbuf_create_empty(pool);
+  size_t sep_len = strlen(separator);
+  int i;
+
+  for (i = 0; i < strings->nelts; i++)
+    {
+      const char *string = APR_ARRAY_IDX(strings, i, const char *);
+      svn_stringbuf_appendbytes(new_str, string, strlen(string));
+      svn_stringbuf_appendbytes(new_str, separator, sep_len);
+    }
+  return new_str->data;
+}
+#endif
+
+#if !APR_CHARSET_EBCDIC
+/*
+ * Our own known-fast translation table for casecmp by character.
+ * Only ASCII alpha characters 41-5A are folded to 61-7A, other
+ * octets (such as extended latin alphabetics) are never case-folded.
+ * NOTE: Other than Alpha A-Z/a-z, each code point is unique!
+ */
+static const short ucharmap[] = {
+    0x0,  0x1,  0x2,  0x3,  0x4,  0x5,  0x6,  0x7,
+    0x8,  0x9,  0xa,  0xb,  0xc,  0xd,  0xe,  0xf,
+    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+    0x40,  'a',  'b',  'c',  'd',  'e',  'f',  'g',
+     'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o',
+     'p',  'q',  'r',  's',  't',  'u',  'v',  'w',
+     'x',  'y',  'z', 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+    0x60,  'a',  'b',  'c',  'd',  'e',  'f',  'g',
+     'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o',
+     'p',  'q',  'r',  's',  't',  'u',  'v',  'w',
+     'x',  'y',  'z', 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+    0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+    0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+    0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+    0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+    0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+    0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+    0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+    0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+    0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+    0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+    0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+};
+#else /* APR_CHARSET_EBCDIC */
+/*
+ * Derived from apr-iconv/ccs/cp037.c for EBCDIC case comparison,
+ * provides unique identity of every char value (strict ISO-646
+ * conformance, arbitrary election of an ISO-8859-1 ordering, and
+ * very arbitrary control code assignments into C1 to achieve
+ * identity and a reversible mapping of code points),
+ * then folding the equivalences of ASCII 41-5A into 61-7A, 
+ * presenting comparison results in a somewhat ISO/IEC 10646
+ * (ASCII-like) order, depending on the EBCDIC code page in use.
+ *
+ * NOTE: Other than Alpha A-Z/a-z, each code point is unique!
+ */
+static const short ucharmap[] = {
+    0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F,
+    0x97, 0x8D, 0x8E, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+    0x10, 0x11, 0x12, 0x13, 0x9D, 0x85, 0x08, 0x87,
+    0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F,
+    0x80, 0x81, 0x82, 0x83, 0x84, 0x0A, 0x17, 0x1B,
+    0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07,
+    0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04,
+    0x98, 0x99, 0x9A, 0x9B, 0x14, 0x15, 0x9E, 0x1A,
+    0x20, 0xA0, 0xE2, 0xE4, 0xE0, 0xE1, 0xE3, 0xE5,
+    0xE7, 0xF1, 0xA2, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
+    0x26, 0xE9, 0xEA, 0xEB, 0xE8, 0xED, 0xEE, 0xEF,
+    0xEC, 0xDF, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAC,
+    0x2D, 0x2F, 0xC2, 0xC4, 0xC0, 0xC1, 0xC3, 0xC5,
+    0xC7, 0xD1, 0xA6, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
+    0xF8, 0xC9, 0xCA, 0xCB, 0xC8, 0xCD, 0xCE, 0xCF,
+    0xCC, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
+    0xD8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+    0x68, 0x69, 0xAB, 0xBB, 0xF0, 0xFD, 0xFE, 0xB1,
+    0xB0, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
+    0x71, 0x72, 0xAA, 0xBA, 0xE6, 0xB8, 0xC6, 0xA4,
+    0xB5, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+    0x79, 0x7A, 0xA1, 0xBF, 0xD0, 0xDD, 0xDE, 0xAE,
+    0x5E, 0xA3, 0xA5, 0xB7, 0xA9, 0xA7, 0xB6, 0xBC,
+    0xBD, 0xBE, 0x5B, 0x5D, 0xAF, 0xA8, 0xB4, 0xD7,
+    0x7B, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+    0x68, 0x69, 0xAD, 0xF4, 0xF6, 0xF2, 0xF3, 0xF5,
+    0x7D, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
+    0x71, 0x72, 0xB9, 0xFB, 0xFC, 0xF9, 0xFA, 0xFF,
+    0x5C, 0xF7, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+    0x79, 0x7A, 0xB2, 0xD4, 0xD6, 0xD2, 0xD3, 0xD5,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0xB3, 0xDB, 0xDC, 0xD9, 0xDA, 0x9F
+};
+#endif
+
+APR_DECLARE(int) apr_cstr_casecmp(const char *s1, const char *s2)
+{
+    const unsigned char *str1 = (const unsigned char *)s1;
+    const unsigned char *str2 = (const unsigned char *)s2;
+    for (;;)
+    {
+        const int c1 = (int)(*str1);
+        const int c2 = (int)(*str2);
+        const int cmp = ucharmap[c1] - ucharmap[c2];
+        /* Not necessary to test for !c2, this is caught by cmp */
+        if (cmp || !c1)
+            return cmp;
+        str1++;
+        str2++;
+    }
+}
+
+APR_DECLARE(int) apr_cstr_casecmpn(const char *s1, const char *s2,
+                                   apr_size_t n)
+{
+    const unsigned char *str1 = (const unsigned char *)s1;
+    const unsigned char *str2 = (const unsigned char *)s2;
+    while (n--)
+    {
+        const int c1 = (int)(*str1);
+        const int c2 = (int)(*str2);
+        const int cmp = ucharmap[c1] - ucharmap[c2];
+        /* Not necessary to test for !c2, this is caught by cmp */
+        if (cmp || !c1)
+            return cmp;
+        str1++;
+        str2++;
+    }
+    return 0;
+}
+
+APR_DECLARE(apr_status_t) apr_cstr_strtoui64(apr_uint64_t *n,
+                                             const char *str,
+                                             apr_uint64_t minval,
+                                             apr_uint64_t maxval,
+                                             int base)
+{
+  apr_int64_t val;
+  char *endptr;
+
+  /* We assume errno is thread-safe. */
+  errno = 0; /* APR-0.9 doesn't always set errno */
+
+  /* ### We're throwing away half the number range here.
+   * ### APR needs a apr_strtoui64() function. */
+  val = apr_strtoi64(str, &endptr, base);
+  if (errno == EINVAL || endptr == str || str[0] == '\0' || *endptr != '\0')
+    return APR_EINVAL;
+  if ((errno == ERANGE && (val == APR_INT64_MIN || val == APR_INT64_MAX)) ||
+      val < 0 || (apr_uint64_t)val < minval || (apr_uint64_t)val > maxval)
+    return APR_ERANGE;
+  *n = val;
+  return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_cstr_atoui64(apr_uint64_t *n, const char *str)
+{
+  return apr_cstr_strtoui64(n, str, 0, APR_UINT64_MAX, 10);
+}
+
+APR_DECLARE(apr_status_t) apr_cstr_atoui(unsigned int *n, const char *str)
+{
+  apr_uint64_t val;
+  apr_status_t rv = apr_cstr_strtoui64(&val, str, 0, APR_UINT32_MAX, 10);
+  if (rv == APR_SUCCESS)
+    *n = (unsigned int)val;
+  return rv;
+}
+
+APR_DECLARE(apr_status_t) apr_cstr_strtoi64(apr_int64_t *n,
+                                            const char *str,
+                                            apr_int64_t minval,
+                                            apr_int64_t maxval,
+                                            int base)
+{
+  apr_int64_t val;
+  char *endptr;
+
+  /* We assume errno is thread-safe. */
+  errno = 0; /* APR-0.9 doesn't always set errno */
+
+  val = apr_strtoi64(str, &endptr, base);
+  if (errno == EINVAL || endptr == str || str[0] == '\0' || *endptr != '\0')
+    return APR_EINVAL;
+  if ((errno == ERANGE && (val == APR_INT64_MIN || val == APR_INT64_MAX)) ||
+      val < minval || val > maxval)
+    return APR_ERANGE;
+  *n = val;
+  return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_cstr_atoi64(apr_int64_t *n, const char *str)
+{
+  return apr_cstr_strtoi64(n, str, APR_INT64_MIN, APR_INT64_MAX, 10);
+}
+
+APR_DECLARE(apr_status_t) apr_cstr_atoi(int *n, const char *str)
+{
+  apr_int64_t val;
+  apr_status_t rv;
+
+  rv = apr_cstr_strtoi64(&val, str, APR_INT32_MIN, APR_INT32_MAX, 10);
+  if (rv == APR_SUCCESS)
+    *n = (int)val;
+  return rv;
+}
+
+APR_DECLARE(const char *)
+apr_cstr_skip_prefix(const char *str, const char *prefix)
+{
+  apr_size_t len = strlen(prefix);
+
+  if (strncmp(str, prefix, len) == 0)
+    {
+      return str + len;
+    }
+  else
+    {
+      return NULL;
+    }
+}
diff --git a/strings/apr_fnmatch.c b/strings/apr_fnmatch.c
new file mode 100644
index 00000000000..7dfa846993b
--- /dev/null
+++ b/strings/apr_fnmatch.c
@@ -0,0 +1,482 @@
+/* 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.
+ */ 
+
+
+/* Derived from The Open Group Base Specifications Issue 7, IEEE Std 1003.1-2008
+ * as described in;
+ *   http://pubs.opengroup.org/onlinepubs/9699919799/functions/fnmatch.html
+ *
+ * Filename pattern matches defined in section 2.13, "Pattern Matching Notation"
+ * from chapter 2. "Shell Command Language"
+ *   http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_13
+ * where; 1. A bracket expression starting with an unquoted <circumflex> '^' 
+ * character CONTINUES to specify a non-matching list; 2. an explicit <period> '.' 
+ * in a bracket expression matching list, e.g. "[.abc]" does NOT match a leading 
+ * <period> in a filename; 3. a <left-square-bracket> '[' which does not introduce
+ * a valid bracket expression is treated as an ordinary character; 4. a differing
+ * number of consecutive slashes within pattern and string will NOT match;
+ * 5. a trailing '\' in FNM_ESCAPE mode is treated as an ordinary '\' character.
+ *
+ * Bracket expansion defined in section 9.3.5, "RE Bracket Expression",
+ * from chapter 9, "Regular Expressions"
+ *   http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_03_05
+ * with no support for collating symbols, equivalence class expressions or 
+ * character class expressions.  A partial range expression with a leading 
+ * hyphen following a valid range expression will match only the ordinary
+ * <hyphen> and the ending character (e.g. "[a-m-z]" will match characters 
+ * 'a' through 'm', a <hyphen> '-', or a 'z').
+ *
+ * NOTE: Only POSIX/C single byte locales are correctly supported at this time.
+ * Notably, non-POSIX locales with FNM_CASEFOLD produce undefined results,
+ * particularly in ranges of mixed case (e.g. "[A-z]") or spanning alpha and
+ * nonalpha characters within a range.
+ *
+ * XXX comments below indicate porting required for multi-byte character sets
+ * and non-POSIX locale collation orders; requires mbr* APIs to track shift
+ * state of pattern and string (rewinding pattern and string repeatedly).
+ *
+ * Certain parts of the code assume 0x00-0x3F are unique with any MBCS (e.g.
+ * UTF-8, SHIFT-JIS, etc).  Any implementation allowing '\' as an alternate
+ * path delimiter must be aware that 0x5C is NOT unique within SHIFT-JIS.
+ */
+
+#include "apr_file_info.h"
+#include "apr_fnmatch.h"
+#include "apr_tables.h"
+#include "apr_lib.h"
+#include "apr_strings.h"
+#include <string.h>
+#if APR_HAVE_CTYPE_H
+# include <ctype.h>
+#endif
+
+
+/* Most MBCS/collation/case issues handled here.  Wildcard '*' is not handled.
+ * EOS '\0' and the FNM_PATHNAME '/' delimiters are not advanced over, 
+ * however the "\/" sequence is advanced to '/'.
+ *
+ * Both pattern and string are **char to support pointer increment of arbitrary
+ * multibyte characters for the given locale, in a later iteration of this code
+ */
+static APR_INLINE int fnmatch_ch(const char **pattern, const char **string, int flags)
+{
+    const char * const mismatch = *pattern;
+    const int nocase = !!(flags & APR_FNM_CASE_BLIND);
+    const int escape = !(flags & APR_FNM_NOESCAPE);
+    const int slash = !!(flags & APR_FNM_PATHNAME);
+    int result = APR_FNM_NOMATCH;
+    const char *startch;
+    int negate;
+
+    if (**pattern == '[')
+    {
+        ++*pattern;
+
+        /* Handle negation, either leading ! or ^ operators (never both) */
+        negate = ((**pattern == '!') || (**pattern == '^'));
+        if (negate)
+            ++*pattern;
+
+        /* ']' is an ordinary character at the start of the range pattern */
+        if (**pattern == ']')
+            goto leadingclosebrace;
+
+        while (**pattern)
+        {
+            if (**pattern == ']') {
+                ++*pattern;
+                /* XXX: Fix for MBCS character width */
+                ++*string;
+                return (result ^ negate);
+            }
+
+            if (escape && (**pattern == '\\')) {
+                ++*pattern;
+
+                /* Patterns must be terminated with ']', not EOS */
+                if (!**pattern)
+                    break;
+            }
+
+            /* Patterns must be terminated with ']' not '/' */
+            if (slash && (**pattern == '/'))
+                break;
+
+leadingclosebrace:
+            /* Look at only well-formed range patterns; 
+             * "x-]" is not allowed unless escaped ("x-\]")
+             * XXX: Fix for locale/MBCS character width
+             */
+            if (((*pattern)[1] == '-') && ((*pattern)[2] != ']'))
+            {
+                startch = *pattern;
+                *pattern += (escape && ((*pattern)[2] == '\\')) ? 3 : 2;
+
+                /* NOT a properly balanced [expr] pattern, EOS terminated 
+                 * or ranges containing a slash in FNM_PATHNAME mode pattern
+                 * fall out to to the rewind and test '[' literal code path
+                 */
+                if (!**pattern || (slash && (**pattern == '/')))
+                    break;
+
+                /* XXX: handle locale/MBCS comparison, advance by MBCS char width */
+                if ((**string >= *startch) && (**string <= **pattern))
+                    result = 0;
+                else if (nocase && (isupper(**string) || isupper(*startch)
+                                                      || isupper(**pattern))
+                            && (tolower(**string) >= tolower(*startch)) 
+                            && (tolower(**string) <= tolower(**pattern)))
+                    result = 0;
+
+                ++*pattern;
+                continue;
+            }
+
+            /* XXX: handle locale/MBCS comparison, advance by MBCS char width */
+            if ((**string == **pattern))
+                result = 0;
+            else if (nocase && (isupper(**string) || isupper(**pattern))
+                            && (tolower(**string) == tolower(**pattern)))
+                result = 0;
+
+            ++*pattern;
+        }
+
+        /* NOT a properly balanced [expr] pattern; Rewind
+         * and reset result to test '[' literal
+         */
+        *pattern = mismatch;
+        result = APR_FNM_NOMATCH;
+    }
+    else if (**pattern == '?') {
+        /* Optimize '?' match before unescaping **pattern */
+        if (!**string || (slash && (**string == '/')))
+            return APR_FNM_NOMATCH;
+        result = 0;
+        goto fnmatch_ch_success;
+    }
+    else if (escape && (**pattern == '\\') && (*pattern)[1]) {
+        ++*pattern;
+    }
+
+    /* XXX: handle locale/MBCS comparison, advance by the MBCS char width */
+    if (**string == **pattern)
+        result = 0;
+    else if (nocase && (isupper(**string) || isupper(**pattern))
+                    && (tolower(**string) == tolower(**pattern)))
+        result = 0;
+
+    /* Refuse to advance over trailing slash or nulls
+     */
+    if (!**string || !**pattern || (slash && ((**string == '/') || (**pattern == '/'))))
+        return result;
+
+fnmatch_ch_success:
+    ++*pattern;
+    ++*string;
+    return result;
+}
+
+
+APR_DECLARE(int) apr_fnmatch(const char *pattern, const char *string, int flags)
+{
+    static const char dummystring[2] = {' ', 0};
+    const int escape = !(flags & APR_FNM_NOESCAPE);
+    const int slash = !!(flags & APR_FNM_PATHNAME);
+    const char *strendseg;
+    const char *dummyptr;
+    const char *matchptr;
+    int wild;
+    /* For '*' wild processing only; surpress 'used before initialization'
+     * warnings with dummy initialization values;
+     */
+    const char *strstartseg = NULL;
+    const char *mismatch = NULL;
+    int matchlen = 0;
+
+    if (*pattern == '*')
+        goto firstsegment;
+
+    while (*pattern && *string)
+    {
+        /* Pre-decode "\/" which has no special significance, and
+         * match balanced slashes, starting a new segment pattern
+         */
+        if (slash && escape && (*pattern == '\\') && (pattern[1] == '/'))
+            ++pattern;
+        if (slash && (*pattern == '/') && (*string == '/')) {
+            ++pattern;
+            ++string;
+        }            
+
+firstsegment:
+        /* At the beginning of each segment, validate leading period behavior.
+         */
+        if ((flags & APR_FNM_PERIOD) && (*string == '.'))
+        {
+            if (*pattern == '.')
+                ++pattern;
+            else if (escape && (*pattern == '\\') && (pattern[1] == '.'))
+                pattern += 2;
+            else
+                return APR_FNM_NOMATCH;
+            ++string;
+        }
+
+        /* Determine the end of string segment
+         *
+         * Presumes '/' character is unique, not composite in any MBCS encoding
+         */
+        if (slash) {
+            strendseg = strchr(string, '/');
+            if (!strendseg)
+                strendseg = strchr(string, '\0');
+        }
+        else {
+            strendseg = strchr(string, '\0');
+        }
+
+        /* Allow pattern '*' to be consumed even with no remaining string to match
+         */
+        while (*pattern)
+        {
+            if ((string > strendseg)
+                || ((string == strendseg) && (*pattern != '*')))
+                break;
+
+            if (slash && ((*pattern == '/')
+                           || (escape && (*pattern == '\\')
+                                      && (pattern[1] == '/'))))
+                break;
+
+            /* Reduce groups of '*' and '?' to n '?' matches
+             * followed by one '*' test for simplicity
+             */
+            for (wild = 0; ((*pattern == '*') || (*pattern == '?')); ++pattern)
+            {
+                if (*pattern == '*') {
+                    wild = 1;
+                }
+                else if (string < strendseg) {  /* && (*pattern == '?') */
+                    /* XXX: Advance 1 char for MBCS locale */
+                    ++string;
+                }
+                else {  /* (string >= strendseg) && (*pattern == '?') */
+                    return APR_FNM_NOMATCH;
+                }
+            }
+
+            if (wild)
+            {
+                strstartseg = string;
+                mismatch = pattern;
+
+                /* Count fixed (non '*') char matches remaining in pattern
+                 * excluding '/' (or "\/") and '*'
+                 */
+                for (matchptr = pattern, matchlen = 0; 1; ++matchlen)
+                {
+                    if ((*matchptr == '\0') 
+                        || (slash && ((*matchptr == '/')
+                                      || (escape && (*matchptr == '\\')
+                                                 && (matchptr[1] == '/')))))
+                    {
+                        /* Compare precisely this many trailing string chars,
+                         * the resulting match needs no wildcard loop
+                         */
+                        /* XXX: Adjust for MBCS */
+                        if (string + matchlen > strendseg)
+                            return APR_FNM_NOMATCH;
+
+                        string = strendseg - matchlen;
+                        wild = 0;
+                        break;
+                    }
+
+                    if (*matchptr == '*')
+                    {
+                        /* Ensure at least this many trailing string chars remain
+                         * for the first comparison
+                         */
+                        /* XXX: Adjust for MBCS */
+                        if (string + matchlen > strendseg)
+                            return APR_FNM_NOMATCH;
+
+                        /* Begin first wild comparison at the current position */
+                        break;
+                    }
+
+                    /* Skip forward in pattern by a single character match
+                     * Use a dummy fnmatch_ch() test to count one "[range]" escape
+                     */ 
+                    /* XXX: Adjust for MBCS */
+                    if (escape && (*matchptr == '\\') && matchptr[1]) {
+                        matchptr += 2;
+                    }
+                    else if (*matchptr == '[') {
+                        dummyptr = dummystring;
+                        fnmatch_ch(&matchptr, &dummyptr, flags);
+                    }
+                    else {
+                        ++matchptr;
+                    }
+                }
+            }
+
+            /* Incrementally match string against the pattern
+             */
+            while (*pattern && (string < strendseg))
+            {
+                /* Success; begin a new wild pattern search
+                 */
+                if (*pattern == '*')
+                    break;
+
+                if (slash && ((*string == '/')
+                              || (*pattern == '/')
+                              || (escape && (*pattern == '\\')
+                                         && (pattern[1] == '/'))))
+                    break;
+
+                /* Compare ch's (the pattern is advanced over "\/" to the '/',
+                 * but slashes will mismatch, and are not consumed)
+                 */
+                if (!fnmatch_ch(&pattern, &string, flags))
+                    continue;
+
+                /* Failed to match, loop against next char offset of string segment 
+                 * until not enough string chars remain to match the fixed pattern
+                 */
+                if (wild) {
+                    /* XXX: Advance 1 char for MBCS locale */
+                    string = ++strstartseg;
+                    if (string + matchlen > strendseg)
+                        return APR_FNM_NOMATCH;
+
+                    pattern = mismatch;
+                    continue;
+                }
+                else
+                    return APR_FNM_NOMATCH;
+            }
+        }
+
+        if (*string && !(slash && (*string == '/')))
+            return APR_FNM_NOMATCH;
+
+        if (*pattern && !(slash && ((*pattern == '/')
+                                    || (escape && (*pattern == '\\')
+                                               && (pattern[1] == '/')))))
+            return APR_FNM_NOMATCH;
+    }
+
+    /* Where both pattern and string are at EOS, declare success
+     */
+    if (!*string && !*pattern)
+        return 0;
+
+    /* pattern didn't match to the end of string */
+    return APR_FNM_NOMATCH;
+}
+
+
+/* This function is an Apache addition
+ * return non-zero if pattern has any glob chars in it
+ * @bug Function does not distinguish for FNM_PATHNAME mode, which renders
+ * a false positive for test[/]this (which is not a range, but 
+ * seperate test[ and ]this segments and no glob.)
+ * @bug Function does not distinguish for non-FNM_ESCAPE mode.
+ * @bug Function does not parse []] correctly
+ * Solution may be to use fnmatch_ch() to walk the patterns?
+ */
+APR_DECLARE(int) apr_fnmatch_test(const char *pattern)
+{
+    int nesting;
+
+    nesting = 0;
+    while (*pattern) {
+        switch (*pattern) {
+        case '?':
+        case '*':
+            return 1;
+
+        case '\\':
+            if (*++pattern == '\0') {
+                return 0;
+            }
+            break;
+
+        case '[':         /* '[' is only a glob if it has a matching ']' */
+            ++nesting;
+            break;
+
+        case ']':
+            if (nesting) {
+                return 1;
+            }
+            break;
+        }
+        ++pattern;    }
+    return 0;
+}
+
+
+/* Find all files matching the specified pattern */
+APR_DECLARE(apr_status_t) apr_match_glob(const char *pattern, 
+                                         apr_array_header_t **result,
+                                         apr_pool_t *p)
+{
+    apr_dir_t *dir;
+    apr_finfo_t finfo;
+    apr_status_t rv;
+    char *path;
+
+    /* XXX So, this is kind of bogus.  Basically, I need to strip any leading
+     * directories off the pattern, but there is no portable way to do that.
+     * So, for now we just find the last occurance of '/' and if that doesn't
+     * return anything, then we look for '\'.  This means that we could
+     * screw up on unix if the pattern is something like "foo\.*"  That '\'
+     * isn't a directory delimiter, it is a part of the filename.  To fix this,
+     * we really need apr_filepath_basename, which will be coming as soon as
+     * I get to it.  rbb
+     */
+    char *idx = strrchr(pattern, '/');
+    
+    if (idx == NULL) {
+        idx = strrchr(pattern, '\\');
+    }
+    if (idx == NULL) {
+        path = ".";
+    }
+    else {
+        path = apr_pstrmemdup(p, pattern, idx - pattern);
+        pattern = idx + 1;
+    }
+
+    *result = apr_array_make(p, 0, sizeof(char *));
+    rv = apr_dir_open(&dir, path, p);
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
+    while (apr_dir_read(&finfo, APR_FINFO_NAME, dir) == APR_SUCCESS) {
+        if (apr_fnmatch(pattern, finfo.name, 0) == APR_SUCCESS) {
+            *(const char **)apr_array_push(*result) = apr_pstrdup(p, finfo.name);
+        }
+    }
+    apr_dir_close(dir);
+    return APR_SUCCESS;
+}
diff --git a/strings/apr_snprintf.c b/strings/apr_snprintf.c
new file mode 100644
index 00000000000..4acbe2fa5b0
--- /dev/null
+++ b/strings/apr_snprintf.c
@@ -0,0 +1,1407 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_private.h"
+
+#include "apr_lib.h"
+#include "apr_strings.h"
+#include "apr_network_io.h"
+#include "apr_portable.h"
+#include "apr_errno.h"
+#include <math.h>
+#if APR_HAVE_CTYPE_H
+#include <ctype.h>
+#endif
+#if APR_HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#if APR_HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#if APR_HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#if APR_HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#if APR_HAVE_STRING_H
+#include <string.h>
+#endif
+
+typedef enum {
+    NO = 0, YES = 1
+} boolean_e;
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+#define NUL '\0'
+
+static const char null_string[] = "(null)";
+#define S_NULL ((char *)null_string)
+#define S_NULL_LEN 6
+
+#define FLOAT_DIGITS 6
+#define EXPONENT_LENGTH 10
+
+/*
+ * NUM_BUF_SIZE is the size of the buffer used for arithmetic conversions
+ *
+ * NOTICE: this is a magic number; do not decrease it
+ */
+#define NUM_BUF_SIZE 512
+
+/*
+ * cvt - IEEE floating point formatting routines.
+ *       Derived from UNIX V7, Copyright(C) Caldera International Inc.
+ */
+
+/*
+ *    apr_ecvt converts to decimal
+ *      the number of digits is specified by ndigit
+ *      decpt is set to the position of the decimal point
+ *      sign is set to 0 for positive, 1 for negative
+ */
+
+#define NDIG 80
+
+/* buf must have at least NDIG bytes */
+static char *apr_cvt(double arg, int ndigits, int *decpt, int *sign, 
+                     int eflag, char *buf)
+{
+    register int r2;
+    double fi, fj;
+    register char *p, *p1;
+    
+    if (ndigits >= NDIG - 1)
+        ndigits = NDIG - 2;
+    r2 = 0;
+    *sign = 0;
+    p = &buf[0];
+    if (arg < 0) {
+        *sign = 1;
+        arg = -arg;
+    }
+    arg = modf(arg, &fi);
+    /*
+     * Do integer part
+     */
+    if (fi != 0) {
+        p1 = &buf[NDIG];
+        while (p1 > &buf[0] && fi != 0) {
+            fj = modf(fi / 10, &fi);
+            *--p1 = (int) ((fj + .03) * 10) + '0';
+            r2++;
+        }
+        while (p1 < &buf[NDIG])
+            *p++ = *p1++;
+    }
+    else if (arg > 0) {
+        while ((fj = arg * 10) < 1) {
+            arg = fj;
+            r2--;
+        }
+    }
+    p1 = &buf[ndigits];
+    if (eflag == 0)
+        p1 += r2;
+    if (p1 < &buf[0]) {
+        *decpt = -ndigits;
+        buf[0] = '\0';
+        return (buf);
+    }
+    *decpt = r2;
+    while (p <= p1 && p < &buf[NDIG]) {
+        arg *= 10;
+        arg = modf(arg, &fj);
+        *p++ = (int) fj + '0';
+    }
+    if (p1 >= &buf[NDIG]) {
+        buf[NDIG - 1] = '\0';
+        return (buf);
+    }
+    p = p1;
+    *p1 += 5;
+    while (*p1 > '9') {
+        *p1 = '0';
+        if (p1 > buf)
+            ++ * --p1;
+        else {
+            *p1 = '1';
+            (*decpt)++;
+            if (eflag == 0) {
+                if (p > buf)
+                    *p = '0';
+                p++;
+            }
+        }
+    }
+    *p = '\0';
+    return (buf);
+}
+
+static char *apr_ecvt(double arg, int ndigits, int *decpt, int *sign, char *buf)
+{
+    return (apr_cvt(arg, ndigits, decpt, sign, 1, buf));
+}
+
+static char *apr_fcvt(double arg, int ndigits, int *decpt, int *sign, char *buf)
+{
+    return (apr_cvt(arg, ndigits, decpt, sign, 0, buf));
+}
+
+/*
+ * apr_gcvt  - Floating output conversion to
+ * minimal length string
+ */
+
+static char *apr_gcvt(double number, int ndigit, char *buf, boolean_e altform)
+{
+    int sign, decpt;
+    register char *p1, *p2;
+    register int i;
+    char buf1[NDIG];
+
+    p1 = apr_ecvt(number, ndigit, &decpt, &sign, buf1);
+    p2 = buf;
+    if (sign)
+        *p2++ = '-';
+    for (i = ndigit - 1; i > 0 && p1[i] == '0'; i--)
+        ndigit--;
+    if ((decpt >= 0 && decpt - ndigit > 4)
+        || (decpt < 0 && decpt < -3)) {                /* use E-style */
+        decpt--;
+        *p2++ = *p1++;
+        *p2++ = '.';
+        for (i = 1; i < ndigit; i++)
+            *p2++ = *p1++;
+        *p2++ = 'e';
+        if (decpt < 0) {
+            decpt = -decpt;
+            *p2++ = '-';
+        }
+        else
+            *p2++ = '+';
+        if (decpt / 100 > 0)
+            *p2++ = decpt / 100 + '0';
+        if (decpt / 10 > 0)
+            *p2++ = (decpt % 100) / 10 + '0';
+        *p2++ = decpt % 10 + '0';
+    }
+    else {
+        if (decpt <= 0) {
+            if (*p1 != '0')
+                *p2++ = '.';
+            while (decpt < 0) {
+                decpt++;
+                *p2++ = '0';
+            }
+        }
+        for (i = 1; i <= ndigit; i++) {
+            *p2++ = *p1++;
+            if (i == decpt)
+                *p2++ = '.';
+        }
+        if (ndigit < decpt) {
+            while (ndigit++ < decpt)
+                *p2++ = '0';
+            *p2++ = '.';
+        }
+    }
+    if (p2[-1] == '.' && !altform)
+        p2--;
+    *p2 = '\0';
+    return (buf);
+}
+
+/*
+ * The INS_CHAR macro inserts a character in the buffer and writes
+ * the buffer back to disk if necessary
+ * It uses the char pointers sp and bep:
+ *      sp points to the next available character in the buffer
+ *      bep points to the end-of-buffer+1
+ * While using this macro, note that the nextb pointer is NOT updated.
+ *
+ * NOTE: Evaluation of the c argument should not have any side-effects
+ */
+#define INS_CHAR(c, sp, bep, cc)                    \
+{                                                   \
+    if (sp) {                                       \
+        if (sp >= bep) {                            \
+            vbuff->curpos = sp;                     \
+            if (flush_func(vbuff))                  \
+                return -1;                          \
+            sp = vbuff->curpos;                     \
+            bep = vbuff->endpos;                    \
+        }                                           \
+        *sp++ = (c);                                \
+    }                                               \
+    cc++;                                           \
+}
+
+#define NUM(c) (c - '0')
+
+#define STR_TO_DEC(str, num)                        \
+    num = NUM(*str++);                              \
+    while (apr_isdigit(*str))                       \
+    {                                               \
+        num *= 10 ;                                 \
+        num += NUM(*str++);                         \
+    }
+
+/*
+ * This macro does zero padding so that the precision
+ * requirement is satisfied. The padding is done by
+ * adding '0's to the left of the string that is going
+ * to be printed. We don't allow precision to be large
+ * enough that we continue past the start of s.
+ *
+ * NOTE: this makes use of the magic info that s is
+ * always based on num_buf with a size of NUM_BUF_SIZE.
+ */
+#define FIX_PRECISION(adjust, precision, s, s_len)  \
+    if (adjust) {                                   \
+        apr_size_t p = (precision + 1 < NUM_BUF_SIZE) \
+                     ? precision : NUM_BUF_SIZE - 1;  \
+        while (s_len < p)                           \
+        {                                           \
+            *--s = '0';                             \
+            s_len++;                                \
+        }                                           \
+    }
+
+/*
+ * Macro that does padding. The padding is done by printing
+ * the character ch.
+ */
+#define PAD(width, len, ch)                         \
+do                                                  \
+{                                                   \
+    INS_CHAR(ch, sp, bep, cc);                      \
+    width--;                                        \
+}                                                   \
+while (width > len)
+
+/*
+ * Prefix the character ch to the string str
+ * Increase length
+ * Set the has_prefix flag
+ */
+#define PREFIX(str, length, ch)                     \
+    *--str = ch;                                    \
+    length++;                                       \
+    has_prefix=YES;
+
+
+/*
+ * Convert num to its decimal format.
+ * Return value:
+ *   - a pointer to a string containing the number (no sign)
+ *   - len contains the length of the string
+ *   - is_negative is set to TRUE or FALSE depending on the sign
+ *     of the number (always set to FALSE if is_unsigned is TRUE)
+ *
+ * The caller provides a buffer for the string: that is the buf_end argument
+ * which is a pointer to the END of the buffer + 1 (i.e. if the buffer
+ * is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
+ *
+ * Note: we have 2 versions. One is used when we need to use quads
+ * (conv_10_quad), the other when we don't (conv_10). We're assuming the
+ * latter is faster.
+ */
+static char *conv_10(register apr_int32_t num, register int is_unsigned,
+                     register int *is_negative, char *buf_end,
+                     register apr_size_t *len)
+{
+    register char *p = buf_end;
+    register apr_uint32_t magnitude = num;
+
+    if (is_unsigned) {
+        *is_negative = FALSE;
+    }
+    else {
+        *is_negative = (num < 0);
+
+        /*
+         * On a 2's complement machine, negating the most negative integer 
+         * results in a number that cannot be represented as a signed integer.
+         * Here is what we do to obtain the number's magnitude:
+         *      a. add 1 to the number
+         *      b. negate it (becomes positive)
+         *      c. convert it to unsigned
+         *      d. add 1
+         */
+        if (*is_negative) {
+            apr_int32_t t = num + 1;
+            magnitude = ((apr_uint32_t) -t) + 1;
+        }
+    }
+
+    /*
+     * We use a do-while loop so that we write at least 1 digit 
+     */
+    do {
+        register apr_uint32_t new_magnitude = magnitude / 10;
+
+        *--p = (char) (magnitude - new_magnitude * 10 + '0');
+        magnitude = new_magnitude;
+    }
+    while (magnitude);
+
+    *len = buf_end - p;
+    return (p);
+}
+
+static char *conv_10_quad(apr_int64_t num, register int is_unsigned,
+                     register int *is_negative, char *buf_end,
+                     register apr_size_t *len)
+{
+    register char *p = buf_end;
+    apr_uint64_t magnitude = num;
+
+    /*
+     * We see if we can use the faster non-quad version by checking the
+     * number against the largest long value it can be. If <=, we
+     * punt to the quicker version.
+     */
+    if ((magnitude <= APR_UINT32_MAX && is_unsigned)
+        || (num <= APR_INT32_MAX && num >= APR_INT32_MIN && !is_unsigned))
+            return(conv_10((apr_int32_t)num, is_unsigned, is_negative, buf_end, len));
+
+    if (is_unsigned) {
+        *is_negative = FALSE;
+    }
+    else {
+        *is_negative = (num < 0);
+
+        /*
+         * On a 2's complement machine, negating the most negative integer 
+         * results in a number that cannot be represented as a signed integer.
+         * Here is what we do to obtain the number's magnitude:
+         *      a. add 1 to the number
+         *      b. negate it (becomes positive)
+         *      c. convert it to unsigned
+         *      d. add 1
+         */
+        if (*is_negative) {
+            apr_int64_t t = num + 1;
+            magnitude = ((apr_uint64_t) -t) + 1;
+        }
+    }
+
+    /*
+     * We use a do-while loop so that we write at least 1 digit 
+     */
+    do {
+        apr_uint64_t new_magnitude = magnitude / 10;
+
+        *--p = (char) (magnitude - new_magnitude * 10 + '0');
+        magnitude = new_magnitude;
+    }
+    while (magnitude);
+
+    *len = buf_end - p;
+    return (p);
+}
+
+static char *conv_in_addr(struct in_addr *ia, char *buf_end, apr_size_t *len)
+{
+    unsigned addr = ntohl(ia->s_addr);
+    char *p = buf_end;
+    int is_negative;
+    apr_size_t sub_len;
+
+    p = conv_10((addr & 0x000000FF)      , TRUE, &is_negative, p, &sub_len);
+    *--p = '.';
+    p = conv_10((addr & 0x0000FF00) >>  8, TRUE, &is_negative, p, &sub_len);
+    *--p = '.';
+    p = conv_10((addr & 0x00FF0000) >> 16, TRUE, &is_negative, p, &sub_len);
+    *--p = '.';
+    p = conv_10((addr & 0xFF000000) >> 24, TRUE, &is_negative, p, &sub_len);
+
+    *len = buf_end - p;
+    return (p);
+}
+
+
+/* Must be passed a buffer of size NUM_BUF_SIZE where buf_end points
+ * to 1 byte past the end of the buffer. */
+static char *conv_apr_sockaddr(apr_sockaddr_t *sa, char *buf_end, apr_size_t *len)
+{
+    char *p = buf_end;
+    int is_negative;
+    apr_size_t sub_len;
+    char *ipaddr_str;
+
+    p = conv_10(sa->port, TRUE, &is_negative, p, &sub_len);
+    *--p = ':';
+    ipaddr_str = buf_end - NUM_BUF_SIZE;
+    if (apr_sockaddr_ip_getbuf(ipaddr_str, sa->addr_str_len, sa)) {
+        /* Should only fail if the buffer is too small, which it
+         * should not be; but fail safe anyway: */
+        *--p = '?';
+        *len = buf_end - p;
+        return p;
+    }
+    sub_len = strlen(ipaddr_str);
+#if APR_HAVE_IPV6
+    if (sa->family == APR_INET6 &&
+        !IN6_IS_ADDR_V4MAPPED(&sa->sa.sin6.sin6_addr)) {
+        *(p - 1) = ']';
+        p -= sub_len + 2;
+        *p = '[';
+        memcpy(p + 1, ipaddr_str, sub_len);
+    }
+    else
+#endif
+    {
+        p -= sub_len;
+        memcpy(p, ipaddr_str, sub_len);
+    }
+
+    *len = buf_end - p;
+    return (p);
+}
+
+
+
+#if APR_HAS_THREADS
+static char *conv_os_thread_t(apr_os_thread_t *tid, char *buf_end, apr_size_t *len)
+{
+    union {
+        apr_os_thread_t tid;
+        apr_uint64_t u64;
+        apr_uint32_t u32;
+    } u;
+    int is_negative;
+
+    u.tid = *tid;
+    switch(sizeof(u.tid)) {
+    case sizeof(apr_int32_t):
+        return conv_10(u.u32, TRUE, &is_negative, buf_end, len);
+    case sizeof(apr_int64_t):
+        return conv_10_quad(u.u64, TRUE, &is_negative, buf_end, len);
+    default:
+        /* not implemented; stick 0 in the buffer */
+        return conv_10(0, TRUE, &is_negative, buf_end, len);
+    }
+}
+#endif
+
+
+
+/*
+ * Convert a floating point number to a string formats 'f', 'e' or 'E'.
+ * The result is placed in buf, and len denotes the length of the string
+ * The sign is returned in the is_negative argument (and is not placed
+ * in buf).
+ */
+static char *conv_fp(register char format, register double num,
+    boolean_e add_dp, int precision, int *is_negative,
+    char *buf, apr_size_t *len)
+{
+    register char *s = buf;
+    register char *p;
+    int decimal_point;
+    char buf1[NDIG];
+
+    if (format == 'f')
+        p = apr_fcvt(num, precision, &decimal_point, is_negative, buf1);
+    else /* either e or E format */
+        p = apr_ecvt(num, precision + 1, &decimal_point, is_negative, buf1);
+
+    /*
+     * Check for Infinity and NaN
+     */
+    if (apr_isalpha(*p)) {
+        *len = strlen(p);
+        memcpy(buf, p, *len + 1);
+        *is_negative = FALSE;
+        return (buf);
+    }
+
+    if (format == 'f') {
+        if (decimal_point <= 0) {
+            *s++ = '0';
+            if (precision > 0) {
+                *s++ = '.';
+                while (decimal_point++ < 0)
+                    *s++ = '0';
+            }
+            else if (add_dp)
+                *s++ = '.';
+        }
+        else {
+            while (decimal_point-- > 0)
+                *s++ = *p++;
+            if (precision > 0 || add_dp)
+                *s++ = '.';
+        }
+    }
+    else {
+        *s++ = *p++;
+        if (precision > 0 || add_dp)
+            *s++ = '.';
+    }
+
+    /*
+     * copy the rest of p, the NUL is NOT copied
+     */
+    while (*p)
+        *s++ = *p++;
+
+    if (format != 'f') {
+        char temp[EXPONENT_LENGTH];        /* for exponent conversion */
+        apr_size_t t_len;
+        int exponent_is_negative;
+
+        *s++ = format;                /* either e or E */
+        decimal_point--;
+        if (decimal_point != 0) {
+            p = conv_10((apr_int32_t) decimal_point, FALSE, &exponent_is_negative,
+                        &temp[EXPONENT_LENGTH], &t_len);
+            *s++ = exponent_is_negative ? '-' : '+';
+
+            /*
+             * Make sure the exponent has at least 2 digits
+             */
+            if (t_len == 1)
+                *s++ = '0';
+            while (t_len--)
+                *s++ = *p++;
+        }
+        else {
+            *s++ = '+';
+            *s++ = '0';
+            *s++ = '0';
+        }
+    }
+
+    *len = s - buf;
+    return (buf);
+}
+
+
+/*
+ * Convert num to a base X number where X is a power of 2. nbits determines X.
+ * For example, if nbits is 3, we do base 8 conversion
+ * Return value:
+ *      a pointer to a string containing the number
+ *
+ * The caller provides a buffer for the string: that is the buf_end argument
+ * which is a pointer to the END of the buffer + 1 (i.e. if the buffer
+ * is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
+ *
+ * As with conv_10, we have a faster version which is used when
+ * the number isn't quad size.
+ */
+static char *conv_p2(register apr_uint32_t num, register int nbits,
+                     char format, char *buf_end, register apr_size_t *len)
+{
+    register int mask = (1 << nbits) - 1;
+    register char *p = buf_end;
+    static const char low_digits[] = "0123456789abcdef";
+    static const char upper_digits[] = "0123456789ABCDEF";
+    register const char *digits = (format == 'X') ? upper_digits : low_digits;
+
+    do {
+        *--p = digits[num & mask];
+        num >>= nbits;
+    }
+    while (num);
+
+    *len = buf_end - p;
+    return (p);
+}
+
+static char *conv_p2_quad(apr_uint64_t num, register int nbits,
+                     char format, char *buf_end, register apr_size_t *len)
+{
+    register int mask = (1 << nbits) - 1;
+    register char *p = buf_end;
+    static const char low_digits[] = "0123456789abcdef";
+    static const char upper_digits[] = "0123456789ABCDEF";
+    register const char *digits = (format == 'X') ? upper_digits : low_digits;
+
+    if (num <= APR_UINT32_MAX)
+        return(conv_p2((apr_uint32_t)num, nbits, format, buf_end, len));
+
+    do {
+        *--p = digits[num & mask];
+        num >>= nbits;
+    }
+    while (num);
+
+    *len = buf_end - p;
+    return (p);
+}
+
+#if APR_HAS_THREADS
+static char *conv_os_thread_t_hex(apr_os_thread_t *tid, char *buf_end, apr_size_t *len)
+{
+    union {
+        apr_os_thread_t tid;
+        apr_uint64_t u64;
+        apr_uint32_t u32;
+    } u;
+    int is_negative;
+
+    u.tid = *tid;
+    switch(sizeof(u.tid)) {
+    case sizeof(apr_int32_t):
+        return conv_p2(u.u32, 4, 'x', buf_end, len);
+    case sizeof(apr_int64_t):
+        return conv_p2_quad(u.u64, 4, 'x', buf_end, len);
+    default:
+        /* not implemented; stick 0 in the buffer */
+        return conv_10(0, TRUE, &is_negative, buf_end, len);
+    }
+}
+#endif
+
+/*
+ * Do format conversion placing the output in buffer
+ */
+APR_DECLARE(int) apr_vformatter(int (*flush_func)(apr_vformatter_buff_t *),
+    apr_vformatter_buff_t *vbuff, const char *fmt, va_list ap)
+{
+    register char *sp;
+    register char *bep;
+    register int cc = 0;
+    register apr_size_t i;
+
+    register char *s = NULL;
+    char *q;
+    apr_size_t s_len = 0;
+
+    register apr_size_t min_width = 0;
+    apr_size_t precision = 0;
+    enum {
+        LEFT, RIGHT
+    } adjust;
+    char pad_char;
+    char prefix_char;
+
+    double fp_num;
+    apr_int64_t i_quad = 0;
+    apr_uint64_t ui_quad;
+    apr_int32_t i_num = 0;
+    apr_uint32_t ui_num = 0;
+
+    char num_buf[NUM_BUF_SIZE];
+    char char_buf[2];                /* for printing %% and %<unknown> */
+
+    enum var_type_enum {
+            IS_QUAD, IS_LONG, IS_SHORT, IS_INT
+    };
+    enum var_type_enum var_type = IS_INT;
+
+    /*
+     * Flag variables
+     */
+    boolean_e alternate_form;
+    boolean_e print_sign;
+    boolean_e print_blank;
+    boolean_e adjust_precision;
+    boolean_e adjust_width;
+    int is_negative;
+
+    sp = vbuff->curpos;
+    bep = vbuff->endpos;
+
+    while (*fmt) {
+        if (*fmt != '%') {
+            INS_CHAR(*fmt, sp, bep, cc);
+        }
+        else {
+            /*
+             * Default variable settings
+             */
+            boolean_e print_something = YES;
+            adjust = RIGHT;
+            alternate_form = print_sign = print_blank = NO;
+            pad_char = ' ';
+            prefix_char = NUL;
+
+            fmt++;
+
+            /*
+             * Try to avoid checking for flags, width or precision
+             */
+            if (!apr_islower(*fmt)) {
+                /*
+                 * Recognize flags: -, #, BLANK, +
+                 */
+                for (;; fmt++) {
+                    if (*fmt == '-')
+                        adjust = LEFT;
+                    else if (*fmt == '+')
+                        print_sign = YES;
+                    else if (*fmt == '#')
+                        alternate_form = YES;
+                    else if (*fmt == ' ')
+                        print_blank = YES;
+                    else if (*fmt == '0')
+                        pad_char = '0';
+                    else
+                        break;
+                }
+
+                /*
+                 * Check if a width was specified
+                 */
+                if (apr_isdigit(*fmt)) {
+                    STR_TO_DEC(fmt, min_width);
+                    adjust_width = YES;
+                }
+                else if (*fmt == '*') {
+                    int v = va_arg(ap, int);
+                    fmt++;
+                    adjust_width = YES;
+                    if (v < 0) {
+                        adjust = LEFT;
+                        min_width = (apr_size_t)(-v);
+                    }
+                    else
+                        min_width = (apr_size_t)v;
+                }
+                else
+                    adjust_width = NO;
+
+                /*
+                 * Check if a precision was specified
+                 */
+                if (*fmt == '.') {
+                    adjust_precision = YES;
+                    fmt++;
+                    if (apr_isdigit(*fmt)) {
+                        STR_TO_DEC(fmt, precision);
+                    }
+                    else if (*fmt == '*') {
+                        int v = va_arg(ap, int);
+                        fmt++;
+                        precision = (v < 0) ? 0 : (apr_size_t)v;
+                    }
+                    else
+                        precision = 0;
+                }
+                else
+                    adjust_precision = NO;
+            }
+            else
+                adjust_precision = adjust_width = NO;
+
+            /*
+             * Modifier check.  In same cases, APR_OFF_T_FMT can be
+             * "lld" and APR_INT64_T_FMT can be "ld" (that is, off_t is
+             * "larger" than int64). Check that case 1st.
+             * Note that if APR_OFF_T_FMT is "d",
+             * the first if condition is never true. If APR_INT64_T_FMT
+             * is "d' then the second if condition is never true.
+             */
+            if ((sizeof(APR_OFF_T_FMT) > sizeof(APR_INT64_T_FMT)) &&
+                ((sizeof(APR_OFF_T_FMT) == 4 &&
+                 fmt[0] == APR_OFF_T_FMT[0] &&
+                 fmt[1] == APR_OFF_T_FMT[1]) ||
+                (sizeof(APR_OFF_T_FMT) == 3 &&
+                 fmt[0] == APR_OFF_T_FMT[0]) ||
+                (sizeof(APR_OFF_T_FMT) > 4 &&
+                 strncmp(fmt, APR_OFF_T_FMT, 
+                         sizeof(APR_OFF_T_FMT) - 2) == 0))) {
+                /* Need to account for trailing 'd' and null in sizeof() */
+                var_type = IS_QUAD;
+                fmt += (sizeof(APR_OFF_T_FMT) - 2);
+            }
+            else if ((sizeof(APR_INT64_T_FMT) == 4 &&
+                 fmt[0] == APR_INT64_T_FMT[0] &&
+                 fmt[1] == APR_INT64_T_FMT[1]) ||
+                (sizeof(APR_INT64_T_FMT) == 3 &&
+                 fmt[0] == APR_INT64_T_FMT[0]) ||
+                (sizeof(APR_INT64_T_FMT) > 4 &&
+                 strncmp(fmt, APR_INT64_T_FMT, 
+                         sizeof(APR_INT64_T_FMT) - 2) == 0)) {
+                /* Need to account for trailing 'd' and null in sizeof() */
+                var_type = IS_QUAD;
+                fmt += (sizeof(APR_INT64_T_FMT) - 2);
+            }
+            else if (*fmt == 'q') {
+                var_type = IS_QUAD;
+                fmt++;
+            }
+            else if (*fmt == 'l') {
+                var_type = IS_LONG;
+                fmt++;
+            }
+            else if (*fmt == 'h') {
+                var_type = IS_SHORT;
+                fmt++;
+            }
+            else {
+                var_type = IS_INT;
+            }
+
+            /*
+             * Argument extraction and printing.
+             * First we determine the argument type.
+             * Then, we convert the argument to a string.
+             * On exit from the switch, s points to the string that
+             * must be printed, s_len has the length of the string
+             * The precision requirements, if any, are reflected in s_len.
+             *
+             * NOTE: pad_char may be set to '0' because of the 0 flag.
+             *   It is reset to ' ' by non-numeric formats
+             */
+            switch (*fmt) {
+            case 'u':
+                if (var_type == IS_QUAD) {
+                    i_quad = va_arg(ap, apr_uint64_t);
+                    s = conv_10_quad(i_quad, 1, &is_negative,
+                            &num_buf[NUM_BUF_SIZE], &s_len);
+                }
+                else {
+                    if (var_type == IS_LONG)
+                        i_num = (apr_int32_t) va_arg(ap, apr_uint32_t);
+                    else if (var_type == IS_SHORT)
+                        i_num = (apr_int32_t) (unsigned short) va_arg(ap, unsigned int);
+                    else
+                        i_num = (apr_int32_t) va_arg(ap, unsigned int);
+                    s = conv_10(i_num, 1, &is_negative,
+                            &num_buf[NUM_BUF_SIZE], &s_len);
+                }
+                FIX_PRECISION(adjust_precision, precision, s, s_len);
+                break;
+
+            case 'd':
+            case 'i':
+                if (var_type == IS_QUAD) {
+                    i_quad = va_arg(ap, apr_int64_t);
+                    s = conv_10_quad(i_quad, 0, &is_negative,
+                            &num_buf[NUM_BUF_SIZE], &s_len);
+                }
+                else {
+                    if (var_type == IS_LONG)
+                        i_num = va_arg(ap, apr_int32_t);
+                    else if (var_type == IS_SHORT)
+                        i_num = (short) va_arg(ap, int);
+                    else
+                        i_num = va_arg(ap, int);
+                    s = conv_10(i_num, 0, &is_negative,
+                            &num_buf[NUM_BUF_SIZE], &s_len);
+                }
+                FIX_PRECISION(adjust_precision, precision, s, s_len);
+
+                if (is_negative)
+                    prefix_char = '-';
+                else if (print_sign)
+                    prefix_char = '+';
+                else if (print_blank)
+                    prefix_char = ' ';
+                break;
+
+
+            case 'o':
+                if (var_type == IS_QUAD) {
+                    ui_quad = va_arg(ap, apr_uint64_t);
+                    s = conv_p2_quad(ui_quad, 3, *fmt,
+                            &num_buf[NUM_BUF_SIZE], &s_len);
+                }
+                else {
+                    if (var_type == IS_LONG)
+                        ui_num = va_arg(ap, apr_uint32_t);
+                    else if (var_type == IS_SHORT)
+                        ui_num = (unsigned short) va_arg(ap, unsigned int);
+                    else
+                        ui_num = va_arg(ap, unsigned int);
+                    s = conv_p2(ui_num, 3, *fmt,
+                            &num_buf[NUM_BUF_SIZE], &s_len);
+                }
+                FIX_PRECISION(adjust_precision, precision, s, s_len);
+                if (alternate_form && *s != '0') {
+                    *--s = '0';
+                    s_len++;
+                }
+                break;
+
+
+            case 'x':
+            case 'X':
+                if (var_type == IS_QUAD) {
+                    ui_quad = va_arg(ap, apr_uint64_t);
+                    s = conv_p2_quad(ui_quad, 4, *fmt,
+                            &num_buf[NUM_BUF_SIZE], &s_len);
+                }
+                else {
+                    if (var_type == IS_LONG)
+                        ui_num = va_arg(ap, apr_uint32_t);
+                    else if (var_type == IS_SHORT)
+                        ui_num = (unsigned short) va_arg(ap, unsigned int);
+                    else
+                        ui_num = va_arg(ap, unsigned int);
+                    s = conv_p2(ui_num, 4, *fmt,
+                            &num_buf[NUM_BUF_SIZE], &s_len);
+                }
+                FIX_PRECISION(adjust_precision, precision, s, s_len);
+                if (alternate_form && ui_num != 0) {
+                    *--s = *fmt;        /* 'x' or 'X' */
+                    *--s = '0';
+                    s_len += 2;
+                }
+                break;
+
+
+            case 's':
+                s = va_arg(ap, char *);
+                if (s != NULL) {
+                    if (!adjust_precision) {
+                        s_len = strlen(s);
+                    }
+                    else {
+                        /* From the C library standard in section 7.9.6.1:
+                         * ...if the precision is specified, no more then
+                         * that many characters are written.  If the
+                         * precision is not specified or is greater
+                         * than the size of the array, the array shall
+                         * contain a null character.
+                         *
+                         * My reading is is precision is specified and
+                         * is less then or equal to the size of the
+                         * array, no null character is required.  So
+                         * we can't do a strlen.
+                         *
+                         * This figures out the length of the string
+                         * up to the precision.  Once it's long enough
+                         * for the specified precision, we don't care
+                         * anymore.
+                         *
+                         * NOTE: you must do the length comparison
+                         * before the check for the null character.
+                         * Otherwise, you'll check one beyond the
+                         * last valid character.
+                         */
+                        const char *walk;
+
+                        for (walk = s, s_len = 0;
+                             (s_len < precision) && (*walk != '\0');
+                             ++walk, ++s_len);
+                    }
+                }
+                else {
+                    s = S_NULL;
+                    s_len = S_NULL_LEN;
+                }
+                pad_char = ' ';
+                break;
+
+
+            case 'f':
+            case 'e':
+            case 'E':
+                fp_num = va_arg(ap, double);
+                /*
+                 * We use &num_buf[ 1 ], so that we have room for the sign
+                 */
+                s = NULL;
+#ifdef HAVE_ISNAN
+                if (isnan(fp_num)) {
+                    s = "nan";
+                    s_len = 3;
+                }
+#endif
+#ifdef HAVE_ISINF
+                if (!s && isinf(fp_num)) {
+                    s = "inf";
+                    s_len = 3;
+                }
+#endif
+                if (!s) {
+                    s = conv_fp(*fmt, fp_num, alternate_form,
+                                (int)((adjust_precision == NO) ? FLOAT_DIGITS : precision),
+                                &is_negative, &num_buf[1], &s_len);
+                    if (is_negative)
+                        prefix_char = '-';
+                    else if (print_sign)
+                        prefix_char = '+';
+                    else if (print_blank)
+                        prefix_char = ' ';
+                }
+                break;
+
+
+            case 'g':
+            case 'G':
+                if (adjust_precision == NO)
+                    precision = FLOAT_DIGITS;
+                else if (precision == 0)
+                    precision = 1;
+                /*
+                 * * We use &num_buf[ 1 ], so that we have room for the sign
+                 */
+                s = apr_gcvt(va_arg(ap, double), (int) precision, &num_buf[1],
+                            alternate_form);
+                if (*s == '-')
+                    prefix_char = *s++;
+                else if (print_sign)
+                    prefix_char = '+';
+                else if (print_blank)
+                    prefix_char = ' ';
+
+                s_len = strlen(s);
+
+                if (alternate_form && (q = strchr(s, '.')) == NULL) {
+                    s[s_len++] = '.';
+                    s[s_len] = '\0'; /* delimit for following strchr() */
+                }
+                if (*fmt == 'G' && (q = strchr(s, 'e')) != NULL)
+                    *q = 'E';
+                break;
+
+
+            case 'c':
+                char_buf[0] = (char) (va_arg(ap, int));
+                s = &char_buf[0];
+                s_len = 1;
+                pad_char = ' ';
+                break;
+
+
+            case '%':
+                char_buf[0] = '%';
+                s = &char_buf[0];
+                s_len = 1;
+                pad_char = ' ';
+                break;
+
+
+            case 'n':
+                if (var_type == IS_QUAD)
+                    *(va_arg(ap, apr_int64_t *)) = cc;
+                else if (var_type == IS_LONG)
+                    *(va_arg(ap, long *)) = cc;
+                else if (var_type == IS_SHORT)
+                    *(va_arg(ap, short *)) = cc;
+                else
+                    *(va_arg(ap, int *)) = cc;
+                print_something = NO;
+                break;
+
+                /*
+                 * This is where we extend the printf format, with a second
+                 * type specifier
+                 */
+            case 'p':
+                switch(*++fmt) {
+                /*
+                 * If the pointer size is equal to or smaller than the size
+                 * of the largest unsigned int, we convert the pointer to a
+                 * hex number, otherwise we print "%p" to indicate that we
+                 * don't handle "%p".
+                 */
+                case 'p':
+#if APR_SIZEOF_VOIDP == 8
+                    if (sizeof(void *) <= sizeof(apr_uint64_t)) {
+                        ui_quad = (apr_uint64_t) va_arg(ap, void *);
+                        s = conv_p2_quad(ui_quad, 4, 'x',
+                                &num_buf[NUM_BUF_SIZE], &s_len);
+                    }
+#else
+                    if (sizeof(void *) <= sizeof(apr_uint32_t)) {
+                        ui_num = (apr_uint32_t) va_arg(ap, void *);
+                        s = conv_p2(ui_num, 4, 'x',
+                                &num_buf[NUM_BUF_SIZE], &s_len);
+                    }
+#endif
+                    else {
+                        s = "%p";
+                        s_len = 2;
+                        prefix_char = NUL;
+                    }
+                    pad_char = ' ';
+                    break;
+
+                /* print an apr_sockaddr_t as a.b.c.d:port */
+                case 'I':
+                {
+                    apr_sockaddr_t *sa;
+
+                    sa = va_arg(ap, apr_sockaddr_t *);
+                    if (sa != NULL) {
+                        s = conv_apr_sockaddr(sa, &num_buf[NUM_BUF_SIZE], &s_len);
+                        if (adjust_precision && precision < s_len)
+                            s_len = precision;
+                    }
+                    else {
+                        s = S_NULL;
+                        s_len = S_NULL_LEN;
+                    }
+                    pad_char = ' ';
+                }
+                break;
+
+                /* print a struct in_addr as a.b.c.d */
+                case 'A':
+                {
+                    struct in_addr *ia;
+
+                    ia = va_arg(ap, struct in_addr *);
+                    if (ia != NULL) {
+                        s = conv_in_addr(ia, &num_buf[NUM_BUF_SIZE], &s_len);
+                        if (adjust_precision && precision < s_len)
+                            s_len = precision;
+                    }
+                    else {
+                        s = S_NULL;
+                        s_len = S_NULL_LEN;
+                    }
+                    pad_char = ' ';
+                }
+                break;
+
+                /* print the error for an apr_status_t */
+                case 'm':
+                {
+                    apr_status_t *mrv;
+
+                    mrv = va_arg(ap, apr_status_t *);
+                    if (mrv != NULL) {
+                        s = apr_strerror(*mrv, num_buf, NUM_BUF_SIZE-1);
+                        s_len = strlen(s);
+                    }
+                    else {
+                        s = S_NULL;
+                        s_len = S_NULL_LEN;
+                    }
+                    pad_char = ' ';
+                }
+                break;
+
+                case 'T':
+#if APR_HAS_THREADS
+                {
+                    apr_os_thread_t *tid;
+
+                    tid = va_arg(ap, apr_os_thread_t *);
+                    if (tid != NULL) {
+                        s = conv_os_thread_t(tid, &num_buf[NUM_BUF_SIZE], &s_len);
+                        if (adjust_precision && precision < s_len)
+                            s_len = precision;
+                    }
+                    else {
+                        s = S_NULL;
+                        s_len = S_NULL_LEN;
+                    }
+                    pad_char = ' ';
+                }
+#else
+                    char_buf[0] = '0';
+                    s = &char_buf[0];
+                    s_len = 1;
+                    pad_char = ' ';
+#endif
+                    break;
+
+                case 't':
+#if APR_HAS_THREADS
+                {
+                    apr_os_thread_t *tid;
+
+                    tid = va_arg(ap, apr_os_thread_t *);
+                    if (tid != NULL) {
+                        s = conv_os_thread_t_hex(tid, &num_buf[NUM_BUF_SIZE], &s_len);
+                        if (adjust_precision && precision < s_len)
+                            s_len = precision;
+                    }
+                    else {
+                        s = S_NULL;
+                        s_len = S_NULL_LEN;
+                    }
+                    pad_char = ' ';
+                }
+#else
+                    char_buf[0] = '0';
+                    s = &char_buf[0];
+                    s_len = 1;
+                    pad_char = ' ';
+#endif
+                    break;
+
+                case 'B':
+                case 'F':
+                case 'S':
+                {
+                    char buf[5];
+                    apr_off_t size = 0;
+
+                    if (*fmt == 'B') {
+                        apr_uint32_t *arg = va_arg(ap, apr_uint32_t *);
+                        size = (arg) ? *arg : 0;
+                    }
+                    else if (*fmt == 'F') {
+                        apr_off_t *arg = va_arg(ap, apr_off_t *);
+                        size = (arg) ? *arg : 0;
+                    }
+                    else {
+                        apr_size_t *arg = va_arg(ap, apr_size_t *);
+                        size = (arg) ? *arg : 0;
+                    }
+
+                    s = apr_strfsize(size, buf);
+                    s_len = strlen(s);
+                    pad_char = ' ';
+                }
+                break;
+
+                case NUL:
+                    /* if %p ends the string, oh well ignore it */
+                    continue;
+
+                default:
+                    s = "bogus %p";
+                    s_len = 8;
+                    prefix_char = NUL;
+                    (void)va_arg(ap, void *); /* skip the bogus argument on the stack */
+                    break;
+                }
+                break;
+
+            case NUL:
+                /*
+                 * The last character of the format string was %.
+                 * We ignore it.
+                 */
+                continue;
+
+
+                /*
+                 * The default case is for unrecognized %'s.
+                 * We print %<char> to help the user identify what
+                 * option is not understood.
+                 * This is also useful in case the user wants to pass
+                 * the output of format_converter to another function
+                 * that understands some other %<char> (like syslog).
+                 * Note that we can't point s inside fmt because the
+                 * unknown <char> could be preceded by width etc.
+                 */
+            default:
+                char_buf[0] = '%';
+                char_buf[1] = *fmt;
+                s = char_buf;
+                s_len = 2;
+                pad_char = ' ';
+                break;
+            }
+
+            if (prefix_char != NUL && s != S_NULL && s != char_buf) {
+                *--s = prefix_char;
+                s_len++;
+            }
+
+            if (adjust_width && adjust == RIGHT && min_width > s_len) {
+                if (pad_char == '0' && prefix_char != NUL) {
+                    INS_CHAR(*s, sp, bep, cc);
+                    s++;
+                    s_len--;
+                    min_width--;
+                }
+                PAD(min_width, s_len, pad_char);
+            }
+
+            /*
+             * Print the string s. 
+             */
+            if (print_something == YES) {
+                for (i = s_len; i != 0; i--) {
+                    INS_CHAR(*s, sp, bep, cc);
+                    s++;
+                }
+            }
+
+            if (adjust_width && adjust == LEFT && min_width > s_len)
+                PAD(min_width, s_len, pad_char);
+        }
+        fmt++;
+    }
+    vbuff->curpos = sp;
+
+    return cc;
+}
+
+
+static int snprintf_flush(apr_vformatter_buff_t *vbuff)
+{
+    /* if the buffer fills we have to abort immediately, there is no way
+     * to "flush" an apr_snprintf... there's nowhere to flush it to.
+     */
+    return -1;
+}
+
+
+APR_DECLARE_NONSTD(int) apr_snprintf(char *buf, apr_size_t len, 
+                                     const char *format, ...)
+{
+    int cc;
+    va_list ap;
+    apr_vformatter_buff_t vbuff;
+
+    if (len == 0) {
+        /* NOTE: This is a special case; we just want to return the number
+         * of chars that would be written (minus \0) if the buffer
+         * size was infinite. We leverage the fact that INS_CHAR
+         * just does actual inserts iff the buffer pointer is non-NULL.
+         * In this case, we don't care what buf is; it can be NULL, since
+         * we don't touch it at all.
+         */
+        vbuff.curpos = NULL;
+        vbuff.endpos = NULL;
+    } else {
+        /* save one byte for nul terminator */
+        vbuff.curpos = buf;
+        vbuff.endpos = buf + len - 1;
+    }
+    va_start(ap, format);
+    cc = apr_vformatter(snprintf_flush, &vbuff, format, ap);
+    va_end(ap);
+    if (len != 0) {
+        *vbuff.curpos = '\0';
+    }
+    return (cc == -1) ? (int)len - 1 : cc;
+}
+
+
+APR_DECLARE(int) apr_vsnprintf(char *buf, apr_size_t len, const char *format,
+                               va_list ap)
+{
+    int cc;
+    apr_vformatter_buff_t vbuff;
+
+    if (len == 0) {
+        /* See above note */
+        vbuff.curpos = NULL;
+        vbuff.endpos = NULL;
+    } else {
+        /* save one byte for nul terminator */
+        vbuff.curpos = buf;
+        vbuff.endpos = buf + len - 1;
+    }
+    cc = apr_vformatter(snprintf_flush, &vbuff, format, ap);
+    if (len != 0) {
+        *vbuff.curpos = '\0';
+    }
+    return (cc == -1) ? (int)len - 1 : cc;
+}
diff --git a/strings/apr_strings.c b/strings/apr_strings.c
new file mode 100644
index 00000000000..0ba49c844c6
--- /dev/null
+++ b/strings/apr_strings.c
@@ -0,0 +1,467 @@
+/* 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.
+ */
+/*
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "apr.h"
+#include "apr_strings.h"
+#include "apr_general.h"
+#include "apr_private.h"
+#include "apr_lib.h"
+#define APR_WANT_STDIO
+#define APR_WANT_STRFUNC
+#include "apr_want.h"
+
+#ifdef HAVE_STDDEF_H
+#include <stddef.h> /* NULL */
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h> /* strtol and strtoll */
+#endif
+
+/** this is used to cache lengths in apr_pstrcat */
+#define MAX_SAVED_LENGTHS  6
+
+APR_DECLARE(char *) apr_pstrdup(apr_pool_t *a, const char *s)
+{
+    char *res;
+    apr_size_t len;
+
+    if (s == NULL) {
+        return NULL;
+    }
+    len = strlen(s) + 1;
+    res = apr_pmemdup(a, s, len);
+    return res;
+}
+
+APR_DECLARE(char *) apr_pstrndup(apr_pool_t *a, const char *s, apr_size_t n)
+{
+    char *res;
+    const char *end;
+
+    if (s == NULL) {
+        return NULL;
+    }
+    end = memchr(s, '\0', n);
+    if (end != NULL)
+        n = end - s;
+    res = apr_palloc(a, n + 1);
+    memcpy(res, s, n);
+    res[n] = '\0';
+    return res;
+}
+
+APR_DECLARE(char *) apr_pstrmemdup(apr_pool_t *a, const char *s, apr_size_t n)
+{
+    char *res;
+
+    if (s == NULL) {
+        return NULL;
+    }
+    res = apr_palloc(a, n + 1);
+    memcpy(res, s, n);
+    res[n] = '\0';
+    return res;
+}
+
+APR_DECLARE(void *) apr_pmemdup(apr_pool_t *a, const void *m, apr_size_t n)
+{
+    void *res;
+
+    if (m == NULL)
+	return NULL;
+    res = apr_palloc(a, n);
+    memcpy(res, m, n);
+    return res;
+}
+
+APR_DECLARE_NONSTD(char *) apr_pstrcat(apr_pool_t *a, ...)
+{
+    char *cp, *argp, *res;
+    apr_size_t saved_lengths[MAX_SAVED_LENGTHS];
+    int nargs = 0;
+
+    /* Pass one --- find length of required string */
+
+    apr_size_t len = 0;
+    va_list adummy;
+
+    va_start(adummy, a);
+
+    while ((cp = va_arg(adummy, char *)) != NULL) {
+        apr_size_t cplen = strlen(cp);
+        if (nargs < MAX_SAVED_LENGTHS) {
+            saved_lengths[nargs++] = cplen;
+        }
+        len += cplen;
+    }
+
+    va_end(adummy);
+
+    /* Allocate the required string */
+
+    res = (char *) apr_palloc(a, len + 1);
+    cp = res;
+
+    /* Pass two --- copy the argument strings into the result space */
+
+    va_start(adummy, a);
+
+    nargs = 0;
+    while ((argp = va_arg(adummy, char *)) != NULL) {
+        if (nargs < MAX_SAVED_LENGTHS) {
+            len = saved_lengths[nargs++];
+        }
+        else {
+            len = strlen(argp);
+        }
+ 
+        memcpy(cp, argp, len);
+        cp += len;
+    }
+
+    va_end(adummy);
+
+    /* Return the result string */
+
+    *cp = '\0';
+
+    return res;
+}
+
+APR_DECLARE(char *) apr_pstrcatv(apr_pool_t *a, const struct iovec *vec,
+                                 apr_size_t nvec, apr_size_t *nbytes)
+{
+    apr_size_t i;
+    apr_size_t len;
+    const struct iovec *src;
+    char *res;
+    char *dst;
+
+    /* Pass one --- find length of required string */
+    len = 0;
+    src = vec;
+    for (i = nvec; i; i--) {
+        len += src->iov_len;
+        src++;
+    }
+    if (nbytes) {
+        *nbytes = len;
+    }
+
+    /* Allocate the required string */
+    res = (char *) apr_palloc(a, len + 1);
+    
+    /* Pass two --- copy the argument strings into the result space */
+    src = vec;
+    dst = res;
+    for (i = nvec; i; i--) {
+        memcpy(dst, src->iov_base, src->iov_len);
+        dst += src->iov_len;
+        src++;
+    }
+
+    /* Return the result string */
+    *dst = '\0';
+
+    return res;
+}
+
+#if (!APR_HAVE_MEMCHR)
+void *memchr(const void *s, int c, size_t n)
+{
+    const char *cp;
+
+    for (cp = s; n > 0; n--, cp++) {
+        if (*cp == c)
+            return (char *) cp; /* Casting away the const here */
+    }
+
+    return NULL;
+}
+#endif
+
+#ifndef INT64_MAX
+#define INT64_MAX  APR_INT64_C(0x7fffffffffffffff)
+#endif
+#ifndef INT64_MIN
+#define INT64_MIN (-APR_INT64_C(0x7fffffffffffffff) - APR_INT64_C(1))
+#endif
+
+APR_DECLARE(apr_status_t) apr_strtoff(apr_off_t *offset, const char *nptr,
+                                      char **endptr, int base)
+{
+    errno = 0;
+    *offset = APR_OFF_T_STRFN(nptr, endptr, base);
+    return APR_FROM_OS_ERROR(errno);
+}
+
+APR_DECLARE(apr_int64_t) apr_strtoi64(const char *nptr, char **endptr, int base)
+{
+#ifdef APR_INT64_STRFN
+    errno = 0;
+    return APR_INT64_STRFN(nptr, endptr, base);
+#else
+    const char *s;
+    apr_int64_t acc;
+    apr_int64_t val;
+    int neg, any;
+    char c;
+
+    errno = 0;
+    /*
+     * Skip white space and pick up leading +/- sign if any.
+     * If base is 0, allow 0x for hex and 0 for octal, else
+     * assume decimal; if base is already 16, allow 0x.
+     */
+    s = nptr;
+    do {
+	c = *s++;
+    } while (apr_isspace(c));
+    if (c == '-') {
+	neg = 1;
+	c = *s++;
+    } else {
+	neg = 0;
+	if (c == '+')
+	    c = *s++;
+    }
+    if ((base == 0 || base == 16) &&
+	c == '0' && (*s == 'x' || *s == 'X')) {
+	    c = s[1];
+	    s += 2;
+	    base = 16;
+    }
+    if (base == 0)
+	base = c == '0' ? 8 : 10;
+    acc = any = 0;
+    if (base < 2 || base > 36) {
+	errno = EINVAL;
+        if (endptr != NULL)
+	    *endptr = (char *)(any ? s - 1 : nptr);
+        return acc;
+    }
+
+    /* The classic bsd implementation requires div/mod operators
+     * to compute a cutoff.  Benchmarking proves that is very, very
+     * evil to some 32 bit processors.  Instead, look for underflow
+     * in both the mult and add/sub operation.  Unlike the bsd impl,
+     * we also work strictly in a signed int64 word as we haven't
+     * implemented the unsigned type in win32.
+     * 
+     * Set 'any' if any `digits' consumed; make it negative to indicate
+     * overflow.
+     */
+    val = 0;
+    for ( ; ; c = *s++) {
+        if (c >= '0' && c <= '9')
+	    c -= '0';
+#if (('Z' - 'A') == 25)
+	else if (c >= 'A' && c <= 'Z')
+	    c -= 'A' - 10;
+	else if (c >= 'a' && c <= 'z')
+	    c -= 'a' - 10;
+#elif APR_CHARSET_EBCDIC
+	else if (c >= 'A' && c <= 'I')
+	    c -= 'A' - 10;
+	else if (c >= 'J' && c <= 'R')
+	    c -= 'J' - 19;
+	else if (c >= 'S' && c <= 'Z')
+	    c -= 'S' - 28;
+	else if (c >= 'a' && c <= 'i')
+	    c -= 'a' - 10;
+	else if (c >= 'j' && c <= 'r')
+	    c -= 'j' - 19;
+	else if (c >= 's' && c <= 'z')
+	    c -= 'z' - 28;
+#else
+#error "CANNOT COMPILE apr_strtoi64(), only ASCII and EBCDIC supported" 
+#endif
+	else
+	    break;
+	if (c >= base)
+	    break;
+	val *= base;
+        if ( (any < 0)	/* already noted an over/under flow - short circuit */
+           || (neg && (val > acc || (val -= c) > acc)) /* underflow */
+           || (!neg && (val < acc || (val += c) < acc))) {       /* overflow */
+            any = -1;	/* once noted, over/underflows never go away */
+#ifdef APR_STRTOI64_OVERFLOW_IS_BAD_CHAR
+            break;
+#endif
+        } else {
+            acc = val;
+	    any = 1;
+        }
+    }
+
+    if (any < 0) {
+	acc = neg ? INT64_MIN : INT64_MAX;
+	errno = ERANGE;
+    } else if (!any) {
+	errno = EINVAL;
+    }
+    if (endptr != NULL)
+	*endptr = (char *)(any ? s - 1 : nptr);
+    return (acc);
+#endif
+}
+
+APR_DECLARE(apr_int64_t) apr_atoi64(const char *buf)
+{
+    return apr_strtoi64(buf, NULL, 10);
+}
+
+APR_DECLARE(char *) apr_itoa(apr_pool_t *p, int n)
+{
+    const int BUFFER_SIZE = sizeof(int) * 3 + 2;
+    char *buf = apr_palloc(p, BUFFER_SIZE);
+    char *start = buf + BUFFER_SIZE - 1;
+    int negative;
+    if (n < 0) {
+	negative = 1;
+	n = -n;
+    }
+    else {
+	negative = 0;
+    }
+    *start = 0;
+    do {
+	*--start = '0' + (n % 10);
+	n /= 10;
+    } while (n);
+    if (negative) {
+	*--start = '-';
+    }
+    return start;
+}
+
+APR_DECLARE(char *) apr_ltoa(apr_pool_t *p, long n)
+{
+    const int BUFFER_SIZE = sizeof(long) * 3 + 2;
+    char *buf = apr_palloc(p, BUFFER_SIZE);
+    char *start = buf + BUFFER_SIZE - 1;
+    int negative;
+    if (n < 0) {
+	negative = 1;
+	n = -n;
+    }
+    else {
+	negative = 0;
+    }
+    *start = 0;
+    do {
+	*--start = (char)('0' + (n % 10));
+	n /= 10;
+    } while (n);
+    if (negative) {
+	*--start = '-';
+    }
+    return start;
+}
+
+APR_DECLARE(char *) apr_off_t_toa(apr_pool_t *p, apr_off_t n)
+{
+    const int BUFFER_SIZE = sizeof(apr_off_t) * 3 + 2;
+    char *buf = apr_palloc(p, BUFFER_SIZE);
+    char *start = buf + BUFFER_SIZE - 1;
+    int negative;
+    if (n < 0) {
+	negative = 1;
+	n = -n;
+    }
+    else {
+	negative = 0;
+    }
+    *start = 0;
+    do {
+	*--start = '0' + (char)(n % 10);
+	n /= 10;
+    } while (n);
+    if (negative) {
+	*--start = '-';
+    }
+    return start;
+}
+
+APR_DECLARE(char *) apr_strfsize(apr_off_t size, char *buf)
+{
+    const char ord[] = "KMGTPE";
+    const char *o = ord;
+    int remain;
+
+    if (size < 0) {
+        return strcpy(buf, "  - ");
+    }
+    if (size < 973) {
+        if (apr_snprintf(buf, 5, "%3d ", (int) size) < 0)
+            return strcpy(buf, "****");
+        return buf;
+    }
+    do {
+        remain = (int)(size & 1023);
+        size >>= 10;
+        if (size >= 973) {
+            ++o;
+            continue;
+        }
+        if (size < 9 || (size == 9 && remain < 973)) {
+            if ((remain = ((remain * 5) + 256) / 512) >= 10)
+                ++size, remain = 0;
+            if (apr_snprintf(buf, 5, "%d.%d%c", (int) size, remain, *o) < 0)
+                return strcpy(buf, "****");
+            return buf;
+        }
+        if (remain >= 512)
+            ++size;
+        if (apr_snprintf(buf, 5, "%3d%c", (int) size, *o) < 0)
+            return strcpy(buf, "****");
+        return buf;
+    } while (1);
+}
+
diff --git a/lib/apr_strnatcmp.c b/strings/apr_strnatcmp.c
similarity index 82%
rename from lib/apr_strnatcmp.c
rename to strings/apr_strnatcmp.c
index ea29fd1778d..0e960e8a90b 100644
--- a/lib/apr_strnatcmp.c
+++ b/strings/apr_strnatcmp.c
@@ -22,10 +22,8 @@
 
 #include <ctype.h>
 #include <string.h>
-#include <assert.h>
-#include <stdio.h>
-
-#include "apr_strnatcmp.h"
+#include "apr_strings.h"
+#include "apr_lib.h"            /* for apr_is*() */
 
 #if defined(__GNUC__)
 #  define UNUSED __attribute__((__unused__))
@@ -45,11 +43,11 @@ compare_right(char const *a, char const *b)
 	both numbers to know that they have the same magnitude, so we
 	remember it in BIAS. */
      for (;; a++, b++) {
-	  if (!isdigit(*a)  &&  !isdigit(*b))
-	       return bias;
-	  else if (!isdigit(*a))
+	  if (!apr_isdigit(*a)  &&  !apr_isdigit(*b))
+	       break;
+	  else if (!apr_isdigit(*a))
 	       return -1;
-	  else if (!isdigit(*b))
+	  else if (!apr_isdigit(*b))
 	       return +1;
 	  else if (*a < *b) {
 	       if (!bias)
@@ -58,10 +56,10 @@ compare_right(char const *a, char const *b)
 	       if (!bias)
 		    bias = +1;
 	  } else if (!*a  &&  !*b)
-	       return bias;
+	       break;
      }
 
-     return 0;
+     return bias;
 }
 
 
@@ -71,11 +69,11 @@ compare_left(char const *a, char const *b)
      /* Compare two left-aligned numbers: the first to have a
         different value wins. */
      for (;; a++, b++) {
-	  if (!isdigit(*a)  &&  !isdigit(*b))
-	       return 0;
-	  else if (!isdigit(*a))
+	  if (!apr_isdigit(*a)  &&  !apr_isdigit(*b))
+	       break;
+	  else if (!apr_isdigit(*a))
 	       return -1;
-	  else if (!isdigit(*b))
+	  else if (!apr_isdigit(*b))
 	       return +1;
 	  else if (*a < *b)
 	       return -1;
@@ -92,21 +90,19 @@ static int strnatcmp0(char const *a, char const *b, int fold_case)
      int ai, bi;
      char ca, cb;
      int fractional, result;
-     
-     assert(a && b);
      ai = bi = 0;
      while (1) {
 	  ca = a[ai]; cb = b[bi];
 
 	  /* skip over leading spaces or zeros */
-	  while (isspace(ca))
+	  while (apr_isspace(ca))
 	       ca = a[++ai];
 
-	  while (isspace(cb))
+	  while (apr_isspace(cb))
 	       cb = b[++bi];
 
 	  /* process run of digits */
-	  if (isdigit(ca)  &&  isdigit(cb)) {
+	  if (apr_isdigit(ca)  &&  apr_isdigit(cb)) {
 	       fractional = (ca == '0' || cb == '0');
 
 	       if (fractional) {
@@ -125,8 +121,8 @@ static int strnatcmp0(char const *a, char const *b, int fold_case)
 	  }
 
 	  if (fold_case) {
-	       ca = toupper(ca);
-	       cb = toupper(cb);
+	       ca = apr_toupper(ca);
+	       cb = apr_toupper(cb);
 	  }
 	  
 	  if (ca < cb)
@@ -140,12 +136,14 @@ static int strnatcmp0(char const *a, char const *b, int fold_case)
 
 
 
-int ap_strnatcmp(char const *a, char const *b) {
+APR_DECLARE(int) apr_strnatcmp(char const *a, char const *b)
+{
      return strnatcmp0(a, b, 0);
 }
 
 
 /* Compare, recognizing numeric string and ignoring case. */
-int ap_strnatcasecmp(char const *a, char const *b) {
+APR_DECLARE(int) apr_strnatcasecmp(char const *a, char const *b)
+{
      return strnatcmp0(a, b, 1);
 }
diff --git a/strings/apr_strtok.c b/strings/apr_strtok.c
new file mode 100644
index 00000000000..517b319d47f
--- /dev/null
+++ b/strings/apr_strtok.c
@@ -0,0 +1,56 @@
+/* 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.
+ */
+
+#ifdef HAVE_STDDEF_H
+#include <stddef.h>        /* for NULL */
+#endif
+
+#include "apr.h"
+#include "apr_strings.h"
+
+#define APR_WANT_STRFUNC   /* for strchr() */
+#include "apr_want.h"
+
+APR_DECLARE(char *) apr_strtok(char *str, const char *sep, char **last)
+{
+    char *token;
+
+    if (!str)           /* subsequent call */
+        str = *last;    /* start where we left off */
+
+    /* skip characters in sep (will terminate at '\0') */
+    while (*str && strchr(sep, *str))
+        ++str;
+
+    if (!*str)          /* no more tokens */
+        return NULL;
+
+    token = str;
+
+    /* skip valid token characters to terminate token and
+     * prepare for the next call (will terminate at '\0) 
+     */
+    *last = token + 1;
+    while (**last && !strchr(sep, **last))
+        ++*last;
+
+    if (**last) {
+        **last = '\0';
+        ++*last;
+    }
+
+    return token;
+}
diff --git a/strmatch/apr_strmatch.c b/strmatch/apr_strmatch.c
new file mode 100644
index 00000000000..e5a0a81b939
--- /dev/null
+++ b/strmatch/apr_strmatch.c
@@ -0,0 +1,118 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_strmatch.h"
+#include "apr_lib.h"
+#define APR_WANT_STRFUNC
+#include "apr_want.h"
+
+
+#define NUM_CHARS  256
+
+/*
+ * String searching functions
+ */
+static const char *match_no_op(const apr_strmatch_pattern *this_pattern,
+                               const char *s, apr_size_t slen)
+{
+    return s;
+}
+
+static const char *match_boyer_moore_horspool(
+                               const apr_strmatch_pattern *this_pattern,
+                               const char *s, apr_size_t slen)
+{
+    const char *s_end = s + slen;
+    apr_size_t *shift = (apr_size_t *)(this_pattern->context);
+    const char *s_next = s + this_pattern->length - 1;
+    const char *p_start = this_pattern->pattern;
+    const char *p_end = p_start + this_pattern->length - 1;
+    while (s_next < s_end) {
+        const char *s_tmp = s_next;
+        const char *p_tmp = p_end;
+        while (*s_tmp == *p_tmp) {
+            p_tmp--;
+            if (p_tmp < p_start) {
+                return s_tmp;
+            }
+            s_tmp--;
+        }
+        s_next += shift[(int)*((const unsigned char *)s_next)];
+    }
+    return NULL;
+}
+
+static const char *match_boyer_moore_horspool_nocase(
+                               const apr_strmatch_pattern *this_pattern,
+                               const char *s, apr_size_t slen)
+{
+    const char *s_end = s + slen;
+    apr_size_t *shift = (apr_size_t *)(this_pattern->context);
+    const char *s_next = s + this_pattern->length - 1;
+    const char *p_start = this_pattern->pattern;
+    const char *p_end = p_start + this_pattern->length - 1;
+    while (s_next < s_end) {
+        const char *s_tmp = s_next;
+        const char *p_tmp = p_end;
+        while (apr_tolower(*s_tmp) == apr_tolower(*p_tmp)) {
+            p_tmp--;
+            if (p_tmp < p_start) {
+                return s_tmp;
+            }
+            s_tmp--;
+        }
+        s_next += shift[(unsigned char)apr_tolower(*s_next)];
+    }
+    return NULL;
+}
+
+APR_DECLARE(const apr_strmatch_pattern *) apr_strmatch_precompile(
+                                              apr_pool_t *p, const char *s,
+                                              int case_sensitive)
+{
+    apr_strmatch_pattern *pattern;
+    apr_size_t i;
+    apr_size_t *shift;
+
+    pattern = apr_palloc(p, sizeof(*pattern));
+    pattern->pattern = s;
+    pattern->length = strlen(s);
+    if (pattern->length == 0) {
+        pattern->compare = match_no_op;
+        pattern->context = NULL;
+        return pattern;
+    }
+
+    shift = (apr_size_t *)apr_palloc(p, sizeof(apr_size_t) * NUM_CHARS);
+    for (i = 0; i < NUM_CHARS; i++) {
+        shift[i] = pattern->length;
+    }
+    if (case_sensitive) {
+        pattern->compare = match_boyer_moore_horspool;
+        for (i = 0; i < pattern->length - 1; i++) {
+            shift[(unsigned char)s[i]] = pattern->length - i - 1;
+        }
+    }
+    else {
+        pattern->compare = match_boyer_moore_horspool_nocase;
+        for (i = 0; i < pattern->length - 1; i++) {
+            shift[(unsigned char)apr_tolower(s[i])] = pattern->length - i - 1;
+        }
+    }
+    pattern->context = shift;
+
+    return pattern;
+}
diff --git a/support/os2/waitio.c b/support/os2/waitio.c
new file mode 100644
index 00000000000..60530e732ff
--- /dev/null
+++ b/support/os2/waitio.c
@@ -0,0 +1,34 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_arch_file_io.h"
+#include "apr_arch_networkio.h"
+#include "apr_errno.h"
+#include "apr_support.h"
+
+apr_status_t apr_wait_for_io_or_timeout(apr_file_t *f, apr_socket_t *s,
+                                        int for_read)
+{
+    if (f) {
+        return apr_file_pipe_wait(f, for_read ? APR_WAIT_READ : APR_WAIT_WRITE);
+    }
+    else if (s) {
+        return apr_socket_wait(s, for_read ? APR_WAIT_READ : APR_WAIT_WRITE);
+    }
+
+    /* Didn't specify a file or socket */
+    return APR_EINVAL;
+}
diff --git a/support/unix/waitio.c b/support/unix/waitio.c
new file mode 100644
index 00000000000..0d762ea6dd6
--- /dev/null
+++ b/support/unix/waitio.c
@@ -0,0 +1,123 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_arch_file_io.h"
+#include "apr_arch_networkio.h"
+#include "apr_poll.h"
+#include "apr_errno.h"
+#include "apr_support.h"
+
+/* The only case where we don't use wait_for_io_or_timeout is on
+ * pre-BONE BeOS, so this check should be sufficient and simpler */
+#if !defined(BEOS_R5) && !defined(OS2) && APR_FILES_AS_SOCKETS
+#define USE_WAIT_FOR_IO
+#endif
+
+#ifdef USE_WAIT_FOR_IO
+
+#ifdef WAITIO_USES_POLL
+
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif
+#ifdef HAVE_SYS_POLL_H
+#include <sys/poll.h>
+#endif
+
+apr_status_t apr_wait_for_io_or_timeout(apr_file_t *f, apr_socket_t *s,
+                                        int for_read)
+{
+    struct pollfd pfd;
+    int rc, timeout;
+
+    timeout    = f        ? f->timeout / 1000 : s->timeout / 1000;
+    pfd.fd     = f        ? f->filedes        : s->socketdes;
+    pfd.events = for_read ? POLLIN            : POLLOUT;
+
+    do {
+        rc = poll(&pfd, 1, timeout);
+    } while (rc == -1 && errno == EINTR);
+    if (rc == 0) {
+        return APR_TIMEUP;
+    }
+    else if (rc > 0) {
+        return APR_SUCCESS;
+    }
+    else {
+        return errno;
+    }
+}
+
+#else /* !WAITIO_USES_POLL */
+
+apr_status_t apr_wait_for_io_or_timeout(apr_file_t *f, apr_socket_t *s,
+                                        int for_read)
+{
+    apr_interval_time_t timeout;
+    apr_pollfd_t pfd;
+    int type = for_read ? APR_POLLIN : APR_POLLOUT;
+    apr_pollset_t *pollset;
+    apr_status_t status;
+
+    /* TODO - timeout should be less each time through this loop */
+    if (f) {
+        pfd.desc_type = APR_POLL_FILE;
+        pfd.desc.f = f;
+
+        pollset = f->pollset;
+        if (pollset == NULL) {
+            status = apr_pollset_create(&(f->pollset), 1, f->pool, 0);
+            if (status != APR_SUCCESS) {
+                return status;
+            }
+            pollset = f->pollset;
+        }
+        timeout = f->timeout;
+    }
+    else {
+        pfd.desc_type = APR_POLL_SOCKET;
+        pfd.desc.s = s;
+
+        pollset = s->pollset;
+        timeout = s->timeout;
+    }
+    pfd.reqevents = type;
+
+    /* Remove the object if it was in the pollset, then add in the new
+     * object with the correct reqevents value. Ignore the status result
+     * on the remove, because it might not be in there (yet).
+     */
+    (void) apr_pollset_remove(pollset, &pfd);
+
+    /* ### check status code */
+    (void) apr_pollset_add(pollset, &pfd);
+
+    do {
+        int numdesc;
+        const apr_pollfd_t *pdesc;
+
+        status = apr_pollset_poll(pollset, timeout, &numdesc, &pdesc);
+
+        if (numdesc == 1 && (pdesc[0].rtnevents & type) != 0) {
+            return APR_SUCCESS;
+        }
+    } while (APR_STATUS_IS_EINTR(status));
+
+    return status;
+}
+#endif /* WAITIO_USES_POLL */
+
+#endif /* USE_WAIT_FOR_IO */
diff --git a/tables/apr_hash.c b/tables/apr_hash.c
new file mode 100644
index 00000000000..d4567710d66
--- /dev/null
+++ b/tables/apr_hash.c
@@ -0,0 +1,571 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_private.h"
+
+#include "apr_general.h"
+#include "apr_pools.h"
+#include "apr_time.h"
+
+#include "apr_hash.h"
+
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if APR_HAVE_STRING_H
+#include <string.h>
+#endif
+
+#if APR_POOL_DEBUG && APR_HAVE_STDIO_H
+#include <stdio.h>
+#endif
+
+/*
+ * The internal form of a hash table.
+ *
+ * The table is an array indexed by the hash of the key; collisions
+ * are resolved by hanging a linked list of hash entries off each
+ * element of the array. Although this is a really simple design it
+ * isn't too bad given that pools have a low allocation overhead.
+ */
+
+typedef struct apr_hash_entry_t apr_hash_entry_t;
+
+struct apr_hash_entry_t {
+    apr_hash_entry_t *next;
+    unsigned int      hash;
+    const void       *key;
+    apr_ssize_t       klen;
+    const void       *val;
+};
+
+/*
+ * Data structure for iterating through a hash table.
+ *
+ * We keep a pointer to the next hash entry here to allow the current
+ * hash entry to be freed or otherwise mangled between calls to
+ * apr_hash_next().
+ */
+struct apr_hash_index_t {
+    apr_hash_t         *ht;
+    apr_hash_entry_t   *this, *next;
+    unsigned int        index;
+};
+
+/*
+ * The size of the array is always a power of two. We use the maximum
+ * index rather than the size so that we can use bitwise-AND for
+ * modular arithmetic.
+ * The count of hash entries may be greater depending on the chosen
+ * collision rate.
+ */
+struct apr_hash_t {
+    apr_pool_t          *pool;
+    apr_hash_entry_t   **array;
+    apr_hash_index_t     iterator;  /* For apr_hash_first(NULL, ...) */
+    unsigned int         count, max, seed;
+    apr_hashfunc_t       hash_func;
+    apr_hash_entry_t    *free;  /* List of recycled entries */
+};
+
+#define INITIAL_MAX 15 /* tunable == 2^n - 1 */
+
+
+/*
+ * Hash creation functions.
+ */
+
+static apr_hash_entry_t **alloc_array(apr_hash_t *ht, unsigned int max)
+{
+   return apr_pcalloc(ht->pool, sizeof(*ht->array) * (max + 1));
+}
+
+APR_DECLARE(apr_hash_t *) apr_hash_make(apr_pool_t *pool)
+{
+    apr_hash_t *ht;
+    apr_time_t now = apr_time_now();
+
+    ht = apr_palloc(pool, sizeof(apr_hash_t));
+    ht->pool = pool;
+    ht->free = NULL;
+    ht->count = 0;
+    ht->max = INITIAL_MAX;
+    ht->seed = (unsigned int)((now >> 32) ^ now ^ (apr_uintptr_t)pool ^
+                              (apr_uintptr_t)ht ^ (apr_uintptr_t)&now) - 1;
+    ht->array = alloc_array(ht, ht->max);
+    ht->hash_func = NULL;
+
+    return ht;
+}
+
+APR_DECLARE(apr_hash_t *) apr_hash_make_custom(apr_pool_t *pool,
+                                               apr_hashfunc_t hash_func)
+{
+    apr_hash_t *ht = apr_hash_make(pool);
+    ht->hash_func = hash_func;
+    return ht;
+}
+
+
+/*
+ * Hash iteration functions.
+ */
+
+APR_DECLARE(apr_hash_index_t *) apr_hash_next(apr_hash_index_t *hi)
+{
+    hi->this = hi->next;
+    while (!hi->this) {
+        if (hi->index > hi->ht->max)
+            return NULL;
+
+        hi->this = hi->ht->array[hi->index++];
+    }
+    hi->next = hi->this->next;
+    return hi;
+}
+
+APR_DECLARE(apr_hash_index_t *) apr_hash_first(apr_pool_t *p, apr_hash_t *ht)
+{
+    apr_hash_index_t *hi;
+    if (p)
+        hi = apr_palloc(p, sizeof(*hi));
+    else
+        hi = &ht->iterator;
+
+    hi->ht = ht;
+    hi->index = 0;
+    hi->this = NULL;
+    hi->next = NULL;
+    return apr_hash_next(hi);
+}
+
+APR_DECLARE(void) apr_hash_this(apr_hash_index_t *hi,
+                                const void **key,
+                                apr_ssize_t *klen,
+                                void **val)
+{
+    if (key)  *key  = hi->this->key;
+    if (klen) *klen = hi->this->klen;
+    if (val)  *val  = (void *)hi->this->val;
+}
+
+APR_DECLARE(const void *) apr_hash_this_key(apr_hash_index_t *hi)
+{
+    const void *key;
+
+    apr_hash_this(hi, &key, NULL, NULL);
+    return key;
+}
+
+APR_DECLARE(apr_ssize_t) apr_hash_this_key_len(apr_hash_index_t *hi)
+{
+    apr_ssize_t klen;
+
+    apr_hash_this(hi, NULL, &klen, NULL);
+    return klen;
+}
+
+APR_DECLARE(void *) apr_hash_this_val(apr_hash_index_t *hi)
+{
+    void *val;
+
+    apr_hash_this(hi, NULL, NULL, &val);
+    return val;
+}
+
+/*
+ * Expanding a hash table
+ */
+
+static void expand_array(apr_hash_t *ht)
+{
+    apr_hash_index_t *hi;
+    apr_hash_entry_t **new_array;
+    unsigned int new_max;
+
+    new_max = ht->max * 2 + 1;
+    new_array = alloc_array(ht, new_max);
+    for (hi = apr_hash_first(NULL, ht); hi; hi = apr_hash_next(hi)) {
+        unsigned int i = hi->this->hash & new_max;
+        hi->this->next = new_array[i];
+        new_array[i] = hi->this;
+    }
+    ht->array = new_array;
+    ht->max = new_max;
+}
+
+static unsigned int hashfunc_default(const char *char_key, apr_ssize_t *klen,
+                                     unsigned int hash)
+{
+    const unsigned char *key = (const unsigned char *)char_key;
+    const unsigned char *p;
+    apr_ssize_t i;
+    
+    /*
+     * This is the popular `times 33' hash algorithm which is used by
+     * perl and also appears in Berkeley DB. This is one of the best
+     * known hash functions for strings because it is both computed
+     * very fast and distributes very well.
+     *
+     * The originator may be Dan Bernstein but the code in Berkeley DB
+     * cites Chris Torek as the source. The best citation I have found
+     * is "Chris Torek, Hash function for text in C, Usenet message
+     * <27038@mimsy.umd.edu> in comp.lang.c , October, 1990." in Rich
+     * Salz's USENIX 1992 paper about INN which can be found at
+     * <http://citeseer.nj.nec.com/salz92internetnews.html>.
+     *
+     * The magic of number 33, i.e. why it works better than many other
+     * constants, prime or not, has never been adequately explained by
+     * anyone. So I try an explanation: if one experimentally tests all
+     * multipliers between 1 and 256 (as I did while writing a low-level
+     * data structure library some time ago) one detects that even
+     * numbers are not useable at all. The remaining 128 odd numbers
+     * (except for the number 1) work more or less all equally well.
+     * They all distribute in an acceptable way and this way fill a hash
+     * table with an average percent of approx. 86%.
+     *
+     * If one compares the chi^2 values of the variants (see
+     * Bob Jenkins ``Hashing Frequently Asked Questions'' at
+     * http://burtleburtle.net/bob/hash/hashfaq.html for a description
+     * of chi^2), the number 33 not even has the best value. But the
+     * number 33 and a few other equally good numbers like 17, 31, 63,
+     * 127 and 129 have nevertheless a great advantage to the remaining
+     * numbers in the large set of possible multipliers: their multiply
+     * operation can be replaced by a faster operation based on just one
+     * shift plus either a single addition or subtraction operation. And
+     * because a hash function has to both distribute good _and_ has to
+     * be very fast to compute, those few numbers should be preferred.
+     *
+     *                  -- Ralf S. Engelschall <rse@engelschall.com>
+     */
+
+    if (*klen == APR_HASH_KEY_STRING) {
+        for (p = key; *p; p++) {
+            hash = hash * 33 + *p;
+        }
+        *klen = p - key;
+    }
+    else {
+        for (p = key, i = *klen; i; i--, p++) {
+            hash = hash * 33 + *p;
+        }
+    }
+
+    return hash;
+}
+
+APR_DECLARE_NONSTD(unsigned int) apr_hashfunc_default(const char *char_key,
+                                                      apr_ssize_t *klen)
+{
+    return hashfunc_default(char_key, klen, 0);
+}
+
+/*
+ * This is where we keep the details of the hash function and control
+ * the maximum collision rate.
+ *
+ * If val is non-NULL it creates and initializes a new hash entry if
+ * there isn't already one there; it returns an updatable pointer so
+ * that hash entries can be removed.
+ */
+
+static apr_hash_entry_t **find_entry(apr_hash_t *ht,
+                                     const void *key,
+                                     apr_ssize_t klen,
+                                     const void *val)
+{
+    apr_hash_entry_t **hep, *he;
+    unsigned int hash;
+
+    if (ht->hash_func)
+        hash = ht->hash_func(key, &klen);
+    else
+        hash = hashfunc_default(key, &klen, ht->seed);
+
+    /* scan linked list */
+    for (hep = &ht->array[hash & ht->max], he = *hep;
+         he; hep = &he->next, he = *hep) {
+        if (he->hash == hash
+            && he->klen == klen
+            && memcmp(he->key, key, klen) == 0)
+            break;
+    }
+    if (he || !val)
+        return hep;
+
+    /* add a new entry for non-NULL values */
+    if ((he = ht->free) != NULL)
+        ht->free = he->next;
+    else
+        he = apr_palloc(ht->pool, sizeof(*he));
+    he->next = NULL;
+    he->hash = hash;
+    he->key  = key;
+    he->klen = klen;
+    he->val  = val;
+    *hep = he;
+    ht->count++;
+    return hep;
+}
+
+APR_DECLARE(apr_hash_t *) apr_hash_copy(apr_pool_t *pool,
+                                        const apr_hash_t *orig)
+{
+    apr_hash_t *ht;
+    apr_hash_entry_t *new_vals;
+    unsigned int i, j;
+
+    ht = apr_palloc(pool, sizeof(apr_hash_t) +
+                    sizeof(*ht->array) * (orig->max + 1) +
+                    sizeof(apr_hash_entry_t) * orig->count);
+    ht->pool = pool;
+    ht->free = NULL;
+    ht->count = orig->count;
+    ht->max = orig->max;
+    ht->seed = orig->seed;
+    ht->hash_func = orig->hash_func;
+    ht->array = (apr_hash_entry_t **)((char *)ht + sizeof(apr_hash_t));
+
+    new_vals = (apr_hash_entry_t *)((char *)(ht) + sizeof(apr_hash_t) +
+                                    sizeof(*ht->array) * (orig->max + 1));
+    j = 0;
+    for (i = 0; i <= ht->max; i++) {
+        apr_hash_entry_t **new_entry = &(ht->array[i]);
+        apr_hash_entry_t *orig_entry = orig->array[i];
+        while (orig_entry) {
+            *new_entry = &new_vals[j++];
+            (*new_entry)->hash = orig_entry->hash;
+            (*new_entry)->key = orig_entry->key;
+            (*new_entry)->klen = orig_entry->klen;
+            (*new_entry)->val = orig_entry->val;
+            new_entry = &((*new_entry)->next);
+            orig_entry = orig_entry->next;
+        }
+        *new_entry = NULL;
+    }
+    return ht;
+}
+
+APR_DECLARE(void *) apr_hash_get(apr_hash_t *ht,
+                                 const void *key,
+                                 apr_ssize_t klen)
+{
+    apr_hash_entry_t *he;
+    he = *find_entry(ht, key, klen, NULL);
+    if (he)
+        return (void *)he->val;
+    else
+        return NULL;
+}
+
+APR_DECLARE(void) apr_hash_set(apr_hash_t *ht,
+                               const void *key,
+                               apr_ssize_t klen,
+                               const void *val)
+{
+    apr_hash_entry_t **hep;
+    hep = find_entry(ht, key, klen, val);
+    if (*hep) {
+        if (!val) {
+            /* delete entry */
+            apr_hash_entry_t *old = *hep;
+            *hep = (*hep)->next;
+            old->next = ht->free;
+            ht->free = old;
+            --ht->count;
+        }
+        else {
+            /* replace entry */
+            (*hep)->val = val;
+            /* check that the collision rate isn't too high */
+            if (ht->count > ht->max) {
+                expand_array(ht);
+            }
+        }
+    }
+    /* else key not present and val==NULL */
+}
+
+APR_DECLARE(void *) apr_hash_get_or_set(apr_hash_t *ht,
+                                        const void *key,
+                                        apr_ssize_t klen,
+                                        const void *val)
+{
+    apr_hash_entry_t **hep;
+    hep = find_entry(ht, key, klen, val);
+    if (*hep) {
+        val = (*hep)->val;
+        /* check that the collision rate isn't too high */
+        if (ht->count > ht->max) {
+            expand_array(ht);
+        }
+        return (void *)val;
+    }
+    /* else key not present and val==NULL */
+    return NULL;
+}
+
+APR_DECLARE(unsigned int) apr_hash_count(apr_hash_t *ht)
+{
+    return ht->count;
+}
+
+APR_DECLARE(void) apr_hash_clear(apr_hash_t *ht)
+{
+    apr_hash_index_t *hi;
+    for (hi = apr_hash_first(NULL, ht); hi; hi = apr_hash_next(hi))
+        apr_hash_set(ht, hi->this->key, hi->this->klen, NULL);
+}
+
+APR_DECLARE(apr_hash_t*) apr_hash_overlay(apr_pool_t *p,
+                                          const apr_hash_t *overlay,
+                                          const apr_hash_t *base)
+{
+    return apr_hash_merge(p, overlay, base, NULL, NULL);
+}
+
+APR_DECLARE(apr_hash_t *) apr_hash_merge(apr_pool_t *p,
+                                         const apr_hash_t *overlay,
+                                         const apr_hash_t *base,
+                                         void * (*merger)(apr_pool_t *p,
+                                                     const void *key,
+                                                     apr_ssize_t klen,
+                                                     const void *h1_val,
+                                                     const void *h2_val,
+                                                     const void *data),
+                                         const void *data)
+{
+    apr_hash_t *res;
+    apr_hash_entry_t *new_vals = NULL;
+    apr_hash_entry_t *iter;
+    apr_hash_entry_t *ent;
+    unsigned int i, j, k, hash;
+
+#if APR_POOL_DEBUG
+    /* we don't copy keys and values, so it's necessary that
+     * overlay->a.pool and base->a.pool have a life span at least
+     * as long as p
+     */
+    if (!apr_pool_is_ancestor(overlay->pool, p)) {
+        fprintf(stderr,
+                "apr_hash_merge: overlay's pool is not an ancestor of p\n");
+        abort();
+    }
+    if (!apr_pool_is_ancestor(base->pool, p)) {
+        fprintf(stderr,
+                "apr_hash_merge: base's pool is not an ancestor of p\n");
+        abort();
+    }
+#endif
+
+    res = apr_palloc(p, sizeof(apr_hash_t));
+    res->pool = p;
+    res->free = NULL;
+    res->hash_func = base->hash_func;
+    res->count = base->count;
+    res->max = (overlay->max > base->max) ? overlay->max : base->max;
+    if (base->count + overlay->count > res->max) {
+        res->max = res->max * 2 + 1;
+    }
+    res->seed = base->seed;
+    res->array = alloc_array(res, res->max);
+    if (base->count + overlay->count) {
+        new_vals = apr_palloc(p, sizeof(apr_hash_entry_t) *
+                              (base->count + overlay->count));
+    }
+    j = 0;
+    for (k = 0; k <= base->max; k++) {
+        for (iter = base->array[k]; iter; iter = iter->next) {
+            i = iter->hash & res->max;
+            new_vals[j].klen = iter->klen;
+            new_vals[j].key = iter->key;
+            new_vals[j].val = iter->val;
+            new_vals[j].hash = iter->hash;
+            new_vals[j].next = res->array[i];
+            res->array[i] = &new_vals[j];
+            j++;
+        }
+    }
+
+    for (k = 0; k <= overlay->max; k++) {
+        for (iter = overlay->array[k]; iter; iter = iter->next) {
+            if (res->hash_func)
+                hash = res->hash_func(iter->key, &iter->klen);
+            else
+                hash = hashfunc_default(iter->key, &iter->klen, res->seed);
+            i = hash & res->max;
+            for (ent = res->array[i]; ent; ent = ent->next) {
+                if ((ent->klen == iter->klen) &&
+                    (memcmp(ent->key, iter->key, iter->klen) == 0)) {
+                    if (merger) {
+                        ent->val = (*merger)(p, iter->key, iter->klen,
+                                             iter->val, ent->val, data);
+                    }
+                    else {
+                        ent->val = iter->val;
+                    }
+                    break;
+                }
+            }
+            if (!ent) {
+                new_vals[j].klen = iter->klen;
+                new_vals[j].key = iter->key;
+                new_vals[j].val = iter->val;
+                new_vals[j].hash = hash;
+                new_vals[j].next = res->array[i];
+                res->array[i] = &new_vals[j];
+                res->count++;
+                j++;
+            }
+        }
+    }
+    return res;
+}
+
+/* This is basically the following...
+ * for every element in hash table {
+ *    comp elemeny.key, element.value
+ * }
+ *
+ * Like with apr_table_do, the comp callback is called for each and every
+ * element of the hash table.
+ */
+APR_DECLARE(int) apr_hash_do(apr_hash_do_callback_fn_t *comp,
+                             void *rec, const apr_hash_t *ht)
+{
+    apr_hash_index_t  hix;
+    apr_hash_index_t *hi;
+    int rv, dorv  = 1;
+
+    hix.ht    = (apr_hash_t *)ht;
+    hix.index = 0;
+    hix.this  = NULL;
+    hix.next  = NULL;
+
+    if ((hi = apr_hash_next(&hix))) {
+        /* Scan the entire table */
+        do {
+            rv = (*comp)(rec, hi->this->key, hi->this->klen, hi->this->val);
+        } while (rv && (hi = apr_hash_next(hi)));
+
+        if (rv == 0) {
+            dorv = 0;
+        }
+    }
+    return dorv;
+}
+
+APR_POOL_IMPLEMENT_ACCESSOR(hash)
diff --git a/tables/apr_skiplist.c b/tables/apr_skiplist.c
new file mode 100644
index 00000000000..5ea8643dbf2
--- /dev/null
+++ b/tables/apr_skiplist.c
@@ -0,0 +1,852 @@
+/* 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.
+ */
+
+/*
+ * Modified to use APR and APR pools.
+ *  TODO: Is malloc() better? Will long running skiplists grow too much?
+ *  Keep the skiplist_alloc() and skiplist_free() until we know
+ *  Yeah, if using pools it means some bogus cycles for checks
+ *  (and an useless function call for skiplist_free) which we
+ *  can removed if/when needed.
+ */
+
+#include "apr_skiplist.h"
+
+typedef struct {
+    apr_skiplistnode **data;
+    size_t size, pos;
+    apr_pool_t *p;
+} apr_skiplist_q; 
+
+struct apr_skiplist {
+    apr_skiplist_compare compare;
+    apr_skiplist_compare comparek;
+    int height;
+    int preheight;
+    size_t size;
+    apr_skiplistnode *top;
+    apr_skiplistnode *bottom;
+    /* These two are needed for appending */
+    apr_skiplistnode *topend;
+    apr_skiplistnode *bottomend;
+    apr_skiplist *index;
+    apr_array_header_t *memlist;
+    apr_skiplist_q nodes_q,
+                   stack_q;
+    apr_pool_t *pool;
+};
+
+struct apr_skiplistnode {
+    void *data;
+    apr_skiplistnode *next;
+    apr_skiplistnode *prev;
+    apr_skiplistnode *down;
+    apr_skiplistnode *up;
+    apr_skiplistnode *previndex;
+    apr_skiplistnode *nextindex;
+    apr_skiplist *sl;
+};
+
+static int get_b_rand(void)
+{
+    static int ph = 32;         /* More bits than we will ever use */
+    static int randseq;
+    if (ph > 31) {              /* Num bits in return of rand() */
+        ph = 0;
+        randseq = rand();
+    }
+    return randseq & (1 << ph++);
+}
+
+typedef struct {
+    size_t size;
+    apr_array_header_t *list;
+} memlist_t;
+
+typedef struct {
+    void *ptr;
+    char inuse;
+} chunk_t;
+
+APR_DECLARE(void *) apr_skiplist_alloc(apr_skiplist *sl, size_t size)
+{
+    if (sl->pool) {
+        void *ptr;
+        int found_size = 0;
+        int i;
+        chunk_t *newchunk;
+        memlist_t *memlist = (memlist_t *)sl->memlist->elts;
+        for (i = 0; i < sl->memlist->nelts; i++) {
+            if (memlist->size == size) {
+                int j;
+                chunk_t *chunk = (chunk_t *)memlist->list->elts;
+                found_size = 1;
+                for (j = 0; j < memlist->list->nelts; j++) {
+                    if (!chunk->inuse) {
+                        chunk->inuse = 1;
+                        return chunk->ptr;
+                    }
+                    chunk++;
+                }
+                break; /* no free of this size; punt */
+            }
+            memlist++;
+        }
+        /* no free chunks */
+        ptr = apr_palloc(sl->pool, size);
+        if (!ptr) {
+            return ptr;
+        }
+        /*
+         * is this a new sized chunk? If so, we need to create a new
+         * array of them. Otherwise, re-use what we already have.
+         */
+        if (!found_size) {
+            memlist = apr_array_push(sl->memlist);
+            memlist->size = size;
+            memlist->list = apr_array_make(sl->pool, 20, sizeof(chunk_t));
+        }
+        newchunk = apr_array_push(memlist->list);
+        newchunk->ptr = ptr;
+        newchunk->inuse = 1;
+        return ptr;
+    }
+    else {
+        return malloc(size);
+    }
+}
+
+APR_DECLARE(void) apr_skiplist_free(apr_skiplist *sl, void *mem)
+{
+    if (!sl->pool) {
+        free(mem);
+    }
+    else {
+        int i;
+        memlist_t *memlist = (memlist_t *)sl->memlist->elts;
+        for (i = 0; i < sl->memlist->nelts; i++) {
+            int j;
+            chunk_t *chunk = (chunk_t *)memlist->list->elts;
+            for (j = 0; j < memlist->list->nelts; j++) {
+                if (chunk->ptr == mem) {
+                    chunk->inuse = 0;
+                    return;
+                }
+                chunk++;
+            }
+            memlist++;
+        }
+    }
+}
+
+static apr_status_t skiplist_qpush(apr_skiplist_q *q, apr_skiplistnode *m)
+{
+    if (q->pos >= q->size) {
+        apr_skiplistnode **data;
+        size_t size = (q->pos) ? q->pos * 2 : 32;
+        if (q->p) {
+            data = apr_palloc(q->p, size * sizeof(*data));
+            if (data) {
+                memcpy(data, q->data, q->pos * sizeof(*data));
+            }
+        }
+        else {
+            data = realloc(q->data, size * sizeof(*data));
+        }
+        if (!data) {
+            return APR_ENOMEM;
+        }
+        q->data = data;
+        q->size = size;
+    }
+    q->data[q->pos++] = m;
+    return APR_SUCCESS;
+}
+
+static APR_INLINE apr_skiplistnode *skiplist_qpop(apr_skiplist_q *q)
+{
+    return (q->pos > 0) ? q->data[--q->pos] : NULL;
+}
+
+static APR_INLINE void skiplist_qclear(apr_skiplist_q *q)
+{
+    q->pos = 0;
+}
+
+static apr_skiplistnode *skiplist_new_node(apr_skiplist *sl)
+{
+    apr_skiplistnode *m = skiplist_qpop(&sl->nodes_q);
+    if (!m) {
+        if (sl->pool) {
+            m = apr_palloc(sl->pool, sizeof *m);
+        }
+        else {
+            m = malloc(sizeof *m);
+        }
+    }
+    return m;
+}
+
+static apr_status_t skiplist_put_node(apr_skiplist *sl, apr_skiplistnode *m)
+{
+    return skiplist_qpush(&sl->nodes_q, m);
+}
+
+static apr_status_t skiplisti_init(apr_skiplist **s, apr_pool_t *p)
+{
+    apr_skiplist *sl;
+    if (p) {
+        sl = apr_pcalloc(p, sizeof(apr_skiplist));
+        sl->memlist = apr_array_make(p, 20, sizeof(memlist_t));
+        sl->pool = sl->nodes_q.p = sl->stack_q.p = p;
+    }
+    else {
+        sl = calloc(1, sizeof(apr_skiplist));
+        if (!sl) {
+            return APR_ENOMEM;
+        }
+    }
+    *s = sl;
+    return APR_SUCCESS;
+}
+
+static int indexing_comp(void *a, void *b)
+{
+    void *ac = (void *) (((apr_skiplist *) a)->compare);
+    void *bc = (void *) (((apr_skiplist *) b)->compare);
+    return ((ac < bc) ? -1 : ((ac > bc) ? 1 : 0));
+}
+
+static int indexing_compk(void *ac, void *b)
+{
+    void *bc = (void *) (((apr_skiplist *) b)->compare);
+    return ((ac < bc) ? -1 : ((ac > bc) ? 1 : 0));
+}
+
+APR_DECLARE(apr_status_t) apr_skiplist_init(apr_skiplist **s, apr_pool_t *p)
+{
+    apr_skiplist *sl;
+    skiplisti_init(s, p);
+    sl = *s;
+    skiplisti_init(&(sl->index), p);
+    apr_skiplist_set_compare(sl->index, indexing_comp, indexing_compk);
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(void) apr_skiplist_set_compare(apr_skiplist *sl,
+                          apr_skiplist_compare comp,
+                          apr_skiplist_compare compk)
+{
+    if (sl->compare && sl->comparek) {
+        apr_skiplist_add_index(sl, comp, compk);
+    }
+    else {
+        sl->compare = comp;
+        sl->comparek = compk;
+    }
+}
+
+APR_DECLARE(void) apr_skiplist_add_index(apr_skiplist *sl,
+                        apr_skiplist_compare comp,
+                        apr_skiplist_compare compk)
+{
+    apr_skiplistnode *m;
+    apr_skiplist *ni;
+    int icount = 0;
+    apr_skiplist_find(sl->index, (void *)comp, &m);
+    if (m) {
+        return;                 /* Index already there! */
+    }
+    skiplisti_init(&ni, sl->pool);
+    apr_skiplist_set_compare(ni, comp, compk);
+    /* Build the new index... This can be expensive! */
+    m = apr_skiplist_insert(sl->index, ni);
+    while (m->prev) {
+        m = m->prev;
+        icount++;
+    }
+    for (m = apr_skiplist_getlist(sl); m; apr_skiplist_next(sl, &m)) {
+        int j = icount - 1;
+        apr_skiplistnode *nsln;
+        nsln = apr_skiplist_insert(ni, m->data);
+        /* skip from main index down list */
+        while (j > 0) {
+            m = m->nextindex;
+            j--;
+        }
+        /* insert this node in the indexlist after m */
+        nsln->nextindex = m->nextindex;
+        if (m->nextindex) {
+            m->nextindex->previndex = nsln;
+        }
+        nsln->previndex = m;
+        m->nextindex = nsln;
+    }
+}
+
+static int skiplisti_find_compare(apr_skiplist *sl, void *data,
+                                  apr_skiplistnode **ret,
+                                  apr_skiplist_compare comp,
+                                  int last)
+{
+    int count = 0;
+    apr_skiplistnode *m, *found = NULL;
+    for (m = sl->top; m; count++) {
+        if (m->next) {
+            int compared = comp(data, m->next->data);
+            if (compared == 0) {
+                found = m = m->next;
+                if (!last) {
+                    break;
+                }
+                continue;
+            }
+            if (compared > 0) {
+                m = m->next;
+                continue;
+            }
+        }
+        m = m->down;
+    }
+    if (found) {
+        while (found->down) {
+            found = found->down;
+        }
+        *ret = found;
+    }
+    else {
+        *ret = NULL;
+    }
+    return count;
+}
+
+static void *find_compare(apr_skiplist *sli, void *data,
+                          apr_skiplistnode **iter,
+                          apr_skiplist_compare comp,
+                          int last)
+{
+    apr_skiplistnode *m;
+    apr_skiplist *sl;
+    if (!comp) {
+        if (iter) {
+            *iter = NULL;
+        }
+        return NULL;
+    }
+    if (comp == sli->compare || !sli->index) {
+        sl = sli;
+    }
+    else {
+        apr_skiplist_find(sli->index, (void *)comp, &m);
+        if (!m) {
+            if (iter) {
+                *iter = NULL;
+            }
+            return NULL;
+        }
+        sl = (apr_skiplist *) m->data;
+    }
+    skiplisti_find_compare(sl, data, &m, sl->comparek, last);
+    if (iter) {
+        *iter = m;
+    }
+    return (m) ? m->data : NULL;
+}
+
+APR_DECLARE(void *) apr_skiplist_find_compare(apr_skiplist *sl, void *data,
+                                              apr_skiplistnode **iter,
+                                              apr_skiplist_compare comp)
+{
+    return find_compare(sl, data, iter, comp, 0);
+}
+
+APR_DECLARE(void *) apr_skiplist_find(apr_skiplist *sl, void *data, apr_skiplistnode **iter)
+{
+    return find_compare(sl, data, iter, sl->compare, 0);
+}
+
+APR_DECLARE(void *) apr_skiplist_last_compare(apr_skiplist *sl, void *data,
+                                              apr_skiplistnode **iter,
+                                              apr_skiplist_compare comp)
+{
+    return find_compare(sl, data, iter, comp, 1);
+}
+
+APR_DECLARE(void *) apr_skiplist_last(apr_skiplist *sl, void *data,
+                                      apr_skiplistnode **iter)
+{
+    return find_compare(sl, data, iter, sl->compare, 1);
+}
+
+
+APR_DECLARE(apr_skiplistnode *) apr_skiplist_getlist(apr_skiplist *sl)
+{
+    if (!sl->bottom) {
+        return NULL;
+    }
+    return sl->bottom->next;
+}
+
+APR_DECLARE(void *) apr_skiplist_next(apr_skiplist *sl, apr_skiplistnode **iter)
+{
+    if (!*iter) {
+        return NULL;
+    }
+    *iter = (*iter)->next;
+    return (*iter) ? ((*iter)->data) : NULL;
+}
+
+APR_DECLARE(void *) apr_skiplist_previous(apr_skiplist *sl, apr_skiplistnode **iter)
+{
+    if (!*iter) {
+        return NULL;
+    }
+    *iter = (*iter)->prev;
+    return (*iter) ? ((*iter)->data) : NULL;
+}
+
+APR_DECLARE(void *) apr_skiplist_element(apr_skiplistnode *iter)
+{
+    return (iter) ? iter->data : NULL;
+}
+
+/* forward declared */
+static int skiplisti_remove(apr_skiplist *sl, apr_skiplistnode *m,
+                            apr_skiplist_freefunc myfree);
+
+static APR_INLINE int skiplist_height(const apr_skiplist *sl)
+{
+    /* Skiplists (even empty) always have a top node, although this
+     * implementation defers its creation until the first insert, or
+     * deletes it with the last remove. We want the real height here.
+     */
+    return sl->height ? sl->height : 1;
+}
+
+static apr_skiplistnode *insert_compare(apr_skiplist *sl, void *data,
+                                        apr_skiplist_compare comp, int add,
+                                        apr_skiplist_freefunc myfree)
+{
+    apr_skiplistnode *m, *p, *tmp, *ret = NULL;
+    int ch, top_nh, nh = 1;
+
+    ch = skiplist_height(sl);
+    if (sl->preheight) {
+        while (nh < sl->preheight && get_b_rand()) {
+            nh++;
+        }
+    }
+    else {
+        while (nh <= ch && get_b_rand()) {
+            nh++;
+        }
+    }
+    top_nh = nh;
+
+    /* Now we have in nh the height at which we wish to insert our new node,
+     * and in ch the current height: don't create skip paths to the inserted
+     * element until the walk down through the tree (which decrements ch)
+     * reaches nh. From there, any walk down pushes the current node on a
+     * stack (the node(s) after which we would insert) to pop back through
+     * for insertion later.
+     */
+    m = sl->top;
+    while (m) {
+        /*
+         * To maintain stability, dups (compared == 0) must be added
+         * AFTER each other.
+         */
+        if (m->next) {
+            int compared = comp(data, m->next->data);
+            if (compared == 0) {
+                if (!add) {
+                    /* Keep the existing element(s) */
+                    skiplist_qclear(&sl->stack_q);
+                    return NULL;
+                }
+                if (add < 0) {
+                    /* Remove this element and continue with the next node
+                     * or the new top if the current one is also removed.
+                     */
+                    apr_skiplistnode *top = sl->top;
+                    skiplisti_remove(sl, m->next, myfree);
+                    if (top != sl->top) {
+                        m = sl->top;
+                        skiplist_qclear(&sl->stack_q);
+                        ch = skiplist_height(sl);
+                        nh = top_nh;
+                    }
+                    continue;
+                }
+            }
+            if (compared >= 0) {
+                m = m->next;
+                continue;
+            }
+        }
+        if (ch <= nh) {
+            /* push on stack */
+            skiplist_qpush(&sl->stack_q, m);
+        }
+        m = m->down;
+        ch--;
+    }
+    /* Pop the stack and insert nodes */
+    p = NULL;
+    while ((m = skiplist_qpop(&sl->stack_q))) {
+        tmp = skiplist_new_node(sl);
+        tmp->next = m->next;
+        if (m->next) {
+            m->next->prev = tmp;
+        }
+        m->next = tmp;
+        tmp->prev = m;
+        tmp->up = NULL;
+        tmp->nextindex = tmp->previndex = NULL;
+        tmp->down = p;
+        if (p) {
+            p->up = tmp;
+        }
+        else {
+            /* This sets ret to the bottom-most node we are inserting */
+            ret = tmp;
+        }
+        tmp->data = data;
+        tmp->sl = sl;
+        p = tmp;
+    }
+
+    /* Now we are sure the node is inserted, grow our tree to 'nh' tall */
+    for (; sl->height < nh; sl->height++) {
+        m = skiplist_new_node(sl);
+        tmp = skiplist_new_node(sl);
+        m->up = m->prev = m->nextindex = m->previndex = NULL;
+        m->next = tmp;
+        m->down = sl->top;
+        m->data = NULL;
+        m->sl = sl;
+        if (sl->top) {
+            sl->top->up = m;
+        }
+        else {
+            sl->bottom = sl->bottomend = m;
+        }
+        sl->top = sl->topend = tmp->prev = m;
+        tmp->up = tmp->next = tmp->nextindex = tmp->previndex = NULL;
+        tmp->down = p;
+        tmp->data = data;
+        tmp->sl = sl;
+        if (p) {
+            p->up = tmp;
+        }
+        else {
+            /* This sets ret to the bottom-most node we are inserting */
+            ret = tmp;
+        }
+        p = tmp;
+    }
+    if (sl->index != NULL) {
+        /*
+         * this is a external insertion, we must insert into each index as
+         * well
+         */
+        apr_skiplistnode *ni, *li;
+        li = ret;
+        for (p = apr_skiplist_getlist(sl->index); p; apr_skiplist_next(sl->index, &p)) {
+            apr_skiplist *sli = (apr_skiplist *)p->data;
+            ni = insert_compare(sli, ret->data, sli->compare, 1, NULL);
+            li->nextindex = ni;
+            ni->previndex = li;
+            li = ni;
+        }
+    }
+    sl->size++;
+    return ret;
+}
+
+APR_DECLARE(apr_skiplistnode *) apr_skiplist_insert_compare(apr_skiplist *sl, void *data,
+                                      apr_skiplist_compare comp)
+{
+    if (!comp) {
+        return NULL;
+    }
+    return insert_compare(sl, data, comp, 0, NULL);
+}
+
+APR_DECLARE(apr_skiplistnode *) apr_skiplist_insert(apr_skiplist *sl, void *data)
+{
+    return apr_skiplist_insert_compare(sl, data, sl->compare);
+}
+
+APR_DECLARE(apr_skiplistnode *) apr_skiplist_add_compare(apr_skiplist *sl, void *data,
+                                      apr_skiplist_compare comp)
+{
+    if (!comp) {
+        return NULL;
+    }
+    return insert_compare(sl, data, comp, 1, NULL);
+}
+
+APR_DECLARE(apr_skiplistnode *) apr_skiplist_add(apr_skiplist *sl, void *data)
+{
+    return apr_skiplist_add_compare(sl, data, sl->compare);
+}
+
+APR_DECLARE(apr_skiplistnode *) apr_skiplist_replace_compare(apr_skiplist *sl,
+                                    void *data, apr_skiplist_freefunc myfree,
+                                    apr_skiplist_compare comp)
+{
+    if (!comp) {
+        return NULL;
+    }
+    return insert_compare(sl, data, comp, -1, myfree);
+}
+
+APR_DECLARE(apr_skiplistnode *) apr_skiplist_replace(apr_skiplist *sl,
+                                    void *data, apr_skiplist_freefunc myfree)
+{
+    return apr_skiplist_replace_compare(sl, data, myfree, sl->compare);
+}
+
+#if 0
+void skiplist_print_struct(apr_skiplist * sl, char *prefix)
+{
+    apr_skiplistnode *p, *q;
+    fprintf(stderr, "Skiplist Structure (height: %d)\n", sl->height);
+    p = sl->bottom;
+    while (p) {
+        q = p;
+        fprintf(stderr, prefix);
+        while (q) {
+            fprintf(stderr, "%p ", q->data);
+            q = q->up;
+        }
+        fprintf(stderr, "\n");
+        p = p->next;
+    }
+}
+#endif
+
+static int skiplisti_remove(apr_skiplist *sl, apr_skiplistnode *m,
+                            apr_skiplist_freefunc myfree)
+{
+    apr_skiplistnode *p;
+    if (!m) {
+        return 0;
+    }
+    if (m->nextindex) {
+        skiplisti_remove(m->nextindex->sl, m->nextindex, NULL);
+    }
+    while (m->up) {
+        m = m->up;
+    }
+    do {
+        p = m;
+        /* take me out of the list */
+        p->prev->next = p->next;
+        if (p->next) {
+            p->next->prev = p->prev;
+        }
+        m = m->down;
+        /* This only frees the actual data in the bottom one */
+        if (!m && myfree && p->data) {
+            myfree(p->data);
+        }
+        skiplist_put_node(sl, p);
+    } while (m);
+    sl->size--;
+    while (sl->top && sl->top->next == NULL) {
+        /* While the row is empty and we are not on the bottom row */
+        p = sl->top;
+        sl->top = sl->top->down;/* Move top down one */
+        if (sl->top) {
+            sl->top->up = NULL; /* Make it think its the top */
+        }
+        skiplist_put_node(sl, p);
+        sl->height--;
+    }
+    if (!sl->top) {
+        sl->bottom = sl->bottomend = NULL;
+        sl->topend = NULL;
+    }
+    return skiplist_height(sl);
+}
+
+APR_DECLARE(int) apr_skiplist_remove_node(apr_skiplist *sl,
+                                          apr_skiplistnode *iter,
+                                          apr_skiplist_freefunc myfree)
+{
+    apr_skiplistnode *m = iter;
+    if (!m) {
+        return 0;
+    }
+    while (m->down) {
+        m = m->down;
+    }
+    while (m->previndex) {
+        m = m->previndex;
+    }
+    return skiplisti_remove(sl, m, myfree);
+}
+
+APR_DECLARE(int) apr_skiplist_remove_compare(apr_skiplist *sli,
+                            void *data,
+                            apr_skiplist_freefunc myfree, apr_skiplist_compare comp)
+{
+    apr_skiplistnode *m;
+    apr_skiplist *sl;
+    if (!comp) {
+        return 0;
+    }
+    if (comp == sli->comparek || !sli->index) {
+        sl = sli;
+    }
+    else {
+        apr_skiplist_find(sli->index, (void *)comp, &m);
+        if (!m) {
+            return 0;
+        }
+        sl = (apr_skiplist *) m->data;
+    }
+    skiplisti_find_compare(sl, data, &m, comp, 0);
+    if (!m) {
+        return 0;
+    }
+    while (m->previndex) {
+        m = m->previndex;
+    }
+    return skiplisti_remove(sl, m, myfree);
+}
+
+APR_DECLARE(int) apr_skiplist_remove(apr_skiplist *sl, void *data, apr_skiplist_freefunc myfree)
+{
+    return apr_skiplist_remove_compare(sl, data, myfree, sl->comparek);
+}
+
+APR_DECLARE(void) apr_skiplist_remove_all(apr_skiplist *sl, apr_skiplist_freefunc myfree)
+{
+    /*
+     * This must remove even the place holder nodes (bottom though top)
+     * because we specify in the API that one can free the Skiplist after
+     * making this call without memory leaks
+     */
+    apr_skiplistnode *m, *p, *u;
+    m = sl->bottom;
+    while (m) {
+        p = m->next;
+        if (myfree && p && p->data) {
+            myfree(p->data);
+        }
+        do {
+            u = m->up;
+            skiplist_put_node(sl, m);
+            m = u;
+        } while (m);
+        m = p;
+    }
+    sl->top = sl->bottom = NULL;
+    sl->topend = sl->bottomend = NULL;
+    sl->height = 0;
+    sl->size = 0;
+}
+
+APR_DECLARE(void *) apr_skiplist_pop(apr_skiplist *a, apr_skiplist_freefunc myfree)
+{
+    apr_skiplistnode *sln;
+    void *data = NULL;
+    sln = apr_skiplist_getlist(a);
+    if (sln) {
+        data = sln->data;
+        skiplisti_remove(a, sln, myfree);
+    }
+    return data;
+}
+
+APR_DECLARE(void *) apr_skiplist_peek(apr_skiplist *a)
+{
+    apr_skiplistnode *sln;
+    sln = apr_skiplist_getlist(a);
+    if (sln) {
+        return sln->data;
+    }
+    return NULL;
+}
+
+APR_DECLARE(size_t) apr_skiplist_size(const apr_skiplist *sl)
+{
+    return sl->size;
+}
+
+APR_DECLARE(int) apr_skiplist_height(const apr_skiplist *sl)
+{
+    return skiplist_height(sl);
+}
+
+APR_DECLARE(int) apr_skiplist_preheight(const apr_skiplist *sl)
+{
+    return sl->preheight;
+}
+
+APR_DECLARE(void) apr_skiplist_set_preheight(apr_skiplist *sl, int to)
+{
+    sl->preheight = (to > 0) ? to : 0;
+}
+
+static void skiplisti_destroy(void *vsl)
+{
+    apr_skiplist_destroy(vsl, NULL);
+}
+
+APR_DECLARE(void) apr_skiplist_destroy(apr_skiplist *sl, apr_skiplist_freefunc myfree)
+{
+    while (apr_skiplist_pop(sl->index, skiplisti_destroy) != NULL)
+        ;
+    apr_skiplist_remove_all(sl, myfree);
+    if (!sl->pool) {
+        while (sl->nodes_q.pos)
+            free(sl->nodes_q.data[--sl->nodes_q.pos]);
+        free(sl->nodes_q.data);
+        free(sl->stack_q.data);
+        free(sl);
+    }
+}
+
+APR_DECLARE(apr_skiplist *) apr_skiplist_merge(apr_skiplist *sl1, apr_skiplist *sl2)
+{
+    /* Check integrity! */
+    apr_skiplist temp;
+    struct apr_skiplistnode *b2;
+    if (sl1->bottomend == NULL || sl1->bottomend->prev == NULL) {
+        apr_skiplist_remove_all(sl1, NULL);
+        temp = *sl1;
+        *sl1 = *sl2;
+        *sl2 = temp;
+        /* swap them so that sl2 can be freed normally upon return. */
+        return sl1;
+    }
+    if(sl2->bottom == NULL || sl2->bottom->next == NULL) {
+        apr_skiplist_remove_all(sl2, NULL);
+        return sl1;
+    }
+    /* This is what makes it brute force... Just insert :/ */
+    b2 = apr_skiplist_getlist(sl2);
+    while (b2) {
+        apr_skiplist_insert(sl1, b2->data);
+        apr_skiplist_next(sl2, &b2);
+    }
+    apr_skiplist_remove_all(sl2, NULL);
+    return sl1;
+}
diff --git a/tables/apr_tables.c b/tables/apr_tables.c
new file mode 100644
index 00000000000..6d9aff88168
--- /dev/null
+++ b/tables/apr_tables.c
@@ -0,0 +1,1300 @@
+/* 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.
+ */
+
+/*
+ * Resource allocation code... the code here is responsible for making
+ * sure that nothing leaks.
+ *
+ * rst --- 4/95 --- 6/95
+ */
+
+#include "apr_private.h"
+
+#include "apr_general.h"
+#include "apr_pools.h"
+#include "apr_tables.h"
+#include "apr_strings.h"
+#include "apr_lib.h"
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if APR_HAVE_STRING_H
+#include <string.h>
+#endif
+#if APR_HAVE_STRINGS_H
+#include <strings.h>
+#endif
+
+#if (APR_POOL_DEBUG || defined(MAKE_TABLE_PROFILE)) && APR_HAVE_STDIO_H
+#include <stdio.h>
+#endif
+
+/*****************************************************************
+ * This file contains array and apr_table_t functions only.
+ */
+
+/*****************************************************************
+ *
+ * The 'array' functions...
+ */
+
+static void make_array_core(apr_array_header_t *res, apr_pool_t *p,
+			    int nelts, int elt_size, int clear)
+{
+    /*
+     * Assure sanity if someone asks for
+     * array of zero elts.
+     */
+    if (nelts < 1) {
+        nelts = 1;
+    }
+
+    if (clear) {
+        res->elts = apr_pcalloc(p, nelts * elt_size);
+    }
+    else {
+        res->elts = apr_palloc(p, nelts * elt_size);
+    }
+
+    res->pool = p;
+    res->elt_size = elt_size;
+    res->nelts = 0;		/* No active elements yet... */
+    res->nalloc = nelts;	/* ...but this many allocated */
+}
+
+APR_DECLARE(int) apr_is_empty_array(const apr_array_header_t *a)
+{
+    return ((a == NULL) || (a->nelts == 0));
+}
+
+APR_DECLARE(apr_array_header_t *) apr_array_make(apr_pool_t *p,
+						int nelts, int elt_size)
+{
+    apr_array_header_t *res;
+
+    res = (apr_array_header_t *) apr_palloc(p, sizeof(apr_array_header_t));
+    make_array_core(res, p, nelts, elt_size, 1);
+    return res;
+}
+
+APR_DECLARE(void) apr_array_clear(apr_array_header_t *arr)
+{
+    arr->nelts = 0;
+}
+
+APR_DECLARE(void *) apr_array_pop(apr_array_header_t *arr)
+{
+    if (apr_is_empty_array(arr)) {
+        return NULL;
+    }
+   
+    return arr->elts + (arr->elt_size * (--arr->nelts));
+}
+
+APR_DECLARE(void *) apr_array_push(apr_array_header_t *arr)
+{
+    if (arr->nelts == arr->nalloc) {
+        int new_size = (arr->nalloc <= 0) ? 1 : arr->nalloc * 2;
+        char *new_data;
+
+        new_data = apr_palloc(arr->pool, arr->elt_size * new_size);
+
+        memcpy(new_data, arr->elts, arr->nalloc * arr->elt_size);
+        memset(new_data + arr->nalloc * arr->elt_size, 0,
+               arr->elt_size * (new_size - arr->nalloc));
+        arr->elts = new_data;
+        arr->nalloc = new_size;
+    }
+
+    ++arr->nelts;
+    return arr->elts + (arr->elt_size * (arr->nelts - 1));
+}
+
+static void *apr_array_push_noclear(apr_array_header_t *arr)
+{
+    if (arr->nelts == arr->nalloc) {
+        int new_size = (arr->nalloc <= 0) ? 1 : arr->nalloc * 2;
+        char *new_data;
+
+        new_data = apr_palloc(arr->pool, arr->elt_size * new_size);
+
+        memcpy(new_data, arr->elts, arr->nalloc * arr->elt_size);
+        arr->elts = new_data;
+        arr->nalloc = new_size;
+    }
+
+    ++arr->nelts;
+    return arr->elts + (arr->elt_size * (arr->nelts - 1));
+}
+
+APR_DECLARE(void) apr_array_cat(apr_array_header_t *dst,
+			       const apr_array_header_t *src)
+{
+    int elt_size = dst->elt_size;
+
+    if (dst->nelts + src->nelts > dst->nalloc) {
+	int new_size = (dst->nalloc <= 0) ? 1 : dst->nalloc * 2;
+	char *new_data;
+
+	while (dst->nelts + src->nelts > new_size) {
+	    new_size *= 2;
+	}
+
+	new_data = apr_pcalloc(dst->pool, elt_size * new_size);
+	memcpy(new_data, dst->elts, dst->nalloc * elt_size);
+
+	dst->elts = new_data;
+	dst->nalloc = new_size;
+    }
+
+    memcpy(dst->elts + dst->nelts * elt_size, src->elts,
+	   elt_size * src->nelts);
+    dst->nelts += src->nelts;
+}
+
+APR_DECLARE(apr_array_header_t *) apr_array_copy(apr_pool_t *p,
+						const apr_array_header_t *arr)
+{
+    apr_array_header_t *res =
+        (apr_array_header_t *) apr_palloc(p, sizeof(apr_array_header_t));
+    make_array_core(res, p, arr->nalloc, arr->elt_size, 0);
+
+    memcpy(res->elts, arr->elts, arr->elt_size * arr->nelts);
+    res->nelts = arr->nelts;
+    memset(res->elts + res->elt_size * res->nelts, 0,
+           res->elt_size * (res->nalloc - res->nelts));
+    return res;
+}
+
+/* This cute function copies the array header *only*, but arranges
+ * for the data section to be copied on the first push or arraycat.
+ * It's useful when the elements of the array being copied are
+ * read only, but new stuff *might* get added on the end; we have the
+ * overhead of the full copy only where it is really needed.
+ */
+
+static APR_INLINE void copy_array_hdr_core(apr_array_header_t *res,
+					   const apr_array_header_t *arr)
+{
+    res->elts = arr->elts;
+    res->elt_size = arr->elt_size;
+    res->nelts = arr->nelts;
+    res->nalloc = arr->nelts;	/* Force overflow on push */
+}
+
+APR_DECLARE(apr_array_header_t *)
+    apr_array_copy_hdr(apr_pool_t *p,
+		       const apr_array_header_t *arr)
+{
+    apr_array_header_t *res;
+
+    res = (apr_array_header_t *) apr_palloc(p, sizeof(apr_array_header_t));
+    res->pool = p;
+    copy_array_hdr_core(res, arr);
+    return res;
+}
+
+/* The above is used here to avoid consing multiple new array bodies... */
+
+APR_DECLARE(apr_array_header_t *)
+    apr_array_append(apr_pool_t *p,
+		      const apr_array_header_t *first,
+		      const apr_array_header_t *second)
+{
+    apr_array_header_t *res = apr_array_copy_hdr(p, first);
+
+    apr_array_cat(res, second);
+    return res;
+}
+
+/* apr_array_pstrcat generates a new string from the apr_pool_t containing
+ * the concatenated sequence of substrings referenced as elements within
+ * the array.  The string will be empty if all substrings are empty or null,
+ * or if there are no elements in the array.
+ * If sep is non-NUL, it will be inserted between elements as a separator.
+ */
+APR_DECLARE(char *) apr_array_pstrcat(apr_pool_t *p,
+				     const apr_array_header_t *arr,
+				     const char sep)
+{
+    char *cp, *res, **strpp;
+    apr_size_t len;
+    int i;
+
+    if (arr->nelts <= 0 || arr->elts == NULL) {    /* Empty table? */
+        return (char *) apr_pcalloc(p, 1);
+    }
+
+    /* Pass one --- find length of required string */
+
+    len = 0;
+    for (i = 0, strpp = (char **) arr->elts; ; ++strpp) {
+        if (strpp && *strpp != NULL) {
+            len += strlen(*strpp);
+        }
+        if (++i >= arr->nelts) {
+            break;
+	}
+        if (sep) {
+            ++len;
+	}
+    }
+
+    /* Allocate the required string */
+
+    res = (char *) apr_palloc(p, len + 1);
+    cp = res;
+
+    /* Pass two --- copy the argument strings into the result space */
+
+    for (i = 0, strpp = (char **) arr->elts; ; ++strpp) {
+        if (strpp && *strpp != NULL) {
+            len = strlen(*strpp);
+            memcpy(cp, *strpp, len);
+            cp += len;
+        }
+        if (++i >= arr->nelts) {
+            break;
+	}
+        if (sep) {
+            *cp++ = sep;
+	}
+    }
+
+    *cp = '\0';
+
+    /* Return the result string */
+
+    return res;
+}
+
+
+/*****************************************************************
+ *
+ * The "table" functions.
+ */
+
+#if APR_CHARSET_EBCDIC
+#define CASE_MASK 0xbfbfbfbf
+#else
+#define CASE_MASK 0xdfdfdfdf
+#endif
+
+#define TABLE_HASH_SIZE 32
+#define TABLE_INDEX_MASK 0x1f
+#define TABLE_HASH(key)  (TABLE_INDEX_MASK & *(unsigned char *)(key))
+#define TABLE_INDEX_IS_INITIALIZED(t, i) ((t)->index_initialized & (1 << (i)))
+#define TABLE_SET_INDEX_INITIALIZED(t, i) ((t)->index_initialized |= (1 << (i)))
+
+/* Compute the "checksum" for a key, consisting of the first
+ * 4 bytes, normalized for case-insensitivity and packed into
+ * an int...this checksum allows us to do a single integer
+ * comparison as a fast check to determine whether we can
+ * skip a strcasecmp
+ */
+#define COMPUTE_KEY_CHECKSUM(key, checksum)    \
+{                                              \
+    const char *k = (key);                     \
+    apr_uint32_t c = (apr_uint32_t)*k;         \
+    (checksum) = c;                            \
+    (checksum) <<= 8;                          \
+    if (c) {                                   \
+        c = (apr_uint32_t)*++k;                \
+        checksum |= c;                         \
+    }                                          \
+    (checksum) <<= 8;                          \
+    if (c) {                                   \
+        c = (apr_uint32_t)*++k;                \
+        checksum |= c;                         \
+    }                                          \
+    (checksum) <<= 8;                          \
+    if (c) {                                   \
+        c = (apr_uint32_t)*++k;                \
+        checksum |= c;                         \
+    }                                          \
+    checksum &= CASE_MASK;                     \
+}
+
+/** The opaque string-content table type */
+struct apr_table_t {
+    /* This has to be first to promote backwards compatibility with
+     * older modules which cast a apr_table_t * to an apr_array_header_t *...
+     * they should use the apr_table_elts() function for most of the
+     * cases they do this for.
+     */
+    /** The underlying array for the table */
+    apr_array_header_t a;
+#ifdef MAKE_TABLE_PROFILE
+    /** Who created the array. */
+    void *creator;
+#endif
+    /* An index to speed up table lookups.  The way this works is:
+     *   - Hash the key into the index:
+     *     - index_first[TABLE_HASH(key)] is the offset within
+     *       the table of the first entry with that key
+     *     - index_last[TABLE_HASH(key)] is the offset within
+     *       the table of the last entry with that key
+     *   - If (and only if) there is no entry in the table whose
+     *     key hashes to index element i, then the i'th bit
+     *     of index_initialized will be zero.  (Check this before
+     *     trying to use index_first[i] or index_last[i]!)
+     */
+    apr_uint32_t index_initialized;
+    int index_first[TABLE_HASH_SIZE];
+    int index_last[TABLE_HASH_SIZE];
+};
+
+/* keep state for apr_table_getm() */
+typedef struct
+{
+    apr_pool_t *p;
+    const char *first;
+    apr_array_header_t *merged;
+} table_getm_t;
+
+/*
+ * NOTICE: if you tweak this you should look at is_empty_table() 
+ * and table_elts() in alloc.h
+ */
+#ifdef MAKE_TABLE_PROFILE
+static apr_table_entry_t *do_table_push(const char *func, apr_table_t *t)
+{
+    if (t->a.nelts == t->a.nalloc) {
+        fprintf(stderr, "%s: table created by %p hit limit of %u\n",
+                func ? func : "table_push", t->creator, t->a.nalloc);
+    }
+    return (apr_table_entry_t *) apr_array_push_noclear(&t->a);
+}
+#if defined(__GNUC__) && __GNUC__ >= 2
+#define table_push(t) do_table_push(__FUNCTION__, t)
+#else
+#define table_push(t) do_table_push(NULL, t)
+#endif
+#else /* MAKE_TABLE_PROFILE */
+#define table_push(t)	((apr_table_entry_t *) apr_array_push_noclear(&(t)->a))
+#endif /* MAKE_TABLE_PROFILE */
+
+APR_DECLARE(const apr_array_header_t *) apr_table_elts(const apr_table_t *t)
+{
+    return (const apr_array_header_t *)t;
+}
+
+APR_DECLARE(int) apr_is_empty_table(const apr_table_t *t)
+{
+    return ((t == NULL) || (t->a.nelts == 0));
+}
+
+APR_DECLARE(apr_table_t *) apr_table_make(apr_pool_t *p, int nelts)
+{
+    apr_table_t *t = apr_palloc(p, sizeof(apr_table_t));
+
+    make_array_core(&t->a, p, nelts, sizeof(apr_table_entry_t), 0);
+#ifdef MAKE_TABLE_PROFILE
+    t->creator = __builtin_return_address(0);
+#endif
+    t->index_initialized = 0;
+    return t;
+}
+
+APR_DECLARE(apr_table_t *) apr_table_copy(apr_pool_t *p, const apr_table_t *t)
+{
+    apr_table_t *new = apr_palloc(p, sizeof(apr_table_t));
+
+#if APR_POOL_DEBUG
+    /* we don't copy keys and values, so it's necessary that t->a.pool
+     * have a life span at least as long as p
+     */
+    if (!apr_pool_is_ancestor(t->a.pool, p)) {
+	fprintf(stderr, "apr_table_copy: t's pool is not an ancestor of p\n");
+	abort();
+    }
+#endif
+    make_array_core(&new->a, p, t->a.nalloc, sizeof(apr_table_entry_t), 0);
+    memcpy(new->a.elts, t->a.elts, t->a.nelts * sizeof(apr_table_entry_t));
+    new->a.nelts = t->a.nelts;
+    memcpy(new->index_first, t->index_first, sizeof(int) * TABLE_HASH_SIZE);
+    memcpy(new->index_last, t->index_last, sizeof(int) * TABLE_HASH_SIZE);
+    new->index_initialized = t->index_initialized;
+    return new;
+}
+
+APR_DECLARE(apr_table_t *) apr_table_clone(apr_pool_t *p, const apr_table_t *t)
+{
+    const apr_array_header_t *array = apr_table_elts(t);
+    apr_table_entry_t *elts = (apr_table_entry_t *) array->elts;
+    apr_table_t *new = apr_table_make(p, array->nelts);
+    int i;
+
+    for (i = 0; i < array->nelts; i++) {
+        apr_table_add(new, elts[i].key, elts[i].val);
+    }
+
+    return new;
+}
+
+static void table_reindex(apr_table_t *t)
+{
+    int i;
+    int hash;
+    apr_table_entry_t *next_elt = (apr_table_entry_t *) t->a.elts;
+
+    t->index_initialized = 0;
+    for (i = 0; i < t->a.nelts; i++, next_elt++) {
+        hash = TABLE_HASH(next_elt->key);
+        t->index_last[hash] = i;
+        if (!TABLE_INDEX_IS_INITIALIZED(t, hash)) {
+            t->index_first[hash] = i;
+            TABLE_SET_INDEX_INITIALIZED(t, hash);
+        }
+    }
+}
+
+APR_DECLARE(void) apr_table_clear(apr_table_t *t)
+{
+    t->a.nelts = 0;
+    t->index_initialized = 0;
+}
+
+APR_DECLARE(const char *) apr_table_get(const apr_table_t *t, const char *key)
+{
+    apr_table_entry_t *next_elt;
+    apr_table_entry_t *end_elt;
+    apr_uint32_t checksum;
+    int hash;
+
+    if (key == NULL) {
+	return NULL;
+    }
+
+    hash = TABLE_HASH(key);
+    if (!TABLE_INDEX_IS_INITIALIZED(t, hash)) {
+        return NULL;
+    }
+    COMPUTE_KEY_CHECKSUM(key, checksum);
+    next_elt = ((apr_table_entry_t *) t->a.elts) + t->index_first[hash];;
+    end_elt = ((apr_table_entry_t *) t->a.elts) + t->index_last[hash];
+
+    for (; next_elt <= end_elt; next_elt++) {
+	if ((checksum == next_elt->key_checksum) &&
+            !strcasecmp(next_elt->key, key)) {
+	    return next_elt->val;
+	}
+    }
+
+    return NULL;
+}
+
+APR_DECLARE(void) apr_table_set(apr_table_t *t, const char *key,
+                                const char *val)
+{
+    apr_table_entry_t *next_elt;
+    apr_table_entry_t *end_elt;
+    apr_table_entry_t *table_end;
+    apr_uint32_t checksum;
+    int hash;
+
+    COMPUTE_KEY_CHECKSUM(key, checksum);
+    hash = TABLE_HASH(key);
+    if (!TABLE_INDEX_IS_INITIALIZED(t, hash)) {
+        t->index_first[hash] = t->a.nelts;
+        TABLE_SET_INDEX_INITIALIZED(t, hash);
+        goto add_new_elt;
+    }
+    next_elt = ((apr_table_entry_t *) t->a.elts) + t->index_first[hash];;
+    end_elt = ((apr_table_entry_t *) t->a.elts) + t->index_last[hash];
+    table_end =((apr_table_entry_t *) t->a.elts) + t->a.nelts;
+
+    for (; next_elt <= end_elt; next_elt++) {
+	if ((checksum == next_elt->key_checksum) &&
+            !strcasecmp(next_elt->key, key)) {
+
+            /* Found an existing entry with the same key, so overwrite it */
+
+            int must_reindex = 0;
+            apr_table_entry_t *dst_elt = NULL;
+
+            next_elt->val = apr_pstrdup(t->a.pool, val);
+
+            /* Remove any other instances of this key */
+            for (next_elt++; next_elt <= end_elt; next_elt++) {
+                if ((checksum == next_elt->key_checksum) &&
+                    !strcasecmp(next_elt->key, key)) {
+                    t->a.nelts--;
+                    if (!dst_elt) {
+                        dst_elt = next_elt;
+                    }
+                }
+                else if (dst_elt) {
+                    *dst_elt++ = *next_elt;
+                    must_reindex = 1;
+                }
+            }
+
+            /* If we've removed anything, shift over the remainder
+             * of the table (note that the previous loop didn't
+             * run to the end of the table, just to the last match
+             * for the index)
+             */
+            if (dst_elt) {
+                for (; next_elt < table_end; next_elt++) {
+                    *dst_elt++ = *next_elt;
+                }
+                must_reindex = 1;
+            }
+            if (must_reindex) {
+                table_reindex(t);
+            }
+            return;
+        }
+    }
+
+add_new_elt:
+    t->index_last[hash] = t->a.nelts;
+    next_elt = (apr_table_entry_t *) table_push(t);
+    next_elt->key = apr_pstrdup(t->a.pool, key);
+    next_elt->val = apr_pstrdup(t->a.pool, val);
+    next_elt->key_checksum = checksum;
+}
+
+APR_DECLARE(void) apr_table_setn(apr_table_t *t, const char *key,
+                                 const char *val)
+{
+    apr_table_entry_t *next_elt;
+    apr_table_entry_t *end_elt;
+    apr_table_entry_t *table_end;
+    apr_uint32_t checksum;
+    int hash;
+
+    COMPUTE_KEY_CHECKSUM(key, checksum);
+    hash = TABLE_HASH(key);
+    if (!TABLE_INDEX_IS_INITIALIZED(t, hash)) {
+        t->index_first[hash] = t->a.nelts;
+        TABLE_SET_INDEX_INITIALIZED(t, hash);
+        goto add_new_elt;
+    }
+    next_elt = ((apr_table_entry_t *) t->a.elts) + t->index_first[hash];;
+    end_elt = ((apr_table_entry_t *) t->a.elts) + t->index_last[hash];
+    table_end =((apr_table_entry_t *) t->a.elts) + t->a.nelts;
+
+    for (; next_elt <= end_elt; next_elt++) {
+	if ((checksum == next_elt->key_checksum) &&
+            !strcasecmp(next_elt->key, key)) {
+
+            /* Found an existing entry with the same key, so overwrite it */
+
+            int must_reindex = 0;
+            apr_table_entry_t *dst_elt = NULL;
+
+            next_elt->val = (char *)val;
+
+            /* Remove any other instances of this key */
+            for (next_elt++; next_elt <= end_elt; next_elt++) {
+                if ((checksum == next_elt->key_checksum) &&
+                    !strcasecmp(next_elt->key, key)) {
+                    t->a.nelts--;
+                    if (!dst_elt) {
+                        dst_elt = next_elt;
+                    }
+                }
+                else if (dst_elt) {
+                    *dst_elt++ = *next_elt;
+                    must_reindex = 1;
+                }
+            }
+
+            /* If we've removed anything, shift over the remainder
+             * of the table (note that the previous loop didn't
+             * run to the end of the table, just to the last match
+             * for the index)
+             */
+            if (dst_elt) {
+                for (; next_elt < table_end; next_elt++) {
+                    *dst_elt++ = *next_elt;
+                }
+                must_reindex = 1;
+            }
+            if (must_reindex) {
+                table_reindex(t);
+            }
+            return;
+        }
+    }
+
+add_new_elt:
+    t->index_last[hash] = t->a.nelts;
+    next_elt = (apr_table_entry_t *) table_push(t);
+    next_elt->key = (char *)key;
+    next_elt->val = (char *)val;
+    next_elt->key_checksum = checksum;
+}
+
+APR_DECLARE(void) apr_table_unset(apr_table_t *t, const char *key)
+{
+    apr_table_entry_t *next_elt;
+    apr_table_entry_t *end_elt;
+    apr_table_entry_t *dst_elt;
+    apr_uint32_t checksum;
+    int hash;
+    int must_reindex;
+
+    hash = TABLE_HASH(key);
+    if (!TABLE_INDEX_IS_INITIALIZED(t, hash)) {
+        return;
+    }
+    COMPUTE_KEY_CHECKSUM(key, checksum);
+    next_elt = ((apr_table_entry_t *) t->a.elts) + t->index_first[hash];
+    end_elt = ((apr_table_entry_t *) t->a.elts) + t->index_last[hash];
+    must_reindex = 0;
+    for (; next_elt <= end_elt; next_elt++) {
+	if ((checksum == next_elt->key_checksum) &&
+            !strcasecmp(next_elt->key, key)) {
+
+            /* Found a match: remove this entry, plus any additional
+             * matches for the same key that might follow
+             */
+            apr_table_entry_t *table_end = ((apr_table_entry_t *) t->a.elts) +
+                t->a.nelts;
+            t->a.nelts--;
+            dst_elt = next_elt;
+            for (next_elt++; next_elt <= end_elt; next_elt++) {
+                if ((checksum == next_elt->key_checksum) &&
+                    !strcasecmp(next_elt->key, key)) {
+                    t->a.nelts--;
+                }
+                else {
+                    *dst_elt++ = *next_elt;
+                }
+            }
+
+            /* Shift over the remainder of the table (note that
+             * the previous loop didn't run to the end of the table,
+             * just to the last match for the index)
+             */
+            for (; next_elt < table_end; next_elt++) {
+                *dst_elt++ = *next_elt;
+            }
+            must_reindex = 1;
+            break;
+        }
+    }
+    if (must_reindex) {
+        table_reindex(t);
+    }
+}
+
+APR_DECLARE(void) apr_table_merge(apr_table_t *t, const char *key,
+				 const char *val)
+{
+    apr_table_entry_t *next_elt;
+    apr_table_entry_t *end_elt;
+    apr_uint32_t checksum;
+    int hash;
+
+    COMPUTE_KEY_CHECKSUM(key, checksum);
+    hash = TABLE_HASH(key);
+    if (!TABLE_INDEX_IS_INITIALIZED(t, hash)) {
+        t->index_first[hash] = t->a.nelts;
+        TABLE_SET_INDEX_INITIALIZED(t, hash);
+        goto add_new_elt;
+    }
+    next_elt = ((apr_table_entry_t *) t->a.elts) + t->index_first[hash];
+    end_elt = ((apr_table_entry_t *) t->a.elts) + t->index_last[hash];
+
+    for (; next_elt <= end_elt; next_elt++) {
+	if ((checksum == next_elt->key_checksum) &&
+            !strcasecmp(next_elt->key, key)) {
+
+            /* Found an existing entry with the same key, so merge with it */
+	    next_elt->val = apr_pstrcat(t->a.pool, next_elt->val, ", ",
+                                        val, NULL);
+            return;
+        }
+    }
+
+add_new_elt:
+    t->index_last[hash] = t->a.nelts;
+    next_elt = (apr_table_entry_t *) table_push(t);
+    next_elt->key = apr_pstrdup(t->a.pool, key);
+    next_elt->val = apr_pstrdup(t->a.pool, val);
+    next_elt->key_checksum = checksum;
+}
+
+APR_DECLARE(void) apr_table_mergen(apr_table_t *t, const char *key,
+				  const char *val)
+{
+    apr_table_entry_t *next_elt;
+    apr_table_entry_t *end_elt;
+    apr_uint32_t checksum;
+    int hash;
+
+#if APR_POOL_DEBUG
+    {
+	apr_pool_t *pool;
+	pool = apr_pool_find(key);
+	if ((pool != (apr_pool_t *)key)
+            && (!apr_pool_is_ancestor(pool, t->a.pool))) {
+	    fprintf(stderr, "apr_table_mergen: key not in ancestor pool of t\n");
+	    abort();
+	}
+	pool = apr_pool_find(val);
+	if ((pool != (apr_pool_t *)val)
+            && (!apr_pool_is_ancestor(pool, t->a.pool))) {
+	    fprintf(stderr, "apr_table_mergen: val not in ancestor pool of t\n");
+	    abort();
+	}
+    }
+#endif
+
+    COMPUTE_KEY_CHECKSUM(key, checksum);
+    hash = TABLE_HASH(key);
+    if (!TABLE_INDEX_IS_INITIALIZED(t, hash)) {
+        t->index_first[hash] = t->a.nelts;
+        TABLE_SET_INDEX_INITIALIZED(t, hash);
+        goto add_new_elt;
+    }
+    next_elt = ((apr_table_entry_t *) t->a.elts) + t->index_first[hash];;
+    end_elt = ((apr_table_entry_t *) t->a.elts) + t->index_last[hash];
+
+    for (; next_elt <= end_elt; next_elt++) {
+	if ((checksum == next_elt->key_checksum) &&
+            !strcasecmp(next_elt->key, key)) {
+
+            /* Found an existing entry with the same key, so merge with it */
+	    next_elt->val = apr_pstrcat(t->a.pool, next_elt->val, ", ",
+                                        val, NULL);
+            return;
+        }
+    }
+
+add_new_elt:
+    t->index_last[hash] = t->a.nelts;
+    next_elt = (apr_table_entry_t *) table_push(t);
+    next_elt->key = (char *)key;
+    next_elt->val = (char *)val;
+    next_elt->key_checksum = checksum;
+}
+
+APR_DECLARE(void) apr_table_add(apr_table_t *t, const char *key,
+			       const char *val)
+{
+    apr_table_entry_t *elts;
+    apr_uint32_t checksum;
+    int hash;
+
+    hash = TABLE_HASH(key);
+    t->index_last[hash] = t->a.nelts;
+    if (!TABLE_INDEX_IS_INITIALIZED(t, hash)) {
+        t->index_first[hash] = t->a.nelts;
+        TABLE_SET_INDEX_INITIALIZED(t, hash);
+    }
+    COMPUTE_KEY_CHECKSUM(key, checksum);
+    elts = (apr_table_entry_t *) table_push(t);
+    elts->key = apr_pstrdup(t->a.pool, key);
+    elts->val = apr_pstrdup(t->a.pool, val);
+    elts->key_checksum = checksum;
+}
+
+APR_DECLARE(void) apr_table_addn(apr_table_t *t, const char *key,
+				const char *val)
+{
+    apr_table_entry_t *elts;
+    apr_uint32_t checksum;
+    int hash;
+
+#if APR_POOL_DEBUG
+    {
+	if (!apr_pool_is_ancestor(apr_pool_find(key), t->a.pool)) {
+	    fprintf(stderr, "apr_table_addn: key not in ancestor pool of t\n");
+	    abort();
+	}
+	if (!apr_pool_is_ancestor(apr_pool_find(val), t->a.pool)) {
+	    fprintf(stderr, "apr_table_addn: val not in ancestor pool of t\n");
+	    abort();
+	}
+    }
+#endif
+
+    hash = TABLE_HASH(key);
+    t->index_last[hash] = t->a.nelts;
+    if (!TABLE_INDEX_IS_INITIALIZED(t, hash)) {
+        t->index_first[hash] = t->a.nelts;
+        TABLE_SET_INDEX_INITIALIZED(t, hash);
+    }
+    COMPUTE_KEY_CHECKSUM(key, checksum);
+    elts = (apr_table_entry_t *) table_push(t);
+    elts->key = (char *)key;
+    elts->val = (char *)val;
+    elts->key_checksum = checksum;
+}
+
+APR_DECLARE(apr_table_t *) apr_table_overlay(apr_pool_t *p,
+					     const apr_table_t *overlay,
+					     const apr_table_t *base)
+{
+    apr_table_t *res;
+
+#if APR_POOL_DEBUG
+    /* we don't copy keys and values, so it's necessary that
+     * overlay->a.pool and base->a.pool have a life span at least
+     * as long as p
+     */
+    if (!apr_pool_is_ancestor(overlay->a.pool, p)) {
+	fprintf(stderr,
+		"apr_table_overlay: overlay's pool is not an ancestor of p\n");
+	abort();
+    }
+    if (!apr_pool_is_ancestor(base->a.pool, p)) {
+	fprintf(stderr,
+		"apr_table_overlay: base's pool is not an ancestor of p\n");
+	abort();
+    }
+#endif
+
+    res = apr_palloc(p, sizeof(apr_table_t));
+    /* behave like append_arrays */
+    res->a.pool = p;
+    copy_array_hdr_core(&res->a, &overlay->a);
+    apr_array_cat(&res->a, &base->a);
+    table_reindex(res);
+    return res;
+}
+
+/* And now for something completely abstract ...
+
+ * For each key value given as a vararg:
+ *   run the function pointed to as
+ *     int comp(void *r, char *key, char *value);
+ *   on each valid key-value pair in the apr_table_t t that matches the vararg key,
+ *   or once for every valid key-value pair if the vararg list is empty,
+ *   until the function returns false (0) or we finish the table.
+ *
+ * Note that we restart the traversal for each vararg, which means that
+ * duplicate varargs will result in multiple executions of the function
+ * for each matching key.  Note also that if the vararg list is empty,
+ * only one traversal will be made and will cut short if comp returns 0.
+ *
+ * Note that the table_get and table_merge functions assume that each key in
+ * the apr_table_t is unique (i.e., no multiple entries with the same key).  This
+ * function does not make that assumption, since it (unfortunately) isn't
+ * true for some of Apache's tables.
+ *
+ * Note that rec is simply passed-on to the comp function, so that the
+ * caller can pass additional info for the task.
+ *
+ * ADDENDUM for apr_table_vdo():
+ * 
+ * The caching api will allow a user to walk the header values:
+ *
+ * apr_status_t apr_cache_el_header_walk(apr_cache_el *el, 
+ *    int (*comp)(void *, const char *, const char *), void *rec, ...);
+ *
+ * So it can be ..., however from there I use a  callback that use a va_list:
+ *
+ * apr_status_t (*cache_el_header_walk)(apr_cache_el *el, 
+ *    int (*comp)(void *, const char *, const char *), void *rec, va_list);
+ *
+ * To pass those ...'s on down to the actual module that will handle walking
+ * their headers, in the file case this is actually just an apr_table - and
+ * rather than reimplementing apr_table_do (which IMHO would be bad) I just
+ * called it with the va_list. For mod_shmem_cache I don't need it since I
+ * can't use apr_table's, but mod_file_cache should (though a good hash would
+ * be better, but that's a different issue :). 
+ *
+ * So to make mod_file_cache easier to maintain, it's a good thing
+ */
+APR_DECLARE_NONSTD(int) apr_table_do(apr_table_do_callback_fn_t *comp,
+                                     void *rec, const apr_table_t *t, ...)
+{
+    int rv;
+
+    va_list vp;
+    va_start(vp, t);
+    rv = apr_table_vdo(comp, rec, t, vp);
+    va_end(vp);
+
+    return rv;
+} 
+
+/* XXX: do the semantics of this routine make any sense?  Right now,
+ * if the caller passed in a non-empty va_list of keys to search for,
+ * the "early termination" facility only terminates on *that* key; other
+ * keys will continue to process.  Note that this only has any effect
+ * at all if there are multiple entries in the table with the same key,
+ * otherwise the called function can never effectively early-terminate
+ * this function, as the zero return value is effectively ignored.
+ *
+ * Note also that this behavior is at odds with the behavior seen if an
+ * empty va_list is passed in -- in that case, a zero return value terminates
+ * the entire apr_table_vdo (which is what I think should happen in
+ * both cases).
+ *
+ * If nobody objects soon, I'm going to change the order of the nested
+ * loops in this function so that any zero return value from the (*comp)
+ * function will cause a full termination of apr_table_vdo.  I'm hesitant
+ * at the moment because these (funky) semantics have been around for a
+ * very long time, and although Apache doesn't seem to use them at all,
+ * some third-party vendor might.  I can only think of one possible reason
+ * the existing semantics would make any sense, and it's very Apache-centric,
+ * which is this: if (*comp) is looking for matches of a particular
+ * substring in request headers (let's say it's looking for a particular
+ * cookie name in the Set-Cookie headers), then maybe it wants to be
+ * able to stop searching early as soon as it finds that one and move
+ * on to the next key.  That's only an optimization of course, but changing
+ * the behavior of this function would mean that any code that tried
+ * to do that would stop working right.
+ *
+ * Sigh.  --JCW, 06/28/02
+ */
+APR_DECLARE(int) apr_table_vdo(apr_table_do_callback_fn_t *comp,
+                               void *rec, const apr_table_t *t, va_list vp)
+{
+    char *argp;
+    apr_table_entry_t *elts = (apr_table_entry_t *) t->a.elts;
+    int vdorv = 1;
+
+    argp = va_arg(vp, char *);
+    do {
+        int rv = 1, i;
+        if (argp) {
+            /* Scan for entries that match the next key */
+            int hash = TABLE_HASH(argp);
+            if (TABLE_INDEX_IS_INITIALIZED(t, hash)) {
+                apr_uint32_t checksum;
+                COMPUTE_KEY_CHECKSUM(argp, checksum);
+                for (i = t->index_first[hash];
+                     rv && (i <= t->index_last[hash]); ++i) {
+                    if (elts[i].key && (checksum == elts[i].key_checksum) &&
+                                        !strcasecmp(elts[i].key, argp)) {
+                        rv = (*comp) (rec, elts[i].key, elts[i].val);
+                    }
+                }
+            }
+        }
+        else {
+            /* Scan the entire table */
+            for (i = 0; rv && (i < t->a.nelts); ++i) {
+                if (elts[i].key) {
+                    rv = (*comp) (rec, elts[i].key, elts[i].val);
+                }
+            }
+        }
+        if (rv == 0) {
+            vdorv = 0;
+        }
+    } while (argp && ((argp = va_arg(vp, char *)) != NULL));
+
+    return vdorv;
+}
+
+static apr_table_entry_t **table_mergesort(apr_pool_t *pool,
+                                           apr_table_entry_t **values, 
+                                           apr_size_t n)
+{
+    /* Bottom-up mergesort, based on design in Sedgewick's "Algorithms
+     * in C," chapter 8
+     */
+    apr_table_entry_t **values_tmp =
+        (apr_table_entry_t **)apr_palloc(pool, n * sizeof(apr_table_entry_t*));
+    apr_size_t i;
+    apr_size_t blocksize;
+
+    /* First pass: sort pairs of elements (blocksize=1) */
+    for (i = 0; i + 1 < n; i += 2) {
+        if (strcasecmp(values[i]->key, values[i + 1]->key) > 0) {
+            apr_table_entry_t *swap = values[i];
+            values[i] = values[i + 1];
+            values[i + 1] = swap;
+        }
+    }
+
+    /* Merge successively larger blocks */
+    blocksize = 2;
+    while (blocksize < n) {
+        apr_table_entry_t **dst = values_tmp;
+        apr_size_t next_start;
+        apr_table_entry_t **swap;
+
+        /* Merge consecutive pairs blocks of the next blocksize.
+         * Within a block, elements are in sorted order due to
+         * the previous iteration.
+         */
+        for (next_start = 0; next_start + blocksize < n;
+             next_start += (blocksize + blocksize)) {
+
+            apr_size_t block1_start = next_start;
+            apr_size_t block2_start = block1_start + blocksize;
+            apr_size_t block1_end = block2_start;
+            apr_size_t block2_end = block2_start + blocksize;
+            if (block2_end > n) {
+                /* The last block may be smaller than blocksize */
+                block2_end = n;
+            }
+            for (;;) {
+
+                /* Merge the next two blocks:
+                 * Pick the smaller of the next element from
+                 * block 1 and the next element from block 2.
+                 * Once either of the blocks is emptied, copy
+                 * over all the remaining elements from the
+                 * other block
+                 */
+                if (block1_start == block1_end) {
+                    for (; block2_start < block2_end; block2_start++) {
+                        *dst++ = values[block2_start];
+                    }
+                    break;
+                }
+                else if (block2_start == block2_end) {
+                    for (; block1_start < block1_end; block1_start++) {
+                        *dst++ = values[block1_start];
+                    }
+                    break;
+                }
+                if (strcasecmp(values[block1_start]->key,
+                               values[block2_start]->key) > 0) {
+                    *dst++ = values[block2_start++];
+                }
+                else {
+                    *dst++ = values[block1_start++];
+                }
+            }
+        }
+
+        /* If n is not a multiple of 2*blocksize, some elements
+         * will be left over at the end of the array.
+         */
+        for (i = dst - values_tmp; i < n; i++) {
+            values_tmp[i] = values[i];
+        }
+
+        /* The output array of this pass becomes the input
+         * array of the next pass, and vice versa
+         */
+        swap = values_tmp;
+        values_tmp = values;
+        values = swap;
+
+        blocksize += blocksize;
+    }
+
+    return values;
+}
+
+APR_DECLARE(void) apr_table_compress(apr_table_t *t, unsigned flags)
+{
+    apr_table_entry_t **sort_array;
+    apr_table_entry_t **sort_next;
+    apr_table_entry_t **sort_end;
+    apr_table_entry_t *table_next;
+    apr_table_entry_t **last;
+    int i;
+    int dups_found;
+
+    if (flags == APR_OVERLAP_TABLES_ADD) {
+        return;
+    }
+
+    if (t->a.nelts <= 1) {
+        return;
+    }
+
+    /* Copy pointers to all the table elements into an
+     * array and sort to allow for easy detection of
+     * duplicate keys
+     */
+    sort_array = (apr_table_entry_t **)
+        apr_palloc(t->a.pool, t->a.nelts * sizeof(apr_table_entry_t*));
+    sort_next = sort_array;
+    table_next = (apr_table_entry_t *)t->a.elts;
+    i = t->a.nelts;
+    do {
+        *sort_next++ = table_next++;
+    } while (--i);
+
+    /* Note: the merge is done with mergesort instead of quicksort
+     * because mergesort is a stable sort and runs in n*log(n)
+     * time regardless of its inputs (quicksort is quadratic in
+     * the worst case)
+     */
+    sort_array = table_mergesort(t->a.pool, sort_array, t->a.nelts);
+
+    /* Process any duplicate keys */
+    dups_found = 0;
+    sort_next = sort_array;
+    sort_end = sort_array + t->a.nelts;
+    last = sort_next++;
+    while (sort_next < sort_end) {
+        if (((*sort_next)->key_checksum == (*last)->key_checksum) &&
+            !strcasecmp((*sort_next)->key, (*last)->key)) {
+            apr_table_entry_t **dup_last = sort_next + 1;
+            dups_found = 1;
+            while ((dup_last < sort_end) &&
+                   ((*dup_last)->key_checksum == (*last)->key_checksum) &&
+                   !strcasecmp((*dup_last)->key, (*last)->key)) {
+                dup_last++;
+            }
+            dup_last--; /* Elements from last through dup_last, inclusive,
+                         * all have the same key
+                         */
+            if (flags == APR_OVERLAP_TABLES_MERGE) {
+                apr_size_t len = 0;
+                apr_table_entry_t **next = last;
+                char *new_val;
+                char *val_dst;
+                do {
+                    len += strlen((*next)->val);
+                    len += 2; /* for ", " or trailing null */
+                } while (++next <= dup_last);
+                new_val = (char *)apr_palloc(t->a.pool, len);
+                val_dst = new_val;
+                next = last;
+                for (;;) {
+                    strcpy(val_dst, (*next)->val);
+                    val_dst += strlen((*next)->val);
+                    next++;
+                    if (next > dup_last) {
+                        *val_dst = 0;
+                        break;
+                    }
+                    else {
+                        *val_dst++ = ',';
+                        *val_dst++ = ' ';
+                    }
+                }
+                (*last)->val = new_val;
+            }
+            else { /* overwrite */
+                (*last)->val = (*dup_last)->val;
+            }
+            do {
+                (*sort_next)->key = NULL;
+            } while (++sort_next <= dup_last);
+        }
+        else {
+            last = sort_next++;
+        }
+    }
+
+    /* Shift elements to the left to fill holes left by removing duplicates */
+    if (dups_found) {
+        apr_table_entry_t *src = (apr_table_entry_t *)t->a.elts;
+        apr_table_entry_t *dst = (apr_table_entry_t *)t->a.elts;
+        apr_table_entry_t *last_elt = src + t->a.nelts;
+        do {
+            if (src->key) {
+                *dst++ = *src;
+            }
+        } while (++src < last_elt);
+        t->a.nelts -= (int)(last_elt - dst);
+    }
+
+    table_reindex(t);
+}
+
+static void apr_table_cat(apr_table_t *t, const apr_table_t *s)
+{
+    const int n = t->a.nelts;
+    register int idx;
+
+    apr_array_cat(&t->a,&s->a);
+
+    if (n == 0) {
+        memcpy(t->index_first,s->index_first,sizeof(int) * TABLE_HASH_SIZE);
+        memcpy(t->index_last, s->index_last, sizeof(int) * TABLE_HASH_SIZE);
+        t->index_initialized = s->index_initialized;
+        return;
+    }
+
+    for (idx = 0; idx < TABLE_HASH_SIZE; ++idx) {
+        if (TABLE_INDEX_IS_INITIALIZED(s, idx)) {
+            t->index_last[idx] = s->index_last[idx] + n;
+            if (!TABLE_INDEX_IS_INITIALIZED(t, idx)) {
+                t->index_first[idx] = s->index_first[idx] + n;
+            }
+        }
+    }
+
+    t->index_initialized |= s->index_initialized;
+}
+
+APR_DECLARE(void) apr_table_overlap(apr_table_t *a, const apr_table_t *b,
+				    unsigned flags)
+{
+    if (a->a.nelts + b->a.nelts == 0) {
+        return;
+    }
+
+#if APR_POOL_DEBUG
+    /* Since the keys and values are not copied, it's required that
+     * b->a.pool has a lifetime at least as long as a->a.pool. */
+    if (!apr_pool_is_ancestor(b->a.pool, a->a.pool)) {
+        fprintf(stderr, "apr_table_overlap: b's pool is not an ancestor of a's\n");
+        abort();
+    }
+#endif
+
+    apr_table_cat(a, b);
+
+    apr_table_compress(a, flags);
+}
+
+static int table_getm_do(void *v, const char *key, const char *val)
+{
+    table_getm_t *state = (table_getm_t *) v;
+
+    if (!state->first) {
+        /**
+         * The most common case is a single header, and this is covered by
+         * a fast path that doesn't allocate any memory. On the second and
+         * subsequent header, an array is created and the array concatenated
+         * together to form the final value.
+         */
+        state->first = val;
+    }
+    else {
+        const char **elt;
+        if (!state->merged) {
+            state->merged = apr_array_make(state->p, 10, sizeof(const char *));
+            elt = apr_array_push(state->merged);
+            *elt = state->first;
+        }
+        elt = apr_array_push(state->merged);
+        *elt = val;
+    }
+    return 1;
+}
+
+APR_DECLARE(const char *) apr_table_getm(apr_pool_t *p, const apr_table_t *t,
+        const char *key)
+{
+    table_getm_t state;
+
+    state.p = p;
+    state.first = NULL;
+    state.merged = NULL;
+
+    apr_table_do(table_getm_do, &state, t, key, NULL);
+
+    if (!state.first) {
+        return NULL;
+    }
+    else if (!state.merged) {
+        return state.first;
+    }
+    else {
+        return apr_array_pstrcat(p, state.merged, ',');
+    }
+}
diff --git a/test/.cvsignore b/test/.cvsignore
deleted file mode 100644
index 71ba7393632..00000000000
--- a/test/.cvsignore
+++ /dev/null
@@ -1,18 +0,0 @@
-Makefile
-testmmap
-htdigest
-ab
-proctest
-testcontext
-testargs
-testdso
-testoc
-testpipe
-testshmem
-testtime
-testthread
-client
-server
-testsock
-testproc
-testfile
diff --git a/test/Makefile.in b/test/Makefile.in
index e911abf4d8a..4fb4d94d36e 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -1,165 +1,214 @@
-# Generated automatically from Makefile.in by configure.
-#CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
-#LIBS=$(EXTRA_LIBS) $(LIBS1)
-#INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
-#LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
-
-RM=@RM@
-CC=@CC@
-RANLIB=@RANLIB@
-CFLAGS=@CFLAGS@ @OPTIM@ 
-LIBS=-L.. -lapr @LIBS@ 
-LDFLAGS=@LDFLAGS@ $(LIBS)
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+# PROGRAMS includes all test programs built on this platform.
+# STDTEST_PORTABLE
+#   test programs invoked via standard user interface, run on all platforms
+# TESTS
+#   test modules invoked through the abts suite (./testall)
+# STDTEST_NONPORTABLE
+#   test programs invoked via standard user interface, not portable
+# OTHER_PROGRAMS
+#   programs such as sockperf, that have to be invoked in a special sequence
+#   or with special parameters
+# TESTALL_COMPONENTS
+#   programs such as globalmutexchild which the various TESTS will invoke
+#   to validate process creation, pipes, dso mechanisms and so forth
+
+STDTEST_PORTABLE = \
+	testlockperf@EXEEXT@ \
+	testmutexscope@EXEEXT@ \
+	testall@EXEEXT@ \
+	dbd@EXEEXT@ \
+	sendfile@EXEEXT@ \
+
+TESTS = testtime.lo teststr.lo testvsn.lo testipsub.lo testshm.lo	\
+	testmmap.lo testud.lo testtable.lo testsleep.lo testpools.lo	\
+	testfmt.lo testfile.lo testdir.lo testfileinfo.lo testrand.lo	\
+	testdso.lo testoc.lo testdup.lo testsockets.lo testproc.lo	\
+	testpoll.lo testlock.lo testsockopt.lo testpipe.lo		\
+	testthread.lo testhash.lo testargs.lo testnames.lo testuser.lo	\
+	testpath.lo testenv.lo testprocmutex.lo testfnmatch.lo		\
+	testatomic.lo testflock.lo testsock.lo testglobalmutex.lo	\
+	teststrnatcmp.lo testfilecopy.lo testtemp.lo testlfs.lo		\
+	testcond.lo testuri.lo testmemcache.lo testdate.lo		\
+	testxlate.lo testdbd.lo testrmm.lo testmd4.lo	\
+	teststrmatch.lo testpass.lo testcrypto.lo testqueue.lo		\
+	testbuckets.lo testxml.lo testdbm.lo testuuid.lo testmd5.lo	\
+	testreslist.lo testbase64.lo testhooks.lo testlfsabi.lo		\
+	testlfsabi32.lo testlfsabi64.lo testescape.lo testskiplist.lo	\
+	testsiphash.lo testredis.lo
+
+OTHER_PROGRAMS = \
+	echod@EXEEXT@ \
+	sockperf@EXEEXT@
+
+TESTALL_COMPONENTS = \
+	globalmutexchild@EXEEXT@ \
+	libmod_test.la \
+	mod_test.la \
+	occhild@EXEEXT@ \
+	proc_child@EXEEXT@ \
+	readchild@EXEEXT@ \
+	sockchild@EXEEXT@ \
+	testshmproducer@EXEEXT@ \
+	testshmconsumer@EXEEXT@ \
+	tryread@EXEEXT@
+
+PROGRAMS = $(TESTALL_COMPONENTS) $(STDTEST_PORTABLE) $(STDTEST_NONPORTABLE) \
+	   $(OTHER_PROGRAMS)
+
+TARGETS = $(PROGRAMS)
+
+# bring in rules.mk for standard functionality
+@INCLUDE_RULES@
+
+LOCAL_LIBS=../lib@APR_LIBNAME@.la
+
+CLEAN_TARGETS = testfile.tmp lfstests/*.bin \
+	data/test*.txt data/test*.dat data/apr.testshm.shm
+
+CLEAN_SUBDIRS = internal
+
 INCDIR=../include
-INCLUDES=-I$(INCDIR)
-
-TARGETS= testfile@EXEEXT@ \
-	testproc@EXEEXT@ \
-	testsock@EXEEXT@ \
-	testthread@EXEEXT@ \
-	testtime@EXEEXT@ \
-	testargs@EXEEXT@ \
-	testcontext@EXEEXT@ \
-	testmmap@EXEEXT@ \
-	testshmem@EXEEXT@ \
-	testpipe@EXEEXT@ \
-	testdso@EXEEXT@ \
-	testoc@EXEEXT@ \
-	mod_test.so
-
-OBJS= testfile.o \
-	testproc.o \
-	testsock.o \
-	testthread.o \
-	testtime.o \
-        testargs.o \
-        testcontext.o \
-	testmmap.o \
-	testdso.o \
-	testoc.o \
-	mod_test.o
-
-.c.o:
-	$(CC) -c $(CFLAGS) $(INCLUDES) $<
-
-all: $(TARGETS) 
-
-testfile@EXEEXT@: testfile.o
-	$(CC) $(CFLAGS) testfile.o -o testfile@EXEEXT@ $(LDFLAGS) 
-
-testdso@EXEEXT@: testdso.o
-	$(CC) $(CFLAGS) --export-dynamic -fPIC testdso.o -o testdso@EXEEXT@ $(LDFLAGS) 
-
-testoc@EXEEXT@: testoc.o
-	$(CC) $(CFLAGS) testoc.o -o testoc@EXEEXT@ $(LDFLAGS) 
-
-mod_test.so: mod_test.o
-	$(CC) -shared mod_test.o -o mod_test.so 
-
-testargs@EXEEXT@: testargs.o
-	$(CC) $(CFLAGS) testargs.o -o testargs@EXEEXT@ $(LDFLAGS) 
-
-testcontext@EXEEXT@: testcontext.o
-	$(CC) $(CFLAGS) testcontext.o -o testcontext@EXEEXT@ $(LDFLAGS) 
-
-testproc@EXEEXT@: testproc.o
-	$(CC) $(CFLAGS) testproc.o -o testproc@EXEEXT@ $(LDFLAGS)
-
-testthread@EXEEXT@: testthread.o
-	$(CC) $(CFLAGS) testthread.o -o testthread@EXEEXT@ $(LDFLAGS)
-
-testsock@EXEEXT@: testsock.o client.o server.o 
-	$(CC) $(CFLAGS) testsock.o -o testsock@EXEEXT@  $(LDFLAGS)
-	$(CC) $(CFLAGS) server.o -o server@EXEEXT@ $(LDFLAGS) 
-	$(CC) $(CFLAGS) client.o -o client@EXEEXT@ $(LDFLAGS)
-
-testtime@EXEEXT@: testtime.o
-	$(CC) $(CFLAGS) testtime.o -o testtime@EXEEXT@ $(LDFLAGS)
-
-testmmap@EXEEXT@: testmmap.o
-	$(CC) $(CFLAGS) testmmap.o -o testmmap@EXEEXT@ $(LDFLAGS)
-
-testshmem@EXEEXT@: testshmem.o
-	$(CC) $(CFLAGS) testshmem.o -o testshmem@EXEEXT@ $(LDFLAGS)
-
-testpipe@EXEEXT@: testpipe.o
-	$(CC) $(CFLAGS) testpipe.o -o testpipe@EXEEXT@ $(LDFLAGS)
-
-clean:
-	$(RM) -f *.o *.a *.so $(TARGETS)
-
-distclean: clean
-	-$(RM) -f Makefile
-
-$(OBJS): Makefile
-
-#
-# We really don't expect end users to use this rule.  It works only with
-# gcc, and rebuilds Makefile.tmpl.  You have to re-run Configure after
-# using it.
-#
-depend:
-	cp Makefile.in Makefile.in.bak \
-	    && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.in > Makefile.new \
-	    && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \
-	    && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
-	           -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
-		> Makefile.in \
-	    && rm Makefile.new
+INCLUDES=-I$(INCDIR) -I$(srcdir)/../include
+
+# link programs using -no-install to get real executables not
+# libtool wrapper scripts which link an executable when first run.
+LINK_PROG = $(LIBTOOL) $(LTFLAGS) --mode=link $(COMPILE) $(LT_LDFLAGS) \
+	    @LT_NO_INSTALL@ $(ALL_LDFLAGS) -o $@
+
+# STDTEST_PORTABLE;
+
+abts.lo: $(srcdir)/abts.c $(srcdir)/abts.h $(srcdir)/abts_tests.h \
+	 $(srcdir)/testutil.h
+
+testutil.lo: $(srcdir)/abts.c $(srcdir)/abts.h $(srcdir)/abts_tests.h \
+	     $(srcdir)/testutil.h
+
+OBJECTS_testall = abts.lo testutil.lo $(TESTS) $(LOCAL_LIBS)
+testall@EXEEXT@: $(OBJECTS_testall)
+	$(LINK_PROG) $(OBJECTS_testall) $(ALL_LIBS)
+# For VPATH builds; where we have no ./data, copy us some data
+# if we wait until 'make check', then 'make; ./testall' fails;
+	if test ! -d "./data"; then cp -r $(srcdir)/data data; fi
+
+OBJECTS_testlockperf = testlockperf.lo $(LOCAL_LIBS)
+testlockperf@EXEEXT@: $(OBJECTS_testlockperf)
+	$(LINK_PROG) $(OBJECTS_testlockperf) $(ALL_LIBS)
+
+OBJECTS_testmutexscope = testmutexscope.lo $(LOCAL_LIBS)
+testmutexscope@EXEEXT@: $(OBJECTS_testmutexscope)
+	$(LINK_PROG) $(OBJECTS_testmutexscope) $(ALL_LIBS)
+
+# OTHER_PROGRAMS;
+
+OBJECTS_echod = echod.lo $(LOCAL_LIBS)
+echod@EXEEXT@: $(OBJECTS_echod)
+	$(LINK_PROG) $(OBJECTS_echod) $(ALL_LIBS)
+
+OBJECTS_sendfile = sendfile.lo $(LOCAL_LIBS)
+sendfile@EXEEXT@: $(OBJECTS_sendfile)
+	$(LINK_PROG) $(OBJECTS_sendfile) $(ALL_LIBS)
+
+OBJECTS_sockperf = sockperf.lo $(LOCAL_LIBS)
+sockperf@EXEEXT@: $(OBJECTS_sockperf)
+	$(LINK_PROG) $(OBJECTS_sockperf) $(ALL_LIBS)
+
+# TESTALL_COMPONENTS;
+
+OBJECTS_globalmutexchild = globalmutexchild.lo $(LOCAL_LIBS)
+globalmutexchild@EXEEXT@: $(OBJECTS_globalmutexchild)
+	$(LINK_PROG) $(OBJECTS_globalmutexchild) $(ALL_LIBS)
+
+# Note -prefer-pic is only supported with libtool-1.4+
+mod_test.lo: $(srcdir)/mod_test.c
+	$(LIBTOOL) $(LTFLAGS) --mode=compile $(COMPILE) -prefer-pic -o $@ \
+	  -c $(srcdir)/mod_test.c
+
+OBJECTS_mod_test = mod_test.lo
+mod_test.la: $(OBJECTS_mod_test) $(LOCAL_LIBS)
+	$(LIBTOOL) $(LTFLAGS) --mode=link $(COMPILE) -rpath `pwd` -module \
+	  -avoid-version $(LT_LDFLAGS) $(ALL_LDFLAGS) -o $@ \
+	  $(OBJECTS_mod_test) $(LOCAL_LIBS)
+
+OBJECTS_libmod_test = mod_test.lo $(LOCAL_LIBS)
+libmod_test.la: $(OBJECTS_libmod_test)
+	$(LIBTOOL) $(LTFLAGS) --mode=link $(COMPILE) -rpath `pwd` \
+	  -avoid-version $(LT_LDFLAGS) $(ALL_LDFLAGS) -o $@ \
+	  $(OBJECTS_libmod_test) $(ALL_LIBS)
+
+OBJECTS_occhild = occhild.lo $(LOCAL_LIBS)
+occhild@EXEEXT@: $(OBJECTS_occhild)
+	$(LINK_PROG) $(OBJECTS_occhild) $(ALL_LIBS)
+
+OBJECTS_proc_child = proc_child.lo $(LOCAL_LIBS)
+proc_child@EXEEXT@: $(OBJECTS_proc_child)
+	$(LINK_PROG) $(OBJECTS_proc_child) $(ALL_LIBS)
+
+OBJECTS_readchild = readchild.lo $(LOCAL_LIBS)
+readchild@EXEEXT@: $(OBJECTS_readchild)
+	$(LINK_PROG) $(OBJECTS_readchild) $(ALL_LIBS)
+
+OBJECTS_sockchild = sockchild.lo $(LOCAL_LIBS)
+sockchild@EXEEXT@: $(OBJECTS_sockchild)
+	$(LINK_PROG) $(OBJECTS_sockchild) $(ALL_LIBS)
+
+OBJECTS_testshmconsumer = testshmconsumer.lo $(LOCAL_LIBS)
+testshmconsumer@EXEEXT@: $(OBJECTS_testshmconsumer) $(LOCAL_LIBS)
+	$(LINK_PROG) $(OBJECTS_testshmconsumer) $(ALL_LIBS)
+
+OBJECTS_testshmproducer = testshmproducer.lo $(LOCAL_LIBS)
+testshmproducer@EXEEXT@: $(OBJECTS_testshmproducer)
+	$(LINK_PROG) $(OBJECTS_testshmproducer) $(ALL_LIBS)
+
+OBJECTS_tryread = tryread.lo $(LOCAL_LIBS)
+tryread@EXEEXT@: $(OBJECTS_tryread)
+	$(LINK_PROG) $(OBJECTS_tryread) $(ALL_LIBS)
+
+OBJECTS_dbd = dbd.lo $(LOCAL_LIBS)
+dbd@EXEEXT@: $(OBJECTS_dbd)
+	$(LINK_PROG) $(OBJECTS_dbd) $(APRUTIL_LIBS)
+
+check: $(TESTALL_COMPONENTS) $(STDTEST_PORTABLE) $(STDTEST_NONPORTABLE)
+	teststatus=0; \
+	progfailed=""; \
+	for prog in $(STDTEST_PORTABLE) $(STDTEST_NONPORTABLE); do \
+	        if test "$$prog" = 'dbd@EXEEXT@'; then \
+			for driver in none @apu_dbd_tests@; do \
+				if test "$$driver" != 'none'; then \
+					@shlibpath_var@="`echo "../dbm/.libs:../dbd/.libs:$$@shlibpath_var@" | sed -e 's/::*$$//'`" \
+					./$$prog $$driver; \
+					status=$$?; \
+					if test $$status != 0; then \
+						teststatus=$$status; \
+						progfailed="$$progfailed '$$prog $$driver'"; \
+					fi; \
+				fi; \
+			done; \
+		elif test "$$prog" = 'sendfile@EXEEXT@'; then \
+			for mode in blocking nonblocking timeout; do \
+				@shlibpath_var@="`echo "../dbm/.libs:../dbd/.libs:$$@shlibpath_var@" | sed -e 's/::*$$//'`" \
+				./$$prog client $$mode startserver 127.0.0.1; \
+				status=$$?; \
+				if test $$status != 0; then \
+					teststatus=$$status; \
+					progfailed="$$progfailed '$$prog mode $$mode'"; \
+				fi; \
+			done; \
+	        else \
+			@shlibpath_var@="`echo "../dbm/.libs:../dbd/.libs:$$@shlibpath_var@" | sed -e 's/::*$$//'`" \
+			./$$prog -v; \
+			status=$$?; \
+			if test $$status != 0; then \
+				teststatus=$$status; \
+				progfailed="$$progfailed $$prog"; \
+			fi; \
+		fi; \
+	done; \
+	if test $$teststatus != 0; then \
+		echo "Programs failed:$$progfailed"; \
+	fi; \
+	exit $$teststatus
 
 # DO NOT REMOVE
-abc.o: abc.c $(INCDIR)/apr_file_io.h $(INCDIR)/apr_general.h \
- $(INCDIR)/apr.h $(INCDIR)/apr_errno.h $(INCDIR)/apr_time.h
-client.o: client.c $(INCDIR)/apr_network_io.h \
- $(INCDIR)/apr_general.h $(INCDIR)/apr.h $(INCDIR)/apr_errno.h \
- $(INCDIR)/apr_file_io.h $(INCDIR)/apr_time.h $(OSDIR)/usr/include/errno.h
-mod_test.o: mod_test.c
-server.o: server.c $(INCDIR)/apr_network_io.h \
- $(INCDIR)/apr_general.h $(INCDIR)/apr.h $(INCDIR)/apr_errno.h \
- $(INCDIR)/apr_file_io.h $(INCDIR)/apr_time.h
-testargs.o: testargs.c $(INCDIR)/apr_file_io.h \
- $(INCDIR)/apr_general.h $(INCDIR)/apr.h $(INCDIR)/apr_errno.h \
- $(INCDIR)/apr_time.h $(INCDIR)/apr_lib.h \
- $(INCDIR)/apr_thread_proc.h $(INCDIR)/apr_getopt.h
-testcontext.o: testcontext.c $(INCDIR)/apr_file_io.h \
- $(INCDIR)/apr_general.h $(INCDIR)/apr.h $(INCDIR)/apr_errno.h \
- $(INCDIR)/apr_time.h $(INCDIR)/apr_lib.h \
- $(INCDIR)/apr_thread_proc.h
-testdso.o: testdso.c $(INCDIR)/apr_general.h $(INCDIR)/apr.h \
- $(INCDIR)/apr_errno.h $(INCDIR)/apr_pools.h $(INCDIR)/apr_lib.h \
- $(INCDIR)/apr_file_io.h $(INCDIR)/apr_time.h \
- $(INCDIR)/apr_thread_proc.h $(INCDIR)/apr_dso.h
-testfile.o: testfile.c $(INCDIR)/apr_file_io.h \
- $(INCDIR)/apr_general.h $(INCDIR)/apr.h $(INCDIR)/apr_errno.h \
- $(INCDIR)/apr_time.h $(INCDIR)/apr_lib.h \
- $(INCDIR)/apr_thread_proc.h
-testmmap.o: testmmap.c $(INCDIR)/apr_mmap.h $(INCDIR)/apr_general.h \
- $(INCDIR)/apr.h $(INCDIR)/apr_errno.h $(INCDIR)/apr_network_io.h \
- $(INCDIR)/apr_file_io.h $(INCDIR)/apr_time.h \
- $(INCDIR)/apr_portable.h $(INCDIR)/apr_thread_proc.h \
- $(INCDIR)/apr_lock.h $(INCDIR)/apr_lib.h
-testoc.o: testoc.c $(INCDIR)/apr_thread_proc.h \
- $(INCDIR)/apr_file_io.h $(INCDIR)/apr_general.h $(INCDIR)/apr.h \
- $(INCDIR)/apr_errno.h $(INCDIR)/apr_time.h $(INCDIR)/apr_lib.h \
- $(OSDIR)/usr/include/errno.h
-testpipe.o: testpipe.c $(INCDIR)/apr_file_io.h \
- $(INCDIR)/apr_general.h $(INCDIR)/apr.h $(INCDIR)/apr_errno.h \
- $(INCDIR)/apr_time.h $(INCDIR)/apr_lib.h \
- $(INCDIR)/apr_thread_proc.h
-testproc.o: testproc.c $(INCDIR)/apr_thread_proc.h \
- $(INCDIR)/apr_file_io.h $(INCDIR)/apr_general.h $(INCDIR)/apr.h \
- $(INCDIR)/apr_errno.h $(INCDIR)/apr_time.h $(INCDIR)/apr_lib.h \
- $(OSDIR)/usr/include/errno.h
-testshmem.o: testshmem.c $(INCDIR)/apr_shmem.h $(INCDIR)/apr.h \
- $(INCDIR)/apr_general.h $(INCDIR)/apr_errno.h $(INCDIR)/apr_lock.h \
- $(INCDIR)/apr_lib.h $(INCDIR)/apr_file_io.h $(INCDIR)/apr_time.h \
- $(INCDIR)/apr_thread_proc.h $(OSDIR)/usr/include/errno.h
-testsock.o: testsock.c $(INCDIR)/apr_thread_proc.h \
- $(INCDIR)/apr_file_io.h $(INCDIR)/apr_general.h $(INCDIR)/apr.h \
- $(INCDIR)/apr_errno.h $(INCDIR)/apr_time.h $(INCDIR)/apr_lib.h
-testthread.o: testthread.c $(INCDIR)/apr_thread_proc.h \
- $(INCDIR)/apr_file_io.h $(INCDIR)/apr_general.h $(INCDIR)/apr.h \
- $(INCDIR)/apr_errno.h $(INCDIR)/apr_time.h $(INCDIR)/apr_lock.h \
- $(OSDIR)/usr/include/errno.h
-testtime.o: testtime.c $(INCDIR)/apr_time.h $(INCDIR)/apr_general.h \
- $(INCDIR)/apr.h $(INCDIR)/apr_errno.h $(OSDIR)/usr/include/errno.h
diff --git a/test/Makefile.win b/test/Makefile.win
new file mode 100644
index 00000000000..21344ea0309
--- /dev/null
+++ b/test/Makefile.win
@@ -0,0 +1,318 @@
+# PROGRAMS includes all test programs built on this platform.
+# STDTEST_PORTABLE
+#   test programs invoked via standard user interface, run on all platforms
+# TESTS
+#   test modules invoked through the abts suite (./testall)
+# STDTEST_NONPORTABLE
+#   test programs invoked via standard user interface, not portable
+# OTHER_PROGRAMS
+#   programs such as sendfile, that have to be invoked in a special sequence
+#   or with special parameters
+# TESTALL_COMPONENTS
+#   programs such as globalmutexchild which the various TESTS will invoke
+#   to validate process creation, pipes, dso mechanisms and so forth
+
+# Windows Specific;
+# MODEL
+#   dynamic or static - refers to which set of bindings are desired
+#   and controls which libraries (apr-2 or libapr-2) will be linked.
+# OUTDIR
+#   the library path of the libraries, and also the path within test/
+#   where all of the tests for that library will be built
+
+!IFNDEF MODEL
+MODEL=dynamic
+!ENDIF
+
+INCDIR=../include
+
+!IFNDEF OUTDIR
+!IF "$(MODEL)" == "static"
+OUTDIR=LibR
+!ELSE
+OUTDIR=Release
+!ENDIF
+
+!IF [$(COMSPEC) /c cl /nologo /? \
+	| $(SystemRoot)\System32\find.exe "x64" >NUL ] == 0
+OUTDIR=x64\$(OUTDIR)
+!ENDIF
+!ENDIF
+
+!IF !EXIST("$(OUTDIR)\.")
+!IF ([$(COMSPEC) /C mkdir $(OUTDIR)] == 0)
+!ENDIF
+!ENDIF
+
+!IFNDEF INTDIR
+INTDIR=$(OUTDIR)
+!ELSE
+!IF !EXIST("$(INTDIR)\.")
+!IF ([$(COMSPEC) /C mkdir $(INTDIR)] == 0)
+!ENDIF
+!ENDIF
+!ENDIF
+
+!MESSAGE Building tests into $(OUTDIR) for $(MODEL)
+
+STDTEST_PORTABLE = \
+	$(OUTDIR)\testapp.exe \
+	$(OUTDIR)\testall.exe \
+	$(OUTDIR)\testlockperf.exe \
+	$(OUTDIR)\testmutexscope.exe
+
+OTHER_PROGRAMS = \
+	$(OUTDIR)\echod.exe \
+	$(OUTDIR)\sendfile.exe \
+	$(OUTDIR)\sockperf.exe
+
+TESTALL_COMPONENTS = \
+	$(OUTDIR)\mod_test.dll \
+	$(OUTDIR)\occhild.exe \
+	$(OUTDIR)\readchild.exe \
+	$(OUTDIR)\proc_child.exe \
+        $(OUTDIR)\tryread.exe \
+	$(OUTDIR)\sockchild.exe \
+	$(OUTDIR)\testshmproducer.exe \
+	$(OUTDIR)\testshmconsumer.exe \
+	$(OUTDIR)\globalmutexchild.exe
+
+ALL_TESTS = \
+	$(INTDIR)\testargs.obj \
+	$(INTDIR)\testatomic.obj \
+	$(INTDIR)\testbase64.obj \
+	$(INTDIR)\testbuckets.obj \
+	$(INTDIR)\testcond.obj \
+	$(INTDIR)\testcrypto.obj \
+	$(INTDIR)\testdate.obj \
+	$(INTDIR)\testdbd.obj \
+	$(INTDIR)\testdbm.obj \
+	$(INTDIR)\testdir.obj \
+	$(INTDIR)\testdso.obj \
+	$(INTDIR)\testdup.obj \
+	$(INTDIR)\testenv.obj \
+	$(INTDIR)\testescape.obj \
+	$(INTDIR)\testfile.obj \
+	$(INTDIR)\testfilecopy.obj \
+	$(INTDIR)\testfileinfo.obj \
+	$(INTDIR)\testflock.obj \
+	$(INTDIR)\testfmt.obj \
+	$(INTDIR)\testfnmatch.obj \
+	$(INTDIR)\testglobalmutex.obj \
+	$(INTDIR)\testhash.obj \
+	$(INTDIR)\testhooks.obj \
+	$(INTDIR)\testipsub.obj \
+	$(INTDIR)\testlfs.obj \
+	$(INTDIR)\testlfsabi.obj \
+	$(INTDIR)\testlfsabi32.obj \
+	$(INTDIR)\testlfsabi64.obj \
+	$(INTDIR)\testlock.obj \
+	$(INTDIR)\testmd4.obj \
+	$(INTDIR)\testmd5.obj \
+	$(INTDIR)\testmemcache.obj \
+	$(INTDIR)\testmmap.obj \
+	$(INTDIR)\testnames.obj \
+	$(INTDIR)\testoc.obj \
+	$(INTDIR)\testpass.obj \
+	$(INTDIR)\testpath.obj \
+	$(INTDIR)\testpipe.obj \
+	$(INTDIR)\testpoll.obj \
+	$(INTDIR)\testpools.obj \
+	$(INTDIR)\testproc.obj \
+	$(INTDIR)\testprocmutex.obj \
+	$(INTDIR)\testqueue.obj \
+	$(INTDIR)\testrand.obj \
+	$(INTDIR)\testredis.obj \
+	$(INTDIR)\testreslist.obj \
+	$(INTDIR)\testrmm.obj \
+	$(INTDIR)\testshm.obj \
+	$(INTDIR)\testsiphash.obj \
+	$(INTDIR)\testsleep.obj \
+	$(INTDIR)\testsock.obj \
+	$(INTDIR)\testsockets.obj \
+	$(INTDIR)\testsockopt.obj \
+	$(INTDIR)\teststr.obj \
+	$(INTDIR)\teststrmatch.obj \
+	$(INTDIR)\teststrnatcmp.obj \
+	$(INTDIR)\testskiplist.obj \
+	$(INTDIR)\testtable.obj \
+	$(INTDIR)\testtemp.obj \
+	$(INTDIR)\testthread.obj \
+	$(INTDIR)\testtime.obj \
+	$(INTDIR)\testud.obj\
+	$(INTDIR)\testuri.obj \
+	$(INTDIR)\testuser.obj \
+	$(INTDIR)\testutil.obj \
+	$(INTDIR)\testuuid.obj \
+	$(INTDIR)\testvsn.obj \
+	$(INTDIR)\testxlate.obj \
+	$(INTDIR)\testxml.obj
+
+CLEAN_DATA = testfile.tmp lfstests\large.bin \
+	data\testputs.txt data\testbigfprintf.dat \
+	data\testwritev.txt data\testwritev_full.txt \
+	data\testflush.dat data\testxthread.dat \
+	data\apr.testshm.shm
+
+CLEAN_BUILDDIRS = Debug Release LibD LibR x64
+
+TEST_SUBDIRS = internal
+
+PROGRAMS = $(TESTALL_COMPONENTS) $(STDTEST_PORTABLE) $(STDTEST_NONPORTABLE) \
+	$(OTHER_PROGRAMS)
+
+TARGETS = $(PROGRAMS)
+
+# bring in rules.mk for standard functionality
+ALL: $(TARGETS)
+
+CL = cl.exe
+LD = link.exe 
+
+!IF "$(MODEL)" == "static"
+LOCAL_LIB= ..\$(OUTDIR)\apr-2.lib ..\..\expat\win32\bin\Release\libexpatMT.lib
+APP_LIB= ..\$(OUTDIR)\aprapp-2.lib
+STATIC_CFLAGS = /D APR_DECLARE_STATIC
+!ELSE
+LOCAL_LIB= ..\$(OUTDIR)\libapr-2.lib 
+APP_LIB= ..\$(OUTDIR)\libaprapp-2.lib 
+STATIC_CFLAGS = 
+PATH=$(OUTDIR);..\$(OUTDIR);..\..\expat\win32\bin\$(OUTDIR);$(PATH)
+!ENDIF
+
+!IFDEF _DEBUG
+DEBUG_CFLAGS = /MDd
+!ELSE
+DEBUG_CFLAGS = /MD 
+!ENDIF
+
+INCLUDES=/I "$(INCDIR)"
+
+CFLAGS = /nologo /c /W3 /Gm /EHsc /Zi /Od $(INCLUDES) \
+	 $(STATIC_CFLAGS) $(DEBUG_CFLAGS) /D "BINPATH=$(OUTDIR:\=/)" \
+	 /D _DEBUG /D WIN32 /Fo"$(INTDIR)/" /FD
+
+LD_LIBS = kernel32.lib advapi32.lib ws2_32.lib wsock32.lib \
+	  ole32.lib shell32.lib rpcrt4.lib
+
+LDFLAGS = /nologo /debug /subsystem:console /incremental:no /nodefaultlib:libcmt
+
+SHLDFLAGS = /nologo /dll /debug /subsystem:windows /incremental:no
+
+.c{$(INTDIR)}.obj::
+	$(CL) $(CFLAGS) -c $< -Fd$(INTDIR)\ $(INCLUDES)
+
+# STDTEST_PORTABLE;
+
+$(OUTDIR)\testall.exe: $(ALL_TESTS) $(INTDIR)\abts.obj $(LOCAL_LIB)
+	$(LD) $(LDFLAGS) /out:"$@" $** $(LD_LIBS)
+	@if exist "$@.manifest" \
+	    mt.exe -manifest "$@.manifest" -outputresource:$@;1
+
+$(OUTDIR)\testapp.exe: $(INTDIR)/testapp.obj $(LOCAL_LIB) $(APP_LIB) 
+	$(LD) $(LDFLAGS) /entry:wmainCRTStartup /out:"$@" $** $(LD_LIBS)
+	@if exist "$@.manifest" \
+	    mt.exe -manifest "$@.manifest" -outputresource:$@;2
+
+$(OUTDIR)\testlockperf.exe: $(INTDIR)\testlockperf.obj $(LOCAL_LIB)
+	$(LD) $(LDFLAGS) /out:"$@" $** $(LD_LIBS)
+	@if exist "$@.manifest" \
+	    mt.exe -manifest "$@.manifest" -outputresource:$@;1
+
+$(OUTDIR)\testmutexscope.exe: $(INTDIR)\testmutexscope.obj $(LOCAL_LIB)
+	$(LD) $(LDFLAGS) /out:"$@" $** $(LD_LIBS)
+	@if exist "$@.manifest" \
+	    mt.exe -manifest "$@.manifest" -outputresource:$@;1
+
+# OTHER_PROGRAMS;
+
+$(OUTDIR)\echod.exe: $(INTDIR)\echod.obj $(LOCAL_LIB)
+	$(LD) $(LDFLAGS) /out:"$@" $** $(LD_LIBS)
+	@if exist "$@.manifest" \
+	    mt.exe -manifest "$@.manifest" -outputresource:$@;1
+
+$(OUTDIR)\sendfile.exe: $(INTDIR)\sendfile.obj $(LOCAL_LIB)
+	$(LD) $(LDFLAGS) /out:"$@" $** $(LD_LIBS)
+	@if exist "$@.manifest" \
+	    mt.exe -manifest "$@.manifest" -outputresource:$@;1
+
+$(OUTDIR)\sockperf.exe: $(INTDIR)\sockperf.obj $(LOCAL_LIB)
+	$(LD) $(LDFLAGS) /out:"$@" $** $(LD_LIBS)
+	@if exist "$@.manifest" \
+	    mt.exe -manifest "$@.manifest" -outputresource:$@;1
+
+# TESTALL_COMPONENTS;
+
+$(OUTDIR)\globalmutexchild.exe: $(INTDIR)\globalmutexchild.obj $(LOCAL_LIB)
+	$(LD) $(LDFLAGS) /out:"$@" $** $(LD_LIBS)
+	@if exist "$@.manifest" \
+	    mt.exe -manifest "$@.manifest" -outputresource:$@;1
+
+$(OUTDIR)\mod_test.dll: $(INTDIR)/mod_test.obj $(LOCAL_LIB) 
+	$(LD) $(SHLDFLAGS) /out:"$@" $** \
+	       /export:print_hello /export:count_reps $(LD_LIBS)
+	@if exist "$@.manifest" \
+	    mt.exe -manifest "$@.manifest" -outputresource:$@;2
+
+$(OUTDIR)\occhild.exe: $(INTDIR)\occhild.obj $(LOCAL_LIB)
+	$(LD) $(LDFLAGS) /out:"$@" $** $(LD_LIBS)
+	@if exist "$@.manifest" \
+	    mt.exe -manifest "$@.manifest" -outputresource:$@;1
+
+$(OUTDIR)\proc_child.exe: $(INTDIR)\proc_child.obj $(LOCAL_LIB)
+	$(LD) $(LDFLAGS) /out:"$@" $** $(LD_LIBS)
+	@if exist "$@.manifest" \
+	    mt.exe -manifest "$@.manifest" -outputresource:$@;1
+
+$(OUTDIR)\readchild.exe: $(INTDIR)\readchild.obj $(LOCAL_LIB)
+	$(LD) $(LDFLAGS) /out:"$@" $** $(LD_LIBS)
+	@if exist "$@.manifest" \
+	    mt.exe -manifest "$@.manifest" -outputresource:$@;1
+
+$(OUTDIR)\sockchild.exe: $(INTDIR)\sockchild.obj $(LOCAL_LIB)
+	$(LD) $(LDFLAGS) /out:"$@" $** $(LD_LIBS)
+	@if exist "$@.manifest" \
+	    mt.exe -manifest "$@.manifest" -outputresource:$@;1
+
+$(OUTDIR)\testshmconsumer.exe: $(INTDIR)\testshmconsumer.obj $(LOCAL_LIB)
+	$(LD) $(LDFLAGS) /out:"$@" $** $(LD_LIBS)
+	@if exist "$@.manifest" \
+	    mt.exe -manifest "$@.manifest" -outputresource:$@;1
+
+$(OUTDIR)\testshmproducer.exe: $(INTDIR)\testshmproducer.obj $(LOCAL_LIB)
+	$(LD) $(LDFLAGS) /out:"$@" $** $(LD_LIBS)
+	@if exist "$@.manifest" \
+	    mt.exe -manifest "$@.manifest" -outputresource:$@;1
+
+$(OUTDIR)\tryread.exe: $(INTDIR)\tryread.obj $(LOCAL_LIB)
+	$(LD) $(LDFLAGS) /out:"$@" $** $(LD_LIBS)
+	@if exist "$@.manifest" \
+	    mt.exe -manifest "$@.manifest" -outputresource:$@;1
+
+
+cleandata:
+	@for %f in ($(CLEAN_DATA)) do @if EXIST %f del /f %f
+
+clean: cleandata
+	@if EXIST $(INTDIR)\. rmdir /s /q $(INTDIR)
+	@if EXIST $(OUTDIR)\. rmdir /s /q $(OUTDIR)
+	@for %d in ($(TEST_SUBDIRS)) do \
+	    %COMSPEC% /c "cd %%d && $(MAKE) -f Makefile.win clean" \
+
+cleanall: 
+	@for %d in ($(CLEAN_BUILDDIRS) $(INTDIR) $(OUTDIR)) do \
+	    @if EXIST %d\. rmdir /s /q %d
+	@for %d in ($(TEST_SUBDIRS)) do \
+	    %COMSPEC% /c "cd %%d & $(MAKE) -f Makefile.win cleanall" \
+
+
+check: $(TESTALL_COMPONENTS) $(STDTEST_PORTABLE) $(STDTEST_NONPORTABLE)
+	@for %p in ($(STDTEST_PORTABLE) $(STDTEST_NONPORTABLE)) do @( \
+	    echo Testing %p && %p -v || echo %p failed \
+	)
+
+checkall: check
+	@for %d in ($(TEST_SUBDIRS)) do \
+	    %COMSPEC% /c "cd %%d && $(MAKE) -f Makefile.win check" \
+
+# DO NOT REMOVE
diff --git a/test/NWGNUaprtest b/test/NWGNUaprtest
new file mode 100644
index 00000000000..0a8bc01ceb9
--- /dev/null
+++ b/test/NWGNUaprtest
@@ -0,0 +1,335 @@
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# Get the 'head' of the build environment if necessary.  This includes default
+# targets and paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(APR_WORK)/build/NWGNUhead.inc
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS	+= \
+			$(APR)/include \
+			$(APR)/include/arch/netware \
+			$(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	= aprtest
+#
+# This is used by the link '-desc ' directive. 
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION	= NLM is to test the apr layer
+
+#
+# This is used by the '-threadname' directive.  If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME	= $(NLM_NAME)
+
+#
+# This is used by the '-screenname' directive.  If left blank,
+# 'Apache for NetWare' Thread will be used.
+#
+NLM_SCREEN_NAME	= $(NLM_NAME)
+
+#
+# If this is specified, it will override VERSION value in 
+# $(APR_WORK)/build/NWGNUenvironment.inc
+#
+NLM_VERSION	=
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE	= 524288
+
+#
+# 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 this is 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 $(APR)/misc/netware/apache.xdc.  XDCData can 
+# be disabled by setting APACHE_UNIPROC in the environment
+#
+XDCDATA		= 
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+	$(OBJDIR)/$(NLM_NAME).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)/abts.o \
+	$(OBJDIR)/testargs.o \
+	$(OBJDIR)/testatomic.o \
+	$(OBJDIR)/testbase64.o \
+	$(OBJDIR)/testbuckets.o \
+	$(OBJDIR)/testcond.o \
+	$(OBJDIR)/testcrypto.o \
+	$(OBJDIR)/testdate.o \
+	$(OBJDIR)/testdbd.o \
+	$(OBJDIR)/testdbm.o \
+	$(OBJDIR)/testdir.o \
+	$(OBJDIR)/testdup.o \
+	$(OBJDIR)/testdso.o \
+	$(OBJDIR)/testenv.o \
+	$(OBJDIR)/testescape.o \
+	$(OBJDIR)/testfilecopy.o \
+	$(OBJDIR)/testfileinfo.o \
+	$(OBJDIR)/testfile.o \
+	$(OBJDIR)/testflock.o \
+	$(OBJDIR)/testfmt.o \
+	$(OBJDIR)/testfnmatch.o \
+	$(OBJDIR)/testglobalmutex.o \
+	$(OBJDIR)/testhash.o \
+	$(OBJDIR)/testhooks.o \
+	$(OBJDIR)/testipsub.o \
+	$(OBJDIR)/testlfs.o \
+	$(OBJDIR)/testlfsabi.o \
+	$(OBJDIR)/testlfsabi32.o \
+	$(OBJDIR)/testlfsabi64.o \
+	$(OBJDIR)/testlock.o \
+	$(OBJDIR)/testmd4.o \
+	$(OBJDIR)/testmd5.o \
+	$(OBJDIR)/testmmap.o \
+	$(OBJDIR)/testmemcache.o \
+	$(OBJDIR)/testnames.o \
+	$(OBJDIR)/testoc.o \
+	$(OBJDIR)/testpass.o \
+	$(OBJDIR)/testpath.o \
+	$(OBJDIR)/testpipe.o \
+	$(OBJDIR)/testpoll.o \
+	$(OBJDIR)/testpools.o \
+	$(OBJDIR)/testproc.o \
+	$(OBJDIR)/testprocmutex.o \
+	$(OBJDIR)/testqueue.o \
+	$(OBJDIR)/testreslist.o \
+	$(OBJDIR)/testrand.o \
+	$(OBJDIR)/testrmm.o \
+	$(OBJDIR)/testshm.o \
+	$(OBJDIR)/testsiphash.o \
+	$(OBJDIR)/testskiplist.o \
+	$(OBJDIR)/testsleep.o \
+	$(OBJDIR)/testsock.o \
+	$(OBJDIR)/testsockets.o \
+	$(OBJDIR)/testsockopt.o \
+	$(OBJDIR)/teststr.o \
+	$(OBJDIR)/teststrmatch.o \
+	$(OBJDIR)/teststrnatcmp.o \
+	$(OBJDIR)/testtable.o \
+	$(OBJDIR)/testtemp.o \
+	$(OBJDIR)/testthread.o \
+	$(OBJDIR)/testtime.o \
+	$(OBJDIR)/testud.o \
+	$(OBJDIR)/testuri.o \
+	$(OBJDIR)/testuser.o \
+	$(OBJDIR)/testutil.o \
+	$(OBJDIR)/testuuid.o \
+	$(OBJDIR)/testvsn.o \
+	$(OBJDIR)/testxml.o \
+	$(OBJDIR)/testxlate.o \
+	$(OBJDIR)/nw_misc.o \
+	$(EOLIST) 
+
+# Pending tests
+
+#
+# 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 = \
+	Libc \
+	APRLIB \
+	$(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 the default copyright.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+	@$(APR)/aprlib.imp \
+	@$(NOVI)/libc.imp \
+	$(EOLIST)
+ 
+# Include the Winsock imports if Winsock is being used
+ifndef USE_STDSOCKETS
+FILES_nlm_Ximports +=  \
+	@$(NOVI)/ws2nlm.imp \
+	$(EOLIST)
+FILES_nlm_imports +=  \
+	WSAStartupRTags \
+	WSACleanupRTag \
+	$(EOLIST)
+endif
+
+#   
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+	$(EOLIST)
+
+#   
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+	$(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the 
+# correct place.  (See $(APR_WORK)/build/NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(APRBUILD)/NWGNUtail.inc
+
diff --git a/test/NWGNUechod b/test/NWGNUechod
new file mode 100644
index 00000000000..470c0cd8765
--- /dev/null
+++ b/test/NWGNUechod
@@ -0,0 +1,253 @@
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# Get the 'head' of the build environment if necessary.  This includes default
+# targets and paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(APR_WORK)/build/NWGNUhead.inc
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS	+= \
+			$(APR)/include \
+			$(APR)/include/arch/netware \
+			$(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	= echod
+
+#
+# This is used by the link '-desc ' directive. 
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION	= Echo Daemon NLM to test socket performance
+
+#
+# This is used by the '-threadname' directive.  If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME	= $(NLM_NAME)
+
+#
+# This is used by the '-screenname' directive.  If left blank,
+# 'Apache for NetWare' Thread will be used.
+#
+NLM_SCREEN_NAME = $(NLM_NAME)
+
+#
+# If this is specified, it will override VERSION value in 
+# $(APR_WORK)/build/NWGNUenvironment.inc
+#
+NLM_VERSION	=
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE	= 
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM	=
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM	=
+
+#
+# If this is specified it will be used by the link '-check' directive
+#
+NLM_CHECK_SYM	=
+
+#
+# If this is specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS	= AUTOUNLOAD, PSEUDOPREEMPTION, MULTIPLE
+ 
+#
+# If this is specified it will be linked in with the XDCData option in the def 
+# file instead of the default of $(APR)/misc/netware/apache.xdc.  XDCData can 
+# be disabled by setting APACHE_UNIPROC in the environment
+#
+XDCDATA		= 
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+	$(OBJDIR)/$(NLM_NAME).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)/$(NLM_NAME).o \
+	$(OBJDIR)/nw_misc.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 the default copyright.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+	@$(APR)/aprlib.imp \
+	@$(NOVI)/libc.imp \
+	$(EOLIST)
+ 
+#   
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+	$(EOLIST)
+
+#   
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+	$(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the 
+# correct place.  (See $(APR_WORK)/build/NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(APRBUILD)/NWGNUtail.inc
+
diff --git a/test/NWGNUglobalmutexchild b/test/NWGNUglobalmutexchild
new file mode 100644
index 00000000000..9a1518a63fc
--- /dev/null
+++ b/test/NWGNUglobalmutexchild
@@ -0,0 +1,254 @@
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# Get the 'head' of the build environment if necessary.  This includes default
+# targets and paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(APR_WORK)/build/NWGNUhead.inc
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS	+= \
+			$(APR)/include \
+			$(APR)/include/arch/netware \
+			$(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)
+
+			$(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	= globalmutexchild
+
+#
+# This is used by the link '-desc ' directive. 
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION	=  child NLM to test the global Mutex layer
+
+#
+# This is used by the '-threadname' directive.  If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME	= $(NLM_NAME)
+
+#
+# This is used by the '-screenname' directive.  If left blank,
+# 'Apache for NetWare' Thread will be used.
+#
+NLM_SCREEN_NAME = DEFAULT
+
+#
+# If this is specified, it will override VERSION value in 
+# $(APR_WORK)/build/NWGNUenvironment.inc
+#
+NLM_VERSION	=
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE	= 
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM	=
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM	=
+
+#
+# If this is specified it will be used by the link '-check' directive
+#
+NLM_CHECK_SYM	=
+
+#
+# If this is specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS	= AUTOUNLOAD, PSEUDOPREEMPTION, MULTIPLE
+ 
+#
+# If this is specified it will be linked in with the XDCData option in the def 
+# file instead of the default of $(APR)/misc/netware/apache.xdc.  XDCData can 
+# be disabled by setting APACHE_UNIPROC in the environment
+#
+XDCDATA		= 
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+	$(OBJDIR)/$(NLM_NAME).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)/$(NLM_NAME).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 the default copyright.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+	@$(APR)/aprlib.imp \
+	@$(NOVI)/libc.imp \
+	$(EOLIST)
+ 
+#   
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+	$(EOLIST)
+
+#   
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+	$(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the 
+# correct place.  (See $(APR_WORK)/build/NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(APRBUILD)/NWGNUtail.inc
+
diff --git a/test/NWGNUmakefile b/test/NWGNUmakefile
new file mode 100644
index 00000000000..350e6652e7d
--- /dev/null
+++ b/test/NWGNUmakefile
@@ -0,0 +1,264 @@
+#
+# 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 $(APR_WORK)/build/NWGNUhead.inc
+
+#
+# build this level's files
+
+#
+# Make sure all needed macro's are defined
+#
+
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS	+= \
+			$(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS		+= \
+			$(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES	+= \
+			$(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS		+= \
+			$(EOLIST)
+
+#
+# These values will be appended to the correct variables based on the value of
+# RELEASE
+#
+ifeq "$(RELEASE)" "debug"
+XINCDIRS	+= \
+			$(EOLIST)
+
+XCFLAGS		+= \
+			$(EOLIST)
+
+XDEFINES	+= \
+			$(EOLIST)
+
+XLFLAGS		+= \
+			$(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "noopt"
+XINCDIRS	+= \
+			$(EOLIST)
+
+XCFLAGS		+= \
+			$(EOLIST)
+
+XDEFINES	+= \
+			$(EOLIST)
+
+XLFLAGS		+= \
+			$(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "release"
+XINCDIRS	+= \
+			$(EOLIST)
+
+XCFLAGS		+= \
+			$(EOLIST)
+
+XDEFINES	+= \
+			$(EOLIST)
+
+XLFLAGS		+= \
+			$(EOLIST)
+endif
+
+#
+# These are used by the link target if an NLM is being generated
+# This is used by the link 'name' directive to name the nlm.  If left blank
+# TARGET_nlm (see below) will be used.
+#
+NLM_NAME	=
+
+#
+# This is used by the link '-desc ' directive. 
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION	=  NLM is to test the apr layer
+
+#
+# This is used by the '-threadname' directive.  If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME	= 
+
+#
+# This is used by the '-screenname' directive.  If left blank,
+# 'Apache for NetWare' Thread will be used.
+#
+NLM_SCREEN_NAME =
+
+#
+# If this is specified, it will override VERSION value in 
+# $(APR_WORK)/build/NWGNUenvironment.inc
+#
+NLM_VERSION	= 
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE	= 
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM	= 
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM	= 
+
+#
+# If this is specified it will be used by the link '-check' directive
+#
+NLM_CHECK_SYM	=
+
+#
+# If this is 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 $(APR)/misc/netware/apache.xdc.  XDCData can 
+# be disabled by setting APACHE_UNIPROC in the environment
+#
+XDCDATA		= 
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+	$(OBJDIR)/aprtest.nlm \
+	$(OBJDIR)/echod.nlm \
+	$(OBJDIR)/globalmutexchild.nlm \
+	$(OBJDIR)/mod_test.nlm \
+	$(OBJDIR)/proc_child.nlm \
+	$(OBJDIR)/readchild.nlm \
+	$(OBJDIR)/sockchild.nlm \
+	$(OBJDIR)/sockperf.nlm \
+	$(OBJDIR)/testatmc.nlm \
+	$(OBJDIR)/tryread.nlm \
+	$(EOLIST)
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+	$(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+	$(EOLIST)
+
+#
+# These are the LIB files needed to create the NLM target above.
+# These will be added as a library command in the link.opt file.
+#
+FILES_nlm_libs = \
+	$(EOLIST)
+
+#
+# These are the modules that the above NLM target depends on to load.
+# These will be added as a module command in the link.opt file.
+#
+FILES_nlm_modules = \
+	aprlib \
+	$(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 the default copyright.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+	$(EOLIST)
+ 
+#   
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+	$(EOLIST)
+
+#   
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+	$(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the 
+# correct place.  (See $(APR_WORK)/build/NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+	$(call COPY,$(OBJDIR)/*.nlm,$(INSTALLBASE)/)
+	$(call COPYR,data,$(INSTALLBASE)/data/)
+
+#
+# Any specialized rules here
+#
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(APRBUILD)/NWGNUtail.inc
+
diff --git a/test/NWGNUmod_test b/test/NWGNUmod_test
new file mode 100644
index 00000000000..a69f4eab832
--- /dev/null
+++ b/test/NWGNUmod_test
@@ -0,0 +1,254 @@
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# Get the 'head' of the build environment if necessary.  This includes default
+# targets and paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(APR_WORK)/build/NWGNUhead.inc
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS	+= \
+			$(APR)/include \
+			$(APR)/include/arch/netware \
+			$(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	= mod_test
+
+#
+# This is used by the link '-desc ' directive. 
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION	= DSO NLM to test the apr DSO loading layer
+
+#
+# This is used by the '-threadname' directive.  If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME	= mod_test
+
+#
+# This is used by the '-screenname' directive.  If left blank,
+# 'Apache for NetWare' Thread will be used.
+#
+NLM_SCREEN_NAME = DEFAULT
+
+#
+# If this is specified, it will override VERSION value in 
+# $(APR_WORK)/build/NWGNUenvironment.inc
+#
+NLM_VERSION	=
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE	= 
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM	=
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM	=
+
+#
+# If this is specified it will be used by the link '-check' directive
+#
+NLM_CHECK_SYM	=
+
+#
+# If this is 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 $(APR)/misc/netware/apache.xdc.  XDCData can 
+# be disabled by setting APACHE_UNIPROC in the environment
+#
+XDCDATA		= 
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+	$(OBJDIR)/mod_test.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_test.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 the default copyright.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+	@$(APR)/aprlib.imp \
+	@$(NOVI)/libc.imp \
+	$(EOLIST)
+ 
+#   
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+	print_hello \
+	count_reps \
+	$(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 $(APR_WORK)/build/NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(APRBUILD)/NWGNUtail.inc
+
diff --git a/test/NWGNUproc_child b/test/NWGNUproc_child
new file mode 100644
index 00000000000..423089c8ab6
--- /dev/null
+++ b/test/NWGNUproc_child
@@ -0,0 +1,252 @@
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# Get the 'head' of the build environment if necessary.  This includes default
+# targets and paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(APR_WORK)/build/NWGNUhead.inc
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS	+= \
+			$(APR)/include \
+			$(APR)/include/arch/netware \
+			$(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	= proc_child
+
+#
+# This is used by the link '-desc ' directive. 
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION	= child NLM to test the proc layer
+
+#
+# This is used by the '-threadname' directive.  If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME	= $(NLM_NAME)
+
+#
+# This is used by the '-screenname' directive.  If left blank,
+# 'Apache for NetWare' Thread will be used.
+#
+NLM_SCREEN_NAME = DEFAULT
+
+#
+# If this is specified, it will override VERSION value in 
+# $(APR_WORK)/build/NWGNUenvironment.inc
+#
+NLM_VERSION	=
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE	= 
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM	=
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM	=
+
+#
+# If this is specified it will be used by the link '-check' directive
+#
+NLM_CHECK_SYM	=
+
+#
+# If this is specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS	= AUTOUNLOAD, PSEUDOPREEMPTION, MULTIPLE
+ 
+#
+# If this is specified it will be linked in with the XDCData option in the def 
+# file instead of the default of $(APR)/misc/netware/apache.xdc.  XDCData can 
+# be disabled by setting APACHE_UNIPROC in the environment
+#
+XDCDATA		= 
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+	$(OBJDIR)/$(NLM_NAME).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)/$(NLM_NAME).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 the default copyright.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+	@$(APR)/aprlib.imp \
+	@$(NOVI)/libc.imp \
+	$(EOLIST)
+ 
+#   
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+	$(EOLIST)
+
+#   
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+	$(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the 
+# correct place.  (See $(APR_WORK)/build/NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(APRBUILD)/NWGNUtail.inc
+
diff --git a/test/NWGNUreadchild b/test/NWGNUreadchild
new file mode 100644
index 00000000000..451407f9452
--- /dev/null
+++ b/test/NWGNUreadchild
@@ -0,0 +1,252 @@
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# Get the 'head' of the build environment if necessary.  This includes default
+# targets and paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(APR_WORK)/build/NWGNUhead.inc
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS	+= \
+			$(APR)/include \
+			$(APR)/include/arch/netware \
+			$(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	= readchild
+
+#
+# This is used by the link '-desc ' directive. 
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION	= child NLM to test the pipe layer
+
+#
+# This is used by the '-threadname' directive.  If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME	= $(NLM_NAME)
+
+#
+# This is used by the '-screenname' directive.  If left blank,
+# 'Apache for NetWare' Thread will be used.
+#
+NLM_SCREEN_NAME = DEFAULT
+
+#
+# If this is specified, it will override VERSION value in 
+# $(APR_WORK)/build/NWGNUenvironment.inc
+#
+NLM_VERSION	=
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE	= 
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM	=
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM	=
+
+#
+# If this is specified it will be used by the link '-check' directive
+#
+NLM_CHECK_SYM	=
+
+#
+# If this is specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS	= AUTOUNLOAD, PSEUDOPREEMPTION, MULTIPLE
+ 
+#
+# If this is specified it will be linked in with the XDCData option in the def 
+# file instead of the default of $(APR)/misc/netware/apache.xdc.  XDCData can 
+# be disabled by setting APACHE_UNIPROC in the environment
+#
+XDCDATA		= 
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+	$(OBJDIR)/$(NLM_NAME).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)/$(NLM_NAME).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 the default copyright.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+	@$(APR)/aprlib.imp \
+	@$(NOVI)/libc.imp \
+	$(EOLIST)
+ 
+#   
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+	$(EOLIST)
+
+#   
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+	$(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the 
+# correct place.  (See $(APR_WORK)/build/NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(APRBUILD)/NWGNUtail.inc
+
diff --git a/test/NWGNUsockchild b/test/NWGNUsockchild
new file mode 100644
index 00000000000..5ed87ab218b
--- /dev/null
+++ b/test/NWGNUsockchild
@@ -0,0 +1,252 @@
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# Get the 'head' of the build environment if necessary.  This includes default
+# targets and paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(APR_WORK)/build/NWGNUhead.inc
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS	+= \
+			$(APR)/include \
+			$(APR)/include/arch/netware \
+			$(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	= sockchild
+
+#
+# This is used by the link '-desc ' directive. 
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION	= socket NLM to test sockets
+
+#
+# This is used by the '-threadname' directive.  If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME	= $(NLM_NAME)
+
+#
+# This is used by the '-screenname' directive.  If left blank,
+# 'Apache for NetWare' Thread will be used.
+#
+NLM_SCREEN_NAME = DEFAULT
+
+#
+# If this is specified, it will override VERSION value in 
+# $(APR_WORK)/build/NWGNUenvironment.inc
+#
+NLM_VERSION	=
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE	= 
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM	=
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM	=
+
+#
+# If this is specified it will be used by the link '-check' directive
+#
+NLM_CHECK_SYM	=
+
+#
+# If this is specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS	= AUTOUNLOAD, PSEUDOPREEMPTION, MULTIPLE
+ 
+#
+# If this is specified it will be linked in with the XDCData option in the def 
+# file instead of the default of $(APR)/misc/netware/apache.xdc.  XDCData can 
+# be disabled by setting APACHE_UNIPROC in the environment
+#
+XDCDATA		= 
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+	$(OBJDIR)/$(NLM_NAME).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)/$(NLM_NAME).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 the default copyright.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+	@$(APR)/aprlib.imp \
+	@$(NOVI)/libc.imp \
+	$(EOLIST)
+ 
+#   
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+	$(EOLIST)
+
+#   
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+	$(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the 
+# correct place.  (See $(APR_WORK)/build/NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(APRBUILD)/NWGNUtail.inc
+
diff --git a/test/NWGNUsockperf b/test/NWGNUsockperf
new file mode 100644
index 00000000000..db6486af4e6
--- /dev/null
+++ b/test/NWGNUsockperf
@@ -0,0 +1,253 @@
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# Get the 'head' of the build environment if necessary.  This includes default
+# targets and paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(APR_WORK)/build/NWGNUhead.inc
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS	+= \
+			$(APR)/include \
+			$(APR)/include/arch/netware \
+			$(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	= sockperf
+
+#
+# This is used by the link '-desc ' directive. 
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION	= socket NLM to test socket performance
+
+#
+# This is used by the '-threadname' directive.  If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME	= $(NLM_NAME)
+
+#
+# This is used by the '-screenname' directive.  If left blank,
+# 'Apache for NetWare' Thread will be used.
+#
+NLM_SCREEN_NAME = $(NLM_NAME)
+
+#
+# If this is specified, it will override VERSION value in 
+# $(APR_WORK)/build/NWGNUenvironment.inc
+#
+NLM_VERSION	=
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE	= 
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM	=
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM	=
+
+#
+# If this is specified it will be used by the link '-check' directive
+#
+NLM_CHECK_SYM	=
+
+#
+# If this is specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS	= AUTOUNLOAD, PSEUDOPREEMPTION, MULTIPLE
+ 
+#
+# If this is specified it will be linked in with the XDCData option in the def 
+# file instead of the default of $(APR)/misc/netware/apache.xdc.  XDCData can 
+# be disabled by setting APACHE_UNIPROC in the environment
+#
+XDCDATA		= 
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+	$(OBJDIR)/$(NLM_NAME).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)/$(NLM_NAME).o \
+	$(OBJDIR)/nw_misc.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 the default copyright.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+	@$(APR)/aprlib.imp \
+	@$(NOVI)/libc.imp \
+	$(EOLIST)
+ 
+#   
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+	$(EOLIST)
+
+#   
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+	$(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the 
+# correct place.  (See $(APR_WORK)/build/NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(APRBUILD)/NWGNUtail.inc
+
diff --git a/test/NWGNUtestatmc b/test/NWGNUtestatmc
new file mode 100644
index 00000000000..977fd8bfcc0
--- /dev/null
+++ b/test/NWGNUtestatmc
@@ -0,0 +1,255 @@
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# Get the 'head' of the build environment if necessary.  This includes default
+# targets and paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(APR_WORK)/build/NWGNUhead.inc
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS	+= \
+			$(APR)/include \
+			$(APR)/include/arch/netware \
+			$(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	= testatmc
+#
+# This is used by the link '-desc ' directive. 
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION	= NLM is to test the atomic functions
+
+#
+# This is used by the '-threadname' directive.  If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME	= $(NLM_NAME)
+
+#
+# This is used by the '-screenname' directive.  If left blank,
+# 'Apache for NetWare' Thread will be used.
+#
+NLM_SCREEN_NAME = $(NLM_NAME)
+
+#
+# If this is specified, it will override VERSION value in 
+# $(APR_WORK)/build/NWGNUenvironment.inc
+#
+NLM_VERSION	=
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE	=
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM	=
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM	=
+
+#
+# If this is specified it will be used by the link '-check' directive
+#
+NLM_CHECK_SYM	=
+
+#
+# If this is 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 $(APR)/misc/netware/apache.xdc.  XDCData can 
+# be disabled by setting APACHE_UNIPROC in the environment
+#
+XDCDATA		= 
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+	$(OBJDIR)/$(NLM_NAME).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)/testatomic.o \
+	$(OBJDIR)/nw_misc.o \
+	$(EOLIST)
+
+# Pending tests
+
+#
+# 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 the default copyright.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+	@$(APR)/aprlib.imp \
+	@$(NOVI)/libc.imp \
+	$(EOLIST)
+ 
+#   
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+	$(EOLIST)
+
+#   
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+	$(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the 
+# correct place.  (See $(APR_WORK)/build/NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(APRBUILD)/NWGNUtail.inc
+
diff --git a/test/NWGNUtryread b/test/NWGNUtryread
new file mode 100644
index 00000000000..f18d20d32a8
--- /dev/null
+++ b/test/NWGNUtryread
@@ -0,0 +1,253 @@
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# Get the 'head' of the build environment if necessary.  This includes default
+# targets and paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(APR_WORK)/build/NWGNUhead.inc
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS	+= \
+			$(APR)/include \
+			$(APR)/include/arch/netware \
+			$(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	= tryread
+
+#
+# This is used by the link '-desc ' directive. 
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION	= reader NLM to test flock
+
+#
+# This is used by the '-threadname' directive.  If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME	= $(NLM_NAME)
+
+#
+# This is used by the '-screenname' directive.  If left blank,
+# 'Apache for NetWare' Thread will be used.
+#
+NLM_SCREEN_NAME = DEFAULT
+
+#
+# If this is specified, it will override VERSION value in 
+# $(APR_WORK)/build/NWGNUenvironment.inc
+#
+NLM_VERSION	=
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE	= 
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM	=
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM	=
+
+#
+# If this is specified it will be used by the link '-check' directive
+#
+NLM_CHECK_SYM	=
+
+#
+# If this is specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS	= AUTOUNLOAD, PSEUDOPREEMPTION, MULTIPLE
+ 
+#
+# If this is specified it will be linked in with the XDCData option in the def 
+# file instead of the default of $(APR)/misc/netware/apache.xdc.  XDCData can 
+# be disabled by setting APACHE_UNIPROC in the environment
+#
+XDCDATA		= 
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+	$(OBJDIR)/$(NLM_NAME).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)/$(NLM_NAME).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 the default copyright.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+	@$(APR)/aprlib.imp \
+	@$(NOVI)/libc.imp \
+	$(EOLIST)
+ 
+#   
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+	$(EOLIST)
+
+#   
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+	$(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the 
+# correct place.  (See $(APR_WORK)/build/NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(APRBUILD)/NWGNUtail.inc
+
+
diff --git a/test/README b/test/README
new file mode 100644
index 00000000000..408a6a22ed8
--- /dev/null
+++ b/test/README
@@ -0,0 +1,332 @@
+Writing APR tests
+
+All APR tests should be executable in 2 ways, as an individual program, or
+as a part of the full test suite.  The full test suite is controlled with
+the testall program.  At the beginning of the testall.c file, there is an
+array of functions called tests.  The testall program loops through this 
+array calling each function.  Each function returns a CuSuite variable, which
+is then added to the SuiteList.  Once all Suites have been added, the SuiteList
+is executed, and the output is printed to the screen.  All functions in the
+array should follow the same basic format:
+
+The Full Suite
+--------------
+
+/* The driver function.  This must return a CuSuite variable, which will
+ * then be used to actually run the tests.  Essentially, all Suites are a
+ * collection of tests.  The driver will take each Suite, and put it in a
+ * SuiteList, which is a collection of Suites.
+ */
+CuSuite *testtime(void)
+{
+    /* The actual suite, this must be created for each test program.  Please
+     * give it a useful name, that will inform the user of the feature being
+     * tested.
+     */
+    CuSuite *suite = CuSuiteNew("Test Time");
+
+    /* Each function must be added to the suite.  Each function represents
+     * a single test.  It is possible to test multiple features in a single
+     * function, although no tests currently do that.
+     */
+    SUITE_ADD_TEST(suite, test_now);
+    SUITE_ADD_TEST(suite, test_gmtstr);
+    SUITE_ADD_TEST(suite, test_localstr);
+    SUITE_ADD_TEST(suite, test_exp_get_gmt);
+    SUITE_ADD_TEST(suite, test_exp_get_lt);
+    SUITE_ADD_TEST(suite, test_imp_gmt);
+    SUITE_ADD_TEST(suite, test_rfcstr);
+    SUITE_ADD_TEST(suite, test_ctime);
+    SUITE_ADD_TEST(suite, test_strftime);
+    SUITE_ADD_TEST(suite, test_strftimesmall);
+    SUITE_ADD_TEST(suite, test_exp_tz);
+    SUITE_ADD_TEST(suite, test_strftimeoffset);
+
+    /* You must return the suite so that the driver knows which suites to
+     * run.
+     */
+    return suite;
+}
+
+Building the full driver
+------------------------
+
+All you need to do to build the full driver is run:
+
+    make
+
+To run it, run:
+
+    ./testall
+
+Running individual tests
+------------------------
+
+It is not possible to build individual tests, however it is possible to
+run individual tests.  When running the test suite, specify the name of the
+tests that you want to run on the command line.  For example:
+
+	./testall teststr testrand
+
+Will run the Strings and Random generator tests.
+
+Reading the test suite output
+-----------------------------
+
+Once you run the test suite, you will get output like:
+
+All APR Tests:
+    Test Strings:       ....
+    Test Time:  ............
+
+16 tests run:  16 passed, 0 failed, 0 not implemented.
+
+Known test failures are documented in ../STATUS.
+
+There are a couple of things to look at with this.  First, if you look at the
+first function in this document, you should notice that the string passed to
+the CuSuiteNew function is in the output.  That is why the string should
+explain the feature you are testing.
+
+Second, this test passed completely.  This is obvious in two ways.  First, and
+most obvious, the summary line tells you that 16 tests were run and 16 tests
+passed.  However, the results can also be found in the lines above.  Every
+'.' in the output represents a passed test.
+
+If a test fails, the output will look like:
+
+All APR Tests:
+    Test Strings:       ....
+    Test Time:  ..F.........
+
+16 tests run:  15 passed, 1 failed, 0 not implemented.
+
+This is not very useful, because you don't know which test failed.  However,
+once you know that a test failed, you can run the suite again, with the
+-v option.  If you do this, you will get something like:
+
+All APR Tests:
+    Test Strings:       ....
+    Test Time:  ..F.........
+
+16 tests run:  15 passed, 1 failed, 0 not implemented.
+Failed tests:
+1) test_localstr: assert failed
+
+In this case, we know the test_localstr function failed, and there is an
+Assert in this that failed (I modified the test to fail for this document).
+Now, you can look at what that test does, and why it would have failed.
+
+There is one other possible output for the test suite (run with -v):
+
+All APR Tests:
+    Test Strings:       ....
+    Test Time:  ..N.........
+
+16 tests run:  15 passed, 0 failed, 1 not implemented.
+
+Not Implemented tests:
+
+Not Implemented tests:
+1) test_localstr: apr_time_exp_lt not implemented on this platform
+
+The 'N' means that a function has returned APR_ENOTIMPL.  This should be 
+treated as an error, and the function should be implemented as soon as
+possible.
+
+Adding New test Suites to the full driver
+-------------------------------------------
+
+To add a new Suite to the full driver, you must make a couple of modifications.
+
+1)  Edit test_apr.h, and add the prototype for the function.
+2)  Edit testall.c, and add the function and name to the tests array.
+3)  Edit Makefile.in, and add the .lo file to the testall target.
+
+Once those four things are done, your tests will automatically be added
+to the suite.
+
+Writting an ABTS unit test
+--------------------------
+
+The aim of this quick and dirty Howto is to give a short introduction
+to APR (Apache Portable Runtime) unit tests, and how to write
+one. During my Google's Summer of Code 2005 project, I discovered a
+small bug in the APR-Util's date parsing routines, and I needed to
+write a unit test for the fixed code. I decided to write this
+documentation because I did not find any. Thanks to Garrett Rooney for
+his help on writing the unit test !
+
+The APR and APR-Util libraries provide a platform independent API for
+software developers. They contain a lot of modules, including network
+programming, threads, string and memory management, etc. All these
+functions need to be heavily tested so that developers can be sure the
+library is reliable.
+
+The ABTS give APR developers the ability to build a complete test
+suite for the bunch of tests they wrote, which can then be ran under
+various platforms. In this Howto, I will try teach you how to write an
+ABTS unit test.
+
+As you may probably know, a unit test is a simple routine which tests
+a very specific feature of the tested software or library. To build a
+unit test, you need three different things :
+
+ * the to-be-tested function,
+ * the input data that will be given to the function,
+ * the expected output data.
+
+The principle of a unit test is very simple : for each entry in your
+set of input data, we pass it to our function, fetch what the function
+returned and compare it to the corresponding expected output data. Of
+course, the more edge cases you can test, the better your input data
+set is.
+
+The ABTS aims to quicken the write of unit test, and make them
+available to the whole test suite by providing a set of preprocessor
+macros. Adding a unit test to a test suite can be easily done by the
+following piece of code :
+
+abts_suite *testdaterfc(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite);
+    abts_run_test(suite, test_date_rfc, NULL);
+
+    return suite;
+}
+
+Where test_date_rfc is the name of the function performing the
+test. Writing such a function is, in the light of the explanation I
+just gave, pretty much easy too. As I said, we need to check every
+entry of our input data set. That gives us a loop. For each loop
+iteration, we call our to-be-tested function, grab its result and
+compare the returned value with the expected one.
+
+Test functions must have the following prototype :
+
+static void my_test_function(abts_case *tc, void *data);
+
+The comparison step is performed by the ABTS, thus giving the
+whole test suite the correct behavior if your unit test fails. Here
+comes a list of the available test methods :
+
+ABTS_INT_EQUAL(tc, a, b)
+ABTS_INT_NEQUAL(tc, a, b)
+ABTS_STR_EQUAL(tc, a, b)
+ABTS_STR_NEQUAL(tc, a, b, c)
+ABTS_PTR_NOTNULL(tc, b)
+ABTS_PTR_EQUAL(tc, a, b)
+ABTS_TRUE(tc, b)
+ABTS_FAIL(tc, b)
+ABTS_NOT_IMPL(tc, b)
+ABTS_ASSERT(tc, a, b)
+
+The first argument, tc is a reference to the unit test currently
+processed by the test suite (passed to your test function). The other
+parameters are the data to be tested. For example, the following line
+will never make your unit test fail :
+
+ABTS_INT_EQUAL(tc, 1, 1);
+
+See, it's easy ! Let's take a look at the complete example :
+testdaterfc. We want to test our date string parser. For this, we will
+use some chosen date strings (from mail headers for example) written
+in various formats but that should all be handled by our function, and
+their equivalents in correct RFC822 format.
+
+The function we want to test returns an apr_time_t}, which will be
+directly given as input to the apr_rfc822_date() function, thus
+producing the corresponding RFC822 date string. All we need to do
+after this is to call the correct test method from the ABTS macros !
+
+You can take a look at the apr-util/test/testdaterfc.c file for the
+complete source code of this unit test.
+
+Although this Howto is very small and mostly dedicated to the
+testdaterfc unit test, I hope you'll find it useful. Good luck !
+
+Writing tests for CuTest (no longer used)
+-----------------------------------------
+
+There are a couple of rules for writing good tests for the test suite.
+
+1)  All tests can determine for themselves if it passed or not.  This means
+that there is no reason for the person running the test suite to interpret
+the results of the tests.
+2)  Never use printf to add to the output of the test suite.  The suite
+library should be able to print all of the information required to debug
+a problem.
+3)  Functions should be tested with both positive and negative tests.  This
+means that you should test things that should both succeed and fail.
+4)  Just checking the return code does _NOT_ make a useful test.  You must
+check to determine that the test actually did what you expected it to do.
+
+An example test
+---------------
+
+Finally, we will look at a quick test:
+
+/* All tests are passed a CuTest variable.  This is how the suite determines
+ * if the test succeeded or failed.
+ */
+static void test_localstr(CuTest *tc)
+{
+    apr_status_t rv;
+    apr_time_exp_t xt;
+    time_t os_now;
+
+    rv = apr_time_exp_lt(&xt, now);
+    os_now = now / APR_USEC_PER_SEC;
+   
+    /* If the function can return APR_ENOTIMPL, then you should check for it.
+     * This allows platform implementors to know if they have to implement
+     * the function.
+     */
+    if (rv == APR_ENOTIMPL) {
+        CuNotImpl(tc, "apr_time_exp_lt");
+    }
+
+    /* It often helps to ensure that the return code was APR_SUCESS.  If it
+     * wasn't, then we know the test failed.
+     */
+    CuAssertTrue(tc, rv == APR_SUCCESS);
+
+    /* Now that we know APR thinks it worked properly, we need to check the
+     * output to ensure that we got what we expected.
+     */
+    CuAssertStrEquals(tc, "2002-08-14 12:05:36.186711 -25200 [257 Sat] DST",
+                      print_time(p, &xt));
+}
+
+Notice, the same test can fail for any of a number of reasons.  The first 
+test to fail ends the test.
+
+CuTest
+------
+
+CuTest is an open source test suite written by Asim Jalis.  It has been 
+released under the zlib/libpng license.  That license can be found in the
+CuTest.c and CuTest.h files.
+
+The version of CuTest that is included in the APR test suite has been modified
+from the original distribution in the following ways:
+
+1)  The original distribution does not have a -v flag, the details are always
+printed.
+2)  The NotImplemented result does not exist.
+3)  SuiteLists do not exist.  In the original distribution, you can add suites
+to suites, but it just adds the tests in the first suite to the list of tests
+in the original suite.  The output wasn't as detailed as I wanted, so I created
+SuiteLists.
+
+The first two modifications have been sent to the original author of CuTest,
+but they have not been integrated into the base distribution.  The SuiteList
+changes will be sent to the original author soon.
+
+The modified version of CuTest is not currently in any CVS or Subversion
+server.  In time, it will be hosted at rkbloom.net.
+
+There are currently no docs for how to write tests, but the teststr and 
+testtime programs should give an idea of how it is done.  In time, a document
+should be written to define how tests are written.
+
diff --git a/test/ab_apr.dsp b/test/ab_apr.dsp
deleted file mode 100644
index 522b6312ca4..00000000000
--- a/test/ab_apr.dsp
+++ /dev/null
@@ -1,90 +0,0 @@
-# Microsoft Developer Studio Project File - Name="ab_apr" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 5.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=ab_apr - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "ab_apr.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 "ab_apr.mak" CFG="ab_apr - Win32 Debug"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "ab_apr - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "ab_apr - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE 
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF  "$(CFG)" == "ab_apr - 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 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /W3 /GX /O2 /I "..\include" /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ..\Release\aprlib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"..\Release\ab_apr.exe"
-
-!ELSEIF  "$(CFG)" == "ab_apr - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "ab_apr__"
-# PROP BASE Intermediate_Dir "ab_apr__"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "ab_apr"
-# PROP Intermediate_Dir "ab_apr"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\include" /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
-# SUBTRACT CPP /Fr /YX /Yc /Yu
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 ..\Debug\aprlib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\Debug\ab_apr.exe" /pdbtype:sept
-
-!ENDIF 
-
-# Begin Target
-
-# Name "ab_apr - Win32 Release"
-# Name "ab_apr - Win32 Debug"
-# Begin Source File
-
-SOURCE=.\ab_apr.c
-# End Source File
-# End Target
-# End Project
diff --git a/test/abc.c b/test/abc.c
deleted file mode 100644
index eeb215e6ae7..00000000000
--- a/test/abc.c
+++ /dev/null
@@ -1,28 +0,0 @@
-#include <stdio.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include "apr_file_io.h"
-#include "apr_general.h"
-
-int main(int argc, char *argv[])
-{
-    ap_file_t *fd = NULL;
-    char ch;
-    int status = 0;
-    ap_pool_t *context;
-
-    ap_create_pool(&context, NULL); 
-
-    ap_open(&fd, argv[1], APR_READ, -1, context);
-    
-    while (!status) {
-        status = ap_getc(&ch, fd);
-        if (status == APR_EOF )
-            fprintf(stdout, "EOF, YEAH!!!!!!!!!\n");
-        else if (status == APR_SUCCESS)
-            fprintf(stdout, "%c", ch);
-        else
-            fprintf(stdout, " Big error, NOooooooooo!\n");
-    }
-    return 1; 
-}    
diff --git a/test/abts.c b/test/abts.c
new file mode 100644
index 00000000000..cab2e1aa094
--- /dev/null
+++ b/test/abts.c
@@ -0,0 +1,435 @@
+/* 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 "abts.h"
+#include "abts_tests.h"
+#include "testutil.h"
+
+#define ABTS_STAT_SIZE 6
+static char status[ABTS_STAT_SIZE] = {'|', '/', '-', '|', '\\', '-'};
+static int curr_char;
+static int verbose = 0;
+static int exclude = 0;
+static int quiet = 0;
+static int list_tests = 0;
+
+const char **testlist = NULL;
+
+static int find_test_name(const char *testname) {
+    int i;
+    for (i = 0; testlist[i] != NULL; i++) {
+        if (!strcmp(testlist[i], testname)) {
+            return 1;
+        }
+    }
+    return 0;
+}
+
+/* Determine if the test should be run at all */
+static int should_test_run(const char *testname) {
+    int found = 0;
+    if (list_tests == 1) {
+        return 0;
+    }
+    if (testlist == NULL) {
+        return 1;
+    }
+    found = find_test_name(testname);
+    if ((found && !exclude) || (!found && exclude)) {
+        return 1;
+    }
+    return 0;
+}
+
+static void reset_status(void)
+{
+    curr_char = 0;
+}
+
+static void update_status(void)
+{
+    if (!quiet) {
+        curr_char = (curr_char + 1) % ABTS_STAT_SIZE;
+        fprintf(stdout, "\b%c", status[curr_char]);
+        fflush(stdout);
+    }
+}
+
+static void end_suite(abts_suite *suite)
+{
+    if (suite != NULL) {
+        sub_suite *last = suite->tail;
+        if (!quiet) {
+            fprintf(stdout, "\b");
+            fflush(stdout);
+        }
+        if (last->failed == 0) {
+            fprintf(stdout, "SUCCESS\n");
+            fflush(stdout);
+        }
+        else {
+            fprintf(stdout, "FAILED %d of %d\n", last->failed, last->num_test);
+            fflush(stdout);
+        }
+    }
+}
+
+abts_suite *abts_add_suite(abts_suite *suite, const char *suite_name_full)
+{
+    sub_suite *subsuite;
+    char *p;
+    const char *suite_name;
+    curr_char = 0;
+    
+    /* Only end the suite if we actually ran it */
+    if (suite && suite->tail &&!suite->tail->not_run) {
+        end_suite(suite);
+    }
+
+    subsuite = malloc(sizeof(*subsuite));
+    subsuite->num_test = 0;
+    subsuite->failed = 0;
+    subsuite->next = NULL;
+    /* suite_name_full may be an absolute path depending on __FILE__ 
+     * expansion */
+    suite_name = strrchr(suite_name_full, '/');
+    if (!suite_name) {
+        suite_name = strrchr(suite_name_full, '\\');
+    }
+    if (suite_name) {
+        suite_name++;
+    } else {
+        suite_name = suite_name_full;
+    }
+    p = strrchr(suite_name, '.');
+    if (p) {
+        subsuite->name = memcpy(calloc(p - suite_name + 1, 1),
+                                suite_name, p - suite_name);
+    }
+    else {
+        subsuite->name = suite_name;
+    }
+
+    if (list_tests) {
+        fprintf(stdout, "%s\n", subsuite->name);
+    }
+    
+    subsuite->not_run = 0;
+
+    if (suite == NULL) {
+        suite = malloc(sizeof(*suite));
+        suite->head = subsuite;
+        suite->tail = subsuite;
+    }
+    else {
+        suite->tail->next = subsuite;
+        suite->tail = subsuite;
+    }
+
+    if (!should_test_run(subsuite->name)) {
+        subsuite->not_run = 1;
+        return suite;
+    }
+
+    reset_status();
+    fprintf(stdout, "%-20s:  ", subsuite->name);
+    update_status();
+    fflush(stdout);
+
+    return suite;
+}
+
+void abts_run_test(abts_suite *ts, test_func f, void *value)
+{
+    abts_case tc;
+    sub_suite *ss;
+
+    if (!should_test_run(ts->tail->name)) {
+        return;
+    }
+    ss = ts->tail;
+
+    tc.failed = 0;
+    tc.suite = ss;
+    
+    ss->num_test++;
+    update_status();
+
+    f(&tc, value);
+    
+    if (tc.failed) {
+        ss->failed++;
+    }
+}
+
+static int report(abts_suite *suite)
+{
+    int count = 0;
+    sub_suite *dptr;
+
+    if (suite && suite->tail &&!suite->tail->not_run) {
+        end_suite(suite);
+    }
+
+    for (dptr = suite->head; dptr; dptr = dptr->next) {
+        count += dptr->failed;
+    }
+
+    if (list_tests) {
+        return 0;
+    }
+
+    if (count == 0) {
+        printf("All tests passed.\n");
+        return 0;
+    }
+
+    dptr = suite->head;
+    fprintf(stdout, "%-15s\t\tTotal\tFail\tFailed %%\n", "Failed Tests");
+    fprintf(stdout, "===================================================\n");
+    while (dptr != NULL) {
+        if (dptr->failed != 0) {
+            float percent = ((float)dptr->failed / (float)dptr->num_test);
+            fprintf(stdout, "%-15s\t\t%5d\t%4d\t%6.2f%%\n", dptr->name, 
+                    dptr->num_test, dptr->failed, percent * 100);
+        }
+        dptr = dptr->next;
+    }
+    return 1;
+}
+
+void abts_log_message(const char *fmt, ...)
+{
+    va_list args;
+    update_status();
+
+    if (verbose) {
+        va_start(args, fmt);
+        vfprintf(stderr, fmt, args);
+        va_end(args);
+        fprintf(stderr, "\n");
+        fflush(stderr);
+    }
+}
+
+void abts_int_equal(abts_case *tc, const int expected, const int actual, int lineno)
+{
+    update_status();
+    if (tc->failed) return;
+
+    if (expected == actual) return;
+
+    tc->failed = TRUE;
+    if (verbose) {
+        fprintf(stderr, "Line %d: expected <%d>, but saw <%d>\n", lineno, expected, actual);
+        fflush(stderr);
+    }
+}
+
+void abts_int_nequal(abts_case *tc, const int expected, const int actual, int lineno)
+{
+    update_status();
+    if (tc->failed) return;
+
+    if (expected != actual) return;
+
+    tc->failed = TRUE;
+    if (verbose) {
+        fprintf(stderr, "Line %d: expected something other than <%d>, but saw <%d>\n",
+                lineno, expected, actual);
+        fflush(stderr);
+    }
+}
+
+void abts_size_equal(abts_case *tc, size_t expected, size_t actual, int lineno)
+{
+    update_status();
+    if (tc->failed) return;
+
+    if (expected == actual) return;
+
+    tc->failed = TRUE;
+    if (verbose) {
+        /* Note that the comparison is type-exact, reporting must be a best-fit */
+        fprintf(stderr, "Line %d: expected %lu, but saw %lu\n", lineno, 
+                (unsigned long)expected, (unsigned long)actual);
+        fflush(stderr);
+    }
+}
+
+void abts_str_equal(abts_case *tc, const char *expected, const char *actual, int lineno)
+{
+    update_status();
+    if (tc->failed) return;
+
+    if (!expected && !actual) return;
+    if (expected && actual)
+        if (!strcmp(expected, actual)) return;
+
+    tc->failed = TRUE;
+    if (verbose) {
+        fprintf(stderr, "Line %d: expected <%s>, but saw <%s>\n", lineno, expected, actual);
+        fflush(stderr);
+    }
+}
+
+void abts_str_nequal(abts_case *tc, const char *expected, const char *actual,
+                       size_t n, int lineno)
+{
+    update_status();
+    if (tc->failed) return;
+
+    if (!strncmp(expected, actual, n)) return;
+
+    tc->failed = TRUE;
+    if (verbose) {
+        fprintf(stderr, "Line %d: expected something other than <%s>, but saw <%s>\n",
+                lineno, expected, actual);
+        fflush(stderr);
+    }
+}
+
+void abts_ptr_notnull(abts_case *tc, const void *ptr, int lineno)
+{
+    update_status();
+    if (tc->failed) return;
+
+    if (ptr != NULL) return;
+
+    tc->failed = TRUE;
+    if (verbose) {
+        fprintf(stderr, "Line %d: expected non-NULL, but saw NULL\n", lineno);
+        fflush(stderr);
+    }
+}
+ 
+void abts_ptr_equal(abts_case *tc, const void *expected, const void *actual, int lineno)
+{
+    update_status();
+    if (tc->failed) return;
+
+    if (expected == actual) return;
+
+    tc->failed = TRUE;
+    if (verbose) {
+        fprintf(stderr, "Line %d: expected <%p>, but saw <%p>\n", lineno, expected, actual);
+        fflush(stderr);
+    }
+}
+
+void abts_fail(abts_case *tc, const char *message, int lineno)
+{
+    update_status();
+    if (tc->failed) return;
+
+    tc->failed = TRUE;
+    if (verbose) {
+        fprintf(stderr, "Line %d: %s\n", lineno, message);
+        fflush(stderr);
+    }
+}
+ 
+void abts_assert(abts_case *tc, const char *message, int condition, int lineno)
+{
+    update_status();
+    if (tc->failed) return;
+
+    if (condition) return;
+
+    tc->failed = TRUE;
+    if (verbose) {
+        fprintf(stderr, "Line %d: %s\n", lineno, message);
+        fflush(stderr);
+    }
+}
+
+void abts_true(abts_case *tc, int condition, int lineno)
+{
+    update_status();
+    if (tc->failed) return;
+
+    if (condition) return;
+
+    tc->failed = TRUE;
+    if (verbose) {
+        fprintf(stderr, "Line %d: Condition is false, but expected true\n", lineno);
+        fflush(stderr);
+    }
+}
+
+void abts_not_impl(abts_case *tc, const char *message, int lineno)
+{
+    update_status();
+
+    tc->suite->not_impl++;
+    if (verbose) {
+        fprintf(stderr, "Line %d: %s\n", lineno, message);
+        fflush(stderr);
+    }
+}
+
+int main(int argc, const char *const argv[]) {
+    int i;
+    int rv;
+    int list_provided = 0;
+    abts_suite *suite = NULL;
+   
+    initialize();
+
+    quiet = !isatty(STDOUT_FILENO);
+
+    for (i = 1; i < argc; i++) {
+        if (!strcmp(argv[i], "-v")) {
+            verbose = 1;
+            continue;
+        }
+        if (!strcmp(argv[i], "-x")) {
+            exclude = 1;
+            continue;
+        }
+        if (!strcmp(argv[i], "-l")) {
+            list_tests = 1;
+            continue;
+        }
+        if (!strcmp(argv[i], "-q")) {
+            quiet = 1;
+            continue;
+        }
+        if (argv[i][0] == '-') {
+            fprintf(stderr, "Invalid option: `%s'\n", argv[i]);
+            exit(1);
+        }
+        list_provided = 1;
+    }
+
+    if (list_provided) {
+        /* Waste a little space here, because it is easier than counting the
+         * number of tests listed.  Besides it is at most three char *.
+         */
+        testlist = calloc(argc + 1, sizeof(char *));
+        for (i = 1; i < argc; i++) {
+            testlist[i - 1] = argv[i];
+        }
+    }
+
+    for (i = 0; i < (sizeof(alltests) / sizeof(struct testlist *)); i++) {
+        suite = alltests[i].func(suite);
+    }
+
+    rv = report(suite);
+    return rv;
+}
+       
diff --git a/test/abts.h b/test/abts.h
new file mode 100644
index 00000000000..7385ca95728
--- /dev/null
+++ b/test/abts.h
@@ -0,0 +1,108 @@
+/* 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.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef WIN32
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+
+#ifndef ABTS_H
+#define ABTS_H
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE  1
+#endif
+
+struct sub_suite {
+    const char *name;
+    int num_test;
+    int failed;
+    int not_run;
+    int not_impl;
+    struct sub_suite *next;
+};
+typedef struct sub_suite sub_suite;
+
+struct abts_suite {
+    sub_suite *head;
+    sub_suite *tail;
+};
+typedef struct abts_suite abts_suite;
+
+struct abts_case {
+    int failed;
+    sub_suite *suite;
+};
+typedef struct abts_case abts_case;
+
+typedef void (*test_func)(abts_case *tc, void *data);
+
+#define ADD_SUITE(suite) abts_add_suite(suite, __FILE__);
+
+abts_suite *abts_add_suite(abts_suite *suite, const char *suite_name);
+void abts_run_test(abts_suite *ts, test_func f, void *value);
+void abts_log_message(const char *fmt, ...);
+
+void abts_int_equal(abts_case *tc, const int expected, const int actual, int lineno);
+void abts_int_nequal(abts_case *tc, const int expected, const int actual, int lineno);
+void abts_str_equal(abts_case *tc, const char *expected, const char *actual, int lineno);
+void abts_str_nequal(abts_case *tc, const char *expected, const char *actual,
+                       size_t n, int lineno);
+void abts_ptr_notnull(abts_case *tc, const void *ptr, int lineno);
+void abts_ptr_equal(abts_case *tc, const void *expected, const void *actual, int lineno);
+void abts_true(abts_case *tc, int condition, int lineno);
+void abts_fail(abts_case *tc, const char *message, int lineno);
+void abts_not_impl(abts_case *tc, const char *message, int lineno);
+void abts_assert(abts_case *tc, const char *message, int condition, int lineno);
+void abts_size_equal(abts_case *tc, size_t expected, size_t actual, int lineno);
+
+/* Convenience macros. Ryan hates these! */
+#define ABTS_INT_EQUAL(a, b, c)     abts_int_equal(a, b, c, __LINE__)
+#define ABTS_INT_NEQUAL(a, b, c)    abts_int_nequal(a, b, c, __LINE__)
+#define ABTS_STR_EQUAL(a, b, c)     abts_str_equal(a, b, c, __LINE__)
+#define ABTS_STR_NEQUAL(a, b, c, d) abts_str_nequal(a, b, c, d, __LINE__)
+#define ABTS_PTR_NOTNULL(a, b)      abts_ptr_notnull(a, b, __LINE__)
+#define ABTS_PTR_EQUAL(a, b, c)     abts_ptr_equal(a, b, c, __LINE__)
+#define ABTS_TRUE(a, b)             abts_true(a, b, __LINE__);
+#define ABTS_FAIL(a, b)             abts_fail(a, b, __LINE__);
+#define ABTS_NOT_IMPL(a, b)         abts_not_impl(a, b, __LINE__);
+#define ABTS_ASSERT(a, b, c)        abts_assert(a, b, c, __LINE__);
+
+#define ABTS_SIZE_EQUAL(a, b, c)    abts_size_equal(a, b, c, __LINE__)
+
+
+abts_suite *run_tests(abts_suite *suite);
+abts_suite *run_tests1(abts_suite *suite);
+
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/test/abts_tests.h b/test/abts_tests.h
new file mode 100644
index 00000000000..bfd83cf428d
--- /dev/null
+++ b/test/abts_tests.h
@@ -0,0 +1,96 @@
+/* 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 APR_TEST_INCLUDES
+#define APR_TEST_INCLUDES
+
+#include "abts.h"
+#include "testutil.h"
+
+const struct testlist {
+    abts_suite *(*func)(abts_suite *suite);
+} alltests[] = {
+    {testatomic},
+    {testdir},
+    {testdso},
+    {testdup},
+    {testenv},
+    {testescape},
+    {testfile},
+    {testfilecopy},
+    {testfileinfo},
+    {testflock},
+    {testfmt},
+    {testfnmatch},
+    {testgetopt},
+#if 0 /* not ready yet due to API issues */
+    {testglobalmutex},
+#endif
+    {testhash},
+    {testhooks},
+    {testipsub},
+    {testlock},
+    {testcond},
+    {testlfs},
+    {testmmap},
+    {testnames},
+    {testoc},
+    {testpath},
+    {testpipe},
+    {testpoll},
+    {testpool},
+    {testproc},
+    {testprocmutex},
+    {testrand},
+    {testsleep},
+    {testshm},
+    {testsock},
+    {testsockets},
+    {testsockopt},
+    {teststr},
+    {teststrnatcmp},
+    {testtable},
+    {testtemp},
+    {testthread},
+    {testtime},
+    {testud},
+    {testuser},
+    {testvsn},
+    {teststrmatch},
+    {testuri},
+    {testuuid},
+    {testbuckets},
+    {testpass},
+    {testbase64},
+    {testmd4},
+    {testmd5},
+    {testcrypto},
+    {testdbd},
+    {testdate},
+    {testmemcache},
+    {testredis},
+    {testxml},
+    {testxlate},
+    {testrmm},
+    {testdbm},
+    {testqueue},
+    {testreslist},
+    {testlfsabi},
+    {testskiplist},
+    {testsiphash}
+};
+
+#endif /* APR_TEST_INCLUDES */
diff --git a/test/client.c b/test/client.c
deleted file mode 100644
index cd78ce11142..00000000000
--- a/test/client.c
+++ /dev/null
@@ -1,195 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include <stdlib.h>
-#include "apr_network_io.h"
-#include "apr_errno.h"
-#include "apr_general.h"
-#include "errno.h"
-
-#define STRLEN 15
-
-int main(int argc, char *argv[])
-{
-    ap_pool_t *context;
-    ap_socket_t *sock;
-    ap_ssize_t length;
-    ap_status_t stat;
-    char datasend[STRLEN] = "Send data test";
-    char datarecv[STRLEN];
-    char *local_ipaddr, *remote_ipaddr;
-    char *dest = "127.0.0.1";
-    ap_uint32_t local_port, remote_port;
-    ap_interval_time_t read_timeout = -1;
-
-    setbuf(stdout, NULL);
-    if (argc > 1) {
-        dest = argv[1];
-    }
-
-    if (argc > 2) {
-        read_timeout = AP_USEC_PER_SEC * atoi(argv[2]);
-    }
-
-    fprintf(stdout, "Initializing.........");
-    if (ap_initialize() != APR_SUCCESS) {
-        fprintf(stderr, "Something went wrong\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK\n");
-    atexit(ap_terminate);
-
-    fprintf(stdout, "Creating context.......");
-    if (ap_create_pool(&context, NULL) != APR_SUCCESS) {
-        fprintf(stderr, "Something went wrong\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK\n");
-
-    fprintf(stdout, "\tClient:  Creating new socket.......");
-    if (ap_create_tcp_socket(&sock, context) != APR_SUCCESS) {
-        fprintf(stderr, "Couldn't create socket\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK\n");
-
-    if (read_timeout == -1) {
-        fprintf(stdout, "\tClient:  Setting socket option NONBLOCK.......");
-        if (ap_setsocketopt(sock, APR_SO_NONBLOCK, 1) != APR_SUCCESS) {
-            ap_close_socket(sock);
-            fprintf(stderr, "Couldn't set socket option\n");
-            exit(-1);
-        }
-        fprintf(stdout, "OK\n");
-    }
-
-    fprintf(stdout, "\tClient:  Setting port for socket.......");
-    if (ap_set_remote_port(sock, 8021) != APR_SUCCESS) {
-        ap_close_socket(sock);
-        fprintf(stderr, "Couldn't set the port correctly\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK\n");           
-
-    fprintf(stdout, "\tClient:  Connecting to socket.......");
-
-    do {
-      stat = ap_connect(sock, dest);
-    } while (stat == APR_ECONNREFUSED);
-
-    if (stat != APR_SUCCESS) {
-        ap_close_socket(sock);
-        fprintf(stderr, "Could not connect  %d\n", stat);
-        fflush(stderr);
-        exit(-1);
-    }
-    fprintf(stdout, "OK\n");
-
-    ap_get_remote_ipaddr(&remote_ipaddr, sock);
-    ap_get_remote_port(&remote_port, sock);
-    ap_get_local_ipaddr(&local_ipaddr, sock);
-    ap_get_local_port(&local_port, sock);
-    fprintf(stdout, "\tClient socket: %s:%u -> %s:%u\n", local_ipaddr, local_port, remote_ipaddr, remote_port);
-
-    fprintf(stdout, "\tClient:  Trying to send data over socket.......");
-    length = STRLEN;
-    if (ap_send(sock, datasend, &length) != APR_SUCCESS) {
-        ap_close_socket(sock);
-        fprintf(stderr, "Problem sending data\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK\n");
-   
-    if (read_timeout != -1) {
-        fprintf(stdout, "\tClient:  Setting read timeout.......");
-        stat = ap_setsocketopt(sock, APR_SO_TIMEOUT, read_timeout);
-        if (stat) {
-            fprintf(stderr, "Problem setting timeout: %d\n", stat);
-            exit(-1);
-        }
-        fprintf(stdout, "OK\n");
-    }
-
-    length = STRLEN; 
-    fprintf(stdout, "\tClient:  Trying to receive data over socket.......");
-
-    if ((stat = ap_recv(sock, datarecv, &length)) != APR_SUCCESS) {
-        ap_close_socket(sock);
-        fprintf(stderr, "Problem receiving data: %d\n", stat);
-        exit(-1);
-    }
-    if (strcmp(datarecv, "Recv data test")) {
-        ap_close_socket(sock);
-        fprintf(stderr, "I did not receive the correct data %s\n", datarecv);
-        exit(-1);
-    }
-    fprintf(stdout, "OK\n");
-
-    fprintf(stdout, "\tClient:  Shutting down socket.......");
-    if (ap_shutdown(sock, APR_SHUTDOWN_WRITE) != APR_SUCCESS) {
-        ap_close_socket(sock);
-        fprintf(stderr, "Could not shutdown socket\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK\n");
-
-    fprintf(stdout, "\tClient:  Closing down socket.......");
-    if (ap_close_socket(sock) != APR_SUCCESS) {
-        fprintf(stderr, "Could not shutdown socket\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK\n");
-
-    return 1;
-}
diff --git a/test/client.dsp b/test/client.dsp
deleted file mode 100644
index 2afd1150a16..00000000000
--- a/test/client.dsp
+++ /dev/null
@@ -1,90 +0,0 @@
-# Microsoft Developer Studio Project File - Name="client" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 5.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=client - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "client.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 "client.mak" CFG="client - Win32 Debug"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "client - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "client - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE 
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF  "$(CFG)" == "client - 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 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /W3 /GX /O2 /I "..\include" /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ..\Release\aprlib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"..\Release\client.exe"
-
-!ELSEIF  "$(CFG)" == "client - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "client__"
-# PROP BASE Intermediate_Dir "client__"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "client"
-# PROP Intermediate_Dir "client"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\include" /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "HAVE_STDIO_H" /FD /c
-# SUBTRACT CPP /YX /Yc /Yu
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 ..\Debug\aprlib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\Debug\client.exe" /pdbtype:sept
-
-!ENDIF 
-
-# Begin Target
-
-# Name "client - Win32 Release"
-# Name "client - Win32 Debug"
-# Begin Source File
-
-SOURCE=.\client.c
-# End Source File
-# End Target
-# End Project
diff --git a/test/data/billion-laughs.xml b/test/data/billion-laughs.xml
new file mode 100644
index 00000000000..3af89ae4dc7
--- /dev/null
+++ b/test/data/billion-laughs.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<!DOCTYPE billion [
+<!ELEMENT billion (#PCDATA)>
+<!ENTITY laugh0 "ha">
+<!ENTITY laugh1 "&laugh0;&laugh0;">
+<!ENTITY laugh2 "&laugh1;&laugh1;">
+<!ENTITY laugh3 "&laugh2;&laugh2;">
+<!ENTITY laugh4 "&laugh3;&laugh3;">
+<!ENTITY laugh5 "&laugh4;&laugh4;">
+<!ENTITY laugh6 "&laugh5;&laugh5;">
+<!ENTITY laugh7 "&laugh6;&laugh6;">
+<!ENTITY laugh8 "&laugh7;&laugh7;">
+<!ENTITY laugh9 "&laugh8;&laugh8;">
+<!ENTITY laugh10 "&laugh9;&laugh9;">
+<!ENTITY laugh11 "&laugh10;&laugh10;">
+<!ENTITY laugh12 "&laugh11;&laugh11;">
+<!ENTITY laugh13 "&laugh12;&laugh12;">
+<!ENTITY laugh14 "&laugh13;&laugh13;">
+<!ENTITY laugh15 "&laugh14;&laugh14;">
+<!ENTITY laugh16 "&laugh15;&laugh15;">
+<!ENTITY laugh17 "&laugh16;&laugh16;">
+<!ENTITY laugh18 "&laugh17;&laugh17;">
+<!ENTITY laugh19 "&laugh18;&laugh18;">
+<!ENTITY laugh20 "&laugh19;&laugh19;">
+<!ENTITY laugh21 "&laugh20;&laugh20;">
+<!ENTITY laugh22 "&laugh21;&laugh21;">
+<!ENTITY laugh23 "&laugh22;&laugh22;">
+<!ENTITY laugh24 "&laugh23;&laugh23;">
+<!ENTITY laugh25 "&laugh24;&laugh24;">
+<!ENTITY laugh26 "&laugh25;&laugh25;">
+<!ENTITY laugh27 "&laugh26;&laugh26;">
+<!ENTITY laugh28 "&laugh27;&laugh27;">
+<!ENTITY laugh29 "&laugh28;&laugh28;">
+<!ENTITY laugh30 "&laugh29;&laugh29;">
+]>
+<billion>&laugh30;</billion>
diff --git a/test/data/file_datafile.txt b/test/data/file_datafile.txt
new file mode 100644
index 00000000000..1651a3293f6
--- /dev/null
+++ b/test/data/file_datafile.txt
@@ -0,0 +1 @@
+This is the file data file.
\ No newline at end of file
diff --git a/test/data/mmap_datafile.txt b/test/data/mmap_datafile.txt
new file mode 100644
index 00000000000..50f47a609ed
--- /dev/null
+++ b/test/data/mmap_datafile.txt
@@ -0,0 +1 @@
+This is the MMAP data file.
diff --git a/test/dbd.c b/test/dbd.c
new file mode 100644
index 00000000000..dc2b1fb2401
--- /dev/null
+++ b/test/dbd.c
@@ -0,0 +1,409 @@
+/* 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 "apu.h"
+#include "apr_pools.h"
+#include "apr_dbd.h"
+
+#include <stdio.h>
+
+#define TEST(msg,func)					\
+    printf("======== %s ========\n", msg);		\
+    rv = func(pool, sql, driver);			\
+    if (rv != 0) {					\
+        printf("Error in %s: rc=%d\n\n", msg, rv);	\
+    }							\
+    else {						\
+        printf("%s test successful\n\n", msg);		\
+    }							\
+    fflush(stdout);
+
+static int create_table(apr_pool_t* pool, apr_dbd_t* handle,
+                        const apr_dbd_driver_t* driver)
+{
+    int rv = 0;
+    int nrows;
+    const char *statement = "CREATE TABLE apr_dbd_test ("
+        "col1 varchar(40) not null,"
+        "col2 varchar(40),"
+        "col3 integer)" ;
+    rv = apr_dbd_query(driver, handle, &nrows, statement);
+    return rv;
+}
+static int drop_table(apr_pool_t* pool, apr_dbd_t* handle,
+                      const apr_dbd_driver_t* driver)
+{
+    int rv = 0;
+    int nrows;
+    const char *statement = "DROP TABLE apr_dbd_test" ;
+    rv = apr_dbd_query(driver, handle, &nrows, statement);
+    return rv;
+}
+static int insert_rows(apr_pool_t* pool, apr_dbd_t* handle,
+                       const apr_dbd_driver_t* driver)
+{
+    int i;
+    int rv = 0;
+    int nrows;
+    int nerrors = 0;
+    const char *statement =
+        "INSERT into apr_dbd_test (col1) values ('foo');"
+        "INSERT into apr_dbd_test values ('wibble', 'other', 5);"
+        "INSERT into apr_dbd_test values ('wibble', 'nothing', 5);"
+        "INSERT into apr_dbd_test values ('qwerty', 'foo', 0);"
+        "INSERT into apr_dbd_test values ('asdfgh', 'bar', 1);"
+    ;
+    rv = apr_dbd_query(driver, handle, &nrows, statement);
+    if (rv) {
+        const char* stmt[] = {
+            "INSERT into apr_dbd_test (col1) values ('foo');",
+            "INSERT into apr_dbd_test values ('wibble', 'other', 5);",
+            "INSERT into apr_dbd_test values ('wibble', 'nothing', 5);",
+            "INSERT into apr_dbd_test values ('qwerty', 'foo', 0);",
+            "INSERT into apr_dbd_test values ('asdfgh', 'bar', 1);",
+            NULL
+        };
+        printf("Compound insert failed; trying statements one-by-one\n") ;
+        for (i=0; stmt[i] != NULL; ++i) {
+            statement = stmt[i];
+            rv = apr_dbd_query(driver, handle, &nrows, statement);
+            if (rv) {
+                nerrors++;
+            }
+        }
+        if (nerrors) {
+            printf("%d single inserts failed too.\n", nerrors) ;
+        }
+    }
+    return rv;
+}
+static int invalid_op(apr_pool_t* pool, apr_dbd_t* handle,
+                      const apr_dbd_driver_t* driver)
+{
+    int rv = 0;
+    int nrows;
+    const char *statement = "INSERT into apr_dbd_test1 (col2) values ('foo')" ;
+    rv = apr_dbd_query(driver, handle, &nrows, statement);
+    printf("invalid op returned %d (should be nonzero).  Error msg follows\n", rv);
+    printf("'%s'\n", apr_dbd_error(driver, handle, rv));
+    statement = "INSERT into apr_dbd_test (col1, col2) values ('bar', 'foo')" ;
+    rv = apr_dbd_query(driver, handle, &nrows, statement);
+    printf("valid op returned %d (should be zero; error shouldn't affect subsequent ops)\n", rv);
+    return rv;
+}
+static int select_sequential(apr_pool_t* pool, apr_dbd_t* handle,
+                             const apr_dbd_driver_t* driver)
+{
+    int rv = 0;
+    int i = 0;
+    int n;
+    const char* entry;
+    const char* statement = "SELECT * FROM apr_dbd_test ORDER BY col1, col2";
+    apr_dbd_results_t *res = NULL;
+    apr_dbd_row_t *row = NULL;
+    rv = apr_dbd_select(driver,pool,handle,&res,statement,0);
+    if (rv) {
+        printf("Select failed: %s", apr_dbd_error(driver, handle, rv));
+        return rv;
+    }
+    for (rv = apr_dbd_get_row(driver, pool, res, &row, -1);
+         rv == 0;
+         rv = apr_dbd_get_row(driver, pool, res, &row, -1)) {
+        printf("ROW %d:	", ++i) ;
+        for (n = 0; n < apr_dbd_num_cols(driver, res); ++n) {
+            entry = apr_dbd_get_entry(driver, row, n);
+            if (entry == NULL) {
+                printf("(null)	") ;
+            }
+            else {
+                printf("%s	", entry);
+            }
+        }
+	fputs("\n", stdout);
+    }
+    return (rv == -1) ? 0 : 1;
+}
+static int select_random(apr_pool_t* pool, apr_dbd_t* handle,
+                         const apr_dbd_driver_t* driver)
+{
+    int rv = 0;
+    int n;
+    const char* entry;
+    const char* statement = "SELECT * FROM apr_dbd_test ORDER BY col1, col2";
+    apr_dbd_results_t *res = NULL;
+    apr_dbd_row_t *row = NULL;
+    rv = apr_dbd_select(driver,pool,handle,&res,statement,1);
+    if (rv) {
+        printf("Select failed: %s", apr_dbd_error(driver, handle, rv));
+        return rv;
+    }
+    rv = apr_dbd_get_row(driver, pool, res, &row, 5) ;
+    if (rv) {
+        printf("get_row failed: %s", apr_dbd_error(driver, handle, rv));
+        return rv;
+    }
+    printf("ROW 5:	");
+    for (n = 0; n < apr_dbd_num_cols(driver, res); ++n) {
+        entry = apr_dbd_get_entry(driver, row, n);
+        if (entry == NULL) {
+            printf("(null)	") ;
+        }
+        else {
+            printf("%s	", entry);
+        }
+    }
+    fputs("\n", stdout);
+    rv = apr_dbd_get_row(driver, pool, res, &row, 1) ;
+    if (rv) {
+        printf("get_row failed: %s", apr_dbd_error(driver, handle, rv));
+        return rv;
+    }
+    printf("ROW 1:	");
+    for (n = 0; n < apr_dbd_num_cols(driver, res); ++n) {
+        entry = apr_dbd_get_entry(driver, row, n);
+        if (entry == NULL) {
+            printf("(null)	") ;
+        }
+        else {
+            printf("%s	", entry);
+        }
+    }
+    fputs("\n", stdout);
+    rv = apr_dbd_get_row(driver, pool, res, &row, 11) ;
+    if (rv != -1) {
+        printf("Oops!  get_row out of range but thinks it succeeded!\n%s\n",
+                apr_dbd_error(driver, handle, rv));
+        return -1;
+    }
+    rv = 0;
+
+    return rv;
+}
+static int test_transactions(apr_pool_t* pool, apr_dbd_t* handle,
+                             const apr_dbd_driver_t* driver)
+{
+    int rv = 0;
+    int nrows;
+    apr_dbd_transaction_t *trans = NULL;
+    const char* statement;
+
+    /* trans 1 - error out early */
+    printf("Transaction 1\n");
+    rv = apr_dbd_transaction_start(driver, pool, handle, &trans);
+    if (rv) {
+        printf("Start transaction failed!\n%s\n",
+               apr_dbd_error(driver, handle, rv));
+        return rv;
+    }
+    statement = "UPDATE apr_dbd_test SET col2 = 'failed'";
+    rv = apr_dbd_query(driver, handle, &nrows, statement);
+    if (rv) {
+        printf("Update failed: '%s'\n", apr_dbd_error(driver, handle, rv));
+        apr_dbd_transaction_end(driver, pool, trans);
+        return rv;
+    }
+    printf("%d rows updated\n", nrows);
+
+    statement = "INSERT INTO apr_dbd_test1 (col3) values (3)";
+    rv = apr_dbd_query(driver, handle, &nrows, statement);
+    if (!rv) {
+        printf("Oops, invalid op succeeded but shouldn't!\n");
+    }
+    statement = "INSERT INTO apr_dbd_test values ('zzz', 'aaa', 3)";
+    rv = apr_dbd_query(driver, handle, &nrows, statement);
+    printf("Valid insert returned %d.  Should be nonzero (fail) because transaction is bad\n", rv) ;
+
+    rv = apr_dbd_transaction_end(driver, pool, trans);
+    if (rv) {
+        printf("End transaction failed!\n%s\n",
+               apr_dbd_error(driver, handle, rv));
+        return rv;
+    }
+    printf("Transaction ended (should be rollback) - viewing table\n"
+           "A column of \"failed\" indicates transaction failed (no rollback)\n");
+    select_sequential(pool, handle, driver);
+
+    /* trans 2 - complete successfully */
+    printf("Transaction 2\n");
+    rv = apr_dbd_transaction_start(driver, pool, handle, &trans);
+    if (rv) {
+        printf("Start transaction failed!\n%s\n",
+               apr_dbd_error(driver, handle, rv));
+        return rv;
+    }
+    statement = "UPDATE apr_dbd_test SET col2 = 'success'";
+    rv = apr_dbd_query(driver, handle, &nrows, statement);
+    if (rv) {
+        printf("Update failed: '%s'\n", apr_dbd_error(driver, handle, rv));
+        apr_dbd_transaction_end(driver, pool, trans);
+        return rv;
+    }
+    printf("%d rows updated\n", nrows);
+    statement = "INSERT INTO apr_dbd_test values ('aaa', 'zzz', 3)";
+    rv = apr_dbd_query(driver, handle, &nrows, statement);
+    printf("Valid insert returned %d.  Should be zero (OK)\n", rv) ;
+    rv = apr_dbd_transaction_end(driver, pool, trans);
+    if (rv) {
+        printf("End transaction failed!\n%s\n",
+               apr_dbd_error(driver, handle, rv));
+        return rv;
+    }
+    printf("Transaction ended (should be commit) - viewing table\n");
+    select_sequential(pool, handle, driver);
+    return rv;
+}
+static int test_pselect(apr_pool_t* pool, apr_dbd_t* handle,
+                        const apr_dbd_driver_t* driver)
+{
+    int rv = 0;
+    int i, n;
+    const char *query =
+        "SELECT * FROM apr_dbd_test WHERE col3 <= %s or col1 = 'bar'" ;
+    const char *label = "lowvalues";
+    apr_dbd_prepared_t *statement = NULL;
+    apr_dbd_results_t *res = NULL;
+    apr_dbd_row_t *row = NULL;
+    const char *entry = NULL;
+
+    rv = apr_dbd_prepare(driver, pool, handle, query, label, &statement);
+    if (rv) {
+        printf("Prepare statement failed!\n%s\n",
+               apr_dbd_error(driver, handle, rv));
+        return rv;
+    }
+    rv = apr_dbd_pvselect(driver, pool, handle, &res, statement, 0, "3", NULL);
+    if (rv) {
+        printf("Exec of prepared statement failed!\n%s\n",
+               apr_dbd_error(driver, handle, rv));
+        return rv;
+    }
+    i = 0;
+    printf("Selecting rows where col3 <= 3 and bar row where it's unset.\nShould show four rows.\n");
+    for (rv = apr_dbd_get_row(driver, pool, res, &row, -1);
+         rv == 0;
+         rv = apr_dbd_get_row(driver, pool, res, &row, -1)) {
+        printf("ROW %d:	", ++i) ;
+        for (n = 0; n < apr_dbd_num_cols(driver, res); ++n) {
+            entry = apr_dbd_get_entry(driver, row, n);
+            if (entry == NULL) {
+                printf("(null)	") ;
+            }
+            else {
+                printf("%s	", entry);
+            }
+        }
+	fputs("\n", stdout);
+    }
+    return (rv == -1) ? 0 : 1;
+}
+static int test_pquery(apr_pool_t* pool, apr_dbd_t* handle,
+                       const apr_dbd_driver_t* driver)
+{
+    int rv = 0;
+    const char *query = "INSERT INTO apr_dbd_test VALUES (%s, %s, %d)";
+    apr_dbd_prepared_t *statement = NULL;
+    const char *label = "testpquery";
+    int nrows;
+    apr_dbd_transaction_t *trans =0;
+
+    rv = apr_dbd_prepare(driver, pool, handle, query, label, &statement);
+    /* rv = apr_dbd_prepare(driver, pool, handle, query, NULL, &statement); */
+    if (rv) {
+        printf("Prepare statement failed!\n%s\n",
+               apr_dbd_error(driver, handle, rv));
+        return rv;
+    }
+    apr_dbd_transaction_start(driver, pool, handle, &trans);
+    rv = apr_dbd_pvquery(driver, pool, handle, &nrows, statement,
+                         "prepared", "insert", "2", NULL);
+    apr_dbd_transaction_end(driver, pool, trans);
+    if (rv) {
+        printf("Exec of prepared statement failed!\n%s\n",
+               apr_dbd_error(driver, handle, rv));
+        return rv;
+    }
+    printf("Showing table (should now contain row \"prepared insert 2\")\n");
+    select_sequential(pool, handle, driver);
+    return rv;
+}
+int main(int argc, char** argv)
+{
+    const char *name;
+    const char *params;
+    apr_pool_t *pool = NULL;
+    apr_dbd_t *sql = NULL;
+    const apr_dbd_driver_t *driver = NULL;
+    char errbuf[256];
+    int rv;
+
+    apr_initialize();
+    apr_pool_create(&pool, NULL);
+
+    if (argc >= 2 && argc <= 3) {
+        name = argv[1];
+        params = ( argc == 3 ) ? argv[2] : "";
+        apr_dbd_init(pool);
+        setbuf(stdout,NULL);
+        rv = apr_dbd_get_driver(pool, name, &driver);
+        switch (rv) {
+        case APR_SUCCESS:
+           printf("Loaded %s driver OK.\n", name);
+           break;
+        case APR_EDSOOPEN:
+           printf("Failed to load driver file apr_dbd_%s.so\n", name);
+           goto finish;
+        case APR_ESYMNOTFOUND:
+           printf("Failed to load driver apr_dbd_%s_driver.\n", name);
+           goto finish;
+        case APR_ENOTIMPL:
+           printf("No driver available for %s.\n", name);
+           goto finish;
+        default:        /* it's a bug if none of the above happen */
+           printf("Internal error loading %s.\n", name);
+           printf("(%d)%s\n", rv, apr_strerror(rv, errbuf, sizeof errbuf));
+           goto finish;
+        }
+        rv = apr_dbd_open(driver, pool, params, &sql);
+        switch (rv) {
+        case APR_SUCCESS:
+           printf("Opened %s[%s] OK\n", name, params);
+           break;
+        case APR_EGENERAL:
+           printf("Failed to open %s[%s]\n", name, params);
+           goto finish;
+        default:        /* it's a bug if none of the above happen */
+           printf("Internal error opening %s[%s]\n", name, params);
+           goto finish;
+        }
+        TEST("create table", create_table);
+        TEST("insert rows", insert_rows);
+        TEST("invalid op", invalid_op);
+        TEST("select random", select_random);
+        TEST("select sequential", select_sequential);
+        TEST("transactions", test_transactions);
+        TEST("prepared select", test_pselect);
+        TEST("prepared query", test_pquery);
+        TEST("drop table", drop_table);
+        apr_dbd_close(driver, sql);
+    }
+    else {
+        fprintf(stderr, "Usage: %s driver-name [params]\n", argv[0]);
+    }
+finish:
+    apr_pool_destroy(pool);
+    apr_terminate();
+    return 0;
+}
diff --git a/test/echod.c b/test/echod.c
new file mode 100644
index 00000000000..052e47d8796
--- /dev/null
+++ b/test/echod.c
@@ -0,0 +1,134 @@
+/* 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.
+ */
+
+/* Simple echo daemon, designed to be used for network throughput
+ * benchmarks. The aim is to allow us to monitor changes in performance
+ * of APR networking code, nothing more.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>  /* for atexit() */
+
+#include "apr.h"
+#include "apr_network_io.h"
+#include "apr_strings.h"
+
+#define BUF_SIZE 4096
+
+static void reportError(const char *msg, apr_status_t rv, 
+                        apr_pool_t *pool)
+{
+    fprintf(stderr, "%s\nError: %d\n'%s'\n", msg, rv,
+            apr_psprintf(pool, "%pm", &rv));
+}
+
+static apr_status_t talkTalk(apr_socket_t *socket, apr_pool_t *parent)
+{
+    apr_pool_t *pool;
+    apr_size_t len;
+    char *buf;
+    apr_status_t rv;
+
+    if (apr_pool_create(&pool, parent) != APR_SUCCESS)
+        return APR_ENOPOOL;
+
+
+    buf = apr_palloc(pool, BUF_SIZE);
+    if (!buf)
+        return ENOMEM;
+
+    do {
+        len = BUF_SIZE;
+        rv = apr_socket_recv(socket, buf, &len);
+        if (APR_STATUS_IS_EOF(rv) || len == 0 || rv != APR_SUCCESS)
+            break;
+        rv = apr_socket_send(socket, buf, &len);
+        if (len == 0 || rv != APR_SUCCESS)
+            break;
+    } while (rv == APR_SUCCESS);
+
+    apr_pool_clear(pool);
+    return APR_SUCCESS;
+}
+
+static apr_status_t glassToWall(apr_port_t port, apr_pool_t *parent)
+{
+    apr_sockaddr_t *sockAddr;
+    apr_socket_t *listener, *accepted;
+    apr_status_t rv;
+
+    rv = apr_socket_create(&listener, APR_INET, SOCK_STREAM, APR_PROTO_TCP,
+                           parent);
+    if (rv != APR_SUCCESS) {
+        reportError("Unable to create socket", rv, parent);
+        return rv;
+    }
+
+    rv = apr_sockaddr_info_get(&sockAddr, "127.0.0.1", APR_UNSPEC,
+                               port, 0, parent);
+    if (rv != APR_SUCCESS) {
+        reportError("Unable to get socket info", rv, parent);
+        apr_socket_close(listener);
+        return rv;
+    }
+
+    if ((rv = apr_socket_bind(listener, sockAddr)) != APR_SUCCESS ||
+        (rv = apr_socket_listen(listener, 5)) != APR_SUCCESS) {
+        reportError("Unable to bind or listen to socket", rv, parent);
+        apr_socket_close(listener);
+        return rv;
+    }
+
+    for (;;) {
+        rv = apr_socket_accept(&accepted, listener, parent);
+        if (rv != APR_SUCCESS) {
+            reportError("Error accepting on socket", rv, parent);
+            break;
+        }
+        printf("\tAnswering connection\n");
+        rv = talkTalk(accepted, parent);
+        apr_socket_close(accepted);
+        printf("\tConnection closed\n");
+        if (rv != APR_SUCCESS)
+            break;
+    }
+
+    apr_socket_close(listener);
+    return APR_SUCCESS;
+}
+
+int main(int argc, char **argv)
+{
+    apr_pool_t *pool;
+    apr_port_t theport = 4747;
+
+    printf("APR Test Application: echod\n");
+
+    apr_initialize();
+    atexit(apr_terminate);
+
+    apr_pool_create(&pool, NULL);
+
+    if (argc >= 2) {
+        printf("argc = %d, port = '%s'\n", argc, argv[1]);
+        theport = atoi(argv[1]);
+    }
+
+    fprintf(stdout, "Starting to listen on port %d\n", theport);
+    glassToWall(theport, pool);
+
+    return 0;
+}
diff --git a/test/globalmutexchild.c b/test/globalmutexchild.c
new file mode 100644
index 00000000000..4b8737b02bd
--- /dev/null
+++ b/test/globalmutexchild.c
@@ -0,0 +1,64 @@
+/* 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 "testglobalmutex.h"
+#include "apr_pools.h"
+#include "apr_file_io.h"
+#include "apr_general.h"
+#include "apr_global_mutex.h"
+#include "apr_strings.h"
+#include "apr.h"
+
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+
+int main(int argc, const char * const argv[])
+{
+    apr_pool_t *p;
+    int i = 0;
+    apr_lockmech_e mech;
+    apr_global_mutex_t *global_lock;
+    apr_status_t rv;
+
+    apr_initialize();
+    atexit(apr_terminate);
+    
+    apr_pool_create(&p, NULL);
+    if (argc >= 2) {
+        mech = (apr_lockmech_e)apr_strtoi64(argv[1], NULL, 0);
+    }
+    else {
+        mech = APR_LOCK_DEFAULT;
+    }
+    rv = apr_global_mutex_create(&global_lock, LOCKNAME, mech, p);
+    if (rv != APR_SUCCESS) {
+        exit(-rv);
+    }
+    apr_global_mutex_child_init(&global_lock, LOCKNAME, p);
+    
+    while (1) {
+        apr_global_mutex_lock(global_lock);
+        if (i == MAX_ITER) {
+            apr_global_mutex_unlock(global_lock);
+            exit(i);
+        }
+        i++;
+        apr_global_mutex_unlock(global_lock);
+    }
+    exit(0);
+}
diff --git a/test/htdigest.dsp b/test/htdigest.dsp
deleted file mode 100644
index a0f8f0bf363..00000000000
--- a/test/htdigest.dsp
+++ /dev/null
@@ -1,90 +0,0 @@
-# Microsoft Developer Studio Project File - Name="htdigest" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 5.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=htdigest - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "htdigest.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 "htdigest.mak" CFG="htdigest - Win32 Debug"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "htdigest - Win32 Release" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE "htdigest - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE 
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF  "$(CFG)" == "htdigest - 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 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /W3 /GX /O2 /I "..\include" /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ..\lib\Debug\lib.lib ..\misc\win32\Debug\misc.lib ..\threadproc\win32\Debug\threadproc.lib ..\file_io\win32\Debug\file_io.lib ..\time\win32\Debug\time.lib ..\locks\win32\Debug\locks.lib ..\network_io\win32\Debug\network_io.lib ..\signal\win32\Debug\signal.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-
-!ELSEIF  "$(CFG)" == "htdigest - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "htdigest"
-# PROP BASE Intermediate_Dir "htdigest"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "htdigest"
-# PROP Intermediate_Dir "htdigest"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\include" /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 ..\lib\Debug\lib.lib ..\misc\win32\Debug\misc.lib ..\threadproc\win32\Debug\threadproc.lib ..\file_io\win32\Debug\file_io.lib ..\time\win32\Debug\time.lib ..\locks\win32\Debug\locks.lib ..\network_io\win32\Debug\network_io.lib ..\signal\win32\Debug\signal.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-
-!ENDIF 
-
-# Begin Target
-
-# Name "htdigest - Win32 Release"
-# Name "htdigest - Win32 Debug"
-# Begin Source File
-
-SOURCE=.\htdigest.c
-# End Source File
-# End Target
-# End Project
diff --git a/test/internal/Makefile.in b/test/internal/Makefile.in
new file mode 100644
index 00000000000..b1f6c6a6c43
--- /dev/null
+++ b/test/internal/Makefile.in
@@ -0,0 +1,37 @@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+NONPORTABLE = \
+	testregex@EXEEXT@
+
+PROGRAMS = \
+
+TARGETS = $(PROGRAMS) $(NONPORTABLE)
+
+# bring in rules.mk for standard functionality
+@INCLUDE_RULES@
+
+LOCAL_LIBS=../../lib@APR_LIBNAME@.la
+
+CLEAN_TARGETS = testregex@EXEEXT@
+
+INCDIR=../../include
+INCLUDES=-I$(INCDIR)
+
+CFLAGS=$(MY_CFLAGS)
+
+all: $(PROGRAMS) $(NONPORTABLE)
+
+check: $(PROGRAMS) $(NONPORTABLE)
+	for prog in $(PROGRAMS) $(NONPORTABLE); do \
+		./$$prog; \
+		if test $$i = 255; then \
+			echo "$$prog failed"; \
+			break; \
+		fi \
+	done
+
+testregex@EXEEXT@: testregex.lo $(LOCAL_LIBS)
+	$(LINK) testregex.lo $(LOCAL_LIBS) $(ALL_LIBS)
+
+# DO NOT REMOVE
diff --git a/test/internal/Makefile.win b/test/internal/Makefile.win
new file mode 100644
index 00000000000..a881f078108
--- /dev/null
+++ b/test/internal/Makefile.win
@@ -0,0 +1,109 @@
+# PROGRAMS includes all test programs built on this platform.
+# STDTEST_PORTABLE
+#   test programs invoked via standard user interface, run on all platforms
+# STDTEST_NONPORTABLE
+#   test programs invoked via standard user interface, not portable
+# OTHER_PROGRAMS
+#   programs such as sendfile, that have to be invoked in a special sequence
+#   or with special parameters
+
+!IFNDEF MODEL
+MODEL=dynamic
+!ENDIF
+
+INCDIR=../../include
+
+!IFNDEF OUTDIR
+!IF "$(MODEL)" == "static"
+OUTDIR=LibR
+!ELSE
+OUTDIR=Release
+!ENDIF
+
+!IF [$(COMSPEC) /c cl /nologo /? | find "x64" >NUL ] == 0
+OUTDIR=x64\$(OUTDIR)
+!ENDIF
+!ENDIF
+
+!IF !EXIST("$(OUTDIR)\.")
+!IF ([$(COMSPEC) /C mkdir $(OUTDIR)] == 0)
+!ENDIF
+!ENDIF
+
+!IFNDEF INTDIR
+INTDIR=$(OUTDIR)
+!ELSE
+!IF !EXIST("$(INTDIR)\.")
+!IF ([$(COMSPEC) /C mkdir $(INTDIR)] == 0)
+!ENDIF
+!ENDIF
+!ENDIF
+
+!MESSAGE Building tests into $(OUTDIR) for $(MODEL)
+
+NONPORTABLE = \
+	$(OUTDIR)\testucs.exe
+
+CLEAN_BUILDDIRS = Release Debug 9x x64
+
+PROGRAMS = 
+
+TARGETS = $(PROGRAMS) $(NONPORTABLE)
+
+# bring in rules.mk for standard functionality
+ALL: $(TARGETS)
+
+CL = cl.exe
+LD = link.exe 
+
+!IF "$(MODEL)" == "static"
+LOCAL_LIB= ..\..\$(OUTDIR)\apr-1.lib 
+STATIC_CFLAGS = /D APR_DECLARE_STATIC
+!ELSE
+LOCAL_LIB= ..\..\$(OUTDIR)\libapr-1.lib 
+STATIC_CFLAGS = 
+!ENDIF
+
+!IFDEF _DEBUG
+DEBUG_CFLAGS = /MDd
+!ELSE
+DEBUG_CFLAGS = /MD 
+!ENDIF
+
+INCLUDES=/I "$(INCDIR)"
+
+CFLAGS = /nologo /c /W3 /Gm /EHsc /Zi /Od $(INCLUDES) \
+	 $(STATIC_CFLAGS) $(DEBUG_CFLAGS) /D "BINPATH=$(OUTDIR:\=/)" \
+	 /D _DEBUG /D WIN32 /Fo"$(INTDIR)/" /FD
+
+LD_LIBS = kernel32.lib advapi32.lib ws2_32.lib wsock32.lib \
+	  ole32.lib shell32.lib rpcrt4.lib
+
+LDFLAGS = /nologo /debug /subsystem:console /incremental:no 
+SHLDFLAGS = /nologo /dll /debug /subsystem:windows /incremental:no
+
+.c{$(INTDIR)}.obj:
+	$(CL) $(CFLAGS) -c $< -Fd$(INTDIR)\ $(INCLUDES) 
+
+$(OUTDIR)\testucs.exe: $(INTDIR)\testucs.obj $(LOCAL_LIB) 
+	$(LD) $(LDFLAGS) /out:"$@" $** $(LD_LIBS)
+	@if exist "$@.manifest" \
+	    mt.exe -manifest "$@.manifest" -outputresource:$@;1
+
+
+clean:
+	@if EXIST $(INTDIR)\. rmdir /s /q $(INTDIR)
+	@if EXIST $(OUTDIR)\. rmdir /s /q $(OUTDIR)
+
+cleanall:
+	@for %d in ($(CLEAN_BUILDDIRS)) do @if EXIST %d\. rmdir /s /q %d
+
+
+PATH=$(OUTDIR);..\..\$(OUTDIR);$(PATH)
+
+check: $(NONPORTABLE)
+	@for %p in ($(NONPORTABLE)) do @( \
+	    echo Testing %p && %p || echo %p failed \
+	)
+
+# DO NOT REMOVE
diff --git a/test/internal/testregex.c b/test/internal/testregex.c
new file mode 100644
index 00000000000..20dcfdebe7b
--- /dev/null
+++ b/test/internal/testregex.c
@@ -0,0 +1,91 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "apr_strings.h"
+#include "apr_pools.h"
+#include "apr_general.h"
+#include "apr_hash.h"
+#include "apr_lib.h"
+#include "apr_time.h"
+#include <regex.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int main( int argc, char** argv) {
+    apr_pool_t *context;
+    regex_t regex;
+    int rc;
+    int i;
+    int iters;
+    apr_time_t now;
+    apr_time_t end;
+    apr_hash_t *h;
+    
+
+    if (argc !=4 ) {
+            fprintf(stderr, "Usage %s match string #iterations\n",argv[0]);
+            return -1;
+    }
+    iters = atoi( argv[3]);
+    
+    apr_initialize() ;
+    atexit(apr_terminate);
+    if (apr_pool_create(&context, NULL) != APR_SUCCESS) {
+        fprintf(stderr, "Something went wrong\n");
+        exit(-1);
+    }
+    rc = regcomp( &regex, argv[1], REG_EXTENDED|REG_NOSUB);
+
+
+    if (rc) {
+        char errbuf[2000];
+        regerror(rc, &regex,errbuf,2000);
+        fprintf(stderr,"Couldn't compile regex ;(\n%s\n ",errbuf);
+        return -1;
+    }
+    if ( regexec( &regex, argv[2], 0, NULL,0) == 0 ) {
+        fprintf(stderr,"Match\n");
+    }
+    else {
+        fprintf(stderr,"No Match\n");
+    }
+    now = apr_time_now();
+    for (i=0;i<iters;i++) {
+        regexec( &regex, argv[2], 0, NULL,0) ;
+    }
+    end=apr_time_now();
+    puts(apr_psprintf( context, "Time to run %d regex's          %8lld\n",iters,end-now));
+    h = apr_hash_make( context);
+    for (i=0;i<70;i++) {
+            apr_hash_set(h,apr_psprintf(context, "%dkey",i),APR_HASH_KEY_STRING,"1");
+    }
+    now = apr_time_now();
+    for (i=0;i<iters;i++) {
+        apr_hash_get( h, argv[2], APR_HASH_KEY_STRING);
+    }
+    end=apr_time_now();
+    puts(apr_psprintf( context, "Time to run %d hash (no find)'s %8lld\n",iters,end-now));
+    apr_hash_set(h, argv[2],APR_HASH_KEY_STRING,"1");
+    now = apr_time_now();
+    for (i=0;i<iters;i++) {
+        apr_hash_get( h, argv[2], APR_HASH_KEY_STRING);
+    }
+    end=apr_time_now();
+    puts(apr_psprintf( context, "Time to run %d hash (find)'s    %8lld\n",iters,end-now));
+ 
+    return 0;
+}
diff --git a/test/internal/testucs.c b/test/internal/testucs.c
new file mode 100644
index 00000000000..bf8874e48b7
--- /dev/null
+++ b/test/internal/testucs.c
@@ -0,0 +1,348 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "arch/win32/apr_arch_utf8.h"
+#include <wchar.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+struct testval {
+    unsigned char n[8];
+    apr_size_t nl;
+    wchar_t w[4];
+    apr_size_t wl;
+};
+
+#ifdef FOR_REFERENCE
+/* For reference; a table of invalid utf-8 encoded ucs-2/ucs-4 sequences.
+ * The table consists of start, end pairs for all invalid ranges.
+ * NO_UCS2_PAIRS will pass the reservered D800-DFFF values, halting at FFFF
+ * FULL_UCS4_MAPPER represents all 31 bit values to 7FFF FFFF
+ *
+ * We already tested these, because we ensure there is a 1:1 mapping across
+ * the entire range of byte values in each position of 1 to 6 byte sequences.
+ */
+struct testval malformed[] = [
+    [[0x80,], 1,],      /* 10000000  64 invalid leading continuation values */
+    [[0xBF,], 1,],      /* 10111111  64 invalid leading continuation values */
+    [[0xC0,0x80], 2,],                         /* overshort mapping of 0000 */
+    [[0xC1,0xBF], 2,],                         /* overshort mapping of 007F */
+    [[0xE0,0x80,0x80,], 3,],                   /* overshort mapping of 0000 */
+    [[0xE0,0x9F,0xBF,], 3,],                   /* overshort mapping of 07FF */
+#ifndef NO_UCS2_PAIRS
+    [[0xED,0xA0,0x80,], 3,],    /* unexpected mapping of UCS-2 literal D800 */
+    [[0xED,0xBF,0xBF,], 3,],    /* unexpected mapping of UCS-2 literal DFFF */
+#endif
+    [[0xF0,0x80,0x80,0x80,], 4,],              /* overshort mapping of 0000 */
+    [[0xF0,0x8F,0xBF,0xBF,], 4,],              /* overshort mapping of FFFF */
+#ifdef NO_UCS2_PAIRS
+    [[0xF0,0x90,0x80,0x80,], 4,],      /* invalid too large value 0001 0000 */
+    [[0xF4,0x8F,0xBF,0xBF,], 4,],      /* invalid too large value 0010 FFFF */
+#endif
+#ifndef FULL_UCS4_MAPPER
+    [[0xF4,0x90,0x80,0x80,], 4,],      /* invalid too large value 0011 0000 */
+    [[0xF7,0xBF,0xBF,0xBF,], 4,],      /* invalid too large value 001F FFFF */
+#endif
+    [[0xF8,0x80,0x80,0x80,0x80,], 5,],    /* overshort mapping of 0000 0000 */
+    [[0xF8,0x87,0xBF,0xBF,0xBF,], 5,],    /* overshort mapping of 001F FFFF */
+#ifndef FULL_UCS4_MAPPER
+    [[0xF8,0x88,0x80,0x80,0x80,], 5,], /* invalid too large value 0020 0000 */
+    [[0xFB,0xBF,0xBF,0xBF,0xBF,], 5,], /* invalid too large value 03FF FFFF */
+#endif
+    [[0xFC,0x80,0x80,0x80,0x80,0x80,], 6,],  /* overshort mapping 0000 0000 */
+    [[0xFC,0x83,0xBF,0xBF,0xBF,0xBF,], 6,],  /* overshort mapping 03FF FFFF */
+#ifndef FULL_UCS4_MAPPER
+    [[0xFC,0x84,0x80,0x80,0x80,0x80,], 6,],  /* overshort mapping 0400 0000 */
+    [[0xFD,0xBF,0xBF,0xBF,0xBF,0xBF,], 6,],  /* overshort mapping 7FFF FFFF */
+#endif
+    [[0xFE,], 1,],    /* 11111110  invalid "too large" value, no 7 byte seq */
+    [[0xFF,], 1,],    /* 11111111  invalid "too large" value, no 8 byte seq */
+];
+#endif /* FOR_REFERENCE */
+
+void displaynw(struct testval *f, struct testval *l)
+{
+    char x[80], *t = x;
+    int i;
+    for (i = 0; i < f->nl; ++i)
+        t += sprintf(t, "%02X ", f->n[i]);
+    *(t++) = '-'; 
+    for (i = 0; i < l->nl; ++i)
+        t += sprintf(t, " %02X", l->n[i]);
+    *(t++) = ' ';
+    *(t++) = '=';
+    *(t++) = ' ';
+    for (i = 0; i < f->wl; ++i)
+        t += sprintf(t, "%04X ", f->w[i]);
+    *(t++) = '-';
+    for (i = 0; i < l->wl; ++i)
+        t += sprintf(t, " %04X", l->w[i]);
+    *t = '\0';
+    puts(x);
+}
+
+/*
+ *  Test every possible byte value. 
+ *  If the test passes or fails at this byte value we are done.
+ *  Otherwise iterate test_nrange again, appending another byte.
+ */
+void test_nrange(struct testval *p)
+{
+    struct testval f, l, s;
+    apr_status_t rc;
+    int success = 0;
+    
+    memcpy (&s, p, sizeof(s));
+    ++s.nl;    
+    
+    do {
+        apr_size_t nl = s.nl, wl = sizeof(s.w) / 2;
+        rc = apr_conv_utf8_to_ucs2(s.n, &nl, s.w, &wl);
+        s.wl = (sizeof(s.w) / 2) - wl;
+        if (!nl && rc == APR_SUCCESS) {
+            if (!success) {
+                memcpy(&f, &s, sizeof(s));
+                success = -1;
+            }
+            else {
+                if (s.wl != l.wl 
+                 || memcmp(s.w, l.w, (s.wl - 1) * 2) != 0
+                 || s.w[s.wl - 1] != l.w[l.wl - 1] + 1) {
+                    displaynw(&f, &l);
+                    memcpy(&f, &s, sizeof(s));
+                }
+            }            
+            memcpy(&l, &s, sizeof(s));
+        }
+        else {
+            if (success) {
+                displaynw(&f, &l);
+                success = 0;
+            }
+            if (rc == APR_INCOMPLETE) {
+                test_nrange(&s);
+            }
+        }
+    } while (++s.n[s.nl - 1]);
+
+    if (success) {
+        displaynw(&f, &l);
+        success = 0;
+    }
+}
+
+/* 
+ *  Test every possible word value. 
+ *  Once we are finished, retest every possible word value.
+ *  if the test fails on the following null word, iterate test_nrange 
+ *  again, appending another word.
+ *  This assures the output order of the two tests are in sync.
+ */
+void test_wrange(struct testval *p)
+{
+    struct testval f, l, s;
+    apr_status_t rc;
+    int success = 0;
+    
+    memcpy (&s, p, sizeof(s));
+    ++s.wl;    
+    
+    do {
+        apr_size_t nl = sizeof(s.n), wl = s.wl;        
+        rc = apr_conv_ucs2_to_utf8(s.w, &wl, s.n, &nl);
+        s.nl = sizeof(s.n) - nl;
+        if (!wl && rc == APR_SUCCESS) {
+            if (!success) {
+                memcpy(&f, &s, sizeof(s));
+                success = -1;
+            }
+            else {
+                if (s.nl != l.nl 
+                 || memcmp(s.n, l.n, s.nl - 1) != 0
+                 || s.n[s.nl - 1] != l.n[l.nl - 1] + 1) {
+                    displaynw(&f, &l);
+                    memcpy(&f, &s, sizeof(s));
+                }
+            }            
+            memcpy(&l, &s, sizeof(s));
+        }
+        else {
+            if (success) {
+                displaynw(&f, &l);
+                success = 0;
+            }
+        }
+    } while (++s.w[s.wl - 1]);
+
+    if (success) {
+        displaynw(&f, &l);
+        success = 0;
+    }
+
+    do {
+        apr_size_t wl = s.wl, nl = sizeof(s.n);
+        rc = apr_conv_ucs2_to_utf8(s.w, &wl, s.n, &nl);
+        s.nl = sizeof(s.n) - s.nl;
+        if (rc == APR_INCOMPLETE) {
+            test_wrange(&s);
+        }
+    } while (++s.w[s.wl - 1]);
+}
+
+/*
+ *  Test every possible byte value. 
+ *  If the test passes or fails at this byte value we are done.
+ *  Otherwise iterate test_nrange again, appending another byte.
+ */
+void test_ranges()
+{
+    struct testval ntest, wtest;
+    apr_status_t nrc, wrc;
+    apr_size_t inlen;
+    unsigned long matches = 0;
+
+    memset(&ntest, 0, sizeof(ntest));
+    ++ntest.nl;
+
+    memset(&wtest, 0, sizeof(wtest));
+    ++wtest.wl;
+
+    do {
+        do {
+            inlen = ntest.nl;
+            ntest.wl = sizeof(ntest.w) / 2;
+            nrc = apr_conv_utf8_to_ucs2(ntest.n, &inlen, ntest.w, &ntest.wl);
+            if (nrc == APR_SUCCESS) {
+                ntest.wl = (sizeof(ntest.w) / 2) - ntest.wl;
+                break;
+            }
+            if (nrc == APR_INCOMPLETE) {
+                ++ntest.nl;
+                if (ntest.nl > 6) {
+                    printf ("\n\nUnexpected utf8 sequence of >6 bytes;\n");
+                    exit(255);
+                }
+                continue;
+            }
+            else {
+                while (!(++ntest.n[ntest.nl - 1])) {
+                    if (!(--ntest.nl))
+                        break;
+                }
+            }
+        } while (ntest.nl);
+
+        do {
+            inlen = wtest.wl;
+            wtest.nl = sizeof(wtest.n);
+            wrc = apr_conv_ucs2_to_utf8(wtest.w, &inlen, wtest.n, &wtest.nl);
+            if (wrc == APR_SUCCESS) {
+                wtest.nl = sizeof(wtest.n) - wtest.nl;
+                break;
+            }
+            else {
+                if (!(++wtest.w[wtest.wl - 1])) {
+                    if (wtest.wl == 1)
+                        ++wtest.wl;
+                    else
+                        ++wtest.w[0];
+
+                    /* On the second pass, ensure lead word is incomplete */
+                    do {
+                        inlen = 1;
+                        wtest.nl = sizeof(wtest.n);
+                        if (apr_conv_ucs2_to_utf8(wtest.w, &inlen, wtest.n, &wtest.nl)
+                                == APR_INCOMPLETE)
+                            break;
+                        if (!(++wtest.w[0])) {
+                            wtest.wl = 0;
+                            break;
+                        }
+                    } while (1);
+                }
+            }
+        } while (wtest.wl);
+
+        if (!ntest.nl && !wtest.wl)
+            break;
+
+        /* Identical? */
+        if ((wtest.nl != ntest.nl)
+         || (memcmp(wtest.n, ntest.n, ntest.nl) != 0)
+         || (wtest.wl != ntest.wl)
+         || (memcmp(ntest.w, wtest.w, wtest.wl * 2) != 0)) {
+            printf ("\n\nMismatch of w/n conversion at;\n");
+            displaynw(&ntest, &wtest);
+            exit(255);
+        }
+        ++matches;
+
+        while (!(++ntest.n[ntest.nl - 1])) {
+            if (!(--ntest.nl))
+                break;
+        }
+
+        if (!(++wtest.w[wtest.wl - 1])) {
+            if (wtest.wl == 1)
+                ++wtest.wl;
+            else
+                ++wtest.w[0];
+
+            /* On the second pass, ensure lead word is incomplete */
+            do {
+                inlen = 1;
+                wtest.nl = sizeof(wtest.n);
+                if (apr_conv_ucs2_to_utf8(wtest.w, &inlen, wtest.n, &wtest.nl)
+                        == APR_INCOMPLETE)
+                    break;
+                if (!(++wtest.w[0])) {
+                    wtest.wl = 0;
+                    break;
+                }
+            } while (1);
+        }
+    } while (wtest.wl || ntest.nl);
+
+    printf ("\n\nutf8 and ucs2 sequences of %lu transformations matched OK.\n",
+            matches);
+}
+
+/*
+ *  Syntax: testucs [w|n]
+ *
+ *  If no arg or arg is not recognized, run equality sequence test.
+ */
+int main(int argc, char **argv)
+{
+    struct testval s;
+    memset (&s, 0, sizeof(s));
+
+    if (argc >= 2 && apr_tolower(*argv[1]) != 'w') {
+        printf ("\n\nTesting Narrow Char Ranges\n");
+        test_nrange(&s);
+    }
+    else if (argc >= 2 && apr_tolower(*argv[1]) != 'n') {
+        printf ("\n\nTesting Wide Char Ranges\n");
+        test_wrange(&s);
+    }
+    else {
+        test_ranges();
+    }
+    return 0;
+}
diff --git a/test/mod_test.c b/test/mod_test.c
index 088d748420c..2178e94059c 100644
--- a/test/mod_test.c
+++ b/test/mod_test.c
@@ -1,17 +1,32 @@
-#include <stdio.h>
+/* 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.
+ */
 
-int goodbyes = 0;
+#include "apr_strings.h"
 
-void print_hello(void)
+void print_hello(char str[256]);
+int count_reps(int reps);
+
+void print_hello(char str[256])
 {
-    fprintf(stdout,"Hello - I'm a DSO!\n");
+    apr_cpystrn(str, "Hello - I'm a DSO!\n", strlen("Hello - I'm a DSO!\n") + 1);
 }
 
-int print_goodbye(int reps)
+int count_reps(int reps)
 {
     int i = 0;
-    for (i = 0;i < reps; i++) {
-        fprintf (stdout, "Goodbye from the DSO! (%d of %d)\n", i+1, reps);
-    }
-    goodbyes = reps;
+    for (i = 0;i < reps; i++);
+    return i;
 }
diff --git a/test/nw_misc.c b/test/nw_misc.c
new file mode 100644
index 00000000000..b45f9516dce
--- /dev/null
+++ b/test/nw_misc.c
@@ -0,0 +1,23 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <screen.h>
+/*
+#include "testutil.h"
+*/
+
+/* function to keep the screen open if not launched from bash */
+void _NonAppStop( void )
+{
+  if (getenv("_IN_NETWARE_BASH_") == NULL) {
+    printf("\r\n<Press any key to close screen> ");
+    getcharacter();
+  }
+}
+
+/*
+static void test_not_impl(CuTest *tc)
+{
+    CuNotImpl(tc, "Test not implemented on this platform yet");
+}
+*/
+
diff --git a/test/occhild.c b/test/occhild.c
new file mode 100644
index 00000000000..a96885d8271
--- /dev/null
+++ b/test/occhild.c
@@ -0,0 +1,26 @@
+#include "apr.h"
+#include "apr_file_io.h"
+#include "apr.h"
+
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+int main(void)
+{
+    char buf[256];
+    apr_file_t *err;
+    apr_pool_t *p;
+
+    apr_initialize();
+    atexit(apr_terminate);
+
+    apr_pool_create(&p, NULL);
+    apr_file_open_stdin(&err, p);
+
+    while (1) {
+        apr_size_t length = 256;
+        apr_file_read(err, buf, &length);
+    }
+    exit(0); /* just to keep the compiler happy */
+}
diff --git a/test/proc_child.c b/test/proc_child.c
new file mode 100644
index 00000000000..6cfc8fc9fb4
--- /dev/null
+++ b/test/proc_child.c
@@ -0,0 +1,21 @@
+#include "apr.h"
+#include <stdio.h>
+#if APR_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if APR_HAVE_IO_H
+#include <io.h>
+#endif
+#include <stdlib.h>
+
+int main(void)
+{
+    char buf[256];
+    int bytes;
+    
+    bytes = (int)read(STDIN_FILENO, buf, 256);
+    if (bytes > 0)
+        write(STDOUT_FILENO, buf, (unsigned int)bytes);
+
+    return 0; /* just to keep the compiler happy */
+}
diff --git a/test/readchild.c b/test/readchild.c
new file mode 100644
index 00000000000..f8443cceb8e
--- /dev/null
+++ b/test/readchild.c
@@ -0,0 +1,46 @@
+/* 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 <stdlib.h>
+
+#include "apr_file_io.h"
+
+int main(int argc, char *argv[])
+{
+    apr_file_t *in, *out;
+    apr_size_t nbytes, total_bytes;
+    apr_pool_t *p;
+    char buf[128];
+    apr_status_t rv;
+    
+    apr_initialize();
+    atexit(apr_terminate);
+    apr_pool_create(&p, NULL);
+
+    apr_file_open_stdin(&in, p);
+    apr_file_open_stdout(&out, p);
+
+    total_bytes = 0;
+    nbytes = sizeof(buf);
+    while ((rv = apr_file_read(in, buf, &nbytes)) == APR_SUCCESS) {
+        total_bytes += nbytes;
+        nbytes = sizeof(buf);
+    }
+
+    apr_file_printf(out, "%" APR_SIZE_T_FMT " bytes were read\n",
+                    total_bytes);
+    return 0;
+}
diff --git a/test/sendfile.c b/test/sendfile.c
new file mode 100644
index 00000000000..f8de309846a
--- /dev/null
+++ b/test/sendfile.c
@@ -0,0 +1,770 @@
+/* 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 <assert.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include "apr_network_io.h"
+#include "apr_errno.h"
+#include "apr_general.h"
+#include "apr_poll.h"
+#include "apr_thread_proc.h"
+
+#include "testutil.h"
+
+#if !APR_HAS_SENDFILE
+int main(void)
+{
+    fprintf(stderr, 
+            "This program won't work on this platform because there is no "
+            "support for sendfile().\n");
+    return 0;
+}
+#else /* !APR_HAS_SENDFILE */
+
+#define FILE_LENGTH    200000
+
+#define FILE_DATA_CHAR '0'
+
+#define HDR1           "1234567890ABCD\n"
+#define HDR2           "EFGH\n"
+#define HDR3_LEN       80000
+#define HDR3_CHAR      '^'
+#define TRL1           "IJKLMNOPQRSTUVWXYZ\n"
+#define TRL2           "!@#$%&*()\n"
+#define TRL3_LEN       90000
+#define TRL3_CHAR      '@'
+
+#define TESTSF_PORT    8021
+
+#define TESTFILE       "testsf.dat"
+
+typedef enum {BLK, NONBLK, TIMEOUT} client_socket_mode_t;
+
+static void aprerr(const char *fn, apr_status_t rv)
+{
+    char buf[120];
+
+    fprintf(stderr, "%s->%d/%s\n",
+            fn, rv, apr_strerror(rv, buf, sizeof buf));
+    exit(1);
+}
+
+static void apr_setup(apr_pool_t *p, apr_socket_t **sock, int *family)
+{
+    apr_status_t rv;
+
+    *sock = NULL;
+    rv = apr_socket_create(sock, *family, SOCK_STREAM, 0, p);
+    if (rv != APR_SUCCESS) {
+        aprerr("apr_socket_create()", rv);
+    }
+
+    if (*family == APR_UNSPEC) {
+        apr_sockaddr_t *localsa;
+
+        rv = apr_socket_addr_get(&localsa, APR_LOCAL, *sock);
+        if (rv != APR_SUCCESS) {
+            aprerr("apr_socket_addr_get()", rv);
+        }
+        *family = localsa->family;
+    }
+}
+
+static void create_testfile(apr_pool_t *p, const char *fname)
+{
+    apr_file_t *f = NULL;
+    apr_status_t rv;
+    char buf[120];
+    int i;
+    apr_finfo_t finfo;
+
+    printf("Creating a test file...\n");
+    rv = apr_file_open(&f, fname, 
+                 APR_FOPEN_CREATE | APR_FOPEN_WRITE | APR_FOPEN_TRUNCATE | APR_FOPEN_BUFFERED,
+                 APR_FPROT_UREAD | APR_FPROT_UWRITE, p);
+    if (rv) {
+        aprerr("apr_file_open()", rv);
+    }
+    
+    buf[0] = FILE_DATA_CHAR;
+    buf[1] = '\0';
+    for (i = 0; i < FILE_LENGTH; i++) {
+        /* exercise apr_file_putc() and apr_file_puts() on buffered files */
+        if ((i % 2) == 0) {
+            rv = apr_file_putc(buf[0], f);
+            if (rv) {
+                aprerr("apr_file_putc()", rv);
+            }
+        }
+        else {
+            rv = apr_file_puts(buf, f);
+            if (rv) {
+                aprerr("apr_file_puts()", rv);
+            }
+        }
+    }
+
+    rv = apr_file_close(f);
+    if (rv) {
+        aprerr("apr_file_close()", rv);
+    }
+
+    rv = apr_stat(&finfo, fname, APR_FINFO_NORM, p);
+    if (rv != APR_SUCCESS && ! APR_STATUS_IS_INCOMPLETE(rv)) {
+        aprerr("apr_stat()", rv);
+    }
+
+    if (finfo.size != FILE_LENGTH) {
+        fprintf(stderr, 
+                "test file %s should be %ld-bytes long\n"
+                "instead it is %ld-bytes long\n",
+                fname,
+                (long int)FILE_LENGTH,
+                (long int)finfo.size);
+        exit(1);
+    }
+}
+
+static void spawn_server(apr_pool_t *p, apr_proc_t *out_proc)
+{
+    apr_proc_t proc = {0};
+    apr_procattr_t *procattr;
+    apr_status_t rv;
+    const char *args[3];
+
+    rv = apr_procattr_create(&procattr, p);
+    if (rv != APR_SUCCESS) {
+        aprerr("apr_procattr_create()", rv);
+    }
+
+    rv = apr_procattr_io_set(procattr, APR_CHILD_BLOCK, APR_CHILD_BLOCK,
+                             APR_CHILD_BLOCK);
+    if (rv != APR_SUCCESS) {
+        aprerr("apr_procattr_io_set()", rv);
+    }
+
+    rv = apr_procattr_cmdtype_set(procattr, APR_PROGRAM_ENV);
+    if (rv != APR_SUCCESS) {
+        aprerr("apr_procattr_cmdtype_set()", rv);
+    }
+
+    rv = apr_procattr_error_check_set(procattr, 1);
+    if (rv != APR_SUCCESS) {
+        aprerr("apr_procattr_error_check_set()", rv);
+    }
+
+    args[0] = "sendfile" EXTENSION;
+    args[1] = "server";
+    args[2] = NULL;
+    rv = apr_proc_create(&proc, TESTBINPATH "sendfile" EXTENSION, args, NULL, procattr, p);
+    if (rv != APR_SUCCESS) {
+        aprerr("apr_proc_create()", rv);
+    }
+
+    *out_proc = proc;
+}
+
+static int client(apr_pool_t *p, client_socket_mode_t socket_mode,
+                  const char *host, int start_server)
+{
+    apr_status_t rv, tmprv;
+    apr_socket_t *sock;
+    char buf[120];
+    apr_file_t *f = NULL;
+    apr_size_t len;
+    apr_size_t expected_len;
+    apr_off_t current_file_offset;
+    apr_hdtr_t hdtr;
+    struct iovec headers[3];
+    struct iovec trailers[3];
+    apr_size_t bytes_read;
+    apr_pollset_t *pset;
+    apr_int32_t nsocks;
+    int connect_tries = 1;
+    int i;
+    int family;
+    apr_sockaddr_t *destsa;
+    apr_proc_t server;
+    apr_interval_time_t connect_retry_interval = apr_time_from_msec(50);
+
+    if (start_server) {
+        spawn_server(p, &server);
+        connect_tries = 5; /* give it a chance to start up */
+    }
+
+    create_testfile(p, TESTFILE);
+
+    rv = apr_file_open(&f, TESTFILE, APR_FOPEN_READ, 0, p);
+    if (rv != APR_SUCCESS) {
+        aprerr("apr_file_open()", rv);
+    }
+
+    if (!host) {
+        host = "127.0.0.1";
+    }
+    family = APR_INET;
+    rv = apr_sockaddr_info_get(&destsa, host, family, TESTSF_PORT, 0, p);
+    if (rv != APR_SUCCESS) {
+        aprerr("apr_sockaddr_info_get()", rv);
+    }
+
+    while (connect_tries--) {
+        apr_setup(p, &sock, &family);
+        rv = apr_socket_connect(sock, destsa);
+        if (connect_tries && APR_STATUS_IS_ECONNREFUSED(rv)) {
+            apr_status_t tmprv = apr_socket_close(sock);
+            if (tmprv != APR_SUCCESS) {
+                aprerr("apr_socket_close()", tmprv);
+            }
+            apr_sleep(connect_retry_interval);
+            connect_retry_interval *= 2;
+        }
+        else {
+            break;
+        }
+    }
+    if (rv != APR_SUCCESS) {
+        aprerr("apr_socket_connect()", rv);
+    }
+
+    switch(socket_mode) {
+    case BLK:
+        /* leave it blocking */
+        break;
+    case NONBLK:
+        /* set it non-blocking */
+        rv = apr_socket_opt_set(sock, APR_SO_NONBLOCK, 1);
+        if (rv != APR_SUCCESS) {
+            aprerr("apr_socket_opt_set(APR_SO_NONBLOCK)", rv);
+        }
+        break;
+    case TIMEOUT:
+        /* set a timeout */
+        rv = apr_socket_timeout_set(sock, 100 * APR_USEC_PER_SEC);
+        if (rv != APR_SUCCESS) {
+            aprerr("apr_socket_opt_set(APR_SO_NONBLOCK)", rv);
+            exit(1);
+        }
+        break;
+    default:
+        assert(1 != 1);
+    }
+
+    printf("Sending the file...\n");
+
+    hdtr.headers = headers;
+    hdtr.numheaders = 3;
+    hdtr.headers[0].iov_base = HDR1;
+    hdtr.headers[0].iov_len  = strlen(hdtr.headers[0].iov_base);
+    hdtr.headers[1].iov_base = HDR2;
+    hdtr.headers[1].iov_len  = strlen(hdtr.headers[1].iov_base);
+    hdtr.headers[2].iov_base = malloc(HDR3_LEN);
+    assert(hdtr.headers[2].iov_base);
+    memset(hdtr.headers[2].iov_base, HDR3_CHAR, HDR3_LEN);
+    hdtr.headers[2].iov_len  = HDR3_LEN;
+
+    hdtr.trailers = trailers;
+    hdtr.numtrailers = 3;
+    hdtr.trailers[0].iov_base = TRL1;
+    hdtr.trailers[0].iov_len  = strlen(hdtr.trailers[0].iov_base);
+    hdtr.trailers[1].iov_base = TRL2;
+    hdtr.trailers[1].iov_len  = strlen(hdtr.trailers[1].iov_base);
+    hdtr.trailers[2].iov_base = malloc(TRL3_LEN);
+    memset(hdtr.trailers[2].iov_base, TRL3_CHAR, TRL3_LEN);
+    assert(hdtr.trailers[2].iov_base);
+    hdtr.trailers[2].iov_len  = TRL3_LEN;
+
+    expected_len = 
+        strlen(HDR1) + strlen(HDR2) + HDR3_LEN +
+        strlen(TRL1) + strlen(TRL2) + TRL3_LEN +
+        FILE_LENGTH;
+    
+    if (socket_mode == BLK) {
+        current_file_offset = 0;
+        len = FILE_LENGTH;
+        rv = apr_socket_sendfile(sock, f, &hdtr, &current_file_offset, &len, 0);
+        if (rv != APR_SUCCESS) {
+            aprerr("apr_socket_sendfile()", rv);
+        }
+        
+        printf("apr_socket_sendfile() updated offset with %ld\n",
+               (long int)current_file_offset);
+        
+        printf("apr_socket_sendfile() updated len with %ld\n",
+               (long int)len);
+        
+        printf("bytes really sent: %" APR_SIZE_T_FMT "\n",
+               expected_len);
+
+        if (len != expected_len) {
+            fprintf(stderr, "apr_socket_sendfile() didn't report the correct "
+                    "number of bytes sent!\n");
+            exit(1);
+        }
+    }
+    else {
+        /* non-blocking... wooooooo */
+        apr_size_t total_bytes_sent;
+        apr_pollfd_t pfd;
+
+        pset = NULL;
+        rv = apr_pollset_create(&pset, 1, p, 0);
+        assert(!rv);
+        pfd.p = p;
+        pfd.desc_type = APR_POLL_SOCKET;
+        pfd.reqevents = APR_POLLOUT;
+        pfd.rtnevents = 0;
+        pfd.desc.s = sock;
+        pfd.client_data = NULL;
+
+        rv = apr_pollset_add(pset, &pfd);        
+        assert(!rv);
+
+        total_bytes_sent = 0;
+        current_file_offset = 0;
+        len = FILE_LENGTH;
+        do {
+            apr_size_t tmplen;
+
+            tmplen = len; /* bytes remaining to send from the file */
+            printf("Calling apr_socket_sendfile()...\n");
+            printf("Headers (%d):\n", hdtr.numheaders);
+            for (i = 0; i < hdtr.numheaders; i++) {
+                printf("\t%ld bytes (%c)\n",
+                       (long)hdtr.headers[i].iov_len,
+                       *(char *)hdtr.headers[i].iov_base);
+            }
+            printf("File: %ld bytes from offset %ld\n",
+                   (long)tmplen, (long)current_file_offset);
+            printf("Trailers (%d):\n", hdtr.numtrailers);
+            for (i = 0; i < hdtr.numtrailers; i++) {
+                printf("\t%ld bytes\n",
+                       (long)hdtr.trailers[i].iov_len);
+            }
+
+            rv = apr_socket_sendfile(sock, f, &hdtr, &current_file_offset, &tmplen, 0);
+            printf("apr_socket_sendfile()->%d, sent %ld bytes\n", rv, (long)tmplen);
+            if (rv) {
+                if (APR_STATUS_IS_EAGAIN(rv)) {
+                    assert(tmplen == 0);
+                    nsocks = 1;
+                    tmprv = apr_pollset_poll(pset, -1, &nsocks, NULL);
+                    assert(!tmprv);
+                    assert(nsocks == 1);
+                    /* continue; */
+                }
+            }
+
+            total_bytes_sent += tmplen;
+
+            /* Adjust hdtr to compensate for partially-written
+             * data.
+             */
+
+            /* First, skip over any header data which might have
+             * been written.
+             */
+            while (tmplen && hdtr.numheaders) {
+                if (tmplen >= hdtr.headers[0].iov_len) {
+                    tmplen -= hdtr.headers[0].iov_len;
+                    --hdtr.numheaders;
+                    ++hdtr.headers;
+                }
+                else {
+                    hdtr.headers[0].iov_len -= tmplen;
+                    hdtr.headers[0].iov_base = 
+			(char*) hdtr.headers[0].iov_base + tmplen;
+                    tmplen = 0;
+                }
+            }
+
+            /* Now, skip over any file data which might have been
+             * written.
+             */
+
+            if (tmplen <= len) {
+                current_file_offset += tmplen;
+                len -= tmplen;
+                tmplen = 0;
+            }
+            else {
+                tmplen -= len;
+                len = 0;
+                current_file_offset = 0;
+            }
+
+            /* Last, skip over any trailer data which might have
+             * been written.
+             */
+
+            while (tmplen && hdtr.numtrailers) {
+                if (tmplen >= hdtr.trailers[0].iov_len) {
+                    tmplen -= hdtr.trailers[0].iov_len;
+                    --hdtr.numtrailers;
+                    ++hdtr.trailers;
+                }
+                else {
+                    hdtr.trailers[0].iov_len -= tmplen;
+                    hdtr.trailers[0].iov_base = 
+			(char *)hdtr.trailers[0].iov_base + tmplen;
+                    tmplen = 0;
+                }
+            }
+
+        } while (total_bytes_sent < expected_len &&
+                 (rv == APR_SUCCESS || 
+                 (APR_STATUS_IS_EAGAIN(rv) && socket_mode != TIMEOUT)));
+        if (total_bytes_sent != expected_len) {
+            fprintf(stderr,
+                    "client problem: sent %ld of %ld bytes\n",
+                    (long)total_bytes_sent, (long)expected_len);
+            exit(1);
+        }
+
+        if (rv) {
+            fprintf(stderr,
+                    "client problem: rv %d\n",
+                    rv);
+            exit(1);
+        }
+    }
+    
+    current_file_offset = 0;
+    rv = apr_file_seek(f, APR_CUR, &current_file_offset);
+    if (rv != APR_SUCCESS) {
+        aprerr("apr_file_seek()", rv);
+    }
+
+    printf("After apr_socket_sendfile(), the kernel file pointer is "
+           "at offset %ld.\n",
+           (long int)current_file_offset);
+
+    rv = apr_socket_shutdown(sock, APR_SHUTDOWN_WRITE);
+    if (rv != APR_SUCCESS) {
+        aprerr("apr_socket_shutdown()", rv);
+    }
+
+    /* in case this is the non-blocking test, set socket timeout;
+     * we're just waiting for EOF */
+
+    rv = apr_socket_timeout_set(sock, apr_time_from_sec(3));
+    if (rv != APR_SUCCESS) {
+        aprerr("apr_socket_timeout_set()", rv);
+    }
+    
+    bytes_read = 1;
+    rv = apr_socket_recv(sock, buf, &bytes_read);
+    if (rv != APR_EOF) {
+        aprerr("apr_socket_recv() (expected APR_EOF)", rv);
+    }
+    if (bytes_read != 0) {
+        fprintf(stderr, "We expected to get 0 bytes read with APR_EOF\n"
+                "but instead we read %ld bytes.\n",
+                (long int)bytes_read);
+        exit(1);
+    }
+
+    printf("client: apr_socket_sendfile() worked as expected!\n");
+
+    rv = apr_file_remove(TESTFILE, p);
+    if (rv != APR_SUCCESS) {
+        aprerr("apr_file_remove()", rv);
+    }
+
+    if (start_server) {
+        apr_exit_why_e exitwhy;
+        apr_size_t nbytes;
+        char responsebuf[1024];
+        int exitcode;
+
+        rv = apr_file_pipe_timeout_set(server.out, apr_time_from_sec(2));
+        if (rv != APR_SUCCESS) {
+            aprerr("apr_file_pipe_timeout_set()", rv);
+        }
+        nbytes = sizeof(responsebuf);
+        rv = apr_file_read(server.out, responsebuf, &nbytes);
+        if (rv != APR_SUCCESS) {
+            aprerr("apr_file_read() messages from server", rv);
+        }
+        printf("%.*s", (int)nbytes, responsebuf);
+        rv = apr_proc_wait(&server, &exitcode, &exitwhy, APR_WAIT);
+        if (rv != APR_CHILD_DONE) {
+            aprerr("apr_proc_wait() (expected APR_CHILD_DONE)", rv);
+        }
+        if (exitcode != 0) {
+            fprintf(stderr, "sendfile server returned %d\n", exitcode);
+            exit(1);
+        }
+    }
+
+    return 0;
+}
+
+static int server(apr_pool_t *p)
+{
+    apr_status_t rv;
+    apr_socket_t *sock;
+    char buf[120];
+    int i;
+    apr_socket_t *newsock = NULL;
+    apr_size_t bytes_read;
+    apr_sockaddr_t *localsa;
+    int family;
+
+    family = APR_INET;
+    apr_setup(p, &sock, &family);
+
+    rv = apr_socket_opt_set(sock, APR_SO_REUSEADDR, 1);
+    if (rv != APR_SUCCESS) {
+        aprerr("apr_socket_opt_set()", rv);
+    }
+
+    rv = apr_sockaddr_info_get(&localsa, NULL, family, TESTSF_PORT, 0, p);
+    if (rv != APR_SUCCESS) {
+        aprerr("apr_sockaddr_info_get()", rv);
+    }
+
+    rv = apr_socket_bind(sock, localsa);
+    if (rv != APR_SUCCESS) {
+        aprerr("apr_socket_bind()", rv);
+    }
+
+    rv = apr_socket_listen(sock, 5);
+    if (rv != APR_SUCCESS) {
+        aprerr("apr_socket_listen()", rv);
+    }
+
+    printf("Waiting for a client to connect...\n");
+
+    rv = apr_socket_accept(&newsock, sock, p);
+    if (rv != APR_SUCCESS) {
+        aprerr("apr_socket_accept()", rv);
+    }
+
+    printf("Processing a client...\n");
+
+    assert(sizeof buf > strlen(HDR1));
+    bytes_read = strlen(HDR1);
+    rv = apr_socket_recv(newsock, buf, &bytes_read);
+    if (rv != APR_SUCCESS) {
+        aprerr("apr_socket_recv()", rv);
+    }
+    if (bytes_read != strlen(HDR1)) {
+        fprintf(stderr, "wrong data read (1)\n");
+        exit(1);
+    }
+    if (memcmp(buf, HDR1, strlen(HDR1))) {
+        fprintf(stderr, "wrong data read (2)\n");
+        fprintf(stderr, "received: `%.*s'\nexpected: `%s'\n",
+                (int)bytes_read, buf, HDR1);
+        exit(1);
+    }
+        
+    assert(sizeof buf > strlen(HDR2));
+    bytes_read = strlen(HDR2);
+    rv = apr_socket_recv(newsock, buf, &bytes_read);
+    if (rv != APR_SUCCESS) {
+        aprerr("apr_socket_recv()", rv);
+    }
+    if (bytes_read != strlen(HDR2)) {
+        fprintf(stderr, "wrong data read (3)\n");
+        exit(1);
+    }
+    if (memcmp(buf, HDR2, strlen(HDR2))) {
+        fprintf(stderr, "wrong data read (4)\n");
+        fprintf(stderr, "received: `%.*s'\nexpected: `%s'\n",
+                (int)bytes_read, buf, HDR2);
+        exit(1);
+    }
+
+    for (i = 0; i < HDR3_LEN; i++) {
+        bytes_read = 1;
+        rv = apr_socket_recv(newsock, buf, &bytes_read);
+        if (rv != APR_SUCCESS) {
+            aprerr("apr_socket_recv()", rv);
+        }
+        if (bytes_read != 1) {
+            fprintf(stderr, "apr_socket_recv()->%ld bytes instead of 1\n",
+                    (long int)bytes_read);
+            exit(1);
+        }
+        if (buf[0] != HDR3_CHAR) {
+            fprintf(stderr,
+                    "problem with data read (byte %d of hdr 3):\n",
+                    i);
+            fprintf(stderr, "read `%c' (0x%x) from client; expected "
+                    "`%c'\n",
+                    buf[0], buf[0], HDR3_CHAR);
+            exit(1);
+        }
+    }
+        
+    for (i = 0; i < FILE_LENGTH; i++) {
+        bytes_read = 1;
+        rv = apr_socket_recv(newsock, buf, &bytes_read);
+        if (rv != APR_SUCCESS) {
+            aprerr("apr_socket_recv()", rv);
+        }
+        if (bytes_read != 1) {
+            fprintf(stderr, "apr_socket_recv()->%ld bytes instead of 1\n",
+                    (long int)bytes_read);
+            exit(1);
+        }
+        if (buf[0] != FILE_DATA_CHAR) {
+            fprintf(stderr,
+                    "problem with data read (byte %d of file):\n",
+                    i);
+            fprintf(stderr, "read `%c' (0x%x) from client; expected "
+                    "`%c'\n",
+                    buf[0], buf[0], FILE_DATA_CHAR);
+            exit(1);
+        }
+    }
+        
+    assert(sizeof buf > strlen(TRL1));
+    bytes_read = strlen(TRL1);
+    rv = apr_socket_recv(newsock, buf, &bytes_read);
+    if (rv != APR_SUCCESS) {
+        aprerr("apr_socket_recv()", rv);
+    }
+    if (bytes_read != strlen(TRL1)) {
+        fprintf(stderr, "wrong data read (5)\n");
+        exit(1);
+    }
+    if (memcmp(buf, TRL1, strlen(TRL1))) {
+        fprintf(stderr, "wrong data read (6)\n");
+        fprintf(stderr, "received: `%.*s'\nexpected: `%s'\n",
+                (int)bytes_read, buf, TRL1);
+        exit(1);
+    }
+        
+    assert(sizeof buf > strlen(TRL2));
+    bytes_read = strlen(TRL2);
+    rv = apr_socket_recv(newsock, buf, &bytes_read);
+    if (rv != APR_SUCCESS) {
+        aprerr("apr_socket_recv()", rv);
+    }
+    if (bytes_read != strlen(TRL2)) {
+        fprintf(stderr, "wrong data read (7)\n");
+        exit(1);
+    }
+    if (memcmp(buf, TRL2, strlen(TRL2))) {
+        fprintf(stderr, "wrong data read (8)\n");
+        fprintf(stderr, "received: `%.*s'\nexpected: `%s'\n",
+                (int)bytes_read, buf, TRL2);
+        exit(1);
+    }
+
+    for (i = 0; i < TRL3_LEN; i++) {
+        bytes_read = 1;
+        rv = apr_socket_recv(newsock, buf, &bytes_read);
+        if (rv != APR_SUCCESS) {
+            aprerr("apr_socket_recv()", rv);
+        }
+        if (bytes_read != 1) {
+            fprintf(stderr, "apr_socket_recv()->%ld bytes instead of 1\n",
+                    (long int)bytes_read);
+            exit(1);
+        }
+        if (buf[0] != TRL3_CHAR) {
+            fprintf(stderr,
+                    "problem with data read (byte %d of trl 3):\n",
+                    i);
+            fprintf(stderr, "read `%c' (0x%x) from client; expected "
+                    "`%c'\n",
+                    buf[0], buf[0], TRL3_CHAR);
+            exit(1);
+        }
+    }
+        
+    bytes_read = 1;
+    rv = apr_socket_recv(newsock, buf, &bytes_read);
+    if (rv != APR_EOF) {
+        aprerr("apr_socket_recv() (expected APR_EOF)", rv);
+    }
+    if (bytes_read != 0) {
+        fprintf(stderr, "We expected to get 0 bytes read with APR_EOF\n"
+                "but instead we read %ld bytes (%c).\n",
+                (long int)bytes_read, buf[0]);
+        exit(1);
+    }
+
+    printf("server: apr_socket_sendfile() worked as expected!\n");
+
+    return 0;
+}
+
+int main(int argc, char *argv[])
+{
+    apr_pool_t *p;
+    apr_status_t rv;
+
+#ifdef SIGPIPE
+    signal(SIGPIPE, SIG_IGN);
+#endif
+
+    rv = apr_initialize();
+    if (rv != APR_SUCCESS) {
+        aprerr("apr_initialize()", rv);
+    }
+
+    atexit(apr_terminate);
+
+    rv = apr_pool_create(&p, NULL);
+    if (rv != APR_SUCCESS) {
+        aprerr("apr_pool_create()", rv);
+    }
+
+    if (argc >= 2 && !strcmp(argv[1], "client")) {
+        const char *host = NULL;
+        int mode = BLK;
+        int start_server = 0;
+        int i;
+
+        for (i = 2; i < argc; i++) {
+            if (!strcmp(argv[i], "blocking")) {
+                mode = BLK;
+            }
+            else if (!strcmp(argv[i], "timeout")) {
+                mode = TIMEOUT;
+            }
+            else if (!strcmp(argv[i], "nonblocking")) {
+                mode = NONBLK;
+            }
+            else if (!strcmp(argv[i], "startserver")) {
+                start_server = 1;
+            }
+            else {
+                host = argv[i];
+            }	
+        }
+        return client(p, mode, host, start_server);
+    }
+    else if (argc == 2 && !strcmp(argv[1], "server")) {
+        return server(p);
+    }
+
+    fprintf(stderr, 
+            "Usage: %s client {blocking|nonblocking|timeout} [startserver] [server-host]\n"
+            "       %s server\n",
+            argv[0], argv[0]);
+    return -1;
+}
+
+#endif /* !APR_HAS_SENDFILE */
diff --git a/test/server.c b/test/server.c
deleted file mode 100644
index 3207915f699..00000000000
--- a/test/server.c
+++ /dev/null
@@ -1,214 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include <stdlib.h>
-#include "apr_network_io.h"
-#include "apr_errno.h"
-#include "apr_general.h"
-
-#define STRLEN 15
-
-int main(int argc, char *argv[])
-{
-    ap_pool_t *context;
-    ap_socket_t *sock;
-    ap_socket_t *sock2;
-    ap_ssize_t length;
-    ap_int32_t rv;
-    ap_pollfd_t *sdset;
-    char datasend[STRLEN];
-    char datarecv[STRLEN] = "Recv data test";
-    char *local_ipaddr, *remote_ipaddr;
-    ap_uint32_t local_port, remote_port;
-
-    fprintf(stdout, "Initializing.........");
-    if (ap_initialize() != APR_SUCCESS) {
-        fprintf(stderr, "Something went wrong\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK\n");
-    atexit(ap_terminate);
-
-    fprintf(stdout, "Creating context.......");
-    if (ap_create_pool(&context, NULL) != APR_SUCCESS) {
-        fprintf(stderr, "Could not create a context\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK\n");
-
-    fprintf(stdout, "\tServer:  Creating new socket.......");
-    if (ap_create_tcp_socket(&sock, context) != APR_SUCCESS) {
-        fprintf(stderr, "Couldn't create socket\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK\n");
-
-    fprintf(stdout, "\tServer:  Setting socket option NONBLOCK.......");
-    if (ap_setsocketopt(sock, APR_SO_NONBLOCK, 1) != APR_SUCCESS) {
-        ap_close_socket(sock);
-        fprintf(stderr, "Couldn't set socket option\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK\n");
-
-    fprintf(stdout, "\tServer:  Setting port for socket.......");
-    if (ap_set_local_port(sock, 8021) != APR_SUCCESS) {
-        ap_close_socket(sock);
-        fprintf(stderr, "Couldn't set the port correctly\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK\n");
-
-    fprintf(stdout, "\tServer:  Binding socket to port.......");
-    if (ap_bind(sock) != APR_SUCCESS) {
-        ap_close_socket(sock);
-        fprintf(stderr, "Could not bind\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK\n");
-    
-    fprintf(stdout, "\tServer:  Listening to socket.......");
-    if (ap_listen(sock, 8021) != APR_SUCCESS) {
-        ap_close_socket(sock);
-        fprintf(stderr, "Could not listen\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK\n");
-
-    fprintf(stdout, "\tServer:  Setting up socket for polling.......");
-    ap_setup_poll(&sdset, 1, context);
-    ap_add_poll_socket(sdset, sock, APR_POLLIN);
-    fprintf(stdout, "OK\n");
-    
-    fprintf(stdout, "\tServer:  Beginning to poll for socket.......");
-    rv = 1; 
-    if (ap_poll(sdset, &rv, -1) != APR_SUCCESS) {
-        ap_close_socket(sock);
-        fprintf(stderr, "Select caused an error\n");
-        exit(-1);
-    }
-    else if (rv == 0) {
-        ap_close_socket(sock);
-        fprintf(stderr, "I should not return until rv == 1\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK\n");
-
-    fprintf(stdout, "\tServer:  Accepting a connection.......");
-    if (ap_accept(&sock2, sock, context) != APR_SUCCESS) {
-        ap_close_socket(sock);
-        fprintf(stderr, "Could not accept connection.\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK\n");
-
-    ap_get_remote_ipaddr(&remote_ipaddr, sock2);
-    ap_get_remote_port(&remote_port, sock2);
-    ap_get_local_ipaddr(&local_ipaddr, sock2);
-    ap_get_local_port(&local_port, sock2);
-    fprintf(stdout, "\tServer socket: %s:%u -> %s:%u\n", local_ipaddr, local_port, remote_ipaddr, remote_port);
-
-    length = STRLEN;
-    fprintf(stdout, "\tServer:  Trying to recv data from socket.......");
-    if (ap_recv(sock2, datasend, &length) != APR_SUCCESS) {
-        ap_close_socket(sock);
-        ap_close_socket(sock2);
-        fprintf(stderr, "Problem recving data\n");
-        exit(-1);
-    }
-    if (strcmp(datasend, "Send data test")) {
-        ap_close_socket(sock);
-        ap_close_socket(sock2);
-        fprintf(stderr, "I did not receive the correct data %s\n", datarecv);
-        exit(-1);
-    }
-    fprintf(stdout, "OK\n");
-
-    length = STRLEN;
-    fprintf(stdout, "\tServer:  Sending data over socket.......");
-    if (ap_send(sock2, datarecv, &length) != APR_SUCCESS) {
-        ap_close_socket(sock);
-        ap_close_socket(sock2);
-        fprintf(stderr, "Problem sending data\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK\n");
-    
-    fprintf(stdout, "\tServer:  Shutting down accepte socket.......");
-    if (ap_shutdown(sock2, APR_SHUTDOWN_READ) != APR_SUCCESS) {
-        ap_close_socket(sock);
-        ap_close_socket(sock2);
-        fprintf(stderr, "Problem shutting down\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK\n");
-
-    fprintf(stdout, "\tServer:  closing duplicate socket.......");
-    if (ap_close_socket(sock2) != APR_SUCCESS) {
-        ap_close_socket(sock);
-        fprintf(stderr, "Problem closing down\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK\n");
-    
-    fprintf(stdout, "\tServer:  closing original socket.......");
-    if (ap_close_socket(sock) != APR_SUCCESS) {
-        fprintf(stderr, "Problem closing down\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK\n");
-
-    return 1;
-}
-
diff --git a/test/server.dsp b/test/server.dsp
deleted file mode 100644
index 219546b8c28..00000000000
--- a/test/server.dsp
+++ /dev/null
@@ -1,90 +0,0 @@
-# Microsoft Developer Studio Project File - Name="server" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 5.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=server - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "server.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 "server.mak" CFG="server - Win32 Debug"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "server - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "server - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE 
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF  "$(CFG)" == "server - 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 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /W3 /GX /O2 /I "..\include" /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ..\Release\aprlib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"..\Release\server.exe"
-
-!ELSEIF  "$(CFG)" == "server - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "server__"
-# PROP BASE Intermediate_Dir "server__"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "server"
-# PROP Intermediate_Dir "server"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\include" /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "HAVE_STDIO_H" /FD /c
-# SUBTRACT CPP /YX /Yc /Yu
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 ..\Debug\aprlib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\Debug\server.exe" /pdbtype:sept
-
-!ENDIF 
-
-# Begin Target
-
-# Name "server - Win32 Release"
-# Name "server - Win32 Debug"
-# Begin Source File
-
-SOURCE=.\server.c
-# End Source File
-# End Target
-# End Project
diff --git a/test/sockchild.c b/test/sockchild.c
new file mode 100644
index 00000000000..a1116af2bdc
--- /dev/null
+++ b/test/sockchild.c
@@ -0,0 +1,90 @@
+/* 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 <stdlib.h>
+#include "testsock.h"
+#include "apr_network_io.h"
+#include "apr_pools.h"
+
+int main(int argc, char *argv[])
+{
+    apr_pool_t *p;
+    apr_socket_t *sock;
+    apr_status_t rv;
+    apr_sockaddr_t *remote_sa;
+
+    apr_initialize();
+    atexit(apr_terminate);
+    apr_pool_create(&p, NULL);
+
+    if (argc < 3) {
+        exit(-1);
+    }
+
+    rv = apr_sockaddr_info_get(&remote_sa, argv[2], APR_UNSPEC, 8021, 0, p);
+    if (rv != APR_SUCCESS) {
+        exit(-1);
+    }
+
+    if (apr_socket_create(&sock, remote_sa->family, SOCK_STREAM, 0,
+                p) != APR_SUCCESS) {
+        exit(-1);
+    }
+
+    rv = apr_socket_timeout_set(sock, apr_time_from_sec(3));
+    if (rv) {
+        exit(-1);
+    }
+
+    apr_socket_connect(sock, remote_sa);
+        
+    if (!strcmp("read", argv[1])) {
+        char datarecv[STRLEN];
+        apr_size_t length = STRLEN;
+        apr_status_t rv;
+
+        memset(datarecv, 0, STRLEN);
+        rv = apr_socket_recv(sock, datarecv, &length);
+        apr_socket_close(sock);
+        if (APR_STATUS_IS_TIMEUP(rv)) {
+            exit(SOCKET_TIMEOUT); 
+        }
+
+        if (strcmp(datarecv, DATASTR)) {
+            exit(-1);
+        }
+        
+        exit((int)length);
+    }
+    else if (!strcmp("write", argv[1])
+             || !strcmp("write_after_delay", argv[1])) {
+        apr_size_t length = strlen(DATASTR);
+
+        if (!strcmp("write_after_delay", argv[1])) {
+            apr_sleep(apr_time_from_sec(2));
+        }
+
+        apr_socket_send(sock, DATASTR, &length);
+
+        apr_socket_close(sock);
+        exit((int)length);
+    }
+    else if (!strcmp("close", argv[1])) {
+        apr_socket_close(sock);
+        exit(0);
+    }
+    exit(-1);
+}
diff --git a/test/sockperf.c b/test/sockperf.c
new file mode 100644
index 00000000000..a18d8ba3f98
--- /dev/null
+++ b/test/sockperf.c
@@ -0,0 +1,256 @@
+/* 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.
+ */
+
+/* sockperf.c
+ * This simple network client tries to connect to an echo daemon (echod)
+ * listening on a port it supplies, then time how long it takes to
+ * reply with packets of varying sizes.
+ * It prints results once completed.
+ *
+ * To run,
+ *
+ *   ./echod &
+ *   ./sockperf
+ */
+
+#include <stdio.h>
+#include <stdlib.h>  /* for atexit() */
+
+#include "apr.h"
+#include "apr_network_io.h"
+#include "apr_strings.h"
+
+#define MAX_ITERS    10
+#define TEST_SIZE  1024
+
+struct testSet {
+    char c;
+    apr_size_t size;
+    int iters;
+} testRuns[] = {
+    { 'a', 1, 3 },
+    { 'b', 4, 3 },
+    { 'c', 16, 5 },
+    { 'd', 64, 5 },
+    { 'e', 256, 10 },
+};
+
+struct testResult {
+    int size;
+    int iters;
+    apr_time_t msecs[MAX_ITERS];
+    apr_time_t avg;
+};
+
+static apr_int16_t testPort = 4747;
+static apr_sockaddr_t *sockAddr = NULL;
+
+static void reportError(const char *msg, apr_status_t rv, 
+                        apr_pool_t *pool)
+{
+    fprintf(stderr, "%s\n", msg);
+    if (rv != APR_SUCCESS)
+        fprintf(stderr, "Error: %d\n'%s'\n", rv,
+                apr_psprintf(pool, "%pm", &rv));
+    
+}
+
+static void closeConnection(apr_socket_t *sock)
+{
+    apr_size_t len = 0;
+    apr_socket_send(sock, NULL, &len);
+}
+
+static apr_status_t sendRecvBuffer(apr_time_t *t, const char *buf, 
+                                   apr_size_t size, apr_pool_t *pool)
+{
+    apr_socket_t *sock;
+    apr_status_t rv;
+    apr_size_t len = size, thistime = size;
+    char *recvBuf;
+    apr_time_t testStart = apr_time_now(), testEnd;
+    int i;
+
+    if (! sockAddr) {
+        rv = apr_sockaddr_info_get(&sockAddr, "127.0.0.1", APR_UNSPEC,
+                                   testPort, 0, pool);
+        if (rv != APR_SUCCESS) {
+            reportError("Unable to get socket info", rv, pool);
+            return rv;
+        }
+
+        /* make sure we can connect to daemon before we try tests */
+
+        rv = apr_socket_create(&sock, APR_INET, SOCK_STREAM, APR_PROTO_TCP,
+                           pool);
+        if (rv != APR_SUCCESS) {
+            reportError("Unable to create IPv4 stream socket", rv, pool);
+            return rv;
+        }
+
+        rv = apr_socket_connect(sock, sockAddr);
+        if (rv != APR_SUCCESS) {
+            reportError("Unable to connect to echod!", rv, pool);
+            apr_socket_close(sock);
+            return rv;
+        }
+        apr_socket_close(sock);
+
+    }
+
+    recvBuf = apr_palloc(pool, size);
+    if (! recvBuf) {
+        reportError("Unable to allocate buffer", ENOMEM, pool);
+        return ENOMEM;
+    }
+
+    *t = 0;
+
+    /* START! */
+    testStart = apr_time_now();
+    rv = apr_socket_create(&sock, APR_INET, SOCK_STREAM, APR_PROTO_TCP,
+                           pool);
+    if (rv != APR_SUCCESS) {
+        reportError("Unable to create IPv4 stream socket", rv, pool);
+        return rv;
+    }
+
+    rv = apr_socket_connect(sock, sockAddr);
+    if (rv != APR_SUCCESS) {
+        reportError("Unable to connect to echod!", rv, pool);
+        apr_socket_close(sock);
+        return rv;
+    }
+
+    for (i = 0; i < 3; i++) {
+
+        len = size;
+        thistime = size;
+
+        rv = apr_socket_send(sock, buf, &len);
+        if (rv != APR_SUCCESS || len != size) {
+            reportError(apr_psprintf(pool, 
+                         "Unable to send data correctly (iteration %d of 3)",
+                         i) , rv, pool);
+            closeConnection(sock);
+            apr_socket_close(sock);
+            return rv;
+        }
+    
+        do {
+            len = thistime;
+            rv = apr_socket_recv(sock, &recvBuf[size - thistime], &len);
+            if (rv != APR_SUCCESS) {
+                reportError("Error receiving from socket", rv, pool);
+                break;
+            }
+            thistime -= len;
+        } while (thistime);
+    }
+
+    closeConnection(sock);
+    apr_socket_close(sock);
+    testEnd = apr_time_now();
+    /* STOP! */
+
+    if (thistime) {
+        reportError("Received less than we sent :-(", rv, pool);
+        return rv;
+    }        
+    if (strncmp(recvBuf, buf, size) != 0) {
+        reportError("Received corrupt data :-(", 0, pool);
+        printf("We sent:\n%s\nWe received:\n%s\n", buf, recvBuf);
+        return EINVAL;
+    }
+    *t = testEnd - testStart;
+    return APR_SUCCESS;
+}
+
+static apr_status_t runTest(struct testSet *ts, struct testResult *res,
+                            apr_pool_t *pool)
+{
+    char *buffer;
+    apr_status_t rv;
+    int i;
+    apr_size_t sz = ts->size * TEST_SIZE;
+    
+    buffer = apr_palloc(pool, sz);
+    if (!buffer) {
+        reportError("Unable to allocate buffer", ENOMEM, pool);
+        return ENOMEM;
+    }
+    memset(buffer, ts->c, sz);
+
+    res->iters = ts->iters > MAX_ITERS ? MAX_ITERS : ts->iters;
+
+    for (i = 0; i < res->iters; i++) {
+        apr_time_t iterTime;
+        rv = sendRecvBuffer(&iterTime, buffer, sz, pool);
+        if (rv != APR_SUCCESS) {
+            res->iters = i;
+            break;
+        }
+        res->msecs[i] = iterTime;
+    }
+
+    return rv;
+}
+
+int main(int argc, char **argv)
+{
+    apr_pool_t *pool;
+    apr_status_t rv;
+    int i;
+    int nTests = sizeof(testRuns) / sizeof(testRuns[0]);
+    struct testResult *results;
+
+    printf("APR Test Application: sockperf\n");
+
+    apr_initialize();
+    atexit(apr_terminate);
+
+    apr_pool_create(&pool, NULL);
+
+    results = (struct testResult *)apr_pcalloc(pool, 
+                                        sizeof(*results) * nTests);
+
+    for (i = 0; i < nTests; i++) {
+        printf("Test -> %c\n", testRuns[i].c);
+        results[i].size = testRuns[i].size * (apr_size_t)TEST_SIZE;
+        rv = runTest(&testRuns[i], &results[i], pool);
+        if (rv != APR_SUCCESS) {
+            /* error already reported */
+            exit(1);
+        }
+    }
+
+    printf("Tests Complete!\n");
+    for (i = 0; i < nTests; i++) {
+        int j;
+        apr_time_t totTime = 0;
+        printf("%10d byte block:\n", results[i].size);
+        printf("\t%2d iterations : ", results[i].iters);
+        for (j = 0; j < results[i].iters; j++) {
+            printf("%6" APR_TIME_T_FMT, results[i].msecs[j]);
+            totTime += results[i].msecs[j];
+        }
+        printf("<\n");
+        printf("\t  Average: %6" APR_TIME_T_FMT "\n",
+               totTime / results[i].iters);
+    }
+
+    return 0;
+}
diff --git a/test/testall.dsw b/test/testall.dsw
new file mode 100644
index 00000000000..c56452a0a89
--- /dev/null
+++ b/test/testall.dsw
@@ -0,0 +1,137 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "apr"="..\apr.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "aprapp"="..\build\aprapp.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name preaprapp
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "libapr"="..\libapr.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "libaprapp"="..\build\libaprapp.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name prelibaprapp
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "preaprapp"="..\build\preaprapp.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name apr
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "prelibaprapp"="..\build\prelibaprapp.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name libapr
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "testdll"=".\testdll.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name libapr
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name libaprapp
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "testlib"=".\testlib.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name apr
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name aprapp
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/test/testapp.c b/test/testapp.c
new file mode 100644
index 00000000000..77607aa388f
--- /dev/null
+++ b/test/testapp.c
@@ -0,0 +1,10 @@
+#include <apr.h>
+#include <apr_general.h>
+
+int main(int argc, const char * const * argv, const char * const *env)
+{
+    apr_app_initialize(&argc, &argv, &env);
+
+
+    apr_terminate();
+}
diff --git a/test/testarg.dsp b/test/testarg.dsp
deleted file mode 100644
index a9caadec0d4..00000000000
--- a/test/testarg.dsp
+++ /dev/null
@@ -1,91 +0,0 @@
-# Microsoft Developer Studio Project File - Name="testarg" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 5.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=testarg - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "testarg.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 "testarg.mak" CFG="testarg - Win32 Debug"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "testarg - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "testarg - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE 
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF  "$(CFG)" == "testarg - 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 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /W3 /GX /O2 /I "..\include" /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ..\Release\aprlib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"..\Release\testarg.exe"
-# SUBTRACT LINK32 /debug
-
-!ELSEIF  "$(CFG)" == "testarg - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "testarg_"
-# PROP BASE Intermediate_Dir "testarg_"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "testarg"
-# PROP Intermediate_Dir "testarg"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\include" /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
-# SUBTRACT CPP /YX /Yc /Yu
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 ..\Debug\aprlib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\Debug\testarg.exe" /pdbtype:sept
-
-!ENDIF 
-
-# Begin Target
-
-# Name "testarg - Win32 Release"
-# Name "testarg - Win32 Debug"
-# Begin Source File
-
-SOURCE=.\testargs.c
-# End Source File
-# End Target
-# End Project
diff --git a/test/testargs.c b/test/testargs.c
index 52ddf668feb..405b3bed6d1 100644
--- a/test/testargs.c
+++ b/test/testargs.c
@@ -1,96 +1,236 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
-#include "apr_file_io.h"
 #include "apr_errno.h"
 #include "apr_general.h"
-#include "apr_lib.h"
 #include "apr_getopt.h"
-#include <stdio.h>
-#include <stdlib.h>
-#ifdef BEOS
-#include <unistd.h>
-#endif
+#include "apr_strings.h"
+#include "testutil.h"
 
-int main(int argc, char * const argv[])
+static void format_arg(char *str, char option, const char *arg)
 {
-    ap_pool_t *context;
-    ap_int32_t data;
+    if (arg) {
+        apr_snprintf(str, 8196, "%soption: %c with %s\n", str, option, arg);
+    }
+    else {
+        apr_snprintf(str, 8196, "%soption: %c\n", str, option);
+    }
+}
 
-    ap_initialize();
-    atexit(ap_terminate);
-    ap_create_pool(&context, NULL);
+static void unknown_arg(void *str, const char *err, ...)
+{
+    va_list va;
 
-    while (ap_getopt(argc, argv, "abc:d::", &data, context) == APR_SUCCESS) {
-        switch(data) {
+    va_start(va, err);
+    apr_vsnprintf(str, 8196, err, va);
+    va_end(va);
+}
+
+static void no_options_found(abts_case *tc, void *data)
+{
+    int largc = 5;
+    const char * const largv[] = {"testprog", "-a", "-b", "-c", "-d"};
+    apr_getopt_t *opt;
+    apr_status_t rv;
+    char ch;
+    const char *opt_arg;
+    char str[8196];
+
+    str[0] = '\0';
+    rv = apr_getopt_init(&opt, p, largc, largv);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+   
+    while (apr_getopt(opt, "abcd", &ch, &opt_arg) == APR_SUCCESS) {
+        switch (ch) {
+            case 'a':
+            case 'b':
+            case 'c':
+            case 'd':
+            default:
+                format_arg(str, ch, opt_arg);
+        }
+    }
+    ABTS_STR_EQUAL(tc, "option: a\n"
+                          "option: b\n"
+                          "option: c\n"
+                          "option: d\n", str);
+}
+
+static void no_options(abts_case *tc, void *data)
+{
+    int largc = 5;
+    const char * const largv[] = {"testprog", "-a", "-b", "-c", "-d"};
+    apr_getopt_t *opt;
+    apr_status_t rv;
+    char ch;
+    const char *opt_arg;
+    char str[8196];
+
+    str[0] = '\0';
+    rv = apr_getopt_init(&opt, p, largc, largv);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    opt->errfn = unknown_arg;
+    opt->errarg = str;
+   
+    while (apr_getopt(opt, "efgh", &ch, &opt_arg) == APR_SUCCESS) {
+        switch (ch) {
             case 'a':
             case 'b':
-                printf("option %c\n", data);
-                break;
             case 'c':
-                printf("option %c with %s\n", data, ap_optarg);
-                break;
             case 'd':
-                printf("option %c", data);
-                if (ap_optarg) {
-                    printf(" with %s\n", ap_optarg);
-                }
-                else {
-                    printf("\n");
-                }
+                format_arg(str, ch, opt_arg);
+                break;
+            default:
+                break;
+        }
+    }
+    ABTS_STR_EQUAL(tc, "testprog: illegal option -- a\n", str);
+}
+
+static void required_option(abts_case *tc, void *data)
+{
+    int largc = 3;
+    const char * const largv[] = {"testprog", "-a", "foo"};
+    apr_getopt_t *opt;
+    apr_status_t rv;
+    char ch;
+    const char *opt_arg;
+    char str[8196];
+
+    str[0] = '\0';
+    rv = apr_getopt_init(&opt, p, largc, largv);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    opt->errfn = unknown_arg;
+    opt->errarg = str;
+   
+    while (apr_getopt(opt, "a:", &ch, &opt_arg) == APR_SUCCESS) {
+        switch (ch) {
+            case 'a':
+                format_arg(str, ch, opt_arg);
+                break;
+            default:
+                break;
+        }
+    }
+    ABTS_STR_EQUAL(tc, "option: a with foo\n", str);
+}
+
+static void required_option_notgiven(abts_case *tc, void *data)
+{
+    int largc = 2;
+    const char * const largv[] = {"testprog", "-a"};
+    apr_getopt_t *opt;
+    apr_status_t rv;
+    char ch;
+    const char *opt_arg;
+    char str[8196];
+
+    str[0] = '\0';
+    rv = apr_getopt_init(&opt, p, largc, largv);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    opt->errfn = unknown_arg;
+    opt->errarg = str;
+   
+    while (apr_getopt(opt, "a:", &ch, &opt_arg) == APR_SUCCESS) {
+        switch (ch) {
+            case 'a':
+                format_arg(str, ch, opt_arg);
+                break;
+            default:
+                break;
+        }
+    }
+    ABTS_STR_EQUAL(tc, "testprog: option requires an argument -- a\n", str);
+}
+
+static void optional_option(abts_case *tc, void *data)
+{
+    int largc = 3;
+    const char * const largv[] = {"testprog", "-a", "foo"};
+    apr_getopt_t *opt;
+    apr_status_t rv;
+    char ch;
+    const char *opt_arg;
+    char str[8196];
+
+    str[0] = '\0';
+    rv = apr_getopt_init(&opt, p, largc, largv);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    opt->errfn = unknown_arg;
+    opt->errarg = str;
+   
+    while (apr_getopt(opt, "a::", &ch, &opt_arg) == APR_SUCCESS) {
+        switch (ch) {
+            case 'a':
+                format_arg(str, ch, opt_arg);
+                break;
+            default:
                 break;
         }
     }
-    return 1;
+    ABTS_STR_EQUAL(tc, "option: a with foo\n", str);
+}
+
+static void optional_option_notgiven(abts_case *tc, void *data)
+{
+    int largc = 2;
+    const char * const largv[] = {"testprog", "-a"};
+    apr_getopt_t *opt;
+    apr_status_t rv;
+    char ch;
+    const char *opt_arg;
+    char str[8196];
+
+    str[0] = '\0';
+    rv = apr_getopt_init(&opt, p, largc, largv);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    opt->errfn = unknown_arg;
+    opt->errarg = str;
+   
+    while (apr_getopt(opt, "a::", &ch, &opt_arg) == APR_SUCCESS) {
+        switch (ch) {
+            case 'a':
+                format_arg(str, ch, opt_arg);
+                break;
+            default:
+                break;
+        }
+    }
+#if 0
+/*  Our version of getopt doesn't allow for optional arguments.  */
+    ABTS_STR_EQUAL(tc, "option: a\n", str);
+#endif
+    ABTS_STR_EQUAL(tc, "testprog: option requires an argument -- a\n", str);
+}
+
+abts_suite *testgetopt(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite)
+
+    abts_run_test(suite, no_options, NULL);
+    abts_run_test(suite, no_options_found, NULL);
+    abts_run_test(suite, required_option, NULL);
+    abts_run_test(suite, required_option_notgiven, NULL);
+    abts_run_test(suite, optional_option, NULL);
+    abts_run_test(suite, optional_option_notgiven, NULL);
+
+    return suite;
 }
diff --git a/test/testatomic.c b/test/testatomic.c
new file mode 100644
index 00000000000..4bf2caa4688
--- /dev/null
+++ b/test/testatomic.c
@@ -0,0 +1,536 @@
+/* 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 "testutil.h"
+#include "apr_strings.h"
+#include "apr_thread_proc.h"
+#include "apr_errno.h"
+#include "apr_general.h"
+#include "apr_atomic.h"
+#include "apr_time.h"
+
+/* Use pthread_setconcurrency where it is available and not a nullop,
+ * i.e. platforms using M:N or M:1 thread models: */
+#if APR_HAS_THREADS && \
+   ((defined(SOLARIS2) && SOLARIS2 > 6) || defined(_AIX))
+/* also HP-UX, IRIX? ... */
+#define HAVE_PTHREAD_SETCONCURRENCY
+#endif
+
+#ifdef HAVE_PTHREAD_SETCONCURRENCY
+#include <pthread.h>
+#endif
+
+static void test_init(abts_case *tc, void *data)
+{
+    APR_ASSERT_SUCCESS(tc, "Could not initliaze atomics", apr_atomic_init(p));
+}
+
+static void test_set32(abts_case *tc, void *data)
+{
+    apr_uint32_t y32;
+    apr_atomic_set32(&y32, 2);
+    ABTS_INT_EQUAL(tc, 2, y32);
+}
+
+static void test_read32(abts_case *tc, void *data)
+{
+    apr_uint32_t y32;
+    apr_atomic_set32(&y32, 2);
+    ABTS_INT_EQUAL(tc, 2, apr_atomic_read32(&y32));
+}
+
+static void test_dec32(abts_case *tc, void *data)
+{
+    apr_uint32_t y32;
+    int rv;
+
+    apr_atomic_set32(&y32, 2);
+
+    rv = apr_atomic_dec32(&y32);
+    ABTS_INT_EQUAL(tc, 1, y32);
+    ABTS_ASSERT(tc, "atomic_dec returned zero when it shouldn't", rv != 0);
+
+    rv = apr_atomic_dec32(&y32);
+    ABTS_INT_EQUAL(tc, 0, y32);
+    ABTS_ASSERT(tc, "atomic_dec didn't returned zero when it should", rv == 0);
+}
+
+static void test_xchg32(abts_case *tc, void *data)
+{
+    apr_uint32_t oldval;
+    apr_uint32_t y32;
+
+    apr_atomic_set32(&y32, 100);
+    oldval = apr_atomic_xchg32(&y32, 50);
+
+    ABTS_INT_EQUAL(tc, 100, oldval);
+    ABTS_INT_EQUAL(tc, 50, y32);
+}
+
+static void test_xchgptr(abts_case *tc, void *data)
+{
+    int a;
+    void *ref = "little piggy";
+    void *target_ptr = ref;
+    void *old_ptr;
+
+    old_ptr = apr_atomic_xchgptr(&target_ptr, &a);
+    ABTS_PTR_EQUAL(tc, ref, old_ptr);
+    ABTS_PTR_EQUAL(tc, &a, (void *) target_ptr);
+}
+
+static void test_cas_equal(abts_case *tc, void *data)
+{
+    apr_uint32_t casval = 0;
+    apr_uint32_t oldval;
+
+    oldval = apr_atomic_cas32(&casval, 12, 0);
+    ABTS_INT_EQUAL(tc, 0, oldval);
+    ABTS_INT_EQUAL(tc, 12, casval);
+}
+
+static void test_cas_equal_nonnull(abts_case *tc, void *data)
+{
+    apr_uint32_t casval = 12;
+    apr_uint32_t oldval;
+
+    oldval = apr_atomic_cas32(&casval, 23, 12);
+    ABTS_INT_EQUAL(tc, 12, oldval);
+    ABTS_INT_EQUAL(tc, 23, casval);
+}
+
+static void test_cas_notequal(abts_case *tc, void *data)
+{
+    apr_uint32_t casval = 12;
+    apr_uint32_t oldval;
+
+    oldval = apr_atomic_cas32(&casval, 23, 2);
+    ABTS_INT_EQUAL(tc, 12, oldval);
+    ABTS_INT_EQUAL(tc, 12, casval);
+}
+
+static void test_casptr_equal(abts_case *tc, void *data)
+{
+    int a;
+    void *target_ptr = NULL;
+    void *old_ptr;
+
+    old_ptr = apr_atomic_casptr(&target_ptr, &a, NULL);
+    ABTS_PTR_EQUAL(tc, NULL, old_ptr);
+    ABTS_PTR_EQUAL(tc, &a, (void *) target_ptr);
+}
+
+static void test_casptr_equal_nonnull(abts_case *tc, void *data)
+{
+    int a, b;
+    void *target_ptr = &a;
+    void *old_ptr;
+
+    old_ptr = apr_atomic_casptr(&target_ptr, &b, &a);
+    ABTS_PTR_EQUAL(tc, &a, old_ptr);
+    ABTS_PTR_EQUAL(tc, &b, (void *) target_ptr);
+}
+
+static void test_casptr_notequal(abts_case *tc, void *data)
+{
+    int a, b;
+    void *target_ptr = &a;
+    void *old_ptr;
+
+    old_ptr = apr_atomic_casptr(&target_ptr, &a, &b);
+    ABTS_PTR_EQUAL(tc, &a, old_ptr);
+    ABTS_PTR_EQUAL(tc, &a, (void *) target_ptr);
+}
+
+static void test_add32(abts_case *tc, void *data)
+{
+    apr_uint32_t oldval;
+    apr_uint32_t y32;
+
+    apr_atomic_set32(&y32, 23);
+    oldval = apr_atomic_add32(&y32, 4);
+    ABTS_INT_EQUAL(tc, 23, oldval);
+    ABTS_INT_EQUAL(tc, 27, y32);
+}
+
+static void test_add32_neg(abts_case *tc, void *data)
+{
+    apr_uint32_t oldval;
+    apr_uint32_t y32;
+
+    apr_atomic_set32(&y32, 23);
+    oldval = apr_atomic_add32(&y32, -10);
+    ABTS_INT_EQUAL(tc, 23, oldval);
+    ABTS_INT_EQUAL(tc, 13, y32);
+}
+
+static void test_inc32(abts_case *tc, void *data)
+{
+    apr_uint32_t oldval;
+    apr_uint32_t y32;
+
+    apr_atomic_set32(&y32, 23);
+    oldval = apr_atomic_inc32(&y32);
+    ABTS_INT_EQUAL(tc, 23, oldval);
+    ABTS_INT_EQUAL(tc, 24, y32);
+}
+
+static void test_set_add_inc_sub(abts_case *tc, void *data)
+{
+    apr_uint32_t y32;
+
+    apr_atomic_set32(&y32, 0);
+    apr_atomic_add32(&y32, 20);
+    apr_atomic_inc32(&y32);
+    apr_atomic_sub32(&y32, 10);
+
+    ABTS_INT_EQUAL(tc, 11, y32);
+}
+
+static void test_wrap_zero(abts_case *tc, void *data)
+{
+    apr_uint32_t y32;
+    apr_uint32_t rv;
+    apr_uint32_t minus1 = (apr_uint32_t)-1;
+    char *str;
+
+    apr_atomic_set32(&y32, 0);
+    rv = apr_atomic_dec32(&y32);
+
+    ABTS_ASSERT(tc, "apr_atomic_dec32 on zero returned zero.", rv != 0);
+    str = apr_psprintf(p, "zero wrap failed: 0 - 1 = %d", y32);
+    ABTS_ASSERT(tc, str, y32 == minus1);
+}
+
+static void test_inc_neg1(abts_case *tc, void *data)
+{
+    apr_uint32_t y32 = (apr_uint32_t)-1;
+    apr_uint32_t minus1 = (apr_uint32_t)-1;
+    apr_uint32_t rv;
+    char *str;
+
+    rv = apr_atomic_inc32(&y32);
+
+    ABTS_ASSERT(tc, "apr_atomic_inc32 didn't return the old value.", rv == minus1);
+    str = apr_psprintf(p, "zero wrap failed: -1 + 1 = %d", y32);
+    ABTS_ASSERT(tc, str, y32 == 0);
+}
+
+
+#if APR_HAS_THREADS
+
+void *APR_THREAD_FUNC thread_func_mutex(apr_thread_t *thd, void *data);
+void *APR_THREAD_FUNC thread_func_atomic(apr_thread_t *thd, void *data);
+
+apr_thread_mutex_t *thread_lock;
+volatile apr_uint32_t mutex_locks = 0;
+volatile apr_uint32_t atomic_ops = 0;
+apr_status_t exit_ret_val = 123; /* just some made up number to check on later */
+
+#define NUM_THREADS 40
+#define NUM_ITERATIONS 20000
+
+void *APR_THREAD_FUNC thread_func_mutex(apr_thread_t *thd, void *data)
+{
+    int i;
+
+    for (i = 0; i < NUM_ITERATIONS; i++) {
+        apr_thread_mutex_lock(thread_lock);
+        mutex_locks++;
+        apr_thread_mutex_unlock(thread_lock);
+    }
+    apr_thread_exit(thd, exit_ret_val);
+    return NULL;
+}
+
+void *APR_THREAD_FUNC thread_func_atomic(apr_thread_t *thd, void *data)
+{
+    int i;
+
+    for (i = 0; i < NUM_ITERATIONS ; i++) {
+        apr_atomic_inc32(&atomic_ops);
+        apr_atomic_add32(&atomic_ops, 2);
+        apr_atomic_dec32(&atomic_ops);
+        apr_atomic_dec32(&atomic_ops);
+    }
+    apr_thread_exit(thd, exit_ret_val);
+    return NULL;
+}
+
+static void test_atomics_threaded(abts_case *tc, void *data)
+{
+    apr_thread_t *t1[NUM_THREADS];
+    apr_thread_t *t2[NUM_THREADS];
+    apr_status_t rv;
+    int i;
+
+#ifdef HAVE_PTHREAD_SETCONCURRENCY
+    pthread_setconcurrency(8);
+#endif
+
+    rv = apr_thread_mutex_create(&thread_lock, APR_THREAD_MUTEX_DEFAULT, p);
+    APR_ASSERT_SUCCESS(tc, "Could not create lock", rv);
+
+    for (i = 0; i < NUM_THREADS; i++) {
+        apr_status_t r1, r2;
+        r1 = apr_thread_create(&t1[i], NULL, thread_func_mutex, NULL, p);
+        r2 = apr_thread_create(&t2[i], NULL, thread_func_atomic, NULL, p);
+        ABTS_ASSERT(tc, "Failed creating threads", !r1 && !r2);
+    }
+
+    for (i = 0; i < NUM_THREADS; i++) {
+        apr_status_t s1, s2;
+        apr_thread_join(&s1, t1[i]);
+        apr_thread_join(&s2, t2[i]);
+
+        ABTS_ASSERT(tc, "Invalid return value from thread_join",
+                    s1 == exit_ret_val && s2 == exit_ret_val);
+    }
+
+    ABTS_INT_EQUAL(tc, NUM_THREADS * NUM_ITERATIONS, mutex_locks);
+    ABTS_INT_EQUAL(tc, NUM_THREADS * NUM_ITERATIONS,
+                   apr_atomic_read32(&atomic_ops));
+
+    rv = apr_thread_mutex_destroy(thread_lock);
+    ABTS_ASSERT(tc, "Failed creating threads", rv == APR_SUCCESS);
+}
+
+#undef NUM_THREADS
+#define NUM_THREADS 7
+
+typedef struct tbox_t tbox_t;
+
+struct tbox_t {
+    abts_case *tc;
+    apr_uint32_t *mem;
+    apr_uint32_t preval;
+    apr_uint32_t postval;
+    apr_uint32_t loop;
+    void (*func)(tbox_t *box);
+};
+
+static APR_INLINE void busyloop_read32(tbox_t *tbox)
+{
+    apr_uint32_t val;
+
+    do {
+        val = apr_atomic_read32(tbox->mem);
+
+        if (val != tbox->preval)
+            apr_thread_yield();
+        else
+            break;
+    } while (1);
+}
+
+static void busyloop_set32(tbox_t *tbox)
+{
+    do {
+        busyloop_read32(tbox);
+        apr_atomic_set32(tbox->mem, tbox->postval);
+    } while (--tbox->loop);
+}
+
+static void busyloop_add32(tbox_t *tbox)
+{
+    apr_uint32_t val;
+
+    do {
+        busyloop_read32(tbox);
+        val = apr_atomic_add32(tbox->mem, tbox->postval);
+        apr_thread_mutex_lock(thread_lock);
+        ABTS_INT_EQUAL(tbox->tc, val, tbox->preval);
+        apr_thread_mutex_unlock(thread_lock);
+    } while (--tbox->loop);
+}
+
+static void busyloop_sub32(tbox_t *tbox)
+{
+    do {
+        busyloop_read32(tbox);
+        apr_atomic_sub32(tbox->mem, tbox->postval);
+    } while (--tbox->loop);
+}
+
+static void busyloop_inc32(tbox_t *tbox)
+{
+    apr_uint32_t val;
+
+    do {
+        busyloop_read32(tbox);
+        val = apr_atomic_inc32(tbox->mem);
+        apr_thread_mutex_lock(thread_lock);
+        ABTS_INT_EQUAL(tbox->tc, val, tbox->preval);
+        apr_thread_mutex_unlock(thread_lock);
+    } while (--tbox->loop);
+}
+
+static void busyloop_dec32(tbox_t *tbox)
+{
+    apr_uint32_t val;
+
+    do {
+        busyloop_read32(tbox);
+        val = apr_atomic_dec32(tbox->mem);
+        apr_thread_mutex_lock(thread_lock);
+        ABTS_INT_NEQUAL(tbox->tc, 0, val);
+        apr_thread_mutex_unlock(thread_lock);
+    } while (--tbox->loop);
+}
+
+static void busyloop_cas32(tbox_t *tbox)
+{
+    apr_uint32_t val;
+
+    do {
+        do {
+            val = apr_atomic_cas32(tbox->mem, tbox->postval, tbox->preval);
+
+            if (val != tbox->preval)
+                apr_thread_yield();
+            else
+                break;
+        } while (1);
+    } while (--tbox->loop);
+}
+
+static void busyloop_xchg32(tbox_t *tbox)
+{
+    apr_uint32_t val;
+
+    do {
+        busyloop_read32(tbox);
+        val = apr_atomic_xchg32(tbox->mem, tbox->postval);
+        apr_thread_mutex_lock(thread_lock);
+        ABTS_INT_EQUAL(tbox->tc, val, tbox->preval);
+        apr_thread_mutex_unlock(thread_lock);
+    } while (--tbox->loop);
+}
+
+static void *APR_THREAD_FUNC thread_func_busyloop(apr_thread_t *thd, void *data)
+{
+    tbox_t *tbox = data;
+
+    tbox->func(tbox);
+
+    apr_thread_exit(thd, 0);
+
+    return NULL;
+}
+
+static void test_atomics_busyloop_threaded(abts_case *tc, void *data)
+{
+    unsigned int i;
+    apr_status_t rv;
+    apr_uint32_t count = 0;
+    tbox_t tbox[NUM_THREADS];
+    apr_thread_t *thread[NUM_THREADS];
+
+    rv = apr_thread_mutex_create(&thread_lock, APR_THREAD_MUTEX_DEFAULT, p);
+    APR_ASSERT_SUCCESS(tc, "Could not create lock", rv);
+
+    /* get ready */
+    for (i = 0; i < NUM_THREADS; i++) {
+        tbox[i].tc = tc;
+        tbox[i].mem = &count;
+        tbox[i].loop = 50;
+    }
+
+    tbox[0].preval = 98;
+    tbox[0].postval = 3891;
+    tbox[0].func = busyloop_add32;
+
+    tbox[1].preval = 3989;
+    tbox[1].postval = 1010;
+    tbox[1].func = busyloop_sub32;
+
+    tbox[2].preval = 2979;
+    tbox[2].postval = 0; /* not used */
+    tbox[2].func = busyloop_inc32;
+
+    tbox[3].preval = 2980;
+    tbox[3].postval = 16384;
+    tbox[3].func = busyloop_set32;
+
+    tbox[4].preval = 16384;
+    tbox[4].postval = 0; /* not used */
+    tbox[4].func = busyloop_dec32;
+
+    tbox[5].preval = 16383;
+    tbox[5].postval = 1048576;
+    tbox[5].func = busyloop_cas32;
+
+    tbox[6].preval = 1048576;
+    tbox[6].postval = 98; /* goto tbox[0] */
+    tbox[6].func = busyloop_xchg32;
+
+    /* get set */
+    for (i = 0; i < NUM_THREADS; i++) {
+        rv = apr_thread_create(&thread[i], NULL, thread_func_busyloop,
+                               &tbox[i], p);
+        ABTS_ASSERT(tc, "Failed creating thread", rv == APR_SUCCESS);
+    }
+
+    /* go! */
+    apr_atomic_set32(tbox->mem, 98);
+
+    for (i = 0; i < NUM_THREADS; i++) {
+        apr_status_t retval;
+        rv = apr_thread_join(&retval, thread[i]);
+        ABTS_ASSERT(tc, "Thread join failed", rv == APR_SUCCESS);
+        ABTS_ASSERT(tc, "Invalid return value from thread_join", retval == 0);
+    }
+
+    ABTS_INT_EQUAL(tbox->tc, 98, count);
+
+    rv = apr_thread_mutex_destroy(thread_lock);
+    ABTS_ASSERT(tc, "Failed creating threads", rv == APR_SUCCESS);
+}
+
+#endif /* !APR_HAS_THREADS */
+
+abts_suite *testatomic(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite)
+
+    abts_run_test(suite, test_init, NULL);
+    abts_run_test(suite, test_set32, NULL);
+    abts_run_test(suite, test_read32, NULL);
+    abts_run_test(suite, test_dec32, NULL);
+    abts_run_test(suite, test_xchg32, NULL);
+    abts_run_test(suite, test_xchgptr, NULL);
+    abts_run_test(suite, test_cas_equal, NULL);
+    abts_run_test(suite, test_cas_equal_nonnull, NULL);
+    abts_run_test(suite, test_cas_notequal, NULL);
+    abts_run_test(suite, test_casptr_equal, NULL);
+    abts_run_test(suite, test_casptr_equal_nonnull, NULL);
+    abts_run_test(suite, test_casptr_notequal, NULL);
+    abts_run_test(suite, test_add32, NULL);
+    abts_run_test(suite, test_add32_neg, NULL);
+    abts_run_test(suite, test_inc32, NULL);
+    abts_run_test(suite, test_set_add_inc_sub, NULL);
+    abts_run_test(suite, test_wrap_zero, NULL);
+    abts_run_test(suite, test_inc_neg1, NULL);
+
+#if APR_HAS_THREADS
+    abts_run_test(suite, test_atomics_threaded, NULL);
+    abts_run_test(suite, test_atomics_busyloop_threaded, NULL);
+#endif
+
+    return suite;
+}
+
diff --git a/test/testbase64.c b/test/testbase64.c
new file mode 100644
index 00000000000..92cccb712f0
--- /dev/null
+++ b/test/testbase64.c
@@ -0,0 +1,84 @@
+/* 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 <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "apr_base64.h"
+
+#include "abts.h"
+#include "testutil.h"
+
+static struct {
+   const char *orig;
+   const char *enc;
+} base64_tbl[] =
+{
+    {"", ""},
+    {"H", "SA=="},
+    {"He", "SGU="},
+    {"Hel", "SGVs"},
+    {"Hell", "SGVsbA=="},
+    {"Hello", "SGVsbG8="},
+    {"Hello World", "SGVsbG8gV29ybGQ="},
+    {"\xff\xff\xff\xff", "/////w=="},
+};
+static int num_base64 = sizeof(base64_tbl) / sizeof(base64_tbl[0]);
+
+static void test_base64(abts_case *tc, void *data)
+{
+    apr_pool_t *pool;
+    int i;
+
+    apr_pool_create(&pool, NULL);
+
+    for (i = 0; i < num_base64; i++) {
+        char *enc;
+        int orig_len, enc_len, b64_len, b64_enc_len;
+
+        apr_pool_clear(pool);
+
+        orig_len = strlen(base64_tbl[i].orig);
+        enc_len = strlen(base64_tbl[i].enc);
+
+        /* includes + 1 for term null */
+        b64_enc_len = apr_base64_encode_len(orig_len);
+        ABTS_ASSERT(tc, "base 64 exp. length", (enc_len == (b64_enc_len - 1)));
+
+        enc = apr_palloc(pool, b64_enc_len);
+
+        b64_len = apr_base64_encode(enc, base64_tbl[i].orig, orig_len);
+
+        ABTS_ASSERT(tc, "base 64 encoded length", (b64_enc_len == b64_len));
+        ABTS_ASSERT(tc, "base 64 encoded matches expected output",
+                    (memcmp(enc, base64_tbl[i].enc, b64_enc_len) == 0));
+
+        enc = apr_pbase64_encode(pool, base64_tbl[i].orig);
+        ABTS_ASSERT(tc, "base 64 encoded from pool matches expected output",
+                (strcmp(enc, base64_tbl[i].enc) == 0));
+        ABTS_ASSERT(tc, "base 64 length", strlen(enc) == strlen(base64_tbl[i].enc));
+    }
+}
+
+abts_suite *testbase64(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite);
+
+    abts_run_test(suite, test_base64, NULL);
+
+    return suite;
+}
diff --git a/test/testbuckets.c b/test/testbuckets.c
new file mode 100644
index 00000000000..077a139361d
--- /dev/null
+++ b/test/testbuckets.c
@@ -0,0 +1,535 @@
+/* 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 "abts.h"
+#include "testutil.h"
+#include "apr_buckets.h"
+#include "apr_strings.h"
+
+static void test_create(abts_case *tc, void *data)
+{
+    apr_bucket_alloc_t *ba;
+    apr_bucket_brigade *bb;
+
+    ba = apr_bucket_alloc_create(p);
+    bb = apr_brigade_create(p, ba);
+
+    ABTS_ASSERT(tc, "new brigade not NULL", bb != NULL);
+    ABTS_ASSERT(tc, "new brigade is empty", APR_BRIGADE_EMPTY(bb));
+
+    apr_brigade_destroy(bb);
+    apr_bucket_alloc_destroy(ba);
+}
+
+static void test_simple(abts_case *tc, void *data)
+{
+    apr_bucket_alloc_t *ba;
+    apr_bucket_brigade *bb;
+    apr_bucket *fb, *tb;
+    
+    ba = apr_bucket_alloc_create(p);
+    bb = apr_brigade_create(p, ba);
+    
+    fb = APR_BRIGADE_FIRST(bb);
+    ABTS_ASSERT(tc, "first bucket of empty brigade is sentinel",
+                fb == APR_BRIGADE_SENTINEL(bb));
+
+    fb = apr_bucket_flush_create(ba);
+    APR_BRIGADE_INSERT_HEAD(bb, fb);
+
+    ABTS_ASSERT(tc, "first bucket of brigade is flush",
+                APR_BRIGADE_FIRST(bb) == fb);
+
+    ABTS_ASSERT(tc, "bucket after flush is sentinel",
+                APR_BUCKET_NEXT(fb) == APR_BRIGADE_SENTINEL(bb));
+
+    tb = apr_bucket_transient_create("aaa", 3, ba);
+    APR_BUCKET_INSERT_BEFORE(fb, tb);
+
+    ABTS_ASSERT(tc, "bucket before flush now transient",
+                APR_BUCKET_PREV(fb) == tb);
+    ABTS_ASSERT(tc, "bucket after transient is flush",
+                APR_BUCKET_NEXT(tb) == fb);
+    ABTS_ASSERT(tc, "bucket before transient is sentinel",
+                APR_BUCKET_PREV(tb) == APR_BRIGADE_SENTINEL(bb));
+
+    apr_brigade_cleanup(bb);
+
+    ABTS_ASSERT(tc, "cleaned up brigade was empty", APR_BRIGADE_EMPTY(bb));
+
+    apr_brigade_destroy(bb);
+    apr_bucket_alloc_destroy(ba);
+}
+
+static apr_bucket_brigade *make_simple_brigade(apr_bucket_alloc_t *ba,
+                                               const char *first, 
+                                               const char *second)
+{
+    apr_bucket_brigade *bb = apr_brigade_create(p, ba);
+    apr_bucket *e;
+ 
+    e = apr_bucket_transient_create(first, strlen(first), ba);
+    APR_BRIGADE_INSERT_TAIL(bb, e);
+
+    e = apr_bucket_transient_create(second, strlen(second), ba);
+    APR_BRIGADE_INSERT_TAIL(bb, e);
+
+    return bb;
+}
+
+/* tests that 'bb' flattens to string 'expect'. */
+static void flatten_match(abts_case *tc, const char *ctx,
+                          apr_bucket_brigade *bb,
+                          const char *expect)
+{
+    apr_size_t elen = strlen(expect);
+    char *buf = malloc(elen);
+    apr_size_t len = elen;
+    char msg[200];
+
+    sprintf(msg, "%s: flatten brigade", ctx);
+    APR_ASSERT_SUCCESS(tc, msg, apr_brigade_flatten(bb, buf, &len));
+    sprintf(msg, "%s: length match (%ld not %ld)", ctx,
+            (long)len, (long)elen);
+    ABTS_ASSERT(tc, msg, len == elen);
+    sprintf(msg, "%s: result match", msg);
+    ABTS_STR_NEQUAL(tc, expect, buf, len);
+    free(buf);
+}
+
+static void test_flatten(abts_case *tc, void *data)
+{
+    apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
+    apr_bucket_brigade *bb;
+
+    bb = make_simple_brigade(ba, "hello, ", "world");
+
+    flatten_match(tc, "flatten brigade", bb, "hello, world");
+
+    apr_brigade_destroy(bb);
+    apr_bucket_alloc_destroy(ba);    
+}
+
+static int count_buckets(apr_bucket_brigade *bb)
+{
+    apr_bucket *e;
+    int count = 0;
+
+    for (e = APR_BRIGADE_FIRST(bb); 
+         e != APR_BRIGADE_SENTINEL(bb);
+         e = APR_BUCKET_NEXT(e)) {
+        count++;
+    }
+    
+    return count;
+}
+
+static void test_split(abts_case *tc, void *data)
+{
+    apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
+    apr_bucket_brigade *bb, *bb2;
+    apr_bucket *e;
+
+    bb = make_simple_brigade(ba, "hello, ", "world");
+
+    /* split at the "world" bucket */
+    e = APR_BRIGADE_LAST(bb);
+    bb2 = apr_brigade_split(bb, e);
+
+    ABTS_ASSERT(tc, "split brigade contains one bucket",
+                count_buckets(bb2) == 1);
+    ABTS_ASSERT(tc, "original brigade contains one bucket",
+                count_buckets(bb) == 1);
+
+    flatten_match(tc, "match original brigade", bb, "hello, ");
+    flatten_match(tc, "match split brigade", bb2, "world");
+
+    apr_brigade_destroy(bb2);
+    apr_brigade_destroy(bb);
+    apr_bucket_alloc_destroy(ba);
+}
+
+#define COUNT 3000
+#define THESTR "hello"
+
+static void test_bwrite(abts_case *tc, void *data)
+{
+    apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
+    apr_bucket_brigade *bb = apr_brigade_create(p, ba);
+    apr_off_t length;
+    int n;
+
+    for (n = 0; n < COUNT; n++) {
+        APR_ASSERT_SUCCESS(tc, "brigade_write", 
+                           apr_brigade_write(bb, NULL, NULL,
+                                             THESTR, sizeof THESTR));
+    }
+
+    APR_ASSERT_SUCCESS(tc, "determine brigade length",
+                       apr_brigade_length(bb, 1, &length));
+
+    ABTS_ASSERT(tc, "brigade has correct length",
+                length == (COUNT * sizeof THESTR));
+    
+    apr_brigade_destroy(bb);
+    apr_bucket_alloc_destroy(ba);
+}
+
+static void test_splitline(abts_case *tc, void *data)
+{
+    apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
+    apr_bucket_brigade *bin, *bout;
+
+    bin = make_simple_brigade(ba, "blah blah blah-",
+                              "end of line.\nfoo foo foo");
+    bout = apr_brigade_create(p, ba);
+
+    APR_ASSERT_SUCCESS(tc, "split line",
+                       apr_brigade_split_line(bout, bin,
+                                              APR_BLOCK_READ, 100));
+
+    flatten_match(tc, "split line", bout, "blah blah blah-end of line.\n");
+    flatten_match(tc, "remainder", bin, "foo foo foo");
+
+    apr_brigade_destroy(bout);
+    apr_brigade_destroy(bin);
+    apr_bucket_alloc_destroy(ba);
+}
+
+/* Test that bucket E has content EDATA of length ELEN. */
+static void test_bucket_content(abts_case *tc,
+                                apr_bucket *e,
+                                const char *edata,
+                                apr_size_t elen)
+{
+    const char *adata;
+    apr_size_t alen;
+
+    APR_ASSERT_SUCCESS(tc, "read from bucket",
+                       apr_bucket_read(e, &adata, &alen, 
+                                       APR_BLOCK_READ));
+
+    ABTS_ASSERT(tc, "read expected length", alen == elen);
+    ABTS_STR_NEQUAL(tc, edata, adata, elen);
+}
+
+static void test_splits(abts_case *tc, void *ctx)
+{
+    apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
+    apr_bucket_brigade *bb;
+    apr_bucket *e;
+    char *str = "alphabeta";
+    int n;
+
+    bb = apr_brigade_create(p, ba);
+
+    APR_BRIGADE_INSERT_TAIL(bb,
+                            apr_bucket_immortal_create(str, 9, ba));
+    APR_BRIGADE_INSERT_TAIL(bb, 
+                            apr_bucket_transient_create(str, 9, ba));
+    APR_BRIGADE_INSERT_TAIL(bb, 
+                            apr_bucket_heap_create(strdup(str), 9, free, ba));
+    APR_BRIGADE_INSERT_TAIL(bb, 
+                            apr_bucket_pool_create(apr_pstrdup(p, str), 9, p, 
+                                                   ba));
+
+    ABTS_ASSERT(tc, "four buckets inserted", count_buckets(bb) == 4);
+    
+    /* now split each of the buckets after byte 5 */
+    for (n = 0, e = APR_BRIGADE_FIRST(bb); n < 4; n++) {
+        ABTS_ASSERT(tc, "reached end of brigade", 
+                    e != APR_BRIGADE_SENTINEL(bb));
+        ABTS_ASSERT(tc, "split bucket OK",
+                    apr_bucket_split(e, 5) == APR_SUCCESS);
+        e = APR_BUCKET_NEXT(e);
+        ABTS_ASSERT(tc, "split OK", e != APR_BRIGADE_SENTINEL(bb));
+        e = APR_BUCKET_NEXT(e);
+    }
+    
+    ABTS_ASSERT(tc, "four buckets split into eight", 
+                count_buckets(bb) == 8);
+
+    for (n = 0, e = APR_BRIGADE_FIRST(bb); n < 4; n++) {
+        const char *data;
+        apr_size_t len;
+        
+        APR_ASSERT_SUCCESS(tc, "read alpha from bucket",
+                           apr_bucket_read(e, &data, &len, APR_BLOCK_READ));
+        ABTS_ASSERT(tc, "read 5 bytes", len == 5);
+        ABTS_STR_NEQUAL(tc, "alpha", data, 5);
+
+        e = APR_BUCKET_NEXT(e);
+
+        APR_ASSERT_SUCCESS(tc, "read beta from bucket",
+                           apr_bucket_read(e, &data, &len, APR_BLOCK_READ));
+        ABTS_ASSERT(tc, "read 4 bytes", len == 4);
+        ABTS_STR_NEQUAL(tc, "beta", data, 5);
+
+        e = APR_BUCKET_NEXT(e);
+    }
+
+    /* now delete the "alpha" buckets */
+    for (n = 0, e = APR_BRIGADE_FIRST(bb); n < 4; n++) {
+        apr_bucket *f;
+
+        ABTS_ASSERT(tc, "reached end of brigade",
+                    e != APR_BRIGADE_SENTINEL(bb));
+        f = APR_BUCKET_NEXT(e);
+        apr_bucket_delete(e);
+        e = APR_BUCKET_NEXT(f);
+    }    
+    
+    ABTS_ASSERT(tc, "eight buckets reduced to four", 
+                count_buckets(bb) == 4);
+
+    flatten_match(tc, "flatten beta brigade", bb,
+                  "beta" "beta" "beta" "beta");
+
+    apr_brigade_destroy(bb);
+    apr_bucket_alloc_destroy(ba);
+}
+
+#define TIF_FNAME "testfile.txt"
+
+static void test_insertfile(abts_case *tc, void *ctx)
+{
+    apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
+    apr_bucket_brigade *bb;
+    const apr_off_t bignum = (APR_INT64_C(2) << 32) + 424242;
+    apr_off_t count;
+    apr_file_t *f;
+    apr_bucket *e;
+
+    ABTS_ASSERT(tc, "open test file",
+                apr_file_open(&f, TIF_FNAME,
+                              APR_FOPEN_WRITE | APR_FOPEN_TRUNCATE
+                            | APR_FOPEN_CREATE | APR_FOPEN_SPARSE,
+                              APR_FPROT_OS_DEFAULT, p) == APR_SUCCESS);
+
+    if (apr_file_trunc(f, bignum)) {
+        apr_file_close(f);
+        apr_file_remove(TIF_FNAME, p);
+        ABTS_NOT_IMPL(tc, "Skipped: could not create large file");
+        return;
+    }
+    
+    bb = apr_brigade_create(p, ba);
+
+    e = apr_brigade_insert_file(bb, f, 0, bignum, p);
+    
+    ABTS_ASSERT(tc, "inserted file was not at end of brigade",
+                e == APR_BRIGADE_LAST(bb));
+
+    /* check that the total size of inserted buckets is equal to the
+     * total size of the file. */
+    count = 0;
+
+    for (e = APR_BRIGADE_FIRST(bb);
+         e != APR_BRIGADE_SENTINEL(bb);
+         e = APR_BUCKET_NEXT(e)) {
+        ABTS_ASSERT(tc, "bucket size sane", e->length != (apr_size_t)-1);
+        count += e->length;
+    }
+
+    ABTS_ASSERT(tc, "total size of buckets incorrect", count == bignum);
+
+    apr_brigade_destroy(bb);
+
+    /* Truncate the file to zero size before close() so that we don't
+     * actually write out the large file if we are on a non-sparse file
+     * system - like Mac OS X's HFS.  Otherwise, pity the poor user who
+     * has to wait for the 8GB file to be written to disk.
+     */
+    apr_file_trunc(f, 0);
+
+    apr_file_close(f);
+    apr_bucket_alloc_destroy(ba);
+    apr_file_remove(TIF_FNAME, p);
+}
+
+/* Make a test file named FNAME, and write CONTENTS to it. */
+static apr_file_t *make_test_file(abts_case *tc, const char *fname,
+                                  const char *contents)
+{
+    apr_file_t *f;
+
+    ABTS_ASSERT(tc, "create test file",
+                apr_file_open(&f, fname,
+                              APR_FOPEN_READ|APR_FOPEN_WRITE|APR_FOPEN_TRUNCATE|APR_FOPEN_CREATE,
+                              APR_FPROT_OS_DEFAULT, p) == APR_SUCCESS);
+    
+    ABTS_ASSERT(tc, "write test file contents",
+                apr_file_puts(contents, f) == APR_SUCCESS);
+
+    return f;
+}
+
+static void test_manyfile(abts_case *tc, void *data)
+{
+    apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
+    apr_bucket_brigade *bb = apr_brigade_create(p, ba);
+    apr_file_t *f;
+
+    f = make_test_file(tc, "manyfile.bin",
+                       "world" "hello" "brave" " ,\n");
+
+    apr_brigade_insert_file(bb, f, 5, 5, p);
+    apr_brigade_insert_file(bb, f, 16, 1, p);
+    apr_brigade_insert_file(bb, f, 15, 1, p);
+    apr_brigade_insert_file(bb, f, 10, 5, p);
+    apr_brigade_insert_file(bb, f, 15, 1, p);
+    apr_brigade_insert_file(bb, f, 0, 5, p);
+    apr_brigade_insert_file(bb, f, 17, 1, p);
+
+    /* can you tell what it is yet? */
+    flatten_match(tc, "file seek test", bb,
+                  "hello, brave world\n");
+
+    apr_file_close(f);
+    apr_brigade_destroy(bb);
+    apr_bucket_alloc_destroy(ba);
+}
+
+/* Regression test for PR 34708, where a file bucket will keep
+ * duplicating itself on being read() when EOF is reached
+ * prematurely. */
+static void test_truncfile(abts_case *tc, void *data)
+{
+    apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
+    apr_bucket_brigade *bb = apr_brigade_create(p, ba);
+    apr_file_t *f = make_test_file(tc, "testfile.txt", "hello");
+    apr_bucket *e;
+    const char *buf;
+    apr_size_t len;
+
+    apr_brigade_insert_file(bb, f, 0, 5, p);
+
+    apr_file_trunc(f, 0);
+
+    e = APR_BRIGADE_FIRST(bb);
+
+    ABTS_ASSERT(tc, "single bucket in brigade",
+                APR_BUCKET_NEXT(e) == APR_BRIGADE_SENTINEL(bb));
+
+    apr_bucket_file_enable_mmap(e, 0);
+
+    ABTS_ASSERT(tc, "read gave APR_EOF",
+                apr_bucket_read(e, &buf, &len, APR_BLOCK_READ) == APR_EOF);
+
+    ABTS_ASSERT(tc, "read length 0", len == 0);
+    
+    ABTS_ASSERT(tc, "still a single bucket in brigade",
+                APR_BUCKET_NEXT(e) == APR_BRIGADE_SENTINEL(bb));
+
+    apr_file_close(f);
+    apr_brigade_destroy(bb);
+    apr_bucket_alloc_destroy(ba);
+}
+
+static const char hello[] = "hello, world";
+
+static void test_partition(abts_case *tc, void *data)
+{
+    apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
+    apr_bucket_brigade *bb = apr_brigade_create(p, ba);
+    apr_bucket *e;
+
+    e = apr_bucket_immortal_create(hello, strlen(hello), ba);
+    APR_BRIGADE_INSERT_HEAD(bb, e);
+
+    APR_ASSERT_SUCCESS(tc, "partition brigade",
+                       apr_brigade_partition(bb, 5, &e));
+
+    test_bucket_content(tc, APR_BRIGADE_FIRST(bb),
+                        "hello", 5);
+
+    test_bucket_content(tc, APR_BRIGADE_LAST(bb),
+                        ", world", 7);
+
+    ABTS_ASSERT(tc, "partition returns APR_INCOMPLETE",
+                apr_brigade_partition(bb, 8192, &e));
+
+    ABTS_ASSERT(tc, "APR_INCOMPLETE partition returned sentinel",
+                e == APR_BRIGADE_SENTINEL(bb));
+
+    apr_brigade_destroy(bb);
+    apr_bucket_alloc_destroy(ba);
+}
+
+static void test_write_split(abts_case *tc, void *data)
+{
+    apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
+    apr_bucket_brigade *bb1 = apr_brigade_create(p, ba);
+    apr_bucket_brigade *bb2;
+    apr_bucket *e;
+
+    e = apr_bucket_heap_create(hello, strlen(hello), NULL, ba);
+    APR_BRIGADE_INSERT_HEAD(bb1, e);
+    apr_bucket_split(e, strlen("hello, "));
+    bb2 = apr_brigade_split(bb1, APR_BRIGADE_LAST(bb1));
+    apr_brigade_write(bb1, NULL, NULL, "foo", strlen("foo"));
+    test_bucket_content(tc, APR_BRIGADE_FIRST(bb2), "world", 5);
+
+    apr_brigade_destroy(bb1);
+    apr_brigade_destroy(bb2);
+    apr_bucket_alloc_destroy(ba);
+}
+
+static void test_write_putstrs(abts_case *tc, void *data)
+{
+    apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
+    apr_bucket_brigade *bb = apr_brigade_create(p, ba);
+    apr_bucket *e;
+    char buf[30];
+    apr_size_t len = sizeof(buf);
+    const char *expect = "123456789abcdefghij";
+
+    e = apr_bucket_heap_create("1", 1, NULL, ba);
+    APR_BRIGADE_INSERT_HEAD(bb, e);
+
+    apr_brigade_putstrs(bb, NULL, NULL, "2", "34", "567", "8", "9a", "bcd",
+                        "e", "f", "gh", "i", NULL);
+    apr_brigade_putstrs(bb, NULL, NULL, "j", NULL);
+    APR_ASSERT_SUCCESS(tc, "apr_brigade_flatten",
+                       apr_brigade_flatten(bb, buf, &len));
+    ABTS_STR_NEQUAL(tc, expect, buf, strlen(expect));
+
+    apr_brigade_destroy(bb);
+    apr_bucket_alloc_destroy(ba);
+}
+
+abts_suite *testbuckets(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite);
+
+    abts_run_test(suite, test_create, NULL);
+    abts_run_test(suite, test_simple, NULL);
+    abts_run_test(suite, test_flatten, NULL);
+    abts_run_test(suite, test_split, NULL);
+    abts_run_test(suite, test_bwrite, NULL);
+    abts_run_test(suite, test_splitline, NULL);
+    abts_run_test(suite, test_splits, NULL);
+    abts_run_test(suite, test_insertfile, NULL);
+    abts_run_test(suite, test_manyfile, NULL);
+    abts_run_test(suite, test_truncfile, NULL);
+    abts_run_test(suite, test_partition, NULL);
+    abts_run_test(suite, test_write_split, NULL);
+    abts_run_test(suite, test_write_putstrs, NULL);
+
+    return suite;
+}
+
+
diff --git a/test/testcond.c b/test/testcond.c
new file mode 100644
index 00000000000..b5a20bc46dc
--- /dev/null
+++ b/test/testcond.c
@@ -0,0 +1,670 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_file_io.h"
+#include "apr_thread_proc.h"
+#include "apr_thread_mutex.h"
+#include "apr_thread_cond.h"
+#include "apr_errno.h"
+#include "apr_general.h"
+#include "apr_atomic.h"
+#include "testutil.h"
+
+#define NTHREADS 10
+
+#define ABTS_SUCCESS(rv)    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv)
+
+#if APR_HAS_THREADS
+
+typedef struct toolbox_t toolbox_t;
+
+struct toolbox_t {
+    void *data;
+    abts_case *tc;
+    apr_thread_mutex_t *mutex;
+    apr_thread_cond_t *cond;
+    void (*func)(toolbox_t *box);
+};
+
+typedef struct toolbox_fnptr_t toolbox_fnptr_t;
+
+struct toolbox_fnptr_t {
+    void (*func)(toolbox_t *box);
+};
+
+static void lost_signal(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_thread_cond_t *cond = NULL;
+    apr_thread_mutex_t *mutex = NULL;
+
+    rv = apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_DEFAULT, p);
+    ABTS_SUCCESS(rv);
+    ABTS_PTR_NOTNULL(tc, mutex);
+
+    rv = apr_thread_cond_create(&cond, p);
+    ABTS_SUCCESS(rv);
+    ABTS_PTR_NOTNULL(tc, cond);
+
+    rv = apr_thread_cond_signal(cond);
+    ABTS_SUCCESS(rv);
+
+    rv = apr_thread_mutex_lock(mutex);
+    ABTS_SUCCESS(rv);
+
+    rv = apr_thread_cond_timedwait(cond, mutex, 10000);
+    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv));
+
+    rv = apr_thread_mutex_unlock(mutex);
+    ABTS_SUCCESS(rv);
+
+    rv = apr_thread_cond_broadcast(cond);
+    ABTS_SUCCESS(rv);
+
+    rv = apr_thread_mutex_lock(mutex);
+    ABTS_SUCCESS(rv);
+
+    rv = apr_thread_cond_timedwait(cond, mutex, 10000);
+    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv));
+
+    rv = apr_thread_mutex_unlock(mutex);
+    ABTS_SUCCESS(rv);
+
+    rv = apr_thread_cond_destroy(cond);
+    ABTS_SUCCESS(rv);
+
+    rv = apr_thread_mutex_destroy(mutex);
+    ABTS_SUCCESS(rv);
+}
+
+static void *APR_THREAD_FUNC thread_routine(apr_thread_t *thd, void *data)
+{
+    toolbox_t *box = data;
+
+    box->func(box);
+
+    apr_thread_exit(thd, 0);
+
+    return NULL;
+}
+
+static void lock_and_signal(toolbox_t *box)
+{
+    apr_status_t rv;
+    abts_case *tc = box->tc;
+
+    rv = apr_thread_mutex_lock(box->mutex);
+    ABTS_SUCCESS(rv);
+
+    rv = apr_thread_cond_signal(box->cond);
+    ABTS_SUCCESS(rv);
+
+    rv = apr_thread_mutex_unlock(box->mutex);
+    ABTS_SUCCESS(rv);
+}
+
+static void dynamic_binding(abts_case *tc, void *data)
+{
+    unsigned int i;
+    apr_status_t rv;
+    toolbox_t box[NTHREADS];
+    apr_thread_t *thread[NTHREADS];
+    apr_thread_mutex_t *mutex[NTHREADS];
+    apr_thread_cond_t *cond = NULL;
+
+    rv = apr_thread_cond_create(&cond, p);
+    ABTS_SUCCESS(rv);
+    ABTS_PTR_NOTNULL(tc, cond);
+
+    for (i = 0; i < NTHREADS; i++) {
+        rv = apr_thread_mutex_create(&mutex[i], APR_THREAD_MUTEX_DEFAULT, p);
+        ABTS_SUCCESS(rv);
+
+        rv = apr_thread_mutex_lock(mutex[i]);
+        ABTS_SUCCESS(rv);
+
+        box[i].tc = tc;
+        box[i].cond = cond;
+        box[i].mutex = mutex[i];
+        box[i].func = lock_and_signal;
+
+        rv = apr_thread_create(&thread[i], NULL, thread_routine, &box[i], p);
+        ABTS_SUCCESS(rv);
+    }
+
+    /*
+     * The dynamic binding should be preserved because we use only one waiter
+     */
+
+    for (i = 0; i < NTHREADS; i++) {
+        rv = apr_thread_cond_wait(cond, mutex[i]);
+        ABTS_SUCCESS(rv);
+    }
+
+    for (i = 0; i < NTHREADS; i++) {
+        rv = apr_thread_cond_timedwait(cond, mutex[i], 10000);
+        ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv));
+
+        rv = apr_thread_mutex_unlock(mutex[i]);
+        ABTS_SUCCESS(rv);
+    }
+
+    for (i = 0; i < NTHREADS; i++) {
+        apr_status_t retval;
+        rv = apr_thread_join(&retval, thread[i]);
+        ABTS_SUCCESS(rv);
+    }
+
+    rv = apr_thread_cond_destroy(cond);
+    ABTS_SUCCESS(rv);
+
+    for (i = 0; i < NTHREADS; i++) {
+        rv = apr_thread_mutex_destroy(mutex[i]);
+        ABTS_SUCCESS(rv);
+    }
+}
+
+static void lock_and_wait(toolbox_t *box)
+{
+    apr_status_t rv;
+    abts_case *tc = box->tc;
+    apr_uint32_t *count = box->data;
+
+    rv = apr_thread_mutex_lock(box->mutex);
+    ABTS_SUCCESS(rv);
+
+    apr_atomic_inc32(count);
+
+    rv = apr_thread_cond_wait(box->cond, box->mutex);
+    ABTS_SUCCESS(rv);
+
+    apr_atomic_dec32(count);
+
+    rv = apr_thread_mutex_unlock(box->mutex);
+    ABTS_SUCCESS(rv);
+}
+
+static void broadcast_threads(abts_case *tc, void *data)
+{
+    toolbox_t box;
+    unsigned int i;
+    apr_status_t rv;
+    apr_uint32_t count = 0;
+    apr_thread_cond_t *cond = NULL;
+    apr_thread_mutex_t *mutex = NULL;
+    apr_thread_t *thread[NTHREADS];
+
+    rv = apr_thread_cond_create(&cond, p);
+    ABTS_SUCCESS(rv);
+    ABTS_PTR_NOTNULL(tc, cond);
+
+    rv = apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_DEFAULT, p);
+    ABTS_SUCCESS(rv);
+    ABTS_PTR_NOTNULL(tc, mutex);
+
+    rv = apr_thread_mutex_lock(mutex);
+    ABTS_SUCCESS(rv);
+
+    box.tc = tc;
+    box.data = &count;
+    box.mutex = mutex;
+    box.cond = cond;
+    box.func = lock_and_wait;
+
+    for (i = 0; i < NTHREADS; i++) {
+        rv = apr_thread_create(&thread[i], NULL, thread_routine, &box, p);
+        ABTS_SUCCESS(rv);
+    }
+
+    do {
+        rv = apr_thread_mutex_unlock(mutex);
+        ABTS_SUCCESS(rv);
+        apr_sleep(100000);
+        rv = apr_thread_mutex_lock(mutex);
+        ABTS_SUCCESS(rv);
+    } while (apr_atomic_read32(&count) != NTHREADS);
+
+    rv = apr_thread_cond_broadcast(cond);
+    ABTS_SUCCESS(rv);
+
+    rv = apr_thread_mutex_unlock(mutex);
+    ABTS_SUCCESS(rv);
+
+    for (i = 0; i < NTHREADS; i++) {
+        apr_status_t retval;
+        rv = apr_thread_join(&retval, thread[i]);
+        ABTS_SUCCESS(rv);
+    }
+
+    ABTS_INT_EQUAL(tc, 0, count);
+
+    rv = apr_thread_cond_destroy(cond);
+    ABTS_SUCCESS(rv);
+
+    rv = apr_thread_mutex_destroy(mutex);
+    ABTS_SUCCESS(rv);
+}
+
+static void nested_lock_and_wait(toolbox_t *box)
+{
+    apr_status_t rv;
+    abts_case *tc = box->tc;
+
+    rv = apr_thread_mutex_lock(box->mutex);
+    ABTS_SUCCESS(rv);
+
+    rv = apr_thread_mutex_lock(box->mutex);
+    ABTS_SUCCESS(rv);
+
+    rv = apr_thread_mutex_lock(box->mutex);
+    ABTS_SUCCESS(rv);
+
+    rv = apr_thread_cond_wait(box->cond, box->mutex);
+    ABTS_SUCCESS(rv);
+}
+
+static void nested_lock_and_unlock(toolbox_t *box)
+{
+    apr_status_t rv;
+    abts_case *tc = box->tc;
+
+    rv = apr_thread_mutex_lock(box->mutex);
+    ABTS_SUCCESS(rv);
+
+    rv = apr_thread_mutex_lock(box->mutex);
+    ABTS_SUCCESS(rv);
+
+    rv = apr_thread_mutex_lock(box->mutex);
+    ABTS_SUCCESS(rv);
+
+    rv = apr_thread_cond_timedwait(box->cond, box->mutex, 2000000);
+    ABTS_SUCCESS(rv);
+
+    rv = apr_thread_mutex_unlock(box->mutex);
+    ABTS_SUCCESS(rv);
+
+    rv = apr_thread_mutex_unlock(box->mutex);
+    ABTS_SUCCESS(rv);
+}
+
+static void nested_wait(abts_case *tc, void *data)
+{
+    toolbox_fnptr_t *fnptr = data;
+    toolbox_t box;
+    apr_status_t rv, retval;
+    apr_thread_cond_t *cond = NULL;
+    apr_thread_t *thread = NULL;
+    apr_thread_mutex_t *mutex = NULL;
+
+    rv = apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_NESTED, p);
+    ABTS_SUCCESS(rv);
+    ABTS_PTR_NOTNULL(tc, mutex);
+
+    rv = apr_thread_cond_create(&cond, p);
+    ABTS_SUCCESS(rv);
+    ABTS_PTR_NOTNULL(tc, cond);
+
+    rv = apr_thread_mutex_lock(mutex);
+    ABTS_SUCCESS(rv);
+
+    box.tc = tc;
+    box.cond = cond;
+    box.mutex = mutex;
+    box.func = fnptr->func;
+
+    rv = apr_thread_create(&thread, NULL, thread_routine, &box, p);
+    ABTS_SUCCESS(rv);
+
+    rv = apr_thread_mutex_unlock(mutex);
+    ABTS_SUCCESS(rv);
+
+    /* yield the processor */
+    apr_sleep(500000);
+
+    rv = apr_thread_cond_signal(cond);
+    ABTS_SUCCESS(rv);
+
+    rv = apr_thread_join(&retval, thread);
+    ABTS_SUCCESS(rv);
+
+    rv = apr_thread_mutex_trylock(mutex);
+    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_EBUSY(rv));
+
+    rv = apr_thread_mutex_trylock(mutex);
+    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_EBUSY(rv));
+}
+
+static volatile apr_uint64_t pipe_count;
+static volatile apr_uint32_t exiting;
+
+static void pipe_consumer(toolbox_t *box)
+{
+    char ch;
+    apr_status_t rv;
+    apr_size_t nbytes;
+    abts_case *tc = box->tc;
+    apr_file_t *out = box->data;
+    apr_uint32_t consumed = 0;
+
+    do {
+        rv = apr_thread_mutex_lock(box->mutex);
+        ABTS_SUCCESS(rv);
+
+        while (!pipe_count && !exiting) {
+            rv = apr_thread_cond_wait(box->cond, box->mutex);
+            ABTS_SUCCESS(rv);
+        }
+
+        if (!pipe_count && exiting) {
+            rv = apr_thread_mutex_unlock(box->mutex);
+            ABTS_SUCCESS(rv);
+            break;
+        }
+
+        pipe_count--;
+        consumed++;
+
+        rv = apr_thread_mutex_unlock(box->mutex);
+        ABTS_SUCCESS(rv);
+
+        rv = apr_file_read_full(out, &ch, 1, &nbytes);
+        ABTS_SUCCESS(rv);
+        ABTS_SIZE_EQUAL(tc, 1, nbytes);
+        ABTS_TRUE(tc, ch == '.');
+    } while (1);
+
+    /* naive fairness test - it would be good to introduce or solidify
+     * a solid test to ensure one thread is not starved.  
+     * ABTS_INT_EQUAL(tc, 1, !!consumed);
+     */
+}
+
+static void pipe_write(toolbox_t *box, char ch)
+{
+    apr_status_t rv;
+    apr_size_t nbytes;
+    abts_case *tc = box->tc;
+    apr_file_t *in = box->data;
+
+    rv = apr_file_write_full(in, &ch, 1, &nbytes);
+    ABTS_SUCCESS(rv);
+    ABTS_SIZE_EQUAL(tc, 1, nbytes);
+
+    rv = apr_thread_mutex_lock(box->mutex);
+    ABTS_SUCCESS(rv);
+
+    if (!pipe_count) {
+        rv = apr_thread_cond_signal(box->cond);
+        ABTS_SUCCESS(rv);
+    }
+
+    pipe_count++;
+
+    rv = apr_thread_mutex_unlock(box->mutex);
+    ABTS_SUCCESS(rv);
+}
+
+static void pipe_producer(toolbox_t *box)
+{
+    apr_uint32_t loop = 500;
+
+    do {
+        pipe_write(box, '.');
+    } while (loop--);
+}
+
+static void pipe_producer_consumer(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    toolbox_t boxcons, boxprod;
+    apr_thread_t *thread[NTHREADS];
+    apr_thread_cond_t *cond = NULL;
+    apr_thread_mutex_t *mutex = NULL;
+    apr_file_t *in = NULL, *out = NULL;
+    apr_uint32_t i, ncons = (apr_uint32_t)(NTHREADS * 0.70);
+
+    rv = apr_file_pipe_create(&in, &out, p);
+    ABTS_SUCCESS(rv);
+
+    rv = apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_DEFAULT, p);
+    ABTS_SUCCESS(rv);
+    ABTS_PTR_NOTNULL(tc, mutex);
+
+    rv = apr_thread_cond_create(&cond, p);
+    ABTS_SUCCESS(rv);
+    ABTS_PTR_NOTNULL(tc, cond);
+
+    boxcons.tc = tc;
+    boxcons.data = in;
+    boxcons.mutex = mutex;
+    boxcons.cond = cond;
+    boxcons.func = pipe_consumer;
+
+    for (i = 0; i < ncons; i++) {
+        rv = apr_thread_create(&thread[i], NULL, thread_routine, &boxcons, p);
+        ABTS_SUCCESS(rv);
+    }
+
+    boxprod.tc = tc;
+    boxprod.data = out;
+    boxprod.mutex = mutex;
+    boxprod.cond = cond;
+    boxprod.func = pipe_producer;
+
+    for (; i < NTHREADS; i++) {
+        rv = apr_thread_create(&thread[i], NULL, thread_routine, &boxprod, p);
+        ABTS_SUCCESS(rv);
+    }
+
+    for (i = ncons; i < NTHREADS; i++) {
+        apr_status_t retval;
+        rv = apr_thread_join(&retval, thread[i]);
+        ABTS_SUCCESS(rv);
+    }
+
+    rv = apr_thread_mutex_lock(mutex);
+    ABTS_SUCCESS(rv);
+
+    exiting = 1;
+
+    rv = apr_thread_cond_broadcast(cond);
+    ABTS_SUCCESS(rv);
+
+    rv = apr_thread_mutex_unlock(mutex);
+    ABTS_SUCCESS(rv);
+
+    for (i = 0; i < ncons; i++) {
+        apr_status_t retval;
+        rv = apr_thread_join(&retval, thread[i]);
+        ABTS_SUCCESS(rv);
+    }
+
+    rv = apr_thread_cond_destroy(cond);
+    ABTS_SUCCESS(rv);
+
+    rv = apr_thread_mutex_destroy(mutex);
+    ABTS_SUCCESS(rv);
+
+    rv = apr_file_close(in);
+    ABTS_SUCCESS(rv);
+
+    rv = apr_file_close(out);
+    ABTS_SUCCESS(rv);
+}
+
+volatile enum {
+    TOSS,
+    PING,
+    PONG,
+    OVER
+} state;
+
+static void ping(toolbox_t *box)
+{
+    apr_status_t rv;
+    abts_case *tc = box->tc;
+
+    rv = apr_thread_mutex_lock(box->mutex);
+    ABTS_SUCCESS(rv);
+
+    if (state == TOSS)
+        state = PING;
+
+    do {
+        rv = apr_thread_cond_signal(box->cond);
+        ABTS_SUCCESS(rv);
+
+        state = PONG;
+
+        rv = apr_thread_cond_wait(box->cond, box->mutex);
+        ABTS_SUCCESS(rv);
+
+        ABTS_TRUE(tc, state == PING || state == OVER);
+    } while (state != OVER);
+
+    rv = apr_thread_mutex_unlock(box->mutex);
+    ABTS_SUCCESS(rv);
+
+    rv = apr_thread_cond_broadcast(box->cond);
+    ABTS_SUCCESS(rv);
+}
+
+static void pong(toolbox_t *box)
+{
+    apr_status_t rv;
+    abts_case *tc = box->tc;
+
+    rv = apr_thread_mutex_lock(box->mutex);
+    ABTS_SUCCESS(rv);
+
+    if (state == TOSS)
+        state = PONG;
+
+    do {
+        rv = apr_thread_cond_signal(box->cond);
+        ABTS_SUCCESS(rv);
+
+        state = PING;
+
+        rv = apr_thread_cond_wait(box->cond, box->mutex);
+        ABTS_SUCCESS(rv);
+
+        ABTS_TRUE(tc, state == PONG || state == OVER);
+    } while (state != OVER);
+
+    rv = apr_thread_mutex_unlock(box->mutex);
+    ABTS_SUCCESS(rv);
+
+    rv = apr_thread_cond_broadcast(box->cond);
+    ABTS_SUCCESS(rv);
+}
+
+static void ping_pong(abts_case *tc, void *data)
+{
+    apr_status_t rv, retval;
+    toolbox_t box_ping, box_pong;
+    apr_thread_cond_t *cond = NULL;
+    apr_thread_mutex_t *mutex = NULL;
+    apr_thread_t *thr_ping = NULL, *thr_pong = NULL;
+
+    rv = apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_DEFAULT, p);
+    ABTS_SUCCESS(rv);
+    ABTS_PTR_NOTNULL(tc, mutex);
+
+    rv = apr_thread_cond_create(&cond, p);
+    ABTS_SUCCESS(rv);
+    ABTS_PTR_NOTNULL(tc, cond);
+
+    rv = apr_thread_mutex_lock(mutex);
+    ABTS_SUCCESS(rv);
+
+    box_ping.tc = tc;
+    box_ping.data = NULL;
+    box_ping.mutex = mutex;
+    box_ping.cond = cond;
+    box_ping.func = ping;
+
+    rv = apr_thread_create(&thr_ping, NULL, thread_routine, &box_ping, p);
+    ABTS_SUCCESS(rv);
+
+    box_pong.tc = tc;
+    box_pong.data = NULL;
+    box_pong.mutex = mutex;
+    box_pong.cond = cond;
+    box_pong.func = pong;
+
+    rv = apr_thread_create(&thr_pong, NULL, thread_routine, &box_pong, p);
+    ABTS_SUCCESS(rv);
+
+    state = TOSS;
+
+    rv = apr_thread_mutex_unlock(mutex);
+    ABTS_SUCCESS(rv);
+
+    apr_sleep(3000000);
+
+    rv = apr_thread_mutex_lock(mutex);
+    ABTS_SUCCESS(rv);
+
+    state = OVER;
+
+    rv = apr_thread_mutex_unlock(mutex);
+    ABTS_SUCCESS(rv);
+
+    rv = apr_thread_join(&retval, thr_ping);
+    ABTS_SUCCESS(rv);
+
+    rv = apr_thread_join(&retval, thr_pong);
+    ABTS_SUCCESS(rv);
+
+    rv = apr_thread_cond_destroy(cond);
+    ABTS_SUCCESS(rv);
+
+    rv = apr_thread_mutex_destroy(mutex);
+    ABTS_SUCCESS(rv);
+}
+#endif /* !APR_HAS_THREADS */
+
+#if !APR_HAS_THREADS
+static void threads_not_impl(abts_case *tc, void *data)
+{
+    ABTS_NOT_IMPL(tc, "Threads not implemented on this platform");
+}
+#endif
+
+abts_suite *testcond(abts_suite *suite)
+{
+#if APR_HAS_THREADS
+    toolbox_fnptr_t fnptr;
+#endif
+    suite = ADD_SUITE(suite)
+
+#if !APR_HAS_THREADS
+    abts_run_test(suite, threads_not_impl, NULL);
+#else
+    abts_run_test(suite, lost_signal, NULL);
+    abts_run_test(suite, dynamic_binding, NULL);
+    abts_run_test(suite, broadcast_threads, NULL);
+    fnptr.func = nested_lock_and_wait;
+    abts_run_test(suite, nested_wait, &fnptr);
+    fnptr.func = nested_lock_and_unlock;
+    abts_run_test(suite, nested_wait, &fnptr);
+    abts_run_test(suite, pipe_producer_consumer, NULL);
+    abts_run_test(suite, ping_pong, NULL);
+#endif
+
+    return suite;
+}
diff --git a/test/testcontext.c b/test/testcontext.c
deleted file mode 100644
index 0c91d508002..00000000000
--- a/test/testcontext.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "apr_file_io.h"
-#include "apr_errno.h"
-#include "apr_general.h"
-#include "apr_lib.h"
-#ifdef BEOS
-#include <unistd.h>
-#endif
-
-ap_status_t string_cleanup(void *data)
-{
-    return APR_SUCCESS;
-}
-
-int main()
-{
-    ap_pool_t *context;
-    char *testdata;
-    char *retdata;
-
-    if (ap_initialize() != APR_SUCCESS) {
-        fprintf(stderr, "Couldn't initialize.");
-        exit(-1);
-    }
-    atexit(ap_terminate);
-
-    if (ap_create_pool(&context, NULL) != APR_SUCCESS) {
-        fprintf(stderr, "Couldn't allocate context.");
-        exit(-1);
-    }
-
-    testdata = ap_pstrdup(context, "This is a test\n");
-
-    ap_set_userdata(testdata, "TEST", string_cleanup, context);    
-
-    ap_get_userdata((void **)&retdata, "TEST", context);
-
-    if (!strcmp(testdata, retdata)) {
-        fprintf(stdout, "User data is working ok\n");
-    }
-    else {
-        fprintf(stdout, "User data is not working\n");
-    } 
-    
-    return 1;
-}
diff --git a/test/testcrypto.c b/test/testcrypto.c
new file mode 100644
index 00000000000..865cffc6d5e
--- /dev/null
+++ b/test/testcrypto.c
@@ -0,0 +1,1545 @@
+/* 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 "testutil.h"
+#include "apr.h"
+#include "apu.h"
+#include "apu_errno.h"
+#include "apr_pools.h"
+#include "apr_dso.h"
+#include "apr_crypto.h"
+#include "apr_strings.h"
+
+#if APU_HAVE_CRYPTO
+
+#define TEST_STRING "12345"
+#define ALIGNED_STRING "123456789012345"
+
+static const apr_crypto_driver_t *get_driver(abts_case *tc, apr_pool_t *pool,
+        const char *name, const char *params)
+{
+
+    const apr_crypto_driver_t *driver = NULL;
+    const apu_err_t *result = NULL;
+    apr_status_t rv;
+
+    rv = apr_crypto_init(pool);
+    ABTS_ASSERT(tc, "failed to init apr_crypto", rv == APR_SUCCESS);
+
+    rv = apr_crypto_get_driver(&driver, name, params, &result, pool);
+    if (APR_ENOTIMPL == rv) {
+        ABTS_NOT_IMPL(tc,
+                apr_psprintf(pool, "Crypto driver '%s' not implemented", (char *)name));
+        return NULL;
+    }
+    if (APR_EDSOOPEN == rv) {
+        ABTS_NOT_IMPL(tc,
+                apr_psprintf(pool, "Crypto driver '%s' DSO could not be opened", (char *)name));
+        return NULL;
+    }
+    if (APR_SUCCESS != rv && result) {
+        char err[1024];
+        apr_strerror(rv, err, sizeof(err) - 1);
+        fprintf(stderr, "get_driver error %d: %s: '%s' native error %d: %s (%s),",
+                rv, err, name, result->rc, result->reason ? result->reason : "",
+                result->msg ? result->msg : "");
+    }
+    ABTS_ASSERT(tc, apr_psprintf(pool, "failed to apr_crypto_get_driver for '%s' with %d",
+                name, rv), rv == APR_SUCCESS);
+    ABTS_ASSERT(tc, "apr_crypto_get_driver returned NULL", driver != NULL);
+    if (!driver || rv) {
+        return NULL;
+    }
+
+    return driver;
+
+}
+
+static const apr_crypto_driver_t *get_nss_driver(abts_case *tc,
+        apr_pool_t *pool)
+{
+
+    /* initialise NSS */
+    return get_driver(tc, pool, "nss", "");
+
+}
+
+static const apr_crypto_driver_t *get_openssl_driver(abts_case *tc,
+        apr_pool_t *pool)
+{
+
+    return get_driver(tc, pool, "openssl", NULL);
+
+}
+
+static const apr_crypto_driver_t *get_commoncrypto_driver(abts_case *tc,
+        apr_pool_t *pool)
+{
+
+    return get_driver(tc, pool, "commoncrypto", NULL);
+
+}
+
+static apr_crypto_t *make(abts_case *tc, apr_pool_t *pool,
+        const apr_crypto_driver_t *driver)
+{
+
+    apr_crypto_t *f = NULL;
+
+    if (!driver) {
+        return NULL;
+    }
+
+    /* get the context */
+    apr_crypto_make(&f, driver, "engine=openssl", pool);
+    ABTS_ASSERT(tc, "apr_crypto_make returned NULL", f != NULL);
+
+    return f;
+
+}
+
+static const apr_crypto_key_t *keysecret(abts_case *tc, apr_pool_t *pool,
+        const apr_crypto_driver_t *driver, const apr_crypto_t *f,
+        apr_crypto_block_key_type_e type, apr_crypto_block_key_mode_e mode,
+        int doPad, apr_size_t secretLen, const char *description)
+{
+    apr_crypto_key_t *key = NULL;
+    const apu_err_t *result = NULL;
+    apr_crypto_key_rec_t *rec = apr_pcalloc(pool, sizeof(apr_crypto_key_rec_t));
+    apr_status_t rv;
+
+    if (!f) {
+        return NULL;
+    }
+
+    rec->ktype = APR_CRYPTO_KTYPE_SECRET;
+    rec->type = type;
+    rec->mode = mode;
+    rec->pad = doPad;
+    rec->k.secret.secret = apr_pcalloc(pool, secretLen);
+    rec->k.secret.secretLen = secretLen;
+
+    /* init the passphrase */
+    rv = apr_crypto_key(&key, rec, f, pool);
+    if (APR_ENOCIPHER == rv) {
+        apr_crypto_error(&result, f);
+        ABTS_NOT_IMPL(tc,
+                apr_psprintf(pool, "skipped: %s %s key return APR_ENOCIPHER: error %d: %s (%s)\n", description, apr_crypto_driver_name(driver), result->rc, result->reason ? result->reason : "", result->msg ? result->msg : ""));
+        return NULL;
+    }
+    else {
+        if (APR_SUCCESS != rv) {
+            apr_crypto_error(&result, f);
+            fprintf(stderr, "key: %s %s apr error %d / native error %d: %s (%s)\n",
+                    description, apr_crypto_driver_name(driver), rv, result->rc,
+                    result->reason ? result->reason : "",
+                    result->msg ? result->msg : "");
+        }
+        ABTS_ASSERT(tc, "apr_crypto_key returned APR_EKEYLENGTH", rv != APR_EKEYLENGTH);
+        ABTS_ASSERT(tc, "apr_crypto_key returned APR_ENOKEY", rv != APR_ENOKEY);
+        ABTS_ASSERT(tc, "apr_crypto_key returned APR_EPADDING",
+                rv != APR_EPADDING);
+        ABTS_ASSERT(tc, "apr_crypto_key returned APR_EKEYTYPE",
+                rv != APR_EKEYTYPE);
+        ABTS_ASSERT(tc, "failed to apr_crypto_key", rv == APR_SUCCESS);
+        ABTS_ASSERT(tc, "apr_crypto_key returned NULL context", key != NULL);
+    }
+    if (rv) {
+        return NULL;
+    }
+    return key;
+
+}
+
+static const apr_crypto_key_t *passphrase(abts_case *tc, apr_pool_t *pool,
+        const apr_crypto_driver_t *driver, const apr_crypto_t *f,
+        apr_crypto_block_key_type_e type, apr_crypto_block_key_mode_e mode,
+        int doPad, const char *description)
+{
+
+    apr_crypto_key_t *key = NULL;
+    const apu_err_t *result = NULL;
+    const char *pass = "secret";
+    const char *salt = "salt";
+    apr_status_t rv;
+
+    if (!f) {
+        return NULL;
+    }
+
+    /* init the passphrase */
+    rv = apr_crypto_passphrase(&key, NULL, pass, strlen(pass),
+            (unsigned char *) salt, strlen(salt), type, mode, doPad, 4096, f,
+            pool);
+    if (APR_ENOCIPHER == rv) {
+        apr_crypto_error(&result, f);
+        ABTS_NOT_IMPL(tc, apr_psprintf(pool,
+                        "skipped: %s %s passphrase return APR_ENOCIPHER: error %d: %s (%s)\n",
+                        description, apr_crypto_driver_name(driver), result->rc,
+                        result->reason ? result->reason : "", result->msg ? result->msg : ""));
+        return NULL;
+    }
+    else {
+        if (APR_SUCCESS != rv) {
+            apr_crypto_error(&result, f);
+            fprintf(stderr, "passphrase: %s %s apr error %d / native error %d: %s (%s)\n",
+                    description, apr_crypto_driver_name(driver), rv, result->rc,
+                    result->reason ? result->reason : "",
+                    result->msg ? result->msg : "");
+        }
+        ABTS_ASSERT(tc, "apr_crypto_passphrase returned APR_ENOKEY", rv != APR_ENOKEY);
+        ABTS_ASSERT(tc, "apr_crypto_passphrase returned APR_EPADDING", rv != APR_EPADDING);
+        ABTS_ASSERT(tc, "apr_crypto_passphrase returned APR_EKEYTYPE", rv != APR_EKEYTYPE);
+        ABTS_ASSERT(tc, "failed to apr_crypto_passphrase", rv == APR_SUCCESS);
+        ABTS_ASSERT(tc, "apr_crypto_passphrase returned NULL context", key != NULL);
+    }
+    if (rv) {
+        return NULL;
+    }
+    return key;
+
+}
+
+static const apr_crypto_key_t *keypassphrase(abts_case *tc, apr_pool_t *pool,
+        const apr_crypto_driver_t *driver, const apr_crypto_t *f,
+        apr_crypto_block_key_type_e type, apr_crypto_block_key_mode_e mode,
+        int doPad, const char *description)
+{
+
+    apr_crypto_key_t *key = NULL;
+    const apu_err_t *result = NULL;
+    const char *pass = "secret";
+    const char *salt = "salt";
+    apr_crypto_key_rec_t *rec = apr_pcalloc(pool, sizeof(apr_crypto_key_rec_t));
+    apr_status_t rv;
+
+    if (!f) {
+        return NULL;
+    }
+
+    rec->ktype = APR_CRYPTO_KTYPE_PASSPHRASE;
+    rec->type = type;
+    rec->mode = mode;
+    rec->pad = doPad;
+    rec->k.passphrase.pass = pass;
+    rec->k.passphrase.passLen = strlen(pass);
+    rec->k.passphrase.salt = (unsigned char *)salt;
+    rec->k.passphrase.saltLen = strlen(salt);
+    rec->k.passphrase.iterations = 4096;
+
+    /* init the passphrase */
+    rv = apr_crypto_key(&key, rec, f, pool);
+    if (APR_ENOCIPHER == rv) {
+        apr_crypto_error(&result, f);
+        ABTS_NOT_IMPL(tc, apr_psprintf(pool,
+                        "skipped: %s %s key passphrase return APR_ENOCIPHER: error %d: %s (%s)\n",
+                        description, apr_crypto_driver_name(driver), result->rc,
+                        result->reason ? result->reason : "", result->msg ? result->msg : ""));
+        return NULL;
+    }
+    else {
+        if (APR_SUCCESS != rv) {
+            apr_crypto_error(&result, f);
+            fprintf(stderr, "key passphrase: %s %s apr error %d / native error %d: %s (%s)\n",
+                    description, apr_crypto_driver_name(driver), rv, result->rc,
+                    result->reason ? result->reason : "",
+                    result->msg ? result->msg : "");
+        }
+        ABTS_ASSERT(tc, "apr_crypto_key returned APR_ENOKEY", rv != APR_ENOKEY);
+        ABTS_ASSERT(tc, "apr_crypto_key returned APR_EPADDING", rv != APR_EPADDING);
+        ABTS_ASSERT(tc, "apr_crypto_key returned APR_EKEYTYPE", rv != APR_EKEYTYPE);
+        ABTS_ASSERT(tc, "failed to apr_crypto_key", rv == APR_SUCCESS);
+        ABTS_ASSERT(tc, "apr_crypto_key returned NULL context", key != NULL);
+    }
+    if (rv) {
+        return NULL;
+    }
+    return key;
+
+}
+
+static unsigned char *encrypt_block(abts_case *tc, apr_pool_t *pool,
+        const apr_crypto_driver_t *driver, const apr_crypto_t *f,
+        const apr_crypto_key_t *key, const unsigned char *in,
+        const apr_size_t inlen, unsigned char **cipherText,
+        apr_size_t *cipherTextLen, const unsigned char **iv,
+        apr_size_t *blockSize, const char *description)
+{
+
+    apr_crypto_block_t *block = NULL;
+    const apu_err_t *result = NULL;
+    apr_size_t len = 0;
+    apr_status_t rv;
+
+    if (!driver || !f || !key || !in) {
+        return NULL;
+    }
+
+    /* init the encryption */
+    rv = apr_crypto_block_encrypt_init(&block, iv, key, blockSize, pool);
+    if (APR_ENOTIMPL == rv) {
+        ABTS_NOT_IMPL(tc, "apr_crypto_block_encrypt_init returned APR_ENOTIMPL");
+    }
+    else {
+        if (APR_SUCCESS != rv) {
+            apr_crypto_error(&result, f);
+            fprintf(stderr,
+                    "encrypt_init: %s %s (APR %d) native error %d: %s (%s)\n",
+                    description, apr_crypto_driver_name(driver), rv, result->rc,
+                    result->reason ? result->reason : "",
+                    result->msg ? result->msg : "");
+        }
+        ABTS_ASSERT(tc, "apr_crypto_block_encrypt_init returned APR_ENOKEY",
+                rv != APR_ENOKEY);
+        ABTS_ASSERT(tc, "apr_crypto_block_encrypt_init returned APR_ENOIV",
+                rv != APR_ENOIV);
+        ABTS_ASSERT(tc, "apr_crypto_block_encrypt_init returned APR_EKEYTYPE",
+                rv != APR_EKEYTYPE);
+        ABTS_ASSERT(tc, "apr_crypto_block_encrypt_init returned APR_EKEYLENGTH",
+                rv != APR_EKEYLENGTH);
+        ABTS_ASSERT(tc,
+                "apr_crypto_block_encrypt_init returned APR_ENOTENOUGHENTROPY",
+                rv != APR_ENOTENOUGHENTROPY);
+        ABTS_ASSERT(tc, "failed to apr_crypto_block_encrypt_init",
+                rv == APR_SUCCESS);
+        ABTS_ASSERT(tc, "apr_crypto_block_encrypt_init returned NULL context",
+                block != NULL);
+    }
+    if (!block || rv) {
+        return NULL;
+    }
+
+    /* encrypt the block */
+    rv = apr_crypto_block_encrypt(cipherText, cipherTextLen, in, inlen, block);
+    if (APR_SUCCESS != rv) {
+        apr_crypto_error(&result, f);
+        fprintf(stderr, "encrypt: %s %s (APR %d) native error %d: %s (%s)\n",
+                description, apr_crypto_driver_name(driver), rv, result->rc,
+                result->reason ? result->reason : "",
+                result->msg ? result->msg : "");
+    }
+    ABTS_ASSERT(tc, "apr_crypto_block_encrypt returned APR_ECRYPT", rv != APR_ECRYPT);
+    ABTS_ASSERT(tc, "failed to apr_crypto_block_encrypt", rv == APR_SUCCESS);
+    ABTS_ASSERT(tc, "apr_crypto_block_encrypt failed to allocate buffer", *cipherText != NULL);
+    if (rv) {
+        return NULL;
+    }
+
+    /* finalise the encryption */
+    rv = apr_crypto_block_encrypt_finish(*cipherText + *cipherTextLen, &len,
+            block);
+    if (APR_SUCCESS != rv) {
+        apr_crypto_error(&result, f);
+        fprintf(stderr,
+                "encrypt_finish: %s %s (APR %d) native error %d: %s (%s)\n",
+                description, apr_crypto_driver_name(driver), rv, result->rc,
+                result->reason ? result->reason : "",
+                result->msg ? result->msg : "");
+    }
+    ABTS_ASSERT(tc, "apr_crypto_block_encrypt_finish returned APR_ECRYPT", rv != APR_ECRYPT);
+    ABTS_ASSERT(tc, "apr_crypto_block_encrypt_finish returned APR_EPADDING", rv != APR_EPADDING);
+    ABTS_ASSERT(tc, "apr_crypto_block_encrypt_finish returned APR_ENOSPACE", rv != APR_ENOSPACE);
+    ABTS_ASSERT(tc, "failed to apr_crypto_block_encrypt_finish", rv == APR_SUCCESS);
+    *cipherTextLen += len;
+    apr_crypto_block_cleanup(block);
+    if (rv) {
+        return NULL;
+    }
+
+    return *cipherText;
+
+}
+
+static unsigned char *decrypt_block(abts_case *tc, apr_pool_t *pool,
+        const apr_crypto_driver_t *driver, const apr_crypto_t *f,
+        const apr_crypto_key_t *key, unsigned char *cipherText,
+        apr_size_t cipherTextLen, unsigned char **plainText,
+        apr_size_t *plainTextLen, const unsigned char *iv,
+        apr_size_t *blockSize, const char *description)
+{
+
+    apr_crypto_block_t *block = NULL;
+    const apu_err_t *result = NULL;
+    apr_size_t len = 0;
+    apr_status_t rv;
+
+    if (!driver || !f || !key || !cipherText) {
+        return NULL;
+    }
+
+    /* init the decryption */
+    rv = apr_crypto_block_decrypt_init(&block, blockSize, iv, key, pool);
+    if (APR_ENOTIMPL == rv) {
+        ABTS_NOT_IMPL(tc, "apr_crypto_block_decrypt_init returned APR_ENOTIMPL");
+    }
+    else {
+        if (APR_SUCCESS != rv) {
+            apr_crypto_error(&result, f);
+            fprintf(stderr,
+                    "decrypt_init: %s %s (APR %d) native error %d: %s (%s)\n",
+                    description, apr_crypto_driver_name(driver), rv, result->rc,
+                    result->reason ? result->reason : "",
+                    result->msg ? result->msg : "");
+        }
+        ABTS_ASSERT(tc, "apr_crypto_block_decrypt_init returned APR_ENOKEY", rv != APR_ENOKEY);
+        ABTS_ASSERT(tc, "apr_crypto_block_decrypt_init returned APR_ENOIV", rv != APR_ENOIV);
+        ABTS_ASSERT(tc, "apr_crypto_block_decrypt_init returned APR_EKEYTYPE", rv != APR_EKEYTYPE);
+        ABTS_ASSERT(tc, "apr_crypto_block_decrypt_init returned APR_EKEYLENGTH", rv != APR_EKEYLENGTH);
+        ABTS_ASSERT(tc, "failed to apr_crypto_block_decrypt_init", rv == APR_SUCCESS);
+        ABTS_ASSERT(tc, "apr_crypto_block_decrypt_init returned NULL context", block != NULL);
+    }
+    if (!block || rv) {
+        return NULL;
+    }
+
+    /* decrypt the block */
+    rv = apr_crypto_block_decrypt(plainText, plainTextLen, cipherText,
+            cipherTextLen, block);
+    if (APR_SUCCESS != rv) {
+        apr_crypto_error(&result, f);
+        fprintf(stderr, "decrypt: %s %s (APR %d) native error %d: %s (%s)\n",
+                description, apr_crypto_driver_name(driver), rv, result->rc,
+                result->reason ? result->reason : "",
+                result->msg ? result->msg : "");
+    }
+    ABTS_ASSERT(tc, "apr_crypto_block_decrypt returned APR_ECRYPT", rv != APR_ECRYPT);
+    ABTS_ASSERT(tc, "failed to apr_crypto_block_decrypt", rv == APR_SUCCESS);
+    ABTS_ASSERT(tc, "apr_crypto_block_decrypt failed to allocate buffer", *plainText != NULL);
+    if (rv) {
+        return NULL;
+    }
+
+    /* finalise the decryption */
+    rv = apr_crypto_block_decrypt_finish(*plainText + *plainTextLen, &len,
+            block);
+    if (APR_SUCCESS != rv) {
+        apr_crypto_error(&result, f);
+        fprintf(stderr,
+                "decrypt_finish: %s %s (APR %d) native error %d: %s (%s)\n",
+                description, apr_crypto_driver_name(driver), rv, result->rc,
+                result->reason ? result->reason : "",
+                result->msg ? result->msg : "");
+    }
+    ABTS_ASSERT(tc, "apr_crypto_block_decrypt_finish returned APR_ECRYPT", rv != APR_ECRYPT);
+    ABTS_ASSERT(tc, "apr_crypto_block_decrypt_finish returned APR_EPADDING", rv != APR_EPADDING);
+    ABTS_ASSERT(tc, "apr_crypto_block_decrypt_finish returned APR_ENOSPACE", rv != APR_ENOSPACE);
+    ABTS_ASSERT(tc, "failed to apr_crypto_block_decrypt_finish", rv == APR_SUCCESS);
+    if (rv) {
+        return NULL;
+    }
+
+    *plainTextLen += len;
+    apr_crypto_block_cleanup(block);
+
+    return *plainText;
+
+}
+
+/**
+ * Interoperability test.
+ *
+ * data must point at an array of two driver structures. Data will be encrypted
+ * with the first driver, and decrypted with the second.
+ *
+ * If the two drivers interoperate, the test passes.
+ */
+static void crypto_block_cross(abts_case *tc, apr_pool_t *pool,
+        const apr_crypto_driver_t **drivers,
+        const apr_crypto_block_key_type_e type,
+        const apr_crypto_block_key_mode_e mode, int doPad,
+        const unsigned char *in, apr_size_t inlen, apr_size_t secretLen,
+        const char *description)
+{
+    const apr_crypto_driver_t *driver1 = drivers[0];
+    const apr_crypto_driver_t *driver2 = drivers[1];
+    apr_crypto_t *f1 = NULL;
+    apr_crypto_t *f2 = NULL;
+    const apr_crypto_key_t *key1 = NULL;
+    const apr_crypto_key_t *key2 = NULL;
+    const apr_crypto_key_t *key3 = NULL;
+    const apr_crypto_key_t *key4 = NULL;
+    const apr_crypto_key_t *key5 = NULL;
+    const apr_crypto_key_t *key6 = NULL;
+
+    unsigned char *cipherText = NULL;
+    apr_size_t cipherTextLen = 0;
+    unsigned char *plainText = NULL;
+    apr_size_t plainTextLen = 0;
+    const unsigned char *iv = NULL;
+    apr_size_t blockSize = 0;
+
+    f1 = make(tc, pool, driver1);
+    f2 = make(tc, pool, driver2);
+    key1 = passphrase(tc, pool, driver1, f1, type, mode, doPad, description);
+    key2 = passphrase(tc, pool, driver2, f2, type, mode, doPad, description);
+
+    cipherText = encrypt_block(tc, pool, driver1, f1, key1, in, inlen,
+            &cipherText, &cipherTextLen, &iv, &blockSize, description);
+    plainText = decrypt_block(tc, pool, driver2, f2, key2, cipherText,
+            cipherTextLen, &plainText, &plainTextLen, iv, &blockSize,
+            description);
+
+    if (cipherText && plainText) {
+        if (memcmp(in, plainText, inlen)) {
+            fprintf(stderr, "passphrase cross mismatch: %s %s/%s\n", description,
+                    apr_crypto_driver_name(driver1), apr_crypto_driver_name(
+                            driver2));
+        }
+        ABTS_STR_EQUAL(tc, (char *)in, (char *)plainText);
+    }
+
+    key3 = keysecret(tc, pool, driver1, f1, type, mode, doPad, secretLen, description);
+    key4 = keysecret(tc, pool, driver2, f2, type, mode, doPad, secretLen, description);
+
+    iv = NULL;
+    blockSize = 0;
+    cipherText = NULL;
+    plainText = NULL;
+    cipherText = encrypt_block(tc, pool, driver1, f1, key3, in, inlen,
+            &cipherText, &cipherTextLen, &iv, &blockSize, description);
+    plainText = decrypt_block(tc, pool, driver2, f2, key4, cipherText,
+            cipherTextLen, &plainText, &plainTextLen, iv, &blockSize,
+            description);
+
+    if (cipherText && plainText) {
+        if (memcmp(in, plainText, inlen)) {
+            fprintf(stderr, "key secret cross mismatch: %s %s/%s\n", description,
+                    apr_crypto_driver_name(driver1), apr_crypto_driver_name(
+                            driver2));
+        }
+        ABTS_STR_EQUAL(tc, (char *)in, (char *)plainText);
+    }
+
+    key5 = keypassphrase(tc, pool, driver1, f1, type, mode, doPad, description);
+    key6 = keypassphrase(tc, pool, driver2, f2, type, mode, doPad, description);
+
+    iv = NULL;
+    blockSize = 0;
+    cipherText = NULL;
+    plainText = NULL;
+    cipherText = encrypt_block(tc, pool, driver1, f1, key5, in, inlen,
+            &cipherText, &cipherTextLen, &iv, &blockSize, description);
+    plainText = decrypt_block(tc, pool, driver2, f2, key6, cipherText,
+            cipherTextLen, &plainText, &plainTextLen, iv, &blockSize,
+            description);
+
+    if (cipherText && plainText) {
+        if (memcmp(in, plainText, inlen)) {
+            fprintf(stderr, "key passphrase cross mismatch: %s %s/%s\n", description,
+                    apr_crypto_driver_name(driver1), apr_crypto_driver_name(
+                            driver2));
+        }
+        ABTS_STR_EQUAL(tc, (char *)in, (char *)plainText);
+    }
+
+}
+
+/**
+ * Test initialisation.
+ */
+static void test_crypto_init(abts_case *tc, void *data)
+{
+    apr_pool_t *pool = NULL;
+    apr_status_t rv;
+
+    apr_pool_create(&pool, NULL);
+
+    rv = apr_crypto_init(pool);
+    ABTS_ASSERT(tc, "failed to init apr_crypto", rv == APR_SUCCESS);
+
+    apr_pool_destroy(pool);
+
+}
+
+/**
+ * Simple test of OpenSSL key.
+ */
+static void test_crypto_key_openssl(abts_case *tc, void *data)
+{
+    apr_pool_t *pool = NULL;
+    const apr_crypto_driver_t *driver;
+    apr_crypto_t *f = NULL;
+
+    apr_pool_create(&pool, NULL);
+    driver = get_openssl_driver(tc, pool);
+
+    f = make(tc, pool, driver);
+    keysecret(tc, pool, driver, f, APR_KEY_AES_256, APR_MODE_CBC, 1, 32,
+            "KEY_AES_256/MODE_CBC");
+    apr_pool_destroy(pool);
+
+}
+
+/**
+ * Simple test of NSS key.
+ */
+static void test_crypto_key_nss(abts_case *tc, void *data)
+{
+    apr_pool_t *pool = NULL;
+    const apr_crypto_driver_t *driver;
+    apr_crypto_t *f = NULL;
+
+    apr_pool_create(&pool, NULL);
+    driver = get_nss_driver(tc, pool);
+
+    f = make(tc, pool, driver);
+    keysecret(tc, pool, driver, f, APR_KEY_AES_256, APR_MODE_CBC, 1, 32,
+            "KEY_AES_256/MODE_CBC");
+    apr_pool_destroy(pool);
+
+}
+
+/**
+ * Simple test of CommonCrypto key.
+ */
+static void test_crypto_key_commoncrypto(abts_case *tc, void *data)
+{
+    apr_pool_t *pool = NULL;
+    const apr_crypto_driver_t *driver;
+    apr_crypto_t *f = NULL;
+
+    apr_pool_create(&pool, NULL);
+    driver = get_commoncrypto_driver(tc, pool);
+
+    f = make(tc, pool, driver);
+    keysecret(tc, pool, driver, f, APR_KEY_AES_256, APR_MODE_CBC, 1, 32,
+            "KEY_AES_256/MODE_CBC");
+    apr_pool_destroy(pool);
+
+}
+
+/**
+ * Simple test of OpenSSL block crypt.
+ */
+static void test_crypto_block_openssl(abts_case *tc, void *data)
+{
+    apr_pool_t *pool = NULL;
+    const apr_crypto_driver_t *drivers[] = { NULL, NULL };
+
+    const unsigned char *in = (const unsigned char *) ALIGNED_STRING;
+    apr_size_t inlen = sizeof(ALIGNED_STRING);
+
+    apr_pool_create(&pool, NULL);
+    drivers[0] = get_openssl_driver(tc, pool);
+    drivers[1] = get_openssl_driver(tc, pool);
+    crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 0,
+            in, inlen, 24, "KEY_3DES_192/MODE_CBC");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_ECB, 0,
+            in, inlen, 24, "KEY_3DES_192/MODE_ECB");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 0, in,
+            inlen, 32, "KEY_AES_256/MODE_CBC");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_ECB, 0, in,
+            inlen, 32, "KEY_AES_256/MODE_ECB");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 0, in,
+            inlen, 24, "KEY_AES_192/MODE_CBC");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_ECB, 0, in,
+            inlen, 24, "KEY_AES_192/MODE_ECB");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 0, in,
+            inlen, 16, "KEY_AES_128/MODE_CBC");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_ECB, 0, in,
+            inlen, 16, "KEY_AES_128/MODE_ECB");
+    apr_pool_destroy(pool);
+
+}
+
+/**
+ * Simple test of NSS block crypt.
+ */
+static void test_crypto_block_nss(abts_case *tc, void *data)
+{
+    apr_pool_t *pool = NULL;
+    const apr_crypto_driver_t *drivers[] = { NULL, NULL };
+
+    const unsigned char *in = (const unsigned char *) ALIGNED_STRING;
+    apr_size_t inlen = sizeof(ALIGNED_STRING);
+
+    apr_pool_create(&pool, NULL);
+    drivers[0] = get_nss_driver(tc, pool);
+    drivers[1] = get_nss_driver(tc, pool);
+    crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 0,
+            in, inlen, 24, "KEY_3DES_192/MODE_CBC");
+    /* KEY_3DES_192 / MODE_ECB doesn't work on NSS */
+    /* crypto_block_cross(tc, pool, drivers, KEY_3DES_192, MODE_ECB, 0, in, inlen, "KEY_3DES_192/MODE_ECB"); */
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 0, in,
+            inlen, 32, "KEY_AES_256/MODE_CBC");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_ECB, 0, in,
+            inlen, 32, "KEY_AES_256/MODE_ECB");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 0, in,
+            inlen, 24, "KEY_AES_192/MODE_CBC");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_ECB, 0, in,
+            inlen, 24, "KEY_AES_192/MODE_ECB");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 0, in,
+            inlen, 16, "KEY_AES_128/MODE_CBC");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_ECB, 0, in,
+            inlen, 16, "KEY_AES_128/MODE_ECB");
+    apr_pool_destroy(pool);
+
+}
+
+/**
+ * Simple test of Common Crypto block crypt.
+ */
+static void test_crypto_block_commoncrypto(abts_case *tc, void *data)
+{
+    apr_pool_t *pool = NULL;
+    const apr_crypto_driver_t *drivers[] = { NULL, NULL };
+
+    const unsigned char *in = (const unsigned char *) ALIGNED_STRING;
+    apr_size_t inlen = sizeof(ALIGNED_STRING);
+
+    apr_pool_create(&pool, NULL);
+    drivers[0] = get_commoncrypto_driver(tc, pool);
+    drivers[1] = get_commoncrypto_driver(tc, pool);
+    crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 0,
+            in, inlen, 24, "KEY_3DES_192/MODE_CBC");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_ECB, 0,
+            in, inlen, 24, "KEY_3DES_192/MODE_ECB");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 0, in,
+            inlen, 32, "KEY_AES_256/MODE_CBC");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_ECB, 0, in,
+            inlen, 32, "KEY_AES_256/MODE_ECB");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 0, in,
+            inlen, 24, "KEY_AES_192/MODE_CBC");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_ECB, 0, in,
+            inlen, 24, "KEY_AES_192/MODE_ECB");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 0, in,
+            inlen, 16, "KEY_AES_128/MODE_CBC");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_ECB, 0, in,
+            inlen, 16, "KEY_AES_128/MODE_ECB");
+    apr_pool_destroy(pool);
+
+}
+
+/**
+ * Encrypt NSS, decrypt OpenSSL.
+ */
+static void test_crypto_block_nss_openssl(abts_case *tc, void *data)
+{
+    apr_pool_t *pool = NULL;
+    const apr_crypto_driver_t *drivers[] = { NULL, NULL };
+
+    const unsigned char *in = (const unsigned char *) ALIGNED_STRING;
+    apr_size_t inlen = sizeof(ALIGNED_STRING);
+
+    apr_pool_create(&pool, NULL);
+    drivers[0] = get_nss_driver(tc, pool);
+    drivers[1] = get_openssl_driver(tc, pool);
+
+    crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 0,
+            in, inlen, 24, "KEY_3DES_192/MODE_CBC");
+
+    /* KEY_3DES_192 / MODE_ECB doesn't work on NSS */
+    /* crypto_block_cross(tc, pool, drivers, KEY_3DES_192, MODE_ECB, 0, in, inlen, 24, "KEY_3DES_192/MODE_ECB"); */
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 0, in,
+            inlen, 32, "KEY_AES_256/MODE_CBC");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_ECB, 0, in,
+            inlen, 32, "KEY_AES_256/MODE_ECB");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 0, in,
+            inlen, 24, "KEY_AES_192/MODE_CBC");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_ECB, 0, in,
+            inlen, 24, "KEY_AES_192/MODE_ECB");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 0, in,
+            inlen, 16, "KEY_AES_128/MODE_CBC");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_ECB, 0, in,
+            inlen, 16, "KEY_AES_128/MODE_ECB");
+    apr_pool_destroy(pool);
+
+}
+
+/**
+ * Encrypt OpenSSL, decrypt NSS.
+ */
+static void test_crypto_block_openssl_nss(abts_case *tc, void *data)
+{
+    apr_pool_t *pool = NULL;
+    const apr_crypto_driver_t *drivers[] = { NULL, NULL };
+
+    const unsigned char *in = (const unsigned char *) ALIGNED_STRING;
+    apr_size_t inlen = sizeof(ALIGNED_STRING);
+
+    apr_pool_create(&pool, NULL);
+    drivers[0] = get_openssl_driver(tc, pool);
+    drivers[1] = get_nss_driver(tc, pool);
+    crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 0,
+            in, inlen, 24, "KEY_3DES_192/MODE_CBC");
+
+    /* KEY_3DES_192 / MODE_ECB doesn't work on NSS */
+    /* crypto_block_cross(tc, pool, drivers, KEY_3DES_192, MODE_ECB, 0, in, inlen, 24, "KEY_3DES_192/MODE_ECB"); */
+
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 0, in,
+            inlen, 32, "KEY_AES_256/MODE_CBC");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_ECB, 0, in,
+            inlen, 32, "KEY_AES_256/MODE_ECB");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 0, in,
+            inlen, 24, "KEY_AES_192/MODE_CBC");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_ECB, 0, in,
+            inlen, 24, "KEY_AES_192/MODE_ECB");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 0, in,
+            inlen, 16, "KEY_AES_128/MODE_CBC");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_ECB, 0, in,
+            inlen, 16, "KEY_AES_128/MODE_ECB");
+    apr_pool_destroy(pool);
+
+}
+
+/**
+ * Encrypt OpenSSL, decrypt CommonCrypto.
+ */
+static void test_crypto_block_openssl_commoncrypto(abts_case *tc, void *data)
+{
+    apr_pool_t *pool = NULL;
+    const apr_crypto_driver_t *drivers[] =
+    { NULL, NULL };
+
+    const unsigned char *in = (const unsigned char *) ALIGNED_STRING;
+    apr_size_t inlen = sizeof(ALIGNED_STRING);
+
+    apr_pool_create(&pool, NULL);
+    drivers[0] = get_openssl_driver(tc, pool);
+    drivers[1] = get_commoncrypto_driver(tc, pool);
+
+    crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 0, in,
+            inlen, 24, "KEY_3DES_192/MODE_CBC");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_ECB, 0, in,
+            inlen, 24, "KEY_3DES_192/MODE_ECB");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 0, in,
+            inlen, 32, "KEY_AES_256/MODE_CBC");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_ECB, 0, in,
+            inlen, 32, "KEY_AES_256/MODE_ECB");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 0, in,
+            inlen, 24, "KEY_AES_192/MODE_CBC");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_ECB, 0, in,
+            inlen, 24, "KEY_AES_192/MODE_ECB");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 0, in,
+            inlen, 16, "KEY_AES_128/MODE_CBC");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_ECB, 0, in,
+            inlen, 16, "KEY_AES_128/MODE_ECB");
+    apr_pool_destroy(pool);
+
+}
+
+/**
+ * Encrypt OpenSSL, decrypt CommonCrypto.
+ */
+static void test_crypto_block_commoncrypto_openssl(abts_case *tc, void *data)
+{
+    apr_pool_t *pool = NULL;
+    const apr_crypto_driver_t *drivers[] =
+    { NULL, NULL };
+
+    const unsigned char *in = (const unsigned char *) ALIGNED_STRING;
+    apr_size_t inlen = sizeof(ALIGNED_STRING);
+
+    apr_pool_create(&pool, NULL);
+    drivers[0] = get_commoncrypto_driver(tc, pool);
+    drivers[1] = get_openssl_driver(tc, pool);
+
+    crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 0, in,
+            inlen, 24, "KEY_3DES_192/MODE_CBC");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_ECB, 0, in,
+            inlen, 24, "KEY_3DES_192/MODE_ECB");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 0, in,
+            inlen, 32, "KEY_AES_256/MODE_CBC");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_ECB, 0, in,
+            inlen, 32, "KEY_AES_256/MODE_ECB");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 0, in,
+            inlen, 24, "KEY_AES_192/MODE_CBC");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_ECB, 0, in,
+            inlen, 24, "KEY_AES_192/MODE_ECB");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 0, in,
+            inlen, 16, "KEY_AES_128/MODE_CBC");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_ECB, 0, in,
+            inlen, 16, "KEY_AES_128/MODE_ECB");
+    apr_pool_destroy(pool);
+
+}
+
+/**
+ * Simple test of OpenSSL block crypt.
+ */
+static void test_crypto_block_openssl_pad(abts_case *tc, void *data)
+{
+    apr_pool_t *pool = NULL;
+    const apr_crypto_driver_t *drivers[] = { NULL, NULL };
+
+    const unsigned char *in = (const unsigned char *) TEST_STRING;
+    apr_size_t inlen = sizeof(TEST_STRING);
+
+    apr_pool_create(&pool, NULL);
+    drivers[0] = get_openssl_driver(tc, pool);
+    drivers[1] = get_openssl_driver(tc, pool);
+
+    crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 1,
+            in, inlen, 24, "KEY_3DES_192/MODE_CBC");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_ECB, 1,
+            in, inlen, 24, "KEY_3DES_192/MODE_ECB");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 1, in,
+            inlen, 32, "KEY_AES_256/MODE_CBC");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_ECB, 1, in,
+            inlen, 32, "KEY_AES_256/MODE_ECB");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 1, in,
+            inlen, 24, "KEY_AES_192/MODE_CBC");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_ECB, 1, in,
+            inlen, 24, "KEY_AES_192/MODE_ECB");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 1, in,
+            inlen, 16, "KEY_AES_128/MODE_CBC");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_ECB, 1, in,
+            inlen, 16, "KEY_AES_128/MODE_ECB");
+
+    apr_pool_destroy(pool);
+
+}
+
+/**
+ * Simple test of NSS block crypt.
+ */
+static void test_crypto_block_nss_pad(abts_case *tc, void *data)
+{
+    apr_pool_t *pool = NULL;
+    const apr_crypto_driver_t *drivers[] =
+    { NULL, NULL };
+
+    const unsigned char *in = (const unsigned char *) TEST_STRING;
+    apr_size_t inlen = sizeof(TEST_STRING);
+
+    apr_pool_create(&pool, NULL);
+    drivers[0] = get_nss_driver(tc, pool);
+    drivers[1] = get_nss_driver(tc, pool);
+
+    crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 1,
+            in, inlen, 24, "KEY_3DES_192/MODE_CBC");
+    /* KEY_3DES_192 / MODE_ECB doesn't work on NSS */
+    /* crypto_block_cross(tc, pool, drivers, KEY_3DES_192, MODE_ECB, 1, in, inlen, 24, "KEY_3DES_192/MODE_ECB"); */
+
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 1, in,
+            inlen, 32, "KEY_AES_256/MODE_CBC");
+
+    /* KEY_AES_256 / MODE_ECB doesn't support padding on NSS */
+    /*crypto_block_cross(tc, pool, drivers, KEY_AES_256, MODE_ECB, 1, in, inlen, 32, "KEY_AES_256/MODE_ECB");*/
+
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 1, in,
+            inlen, 24, "KEY_AES_192/MODE_CBC");
+
+    /* KEY_AES_256 / MODE_ECB doesn't support padding on NSS */
+    /*crypto_block_cross(tc, pool, drivers, KEY_AES_192, MODE_ECB, 1, in, inlen, 24, "KEY_AES_192/MODE_ECB");*/
+
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 1, in,
+            inlen, 16, "KEY_AES_128/MODE_CBC");
+
+    /* KEY_AES_256 / MODE_ECB doesn't support padding on NSS */
+    /*crypto_block_cross(tc, pool, drivers, KEY_AES_128, MODE_ECB, 1, in, inlen, 16, "KEY_AES_128/MODE_ECB");*/
+
+    apr_pool_destroy(pool);
+
+}
+
+/**
+ * Simple test of Common Crypto block crypt.
+ */
+static void test_crypto_block_commoncrypto_pad(abts_case *tc, void *data)
+{
+    apr_pool_t *pool = NULL;
+    const apr_crypto_driver_t *drivers[] = { NULL, NULL };
+
+    const unsigned char *in = (const unsigned char *) TEST_STRING;
+    apr_size_t inlen = sizeof(TEST_STRING);
+
+    apr_pool_create(&pool, NULL);
+    drivers[0] = get_commoncrypto_driver(tc, pool);
+    drivers[1] = get_commoncrypto_driver(tc, pool);
+
+    crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 1,
+            in, inlen, 24, "KEY_3DES_192/MODE_CBC");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_ECB, 1,
+            in, inlen, 24, "KEY_3DES_192/MODE_ECB");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 1, in,
+            inlen, 32, "KEY_AES_256/MODE_CBC");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_ECB, 1, in,
+            inlen, 32, "KEY_AES_256/MODE_ECB");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 1, in,
+            inlen, 24, "KEY_AES_192/MODE_CBC");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_ECB, 1, in,
+            inlen, 24, "KEY_AES_192/MODE_ECB");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 1, in,
+            inlen, 16, "KEY_AES_128/MODE_CBC");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_ECB, 1, in,
+            inlen, 16, "KEY_AES_128/MODE_ECB");
+
+    apr_pool_destroy(pool);
+
+}
+
+/**
+ * Encrypt NSS, decrypt OpenSSL.
+ */
+static void test_crypto_block_nss_openssl_pad(abts_case *tc, void *data)
+{
+    apr_pool_t *pool = NULL;
+    const apr_crypto_driver_t *drivers[] = { NULL, NULL };
+
+    const unsigned char *in = (const unsigned char *) TEST_STRING;
+    apr_size_t inlen = sizeof(TEST_STRING);
+
+    apr_pool_create(&pool, NULL);
+    drivers[0] = get_nss_driver(tc, pool);
+    drivers[1] = get_openssl_driver(tc, pool);
+
+    crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 1,
+            in, inlen, 24, "KEY_3DES_192/MODE_CBC");
+
+    /* KEY_3DES_192 / MODE_ECB doesn't work on NSS */
+    /* crypto_block_cross(tc, pool, drivers, KEY_3DES_192, MODE_ECB, 1, in, inlen, 24, "KEY_3DES_192/MODE_ECB"); */
+
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 1, in,
+            inlen, 32, "KEY_AES_256/MODE_CBC");
+
+    /* KEY_AES_256 / MODE_ECB doesn't support padding on NSS */
+    /*crypto_block_cross(tc, pool, drivers, KEY_AES_256, MODE_ECB, 1, in, inlen, 32, "KEY_AES_256/MODE_ECB");*/
+
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 1, in,
+            inlen, 24, "KEY_AES_192/MODE_CBC");
+
+    /* KEY_AES_192 / MODE_ECB doesn't support padding on NSS */
+    /*crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_ECB, 1, in,
+            inlen, 24, "KEY_AES_192/MODE_ECB");*/
+
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 1, in,
+            inlen, 16, "KEY_AES_128/MODE_CBC");
+
+    /* KEY_AES_192 / MODE_ECB doesn't support padding on NSS */
+    /*crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_ECB, 1, in,
+            inlen, 16, "KEY_AES_128/MODE_ECB");*/
+
+    apr_pool_destroy(pool);
+
+}
+
+/**
+ * Encrypt OpenSSL, decrypt NSS.
+ */
+static void test_crypto_block_openssl_nss_pad(abts_case *tc, void *data)
+{
+    apr_pool_t *pool = NULL;
+    const apr_crypto_driver_t *drivers[] = { NULL, NULL };
+
+    const unsigned char *in = (const unsigned char *) TEST_STRING;
+    apr_size_t inlen = sizeof(TEST_STRING);
+
+    apr_pool_create(&pool, NULL);
+    drivers[0] = get_openssl_driver(tc, pool);
+    drivers[1] = get_nss_driver(tc, pool);
+    crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 1,
+            in, inlen, 24, "KEY_3DES_192/MODE_CBC");
+
+    /* KEY_3DES_192 / MODE_ECB doesn't work on NSS */
+    /* crypto_block_cross(tc, pool, drivers, KEY_3DES_192, MODE_ECB, 1, in, inlen, 24, "KEY_3DES_192/MODE_ECB"); */
+
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 1, in,
+            inlen, 32, "KEY_AES_256/MODE_CBC");
+
+    /* KEY_AES_256 / MODE_ECB doesn't support padding on NSS */
+    /*crypto_block_cross(tc, pool, drivers, KEY_AES_256, MODE_ECB, 1, in, inlen, 32, "KEY_AES_256/MODE_ECB");*/
+
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 1, in, inlen,
+            24, "KEY_AES_192/MODE_CBC");
+
+    /* KEY_AES_192 / MODE_ECB doesn't support padding on NSS */
+    /*crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_ECB, 1, in, inlen,
+            24, "KEY_AES_192/MODE_ECB");*/
+
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 1, in, inlen,
+            16, "KEY_AES_128/MODE_CBC");
+
+    /* KEY_AES_128 / MODE_ECB doesn't support padding on NSS */
+    /*crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_ECB, 1, in, inlen,
+            16, "KEY_AES_128/MODE_ECB");*/
+
+    apr_pool_destroy(pool);
+
+}
+
+/**
+ * Encrypt CommonCrypto, decrypt OpenSSL.
+ */
+static void test_crypto_block_commoncrypto_openssl_pad(abts_case *tc,
+        void *data)
+{
+    apr_pool_t *pool = NULL;
+    const apr_crypto_driver_t *drivers[] =
+    { NULL, NULL };
+
+    const unsigned char *in = (const unsigned char *) TEST_STRING;
+    apr_size_t inlen = sizeof(TEST_STRING);
+
+    apr_pool_create(&pool, NULL);
+    drivers[0] = get_commoncrypto_driver(tc, pool);
+    drivers[1] = get_openssl_driver(tc, pool);
+
+    crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 1, in,
+            inlen, 24, "KEY_3DES_192/MODE_CBC");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_ECB, 1, in,
+            inlen, 24, "KEY_3DES_192/MODE_ECB");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 1, in,
+            inlen, 32, "KEY_AES_256/MODE_CBC");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_ECB, 1, in,
+            inlen, 32, "KEY_AES_256/MODE_ECB");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 1, in,
+            inlen, 24, "KEY_AES_192/MODE_CBC");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_ECB, 1, in,
+            inlen, 24, "KEY_AES_192/MODE_ECB");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 1, in,
+            inlen, 16, "KEY_AES_128/MODE_CBC");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_ECB, 1, in,
+            inlen, 16, "KEY_AES_128/MODE_ECB");
+
+    apr_pool_destroy(pool);
+
+}
+
+/**
+ * Encrypt OpenSSL, decrypt CommonCrypto.
+ */
+static void test_crypto_block_openssl_commoncrypto_pad(abts_case *tc,
+        void *data)
+{
+    apr_pool_t *pool = NULL;
+    const apr_crypto_driver_t *drivers[] =
+    { NULL, NULL };
+
+    const unsigned char *in = (const unsigned char *) TEST_STRING;
+    apr_size_t inlen = sizeof(TEST_STRING);
+
+    apr_pool_create(&pool, NULL);
+    drivers[0] = get_openssl_driver(tc, pool);
+    drivers[1] = get_commoncrypto_driver(tc, pool);
+
+    crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 1, in,
+            inlen, 24, "KEY_3DES_192/MODE_CBC");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_ECB, 1, in,
+            inlen, 24, "KEY_3DES_192/MODE_ECB");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 1, in,
+            inlen, 32, "KEY_AES_256/MODE_CBC");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_ECB, 1, in,
+            inlen, 32, "KEY_AES_256/MODE_ECB");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 1, in,
+            inlen, 24, "KEY_AES_192/MODE_CBC");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_ECB, 1, in,
+            inlen, 24, "KEY_AES_192/MODE_ECB");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 1, in,
+            inlen, 16, "KEY_AES_128/MODE_CBC");
+    crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_ECB, 1, in,
+            inlen, 16, "KEY_AES_128/MODE_ECB");
+
+    apr_pool_destroy(pool);
+
+}
+
+/**
+ * Get Types, OpenSSL.
+ */
+static void test_crypto_get_block_key_types_openssl(abts_case *tc, void *data)
+{
+    apr_pool_t *pool = NULL;
+    const apr_crypto_driver_t *driver;
+    apr_crypto_t *f;
+    apr_hash_t *types;
+    int *key_3des_192;
+    int *key_aes_128;
+    int *key_aes_192;
+    int *key_aes_256;
+
+    apr_pool_create(&pool, NULL);
+    driver = get_openssl_driver(tc, pool);
+    if (driver) {
+
+        f = make(tc, pool, driver);
+        apr_crypto_get_block_key_types(&types, f);
+
+        key_3des_192 = apr_hash_get(types, "3des192", APR_HASH_KEY_STRING);
+        ABTS_PTR_NOTNULL(tc, key_3des_192);
+        ABTS_INT_EQUAL(tc, *key_3des_192, APR_KEY_3DES_192);
+
+        key_aes_128 = apr_hash_get(types, "aes128", APR_HASH_KEY_STRING);
+        ABTS_PTR_NOTNULL(tc, key_aes_128);
+        ABTS_INT_EQUAL(tc, *key_aes_128, APR_KEY_AES_128);
+
+        key_aes_192 = apr_hash_get(types, "aes192", APR_HASH_KEY_STRING);
+        ABTS_PTR_NOTNULL(tc, key_aes_192);
+        ABTS_INT_EQUAL(tc, *key_aes_192, APR_KEY_AES_192);
+
+        key_aes_256 = apr_hash_get(types, "aes256", APR_HASH_KEY_STRING);
+        ABTS_PTR_NOTNULL(tc, key_aes_256);
+        ABTS_INT_EQUAL(tc, *key_aes_256, APR_KEY_AES_256);
+
+    }
+
+    apr_pool_destroy(pool);
+
+}
+
+/**
+ * Get Types, NSS.
+ */
+static void test_crypto_get_block_key_types_nss(abts_case *tc, void *data)
+{
+    apr_pool_t *pool = NULL;
+    const apr_crypto_driver_t *driver;
+    apr_crypto_t *f;
+    apr_hash_t *types;
+    int *key_3des_192;
+    int *key_aes_128;
+    int *key_aes_192;
+    int *key_aes_256;
+
+    apr_pool_create(&pool, NULL);
+    driver = get_nss_driver(tc, pool);
+    if (driver) {
+
+        f = make(tc, pool, driver);
+        apr_crypto_get_block_key_types(&types, f);
+
+        key_3des_192 = apr_hash_get(types, "3des192", APR_HASH_KEY_STRING);
+        ABTS_PTR_NOTNULL(tc, key_3des_192);
+        ABTS_INT_EQUAL(tc, *key_3des_192, APR_KEY_3DES_192);
+
+        key_aes_128 = apr_hash_get(types, "aes128", APR_HASH_KEY_STRING);
+        ABTS_PTR_NOTNULL(tc, key_aes_128);
+        ABTS_INT_EQUAL(tc, *key_aes_128, APR_KEY_AES_128);
+
+        key_aes_192 = apr_hash_get(types, "aes192", APR_HASH_KEY_STRING);
+        ABTS_PTR_NOTNULL(tc, key_aes_192);
+        ABTS_INT_EQUAL(tc, *key_aes_192, APR_KEY_AES_192);
+
+        key_aes_256 = apr_hash_get(types, "aes256", APR_HASH_KEY_STRING);
+        ABTS_PTR_NOTNULL(tc, key_aes_256);
+        ABTS_INT_EQUAL(tc, *key_aes_256, APR_KEY_AES_256);
+
+    }
+
+    apr_pool_destroy(pool);
+
+}
+
+/**
+ * Get Types, Common Crypto.
+ */
+static void test_crypto_get_block_key_types_commoncrypto(abts_case *tc, void *data)
+{
+    apr_pool_t *pool = NULL;
+    const apr_crypto_driver_t *driver;
+    apr_crypto_t *f;
+    apr_hash_t *types;
+    int *key_3des_192;
+    int *key_aes_128;
+    int *key_aes_192;
+    int *key_aes_256;
+
+    apr_pool_create(&pool, NULL);
+    driver = get_commoncrypto_driver(tc, pool);
+    if (driver) {
+
+        f = make(tc, pool, driver);
+        apr_crypto_get_block_key_types(&types, f);
+
+        key_3des_192 = apr_hash_get(types, "3des192", APR_HASH_KEY_STRING);
+        ABTS_PTR_NOTNULL(tc, key_3des_192);
+        ABTS_INT_EQUAL(tc, *key_3des_192, APR_KEY_3DES_192);
+
+        key_aes_128 = apr_hash_get(types, "aes128", APR_HASH_KEY_STRING);
+        ABTS_PTR_NOTNULL(tc, key_aes_128);
+        ABTS_INT_EQUAL(tc, *key_aes_128, APR_KEY_AES_128);
+
+        key_aes_192 = apr_hash_get(types, "aes192", APR_HASH_KEY_STRING);
+        ABTS_PTR_NOTNULL(tc, key_aes_192);
+        ABTS_INT_EQUAL(tc, *key_aes_192, APR_KEY_AES_192);
+
+        key_aes_256 = apr_hash_get(types, "aes256", APR_HASH_KEY_STRING);
+        ABTS_PTR_NOTNULL(tc, key_aes_256);
+        ABTS_INT_EQUAL(tc, *key_aes_256, APR_KEY_AES_256);
+
+    }
+
+    apr_pool_destroy(pool);
+
+}
+
+/**
+ * Get Modes, OpenSSL.
+ */
+static void test_crypto_get_block_key_modes_openssl(abts_case *tc, void *data)
+{
+    apr_pool_t *pool = NULL;
+    const apr_crypto_driver_t *driver;
+    apr_crypto_t *f;
+    apr_hash_t *modes;
+    int *mode_ecb;
+    int *mode_cbc;
+
+    apr_pool_create(&pool, NULL);
+    driver = get_openssl_driver(tc, pool);
+    if (driver) {
+
+        f = make(tc, pool, driver);
+        apr_crypto_get_block_key_modes(&modes, f);
+
+        mode_ecb = apr_hash_get(modes, "ecb", APR_HASH_KEY_STRING);
+        ABTS_PTR_NOTNULL(tc, mode_ecb);
+        ABTS_INT_EQUAL(tc, *mode_ecb, APR_MODE_ECB);
+
+        mode_cbc = apr_hash_get(modes, "cbc", APR_HASH_KEY_STRING);
+        ABTS_PTR_NOTNULL(tc, mode_cbc);
+        ABTS_INT_EQUAL(tc, *mode_cbc, APR_MODE_CBC);
+
+    }
+
+    apr_pool_destroy(pool);
+
+}
+
+/**
+ * Get Modes, NSS.
+ */
+static void test_crypto_get_block_key_modes_nss(abts_case *tc, void *data)
+{
+    apr_pool_t *pool = NULL;
+    const apr_crypto_driver_t *driver;
+    apr_crypto_t *f;
+    apr_hash_t *modes;
+    int *mode_ecb;
+    int *mode_cbc;
+
+    apr_pool_create(&pool, NULL);
+    driver = get_nss_driver(tc, pool);
+    if (driver) {
+
+        f = make(tc, pool, driver);
+        apr_crypto_get_block_key_modes(&modes, f);
+
+        mode_ecb = apr_hash_get(modes, "ecb", APR_HASH_KEY_STRING);
+        ABTS_PTR_NOTNULL(tc, mode_ecb);
+        ABTS_INT_EQUAL(tc, *mode_ecb, APR_MODE_ECB);
+
+        mode_cbc = apr_hash_get(modes, "cbc", APR_HASH_KEY_STRING);
+        ABTS_PTR_NOTNULL(tc, mode_cbc);
+        ABTS_INT_EQUAL(tc, *mode_cbc, APR_MODE_CBC);
+
+    }
+
+    apr_pool_destroy(pool);
+
+}
+
+/**
+ * Get Modes, Common Crypto.
+ */
+static void test_crypto_get_block_key_modes_commoncrypto(abts_case *tc, void *data)
+{
+    apr_pool_t *pool = NULL;
+    const apr_crypto_driver_t *driver;
+    apr_crypto_t *f;
+    apr_hash_t *modes;
+    int *mode_ecb;
+    int *mode_cbc;
+
+    apr_pool_create(&pool, NULL);
+    driver = get_commoncrypto_driver(tc, pool);
+    if (driver) {
+
+        f = make(tc, pool, driver);
+        apr_crypto_get_block_key_modes(&modes, f);
+
+        mode_ecb = apr_hash_get(modes, "ecb", APR_HASH_KEY_STRING);
+        ABTS_PTR_NOTNULL(tc, mode_ecb);
+        ABTS_INT_EQUAL(tc, *mode_ecb, APR_MODE_ECB);
+
+        mode_cbc = apr_hash_get(modes, "cbc", APR_HASH_KEY_STRING);
+        ABTS_PTR_NOTNULL(tc, mode_cbc);
+        ABTS_INT_EQUAL(tc, *mode_cbc, APR_MODE_CBC);
+
+    }
+
+    apr_pool_destroy(pool);
+
+}
+
+static void test_crypto_memzero(abts_case *tc, void *data)
+{
+    /* Aligned message */
+    struct {
+        char buf[7 * sizeof(int)];
+        int untouched;
+    } msg;
+    /* A bit of type punning such that 'msg' might look unused
+     * after the call to apr_crypto_memzero().
+     */
+    int *ptr = (int *)&msg;
+    int i;
+
+    /* Fill buf with non-zeros (odds) */
+    for (i = 1; i < 2 * sizeof(msg.buf); i += 2) {
+        msg.buf[i / 2] = (char)i;
+        ABTS_ASSERT(tc, "test_crypto_memzero() barrier", msg.buf[i / 2] != 0);
+    }
+
+    /* Zero out the whole, and check it */
+    apr_crypto_memzero(&msg, sizeof msg);
+    for (i = 0; i < sizeof(msg) / sizeof(*ptr); ++i) {
+        ABTS_ASSERT(tc, "test_crypto_memzero() optimized out", ptr[i] == 0);
+    }
+}
+
+static void test_crypto_equals(abts_case *tc, void *data)
+{
+    /* Buffers of each type of scalar */
+    union {
+        char c;
+        short s;
+        int i;
+        long l;
+        float f;
+        double d;
+        void *p;
+    } buf0[7], buf1[7], buf[7];
+    char *ptr = (char *)buf;
+    int i;
+
+#define TEST_SCALAR_MATCH(i, x, r) \
+    ABTS_ASSERT(tc, "test_crypto_equals(" APR_STRINGIFY(x) ")" \
+                                   " != " APR_STRINGIFY(r), \
+                apr_crypto_equals(&buf##r[i].x, &buf[i].x, \
+                                  sizeof(buf[i].x)) == r)
+
+    /* Fill buf with non-zeros (odds) */
+    for (i = 1; i < 2 * sizeof(buf); i += 2) {
+        ptr[i / 2] = (char)i;
+    }
+    /* Set buf1 = buf */
+    memcpy(buf1, buf, sizeof buf);
+    /* Set buf0 = {0} */
+    memset(buf0, 0, sizeof buf0);
+
+    /* Check that buf1 == buf for each scalar */
+    TEST_SCALAR_MATCH(0, c, 1);
+    TEST_SCALAR_MATCH(1, s, 1);
+    TEST_SCALAR_MATCH(2, i, 1);
+    TEST_SCALAR_MATCH(3, l, 1);
+    TEST_SCALAR_MATCH(4, f, 1);
+    TEST_SCALAR_MATCH(5, d, 1);
+    TEST_SCALAR_MATCH(6, p, 1);
+
+    /* Check that buf0 != buf for each scalar */
+    TEST_SCALAR_MATCH(0, c, 0);
+    TEST_SCALAR_MATCH(1, s, 0);
+    TEST_SCALAR_MATCH(2, i, 0);
+    TEST_SCALAR_MATCH(3, l, 0);
+    TEST_SCALAR_MATCH(4, f, 0);
+    TEST_SCALAR_MATCH(5, d, 0);
+    TEST_SCALAR_MATCH(6, p, 0);
+}
+
+abts_suite *testcrypto(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite);
+
+    /* test simple init and shutdown */
+    abts_run_test(suite, test_crypto_init, NULL);
+
+    /* test key parsing - openssl */
+    abts_run_test(suite, test_crypto_key_openssl, NULL);
+
+    /* test key parsing - nss */
+    abts_run_test(suite, test_crypto_key_nss, NULL);
+
+    /* test key parsing - commoncrypto */
+    abts_run_test(suite, test_crypto_key_commoncrypto, NULL);
+
+    /* test a simple encrypt / decrypt operation - openssl */
+    abts_run_test(suite, test_crypto_block_openssl, NULL);
+
+    /* test a padded encrypt / decrypt operation - openssl */
+    abts_run_test(suite, test_crypto_block_openssl_pad, NULL);
+
+    /* test a simple encrypt / decrypt operation - nss */
+    abts_run_test(suite, test_crypto_block_nss, NULL);
+
+    /* test a padded encrypt / decrypt operation - nss */
+    abts_run_test(suite, test_crypto_block_nss_pad, NULL);
+
+    /* test a simple encrypt / decrypt operation - commoncrypto */
+    abts_run_test(suite, test_crypto_block_commoncrypto, NULL);
+
+    /* test a padded encrypt / decrypt operation - commoncrypto */
+    abts_run_test(suite, test_crypto_block_commoncrypto_pad, NULL);
+
+    /* test encrypt nss / decrypt openssl */
+    abts_run_test(suite, test_crypto_block_nss_openssl, NULL);
+
+    /* test padded encrypt nss / decrypt openssl */
+    abts_run_test(suite, test_crypto_block_nss_openssl_pad, NULL);
+
+    /* test encrypt openssl / decrypt nss */
+    abts_run_test(suite, test_crypto_block_openssl_nss, NULL);
+
+    /* test padded encrypt openssl / decrypt nss */
+    abts_run_test(suite, test_crypto_block_openssl_nss_pad, NULL);
+
+    /* test encrypt openssl / decrypt commoncrypto */
+    abts_run_test(suite, test_crypto_block_openssl_commoncrypto, NULL);
+
+    /* test padded encrypt openssl / decrypt commoncrypto */
+    abts_run_test(suite, test_crypto_block_openssl_commoncrypto_pad, NULL);
+
+    /* test encrypt commoncrypto / decrypt openssl */
+    abts_run_test(suite, test_crypto_block_commoncrypto_openssl, NULL);
+
+    /* test padded encrypt commoncrypto / decrypt openssl */
+    abts_run_test(suite, test_crypto_block_commoncrypto_openssl_pad, NULL);
+
+    /* test block key types openssl */
+    abts_run_test(suite, test_crypto_get_block_key_types_openssl, NULL);
+
+    /* test block key types nss */
+    abts_run_test(suite, test_crypto_get_block_key_types_nss, NULL);
+
+    /* test block key types commoncrypto */
+    abts_run_test(suite, test_crypto_get_block_key_types_commoncrypto, NULL);
+
+    /* test block key modes openssl */
+    abts_run_test(suite, test_crypto_get_block_key_modes_openssl, NULL);
+
+    /* test block key modes nss */
+    abts_run_test(suite, test_crypto_get_block_key_modes_nss, NULL);
+
+    /* test block key modes commoncrypto */
+    abts_run_test(suite, test_crypto_get_block_key_modes_commoncrypto, NULL);
+
+    abts_run_test(suite, test_crypto_memzero, NULL);
+    abts_run_test(suite, test_crypto_equals, NULL);
+
+    return suite;
+}
+
+#else
+
+/**
+ * Dummy test suite when crypto is turned off.
+ */
+abts_suite *testcrypto(abts_suite *suite)
+{
+    return ADD_SUITE(suite);
+}
+
+#endif /* APU_HAVE_CRYPTO */
diff --git a/test/testdate.c b/test/testdate.c
new file mode 100644
index 00000000000..b4e2edf263e
--- /dev/null
+++ b/test/testdate.c
@@ -0,0 +1,202 @@
+/* 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 "abts.h"
+#include "testutil.h"
+#include "apr_date.h"
+#include "apr_general.h"
+
+#if APR_HAVE_TIME_H
+#include <time.h>
+#endif /* APR_HAVE_TIME_H */
+
+static struct datetest {
+  const char *input;
+  const char *output;
+} tests[] = {
+  { "Mon, 27 Feb 1995 20:49:44 -0800",  "Tue, 28 Feb 1995 04:49:44 GMT" },
+  { "Fri,  1 Jul 2005 11:34:25 -0400",  "Fri, 01 Jul 2005 15:34:25 GMT" },
+  { "Monday, 27-Feb-95 20:49:44 -0800", "Tue, 28 Feb 1995 04:49:44 GMT" },
+  { "Tue, 4 Mar 1997 12:43:52 +0200",   "Tue, 04 Mar 1997 10:43:52 GMT" },
+  { "Mon, 27 Feb 95 20:49:44 -0800",    "Tue, 28 Feb 1995 04:49:44 GMT" },
+  { "Tue,  4 Mar 97 12:43:52 +0200",    "Tue, 04 Mar 1997 10:43:52 GMT" },
+  { "Tue, 4 Mar 97 12:43:52 +0200",     "Tue, 04 Mar 1997 10:43:52 GMT" },
+  { "Mon, 27 Feb 95 20:49 GMT",         "Mon, 27 Feb 1995 20:49:00 GMT" },
+  { "Tue, 4 Mar 97 12:43 GMT",          "Tue, 04 Mar 1997 12:43:00 GMT" },
+  { NULL, NULL }
+};
+
+static const apr_time_t year2secs[] = {
+             APR_INT64_C(0),    /* 1970 */
+      APR_INT64_C(31536000),    /* 1971 */
+      APR_INT64_C(63072000),    /* 1972 */
+      APR_INT64_C(94694400),    /* 1973 */
+     APR_INT64_C(126230400),    /* 1974 */
+     APR_INT64_C(157766400),    /* 1975 */
+     APR_INT64_C(189302400),    /* 1976 */
+     APR_INT64_C(220924800),    /* 1977 */
+     APR_INT64_C(252460800),    /* 1978 */
+     APR_INT64_C(283996800),    /* 1979 */
+     APR_INT64_C(315532800),    /* 1980 */
+     APR_INT64_C(347155200),    /* 1981 */
+     APR_INT64_C(378691200),    /* 1982 */
+     APR_INT64_C(410227200),    /* 1983 */
+     APR_INT64_C(441763200),    /* 1984 */
+     APR_INT64_C(473385600),    /* 1985 */
+     APR_INT64_C(504921600),    /* 1986 */
+     APR_INT64_C(536457600),    /* 1987 */
+     APR_INT64_C(567993600),    /* 1988 */
+     APR_INT64_C(599616000),    /* 1989 */
+     APR_INT64_C(631152000),    /* 1990 */
+     APR_INT64_C(662688000),    /* 1991 */
+     APR_INT64_C(694224000),    /* 1992 */
+     APR_INT64_C(725846400),    /* 1993 */
+     APR_INT64_C(757382400),    /* 1994 */
+     APR_INT64_C(788918400),    /* 1995 */
+     APR_INT64_C(820454400),    /* 1996 */
+     APR_INT64_C(852076800),    /* 1997 */
+     APR_INT64_C(883612800),    /* 1998 */
+     APR_INT64_C(915148800),    /* 1999 */
+     APR_INT64_C(946684800),    /* 2000 */
+     APR_INT64_C(978307200),    /* 2001 */
+    APR_INT64_C(1009843200),    /* 2002 */
+    APR_INT64_C(1041379200),    /* 2003 */
+    APR_INT64_C(1072915200),    /* 2004 */
+    APR_INT64_C(1104537600),    /* 2005 */
+    APR_INT64_C(1136073600),    /* 2006 */
+    APR_INT64_C(1167609600),    /* 2007 */
+    APR_INT64_C(1199145600),    /* 2008 */
+    APR_INT64_C(1230768000),    /* 2009 */
+    APR_INT64_C(1262304000),    /* 2010 */
+    APR_INT64_C(1293840000),    /* 2011 */
+    APR_INT64_C(1325376000),    /* 2012 */
+    APR_INT64_C(1356998400),    /* 2013 */
+    APR_INT64_C(1388534400),    /* 2014 */
+    APR_INT64_C(1420070400),    /* 2015 */
+    APR_INT64_C(1451606400),    /* 2016 */
+    APR_INT64_C(1483228800),    /* 2017 */
+    APR_INT64_C(1514764800),    /* 2018 */
+    APR_INT64_C(1546300800),    /* 2019 */
+    APR_INT64_C(1577836800),    /* 2020 */
+    APR_INT64_C(1609459200),    /* 2021 */
+    APR_INT64_C(1640995200),    /* 2022 */
+    APR_INT64_C(1672531200),    /* 2023 */
+    APR_INT64_C(1704067200),    /* 2024 */
+    APR_INT64_C(1735689600),    /* 2025 */
+    APR_INT64_C(1767225600),    /* 2026 */
+    APR_INT64_C(1798761600),    /* 2027 */
+    APR_INT64_C(1830297600),    /* 2028 */
+    APR_INT64_C(1861920000),    /* 2029 */
+    APR_INT64_C(1893456000),    /* 2030 */
+    APR_INT64_C(1924992000),    /* 2031 */
+    APR_INT64_C(1956528000),    /* 2032 */
+    APR_INT64_C(1988150400),    /* 2033 */
+    APR_INT64_C(2019686400),    /* 2034 */
+    APR_INT64_C(2051222400),    /* 2035 */
+    APR_INT64_C(2082758400),    /* 2036 */
+    APR_INT64_C(2114380800),    /* 2037 */
+    APR_INT64_C(2145916800)     /* 2038 */
+};
+
+const char month_snames[12][4] = {
+    "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"
+};
+
+/* XXX: non-portable */
+static void gm_timestr_822(char *ts, apr_time_t sec)
+{
+    static const char *const days[7]=
+        {"Sun","Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
+    struct tm *tms;
+    time_t ls = (time_t)sec;
+
+    tms = gmtime(&ls);
+
+    sprintf(ts, "%s, %.2d %s %d %.2d:%.2d:%.2d GMT", days[tms->tm_wday],
+            tms->tm_mday, month_snames[tms->tm_mon], tms->tm_year + 1900,
+            tms->tm_hour, tms->tm_min, tms->tm_sec);
+}
+
+/* Linear congruential generator */
+static apr_uint32_t lgc(apr_uint32_t a)
+{
+    apr_uint64_t z = a;
+    z *= 279470273;
+    z %= APR_UINT64_C(4294967291);
+    return (apr_uint32_t)z;
+}
+
+static void test_date_parse_http(abts_case *tc, void *data)
+{
+    int year, i;
+    apr_time_t guess;
+    apr_time_t offset = 0;
+    apr_time_t secstodate, newsecs;
+    char datestr[50];
+
+    for (year = 1970; year < 2038; ++year) {
+        secstodate = year2secs[year - 1970] + offset;
+        gm_timestr_822(datestr, secstodate);
+        secstodate *= APR_USEC_PER_SEC;
+        newsecs = apr_date_parse_http(datestr);
+        ABTS_TRUE(tc, secstodate == newsecs);
+    }
+
+#if APR_HAS_RANDOM
+    apr_generate_random_bytes((unsigned char *)&guess, sizeof(guess));
+#else
+    guess = apr_time_now() % APR_TIME_C(4294967291);
+#endif
+
+    for (i = 0; i < 10000; ++i) {
+        guess = (time_t)lgc((apr_uint32_t)guess);
+        if (guess < 0)
+            guess *= -1;
+        secstodate = guess + offset;
+        gm_timestr_822(datestr, secstodate);
+        secstodate *= APR_USEC_PER_SEC;
+        newsecs = apr_date_parse_http(datestr);
+        ABTS_TRUE(tc, secstodate == newsecs);
+    }
+}
+
+static void test_date_rfc(abts_case *tc, void *data)
+{
+    apr_time_t date;
+    int i = 0;
+
+    while (tests[i].input) {
+        char str_date[APR_RFC822_DATE_LEN] = { 0 };
+
+        date = apr_date_parse_rfc(tests[i].input);
+
+        apr_rfc822_date(str_date, date);
+
+        ABTS_STR_EQUAL(tc, str_date, tests[i].output);
+
+        i++;
+    }
+}
+
+abts_suite *testdate(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite);
+
+    abts_run_test(suite, test_date_parse_http, NULL);
+    abts_run_test(suite, test_date_rfc, NULL);
+
+    return suite;
+}
diff --git a/test/testdbd.c b/test/testdbd.c
new file mode 100644
index 00000000000..b94c491b932
--- /dev/null
+++ b/test/testdbd.c
@@ -0,0 +1,245 @@
+/* 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 "testutil.h"
+#include "apr.h"
+#include "apu.h"
+#include "apr_pools.h"
+#include "apr_dbd.h"
+#include "apr_strings.h"
+
+static void test_dbd_init(abts_case *tc, void *data)
+{
+    apr_pool_t *pool = p;
+    apr_status_t rv;
+
+    rv = apr_dbd_init(pool);
+    ABTS_ASSERT(tc, "failed to init apr_dbd", rv == APR_SUCCESS);
+}
+
+#if APU_HAVE_SQLITE2 || APU_HAVE_SQLITE3
+static void test_statement(abts_case *tc, apr_dbd_t* handle,
+                           const apr_dbd_driver_t* driver, const char* sql)
+{
+    int nrows;
+    apr_status_t rv;
+
+    rv = apr_dbd_query(driver, handle, &nrows, sql);
+
+    ABTS_ASSERT(tc, sql, rv == APR_SUCCESS);
+}
+
+static void create_table(abts_case *tc, apr_dbd_t* handle,
+                         const apr_dbd_driver_t* driver)
+{
+    const char *sql = "CREATE TABLE apr_dbd_test ("
+                             "col1 varchar(40) not null,"
+                             "col2 varchar(40),"
+                             "col3 integer)";
+
+    test_statement(tc, handle, driver, sql);
+}
+
+static void drop_table(abts_case *tc, apr_dbd_t* handle,
+                       const apr_dbd_driver_t* driver)
+{
+    const char *sql = "DROP TABLE apr_dbd_test";
+    test_statement(tc, handle, driver, sql);
+}
+
+static void delete_rows(abts_case *tc, apr_dbd_t* handle,
+                        const apr_dbd_driver_t* driver)
+{
+    const char *sql = "DELETE FROM apr_dbd_test";
+    test_statement(tc, handle, driver, sql);
+}
+
+
+static void insert_data(abts_case *tc, apr_dbd_t* handle,
+                        const apr_dbd_driver_t* driver, int count)
+{
+    apr_pool_t* pool = p;
+    const char* sql = "INSERT INTO apr_dbd_test VALUES('%d', '%d', %d)";
+    char* sqf = NULL;
+    int i;
+    int nrows;
+    apr_status_t rv;
+
+    for (i=0; i<count; i++) {
+        sqf = apr_psprintf(pool, sql, i, i, i);
+        rv = apr_dbd_query(driver, handle, &nrows, sqf);
+        ABTS_ASSERT(tc, sqf, rv == APR_SUCCESS);
+        ABTS_ASSERT(tc, sqf, 1 == nrows);
+    }
+}
+
+static void select_rows(abts_case *tc, apr_dbd_t* handle,
+                        const apr_dbd_driver_t* driver, int count)
+{
+    apr_status_t rv;
+    apr_pool_t* pool = p;
+    apr_pool_t* tpool;
+    const char* sql = "SELECT * FROM apr_dbd_test ORDER BY col1";
+    apr_dbd_results_t *res = NULL;
+    apr_dbd_row_t *row = NULL;
+    int i;
+
+    rv = apr_dbd_select(driver, pool, handle, &res, sql, 0);
+    ABTS_ASSERT(tc, sql, rv == APR_SUCCESS);
+    ABTS_PTR_NOTNULL(tc, res);
+
+    apr_pool_create(&tpool, pool);
+    i = count;
+    while (i > 0) {
+        row = NULL;
+        rv = apr_dbd_get_row(driver, pool, res, &row, -1);
+        ABTS_ASSERT(tc, sql, rv == APR_SUCCESS);
+        ABTS_PTR_NOTNULL(tc, row);
+        apr_pool_clear(tpool);
+        i--;
+    }
+    ABTS_ASSERT(tc, "Missing Rows!", i == 0);
+
+    res = NULL;
+    i = count;
+
+    rv = apr_dbd_select(driver, pool, handle, &res, sql, 1);
+    ABTS_ASSERT(tc, sql, rv == APR_SUCCESS);
+    ABTS_PTR_NOTNULL(tc, res);
+
+    rv = apr_dbd_num_tuples(driver, res);
+    ABTS_ASSERT(tc, "invalid row count", rv == count);
+
+    while (i > 0) {
+        row = NULL;
+        rv = apr_dbd_get_row(driver, pool, res, &row, i);
+        ABTS_ASSERT(tc, sql, rv == APR_SUCCESS);
+        ABTS_PTR_NOTNULL(tc, row);
+        apr_pool_clear(tpool);
+        i--;
+    }
+    ABTS_ASSERT(tc, "Missing Rows!", i == 0);
+    rv = apr_dbd_get_row(driver, pool, res, &row, count+100);
+    ABTS_ASSERT(tc, "If we overseek, get_row should return -1", rv == -1);
+}
+
+static void test_escape(abts_case *tc, apr_dbd_t *handle,
+                        const apr_dbd_driver_t *driver)
+{
+  const char *escaped = apr_dbd_escape(driver, p, "foo'bar", handle);
+
+  ABTS_STR_EQUAL(tc, "foo''bar", escaped);
+}
+
+static void test_dbd_generic(abts_case *tc, apr_dbd_t* handle,
+                             const apr_dbd_driver_t* driver)
+{
+    void* native;
+    apr_pool_t *pool = p;
+    apr_status_t rv;
+
+    native = apr_dbd_native_handle(driver, handle);
+    ABTS_PTR_NOTNULL(tc, native);
+
+    rv = apr_dbd_check_conn(driver, pool, handle);
+
+    create_table(tc, handle, driver);
+    select_rows(tc, handle, driver, 0);
+    insert_data(tc, handle, driver, 5);
+    select_rows(tc, handle, driver, 5);
+    delete_rows(tc, handle, driver);
+    select_rows(tc, handle, driver, 0);
+    drop_table(tc, handle, driver);
+
+    test_escape(tc, handle, driver);
+
+    rv = apr_dbd_close(driver, handle);
+    ABTS_ASSERT(tc, "failed to close database", rv == APR_SUCCESS);
+}
+#endif
+
+#if APU_HAVE_SQLITE2
+static void test_dbd_sqlite2(abts_case *tc, void *data)
+{
+    apr_pool_t *pool = p;
+    apr_status_t rv;
+    const apr_dbd_driver_t* driver = NULL;
+    apr_dbd_t* handle = NULL;
+
+    rv = apr_dbd_get_driver(pool, "sqlite2", &driver);
+    ABTS_ASSERT(tc, "failed to fetch sqlite2 driver", rv == APR_SUCCESS);
+    ABTS_PTR_NOTNULL(tc, driver);
+    if (!driver) {
+    	return;
+    }
+
+    ABTS_STR_EQUAL(tc, "sqlite2", apr_dbd_name(driver));
+
+    rv = apr_dbd_open(driver, pool, "data/sqlite2.db:600", &handle);
+    ABTS_ASSERT(tc, "failed to open sqlite2 atabase", rv == APR_SUCCESS);
+    ABTS_PTR_NOTNULL(tc, handle);
+    if (!handle) {
+    	return;
+    }
+
+    test_dbd_generic(tc, handle, driver);
+}
+#endif
+
+#if APU_HAVE_SQLITE3
+static void test_dbd_sqlite3(abts_case *tc, void *data)
+{
+    apr_pool_t *pool = p;
+    apr_status_t rv;
+    const apr_dbd_driver_t* driver = NULL;
+    apr_dbd_t* handle = NULL;
+
+    rv = apr_dbd_get_driver(pool, "sqlite3", &driver);
+    ABTS_ASSERT(tc, "failed to fetch sqlite3 driver", rv == APR_SUCCESS);
+    ABTS_PTR_NOTNULL(tc, driver);
+    if (!driver) {
+    	return;
+    }
+
+    ABTS_STR_EQUAL(tc, "sqlite3", apr_dbd_name(driver));
+
+    rv = apr_dbd_open(driver, pool, "data/sqlite3.db", &handle);
+    ABTS_ASSERT(tc, "failed to open sqlite3 database", rv == APR_SUCCESS);
+    ABTS_PTR_NOTNULL(tc, handle);
+    if (!handle) {
+    	return;
+    }
+
+    test_dbd_generic(tc, handle, driver);
+}
+#endif
+
+abts_suite *testdbd(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite);
+
+
+    abts_run_test(suite, test_dbd_init, NULL);
+
+#if APU_HAVE_SQLITE2
+    abts_run_test(suite, test_dbd_sqlite2, NULL);
+#endif
+
+#if APU_HAVE_SQLITE3
+    abts_run_test(suite, test_dbd_sqlite3, NULL);
+#endif
+    return suite;
+}
diff --git a/test/testdbm.c b/test/testdbm.c
new file mode 100644
index 00000000000..aaea4116bc2
--- /dev/null
+++ b/test/testdbm.c
@@ -0,0 +1,221 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_general.h"
+#include "apr_pools.h"
+#include "apr_errno.h"
+#include "apr_dbm.h"
+#include "apr_uuid.h"
+#include "apr_strings.h"
+#include "abts.h"
+#include "testutil.h"
+
+#define NUM_TABLE_ROWS  1024
+
+typedef struct {
+    apr_datum_t key;
+    apr_datum_t val;
+    int deleted;
+    int visited;
+} dbm_table_t;
+
+static dbm_table_t *generate_table(void)
+{
+    unsigned int i;
+    apr_uuid_t uuid;
+    dbm_table_t *table = apr_pcalloc(p, sizeof(*table) * NUM_TABLE_ROWS);
+
+    for (i = 0; i < NUM_TABLE_ROWS/2; i++) {
+        apr_uuid_get(&uuid);
+        table[i].key.dptr = apr_pmemdup(p, uuid.data, sizeof(uuid.data));
+        table[i].key.dsize = sizeof(uuid.data);
+        table[i].val.dptr = apr_palloc(p, APR_UUID_FORMATTED_LENGTH + 1);
+        table[i].val.dsize = APR_UUID_FORMATTED_LENGTH + 1;
+        apr_uuid_format(table[i].val.dptr, &uuid);
+    }
+
+    for (; i < NUM_TABLE_ROWS; i++) {
+        apr_uuid_get(&uuid);
+        table[i].val.dptr = apr_pmemdup(p, uuid.data, sizeof(uuid.data));
+        table[i].val.dsize = sizeof(uuid.data);
+        table[i].key.dptr = apr_palloc(p, APR_UUID_FORMATTED_LENGTH + 1);
+        table[i].key.dsize = APR_UUID_FORMATTED_LENGTH + 1;
+        apr_uuid_format(table[i].key.dptr, &uuid);
+    }
+
+    return table;
+}
+
+static void test_dbm_store(abts_case *tc, apr_dbm_t *db, dbm_table_t *table)
+{
+    apr_status_t rv;
+    unsigned int i = NUM_TABLE_ROWS - 1;
+
+    for (; i >= NUM_TABLE_ROWS/2; i--) {
+        rv = apr_dbm_store(db, table[i].key, table[i].val);
+        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+        table[i].deleted = FALSE;
+    }
+
+    for (i = 0; i < NUM_TABLE_ROWS/2; i++) {
+        rv = apr_dbm_store(db, table[i].key, table[i].val);
+        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+        table[i].deleted = FALSE;
+    }
+}
+
+static void test_dbm_fetch(abts_case *tc, apr_dbm_t *db, dbm_table_t *table)
+{
+    apr_status_t rv;
+    unsigned int i;
+    apr_datum_t val;
+
+    for (i = 0; i < NUM_TABLE_ROWS; i++) {
+        memset(&val, 0, sizeof(val));
+        rv = apr_dbm_fetch(db, table[i].key, &val);
+        if (!table[i].deleted) {
+            ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+            ABTS_INT_EQUAL(tc, table[i].val.dsize, val.dsize);
+            ABTS_INT_EQUAL(tc, 0, memcmp(table[i].val.dptr, val.dptr, val.dsize));
+            apr_dbm_freedatum(db, val);
+        } else {
+            ABTS_INT_EQUAL(tc, 0, val.dsize);
+        }
+    }
+}
+
+static void test_dbm_delete(abts_case *tc, apr_dbm_t *db, dbm_table_t *table)
+{
+    apr_status_t rv;
+    unsigned int i;
+
+    for (i = 0; i < NUM_TABLE_ROWS; i++) {
+        /* XXX: random */
+        if (i & 1)
+            continue;
+        rv = apr_dbm_delete(db, table[i].key);
+        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+        table[i].deleted = TRUE;
+    }
+}
+
+static void test_dbm_exists(abts_case *tc, apr_dbm_t *db, dbm_table_t *table)
+{
+    unsigned int i;
+    int cond;
+
+    for (i = 0; i < NUM_TABLE_ROWS; i++) {
+        cond = apr_dbm_exists(db, table[i].key);
+        if (table[i].deleted) {
+            ABTS_TRUE(tc, cond == 0);
+        } else {
+            ABTS_TRUE(tc, cond != 0);
+        }
+    }
+}
+
+static void test_dbm_traversal(abts_case *tc, apr_dbm_t *db, dbm_table_t *table)
+{
+    apr_status_t rv;
+    unsigned int i;
+    apr_datum_t key;
+
+    rv = apr_dbm_firstkey(db, &key);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    do {
+        if (key.dptr == NULL || key.dsize == 0)
+            break;
+
+        for (i = 0; i < NUM_TABLE_ROWS; i++) {
+            if (table[i].key.dsize != key.dsize)
+                continue;
+            if (memcmp(table[i].key.dptr, key.dptr, key.dsize))
+                continue;
+            ABTS_INT_EQUAL(tc, 0, table[i].deleted);
+            ABTS_INT_EQUAL(tc, 0, table[i].visited);
+            table[i].visited++;
+        }
+
+        rv = apr_dbm_nextkey(db, &key);
+        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    } while (1);
+
+    for (i = 0; i < NUM_TABLE_ROWS; i++) {
+        if (table[i].deleted)
+            continue;
+        ABTS_INT_EQUAL(tc, 1, table[i].visited);
+        table[i].visited = 0;
+    }
+}
+
+static void test_dbm(abts_case *tc, void *data)
+{
+    apr_dbm_t *db;
+    apr_status_t rv;
+    dbm_table_t *table;
+    const char *type = data;
+    const char *file = apr_pstrcat(p, "data/test-", type, NULL);
+
+    rv = apr_dbm_open_ex(&db, type, file, APR_DBM_RWCREATE, APR_FPROT_OS_DEFAULT, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    if (rv != APR_SUCCESS)
+        return;
+
+    table = generate_table();
+
+    test_dbm_store(tc, db, table);
+    test_dbm_fetch(tc, db, table);
+    test_dbm_delete(tc, db, table);
+    test_dbm_exists(tc, db, table);
+    test_dbm_traversal(tc, db, table);
+
+    apr_dbm_close(db);
+
+    rv = apr_dbm_open_ex(&db, type, file, APR_DBM_READONLY, APR_FPROT_OS_DEFAULT, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    if (rv != APR_SUCCESS)
+        return;
+
+    test_dbm_exists(tc, db, table);
+    test_dbm_traversal(tc, db, table);
+    test_dbm_fetch(tc, db, table);
+
+    apr_dbm_close(db);
+}
+
+abts_suite *testdbm(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite);
+
+#if APU_HAVE_GDBM
+    abts_run_test(suite, test_dbm, "gdbm");
+#endif
+#if APU_HAVE_NDBM
+    abts_run_test(suite, test_dbm, "ndbm");
+#endif
+#if APU_HAVE_SDBM
+    abts_run_test(suite, test_dbm, "sdbm");
+#endif
+#if APU_HAVE_DB
+    abts_run_test(suite, test_dbm, "db");
+#endif
+
+    return suite;
+}
diff --git a/test/testdir.c b/test/testdir.c
new file mode 100644
index 00000000000..87085bd0a0f
--- /dev/null
+++ b/test/testdir.c
@@ -0,0 +1,405 @@
+/* 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "apr_file_io.h"
+#include "apr_file_info.h"
+#include "apr_errno.h"
+#include "apr_general.h"
+#include "apr_lib.h"
+#include "apr_thread_proc.h"
+#include "testutil.h"
+
+static void test_mkdir(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_finfo_t finfo;
+
+    rv = apr_dir_make("data/testdir",
+                      APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_UEXECUTE,
+                      p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_stat(&finfo, "data/testdir", APR_FINFO_TYPE, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_INT_EQUAL(tc, APR_DIR, finfo.filetype);
+}
+
+static void test_mkdir_recurs(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_finfo_t finfo;
+
+    rv = apr_dir_make_recursive("data/one/two/three", 
+                                APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_UEXECUTE,
+                                p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_stat(&finfo, "data/one", APR_FINFO_TYPE, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_INT_EQUAL(tc, APR_DIR, finfo.filetype);
+
+    rv = apr_stat(&finfo, "data/one/two", APR_FINFO_TYPE, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_INT_EQUAL(tc, APR_DIR, finfo.filetype);
+
+    rv = apr_stat(&finfo, "data/one/two/three", APR_FINFO_TYPE, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_INT_EQUAL(tc, APR_DIR, finfo.filetype);
+}
+
+struct thread_data
+{
+    abts_case *tc;
+    apr_pool_t *pool;
+};
+
+static void *APR_THREAD_FUNC thread_mkdir_func(apr_thread_t *thd, void *data)
+{
+    struct thread_data *td = data;
+    apr_status_t s1, s2, s3, s4, s5;
+
+    s1 = apr_dir_make_recursive("data/prll/one/thwo/three",
+                                APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_UEXECUTE,
+                                td->pool);
+    s2 = apr_dir_make_recursive("data/prll/four/five/six/seven/eight",
+                                APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_UEXECUTE,
+                                td->pool);
+    s3 = apr_dir_make_recursive("data/prll/nine/ten",
+                                APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_UEXECUTE,
+                                td->pool);
+    s4 = apr_dir_make_recursive("data/prll/11/12/13/14/15/16/17/18/19/20",
+                                APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_UEXECUTE,
+                                td->pool);
+    s5 = apr_dir_make_recursive("data/fortytwo",
+                                APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_UEXECUTE,
+                                td->pool);
+
+    ABTS_INT_EQUAL(td->tc, APR_SUCCESS, s1);
+    ABTS_INT_EQUAL(td->tc, APR_SUCCESS, s2);
+    ABTS_INT_EQUAL(td->tc, APR_SUCCESS, s3);
+    ABTS_INT_EQUAL(td->tc, APR_SUCCESS, s4);
+    ABTS_INT_EQUAL(td->tc, APR_SUCCESS, s5);
+    return NULL;
+}
+
+static void test_mkdir_recurs_parallel(abts_case *tc, void *data)
+{
+    struct thread_data td1, td2, td3, td4;
+    apr_thread_t *t1, *t2, *t3, *t4;
+    apr_status_t s1, s2, s3, s4;
+
+    td1.tc = td2.tc = td3.tc = td4.tc = tc;
+    apr_pool_create(&td1.pool, p);
+    apr_pool_create(&td2.pool, p);
+    apr_pool_create(&td3.pool, p);
+    apr_pool_create(&td4.pool, p);
+
+    s1 = apr_thread_create(&t1, NULL, thread_mkdir_func, &td1, td1.pool);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, s1);
+    s2 = apr_thread_create(&t2, NULL, thread_mkdir_func, &td2, td2.pool);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, s2);
+    s3 = apr_thread_create(&t3, NULL, thread_mkdir_func, &td3, td3.pool);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, s3);
+    s4 = apr_thread_create(&t4, NULL, thread_mkdir_func, &td4, td4.pool);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, s4);
+
+    apr_thread_join(&s1, t1);
+    apr_thread_join(&s2, t2);
+    apr_thread_join(&s3, t3);
+    apr_thread_join(&s4, t4);
+
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, s1);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, s2);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, s3);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, s4);
+}
+
+static void test_remove(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_finfo_t finfo;
+
+    rv = apr_dir_remove("data/testdir", p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_stat(&finfo, "data/testdir", APR_FINFO_TYPE, p);
+    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOENT(rv));
+}
+
+static void test_removeall_fail(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+
+    rv = apr_dir_remove("data/one", p);
+    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOTEMPTY(rv));
+}
+
+static void test_removeall(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+
+    rv = apr_dir_remove("data/one/two/three", p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_dir_remove("data/one/two", p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_dir_remove("data/one", p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_dir_remove("data/prll/one/thwo/three", p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_dir_remove("data/prll/one/thwo", p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_dir_remove("data/prll/one", p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_dir_remove("data/prll/four/five/six/seven/eight", p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_dir_remove("data/prll/four/five/six/seven", p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_dir_remove("data/prll/four/five/six", p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_dir_remove("data/prll/four/five", p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_dir_remove("data/prll/four", p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_dir_remove("data/prll/nine/ten", p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_dir_remove("data/prll/nine", p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_dir_remove("data/prll/11/12/13/14/15/16/17/18/19/20", p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_dir_remove("data/prll/11/12/13/14/15/16/17/18/19", p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_dir_remove("data/prll/11/12/13/14/15/16/17/18", p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_dir_remove("data/prll/11/12/13/14/15/16/17", p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_dir_remove("data/prll/11/12/13/14/15/16", p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_dir_remove("data/prll/11/12/13/14/15", p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_dir_remove("data/prll/11/12/13/14", p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_dir_remove("data/prll/11/12/13", p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_dir_remove("data/prll/11/12", p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_dir_remove("data/prll/11", p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_dir_remove("data/prll", p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_dir_remove("data/fortytwo", p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+}
+
+static void test_remove_notthere(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+
+    rv = apr_dir_remove("data/notthere", p);
+    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOENT(rv));
+}
+
+static void test_mkdir_twice(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+
+    rv = apr_dir_make("data/testdir", APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_UEXECUTE,
+                      p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_dir_make("data/testdir", APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_UEXECUTE,
+                      p);
+    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_EEXIST(rv));
+
+    rv = apr_dir_remove("data/testdir", p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+}
+
+static void test_opendir(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_dir_t *dir;
+
+    rv = apr_dir_open(&dir, "data", p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    apr_dir_close(dir);
+}
+
+static void test_opendir_notthere(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_dir_t *dir;
+
+    rv = apr_dir_open(&dir, "notthere", p);
+    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOENT(rv));
+}
+
+static void test_closedir(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_dir_t *dir;
+
+    rv = apr_dir_open(&dir, "data", p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    rv = apr_dir_close(dir);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+}
+
+static void test_rewind(abts_case *tc, void *data)
+{
+    apr_dir_t *dir;
+    apr_finfo_t first, second;
+
+    APR_ASSERT_SUCCESS(tc, "apr_dir_open failed", apr_dir_open(&dir, "data", p));
+
+    APR_ASSERT_SUCCESS(tc, "apr_dir_read failed",
+                       apr_dir_read(&first, APR_FINFO_DIRENT, dir));
+
+    APR_ASSERT_SUCCESS(tc, "apr_dir_rewind failed", apr_dir_rewind(dir));
+
+    APR_ASSERT_SUCCESS(tc, "second apr_dir_read failed",
+                       apr_dir_read(&second, APR_FINFO_DIRENT, dir));
+
+    APR_ASSERT_SUCCESS(tc, "apr_dir_close failed", apr_dir_close(dir));
+
+    ABTS_STR_EQUAL(tc, first.name, second.name);
+}
+
+/* Test for a (fixed) bug in apr_dir_read().  This bug only happened
+   in threadless cases. */
+static void test_uncleared_errno(abts_case *tc, void *data)
+{
+    apr_file_t *thefile = NULL;
+    apr_finfo_t finfo;
+    apr_int32_t finfo_flags = APR_FINFO_TYPE | APR_FINFO_NAME;
+    apr_dir_t *this_dir;
+    apr_status_t rv; 
+
+    rv = apr_dir_make("dir1", APR_FPROT_OS_DEFAULT, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    rv = apr_dir_make("dir2", APR_FPROT_OS_DEFAULT, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    rv = apr_file_open(&thefile, "dir1/file1",
+                       APR_FOPEN_READ | APR_FOPEN_WRITE | APR_FOPEN_CREATE,
+                       APR_FPROT_OS_DEFAULT, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    rv = apr_file_close(thefile);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    /* Try to remove dir1.  This should fail because it's not empty.
+       However, on a platform with threads disabled (such as FreeBSD),
+       `errno' will be set as a result. */
+    rv = apr_dir_remove("dir1", p);
+    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOTEMPTY(rv));
+    
+    /* Read `.' and `..' out of dir2. */
+    rv = apr_dir_open(&this_dir, "dir2", p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    rv = apr_dir_read(&finfo, finfo_flags, this_dir);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    rv = apr_dir_read(&finfo, finfo_flags, this_dir);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    /* Now, when we attempt to do a third read of empty dir2, and the
+       underlying system readdir() returns NULL, the old value of
+       errno shouldn't cause a false alarm.  We should get an ENOENT
+       back from apr_dir_read, and *not* the old errno. */
+    rv = apr_dir_read(&finfo, finfo_flags, this_dir);
+    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOENT(rv));
+
+    rv = apr_dir_close(this_dir);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+		 
+    /* Cleanup */
+    rv = apr_file_remove("dir1/file1", p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    rv = apr_dir_remove("dir1", p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    rv = apr_dir_remove("dir2", p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+}
+
+static void test_rmkdir_nocwd(abts_case *tc, void *data)
+{
+    char *cwd, *path;
+
+    APR_ASSERT_SUCCESS(tc, "make temp dir",
+                       apr_dir_make("dir3", APR_FPROT_OS_DEFAULT, p));
+
+    APR_ASSERT_SUCCESS(tc, "obtain cwd", apr_filepath_get(&cwd, 0, p));
+
+    APR_ASSERT_SUCCESS(tc, "determine path to temp dir",
+                       apr_filepath_merge(&path, cwd, "dir3", 0, p));
+
+    APR_ASSERT_SUCCESS(tc, "change to temp dir", apr_filepath_set(path, p));
+
+    APR_ASSERT_SUCCESS(tc, "restore cwd", apr_filepath_set(cwd, p));
+
+    APR_ASSERT_SUCCESS(tc, "remove cwd", apr_dir_remove(path, p));
+}
+
+
+abts_suite *testdir(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite)
+
+    abts_run_test(suite, test_mkdir, NULL);
+    abts_run_test(suite, test_mkdir_recurs, NULL);
+    abts_run_test(suite, test_mkdir_recurs_parallel, NULL);
+    abts_run_test(suite, test_remove, NULL);
+    abts_run_test(suite, test_removeall_fail, NULL);
+    abts_run_test(suite, test_removeall, NULL);
+    abts_run_test(suite, test_remove_notthere, NULL);
+    abts_run_test(suite, test_mkdir_twice, NULL);
+    abts_run_test(suite, test_rmkdir_nocwd, NULL);
+
+    abts_run_test(suite, test_rewind, NULL);
+
+    abts_run_test(suite, test_opendir, NULL);
+    abts_run_test(suite, test_opendir_notthere, NULL);
+    abts_run_test(suite, test_closedir, NULL);
+    abts_run_test(suite, test_uncleared_errno, NULL);
+
+    return suite;
+}
+
diff --git a/test/testdll.dsp b/test/testdll.dsp
new file mode 100644
index 00000000000..e19285d457a
--- /dev/null
+++ b/test/testdll.dsp
@@ -0,0 +1,462 @@
+# Microsoft Developer Studio Project File - Name="testdll" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) External Target" 0x0106
+
+CFG=testdll - 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 "testdll.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 "testdll.mak" CFG="testdll - Win32 Release"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "testdll - Win32 Release" (based on "Win32 (x86) External Target")
+!MESSAGE "testdll - Win32 Debug" (based on "Win32 (x86) External Target")
+!MESSAGE "testdll - Win32 Release9x" (based on "Win32 (x86) External Target")
+!MESSAGE "testdll - Win32 Debug9x" (based on "Win32 (x86) External Target")
+!MESSAGE "testdll - x64 Release" (based on "Win32 (x86) External Target")
+!MESSAGE "testdll - x64 Debug" (based on "Win32 (x86) External Target")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+
+!IF  "$(CFG)" == "testdll - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir ""
+# PROP BASE Intermediate_Dir ""
+# PROP BASE Cmd_Line "NMAKE /f Makefile.win INTDIR=Release OUTDIR=Release MODEL=dynamic all check"
+# PROP BASE Rebuild_Opt "/a"
+# PROP BASE Target_File "Release\testall.exe"
+# PROP BASE Bsc_Name ""
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ""
+# PROP Intermediate_Dir ""
+# PROP Cmd_Line "NMAKE /f Makefile.win INTDIR=Release OUTDIR=Release MODEL=dynamic all check"
+# PROP Rebuild_Opt "/a"
+# PROP Target_File "Release\testall.exe"
+# PROP Bsc_Name ""
+# PROP Target_Dir ""
+
+!ELSEIF  "$(CFG)" == "testdll - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir ""
+# PROP BASE Intermediate_Dir ""
+# PROP BASE Cmd_Line "NMAKE /f Makefile.win INTDIR=Debug OUTDIR=Debug MODEL=dynamic _DEBUG=1 all check"
+# PROP BASE Rebuild_Opt "/a"
+# PROP BASE Target_File "Debug\testall.exe"
+# PROP BASE Bsc_Name ""
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir ""
+# PROP Cmd_Line "NMAKE /f Makefile.win INTDIR=Debug OUTDIR=Debug MODEL=dynamic _DEBUG=1 all check"
+# PROP Rebuild_Opt "/a"
+# PROP Target_File "Debug\testall.exe"
+# PROP Bsc_Name ""
+# PROP Target_Dir ""
+
+!ELSEIF  "$(CFG)" == "testdll - Win32 Release9x"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir ""
+# PROP BASE Intermediate_Dir ""
+# PROP BASE Cmd_Line "NMAKE /f Makefile.win INTDIR=9x\Release OUTDIR=9x\Release MODEL=dynamic all check"
+# PROP BASE Rebuild_Opt "/a"
+# PROP BASE Target_File "9x\Release\testall.exe"
+# PROP BASE Bsc_Name ""
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ""
+# PROP Intermediate_Dir ""
+# PROP Cmd_Line "NMAKE /f Makefile.win INTDIR=9x\Release OUTDIR=9x\Release MODEL=dynamic all check"
+# PROP Rebuild_Opt "/a"
+# PROP Target_File "9x\Release\testall.exe"
+# PROP Bsc_Name ""
+# PROP Target_Dir ""
+
+!ELSEIF  "$(CFG)" == "testdll - Win32 Debug9x"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir ""
+# PROP BASE Intermediate_Dir ""
+# PROP BASE Cmd_Line "NMAKE /f Makefile.win INTDIR=9x\Debug OUTDIR=9x\Debug MODEL=dynamic _DEBUG=1 all check"
+# PROP BASE Rebuild_Opt "/a"
+# PROP BASE Target_File "9x\Debug\testall.exe"
+# PROP BASE Bsc_Name ""
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir ""
+# PROP Cmd_Line "NMAKE /f Makefile.win INTDIR=9x\Debug OUTDIR=9x\Debug MODEL=dynamic _DEBUG=1 all check"
+# PROP Rebuild_Opt "/a"
+# PROP Target_File "9x\Debug\testall.exe"
+# PROP Bsc_Name ""
+# PROP Target_Dir ""
+
+!ELSEIF  "$(CFG)" == "testdll - x64 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir ""
+# PROP BASE Intermediate_Dir ""
+# PROP BASE Cmd_Line "NMAKE /f Makefile.win INTDIR=x64\Release OUTDIR=x64\Release MODEL=dynamic all check"
+# PROP BASE Rebuild_Opt "/a"
+# PROP BASE Target_File "x64\Release\testall.exe"
+# PROP BASE Bsc_Name ""
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ""
+# PROP Intermediate_Dir ""
+# PROP Cmd_Line "NMAKE /f Makefile.win INTDIR=x64\Release OUTDIR=x64\Release MODEL=dynamic all check"
+# PROP Rebuild_Opt "/a"
+# PROP Target_File "x64\Release\testall.exe"
+# PROP Bsc_Name ""
+# PROP Target_Dir ""
+
+!ELSEIF  "$(CFG)" == "testdll - x64 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir ""
+# PROP BASE Intermediate_Dir ""
+# PROP BASE Cmd_Line "NMAKE /f Makefile.win INTDIR=x64\Debug OUTDIR=x64\Debug MODEL=dynamic _DEBUG=1 all check"
+# PROP BASE Rebuild_Opt "/a"
+# PROP BASE Target_File "x64\Debug\testall.exe"
+# PROP BASE Bsc_Name ""
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir ""
+# PROP Cmd_Line "NMAKE /f Makefile.win INTDIR=x64\Debug OUTDIR=x64\Debug MODEL=dynamic _DEBUG=1 all check"
+# PROP Rebuild_Opt "/a"
+# PROP Target_File "x64\Debug\testall.exe"
+# PROP Bsc_Name ""
+# PROP Target_Dir ""
+
+!ENDIF 
+
+# Begin Target
+
+# Name "testdll - Win32 Release"
+# Name "testdll - Win32 Debug"
+# Name "testdll - Win32 Release9x"
+# Name "testdll - Win32 Debug9x"
+# Name "testdll - x64 Release"
+# Name "testdll - x64 Debug"
+# Begin Group "testall Source Files"
+
+# PROP Default_Filter ".c"
+# Begin Source File
+
+SOURCE=.\abts.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\abts.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\abts_tests.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\testapp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testargs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testatomic.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testcond.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testdir.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testdso.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testdup.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testenv.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testfile.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testfilecopy.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testfileinfo.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testflock.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testflock.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\testfmt.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testfnmatch.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testglobalmutex.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testglobalmutex.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\testhash.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testipsub.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testlfs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testlfsabi.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testlfsabi.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\testlfsabi_include.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testlfsabi32.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testlfsabi64.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testlock.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testmmap.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testnames.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testoc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testpath.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testpipe.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testpoll.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testpools.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testproc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testrand.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testshm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testshm.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\testsleep.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testsock.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testsock.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\testsockets.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testsockopt.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\teststr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\teststrnatcmp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testtable.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testtemp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testthread.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testtime.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testud.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testuser.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testutil.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testutil.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\testvsn.c
+# End Source File
+# End Group
+# Begin Group "Other Source Files"
+
+# PROP Default_Filter ".c"
+# Begin Source File
+
+SOURCE=.\globalmutexchild.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mod_test.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\nw_misc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\occhild.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\proc_child.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\readchild.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\sendfile.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\sockchild.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testlockperf.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testmutexscope.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testprocmutex.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testshmconsumer.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testshmproducer.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\tryread.c
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\Makefile.win
+# End Source File
+# End Target
+# End Project
diff --git a/test/testdso.c b/test/testdso.c
index ecc6eeaa119..0d9f27bb2ee 100644
--- a/test/testdso.c
+++ b/test/testdso.c
@@ -1,100 +1,263 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "apr.h"
+#include "testutil.h"
 #include "apr_general.h"
 #include "apr_pools.h"
 #include "apr_errno.h"
 #include "apr_dso.h"
-#include <string.h>
-#include <stdlib.h>
+#include "apr_strings.h"
+#include "apr_file_info.h"
+#if APR_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#if APR_HAS_DSO
 
-#define LIB_NAME "mod_test.so"
+#ifdef NETWARE
+# define MOD_NAME "mod_test.nlm"
+#elif defined(BEOS) || defined(__MVS__)
+# define MOD_NAME "mod_test.so"
+#elif defined(WIN32)
+# define MOD_NAME TESTBINPATH "mod_test.dll"
+#elif defined(DARWIN)
+# define MOD_NAME ".libs/mod_test.so" 
+# define LIB_NAME ".libs/libmod_test.dylib" 
+#elif (defined(__hpux__) || defined(__hpux)) && !defined(__ia64)
+# define MOD_NAME ".libs/mod_test.sl"
+# define LIB_NAME ".libs/libmod_test.sl"
+#elif defined(_AIX) || defined(__bsdi__)
+# define MOD_NAME ".libs/libmod_test.so"
+# define LIB_NAME ".libs/libmod_test.so"
+#else /* Every other Unix */
+# define MOD_NAME ".libs/mod_test.so"
+# define LIB_NAME ".libs/libmod_test.so"
+#endif
 
-int main (int argc, char ** argv)
+static char *modname;
+
+static void test_load_module(abts_case *tc, void *data)
 {
-    ap_dso_handle_t *h = NULL;
-    ap_dso_handle_sym_t func1 = NULL;
-    ap_dso_handle_sym_t func2 = NULL;
-    ap_pool_t *cont;
-    void (*function)(void);
-    void (*function1)(int);
-    int *retval;
-    char filename[256];   
-
-    getcwd(filename, 256);
-    strcat(filename, "/");
-    strcat(filename, LIB_NAME);
-
-    ap_initialize();
-    atexit(ap_terminate);
-        
-    if (ap_create_pool(&cont, NULL) != APR_SUCCESS) {
-        fprintf(stderr, "Couldn't allocate context.");
-        exit(-1);
-    }
+    apr_dso_handle_t *h = NULL;
+    apr_status_t status;
+    char errstr[256];
 
-    fprintf(stdout,"Initializing DSO's.........................");
-    if (ap_dso_init() != APR_SUCCESS) {
-        fprintf(stderr, "Couldn't initialize DSO's !");
-        exit (-1);
-    }
-    fprintf(stdout,"OK\n");
-    fprintf(stdout,"Trying to load DSO now.....................");
-    fflush(stdout);
-    if (ap_dso_load(&h, filename, cont) != APR_SUCCESS){
-        fprintf(stderr, "Failed to load %s!\n", filename);
-        exit (-1);
+    status = apr_dso_load(&h, modname, p);
+    ABTS_ASSERT(tc, apr_dso_error(h, errstr, 256), APR_SUCCESS == status);
+    ABTS_PTR_NOTNULL(tc, h);
+
+    apr_dso_unload(h);
+}
+
+static void test_dso_sym(abts_case *tc, void *data)
+{
+    apr_dso_handle_t *h = NULL;
+    apr_dso_handle_sym_t func1 = NULL;
+    apr_status_t status;
+    void (*function)(char str[256]);
+    char teststr[256];
+    char errstr[256];
+
+    status = apr_dso_load(&h, modname, p);
+    ABTS_ASSERT(tc, apr_dso_error(h, errstr, 256), APR_SUCCESS == status);
+    ABTS_PTR_NOTNULL(tc, h);
+
+    status = apr_dso_sym(&func1, h, "print_hello");
+    ABTS_ASSERT(tc, apr_dso_error(h, errstr, 256), APR_SUCCESS == status);
+    ABTS_PTR_NOTNULL(tc, func1);
+
+    if (!tc->failed) {
+        function = (void (*)(char *))func1;
+        (*function)(teststr);
+        ABTS_STR_EQUAL(tc, "Hello - I'm a DSO!\n", teststr);
     }
-    fprintf(stdout,"OK\n");
-
-    fprintf(stdout,"Trying to get the DSO's attention..........");
-    fflush(stdout);
-    if (ap_dso_sym(&func1, h, "print_hello") != APR_SUCCESS) { 
-        fprintf(stderr, "Failed!\n");
-        exit (-1);
-    }        
-    fprintf(stdout,"OK\n");
-    
-    function = (void *)func1;
-    (*function)();
-
-    fprintf(stdout,"Saying farewell 5 times....................");
-    fflush(stdout);
-    if (ap_dso_sym(&func2, h, "print_goodbye") != APR_SUCCESS) {
-        fprintf(stderr, "Failed!\n");
-        exit (-1);
-    }        
-    fprintf(stdout,"OK\n");
-
-    function1 = (void *)(int)func2;
-    (*function1)(5);
-
-    fprintf(stdout,"Checking how many times I said goodbye..");
-    fflush(stdout);
-    if (ap_dso_sym(&func1, h, "goodbyes") != APR_SUCCESS) {
-        fprintf(stderr, "Failed!\n");
-        exit (-1);
+
+    apr_dso_unload(h);
+}
+
+static void test_dso_sym_return_value(abts_case *tc, void *data)
+{
+    apr_dso_handle_t *h = NULL;
+    apr_dso_handle_sym_t func1 = NULL;
+    apr_status_t status;
+    int (*function)(int);
+    char errstr[256];
+
+    status = apr_dso_load(&h, modname, p);
+    ABTS_ASSERT(tc, apr_dso_error(h, errstr, 256), APR_SUCCESS == status);
+    ABTS_PTR_NOTNULL(tc, h);
+
+    status = apr_dso_sym(&func1, h, "count_reps");
+    ABTS_ASSERT(tc, apr_dso_error(h, errstr, 256), APR_SUCCESS == status);
+    ABTS_PTR_NOTNULL(tc, func1);
+
+    if (!tc->failed) {
+        function = (int (*)(int))func1;
+        status = (*function)(5);
+        ABTS_INT_EQUAL(tc, 5, status);
     }
-    retval = (int *)func1;
-    fprintf(stdout,"%d..", (*retval));
-    fflush(stdout);
-    if ((*retval) == 5){
-        fprintf(stderr,"OK\n");
-    } else {
-        fprintf(stderr,"Failed!\n");
+
+    apr_dso_unload(h);
+}
+
+static void test_unload_module(abts_case *tc, void *data)
+{
+    apr_dso_handle_t *h = NULL;
+    apr_status_t status;
+    char errstr[256];
+    apr_dso_handle_sym_t func1 = NULL;
+
+    status = apr_dso_load(&h, modname, p);
+    ABTS_ASSERT(tc, apr_dso_error(h, errstr, 256), APR_SUCCESS == status);
+    ABTS_PTR_NOTNULL(tc, h);
+
+    status = apr_dso_unload(h);
+    ABTS_ASSERT(tc, apr_dso_error(h, errstr, 256), APR_SUCCESS == status);
+
+    status = apr_dso_sym(&func1, h, "print_hello");
+    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ESYMNOTFOUND(status));
+}
+
+
+#ifdef LIB_NAME
+static char *libname;
+
+static void test_load_library(abts_case *tc, void *data)
+{
+    apr_dso_handle_t *h = NULL;
+    apr_status_t status;
+    char errstr[256];
+
+    status = apr_dso_load(&h, libname, p);
+    ABTS_ASSERT(tc, apr_dso_error(h, errstr, 256), APR_SUCCESS == status);
+    ABTS_PTR_NOTNULL(tc, h);
+
+    apr_dso_unload(h);
+}
+
+static void test_dso_sym_library(abts_case *tc, void *data)
+{
+    apr_dso_handle_t *h = NULL;
+    apr_dso_handle_sym_t func1 = NULL;
+    apr_status_t status;
+    void (*function)(char str[256]);
+    char teststr[256];
+    char errstr[256];
+
+    status = apr_dso_load(&h, libname, p);
+    ABTS_ASSERT(tc, apr_dso_error(h, errstr, 256), APR_SUCCESS == status);
+    ABTS_PTR_NOTNULL(tc, h);
+
+    status = apr_dso_sym(&func1, h, "print_hello");
+    ABTS_ASSERT(tc, apr_dso_error(h, errstr, 256), APR_SUCCESS == status);
+    ABTS_PTR_NOTNULL(tc, func1);
+
+    if (!tc->failed) {
+        function = (void (*)(char *))func1;
+        (*function)(teststr);
+        ABTS_STR_EQUAL(tc, "Hello - I'm a DSO!\n", teststr);
     }
-       
-    fprintf(stdout,"Trying to unload DSO now...................");
-    if (ap_dso_unload(h) != APR_SUCCESS) {
-        fprintf(stderr, "Failed!\n");
-        exit (-1);
+
+    apr_dso_unload(h);
+}
+
+static void test_dso_sym_return_value_library(abts_case *tc, void *data)
+{
+    apr_dso_handle_t *h = NULL;
+    apr_dso_handle_sym_t func1 = NULL;
+    apr_status_t status;
+    int (*function)(int);
+    char errstr[256];
+
+    status = apr_dso_load(&h, libname, p);
+    ABTS_ASSERT(tc, apr_dso_error(h, errstr, 256), APR_SUCCESS == status);
+    ABTS_PTR_NOTNULL(tc, h);
+
+    status = apr_dso_sym(&func1, h, "count_reps");
+    ABTS_ASSERT(tc, apr_dso_error(h, errstr, 256), APR_SUCCESS == status);
+    ABTS_PTR_NOTNULL(tc, func1);
+
+    if (!tc->failed) {
+        function = (int (*)(int))func1;
+        status = (*function)(5);
+        ABTS_INT_EQUAL(tc, 5, status);
     }
-    fprintf(stdout,"OK\n");
-
-    fprintf(stdout,"Checking it's been unloaded................");
-    fflush(stdout);
-    if (ap_dso_sym(&func1, h, "print_hello") == APR_SUCCESS) {
-        fprintf(stderr, "Failed!\n");
-        exit (-1);
-    }        
-    fprintf(stdout,"OK\n");
+
+    apr_dso_unload(h);
+}
+
+static void test_unload_library(abts_case *tc, void *data)
+{
+    apr_dso_handle_t *h = NULL;
+    apr_status_t status;
+    char errstr[256];
+    apr_dso_handle_sym_t func1 = NULL;
+
+    status = apr_dso_load(&h, libname, p);
+    ABTS_ASSERT(tc, apr_dso_error(h, errstr, 256), APR_SUCCESS == status);
+    ABTS_PTR_NOTNULL(tc, h);
+
+    status = apr_dso_unload(h);
+    ABTS_ASSERT(tc, apr_dso_error(h, errstr, 256), APR_SUCCESS == status);
+
+    status = apr_dso_sym(&func1, h, "print_hello");
+    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ESYMNOTFOUND(status));
+}
+
+#endif /* def(LIB_NAME) */
+
+static void test_load_notthere(abts_case *tc, void *data)
+{
+    apr_dso_handle_t *h = NULL;
+    apr_status_t status;
+
+    status = apr_dso_load(&h, "No_File.so", p);
+
+    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_EDSOOPEN(status));
+    ABTS_PTR_NOTNULL(tc, h);
+}    
+
+#endif /* APR_HAS_DSO */
+
+abts_suite *testdso(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite)
+
+#if APR_HAS_DSO
+    apr_filepath_merge(&modname, NULL, MOD_NAME, 0, p);
+    
+    abts_run_test(suite, test_load_module, NULL);
+    abts_run_test(suite, test_dso_sym, NULL);
+    abts_run_test(suite, test_dso_sym_return_value, NULL);
+    abts_run_test(suite, test_unload_module, NULL);
+
+#ifdef LIB_NAME
+    apr_filepath_merge(&libname, NULL, LIB_NAME, 0, p);
     
-    return 0;
+    abts_run_test(suite, test_load_library, NULL);
+    abts_run_test(suite, test_dso_sym_library, NULL);
+    abts_run_test(suite, test_dso_sym_return_value_library, NULL);
+    abts_run_test(suite, test_unload_library, NULL);
+#endif
+
+    abts_run_test(suite, test_load_notthere, NULL);
+#endif /* APR_HAS_DSO */
+
+    return suite;
 }
+
diff --git a/test/testdup.c b/test/testdup.c
new file mode 100644
index 00000000000..2a261f2d798
--- /dev/null
+++ b/test/testdup.c
@@ -0,0 +1,198 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "apr_general.h"
+#include "apr_pools.h"
+#include "apr_errno.h"
+#include "apr_file_io.h"
+#include "testutil.h"
+
+#define TEST "Testing\n"
+#define TEST2 "Testing again\n"
+#define FILEPATH "data/"
+
+static void test_file_dup(abts_case *tc, void *data)
+{
+    apr_file_t *file1 = NULL;
+    apr_file_t *file3 = NULL;
+    apr_status_t rv;
+    apr_finfo_t finfo;
+
+    /* First, create a new file, empty... */
+    rv = apr_file_open(&file1, FILEPATH "testdup.file", 
+                       APR_FOPEN_READ | APR_FOPEN_WRITE | APR_FOPEN_CREATE |
+                       APR_FOPEN_DELONCLOSE, APR_FPROT_OS_DEFAULT, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_PTR_NOTNULL(tc, file1);
+
+    rv = apr_file_dup(&file3, file1, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_PTR_NOTNULL(tc, file3);
+
+    rv = apr_file_close(file1);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    /* cleanup after ourselves */
+    rv = apr_file_close(file3);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    rv = apr_stat(&finfo, FILEPATH "testdup.file", APR_FINFO_NORM, p);
+    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOENT(rv));
+}  
+
+static void test_file_readwrite(abts_case *tc, void *data)
+{
+    apr_file_t *file1 = NULL;
+    apr_file_t *file3 = NULL;
+    apr_status_t rv;
+    apr_finfo_t finfo;
+    apr_size_t txtlen = sizeof(TEST);
+    char buff[50];
+    apr_off_t fpos;
+
+    /* First, create a new file, empty... */
+    rv = apr_file_open(&file1, FILEPATH "testdup.readwrite.file", 
+                       APR_FOPEN_READ | APR_FOPEN_WRITE | APR_FOPEN_CREATE |
+                       APR_FOPEN_DELONCLOSE, APR_FPROT_OS_DEFAULT, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_PTR_NOTNULL(tc, file1);
+
+    rv = apr_file_dup(&file3, file1, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_PTR_NOTNULL(tc, file3);
+
+    rv = apr_file_write(file3, TEST, &txtlen);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_SIZE_EQUAL(tc, sizeof(TEST), txtlen);
+
+    fpos = 0;
+    rv = apr_file_seek(file1, APR_SET, &fpos);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_ASSERT(tc, "File position mismatch, expected 0", fpos == 0);
+
+    txtlen = 50;
+    rv = apr_file_read(file1, buff, &txtlen);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_STR_EQUAL(tc, TEST, buff);
+
+    /* cleanup after ourselves */
+    rv = apr_file_close(file1);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_file_close(file3);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    rv = apr_stat(&finfo, FILEPATH "testdup.readwrite.file", APR_FINFO_NORM, p);
+    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOENT(rv));
+}  
+
+static void test_dup2(abts_case *tc, void *data)
+{
+    apr_file_t *testfile = NULL;
+    apr_file_t *errfile = NULL;
+    apr_file_t *saveerr = NULL;
+    apr_status_t rv;
+
+    rv = apr_file_open(&testfile, FILEPATH "testdup2.file", 
+                       APR_FOPEN_READ | APR_FOPEN_WRITE | APR_FOPEN_CREATE |
+                       APR_FOPEN_DELONCLOSE, APR_FPROT_OS_DEFAULT, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_PTR_NOTNULL(tc, testfile);
+
+    rv = apr_file_open_stderr(&errfile, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    /* Set aside the real errfile */
+    rv = apr_file_dup(&saveerr, errfile, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_PTR_NOTNULL(tc, saveerr);
+
+    rv = apr_file_dup2(errfile, testfile, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_PTR_NOTNULL(tc, errfile);
+
+    apr_file_close(testfile);
+
+    rv = apr_file_dup2(errfile, saveerr, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_PTR_NOTNULL(tc, errfile);
+
+    apr_file_close(saveerr);
+}
+
+static void test_dup2_readwrite(abts_case *tc, void *data)
+{
+    apr_file_t *errfile = NULL;
+    apr_file_t *testfile = NULL;
+    apr_file_t *saveerr = NULL;
+    apr_status_t rv;
+    apr_size_t txtlen = sizeof(TEST);
+    char buff[50];
+    apr_off_t fpos;
+
+    rv = apr_file_open(&testfile, FILEPATH "testdup2.readwrite.file", 
+                       APR_FOPEN_READ | APR_FOPEN_WRITE | APR_FOPEN_CREATE |
+                       APR_FOPEN_DELONCLOSE, APR_FPROT_OS_DEFAULT, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_PTR_NOTNULL(tc, testfile);
+
+    rv = apr_file_open_stderr(&errfile, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    /* Set aside the real errfile */
+    rv = apr_file_dup(&saveerr, errfile, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_PTR_NOTNULL(tc, saveerr);
+
+    rv = apr_file_dup2(errfile, testfile, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_PTR_NOTNULL(tc, errfile);
+
+    txtlen = sizeof(TEST2);
+    rv = apr_file_write(errfile, TEST2, &txtlen);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_SIZE_EQUAL(tc, sizeof(TEST2), txtlen);
+
+    fpos = 0;
+    rv = apr_file_seek(testfile, APR_SET, &fpos);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_ASSERT(tc, "File position mismatch, expected 0", fpos == 0);
+
+    txtlen = 50;
+    rv = apr_file_read(testfile, buff, &txtlen);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_STR_EQUAL(tc, TEST2, buff);
+      
+    apr_file_close(testfile);
+
+    rv = apr_file_dup2(errfile, saveerr, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_PTR_NOTNULL(tc, errfile);
+
+    apr_file_close(saveerr);
+}
+
+abts_suite *testdup(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite)
+
+    abts_run_test(suite, test_file_dup, NULL);
+    abts_run_test(suite, test_file_readwrite, NULL);
+    abts_run_test(suite, test_dup2, NULL);
+    abts_run_test(suite, test_dup2_readwrite, NULL);
+
+    return suite;
+}
+
diff --git a/test/testenv.c b/test/testenv.c
new file mode 100644
index 00000000000..f5a74c38d91
--- /dev/null
+++ b/test/testenv.c
@@ -0,0 +1,144 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_env.h"
+#include "apr_errno.h"
+#include "testutil.h"
+
+#define TEST_ENVVAR_NAME "apr_test_envvar"
+#define TEST_ENVVAR2_NAME "apr_test_envvar2"
+#define TEST_ENVVAR_VALUE "Just a value that we'll check"
+
+static int have_env_set;
+static int have_env_get;
+static int have_env_del;
+
+static void test_setenv(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+
+    rv = apr_env_set(TEST_ENVVAR_NAME, TEST_ENVVAR_VALUE, p);
+    have_env_set = (rv != APR_ENOTIMPL);
+    if (!have_env_set) {
+        ABTS_NOT_IMPL(tc, "apr_env_set");
+    } else {
+        APR_ASSERT_SUCCESS(tc, "set environment variable", rv);
+    }
+}
+
+static void test_getenv(abts_case *tc, void *data)
+{
+    char *value;
+    apr_status_t rv;
+
+    if (!have_env_set) {
+        ABTS_NOT_IMPL(tc, "apr_env_set (skip test for apr_env_get)");
+        return;
+    }
+
+    rv = apr_env_get(&value, TEST_ENVVAR_NAME, p);
+    have_env_get = (rv != APR_ENOTIMPL);
+    if (!have_env_get) {
+        ABTS_NOT_IMPL(tc, "apr_env_get");
+        return;
+    }
+    APR_ASSERT_SUCCESS(tc, "get environment variable", rv);
+    ABTS_STR_EQUAL(tc, TEST_ENVVAR_VALUE, value);
+}
+
+static void test_delenv(abts_case *tc, void *data)
+{
+    char *value;
+    apr_status_t rv;
+
+    if (!have_env_set) {
+        ABTS_NOT_IMPL(tc, "apr_env_set (skip test for apr_env_delete)");
+        return;
+    }
+
+    rv = apr_env_delete(TEST_ENVVAR_NAME, p);
+    have_env_del = (rv != APR_ENOTIMPL);
+    if (!have_env_del) {
+        ABTS_NOT_IMPL(tc, "apr_env_delete");
+        return;
+    }
+    APR_ASSERT_SUCCESS(tc, "delete environment variable", rv);
+
+    if (!have_env_get) {
+        ABTS_NOT_IMPL(tc, "apr_env_get (skip sanity check for apr_env_delete)");
+        return;
+    }
+    rv = apr_env_get(&value, TEST_ENVVAR_NAME, p);
+    ABTS_INT_EQUAL(tc, APR_ENOENT, rv);
+}
+
+/** http://issues.apache.org/bugzilla/show_bug.cgi?id=40764 */
+static void test_emptyenv(abts_case *tc, void *data)
+{
+    char *value;
+    apr_status_t rv;
+
+    if (!(have_env_set && have_env_get)) {
+        ABTS_NOT_IMPL(tc, "apr_env_set (skip test_emptyenv)");
+        return;
+    }
+    /** Set empty string and test that rv != ENOENT) */
+    rv = apr_env_set(TEST_ENVVAR_NAME, "", p);
+    APR_ASSERT_SUCCESS(tc, "set environment variable", rv);
+    rv = apr_env_get(&value, TEST_ENVVAR_NAME, p);
+    APR_ASSERT_SUCCESS(tc, "get environment variable", rv);
+    ABTS_STR_EQUAL(tc, "", value);
+
+    if (!have_env_del) {
+        ABTS_NOT_IMPL(tc, "apr_env (skip recycle test_emptyenv)");
+        return;
+    }
+    /** Delete and retest */
+    rv = apr_env_delete(TEST_ENVVAR_NAME, p);
+    APR_ASSERT_SUCCESS(tc, "delete environment variable", rv);
+    rv = apr_env_get(&value, TEST_ENVVAR_NAME, p);
+    ABTS_INT_EQUAL(tc, APR_ENOENT, rv);
+
+    /** Set second variable + test*/
+    rv = apr_env_set(TEST_ENVVAR2_NAME, TEST_ENVVAR_VALUE, p);
+    APR_ASSERT_SUCCESS(tc, "set second environment variable", rv);
+    rv = apr_env_get(&value, TEST_ENVVAR2_NAME, p);
+    APR_ASSERT_SUCCESS(tc, "get second environment variable", rv);
+    ABTS_STR_EQUAL(tc, TEST_ENVVAR_VALUE, value);
+
+    /** Finally, test ENOENT (first variable) followed by second != ENOENT) */
+    rv = apr_env_get(&value, TEST_ENVVAR_NAME, p);
+    ABTS_INT_EQUAL(tc, APR_ENOENT, rv);
+    rv = apr_env_get(&value, TEST_ENVVAR2_NAME, p);
+    APR_ASSERT_SUCCESS(tc, "verify second environment variable", rv);
+    ABTS_STR_EQUAL(tc, TEST_ENVVAR_VALUE, value);
+
+    /** Cleanup */
+    apr_env_delete(TEST_ENVVAR2_NAME, p);
+}
+
+abts_suite *testenv(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite)
+
+    abts_run_test(suite, test_setenv, NULL);
+    abts_run_test(suite, test_getenv, NULL);
+    abts_run_test(suite, test_delenv, NULL);
+    abts_run_test(suite, test_emptyenv, NULL);
+
+    return suite;
+}
+
diff --git a/test/testescape.c b/test/testescape.c
new file mode 100644
index 00000000000..66452274d5f
--- /dev/null
+++ b/test/testescape.c
@@ -0,0 +1,311 @@
+/* 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 <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "apr_escape.h"
+#include "apr_strings.h"
+
+#include "abts.h"
+#include "testutil.h"
+
+static void test_escape(abts_case *tc, void *data)
+{
+    apr_pool_t *pool;
+    const char *src, *target;
+    const char *dest;
+    const void *vdest;
+    apr_size_t len, vlen;
+
+    apr_pool_create(&pool, NULL);
+
+    src = "Hello World &;`'\"|*?~<>^()[]{}$\\";
+    target = "Hello World \\&\\;\\`\\'\\\"\\|\\*\\?\\~\\<\\>\\^\\(\\)\\[\\]\\{\\}\\$\\\\";
+    dest = apr_pescape_shell(pool, src);
+    ABTS_ASSERT(tc,
+                apr_psprintf(pool, "shell escaped (%s) does not match expected output (%s)",
+                             dest, target),
+                (strcmp(dest, target) == 0));
+    apr_escape_shell(NULL, src, APR_ESCAPE_STRING, &len);
+    ABTS_ASSERT(tc,
+            apr_psprintf(pool, "size mismatch (%" APR_SIZE_T_FMT "!=%" APR_SIZE_T_FMT ")", len, strlen(dest) + 1),
+            (len == strlen(dest) + 1));
+
+#if !(defined(OS2) || defined(WIN32))
+    /* Now try with newline, which is converted to a space on OS/2 and Windows.
+     */
+    src = "Hello World &;`'\"|*?~<>^()[]{}$\\\n";
+    target = "Hello World \\&\\;\\`\\'\\\"\\|\\*\\?\\~\\<\\>\\^\\(\\)\\[\\]\\{\\}\\$\\\\\\\n";
+    dest = apr_pescape_shell(pool, src);
+    ABTS_ASSERT(tc,
+                apr_psprintf(pool, "shell escaped (%s) does not match expected output (%s)",
+                             dest, target),
+                (strcmp(dest, target) == 0));
+    apr_escape_shell(NULL, src, APR_ESCAPE_STRING, &len);
+    ABTS_ASSERT(tc,
+            apr_psprintf(pool, "size mismatch (%" APR_SIZE_T_FMT "!=%" APR_SIZE_T_FMT ")", len, strlen(dest) + 1),
+            (len == strlen(dest) + 1));
+#endif
+
+    src = "Hello";
+    dest = apr_punescape_url(pool, src, NULL, NULL, 0);
+    ABTS_PTR_EQUAL(tc, src, dest);
+
+    src = "Hello";
+    dest = apr_punescape_url(pool, src, NULL, NULL, 1);
+    ABTS_PTR_EQUAL(tc, src, dest);
+
+    src = "Hello%20";
+    dest = apr_punescape_url(pool, src, " ", NULL, 0);
+    ABTS_PTR_EQUAL(tc, NULL, dest);
+
+    src = "Hello%20World";
+    target = "Hello World";
+    dest = apr_punescape_url(pool, src, NULL, NULL, 0);
+    ABTS_STR_EQUAL(tc, target, dest);
+    apr_unescape_url(NULL, src, APR_ESCAPE_STRING, NULL, NULL, 0, &len);
+    ABTS_ASSERT(tc,
+            apr_psprintf(pool, "size mismatch (%" APR_SIZE_T_FMT "!=%" APR_SIZE_T_FMT ")", len, strlen(dest) + 1),
+            (len == strlen(dest) + 1));
+
+    src = "Hello+World";
+    target = "Hello World";
+    dest = apr_punescape_url(pool, src, NULL, NULL, 1);
+    ABTS_STR_EQUAL(tc, target, dest);
+    apr_unescape_url(NULL, src, APR_ESCAPE_STRING, NULL, NULL, 1, &len);
+    ABTS_ASSERT(tc,
+            apr_psprintf(pool, "size mismatch (%" APR_SIZE_T_FMT "!=%" APR_SIZE_T_FMT ")", len, strlen(dest) + 1),
+            (len == strlen(dest) + 1));
+
+    src = "Hello%20World";
+    target = "Hello%20World";
+    dest = apr_punescape_url(pool, src, NULL, " ", 0);
+    ABTS_STR_EQUAL(tc, target, dest);
+    apr_unescape_url(NULL, src, APR_ESCAPE_STRING, NULL, " ", 0, &len);
+    ABTS_ASSERT(tc,
+            apr_psprintf(pool, "size mismatch (%" APR_SIZE_T_FMT "!=%" APR_SIZE_T_FMT ")", len, strlen(dest) + 1),
+            (len == strlen(dest) + 1));
+
+    src = "Hello";
+    dest = apr_pescape_path_segment(pool, src);
+    ABTS_PTR_EQUAL(tc, src, dest);
+
+    src = "$-_.+!*'(),:@&=/~Hello World";
+    target = "$-_.+!*'(),:@&=%2f~Hello%20World";
+    dest = apr_pescape_path_segment(pool, src);
+    ABTS_STR_EQUAL(tc, target, dest);
+    apr_escape_path_segment(NULL, src, APR_ESCAPE_STRING, &len);
+    ABTS_ASSERT(tc,
+            apr_psprintf(pool, "size mismatch (%" APR_SIZE_T_FMT "!=%" APR_SIZE_T_FMT ")", len, strlen(dest) + 1),
+            (len == strlen(dest) + 1));
+
+    src = "Hello";
+    dest = apr_pescape_path(pool, src, 0);
+    ABTS_PTR_EQUAL(tc, src, dest);
+
+    src = "$-_.+!*'(),:@&=/~Hello World";
+    target = "./$-_.+!*'(),:@&=/~Hello%20World";
+    dest = apr_pescape_path(pool, src, 0);
+    ABTS_STR_EQUAL(tc, target, dest);
+    apr_escape_path(NULL, src, APR_ESCAPE_STRING, 0, &len);
+    ABTS_ASSERT(tc,
+            apr_psprintf(pool, "size mismatch (%" APR_SIZE_T_FMT "!=%" APR_SIZE_T_FMT ")", len, strlen(dest) + 1),
+            (len == strlen(dest) + 1));
+
+    src = "Hello";
+    dest = apr_pescape_path(pool, src, 1);
+    ABTS_PTR_EQUAL(tc, src, dest);
+
+    src = "$-_.+!*'(),:@&=/~Hello World";
+    target = "$-_.+!*'(),:@&=/~Hello%20World";
+    dest = apr_pescape_path(pool, src, 1);
+    ABTS_STR_EQUAL(tc, target, dest);
+    apr_escape_path(NULL, src, APR_ESCAPE_STRING, 1, &len);
+    ABTS_ASSERT(tc,
+            apr_psprintf(pool, "size mismatch (%" APR_SIZE_T_FMT "!=%" APR_SIZE_T_FMT ")", len, strlen(dest) + 1),
+            (len == strlen(dest) + 1));
+
+    src = "Hello";
+    dest = apr_pescape_urlencoded(pool, src);
+    ABTS_PTR_EQUAL(tc, src, dest);
+
+    src = "$-_.+!*'(),:@&=/~Hello World";
+    target = "%24-_.%2b%21*%27%28%29%2c%3a%40%26%3d%2f%7eHello+World";
+    dest = apr_pescape_urlencoded(pool, src);
+    ABTS_STR_EQUAL(tc, target, dest);
+    apr_escape_urlencoded(NULL, src, APR_ESCAPE_STRING, &len);
+    ABTS_ASSERT(tc,
+            apr_psprintf(pool, "size mismatch (%" APR_SIZE_T_FMT "!=%" APR_SIZE_T_FMT ")", len, strlen(dest) + 1),
+            (len == strlen(dest) + 1));
+
+    src = "Hello";
+    dest = apr_pescape_entity(pool, src, 0);
+    ABTS_PTR_EQUAL(tc, src, dest);
+
+    src = "\xFF<>&\'\"Hello World";
+    target = "\xFF&lt;&gt;&amp;'&quot;Hello World";
+    dest = apr_pescape_entity(pool, src, 0);
+    ABTS_STR_EQUAL(tc, target, dest);
+    apr_escape_entity(NULL, src, APR_ESCAPE_STRING, 0, &len);
+    ABTS_ASSERT(tc,
+            apr_psprintf(pool, "size mismatch (%" APR_SIZE_T_FMT "!=%" APR_SIZE_T_FMT ")", len, strlen(dest) + 1),
+            (len == strlen(dest) + 1));
+
+#if !APR_CHARSET_EBCDIC
+    src = "Hello";
+    dest = apr_pescape_entity(pool, src, 1);
+    ABTS_PTR_EQUAL(tc, src, dest);
+
+    src = "\xFF<>&\'\"Hello World";
+    target = "&#255&lt;&gt;&amp;'&quot;Hello World";
+    dest = apr_pescape_entity(pool, src, 1);
+    ABTS_STR_EQUAL(tc, target, dest);
+    apr_escape_entity(NULL, src, APR_ESCAPE_STRING, 1, &len);
+    ABTS_ASSERT(tc,
+            apr_psprintf(pool, "size mismatch (%" APR_SIZE_T_FMT "!=%" APR_SIZE_T_FMT ")", len, strlen(dest) + 1),
+            (len == strlen(dest) + 1));
+
+    src = "Hello";
+    dest = apr_punescape_entity(pool, src);
+    ABTS_PTR_EQUAL(tc, src, dest);
+
+    src = "\xFF&lt;&gt;&amp;'&quot;Hello World";
+    target = "\xFF<>&\'\"Hello World";
+    dest = apr_punescape_entity(pool, src);
+    ABTS_STR_EQUAL(tc, target, dest);
+    apr_unescape_entity(NULL, src, APR_ESCAPE_STRING, &len);
+    ABTS_ASSERT(tc,
+            apr_psprintf(pool, "size mismatch (%" APR_SIZE_T_FMT "!=%" APR_SIZE_T_FMT ")", len, strlen(dest) + 1),
+            (len == strlen(dest) + 1));
+
+    src = "&#255;&lt;&gt;&amp;'&quot;Hello World";
+    target = "\xFF<>&\'\"Hello World";
+    dest = apr_punescape_entity(pool, src);
+    ABTS_STR_EQUAL(tc, target, dest);
+    apr_unescape_entity(NULL, src, APR_ESCAPE_STRING, &len);
+    ABTS_ASSERT(tc,
+            apr_psprintf(pool, "size mismatch (%" APR_SIZE_T_FMT "!=%" APR_SIZE_T_FMT ")", len, strlen(dest) + 1),
+            (len == strlen(dest) + 1));
+
+    src = "&#32;&lt;&gt;&amp;'&quot;Hello World";
+    target = " <>&\'\"Hello World";
+    dest = apr_punescape_entity(pool, src);
+    ABTS_STR_EQUAL(tc, target, dest);
+    apr_unescape_entity(NULL, src, APR_ESCAPE_STRING, &len);
+    ABTS_ASSERT(tc,
+            apr_psprintf(pool, "size mismatch (%" APR_SIZE_T_FMT "!=%" APR_SIZE_T_FMT ")", len, strlen(dest) + 1),
+            (len == strlen(dest) + 1));
+#endif
+
+    src = "Hello";
+    dest = apr_pescape_echo(pool, src, 0);
+    ABTS_PTR_EQUAL(tc, src, dest);
+
+    src = "\a\b\f\\n\r\t\v\"Hello World\"";
+    target = "\\a\\b\\f\\\\n\\r\\t\\v\"Hello World\"";
+    dest = apr_pescape_echo(pool, src, 0);
+    ABTS_STR_EQUAL(tc, target, dest);
+    apr_escape_echo(NULL, src, APR_ESCAPE_STRING, 0, &len);
+    ABTS_ASSERT(tc,
+            apr_psprintf(pool, "size mismatch (%" APR_SIZE_T_FMT "!=%" APR_SIZE_T_FMT ")", len, strlen(dest) + 1),
+            (len == strlen(dest) + 1));
+
+    src = "\a\b\f\\n\r\t\v\"Hello World\"";
+    target = "\\a\\b\\f\\\\n\\r\\t\\v\\\"Hello World\\\"";
+    dest = apr_pescape_echo(pool, src, 1);
+    ABTS_STR_EQUAL(tc, target, dest);
+    apr_escape_echo(NULL, src, APR_ESCAPE_STRING, 1, &len);
+    ABTS_ASSERT(tc,
+            apr_psprintf(pool, "size mismatch (%" APR_SIZE_T_FMT "!=%" APR_SIZE_T_FMT ")", len, strlen(dest) + 1),
+            (len == strlen(dest) + 1));
+
+    src = "\xFF\x00\xFF\x00";
+    target = "ff00ff00";
+    dest = apr_pescape_hex(pool, src, 4, 0);
+    ABTS_STR_EQUAL(tc, target, dest);
+    apr_escape_hex(NULL, src, 4, 0, &len);
+    ABTS_ASSERT(tc,
+            apr_psprintf(pool, "size mismatch (%" APR_SIZE_T_FMT "!=%" APR_SIZE_T_FMT ")", len, strlen(dest) + 1),
+            (len == strlen(dest) + 1));
+
+    src = "\xFF\x00\xFF\x00";
+    target = "ff:00:ff:00";
+    dest = apr_pescape_hex(pool, src, 4, 1);
+    ABTS_STR_EQUAL(tc, target, dest);
+    apr_escape_hex(NULL, src, 4, 1, &len);
+    ABTS_ASSERT(tc,
+            apr_psprintf(pool, "size mismatch (%" APR_SIZE_T_FMT "!=%" APR_SIZE_T_FMT ")", len, strlen(dest) + 1),
+            (len == strlen(dest) + 1));
+
+    src = "ff:00:ff:00";
+    target = "\xFF\x00\xFF\x00";
+    vdest = apr_punescape_hex(pool, src, 1, &vlen);
+    ABTS_ASSERT(tc, "apr_punescape_hex target!=dest", memcmp(target, vdest, 4) == 0);
+    ABTS_INT_EQUAL(tc, (int)vlen, 4);
+    apr_unescape_hex(NULL, src, APR_ESCAPE_STRING, 1, &len);
+    ABTS_ASSERT(tc,
+            apr_psprintf(pool, "size mismatch (%" APR_SIZE_T_FMT "!=%" APR_SIZE_T_FMT ")", len, (apr_size_t)4),
+            (len == 4));
+
+    src = "Parens R Us (for all your parenthetical needs) plus asterisk* \"+,;<>\\";
+    target = "Parens R Us (for all your parenthetical needs) plus asterisk* \\22\\2b\\2c\\3b\\3c\\3e\\5c";
+    dest = apr_pescape_ldap(pool, src, APR_ESCAPE_STRING, APR_ESCAPE_LDAP_DN);
+    ABTS_ASSERT(tc,
+                apr_psprintf(pool, "ldap escaped (%s) does not match expected output (%s)",
+                             dest, target),
+                (strcmp(dest, target) == 0));
+    apr_escape_ldap(NULL, src, APR_ESCAPE_STRING, APR_ESCAPE_LDAP_DN, &len);
+    ABTS_ASSERT(tc,
+            apr_psprintf(pool, "size mismatch (%" APR_SIZE_T_FMT "!=%" APR_SIZE_T_FMT ")", len, strlen(dest) + 1),
+            (len == strlen(dest) + 1));
+
+    src = "Parens R Us (for all your parenthetical needs) plus asterisk* \"+,;<>\\";
+    target = "Parens R Us \\28for all your parenthetical needs\\29 plus asterisk\\2a \"+,;<>\\5c";
+    dest = apr_pescape_ldap(pool, src, APR_ESCAPE_STRING, APR_ESCAPE_LDAP_FILTER);
+    ABTS_ASSERT(tc,
+                apr_psprintf(pool, "ldap escaped (%s) does not match expected output (%s)",
+                             dest, target),
+                (strcmp(dest, target) == 0));
+    apr_escape_ldap(NULL, src, APR_ESCAPE_STRING, APR_ESCAPE_LDAP_FILTER, &len);
+    ABTS_ASSERT(tc,
+            apr_psprintf(pool, "size mismatch (%" APR_SIZE_T_FMT "!=%" APR_SIZE_T_FMT ")", len, strlen(dest) + 1),
+            (len == strlen(dest) + 1));
+
+    src = "Parens R Us (for all your parenthetical needs) plus asterisk* \"+,;<>\\";
+    target = "Parens R Us \\28for all your parenthetical needs\\29 plus asterisk\\2a \\22\\2b\\2c\\3b\\3c\\3e\\5c";
+    dest = apr_pescape_ldap(pool, src, APR_ESCAPE_STRING, APR_ESCAPE_LDAP_ALL);
+    ABTS_ASSERT(tc,
+                apr_psprintf(pool, "ldap escaped (%s) does not match expected output (%s)",
+                             dest, target),
+                (strcmp(dest, target) == 0));
+    apr_escape_ldap(NULL, src, APR_ESCAPE_STRING, APR_ESCAPE_LDAP_ALL, &len);
+    ABTS_ASSERT(tc,
+            apr_psprintf(pool, "size mismatch (%" APR_SIZE_T_FMT "!=%" APR_SIZE_T_FMT ")", len, strlen(dest) + 1),
+            (len == strlen(dest) + 1));
+
+    apr_pool_destroy(pool);
+}
+
+abts_suite *testescape(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite);
+
+    abts_run_test(suite, test_escape, NULL);
+
+    return suite;
+}
diff --git a/test/testfile.c b/test/testfile.c
index 1b164515e6f..73b13c4bf14 100644
--- a/test/testfile.c
+++ b/test/testfile.c
@@ -1,356 +1,1905 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 <stdio.h>
-#include <stdlib.h>
 #include "apr_file_io.h"
+#include "apr_file_info.h"
+#include "apr_network_io.h"
 #include "apr_errno.h"
 #include "apr_general.h"
+#include "apr_poll.h"
 #include "apr_lib.h"
-#ifdef BEOS
-#include <unistd.h>
-#endif
-
-int test_filedel(ap_pool_t *);
-int testdirs(ap_pool_t *);
-
-int main()
-{
-    ap_pool_t *context;
-    ap_pool_t *cont2;
-    ap_file_t *thefile = NULL;
-    ap_status_t status = 0;
-    ap_int32_t flag = APR_READ | APR_WRITE | APR_CREATE;
-    ap_ssize_t nbytes = 0;
-    ap_off_t zer = 0;
-    char *buf;
-    char *str;
-    char *filename = "test.fil";
+#include "apr_strings.h"
+#include "apr_thread_proc.h"
+#include "testutil.h"
+
+#define DIRNAME "data"
+#define FILENAME DIRNAME "/file_datafile.txt"
+#define TESTSTR  "This is the file data file."
+
+#define TESTREAD_BLKSIZE 1024
+#define APR_BUFFERSIZE   4096 /* This should match APR's buffer size. */
+
+
+
+static void test_open_noreadwrite(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_file_t *thefile = NULL;
+
+    rv = apr_file_open(&thefile, FILENAME,
+                       APR_FOPEN_CREATE | APR_FOPEN_EXCL,
+                       APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_GREAD, p);
+    ABTS_TRUE(tc, rv != APR_SUCCESS);
+    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_EACCES(rv));
+    ABTS_PTR_EQUAL(tc, NULL, thefile); 
+}
+
+static void test_open_excl(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_file_t *thefile = NULL;
+
+    rv = apr_file_open(&thefile, FILENAME,
+                       APR_FOPEN_CREATE | APR_FOPEN_EXCL | APR_FOPEN_WRITE,
+                       APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_GREAD, p);
+    ABTS_TRUE(tc, rv != APR_SUCCESS);
+    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_EEXIST(rv));
+    ABTS_PTR_EQUAL(tc, NULL, thefile); 
+}
+
+static void test_open_read(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_file_t *filetest = NULL;
+
+    rv = apr_file_open(&filetest, FILENAME, 
+                       APR_FOPEN_READ,
+                       APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_GREAD, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_PTR_NOTNULL(tc, filetest);
+    apr_file_close(filetest);
+}
+
+static void link_existing(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    
+    rv = apr_file_link("data/file_datafile.txt", "data/file_datafile2.txt");
+    apr_file_remove("data/file_datafile2.txt", p);
+    ABTS_ASSERT(tc, "Couldn't create hardlink to file", rv == APR_SUCCESS);
+}
+
+static void link_nonexisting(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    
+    rv = apr_file_link("data/does_not_exist.txt", "data/fake.txt");
+    ABTS_ASSERT(tc, "", rv != APR_SUCCESS);
+}
+
+static void test_read(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_size_t nbytes = 256;
+    char *str = apr_pcalloc(p, nbytes + 1);
+    apr_file_t *filetest = NULL;
+    
+    rv = apr_file_open(&filetest, FILENAME, 
+                       APR_FOPEN_READ,
+                       APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_GREAD, p);
+
+    APR_ASSERT_SUCCESS(tc, "Opening test file " FILENAME, rv);
+    rv = apr_file_read(filetest, str, &nbytes);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_SIZE_EQUAL(tc, strlen(TESTSTR), nbytes);
+    ABTS_STR_EQUAL(tc, TESTSTR, str);
+
+    apr_file_close(filetest);
+}
+
+static void test_readzero(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_size_t nbytes = 0;
+    char *str = NULL;
+    apr_file_t *filetest;
+    
+    rv = apr_file_open(&filetest, FILENAME, APR_FOPEN_READ, APR_FPROT_OS_DEFAULT, p);
+    APR_ASSERT_SUCCESS(tc, "Opening test file " FILENAME, rv);
+
+    rv = apr_file_read(filetest, str, &nbytes);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_SIZE_EQUAL(tc, 0, nbytes);
+
+    apr_file_close(filetest);
+}
+
+static void test_filename(abts_case *tc, void *data)
+{
+    const char *str;
+    apr_status_t rv;
+    apr_file_t *filetest = NULL;
+    
+    rv = apr_file_open(&filetest, FILENAME, 
+                       APR_FOPEN_READ,
+                       APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_GREAD, p);
+    APR_ASSERT_SUCCESS(tc, "Opening test file " FILENAME, rv);
+
+    rv = apr_file_name_get(&str, filetest);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_STR_EQUAL(tc, FILENAME, str);
+
+    apr_file_close(filetest);
+}
+    
+static void test_fileclose(abts_case *tc, void *data)
+{
+    char str;
+    apr_status_t rv;
+    apr_size_t one = 1;
+    apr_file_t *filetest = NULL;
+    
+    rv = apr_file_open(&filetest, FILENAME, 
+                       APR_FOPEN_READ,
+                       APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_GREAD, p);
+    APR_ASSERT_SUCCESS(tc, "Opening test file " FILENAME, rv);
+
+    rv = apr_file_close(filetest);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    /* We just closed the file, so this should fail */
+    rv = apr_file_read(filetest, &str, &one);
+    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_EBADF(rv));
+}
+
+static void test_file_remove(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_file_t *filetest = NULL;
+
+    rv = apr_file_remove(FILENAME, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_file_open(&filetest, FILENAME, APR_FOPEN_READ,
+                       APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_GREAD, p);
+    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOENT(rv));
+}
+
+static void test_open_write(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_file_t *filetest = NULL;
+
+    filetest = NULL;
+    rv = apr_file_open(&filetest, FILENAME, 
+                       APR_FOPEN_WRITE,
+                       APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_GREAD, p);
+    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOENT(rv));
+    ABTS_PTR_EQUAL(tc, NULL, filetest);
+}
+
+static void test_open_writecreate(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_file_t *filetest = NULL;
+
+    filetest = NULL;
+    rv = apr_file_open(&filetest, FILENAME, 
+                       APR_FOPEN_WRITE | APR_FOPEN_CREATE,
+                       APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_GREAD, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    apr_file_close(filetest);
+}
+
+static void test_write(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_size_t bytes = strlen(TESTSTR);
+    apr_file_t *filetest = NULL;
+
+    rv = apr_file_open(&filetest, FILENAME, 
+                       APR_FOPEN_WRITE | APR_FOPEN_CREATE,
+                       APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_GREAD, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_file_write(filetest, TESTSTR, &bytes);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    apr_file_close(filetest);
+}
+
+static void test_open_readwrite(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_file_t *filetest = NULL;
+
+    filetest = NULL;
+    rv = apr_file_open(&filetest, FILENAME, 
+                       APR_FOPEN_READ | APR_FOPEN_WRITE,
+                       APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_GREAD, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_PTR_NOTNULL(tc, filetest);
+
+    apr_file_close(filetest);
+}
+
+static void test_seek(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_off_t offset = 5;
+    apr_size_t nbytes = 256;
+    char *str = apr_pcalloc(p, nbytes + 1);
+    apr_file_t *filetest = NULL;
+
+    rv = apr_file_open(&filetest, FILENAME, 
+                       APR_FOPEN_READ,
+                       APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_GREAD, p);
+    APR_ASSERT_SUCCESS(tc, "Open test file " FILENAME, rv);
+
+    rv = apr_file_read(filetest, str, &nbytes);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_SIZE_EQUAL(tc, strlen(TESTSTR), nbytes);
+    ABTS_STR_EQUAL(tc, TESTSTR, str);
+
+    memset(str, 0, nbytes + 1);
+
+    rv = apr_file_seek(filetest, SEEK_SET, &offset);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    
+    rv = apr_file_read(filetest, str, &nbytes);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_SIZE_EQUAL(tc, strlen(TESTSTR) - 5, nbytes);
+    ABTS_STR_EQUAL(tc, TESTSTR + 5, str);
+
+    apr_file_close(filetest);
+
+    /* Test for regression of sign error bug with SEEK_END and
+       buffered files. */
+    rv = apr_file_open(&filetest, FILENAME,
+                       APR_FOPEN_READ | APR_FOPEN_BUFFERED,
+                       APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_GREAD, p);
+    APR_ASSERT_SUCCESS(tc, "Open test file " FILENAME, rv);
+
+    offset = -5;
+    rv = apr_file_seek(filetest, SEEK_END, &offset);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_SIZE_EQUAL(tc, strlen(TESTSTR) - 5, nbytes);
+
+    memset(str, 0, nbytes + 1);
+    nbytes = 256;
+    rv = apr_file_read(filetest, str, &nbytes);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_SIZE_EQUAL(tc, 5, nbytes);
+    ABTS_STR_EQUAL(tc, TESTSTR + strlen(TESTSTR) - 5, str);
+
+    apr_file_close(filetest);
+}                
+
+static void test_userdata_set(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_file_t *filetest = NULL;
+
+    rv = apr_file_open(&filetest, FILENAME, 
+                       APR_FOPEN_WRITE,
+                       APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_GREAD, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_file_data_set(filetest, "This is a test",
+                           "test", apr_pool_cleanup_null);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    apr_file_close(filetest);
+}
+
+static void test_userdata_get(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    void *udata;
     char *teststr;
+    apr_file_t *filetest = NULL;
 
-    if (ap_initialize() != APR_SUCCESS) {
-        fprintf(stderr, "Couldn't initialize.");
-        exit(-1);
-    }
-    atexit(ap_terminate);
-    if (ap_create_pool(&context, NULL) != APR_SUCCESS) {
-        fprintf(stderr, "Couldn't allocate context.");
-        exit(-1);
-    }
-    if (ap_create_pool(&cont2, context) != APR_SUCCESS) {
-        fprintf(stderr, "Couldn't allocate context.");
-        exit(-1);
-    }
+    rv = apr_file_open(&filetest, FILENAME, 
+                       APR_FOPEN_WRITE,
+                       APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_GREAD, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
 
-    fprintf(stdout, "Testing file functions.\n");
+    rv = apr_file_data_set(filetest, "This is a test",
+                           "test", apr_pool_cleanup_null);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
 
-    fprintf(stdout, "\tOpening file.......");
-    if (ap_open(&thefile, filename, flag, APR_UREAD | APR_UWRITE | APR_GREAD, context) != APR_SUCCESS) {
-        perror("Didn't open file");
-        exit(-1);
-    }
-    else {
-        fprintf(stdout, "OK\n");
-    }
+    rv = apr_file_data_get(&udata, "test", filetest);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    teststr = udata;
+    ABTS_STR_EQUAL(tc, "This is a test", teststr);
+
+    apr_file_close(filetest);
+}
+
+static void test_userdata_getnokey(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    void *teststr;
+    apr_file_t *filetest = NULL;
+
+    rv = apr_file_open(&filetest, FILENAME, 
+                       APR_FOPEN_WRITE,
+                       APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_GREAD, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_file_data_get(&teststr, "nokey", filetest);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_PTR_EQUAL(tc, NULL, teststr);
+    apr_file_close(filetest);
+}
+
+static void test_buffer_set_get(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_size_t bufsize;
+    apr_file_t *filetest = NULL;
+    char   * buffer;
+
+    rv = apr_file_open(&filetest, FILENAME, 
+                       APR_FOPEN_WRITE | APR_FOPEN_BUFFERED,
+                       APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_GREAD, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    bufsize = apr_file_buffer_size_get(filetest);
+    ABTS_SIZE_EQUAL(tc, APR_BUFFERSIZE, bufsize);
+ 
+    buffer = apr_pcalloc(p, 10240);
+    rv = apr_file_buffer_set(filetest, buffer, 10240);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
     
-    fprintf(stdout, "\tChecking file.......");
-    if (thefile == NULL) {
-        fprintf(stderr, "Bad file des\n");
-        exit(-1);
-    }
-    ap_get_filename(&str, thefile);
-    if (strcmp(str, filename) != 0) {
-        fprintf(stderr, "wrong filename\n");
-        exit(-1);
-    }
-    else {
-        fprintf(stdout, "OK\n");
-    }
+    bufsize = apr_file_buffer_size_get(filetest);
+    ABTS_SIZE_EQUAL(tc, 10240, bufsize);
+    
+    rv = apr_file_buffer_set(filetest, buffer, 12);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    
+    bufsize = apr_file_buffer_size_get(filetest);
+    ABTS_SIZE_EQUAL(tc, 12, bufsize);
+    
+    apr_file_close(filetest);
+}
+static void test_getc(abts_case *tc, void *data)
+{
+    apr_file_t *f = NULL;
+    apr_status_t rv;
+    char ch;
+
+    rv = apr_file_open(&f, FILENAME, APR_FOPEN_READ, 0, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    apr_file_getc(&ch, f);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_INT_EQUAL(tc, (int)TESTSTR[0], (int)ch);
+    apr_file_close(f);
+}
+
+static void test_ungetc(abts_case *tc, void *data)
+{
+    apr_file_t *f = NULL;
+    apr_status_t rv;
+    char ch;
+
+    rv = apr_file_open(&f, FILENAME, APR_FOPEN_READ, 0, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    apr_file_getc(&ch, f);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_INT_EQUAL(tc, (int)TESTSTR[0], (int)ch);
+
+    apr_file_ungetc('X', f);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    apr_file_getc(&ch, f);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_INT_EQUAL(tc, 'X', (int)ch);
+
+    apr_file_close(f);
+}
+
+static void test_gets(abts_case *tc, void *data)
+{
+    apr_file_t *f = NULL;
+    apr_status_t rv;
+    char *str = apr_palloc(p, 256);
+
+    rv = apr_file_open(&f, FILENAME, APR_FOPEN_READ, 0, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_file_gets(str, 256, f);
+    /* Only one line in the test file, so APR will encounter EOF on the first
+     * call to gets, but we should get APR_SUCCESS on this call and
+     * APR_EOF on the next.
+     */
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_STR_EQUAL(tc, TESTSTR, str);
+    rv = apr_file_gets(str, 256, f);
+    ABTS_INT_EQUAL(tc, APR_EOF, rv);
+    ABTS_STR_EQUAL(tc, "", str);
+    /* Calling gets after EOF should return EOF. */
+    rv = apr_file_gets(str, 256, f);
+    ABTS_INT_EQUAL(tc, APR_EOF, rv);
+    ABTS_STR_EQUAL(tc, "", str);
+    apr_file_close(f);
+}
+
+static void test_gets_buffered(abts_case *tc, void *data)
+{
+    apr_file_t *f = NULL;
+    apr_status_t rv;
+    char *str = apr_palloc(p, 256);
+
+    /* This will deadlock gets before the r524355 fix. */
+    rv = apr_file_open(&f, FILENAME, APR_FOPEN_READ|APR_FOPEN_BUFFERED|APR_FOPEN_XTHREAD, 0, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_file_gets(str, 256, f);
+    /* Only one line in the test file, so APR will encounter EOF on the first
+     * call to gets, but we should get APR_SUCCESS on this call and
+     * APR_EOF on the next.
+     */
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_STR_EQUAL(tc, TESTSTR, str);
+    rv = apr_file_gets(str, 256, f);
+    ABTS_INT_EQUAL(tc, APR_EOF, rv);
+    ABTS_STR_EQUAL(tc, "", str);
+    /* Calling gets after EOF should return EOF. */
+    rv = apr_file_gets(str, 256, f);
+    ABTS_INT_EQUAL(tc, APR_EOF, rv);
+    ABTS_STR_EQUAL(tc, "", str);
+    apr_file_close(f);
+}
+
+static void test_gets_empty(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_file_t *f;
+    const char *fname = "data/testgets_empty.txt";
+    char buf[256];
+
+    apr_file_remove(fname, p);
+
+    rv = apr_file_open(&f, fname, APR_FOPEN_CREATE | APR_FOPEN_WRITE,
+                       APR_FPROT_OS_DEFAULT, p);
+    APR_ASSERT_SUCCESS(tc, "open test file", rv);
+    apr_file_close(f);
+
+    rv = apr_file_open(&f, fname, APR_FOPEN_READ, APR_FPROT_OS_DEFAULT, p);
+    APR_ASSERT_SUCCESS(tc, "re-open test file", rv);
+
+    rv = apr_file_gets(buf, sizeof(buf), f);
+    ABTS_INT_EQUAL(tc, APR_EOF, rv);
+    ABTS_STR_EQUAL(tc, "", buf);
+    /* Calling gets after EOF should return EOF. */
+    rv = apr_file_gets(buf, sizeof(buf), f);
+    ABTS_INT_EQUAL(tc, APR_EOF, rv);
+    ABTS_STR_EQUAL(tc, "", buf);
+    apr_file_close(f);
+}
+
+static void test_gets_multiline(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_file_t *f;
+    const char *fname = "data/testgets_multiline.txt";
+    char buf[256];
+
+    apr_file_remove(fname, p);
+
+    rv = apr_file_open(&f, fname, APR_FOPEN_CREATE | APR_FOPEN_WRITE,
+                       APR_FPROT_OS_DEFAULT, p);
+    APR_ASSERT_SUCCESS(tc, "open test file", rv);
+    rv = apr_file_puts("a\nb\n", f);
+    APR_ASSERT_SUCCESS(tc, "write test data", rv);
+    apr_file_close(f);
+
+    rv = apr_file_open(&f, fname, APR_FOPEN_READ, APR_FPROT_OS_DEFAULT, p);
+    APR_ASSERT_SUCCESS(tc, "re-open test file", rv);
+
+    memset(buf, 0, sizeof(buf));
+    rv = apr_file_gets(buf, sizeof(buf), f);
+    APR_ASSERT_SUCCESS(tc, "read first line", rv);
+    ABTS_STR_EQUAL(tc, "a\n", buf);
+
+    memset(buf, 0, sizeof(buf));
+    rv = apr_file_gets(buf, sizeof(buf), f);
+    APR_ASSERT_SUCCESS(tc, "read second line", rv);
+    ABTS_STR_EQUAL(tc, "b\n", buf);
+
+    rv = apr_file_gets(buf, sizeof(buf), f);
+    ABTS_INT_EQUAL(tc, APR_EOF, rv);
+    ABTS_STR_EQUAL(tc, "", buf);
+    /* Calling gets after EOF should return EOF. */
+    rv = apr_file_gets(buf, sizeof(buf), f);
+    ABTS_INT_EQUAL(tc, APR_EOF, rv);
+    ABTS_STR_EQUAL(tc, "", buf);
+    apr_file_close(f);
+}
+
+static void test_gets_small_buf(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_file_t *f;
+    const char *fname = "data/testgets_small_buf.txt";
+    char buf[2];
+
+    apr_file_remove(fname, p);
+
+    rv = apr_file_open(&f, fname, APR_FOPEN_CREATE | APR_FOPEN_WRITE,
+                       APR_FPROT_OS_DEFAULT, p);
+    APR_ASSERT_SUCCESS(tc, "open test file", rv);
+    rv = apr_file_puts("ab\n", f);
+    apr_file_close(f);
+
+    rv = apr_file_open(&f, fname, APR_FOPEN_READ, APR_FPROT_OS_DEFAULT, p);
+    APR_ASSERT_SUCCESS(tc, "re-open test file", rv);
+    /* Buffer is too small to hold the full line, test that gets properly
+     * returns the line content character by character.
+     */
+    memset(buf, 0, sizeof(buf));
+    rv = apr_file_gets(buf, sizeof(buf), f);
+    APR_ASSERT_SUCCESS(tc, "read first chunk", rv);
+    ABTS_STR_EQUAL(tc, "a", buf);
+
+    memset(buf, 0, sizeof(buf));
+    rv = apr_file_gets(buf, sizeof(buf), f);
+    APR_ASSERT_SUCCESS(tc, "read second chunk", rv);
+    ABTS_STR_EQUAL(tc, "b", buf);
+
+    memset(buf, 0, sizeof(buf));
+    rv = apr_file_gets(buf, sizeof(buf), f);
+    APR_ASSERT_SUCCESS(tc, "read third chunk", rv);
+    ABTS_STR_EQUAL(tc, "\n", buf);
+
+    rv = apr_file_gets(buf, sizeof(buf), f);
+    ABTS_INT_EQUAL(tc, APR_EOF, rv);
+    ABTS_STR_EQUAL(tc, "", buf);
+    /* Calling gets after EOF should return EOF. */
+    rv = apr_file_gets(buf, sizeof(buf), f);
+    ABTS_INT_EQUAL(tc, APR_EOF, rv);
+    ABTS_STR_EQUAL(tc, "", buf);
+    apr_file_close(f);
+}
+
+static void test_gets_ungetc(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_file_t *f;
+    const char *fname = "data/testgets_ungetc.txt";
+    char buf[256];
+
+    apr_file_remove(fname, p);
+
+    rv = apr_file_open(&f, fname, APR_FOPEN_CREATE | APR_FOPEN_WRITE,
+                       APR_FPROT_OS_DEFAULT, p);
+    APR_ASSERT_SUCCESS(tc, "open test file", rv);
+    rv = apr_file_puts("a\n", f);
+    APR_ASSERT_SUCCESS(tc, "write test data", rv);
+    apr_file_close(f);
+
+    rv = apr_file_open(&f, fname, APR_FOPEN_READ, APR_FPROT_OS_DEFAULT, p);
+    APR_ASSERT_SUCCESS(tc, "re-open test file", rv);
+
+    rv = apr_file_ungetc('b', f);
+    APR_ASSERT_SUCCESS(tc, "call ungetc", rv);
+    memset(buf, 0, sizeof(buf));
+    rv = apr_file_gets(buf, sizeof(buf), f);
+    APR_ASSERT_SUCCESS(tc, "read line", rv);
+    ABTS_STR_EQUAL(tc, "ba\n", buf);
+
+    rv = apr_file_ungetc('\n', f);
+    APR_ASSERT_SUCCESS(tc, "call ungetc with EOL", rv);
+    memset(buf, 0, sizeof(buf));
+    rv = apr_file_gets(buf, sizeof(buf), f);
+    APR_ASSERT_SUCCESS(tc, "read line", rv);
+    ABTS_STR_EQUAL(tc, "\n", buf);
+
+    rv = apr_file_gets(buf, sizeof(buf), f);
+    ABTS_INT_EQUAL(tc, APR_EOF, rv);
+    ABTS_STR_EQUAL(tc, "", buf);
+    /* Calling gets after EOF should return EOF. */
+    rv = apr_file_gets(buf, sizeof(buf), f);
+    ABTS_INT_EQUAL(tc, APR_EOF, rv);
+    ABTS_STR_EQUAL(tc, "", buf);
+    apr_file_close(f);
+}
+
+static void test_gets_buffered_big(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_file_t *f;
+    const char *fname = "data/testgets_buffered_big.txt";
+    char hugestr[APR_BUFFERSIZE + 2];
+    char buf[APR_BUFFERSIZE + 2];
+
+    apr_file_remove(fname, p);
+
+    rv = apr_file_open(&f, fname, APR_FOPEN_CREATE | APR_FOPEN_WRITE,
+                       APR_FPROT_OS_DEFAULT, p);
+    APR_ASSERT_SUCCESS(tc, "open test file", rv);
+    /* Test an edge case with a buffered file and the line that exceeds
+     * the default buffer size by 1 (the line itself fits into the buffer,
+     * but the line + EOL does not).
+     */
+    memset(hugestr, 'a', sizeof(hugestr));
+    hugestr[sizeof(hugestr) - 2] = '\n';
+    hugestr[sizeof(hugestr) - 1] = '\0';
+    rv = apr_file_puts(hugestr, f);
+    APR_ASSERT_SUCCESS(tc, "write first line", rv);
+    rv = apr_file_puts("b\n", f);
+    APR_ASSERT_SUCCESS(tc, "write second line", rv);
+    apr_file_close(f);
 
-    fprintf(stdout, "\tWriting to file.......");
+    rv = apr_file_open(&f, fname, APR_FOPEN_READ | APR_FOPEN_BUFFERED,
+                       APR_FPROT_OS_DEFAULT, p);
+    APR_ASSERT_SUCCESS(tc, "re-open test file", rv);
+
+    memset(buf, 0, sizeof(buf));
+    rv = apr_file_gets(buf, sizeof(buf), f);
+    APR_ASSERT_SUCCESS(tc, "read first line", rv);
+    ABTS_STR_EQUAL(tc, hugestr, buf);
+
+    memset(buf, 0, sizeof(buf));
+    rv = apr_file_gets(buf, sizeof(buf), f);
+    APR_ASSERT_SUCCESS(tc, "read second line", rv);
+    ABTS_STR_EQUAL(tc, "b\n", buf);
+
+    rv = apr_file_gets(buf, sizeof(buf), f);
+    ABTS_INT_EQUAL(tc, APR_EOF, rv);
+    ABTS_STR_EQUAL(tc, "", buf);
+    /* Calling gets after EOF should return EOF. */
+    rv = apr_file_gets(buf, sizeof(buf), f);
+    ABTS_INT_EQUAL(tc, APR_EOF, rv);
+    ABTS_STR_EQUAL(tc, "", buf);
+    apr_file_close(f);
+}
+
+static void test_bigread(abts_case *tc, void *data)
+{
+    apr_file_t *f = NULL;
+    apr_status_t rv;
+    char buf[APR_BUFFERSIZE * 2];
+    apr_size_t nbytes;
+
+    /* Create a test file with known content.
+     */
+    rv = apr_file_open(&f, "data/created_file", 
+                       APR_FOPEN_CREATE | APR_FOPEN_WRITE | APR_FOPEN_TRUNCATE,
+                       APR_FPROT_UREAD | APR_FPROT_UWRITE, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    nbytes = APR_BUFFERSIZE;
+    memset(buf, 0xFE, nbytes);
+
+    rv = apr_file_write(f, buf, &nbytes);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_SIZE_EQUAL(tc, APR_BUFFERSIZE, nbytes);
+
+    rv = apr_file_close(f);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    f = NULL;
+    rv = apr_file_open(&f, "data/created_file", APR_FOPEN_READ, 0, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    nbytes = sizeof buf;
+    rv = apr_file_read(f, buf, &nbytes);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_SIZE_EQUAL(tc, APR_BUFFERSIZE, nbytes);
+
+    rv = apr_file_close(f);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_file_remove("data/created_file", p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+}
+
+/* This is a horrible name for this function.  We are testing APR, not how
+ * Apache uses APR.  And, this function tests _way_ too much stuff.
+ */
+static void test_mod_neg(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_file_t *f;
+    const char *s;
+    int i;
+    apr_size_t nbytes;
+    char buf[8192];
+    apr_off_t cur;
+    const char *fname = "data/modneg.dat";
+
+    rv = apr_file_open(&f, fname, 
+                       APR_FOPEN_CREATE | APR_FOPEN_WRITE,
+                       APR_FPROT_UREAD | APR_FPROT_UWRITE, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    s = "body56789\n";
+    nbytes = strlen(s);
+    rv = apr_file_write(f, s, &nbytes);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_SIZE_EQUAL(tc, strlen(s), nbytes);
     
-    nbytes = (ap_ssize_t)strlen("this is a test");
-    if (ap_write(thefile, "this is a test", &nbytes) != APR_SUCCESS) {
-        perror("something's wrong");
-        exit(-1);
-    }
-    if (nbytes != (ap_ssize_t)strlen("this is a test")) {
-        fprintf(stderr, "didn't write properly.\n");
-        exit(-1);
-    }
-    else {
-        fprintf(stdout, "OK\n");
+    for (i = 0; i < 7980; i++) {
+        s = "0";
+        nbytes = strlen(s);
+        rv = apr_file_write(f, s, &nbytes);
+        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+        ABTS_SIZE_EQUAL(tc, strlen(s), nbytes);
     }
+    
+    s = "end456789\n";
+    nbytes = strlen(s);
+    rv = apr_file_write(f, s, &nbytes);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_SIZE_EQUAL(tc, strlen(s), nbytes);
 
-    fprintf(stdout, "\tMoving to start of file.......");
-    zer = 0;
-    if (ap_seek(thefile, SEEK_SET, &zer) != 0) {
-        perror("couldn't seek to beginning of file.");
-        exit(-1);
-    }
-    else {
-        fprintf(stdout, "OK\n");
+    for (i = 0; i < 10000; i++) {
+        s = "1";
+        nbytes = strlen(s);
+        rv = apr_file_write(f, s, &nbytes);
+        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+        ABTS_SIZE_EQUAL(tc, strlen(s), nbytes);
     }
+    
+    rv = apr_file_close(f);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
 
-    fprintf(stdout, "\tReading from the file.......");
-    nbytes = (ap_ssize_t)strlen("this is a test");
-    buf = (char *)ap_palloc(context, nbytes + 1);
-    if (ap_read(thefile, buf, &nbytes) != APR_SUCCESS) {
-        perror("something's wrong");
-        exit(-1);
-    }
-    if (nbytes != (ap_ssize_t)strlen("this is a test")) {
-        fprintf(stderr, "didn't read properly.\n");
-        exit(-1);
-    }
-    else {
-        fprintf(stdout, "OK\n");
-    }
+    rv = apr_file_open(&f, fname, APR_FOPEN_READ, 0, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
 
-    fprintf(stdout, "\tAdding user data to the file.......");
-    status = ap_set_filedata(thefile, "This is a test", "test", ap_null_cleanup);
-    if (status  != APR_SUCCESS) {
-        fprintf(stderr, "Couldn't add the data\n");
-        exit(-1); 
-    }
-    else {
-        fprintf(stdout, "OK\n");
-    }
+    rv = apr_file_gets(buf, 11, f);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_STR_EQUAL(tc, "body56789\n", buf);
 
-    fprintf(stdout, "\tGetting user data from the file.......");
-    status = ap_get_filedata((void **)&teststr, "test", thefile);
-    if (status  != APR_SUCCESS || strcmp(teststr, "This is a test")) {
-        fprintf(stderr, "Couldn't get the data\n");
-        exit(-1); 
-    }
-    else {
-        fprintf(stdout, "OK\n");
-    }
+    cur = 0;
+    rv = apr_file_seek(f, APR_CUR, &cur);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_ASSERT(tc, "File Pointer Mismatch, expected 10", cur == 10);
 
-    fprintf(stdout, "\tClosing File.......");
-    status = ap_close(thefile);
-    if (status  != APR_SUCCESS) {
-        fprintf(stderr, "Couldn't close the file\n");
-        exit(-1); 
-    }
-    else {
-        fprintf(stdout, "OK\n");
-    }
+    nbytes = sizeof(buf);
+    rv = apr_file_read(f, buf, &nbytes);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_SIZE_EQUAL(tc, nbytes, sizeof(buf));
+
+    cur = -((apr_off_t)nbytes - 7980);
+    rv = apr_file_seek(f, APR_CUR, &cur);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_ASSERT(tc, "File Pointer Mismatch, expected 7990", cur == 7990);
+
+    rv = apr_file_gets(buf, 11, f);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_STR_EQUAL(tc, "end456789\n", buf);
+
+    rv = apr_file_close(f);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_file_remove(fname, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+}
+
+/* Test that the contents of file FNAME are equal to data EXPECT of
+ * length EXPECTLEN. */
+static void file_contents_equal(abts_case *tc,
+                                const char *fname,
+                                const void *expect,
+                                apr_size_t expectlen)
+{
+    void *actual = apr_palloc(p, expectlen);
+    apr_file_t *f;
+
+    APR_ASSERT_SUCCESS(tc, "open file",
+                       apr_file_open(&f, fname, APR_FOPEN_READ|APR_FOPEN_BUFFERED,
+                                     0, p));
+    APR_ASSERT_SUCCESS(tc, "read from file",
+                       apr_file_read_full(f, actual, expectlen, NULL));
     
-    fprintf(stdout, "\tDeleting file.......");
-    status = ap_remove_file(filename, context);
-    if (status  != APR_SUCCESS) {
-        fprintf(stderr, "Couldn't delete the file\n");
-        exit(-1); 
-    }
-    else {
-        fprintf(stdout, "OK\n");
-    }
+    ABTS_ASSERT(tc, "matched expected file contents",
+                memcmp(expect, actual, expectlen) == 0);
+
+    APR_ASSERT_SUCCESS(tc, "close file", apr_file_close(f));
+}
+
+#define LINE1 "this is a line of text\n"
+#define LINE2 "this is a second line of text\n"
+
+static void test_puts(abts_case *tc, void *data)
+{
+    apr_file_t *f;
+    const char *fname = "data/testputs.txt";
+
+    APR_ASSERT_SUCCESS(tc, "open file for writing",
+                       apr_file_open(&f, fname, 
+                                     APR_FOPEN_WRITE|APR_FOPEN_CREATE|APR_FOPEN_TRUNCATE,
+                                     APR_FPROT_OS_DEFAULT, p));
     
-    fprintf(stdout, "\tMaking sure it's gone.......");
-    status = ap_open(&thefile, filename, APR_READ, APR_UREAD | APR_UWRITE | APR_GREAD, context);
-    if (status == APR_SUCCESS) {
-        fprintf(stderr, "I could open the file for some reason?\n");
-        exit(-1);
-    }
-    else {
-        fprintf(stdout, "OK\n");
-    }
+    APR_ASSERT_SUCCESS(tc, "write line to file", 
+                       apr_file_puts(LINE1, f));
+    APR_ASSERT_SUCCESS(tc, "write second line to file", 
+                       apr_file_puts(LINE2, f));
+    
+    APR_ASSERT_SUCCESS(tc, "close for writing",
+                       apr_file_close(f));
 
-    testdirs(context); 
-    test_filedel(context);
+    file_contents_equal(tc, fname, LINE1 LINE2, strlen(LINE1 LINE2));
+}
+
+static void test_writev(abts_case *tc, void *data)
+{
+    apr_file_t *f;
+    apr_size_t nbytes;
+    struct iovec vec[5];
+    const char *fname = "data/testwritev.txt";
+
+    APR_ASSERT_SUCCESS(tc, "open file for writing",
+                       apr_file_open(&f, fname, 
+                                     APR_FOPEN_WRITE|APR_FOPEN_CREATE|APR_FOPEN_TRUNCATE,
+                                     APR_FPROT_OS_DEFAULT, p));
+    
+    vec[0].iov_base = LINE1;
+    vec[0].iov_len = strlen(LINE1);
+
+    APR_ASSERT_SUCCESS(tc, "writev of size 1 to file",
+                       apr_file_writev(f, vec, 1, &nbytes));
+
+    file_contents_equal(tc, fname, LINE1, strlen(LINE1));
+    
+    vec[0].iov_base = LINE1;
+    vec[0].iov_len = strlen(LINE1);
+    vec[1].iov_base = LINE2;
+    vec[1].iov_len = strlen(LINE2);
+    vec[2].iov_base = LINE1;
+    vec[2].iov_len = strlen(LINE1);
+    vec[3].iov_base = LINE1;
+    vec[3].iov_len = strlen(LINE1);
+    vec[4].iov_base = LINE2;
+    vec[4].iov_len = strlen(LINE2);
+
+    APR_ASSERT_SUCCESS(tc, "writev of size 5 to file",
+                       apr_file_writev(f, vec, 5, &nbytes));
+
+    APR_ASSERT_SUCCESS(tc, "close for writing",
+                       apr_file_close(f));
+
+    file_contents_equal(tc, fname, LINE1 LINE1 LINE2 LINE1 LINE1 LINE2, 
+                        strlen(LINE1)*4 + strlen(LINE2)*2);
 
-    return 1;
 }
 
-int test_filedel(ap_pool_t *context)
+static void test_writev_full(abts_case *tc, void *data)
 {
-    ap_file_t *thefile = NULL;
-    ap_int32_t flag = APR_READ | APR_WRITE | APR_CREATE;
-    ap_status_t stat;
-  
-    stat = ap_open(&thefile, "testdel", flag, APR_UREAD | APR_UWRITE | APR_GREAD, context);
-    if (stat != APR_SUCCESS) {
-         return stat;
-    }
+    apr_file_t *f;
+    apr_size_t nbytes;
+    struct iovec vec[5];
+    const char *fname = "data/testwritev_full.txt";
 
-    if ((stat = ap_close(thefile))  != APR_SUCCESS) {
-        return stat;
-    }
+    APR_ASSERT_SUCCESS(tc, "open file for writing",
+                       apr_file_open(&f, fname, 
+                                     APR_FOPEN_WRITE|APR_FOPEN_CREATE|APR_FOPEN_TRUNCATE,
+                                     APR_FPROT_OS_DEFAULT, p));
+    
+    vec[0].iov_base = LINE1;
+    vec[0].iov_len = strlen(LINE1);
+    vec[1].iov_base = LINE2;
+    vec[1].iov_len = strlen(LINE2);
+    vec[2].iov_base = LINE1;
+    vec[2].iov_len = strlen(LINE1);
+    vec[3].iov_base = LINE1;
+    vec[3].iov_len = strlen(LINE1);
+    vec[4].iov_base = LINE2;
+    vec[4].iov_len = strlen(LINE2);
 
-    if ((stat = ap_remove_file("testdel", context))  != APR_SUCCESS) {
-        return stat;
-    }
+    APR_ASSERT_SUCCESS(tc, "writev_full of size 5 to file",
+                       apr_file_writev_full(f, vec, 5, &nbytes));
+
+    ABTS_SIZE_EQUAL(tc, strlen(LINE1)*3 + strlen(LINE2)*2, nbytes);
+
+    APR_ASSERT_SUCCESS(tc, "close for writing",
+                       apr_file_close(f));
+
+    file_contents_equal(tc, fname, LINE1 LINE2 LINE1 LINE1 LINE2, 
+                        strlen(LINE1)*3 + strlen(LINE2)*2);
 
-    stat = ap_open(&thefile, "testdel", APR_READ, APR_UREAD | APR_UWRITE | APR_GREAD, context);
-    if (stat == APR_SUCCESS) {
-        return stat;
-    }
-  
-    return APR_SUCCESS;
 }
 
-int testdirs(ap_pool_t *context)
+static void test_writev_buffered(abts_case *tc, void *data)
 {
-    ap_dir_t *temp;  
-    ap_file_t *file = NULL;
-    ap_ssize_t bytes;
-    ap_filetype_e type;
-    char *fname;
+    apr_file_t *f;
+    apr_size_t nbytes;
+    struct iovec vec[2];
+    const char *fname = "data/testwritev_buffered.dat";
 
-    fprintf(stdout, "Testing Directory functions.\n");
+    APR_ASSERT_SUCCESS(tc, "open file for writing",
+                       apr_file_open(&f, fname,
+                                     APR_FOPEN_WRITE | APR_FOPEN_CREATE | APR_FOPEN_TRUNCATE |
+                                     APR_FOPEN_BUFFERED, APR_FPROT_OS_DEFAULT, p));
 
-    fprintf(stdout, "\tMakeing Directory.......");
-    if (ap_make_dir("testdir", APR_UREAD | APR_UWRITE | APR_UEXECUTE | APR_GREAD | APR_GWRITE | APR_GEXECUTE | APR_WREAD | APR_WWRITE | APR_WEXECUTE, context)  != APR_SUCCESS) {
-        fprintf(stderr, "Could not create directory\n");
-        return -1;
-    }
-    else {
-        fprintf(stdout, "OK\n");
-    }
+    nbytes = strlen(TESTSTR);
+    APR_ASSERT_SUCCESS(tc, "buffered write",
+                       apr_file_write(f, TESTSTR, &nbytes));
 
-    if (ap_open(&file, "testdir/testfile", APR_READ | APR_WRITE | APR_CREATE, APR_UREAD | APR_UWRITE | APR_UEXECUTE, context) != APR_SUCCESS) {;
-        return -1;
-    }
+    vec[0].iov_base = LINE1;
+    vec[0].iov_len = strlen(LINE1);
+    vec[1].iov_base = LINE2;
+    vec[1].iov_len = strlen(LINE2);
 
-    bytes = strlen("Another test!!!");
-    ap_write(file, "Another test!!", &bytes); 
-	ap_close(file);
+    APR_ASSERT_SUCCESS(tc, "writev of size 2 to file",
+                       apr_file_writev(f, vec, 2, &nbytes));
 
-    fprintf(stdout, "\tOpening Directory.......");
-    if (ap_opendir(&temp, "testdir", context) != APR_SUCCESS) {
-        fprintf(stderr, "Could not open directory\n");
-        return -1;
-    }
-    else {
-        fprintf(stdout, "OK\n");
-    }
+    APR_ASSERT_SUCCESS(tc, "close for writing",
+                       apr_file_close(f));
 
-    fprintf(stdout, "\tReading Directory.......");
-    if ((ap_readdir(temp))  != APR_SUCCESS) {
-        fprintf(stderr, "Could not read directory\n");
-        return -1;
-    }
-    else {
-        fprintf(stdout, "OK\n");
-    }
-   
-    fprintf(stdout, "\tGetting Information about the file.......\n");
-    fprintf(stdout, "\t\tFile name.......");
-    do {
-        /* Because I want the file I created, I am skipping the "." and ".."
-         * files that are here. 
-         */
-        if (ap_readdir(temp) != APR_SUCCESS) {
-            fprintf(stderr, "Error reading directory testdir"); 
-            return -1;
-        }
-        ap_get_dir_filename(&fname, temp);
-    } while (fname[0] == '.');
-    if (strcmp(fname, "testfile")) {
-        fprintf(stderr, "Got wrong file name %s\n", fname);
-        return -1;
-    }
-    fprintf(stdout, "OK\n");
+    file_contents_equal(tc, fname, TESTSTR LINE1 LINE2,
+                        strlen(TESTSTR) + strlen(LINE1) + strlen(LINE2));
+}
+
+static void test_writev_buffered_seek(abts_case *tc, void *data)
+{
+    apr_file_t *f;
+    apr_status_t rv;
+    apr_off_t off = 0;
+    struct iovec vec[3];
+    apr_size_t nbytes = strlen(TESTSTR);
+    char *str = apr_pcalloc(p, nbytes+1);
+    const char *fname = "data/testwritev_buffered.dat";
+
+    APR_ASSERT_SUCCESS(tc, "open file for writing",
+                       apr_file_open(&f, fname,
+                                     APR_FOPEN_WRITE | APR_FOPEN_READ | APR_FOPEN_BUFFERED,
+                                     APR_FPROT_OS_DEFAULT, p));
+
+    rv = apr_file_read(f, str, &nbytes);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_STR_EQUAL(tc, TESTSTR, str);
+    APR_ASSERT_SUCCESS(tc, "buffered seek", apr_file_seek(f, APR_SET, &off));
+
+    vec[0].iov_base = LINE1;
+    vec[0].iov_len = strlen(LINE1);
+    vec[1].iov_base = LINE2;
+    vec[1].iov_len = strlen(LINE2);
+    vec[2].iov_base = TESTSTR;
+    vec[2].iov_len = strlen(TESTSTR);
+
+    APR_ASSERT_SUCCESS(tc, "writev of size 2 to file",
+                       apr_file_writev(f, vec, 3, &nbytes));
+
+    APR_ASSERT_SUCCESS(tc, "close for writing",
+                       apr_file_close(f));
+
+    file_contents_equal(tc, fname, LINE1 LINE2 TESTSTR,
+                        strlen(LINE1) + strlen(LINE2) + strlen(TESTSTR));
+
+    APR_ASSERT_SUCCESS(tc, "remove file", apr_file_remove(fname, p));
+}
+
+static void test_truncate(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_file_t *f;
+    const char *fname = "data/testtruncate.dat";
+    const char *s;
+    apr_size_t nbytes;
+    apr_finfo_t finfo;
+
+    apr_file_remove(fname, p);
+
+    rv = apr_file_open(&f, fname,
+                       APR_FOPEN_CREATE | APR_FOPEN_WRITE,
+                       APR_FPROT_UREAD | APR_FPROT_UWRITE, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    
+    s = "some data";
+    nbytes = strlen(s);
+    rv = apr_file_write(f, s, &nbytes);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_SIZE_EQUAL(tc, strlen(s), nbytes);
+
+    rv = apr_file_close(f);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_file_open(&f, fname,
+                       APR_FOPEN_TRUNCATE | APR_FOPEN_WRITE,
+                       APR_FPROT_UREAD | APR_FPROT_UWRITE, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_file_close(f);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_stat(&finfo, fname, APR_FINFO_SIZE, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_ASSERT(tc, "File size mismatch, expected 0 (empty)", finfo.size == 0);
+
+    rv = apr_file_remove(fname, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+}
+
+static void test_file_trunc(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_file_t *f;
+    const char *fname = "data/testtruncate.dat";
+    const char *s;
+    apr_size_t nbytes;
+    apr_finfo_t finfo;
+    char c;
+
+    apr_file_remove(fname, p);
+
+    rv = apr_file_open(&f, fname,
+                        APR_FOPEN_CREATE | APR_FOPEN_READ |
+                        APR_FOPEN_WRITE,
+                        APR_FPROT_UREAD | APR_FPROT_UWRITE, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    s = "some data";
+    nbytes = strlen(s);
+    rv = apr_file_write(f, s, &nbytes);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_SIZE_EQUAL(tc, strlen(s), nbytes);
+    rv = apr_file_trunc(f, 4);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    /* Test apr_file_info_get(). */
+    rv = apr_file_info_get(&finfo, APR_FINFO_SIZE, f);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_INT_EQUAL(tc, 4, (int)finfo.size);
+    /* EOF is not reported until the next read. */
+    rv = apr_file_eof(f);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    rv = apr_file_getc(&c, f);
+    ABTS_INT_EQUAL(tc, APR_EOF, rv);
+    rv = apr_file_eof(f);
+    ABTS_INT_EQUAL(tc, APR_EOF, rv);
+
+    rv = apr_file_close(f);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    rv = apr_stat(&finfo, fname, APR_FINFO_SIZE, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_INT_EQUAL(tc, 4, (int)finfo.size);
+
+    rv = apr_file_remove(fname, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+}
+
+static void test_file_trunc_buffered_write(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_file_t *f;
+    const char *fname = "data/testtruncate_buffered_write.dat";
+    const char *s;
+    apr_size_t nbytes;
+    apr_finfo_t finfo;
+    char c;
+
+    apr_file_remove(fname, p);
+
+    rv = apr_file_open(&f, fname,
+                        APR_FOPEN_CREATE | APR_FOPEN_READ |
+                        APR_FOPEN_WRITE | APR_FOPEN_BUFFERED,
+                        APR_FPROT_UREAD | APR_FPROT_UWRITE, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    s = "some data";
+    nbytes = strlen(s);
+    rv = apr_file_write(f, s, &nbytes);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_SIZE_EQUAL(tc, strlen(s), nbytes);
+    rv = apr_file_trunc(f, 4);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    /* Test apr_file_info_get(). */
+    rv = apr_file_info_get(&finfo, APR_FINFO_SIZE, f);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_INT_EQUAL(tc, 4, (int)finfo.size);
+    /* EOF is not reported until the next read. */
+    rv = apr_file_eof(f);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    rv = apr_file_getc(&c, f);
+    ABTS_INT_EQUAL(tc, APR_EOF, rv);
+    rv = apr_file_eof(f);
+    ABTS_INT_EQUAL(tc, APR_EOF, rv);
+
+    rv = apr_file_close(f);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    rv = apr_stat(&finfo, fname, APR_FINFO_SIZE, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_INT_EQUAL(tc, 4, (int)finfo.size);
+
+    rv = apr_file_remove(fname, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+}
+
+static void test_file_trunc_buffered_write2(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_file_t *f;
+    const char *fname = "data/testtruncate_buffered_write2.dat";
+    apr_finfo_t finfo;
+    char c;
 
-    fprintf(stdout, "\t\tFile type.......");
-    ap_dir_entry_ftype(&type, temp);
-    if (type != APR_REG) {
-        fprintf(stderr, "Got wrong file type\n");
-        return -1;
+    apr_file_remove(fname, p);
+
+    rv = apr_file_open(&f, fname,
+                       APR_FOPEN_CREATE | APR_FOPEN_READ |
+                       APR_FOPEN_WRITE | APR_FOPEN_BUFFERED,
+                       APR_FPROT_OS_DEFAULT, p);
+    APR_ASSERT_SUCCESS(tc, "open test file", rv);
+
+    rv = apr_file_puts("abc", f);
+    APR_ASSERT_SUCCESS(tc, "write first string", rv);
+    rv = apr_file_flush(f);
+    APR_ASSERT_SUCCESS(tc, "flush", rv);
+    rv = apr_file_puts("def", f);
+    APR_ASSERT_SUCCESS(tc, "write second string", rv);
+    /* Truncate behind the write buffer. */
+    rv = apr_file_trunc(f, 2);
+    APR_ASSERT_SUCCESS(tc, "truncate the file", rv);
+    /* Test apr_file_info_get(). */
+    rv = apr_file_info_get(&finfo, APR_FINFO_SIZE, f);
+    APR_ASSERT_SUCCESS(tc, "get file info", rv);
+    ABTS_INT_EQUAL(tc, 2, (int)finfo.size);
+    /* EOF is not reported until the next read. */
+    rv = apr_file_eof(f);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    rv = apr_file_getc(&c, f);
+    ABTS_INT_EQUAL(tc, APR_EOF, rv);
+    rv = apr_file_eof(f);
+    ABTS_INT_EQUAL(tc, APR_EOF, rv);
+
+    apr_file_close(f);
+
+    rv = apr_stat(&finfo, fname, APR_FINFO_SIZE, p);
+    APR_ASSERT_SUCCESS(tc, "stat file", rv);
+    ABTS_INT_EQUAL(tc, 2, (int)finfo.size);
+
+    apr_file_remove(fname, p);
+}
+
+static void test_file_trunc_buffered_read(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_file_t *f;
+    const char *fname = "data/testtruncate_buffered_read.dat";
+    apr_finfo_t finfo;
+    char c;
+
+    apr_file_remove(fname, p);
+
+    rv = apr_file_open(&f, fname,
+                       APR_FOPEN_CREATE | APR_FOPEN_READ |
+                       APR_FOPEN_WRITE, APR_FPROT_OS_DEFAULT, p);
+    APR_ASSERT_SUCCESS(tc, "open test file", rv);
+
+    rv = apr_file_puts("abc", f);
+    APR_ASSERT_SUCCESS(tc, "write test data", rv);
+    apr_file_close(f);
+
+    rv = apr_file_open(&f, fname,
+                       APR_FOPEN_READ | APR_FOPEN_WRITE |
+                       APR_FOPEN_BUFFERED, APR_FPROT_OS_DEFAULT, p);
+    APR_ASSERT_SUCCESS(tc, "re-open test file", rv);
+
+    /* Read to fill in the buffer. */
+    rv = apr_file_getc(&c, f);
+    APR_ASSERT_SUCCESS(tc, "read char", rv);
+    /* Truncate the file. */
+    rv = apr_file_trunc(f, 1);
+    APR_ASSERT_SUCCESS(tc, "truncate the file", rv);
+    /* Test apr_file_info_get(). */
+    rv = apr_file_info_get(&finfo, APR_FINFO_SIZE, f);
+    APR_ASSERT_SUCCESS(tc, "get file info", rv);
+    ABTS_INT_EQUAL(tc, 1, (int)finfo.size);
+    /* EOF is not reported until the next read. */
+    rv = apr_file_eof(f);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    rv = apr_file_getc(&c, f);
+    ABTS_INT_EQUAL(tc, APR_EOF, rv);
+    rv = apr_file_eof(f);
+    ABTS_INT_EQUAL(tc, APR_EOF, rv);
+
+    apr_file_close(f);
+
+    rv = apr_stat(&finfo, fname, APR_FINFO_SIZE, p);
+    APR_ASSERT_SUCCESS(tc, "stat file", rv);
+    ABTS_INT_EQUAL(tc, 1, (int)finfo.size);
+
+    apr_file_remove(fname, p);
+}
+
+static void test_bigfprintf(abts_case *tc, void *data)
+{
+    apr_file_t *f;
+    const char *fname = "data/testbigfprintf.dat";
+    char *to_write;
+    int i;
+
+    apr_file_remove(fname, p);
+
+    APR_ASSERT_SUCCESS(tc, "open test file",
+                       apr_file_open(&f, fname,
+                                     APR_FOPEN_CREATE|APR_FOPEN_WRITE,
+                                     APR_FPROT_UREAD|APR_FPROT_UWRITE, p));
+    
+
+    to_write = malloc(HUGE_STRING_LEN + 3);
+
+    for (i = 0; i < HUGE_STRING_LEN + 1; ++i)
+        to_write[i] = 'A' + i%26;
+
+    strcpy(to_write + HUGE_STRING_LEN, "42");
+
+    i = apr_file_printf(f, "%s", to_write);
+    ABTS_INT_EQUAL(tc, HUGE_STRING_LEN + 2, i);
+
+    apr_file_close(f);
+
+    file_contents_equal(tc, fname, to_write, HUGE_STRING_LEN + 2);
+
+    free(to_write);
+}
+
+static void test_fail_write_flush(abts_case *tc, void *data)
+{
+    apr_file_t *f;
+    const char *fname = "data/testflush.dat";
+    apr_status_t rv;
+    char buf[APR_BUFFERSIZE];
+    int n;
+
+    apr_file_remove(fname, p);
+
+    APR_ASSERT_SUCCESS(tc, "open test file",
+                       apr_file_open(&f, fname,
+                                     APR_FOPEN_CREATE|APR_FOPEN_READ|APR_FOPEN_BUFFERED,
+                                     APR_FPROT_UREAD|APR_FPROT_UWRITE, p));
+
+    memset(buf, 'A', sizeof buf);
+
+    /* Try three writes.  One of these should fail when it exceeds the
+     * internal buffer and actually tries to write to the file, which
+     * was opened read-only and hence should be unwritable. */
+    for (n = 0, rv = APR_SUCCESS; n < 4 && rv == APR_SUCCESS; n++) {
+        apr_size_t bytes = sizeof buf;
+        rv = apr_file_write(f, buf, &bytes);
     }
-    fprintf(stdout, "OK\n");
 
-    fprintf(stdout, "\t\tFile size.......");
-    ap_dir_entry_size(&bytes, temp);
-    if (bytes != (ap_ssize_t)strlen("Another test!!!")) {
-        fprintf(stderr, "Got wrong file size %d\n", bytes);
-        return -1;
+    ABTS_ASSERT(tc, "failed to write to read-only buffered fd",
+                rv != APR_SUCCESS);
+
+    apr_file_close(f);
+}
+
+static void test_fail_read_flush(abts_case *tc, void *data)
+{
+    apr_file_t *f;
+    const char *fname = "data/testflush.dat";
+    apr_status_t rv;
+    char buf[2];
+
+    apr_file_remove(fname, p);
+
+    APR_ASSERT_SUCCESS(tc, "open test file",
+                       apr_file_open(&f, fname,
+                                     APR_FOPEN_CREATE|APR_FOPEN_READ|APR_FOPEN_BUFFERED,
+                                     APR_FPROT_UREAD|APR_FPROT_UWRITE, p));
+
+    /* this write should be buffered. */
+    APR_ASSERT_SUCCESS(tc, "buffered write should succeed",
+                       apr_file_puts("hello", f));
+
+    /* Now, trying a read should fail since the write must be flushed,
+     * and should fail with something other than EOF since the file is
+     * opened read-only. */
+    rv = apr_file_read_full(f, buf, 2, NULL);
+
+    ABTS_ASSERT(tc, "read should flush buffered write and fail",
+                rv != APR_SUCCESS && rv != APR_EOF);
+
+    /* Likewise for gets */
+    rv = apr_file_gets(buf, 2, f);
+
+    ABTS_ASSERT(tc, "gets should flush buffered write and fail",
+                rv != APR_SUCCESS && rv != APR_EOF);
+
+    /* Likewise for seek. */
+    {
+        apr_off_t offset = 0;
+
+        rv = apr_file_seek(f, APR_SET, &offset);
     }
-    fprintf(stdout, "OK\n");
-     
-    fprintf(stdout, "\tRewinding directory.......");
-    ap_rewinddir(temp); 
-    fprintf(stdout, "OK\n");
+
+    ABTS_ASSERT(tc, "seek should flush buffered write and fail",
+                rv != APR_SUCCESS && rv != APR_EOF);
+
+    apr_file_close(f);
+}
+
+static void test_xthread(abts_case *tc, void *data)
+{
+    apr_file_t *f;
+    const char *fname = "data/testxthread.dat";
+    apr_status_t rv;
+    apr_int32_t flags = APR_FOPEN_CREATE|APR_FOPEN_READ|APR_FOPEN_WRITE|APR_FOPEN_APPEND|APR_FOPEN_XTHREAD;
+    char buf[128] = { 0 };
+
+    /* Test for bug 38438, opening file with append + xthread and seeking to 
+       the end of the file resulted in writes going to the beginning not the
+       end. */
+
+    apr_file_remove(fname, p);
+
+    APR_ASSERT_SUCCESS(tc, "open test file",
+                       apr_file_open(&f, fname, flags,
+                                     APR_FPROT_UREAD|APR_FPROT_UWRITE, p));
+
+    APR_ASSERT_SUCCESS(tc, "write should succeed",
+                       apr_file_puts("hello", f));
+
+    apr_file_close(f);
     
-    fprintf(stdout, "\tClosing Directory.......");
-    if (ap_closedir(temp)  != APR_SUCCESS) {
-        fprintf(stderr, "Could not close directory\n");
-        return -1;
+    APR_ASSERT_SUCCESS(tc, "open test file",
+                       apr_file_open(&f, fname, flags,
+                                     APR_FPROT_UREAD|APR_FPROT_UWRITE, p));
+
+    /* Seek to the end. */
+    {
+        apr_off_t offset = 0;
+
+        rv = apr_file_seek(f, APR_END, &offset);
+        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
     }
-    else {
-        fprintf(stdout, "OK\n");
+
+    APR_ASSERT_SUCCESS(tc, "more writes should succeed",
+                       apr_file_puts("world", f));
+
+    /* Back to the beginning. */
+    {
+        apr_off_t offset = 0;
+        
+        rv = apr_file_seek(f, APR_SET, &offset);
+        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
     }
+    
+    apr_file_read_full(f, buf, sizeof(buf), NULL);
+
+    ABTS_STR_EQUAL(tc, "helloworld", buf);
+
+    apr_file_close(f);
+}
+
+static void test_append(abts_case *tc, void *data)
+{
+    apr_file_t *f1;
+    apr_file_t *f2;
+    const char *fname = "data/testappend.dat";
+    apr_int32_t flags = APR_FOPEN_CREATE | APR_FOPEN_READ | APR_FOPEN_WRITE | APR_FOPEN_APPEND;
+    char buf[128];
+    apr_off_t offset;
+
+    apr_file_remove(fname, p);
+
+    /* Open test file with APR_FOPEN_APPEND, but without APR_FOPEN_XTHREAD. */
+    APR_ASSERT_SUCCESS(tc, "open test file",
+        apr_file_open(&f1, fname, flags, APR_FPROT_OS_DEFAULT, p));
+
+    /* Open test file with APR_FOPEN_APPEND and APR_FOPEN_XTHREAD. */
+    APR_ASSERT_SUCCESS(tc, "open test file",
+        apr_file_open(&f2, fname, flags | APR_FOPEN_XTHREAD, APR_FPROT_OS_DEFAULT, p));
+
+    APR_ASSERT_SUCCESS(tc, "write should succeed",
+        apr_file_puts("w1", f1));
+    offset = 0;
+    APR_ASSERT_SUCCESS(tc, "seek should succeed",
+        apr_file_seek(f1, APR_CUR, &offset));
+    ABTS_INT_EQUAL(tc, 2, (int) offset);
+
+    APR_ASSERT_SUCCESS(tc, "write should succeed",
+        apr_file_puts("w2", f2));
+    offset = 0;
+    APR_ASSERT_SUCCESS(tc, "seek should succeed",
+        apr_file_seek(f2, APR_CUR, &offset));
+    ABTS_INT_EQUAL(tc, 4, (int) offset);
+
+    APR_ASSERT_SUCCESS(tc, "write should succeed",
+        apr_file_puts("w3", f1));
+    offset = 0;
+    APR_ASSERT_SUCCESS(tc, "seek should succeed",
+        apr_file_seek(f1, APR_CUR, &offset));
+    ABTS_INT_EQUAL(tc, 6, (int) offset);
+
+    APR_ASSERT_SUCCESS(tc, "write should succeed",
+        apr_file_puts("w4", f2));
+
+    offset = 0;
+    APR_ASSERT_SUCCESS(tc, "seek should succeed",
+        apr_file_seek(f2, APR_CUR, &offset));
+    ABTS_INT_EQUAL(tc, 8, (int) offset);
+
+    /* Check file content file using F1. */
+    offset = 0;
+    APR_ASSERT_SUCCESS(tc, "seek should succeed",
+        apr_file_seek(f1, APR_SET, &offset));
+    memset(buf, 0, sizeof(buf));
+    apr_file_read_full(f1, buf, sizeof(buf), NULL);
+    ABTS_STR_EQUAL(tc, "w1w2w3w4", buf);
+
+    /* Check file content file using F2. */
+    offset = 0;
+    APR_ASSERT_SUCCESS(tc, "seek should succeed",
+        apr_file_seek(f2, APR_SET, &offset));
+    memset(buf, 0, sizeof(buf));
+    apr_file_read_full(f2, buf, sizeof(buf), NULL);
+    ABTS_STR_EQUAL(tc, "w1w2w3w4", buf);
+
+    apr_file_close(f1);
+    apr_file_close(f2);
+}
+
+static void test_large_write_buffered(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_file_t *f;
+    const char *fname = "data/testlarge_write_buffered.dat";
+    apr_size_t len;
+    apr_size_t bytes_written;
+    apr_size_t bytes_read;
+    char *buf;
+    char *buf2;
+
+    apr_file_remove(fname, p);
+
+    rv = apr_file_open(&f, fname,
+                       APR_FOPEN_CREATE | APR_FOPEN_WRITE | APR_FOPEN_BUFFERED,
+                       APR_FPROT_OS_DEFAULT, p);
+    APR_ASSERT_SUCCESS(tc, "open test file for writing", rv);
+
+    /* Test a single large write. */
+    len = 80000;
+    buf = apr_palloc(p, len);
+    memset(buf, 'a', len);
+    rv = apr_file_write_full(f, buf, len, &bytes_written);
+    APR_ASSERT_SUCCESS(tc, "write to file", rv);
+    ABTS_INT_EQUAL(tc, (int)len, (int)bytes_written);
+    apr_file_close(f);
+
+    rv = apr_file_open(&f, fname, APR_FOPEN_READ,
+                       APR_FPROT_OS_DEFAULT, p);
+    APR_ASSERT_SUCCESS(tc, "open test file for reading", rv);
+
+    buf2 = apr_palloc(p, len + 1);
+    rv = apr_file_read_full(f, buf2, len + 1, &bytes_read);
+    ABTS_INT_EQUAL(tc, APR_EOF, rv);
+    ABTS_INT_EQUAL(tc, (int)len, (int)bytes_read);
+    ABTS_TRUE(tc, memcmp(buf, buf2, len) == 0);
+    apr_file_close(f);
+
+    apr_file_remove(fname, p);
+}
+
+static void test_two_large_writes_buffered(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_file_t *f;
+    const char *fname = "data/testtwo_large_writes_buffered.dat";
+    apr_size_t len;
+    apr_size_t bytes_written;
+    apr_size_t bytes_read;
+    char *buf;
+    char *buf2;
+
+    apr_file_remove(fname, p);
+
+    rv = apr_file_open(&f, fname,
+                       APR_FOPEN_CREATE | APR_FOPEN_WRITE | APR_FOPEN_BUFFERED,
+                       APR_FPROT_OS_DEFAULT, p);
+    APR_ASSERT_SUCCESS(tc, "open test file for writing", rv);
+
+    /* Test two consecutive large writes. */
+    len = 80000;
+    buf = apr_palloc(p, len);
+    memset(buf, 'a', len);
+
+    rv = apr_file_write_full(f, buf, len / 2, &bytes_written);
+    APR_ASSERT_SUCCESS(tc, "write to file", rv);
+    ABTS_INT_EQUAL(tc, (int)(len / 2), (int)bytes_written);
+
+    rv = apr_file_write_full(f, buf, len / 2, &bytes_written);
+    APR_ASSERT_SUCCESS(tc, "write to file", rv);
+    ABTS_INT_EQUAL(tc, (int)(len / 2), (int)bytes_written);
+
+    apr_file_close(f);
+
+    rv = apr_file_open(&f, fname, APR_FOPEN_READ,
+                       APR_FPROT_OS_DEFAULT, p);
+    APR_ASSERT_SUCCESS(tc, "open test file for reading", rv);
+
+    buf2 = apr_palloc(p, len + 1);
+    rv = apr_file_read_full(f, buf2, len + 1, &bytes_read);
+    ABTS_INT_EQUAL(tc, APR_EOF, rv);
+    ABTS_INT_EQUAL(tc, (int) len, (int)bytes_read);
+    ABTS_TRUE(tc, memcmp(buf, buf2, len) == 0);
+    apr_file_close(f);
+
+    apr_file_remove(fname, p);
+}
+
+static void test_small_and_large_writes_buffered(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_file_t *f;
+    const char *fname = "data/testtwo_large_writes_buffered.dat";
+    apr_size_t len;
+    apr_size_t bytes_written;
+    apr_size_t bytes_read;
+    char *buf;
+    char *buf2;
+
+    apr_file_remove(fname, p);
+
+    rv = apr_file_open(&f, fname,
+                       APR_FOPEN_CREATE | APR_FOPEN_WRITE | APR_FOPEN_BUFFERED,
+                       APR_FPROT_OS_DEFAULT, p);
+    APR_ASSERT_SUCCESS(tc, "open test file for writing", rv);
+
+    /* Test small write followed by a large write. */
+    len = 80000;
+    buf = apr_palloc(p, len);
+    memset(buf, 'a', len);
+
+    rv = apr_file_write_full(f, buf, 5, &bytes_written);
+    APR_ASSERT_SUCCESS(tc, "write to file", rv);
+    ABTS_INT_EQUAL(tc, 5, (int)bytes_written);
+
+    rv = apr_file_write_full(f, buf, len - 5, &bytes_written);
+    APR_ASSERT_SUCCESS(tc, "write to file", rv);
+    ABTS_INT_EQUAL(tc, (int)(len - 5), (int)bytes_written);
+
+    apr_file_close(f);
+
+    rv = apr_file_open(&f, fname, APR_FOPEN_READ,
+                       APR_FPROT_OS_DEFAULT, p);
+    APR_ASSERT_SUCCESS(tc, "open test file for reading", rv);
+
+    buf2 = apr_palloc(p, len + 1);
+    rv = apr_file_read_full(f, buf2, len + 1, &bytes_read);
+    ABTS_INT_EQUAL(tc, APR_EOF, rv);
+    ABTS_INT_EQUAL(tc, (int) len, (int)bytes_read);
+    ABTS_TRUE(tc, memcmp(buf, buf2, len) == 0);
+    apr_file_close(f);
+
+    apr_file_remove(fname, p);
+}
+
+static void test_write_buffered_spanning_over_bufsize(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_file_t *f;
+    const char *fname = "data/testwrite_buffered_spanning_over_bufsize.dat";
+    apr_size_t len;
+    apr_size_t bytes_written;
+    apr_size_t bytes_read;
+    char *buf;
+    char *buf2;
 
-    fprintf(stdout, "\tRemoving file from directory.......");
-    if (ap_remove_file("testdir/testfile", context)  != APR_SUCCESS) {
-        fprintf(stderr, "Could not remove file\n");
-        return -1;
+    apr_file_remove(fname, p);
+
+    rv = apr_file_open(&f, fname,
+                       APR_FOPEN_CREATE | APR_FOPEN_WRITE | APR_FOPEN_BUFFERED,
+                       APR_FPROT_OS_DEFAULT, p);
+    APR_ASSERT_SUCCESS(tc, "open test file for writing", rv);
+
+    /* Test three writes than span over the default buffer size. */
+    len = APR_BUFFERSIZE + 1;
+    buf = apr_palloc(p, len);
+    memset(buf, 'a', len);
+
+    rv = apr_file_write_full(f, buf, APR_BUFFERSIZE - 1, &bytes_written);
+    APR_ASSERT_SUCCESS(tc, "write to file", rv);
+    ABTS_INT_EQUAL(tc, APR_BUFFERSIZE - 1, (int)bytes_written);
+
+    rv = apr_file_write_full(f, buf, 2, &bytes_written);
+    APR_ASSERT_SUCCESS(tc, "write to file", rv);
+    ABTS_INT_EQUAL(tc, 2, (int)bytes_written);
+
+    apr_file_close(f);
+
+    rv = apr_file_open(&f, fname, APR_FOPEN_READ,
+                       APR_FPROT_OS_DEFAULT, p);
+    APR_ASSERT_SUCCESS(tc, "open test file for reading", rv);
+
+    buf2 = apr_palloc(p, len + 1);
+    rv = apr_file_read_full(f, buf2, len + 1, &bytes_read);
+    ABTS_INT_EQUAL(tc, APR_EOF, rv);
+    ABTS_INT_EQUAL(tc, (int)len, (int)bytes_read);
+    ABTS_TRUE(tc, memcmp(buf, buf2, len) == 0);
+    apr_file_close(f);
+
+    apr_file_remove(fname, p);
+}
+
+typedef struct thread_file_append_ctx_t {
+    apr_pool_t *pool;
+    const char *fname;
+    apr_size_t chunksize;
+    char val;
+    int num_writes;
+    char *errmsg;
+} thread_file_append_ctx_t;
+
+static void * APR_THREAD_FUNC thread_file_append_func(apr_thread_t *thd, void *data)
+{
+    thread_file_append_ctx_t *ctx = data;
+    apr_status_t rv;
+    apr_file_t *f;
+    int i;
+    char *writebuf;
+    char *readbuf;
+
+    rv = apr_file_open(&f, ctx->fname,
+                       APR_FOPEN_READ | APR_FOPEN_WRITE | APR_FOPEN_APPEND,
+                       APR_FPROT_OS_DEFAULT, ctx->pool);
+    if (rv) {
+        apr_thread_exit(thd, rv);
+        return NULL;
     }
-    else {
-        fprintf(stdout, "OK\n");
+
+    writebuf = apr_palloc(ctx->pool, ctx->chunksize);
+    memset(writebuf, ctx->val, ctx->chunksize);
+    readbuf = apr_palloc(ctx->pool, ctx->chunksize);
+
+    for (i = 0; i < ctx->num_writes; i++) {
+        apr_size_t bytes_written;
+        apr_size_t bytes_read;
+        apr_off_t offset;
+
+        rv = apr_file_write_full(f, writebuf, ctx->chunksize, &bytes_written);
+        if (rv) {
+            apr_thread_exit(thd, rv);
+            return NULL;
+        }
+        /* After writing the data, seek back from the current offset and
+         * verify what we just wrote. */
+        offset = -((apr_off_t)ctx->chunksize);
+        rv = apr_file_seek(f, APR_CUR, &offset);
+        if (rv) {
+            apr_thread_exit(thd, rv);
+            return NULL;
+        }
+        rv = apr_file_read_full(f, readbuf, ctx->chunksize, &bytes_read);
+        if (rv) {
+            apr_thread_exit(thd, rv);
+            return NULL;
+        }
+        if (memcmp(readbuf, writebuf, ctx->chunksize) != 0) {
+            ctx->errmsg = apr_psprintf(
+                ctx->pool,
+                "Unexpected data at file offset %" APR_OFF_T_FMT,
+                offset);
+            apr_thread_exit(thd, APR_SUCCESS);
+            return NULL;
+        }
     }
 
-    fprintf(stdout, "\tRemoving Directory.......");
-    if (ap_remove_dir("testdir", context)  != APR_SUCCESS) {
-        fprintf(stderr, "Could not remove directory\n");
-        return -1;
+    apr_file_close(f);
+    apr_thread_exit(thd, APR_SUCCESS);
+
+    return NULL;
+}
+
+static void test_atomic_append(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_status_t thread_rv;
+    apr_file_t *f;
+    const char *fname = "data/testatomic_append.dat";
+    unsigned int seed;
+    thread_file_append_ctx_t ctx1 = {0};
+    thread_file_append_ctx_t ctx2 = {0};
+    apr_thread_t *t1;
+    apr_thread_t *t2;
+
+    apr_file_remove(fname, p);
+
+    rv = apr_file_open(&f, fname, APR_FOPEN_WRITE | APR_FOPEN_CREATE,
+                       APR_FPROT_OS_DEFAULT, p);
+    APR_ASSERT_SUCCESS(tc, "create file", rv);
+    apr_file_close(f);
+
+    seed = (unsigned int)apr_time_now();
+    abts_log_message("Random seed for test_atomic_append() is %u", seed);
+    srand(seed);
+
+    /* Create two threads appending data to the same file. */
+    apr_pool_create(&ctx1.pool, p);
+    ctx1.fname = fname;
+    ctx1.chunksize = 1 + rand() % 8192;
+    ctx1.val = 'A';
+    ctx1.num_writes = 1000;
+    rv = apr_thread_create(&t1, NULL, thread_file_append_func, &ctx1, p);
+    APR_ASSERT_SUCCESS(tc, "create thread", rv);
+
+    apr_pool_create(&ctx2.pool, p);
+    ctx2.fname = fname;
+    ctx2.chunksize = 1 + rand() % 8192;
+    ctx2.val = 'B';
+    ctx2.num_writes = 1000;
+    rv = apr_thread_create(&t2, NULL, thread_file_append_func, &ctx2, p);
+    APR_ASSERT_SUCCESS(tc, "create thread", rv);
+
+    rv = apr_thread_join(&thread_rv, t1);
+    APR_ASSERT_SUCCESS(tc, "join thread", rv);
+    APR_ASSERT_SUCCESS(tc, "no thread errors", thread_rv);
+    if (ctx1.errmsg) {
+        ABTS_FAIL(tc, ctx1.errmsg);
     }
-    else {
-        fprintf(stdout, "OK\n");
+    rv = apr_thread_join(&thread_rv, t2);
+    APR_ASSERT_SUCCESS(tc, "join thread", rv);
+    APR_ASSERT_SUCCESS(tc, "no thread errors", thread_rv);
+    if (ctx2.errmsg) {
+        ABTS_FAIL(tc, ctx2.errmsg);
     }
-    
-    return 1; 
-}    
+
+    apr_file_remove(fname, p);
+}
+
+static void test_append_locked(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_file_t *f;
+    const char *fname = "data/testappend_locked.dat";
+    apr_size_t bytes_written;
+    apr_size_t bytes_read;
+    char buf[64] = {0};
+
+    apr_file_remove(fname, p);
+
+    rv = apr_file_open(&f, fname,
+                       APR_FOPEN_WRITE | APR_FOPEN_CREATE | APR_FOPEN_APPEND,
+                       APR_FPROT_OS_DEFAULT, p);
+    APR_ASSERT_SUCCESS(tc, "create file", rv);
+
+    rv = apr_file_lock(f, APR_FLOCK_EXCLUSIVE);
+    APR_ASSERT_SUCCESS(tc, "lock file", rv);
+
+    /* PR50058: Appending to a locked file should not deadlock. */
+    rv = apr_file_write_full(f, "abc", 3, &bytes_written);
+    APR_ASSERT_SUCCESS(tc, "write to file", rv);
+
+    apr_file_unlock(f);
+    apr_file_close(f);
+
+    rv = apr_file_open(&f, fname, APR_FOPEN_READ, APR_FPROT_OS_DEFAULT, p);
+    APR_ASSERT_SUCCESS(tc, "open file", rv);
+
+    rv = apr_file_read_full(f, buf, sizeof(buf), &bytes_read);
+    ABTS_INT_EQUAL(tc, APR_EOF, rv);
+    ABTS_INT_EQUAL(tc, 3, (int)bytes_read);
+    ABTS_STR_EQUAL(tc, "abc", buf);
+
+    apr_file_close(f);
+    apr_file_remove(fname, p);
+}
+
+static void test_append_read(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_file_t *f;
+    const char *fname = "data/testappend_read.dat";
+    apr_off_t offset;
+    char buf[64];
+
+    apr_file_remove(fname, p);
+
+    /* Create file with contents. */
+    rv = apr_file_open(&f, fname, APR_FOPEN_WRITE | APR_FOPEN_CREATE,
+                       APR_FPROT_OS_DEFAULT, p);
+    APR_ASSERT_SUCCESS(tc, "create file", rv);
+
+    rv = apr_file_puts("abc", f);
+    APR_ASSERT_SUCCESS(tc, "write to file", rv);
+    apr_file_close(f);
+
+    /* Re-open it with APR_FOPEN_APPEND. */
+    rv = apr_file_open(&f, fname,
+                       APR_FOPEN_READ | APR_FOPEN_WRITE | APR_FOPEN_APPEND,
+                       APR_FPROT_OS_DEFAULT, p);
+    APR_ASSERT_SUCCESS(tc, "open file", rv);
+
+    /* Test the initial file offset.  Even though we used APR_FOPEN_APPEND,
+     * the offset should be kept in the beginning of the file until the
+     * first append.  (Previously, the Windows implementation performed
+     * an erroneous seek to the file's end right after opening it.)
+     */
+    offset = 0;
+    rv = apr_file_seek(f, APR_CUR, &offset);
+    APR_ASSERT_SUCCESS(tc, "get file offset", rv);
+    ABTS_INT_EQUAL(tc, 0, (int)offset);
+
+    /* Test reading from the file. */
+    rv = apr_file_gets(buf, sizeof(buf), f);
+    APR_ASSERT_SUCCESS(tc, "read from file", rv);
+    ABTS_STR_EQUAL(tc, "abc", buf);
+
+    /* Test the file offset after reading. */
+    offset = 0;
+    rv = apr_file_seek(f, APR_CUR, &offset);
+    APR_ASSERT_SUCCESS(tc, "get file offset", rv);
+    ABTS_INT_EQUAL(tc, 3, (int)offset);
+
+    apr_file_close(f);
+    apr_file_remove(fname, p);
+}
+
+abts_suite *testfile(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite)
+
+    abts_run_test(suite, test_open_noreadwrite, NULL);
+    abts_run_test(suite, test_open_excl, NULL);
+    abts_run_test(suite, test_open_read, NULL);
+    abts_run_test(suite, test_open_readwrite, NULL);
+    abts_run_test(suite, link_existing, NULL);
+    abts_run_test(suite, link_nonexisting, NULL);
+    abts_run_test(suite, test_read, NULL); 
+    abts_run_test(suite, test_readzero, NULL); 
+    abts_run_test(suite, test_seek, NULL);
+    abts_run_test(suite, test_filename, NULL);
+    abts_run_test(suite, test_fileclose, NULL);
+    abts_run_test(suite, test_file_remove, NULL);
+    abts_run_test(suite, test_open_write, NULL);
+    abts_run_test(suite, test_open_writecreate, NULL);
+    abts_run_test(suite, test_write, NULL);
+    abts_run_test(suite, test_userdata_set, NULL);
+    abts_run_test(suite, test_userdata_get, NULL);
+    abts_run_test(suite, test_userdata_getnokey, NULL);
+    abts_run_test(suite, test_getc, NULL);
+    abts_run_test(suite, test_ungetc, NULL);
+    abts_run_test(suite, test_gets, NULL);
+    abts_run_test(suite, test_gets_buffered, NULL);
+    abts_run_test(suite, test_gets_empty, NULL);
+    abts_run_test(suite, test_gets_multiline, NULL);
+    abts_run_test(suite, test_gets_small_buf, NULL);
+    abts_run_test(suite, test_gets_ungetc, NULL);
+    abts_run_test(suite, test_gets_buffered_big, NULL);
+    abts_run_test(suite, test_puts, NULL);
+    abts_run_test(suite, test_writev, NULL);
+    abts_run_test(suite, test_writev_full, NULL);
+    abts_run_test(suite, test_writev_buffered, NULL);
+    abts_run_test(suite, test_writev_buffered_seek, NULL);
+    abts_run_test(suite, test_bigread, NULL);
+    abts_run_test(suite, test_mod_neg, NULL);
+    abts_run_test(suite, test_truncate, NULL);
+    abts_run_test(suite, test_file_trunc, NULL);
+    abts_run_test(suite, test_file_trunc_buffered_write, NULL);
+    abts_run_test(suite, test_file_trunc_buffered_write2, NULL);
+    abts_run_test(suite, test_file_trunc_buffered_read, NULL);
+    abts_run_test(suite, test_bigfprintf, NULL);
+    abts_run_test(suite, test_fail_write_flush, NULL);
+    abts_run_test(suite, test_fail_read_flush, NULL);
+    abts_run_test(suite, test_buffer_set_get, NULL);
+    abts_run_test(suite, test_xthread, NULL);
+    abts_run_test(suite, test_append, NULL);
+    abts_run_test(suite, test_large_write_buffered, NULL);
+    abts_run_test(suite, test_two_large_writes_buffered, NULL);
+    abts_run_test(suite, test_small_and_large_writes_buffered, NULL);
+    abts_run_test(suite, test_write_buffered_spanning_over_bufsize, NULL);
+    abts_run_test(suite, test_atomic_append, NULL);
+    abts_run_test(suite, test_append_locked, NULL);
+    abts_run_test(suite, test_append_read, NULL);
+
+    return suite;
+}
 
diff --git a/test/testfile.dsp b/test/testfile.dsp
deleted file mode 100644
index 25671fdf927..00000000000
--- a/test/testfile.dsp
+++ /dev/null
@@ -1,92 +0,0 @@
-# Microsoft Developer Studio Project File - Name="testfile" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 5.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=testfile - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "testfile.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 "testfile.mak" CFG="testfile - Win32 Debug"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "testfile - Win32 Release" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE "testfile - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE 
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF  "$(CFG)" == "testfile - 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 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /W3 /GX /O2 /I "..\include" /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ..\Release\aprlib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"..\Release\testfile.exe"
-# SUBTRACT LINK32 /debug
-
-!ELSEIF  "$(CFG)" == "testfile - 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 /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\include" /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /c
-# SUBTRACT CPP /YX /Yc /Yu
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 ..\Debug\aprlib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\Debug\testfile.exe" /pdbtype:sept
-
-!ENDIF 
-
-# Begin Target
-
-# Name "testfile - Win32 Release"
-# Name "testfile - Win32 Debug"
-# Begin Source File
-
-SOURCE=.\testfile.c
-# End Source File
-# End Target
-# End Project
diff --git a/test/testfilecopy.c b/test/testfilecopy.c
new file mode 100644
index 00000000000..fc2dea48b06
--- /dev/null
+++ b/test/testfilecopy.c
@@ -0,0 +1,138 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "testutil.h"
+#include "apr_file_io.h"
+#include "apr_file_info.h"
+#include "apr_errno.h"
+#include "apr_pools.h"
+
+static void copy_helper(abts_case *tc, const char *from, const char * to,
+                        apr_fileperms_t perms, int append, apr_pool_t *p)
+{
+    apr_status_t rv;
+    apr_status_t dest_rv;
+    apr_finfo_t copy;
+    apr_finfo_t orig;
+    apr_finfo_t dest;
+    
+    dest_rv = apr_stat(&dest, to, APR_FINFO_SIZE, p);
+    
+    if (!append) {
+        rv = apr_file_copy(from, to, perms, p);
+    }
+    else {
+        rv = apr_file_append(from, to, perms, p);
+    }
+    APR_ASSERT_SUCCESS(tc, "Error copying file", rv);
+
+    rv = apr_stat(&orig, from, APR_FINFO_SIZE, p);
+    APR_ASSERT_SUCCESS(tc, "Couldn't stat original file", rv);
+
+    rv = apr_stat(&copy, to, APR_FINFO_SIZE, p);
+    APR_ASSERT_SUCCESS(tc, "Couldn't stat copy file", rv);
+
+    if (!append) {
+        ABTS_ASSERT(tc, "File size differs", orig.size == copy.size);
+    }
+    else {
+        ABTS_ASSERT(tc, "File size differs", 
+			            ((dest_rv == APR_SUCCESS) 
+			              ? dest.size : 0) + orig.size == copy.size);
+    }
+}
+
+static void copy_short_file(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+
+    /* make absolutely sure that the dest file doesn't exist. */
+    apr_file_remove("data/file_copy.txt", p);
+    
+    copy_helper(tc, "data/file_datafile.txt", "data/file_copy.txt", 
+                APR_FPROT_FILE_SOURCE_PERMS, 0, p);
+    rv = apr_file_remove("data/file_copy.txt", p);
+    APR_ASSERT_SUCCESS(tc, "Couldn't remove copy file", rv);
+}
+
+static void copy_over_existing(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    
+    /* make absolutely sure that the dest file doesn't exist. */
+    apr_file_remove("data/file_copy.txt", p);
+    
+    /* This is a cheat.  I don't want to create a new file, so I just copy
+     * one file, then I copy another.  If the second copy succeeds, then
+     * this works.
+     */
+    copy_helper(tc, "data/file_datafile.txt", "data/file_copy.txt", 
+                APR_FPROT_FILE_SOURCE_PERMS, 0, p);
+    
+    copy_helper(tc, "data/mmap_datafile.txt", "data/file_copy.txt", 
+                APR_FPROT_FILE_SOURCE_PERMS, 0, p);
+  
+    rv = apr_file_remove("data/file_copy.txt", p);
+    APR_ASSERT_SUCCESS(tc, "Couldn't remove copy file", rv);
+}
+
+static void append_nonexist(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+
+    /* make absolutely sure that the dest file doesn't exist. */
+    apr_file_remove("data/file_copy.txt", p);
+
+    copy_helper(tc, "data/file_datafile.txt", "data/file_copy.txt", 
+                APR_FPROT_FILE_SOURCE_PERMS, 0, p);
+    rv = apr_file_remove("data/file_copy.txt", p);
+    APR_ASSERT_SUCCESS(tc, "Couldn't remove copy file", rv);
+}
+
+static void append_exist(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    
+    /* make absolutely sure that the dest file doesn't exist. */
+    apr_file_remove("data/file_copy.txt", p);
+    
+    /* This is a cheat.  I don't want to create a new file, so I just copy
+     * one file, then I copy another.  If the second copy succeeds, then
+     * this works.
+     */
+    copy_helper(tc, "data/file_datafile.txt", "data/file_copy.txt", 
+                APR_FPROT_FILE_SOURCE_PERMS, 0, p);
+    
+    copy_helper(tc, "data/mmap_datafile.txt", "data/file_copy.txt", 
+                APR_FPROT_FILE_SOURCE_PERMS, 1, p);
+  
+    rv = apr_file_remove("data/file_copy.txt", p);
+    APR_ASSERT_SUCCESS(tc, "Couldn't remove copy file", rv);
+}
+
+abts_suite *testfilecopy(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite)
+
+    abts_run_test(suite, copy_short_file, NULL);
+    abts_run_test(suite, copy_over_existing, NULL);
+
+    abts_run_test(suite, append_nonexist, NULL);
+    abts_run_test(suite, append_exist, NULL);
+
+    return suite;
+}
+
diff --git a/test/testfileinfo.c b/test/testfileinfo.c
new file mode 100644
index 00000000000..ce3f461fc48
--- /dev/null
+++ b/test/testfileinfo.c
@@ -0,0 +1,263 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_file_io.h"
+#include "apr_file_info.h"
+#include "apr_strings.h"
+#include "apr_errno.h"
+#include "apr_general.h"
+#include "apr_poll.h"
+#include "apr_lib.h"
+#include "testutil.h"
+
+#define FILENAME "data/file_datafile.txt"
+#define NEWFILENAME "data/new_datafile.txt"
+#define NEWFILEDATA "This is new text in a new file."
+
+static const struct view_fileinfo
+{
+    apr_int32_t bits;
+    char *description;
+} vfi[] = {
+    {APR_FINFO_MTIME,  "MTIME"},
+    {APR_FINFO_CTIME,  "CTIME"},
+    {APR_FINFO_ATIME,  "ATIME"},
+    {APR_FINFO_SIZE,   "SIZE"},
+    {APR_FINFO_DEV,    "DEV"},
+    {APR_FINFO_INODE,  "INODE"},
+    {APR_FINFO_NLINK,  "NLINK"},
+    {APR_FINFO_TYPE,   "TYPE"},
+    {APR_FINFO_USER,   "USER"}, 
+    {APR_FINFO_GROUP,  "GROUP"}, 
+    {APR_FINFO_UPROT,  "UPROT"}, 
+    {APR_FINFO_GPROT,  "GPROT"},
+    {APR_FINFO_WPROT,  "WPROT"},
+    {0,                NULL}
+}; 
+
+static void finfo_equal(abts_case *tc, apr_finfo_t *f1, apr_finfo_t *f2)
+{
+    /* Minimum supported flags across all platforms (APR_FINFO_MIN) */
+    ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo must return APR_FINFO_TYPE",
+             (f1->valid & f2->valid & APR_FINFO_TYPE));
+    ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in filetype",
+             f1->filetype == f2->filetype);
+    ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo must return APR_FINFO_SIZE",
+             (f1->valid & f2->valid & APR_FINFO_SIZE));
+    ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in size",
+             f1->size == f2->size);
+    ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo must return APR_FINFO_ATIME",
+             (f1->valid & f2->valid & APR_FINFO_ATIME));
+    ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in atime",
+             f1->atime == f2->atime);
+    ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo must return APR_FINFO_MTIME",
+             (f1->valid & f2->valid & APR_FINFO_MTIME));
+    ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in mtime",
+             f1->mtime == f2->mtime);
+    ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo must return APR_FINFO_CTIME",
+             (f1->valid & f2->valid & APR_FINFO_CTIME));
+    ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in ctime",
+             f1->ctime == f2->ctime);
+
+    if (f1->valid & f2->valid & APR_FINFO_NAME)
+        ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in name",
+                 !strcmp(f1->name, f2->name));
+    if (f1->fname && f2->fname)
+        ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in fname",
+                 !strcmp(f1->fname, f2->fname));
+
+    /* Additional supported flags not supported on all platforms */
+    if (f1->valid & f2->valid & APR_FINFO_USER)
+        ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in user",
+                 !apr_uid_compare(f1->user, f2->user));
+    if (f1->valid & f2->valid & APR_FINFO_GROUP)
+        ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in group",
+                 !apr_gid_compare(f1->group, f2->group));
+    if (f1->valid & f2->valid & APR_FINFO_INODE)
+        ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in inode",
+                 f1->inode == f2->inode);
+    if (f1->valid & f2->valid & APR_FINFO_DEV)
+        ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in device",
+                 f1->device == f2->device);
+    if (f1->valid & f2->valid & APR_FINFO_NLINK)
+        ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in nlink",
+                 f1->nlink == f2->nlink);
+    if (f1->valid & f2->valid & APR_FINFO_CSIZE)
+        ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in csize",
+                 f1->csize == f2->csize);
+    if (f1->valid & f2->valid & APR_FINFO_PROT)
+        ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in protection",
+                 f1->protection == f2->protection);
+}
+
+static void test_info_get(abts_case *tc, void *data)
+{
+    apr_file_t *thefile;
+    apr_finfo_t finfo;
+    apr_status_t rv;
+
+    rv = apr_file_open(&thefile, FILENAME, APR_FOPEN_READ, APR_FPROT_OS_DEFAULT, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_file_info_get(&finfo, APR_FINFO_NORM, thefile);
+    if (APR_STATUS_IS_INCOMPLETE(rv)) {
+        char *str;
+	int i;
+        str = apr_pstrdup(p, "APR_INCOMPLETE:  Missing ");
+        for (i = 0; vfi[i].bits; ++i) {
+            if (vfi[i].bits & ~finfo.valid) {
+                str = apr_pstrcat(p, str, vfi[i].description, " ", NULL);
+            }
+        }
+        ABTS_FAIL(tc, str);
+    }
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    apr_file_close(thefile);
+}
+
+static void test_stat(abts_case *tc, void *data)
+{
+    apr_finfo_t finfo;
+    apr_status_t rv;
+
+    rv = apr_stat(&finfo, FILENAME, APR_FINFO_NORM, p);
+    if (APR_STATUS_IS_INCOMPLETE(rv)) {
+        char *str;
+	int i;
+        str = apr_pstrdup(p, "APR_INCOMPLETE:  Missing ");
+        for (i = 0; vfi[i].bits; ++i) {
+            if (vfi[i].bits & ~finfo.valid) {
+                str = apr_pstrcat(p, str, vfi[i].description, " ", NULL);
+            }
+        }
+        ABTS_FAIL(tc, str);
+    }
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+}
+
+static void test_stat_eq_finfo(abts_case *tc, void *data)
+{
+    apr_file_t *thefile;
+    apr_finfo_t finfo;
+    apr_finfo_t stat_finfo;
+    apr_status_t rv;
+
+    rv = apr_file_open(&thefile, FILENAME, APR_FOPEN_READ, APR_FPROT_OS_DEFAULT, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    rv = apr_file_info_get(&finfo, APR_FINFO_NORM, thefile);
+
+    /* Opening the file may have toggled the atime member (time last
+     * accessed), so fetch our apr_stat() after getting the fileinfo 
+     * of the open file...
+     */
+    rv = apr_stat(&stat_finfo, FILENAME, APR_FINFO_NORM, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    apr_file_close(thefile);
+
+    finfo_equal(tc, &stat_finfo, &finfo);
+}
+
+static void test_buffered_write_size(abts_case *tc, void *data)
+{
+    const apr_size_t data_len = strlen(NEWFILEDATA);
+    apr_file_t *thefile;
+    apr_finfo_t finfo;
+    apr_status_t rv;
+    apr_size_t bytes;
+
+    rv = apr_file_open(&thefile, NEWFILENAME,
+                       APR_FOPEN_READ | APR_FOPEN_WRITE | APR_FOPEN_CREATE | APR_FOPEN_TRUNCATE
+                       | APR_FOPEN_BUFFERED | APR_FOPEN_DELONCLOSE,
+                       APR_FPROT_OS_DEFAULT, p);
+    APR_ASSERT_SUCCESS(tc, "open file", rv);
+
+    /* A funny thing happened to me the other day: I wrote something
+     * into a buffered file, then asked for its size using
+     * apr_file_info_get; and guess what? The size was 0! That's not a
+     * nice way to behave.
+     */
+    bytes = data_len;
+    rv = apr_file_write(thefile, NEWFILEDATA, &bytes);
+    APR_ASSERT_SUCCESS(tc, "write file contents", rv);
+    ABTS_TRUE(tc, data_len == bytes);
+
+    rv = apr_file_info_get(&finfo, APR_FINFO_SIZE, thefile);
+    APR_ASSERT_SUCCESS(tc, "get file size", rv);
+    ABTS_TRUE(tc, bytes == (apr_size_t) finfo.size);
+    apr_file_close(thefile);
+}
+
+static void test_mtime_set(abts_case *tc, void *data)
+{
+    apr_file_t *thefile;
+    apr_finfo_t finfo;
+    apr_time_t epoch = 0;
+    apr_status_t rv;
+
+    /* This test sort of depends on the system clock being at least
+     * marginally ccorrect; We'll be setting the modification time to
+     * the epoch.
+     */
+    rv = apr_file_open(&thefile, NEWFILENAME,
+                       APR_FOPEN_READ | APR_FOPEN_WRITE | APR_FOPEN_CREATE | APR_FOPEN_TRUNCATE
+                       | APR_FOPEN_BUFFERED | APR_FOPEN_DELONCLOSE,
+                       APR_FPROT_OS_DEFAULT, p);
+    APR_ASSERT_SUCCESS(tc, "open file", rv);
+
+    /* Check that the current mtime is not the epoch */
+    rv = apr_stat(&finfo, NEWFILENAME, APR_FINFO_MTIME, p);
+    if (APR_STATUS_IS_INCOMPLETE(rv)) {
+        char *str;
+	int i;
+        str = apr_pstrdup(p, "APR_INCOMPLETE:  Missing ");
+        for (i = 0; vfi[i].bits; ++i) {
+            if (vfi[i].bits & ~finfo.valid) {
+                str = apr_pstrcat(p, str, vfi[i].description, " ", NULL);
+            }
+        }
+        ABTS_FAIL(tc, str);
+    }
+    APR_ASSERT_SUCCESS(tc, "get initial mtime", rv);
+    ABTS_TRUE(tc, finfo.mtime != epoch);
+
+    /* Reset the mtime to the epoch and verify the result.
+     * Note: we blindly assume that if the first apr_stat succeeded,
+     * the second one will, too.
+     */
+    rv = apr_file_mtime_set(NEWFILENAME, epoch, p);
+    APR_ASSERT_SUCCESS(tc, "set mtime", rv);
+
+    rv = apr_stat(&finfo, NEWFILENAME, APR_FINFO_MTIME, p);
+    APR_ASSERT_SUCCESS(tc, "get modified mtime", rv);
+    ABTS_TRUE(tc, finfo.mtime == epoch);
+
+    apr_file_close(thefile);
+}
+
+abts_suite *testfileinfo(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite)
+
+    abts_run_test(suite, test_info_get, NULL);
+    abts_run_test(suite, test_stat, NULL);
+    abts_run_test(suite, test_stat_eq_finfo, NULL);
+    abts_run_test(suite, test_buffered_write_size, NULL);
+    abts_run_test(suite, test_mtime_set, NULL);
+
+    return suite;
+}
+
diff --git a/test/testflock.c b/test/testflock.c
new file mode 100644
index 00000000000..2cf9f358ea1
--- /dev/null
+++ b/test/testflock.c
@@ -0,0 +1,104 @@
+/* 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 "testflock.h"
+#include "testutil.h"
+#include "apr_pools.h"
+#include "apr_thread_proc.h"
+#include "apr_file_io.h"
+#include "apr_file_info.h"
+#include "apr_general.h"
+#include "apr_strings.h"
+
+static int launch_reader(abts_case *tc)
+{
+    apr_proc_t proc = {0};
+    apr_procattr_t *procattr;
+    const char *args[2];
+    apr_status_t rv;
+    apr_exit_why_e why;
+    int exitcode;
+
+    rv = apr_procattr_create(&procattr, p);
+    APR_ASSERT_SUCCESS(tc, "Couldn't create procattr", rv);
+
+    rv = apr_procattr_io_set(procattr, APR_NO_PIPE, APR_NO_PIPE,
+            APR_NO_PIPE);
+    APR_ASSERT_SUCCESS(tc, "Couldn't set io in procattr", rv);
+
+    rv = apr_procattr_cmdtype_set(procattr, APR_PROGRAM_ENV);
+    APR_ASSERT_SUCCESS(tc, "Couldn't set copy environment", rv);
+
+    rv = apr_procattr_error_check_set(procattr, 1);
+    APR_ASSERT_SUCCESS(tc, "Couldn't set error check in procattr", rv);
+
+    args[0] = "tryread" EXTENSION;
+    args[1] = NULL;
+    rv = apr_proc_create(&proc, TESTBINPATH "tryread" EXTENSION, args, NULL, procattr, p);
+    APR_ASSERT_SUCCESS(tc, "Couldn't launch program", rv);
+
+    ABTS_ASSERT(tc, "wait for child process",
+            apr_proc_wait(&proc, &exitcode, &why, APR_WAIT) == APR_CHILD_DONE);
+
+    ABTS_ASSERT(tc, "child terminated normally", why == APR_PROC_EXIT);
+    return exitcode;
+}
+
+static void test_withlock(abts_case *tc, void *data)
+{
+    apr_file_t *file;
+    apr_status_t rv;
+    int code;
+    
+    rv = apr_file_open(&file, TESTFILE, APR_FOPEN_WRITE|APR_FOPEN_CREATE,
+                       APR_FPROT_OS_DEFAULT, p);
+    APR_ASSERT_SUCCESS(tc, "Could not create file.", rv);
+    ABTS_PTR_NOTNULL(tc, file);
+
+    rv = apr_file_lock(file, APR_FLOCK_EXCLUSIVE);
+    APR_ASSERT_SUCCESS(tc, "Could not lock the file.", rv);
+    ABTS_PTR_NOTNULL(tc, file);
+
+    code = launch_reader(tc);
+    ABTS_INT_EQUAL(tc, FAILED_READ, code);
+
+    (void) apr_file_close(file);
+}
+
+static void test_withoutlock(abts_case *tc, void *data)
+{
+    int code;
+    
+    code = launch_reader(tc);
+    ABTS_INT_EQUAL(tc, SUCCESSFUL_READ, code);
+}
+
+static void remove_lockfile(abts_case *tc, void *data)
+{
+    APR_ASSERT_SUCCESS(tc, "Couldn't remove lock file.",
+                       apr_file_remove(TESTFILE, p));
+}
+    
+abts_suite *testflock(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite)
+
+    abts_run_test(suite, test_withlock, NULL);
+    abts_run_test(suite, test_withoutlock, NULL);
+    abts_run_test(suite, remove_lockfile, NULL);
+
+    return suite;
+}
diff --git a/test/testflock.h b/test/testflock.h
new file mode 100644
index 00000000000..554a0ce5649
--- /dev/null
+++ b/test/testflock.h
@@ -0,0 +1,27 @@
+/* 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 TESTFLOCK
+#define TESTFLOCK
+
+#define TESTFILE "data/testfile.lock"
+
+#define FAILED_READ      0
+#define SUCCESSFUL_READ  1
+#define UNEXPECTED_ERROR 2
+
+#endif
+
diff --git a/test/testfmt.c b/test/testfmt.c
new file mode 100644
index 00000000000..5b066ddb439
--- /dev/null
+++ b/test/testfmt.c
@@ -0,0 +1,166 @@
+/* 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 "testutil.h"
+#include "apr.h"
+#include "apr_portable.h"
+#include "apr_strings.h"
+
+static void ssize_t_fmt(abts_case *tc, void *data)
+{
+    char buf[100];
+    apr_ssize_t var = 0;
+
+    sprintf(buf, "%" APR_SSIZE_T_FMT, var);
+    ABTS_STR_EQUAL(tc, "0", buf);
+    apr_snprintf(buf, sizeof(buf), "%" APR_SSIZE_T_FMT, var);
+    ABTS_STR_EQUAL(tc, "0", buf);
+}
+
+static void size_t_fmt(abts_case *tc, void *data)
+{
+    char buf[100];
+    apr_size_t var = 0;
+
+    sprintf(buf, "%" APR_SIZE_T_FMT, var);
+    ABTS_STR_EQUAL(tc, "0", buf);
+    apr_snprintf(buf, sizeof(buf), "%" APR_SIZE_T_FMT, var);
+    ABTS_STR_EQUAL(tc, "0", buf);
+}
+
+static void time_t_fmt(abts_case *tc, void *data)
+{
+    char buf[100];
+    apr_time_t var = 1;
+
+    sprintf(buf, "%" APR_TIME_T_FMT, var);
+    ABTS_STR_EQUAL(tc, "1", buf);
+    apr_snprintf(buf, sizeof(buf), "%" APR_TIME_T_FMT, var);
+    ABTS_STR_EQUAL(tc, "1", buf);
+}
+
+static void off_t_fmt(abts_case *tc, void *data)
+{
+    char buf[100];
+    apr_off_t var = 0;
+
+    sprintf(buf, "%" APR_OFF_T_FMT, var);
+    ABTS_STR_EQUAL(tc, "0", buf);
+    apr_snprintf(buf, sizeof(buf), "%" APR_OFF_T_FMT, var);
+    ABTS_STR_EQUAL(tc, "0", buf);
+}
+
+static void pid_t_fmt(abts_case *tc, void *data)
+{
+    char buf[100];
+    pid_t var = 0;
+
+    sprintf(buf, "%" APR_PID_T_FMT, var);
+    ABTS_STR_EQUAL(tc, "0", buf);
+    apr_snprintf(buf, sizeof(buf), "%" APR_PID_T_FMT, var);
+    ABTS_STR_EQUAL(tc, "0", buf);
+}
+
+static void int64_t_fmt(abts_case *tc, void *data)
+{
+    char buf[100];
+    apr_int64_t var = 0;
+
+    sprintf(buf, "%" APR_INT64_T_FMT, var);
+    ABTS_STR_EQUAL(tc, "0", buf);
+    apr_snprintf(buf, sizeof(buf), "%" APR_INT64_T_FMT, var);
+    ABTS_STR_EQUAL(tc, "0", buf);
+}
+
+static void uint64_t_fmt(abts_case *tc, void *data)
+{
+    char buf[100];
+    apr_uint64_t var = APR_UINT64_C(14000000);
+
+    sprintf(buf, "%" APR_UINT64_T_FMT, var);
+    ABTS_STR_EQUAL(tc, "14000000", buf);
+    apr_snprintf(buf, sizeof(buf), "%" APR_UINT64_T_FMT, var);
+    ABTS_STR_EQUAL(tc, "14000000", buf);
+}
+
+static void uint64_t_hex_fmt(abts_case *tc, void *data)
+{
+    char buf[100];
+    apr_uint64_t var = APR_UINT64_C(14000000);
+
+    sprintf(buf, "%" APR_UINT64_T_HEX_FMT, var);
+    ABTS_STR_EQUAL(tc, "d59f80", buf);
+    apr_snprintf(buf, sizeof(buf), "%" APR_UINT64_T_HEX_FMT, var);
+    ABTS_STR_EQUAL(tc, "d59f80", buf);
+}
+
+static void more_int64_fmts(abts_case *tc, void *data)
+{
+    char buf[100];
+    apr_int64_t i = APR_INT64_C(-42);
+    apr_int64_t ibig = APR_INT64_C(-314159265358979323);
+    apr_uint64_t ui = APR_UINT64_C(42);
+    apr_uint64_t big = APR_UINT64_C(10267677267010969076);
+
+    apr_snprintf(buf, sizeof buf, "%" APR_INT64_T_FMT, i);
+    ABTS_STR_EQUAL(tc, "-42", buf);
+
+    apr_snprintf(buf, sizeof buf, "%" APR_UINT64_T_FMT, ui);
+    ABTS_STR_EQUAL(tc, "42", buf);
+
+    apr_snprintf(buf, sizeof buf, "%" APR_UINT64_T_FMT, big);
+    ABTS_STR_EQUAL(tc, "10267677267010969076", buf);
+
+    apr_snprintf(buf, sizeof buf, "%" APR_INT64_T_FMT, ibig);
+    ABTS_STR_EQUAL(tc, "-314159265358979323", buf);
+}
+
+static void error_fmt(abts_case *tc, void *data)
+{
+    char ebuf[150], sbuf[150], *s;
+    apr_status_t rv;
+
+    rv = APR_SUCCESS;
+    apr_strerror(rv, ebuf, sizeof ebuf);
+    apr_snprintf(sbuf, sizeof sbuf, "%pm", &rv);
+    ABTS_STR_EQUAL(tc, sbuf, ebuf);
+
+    rv = APR_ENOTIMPL;
+    s = apr_pstrcat(p, "foo-",
+                    apr_strerror(rv, ebuf, sizeof ebuf),
+                    "-bar", NULL);
+    apr_snprintf(sbuf, sizeof sbuf, "foo-%pm-bar", &rv);
+    ABTS_STR_EQUAL(tc, sbuf, s);
+}
+
+abts_suite *testfmt(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite)
+
+    abts_run_test(suite, ssize_t_fmt, NULL);
+    abts_run_test(suite, size_t_fmt, NULL);
+    abts_run_test(suite, time_t_fmt, NULL);
+    abts_run_test(suite, off_t_fmt, NULL);
+    abts_run_test(suite, pid_t_fmt, NULL);
+    abts_run_test(suite, int64_t_fmt, NULL);
+    abts_run_test(suite, uint64_t_fmt, NULL);
+    abts_run_test(suite, uint64_t_hex_fmt, NULL);
+    abts_run_test(suite, more_int64_fmts, NULL);
+    abts_run_test(suite, error_fmt, NULL);
+
+    return suite;
+}
+
diff --git a/test/testfnmatch.c b/test/testfnmatch.c
new file mode 100644
index 00000000000..1d1c0315dbd
--- /dev/null
+++ b/test/testfnmatch.c
@@ -0,0 +1,256 @@
+/* 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 "testutil.h"
+#include "apr_file_info.h"
+#include "apr_fnmatch.h"
+#include "apr_tables.h"
+
+/* XXX NUM_FILES must be equal to the nummber of expected files with a
+ * .txt extension in the data directory at the time testfnmatch
+ * happens to be run (!?!). */
+
+#define NUM_FILES (10)
+
+#define APR_FNM_BITS    15
+#define APR_FNM_FAILBIT 256
+
+#define FAILS_IF(X)     0, X
+#define SUCCEEDS_IF(X)  X, 256
+#define SUCCEEDS        0, 256
+#define FAILS           256, 0
+
+static struct pattern_s {
+    const char *pattern;
+    const char *string;
+    int         require_flags;
+    int         fail_flags;
+} patterns[] = {
+
+/*   Pattern,  String to Test,          Flags to Match  */
+    {"", "test",                        FAILS},
+    {"", "*",                           FAILS},
+    {"test", "*",                       FAILS},
+    {"test", "test",                    SUCCEEDS},
+
+     /* Remember C '\\' is a single backslash in pattern */
+    {"te\\st", "test",                  FAILS_IF(APR_FNM_NOESCAPE)},
+    {"te\\\\st", "te\\st",              FAILS_IF(APR_FNM_NOESCAPE)},
+    {"te\\*t", "te*t",                  FAILS_IF(APR_FNM_NOESCAPE)},
+    {"te\\*t", "test",                  FAILS},
+    {"te\\?t", "te?t",                  FAILS_IF(APR_FNM_NOESCAPE)},
+    {"te\\?t", "test",                  FAILS},
+
+    {"tesT", "test",                    SUCCEEDS_IF(APR_FNM_CASE_BLIND)},
+    {"test", "Test",                    SUCCEEDS_IF(APR_FNM_CASE_BLIND)},
+    {"tEst", "teSt",                    SUCCEEDS_IF(APR_FNM_CASE_BLIND)},
+
+    {"?est", "test",                    SUCCEEDS},
+    {"te?t", "test",                    SUCCEEDS},
+    {"tes?", "test",                    SUCCEEDS},
+    {"test?", "test",                   FAILS},
+
+    {"*", "",                           SUCCEEDS},
+    {"*", "test",                       SUCCEEDS},
+    {"*test", "test",                   SUCCEEDS},
+    {"*est", "test",                    SUCCEEDS},
+    {"*st", "test",                     SUCCEEDS},
+    {"t*t", "test",                     SUCCEEDS},
+    {"te*t", "test",                    SUCCEEDS},
+    {"te*st", "test",                   SUCCEEDS},
+    {"te*", "test",                     SUCCEEDS},
+    {"tes*", "test",                    SUCCEEDS},
+    {"test*", "test",                   SUCCEEDS},
+
+    {".[\\-\\t]", ".t",                 SUCCEEDS},
+    {"test*?*[a-z]*", "testgoop",       SUCCEEDS},
+    {"te[^x]t", "test",                 SUCCEEDS},
+    {"te[^abc]t", "test",               SUCCEEDS},
+    {"te[^x]t", "test",                 SUCCEEDS},
+    {"te[!x]t", "test",                 SUCCEEDS},
+    {"te[^x]t", "text",                 FAILS},
+    {"te[^\\x]t", "text",               FAILS},
+    {"te[^x\\", "text",                 FAILS},
+    {"te[/]t", "text",                  FAILS},
+    {"te[S]t", "test",                  SUCCEEDS_IF(APR_FNM_CASE_BLIND)},
+    {"te[r-t]t", "test",                SUCCEEDS},
+    {"te[r-t]t", "teSt",                SUCCEEDS_IF(APR_FNM_CASE_BLIND)},
+    {"te[r-T]t", "test",                SUCCEEDS_IF(APR_FNM_CASE_BLIND)},
+    {"te[R-T]t", "test",                SUCCEEDS_IF(APR_FNM_CASE_BLIND)},
+    {"te[r-Tz]t", "tezt",               SUCCEEDS},
+    {"te[R-T]t", "tent",                FAILS},
+    {"tes[]t]", "test",                 SUCCEEDS},
+    {"tes[t-]", "test",                 SUCCEEDS},
+    {"tes[t-]]", "test]",               SUCCEEDS},
+    {"tes[t-]]", "test",                FAILS},
+    {"tes[u-]", "test",                 FAILS},
+    {"tes[t-]", "tes[t-]",              FAILS},
+    {"test[/-/]", "test[/-/]",          SUCCEEDS_IF(APR_FNM_PATHNAME)},
+    {"test[\\/-/]", "test[/-/]",        APR_FNM_PATHNAME, APR_FNM_NOESCAPE},
+    {"test[/-\\/]", "test[/-/]",        APR_FNM_PATHNAME, APR_FNM_NOESCAPE},
+    {"test[/-/]", "test/",              FAILS_IF(APR_FNM_PATHNAME)},
+    {"test[\\/-/]", "test/",            FAILS_IF(APR_FNM_PATHNAME)},
+    {"test[/-\\/]", "test/",            FAILS_IF(APR_FNM_PATHNAME)},
+
+    {"/", "",                           FAILS},
+    {"", "/",                           FAILS},
+    {"/test", "test",                   FAILS},
+    {"test", "/test",                   FAILS},
+    {"test/", "test",                   FAILS},
+    {"test", "test/",                   FAILS},
+    {"\\/test", "/test",                FAILS_IF(APR_FNM_NOESCAPE)},
+    {"*test", "/test",                  FAILS_IF(APR_FNM_PATHNAME)},
+    {"/*/test/", "/test",               FAILS},
+    {"/*/test/", "/test/test/",         SUCCEEDS},
+    {"test/this", "test/",              FAILS},
+    {"test/", "test/this",              FAILS},
+    {"test*/this", "test/this",         SUCCEEDS},
+    {"test*/this", "test/that",         FAILS},
+    {"test/*this", "test/this",         SUCCEEDS},
+
+    {".*", ".this",                     SUCCEEDS},
+    {"*", ".this",                      FAILS_IF(APR_FNM_PERIOD)},
+    {"?this", ".this",                  FAILS_IF(APR_FNM_PERIOD)},
+    {"[.]this", ".this",                FAILS_IF(APR_FNM_PERIOD)},
+
+    {"test/this", "test/this",          SUCCEEDS},
+    {"test?this", "test/this",          FAILS_IF(APR_FNM_PATHNAME)},
+    {"test*this", "test/this",          FAILS_IF(APR_FNM_PATHNAME)},
+    {"test[/]this", "test/this",        FAILS_IF(APR_FNM_PATHNAME)},
+
+    {"test/.*", "test/.this",           SUCCEEDS},
+    {"test/*", "test/.this",            FAILS_IF(APR_FNM_PERIOD | APR_FNM_PATHNAME)},
+    {"test/?this", "test/.this",        FAILS_IF(APR_FNM_PERIOD | APR_FNM_PATHNAME)},
+    {"test/[.]this", "test/.this",      FAILS_IF(APR_FNM_PERIOD | APR_FNM_PATHNAME)},
+
+    {NULL, NULL, 0}
+};
+
+
+
+static void test_fnmatch(abts_case *tc, void *data)
+{
+    struct pattern_s *test = patterns;
+    char buf[80];
+    int i = APR_FNM_BITS + 1;
+    int res;
+
+    for (test = patterns; test->pattern; ++test)
+    {
+        for (i = 0; i <= APR_FNM_BITS; ++i)
+        {
+            res = apr_fnmatch(test->pattern, test->string, i);
+            if (((i & test->require_flags) != test->require_flags)
+                || ((i & test->fail_flags) == test->fail_flags)) {
+                if (res != APR_FNM_NOMATCH)
+                    break;
+            }
+            else {
+                if (res != 0)
+                    break;
+            }
+        }
+        if (i <= APR_FNM_BITS)
+            break;
+    }
+
+    if (i <= APR_FNM_BITS) {
+        sprintf(buf, "apr_fnmatch(\"%s\", \"%s\", %d) returns %d\n",
+                test->pattern, test->string, i, res);
+        abts_fail(tc, buf, __LINE__);
+    }
+}
+
+static void test_fnmatch_test(abts_case *tc, void *data)
+{
+    static const struct test {
+        const char *pattern;
+        int result;
+    } ft_tests[] = {
+        { "a*b", 1 },
+        { "a?", 1 },
+        { "a\\b?", 1 },
+        { "a[b-c]", 1 },
+        { "a", 0 },
+        { "a\\", 0 },
+        { NULL, 0 }
+    };
+    const struct test *t;
+
+    for (t = ft_tests; t->pattern != NULL; t++) {
+        int res = apr_fnmatch_test(t->pattern);
+        
+        if (res != t->result) {
+            char buf[128];
+
+            sprintf(buf, "apr_fnmatch_test(\"%s\") = %d, expected %d\n",
+                    t->pattern, res, t->result);
+            abts_fail(tc, buf, __LINE__);
+        }
+    }
+}
+
+static void test_glob(abts_case *tc, void *data)
+{
+    int i;
+    char **list;
+    apr_array_header_t *result;
+    
+    APR_ASSERT_SUCCESS(tc, "glob match against data/*.txt",
+                       apr_match_glob("data\\*.txt", &result, p));
+
+    ABTS_INT_EQUAL(tc, NUM_FILES, result->nelts);
+
+    list = (char **)result->elts;
+    for (i = 0; i < result->nelts; i++) {
+        char *dot = strrchr(list[i], '.');
+        ABTS_STR_EQUAL(tc, ".txt", dot);
+    }
+}
+
+static void test_glob_currdir(abts_case *tc, void *data)
+{
+    int i;
+    char **list;
+    apr_array_header_t *result;
+    apr_filepath_set("data", p);
+    
+    APR_ASSERT_SUCCESS(tc, "glob match against *.txt with data as current",
+                       apr_match_glob("*.txt", &result, p));
+
+
+    ABTS_INT_EQUAL(tc, NUM_FILES, result->nelts);
+
+    list = (char **)result->elts;
+    for (i = 0; i < result->nelts; i++) {
+        char *dot = strrchr(list[i], '.');
+        ABTS_STR_EQUAL(tc, ".txt", dot);
+    }
+    apr_filepath_set("..", p);
+}
+
+abts_suite *testfnmatch(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite)
+
+    abts_run_test(suite, test_fnmatch, NULL);
+    abts_run_test(suite, test_fnmatch_test, NULL);
+    abts_run_test(suite, test_glob, NULL);
+    abts_run_test(suite, test_glob_currdir, NULL);
+
+    return suite;
+}
+
diff --git a/test/testglobalmutex.c b/test/testglobalmutex.c
new file mode 100644
index 00000000000..c79884cfcf5
--- /dev/null
+++ b/test/testglobalmutex.c
@@ -0,0 +1,143 @@
+/* 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 "testglobalmutex.h"
+#include "apr_thread_proc.h"
+#include "apr_global_mutex.h"
+#include "apr_strings.h"
+#include "apr_errno.h"
+#include "testutil.h"
+
+static void launch_child(abts_case *tc, apr_lockmech_e mech,
+                         apr_proc_t *proc, apr_pool_t *p)
+{
+    apr_procattr_t *procattr;
+    const char *args[3];
+    apr_status_t rv;
+
+    rv = apr_procattr_create(&procattr, p);
+    APR_ASSERT_SUCCESS(tc, "Couldn't create procattr", rv);
+
+    rv = apr_procattr_io_set(procattr, APR_NO_PIPE, APR_NO_PIPE,
+            APR_NO_PIPE);
+    APR_ASSERT_SUCCESS(tc, "Couldn't set io in procattr", rv);
+
+    rv = apr_procattr_error_check_set(procattr, 1);
+    APR_ASSERT_SUCCESS(tc, "Couldn't set error check in procattr", rv);
+
+    args[0] = "globalmutexchild" EXTENSION;
+    args[1] = (const char*)apr_itoa(p, (int)mech);
+    args[2] = NULL;
+    rv = apr_proc_create(proc, TESTBINPATH "globalmutexchild" EXTENSION, args, NULL,
+            procattr, p);
+    APR_ASSERT_SUCCESS(tc, "Couldn't launch program", rv);
+}
+
+static int wait_child(abts_case *tc, apr_proc_t *proc)
+{
+    int exitcode;
+    apr_exit_why_e why;
+
+    ABTS_ASSERT(tc, "Error waiting for child process",
+            apr_proc_wait(proc, &exitcode, &why, APR_WAIT) == APR_CHILD_DONE);
+
+    ABTS_ASSERT(tc, "child didn't terminate normally", why == APR_PROC_EXIT);
+    return exitcode;
+}
+
+/* return symbolic name for a locking meechanism */
+static const char *mutexname(apr_lockmech_e mech)
+{
+    switch (mech) {
+    case APR_LOCK_FCNTL: return "fcntl";
+    case APR_LOCK_FLOCK: return "flock";
+    case APR_LOCK_SYSVSEM: return "sysvsem";
+    case APR_LOCK_PROC_PTHREAD: return "proc_pthread";
+    case APR_LOCK_POSIXSEM: return "posixsem";
+    case APR_LOCK_DEFAULT: return "default";
+    case APR_LOCK_DEFAULT_TIMED: return "default_timed";
+    default: return "unknown";
+    }
+}
+
+static void test_exclusive(abts_case *tc, void *data)
+{
+    apr_lockmech_e mech = *(apr_lockmech_e *)data;
+    apr_proc_t p1, p2, p3, p4;
+    apr_status_t rv;
+    apr_global_mutex_t *global_lock;
+    int x = 0;
+    abts_log_message("lock mechanism is: ");
+    abts_log_message(mutexname(mech));
+ 
+    rv = apr_global_mutex_create(&global_lock, LOCKNAME, mech, p);
+    if (rv == APR_ENOTIMPL) {
+        /* MacOS lacks TIMED implementation, so don't fail for ENOTIMPL */
+        ABTS_NOT_IMPL(tc, "global mutex TIMED not implemented");
+        return;
+    }
+    APR_ASSERT_SUCCESS(tc, "Error creating mutex", rv);
+
+    launch_child(tc, mech, &p1, p);
+    launch_child(tc, mech, &p2, p);
+    launch_child(tc, mech, &p3, p);
+    launch_child(tc, mech, &p4, p);
+ 
+    x += wait_child(tc, &p1);
+    x += wait_child(tc, &p2);
+    x += wait_child(tc, &p3);
+    x += wait_child(tc, &p4);
+
+    if (x != MAX_COUNTER) {
+        char buf[200];
+        sprintf(buf, "global mutex '%s' failed: %d not %d",
+                mutexname(mech), x, MAX_COUNTER);
+        abts_fail(tc, buf, __LINE__);
+    }
+}
+
+abts_suite *testglobalmutex(abts_suite *suite)
+{
+    apr_lockmech_e mech = APR_LOCK_DEFAULT;
+
+    suite = ADD_SUITE(suite)
+    abts_run_test(suite, test_exclusive, &mech);
+#if APR_HAS_POSIXSEM_SERIALIZE
+    mech = APR_LOCK_POSIXSEM;
+    abts_run_test(suite, test_exclusive, &mech);
+#endif
+#if APR_HAS_SYSVSEM_SERIALIZE
+    mech = APR_LOCK_SYSVSEM;
+    abts_run_test(suite, test_exclusive, &mech);
+#endif
+#if APR_HAS_PROC_PTHREAD_SERIALIZE
+    mech = APR_LOCK_PROC_PTHREAD;
+    abts_run_test(suite, test_exclusive, &mech);
+#endif
+#if APR_HAS_FCNTL_SERIALIZE
+    mech = APR_LOCK_FCNTL;
+    abts_run_test(suite, test_exclusive, &mech);
+#endif
+#if APR_HAS_FLOCK_SERIALIZE
+    mech = APR_LOCK_FLOCK;
+    abts_run_test(suite, test_exclusive, &mech);
+#endif
+    mech = APR_LOCK_DEFAULT_TIMED;
+    abts_run_test(suite, test_exclusive, &mech);
+
+    return suite;
+}
+
diff --git a/test/testglobalmutex.h b/test/testglobalmutex.h
new file mode 100644
index 00000000000..027062843dc
--- /dev/null
+++ b/test/testglobalmutex.h
@@ -0,0 +1,27 @@
+/* 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 TESTGLOBALMUTEX_H
+#define TESTGLOBALMUTEX_H
+
+/* set this to 255 so that the child processes can return it successfully. */
+#define MAX_ITER 255
+#define MAX_COUNTER (MAX_ITER * 4)
+
+#define LOCKNAME "data/apr_globalmutex.lock"
+
+#endif
+
diff --git a/test/testhash.c b/test/testhash.c
new file mode 100644
index 00000000000..9dd5804b818
--- /dev/null
+++ b/test/testhash.c
@@ -0,0 +1,570 @@
+/* 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 "testutil.h"
+#include "apr.h"
+#include "apr_strings.h"
+#include "apr_general.h"
+#include "apr_pools.h"
+#include "apr_hash.h"
+
+#define MAX_LTH 256
+#define MAX_DEPTH 11
+
+static int comp_string(const void *str1, const void *str2)
+{
+    return strcmp(str1,str2);
+}
+
+static void dump_hash(apr_pool_t *p, apr_hash_t *h, char str[][MAX_LTH]) 
+{
+    apr_hash_index_t *hi;
+    int i = 0;
+
+    for (hi = apr_hash_first(p, h); hi; hi = apr_hash_next(hi)) {
+        const char *key = apr_hash_this_key(hi);
+        apr_ssize_t len = apr_hash_this_key_len(hi);
+        char *val = apr_hash_this_val(hi);
+
+        str[i][0]='\0';
+        apr_snprintf(str[i], MAX_LTH, "%sKey %s (%" APR_SSIZE_T_FMT ") Value %s\n",
+                 str[i], key, len, val);
+        i++;
+    }
+    str[i][0]='\0';
+    apr_snprintf(str[i], MAX_LTH, "%s#entries %d\n", str[i], i);
+
+    /* Sort the result strings so that they can be checked for expected results easily,
+     * without having to worry about platform quirks
+     */
+    qsort(
+        str, /* Pointer to elements */
+        i,   /* number of elements */
+        MAX_LTH, /* size of one element */
+        comp_string /* Pointer to comparison routine */
+    );
+}
+
+static void sum_hash(apr_pool_t *p, apr_hash_t *h, int *pcount, int *keySum, int *valSum) 
+{
+    apr_hash_index_t *hi;
+    void *val, *key;
+    int count = 0;
+
+    *keySum = 0;
+    *valSum = 0;
+    *pcount = 0;
+    for (hi = apr_hash_first(p, h); hi; hi = apr_hash_next(hi)) {
+        apr_hash_this(hi, (void*)&key, NULL, &val);
+        *valSum += *(int *)val;
+        *keySum += *(int *)key;
+        count++;
+    }
+    *pcount=count;
+}
+
+static void hash_make(abts_case *tc, void *data)
+{
+    apr_hash_t *h = NULL;
+
+    h = apr_hash_make(p);
+    ABTS_PTR_NOTNULL(tc, h);
+}
+
+static void hash_set(abts_case *tc, void *data)
+{
+    apr_hash_t *h = NULL;
+    char *result = NULL;
+
+    h = apr_hash_make(p);
+    ABTS_PTR_NOTNULL(tc, h);
+
+    apr_hash_set(h, "key", APR_HASH_KEY_STRING, "value");
+    result = apr_hash_get(h, "key", APR_HASH_KEY_STRING);
+    ABTS_STR_EQUAL(tc, "value", result);
+}
+
+static void hash_get_or_set(abts_case *tc, void *data)
+{
+    apr_hash_t *h = NULL;
+    char *result = NULL;
+
+    h = apr_hash_make(p);
+    ABTS_PTR_NOTNULL(tc, h);
+
+    result = apr_hash_get_or_set(h, "key", APR_HASH_KEY_STRING, "value");
+    ABTS_STR_EQUAL(tc, "value", result);
+
+    result = apr_hash_get_or_set(h, "key", APR_HASH_KEY_STRING, "other");
+    ABTS_STR_EQUAL(tc, "value", result);
+
+    result = apr_hash_get_or_set(h, "key", APR_HASH_KEY_STRING, NULL);
+    ABTS_STR_EQUAL(tc, "value", result);
+
+    apr_hash_set(h, "key", APR_HASH_KEY_STRING, NULL);
+    result = apr_hash_get(h, "key", APR_HASH_KEY_STRING);
+    ABTS_PTR_EQUAL(tc, NULL, result);
+
+    result = apr_hash_get_or_set(h, "key", APR_HASH_KEY_STRING, NULL);
+    ABTS_PTR_EQUAL(tc, NULL, result);
+
+    result = apr_hash_get_or_set(h, "key", APR_HASH_KEY_STRING, "other");
+    ABTS_STR_EQUAL(tc, "other", result);
+}
+
+static void hash_reset(abts_case *tc, void *data)
+{
+    apr_hash_t *h = NULL;
+    char *result = NULL;
+
+    h = apr_hash_make(p);
+    ABTS_PTR_NOTNULL(tc, h);
+
+    apr_hash_set(h, "key", APR_HASH_KEY_STRING, "value");
+    result = apr_hash_get(h, "key", APR_HASH_KEY_STRING);
+    ABTS_STR_EQUAL(tc, "value", result);
+
+    apr_hash_set(h, "key", APR_HASH_KEY_STRING, "new");
+    result = apr_hash_get(h, "key", APR_HASH_KEY_STRING);
+    ABTS_STR_EQUAL(tc, "new", result);
+}
+
+static void same_value(abts_case *tc, void *data)
+{
+    apr_hash_t *h = NULL;
+    char *result = NULL;
+
+    h = apr_hash_make(p);
+    ABTS_PTR_NOTNULL(tc, h);
+
+    apr_hash_set(h, "same1", APR_HASH_KEY_STRING, "same");
+    result = apr_hash_get(h, "same1", APR_HASH_KEY_STRING);
+    ABTS_STR_EQUAL(tc, "same", result);
+
+    apr_hash_set(h, "same2", APR_HASH_KEY_STRING, "same");
+    result = apr_hash_get(h, "same2", APR_HASH_KEY_STRING);
+    ABTS_STR_EQUAL(tc, "same", result);
+}
+
+static unsigned int hash_custom( const char *key, apr_ssize_t *klen)
+{
+    unsigned int hash = 0;
+    while( *klen ) {
+        (*klen) --;
+        hash = hash * 33 + key[ *klen ];
+    }
+    return hash;
+}
+
+static void same_value_custom(abts_case *tc, void *data)
+{
+    apr_hash_t *h = NULL;
+    char *result = NULL;
+
+    h = apr_hash_make_custom(p, hash_custom);
+    ABTS_PTR_NOTNULL(tc, h);
+
+    apr_hash_set(h, "same1", 5, "same");
+    result = apr_hash_get(h, "same1", 5);
+    ABTS_STR_EQUAL(tc, "same", result);
+
+    apr_hash_set(h, "same2", 5, "same");
+    result = apr_hash_get(h, "same2", 5);
+    ABTS_STR_EQUAL(tc, "same", result);
+}
+
+static void key_space(abts_case *tc, void *data)
+{
+    apr_hash_t *h = NULL;
+    char *result = NULL;
+
+    h = apr_hash_make(p);
+    ABTS_PTR_NOTNULL(tc, h);
+
+    apr_hash_set(h, "key with space", APR_HASH_KEY_STRING, "value");
+    result = apr_hash_get(h, "key with space", APR_HASH_KEY_STRING);
+    ABTS_STR_EQUAL(tc, "value", result);
+}
+
+static void hash_clear(abts_case *tc, void *data)
+{
+    apr_hash_t *h;
+    int i, *e;
+
+    h = apr_hash_make(p);
+    ABTS_PTR_NOTNULL(tc, h);
+
+    for (i = 1; i <= 10; i++) {
+        e = apr_palloc(p, sizeof(int));
+        *e = i;
+        apr_hash_set(h, e, sizeof(*e), e);
+    }
+    apr_hash_clear(h);
+    i = apr_hash_count(h);
+    ABTS_INT_EQUAL(tc, 0, i);
+}
+
+/* This is kind of a hack, but I am just keeping an existing test.  This is
+ * really testing apr_hash_first, apr_hash_next, and apr_hash_this which 
+ * should be tested in three separate tests, but this will do for now.
+ */
+static void hash_traverse(abts_case *tc, void *data)
+{
+    apr_hash_t *h;
+    char StrArray[MAX_DEPTH][MAX_LTH];
+
+    h = apr_hash_make(p);
+    ABTS_PTR_NOTNULL(tc, h);
+
+    apr_hash_set(h, "OVERWRITE", APR_HASH_KEY_STRING, "should not see this");
+    apr_hash_set(h, "FOO3", APR_HASH_KEY_STRING, "bar3");
+    apr_hash_set(h, "FOO3", APR_HASH_KEY_STRING, "bar3");
+    apr_hash_set(h, "FOO1", APR_HASH_KEY_STRING, "bar1");
+    apr_hash_set(h, "FOO2", APR_HASH_KEY_STRING, "bar2");
+    apr_hash_set(h, "FOO4", APR_HASH_KEY_STRING, "bar4");
+    apr_hash_set(h, "SAME1", APR_HASH_KEY_STRING, "same");
+    apr_hash_set(h, "SAME2", APR_HASH_KEY_STRING, "same");
+    apr_hash_set(h, "OVERWRITE", APR_HASH_KEY_STRING, "Overwrite key");
+
+    dump_hash(p, h, StrArray);
+
+    ABTS_STR_EQUAL(tc, "Key FOO1 (4) Value bar1\n", StrArray[0]);
+    ABTS_STR_EQUAL(tc, "Key FOO2 (4) Value bar2\n", StrArray[1]);
+    ABTS_STR_EQUAL(tc, "Key FOO3 (4) Value bar3\n", StrArray[2]);
+    ABTS_STR_EQUAL(tc, "Key FOO4 (4) Value bar4\n", StrArray[3]);
+    ABTS_STR_EQUAL(tc, "Key OVERWRITE (9) Value Overwrite key\n", StrArray[4]);
+    ABTS_STR_EQUAL(tc, "Key SAME1 (5) Value same\n", StrArray[5]);
+    ABTS_STR_EQUAL(tc, "Key SAME2 (5) Value same\n", StrArray[6]);
+    ABTS_STR_EQUAL(tc, "#entries 7\n", StrArray[7]);
+}
+
+/* This is kind of a hack, but I am just keeping an existing test.  This is
+ * really testing apr_hash_first, apr_hash_next, and apr_hash_this which 
+ * should be tested in three separate tests, but this will do for now.
+ */
+static void summation_test(abts_case *tc, void *data)
+{
+    apr_hash_t *h;
+    int sumKeys, sumVal, trySumKey, trySumVal;
+    int i, j, *val, *key;
+
+    h =apr_hash_make(p);
+    ABTS_PTR_NOTNULL(tc, h);
+
+    sumKeys = 0;
+    sumVal = 0;
+    trySumKey = 0;
+    trySumVal = 0;
+
+    for (i = 0; i < 100; i++) {
+        j = i * 10 + 1;
+        sumKeys += j;
+        sumVal += i;
+        key = apr_palloc(p, sizeof(int));
+        *key = j;
+        val = apr_palloc(p, sizeof(int));
+        *val = i;
+        apr_hash_set(h, key, sizeof(int), val);
+    }
+
+    sum_hash(p, h, &i, &trySumKey, &trySumVal);
+    ABTS_INT_EQUAL(tc, 100, i);
+    ABTS_INT_EQUAL(tc, sumVal, trySumVal);
+    ABTS_INT_EQUAL(tc, sumKeys, trySumKey);
+}
+
+static void delete_key(abts_case *tc, void *data)
+{
+    apr_hash_t *h = NULL;
+    char *result = NULL;
+
+    h = apr_hash_make(p);
+    ABTS_PTR_NOTNULL(tc, h);
+
+    apr_hash_set(h, "key", APR_HASH_KEY_STRING, "value");
+    apr_hash_set(h, "key2", APR_HASH_KEY_STRING, "value2");
+
+    result = apr_hash_get(h, "key", APR_HASH_KEY_STRING);
+    ABTS_STR_EQUAL(tc, "value", result);
+
+    result = apr_hash_get(h, "key2", APR_HASH_KEY_STRING);
+    ABTS_STR_EQUAL(tc, "value2", result);
+
+    apr_hash_set(h, "key", APR_HASH_KEY_STRING, NULL);
+
+    result = apr_hash_get(h, "key", APR_HASH_KEY_STRING);
+    ABTS_PTR_EQUAL(tc, NULL, result);
+
+    result = apr_hash_get(h, "key2", APR_HASH_KEY_STRING);
+    ABTS_STR_EQUAL(tc, "value2", result);
+}
+
+static void hash_count_0(abts_case *tc, void *data)
+{
+    apr_hash_t *h = NULL;
+    int count;
+
+    h = apr_hash_make(p);
+    ABTS_PTR_NOTNULL(tc, h);
+
+    count = apr_hash_count(h);
+    ABTS_INT_EQUAL(tc, 0, count);
+}
+
+static void hash_count_1(abts_case *tc, void *data)
+{
+    apr_hash_t *h = NULL;
+    int count;
+
+    h = apr_hash_make(p);
+    ABTS_PTR_NOTNULL(tc, h);
+
+    apr_hash_set(h, "key", APR_HASH_KEY_STRING, "value");
+
+    count = apr_hash_count(h);
+    ABTS_INT_EQUAL(tc, 1, count);
+}
+
+static void hash_count_5(abts_case *tc, void *data)
+{
+    apr_hash_t *h = NULL;
+    int count;
+
+    h = apr_hash_make(p);
+    ABTS_PTR_NOTNULL(tc, h);
+
+    apr_hash_set(h, "key1", APR_HASH_KEY_STRING, "value1");
+    apr_hash_set(h, "key2", APR_HASH_KEY_STRING, "value2");
+    apr_hash_set(h, "key3", APR_HASH_KEY_STRING, "value3");
+    apr_hash_set(h, "key4", APR_HASH_KEY_STRING, "value4");
+    apr_hash_set(h, "key5", APR_HASH_KEY_STRING, "value5");
+
+    count = apr_hash_count(h);
+    ABTS_INT_EQUAL(tc, 5, count);
+}
+
+static void overlay_empty(abts_case *tc, void *data)
+{
+    apr_hash_t *base = NULL;
+    apr_hash_t *overlay = NULL;
+    apr_hash_t *result = NULL;
+    int count;
+    char StrArray[MAX_DEPTH][MAX_LTH];
+
+    base = apr_hash_make(p);
+    overlay = apr_hash_make(p);
+    ABTS_PTR_NOTNULL(tc, base);
+    ABTS_PTR_NOTNULL(tc, overlay);
+
+    apr_hash_set(base, "key1", APR_HASH_KEY_STRING, "value1");
+    apr_hash_set(base, "key2", APR_HASH_KEY_STRING, "value2");
+    apr_hash_set(base, "key3", APR_HASH_KEY_STRING, "value3");
+    apr_hash_set(base, "key4", APR_HASH_KEY_STRING, "value4");
+    apr_hash_set(base, "key5", APR_HASH_KEY_STRING, "value5");
+
+    result = apr_hash_overlay(p, overlay, base);
+
+    count = apr_hash_count(result);
+    ABTS_INT_EQUAL(tc, 5, count);
+
+    dump_hash(p, result, StrArray);
+
+    ABTS_STR_EQUAL(tc, "Key key1 (4) Value value1\n", StrArray[0]);
+    ABTS_STR_EQUAL(tc, "Key key2 (4) Value value2\n", StrArray[1]);
+    ABTS_STR_EQUAL(tc, "Key key3 (4) Value value3\n", StrArray[2]);
+    ABTS_STR_EQUAL(tc, "Key key4 (4) Value value4\n", StrArray[3]);
+    ABTS_STR_EQUAL(tc, "Key key5 (4) Value value5\n", StrArray[4]);
+    ABTS_STR_EQUAL(tc, "#entries 5\n", StrArray[5]);
+}
+
+static void overlay_2unique(abts_case *tc, void *data)
+{
+    apr_hash_t *base = NULL;
+    apr_hash_t *overlay = NULL;
+    apr_hash_t *result = NULL;
+    int count;
+    char StrArray[MAX_DEPTH][MAX_LTH];
+
+    base = apr_hash_make(p);
+    overlay = apr_hash_make(p);
+    ABTS_PTR_NOTNULL(tc, base);
+    ABTS_PTR_NOTNULL(tc, overlay);
+
+    apr_hash_set(base, "base1", APR_HASH_KEY_STRING, "value1");
+    apr_hash_set(base, "base2", APR_HASH_KEY_STRING, "value2");
+    apr_hash_set(base, "base3", APR_HASH_KEY_STRING, "value3");
+    apr_hash_set(base, "base4", APR_HASH_KEY_STRING, "value4");
+    apr_hash_set(base, "base5", APR_HASH_KEY_STRING, "value5");
+
+    apr_hash_set(overlay, "overlay1", APR_HASH_KEY_STRING, "value1");
+    apr_hash_set(overlay, "overlay2", APR_HASH_KEY_STRING, "value2");
+    apr_hash_set(overlay, "overlay3", APR_HASH_KEY_STRING, "value3");
+    apr_hash_set(overlay, "overlay4", APR_HASH_KEY_STRING, "value4");
+    apr_hash_set(overlay, "overlay5", APR_HASH_KEY_STRING, "value5");
+
+    result = apr_hash_overlay(p, overlay, base);
+
+    count = apr_hash_count(result);
+    ABTS_INT_EQUAL(tc, 10, count);
+
+    dump_hash(p, result, StrArray);
+
+    ABTS_STR_EQUAL(tc, "Key base1 (5) Value value1\n", StrArray[0]);
+    ABTS_STR_EQUAL(tc, "Key base2 (5) Value value2\n", StrArray[1]);
+    ABTS_STR_EQUAL(tc, "Key base3 (5) Value value3\n", StrArray[2]);
+    ABTS_STR_EQUAL(tc, "Key base4 (5) Value value4\n", StrArray[3]);
+    ABTS_STR_EQUAL(tc, "Key base5 (5) Value value5\n", StrArray[4]);
+    ABTS_STR_EQUAL(tc, "Key overlay1 (8) Value value1\n", StrArray[5]);
+    ABTS_STR_EQUAL(tc, "Key overlay2 (8) Value value2\n", StrArray[6]);
+    ABTS_STR_EQUAL(tc, "Key overlay3 (8) Value value3\n", StrArray[7]);
+    ABTS_STR_EQUAL(tc, "Key overlay4 (8) Value value4\n", StrArray[8]);
+    ABTS_STR_EQUAL(tc, "Key overlay5 (8) Value value5\n", StrArray[9]);
+    ABTS_STR_EQUAL(tc, "#entries 10\n", StrArray[10]);
+}
+
+static void overlay_same(abts_case *tc, void *data)
+{
+    apr_hash_t *base = NULL;
+    apr_hash_t *result = NULL;
+    int count;
+    char StrArray[MAX_DEPTH][MAX_LTH];
+
+    base = apr_hash_make(p);
+    ABTS_PTR_NOTNULL(tc, base);
+
+    apr_hash_set(base, "base1", APR_HASH_KEY_STRING, "value1");
+    apr_hash_set(base, "base2", APR_HASH_KEY_STRING, "value2");
+    apr_hash_set(base, "base3", APR_HASH_KEY_STRING, "value3");
+    apr_hash_set(base, "base4", APR_HASH_KEY_STRING, "value4");
+    apr_hash_set(base, "base5", APR_HASH_KEY_STRING, "value5");
+
+    result = apr_hash_overlay(p, base, base);
+
+    count = apr_hash_count(result);
+    ABTS_INT_EQUAL(tc, 5, count);
+
+    dump_hash(p, result, StrArray);
+
+    ABTS_STR_EQUAL(tc, "Key base1 (5) Value value1\n", StrArray[0]);
+    ABTS_STR_EQUAL(tc, "Key base2 (5) Value value2\n", StrArray[1]);
+    ABTS_STR_EQUAL(tc, "Key base3 (5) Value value3\n", StrArray[2]);
+    ABTS_STR_EQUAL(tc, "Key base4 (5) Value value4\n", StrArray[3]);
+    ABTS_STR_EQUAL(tc, "Key base5 (5) Value value5\n", StrArray[4]);
+    ABTS_STR_EQUAL(tc, "#entries 5\n", StrArray[5]);
+}
+
+static void overlay_fetch(abts_case *tc, void *data)
+{
+    apr_hash_t *base = NULL;
+    apr_hash_t *overlay = NULL;
+    apr_hash_t *result = NULL;
+    int count;
+
+    base = apr_hash_make(p);
+    overlay = apr_hash_make(p);
+    ABTS_PTR_NOTNULL(tc, base);
+    ABTS_PTR_NOTNULL(tc, overlay);
+
+    apr_hash_set(base, "base1", APR_HASH_KEY_STRING, "value1");
+    apr_hash_set(base, "base2", APR_HASH_KEY_STRING, "value2");
+    apr_hash_set(base, "base3", APR_HASH_KEY_STRING, "value3");
+    apr_hash_set(base, "base4", APR_HASH_KEY_STRING, "value4");
+    apr_hash_set(base, "base5", APR_HASH_KEY_STRING, "value5");
+
+    apr_hash_set(overlay, "overlay1", APR_HASH_KEY_STRING, "value1");
+    apr_hash_set(overlay, "overlay2", APR_HASH_KEY_STRING, "value2");
+    apr_hash_set(overlay, "overlay3", APR_HASH_KEY_STRING, "value3");
+    apr_hash_set(overlay, "overlay4", APR_HASH_KEY_STRING, "value4");
+    apr_hash_set(overlay, "overlay5", APR_HASH_KEY_STRING, "value5");
+
+    result = apr_hash_overlay(p, overlay, base);
+
+    count = apr_hash_count(result);
+    ABTS_INT_EQUAL(tc, 10, count);
+
+    ABTS_STR_EQUAL(tc, "value1",
+                       apr_hash_get(result, "base1", APR_HASH_KEY_STRING));
+    ABTS_STR_EQUAL(tc, "value2",
+                       apr_hash_get(result, "base2", APR_HASH_KEY_STRING));
+    ABTS_STR_EQUAL(tc, "value3",
+                       apr_hash_get(result, "base3", APR_HASH_KEY_STRING));
+    ABTS_STR_EQUAL(tc, "value4",
+                       apr_hash_get(result, "base4", APR_HASH_KEY_STRING));
+    ABTS_STR_EQUAL(tc, "value5",
+                       apr_hash_get(result, "base5", APR_HASH_KEY_STRING));
+    ABTS_STR_EQUAL(tc, "value1",
+                       apr_hash_get(result, "overlay1", APR_HASH_KEY_STRING));
+    ABTS_STR_EQUAL(tc, "value2",
+                       apr_hash_get(result, "overlay2", APR_HASH_KEY_STRING));
+    ABTS_STR_EQUAL(tc, "value3",
+                       apr_hash_get(result, "overlay3", APR_HASH_KEY_STRING));
+    ABTS_STR_EQUAL(tc, "value4",
+                       apr_hash_get(result, "overlay4", APR_HASH_KEY_STRING));
+    ABTS_STR_EQUAL(tc, "value5",
+                       apr_hash_get(result, "overlay5", APR_HASH_KEY_STRING));
+
+    ABTS_STR_EQUAL(tc, "value1",
+                       apr_hash_get(base, "base1", APR_HASH_KEY_STRING));
+    ABTS_STR_EQUAL(tc, "value2",
+                       apr_hash_get(base, "base2", APR_HASH_KEY_STRING));
+    ABTS_STR_EQUAL(tc, "value3",
+                       apr_hash_get(base, "base3", APR_HASH_KEY_STRING));
+    ABTS_STR_EQUAL(tc, "value4",
+                       apr_hash_get(base, "base4", APR_HASH_KEY_STRING));
+    ABTS_STR_EQUAL(tc, "value5",
+                       apr_hash_get(base, "base5", APR_HASH_KEY_STRING));
+
+    ABTS_STR_EQUAL(tc, "value1",
+                       apr_hash_get(overlay, "overlay1", APR_HASH_KEY_STRING));
+    ABTS_STR_EQUAL(tc, "value2",
+                       apr_hash_get(overlay, "overlay2", APR_HASH_KEY_STRING));
+    ABTS_STR_EQUAL(tc, "value3",
+                       apr_hash_get(overlay, "overlay3", APR_HASH_KEY_STRING));
+    ABTS_STR_EQUAL(tc, "value4",
+                       apr_hash_get(overlay, "overlay4", APR_HASH_KEY_STRING));
+    ABTS_STR_EQUAL(tc, "value5",
+                       apr_hash_get(overlay, "overlay5", APR_HASH_KEY_STRING));
+}
+
+abts_suite *testhash(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite)
+
+    abts_run_test(suite, hash_make, NULL);
+    abts_run_test(suite, hash_set, NULL);
+    abts_run_test(suite, hash_get_or_set, NULL);
+    abts_run_test(suite, hash_reset, NULL);
+    abts_run_test(suite, same_value, NULL);
+    abts_run_test(suite, same_value_custom, NULL);
+    abts_run_test(suite, key_space, NULL);
+    abts_run_test(suite, delete_key, NULL);
+
+    abts_run_test(suite, hash_count_0, NULL);
+    abts_run_test(suite, hash_count_1, NULL);
+    abts_run_test(suite, hash_count_5, NULL);
+
+    abts_run_test(suite, hash_clear, NULL);
+    abts_run_test(suite, hash_traverse, NULL);
+    abts_run_test(suite, summation_test, NULL);
+
+    abts_run_test(suite, overlay_empty, NULL);
+    abts_run_test(suite, overlay_2unique, NULL);
+    abts_run_test(suite, overlay_same, NULL);
+    abts_run_test(suite, overlay_fetch, NULL);
+
+    return suite;
+}
+
diff --git a/test/testhooks.c b/test/testhooks.c
new file mode 100644
index 00000000000..b2b16d4c1eb
--- /dev/null
+++ b/test/testhooks.c
@@ -0,0 +1,194 @@
+/* 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 "abts.h"
+#include "testutil.h"
+
+#define APR_HOOK_PROBES_ENABLED
+
+#define APR_HOOK_PROBE_ENTRY(ud,ns,name,args) \
+  ud = toy_hook_probe_entry(#name)
+
+#define APR_HOOK_PROBE_RETURN(ud,ns,name,rv,args) \
+  toy_hook_probe_return(ud, #name, rv)
+
+#define APR_HOOK_PROBE_INVOKE(ud,ns,name,src,args) \
+  toy_hook_probe_invoke(ud, #name, src)
+
+#define APR_HOOK_PROBE_COMPLETE(ud,ns,name,src,rv,args) \
+  toy_hook_probe_complete(ud, #name, src, rv)
+
+#include "apr_hooks.h"
+
+#define TEST_DECLARE(type) type
+
+APR_DECLARE_EXTERNAL_HOOK(test,TEST,int, toyhook, (char *x, apr_size_t s))
+
+APR_HOOK_STRUCT(
+    APR_HOOK_LINK(toyhook)
+)
+
+static void *toy_hook_probe_entry(const char *name);
+static void toy_hook_probe_return(void *ud, const char *name, int rv);
+static void toy_hook_probe_invoke(void *ud, const char *name, const char *src);
+static void toy_hook_probe_complete(void *ud, const char *name,
+                                    const char *src, int rv);
+
+APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(test,TEST,int, toyhook,
+                                    (char *x, apr_size_t s), (x, s), 0, -1)
+
+typedef struct {
+    char *buf;
+    apr_size_t buf_size;
+} hook_probe_data_t;
+
+static apr_pool_t *probe_buf_pool;
+static char *probe_buf;
+
+static void safe_concat(char *buf, apr_size_t buf_size, const char *append)
+{
+    if (strlen(buf) + strlen(append) + 1 <= buf_size) {
+        strcat(buf, append);
+    }
+}
+
+static void *toy_hook_probe_entry(const char *name)
+{
+    hook_probe_data_t *ud = apr_palloc(probe_buf_pool, sizeof *ud);
+    ud->buf_size = 18;
+    ud->buf = (char *)apr_palloc(probe_buf_pool, ud->buf_size);
+    ud->buf[0] = '\0';
+    safe_concat(ud->buf, ud->buf_size, "E");
+    return (void *)ud;
+}
+
+static void toy_hook_probe_return(void *vud, const char *name, int rv)
+{
+    hook_probe_data_t *ud = vud;
+
+    safe_concat(ud->buf, ud->buf_size, "R");
+    probe_buf = ud->buf;
+}
+
+static void toy_hook_probe_invoke(void *vud, const char *name,
+                                  const char *src)
+{
+    hook_probe_data_t *ud = vud;
+
+    safe_concat(ud->buf, ud->buf_size, "I");
+    safe_concat(ud->buf, ud->buf_size, src);
+}
+
+static void toy_hook_probe_complete(void *vud, const char *name,
+                                    const char *src, int rv)
+{
+    hook_probe_data_t *ud = vud;
+
+    safe_concat(ud->buf, ud->buf_size, "C");
+}
+
+static int toyhook_1(char *x, apr_size_t buf_size)
+{
+    safe_concat(x, buf_size, "1");
+    return 0;
+}
+
+static int toyhook_2(char *x, apr_size_t buf_size)
+{
+    safe_concat(x, buf_size, "2");
+    return 0;
+}
+
+static int toyhook_3(char *x, apr_size_t buf_size)
+{
+    safe_concat(x, buf_size, "3");
+    return 0;
+}
+
+static int toyhook_4(char *x, apr_size_t buf_size)
+{
+    safe_concat(x, buf_size, "4");
+    return 0;
+}
+
+static int toyhook_5(char *x, apr_size_t buf_size)
+{
+    safe_concat(x, buf_size, "5");
+    return 0;
+}
+
+static void test_basic_ordering(abts_case *tc, void *data)
+{
+    char buf[6] = {0};
+
+    apr_hook_global_pool = p;
+    apr_hook_deregister_all();
+
+    apr_hook_debug_current = "5";
+    test_hook_toyhook(toyhook_5, NULL, NULL, APR_HOOK_MIDDLE + 2);
+    apr_hook_debug_current = "1";
+    test_hook_toyhook(toyhook_1, NULL, NULL, APR_HOOK_MIDDLE - 2);
+    apr_hook_debug_current = "3";
+    test_hook_toyhook(toyhook_3, NULL, NULL, APR_HOOK_MIDDLE);
+    apr_hook_debug_current = "2";
+    test_hook_toyhook(toyhook_2, NULL, NULL, APR_HOOK_MIDDLE - 1);
+    apr_hook_debug_current = "4";
+    test_hook_toyhook(toyhook_4, NULL, NULL, APR_HOOK_MIDDLE + 1);
+
+    apr_hook_sort_all();
+
+    probe_buf_pool = p;
+    test_run_toyhook(buf, sizeof buf);
+    
+    ABTS_STR_EQUAL(tc, "12345", buf);
+    ABTS_STR_EQUAL(tc, "EI1CI2CI3CI4CI5CR", probe_buf);
+}
+
+static void test_pred_ordering(abts_case *tc, void *data)
+{
+    char buf[10] = {0};
+    static const char *hook2_predecessors[] = {"1", NULL};
+    static const char *hook3_predecessors[] = {"2", NULL};
+
+    apr_hook_global_pool = p;
+    apr_hook_deregister_all();
+
+    apr_hook_debug_current = "1";
+    test_hook_toyhook(toyhook_1, NULL, NULL, APR_HOOK_MIDDLE);
+    apr_hook_debug_current = "3";
+    test_hook_toyhook(toyhook_3, hook3_predecessors, NULL, APR_HOOK_MIDDLE);
+    apr_hook_debug_current = "2";
+    test_hook_toyhook(toyhook_2, hook2_predecessors, NULL, APR_HOOK_MIDDLE);
+    apr_hook_debug_current = "2";
+    test_hook_toyhook(toyhook_2, hook2_predecessors, NULL, APR_HOOK_MIDDLE);
+
+    apr_hook_sort_all();
+
+    probe_buf_pool = p;
+    test_run_toyhook(buf, sizeof buf);
+    
+    /* FAILS ABTS_STR_EQUAL(tc, "1223", buf); */
+}
+
+abts_suite *testhooks(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite);
+
+    abts_run_test(suite, test_basic_ordering, NULL);
+    abts_run_test(suite, test_pred_ordering, NULL);
+
+    return suite;
+}
diff --git a/test/testipsub.c b/test/testipsub.c
new file mode 100644
index 00000000000..7bdb8ccb4e1
--- /dev/null
+++ b/test/testipsub.c
@@ -0,0 +1,233 @@
+/* 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 "testutil.h"
+#include "apr_general.h"
+#include "apr_network_io.h"
+#include "apr_errno.h"
+
+static void test_bad_input(abts_case *tc, void *data)
+{
+    struct {
+        const char *ipstr;
+        const char *mask;
+        apr_status_t expected_rv;
+    } testcases[] =
+    {
+        /* so we have a few good inputs in here; sue me */
+        {"my.host.name",       NULL,               APR_EINVAL}
+        ,{"127.0.0.256",       NULL,               APR_EBADIP}
+        ,{"127.0.0.1",         NULL,               APR_SUCCESS}
+        ,{"127.0.0.1",         "32",               APR_SUCCESS}
+        ,{"127.0.0.1",         "1",                APR_SUCCESS}
+        ,{"127.0.0.1",         "15",               APR_SUCCESS}
+        ,{"127.0.0.1",         "-1",               APR_EBADMASK}
+        ,{"127.0.0.1",         "0",                APR_EBADMASK}
+        ,{"127.0.0.1",         "33",               APR_EBADMASK}
+        ,{"127.0.0.1",         "255.0.0.0",        APR_SUCCESS}
+        ,{"127.0.0.1",         "255.0",            APR_EBADMASK}
+        ,{"127.0.0.1",         "255.255.256.0",    APR_EBADMASK}
+        ,{"127.0.0.1",         "abc",              APR_EBADMASK}
+        ,{"127",               NULL,               APR_SUCCESS}
+        ,{"127.0.0.1.2",       NULL,               APR_EBADIP}
+        ,{"127.0.0.1.2",       "8",                APR_EBADIP}
+        ,{"127",               "255.0.0.0",        APR_EBADIP} /* either EBADIP or EBADMASK seems fine */
+        ,{"",                  NULL,               APR_EINVAL}
+#if APR_HAVE_IPV6
+        ,{"::1",               NULL,               APR_SUCCESS}
+        ,{"::1",               "20",               APR_SUCCESS}
+        ,{"::ffff:9.67.113.15", NULL,              APR_EBADIP} /* yes, this is goodness */
+        ,{"fe80::",            "16",               APR_SUCCESS}
+        ,{"fe80::",            "255.0.0.0",        APR_EBADMASK}
+        ,{"fe80::1",           "0",                APR_EBADMASK}
+        ,{"fe80::1",           "-1",               APR_EBADMASK}
+        ,{"fe80::1",           "1",                APR_SUCCESS}
+        ,{"fe80::1",           "33",               APR_SUCCESS}
+        ,{"fe80::1",           "128",              APR_SUCCESS}
+        ,{"fe80::1",           "129",              APR_EBADMASK}
+#else
+        /* do some IPv6 stuff and verify that it fails with APR_EBADIP */
+        ,{"::ffff:9.67.113.15", NULL,              APR_EBADIP}
+#endif
+    };
+    int i;
+    apr_ipsubnet_t *ipsub;
+    apr_status_t rv;
+
+    for (i = 0; i < (sizeof testcases / sizeof testcases[0]); i++) {
+        rv = apr_ipsubnet_create(&ipsub, testcases[i].ipstr, testcases[i].mask, p);
+        ABTS_INT_EQUAL(tc, testcases[i].expected_rv, rv);
+    }
+}
+
+static void test_singleton_subnets(abts_case *tc, void *data)
+{
+    const char *v4addrs[] = {
+        "127.0.0.1", "129.42.18.99", "63.161.155.20", "207.46.230.229", "64.208.42.36",
+        "198.144.203.195", "192.18.97.241", "198.137.240.91", "62.156.179.119", 
+        "204.177.92.181"
+    };
+    apr_ipsubnet_t *ipsub;
+    apr_sockaddr_t *sa;
+    apr_status_t rv;
+    int i, j, rc;
+
+    for (i = 0; i < sizeof v4addrs / sizeof v4addrs[0]; i++) {
+        rv = apr_ipsubnet_create(&ipsub, v4addrs[i], NULL, p);
+        ABTS_TRUE(tc, rv == APR_SUCCESS);
+        for (j = 0; j < sizeof v4addrs / sizeof v4addrs[0]; j++) {
+            rv = apr_sockaddr_info_get(&sa, v4addrs[j], APR_INET, 0, 0, p);
+            ABTS_TRUE(tc, rv == APR_SUCCESS);
+            rc = apr_ipsubnet_test(ipsub, sa);
+            if (!strcmp(v4addrs[i], v4addrs[j])) {
+                ABTS_TRUE(tc, rc != 0);
+            }
+            else {
+                ABTS_TRUE(tc, rc == 0);
+            }
+        }
+    }
+
+    /* same for v6? */
+}
+
+static void test_interesting_subnets(abts_case *tc, void *data)
+{
+    struct {
+        const char *ipstr, *mask;
+        int family;
+        char *in_subnet, *not_in_subnet;
+    } testcases[] =
+    {
+         {"9.67",             NULL,            APR_INET,  "9.67.113.15",         "10.1.2.3"}
+        ,{"9.67.0.0",         "16",            APR_INET,  "9.67.113.15",         "10.1.2.3"}
+        ,{"9.67.0.0",         "255.255.0.0",   APR_INET,  "9.67.113.15",         "10.1.2.3"}
+        ,{"9.67.113.99",      "16",            APR_INET,  "9.67.113.15",         "10.1.2.3"}
+        ,{"9.67.113.99",      "255.255.255.0", APR_INET,  "9.67.113.15",         "10.1.2.3"}
+        ,{"127",              NULL,            APR_INET,  "127.0.0.1",           "10.1.2.3"}
+        ,{"127.0.0.1",        "8",             APR_INET,  "127.0.0.1",           "10.1.2.3"}
+#if APR_HAVE_IPV6
+        ,{"38.0.0.0",         "8",             APR_INET6, "::ffff:38.1.1.1",     "2600::1"} /* PR 54047 */
+        ,{"fe80::",           "8",             APR_INET6, "fe80::1",             "ff01::1"}
+        ,{"ff01::",           "8",             APR_INET6, "ff01::1",             "fe80::1"}
+        ,{"3FFE:8160::",      "28",            APR_INET6, "3ffE:816e:abcd:1234::1", "3ffe:8170::1"}
+        ,{"127.0.0.1",        NULL,            APR_INET6, "::ffff:127.0.0.1",    "fe80::1"}
+        ,{"127.0.0.1",        "8",             APR_INET6, "::ffff:127.0.0.1",    "fe80::1"}
+#endif
+    };
+    apr_ipsubnet_t *ipsub;
+    apr_sockaddr_t *sa;
+    apr_status_t rv;
+    int i, rc;
+
+    for (i = 0; i < sizeof testcases / sizeof testcases[0]; i++) {
+        rv = apr_ipsubnet_create(&ipsub, testcases[i].ipstr, testcases[i].mask, p);
+        ABTS_TRUE(tc, rv == APR_SUCCESS);
+        rv = apr_sockaddr_info_get(&sa, testcases[i].in_subnet, testcases[i].family, 0, 0, p);
+        ABTS_TRUE(tc, rv == APR_SUCCESS);
+        ABTS_TRUE(tc, sa != NULL);
+        if (!sa) continue;
+        rc = apr_ipsubnet_test(ipsub, sa);
+        ABTS_TRUE(tc, rc != 0);
+        rv = apr_sockaddr_info_get(&sa, testcases[i].not_in_subnet, testcases[i].family, 0, 0, p);
+        ABTS_TRUE(tc, rv == APR_SUCCESS);
+        rc = apr_ipsubnet_test(ipsub, sa);
+        ABTS_TRUE(tc, rc == 0);
+    }
+}
+
+static void test_badmask_str(abts_case *tc, void *data)
+{
+    char buf[128];
+
+    ABTS_STR_EQUAL(tc, apr_strerror(APR_EBADMASK, buf, sizeof buf),
+                      "The specified network mask is invalid.");
+}
+
+static void test_badip_str(abts_case *tc, void *data)
+{
+    char buf[128];
+
+    ABTS_STR_EQUAL(tc, apr_strerror(APR_EBADIP, buf, sizeof buf),
+                      "The specified IP address is invalid.");
+}
+
+static void test_parse_addr_port(abts_case *tc, void *data)
+{
+    const struct {
+        const char *input;
+        apr_status_t rv;
+        const char *addr, *scope_id;
+        apr_port_t port;
+    } *test, testcases[] = {
+        /* Success cases */
+        { "localhost:80", APR_SUCCESS, "localhost", NULL, 80 }
+        ,{ "localhost", APR_SUCCESS, "localhost", NULL, 0 }
+        ,{ "www.example.com:8080", APR_SUCCESS, "www.example.com", NULL, 8080 }
+        ,{ "w:1", APR_SUCCESS, "w", NULL, 1 }
+        ,{ "127.0.0.1:80", APR_SUCCESS, "127.0.0.1", NULL, 80 }
+        ,{ "[::]:80", APR_SUCCESS, "::", NULL, 80 }
+        ,{ "[::%eth0]:80", APR_SUCCESS, "::", "eth0", 80 }
+        ,{ "[::%eth0]", APR_SUCCESS, "::", "eth0", 0 }
+        ,{ "8080", APR_SUCCESS, NULL, NULL, 8080 } /* API doc has this case */
+
+        /* Failure cases */
+        ,{ "localhost:999999", APR_EINVAL, NULL, NULL, 0 }
+        ,{ "localhost:0", APR_EINVAL, NULL, NULL, 0 }
+        ,{ "[abc]", APR_EINVAL, NULL, NULL, 0 }
+        ,{ "[::]z:80", APR_EINVAL, NULL, NULL, 0 }
+        ,{ "[:::80", APR_EINVAL, NULL, NULL, 0 }
+        ,{ "[zzzz]:80", APR_EINVAL, NULL, NULL, 0 }
+        ,{ "[::%]:80", APR_EINVAL, NULL, NULL, 0 }
+/*        ,{ "127.0.0.1:80x", APR_EINVAL, NULL, NULL, 0 }  <- should fail, doesn't  */
+/*        ,{ "127.0.0.1x:80", APR_EINVAL, NULL, NULL, 0 }  <- maybe should fail?, doesn't  */
+/*        ,{ "localhost:-1", APR_EINVAL, NULL, NULL, 0 }   <- should fail, doesn't */
+    };
+    unsigned i;
+        
+    for (i = 0; i < (sizeof testcases / sizeof testcases[0]); i++) {
+        char *addr, *scope_id;
+        apr_port_t port;
+        apr_status_t rv;
+
+        test = &testcases[i];
+        
+        rv = apr_parse_addr_port(&addr, &scope_id, &port, test->input, p);
+        ABTS_INT_EQUAL(tc, test->rv, rv);
+
+        if (test->rv != APR_SUCCESS) continue;
+
+        APR_ASSERT_SUCCESS(tc, "parse address", test->rv);
+
+        ABTS_STR_EQUAL(tc, test->addr, addr);
+        ABTS_STR_EQUAL(tc, test->scope_id, scope_id);
+        ABTS_INT_EQUAL(tc, test->port, port);
+    }
+}
+
+abts_suite *testipsub(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite)
+
+    abts_run_test(suite, test_bad_input, NULL);
+    abts_run_test(suite, test_singleton_subnets, NULL);
+    abts_run_test(suite, test_interesting_subnets, NULL);
+    abts_run_test(suite, test_badmask_str, NULL);
+    abts_run_test(suite, test_badip_str, NULL);
+    abts_run_test(suite, test_parse_addr_port, NULL);
+    return suite;
+}
+
diff --git a/test/testlfs.c b/test/testlfs.c
new file mode 100644
index 00000000000..aa5357389fc
--- /dev/null
+++ b/test/testlfs.c
@@ -0,0 +1,373 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_file_io.h"
+#include "apr_file_info.h"
+#include "apr_errno.h"
+#include "apr_general.h"
+#include "apr_poll.h"
+#include "apr_strings.h"
+#include "apr_lib.h"
+#include "apr_mmap.h"
+#include "testutil.h"
+
+/* TODO: in 1.3.0 this becomes APR_HAS_SPARSE_FILES, HOWEVER we will
+ * still need to test csize before proceeding, because having sparse
+ * file support in the OS/APR does not mean this volume supports it!
+ */
+#if APR_HAS_LARGE_FILES
+
+/* Tests which create an 8GB sparse file and then check it can be used
+ * as normal. */
+
+static apr_off_t oneMB = APR_INT64_C(2) << 19;
+static apr_off_t eightGB = APR_INT64_C(2) << 32;
+
+static int madefile = 0;
+
+#define PRECOND if (!madefile) { ABTS_NOT_IMPL(tc, "Large file tests not enabled"); return; }
+
+#define TESTDIR "lfstests"
+#define TESTFILE "large.bin"
+#define TESTFN "lfstests/large.bin"
+
+static void test_open(abts_case *tc, void *data)
+{
+    apr_file_t *f;
+    apr_finfo_t testsize;
+    apr_status_t rv;
+
+    rv = apr_dir_make(TESTDIR, APR_FPROT_OS_DEFAULT, p);
+    if (rv && !APR_STATUS_IS_EEXIST(rv)) {
+        APR_ASSERT_SUCCESS(tc, "make test directory", rv);
+    }
+
+    /* First attempt a 1MB sparse file so we don't tax the poor test box */
+    rv = apr_file_open(&f, TESTFN, APR_FOPEN_CREATE | APR_FOPEN_WRITE
+                                 | APR_FOPEN_TRUNCATE | APR_FOPEN_SPARSE,
+                       APR_FPROT_OS_DEFAULT, p);
+
+    APR_ASSERT_SUCCESS(tc, "open file", rv);
+
+    APR_ASSERT_SUCCESS(tc, "Truncate to 1MB", rv = apr_file_trunc(f, oneMB+1));
+
+    if (rv == APR_SUCCESS) {
+        rv = apr_file_info_get(&testsize, APR_FINFO_CSIZE, f);
+    }
+
+    /* give up if we can't determine the allocation size of the file,
+     * or if it's not an obviously small allocation but the allocation
+     * unit doesn't appear insanely large - on most platforms, it's just
+     * zero physical bytes at this point.
+     */
+    if (rv != APR_SUCCESS || (testsize.csize > oneMB
+                              && testsize.csize < oneMB * 2)) {
+        ABTS_NOT_IMPL(tc, "Creation of large file (apparently not sparse)");
+
+        madefile = 0;
+    } 
+    else {
+        /* Proceed with our 8GB sparse file now */
+        rv = apr_file_trunc(f, eightGB);
+
+        /* 8GB may pass rlimits or filesystem limits */
+
+        if (APR_STATUS_IS_EINVAL(rv)
+#ifdef EFBIG
+            || rv == EFBIG
+#endif
+            ) {
+            ABTS_NOT_IMPL(tc, "Creation of large file (rlimit, quota or fs)");
+        } 
+        else {
+            APR_ASSERT_SUCCESS(tc, "truncate file to 8gb", rv);
+        }
+        madefile = rv == APR_SUCCESS;
+    }
+
+    APR_ASSERT_SUCCESS(tc, "close large file", apr_file_close(f));
+
+    if (!madefile) {
+        APR_ASSERT_SUCCESS(tc, "remove large file", apr_file_remove(TESTFN, p));
+    }
+}
+
+static void test_reopen(abts_case *tc, void *data)
+{
+    apr_file_t *fh;
+    apr_finfo_t finfo;
+    apr_status_t rv;
+
+    PRECOND;
+    
+    rv = apr_file_open(&fh, TESTFN, APR_FOPEN_SPARSE | APR_FOPEN_READ,
+                       APR_FPROT_OS_DEFAULT, p);
+    APR_ASSERT_SUCCESS(tc, "re-open 8GB file", rv);
+
+    APR_ASSERT_SUCCESS(tc, "file_info_get failed",
+                       apr_file_info_get(&finfo, APR_FINFO_NORM, fh));
+    
+    ABTS_ASSERT(tc, "file_info_get gave incorrect size",
+             finfo.size == eightGB);
+
+    APR_ASSERT_SUCCESS(tc, "re-close large file", apr_file_close(fh));
+}
+
+static void test_stat(abts_case *tc, void *data)
+{
+    apr_finfo_t finfo;
+
+    PRECOND;
+
+    APR_ASSERT_SUCCESS(tc, "stat large file", 
+                       apr_stat(&finfo, TESTFN, APR_FINFO_NORM, p));
+    
+    ABTS_ASSERT(tc, "stat gave incorrect size", finfo.size == eightGB);
+}
+
+static void test_readdir(abts_case *tc, void *data)
+{
+    apr_dir_t *dh;
+    apr_status_t rv;
+
+    PRECOND;
+
+    APR_ASSERT_SUCCESS(tc, "open test directory", 
+                       apr_dir_open(&dh, TESTDIR, p));
+
+    do {
+        apr_finfo_t finfo;
+        
+        rv = apr_dir_read(&finfo, APR_FINFO_MIN, dh);
+        
+        if (rv == APR_SUCCESS && strcmp(finfo.name, TESTFILE) == 0) {
+            ABTS_ASSERT(tc, "apr_dir_read gave incorrect size for large file", 
+                     finfo.size == eightGB);
+        }
+
+    } while (rv == APR_SUCCESS);
+        
+    if (!APR_STATUS_IS_ENOENT(rv)) {
+        APR_ASSERT_SUCCESS(tc, "apr_dir_read failed", rv);
+    }
+    
+    APR_ASSERT_SUCCESS(tc, "close test directory",
+                       apr_dir_close(dh));
+}
+
+#define TESTSTR "Hello, world."
+
+static void test_append(abts_case *tc, void *data)
+{
+    apr_file_t *fh;
+    apr_finfo_t finfo;
+    apr_status_t rv;
+    
+    PRECOND;
+
+    rv = apr_file_open(&fh, TESTFN, APR_FOPEN_SPARSE | APR_FOPEN_WRITE 
+                                  | APR_FOPEN_APPEND, 
+                       APR_FPROT_OS_DEFAULT, p);
+    APR_ASSERT_SUCCESS(tc, "open 8GB file for append", rv);
+
+    APR_ASSERT_SUCCESS(tc, "append to 8GB file",
+                       apr_file_write_full(fh, TESTSTR, strlen(TESTSTR), NULL));
+
+    APR_ASSERT_SUCCESS(tc, "file_info_get failed",
+                       apr_file_info_get(&finfo, APR_FINFO_NORM, fh));
+    
+    ABTS_ASSERT(tc, "file_info_get gave incorrect size",
+             finfo.size == eightGB + strlen(TESTSTR));
+
+    APR_ASSERT_SUCCESS(tc, "close 8GB file", apr_file_close(fh));
+}
+
+static void test_seek(abts_case *tc, void *data)
+{
+    apr_file_t *fh;
+    apr_off_t pos;
+    apr_status_t rv;
+
+    PRECOND;
+    
+    rv = apr_file_open(&fh, TESTFN, APR_FOPEN_SPARSE | APR_FOPEN_WRITE,
+                       APR_FPROT_OS_DEFAULT, p);
+    APR_ASSERT_SUCCESS(tc, "open 8GB file for writing", rv);
+
+    pos = 0;
+    APR_ASSERT_SUCCESS(tc, "relative seek to end", 
+                       apr_file_seek(fh, APR_END, &pos));
+    ABTS_ASSERT(tc, "seek to END gave 8GB", pos == eightGB);
+    
+    pos = eightGB;
+    APR_ASSERT_SUCCESS(tc, "seek to 8GB", apr_file_seek(fh, APR_SET, &pos));
+    ABTS_ASSERT(tc, "seek gave 8GB offset", pos == eightGB);
+
+    pos = 0;
+    APR_ASSERT_SUCCESS(tc, "relative seek to 0", apr_file_seek(fh, APR_CUR, &pos));
+    ABTS_ASSERT(tc, "relative seek gave 8GB offset", pos == eightGB);
+
+    apr_file_close(fh);
+}
+
+static void test_write(abts_case *tc, void *data)
+{
+    apr_file_t *fh;
+    apr_off_t pos = eightGB - 4;
+    apr_status_t rv;
+
+    PRECOND;
+
+    rv = apr_file_open(&fh, TESTFN, APR_FOPEN_SPARSE | APR_FOPEN_WRITE,
+                       APR_FPROT_OS_DEFAULT, p);
+    APR_ASSERT_SUCCESS(tc, "re-open 8GB file", rv);
+
+    APR_ASSERT_SUCCESS(tc, "seek to 8GB - 4", 
+                       apr_file_seek(fh, APR_SET, &pos));
+    ABTS_ASSERT(tc, "seek gave 8GB-4 offset", pos == eightGB - 4);
+
+    APR_ASSERT_SUCCESS(tc, "write magic string to 8GB-4",
+                       apr_file_write_full(fh, "FISH", 4, NULL));
+
+    APR_ASSERT_SUCCESS(tc, "close 8GB file", apr_file_close(fh));
+}
+
+
+#if APR_HAS_MMAP
+static void test_mmap(abts_case *tc, void *data)
+{
+    apr_mmap_t *map;
+    apr_file_t *fh;
+    apr_size_t len = 65536; /* hopefully a multiple of the page size */
+    apr_off_t off = eightGB - len; 
+    apr_status_t rv;
+    void *ptr;
+
+    PRECOND;
+
+    rv = apr_file_open(&fh, TESTFN, APR_FOPEN_SPARSE | APR_FOPEN_READ,
+                       APR_FPROT_OS_DEFAULT, p);
+    APR_ASSERT_SUCCESS(tc, "open 8gb file for mmap", rv);
+    
+    APR_ASSERT_SUCCESS(tc, "mmap 8GB file",
+                       apr_mmap_create(&map, fh, off, len, APR_MMAP_READ, p));
+
+    APR_ASSERT_SUCCESS(tc, "close file", apr_file_close(fh));
+
+    ABTS_ASSERT(tc, "mapped a 64K block", map->size == len);
+    
+    APR_ASSERT_SUCCESS(tc, "get pointer into mmaped region",
+                       apr_mmap_offset(&ptr, map, len - 4));
+    ABTS_ASSERT(tc, "pointer was not NULL", ptr != NULL);
+
+    ABTS_ASSERT(tc, "found the magic string", memcmp(ptr, "FISH", 4) == 0);
+
+    APR_ASSERT_SUCCESS(tc, "delete mmap handle", apr_mmap_delete(map));
+}
+#endif /* APR_HAS_MMAP */
+
+static void test_format(abts_case *tc, void *data)
+{
+    apr_off_t off;
+
+    PRECOND;
+
+    off = apr_atoi64(apr_off_t_toa(p, eightGB));
+
+    ABTS_ASSERT(tc, "apr_atoi64 parsed apr_off_t_toa result incorrectly",
+             off == eightGB);
+}
+
+#define TESTBUFFN TESTDIR "/buffer.bin"
+
+static void test_buffered(abts_case *tc, void *data)
+{
+    apr_off_t off;
+    apr_file_t *f;
+    apr_status_t rv;
+
+    PRECOND;
+
+    rv = apr_file_open(&f, TESTBUFFN, APR_FOPEN_CREATE | APR_FOPEN_WRITE
+                                    | APR_FOPEN_TRUNCATE | APR_FOPEN_BUFFERED
+                                    | APR_FOPEN_SPARSE,
+                       APR_FPROT_OS_DEFAULT, p);
+    APR_ASSERT_SUCCESS(tc, "open buffered file", rv);
+
+    APR_ASSERT_SUCCESS(tc, "truncate to 8GB",
+                       apr_file_trunc(f, eightGB));
+
+    off = eightGB;
+    APR_ASSERT_SUCCESS(tc, "seek to 8GB",
+                       apr_file_seek(f, APR_SET, &off));
+    ABTS_ASSERT(tc, "returned seek position still 8GB",
+                off == eightGB);
+
+    off = 0;
+    APR_ASSERT_SUCCESS(tc, "relative seek",
+                       apr_file_seek(f, APR_CUR, &off));
+    ABTS_ASSERT(tc, "relative seek still at 8GB",
+                off == eightGB);
+
+    off = 0;
+    APR_ASSERT_SUCCESS(tc, "end-relative seek",
+                       apr_file_seek(f, APR_END, &off));
+    ABTS_ASSERT(tc, "end-relative seek still at 8GB",
+                off == eightGB);
+
+    off = -eightGB;
+    APR_ASSERT_SUCCESS(tc, "relative seek to beginning",
+                       apr_file_seek(f, APR_CUR, &off));
+    ABTS_ASSERT(tc, "seek to beginning got zero",
+                off == 0);
+
+    APR_ASSERT_SUCCESS(tc, "close buffered file",
+                       apr_file_close(f));
+}
+
+#else /* !APR_HAS_LARGE_FILES */
+
+static void test_nolfs(abts_case *tc, void *data)
+{
+    ABTS_NOT_IMPL(tc, "Large Files not supported");
+}
+
+#endif
+
+abts_suite *testlfs(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite)
+
+#if APR_HAS_LARGE_FILES
+    abts_run_test(suite, test_open, NULL);
+    abts_run_test(suite, test_reopen, NULL);
+    abts_run_test(suite, test_stat, NULL);
+    abts_run_test(suite, test_readdir, NULL);
+    abts_run_test(suite, test_seek, NULL);
+    abts_run_test(suite, test_append, NULL);
+    abts_run_test(suite, test_write, NULL);
+#if APR_HAS_MMAP
+    abts_run_test(suite, test_mmap, NULL);
+#endif
+    abts_run_test(suite, test_format, NULL);
+    abts_run_test(suite, test_buffered, NULL);
+#else
+    abts_run_test(suite, test_nolfs, NULL);
+#endif
+
+    return suite;
+}
+
diff --git a/test/testlfsabi.c b/test/testlfsabi.c
new file mode 100644
index 00000000000..2c1e963b3e6
--- /dev/null
+++ b/test/testlfsabi.c
@@ -0,0 +1,60 @@
+/* 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 "testutil.h"
+#include "testlfsabi.h"
+#include "apr_file_info.h"
+
+/*
+ * Check that various types don't change size depending on
+ * -D_FILE_OFFSET_BITS=64
+ */
+
+extern void get_type_sizes32(int *res);
+extern void get_type_sizes64(int *res);
+
+static void get_type_sizes(int *res)
+{
+#include "testlfsabi_include.c"
+}
+
+static void check_type_sizes(abts_case *tc, void *data)
+{
+    int normal[IDX_MAX], bits32[IDX_MAX], bits64[IDX_MAX];
+    get_type_sizes(normal);
+    get_type_sizes32(bits32);
+    get_type_sizes64(bits64);
+    CHECKSIZE(tc, normal, bits32, apr_dev_t);
+    CHECKSIZE(tc, normal, bits64, apr_dev_t);
+    CHECKSIZE(tc, normal, bits32, apr_ino_t);
+    CHECKSIZE(tc, normal, bits64, apr_ino_t);
+    CHECKSIZE(tc, normal, bits32, apr_off_t);
+    CHECKSIZE(tc, normal, bits64, apr_off_t);
+    CHECKSIZE(tc, normal, bits32, apr_socklen_t);
+    CHECKSIZE(tc, normal, bits64, apr_socklen_t);
+    CHECKSIZE(tc, normal, bits32, apr_size_t);
+    CHECKSIZE(tc, normal, bits64, apr_size_t);
+}
+
+abts_suite *testlfsabi(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite)
+
+    abts_run_test(suite, check_type_sizes, NULL);
+
+    return suite;
+}
+
diff --git a/test/testlfsabi.h b/test/testlfsabi.h
new file mode 100644
index 00000000000..32c84e8e7fc
--- /dev/null
+++ b/test/testlfsabi.h
@@ -0,0 +1,32 @@
+/* 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 "abts.h"
+
+#define IDX_apr_dev_t       0
+#define IDX_apr_ino_t       1
+#define IDX_apr_off_t       2
+#define IDX_apr_socklen_t   3
+#define IDX_apr_size_t      4
+#define IDX_MAX             5
+
+#define GETSIZE(res, type)  res[(IDX_##type)] = sizeof(type)
+#define CHECKSIZE(tc, res1, res2, type)                         \
+  ABTS_INT_EQUAL(tc, res1[(IDX_##type)], res2[(IDX_##type)]);
+
+extern void get_type_sizes32(int *res);
+extern void get_type_sizes64(int *res);
+
diff --git a/test/testlfsabi32.c b/test/testlfsabi32.c
new file mode 100644
index 00000000000..c65bffda259
--- /dev/null
+++ b/test/testlfsabi32.c
@@ -0,0 +1,29 @@
+/* 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.
+ */
+
+#ifdef _FILE_OFFSET_BITS
+#undef _FILE_OFFSET_BITS
+#endif
+
+#define _FILE_OFFSET_BITS 32
+
+#include "testlfsabi.h"
+#include "apr_file_info.h"
+
+void get_type_sizes32(int *res)
+{
+#include "testlfsabi_include.c"
+}
diff --git a/test/testlfsabi64.c b/test/testlfsabi64.c
new file mode 100644
index 00000000000..ce66c5cf8a8
--- /dev/null
+++ b/test/testlfsabi64.c
@@ -0,0 +1,29 @@
+/* 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.
+ */
+
+#ifdef _FILE_OFFSET_BITS
+#undef _FILE_OFFSET_BITS
+#endif
+
+#define _FILE_OFFSET_BITS 64
+
+#include "testlfsabi.h"
+#include "apr_file_info.h"
+
+void get_type_sizes64(int *res)
+{
+#include "testlfsabi_include.c"
+}
diff --git a/test/testlfsabi_include.c b/test/testlfsabi_include.c
new file mode 100644
index 00000000000..c634d83a917
--- /dev/null
+++ b/test/testlfsabi_include.c
@@ -0,0 +1,21 @@
+/* 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.
+ */
+
+    GETSIZE(res, apr_dev_t);
+    GETSIZE(res, apr_ino_t);
+    GETSIZE(res, apr_off_t);
+    GETSIZE(res, apr_socklen_t);
+    GETSIZE(res, apr_size_t);
diff --git a/test/testlib.dsp b/test/testlib.dsp
new file mode 100644
index 00000000000..93408ca9f2e
--- /dev/null
+++ b/test/testlib.dsp
@@ -0,0 +1,462 @@
+# Microsoft Developer Studio Project File - Name="testlib" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) External Target" 0x0106
+
+CFG=testlib - 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 "testlib.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 "testlib.mak" CFG="testlib - Win32 Release"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "testlib - Win32 Release" (based on "Win32 (x86) External Target")
+!MESSAGE "testlib - Win32 Debug" (based on "Win32 (x86) External Target")
+!MESSAGE "testlib - Win32 Release9x" (based on "Win32 (x86) External Target")
+!MESSAGE "testlib - Win32 Debug9x" (based on "Win32 (x86) External Target")
+!MESSAGE "testlib - x64 Release" (based on "Win32 (x86) External Target")
+!MESSAGE "testlib - x64 Debug" (based on "Win32 (x86) External Target")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+
+!IF  "$(CFG)" == "testlib - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir ""
+# PROP BASE Intermediate_Dir ""
+# PROP BASE Cmd_Line "NMAKE /f Makefile.win INTDIR=LibR OUTDIR=LibR MODEL=static all check"
+# PROP BASE Rebuild_Opt "/a"
+# PROP BASE Target_File "LibR\testall.exe"
+# PROP BASE Bsc_Name ""
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ""
+# PROP Intermediate_Dir ""
+# PROP Cmd_Line "NMAKE /f Makefile.win INTDIR=LibR OUTDIR=LibR MODEL=static all check"
+# PROP Rebuild_Opt "/a"
+# PROP Target_File "LibR\testall.exe"
+# PROP Bsc_Name ""
+# PROP Target_Dir ""
+
+!ELSEIF  "$(CFG)" == "testlib - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir ""
+# PROP BASE Intermediate_Dir ""
+# PROP BASE Cmd_Line "NMAKE /f Makefile.win INTDIR=LibD OUTDIR=LibD MODEL=static _DEBUG=1 all check"
+# PROP BASE Rebuild_Opt "/a"
+# PROP BASE Target_File "LibD\testall.exe"
+# PROP BASE Bsc_Name ""
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir ""
+# PROP Cmd_Line "NMAKE /f Makefile.win INTDIR=LibD OUTDIR=LibD MODEL=static _DEBUG=1 all check"
+# PROP Rebuild_Opt "/a"
+# PROP Target_File "LibD\testall.exe"
+# PROP Bsc_Name ""
+# PROP Target_Dir ""
+
+!ELSEIF  "$(CFG)" == "testlib - Win32 Release9x"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir ""
+# PROP BASE Intermediate_Dir ""
+# PROP BASE Cmd_Line "NMAKE /f Makefile.win INTDIR=9x\LibR OUTDIR=9x\LibR MODEL=static all check"
+# PROP BASE Rebuild_Opt "/a"
+# PROP BASE Target_File "9x\LibR\testall.exe"
+# PROP BASE Bsc_Name ""
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ""
+# PROP Intermediate_Dir ""
+# PROP Cmd_Line "NMAKE /f Makefile.win INTDIR=9x\LibR OUTDIR=9x\LibR MODEL=static all check"
+# PROP Rebuild_Opt "/a"
+# PROP Target_File "9x\LibR\testall.exe"
+# PROP Bsc_Name ""
+# PROP Target_Dir ""
+
+!ELSEIF  "$(CFG)" == "testlib - Win32 Debug9x"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir ""
+# PROP BASE Intermediate_Dir ""
+# PROP BASE Cmd_Line "NMAKE /f Makefile.win INTDIR=9x\LibD OUTDIR=9x\LibD MODEL=static _DEBUG=1 all check"
+# PROP BASE Rebuild_Opt "/a"
+# PROP BASE Target_File "9x\LibD\testall.exe"
+# PROP BASE Bsc_Name ""
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir ""
+# PROP Cmd_Line "NMAKE /f Makefile.win INTDIR=9x\LibD OUTDIR=9x\LibD MODEL=static _DEBUG=1 all check"
+# PROP Rebuild_Opt "/a"
+# PROP Target_File "9x\LibD\testall.exe"
+# PROP Bsc_Name ""
+# PROP Target_Dir ""
+
+!ELSEIF  "$(CFG)" == "testlib - x64 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir ""
+# PROP BASE Intermediate_Dir ""
+# PROP BASE Cmd_Line "NMAKE /f Makefile.win INTDIR=x64\LibR OUTDIR=x64\LibR MODEL=static all check"
+# PROP BASE Rebuild_Opt "/a"
+# PROP BASE Target_File "x64\LibR\testall.exe"
+# PROP BASE Bsc_Name ""
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ""
+# PROP Intermediate_Dir ""
+# PROP Cmd_Line "NMAKE /f Makefile.win INTDIR=x64\LibR OUTDIR=x64\LibR MODEL=static all check"
+# PROP Rebuild_Opt "/a"
+# PROP Target_File "x64\LibR\testall.exe"
+# PROP Bsc_Name ""
+# PROP Target_Dir ""
+
+!ELSEIF  "$(CFG)" == "testlib - x64 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir ""
+# PROP BASE Intermediate_Dir ""
+# PROP BASE Cmd_Line "NMAKE /f Makefile.win INTDIR=x64\LibD OUTDIR=x64\LibD MODEL=static _DEBUG=1 all check"
+# PROP BASE Rebuild_Opt "/a"
+# PROP BASE Target_File "x64\LibD\testall.exe"
+# PROP BASE Bsc_Name ""
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir ""
+# PROP Cmd_Line "NMAKE /f Makefile.win INTDIR=x64\LibD OUTDIR=x64\LibD MODEL=static _DEBUG=1 all check"
+# PROP Rebuild_Opt "/a"
+# PROP Target_File "x64\LibD\testall.exe"
+# PROP Bsc_Name ""
+# PROP Target_Dir ""
+
+!ENDIF 
+
+# Begin Target
+
+# Name "testlib - Win32 Release"
+# Name "testlib - Win32 Debug"
+# Name "testlib - Win32 Release9x"
+# Name "testlib - Win32 Debug9x"
+# Name "testlib - x64 Release"
+# Name "testlib - x64 Debug"
+# Begin Group "testall Source Files"
+
+# PROP Default_Filter ".c"
+# Begin Source File
+
+SOURCE=.\abts.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\abts.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\abts_tests.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\testapp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testargs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testatomic.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testcond.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testdir.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testdso.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testdup.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testenv.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testfile.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testfilecopy.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testfileinfo.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testflock.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testflock.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\testfmt.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testfnmatch.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testglobalmutex.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testglobalmutex.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\testhash.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testipsub.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testlfs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testlfsabi.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testlfsabi.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\testlfsabi_include.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testlfsabi32.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testlfsabi64.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testlock.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testmmap.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testnames.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testoc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testpath.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testpipe.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testpoll.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testpools.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testproc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testrand.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testshm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testshm.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\testsleep.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testsock.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testsock.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\testsockets.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testsockopt.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\teststr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\teststrnatcmp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testtable.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testtemp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testthread.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testtime.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testud.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testuser.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testutil.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testutil.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\testvsn.c
+# End Source File
+# End Group
+# Begin Group "Other Source Files"
+
+# PROP Default_Filter ".c"
+# Begin Source File
+
+SOURCE=.\globalmutexchild.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mod_test.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\nw_misc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\occhild.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\proc_child.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\readchild.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\sendfile.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\sockchild.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testlockperf.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testmutexscope.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testprocmutex.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testshmconsumer.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\testshmproducer.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\tryread.c
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\Makefile.win
+# End Source File
+# End Target
+# End Project
diff --git a/test/testlock.c b/test/testlock.c
new file mode 100644
index 00000000000..cd48768ca67
--- /dev/null
+++ b/test/testlock.c
@@ -0,0 +1,404 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_thread_proc.h"
+#include "apr_file_io.h"
+#include "apr_thread_mutex.h"
+#include "apr_thread_rwlock.h"
+#include "apr_thread_cond.h"
+#include "apr_errno.h"
+#include "apr_general.h"
+#include "apr_getopt.h"
+#include "testutil.h"
+
+#if APR_HAS_THREADS
+
+#define MAX_ITER 40000
+#define MAX_COUNTER 100000
+#define MAX_RETRY 5
+
+static void *APR_THREAD_FUNC thread_rwlock_func(apr_thread_t *thd, void *data);
+static void *APR_THREAD_FUNC thread_mutex_function(apr_thread_t *thd, void *data);
+static void *APR_THREAD_FUNC thread_cond_producer(apr_thread_t *thd, void *data);
+static void *APR_THREAD_FUNC thread_cond_consumer(apr_thread_t *thd, void *data);
+
+static apr_thread_mutex_t *thread_mutex;
+static apr_thread_rwlock_t *rwlock;
+static int i = 0, x = 0;
+
+static int buff[MAX_COUNTER];
+
+struct {
+    apr_thread_mutex_t *mutex;
+    int                nput;
+    int                nval;
+} put;
+
+struct {
+    apr_thread_mutex_t *mutex;
+    apr_thread_cond_t  *cond;
+    int                nready;
+} nready;
+
+static apr_thread_mutex_t *timeout_mutex;
+static apr_thread_cond_t *timeout_cond;
+
+static void *APR_THREAD_FUNC thread_rwlock_func(apr_thread_t *thd, void *data)
+{
+    int exitLoop = 1;
+
+    while (1)
+    {
+        apr_thread_rwlock_rdlock(rwlock);
+        if (i == MAX_ITER)
+            exitLoop = 0;
+        apr_thread_rwlock_unlock(rwlock);
+
+        if (!exitLoop)
+            break;
+
+        apr_thread_rwlock_wrlock(rwlock);
+        if (i != MAX_ITER)
+        {
+            i++;
+            x++;
+        }
+        apr_thread_rwlock_unlock(rwlock);
+    }
+    return NULL;
+} 
+
+static void *APR_THREAD_FUNC thread_mutex_function(apr_thread_t *thd, void *data)
+{
+    int exitLoop = 1;
+
+    /* slight delay to allow things to settle */
+    apr_sleep (1);
+    
+    while (1)
+    {
+        if (data) {
+            apr_thread_mutex_timedlock(thread_mutex, *(apr_interval_time_t *)data);
+        }
+        else {
+            apr_thread_mutex_lock(thread_mutex);
+        }
+        if (i == MAX_ITER)
+            exitLoop = 0;
+        else 
+        {
+            i++;
+            x++;
+        }
+        apr_thread_mutex_unlock(thread_mutex);
+
+        if (!exitLoop)
+            break;
+    }
+    return NULL;
+} 
+
+static void *APR_THREAD_FUNC thread_cond_producer(apr_thread_t *thd, void *data)
+{
+    for (;;) {
+        apr_thread_mutex_lock(put.mutex);
+        if (put.nput >= MAX_COUNTER) {
+            apr_thread_mutex_unlock(put.mutex);
+            return NULL;
+        }
+        buff[put.nput] = put.nval;
+        put.nput++;
+        put.nval++;
+        apr_thread_mutex_unlock(put.mutex);
+
+        apr_thread_mutex_lock(nready.mutex);
+        if (nready.nready == 0)
+            apr_thread_cond_signal(nready.cond);
+        nready.nready++;
+        apr_thread_mutex_unlock(nready.mutex);
+
+        *((int *) data) += 1;
+    }
+
+    return NULL;
+}
+
+static void *APR_THREAD_FUNC thread_cond_consumer(apr_thread_t *thd, void *data)
+{
+    int i;
+
+    for (i = 0; i < MAX_COUNTER; i++) {
+        apr_thread_mutex_lock(nready.mutex);
+        while (nready.nready == 0)
+            apr_thread_cond_wait(nready.cond, nready.mutex);
+        nready.nready--;
+        apr_thread_mutex_unlock(nready.mutex);
+
+        if (buff[i] != i)
+            printf("buff[%d] = %d\n", i, buff[i]);
+    }
+
+    return NULL;
+}
+
+static void test_thread_mutex(abts_case *tc, void *data)
+{
+    apr_thread_t *t1, *t2, *t3, *t4;
+    apr_status_t s1, s2, s3, s4;
+
+    s1 = apr_thread_mutex_create(&thread_mutex, APR_THREAD_MUTEX_DEFAULT, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, s1);
+    ABTS_PTR_NOTNULL(tc, thread_mutex);
+
+    i = 0;
+    x = 0;
+
+    s1 = apr_thread_create(&t1, NULL, thread_mutex_function, NULL, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, s1);
+    s2 = apr_thread_create(&t2, NULL, thread_mutex_function, NULL, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, s2);
+    s3 = apr_thread_create(&t3, NULL, thread_mutex_function, NULL, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, s3);
+    s4 = apr_thread_create(&t4, NULL, thread_mutex_function, NULL, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, s4);
+
+    apr_thread_join(&s1, t1);
+    apr_thread_join(&s2, t2);
+    apr_thread_join(&s3, t3);
+    apr_thread_join(&s4, t4);
+
+    ABTS_INT_EQUAL(tc, MAX_ITER, x);
+}
+
+static void test_thread_timedmutex(abts_case *tc, void *data)
+{
+    apr_thread_t *t1, *t2, *t3, *t4;
+    apr_status_t s1, s2, s3, s4;
+    apr_interval_time_t timeout;
+
+    s1 = apr_thread_mutex_create(&thread_mutex, APR_THREAD_MUTEX_TIMED, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, s1);
+    ABTS_PTR_NOTNULL(tc, thread_mutex);
+
+    i = 0;
+    x = 0;
+
+    timeout = apr_time_from_sec(5);
+
+    s1 = apr_thread_create(&t1, NULL, thread_mutex_function, &timeout, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, s1);
+    s2 = apr_thread_create(&t2, NULL, thread_mutex_function, &timeout, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, s2);
+    s3 = apr_thread_create(&t3, NULL, thread_mutex_function, &timeout, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, s3);
+    s4 = apr_thread_create(&t4, NULL, thread_mutex_function, &timeout, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, s4);
+
+    apr_thread_join(&s1, t1);
+    apr_thread_join(&s2, t2);
+    apr_thread_join(&s3, t3);
+    apr_thread_join(&s4, t4);
+
+    ABTS_INT_EQUAL(tc, MAX_ITER, x);
+}
+
+static void test_thread_rwlock(abts_case *tc, void *data)
+{
+    apr_thread_t *t1, *t2, *t3, *t4;
+    apr_status_t s1, s2, s3, s4;
+
+    s1 = apr_thread_rwlock_create(&rwlock, p);
+    if (s1 == APR_ENOTIMPL) {
+        ABTS_NOT_IMPL(tc, "rwlocks not implemented");
+        return;
+    }
+    APR_ASSERT_SUCCESS(tc, "rwlock_create", s1);
+    ABTS_PTR_NOTNULL(tc, rwlock);
+
+    i = 0;
+    x = 0;
+
+    s1 = apr_thread_create(&t1, NULL, thread_rwlock_func, NULL, p);
+    APR_ASSERT_SUCCESS(tc, "create thread 1", s1);
+    s2 = apr_thread_create(&t2, NULL, thread_rwlock_func, NULL, p);
+    APR_ASSERT_SUCCESS(tc, "create thread 2", s2);
+    s3 = apr_thread_create(&t3, NULL, thread_rwlock_func, NULL, p);
+    APR_ASSERT_SUCCESS(tc, "create thread 3", s3);
+    s4 = apr_thread_create(&t4, NULL, thread_rwlock_func, NULL, p);
+    APR_ASSERT_SUCCESS(tc, "create thread 4", s4);
+
+    apr_thread_join(&s1, t1);
+    apr_thread_join(&s2, t2);
+    apr_thread_join(&s3, t3);
+    apr_thread_join(&s4, t4);
+
+    ABTS_INT_EQUAL(tc, MAX_ITER, x);
+
+    apr_thread_rwlock_destroy(rwlock);
+}
+
+static void test_cond(abts_case *tc, void *data)
+{
+    apr_thread_t *p1, *p2, *p3, *p4, *c1;
+    apr_status_t s0, s1, s2, s3, s4;
+    int count1, count2, count3, count4;
+    int sum;
+    
+    APR_ASSERT_SUCCESS(tc, "create put mutex",
+                       apr_thread_mutex_create(&put.mutex, 
+                                               APR_THREAD_MUTEX_DEFAULT, p));
+    ABTS_PTR_NOTNULL(tc, put.mutex);
+
+    APR_ASSERT_SUCCESS(tc, "create nready mutex",
+                       apr_thread_mutex_create(&nready.mutex, 
+                                               APR_THREAD_MUTEX_DEFAULT, p));
+    ABTS_PTR_NOTNULL(tc, nready.mutex);
+
+    APR_ASSERT_SUCCESS(tc, "create condvar",
+                       apr_thread_cond_create(&nready.cond, p));
+    ABTS_PTR_NOTNULL(tc, nready.cond);
+
+    count1 = count2 = count3 = count4 = 0;
+    put.nput = put.nval = 0;
+    nready.nready = 0;
+    i = 0;
+    x = 0;
+
+    s0 = apr_thread_create(&p1, NULL, thread_cond_producer, &count1, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, s0);
+    s1 = apr_thread_create(&p2, NULL, thread_cond_producer, &count2, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, s1);
+    s2 = apr_thread_create(&p3, NULL, thread_cond_producer, &count3, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, s2);
+    s3 = apr_thread_create(&p4, NULL, thread_cond_producer, &count4, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, s3);
+    s4 = apr_thread_create(&c1, NULL, thread_cond_consumer, NULL, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, s4);
+
+    apr_thread_join(&s0, p1);
+    apr_thread_join(&s1, p2);
+    apr_thread_join(&s2, p3);
+    apr_thread_join(&s3, p4);
+    apr_thread_join(&s4, c1);
+
+    APR_ASSERT_SUCCESS(tc, "destroy condvar", 
+                       apr_thread_cond_destroy(nready.cond));
+
+    sum = count1 + count2 + count3 + count4;
+    /*
+    printf("count1 = %d count2 = %d count3 = %d count4 = %d\n",
+            count1, count2, count3, count4);
+    */
+    ABTS_INT_EQUAL(tc, MAX_COUNTER, sum);
+}
+
+static void test_timeoutcond(abts_case *tc, void *data)
+{
+    apr_status_t s;
+    apr_interval_time_t timeout;
+    apr_time_t begin, end;
+    int i;
+
+    s = apr_thread_mutex_create(&timeout_mutex, APR_THREAD_MUTEX_DEFAULT, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, s);
+    ABTS_PTR_NOTNULL(tc, timeout_mutex);
+
+    s = apr_thread_cond_create(&timeout_cond, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, s);
+    ABTS_PTR_NOTNULL(tc, timeout_cond);
+
+    timeout = apr_time_from_sec(5);
+
+    for (i = 0; i < MAX_RETRY; i++) {
+        apr_thread_mutex_lock(timeout_mutex);
+
+        begin = apr_time_now();
+        s = apr_thread_cond_timedwait(timeout_cond, timeout_mutex, timeout);
+        end = apr_time_now();
+        apr_thread_mutex_unlock(timeout_mutex);
+        
+        if (s != APR_SUCCESS && !APR_STATUS_IS_TIMEUP(s)) {
+            continue;
+        }
+        ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(s));
+        ABTS_ASSERT(tc, "Timer returned too late", end - begin - timeout < 500000);
+        break;
+    }
+    ABTS_ASSERT(tc, "Too many retries", i < MAX_RETRY);
+    APR_ASSERT_SUCCESS(tc, "Unable to destroy the conditional",
+                       apr_thread_cond_destroy(timeout_cond));
+}
+
+static void test_timeoutmutex(abts_case *tc, void *data)
+{
+    apr_status_t s;
+    apr_interval_time_t timeout;
+    apr_time_t begin, end;
+    int i;
+
+    s = apr_thread_mutex_create(&timeout_mutex, APR_THREAD_MUTEX_TIMED, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, s);
+    ABTS_PTR_NOTNULL(tc, timeout_mutex);
+
+    timeout = apr_time_from_sec(5);
+
+    ABTS_INT_EQUAL(tc, 0, apr_thread_mutex_lock(timeout_mutex));
+    for (i = 0; i < MAX_RETRY; i++) {
+        begin = apr_time_now();
+        s = apr_thread_mutex_timedlock(timeout_mutex, timeout);
+        end = apr_time_now();
+
+        if (s != APR_SUCCESS && !APR_STATUS_IS_TIMEUP(s)) {
+            continue;
+        }
+        ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(s));
+        ABTS_ASSERT(tc, "Timer returned too late", end - begin - timeout < 1000000);
+        break;
+    }
+    ABTS_ASSERT(tc, "Too many retries", i < MAX_RETRY);
+    ABTS_INT_EQUAL(tc, 0, apr_thread_mutex_unlock(timeout_mutex));
+    APR_ASSERT_SUCCESS(tc, "Unable to destroy the mutex",
+                       apr_thread_mutex_destroy(timeout_mutex));
+}
+
+#endif /* !APR_HAS_THREADS */
+
+#if !APR_HAS_THREADS
+static void threads_not_impl(abts_case *tc, void *data)
+{
+    ABTS_NOT_IMPL(tc, "Threads not implemented on this platform");
+}
+#endif
+
+
+abts_suite *testlock(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite)
+
+#if !APR_HAS_THREADS
+    abts_run_test(suite, threads_not_impl, NULL);
+#else
+    abts_run_test(suite, test_thread_mutex, NULL);
+    abts_run_test(suite, test_thread_timedmutex, NULL);
+    abts_run_test(suite, test_thread_rwlock, NULL);
+    abts_run_test(suite, test_cond, NULL);
+    abts_run_test(suite, test_timeoutcond, NULL);
+    abts_run_test(suite, test_timeoutmutex, NULL);
+#endif
+
+    return suite;
+}
+
diff --git a/test/testlockperf.c b/test/testlockperf.c
new file mode 100644
index 00000000000..f89d7900b76
--- /dev/null
+++ b/test/testlockperf.c
@@ -0,0 +1,348 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_thread_proc.h"
+#include "apr_thread_mutex.h"
+#include "apr_thread_rwlock.h"
+#include "apr_file_io.h"
+#include "apr_errno.h"
+#include "apr_general.h"
+#include "apr_getopt.h"
+#include "errno.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include "testutil.h"
+
+#if !APR_HAS_THREADS
+int main(void)
+{
+    printf("This program won't work on this platform because there is no "
+           "support for threads.\n");
+    return 0;
+}
+#else /* !APR_HAS_THREADS */
+
+#define DEFAULT_MAX_COUNTER 1000000
+#define MAX_THREADS 6
+
+static int verbose = 0;
+static long mutex_counter;
+static long max_counter = DEFAULT_MAX_COUNTER;
+
+static apr_thread_mutex_t *thread_lock;
+void * APR_THREAD_FUNC thread_mutex_func(apr_thread_t *thd, void *data);
+apr_status_t test_thread_mutex(int num_threads); /* apr_thread_mutex_t */
+
+static apr_thread_rwlock_t *thread_rwlock;
+void * APR_THREAD_FUNC thread_rwlock_func(apr_thread_t *thd, void *data);
+apr_status_t test_thread_rwlock(int num_threads); /* apr_thread_rwlock_t */
+
+int test_thread_mutex_nested(int num_threads);
+
+apr_pool_t *pool;
+int i = 0, x = 0;
+
+void * APR_THREAD_FUNC thread_mutex_func(apr_thread_t *thd, void *data)
+{
+    int i;
+
+    for (i = 0; i < max_counter; i++) {
+        if (data) {
+            apr_thread_mutex_timedlock(thread_lock, *(apr_interval_time_t *)data);
+        }
+        else {
+            apr_thread_mutex_lock(thread_lock);
+        }
+        mutex_counter++;
+        apr_thread_mutex_unlock(thread_lock);
+    }
+    return NULL;
+}
+
+void * APR_THREAD_FUNC thread_rwlock_func(apr_thread_t *thd, void *data)
+{
+    int i;
+
+    for (i = 0; i < max_counter; i++) {
+        apr_thread_rwlock_wrlock(thread_rwlock);
+        mutex_counter++;
+        apr_thread_rwlock_unlock(thread_rwlock);
+    }
+    return NULL;
+}
+
+int test_thread_mutex(int num_threads)
+{
+    apr_thread_t *t[MAX_THREADS];
+    apr_status_t s[MAX_THREADS];
+    apr_time_t time_start, time_stop;
+    int i;
+
+    mutex_counter = 0;
+
+    printf("apr_thread_mutex_t Tests\n");
+    printf("%-60s", "    Initializing the apr_thread_mutex_t (UNNESTED)");
+    s[0] = apr_thread_mutex_create(&thread_lock, APR_THREAD_MUTEX_UNNESTED, pool);
+    if (s[0] != APR_SUCCESS) {
+        printf("Failed!\n");
+        return s[0];
+    }
+    printf("OK\n");
+
+    apr_thread_mutex_lock(thread_lock);
+    /* set_concurrency(4)? -aaron */
+    printf("    Starting %d threads    ", num_threads); 
+    for (i = 0; i < num_threads; ++i) {
+        s[i] = apr_thread_create(&t[i], NULL, thread_mutex_func, NULL, pool);
+        if (s[i] != APR_SUCCESS) {
+            printf("Failed!\n");
+            return s[i];
+        }
+    }
+    printf("OK\n");
+
+    time_start = apr_time_now();
+    apr_thread_mutex_unlock(thread_lock);
+
+    /* printf("%-60s", "    Waiting for threads to exit"); */
+    for (i = 0; i < num_threads; ++i) {
+        apr_thread_join(&s[i], t[i]);
+    }
+    /* printf("OK\n"); */
+
+    time_stop = apr_time_now();
+    printf("microseconds: %" APR_INT64_T_FMT " usec\n",
+           (time_stop - time_start));
+    if (mutex_counter != max_counter * num_threads)
+        printf("error: counter = %ld\n", mutex_counter);
+
+    return APR_SUCCESS;
+}
+
+int test_thread_mutex_nested(int num_threads)
+{
+    apr_thread_t *t[MAX_THREADS];
+    apr_status_t s[MAX_THREADS];
+    apr_time_t time_start, time_stop;
+    int i;
+
+    mutex_counter = 0;
+
+    printf("apr_thread_mutex_t Tests\n");
+    printf("%-60s", "    Initializing the apr_thread_mutex_t (NESTED)");
+    s[0] = apr_thread_mutex_create(&thread_lock, APR_THREAD_MUTEX_NESTED, pool);
+    if (s[0] != APR_SUCCESS) {
+        printf("Failed!\n");
+        return s[0];
+    }
+    printf("OK\n");
+
+    apr_thread_mutex_lock(thread_lock);
+    /* set_concurrency(4)? -aaron */
+    printf("    Starting %d threads    ", num_threads); 
+    for (i = 0; i < num_threads; ++i) {
+        s[i] = apr_thread_create(&t[i], NULL, thread_mutex_func, NULL, pool);
+        if (s[i] != APR_SUCCESS) {
+            printf("Failed!\n");
+            return s[i];
+        }
+    }
+    printf("OK\n");
+
+    time_start = apr_time_now();
+    apr_thread_mutex_unlock(thread_lock);
+
+    /* printf("%-60s", "    Waiting for threads to exit"); */
+    for (i = 0; i < num_threads; ++i) {
+        apr_thread_join(&s[i], t[i]);
+    }
+    /* printf("OK\n"); */
+
+    time_stop = apr_time_now();
+    printf("microseconds: %" APR_INT64_T_FMT " usec\n",
+           (time_stop - time_start));
+    if (mutex_counter != max_counter * num_threads)
+        printf("error: counter = %ld\n", mutex_counter);
+
+    return APR_SUCCESS;
+}
+
+static int test_thread_mutex_timed(int num_threads)
+{
+    apr_thread_t *t[MAX_THREADS];
+    apr_status_t s[MAX_THREADS];
+    apr_time_t time_start, time_stop;
+    apr_time_t timeout;
+    int i;
+
+    mutex_counter = 0;
+
+    timeout = apr_time_from_sec(5);
+
+    printf("apr_thread_mutex_t Tests\n");
+    printf("%-60s", "    Initializing the apr_thread_mutex_t (TIMED)");
+    s[0] = apr_thread_mutex_create(&thread_lock, APR_THREAD_MUTEX_TIMED, pool);
+    if (s[0] != APR_SUCCESS) {
+        printf("Failed!\n");
+        return s[0];
+    }
+    printf("OK\n");
+
+    apr_thread_mutex_lock(thread_lock);
+    /* set_concurrency(4)? -aaron */
+    printf("    Starting %d threads    ", num_threads); 
+    for (i = 0; i < num_threads; ++i) {
+        s[i] = apr_thread_create(&t[i], NULL, thread_mutex_func, &timeout, pool);
+        if (s[i] != APR_SUCCESS) {
+            printf("Failed!\n");
+            return s[i];
+        }
+    }
+    printf("OK\n");
+
+    time_start = apr_time_now();
+    apr_thread_mutex_unlock(thread_lock);
+
+    /* printf("%-60s", "    Waiting for threads to exit"); */
+    for (i = 0; i < num_threads; ++i) {
+        apr_thread_join(&s[i], t[i]);
+    }
+    /* printf("OK\n"); */
+
+    time_stop = apr_time_now();
+    printf("microseconds: %" APR_INT64_T_FMT " usec\n",
+           (time_stop - time_start));
+    if (mutex_counter != max_counter * num_threads)
+        printf("error: counter = %ld\n", mutex_counter);
+
+    return APR_SUCCESS;
+}
+
+int test_thread_rwlock(int num_threads)
+{
+    apr_thread_t *t[MAX_THREADS];
+    apr_status_t s[MAX_THREADS];
+    apr_time_t time_start, time_stop;
+    int i;
+
+    mutex_counter = 0;
+
+    printf("apr_thread_rwlock_t Tests\n");
+    printf("%-60s", "    Initializing the apr_thread_rwlock_t");
+    s[0] = apr_thread_rwlock_create(&thread_rwlock, pool);
+    if (s[0] != APR_SUCCESS) {
+        printf("Failed!\n");
+        return s[0];
+    }
+    printf("OK\n");
+
+    apr_thread_rwlock_wrlock(thread_rwlock);
+    /* set_concurrency(4)? -aaron */
+    printf("    Starting %d threads    ", num_threads); 
+    for (i = 0; i < num_threads; ++i) {
+        s[i] = apr_thread_create(&t[i], NULL, thread_rwlock_func, NULL, pool);
+        if (s[i] != APR_SUCCESS) {
+            printf("Failed!\n");
+            return s[i];
+        }
+    }
+    printf("OK\n");
+
+    time_start = apr_time_now();
+    apr_thread_rwlock_unlock(thread_rwlock);
+
+    /* printf("%-60s", "    Waiting for threads to exit"); */
+    for (i = 0; i < num_threads; ++i) {
+        apr_thread_join(&s[i], t[i]);
+    }
+    /* printf("OK\n"); */
+
+    time_stop = apr_time_now();
+    printf("microseconds: %" APR_INT64_T_FMT " usec\n",
+           (time_stop - time_start));
+    if (mutex_counter != max_counter * num_threads)
+        printf("error: counter = %ld\n", mutex_counter);
+
+    return APR_SUCCESS;
+}
+
+int main(int argc, const char * const *argv)
+{
+    apr_status_t rv;
+    char errmsg[200];
+    apr_getopt_t *opt;
+    char optchar;
+    const char *optarg;
+
+    printf("APR Lock Performance Test\n==============\n\n");
+        
+    apr_initialize();
+    atexit(apr_terminate);
+
+    if (apr_pool_create(&pool, NULL) != APR_SUCCESS)
+        exit(-1);
+
+    if ((rv = apr_getopt_init(&opt, pool, argc, argv)) != APR_SUCCESS) {
+        fprintf(stderr, "Could not set up to parse options: [%d] %s\n",
+                rv, apr_strerror(rv, errmsg, sizeof errmsg));
+        exit(-1);
+    }
+        
+    while ((rv = apr_getopt(opt, "c:v", &optchar, &optarg)) == APR_SUCCESS) {
+        if (optchar == 'c') {
+            max_counter = atol(optarg);
+        }
+        else if (optchar == 'v') {
+            verbose = 1;
+        }
+    }
+
+    if (rv != APR_SUCCESS && rv != APR_EOF) {
+        fprintf(stderr, "Could not parse options: [%d] %s\n",
+                rv, apr_strerror(rv, errmsg, sizeof errmsg));
+        exit(-1);
+    }
+
+    for (i = 1; i <= MAX_THREADS; ++i) {
+        if ((rv = test_thread_mutex(i)) != APR_SUCCESS) {
+            fprintf(stderr,"thread_mutex test failed : [%d] %s\n",
+                    rv, apr_strerror(rv, (char*)errmsg, 200));
+            exit(-3);
+        }
+
+        if ((rv = test_thread_mutex_nested(i)) != APR_SUCCESS) {
+            fprintf(stderr,"thread_mutex (NESTED) test failed : [%d] %s\n",
+                    rv, apr_strerror(rv, (char*)errmsg, 200));
+            exit(-4);
+        }
+
+        if ((rv = test_thread_mutex_timed(i)) != APR_SUCCESS) {
+            fprintf(stderr,"thread_mutex (TIMED) test failed : [%d] %s\n",
+                    rv, apr_strerror(rv, (char*)errmsg, 200));
+            exit(-5);
+        }
+
+        if ((rv = test_thread_rwlock(i)) != APR_SUCCESS) {
+            fprintf(stderr,"thread_rwlock test failed : [%d] %s\n",
+                    rv, apr_strerror(rv, (char*)errmsg, 200));
+            exit(-6);
+        }
+    }
+
+    return 0;
+}
+
+#endif /* !APR_HAS_THREADS */
diff --git a/test/testmd4.c b/test/testmd4.c
new file mode 100644
index 00000000000..53a336149e6
--- /dev/null
+++ b/test/testmd4.c
@@ -0,0 +1,119 @@
+/* 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 is derived from material copyright RSA Data Security, Inc.
+ * Their notice is reproduced below in its entirety.
+ *
+ * Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All
+ * rights reserved.
+ *
+ * RSA Data Security, Inc. makes no representations concerning either
+ * the merchantability of this software or the suitability of this
+ * software for any particular purpose. It is provided "as is"
+ * without express or implied warranty of any kind.
+ *
+ * These notices must be retained in any copies of any part of this
+ * documentation and/or software.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "apr_errno.h"
+#include "apr_md4.h"
+#include "apr_file_io.h"
+
+#include "abts.h"
+#include "testutil.h"
+
+static struct {
+        const char *string;
+        const char *md4sum;
+} md4sums[] = 
+{
+/* 
+* Taken from the old md4 test suite.
+* MD4 ("") = 31d6cfe0d16ae931b73c59d7e0c089c0
+* MD4 ("a") = bde52cb31de33e46245e05fbdbd6fb24
+* MD4 ("abc") = a448017aaf21d8525fc10ae87aa6729d
+* MD4 ("message digest") = d9130a8164549fe818874806e1c7014b
+* MD4 ("abcdefghijklmnopqrstuvwxyz") = d79e1c308aa5bbcdeea8ed63df412da9
+* MD4 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
+* MD4 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") = e33b4ddc9c38f2199c3e7b164fcc0536
+* 
+*/
+        {"", 
+         "\x31\xd6\xcf\xe0\xd1\x6a\xe9\x31\xb7\x3c\x59\xd7\xe0\xc0\x89\xc0"},
+        {"a", 
+         "\xbd\xe5\x2c\xb3\x1d\xe3\x3e\x46\x24\x5e\x05\xfb\xdb\xd6\xfb\x24"},
+        {"abc", 
+         "\xa4\x48\x01\x7a\xaf\x21\xd8\x52\x5f\xc1\x0a\xe8\x7a\xa6\x72\x9d"},
+        {"message digest", 
+         "\xd9\x13\x0a\x81\x64\x54\x9f\xe8\x18\x87\x48\x06\xe1\xc7\x01\x4b"},
+        {"abcdefghijklmnopqrstuvwxyz", 
+         "\xd7\x9e\x1c\x30\x8a\xa5\xbb\xcd\xee\xa8\xed\x63\xdf\x41\x2d\xa9"},
+        {"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 
+         "\x04\x3f\x85\x82\xf2\x41\xdb\x35\x1c\xe6\x27\xe1\x53\xe7\xf0\xe4"},
+        {"12345678901234567890123456789012345678901234567890123456789012345678901234567890", 
+         "\xe3\x3b\x4d\xdc\x9c\x38\xf2\x19\x9c\x3e\x7b\x16\x4f\xcc\x05\x36"}
+};
+
+static int num_sums = sizeof(md4sums) / sizeof(md4sums[0]); 
+static int count;
+
+#if 0
+static int MDStringComp(const void *string, const void *sum)
+{
+        apr_md4_ctx_t context;
+        unsigned char digest[APR_MD4_DIGESTSIZE];
+        unsigned int len = strlen(string);
+
+        apr_md4_init(&context);
+        apr_md4_update(&context, (unsigned char *)string, len);
+        apr_md4_final(digest, &context);
+        return (memcmp(digest, sum, APR_MD4_DIGESTSIZE));
+
+}
+#endif
+
+static void test_md4sum(abts_case *tc, void *data)
+{
+        apr_md4_ctx_t context;
+        unsigned char digest[APR_MD4_DIGESTSIZE];
+        const void *string = md4sums[count].string;
+        const void *sum = md4sums[count].md4sum;
+        unsigned int len = strlen(string);
+
+        ABTS_ASSERT(tc, "apr_md4_init", (apr_md4_init(&context) == 0));
+        ABTS_ASSERT(tc, "apr_md4_update", 
+                    (apr_md4_update(&context, 
+                                    (unsigned char *)string, len) == 0));
+        
+        ABTS_ASSERT(tc, "apr_md4_final", (apr_md4_final(digest, &context) ==0));
+        ABTS_ASSERT(tc, "check for correct md4 digest", 
+                    (memcmp(digest, sum, APR_MD4_DIGESTSIZE) == 0));
+}
+
+abts_suite *testmd4(abts_suite *suite)
+{
+        suite = ADD_SUITE(suite);
+
+        for (count=0; count < num_sums; count++) {
+            abts_run_test(suite, test_md4sum, NULL);
+        }
+
+        return suite;
+}
diff --git a/test/testmd5.c b/test/testmd5.c
new file mode 100644
index 00000000000..4e13da2371a
--- /dev/null
+++ b/test/testmd5.c
@@ -0,0 +1,103 @@
+/* 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 <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "apr_md5.h"
+#include "apr_xlate.h"
+#include "apr_general.h"
+
+#include "abts.h"
+#include "testutil.h"
+
+static struct {
+    const char *string;
+    const char *digest;
+} md5sums[] = 
+{
+    {"Jeff was here!",
+     "\xa5\x25\x8a\x89\x11\xb2\x9d\x1f\x81\x75\x96\x3b\x60\x94\x49\xc0"},
+    {"01234567890aBcDeFASDFGHJKLPOIUYTR"
+     "POIUYTREWQZXCVBN  LLLLLLLLLLLLLLL",
+     "\xd4\x1a\x06\x2c\xc5\xfd\x6f\x24\x67\x68\x56\x7c\x40\x8a\xd5\x69"},
+    {"111111118888888888888888*******%%%%%%%%%%#####"
+     "142134u8097289720432098409289nkjlfkjlmn,m..   ",
+     "\xb6\xea\x5b\xe8\xca\x45\x8a\x33\xf0\xf1\x84\x6f\xf9\x65\xa8\xe1"},
+    {"01234567890aBcDeFASDFGHJKLPOIUYTR"
+     "POIUYTREWQZXCVBN  LLLLLLLLLLLLLLL"
+     "01234567890aBcDeFASDFGHJKLPOIUYTR"
+     "POIUYTREWQZXCVBN  LLLLLLLLLLLLLLL"
+     "1",
+     "\xd1\xa1\xc0\x97\x8a\x60\xbb\xfb\x2a\x25\x46\x9d\xa5\xae\xd0\xb0"}
+};
+
+static int num_sums = sizeof(md5sums) / sizeof(md5sums[0]);
+static int count;
+
+static void test_md5sum(abts_case *tc, void *data)
+{
+        apr_md5_ctx_t context;
+        unsigned char digest[APR_MD5_DIGESTSIZE];
+        const void *string = md5sums[count].string;
+        const void *sum = md5sums[count].digest;
+        unsigned int len = strlen(string);
+
+        ABTS_ASSERT(tc, "apr_md5_init", (apr_md5_init(&context) == 0));
+        ABTS_ASSERT(tc, "apr_md5_update", 
+                    (apr_md5_update(&context, string, len) == 0));
+        ABTS_ASSERT(tc, "apr_md5_final", (apr_md5_final(digest, &context)
+                                          == 0));
+        ABTS_ASSERT(tc, "check for correct md5 digest",
+                    (memcmp(digest, sum, APR_MD5_DIGESTSIZE) == 0));
+}
+
+static void test_md5sum_unaligned(abts_case *tc, void *data)
+{
+        apr_md5_ctx_t context;
+        const char *string = "abcdefghijklmnopqrstuvwxyz01234"
+                             "abcdefghijklmnopqrstuvwxyz01234"
+                             "abcdefghijklmnopqrstuvwxyz01234"
+                             "abcdefghijklmnopqrstuvwxyz01234_";
+        const char *sum =
+            "\x93\x17\x22\x78\xee\x30\x82\xb3\xeb\x95\x33\xec\xea\x78\xb7\x89";
+        unsigned char digest[APR_MD5_DIGESTSIZE];
+        unsigned int i;
+
+        ABTS_ASSERT(tc, "apr_md5_init", (apr_md5_init(&context) == 0));
+        for (i = 0; i < 10; i++) {
+                ABTS_ASSERT(tc, "apr_md5_update",
+                    (apr_md5_update(&context, string, strlen(string)) == 0));
+                string++;
+        }
+        ABTS_ASSERT(tc, "apr_md5_final", (apr_md5_final(digest, &context)
+                                          == 0));
+        ABTS_ASSERT(tc, "check for correct md5 digest of unaligned data",
+                    (memcmp(digest, sum, APR_MD5_DIGESTSIZE) == 0));
+}
+
+abts_suite *testmd5(abts_suite *suite)
+{
+        suite = ADD_SUITE(suite);
+        
+        for (count=0; count < num_sums; count++) {
+            abts_run_test(suite, test_md5sum, NULL);
+        }
+        abts_run_test(suite, test_md5sum_unaligned, NULL);
+
+        return suite;
+}
diff --git a/test/testmemcache.c b/test/testmemcache.c
new file mode 100644
index 00000000000..4ac3694dbfc
--- /dev/null
+++ b/test/testmemcache.c
@@ -0,0 +1,627 @@
+/* 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 "testutil.h"
+#include "apr.h"
+#include "apu.h"
+#include "apr_general.h"
+#include "apr_strings.h"
+#include "apr_hash.h"
+#include "apr_memcache.h"
+#include "apr_network_io.h"
+#include "apr_thread_proc.h"
+
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h>             /* for exit() */
+#endif
+
+#define HOST "localhost"
+#define PORT 11211
+
+/* the total number of items to use for set/get testing */
+#define TDATA_SIZE 3000
+
+/* some smaller subset of TDATA_SIZE used for multiget testing */
+#define TDATA_SET 100
+
+/* our custom hash function just returns this all the time */
+#define HASH_FUNC_RESULT 510
+
+/* all keys will be prefixed with this */
+const char prefix[] = "testmemcache";
+
+/* text for values we store */
+const char txt[] =
+"Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Duis at"
+"lacus in ligula hendrerit consectetuer. Vestibulum tristique odio"
+"iaculis leo. In massa arcu, ultricies a, laoreet nec, hendrerit non,"
+"neque. Nulla sagittis sapien ac risus. Morbi ligula dolor, vestibulum"
+"nec, viverra id, placerat dapibus, arcu. Curabitur egestas feugiat"
+"tellus. Donec dignissim. Nunc ante. Curabitur id lorem. In mollis"
+"tortor sit amet eros auctor dapibus. Proin nulla sem, tristique in,"
+"convallis id, iaculis feugiat cras amet.";
+
+/*
+ * this datatype is for our custom server determination function. this might
+ * be useful if you don't want to rely on simply hashing keys to determine
+ * where a key belongs, but instead want to write something fancy, or use some
+ * other kind of configuration data, i.e. a hash plus some data about a
+ * namespace, or whatever. see my_server_func, and test_memcache_user_funcs
+ * for the examples.
+ */
+typedef struct {
+  const char *someval;
+  apr_uint32_t which_server;
+} my_hash_server_baton;
+
+
+/* this could do something fancy and return some hash result.
+ * for simplicity, just return the same value, so we can test it later on.
+ * if you wanted to use some external hashing library or functions for
+ * consistent hashing, for example, this would be a good place to do it.
+ */
+static apr_uint32_t my_hash_func(void *baton, const char *data,
+                                 apr_size_t data_len)
+{
+
+  return HASH_FUNC_RESULT;
+}
+
+/*
+ * a fancy function to determine which server to use given some kind of data
+ * and a hash value. this example actually ignores the hash value itself
+ * and pulls some number from the *baton, which is a struct that has some
+ * kind of meaningful stuff in it.
+ */
+static apr_memcache_server_t *my_server_func(void *baton,
+                                             apr_memcache_t *mc,
+                                             const apr_uint32_t hash)
+{
+  apr_memcache_server_t *ms = NULL;
+  my_hash_server_baton *mhsb = (my_hash_server_baton *)baton;
+
+  if(mc->ntotal == 0) {
+    return NULL;
+  }
+
+  if(mc->ntotal < mhsb->which_server) {
+    return NULL;
+  }
+
+  ms = mc->live_servers[mhsb->which_server - 1];
+
+  return ms;
+}
+
+apr_uint16_t firsttime = 0;
+static int randval(apr_uint32_t high)
+{
+    apr_uint32_t i = 0;
+    double d = 0;
+
+    if (firsttime == 0) {
+        srand((unsigned) (getpid()));
+        firsttime = 1;
+    }
+
+    d = (double) rand() / ((double) RAND_MAX + 1);
+    i = (int) (d * (high - 0 + 1));
+
+    return i > 0 ? i : 1;
+}
+
+/*
+ * general test to make sure we can create the memcache struct and add
+ * some servers, but not more than we tell it we can add
+ */
+
+static void test_memcache_create(abts_case * tc, void *data)
+{
+  apr_pool_t *pool = p;
+  apr_status_t rv;
+  apr_memcache_t *memcache;
+  apr_memcache_server_t *server, *s;
+  apr_uint32_t max_servers = 10;
+  apr_uint32_t i;
+  apr_uint32_t hash;
+
+  rv = apr_memcache_create(pool, max_servers, 0, &memcache);
+  ABTS_ASSERT(tc, "memcache create failed", rv == APR_SUCCESS);
+
+  for (i = 1; i <= max_servers; i++) {
+    apr_port_t port;
+
+    port = PORT + i;
+    rv =
+      apr_memcache_server_create(pool, HOST, PORT + i, 0, 1, 1, 60, &server);
+    ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS);
+
+    rv = apr_memcache_add_server(memcache, server);
+    ABTS_ASSERT(tc, "server add failed", rv == APR_SUCCESS);
+
+    s = apr_memcache_find_server(memcache, HOST, port);
+    ABTS_PTR_EQUAL(tc, server, s);
+
+    rv = apr_memcache_disable_server(memcache, s);
+    ABTS_ASSERT(tc, "server disable failed", rv == APR_SUCCESS);
+
+    rv = apr_memcache_enable_server(memcache, s);
+    ABTS_ASSERT(tc, "server enable failed", rv == APR_SUCCESS);
+
+    hash = apr_memcache_hash(memcache, prefix, strlen(prefix));
+    ABTS_ASSERT(tc, "hash failed", hash > 0);
+
+    s = apr_memcache_find_server_hash(memcache, hash);
+    ABTS_PTR_NOTNULL(tc, s);
+  }
+
+  rv = apr_memcache_server_create(pool, HOST, PORT, 0, 1, 1, 60, &server);
+  ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS);
+
+  rv = apr_memcache_add_server(memcache, server);
+  ABTS_ASSERT(tc, "server add should have failed", rv != APR_SUCCESS);
+
+}
+
+/* install our own custom hashing and server selection routines. */
+
+static int create_test_hash(apr_pool_t *p, apr_hash_t *h)
+{
+  int i;
+
+  for (i = 0; i < TDATA_SIZE; i++) {
+    char *k, *v;
+
+    k = apr_pstrcat(p, prefix, apr_itoa(p, i), NULL);
+    v = apr_pstrndup(p, txt, randval((apr_uint32_t)strlen(txt)));
+
+    apr_hash_set(h, k, APR_HASH_KEY_STRING, v);
+  }
+
+  return i;
+}
+
+static void test_memcache_user_funcs(abts_case * tc, void *data)
+{
+  apr_pool_t *pool = p;
+  apr_status_t rv;
+  apr_memcache_t *memcache;
+  apr_memcache_server_t *found;
+  apr_uint32_t max_servers = 10;
+  apr_uint32_t hres;
+  apr_uint32_t i;
+  my_hash_server_baton *baton =
+    apr_pcalloc(pool, sizeof(my_hash_server_baton));
+
+  rv = apr_memcache_create(pool, max_servers, 0, &memcache);
+  ABTS_ASSERT(tc, "memcache create failed", rv == APR_SUCCESS);
+
+  /* as noted above, install our custom hash function, and call
+   * apr_memcache_hash. the return value should be our predefined number,
+   * and our function just ignores the other args, for simplicity.
+   */
+  memcache->hash_func = my_hash_func;
+
+  hres = apr_memcache_hash(memcache, "whatever", sizeof("whatever") - 1);
+  ABTS_INT_EQUAL(tc, HASH_FUNC_RESULT, hres);
+
+  /* add some servers */
+  for(i = 1; i <= 10; i++) {
+    apr_memcache_server_t *ms;
+
+    rv = apr_memcache_server_create(pool, HOST, i, 0, 1, 1, 60, &ms);
+    ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS);
+
+    rv = apr_memcache_add_server(memcache, ms);
+    ABTS_ASSERT(tc, "server add failed", rv == APR_SUCCESS);
+  }
+
+  /*
+   * set 'which_server' in our server_baton to find the third server
+   * which should have the same port.
+   */
+  baton->which_server = 3;
+  memcache->server_func = my_server_func;
+  memcache->server_baton = baton;
+  found = apr_memcache_find_server_hash(memcache, 0);
+  ABTS_ASSERT(tc, "wrong server found", found->port == baton->which_server);
+}
+
+/* test non data related commands like stats and version */
+static void test_memcache_meta(abts_case * tc, void *data)
+{
+    apr_pool_t *pool = p;
+    apr_memcache_t *memcache;
+    apr_memcache_server_t *server;
+    apr_memcache_stats_t *stats;
+    char *result;
+    apr_status_t rv;
+
+    rv = apr_memcache_create(pool, 1, 0, &memcache);
+    ABTS_ASSERT(tc, "memcache create failed", rv == APR_SUCCESS);
+
+    rv = apr_memcache_server_create(pool, HOST, PORT, 0, 1, 1, 60, &server);
+    ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS);
+
+    rv = apr_memcache_add_server(memcache, server);
+    ABTS_ASSERT(tc, "server add failed", rv == APR_SUCCESS);
+
+    rv = apr_memcache_version(server, pool, &result);
+    ABTS_PTR_NOTNULL(tc, result);
+
+    rv = apr_memcache_stats(server, p, &stats);
+    ABTS_PTR_NOTNULL(tc, stats);
+
+    ABTS_STR_NEQUAL(tc, stats->version, result, 5);
+
+    /*
+     * no way to know exactly what will be in most of these, so
+     * just make sure there is something.
+     */
+
+    ABTS_ASSERT(tc, "pid", stats->pid >= 0);
+    ABTS_ASSERT(tc, "time", stats->time >= 0);
+    /* ABTS_ASSERT(tc, "pointer_size", stats->pointer_size >= 0); */
+    ABTS_ASSERT(tc, "rusage_user", stats->rusage_user >= 0);
+    ABTS_ASSERT(tc, "rusage_system", stats->rusage_system >= 0);
+
+    ABTS_ASSERT(tc, "curr_items", stats->curr_items >= 0);
+    ABTS_ASSERT(tc, "total_items", stats->total_items >= 0);
+    ABTS_ASSERT(tc, "bytes", stats->bytes >= 0);
+
+    ABTS_ASSERT(tc, "curr_connections", stats->curr_connections >= 0);
+    ABTS_ASSERT(tc, "total_connections", stats->total_connections >= 0);
+    ABTS_ASSERT(tc, "connection_structures",
+                stats->connection_structures >= 0);
+
+    ABTS_ASSERT(tc, "cmd_get", stats->cmd_get >= 0);
+    ABTS_ASSERT(tc, "cmd_set", stats->cmd_set >= 0);
+    ABTS_ASSERT(tc, "get_hits", stats->get_hits >= 0);
+    ABTS_ASSERT(tc, "get_misses", stats->get_misses >= 0);
+
+    /* ABTS_ASSERT(tc, "evictions", stats->evictions >= 0); */
+
+    ABTS_ASSERT(tc, "bytes_read", stats->bytes_read >= 0);
+    ABTS_ASSERT(tc, "bytes_written", stats->bytes_written >= 0);
+    ABTS_ASSERT(tc, "limit_maxbytes", stats->limit_maxbytes >= 0);
+
+    /* ABTS_ASSERT(tc, "threads", stats->threads >= 0); */
+}
+
+/* test add and replace calls */
+
+static void test_memcache_addreplace(abts_case * tc, void *data)
+{
+ apr_pool_t *pool = p;
+ apr_status_t rv;
+ apr_memcache_t *memcache;
+ apr_memcache_server_t *server;
+ apr_hash_t *tdata;
+ apr_hash_index_t *hi;
+ char *result;
+ apr_size_t len;
+
+  rv = apr_memcache_create(pool, 1, 0, &memcache);
+  ABTS_ASSERT(tc, "memcache create failed", rv == APR_SUCCESS);
+
+  rv = apr_memcache_server_create(pool, HOST, PORT, 0, 1, 1, 60, &server);
+  ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS);
+
+  rv = apr_memcache_add_server(memcache, server);
+  ABTS_ASSERT(tc, "server add failed", rv == APR_SUCCESS);
+
+  tdata = apr_hash_make(p);
+  create_test_hash(pool, tdata);
+
+  for (hi = apr_hash_first(p, tdata); hi; hi = apr_hash_next(hi)) {
+    const void *k;
+    void *v;
+    const char *key;
+
+    apr_hash_this(hi, &k, NULL, &v);
+    key = k;
+
+    /* doesn't exist yet, fail */
+    rv = apr_memcache_replace(memcache, key, v, strlen(v) - 1, 0, 27);
+    ABTS_ASSERT(tc, "replace should have failed", rv != APR_SUCCESS);
+
+    /* doesn't exist yet, succeed */
+    rv = apr_memcache_add(memcache, key, v, strlen(v), 0, 27);
+    ABTS_ASSERT(tc, "add failed", rv == APR_SUCCESS);
+
+    /* exists now, succeed */
+    rv = apr_memcache_replace(memcache, key, "new", sizeof("new") - 1, 0, 27);
+    ABTS_ASSERT(tc, "replace failed", rv == APR_SUCCESS);
+
+    /* make sure its different */
+    rv = apr_memcache_getp(memcache, pool, key, &result, &len, NULL);
+    ABTS_ASSERT(tc, "get failed", rv == APR_SUCCESS);
+    ABTS_STR_NEQUAL(tc, result, "new", 3);
+
+    /* exists now, fail */
+    rv = apr_memcache_add(memcache, key, v, strlen(v), 0, 27);
+    ABTS_ASSERT(tc, "add should have failed", rv != APR_SUCCESS);
+
+    /* clean up */
+    rv = apr_memcache_delete(memcache, key, 0);
+    ABTS_ASSERT(tc, "delete failed", rv == APR_SUCCESS);
+  }
+}
+
+/* basic tests of the increment and decrement commands */
+static void test_memcache_incrdecr(abts_case * tc, void *data)
+{
+ apr_pool_t *pool = p;
+ apr_status_t rv;
+ apr_memcache_t *memcache;
+ apr_memcache_server_t *server;
+ apr_uint32_t new;
+ char *result;
+ apr_size_t len;
+ apr_uint32_t i;
+
+  rv = apr_memcache_create(pool, 1, 0, &memcache);
+  ABTS_ASSERT(tc, "memcache create failed", rv == APR_SUCCESS);
+
+  rv = apr_memcache_server_create(pool, HOST, PORT, 0, 1, 1, 60, &server);
+  ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS);
+
+  rv = apr_memcache_add_server(memcache, server);
+  ABTS_ASSERT(tc, "server add failed", rv == APR_SUCCESS);
+
+  rv = apr_memcache_set(memcache, prefix, "271", sizeof("271") - 1, 0, 27);
+  ABTS_ASSERT(tc, "set failed", rv == APR_SUCCESS);
+
+  for( i = 1; i <= TDATA_SIZE; i++) {
+    apr_uint32_t expect;
+
+    rv = apr_memcache_getp(memcache, pool, prefix, &result, &len, NULL);
+    ABTS_ASSERT(tc, "get failed", rv == APR_SUCCESS);
+
+    expect = i + atoi(result);
+
+    rv = apr_memcache_incr(memcache, prefix, i, &new);
+    ABTS_ASSERT(tc, "incr failed", rv == APR_SUCCESS);
+
+    ABTS_INT_EQUAL(tc, expect, new);
+
+    rv = apr_memcache_decr(memcache, prefix, i, &new);
+    ABTS_ASSERT(tc, "decr failed", rv == APR_SUCCESS);
+    ABTS_INT_EQUAL(tc, atoi(result), new);
+
+  }
+
+  rv = apr_memcache_getp(memcache, pool, prefix, &result, &len, NULL);
+  ABTS_ASSERT(tc, "get failed", rv == APR_SUCCESS);
+
+  ABTS_INT_EQUAL(tc, 271, atoi(result));
+
+  rv = apr_memcache_delete(memcache, prefix, 0);
+  ABTS_ASSERT(tc, "delete failed", rv == APR_SUCCESS);
+}
+
+/* test the multiget functionality */
+static void test_memcache_multiget(abts_case * tc, void *data)
+{
+  apr_pool_t *pool = p;
+  apr_pool_t *tmppool;
+  apr_status_t rv;
+  apr_memcache_t *memcache;
+  apr_memcache_server_t *server;
+  apr_hash_t *tdata, *values;
+  apr_hash_index_t *hi;
+  apr_uint32_t i;
+
+  rv = apr_memcache_create(pool, 1, 0, &memcache);
+  ABTS_ASSERT(tc, "memcache create failed", rv == APR_SUCCESS);
+
+  rv = apr_memcache_server_create(pool, HOST, PORT, 0, 1, 1, 60, &server);
+  ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS);
+
+  rv = apr_memcache_add_server(memcache, server);
+  ABTS_ASSERT(tc, "server add failed", rv == APR_SUCCESS);
+
+  values = apr_hash_make(p);
+  tdata = apr_hash_make(p);
+
+  create_test_hash(pool, tdata);
+
+  for (hi = apr_hash_first(p, tdata); hi; hi = apr_hash_next(hi)) {
+    const void *k;
+    void *v;
+    const char *key;
+
+    apr_hash_this(hi, &k, NULL, &v);
+    key = k;
+
+    rv = apr_memcache_set(memcache, key, v, strlen(v), 0, 27);
+    ABTS_ASSERT(tc, "set failed", rv == APR_SUCCESS);
+  }
+
+  rv = apr_pool_create(&tmppool, pool);
+  for (i = 0; i < TDATA_SET; i++)
+    apr_memcache_add_multget_key(pool,
+                                 apr_pstrcat(pool, prefix,
+                                             apr_itoa(pool, i), NULL),
+                                 &values);
+
+  rv = apr_memcache_multgetp(memcache,
+                             tmppool,
+                             pool,
+                             values);
+
+  ABTS_ASSERT(tc, "multgetp failed", rv == APR_SUCCESS);
+  ABTS_ASSERT(tc, "multgetp returned too few results",
+              apr_hash_count(values) == TDATA_SET);
+
+  for (hi = apr_hash_first(p, tdata); hi; hi = apr_hash_next(hi)) {
+    const void *k;
+    const char *key;
+
+    apr_hash_this(hi, &k, NULL, NULL);
+    key = k;
+
+    rv = apr_memcache_delete(memcache, key, 0);
+    ABTS_ASSERT(tc, "delete failed", rv == APR_SUCCESS);
+  }
+
+}
+
+/* test setting and getting */
+
+static void test_memcache_setget(abts_case * tc, void *data)
+{
+    apr_pool_t *pool = p;
+    apr_status_t rv;
+    apr_memcache_t *memcache;
+    apr_memcache_server_t *server;
+    apr_hash_t *tdata;
+    apr_hash_index_t *hi;
+    char *result;
+    apr_size_t len;
+
+    rv = apr_memcache_create(pool, 1, 0, &memcache);
+    ABTS_ASSERT(tc, "memcache create failed", rv == APR_SUCCESS);
+
+    rv = apr_memcache_server_create(pool, HOST, PORT, 0, 1, 1, 60, &server);
+    ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS);
+
+    rv = apr_memcache_add_server(memcache, server);
+    ABTS_ASSERT(tc, "server add failed", rv == APR_SUCCESS);
+
+    tdata = apr_hash_make(pool);
+
+    create_test_hash(pool, tdata);
+
+    for (hi = apr_hash_first(p, tdata); hi; hi = apr_hash_next(hi)) {
+        const void *k;
+        void *v;
+        const char *key;
+
+        apr_hash_this(hi, &k, NULL, &v);
+        key = k;
+
+        rv = apr_memcache_set(memcache, key, v, strlen(v), 0, 27);
+        ABTS_ASSERT(tc, "set failed", rv == APR_SUCCESS);
+        rv = apr_memcache_getp(memcache, pool, key, &result, &len, NULL);
+        ABTS_ASSERT(tc, "get failed", rv == APR_SUCCESS);
+    }
+
+    rv = apr_memcache_getp(memcache, pool, "nothere3423", &result, &len, NULL);
+
+    ABTS_ASSERT(tc, "get should have failed", rv != APR_SUCCESS);
+
+    for (hi = apr_hash_first(p, tdata); hi; hi = apr_hash_next(hi)) {
+        const void *k;
+        const char *key;
+
+        apr_hash_this(hi, &k, NULL, NULL);
+        key = k;
+
+        rv = apr_memcache_delete(memcache, key, 0);
+        ABTS_ASSERT(tc, "delete failed", rv == APR_SUCCESS);
+    }
+}
+
+/* use apr_socket stuff to see if there is in fact a memcached server
+ * running on PORT.
+ */
+static apr_status_t check_mc(void)
+{
+  apr_pool_t *pool = p;
+  apr_status_t rv;
+  apr_socket_t *sock = NULL;
+  apr_sockaddr_t *sa;
+  struct iovec vec[2];
+  apr_size_t written;
+  char buf[128];
+  apr_size_t len;
+
+  rv = apr_socket_create(&sock, APR_INET, SOCK_STREAM, 0, pool);
+  if(rv != APR_SUCCESS) {
+    return rv;
+  }
+
+  rv = apr_sockaddr_info_get(&sa, HOST, APR_INET, PORT, 0, pool);
+  if(rv != APR_SUCCESS) {
+    return rv;
+  }
+
+  rv = apr_socket_timeout_set(sock, 1 * APR_USEC_PER_SEC);
+  if (rv != APR_SUCCESS) {
+    return rv;
+  }
+
+  rv = apr_socket_connect(sock, sa);
+  if (rv != APR_SUCCESS) {
+    return rv;
+  }
+
+  rv = apr_socket_timeout_set(sock, -1);
+  if (rv != APR_SUCCESS) {
+    return rv;
+  }
+
+  vec[0].iov_base = "version";
+  vec[0].iov_len  = sizeof("version") - 1;
+
+  vec[1].iov_base = "\r\n";
+  vec[1].iov_len  = sizeof("\r\n") -1;
+
+  rv = apr_socket_sendv(sock, vec, 2, &written);
+  if (rv != APR_SUCCESS) {
+    return rv;
+  }
+
+  len = sizeof(buf);
+  rv = apr_socket_recv(sock, buf, &len);
+  if(rv != APR_SUCCESS) {
+    return rv;
+  }
+
+  if(strncmp(buf, "VERSION", sizeof("VERSION")-1) != 0) {
+    rv = APR_EGENERAL;
+  }
+
+  apr_socket_close(sock);
+  return rv;
+}
+
+abts_suite *testmemcache(abts_suite * suite)
+{
+    apr_status_t rv;
+    suite = ADD_SUITE(suite);
+    /* check for a running memcached on the typical port before
+     * trying to run the tests. succeed if we don't find one.
+     */
+    rv = check_mc();
+    if (rv == APR_SUCCESS) {
+      abts_run_test(suite, test_memcache_create, NULL);
+      abts_run_test(suite, test_memcache_user_funcs, NULL);
+      abts_run_test(suite, test_memcache_meta, NULL);
+      abts_run_test(suite, test_memcache_setget, NULL);
+      abts_run_test(suite, test_memcache_multiget, NULL);
+      abts_run_test(suite, test_memcache_addreplace, NULL);
+      abts_run_test(suite, test_memcache_incrdecr, NULL);
+    }
+    else {
+        abts_log_message("Error %d occurred attempting to reach memcached "
+                         "on %s:%d.  Skipping apr_memcache tests...",
+                         rv, HOST, PORT);
+    }
+
+    return suite;
+}
diff --git a/test/testmmap.c b/test/testmmap.c
index 3f58ec3c6f6..aeff1a66a1f 100644
--- a/test/testmmap.c
+++ b/test/testmmap.c
@@ -1,135 +1,166 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
+#include "testutil.h"
 #include "apr_mmap.h"
 #include "apr_errno.h"
 #include "apr_general.h"
 #include "apr_lib.h"
 #include "apr_file_io.h"
+#include "apr_strings.h"
 
 /* hmmm, what is a truly portable define for the max path
  * length on a platform?
  */
 #define PATH_LEN 255
 
-int main()
+#if !APR_HAS_MMAP
+static void not_implemented(abts_case *tc, void *data)
+{
+    ABTS_NOT_IMPL(tc, "MMAP functions");
+}
+
+#else
+
+static char test_string[256]; /* read from the datafile */
+static apr_mmap_t *themmap = NULL;
+static apr_file_t *thefile = NULL;
+static char *file1;
+static apr_finfo_t thisfinfo;
+static apr_size_t thisfsize;
+
+static void create_filename(abts_case *tc, void *data)
+{
+    char *oldfileptr;
+
+    apr_filepath_get(&file1, 0, p);
+#ifndef NETWARE
+#ifdef WIN32
+    ABTS_TRUE(tc, file1[1] == ':');
+#else
+    ABTS_TRUE(tc, file1[0] == '/');
+#endif
+#endif
+    ABTS_TRUE(tc, file1[strlen(file1) - 1] != '/');
+
+    oldfileptr = file1;
+    file1 = apr_pstrcat(p, file1,"/data/mmap_datafile.txt" ,NULL);
+    ABTS_TRUE(tc, oldfileptr != file1);
+}
+
+static void test_file_close(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+
+    rv = apr_file_close(thefile);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+}
+   
+static void read_expected_contents(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_size_t nbytes = sizeof(test_string) - 1;
+
+    rv = apr_file_read(thefile, test_string, &nbytes);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    test_string[nbytes] = '\0';
+    thisfsize = strlen(test_string);
+}
+
+static void test_file_open(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+
+    rv = apr_file_open(&thefile, file1, APR_FOPEN_READ,
+                       APR_FPROT_UREAD | APR_FPROT_GREAD, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_PTR_NOTNULL(tc, thefile);
+}
+   
+static void test_get_filesize(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+
+    rv = apr_file_info_get(&thisfinfo, APR_FINFO_NORM, thefile);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_ASSERT(tc, "File size mismatch", thisfsize == thisfinfo.size);
+}
+
+static void test_mmap_create(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+
+    rv = apr_mmap_create(&themmap, thefile, 0, (apr_size_t) thisfinfo.size, 
+		                 APR_MMAP_READ, p);
+    ABTS_PTR_NOTNULL(tc, themmap);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+}
+
+static void test_mmap_contents(abts_case *tc, void *data)
 {
-    ap_pool_t *context;
-    ap_mmap_t *themmap = NULL;
-    ap_file_t *thefile = NULL;
-    ap_finfo_t finfo;
-    ap_int32_t flag = APR_READ;
-    char *file1;
-    
-    fprintf (stdout,"APR MMAP Test\n*************\n\n");
-    
-    fprintf(stdout,"Initializing........................");
-    if (ap_initialize() != APR_SUCCESS) {
-        fprintf(stderr, "Failed.\n");
-        exit(-1);
-    }
-    fprintf(stdout,"OK\n");
-    atexit(ap_terminate);
-
-    fprintf(stdout,"Creating context....................");    
-    if (ap_create_pool(&context, NULL) != APR_SUCCESS) {
-        fprintf(stderr, "Failed.\n");
-        exit(-1);
-    }
-    fprintf(stdout,"OK\n");
-    
-    file1 = (char*) ap_palloc(context, sizeof(char) * PATH_LEN);
-    getcwd(file1, PATH_LEN);
-    strncat(file1,"/testmmap.c",11);  
-
-    fprintf(stdout, "Opening file........................");
-    if (ap_open(&thefile, file1, flag, APR_UREAD | APR_GREAD, context) != APR_SUCCESS) {
-        perror("Didn't open file");
-        exit(-1);
-    }
-    else {
-        fprintf(stdout, "OK\n");
-    }
-    
-    fprintf(stderr, "Getting file size...................");
-    if (ap_getfileinfo(&finfo, thefile) != APR_SUCCESS) {
-        perror("Didn't get file information!");
-        exit(-1);
-    }
-    else {
-        fprintf(stdout, "%d bytes\n", (int)finfo.size);
-    }  
-    
-    fprintf(stdout,"Trying to mmap the file.............");
-    if (ap_mmap_create(&themmap, thefile, 0, finfo.size, context) != APR_SUCCESS) {
-        fprintf(stderr,"Failed!\n");
-        exit(-1);
-    }
-    fprintf(stdout,"OK\n");
-
-    fprintf(stdout,"Trying to delete the mmap file......");
-    if (ap_mmap_delete(themmap) != APR_SUCCESS) {
-        fprintf(stderr,"Failed!\n");
-        exit (-1);
-    }
-    fprintf(stdout,"OK\n");
     
-    fprintf (stdout,"\nTest Complete\n");
+    ABTS_PTR_NOTNULL(tc, themmap);
+    ABTS_PTR_NOTNULL(tc, themmap->mm);
+    ABTS_SIZE_EQUAL(tc, thisfsize, themmap->size);
 
-    return 1;
+    /* Must use nEquals since the string is not guaranteed to be NULL terminated */
+    ABTS_STR_NEQUAL(tc, themmap->mm, test_string, thisfsize);
 }
+
+static void test_mmap_delete(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+
+    ABTS_PTR_NOTNULL(tc, themmap);
+    rv = apr_mmap_delete(themmap);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+}
+
+static void test_mmap_offset(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    void *addr;
+
+    ABTS_PTR_NOTNULL(tc, themmap);
+    rv = apr_mmap_offset(&addr, themmap, 5);
+
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    /* Must use nEquals since the string is not guaranteed to be NULL terminated */
+    ABTS_STR_NEQUAL(tc, addr, test_string + 5, thisfsize-5);
+}
+#endif
+
+abts_suite *testmmap(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite)
+
+#if APR_HAS_MMAP    
+    abts_run_test(suite, create_filename, NULL);
+    abts_run_test(suite, test_file_open, NULL);
+    abts_run_test(suite, read_expected_contents, NULL);
+    abts_run_test(suite, test_get_filesize, NULL);
+    abts_run_test(suite, test_mmap_create, NULL);
+    abts_run_test(suite, test_mmap_contents, NULL);
+    abts_run_test(suite, test_mmap_offset, NULL);
+    abts_run_test(suite, test_mmap_delete, NULL);
+    abts_run_test(suite, test_file_close, NULL);
+#else
+    abts_run_test(suite, not_implemented, NULL);
+#endif
+
+    return suite;
+}
+
diff --git a/test/testmutexscope.c b/test/testmutexscope.c
new file mode 100644
index 00000000000..2120fff24f5
--- /dev/null
+++ b/test/testmutexscope.c
@@ -0,0 +1,234 @@
+/* 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 program won't run or check correctly if assert() is disabled. */
+#undef NDEBUG
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "apr.h"
+#include "apr_general.h"
+#include "apr_proc_mutex.h"
+#include "apr_global_mutex.h"
+#include "apr_thread_proc.h"
+
+#if !APR_HAS_THREADS
+int main(void)
+{
+    printf("This test requires APR thread support.\n");
+    return 0;
+}
+
+#else /* APR_HAS_THREADS */
+
+static apr_thread_mutex_t *thread_mutex;
+static apr_proc_mutex_t *proc_mutex;
+static apr_global_mutex_t *global_mutex;
+static apr_pool_t *p;
+static volatile int counter;
+typedef enum {TEST_GLOBAL, TEST_PROC} test_mode_e;
+
+static int lock_init(apr_lockmech_e mech, test_mode_e test_mode)
+{
+    apr_status_t rv;
+    if (test_mode == TEST_PROC) {
+        rv = apr_proc_mutex_create(&proc_mutex,
+                                           NULL,
+                                           mech,
+                                           p);
+    }
+    else {
+        rv = apr_global_mutex_create(&global_mutex,
+                                     NULL,
+                                     mech,
+                                     p);
+    }
+    return rv;
+}
+
+static void lock_destroy(test_mode_e test_mode)
+{
+    if (test_mode == TEST_PROC) {
+        assert(apr_proc_mutex_destroy(proc_mutex) == APR_SUCCESS);
+    }
+    else {
+        assert(apr_global_mutex_destroy(global_mutex) == APR_SUCCESS);
+    }
+}
+
+static void lock_grab(test_mode_e test_mode)
+{
+    if (test_mode == TEST_PROC) {
+        assert(apr_proc_mutex_lock(proc_mutex) == APR_SUCCESS);
+    }
+    else {
+        assert(apr_global_mutex_lock(global_mutex) == APR_SUCCESS);
+    }
+}
+
+static void lock_release(test_mode_e test_mode)
+{
+    if (test_mode == TEST_PROC) {
+        assert(apr_proc_mutex_unlock(proc_mutex) == APR_SUCCESS);
+    }
+    else {
+        assert(apr_global_mutex_unlock(global_mutex) == APR_SUCCESS);
+    }
+}
+
+static void * APR_THREAD_FUNC eachThread(apr_thread_t *id, void *p)
+{
+    test_mode_e test_mode = (test_mode_e)p;
+
+    lock_grab(test_mode);
+    ++counter;
+    assert(apr_thread_mutex_lock(thread_mutex) == APR_SUCCESS);
+    assert(apr_thread_mutex_unlock(thread_mutex) == APR_SUCCESS);
+    lock_release(test_mode);
+    apr_thread_exit(id, 0);
+    return NULL;
+}
+
+static void test_mech_mode(apr_lockmech_e mech, const char *mech_name,
+                           test_mode_e test_mode)
+{
+  apr_thread_t *threads[20];
+  int numThreads = 5;
+  int i;
+  apr_status_t rv;
+
+  printf("Trying %s mutexes with mechanism `%s'...\n",
+         test_mode == TEST_GLOBAL ? "global" : "proc", mech_name);
+
+  assert(numThreads <= sizeof(threads) / sizeof(threads[0]));
+
+  assert(apr_pool_create(&p, NULL) == APR_SUCCESS);
+
+  assert(apr_thread_mutex_create(&thread_mutex, 0, p) == APR_SUCCESS);
+  assert(apr_thread_mutex_lock(thread_mutex) == APR_SUCCESS);
+  
+  rv = lock_init(mech, test_mode);
+  if (rv != APR_SUCCESS) {
+      char errmsg[256];
+      printf("%s mutexes with mechanism `%s': %s\n",
+             test_mode == TEST_GLOBAL ? "Global" : "Proc", mech_name,
+             apr_strerror(rv, errmsg, sizeof errmsg));
+      if (rv != APR_ENOTIMPL || mech == APR_LOCK_DEFAULT) {
+          exit(1);
+      }
+      return;
+  }
+
+  counter = 0;
+
+  i = 0;
+  while (i < numThreads)
+  {
+    rv = apr_thread_create(&threads[i],
+                           NULL,
+                           eachThread,
+                           (void *)test_mode,
+                           p);
+    if (rv != APR_SUCCESS) {
+      fprintf(stderr, "apr_thread_create->%d\n", rv);
+      exit(1);
+    }
+    ++i;
+  }
+
+  apr_sleep(apr_time_from_sec(5));
+
+  if (test_mode == TEST_PROC) {
+      printf("  mutex mechanism `%s' is %sglobal in scope on this platform.\n",
+             mech_name, counter == 1 ? "" : "*NOT* ");
+  }
+  else {
+      if (counter != 1) {
+          fprintf(stderr, "\n!!!apr_global_mutex operations are broken on this "
+                  "platform for mutex mechanism `%s'!\n"
+                  "They don't block out threads within the same process.\n",
+                  mech_name);
+          fprintf(stderr, "counter value: %d\n", counter);
+          exit(1);
+      }
+      else {
+          printf("  no problem encountered...\n");
+      }
+  }
+  
+  assert(apr_thread_mutex_unlock(thread_mutex) == APR_SUCCESS);
+
+  i = 0;
+  while (i < numThreads)
+  {
+    apr_status_t ignored;
+
+    rv = apr_thread_join(&ignored,
+                         threads[i]);
+    assert(rv == APR_SUCCESS);
+    ++i;
+  }
+
+  lock_destroy(test_mode);
+  apr_thread_mutex_destroy(thread_mutex);
+  apr_pool_destroy(p);
+}
+
+static void test_mech(apr_lockmech_e mech, const char *mech_name)
+{
+    test_mech_mode(mech, mech_name, TEST_PROC);
+    test_mech_mode(mech, mech_name, TEST_GLOBAL);
+}
+
+int main(void)
+{
+    struct {
+        apr_lockmech_e mech;
+        const char *mech_name;
+    } lockmechs[] = {
+        {APR_LOCK_DEFAULT, "default"}
+#if APR_HAS_FLOCK_SERIALIZE
+        ,{APR_LOCK_FLOCK, "flock"}
+#endif
+#if APR_HAS_SYSVSEM_SERIALIZE
+        ,{APR_LOCK_SYSVSEM, "sysvsem"}
+#endif
+#if APR_HAS_POSIXSEM_SERIALIZE
+        ,{APR_LOCK_POSIXSEM, "posix"}
+#endif
+#if APR_HAS_FCNTL_SERIALIZE
+        ,{APR_LOCK_FCNTL, "fcntl"}
+#endif
+#if APR_HAS_PROC_PTHREAD_SERIALIZE
+        ,{APR_LOCK_PROC_PTHREAD, "proc_pthread"}
+#endif
+        ,{APR_LOCK_DEFAULT_TIMED, "default_timed"}
+    };
+    int i;
+        
+    assert(apr_initialize() == APR_SUCCESS);
+
+    for (i = 0; i < sizeof(lockmechs) / sizeof(lockmechs[0]); i++) {
+        test_mech(lockmechs[i].mech, lockmechs[i].mech_name);
+    }
+    
+    apr_terminate();
+    return 0;
+}
+
+#endif /* APR_HAS_THREADS */
diff --git a/test/testnames.c b/test/testnames.c
new file mode 100644
index 00000000000..4fcd3c033f5
--- /dev/null
+++ b/test/testnames.c
@@ -0,0 +1,387 @@
+/* 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 "testutil.h"
+#include "apr_file_io.h"
+#include "apr_file_info.h"
+#include "apr_errno.h"
+#include "apr_general.h"
+#include "apr_pools.h"
+#include "apr_lib.h"
+#include "apr_strings.h"
+
+#if defined(WIN32)
+#include <direct.h>
+#endif
+
+#if defined(WIN32) || defined(OS2)
+#define ABS_ROOT "C:/"
+#elif defined(NETWARE)
+#define ABS_ROOT "SYS:/"
+#else
+#define ABS_ROOT "/"
+#endif
+
+static void merge_aboveroot(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    char *dstpath = NULL;
+    char errmsg[256];
+
+    rv = apr_filepath_merge(&dstpath, ABS_ROOT"foo", ABS_ROOT"bar", APR_FILEPATH_NOTABOVEROOT,
+                            p);
+    apr_strerror(rv, errmsg, sizeof(errmsg));
+    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_EABOVEROOT(rv));
+    ABTS_PTR_EQUAL(tc, NULL, dstpath);
+    ABTS_STR_EQUAL(tc, "The given path was above the root path", errmsg);
+}
+
+static void merge_belowroot(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    char *dstpath = NULL;
+
+    rv = apr_filepath_merge(&dstpath, ABS_ROOT"foo", ABS_ROOT"foo/bar", 
+                            APR_FILEPATH_NOTABOVEROOT, p);
+    ABTS_PTR_NOTNULL(tc, dstpath);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_STR_EQUAL(tc, ABS_ROOT"foo/bar", dstpath);
+}
+
+static void merge_noflag(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    char *dstpath = NULL;
+
+    rv = apr_filepath_merge(&dstpath, ABS_ROOT"foo", ABS_ROOT"foo/bar", 0, p);
+    ABTS_PTR_NOTNULL(tc, dstpath);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_STR_EQUAL(tc, ABS_ROOT"foo/bar", dstpath);
+}
+
+static void merge_dotdot(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    char *dstpath = NULL;
+
+    rv = apr_filepath_merge(&dstpath, ABS_ROOT"foo/bar", "../baz", 0, p);
+    ABTS_PTR_NOTNULL(tc, dstpath);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_STR_EQUAL(tc, ABS_ROOT"foo/baz", dstpath);
+
+    rv = apr_filepath_merge(&dstpath, "", "../test", 0, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_STR_EQUAL(tc, "../test", dstpath);
+
+    /* Very dangerous assumptions here about what the cwd is.  However, let's assume
+     * that the testall is invoked from within apr/test/ so the following test should
+     * return ../test unless a previously fixed bug remains or the developer changes
+     * the case of the test directory:
+     */
+    rv = apr_filepath_merge(&dstpath, "", "../test", APR_FILEPATH_TRUENAME, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_STR_EQUAL(tc, "../test", dstpath);
+}
+
+static void merge_dotdot_dotdot_dotdot(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    char *dstpath = NULL;
+
+    rv = apr_filepath_merge(&dstpath, "", 
+                            "../../..", APR_FILEPATH_TRUENAME, p);
+    ABTS_PTR_NOTNULL(tc, dstpath);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_STR_EQUAL(tc, "../../..", dstpath);
+
+    rv = apr_filepath_merge(&dstpath, "", 
+                            "../../../", APR_FILEPATH_TRUENAME, p);
+    ABTS_PTR_NOTNULL(tc, dstpath);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_STR_EQUAL(tc, "../../../", dstpath);
+}
+
+static void merge_secure(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    char *dstpath = NULL;
+
+    rv = apr_filepath_merge(&dstpath, ABS_ROOT"foo/bar", "../bar/baz", 0, p);
+    ABTS_PTR_NOTNULL(tc, dstpath);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_STR_EQUAL(tc, ABS_ROOT"foo/bar/baz", dstpath);
+}
+
+static void merge_notrel(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    char *dstpath = NULL;
+
+    rv = apr_filepath_merge(&dstpath, ABS_ROOT"foo/bar", "../baz",
+                            APR_FILEPATH_NOTRELATIVE, p);
+    ABTS_PTR_NOTNULL(tc, dstpath);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_STR_EQUAL(tc, ABS_ROOT"foo/baz", dstpath);
+}
+
+static void merge_notrelfail(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    char *dstpath = NULL;
+    char errmsg[256];
+
+    rv = apr_filepath_merge(&dstpath, "foo/bar", "../baz", 
+                            APR_FILEPATH_NOTRELATIVE, p);
+    apr_strerror(rv, errmsg, sizeof(errmsg));
+
+    ABTS_PTR_EQUAL(tc, NULL, dstpath);
+    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ERELATIVE(rv));
+    ABTS_STR_EQUAL(tc, "The given path is relative", errmsg);
+}
+
+static void merge_notabsfail(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    char *dstpath = NULL;
+    char errmsg[256];
+
+    rv = apr_filepath_merge(&dstpath, ABS_ROOT"foo/bar", "../baz", 
+                            APR_FILEPATH_NOTABSOLUTE, p);
+    apr_strerror(rv, errmsg, sizeof(errmsg));
+
+    ABTS_PTR_EQUAL(tc, NULL, dstpath);
+    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_EABSOLUTE(rv));
+    ABTS_STR_EQUAL(tc, "The given path is absolute", errmsg);
+}
+
+static void merge_notabs(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    char *dstpath = NULL;
+
+    rv = apr_filepath_merge(&dstpath, "foo/bar", "../baz", 
+                            APR_FILEPATH_NOTABSOLUTE, p);
+
+    ABTS_PTR_NOTNULL(tc, dstpath);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_STR_EQUAL(tc, "foo/baz", dstpath);
+}
+
+#if defined (WIN32)
+static void merge_lowercasedrive(abts_case *tc, void *data)
+{
+  char current_dir[1024];
+  char current_dir_on_C[1024];
+  char *dir_on_c;
+  char *testdir;
+  apr_status_t rv;
+
+  /* Change the current directory on C: from something like "C:\dir"
+     to something like "c:\dir" to replicate the failing case. */
+  ABTS_PTR_NOTNULL(tc, _getcwd(current_dir, sizeof(current_dir)));
+
+   /* 3 stands for drive C: */
+  ABTS_PTR_NOTNULL(tc, _getdcwd(3, current_dir_on_C,
+	                            sizeof(current_dir_on_C)));
+
+  /* Use the same path, but now with a lower case driveletter */
+  dir_on_c = apr_pstrdup(p, current_dir_on_C);
+  dir_on_c[0] = (char)tolower(dir_on_c[0]);
+
+  chdir(dir_on_c);
+
+  /* Now merge a drive relative path with an upper case drive letter. */
+  rv = apr_filepath_merge(&testdir, NULL, "C:hi",
+                          APR_FILEPATH_NOTRELATIVE, p);
+
+  /* Change back to original directory for next tests */
+  chdir("C:\\"); /* Switch to upper case */
+  chdir(current_dir_on_C); /* Switch cwd on C: */
+  chdir(current_dir); /* Switch back to original cwd */
+
+  ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+}
+
+static void merge_shortname(abts_case *tc, void *data)
+{
+  apr_status_t rv;
+  char *long_path;
+  char short_path[MAX_PATH+1];
+  DWORD short_len;
+  char *result_path;
+
+  /* 'A b.c' is not a valid short path, so will have multiple representations
+     when short path name generation is enabled... but its 'short' path will
+     most likely be longer than the long path */
+  rv = apr_dir_make_recursive("C:/data/short/A b.c",
+                              APR_UREAD | APR_UWRITE | APR_UEXECUTE, p);
+  ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+  rv = apr_filepath_merge(&long_path, NULL, "C:/data/short/A b.c",
+                          APR_FILEPATH_NOTRELATIVE, p);
+  ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+  short_len = GetShortPathName(long_path, short_path, sizeof(short_path));
+  if (short_len > MAX_PATH)
+    return; /* Unable to test. Impossible shortname */
+
+  if (! strcmp(long_path, short_path))
+    return; /* Unable to test. 8dot3name option is probably not enabled */
+
+  rv = apr_filepath_merge(&result_path, "", short_path, APR_FILEPATH_TRUENAME,
+                          p);
+  ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+  ABTS_STR_EQUAL(tc, long_path, result_path);
+}
+#endif
+
+static void root_absolute(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    const char *root = NULL;
+    const char *path = ABS_ROOT"foo/bar";
+
+    rv = apr_filepath_root(&root, &path, 0, p);
+
+    ABTS_PTR_NOTNULL(tc, root);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_STR_EQUAL(tc, ABS_ROOT, root);
+}
+
+static void root_relative(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    const char *root = NULL;
+    const char *path = "foo/bar";
+    char errmsg[256];
+
+    rv = apr_filepath_root(&root, &path, 0, p);
+    apr_strerror(rv, errmsg, sizeof(errmsg));
+
+    ABTS_PTR_EQUAL(tc, NULL, root);
+    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ERELATIVE(rv));
+    ABTS_STR_EQUAL(tc, "The given path is relative", errmsg);
+}
+
+static void root_from_slash(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    const char *root = NULL;
+    const char *path = "//";
+
+    rv = apr_filepath_root(&root, &path, APR_FILEPATH_TRUENAME, p);
+
+#if defined(WIN32) || defined(OS2)
+    ABTS_INT_EQUAL(tc, APR_EINCOMPLETE, rv);
+    ABTS_STR_EQUAL(tc, "//", root);
+#else
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_STR_EQUAL(tc, "/", root);
+#endif
+    ABTS_STR_EQUAL(tc, "", path);
+}
+
+static void root_from_cwd_and_back(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    const char *root = NULL;
+    const char *path = "//";
+    char *origpath;
+    char *testpath;
+#if defined(WIN32) || defined(OS2) || defined(NETWARE)
+    int hadfailed;
+#endif
+
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, apr_filepath_get(&origpath, 0, p));
+    path = origpath;
+    rv = apr_filepath_root(&root, &path, APR_FILEPATH_TRUENAME, p);
+
+#if defined(WIN32) || defined(OS2)
+    hadfailed = tc->failed;
+    /* It appears some mingw/cygwin and more modern builds can return
+     * a lowercase drive designation, but we canonicalize to uppercase
+     */
+    ABTS_INT_EQUAL(tc, toupper(origpath[0]), root[0]);
+    ABTS_INT_EQUAL(tc, ':', root[1]);
+    ABTS_INT_EQUAL(tc, '/', root[2]);
+    ABTS_INT_EQUAL(tc, 0, root[3]);
+    ABTS_STR_EQUAL(tc, origpath + 3, path);
+#elif defined(NETWARE)
+    ABTS_INT_EQUAL(tc, origpath[0], root[0]);
+    {
+    char *pt = strchr(root, ':');
+    ABTS_PTR_NOTNULL(tc, pt);
+    ABTS_INT_EQUAL(tc, ':', pt[0]);
+    ABTS_INT_EQUAL(tc, '/', pt[1]);
+    ABTS_INT_EQUAL(tc, 0, pt[2]);
+    pt = strchr(origpath, ':');
+    ABTS_PTR_NOTNULL(tc, pt);
+    ABTS_STR_EQUAL(tc, (pt+2), path);
+    }
+#else
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_STR_EQUAL(tc, "/", root);
+    ABTS_STR_EQUAL(tc, origpath + 1, path);
+#endif
+
+    rv = apr_filepath_merge(&testpath, root, path, 
+                            APR_FILEPATH_TRUENAME
+                          | APR_FILEPATH_NOTABOVEROOT
+                          | APR_FILEPATH_NOTRELATIVE, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+#if defined(WIN32) || defined(OS2) || defined(NETWARE)
+    hadfailed = tc->failed;
+#endif
+    /* The API doesn't promise equality!!! 
+     * apr_filepath_get never promised a canonical filepath.
+     * We'll emit noise under verbose so the user is aware,
+     * but translate this back to success.
+     */
+    ABTS_STR_EQUAL(tc, origpath, testpath);
+#if defined(WIN32) || defined(OS2) || defined(NETWARE)
+    if (!hadfailed) tc->failed = 0;
+#endif
+}
+
+
+abts_suite *testnames(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite)
+
+    abts_run_test(suite, merge_aboveroot, NULL);
+    abts_run_test(suite, merge_belowroot, NULL);
+    abts_run_test(suite, merge_noflag, NULL);
+    abts_run_test(suite, merge_dotdot, NULL);
+    abts_run_test(suite, merge_secure, NULL);
+    abts_run_test(suite, merge_notrel, NULL);
+    abts_run_test(suite, merge_notrelfail, NULL);
+    abts_run_test(suite, merge_notabs, NULL);
+    abts_run_test(suite, merge_notabsfail, NULL);
+    abts_run_test(suite, merge_dotdot_dotdot_dotdot, NULL);
+#if defined(WIN32)
+    abts_run_test(suite, merge_lowercasedrive, NULL);
+    abts_run_test(suite, merge_shortname, NULL);
+#endif
+
+    abts_run_test(suite, root_absolute, NULL);
+    abts_run_test(suite, root_relative, NULL);
+    abts_run_test(suite, root_from_slash, NULL);
+    abts_run_test(suite, root_from_cwd_and_back, NULL);
+
+    return suite;
+}
+
diff --git a/test/testoc.c b/test/testoc.c
index dbdd26efe54..923bd4b6df6 100644
--- a/test/testoc.c
+++ b/test/testoc.c
@@ -1,149 +1,120 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "testutil.h"
 #include "apr_thread_proc.h"
 #include "apr_errno.h"
 #include "apr_general.h"
 #include "apr_lib.h"
-#include "errno.h"
-#include <stdio.h>
-#include <stdlib.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
+#include "apr_strings.h"
+
+#if APR_HAS_OTHER_CHILD
+
+static char reasonstr[256];
 
-void ocmaint(int reason, void *data, int status)
+static void ocmaint(int reason, void *data, int status)
 {
-    fprintf(stdout,"[CHILD]  Maintenance routine called....");
-    fflush(stdout);
     switch (reason) {
     case APR_OC_REASON_DEATH:
-        fprintf(stdout, "Died correctly\n");
+        apr_cpystrn(reasonstr, "APR_OC_REASON_DEATH", 
+                    strlen("APR_OC_REASON_DEATH") + 1);
         break;
     case APR_OC_REASON_LOST:
-        fprintf(stdout, "APR_OC_REASON_LOST\n");
+        apr_cpystrn(reasonstr, "APR_OC_REASON_LOST", 
+                    strlen("APR_OC_REASON_LOST") + 1);
+        break;
     case APR_OC_REASON_UNWRITABLE:
-        fprintf(stdout, "APR_OC_REASON_UNWRITEABLE\n");
+        apr_cpystrn(reasonstr, "APR_OC_REASON_UNWRITEABLE", 
+                    strlen("APR_OC_REASON_UNWRITEABLE") + 1);
+        break;
     case APR_OC_REASON_RESTART:
-        fprintf(stdout, "APR_OC_REASON_RESTART\n");
-        fprintf(stdout, "OC maintentance called for reason other than death\n");
+        apr_cpystrn(reasonstr, "APR_OC_REASON_RESTART", 
+                    strlen("APR_OC_REASON_RESTART") + 1);
         break;
     }
 }
 
-int main(int argc, char *argv[])
+#ifndef SIGKILL
+#define SIGKILL 1
+#endif
+
+/* It would be great if we could stress this stuff more, and make the test
+ * more granular.
+ */
+static void test_child_kill(abts_case *tc, void *data)
 {
-    ap_pool_t *context;
-    ap_pool_t *cont2;
-    ap_status_t status = 0;
-    ap_ssize_t nbytes = 0;
-    ap_proc_t *newproc = NULL;
-    ap_procattr_t *procattr = NULL;
-    char *args[3];
-
-    if (argc > 1) {
-        while (1);
-    }
+    apr_file_t *std = NULL;
+    apr_proc_t newproc;
+    apr_procattr_t *procattr = NULL;
+    const char *args[3];
+    apr_status_t rv;
 
-    if (ap_initialize() != APR_SUCCESS) {
-        fprintf(stderr, "Couldn't initialize.");
-        exit(-1);
-    }
-    atexit(ap_terminate);
-    if (ap_create_pool(&context, NULL) != APR_SUCCESS) {
-        fprintf(stderr, "Couldn't allocate context.");
-        exit(-1);
-    }
-    
-    args[0] = ap_pstrdup(context, "testoc");
-    args[1] = ap_pstrdup(context, "-X");
+    args[0] = apr_pstrdup(p, "occhild" EXTENSION);
+    args[1] = apr_pstrdup(p, "-X");
     args[2] = NULL;
 
-    fprintf(stdout, "[PARENT] Creating procattr.............");
-    fflush(stdout);
-    if (ap_createprocattr_init(&procattr, context) != APR_SUCCESS) {
-        fprintf(stderr, "Could not create attr\n");
-        exit(-1);;
-    }
-    fprintf(stdout, "OK\n");
-
-    fprintf(stdout, "[PARENT] Starting other child..........");
-    fflush(stdout);
-    if (ap_create_process(&newproc, "../testoc", args, NULL, procattr, context) 
-                          != APR_SUCCESS) {
-        fprintf(stderr, "error starting other child\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK\n");
+    rv = apr_procattr_create(&procattr, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
 
+    rv = apr_procattr_io_set(procattr, APR_FULL_BLOCK, APR_NO_PIPE, 
+                             APR_NO_PIPE);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
 
-    ap_register_other_child(newproc, ocmaint, NULL, -1, context);
+    rv = apr_procattr_cmdtype_set(procattr, APR_PROGRAM_ENV);
+    APR_ASSERT_SUCCESS(tc, "Couldn't set copy environment", rv);
 
-    fprintf(stdout, "[PARENT] Sending SIGKILL to child......");
-    fflush(stdout);
-    if (ap_kill(newproc, SIGKILL) != APR_SUCCESS) {
-        fprintf(stderr,"couldn't send the signal!\n");
-        exit(-1);
-    }
-    fprintf(stdout,"OK\n");
+    rv = apr_proc_create(&newproc, TESTBINPATH "occhild" EXTENSION, args, NULL, procattr, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_PTR_NOTNULL(tc, newproc.in);
+    ABTS_PTR_EQUAL(tc, NULL, newproc.out);
+    ABTS_PTR_EQUAL(tc, NULL, newproc.err);
+
+    std = newproc.in;
+
+    apr_proc_other_child_register(&newproc, ocmaint, NULL, std, p);
+
+    apr_sleep(apr_time_from_sec(1));
+    rv = apr_proc_kill(&newproc, SIGKILL);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
     
     /* allow time for things to settle... */
-    sleep(1);
-    
-    fprintf(stdout, "[PARENT] Checking on children..........\n");
-    ap_check_other_child();
+    apr_sleep(apr_time_from_sec(3));
     
-    return 1;
+    apr_proc_other_child_refresh_all(APR_OC_REASON_RUNNING);
+    ABTS_STR_EQUAL(tc, "APR_OC_REASON_DEATH", reasonstr);
 }    
+#else
+
+static void oc_not_impl(abts_case *tc, void *data)
+{
+    ABTS_NOT_IMPL(tc, "Other child logic not implemented on this platform");
+}
+#endif
+
+abts_suite *testoc(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite)
+
+#if !APR_HAS_OTHER_CHILD
+    abts_run_test(suite, oc_not_impl, NULL);
+#else
+
+    abts_run_test(suite, test_child_kill, NULL); 
+
+#endif
+    return suite;
+}
 
diff --git a/test/testpass.c b/test/testpass.c
new file mode 100644
index 00000000000..4ba5c69525e
--- /dev/null
+++ b/test/testpass.c
@@ -0,0 +1,217 @@
+/* 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 <stdio.h>
+#include <stdlib.h>
+
+#include "apr_errno.h"
+#include "apr_strings.h"
+#include "apr_file_io.h"
+#include "apr_thread_pool.h"
+#include "apr_md5.h"
+#include "apr_sha1.h"
+
+#include "abts.h"
+#include "testutil.h"
+
+#if defined(WIN32) || defined(BEOS) || defined(NETWARE)
+#define CRYPT_ALGO_SUPPORTED 0
+#else
+#define CRYPT_ALGO_SUPPORTED 1
+#endif
+
+#if defined __GLIBC_PREREQ
+#if __GLIBC_PREREQ(2,7)
+#define GLIBCSHA_ALGO_SUPPORTED
+#endif
+#endif
+
+#if CRYPT_ALGO_SUPPORTED
+
+static struct {
+    const char *password;
+    const char *hash;
+} passwords[] =
+{
+/*
+  passwords and hashes created with Apache's htpasswd utility like this:
+  
+  htpasswd -c -b passwords pass1 pass1
+  htpasswd -b passwords pass2 pass2
+  htpasswd -b passwords pass3 pass3
+  htpasswd -b passwords pass4 pass4
+  htpasswd -b passwords pass5 pass5
+  htpasswd -b passwords pass6 pass6
+  htpasswd -b passwords pass7 pass7
+  htpasswd -b passwords pass8 pass8
+  (insert Perl one-liner to convert to initializer :) )
+ */
+    {"pass1", "1fWDc9QWYCWrQ"},
+    {"pass2", "1fiGx3u7QoXaM"},
+    {"pass3", "1fzijMylTiwCs"},
+    {"pass4", "nHUYc8U2UOP7s"},
+    {"pass5", "nHpETGLGPwAmA"},
+    {"pass6", "nHbsbWmJ3uyhc"},
+    {"pass7", "nHQ3BbF0Y9vpI"},
+    {"pass8", "nHZA1rViSldQk"}
+};
+static int num_passwords = sizeof(passwords) / sizeof(passwords[0]);
+
+static void test_crypt(abts_case *tc, void *data)
+{
+    int i;
+
+    for (i = 0; i < num_passwords; i++) {
+        APR_ASSERT_SUCCESS(tc, "check for valid password",
+                           apr_password_validate(passwords[i].password,
+                                                 passwords[i].hash));
+    }
+}
+
+#if APR_HAS_THREADS
+
+static void * APR_THREAD_FUNC testing_thread(apr_thread_t *thd,
+                                             void *data)
+{
+    abts_case *tc = data;
+    int i;
+
+    for (i = 0; i < 100; i++) {
+        test_crypt(tc, NULL);
+    }
+
+    return APR_SUCCESS;
+}
+
+#define NUM_THR 20
+
+/* test for threadsafe crypt() */
+static void test_threadsafe(abts_case *tc, void *data)
+{
+    int i;
+    apr_status_t rv;
+    apr_thread_pool_t *thrp;
+
+    rv = apr_thread_pool_create(&thrp, NUM_THR/2, NUM_THR, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    for (i = 0; i < NUM_THR; i++) {
+        rv = apr_thread_pool_push(thrp, testing_thread, tc, 0, NULL);
+        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    }
+
+    apr_thread_pool_destroy(thrp);
+}
+#endif
+
+#endif /* CRYPT_ALGO_SUPPORTED */
+
+static void test_shapass(abts_case *tc, void *data)
+{
+    const char *pass = "hellojed";
+    const char *pass2 = "hellojed2";
+    char hash[100];
+
+    apr_sha1_base64(pass, strlen(pass), hash);
+
+    APR_ASSERT_SUCCESS(tc, "SHA1 password validated",
+                       apr_password_validate(pass, hash));
+    APR_ASSERT_FAILURE(tc, "wrong SHA1 password should not validate",
+                       apr_password_validate(pass2, hash));
+}
+
+static void test_md5pass(abts_case *tc, void *data)
+{
+    const char *pass = "hellojed", *salt = "sardine";
+    const char *pass2 = "hellojed2";
+    char hash[100];
+
+    apr_md5_encode(pass, salt, hash, sizeof hash);
+
+    APR_ASSERT_SUCCESS(tc, "MD5 password validated",
+                       apr_password_validate(pass, hash));
+    APR_ASSERT_FAILURE(tc, "wrong MD5 password should not validate",
+                       apr_password_validate(pass2, hash));
+}
+
+#ifdef GLIBCSHA_ALGO_SUPPORTED
+
+static struct {
+    const char *password;
+    const char *hash;
+} glibc_sha_pws[] = {
+    /* SHA256 */
+    { "secret1", "$5$0123456789abcdef$SFX.CooXBS8oXsbAPgU/UyiCodhrLQ19sBgvcA3Zh1D" },
+    { "secret2", "$5$rounds=100000$0123456789abcdef$dLXfO5m4d.xv8G66kpz2LyL0.Mi5wjLlH0m7rtgyhyB" },
+    /* SHA512 */
+    { "secret3", "$6$0123456789abcdef$idOsOfoWwnCQkJm9hd2hxS4NnEs9nBA9poOFXsvtrYSoSHaOToCfyUoZwKe.ZCZnq7D95tGVoi2jxZZMyVwTL1" },
+    { "secret4", "$6$rounds=100000$0123456789abcdef$ZiAMjbeA.iIGTWxq2oks9Bvz9sfxaoGPgAtpwimPEwFwkSNMTK7lLwABzzldds/n4UgCQ16HqawPrCrePr4YX1" },
+    { NULL, NULL }
+};
+
+static void test_glibc_shapass(abts_case *tc, void *data)
+{
+    int i = 0;
+    while (glibc_sha_pws[i].password) {
+        APR_ASSERT_SUCCESS(tc, "check for valid glibc crypt-sha password",
+                           apr_password_validate(glibc_sha_pws[i].password,
+                                                 glibc_sha_pws[i].hash));
+        i++;
+    }
+}
+#endif
+
+static void test_bcryptpass(abts_case *tc, void *data)
+{
+    const char *pass = "hellojed";
+    const char *pass2 = "hellojed2";
+    unsigned char salt[] = "sardine_sardine";
+    char hash[100];
+    const char *hash2 = "$2a$08$qipUJiI9fySUN38hcbz.lucXvAmtgowKOWYtB9y3CXyl6lTknruou";
+    const char *pass3 = "foobar";
+
+    APR_ASSERT_SUCCESS(tc, "bcrypt encode password", 
+                       apr_bcrypt_encode(pass, 5, salt, sizeof(salt), hash,
+                                         sizeof(hash)));
+
+    APR_ASSERT_SUCCESS(tc, "bcrypt password validated",
+                       apr_password_validate(pass, hash));
+    APR_ASSERT_FAILURE(tc, "wrong bcrypt password should not validate",
+                       apr_password_validate(pass2, hash));
+    APR_ASSERT_SUCCESS(tc, "bcrypt password validated",
+                       apr_password_validate(pass3, hash2));
+}
+
+
+abts_suite *testpass(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite);
+
+#if CRYPT_ALGO_SUPPORTED 
+    abts_run_test(suite, test_crypt, NULL);
+#if APR_HAS_THREADS
+    abts_run_test(suite, test_threadsafe, NULL);
+#endif
+#endif /* CRYPT_ALGO_SUPPORTED */
+    abts_run_test(suite, test_shapass, NULL);
+    abts_run_test(suite, test_md5pass, NULL);
+    abts_run_test(suite, test_bcryptpass, NULL);
+#ifdef GLIBCSHA_ALGO_SUPPORTED
+    abts_run_test(suite, test_glibc_shapass, NULL);
+#endif
+    
+    return suite;
+}
diff --git a/test/testpath.c b/test/testpath.c
new file mode 100644
index 00000000000..b05ae9917e0
--- /dev/null
+++ b/test/testpath.c
@@ -0,0 +1,138 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "testutil.h"
+#include "apr_file_info.h"
+#include "apr_errno.h"
+#include "apr_pools.h"
+#include "apr_tables.h"
+
+#if defined(WIN32) || defined(NETWARE) || defined(OS2)
+#define PSEP ";"
+#define DSEP "\\"
+#else
+#define PSEP ":"
+#define DSEP "/"
+#endif
+
+#define PX ""
+#define P1 "first path"
+#define P2 "second" DSEP "path"
+#define P3 "th ird" DSEP "path"
+#define P4 "fourth" DSEP "pa th"
+#define P5 "fifthpath"
+
+static const char *parts_in[] = { P1, P2, P3, PX, P4, P5 };
+static const char *path_in = P1 PSEP P2 PSEP P3 PSEP PX PSEP P4 PSEP P5;
+static const int  parts_in_count = sizeof(parts_in)/sizeof(*parts_in);
+
+static const char *parts_out[] = { P1, P2, P3, P4, P5 };
+static const char *path_out = P1 PSEP P2 PSEP P3 PSEP P4 PSEP P5;
+static const int  parts_out_count = sizeof(parts_out)/sizeof(*parts_out);
+
+static void list_split_multi(abts_case *tc, void *data)
+{
+    int i;
+    apr_status_t rv;
+    apr_array_header_t *pathelts;
+
+    pathelts = NULL;
+    rv = apr_filepath_list_split(&pathelts, path_in, p);
+    ABTS_PTR_NOTNULL(tc, pathelts);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_INT_EQUAL(tc, parts_out_count, pathelts->nelts);
+    for (i = 0; i < pathelts->nelts; ++i)
+        ABTS_STR_EQUAL(tc, parts_out[i], ((char**)pathelts->elts)[i]);
+}
+
+static void list_split_single(abts_case *tc, void *data)
+{
+    int i;
+    apr_status_t rv;
+    apr_array_header_t *pathelts;
+
+    for (i = 0; i < parts_in_count; ++i)
+    {
+        pathelts = NULL;
+        rv = apr_filepath_list_split(&pathelts, parts_in[i], p);
+        ABTS_PTR_NOTNULL(tc, pathelts);
+        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+        if (parts_in[i][0] == '\0')
+            ABTS_INT_EQUAL(tc, 0, pathelts->nelts);
+        else
+        {
+            ABTS_INT_EQUAL(tc, 1, pathelts->nelts);
+            ABTS_STR_EQUAL(tc, parts_in[i], *(char**)pathelts->elts);
+        }
+    }
+}
+
+static void list_merge_multi(abts_case *tc, void *data)
+{
+    int i;
+    char *liststr;
+    apr_status_t rv;
+    apr_array_header_t *pathelts;
+
+    pathelts = apr_array_make(p, parts_in_count, sizeof(const char*));
+    for (i = 0; i < parts_in_count; ++i)
+        *(const char**)apr_array_push(pathelts) = parts_in[i];
+
+    liststr = NULL;
+    rv = apr_filepath_list_merge(&liststr, pathelts, p);
+    ABTS_PTR_NOTNULL(tc, liststr);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_STR_EQUAL(tc, liststr, path_out);
+}
+
+static void list_merge_single(abts_case *tc, void *data)
+{
+    int i;
+    char *liststr;
+    apr_status_t rv;
+    apr_array_header_t *pathelts;
+
+    pathelts = apr_array_make(p, 1, sizeof(const char*));
+    apr_array_push(pathelts);
+    for (i = 0; i < parts_in_count; ++i)
+    {
+        *(const char**)pathelts->elts = parts_in[i];
+        liststr = NULL;
+        rv = apr_filepath_list_merge(&liststr, pathelts, p);
+        if (parts_in[i][0] == '\0')
+            ABTS_PTR_EQUAL(tc, NULL, liststr);
+        else
+        {
+            ABTS_PTR_NOTNULL(tc, liststr);
+            ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+            ABTS_STR_EQUAL(tc, liststr, parts_in[i]);
+        }
+    }
+}
+
+
+abts_suite *testpath(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite)
+
+    abts_run_test(suite, list_split_multi, NULL);
+    abts_run_test(suite, list_split_single, NULL);
+    abts_run_test(suite, list_merge_multi, NULL);
+    abts_run_test(suite, list_merge_single, NULL);
+
+    return suite;
+}
+
diff --git a/test/testpipe.c b/test/testpipe.c
index 1c96ac92ab4..810ffe7b505 100644
--- a/test/testpipe.c
+++ b/test/testpipe.c
@@ -1,117 +1,235 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 <stdio.h>
+#include <stdlib.h>
+
+#include "testutil.h"
 #include "apr_file_io.h"
 #include "apr_errno.h"
 #include "apr_general.h"
 #include "apr_lib.h"
-#include <stdlib.h>
-#ifdef BEOS
-#include <unistd.h>
-#endif
+#include "apr_thread_proc.h"
+#include "apr_strings.h"
+
+static apr_file_t *readp = NULL;
+static apr_file_t *writep = NULL;
+
+static void create_pipe(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+
+    rv = apr_file_pipe_create(&readp, &writep, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_PTR_NOTNULL(tc, readp);
+    ABTS_PTR_NOTNULL(tc, writep);
+}   
+
+static void close_pipe(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_size_t nbytes = 256;
+    char buf[256];
+
+    rv = apr_file_close(readp);
+    rv = apr_file_close(writep);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
 
-int test_filedel(ap_pool_t *);
-int testdirs(ap_pool_t *);
+    rv = apr_file_read(readp, buf, &nbytes);
+    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_EBADF(rv));
+}   
 
-int main()
+static void set_timeout(abts_case *tc, void *data)
 {
-    ap_pool_t *context;
-    ap_file_t *readp = NULL;
-    ap_file_t *writep = NULL;
-    ap_size_t nbytes;
+    apr_status_t rv;
+    apr_interval_time_t timeout;
+
+    rv = apr_file_pipe_create_pools(&readp, &writep, APR_WRITE_BLOCK, p, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_PTR_NOTNULL(tc, readp);
+    ABTS_PTR_NOTNULL(tc, writep);
+
+    rv = apr_file_pipe_timeout_get(writep, &timeout);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_ASSERT(tc, "Timeout mismatch, expected -1", timeout == -1);
+
+    rv = apr_file_pipe_timeout_set(readp, apr_time_from_sec(1));
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_file_pipe_timeout_get(readp, &timeout);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_ASSERT(tc, "Timeout mismatch, expected 1 second", 
+		        timeout == apr_time_from_sec(1));
+}
+
+static void read_write(abts_case *tc, void *data)
+{
+    apr_status_t rv;
     char *buf;
+    apr_size_t nbytes;
+    
+    nbytes = strlen("this is a test");
+    buf = (char *)apr_palloc(p, nbytes + 1);
 
-    if (ap_initialize() != APR_SUCCESS) {
-        fprintf(stderr, "Couldn't initialize.");
-        exit(-1);
-    }
-    atexit(ap_terminate);
-    if (ap_create_pool(&context, NULL) != APR_SUCCESS) {
-        fprintf(stderr, "Couldn't allocate context.");
-        exit(-1);
-    }
+    rv = apr_file_pipe_create_pools(&readp, &writep, APR_WRITE_BLOCK, p, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_PTR_NOTNULL(tc, readp);
+    ABTS_PTR_NOTNULL(tc, writep);
 
-    fprintf(stdout, "Testing pipe functions.\n");
+    rv = apr_file_pipe_timeout_set(readp, apr_time_from_sec(1));
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
 
-    fprintf(stdout, "\tCreating pipes.......");
-    if (ap_create_pipe(&readp, &writep, context) != APR_SUCCESS) {
-        perror("Didn't create the pipe");
-        exit(-1);
-    }
-    else {
-        fprintf(stdout, "OK\n");
+    if (!rv) {
+        rv = apr_file_read(readp, buf, &nbytes);
+        ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv));
+        ABTS_SIZE_EQUAL(tc, 0, nbytes);
     }
+}
+
+static void read_write_notimeout(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    char *buf = "this is a test";
+    char *input;
+    apr_size_t nbytes;
     
-    fprintf(stdout, "\tSetting pipe timeout.......");
-    if (ap_set_pipe_timeout(readp, 1 * AP_USEC_PER_SEC) != APR_SUCCESS) {
-        perror("Couldn't set a timeout");
-        exit(-1);
-    } else {
-        fprintf(stdout, "OK\n");
-    }        
-
-    fprintf(stdout, "\tReading from the file.......");
-    nbytes = (ap_ssize_t)strlen("this is a test");
-    buf = (char *)ap_palloc(context, nbytes + 1);
-    if (ap_read(readp, buf, &nbytes) == APR_TIMEUP) {
-        fprintf(stdout, "OK\n");
-    }
-    else {
-        fprintf(stdout, "The timeout didn't work  :-(\n");
-        exit(-1);
-    }
+    nbytes = strlen("this is a test");
 
-    return 1;
+    rv = apr_file_pipe_create(&readp, &writep, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_PTR_NOTNULL(tc, readp);
+    ABTS_PTR_NOTNULL(tc, writep);
+
+    rv = apr_file_write(writep, buf, &nbytes);
+    ABTS_SIZE_EQUAL(tc, strlen("this is a test"), nbytes);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    nbytes = 256;
+    input = apr_pcalloc(p, nbytes + 1);
+    rv = apr_file_read(readp, input, &nbytes);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_SIZE_EQUAL(tc, strlen("this is a test"), nbytes);
+    ABTS_STR_EQUAL(tc, "this is a test", input);
 }
+
+static void test_pipe_writefull(abts_case *tc, void *data)
+{
+    int iterations = 1000;
+    int i;
+    int bytes_per_iteration = 8000;
+    char *buf = (char *)calloc(bytes_per_iteration, 1);
+    char responsebuf[128];
+    apr_size_t nbytes;
+    int bytes_processed;
+    apr_proc_t proc = {0};
+    apr_procattr_t *procattr;
+    const char *args[2];
+    apr_status_t rv;
+    apr_exit_why_e why;
+    
+    rv = apr_procattr_create(&procattr, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_procattr_io_set(procattr, APR_CHILD_BLOCK, APR_CHILD_BLOCK,
+                             APR_CHILD_BLOCK);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_procattr_cmdtype_set(procattr, APR_PROGRAM_ENV);
+    APR_ASSERT_SUCCESS(tc, "Couldn't set copy environment", rv);
+
+    rv = apr_procattr_error_check_set(procattr, 1);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    args[0] = "readchild" EXTENSION;
+    args[1] = NULL;
+    rv = apr_proc_create(&proc, TESTBINPATH "readchild" EXTENSION, args, NULL, procattr, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_file_pipe_timeout_set(proc.in, apr_time_from_sec(10));
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_file_pipe_timeout_set(proc.out, apr_time_from_sec(10));
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    i = iterations;
+    do {
+        rv = apr_file_write_full(proc.in, buf, bytes_per_iteration, NULL);
+        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    } while (--i);
+
+    free(buf);
+
+    rv = apr_file_close(proc.in);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    
+    nbytes = sizeof(responsebuf);
+    rv = apr_file_read(proc.out, responsebuf, &nbytes);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    bytes_processed = (int)apr_strtoi64(responsebuf, NULL, 10);
+    ABTS_INT_EQUAL(tc, iterations * bytes_per_iteration, bytes_processed);
+
+    ABTS_ASSERT(tc, "wait for child process",
+             apr_proc_wait(&proc, NULL, &why, APR_WAIT) == APR_CHILD_DONE);
+    
+    ABTS_ASSERT(tc, "child terminated normally", why == APR_PROC_EXIT);
+}
+
+static void wait_pipe(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_interval_time_t delay = 200000;
+    apr_time_t start_time;
+    apr_time_t end_time;
+    apr_size_t nbytes;
+
+    rv = apr_file_pipe_create(&readp, &writep, p);
+    APR_ASSERT_SUCCESS(tc, "Couldn't create pipe", rv);
+
+    rv = apr_file_pipe_timeout_set(readp, delay);
+    APR_ASSERT_SUCCESS(tc, "Couldn't set pipe timeout", rv);
+
+    start_time = apr_time_now();
+    rv = apr_file_pipe_wait(readp, APR_WAIT_READ);
+    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv));
+
+    end_time = apr_time_now();
+    ABTS_ASSERT(tc, "apr_file_pipe_wait() waited for the time out", end_time - start_time >= delay);
+
+    nbytes = 4;
+    rv = apr_file_write(writep, "data", &nbytes);
+    APR_ASSERT_SUCCESS(tc, "Couldn't write to pipe", rv);
+
+    rv = apr_file_pipe_wait(readp, APR_WAIT_READ);
+    APR_ASSERT_SUCCESS(tc, "Wait for pipe failed", rv);
+}
+
+abts_suite *testpipe(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite)
+
+    abts_run_test(suite, create_pipe, NULL);
+    abts_run_test(suite, close_pipe, NULL);
+    abts_run_test(suite, set_timeout, NULL);
+    abts_run_test(suite, close_pipe, NULL);
+    abts_run_test(suite, read_write, NULL);
+    abts_run_test(suite, close_pipe, NULL);
+    abts_run_test(suite, read_write_notimeout, NULL);
+    abts_run_test(suite, test_pipe_writefull, NULL);
+    abts_run_test(suite, close_pipe, NULL);
+    abts_run_test(suite, wait_pipe, NULL);
+
+    return suite;
+}
+
diff --git a/test/testpoll.c b/test/testpoll.c
new file mode 100644
index 00000000000..9f90af2dd50
--- /dev/null
+++ b/test/testpoll.c
@@ -0,0 +1,965 @@
+/* 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 "testutil.h"
+#include "apr_strings.h"
+#include "apr_errno.h"
+#include "apr_general.h"
+#include "apr_lib.h"
+#include "apr_network_io.h"
+#include "apr_poll.h"
+
+#define SMALL_NUM_SOCKETS 3
+/* We can't use 64 here, because some platforms *ahem* Solaris *ahem* have
+ * a default limit of 64 open file descriptors per process.  If we use
+ * 64, the test will fail even though the code is correct.
+ */
+#define LARGE_NUM_SOCKETS 50
+
+static apr_socket_t *s[LARGE_NUM_SOCKETS];
+static apr_sockaddr_t *sa[LARGE_NUM_SOCKETS];
+static apr_pollset_t *pollset;
+static apr_pollcb_t *pollcb;
+
+/* ###: tests surrounded by ifdef OLD_POLL_INTERFACE either need to be
+ * converted to use the pollset interface or removed. */
+
+#ifdef OLD_POLL_INTERFACE
+static apr_pollfd_t *pollarray;
+static apr_pollfd_t *pollarray_large;
+#endif
+
+/* default_pollset_impl can be overridden temporarily to control
+ * testcases which don't specify an implementation explicitly
+ */
+static int default_pollset_impl = APR_POLLSET_DEFAULT;
+
+static void make_socket(apr_socket_t **sock, apr_sockaddr_t **sa, 
+                        apr_port_t port, apr_pool_t *p, abts_case *tc)
+{
+    apr_status_t rv;
+
+    rv = apr_sockaddr_info_get(sa, "127.0.0.1", APR_UNSPEC, port, 0, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_socket_create(sock, (*sa)->family, SOCK_DGRAM, 0, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_socket_bind((*sock), (*sa));
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+}
+
+#ifdef OLD_POLL_INTERFACE
+static void check_sockets(const apr_pollfd_t *pollarray, 
+                          apr_socket_t **sockarray, int which, int pollin, 
+                          abts_case *tc)
+{
+    apr_status_t rv;
+    apr_int16_t event;
+    char *str;
+
+    rv = apr_poll_revents_get(&event, sockarray[which], 
+                              (apr_pollfd_t *)pollarray);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    if (pollin) {
+        str = apr_psprintf(p, "Socket %d not signalled when it should be",
+                           which);
+        ABTS_ASSERT(tc, str, event & APR_POLLIN);
+    } else {
+        str = apr_psprintf(p, "Socket %d signalled when it should not be",
+                           which);
+        ABTS_ASSERT(tc, str, !(event & APR_POLLIN));
+    }
+}
+#endif
+
+static void send_msg(apr_socket_t **sockarray, apr_sockaddr_t **sas, int which,
+                     abts_case *tc)
+{
+    apr_size_t len = 5;
+    apr_status_t rv;
+
+    ABTS_PTR_NOTNULL(tc, sockarray[which]);
+
+    rv = apr_socket_sendto(sockarray[which], sas[which], 0, "hello", &len);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_SIZE_EQUAL(tc, strlen("hello"), len);
+}
+
+static void recv_msg(apr_socket_t **sockarray, int which, apr_pool_t *p, 
+                     abts_case *tc)
+{
+    apr_size_t buflen = 5;
+    char *buffer = apr_pcalloc(p, sizeof(char) * (buflen + 1));
+    apr_sockaddr_t *recsa;
+    apr_status_t rv;
+
+    ABTS_PTR_NOTNULL(tc, sockarray[which]);
+
+    apr_sockaddr_info_get(&recsa, "127.0.0.1", APR_UNSPEC, 7770, 0, p);
+
+    rv = apr_socket_recvfrom(recsa, sockarray[which], 0, buffer, &buflen);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_SIZE_EQUAL(tc, strlen("hello"), buflen);
+    ABTS_STR_EQUAL(tc, "hello", buffer);
+}
+
+    
+static void create_all_sockets(abts_case *tc, void *data)
+{
+    int i;
+
+    for (i = 0; i < LARGE_NUM_SOCKETS; i++){
+        make_socket(&s[i], &sa[i], 7777 + i, p, tc);
+    }
+}
+       
+#ifdef OLD_POLL_INTERFACE
+static void setup_small_poll(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    int i;
+
+    rv = apr_poll_setup(&pollarray, SMALL_NUM_SOCKETS, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    
+    for (i = 0; i < SMALL_NUM_SOCKETS;i++){
+        ABTS_INT_EQUAL(tc, 0, pollarray[i].reqevents);
+        ABTS_INT_EQUAL(tc, 0, pollarray[i].rtnevents);
+
+        rv = apr_poll_socket_add(pollarray, s[i], APR_POLLIN);
+        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+        ABTS_PTR_EQUAL(tc, s[i], pollarray[i].desc.s);
+    }
+}
+
+static void setup_large_poll(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    int i;
+
+    rv = apr_poll_setup(&pollarray_large, LARGE_NUM_SOCKETS, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    
+    for (i = 0; i < LARGE_NUM_SOCKETS;i++){
+        ABTS_INT_EQUAL(tc, 0, pollarray_large[i].reqevents);
+        ABTS_INT_EQUAL(tc, 0, pollarray_large[i].rtnevents);
+
+        rv = apr_poll_socket_add(pollarray_large, s[i], APR_POLLIN);
+        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+        ABTS_PTR_EQUAL(tc, s[i], pollarray_large[i].desc.s);
+    }
+}
+
+static void nomessage(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    int srv = SMALL_NUM_SOCKETS;
+
+    rv = apr_poll(pollarray, SMALL_NUM_SOCKETS, &srv, 2 * APR_USEC_PER_SEC);
+    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv));
+    check_sockets(pollarray, s, 0, 0, tc);
+    check_sockets(pollarray, s, 1, 0, tc);
+    check_sockets(pollarray, s, 2, 0, tc);
+}
+
+static void send_2(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    int srv = SMALL_NUM_SOCKETS;
+
+    send_msg(s, sa, 2, tc);
+
+    rv = apr_poll(pollarray, SMALL_NUM_SOCKETS, &srv, 2 * APR_USEC_PER_SEC);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    check_sockets(pollarray, s, 0, 0, tc);
+    check_sockets(pollarray, s, 1, 0, tc);
+    check_sockets(pollarray, s, 2, 1, tc);
+}
+
+static void recv_2_send_1(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    int srv = SMALL_NUM_SOCKETS;
+
+    recv_msg(s, 2, p, tc);
+    send_msg(s, sa, 1, tc);
+
+    rv = apr_poll(pollarray, SMALL_NUM_SOCKETS, &srv, 2 * APR_USEC_PER_SEC);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    check_sockets(pollarray, s, 0, 0, tc);
+    check_sockets(pollarray, s, 1, 1, tc);
+    check_sockets(pollarray, s, 2, 0, tc);
+}
+
+static void send_2_signaled_1(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    int srv = SMALL_NUM_SOCKETS;
+
+    send_msg(s, sa, 2, tc);
+
+    rv = apr_poll(pollarray, SMALL_NUM_SOCKETS, &srv, 2 * APR_USEC_PER_SEC);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    check_sockets(pollarray, s, 0, 0, tc);
+    check_sockets(pollarray, s, 1, 1, tc);
+    check_sockets(pollarray, s, 2, 1, tc);
+}
+
+static void recv_1_send_0(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    int srv = SMALL_NUM_SOCKETS;
+
+    recv_msg(s, 1, p, tc);
+    send_msg(s, sa, 0, tc);
+
+    rv = apr_poll(pollarray, SMALL_NUM_SOCKETS, &srv, 2 * APR_USEC_PER_SEC);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    check_sockets(pollarray, s, 0, 1, tc);
+    check_sockets(pollarray, s, 1, 0, tc);
+    check_sockets(pollarray, s, 2, 1, tc);
+}
+
+static void clear_all_signalled(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    int srv = SMALL_NUM_SOCKETS;
+
+    recv_msg(s, 0, p, tc);
+    recv_msg(s, 2, p, tc);
+
+    rv = apr_poll(pollarray, SMALL_NUM_SOCKETS, &srv, 2 * APR_USEC_PER_SEC);
+    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv));
+    check_sockets(pollarray, s, 0, 0, tc);
+    check_sockets(pollarray, s, 1, 0, tc);
+    check_sockets(pollarray, s, 2, 0, tc);
+}
+
+static void send_large_pollarray(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    int lrv = LARGE_NUM_SOCKETS;
+    int i;
+
+    send_msg(s, sa, LARGE_NUM_SOCKETS - 1, tc);
+
+    rv = apr_poll(pollarray_large, LARGE_NUM_SOCKETS, &lrv, 
+                  2 * APR_USEC_PER_SEC);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    for (i = 0; i < LARGE_NUM_SOCKETS; i++) {
+        if (i == (LARGE_NUM_SOCKETS - 1)) {
+            check_sockets(pollarray_large, s, i, 1, tc);
+        }
+        else {
+            check_sockets(pollarray_large, s, i, 0, tc);
+        }
+    }
+}
+
+static void recv_large_pollarray(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    int lrv = LARGE_NUM_SOCKETS;
+    int i;
+
+    recv_msg(s, LARGE_NUM_SOCKETS - 1, p, tc);
+
+    rv = apr_poll(pollarray_large, LARGE_NUM_SOCKETS, &lrv, 
+                  2 * APR_USEC_PER_SEC);
+    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv));
+
+    for (i = 0; i < LARGE_NUM_SOCKETS; i++) {
+        check_sockets(pollarray_large, s, i, 0, tc);
+    }
+}
+#endif
+
+static void setup_pollset(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    rv = apr_pollset_create_ex(&pollset, LARGE_NUM_SOCKETS, p, 0,
+                               default_pollset_impl);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+}
+
+static void multi_event_pollset(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_pollfd_t socket_pollfd;
+    int lrv;
+    const apr_pollfd_t *descs = NULL;
+
+    ABTS_PTR_NOTNULL(tc, s[0]);
+    socket_pollfd.desc_type = APR_POLL_SOCKET;
+    socket_pollfd.reqevents = APR_POLLIN | APR_POLLOUT;
+    socket_pollfd.desc.s = s[0];
+    socket_pollfd.client_data = s[0];
+    rv = apr_pollset_add(pollset, &socket_pollfd);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    send_msg(s, sa, 0, tc);
+
+    rv = apr_pollset_poll(pollset, -1, &lrv, &descs);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    if (lrv == 1) {
+        int ev = descs[0].rtnevents;
+        ABTS_PTR_EQUAL(tc, s[0], descs[0].desc.s);
+        ABTS_PTR_EQUAL(tc, s[0],  descs[0].client_data);
+        ABTS_ASSERT(tc, "either or both of APR_POLLIN, APR_POLLOUT returned",
+                    ((ev & APR_POLLIN) != 0) || ((ev & APR_POLLOUT) != 0));
+    }
+    else if (lrv == 2) {
+        ABTS_PTR_EQUAL(tc, s[0], descs[0].desc.s);
+        ABTS_PTR_EQUAL(tc, s[0], descs[0].client_data);
+        ABTS_PTR_EQUAL(tc, s[0], descs[1].desc.s);
+        ABTS_PTR_EQUAL(tc, s[0], descs[1].client_data);
+        ABTS_ASSERT(tc, "returned events incorrect",
+                    ((descs[0].rtnevents | descs[1].rtnevents)
+                     == (APR_POLLIN | APR_POLLOUT))
+                    && descs[0].rtnevents != descs[1].rtnevents);
+    }
+    else {
+        ABTS_ASSERT(tc, "either one or two events returned",
+                    lrv == 1 || lrv == 2);
+    }
+
+    recv_msg(s, 0, p, tc);
+
+    rv = apr_pollset_poll(pollset, 0, &lrv, &descs);
+    ABTS_INT_EQUAL(tc, 0, APR_STATUS_IS_TIMEUP(rv));
+    ABTS_INT_EQUAL(tc, 1, lrv);
+    ABTS_PTR_EQUAL(tc, s[0], descs[0].desc.s);
+    ABTS_INT_EQUAL(tc, APR_POLLOUT, descs[0].rtnevents);
+    ABTS_PTR_EQUAL(tc, s[0],  descs[0].client_data);
+
+    rv = apr_pollset_remove(pollset, &socket_pollfd);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+}
+                         
+static void add_sockets_pollset(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    int i;
+
+    for (i = 0; i < LARGE_NUM_SOCKETS;i++){
+        apr_pollfd_t socket_pollfd;
+
+        ABTS_PTR_NOTNULL(tc, s[i]);
+
+        socket_pollfd.desc_type = APR_POLL_SOCKET;
+        socket_pollfd.reqevents = APR_POLLIN;
+        socket_pollfd.desc.s = s[i];
+        socket_pollfd.client_data = s[i];
+        rv = apr_pollset_add(pollset, &socket_pollfd);
+        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    }
+}
+
+static void nomessage_pollset(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    int lrv;
+    const apr_pollfd_t *descs = NULL;
+
+    rv = apr_pollset_poll(pollset, 0, &lrv, &descs);
+    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv));
+    ABTS_INT_EQUAL(tc, 0, lrv);
+    ABTS_PTR_EQUAL(tc, NULL, descs);
+}
+
+static void send0_pollset(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    const apr_pollfd_t *descs = NULL;
+    int num;
+
+    send_msg(s, sa, 0, tc);
+    rv = apr_pollset_poll(pollset, -1, &num, &descs);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_INT_EQUAL(tc, 1, num);
+    ABTS_PTR_NOTNULL(tc, descs);
+
+    ABTS_PTR_EQUAL(tc, s[0], descs[0].desc.s);
+    ABTS_PTR_EQUAL(tc, s[0], descs[0].client_data);
+}
+
+static void recv0_pollset(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    int lrv;
+    const apr_pollfd_t *descs = NULL;
+
+    recv_msg(s, 0, p, tc);
+    rv = apr_pollset_poll(pollset, 0, &lrv, &descs);
+    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv));
+    ABTS_INT_EQUAL(tc, 0, lrv);
+    ABTS_PTR_EQUAL(tc, NULL, descs);
+}
+
+static void send_middle_pollset(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    const apr_pollfd_t *descs = NULL;
+    int num;
+    
+    send_msg(s, sa, 2, tc);
+    send_msg(s, sa, 5, tc);
+    rv = apr_pollset_poll(pollset, -1, &num, &descs);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_PTR_NOTNULL(tc, descs);
+    ABTS_ASSERT(tc, "either one or two events returned",
+                num == 1 || num == 2);
+
+    /* The poll might only see the first sent message, in which
+     * case we just don't bother checking this assertion */
+    if (num == 2) {
+        ABTS_ASSERT(tc, "Incorrect socket in result set",
+                    ((descs[0].desc.s == s[2]) && (descs[1].desc.s == s[5])) ||
+                    ((descs[0].desc.s == s[5]) && (descs[1].desc.s == s[2])));
+    }
+}
+
+static void clear_middle_pollset(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    int lrv;
+    const apr_pollfd_t *descs = NULL;
+
+    recv_msg(s, 2, p, tc);
+    recv_msg(s, 5, p, tc);
+
+    rv = apr_pollset_poll(pollset, 0, &lrv, &descs);
+    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv));
+    ABTS_INT_EQUAL(tc, 0, lrv);
+    ABTS_PTR_EQUAL(tc, NULL, descs);
+}
+
+static void send_last_pollset(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    const apr_pollfd_t *descs = NULL;
+    int num;
+    
+    send_msg(s, sa, LARGE_NUM_SOCKETS - 1, tc);
+    rv = apr_pollset_poll(pollset, -1, &num, &descs);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_INT_EQUAL(tc, 1, num);
+    ABTS_PTR_NOTNULL(tc, descs);
+
+    ABTS_PTR_EQUAL(tc, s[LARGE_NUM_SOCKETS - 1], descs[0].desc.s);
+    ABTS_PTR_EQUAL(tc, s[LARGE_NUM_SOCKETS - 1], descs[0].client_data);
+}
+
+static void clear_last_pollset(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    int lrv;
+    const apr_pollfd_t *descs = NULL;
+
+    recv_msg(s, LARGE_NUM_SOCKETS - 1, p, tc);
+
+    rv = apr_pollset_poll(pollset, 0, &lrv, &descs);
+    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv));
+    ABTS_INT_EQUAL(tc, 0, lrv);
+    ABTS_PTR_EQUAL(tc, NULL, descs);
+}
+
+static void close_all_sockets(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    int i;
+
+    for (i = 0; i < LARGE_NUM_SOCKETS; i++){
+        rv = apr_socket_close(s[i]);
+        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    }
+}
+
+static void pollset_remove(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_pollset_t *pollset;
+    const apr_pollfd_t *hot_files;
+    apr_pollfd_t pfd;
+    apr_int32_t num;
+
+    rv = apr_pollset_create_ex(&pollset, 5, p, 0,
+                               default_pollset_impl);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    pfd.p = p;
+    pfd.desc_type = APR_POLL_SOCKET;
+    pfd.reqevents = APR_POLLOUT;
+
+    pfd.desc.s = s[0];
+    pfd.client_data = (void *)1;
+    rv = apr_pollset_add(pollset, &pfd);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    pfd.desc.s = s[1];
+    pfd.client_data = (void *)2;
+    rv = apr_pollset_add(pollset, &pfd);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    pfd.desc.s = s[2];
+    pfd.client_data = (void *)3;
+    rv = apr_pollset_add(pollset, &pfd);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    pfd.desc.s = s[3];
+    pfd.client_data = (void *)4;
+    rv = apr_pollset_add(pollset, &pfd);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_pollset_poll(pollset, 1000, &num, &hot_files);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_INT_EQUAL(tc, 4, num);
+
+    /* now remove the pollset element referring to desc s[1] */
+    pfd.desc.s = s[1];
+    pfd.client_data = (void *)999; /* not used on this call */
+    rv = apr_pollset_remove(pollset, &pfd);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    /* this time only three should match */
+    rv = apr_pollset_poll(pollset, 1000, &num, &hot_files);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_INT_EQUAL(tc, 3, num);
+    ABTS_PTR_EQUAL(tc, (void *)1, hot_files[0].client_data);
+    ABTS_PTR_EQUAL(tc, s[0], hot_files[0].desc.s);
+    ABTS_PTR_EQUAL(tc, (void *)3, hot_files[1].client_data);
+    ABTS_PTR_EQUAL(tc, s[2], hot_files[1].desc.s);
+    ABTS_PTR_EQUAL(tc, (void *)4, hot_files[2].client_data);
+    ABTS_PTR_EQUAL(tc, s[3], hot_files[2].desc.s);
+    
+    /* now remove the pollset elements referring to desc s[2] */
+    pfd.desc.s = s[2];
+    pfd.client_data = (void *)999; /* not used on this call */
+    rv = apr_pollset_remove(pollset, &pfd);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    /* this time only two should match */
+    rv = apr_pollset_poll(pollset, 1000, &num, &hot_files);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_INT_EQUAL(tc, 2, num);
+    ABTS_ASSERT(tc, "Incorrect socket in result set",
+            ((hot_files[0].desc.s == s[0]) && (hot_files[1].desc.s == s[3]))  ||
+            ((hot_files[0].desc.s == s[3]) && (hot_files[1].desc.s == s[0])));
+    ABTS_ASSERT(tc, "Incorrect client data in result set",
+            ((hot_files[0].client_data == (void *)1) &&
+             (hot_files[1].client_data == (void *)4)) ||
+            ((hot_files[0].client_data == (void *)4) &&
+             (hot_files[1].client_data == (void *)1)));
+}
+
+#define POLLCB_PREREQ \
+    do { \
+        if (pollcb == NULL) { \
+            ABTS_NOT_IMPL(tc, "pollcb interface not supported"); \
+            return; \
+        } \
+    } while (0)
+
+static void setup_pollcb(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    rv = apr_pollcb_create(&pollcb, LARGE_NUM_SOCKETS, p, 0);
+    if (rv == APR_ENOTIMPL) {
+        pollcb = NULL;
+        ABTS_NOT_IMPL(tc, "pollcb interface not supported");
+    }
+    else {
+        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    }
+}
+
+typedef struct pollcb_baton_t {
+    abts_case *tc;
+    int count;
+} pollcb_baton_t;
+
+static apr_status_t trigger_pollcb_cb(void *baton, apr_pollfd_t *descriptor)
+{
+    pollcb_baton_t *pcb = (pollcb_baton_t *) baton;
+    ABTS_PTR_EQUAL(pcb->tc, s[0], descriptor->desc.s);
+    ABTS_PTR_EQUAL(pcb->tc, s[0], descriptor->client_data);
+    pcb->count++;
+    return APR_SUCCESS;
+}
+
+static void trigger_pollcb(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_pollfd_t socket_pollfd;
+    pollcb_baton_t pcb;
+    
+    POLLCB_PREREQ;
+
+    ABTS_PTR_NOTNULL(tc, s[0]);
+    socket_pollfd.desc_type = APR_POLL_SOCKET;
+    socket_pollfd.reqevents = APR_POLLIN;
+    socket_pollfd.desc.s = s[0];
+    socket_pollfd.client_data = s[0];
+    rv = apr_pollcb_add(pollcb, &socket_pollfd);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    
+    send_msg(s, sa, 0, tc);
+    pcb.tc = tc;
+    pcb.count = 0;
+    rv = apr_pollcb_poll(pollcb, -1, trigger_pollcb_cb, &pcb);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_INT_EQUAL(tc, 1, pcb.count);
+
+    rv = apr_pollcb_remove(pollcb, &socket_pollfd);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+}
+
+static void timeout_pollcb(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    pollcb_baton_t pcb;
+
+    POLLCB_PREREQ;
+
+    pcb.count = 0;
+    pcb.tc = tc;
+
+    rv = apr_pollcb_poll(pollcb, 1, trigger_pollcb_cb, &pcb);    
+    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv));
+    ABTS_INT_EQUAL(tc, 0, pcb.count);
+}
+
+static void timeout_pollin_pollcb(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    pollcb_baton_t pcb;
+    apr_pollfd_t socket_pollfd;
+
+    POLLCB_PREREQ;
+
+    recv_msg(s, 0, p, tc);
+    
+    ABTS_PTR_NOTNULL(tc, s[0]);
+    socket_pollfd.desc_type = APR_POLL_SOCKET;
+    socket_pollfd.reqevents = APR_POLLIN;
+    socket_pollfd.desc.s = s[0];
+    socket_pollfd.client_data = s[0];
+    rv = apr_pollcb_add(pollcb, &socket_pollfd);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    
+    pcb.count = 0;
+    pcb.tc = tc;
+    
+    rv = apr_pollcb_poll(pollcb, 1, trigger_pollcb_cb, &pcb);    
+    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv));
+    ABTS_INT_EQUAL(tc, 0, pcb.count);
+
+    rv = apr_pollcb_remove(pollcb, &socket_pollfd);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+}
+
+static void pollset_default(abts_case *tc, void *data)
+{
+    apr_status_t rv1, rv2;
+    apr_pollset_t *pollset;
+
+    /* verify that APR will successfully create a pollset if an invalid method
+     * is specified as long as APR_POLLSET_NODEFAULT isn't specified
+     * (no platform has both APR_POLLSET_PORT and APR_POLLSET_KQUEUE, so at
+     * least one create call will succeed after having to switch to the default
+     * type)
+     */
+    rv1 = apr_pollset_create_ex(&pollset, 1, p, 0, APR_POLLSET_PORT);
+
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv1);
+    ABTS_PTR_NOTNULL(tc, pollset);
+    
+    rv1 = apr_pollset_create_ex(&pollset, 1, p, 0, APR_POLLSET_KQUEUE);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv1);
+    ABTS_PTR_NOTNULL(tc, pollset);
+
+    /* verify that APR will fail to create a pollset if an invalid method is
+     * specified along with APR_POLLSET_NODEFAULT
+     * (no platform has both APR_POLLSET_PORT and APR_POLLSET_KQUEUE, so at
+     * least one create call will fail since it can't switch to the default
+     * type)
+     */
+    rv1 = apr_pollset_create_ex(&pollset, 1, p, APR_POLLSET_NODEFAULT,
+                               APR_POLLSET_PORT);
+
+    if (rv1 == APR_SUCCESS) {
+        ABTS_PTR_NOTNULL(tc, pollset);
+    }
+    
+    rv2 = apr_pollset_create_ex(&pollset, 1, p, APR_POLLSET_NODEFAULT,
+                               APR_POLLSET_KQUEUE);
+    if (rv2 == APR_SUCCESS) {
+        ABTS_PTR_NOTNULL(tc, pollset);
+    }
+    
+    ABTS_ASSERT(tc,
+                "failure using APR_POLLSET_NODEFAULT with unsupported method",
+                rv1 != APR_SUCCESS || rv2 != APR_SUCCESS);
+}
+
+static void pollcb_default(abts_case *tc, void *data)
+{
+    apr_status_t rv1, rv2;
+    apr_pollcb_t *pollcb;
+
+    /* verify that APR will successfully create a pollcb if an invalid method
+     * is specified as long as APR_POLLSET_NODEFAULT isn't specified
+     * (no platform has both APR_POLLSET_PORT and APR_POLLSET_KQUEUE, so at
+     * least one create call will succeed after having to switch to the default
+     * type)
+     */
+    rv1 = apr_pollcb_create_ex(&pollcb, 1, p, 0, APR_POLLSET_PORT);
+    if (rv1 == APR_ENOTIMPL) {
+        ABTS_NOT_IMPL(tc, "pollcb interface not supported");
+        return;
+    }
+
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv1);
+    ABTS_PTR_NOTNULL(tc, pollcb);
+    
+    rv1 = apr_pollcb_create_ex(&pollcb, 1, p, 0, APR_POLLSET_KQUEUE);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv1);
+    ABTS_PTR_NOTNULL(tc, pollcb);
+
+    /* verify that APR will fail to create a pollcb if an invalid method is
+     * specified along with APR_POLLSET_NODEFAULT
+     * (no platform has both APR_POLLSET_PORT and APR_POLLSET_KQUEUE, so at
+     * least one create call will fail since it can't switch to the default
+     * type)
+     */
+    rv1 = apr_pollcb_create_ex(&pollcb, 1, p, APR_POLLSET_NODEFAULT,
+                               APR_POLLSET_PORT);
+
+    if (rv1 == APR_SUCCESS) {
+        ABTS_PTR_NOTNULL(tc, pollcb);
+    }
+    
+    rv2 = apr_pollcb_create_ex(&pollcb, 1, p, APR_POLLSET_NODEFAULT,
+                               APR_POLLSET_KQUEUE);
+    if (rv2 == APR_SUCCESS) {
+        ABTS_PTR_NOTNULL(tc, pollcb);
+    }
+    
+    ABTS_ASSERT(tc,
+                "failure using APR_POLLSET_NODEFAULT with unsupported method",
+                rv1 != APR_SUCCESS || rv2 != APR_SUCCESS);
+
+
+    /* verify basic behavior for another method fallback case (this caused
+     * APR to crash before r834029)
+     */
+
+    rv1 = apr_pollcb_create_ex(&pollcb, 1, p, 0, APR_POLLSET_POLL);
+    if (rv1 != APR_ENOTIMPL) {
+        ABTS_INT_EQUAL(tc, rv1, APR_SUCCESS);
+        ABTS_PTR_NOTNULL(tc, pollcb);
+    }
+}
+
+static void pollset_wakeup(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_pollfd_t socket_pollfd;
+    apr_pollset_t *pollset;
+    apr_int32_t num;
+    const apr_pollfd_t *descriptors;
+    int i;
+
+    rv = apr_pollset_create_ex(&pollset, 1, p, APR_POLLSET_WAKEABLE,
+                               default_pollset_impl);
+    if (rv == APR_ENOTIMPL) {
+        ABTS_NOT_IMPL(tc, "apr_pollset_wakeup() not supported");
+        return;
+    }
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    /* Send wakeup but no data; apr_pollset_poll() should return APR_EINTR.
+     * Do it twice to test implementations that need to re-arm the events after
+     * poll()ing (e.g. APR_POLLSET_PORT), hence verify that the wakeup pipe is
+     * still in the place afterward.
+     */
+    for (i = 0; i < 2; ++i) {
+        rv = apr_pollset_wakeup(pollset);
+        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+        rv = apr_pollset_poll(pollset, -1, &num, &descriptors);
+        ABTS_INT_EQUAL(tc, APR_EINTR, rv);
+    }
+
+    /* send wakeup and data; apr_pollset_poll() should return APR_SUCCESS */
+    socket_pollfd.desc_type = APR_POLL_SOCKET;
+    socket_pollfd.reqevents = APR_POLLIN;
+    socket_pollfd.desc.s = s[0];
+    socket_pollfd.client_data = s[0];
+    rv = apr_pollset_add(pollset, &socket_pollfd);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    send_msg(s, sa, 0, tc); apr_sleep(1000);
+
+    rv = apr_pollset_wakeup(pollset);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_pollset_poll(pollset, -1, &num, &descriptors);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_INT_EQUAL(tc, 1, num);
+}
+
+/* Should never be invoked */
+static apr_status_t wakeup_pollcb_cb(void *baton, apr_pollfd_t *descriptor)
+{
+    abts_case *tc = (abts_case *) baton;
+
+    ABTS_FAIL(tc, "pollcb callback invoked on apr_pollcb_wakeup()");
+    return APR_SUCCESS;
+}
+
+static void pollcb_wakeup(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_pollcb_t *pcb;
+
+    rv = apr_pollcb_create(&pcb, 1, p, APR_POLLSET_WAKEABLE);
+    if (rv == APR_ENOTIMPL) {
+        ABTS_NOT_IMPL(tc, "pollcb interface not supported");
+        return;
+    }
+    else {
+        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    }
+
+    rv = apr_pollcb_wakeup(pcb);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_pollcb_poll(pcb, -1, wakeup_pollcb_cb, tc);
+    ABTS_INT_EQUAL(tc, APR_EINTR, rv);
+}
+
+static void justsleep(abts_case *tc, void *data)
+{
+    apr_int32_t nsds;
+    const apr_pollfd_t *hot_files;
+    apr_pollset_t *pollset;
+    apr_status_t rv;
+    apr_time_t t1, t2;
+    int i;
+    apr_pollset_method_e methods[] = {
+        APR_POLLSET_DEFAULT,
+        APR_POLLSET_SELECT,
+        APR_POLLSET_KQUEUE,
+        APR_POLLSET_PORT,
+        APR_POLLSET_EPOLL,
+        APR_POLLSET_POLL};
+
+    nsds = 1;
+    t1 = apr_time_now();
+    rv = apr_poll(NULL, 0, &nsds, apr_time_from_msec(200));
+    t2 = apr_time_now();
+    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv));
+    ABTS_INT_EQUAL(tc, 0, nsds);
+    ABTS_ASSERT(tc,
+                "apr_poll() didn't sleep",
+                (t2 - t1) > apr_time_from_msec(100));
+
+    for (i = 0; i < sizeof methods / sizeof methods[0]; i++) {
+        rv = apr_pollset_create_ex(&pollset, 5, p, 0, methods[i]);
+        if (rv != APR_ENOTIMPL) {
+            ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+            nsds = 1;
+            t1 = apr_time_now();
+            rv = apr_pollset_poll(pollset, apr_time_from_msec(200), &nsds,
+                                  &hot_files);
+            t2 = apr_time_now();
+            ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv));
+            ABTS_INT_EQUAL(tc, 0, nsds);
+            ABTS_ASSERT(tc,
+                        "apr_pollset_poll() didn't sleep",
+                        (t2 - t1) > apr_time_from_msec(100));
+
+            rv = apr_pollset_destroy(pollset);
+            ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+        }
+
+        rv = apr_pollcb_create_ex(&pollcb, 5, p, 0, methods[0]);
+        if (rv != APR_ENOTIMPL) {
+            ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+            t1 = apr_time_now();
+            rv = apr_pollcb_poll(pollcb, apr_time_from_msec(200), NULL, NULL);
+            t2 = apr_time_now();
+            ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv));
+            ABTS_ASSERT(tc,
+                        "apr_pollcb_poll() didn't sleep",
+                        (t2 - t1) > apr_time_from_msec(100));
+
+            /* no apr_pollcb_destroy() */
+        }
+    }
+}
+
+abts_suite *testpoll(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite)
+
+    abts_run_test(suite, create_all_sockets, NULL);
+
+#ifdef OLD_POLL_INTERFACE
+    abts_run_test(suite, setup_small_poll, NULL);
+    abts_run_test(suite, setup_large_poll, NULL);
+    abts_run_test(suite, nomessage, NULL);
+    abts_run_test(suite, send_2, NULL);
+    abts_run_test(suite, recv_2_send_1, NULL);
+    abts_run_test(suite, send_2_signaled_1, NULL);
+    abts_run_test(suite, recv_1_send_0, NULL);
+    abts_run_test(suite, clear_all_signalled, NULL);
+    abts_run_test(suite, send_large_pollarray, NULL);
+    abts_run_test(suite, recv_large_pollarray, NULL);
+#endif
+
+    abts_run_test(suite, setup_pollset, NULL);
+    abts_run_test(suite, multi_event_pollset, NULL);
+    abts_run_test(suite, add_sockets_pollset, NULL);
+    abts_run_test(suite, nomessage_pollset, NULL);
+    abts_run_test(suite, send0_pollset, NULL);
+    abts_run_test(suite, recv0_pollset, NULL);
+    abts_run_test(suite, send_middle_pollset, NULL);
+    abts_run_test(suite, clear_middle_pollset, NULL);
+    abts_run_test(suite, send_last_pollset, NULL);
+    abts_run_test(suite, clear_last_pollset, NULL);
+    abts_run_test(suite, pollset_remove, NULL);
+    abts_run_test(suite, close_all_sockets, NULL);
+    abts_run_test(suite, create_all_sockets, NULL);
+    abts_run_test(suite, setup_pollcb, NULL);
+    abts_run_test(suite, trigger_pollcb, NULL);
+    abts_run_test(suite, timeout_pollcb, NULL);
+    abts_run_test(suite, timeout_pollin_pollcb, NULL);
+    abts_run_test(suite, pollset_wakeup, NULL);
+    abts_run_test(suite, pollcb_wakeup, NULL);
+    abts_run_test(suite, close_all_sockets, NULL);
+    abts_run_test(suite, pollset_default, NULL);
+    abts_run_test(suite, pollcb_default, NULL);
+    abts_run_test(suite, justsleep, NULL);
+
+    return suite;
+}
+
diff --git a/test/testpools.c b/test/testpools.c
new file mode 100644
index 00000000000..8b00393893b
--- /dev/null
+++ b/test/testpools.c
@@ -0,0 +1,164 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "apr_general.h"
+#include "apr_pools.h"
+#include "apr_errno.h"
+#include "apr_file_io.h"
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#if APR_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include "testutil.h"
+
+#define ALLOC_BYTES 1024
+
+static apr_pool_t *pmain = NULL;
+static apr_pool_t *pchild = NULL;
+
+static void alloc_bytes(abts_case *tc, void *data)
+{
+    int i;
+    char *alloc;
+    
+    alloc = apr_palloc(pmain, ALLOC_BYTES);
+    ABTS_PTR_NOTNULL(tc, alloc);
+
+    for (i=0;i<ALLOC_BYTES;i++) {
+        char *ptr = alloc + i;
+        *ptr = 0xa;
+    }
+    /* This is just added to get the positive.  If this test fails, the
+     * suite will seg fault.
+     */
+    ABTS_TRUE(tc, 1);
+}
+
+static void calloc_bytes(abts_case *tc, void *data)
+{
+    int i;
+    char *alloc;
+    
+    alloc = apr_pcalloc(pmain, ALLOC_BYTES);
+    ABTS_PTR_NOTNULL(tc, alloc);
+
+    for (i=0;i<ALLOC_BYTES;i++) {
+        char *ptr = alloc + i;
+        ABTS_TRUE(tc, *ptr == '\0');
+    }
+}
+
+static void parent_pool(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+
+    rv = apr_pool_create(&pmain, NULL);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_PTR_NOTNULL(tc, pmain);
+}
+
+static void child_pool(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+
+    rv = apr_pool_create(&pchild, pmain);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_PTR_NOTNULL(tc, pchild);
+}
+
+static void test_ancestor(abts_case *tc, void *data)
+{
+    ABTS_INT_EQUAL(tc, 1, apr_pool_is_ancestor(pmain, pchild));
+}
+
+static void test_notancestor(abts_case *tc, void *data)
+{
+    ABTS_INT_EQUAL(tc, 0, apr_pool_is_ancestor(pchild, pmain));
+}
+
+static apr_status_t success_cleanup(void *data)
+{
+    return APR_SUCCESS;
+}
+
+static char *checker_data = "Hello, world.";
+
+static apr_status_t checker_cleanup(void *data)
+{
+    return data == checker_data ? APR_SUCCESS : APR_EGENERAL;
+}
+
+static void test_cleanups(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    int n;
+
+    /* do this several times to test the cleanup freelist handling. */
+    for (n = 0; n < 5; n++) {
+        apr_pool_cleanup_register(pchild, NULL, success_cleanup,
+                                  success_cleanup);
+        apr_pool_cleanup_register(pchild, checker_data, checker_cleanup,
+                                  success_cleanup);
+        apr_pool_cleanup_register(pchild, NULL, checker_cleanup, 
+                                  success_cleanup);
+
+        rv = apr_pool_cleanup_run(p, NULL, success_cleanup);
+        ABTS_ASSERT(tc, "nullop cleanup run OK", rv == APR_SUCCESS);
+        rv = apr_pool_cleanup_run(p, checker_data, checker_cleanup);
+        ABTS_ASSERT(tc, "cleanup passed correct data", rv == APR_SUCCESS);
+        rv = apr_pool_cleanup_run(p, NULL, checker_cleanup);
+        ABTS_ASSERT(tc, "cleanup passed correct data", rv == APR_EGENERAL);
+
+        if (n == 2) {
+            /* clear the pool to check that works */
+            apr_pool_clear(pchild);
+        }
+
+        if (n % 2 == 0) {
+            /* throw another random cleanup into the mix */
+            apr_pool_cleanup_register(pchild, NULL,
+                                      apr_pool_cleanup_null,
+                                      apr_pool_cleanup_null);
+        }
+    }
+}
+
+static void test_tags(abts_case *tc, void *data)
+{
+    ABTS_PTR_EQUAL(tc, NULL, apr_pool_get_tag(pmain));
+    apr_pool_tag(pmain, "main pool");
+    ABTS_STR_EQUAL(tc, "main pool", apr_pool_get_tag(pmain));
+}
+
+abts_suite *testpool(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite)
+
+    abts_run_test(suite, parent_pool, NULL);
+    abts_run_test(suite, child_pool, NULL);
+    abts_run_test(suite, test_ancestor, NULL);
+    abts_run_test(suite, test_notancestor, NULL);
+    abts_run_test(suite, alloc_bytes, NULL);
+    abts_run_test(suite, calloc_bytes, NULL);
+    abts_run_test(suite, test_cleanups, NULL);
+    abts_run_test(suite, test_tags, NULL);
+
+    return suite;
+}
+
diff --git a/test/testproc.c b/test/testproc.c
index 74903d24672..c86fb2997b5 100644
--- a/test/testproc.c
+++ b/test/testproc.c
@@ -1,192 +1,174 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
 #include "apr_thread_proc.h"
 #include "apr_errno.h"
 #include "apr_general.h"
 #include "apr_lib.h"
-#include "errno.h"
-#ifndef WIN32
-#include <unistd.h>
-#endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <string.h>
-
-int test_filedel(void);
-int testdirs(void);
-
-int main(int argc, char *argv[])
+#include "apr_strings.h"
+#include "testutil.h"
+
+#define TESTSTR "This is a test"
+
+#define PROC_CHILD_NAME TESTBINPATH "proc_child" EXTENSION
+
+static char *proc_child;
+
+static apr_proc_t newproc;
+
+static void test_create_proc(abts_case *tc, void *data)
 {
-    ap_pool_t *context;
-    ap_proc_t *newproc;
-    ap_procattr_t *attr;
-    ap_file_t *testfile = NULL;
-    ap_ssize_t length;
+    const char *args[2];
+    apr_procattr_t *attr;
+    apr_file_t *testfile = NULL;
+    apr_status_t rv;
+    apr_size_t length;
     char *buf;
-    char *args[3];
-    char *teststr;
-
-    if (ap_initialize() != APR_SUCCESS) {
-        fprintf(stderr, "Couldn't initialize.");
-        exit(-1);
-    }
-    atexit(ap_terminate);
-    ap_create_pool(&context, NULL);
-
-
-    if (argc > 1) {
-        teststr = ap_palloc(context, 256);
-        teststr = fgets(teststr, 256, stdin);      
-        fprintf(stdout, "%s", teststr);      
-        exit(1);
-    }
-    teststr = ap_pstrdup(context, "Whooo Hoooo\0");
-
-    fprintf(stdout, "Creating directory for later use.......");
-    if (ap_make_dir("proctest", APR_UREAD | APR_UWRITE | APR_UEXECUTE, context) != APR_SUCCESS) {
-        fprintf(stderr, "Could not create dir\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK\n");
-
-    fprintf(stdout, "Creating procattr.......");
-    if (ap_createprocattr_init(&attr, context) != APR_SUCCESS) {
-        fprintf(stderr, "Could not create attr\n");
-        exit(-1);;
-    }
-    fprintf(stdout, "OK.\n");
-
-    fprintf(stdout, "Setting attr pipes, all three.......");
-    if (ap_setprocattr_io(attr, APR_FULL_BLOCK, 
-                          APR_CHILD_BLOCK, APR_NO_PIPE) != APR_SUCCESS) {
-        fprintf(stderr, "Could not set pipes attr\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK.\n");
-    
-    fprintf(stdout, "Setting attr dir.......");
-    if (ap_setprocattr_dir(attr, "proctest") != APR_SUCCESS) {
-        fprintf(stderr, "Could not set directory attr\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK.\n");
-
-    fprintf(stdout, "Setting attr cmd type.......");
-    if (ap_setprocattr_cmdtype(attr, APR_PROGRAM) != APR_SUCCESS) {
-        fprintf(stderr, "Could not set cmd type attr\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK.\n");
-
-    args[0] = ap_pstrdup(context, "testproc");
-    args[1] = ap_pstrdup(context, "-X");
-    args[2] = NULL;
+
+    rv = apr_procattr_create(&attr, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_procattr_io_set(attr, APR_FULL_BLOCK, APR_FULL_BLOCK, 
+                             APR_NO_PIPE);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_procattr_dir_set(attr, "data");
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_procattr_cmdtype_set(attr, APR_PROGRAM_ENV);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    args[0] = "proc_child" EXTENSION;
+    args[1] = NULL;
     
-    fprintf(stdout, "Creating a new process.......");
-    if (ap_create_process(&newproc, "../testproc", args, NULL, attr, context) != APR_SUCCESS) {
-        fprintf(stderr, "Could not create the new process\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK.\n");
-
-    fprintf(stdout, "Grabbing child's stdin.......");
-    if (ap_get_childin(&testfile, newproc) != APR_SUCCESS) {
-        fprintf(stderr, "Could not get child's stdout\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK.\n");
+    rv = apr_proc_create(&newproc, proc_child, args, NULL, 
+                         attr, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
 
+    testfile = newproc.in;
+
+    length = strlen(TESTSTR);
+    rv = apr_file_write(testfile, TESTSTR, &length);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_SIZE_EQUAL(tc, strlen(TESTSTR), length);
+
+    testfile = newproc.out;
     length = 256;
-    fprintf(stdout, "Writing the data to child.......");
-    if (ap_write(testfile, teststr, &length) == APR_SUCCESS) {
-        fprintf(stdout,"OK\n");
-    }
-    else fprintf(stderr, "Write failed.\n");
-
-    fprintf(stdout, "Grabbing child's stdout.......");
-    if (ap_get_childout(&testfile, newproc) != APR_SUCCESS) {
-        fprintf(stderr, "Could not get child's stdout\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK.\n");
+    buf = apr_pcalloc(p, length);
+    rv = apr_file_read(testfile, buf, &length);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_STR_EQUAL(tc, TESTSTR, buf);
+}
+
+static void test_proc_wait(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+
+    rv = apr_proc_wait(&newproc, NULL, NULL, APR_WAIT);
+    ABTS_INT_EQUAL(tc, APR_CHILD_DONE, rv);
+}
+
+static void test_file_redir(abts_case *tc, void *data)
+{
+    apr_file_t *testout = NULL;
+    apr_file_t *testerr = NULL;
+    apr_off_t offset;
+    apr_status_t rv;
+    const char *args[2];
+    apr_procattr_t *attr;
+    apr_file_t *testfile = NULL;
+    apr_size_t length;
+    char *buf;
+
+    testfile = NULL;
+    rv = apr_file_open(&testfile, "data/stdin",
+                       APR_FOPEN_READ | APR_FOPEN_WRITE | APR_FOPEN_CREATE | APR_FOPEN_EXCL,
+                       APR_FPROT_OS_DEFAULT, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    rv = apr_file_open(&testout, "data/stdout",
+                       APR_FOPEN_READ | APR_FOPEN_WRITE | APR_FOPEN_CREATE | APR_FOPEN_EXCL,
+                       APR_FPROT_OS_DEFAULT, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    rv = apr_file_open(&testerr, "data/stderr",
+                       APR_FOPEN_READ | APR_FOPEN_WRITE | APR_FOPEN_CREATE | APR_FOPEN_EXCL,
+                       APR_FPROT_OS_DEFAULT, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    length = strlen(TESTSTR);
+    apr_file_write(testfile, TESTSTR, &length);
+    offset = 0;
+    rv = apr_file_seek(testfile, APR_SET, &offset);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_ASSERT(tc, "File position mismatch, expected 0", offset == 0);
+
+    rv = apr_procattr_create(&attr, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    rv = apr_procattr_child_in_set(attr, testfile, NULL);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    rv = apr_procattr_child_out_set(attr, testout, NULL);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    rv = apr_procattr_child_err_set(attr, testerr, NULL);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    rv = apr_procattr_dir_set(attr, "data");
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    rv = apr_procattr_cmdtype_set(attr, APR_PROGRAM_ENV);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    args[0] = "proc_child";
+    args[1] = NULL;
+
+    rv = apr_proc_create(&newproc, proc_child, args, NULL, 
+                         attr, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_proc_wait(&newproc, NULL, NULL, APR_WAIT);
+    ABTS_INT_EQUAL(tc, APR_CHILD_DONE, rv);
+
+    offset = 0;
+    rv = apr_file_seek(testout, APR_SET, &offset);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
 
     length = 256;
-    fprintf(stdout, "Checking the data read from pipe to child.......");
-    buf = ap_pcalloc(context, length);
-    if (ap_read(testfile, buf, &length) == APR_SUCCESS) {
-        if (!strcmp(buf, teststr))
-            fprintf(stdout,"OK\n");
-        else fprintf(stderr, "Uh-Oh\n");
-    }
-    else fprintf(stderr, "Read failed.\n");
-
-    fprintf(stdout, "Waiting for child to die.......");
-    if (ap_wait_proc(newproc, APR_WAIT) != APR_CHILD_DONE) {
-        fprintf(stderr, "Wait for child failed\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK\n");
-    
-    fprintf(stdout, "Removing directory.......");
-    if (ap_remove_dir("proctest", context) != APR_SUCCESS) {
-        fprintf(stderr, "Could not remove directory.\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK\n");
-
-    return(1);
+    buf = apr_pcalloc(p, length);
+    rv = apr_file_read(testout, buf, &length);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_STR_EQUAL(tc, TESTSTR, buf);
+
+
+    apr_file_close(testfile);
+    apr_file_close(testout);
+    apr_file_close(testerr);
+
+    rv = apr_file_remove("data/stdin", p);;
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    rv = apr_file_remove("data/stdout", p);;
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    rv = apr_file_remove("data/stderr", p);;
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+}
+
+abts_suite *testproc(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite)
+
+    apr_filepath_merge(&proc_child, NULL, PROC_CHILD_NAME, 0, p);
+    abts_run_test(suite, test_create_proc, NULL);
+    abts_run_test(suite, test_proc_wait, NULL);
+    abts_run_test(suite, test_file_redir, NULL);
+
+    return suite;
 }
 
diff --git a/test/testproc.dsp b/test/testproc.dsp
deleted file mode 100644
index b0a547c8288..00000000000
--- a/test/testproc.dsp
+++ /dev/null
@@ -1,91 +0,0 @@
-# Microsoft Developer Studio Project File - Name="testproc" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 5.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=testproc - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "testproc.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 "testproc.mak" CFG="testproc - Win32 Debug"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "testproc - Win32 Release" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE "testproc - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE 
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF  "$(CFG)" == "testproc - 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 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /W3 /GX /O2 /I "..\include" /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ..\Release\aprlib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"..\Release\testproc.exe"
-
-!ELSEIF  "$(CFG)" == "testproc - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "testproc"
-# PROP BASE Intermediate_Dir "testproc"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "testproc"
-# PROP Intermediate_Dir "testproc"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\include" /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
-# SUBTRACT CPP /YX /Yc /Yu
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 ..\Debug\aprlib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\Debug\testproc.exe" /pdbtype:sept
-
-!ENDIF 
-
-# Begin Target
-
-# Name "testproc - Win32 Release"
-# Name "testproc - Win32 Debug"
-# Begin Source File
-
-SOURCE=.\testproc.c
-# End Source File
-# End Target
-# End Project
diff --git a/test/testproc.rbb b/test/testproc.rbb
deleted file mode 100644
index ac2c738bc44..00000000000
--- a/test/testproc.rbb
+++ /dev/null
@@ -1,148 +0,0 @@
-/* ====================================================================
- * Copyright (c) 2000 The Apache Software Foundation.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- *    software must display the following acknowledgment:
- *    "This product includes software developed by the Apache Software Foundation
- *    for use in the Apache HTTP server project (http://www.apache.org/)."
- *
- * 4. The names "Apache Server" and "Apache Software Foundation" must not be used to
- *    endorse or promote products derived from this software without
- *    prior written permission. For written permission, please contact
- *    apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- *    nor may "Apache" appear in their names without prior written
- *    permission of the Apache Software Foundation.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- *    acknowledgment:
- *    "This product includes software developed by the Apache Software Foundation
- *    for use in the Apache HTTP server project (http://www.apache.org/)."
- *
- * THIS SOFTWARE IS PROVIDED BY THE Apache Software Foundation ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE Apache Software Foundation OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.
- * For more information on the Apache Software Foundation and the Apache HTTP server
- * project, please see <http://www.apache.org/>.
- *
- */
-
-#include "apr_thread_proc.h"
-#include "apr_errno.h"
-#include "apr_general.h"
-#include "apr_lib.h"
-#include "errno.h"
-#ifndef WIN32
-#include <unistd.h>
-#endif
-#include <stdio.h>
-#include <signal.h>
-#include <string.h>
-
-int test_filedel(void);
-int testdirs(void);
-
-int main(int argc, char *argv[])
-{
-    ap_context_t *context;
-    ap_proc_t *newproc;
-    ap_procattr_t *attr;
-    ap_file_t *testfile;
-    ap_ssize_t length;
-    char *buf;
-    char *args[3];
-    char *teststr;
-
-    ap_create_context(NULL, NULL, &context);
-
-    teststr = ap_pstrdup(context, "Whooo Hoooo\n");
-
-    if (argc > 1) {
-	fprintf(stdout, "%s", teststr);
-        exit(1);
-    }
-    fprintf(stdout, "Creating procattr.......");
-    if (ap_createprocattr_init(context, &attr) != APR_SUCCESS) {
-        fprintf(stderr, "Could not create attr\n");
-        exit(-1);;
-    }
-    fprintf(stdout, "OK.\n");
-
-    fprintf(stdout, "Setting attr pipes, all three.......");
-    if (ap_setprocattr_io(attr, 1, 1, 0) != APR_SUCCESS) {
-        fprintf(stderr, "Could not set pipes attr\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK.\n");
-    
-    fprintf(stdout, "Setting attr dir.......");
-    if (ap_setprocattr_dir(attr, "proctest") != APR_SUCCESS) {
-        fprintf(stderr, "Could not set directory attr\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK.\n");
-
-    fprintf(stdout, "Setting attr cmd type.......");
-    if (ap_setprocattr_cmdtype(attr, APR_PROGRAM) != APR_SUCCESS) {
-        fprintf(stderr, "Could not set cmd type attr\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK.\n");
-   
-    args[0] = ap_pstrdup(context, "testproc");
-    args[1] = ap_pstrdup(context, "-X");
-    args[2] = NULL;
-    
-    fprintf(stdout, "Creating a new process.......");
-    if (ap_create_process(context, "../testproc", args, NULL, attr, &newproc) != APR_SUCCESS) {
-        fprintf(stderr, "Could not create the new process\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK.\n");
-
-    fprintf(stdout, "Grabbing child's stdout.......");
-    if (ap_get_childout(newproc, &testfile) != APR_SUCCESS) {
-        fprintf(stderr, "Could not get child's stdout\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK.\n");
-
-    length = 256;
-    fprintf(stdout, "Checking the data read from pipe to child.......");
-    buf = ap_pcalloc(context, length);
-    if (ap_read(testfile, buf, &length) == APR_SUCCESS) {
-        if (!strcmp(buf, teststr))
-            fprintf(stdout,"OK\n");
-        else fprintf(stderr, "Uh-Oh\n");
-    }
-    else fprintf(stderr, "Read failed.\n");
-
-	return(1);
-}
-
diff --git a/test/testprocmutex.c b/test/testprocmutex.c
new file mode 100644
index 00000000000..24cc4418977
--- /dev/null
+++ b/test/testprocmutex.c
@@ -0,0 +1,287 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_shm.h"
+#include "apr_thread_proc.h"
+#include "apr_file_io.h"
+#include "apr_proc_mutex.h"
+#include "apr_errno.h"
+#include "apr_general.h"
+#include "apr_strings.h"
+#include "apr_getopt.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include "testutil.h"
+
+#if APR_HAS_FORK
+
+#define MAX_ITER 200
+#define CHILDREN 6
+#define MAX_COUNTER (MAX_ITER * CHILDREN)
+#define MAX_WAIT_USEC (1000*1000)
+
+static apr_proc_mutex_t *proc_lock;
+static volatile int *x;
+
+typedef struct lockmech {
+    apr_lockmech_e num;
+    const char *name;
+} lockmech_t;
+
+/* a slower more racy way to implement (*x)++ */
+static int increment(int n)
+{
+    apr_sleep(1);
+    return n+1;
+}
+
+static void make_child(abts_case *tc, int trylock, apr_proc_t **proc, apr_pool_t *p)
+{
+    apr_status_t rv;
+
+    *proc = apr_pcalloc(p, sizeof(**proc));
+
+    /* slight delay to allow things to settle */
+    apr_sleep (1);
+
+    rv = apr_proc_fork(*proc, p);
+    if (rv == APR_INCHILD) {
+        int i = 0;
+        /* The parent process has setup all processes to call apr_terminate
+         * at exit.  But, that means that all processes must also call
+         * apr_initialize at startup.  You cannot have an unequal number
+         * of apr_terminate and apr_initialize calls.  If you do, bad things
+         * will happen.  In this case, the bad thing is that if the mutex
+         * is a semaphore, it will be destroyed before all of the processes
+         * die.  That means that the test will most likely fail.
+         */
+        apr_initialize();
+
+        if (apr_proc_mutex_child_init(&proc_lock, NULL, p))
+            exit(1);
+
+        do {
+            if (trylock > 0) {
+                int wait_usec = 0;
+
+                while ((rv = apr_proc_mutex_trylock(proc_lock))) {
+                    if (!APR_STATUS_IS_EBUSY(rv))
+                        exit(1);
+                    if (++wait_usec >= MAX_WAIT_USEC)
+                        exit(1);
+                    apr_sleep(1);
+                }
+            }
+            else if (trylock < 0) {
+                int wait_usec = 0;
+
+                while ((rv = apr_proc_mutex_timedlock(proc_lock, 1))) {
+                    if (!APR_STATUS_IS_TIMEUP(rv))
+                        exit(1);
+                    if (++wait_usec >= MAX_WAIT_USEC)
+                        exit(1);
+                }
+            }
+            else {
+                if (apr_proc_mutex_lock(proc_lock))
+                    exit(1);
+            }
+
+            i++;
+            *x = increment(*x);
+            if (apr_proc_mutex_unlock(proc_lock))
+                exit(1);
+        } while (i < MAX_ITER);
+        exit(0);
+    } 
+
+    ABTS_ASSERT(tc, "fork failed", rv == APR_INPARENT);
+}
+
+/* Wait for a child process and check it terminated with success. */
+static void await_child(abts_case *tc, apr_proc_t *proc)
+{
+    int code;
+    apr_exit_why_e why;
+    apr_status_t rv;
+
+    rv = apr_proc_wait(proc, &code, &why, APR_WAIT);
+    ABTS_ASSERT(tc, "child did not terminate with success",
+             rv == APR_CHILD_DONE && why == APR_PROC_EXIT && code == 0);
+}
+
+static void test_exclusive(abts_case *tc, const char *lockname, 
+                           lockmech_t *mech)
+{
+    apr_proc_t *child[CHILDREN];
+    apr_status_t rv;
+    int n;
+ 
+    rv = apr_proc_mutex_create(&proc_lock, lockname, mech->num, p);
+    APR_ASSERT_SUCCESS(tc, "create the mutex", rv);
+ 
+    for (n = 0; n < CHILDREN; n++)
+        make_child(tc, 0, &child[n], p);
+
+    for (n = 0; n < CHILDREN; n++)
+        await_child(tc, child[n]);
+    
+    ABTS_ASSERT(tc, "Locks don't appear to work", *x == MAX_COUNTER);
+
+    rv = apr_proc_mutex_trylock(proc_lock);
+    if (rv == APR_ENOTIMPL) {
+        fprintf(stderr, "%s_trylock() not implemented, ", mech->name);
+        ABTS_ASSERT(tc, "Default timed trylock not implemented",
+                    mech->num != APR_LOCK_DEFAULT &&
+                    mech->num != APR_LOCK_DEFAULT_TIMED);
+    }
+    else {
+        APR_ASSERT_SUCCESS(tc, "check for trylock", rv);
+
+        for (n = 0; n < 2; n++) {
+            rv = apr_proc_mutex_trylock(proc_lock);
+            /* Some mech (eg. flock or fcntl) may succeed when the
+             * lock is re-acquired in the same process.
+             */
+            if (rv != APR_SUCCESS) {
+                ABTS_ASSERT(tc,
+                            apr_psprintf(p, "%s_trylock() should be busy => %pm",
+                                         mech->name, &rv),
+                            APR_STATUS_IS_EBUSY(rv));
+            }
+        }
+
+        rv = apr_proc_mutex_unlock(proc_lock);
+        APR_ASSERT_SUCCESS(tc, "unlock after trylock check", rv);
+
+        *x = 0;
+
+        for (n = 0; n < CHILDREN; n++)
+            make_child(tc, 1, &child[n], p);
+
+        for (n = 0; n < CHILDREN; n++)
+            await_child(tc, child[n]);
+        
+        ABTS_ASSERT(tc, "Locks don't appear to work with trylock",
+                    *x == MAX_COUNTER);
+    }
+
+    rv = apr_proc_mutex_timedlock(proc_lock, 1);
+    if (rv == APR_ENOTIMPL) {
+        fprintf(stderr, "%s_timedlock() not implemented, ", mech->name);
+        ABTS_ASSERT(tc, "Default timed timedlock not implemented",
+                    mech->num != APR_LOCK_DEFAULT_TIMED);
+    }
+    else {
+        APR_ASSERT_SUCCESS(tc, "check for timedlock", rv);
+
+        for (n = 0; n < 2; n++) {
+            rv = apr_proc_mutex_timedlock(proc_lock, 1);
+            /* Some mech (eg. flock or fcntl) may succeed when the
+             * lock is re-acquired in the same process.
+             */
+            if (rv != APR_SUCCESS) {
+                ABTS_ASSERT(tc,
+                            apr_psprintf(p, "%s_timedlock() should time out => %pm",
+                                         mech->name, &rv),
+                            APR_STATUS_IS_TIMEUP(rv));
+            }
+        }
+
+        rv = apr_proc_mutex_unlock(proc_lock);
+        APR_ASSERT_SUCCESS(tc, "unlock after timedlock check", rv);
+
+        *x = 0;
+
+        for (n = 0; n < CHILDREN; n++)
+            make_child(tc, -1, &child[n], p);
+
+        for (n = 0; n < CHILDREN; n++)
+            await_child(tc, child[n]);
+        
+        ABTS_ASSERT(tc, "Locks don't appear to work with timedlock",
+                    *x == MAX_COUNTER);
+    }
+}
+
+static void proc_mutex(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    const char *shmname = "tpm.shm";
+    apr_shm_t *shm;
+
+    /* Use anonymous shm if available. */
+    rv = apr_shm_create(&shm, sizeof(int), NULL, p);
+    if (rv == APR_ENOTIMPL) {
+        apr_file_remove(shmname, p);
+        rv = apr_shm_create(&shm, sizeof(int), shmname, p);
+    }
+
+    APR_ASSERT_SUCCESS(tc, "create shm segment", rv);
+    if (rv != APR_SUCCESS)
+        return;
+
+    x = apr_shm_baseaddr_get(shm);
+    test_exclusive(tc, NULL, data);
+    rv = apr_shm_destroy(shm);
+    APR_ASSERT_SUCCESS(tc, "Error destroying shared memory block", rv);
+}
+
+
+abts_suite *testprocmutex(abts_suite *suite)
+{
+    lockmech_t lockmechs[] = {
+        {APR_LOCK_DEFAULT, "default"}
+#if APR_HAS_FLOCK_SERIALIZE
+        ,{APR_LOCK_FLOCK, "flock"}
+#endif
+#if APR_HAS_SYSVSEM_SERIALIZE
+        ,{APR_LOCK_SYSVSEM, "sysvsem"}
+#endif
+#if APR_HAS_POSIXSEM_SERIALIZE
+        ,{APR_LOCK_POSIXSEM, "posix"}
+#endif
+#if APR_HAS_FCNTL_SERIALIZE
+        ,{APR_LOCK_FCNTL, "fcntl"}
+#endif
+#if APR_HAS_PROC_PTHREAD_SERIALIZE
+        ,{APR_LOCK_PROC_PTHREAD, "proc_pthread"}
+#endif
+        ,{APR_LOCK_DEFAULT_TIMED, "default_timed"}
+    };
+    int i;
+
+    suite = ADD_SUITE(suite)
+    for (i = 0; i < sizeof(lockmechs) / sizeof(lockmechs[0]); i++) {
+        abts_run_test(suite, proc_mutex, &lockmechs[i]);
+    }
+    return suite;
+}
+
+#else /* APR_HAS_FORK */
+
+static void proc_mutex(abts_case *tc, void *data)
+{
+    ABTS_NOT_IMPL(tc, "APR lacks fork() support");
+}
+
+abts_suite *testprocmutex(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite);
+    abts_run_test(suite, proc_mutex, NULL);
+    return suite;
+}
+#endif /* APR_HAS_FORK */
diff --git a/test/testqueue.c b/test/testqueue.c
new file mode 100644
index 00000000000..264e4d3a1cd
--- /dev/null
+++ b/test/testqueue.c
@@ -0,0 +1,185 @@
+/* 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 "apu.h"
+#include "apr_queue.h"
+#include "apr_thread_pool.h"
+#include "apr_time.h"
+#include "abts.h"
+#include "testutil.h"
+
+#if APR_HAS_THREADS
+
+#define NUMBER_CONSUMERS    3
+#define CONSUMER_ACTIVITY   4
+#define NUMBER_PRODUCERS    4
+#define PRODUCER_ACTIVITY   5
+#define QUEUE_SIZE          100
+
+static apr_queue_t *queue;
+
+static void * APR_THREAD_FUNC consumer(apr_thread_t *thd, void *data)
+{
+    long sleeprate;
+    abts_case *tc = data;
+    apr_status_t rv;
+    void *v;
+
+    sleeprate = 1000000/CONSUMER_ACTIVITY;
+    apr_sleep((rand() % 4) * 1000000); /* sleep random seconds */
+
+    while (1)
+    {
+        rv = apr_queue_pop(queue, &v);
+
+        if (rv == APR_EINTR)
+            continue;
+
+        if (rv == APR_EOF)
+            break;
+
+        ABTS_TRUE(tc, v == NULL);
+        ABTS_TRUE(tc, rv == APR_SUCCESS);
+
+        apr_sleep(sleeprate); /* sleep this long to acheive our rate */
+    }
+
+    return NULL;
+}
+
+static void * APR_THREAD_FUNC producer(apr_thread_t *thd, void *data)
+{
+    long sleeprate;
+    abts_case *tc = data;
+    apr_status_t rv;
+
+    sleeprate = 1000000/PRODUCER_ACTIVITY;
+    apr_sleep((rand() % 4) * 1000000); /* sleep random seconds */
+
+    while (1)
+    {
+        rv = apr_queue_push(queue, NULL);
+
+        if (rv == APR_EINTR)
+            continue;
+
+        if (rv == APR_EOF)
+            break;
+
+        ABTS_TRUE(tc, rv == APR_SUCCESS);
+
+        apr_sleep(sleeprate); /* sleep this long to acheive our rate */
+    }
+
+    return NULL;
+}
+
+static void test_queue_producer_consumer(abts_case *tc, void *data)
+{
+    unsigned int i;
+    apr_status_t rv;
+    apr_thread_pool_t *thrp;
+
+    /* XXX: non-portable */
+    srand((unsigned int)apr_time_now());
+
+    rv = apr_queue_create(&queue, QUEUE_SIZE, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_thread_pool_create(&thrp, 0, NUMBER_CONSUMERS + NUMBER_PRODUCERS, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    for (i = 0; i < NUMBER_CONSUMERS; i++) {
+        rv = apr_thread_pool_push(thrp, consumer, tc, 0, NULL);
+        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    }
+
+    for (i = 0; i < NUMBER_PRODUCERS; i++) {
+        rv = apr_thread_pool_push(thrp, producer, tc, 0, NULL);
+        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    }
+
+    apr_sleep(5000000); /* sleep 5 seconds */
+
+    rv = apr_queue_term(queue);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_thread_pool_destroy(thrp);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+}
+
+static void test_queue_timeout(abts_case *tc, void *data)
+{
+    apr_queue_t *q;
+    apr_status_t rv;
+    apr_time_t start;
+    unsigned int i;
+    void *value;
+
+    rv = apr_queue_create(&q, 5, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    for (i = 0; i < 2; ++i) {
+        rv = apr_queue_timedpush(q, NULL, apr_time_from_msec(1));
+        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    }
+    for (i = 0; i < 3; ++i) {
+        rv = apr_queue_trypush(q, NULL);
+        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    }
+
+    start = apr_time_now();
+    rv = apr_queue_timedpush(q, NULL, apr_time_from_msec(1));
+    ABTS_TRUE(tc, APR_STATUS_IS_TIMEUP(rv));
+    ABTS_TRUE(tc, apr_time_now() - start >= apr_time_from_msec(1));
+
+    rv = apr_queue_trypush(q, NULL);
+    ABTS_TRUE(tc, APR_STATUS_IS_EAGAIN(rv));
+
+    for (i = 0; i < 2; ++i) {
+        rv = apr_queue_timedpop(q, &value, apr_time_from_msec(1));
+        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    }
+    for (i = 0; i < 3; ++i) {
+        rv = apr_queue_trypop(q, &value);
+        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    }
+
+    start = apr_time_now();
+    rv = apr_queue_timedpop(q, &value, apr_time_from_sec(1));
+    ABTS_TRUE(tc, APR_STATUS_IS_TIMEUP(rv));
+    ABTS_TRUE(tc, apr_time_now() - start >= apr_time_from_msec(1));
+
+    rv = apr_queue_trypop(q, &value);
+    ABTS_TRUE(tc, APR_STATUS_IS_EAGAIN(rv));
+
+    rv = apr_queue_term(q);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+}
+
+#endif /* APR_HAS_THREADS */
+
+abts_suite *testqueue(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite);
+
+#if APR_HAS_THREADS
+    abts_run_test(suite, test_queue_producer_consumer, NULL);
+    abts_run_test(suite, test_queue_timeout, NULL);
+#endif /* APR_HAS_THREADS */
+
+    return suite;
+}
diff --git a/test/testrand.c b/test/testrand.c
new file mode 100644
index 00000000000..46c55d29f79
--- /dev/null
+++ b/test/testrand.c
@@ -0,0 +1,359 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_general.h"
+#include "apr_pools.h"
+#include "apr_random.h"
+#include "apr_thread_proc.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include "testutil.h"
+
+#define RANDOM_BUF_SZ 128
+
+static void hexdump(const char *msg, const unsigned char *b, int n)
+{
+    int i;
+
+    printf("\n%s", msg);
+    for (i = 0; i < n; ++i) {
+#if 0
+        if ((i & 0xf) == 0)
+            printf("%04x", i);
+        printf(" %02x", b[i]);
+        if ((i & 0xf) == 0xf)
+            printf("\n");
+#else
+        printf("0x%02x,", b[i]);
+        if ((i & 7) == 7)
+            printf("\n");
+#endif
+    }
+    printf("\n");
+}
+
+static apr_random_t *r;
+
+typedef apr_status_t APR_THREAD_FUNC rnd_fn(apr_random_t * r, void *b,
+                                            apr_size_t n);
+
+static void rand_run_kat(abts_case *tc, rnd_fn *f, apr_random_t *r,
+                         const unsigned char expected[RANDOM_BUF_SZ])
+{
+    unsigned char c[RANDOM_BUF_SZ];
+    apr_status_t rv;
+
+    rv = f(r, c, RANDOM_BUF_SZ);
+    ABTS_INT_EQUAL(tc, 0, rv);
+    if (rv)
+        return;
+    if (memcmp(c, expected, RANDOM_BUF_SZ)) {
+        hexdump("Generated: ", c, RANDOM_BUF_SZ);
+        hexdump("Expected:  ", expected, RANDOM_BUF_SZ);
+        ABTS_FAIL(tc, "Randomness mismatch");
+    }
+}
+
+#if APR_HAS_FORK
+static int rand_check_kat(rnd_fn *f, apr_random_t *r,
+                          const unsigned char expected[RANDOM_BUF_SZ],
+                          apr_file_t *readp, apr_file_t *writep)
+{
+    apr_size_t nbytes = RANDOM_BUF_SZ;
+    apr_size_t cmd_size = 1;
+    unsigned char c[RANDOM_BUF_SZ];
+    char ack;
+    apr_status_t rv;
+
+    rv = f(r, c, RANDOM_BUF_SZ);
+    if (rv)
+        return 2;
+    rv = 0;
+    if (memcmp(c, expected, RANDOM_BUF_SZ)) {
+        rv = 1;
+    } else {
+        hexdump("Generated: ", c, RANDOM_BUF_SZ);
+        hexdump("Previous:  ", expected, RANDOM_BUF_SZ);
+    }
+    /* Report back our random values for comparison in another child */
+    apr_file_write(writep, c, &nbytes);
+    /* Wait for our parent ack the data */
+    apr_file_read(readp, &ack, &cmd_size);
+    return rv;
+}
+#endif
+
+static void rand_add_zeroes(apr_random_t *r)
+{
+    static unsigned char c[2048];
+
+    apr_random_add_entropy(r, c, sizeof c);
+}
+
+static void rand_run_seed_short(abts_case *tc, rnd_fn *f, apr_random_t *r,
+                                int count)
+{
+    int i;
+    apr_status_t rv;
+    char c[1];
+
+    for (i = 0; i < count; ++i)
+        rand_add_zeroes(r);
+    rv = f(r, c, 1);
+    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOTENOUGHENTROPY(rv));
+}
+
+static void rand_seed_short(abts_case *tc, void *data)
+{
+    r = apr_random_standard_new(p);
+    rand_run_seed_short(tc, apr_random_insecure_bytes, r, 32);
+}
+
+static void rand_kat(abts_case *tc, void *data)
+{
+    unsigned char expected[RANDOM_BUF_SZ] = {
+        0x82, 0x04, 0xad, 0xd2, 0x0b, 0xd5, 0xac, 0xda,
+        0x3d, 0x85, 0x58, 0x38, 0x54, 0x6b, 0x69, 0x45,
+        0x37, 0x4c, 0xc7, 0xd7, 0x87, 0xeb, 0xbf, 0xd9,
+        0xb1, 0xb8, 0xb8, 0x2d, 0x9b, 0x33, 0x6e, 0x97,
+        0x04, 0x1d, 0x4c, 0xb0, 0xd1, 0xdf, 0x3d, 0xac,
+        0xd2, 0xaa, 0xfa, 0xcd, 0x96, 0xb7, 0xcf, 0xb1,
+        0x8e, 0x3d, 0xb3, 0xe5, 0x37, 0xa9, 0x95, 0xb4,
+        0xaa, 0x3d, 0x11, 0x1a, 0x08, 0x20, 0x21, 0x9f,
+        0xdb, 0x08, 0x3a, 0xb9, 0x57, 0x9f, 0xf2, 0x1f,
+        0x27, 0xdc, 0xb6, 0xc0, 0x85, 0x08, 0x05, 0xbb,
+        0x13, 0xbe, 0xb1, 0xe9, 0x63, 0x2a, 0xe2, 0xa4,
+        0x23, 0x15, 0x2a, 0x10, 0xbf, 0xdf, 0x09, 0xb3,
+        0xc7, 0xfb, 0x2d, 0x87, 0x48, 0x19, 0xfb, 0xc0,
+        0x15, 0x8c, 0xcb, 0xc6, 0xbd, 0x89, 0x38, 0x69,
+        0xa3, 0xae, 0xa3, 0x21, 0x58, 0x50, 0xe7, 0xc4,
+        0x87, 0xec, 0x2e, 0xb1, 0x2d, 0x6a, 0xbd, 0x46
+    };
+
+    rand_add_zeroes(r);
+    rand_run_kat(tc, apr_random_insecure_bytes, r, expected);
+}
+
+static void rand_seed_short2(abts_case *tc, void *data)
+{
+    rand_run_seed_short(tc, apr_random_secure_bytes, r, 320);
+}
+
+static void rand_kat2(abts_case *tc, void *data)
+{
+    unsigned char expected[RANDOM_BUF_SZ] = {
+        0x38, 0x8f, 0x01, 0x29, 0x5a, 0x5c, 0x1f, 0xa8,
+        0x00, 0xde, 0x16, 0x4c, 0xe5, 0xf7, 0x1f, 0x58,
+        0xc0, 0x67, 0xe2, 0x98, 0x3d, 0xde, 0x4a, 0x75,
+        0x61, 0x3f, 0x23, 0xd8, 0x45, 0x7a, 0x10, 0x60,
+        0x59, 0x9b, 0xd6, 0xaf, 0xcb, 0x0a, 0x2e, 0x34,
+        0x9c, 0x39, 0x5b, 0xd0, 0xbc, 0x9a, 0xf0, 0x7b,
+        0x7f, 0x40, 0x8b, 0x33, 0xc0, 0x0e, 0x2a, 0x56,
+        0xfc, 0xe5, 0xab, 0xde, 0x7b, 0x13, 0xf5, 0xec,
+        0x15, 0x68, 0xb8, 0x09, 0xbc, 0x2c, 0x15, 0xf0,
+        0x7b, 0xef, 0x2a, 0x97, 0x19, 0xa8, 0x69, 0x51,
+        0xdf, 0xb0, 0x5f, 0x1a, 0x4e, 0xdf, 0x42, 0x02,
+        0x71, 0x36, 0xa7, 0x25, 0x64, 0x85, 0xe2, 0x72,
+        0xc7, 0x87, 0x4d, 0x7d, 0x15, 0xbb, 0x15, 0xd1,
+        0xb1, 0x62, 0x0b, 0x25, 0xd9, 0xd3, 0xd9, 0x5a,
+        0xe3, 0x47, 0x1e, 0xae, 0x67, 0xb4, 0x19, 0x9e,
+        0xed, 0xd2, 0xde, 0xce, 0x18, 0x70, 0x57, 0x12
+    };
+
+    rand_add_zeroes(r);
+    rand_run_kat(tc, apr_random_secure_bytes, r, expected);
+}
+
+static void rand_barrier(abts_case *tc, void *data)
+{
+    apr_random_barrier(r);
+    rand_run_seed_short(tc, apr_random_secure_bytes, r, 320);
+}
+
+static void rand_kat3(abts_case *tc, void *data)
+{
+    unsigned char expected[RANDOM_BUF_SZ] = {
+        0xe8, 0xe7, 0xc9, 0x45, 0xe2, 0x2a, 0x54, 0xb2,
+        0xdd, 0xe0, 0xf9, 0xbc, 0x3d, 0xf9, 0xce, 0x3c,
+        0x4c, 0xbd, 0xc9, 0xe2, 0x20, 0x4a, 0x35, 0x1c,
+        0x04, 0x52, 0x7f, 0xb8, 0x0f, 0x60, 0x89, 0x63,
+        0x8a, 0xbe, 0x0a, 0x44, 0xac, 0x5d, 0xd8, 0xeb,
+        0x24, 0x7d, 0xd1, 0xda, 0x4d, 0x86, 0x9b, 0x94,
+        0x26, 0x56, 0x4a, 0x5e, 0x30, 0xea, 0xd4, 0xa9,
+        0x9a, 0xdf, 0xdd, 0xb6, 0xb1, 0x15, 0xe0, 0xfa,
+        0x28, 0xa4, 0xd6, 0x95, 0xa4, 0xf1, 0xd8, 0x6e,
+        0xeb, 0x8c, 0xa4, 0xac, 0x34, 0xfe, 0x06, 0x92,
+        0xc5, 0x09, 0x99, 0x86, 0xdc, 0x5a, 0x3c, 0x92,
+        0xc8, 0x3e, 0x52, 0x00, 0x4d, 0x01, 0x43, 0x6f,
+        0x69, 0xcf, 0xe2, 0x60, 0x9c, 0x23, 0xb3, 0xa5,
+        0x5f, 0x51, 0x47, 0x8c, 0x07, 0xde, 0x60, 0xc6,
+        0x04, 0xbf, 0x32, 0xd6, 0xdc, 0xb7, 0x31, 0x01,
+        0x29, 0x51, 0x51, 0xb3, 0x19, 0x6e, 0xe4, 0xf8
+    };
+
+    rand_run_kat(tc, apr_random_insecure_bytes, r, expected);
+}
+
+static void rand_kat4(abts_case *tc, void *data)
+{
+    unsigned char expected[RANDOM_BUF_SZ] = {
+        0x7d, 0x0e, 0xc4, 0x4e, 0x3e, 0xac, 0x86, 0x50,
+        0x37, 0x95, 0x7a, 0x98, 0x23, 0x26, 0xa7, 0xbf,
+        0x60, 0xfb, 0xa3, 0x70, 0x90, 0xc3, 0x58, 0xc6,
+        0xbd, 0xd9, 0x5e, 0xa6, 0x77, 0x62, 0x7a, 0x5c,
+        0x96, 0x83, 0x7f, 0x80, 0x3d, 0xf4, 0x9c, 0xcc,
+        0x9b, 0x0c, 0x8c, 0xe1, 0x72, 0xa8, 0xfb, 0xc9,
+        0xc5, 0x43, 0x91, 0xdc, 0x9d, 0x92, 0xc2, 0xce,
+        0x1c, 0x5e, 0x36, 0xc7, 0x87, 0xb1, 0xb4, 0xa3,
+        0xc8, 0x69, 0x76, 0xfc, 0x35, 0x75, 0xcb, 0x08,
+        0x2f, 0xe3, 0x98, 0x76, 0x37, 0x80, 0x04, 0x5c,
+        0xb8, 0xb0, 0x7f, 0xb2, 0xda, 0xe3, 0xa3, 0xba,
+        0xed, 0xff, 0xf5, 0x9d, 0x3b, 0x7b, 0xf3, 0x32,
+        0x6c, 0x50, 0xa5, 0x3e, 0xcc, 0xe1, 0x84, 0x9c,
+        0x17, 0x9e, 0x80, 0x64, 0x09, 0xbb, 0x62, 0xf1,
+        0x95, 0xf5, 0x2c, 0xc6, 0x9f, 0x6a, 0xee, 0x6d,
+        0x17, 0x35, 0x5f, 0x35, 0x8d, 0x55, 0x0c, 0x07
+    };
+
+    rand_add_zeroes(r);
+    rand_run_kat(tc, apr_random_secure_bytes, r, expected);
+}
+
+#if APR_HAS_FORK
+static void rand_fork(abts_case *tc, void *data)
+{
+    apr_proc_t proc;
+    apr_status_t rv;
+    apr_size_t nbytes = RANDOM_BUF_SZ;
+    apr_size_t cmd_size = 1;
+    char cmd = 'X';
+    unsigned char expected[RANDOM_BUF_SZ] = {
+        0xac, 0x93, 0xd2, 0x5c, 0xc7, 0xf5, 0x8d, 0xc2,
+        0xd8, 0x8d, 0xb6, 0x7a, 0x94, 0xe1, 0x83, 0x4c,
+        0x26, 0xe2, 0x38, 0x6d, 0xf5, 0xbd, 0x9d, 0x6e,
+        0x91, 0x77, 0x3a, 0x4b, 0x9b, 0xef, 0x9b, 0xa3,
+        0x9f, 0xf6, 0x6d, 0x0c, 0xdc, 0x4b, 0x02, 0xe9,
+        0x5d, 0x3d, 0xfc, 0x92, 0x6b, 0xdf, 0xc9, 0xef,
+        0xb9, 0xa8, 0x74, 0x09, 0xa3, 0xff, 0x64, 0x8d,
+        0x19, 0xc1, 0x31, 0x31, 0x17, 0xe1, 0xb7, 0x7a,
+        0xe7, 0x55, 0x14, 0x92, 0x05, 0xe3, 0x1e, 0xb8,
+        0x9b, 0x1b, 0xdc, 0xac, 0x0e, 0x15, 0x08, 0xa2,
+        0x93, 0x13, 0xf6, 0x04, 0xc6, 0x9d, 0xf8, 0x7f,
+        0x26, 0x32, 0x68, 0x43, 0x2e, 0x5a, 0x4f, 0x47,
+        0xe8, 0xf8, 0x59, 0xb7, 0xfb, 0xbe, 0x30, 0x04,
+        0xb6, 0x63, 0x6f, 0x19, 0xf3, 0x2c, 0xd4, 0xeb,
+        0x32, 0x8a, 0x54, 0x01, 0xd0, 0xaf, 0x3f, 0x13,
+        0xc1, 0x7f, 0x10, 0x2e, 0x08, 0x1c, 0x28, 0x4b,
+    };
+
+    apr_file_t *readdatap = NULL;
+    apr_file_t *writedatap = NULL;
+    apr_file_t *readcmdp = NULL;
+    apr_file_t *writecmdp = NULL;
+    apr_pool_t *p;
+    int i;
+
+    apr_pool_create(&p, NULL);
+    /* Set up data pipe for children */
+    rv = apr_file_pipe_create(&readdatap, &writedatap, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_PTR_NOTNULL(tc, readdatap);
+    ABTS_PTR_NOTNULL(tc, writedatap);
+    /* Set up cmd pipe for children */
+    rv = apr_file_pipe_create(&readcmdp, &writecmdp, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_PTR_NOTNULL(tc, readcmdp);
+    ABTS_PTR_NOTNULL(tc, writecmdp);
+
+    rand_run_kat(tc, apr_random_secure_bytes, r, expected);
+
+    for (i = 0; i< 10; i++)
+    {
+        rv = apr_proc_fork(&proc, p);
+        if (rv == APR_INCHILD) {
+            int n = rand_check_kat(apr_random_secure_bytes, r, expected, readcmdp, writedatap);
+            exit(n);
+        }
+        else if (rv == APR_INPARENT) {
+            int exitcode;
+            apr_exit_why_e why;
+
+            /* Read the random data generated by child */
+            rv = apr_file_read(readdatap, expected, &nbytes);
+            ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+            /* Tell child to finish */
+            rv = apr_file_write(writecmdp, &cmd, &cmd_size);
+            ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+            apr_proc_wait(&proc, &exitcode, &why, APR_WAIT);
+            if (why != APR_PROC_EXIT) {
+                ABTS_FAIL(tc, "Child terminated abnormally");
+            }
+            else if (exitcode == 0) {
+                if (i == 0)
+                {
+                    ABTS_FAIL(tc, "Child produced our randomness");
+                } else
+                {
+                    ABTS_FAIL(tc, "Child produced randomness of previous child");
+                }
+            }
+            else if (exitcode == 2) {
+                ABTS_FAIL(tc, "Child randomness failed");
+            }
+            else if (exitcode != 1) {
+                ABTS_FAIL(tc, "Unknown child error");
+            }
+        } else {
+            ABTS_FAIL(tc, "Fork failed");
+        }
+    }
+
+}
+#endif
+
+static void rand_exists(abts_case *tc, void *data)
+{
+#if !APR_HAS_RANDOM
+    ABTS_NOT_IMPL(tc, "apr_generate_random_bytes");
+#else
+    unsigned char c[42];
+
+    /* There must be a better way to test random-ness, but I don't know
+     * what it is right now.
+     */
+    APR_ASSERT_SUCCESS(tc, "apr_generate_random_bytes failed",
+                       apr_generate_random_bytes(c, sizeof c));
+#endif
+}
+
+abts_suite *testrand(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite)
+
+    abts_run_test(suite, rand_exists, NULL);
+    abts_run_test(suite, rand_seed_short, NULL);
+    abts_run_test(suite, rand_kat, NULL);
+    abts_run_test(suite, rand_seed_short2, NULL);
+    abts_run_test(suite, rand_kat2, NULL);
+    abts_run_test(suite, rand_barrier, NULL);
+    abts_run_test(suite, rand_kat3, NULL);
+    abts_run_test(suite, rand_kat4, NULL);
+#if APR_HAS_FORK
+    abts_run_test(suite, rand_fork, NULL);
+#endif
+
+    return suite;
+}
diff --git a/test/testredis.c b/test/testredis.c
new file mode 100644
index 00000000000..4b654322f54
--- /dev/null
+++ b/test/testredis.c
@@ -0,0 +1,552 @@
+/* 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 "testutil.h"
+#include "apr.h"
+#include "apu.h"
+#include "apr_general.h"
+#include "apr_strings.h"
+#include "apr_hash.h"
+#include "apr_redis.h"
+#include "apr_network_io.h"
+
+#include <stdio.h>
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h>		/* for exit() */
+#endif
+
+#define HOST "localhost"
+#define PORT 6379
+
+/* the total number of items to use for set/get testing */
+#define TDATA_SIZE 3000
+
+/* some smaller subset of TDATA_SIZE used for multiget testing */
+#define TDATA_SET 100
+
+/* our custom hash function just returns this all the time */
+#define HASH_FUNC_RESULT 510
+
+/* all keys will be prefixed with this */
+static const char prefix[] = "testredis";
+
+/* text for values we store */
+static const char txt[] =
+"Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Duis at"
+"lacus in ligula hendrerit consectetuer. Vestibulum tristique odio"
+"iaculis leo. In massa arcu, ultricies a, laoreet nec, hendrerit non,"
+"neque. Nulla sagittis sapien ac risus. Morbi ligula dolor, vestibulum"
+"nec, viverra id, placerat dapibus, arcu. Curabitur egestas feugiat"
+"tellus. Donec dignissim. Nunc ante. Curabitur id lorem. In mollis"
+"tortor sit amet eros auctor dapibus. Proin nulla sem, tristique in,"
+"convallis id, iaculis feugiat cras amet.";
+
+/*
+ * this datatype is for our custom server determination function. this might
+ * be useful if you don't want to rely on simply hashing keys to determine
+ * where a key belongs, but instead want to write something fancy, or use some
+ * other kind of configuration data, i.e. a hash plus some data about a 
+ * namespace, or whatever. see my_server_func, and test_redis_user_funcs
+ * for the examples.
+ */
+typedef struct {
+  const char *someval;
+  apr_uint32_t which_server;
+} my_hash_server_baton;
+
+
+/* this could do something fancy and return some hash result. 
+ * for simplicity, just return the same value, so we can test it later on.
+ * if you wanted to use some external hashing library or functions for
+ * consistent hashing, for example, this would be a good place to do it.
+ */
+static apr_uint32_t my_hash_func(void *baton, const char *data,
+                                 apr_size_t data_len)
+{
+
+  return HASH_FUNC_RESULT;
+}
+
+/*
+ * a fancy function to determine which server to use given some kind of data
+ * and a hash value. this example actually ignores the hash value itself
+ * and pulls some number from the *baton, which is a struct that has some 
+ * kind of meaningful stuff in it.
+ */
+static apr_redis_server_t *my_server_func(void *baton,
+                                             apr_redis_t *mc,
+                                             const apr_uint32_t hash)
+{
+  apr_redis_server_t *ms = NULL;
+  my_hash_server_baton *mhsb = (my_hash_server_baton *)baton;
+
+  if(mc->ntotal == 0) {
+    return NULL;
+  } 
+
+  if(mc->ntotal < mhsb->which_server) {
+    return NULL;
+  }
+
+  ms = mc->live_servers[mhsb->which_server - 1];
+
+  return ms;
+}
+
+static apr_uint16_t firsttime = 0;
+static int randval(apr_uint32_t high)
+{
+    apr_uint32_t i = 0;
+    double d = 0;
+
+    if (firsttime == 0) {
+	srand((unsigned) (getpid()));
+	firsttime = 1;
+    }
+
+    d = (double) rand() / ((double) RAND_MAX + 1);
+    i = (int) (d * (high - 0 + 1));
+
+    return i > 0 ? i : 1;
+}
+
+/*
+ * general test to make sure we can create the redis struct and add
+ * some servers, but not more than we tell it we can add
+ */
+
+static void test_redis_create(abts_case * tc, void *data)
+{
+  apr_pool_t *pool = p;
+  apr_status_t rv;
+  apr_redis_t *redis;
+  apr_redis_server_t *server, *s;
+  apr_uint32_t max_servers = 10;
+  apr_uint32_t i;
+  apr_uint32_t hash;
+
+  rv = apr_redis_create(pool, max_servers, 0, &redis);
+  ABTS_ASSERT(tc, "redis create failed", rv == APR_SUCCESS);
+  
+  for (i = 1; i <= max_servers; i++) {
+    apr_port_t port;
+    
+    port = PORT + i;
+    rv =
+      apr_redis_server_create(pool, HOST, PORT + i, 0, 1, 1, 60, 60, &server);
+    ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS);
+    
+    rv = apr_redis_add_server(redis, server);
+    ABTS_ASSERT(tc, "server add failed", rv == APR_SUCCESS);
+    
+    s = apr_redis_find_server(redis, HOST, port);
+    ABTS_PTR_EQUAL(tc, server, s);
+    
+    rv = apr_redis_disable_server(redis, s);
+    ABTS_ASSERT(tc, "server disable failed", rv == APR_SUCCESS);
+    
+    rv = apr_redis_enable_server(redis, s);
+    ABTS_ASSERT(tc, "server enable failed", rv == APR_SUCCESS);
+    
+    hash = apr_redis_hash(redis, prefix, strlen(prefix));
+    ABTS_ASSERT(tc, "hash failed", hash > 0);
+    
+    s = apr_redis_find_server_hash(redis, hash);
+    ABTS_PTR_NOTNULL(tc, s);
+  }
+
+  rv = apr_redis_server_create(pool, HOST, PORT, 0, 1, 1, 60, 60, &server);
+  ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS);
+  
+  rv = apr_redis_add_server(redis, server);
+  ABTS_ASSERT(tc, "server add should have failed", rv != APR_SUCCESS);
+  
+}
+
+/* install our own custom hashing and server selection routines. */
+
+static int create_test_hash(apr_pool_t *p, apr_hash_t *h)
+{
+  int i;
+  
+  for (i = 0; i < TDATA_SIZE; i++) {
+    char *k, *v;
+    
+    k = apr_pstrcat(p, prefix, apr_itoa(p, i), NULL);
+    v = apr_pstrndup(p, txt, randval((apr_uint32_t)strlen(txt)));
+    
+    apr_hash_set(h, k, APR_HASH_KEY_STRING, v);
+  }
+
+  return i;
+}
+
+static void test_redis_user_funcs(abts_case * tc, void *data)
+{
+  apr_pool_t *pool = p;
+  apr_status_t rv;
+  apr_redis_t *redis;
+  apr_redis_server_t *found;
+  apr_uint32_t max_servers = 10;
+  apr_uint32_t hres;
+  apr_uint32_t i;
+  my_hash_server_baton *baton = 
+    apr_pcalloc(pool, sizeof(my_hash_server_baton));
+
+  rv = apr_redis_create(pool, max_servers, 0, &redis);
+  ABTS_ASSERT(tc, "redis create failed", rv == APR_SUCCESS);
+
+  /* as noted above, install our custom hash function, and call 
+   * apr_redis_hash. the return value should be our predefined number,
+   * and our function just ignores the other args, for simplicity.
+   */
+  redis->hash_func = my_hash_func;
+
+  hres = apr_redis_hash(redis, "whatever", sizeof("whatever") - 1);
+  ABTS_INT_EQUAL(tc, HASH_FUNC_RESULT, hres);
+  
+  /* add some servers */
+  for(i = 1; i <= 10; i++) {
+    apr_redis_server_t *ms;
+
+    rv = apr_redis_server_create(pool, HOST, i, 0, 1, 1, 60, 60, &ms);
+    ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS);
+    
+    rv = apr_redis_add_server(redis, ms);
+    ABTS_ASSERT(tc, "server add failed", rv == APR_SUCCESS);
+  }
+
+  /* 
+   * set 'which_server' in our server_baton to find the third server 
+   * which should have the same port.
+   */
+  baton->which_server = 3;
+  redis->server_func = my_server_func;
+  redis->server_baton = baton;
+  found = apr_redis_find_server_hash(redis, 0);
+  ABTS_ASSERT(tc, "wrong server found", found->port == baton->which_server);
+}
+
+/* test non data related commands like stats and version */
+static void test_redis_meta(abts_case * tc, void *data)
+{
+    apr_pool_t *pool = p;
+    apr_redis_t *redis;
+    apr_redis_server_t *server;
+    apr_redis_stats_t *stats;
+    char *result;
+    apr_status_t rv;
+
+    rv = apr_redis_create(pool, 1, 0, &redis);
+    ABTS_ASSERT(tc, "redis create failed", rv == APR_SUCCESS);
+
+    rv = apr_redis_server_create(pool, HOST, PORT, 0, 1, 1, 60, 60, &server);
+    ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS);
+
+    rv = apr_redis_add_server(redis, server);
+    ABTS_ASSERT(tc, "server add failed", rv == APR_SUCCESS);
+
+    rv = apr_redis_version(server, pool, &result);
+    ABTS_PTR_NOTNULL(tc, result);
+
+    rv = apr_redis_stats(server, p, &stats);
+    ABTS_PTR_NOTNULL(tc, stats);
+
+    /* 
+     * no way to know exactly what will be in most of these, so
+     * just make sure there is something.
+     */
+    ABTS_ASSERT(tc, "major", stats->major >= 1);
+    ABTS_ASSERT(tc, "minor", stats->minor >= 0);
+    ABTS_ASSERT(tc, "patch", stats->patch >= 0);
+    ABTS_ASSERT(tc, "process_id", stats->process_id >= 0);
+    ABTS_ASSERT(tc, "uptime_in_seconds", stats->uptime_in_seconds >= 0);
+    ABTS_ASSERT(tc, "arch_bits", stats->arch_bits >= 0);
+    ABTS_ASSERT(tc, "connected_clients", stats->connected_clients >= 0);
+    ABTS_ASSERT(tc, "blocked_clients", stats->blocked_clients >= 0);
+    ABTS_ASSERT(tc, "maxmemory", stats->maxmemory >= 0);
+    ABTS_ASSERT(tc, "used_memory", stats->used_memory >= 0);
+    ABTS_ASSERT(tc, "total_system_memory", stats->total_system_memory >= 0);
+    ABTS_ASSERT(tc, "total_connections_received", stats->total_connections_received >= 0);
+    ABTS_ASSERT(tc, "total_commands_processed", stats->total_commands_processed >= 0);
+    ABTS_ASSERT(tc, "total_net_input_bytes", stats->total_net_input_bytes >= 0);
+    ABTS_ASSERT(tc, "total_net_output_bytes", stats->total_net_output_bytes >= 0);
+    ABTS_ASSERT(tc, "keyspace_hits", stats->keyspace_hits >= 0);
+    ABTS_ASSERT(tc, "keyspace_misses", stats->keyspace_misses >= 0);
+    ABTS_ASSERT(tc, "role", stats->role >= 0);
+    ABTS_ASSERT(tc, "connected_slaves", stats->connected_slaves >= 0);
+    ABTS_ASSERT(tc, "used_cpu_sys", stats->used_cpu_sys >= 0);
+    ABTS_ASSERT(tc, "used_cpu_user", stats->used_cpu_user >= 0);
+    ABTS_ASSERT(tc, "cluster_enabled", stats->cluster_enabled >= 0);
+}
+
+
+/* basic tests of the increment and decrement commands */
+static void test_redis_incrdecr(abts_case * tc, void *data)
+{
+ apr_pool_t *pool = p;
+ apr_status_t rv;
+ apr_redis_t *redis;
+ apr_redis_server_t *server;
+ apr_uint32_t new;
+ char *result;
+ apr_size_t len;
+ apr_uint32_t i;
+
+  rv = apr_redis_create(pool, 1, 0, &redis);
+  ABTS_ASSERT(tc, "redis create failed", rv == APR_SUCCESS);
+  
+  rv = apr_redis_server_create(pool, HOST, PORT, 0, 1, 1, 60, 60, &server);
+  ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS);
+  
+  rv = apr_redis_add_server(redis, server);
+  ABTS_ASSERT(tc, "server add failed", rv == APR_SUCCESS);
+
+  rv = apr_redis_set(redis, prefix, "271", sizeof("271") - 1, 27);
+  ABTS_ASSERT(tc, "set failed", rv == APR_SUCCESS);
+  
+  for( i = 1; i <= TDATA_SIZE; i++) {
+    apr_uint32_t expect;
+
+    rv = apr_redis_getp(redis, pool, prefix, &result, &len, NULL);
+    ABTS_ASSERT(tc, "get failed", rv == APR_SUCCESS);
+
+    expect = i + atoi(result);
+
+    rv = apr_redis_incr(redis, prefix, i, &new);
+    ABTS_ASSERT(tc, "incr failed", rv == APR_SUCCESS);
+
+    ABTS_INT_EQUAL(tc, expect, new);
+
+    rv = apr_redis_decr(redis, prefix, i, &new);
+    ABTS_ASSERT(tc, "decr failed", rv == APR_SUCCESS);
+
+    ABTS_INT_EQUAL(tc, atoi(result), new);
+
+  }
+
+  rv = apr_redis_getp(redis, pool, prefix, &result, &len, NULL);
+  ABTS_ASSERT(tc, "get failed", rv == APR_SUCCESS);
+
+  ABTS_INT_EQUAL(tc, 271, atoi(result));
+
+  rv = apr_redis_delete(redis, prefix, 0);
+  ABTS_ASSERT(tc, "delete failed", rv == APR_SUCCESS);
+}
+
+
+/* test setting and getting */
+
+static void test_redis_setget(abts_case * tc, void *data)
+{
+    apr_pool_t *pool = p;
+    apr_status_t rv;
+    apr_redis_t *redis;
+    apr_redis_server_t *server;
+    apr_hash_t *tdata;
+    apr_hash_index_t *hi;
+    char *result;
+    apr_size_t len;
+
+    rv = apr_redis_create(pool, 1, 0, &redis);
+    ABTS_ASSERT(tc, "redis create failed", rv == APR_SUCCESS);
+
+    rv = apr_redis_server_create(pool, HOST, PORT, 0, 1, 1, 60, 60, &server);
+    ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS);
+
+    rv = apr_redis_add_server(redis, server);
+    ABTS_ASSERT(tc, "server add failed", rv == APR_SUCCESS);
+
+    tdata = apr_hash_make(pool);
+
+    create_test_hash(pool, tdata);
+
+    for (hi = apr_hash_first(p, tdata); hi; hi = apr_hash_next(hi)) {
+	const void *k;
+	void *v;
+        const char *key;
+
+	apr_hash_this(hi, &k, NULL, &v);
+        key = k;
+
+	rv = apr_redis_set(redis, key, v, strlen(v), 27);
+	ABTS_ASSERT(tc, "set failed", rv == APR_SUCCESS);
+	rv = apr_redis_getp(redis, pool, key, &result, &len, NULL);
+	ABTS_ASSERT(tc, "get failed", rv == APR_SUCCESS);
+    }
+
+    rv = apr_redis_getp(redis, pool, "nothere3423", &result, &len, NULL);
+
+    ABTS_ASSERT(tc, "get should have failed", rv != APR_SUCCESS);
+
+    for (hi = apr_hash_first(p, tdata); hi; hi = apr_hash_next(hi)) {
+	const void *k;
+	const char *key;
+
+	apr_hash_this(hi, &k, NULL, NULL);
+	key = k;
+
+	rv = apr_redis_delete(redis, key, 0);
+	ABTS_ASSERT(tc, "delete failed", rv == APR_SUCCESS);
+    }
+}
+
+/* test setting and getting */
+
+static void test_redis_setexget(abts_case * tc, void *data)
+{
+    apr_pool_t *pool = p;
+    apr_status_t rv;
+    apr_redis_t *redis;
+    apr_redis_server_t *server;
+    apr_hash_t *tdata;
+    apr_hash_index_t *hi;
+    char *result;
+    apr_size_t len;
+
+    rv = apr_redis_create(pool, 1, 0, &redis);
+    ABTS_ASSERT(tc, "redis create failed", rv == APR_SUCCESS);
+
+    rv = apr_redis_server_create(pool, HOST, PORT, 0, 1, 1, 60, 60, &server);
+    ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS);
+
+    rv = apr_redis_add_server(redis, server);
+    ABTS_ASSERT(tc, "server add failed", rv == APR_SUCCESS);
+
+    tdata = apr_hash_make(pool);
+
+    create_test_hash(pool, tdata);
+
+    for (hi = apr_hash_first(p, tdata); hi; hi = apr_hash_next(hi)) {
+    const void *k;
+    void *v;
+        const char *key;
+
+    apr_hash_this(hi, &k, NULL, &v);
+        key = k;
+
+    rv = apr_redis_ping(server);
+    ABTS_ASSERT(tc, "ping failed", rv == APR_SUCCESS);
+    rv = apr_redis_setex(redis, key, v, strlen(v), 10, 27);
+    ABTS_ASSERT(tc, "set failed", rv == APR_SUCCESS);
+    rv = apr_redis_getp(redis, pool, key, &result, &len, NULL);
+    ABTS_ASSERT(tc, "get failed", rv == APR_SUCCESS);
+    }
+
+    rv = apr_redis_getp(redis, pool, "nothere3423", &result, &len, NULL);
+
+    ABTS_ASSERT(tc, "get should have failed", rv != APR_SUCCESS);
+
+    for (hi = apr_hash_first(p, tdata); hi; hi = apr_hash_next(hi)) {
+    const void *k;
+    const char *key;
+
+    apr_hash_this(hi, &k, NULL, NULL);
+    key = k;
+
+    rv = apr_redis_delete(redis, key, 0);
+    ABTS_ASSERT(tc, "delete failed", rv == APR_SUCCESS);
+    }
+}
+
+/* use apr_socket stuff to see if there is in fact a Redis server
+ * running on PORT.
+ */
+static apr_status_t check_redis(void)
+{
+  apr_pool_t *pool = p;
+  apr_status_t rv;
+  apr_socket_t *sock = NULL;
+  apr_sockaddr_t *sa;
+  struct iovec vec[2];
+  apr_size_t written;
+  char buf[128];
+  apr_size_t len;
+
+  rv = apr_socket_create(&sock, APR_INET, SOCK_STREAM, 0, pool);
+  if(rv != APR_SUCCESS) {
+    return rv;
+  }
+
+  rv = apr_sockaddr_info_get(&sa, HOST, APR_INET, PORT, 0, pool);
+  if(rv != APR_SUCCESS) {
+    return rv;
+  }
+
+  rv = apr_socket_timeout_set(sock, 1 * APR_USEC_PER_SEC);
+  if (rv != APR_SUCCESS) {
+    return rv;
+  }
+
+  rv = apr_socket_connect(sock, sa);
+  if (rv != APR_SUCCESS) {
+    return rv;
+  }
+
+  rv = apr_socket_timeout_set(sock, -1);
+  if (rv != APR_SUCCESS) {
+    return rv;
+  }
+
+  vec[0].iov_base = "PING";
+  vec[0].iov_len  = sizeof("PING") - 1;
+
+  vec[1].iov_base = "\r\n";
+  vec[1].iov_len  = sizeof("\r\n") -1;
+
+  rv = apr_socket_sendv(sock, vec, 2, &written);
+  if (rv != APR_SUCCESS) {
+    return rv;
+  }
+
+  len = sizeof(buf);
+  rv = apr_socket_recv(sock, buf, &len);
+  if(rv != APR_SUCCESS) {
+    return rv;
+  }
+  if(strncmp(buf, "+PONG", sizeof("+PONG")-1) != 0) {
+    rv = APR_EGENERAL;
+  }
+
+  apr_socket_close(sock);
+  return rv;
+}
+
+abts_suite *testredis(abts_suite * suite)
+{
+    apr_status_t rv;
+    suite = ADD_SUITE(suite);
+    /* check for a running redis on the typical port before
+     * trying to run the tests. succeed if we don't find one.
+     */
+    rv = check_redis();
+    if (rv == APR_SUCCESS) {
+        abts_run_test(suite, test_redis_create, NULL);
+        abts_run_test(suite, test_redis_user_funcs, NULL);
+        abts_run_test(suite, test_redis_meta, NULL);
+        abts_run_test(suite, test_redis_setget, NULL);
+        abts_run_test(suite, test_redis_setexget, NULL);
+        /* abts_run_test(suite, test_redis_multiget, NULL); */
+        abts_run_test(suite, test_redis_incrdecr, NULL);
+    }
+    else {
+        abts_log_message("Error %d occurred attempting to reach Redis "
+                         "on %s:%d.  Skipping apr_redis tests...",
+                         rv, HOST, PORT);
+    }
+
+    return suite;
+}
diff --git a/test/testreslist.c b/test/testreslist.c
new file mode 100644
index 00000000000..36333a1533e
--- /dev/null
+++ b/test/testreslist.c
@@ -0,0 +1,272 @@
+/* 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 <stdio.h>
+#include <stdlib.h>
+
+#include "apr_general.h"
+#include "apu.h"
+#include "apr_reslist.h"
+#include "apr_thread_pool.h"
+
+#if APR_HAVE_TIME_H
+#include <time.h>
+#endif /* APR_HAVE_TIME_H */
+
+#include "abts.h"
+#include "testutil.h"
+
+#if APR_HAS_THREADS
+
+#define RESLIST_MIN   3
+#define RESLIST_SMAX 10
+#define RESLIST_HMAX 20
+#define RESLIST_TTL  APR_TIME_C(35000) /* 35 ms */
+#define CONSUMER_THREADS 25
+#define CONSUMER_ITERATIONS 250
+#define CONSTRUCT_SLEEP_TIME  APR_TIME_C(25000) /* 25 ms */
+#define DESTRUCT_SLEEP_TIME   APR_TIME_C(10000) /* 10 ms */
+#define WORK_DELAY_SLEEP_TIME APR_TIME_C(15000) /* 15 ms */
+
+typedef struct {
+    apr_interval_time_t sleep_upon_construct;
+    apr_interval_time_t sleep_upon_destruct;
+    int c_count;
+    int d_count;
+} my_parameters_t;
+
+typedef struct {
+    int id;
+} my_resource_t;
+
+/* Linear congruential generator */
+static apr_uint32_t lgc(apr_uint32_t a)
+{
+    apr_uint64_t z = a;
+    z *= 279470273;
+    z %= APR_UINT64_C(4294967291);
+    return (apr_uint32_t)z;
+}
+
+static apr_status_t my_constructor(void **resource, void *params,
+                                   apr_pool_t *pool)
+{
+    my_resource_t *res;
+    my_parameters_t *my_params = params;
+
+    /* Create some resource */
+    res = apr_palloc(pool, sizeof(*res));
+    res->id = my_params->c_count++;
+
+    /* Sleep for awhile, to simulate construction overhead. */
+    apr_sleep(my_params->sleep_upon_construct);
+
+    /* Set the resource so it can be managed by the reslist */
+    *resource = res;
+    return APR_SUCCESS;
+}
+
+static apr_status_t my_destructor(void *resource, void *params,
+                                  apr_pool_t *pool)
+{
+    my_resource_t *res = resource;
+    my_parameters_t *my_params = params;
+    res->id = my_params->d_count++;
+
+    apr_sleep(my_params->sleep_upon_destruct);
+
+    return APR_SUCCESS;
+}
+
+typedef struct {
+    int tid;
+    abts_case *tc;
+    apr_reslist_t *reslist;
+    apr_interval_time_t work_delay_sleep;
+} my_thread_info_t;
+
+/* MAX_UINT * .95 = 2**32 * .95 = 4080218931u */
+#define PERCENT95th 4080218931u
+
+static void * APR_THREAD_FUNC resource_consuming_thread(apr_thread_t *thd,
+                                                        void *data)
+{
+    int i;
+    apr_uint32_t chance;
+    void *vp;
+    apr_status_t rv;
+    my_resource_t *res;
+    my_thread_info_t *thread_info = data;
+    apr_reslist_t *rl = thread_info->reslist;
+
+#if APR_HAS_RANDOM
+    apr_generate_random_bytes((void*)&chance, sizeof(chance));
+#else
+    chance = (apr_uint32_t)(apr_time_now() % APR_TIME_C(4294967291));
+#endif
+
+    for (i = 0; i < CONSUMER_ITERATIONS; i++) {
+        rv = apr_reslist_acquire(rl, &vp);
+        ABTS_INT_EQUAL(thread_info->tc, APR_SUCCESS, rv);
+        res = vp;
+        apr_sleep(thread_info->work_delay_sleep);
+
+        /* simulate a 5% chance of the resource being bad */
+        chance = lgc(chance);
+        if ( chance < PERCENT95th ) {
+            rv = apr_reslist_release(rl, res);
+            ABTS_INT_EQUAL(thread_info->tc, APR_SUCCESS, rv);
+        } else {
+            rv = apr_reslist_invalidate(rl, res);
+            ABTS_INT_EQUAL(thread_info->tc, APR_SUCCESS, rv);
+        }
+    }
+
+    return APR_SUCCESS;
+}
+
+static void test_timeout(abts_case *tc, apr_reslist_t *rl)
+{
+    apr_status_t rv;
+    my_resource_t *resources[RESLIST_HMAX];
+    void *vp;
+    int i;
+
+    apr_reslist_timeout_set(rl, 1000);
+
+    /* deplete all possible resources from the resource list
+     * so that the next call will block until timeout is reached
+     * (since there are no other threads to make a resource
+     * available)
+     */
+
+    for (i = 0; i < RESLIST_HMAX; i++) {
+        rv = apr_reslist_acquire(rl, (void**)&resources[i]);
+        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    }
+
+    /* next call will block until timeout is reached */
+    rv = apr_reslist_acquire(rl, &vp);
+    ABTS_TRUE(tc, APR_STATUS_IS_TIMEUP(rv));
+
+    /* release the resources; otherwise the destroy operation
+     * will blow
+     */
+    for (i = 0; i < RESLIST_HMAX; i++) {
+        rv = apr_reslist_release(rl, resources[i]);
+        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    }
+}
+
+static void test_shrinking(abts_case *tc, apr_reslist_t *rl)
+{
+    apr_status_t rv;
+    my_resource_t *resources[RESLIST_HMAX];
+    my_resource_t *res;
+    void *vp;
+    int i;
+    int sleep_time = RESLIST_TTL / RESLIST_HMAX;
+
+    /* deplete all possible resources from the resource list */
+    for (i = 0; i < RESLIST_HMAX; i++) {
+        rv = apr_reslist_acquire(rl, (void**)&resources[i]);
+        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    }
+
+    /* Free all resources above RESLIST_SMAX - 1 */
+    for (i = RESLIST_SMAX - 1; i < RESLIST_HMAX; i++) {
+        rv = apr_reslist_release(rl, resources[i]);
+        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    }
+
+    for (i = 0; i < RESLIST_HMAX; i++) {
+        rv = apr_reslist_acquire(rl, &vp);
+        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+        res = vp;
+        apr_sleep(sleep_time);
+        rv = apr_reslist_release(rl, res);
+        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    }
+    apr_sleep(sleep_time);
+
+    /*
+     * Now free the remaining elements. This should trigger the shrinking of
+     * the list
+     */
+    for (i = 0; i < RESLIST_SMAX - 1; i++) {
+        rv = apr_reslist_release(rl, resources[i]);
+        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    }
+}
+
+static void test_reslist(abts_case *tc, void *data)
+{
+    int i;
+    apr_status_t rv;
+    apr_reslist_t *rl;
+    my_parameters_t *params;
+    apr_thread_pool_t *thrp;
+    my_thread_info_t thread_info[CONSUMER_THREADS];
+
+    rv = apr_thread_pool_create(&thrp, CONSUMER_THREADS/2, CONSUMER_THREADS, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    /* Create some parameters that will be passed into each
+     * constructor and destructor call. */
+    params = apr_pcalloc(p, sizeof(*params));
+    params->sleep_upon_construct = CONSTRUCT_SLEEP_TIME;
+    params->sleep_upon_destruct = DESTRUCT_SLEEP_TIME;
+
+    /* We're going to want 10 blocks of data from our target rmm. */
+    rv = apr_reslist_create(&rl, RESLIST_MIN, RESLIST_SMAX, RESLIST_HMAX,
+                            RESLIST_TTL, my_constructor, my_destructor,
+                            params, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    for (i = 0; i < CONSUMER_THREADS; i++) {
+        thread_info[i].tid = i;
+        thread_info[i].tc = tc;
+        thread_info[i].reslist = rl;
+        thread_info[i].work_delay_sleep = WORK_DELAY_SLEEP_TIME;
+        rv = apr_thread_pool_push(thrp, resource_consuming_thread,
+                                  &thread_info[i], 0, NULL);
+        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    }
+
+    rv = apr_thread_pool_destroy(thrp);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    test_timeout(tc, rl);
+
+    test_shrinking(tc, rl);
+    ABTS_INT_EQUAL(tc, RESLIST_SMAX, params->c_count - params->d_count);
+
+    rv = apr_reslist_destroy(rl);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+}
+
+#endif /* APR_HAS_THREADS */
+
+abts_suite *testreslist(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite);
+
+#if APR_HAS_THREADS
+    abts_run_test(suite, test_reslist, NULL);
+#endif
+
+    return suite;
+}
diff --git a/test/testrmm.c b/test/testrmm.c
new file mode 100644
index 00000000000..4f8fb5ec2c3
--- /dev/null
+++ b/test/testrmm.c
@@ -0,0 +1,191 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_shm.h"
+#include "apr_rmm.h"
+#include "apr_errno.h"
+#include "apr_general.h"
+#include "apr_lib.h"
+#include "apr_strings.h"
+#include "apr_time.h"
+#include "abts.h"
+#include "testutil.h"
+
+#if APR_HAS_SHARED_MEMORY
+
+#define FRAG_SIZE 80
+#define FRAG_COUNT 10
+#define SHARED_SIZE (apr_size_t)(FRAG_SIZE * FRAG_COUNT * sizeof(char*))
+
+static void test_rmm(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_pool_t *pool;
+    apr_shm_t *shm;
+    apr_rmm_t *rmm;
+    apr_size_t size, fragsize;
+    apr_rmm_off_t *off, off2;
+    int i;
+    void *entity;
+
+    rv = apr_pool_create(&pool, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    /* We're going to want 10 blocks of data from our target rmm. */
+    size = SHARED_SIZE + apr_rmm_overhead_get(FRAG_COUNT + 1);
+    rv = apr_shm_create(&shm, size, NULL, pool);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    if (rv != APR_SUCCESS)
+        return;
+
+    rv = apr_rmm_init(&rmm, NULL, apr_shm_baseaddr_get(shm), size, pool);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    if (rv != APR_SUCCESS)
+        return;
+
+    /* Creating each fragment of size fragsize */
+    fragsize = SHARED_SIZE / FRAG_COUNT;
+    off = apr_palloc(pool, FRAG_COUNT * sizeof(apr_rmm_off_t));
+    for (i = 0; i < FRAG_COUNT; i++) {
+        off[i] = apr_rmm_malloc(rmm, fragsize);
+    }
+
+    /* Checking for out of memory allocation */
+    off2 = apr_rmm_malloc(rmm, FRAG_SIZE * FRAG_COUNT);
+    ABTS_TRUE(tc, !off2);
+
+    /* Checking each fragment for address alignment */
+    for (i = 0; i < FRAG_COUNT; i++) {
+        char *c = apr_rmm_addr_get(rmm, off[i]);
+        apr_size_t sc = (apr_size_t)c;
+
+        ABTS_TRUE(tc, !!off[i]);
+        ABTS_TRUE(tc, !(sc & 7));
+    }
+
+    /* Setting each fragment to a unique value */
+    for (i = 0; i < FRAG_COUNT; i++) {
+        int j;
+        char **c = apr_rmm_addr_get(rmm, off[i]);
+        for (j = 0; j < FRAG_SIZE; j++, c++) {
+            *c = apr_itoa(pool, i + j);
+        }
+    }
+
+    /* Checking each fragment for its unique value */
+    for (i = 0; i < FRAG_COUNT; i++) {
+        int j;
+        char **c = apr_rmm_addr_get(rmm, off[i]);
+        for (j = 0; j < FRAG_SIZE; j++, c++) {
+            char *d = apr_itoa(pool, i + j);
+            ABTS_STR_EQUAL(tc, d, *c);
+        }
+    }
+
+    /* Freeing each fragment */
+    for (i = 0; i < FRAG_COUNT; i++) {
+        rv = apr_rmm_free(rmm, off[i]);
+        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    }
+
+    /* Creating one large segment */
+    off[0] = apr_rmm_calloc(rmm, SHARED_SIZE);
+
+    /* Setting large segment */
+    for (i = 0; i < FRAG_COUNT * FRAG_SIZE; i++) {
+        char **c = apr_rmm_addr_get(rmm, off[0]);
+        c[i] = apr_itoa(pool, i);
+    }
+
+    /* Freeing large segment */
+    rv = apr_rmm_free(rmm, off[0]);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    /* Creating each fragment of size fragsize */
+    for (i = 0; i < FRAG_COUNT; i++) {
+        off[i] = apr_rmm_malloc(rmm, fragsize);
+    }
+
+    /* Freeing each fragment backwards */
+    for (i = FRAG_COUNT - 1; i >= 0; i--) {
+        rv = apr_rmm_free(rmm, off[i]);
+        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    }
+
+    /* Creating one large segment (again) */
+    off[0] = apr_rmm_calloc(rmm, SHARED_SIZE);
+
+    /* Freeing large segment */
+    rv = apr_rmm_free(rmm, off[0]);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    /* Checking realloc */
+    off[0] = apr_rmm_calloc(rmm, SHARED_SIZE - 100);
+    off[1] = apr_rmm_calloc(rmm, 100);
+    ABTS_TRUE(tc, !!off[0]);
+    ABTS_TRUE(tc, !!off[1]);
+
+    entity = apr_rmm_addr_get(rmm, off[1]);
+    rv = apr_rmm_free(rmm, off[0]);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    {
+        unsigned char *c = entity;
+
+        /* Fill in the region; the first half with zereos, which will
+         * likely catch the apr_rmm_realloc offset calculation bug by
+         * making it think the old region was zero length. */
+        for (i = 0; i < 100; i++) {
+            c[i] = (i < 50) ? 0 : i;
+        }
+    }
+
+    /* now we can realloc off[1] and get many more bytes */
+    off[0] = apr_rmm_realloc(rmm, entity, SHARED_SIZE - 100);
+    ABTS_TRUE(tc, !!off[0]);
+
+    {
+        unsigned char *c = apr_rmm_addr_get(rmm, off[0]);
+
+        /* fill in the region */
+        for (i = 0; i < 100; i++) {
+            ABTS_TRUE(tc, c[i] == (i < 50 ? 0 : i));
+        }
+    }
+
+    rv = apr_rmm_destroy(rmm);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_shm_destroy(shm);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    apr_pool_destroy(pool);
+}
+
+#endif /* APR_HAS_SHARED_MEMORY */
+
+abts_suite *testrmm(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite);
+
+#if APR_HAS_SHARED_MEMORY
+    abts_run_test(suite, test_rmm, NULL);
+#endif
+
+    return suite;
+}
diff --git a/test/testshm.c b/test/testshm.c
new file mode 100644
index 00000000000..73870690631
--- /dev/null
+++ b/test/testshm.c
@@ -0,0 +1,332 @@
+/* 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 "testutil.h"
+#include "apr_shm.h"
+#include "apr_errno.h"
+#include "apr_general.h"
+#include "apr_lib.h"
+#include "apr_strings.h"
+#include "apr_thread_proc.h"
+#include "apr_time.h"
+#include "testshm.h"
+#include "apr.h"
+
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#if APR_HAS_SHARED_MEMORY
+
+#if APR_HAS_FORK
+static int msgwait(int sleep_sec, int first_box, int last_box)
+{
+    int i;
+    int recvd = 0;
+    apr_time_t start = apr_time_now();
+    apr_interval_time_t sleep_duration = apr_time_from_sec(sleep_sec);
+    while (apr_time_now() - start < sleep_duration) {
+        for (i = first_box; i < last_box; i++) {
+            if (boxes[i].msgavail && !strcmp(boxes[i].msg, MSG)) {
+                recvd++;
+                boxes[i].msgavail = 0; /* reset back to 0 */
+                /* reset the msg field.  1024 is a magic number and it should
+                 * be a macro, but I am being lazy.
+                 */
+                memset(boxes[i].msg, 0, 1024);
+            }
+        }
+        apr_sleep(apr_time_make(0, 10000)); /* 10ms */
+    }
+    return recvd;
+}
+
+static void msgput(int boxnum, char *msg)
+{
+    apr_cpystrn(boxes[boxnum].msg, msg, strlen(msg) + 1);
+    boxes[boxnum].msgavail = 1;
+}
+#endif /* APR_HAS_FORK */
+
+static void test_anon_create(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_shm_t *shm = NULL;
+
+    rv = apr_shm_create(&shm, SHARED_SIZE, NULL, p);
+    APR_ASSERT_SUCCESS(tc, "Error allocating shared memory block", rv);
+    ABTS_PTR_NOTNULL(tc, shm);
+
+    rv = apr_shm_destroy(shm);
+    APR_ASSERT_SUCCESS(tc, "Error destroying shared memory block", rv);
+}
+
+static void test_check_size(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_shm_t *shm = NULL;
+    apr_size_t retsize;
+
+    rv = apr_shm_create(&shm, SHARED_SIZE, NULL, p);
+    APR_ASSERT_SUCCESS(tc, "Error allocating shared memory block", rv);
+    ABTS_PTR_NOTNULL(tc, shm);
+
+    retsize = apr_shm_size_get(shm);
+    ABTS_SIZE_EQUAL(tc, SHARED_SIZE, retsize);
+
+    rv = apr_shm_destroy(shm);
+    APR_ASSERT_SUCCESS(tc, "Error destroying shared memory block", rv);
+}
+
+static void test_shm_allocate(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_shm_t *shm = NULL;
+
+    rv = apr_shm_create(&shm, SHARED_SIZE, NULL, p);
+    APR_ASSERT_SUCCESS(tc, "Error allocating shared memory block", rv);
+    ABTS_PTR_NOTNULL(tc, shm);
+
+    boxes = apr_shm_baseaddr_get(shm);
+    ABTS_PTR_NOTNULL(tc, boxes);
+
+    rv = apr_shm_destroy(shm);
+    APR_ASSERT_SUCCESS(tc, "Error destroying shared memory block", rv);
+}
+
+#if APR_HAS_FORK
+static void test_anon(abts_case *tc, void *data)
+{
+    apr_proc_t proc;
+    apr_status_t rv;
+    apr_shm_t *shm;
+    apr_size_t retsize;
+    int cnt, i;
+    int recvd;
+
+    rv = apr_shm_create(&shm, SHARED_SIZE, NULL, p);
+    APR_ASSERT_SUCCESS(tc, "Error allocating shared memory block", rv);
+    ABTS_PTR_NOTNULL(tc, shm);
+
+    retsize = apr_shm_size_get(shm);
+    ABTS_INT_EQUAL(tc, SHARED_SIZE, retsize);
+
+    boxes = apr_shm_baseaddr_get(shm);
+    ABTS_PTR_NOTNULL(tc, boxes);
+
+    rv = apr_proc_fork(&proc, p);
+    if (rv == APR_INCHILD) { /* child */
+        int num = msgwait(5, 0, N_BOXES);
+        /* exit with the number of messages received so that the parent
+         * can check that all messages were received.
+         */
+        exit(num);
+    }
+    else if (rv == APR_INPARENT) { /* parent */
+        i = N_BOXES;
+        cnt = 0;
+        while (cnt++ < N_MESSAGES) {
+            if ((i-=3) < 0) {
+                i += N_BOXES; /* start over at the top */
+            }
+            msgput(i, MSG);
+            apr_sleep(apr_time_make(0, 10000));
+        }
+    }
+    else {
+        ABTS_FAIL(tc, "apr_proc_fork failed");
+    }
+    /* wait for the child */
+    rv = apr_proc_wait(&proc, &recvd, NULL, APR_WAIT);
+    ABTS_INT_EQUAL(tc, N_MESSAGES, recvd);
+
+    rv = apr_shm_destroy(shm);
+    APR_ASSERT_SUCCESS(tc, "Error destroying shared memory block", rv);
+}
+#endif
+
+static void test_named(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_shm_t *shm = NULL;
+    apr_size_t retsize;
+    apr_proc_t pidproducer, pidconsumer;
+    apr_procattr_t *attr1 = NULL, *attr2 = NULL;
+    int sent, received;
+    apr_exit_why_e why;
+    const char *args[4];
+
+    apr_shm_remove(SHARED_FILENAME, p);
+
+    rv = apr_shm_create(&shm, SHARED_SIZE, SHARED_FILENAME, p);
+    APR_ASSERT_SUCCESS(tc, "Error allocating shared memory block", rv);
+    if (rv != APR_SUCCESS) {
+        return;
+    }
+    ABTS_PTR_NOTNULL(tc, shm);
+
+    retsize = apr_shm_size_get(shm);
+    ABTS_SIZE_EQUAL(tc, SHARED_SIZE, retsize);
+
+    boxes = apr_shm_baseaddr_get(shm);
+    ABTS_PTR_NOTNULL(tc, boxes);
+
+    rv = apr_procattr_create(&attr1, p);
+    ABTS_PTR_NOTNULL(tc, attr1);
+    APR_ASSERT_SUCCESS(tc, "Couldn't create attr1", rv);
+
+    rv = apr_procattr_cmdtype_set(attr1, APR_PROGRAM_ENV);
+    APR_ASSERT_SUCCESS(tc, "Couldn't set copy environment", rv);
+
+    args[0] = apr_pstrdup(p, "testshmproducer" EXTENSION);
+    args[1] = NULL;
+    rv = apr_proc_create(&pidproducer, TESTBINPATH "testshmproducer" EXTENSION, args,
+                         NULL, attr1, p);
+    APR_ASSERT_SUCCESS(tc, "Couldn't launch producer", rv);
+
+    rv = apr_procattr_create(&attr2, p);
+    ABTS_PTR_NOTNULL(tc, attr2);
+    APR_ASSERT_SUCCESS(tc, "Couldn't create attr2", rv);
+
+    rv = apr_procattr_cmdtype_set(attr2, APR_PROGRAM_ENV);
+    APR_ASSERT_SUCCESS(tc, "Couldn't set copy environment", rv);
+
+    args[0] = apr_pstrdup(p, "testshmconsumer" EXTENSION);
+    rv = apr_proc_create(&pidconsumer, TESTBINPATH "testshmconsumer" EXTENSION, args, 
+                         NULL, attr2, p);
+    APR_ASSERT_SUCCESS(tc, "Couldn't launch consumer", rv);
+
+    rv = apr_proc_wait(&pidconsumer, &received, &why, APR_WAIT);
+    ABTS_INT_EQUAL(tc, APR_CHILD_DONE, rv);
+    ABTS_INT_EQUAL(tc, APR_PROC_EXIT, why);
+
+    rv = apr_proc_wait(&pidproducer, &sent, &why, APR_WAIT);
+    ABTS_INT_EQUAL(tc, APR_CHILD_DONE, rv);
+    ABTS_INT_EQUAL(tc, APR_PROC_EXIT, why);
+
+    /* Cleanup before testing that producer and consumer worked correctly.
+     * This way, if they didn't succeed, we can just run this test again
+     * without having to cleanup manually.
+     */
+    APR_ASSERT_SUCCESS(tc, "Error destroying shared memory", 
+                       apr_shm_destroy(shm));
+    
+    ABTS_INT_EQUAL(tc, sent, received);
+
+}
+
+static void test_named_remove(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_shm_t *shm, *shm2;
+
+    apr_shm_remove(SHARED_FILENAME, p);
+
+    rv = apr_shm_create(&shm, SHARED_SIZE, SHARED_FILENAME, p);
+    APR_ASSERT_SUCCESS(tc, "Error allocating shared memory block", rv);
+    if (rv != APR_SUCCESS) {
+        return;
+    }
+    ABTS_PTR_NOTNULL(tc, shm);
+
+    rv = apr_shm_remove(SHARED_FILENAME, p);
+
+    /* On platforms which acknowledge the removal of the shared resource,
+     * ensure another of the same name may be created after removal;
+     */
+    if (rv == APR_SUCCESS)
+    {
+      rv = apr_shm_create(&shm2, SHARED_SIZE, SHARED_FILENAME, p);
+      APR_ASSERT_SUCCESS(tc, "Error allocating shared memory block", rv);
+      if (rv != APR_SUCCESS) {
+          return;
+      }
+      ABTS_PTR_NOTNULL(tc, shm2);
+
+      rv = apr_shm_destroy(shm2);
+      APR_ASSERT_SUCCESS(tc, "Error destroying shared memory block", rv);
+    }
+
+    rv = apr_shm_destroy(shm);
+    APR_ASSERT_SUCCESS(tc, "Error destroying shared memory block", rv);
+
+    /* Now ensure no named resource remains which we may attach to */
+    rv = apr_shm_attach(&shm, SHARED_FILENAME, p);
+    ABTS_TRUE(tc, rv != 0);
+}
+
+static void test_named_delete(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_shm_t *shm, *shm2;
+
+    apr_shm_remove(SHARED_FILENAME, p);
+
+    rv = apr_shm_create(&shm, SHARED_SIZE, SHARED_FILENAME, p);
+    APR_ASSERT_SUCCESS(tc, "Error allocating shared memory block", rv);
+    if (rv != APR_SUCCESS) {
+        return;
+    }
+    ABTS_PTR_NOTNULL(tc, shm);
+
+    rv = apr_shm_delete(shm);
+
+    /* On platforms which acknowledge the removal of the shared resource,
+     * ensure another of the same name may be created after removal;
+     */
+    if (rv == APR_SUCCESS)
+    {
+      rv = apr_shm_create(&shm2, SHARED_SIZE, SHARED_FILENAME, p);
+      APR_ASSERT_SUCCESS(tc, "Error allocating shared memory block", rv);
+      if (rv != APR_SUCCESS) {
+          return;
+      }
+      ABTS_PTR_NOTNULL(tc, shm2);
+
+      rv = apr_shm_destroy(shm2);
+      APR_ASSERT_SUCCESS(tc, "Error destroying shared memory block", rv);
+    }
+
+    rv = apr_shm_destroy(shm);
+    APR_ASSERT_SUCCESS(tc, "Error destroying shared memory block", rv);
+
+    /* Now ensure no named resource remains which we may attach to */
+    rv = apr_shm_attach(&shm, SHARED_FILENAME, p);
+    ABTS_TRUE(tc, rv != 0);
+}
+
+#endif
+
+abts_suite *testshm(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite)
+
+#if APR_HAS_SHARED_MEMORY
+    abts_run_test(suite, test_anon_create, NULL);
+    abts_run_test(suite, test_check_size, NULL);
+    abts_run_test(suite, test_shm_allocate, NULL);
+#if APR_HAS_FORK
+    abts_run_test(suite, test_anon, NULL);
+#endif
+    abts_run_test(suite, test_named, NULL); 
+    abts_run_test(suite, test_named_remove, NULL); 
+    abts_run_test(suite, test_named_delete, NULL); 
+#endif
+
+    return suite;
+}
+
+
diff --git a/test/testshm.h b/test/testshm.h
new file mode 100644
index 00000000000..5b24a9d4271
--- /dev/null
+++ b/test/testshm.h
@@ -0,0 +1,33 @@
+/* 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 TESTSHM_H
+#define TESTSHM_H
+
+typedef struct mbox {
+    char msg[1024]; 
+    int msgavail; 
+} mbox;
+mbox *boxes;
+
+#define N_BOXES 10
+#define SHARED_SIZE (apr_size_t)(N_BOXES * sizeof(mbox))
+#define SHARED_FILENAME "data/apr.testshm.shm"
+#define N_MESSAGES 100
+#define MSG "Sending a message"
+
+#endif
+
diff --git a/test/testshmconsumer.c b/test/testshmconsumer.c
new file mode 100644
index 00000000000..6a2a3c30d3e
--- /dev/null
+++ b/test/testshmconsumer.c
@@ -0,0 +1,94 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_shm.h"
+#include "apr_errno.h"
+#include "apr_general.h"
+#include "apr_lib.h"
+#include "apr_strings.h"
+#include "apr_time.h"
+#include "testshm.h"
+#include "apr.h"
+
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+
+#if APR_HAS_SHARED_MEMORY
+
+static int msgwait(int sleep_sec, int first_box, int last_box)
+{
+    int i;
+    int recvd = 0;
+    apr_time_t start = apr_time_now();
+    apr_interval_time_t sleep_duration = apr_time_from_sec(sleep_sec);
+    while (apr_time_now() - start < sleep_duration) {
+        for (i = first_box; i < last_box; i++) {
+            if (boxes[i].msgavail && !strcmp(boxes[i].msg, MSG)) {
+                recvd++;
+                boxes[i].msgavail = 0; /* reset back to 0 */
+                memset(boxes[i].msg, 0, 1024);
+            }
+        }
+        apr_sleep(apr_time_from_sec(1));
+    }
+    return recvd;
+}
+
+int main(void)
+{
+    apr_status_t rv;
+    apr_pool_t *pool;
+    apr_shm_t *shm;
+    int recvd;
+
+    apr_initialize();
+    
+    if (apr_pool_create(&pool, NULL) != APR_SUCCESS) {
+        exit(-1);
+    }
+
+    rv = apr_shm_attach(&shm, SHARED_FILENAME, pool);
+    if (rv != APR_SUCCESS) {
+        exit(-2);
+    }
+
+    boxes = apr_shm_baseaddr_get(shm);
+
+    /* consume messages on all of the boxes */
+    recvd = msgwait(30, 0, N_BOXES); /* wait for 30 seconds for messages */
+
+    rv = apr_shm_detach(shm);
+    if (rv != APR_SUCCESS) {
+        exit(-3);
+    }
+
+    return recvd;
+}
+
+#else /* APR_HAS_SHARED_MEMORY */
+
+int main(void)
+{
+    /* Just return, this program will never be called, so we don't need
+     * to print a message 
+     */
+    return 0;
+}
+
+#endif /* APR_HAS_SHARED_MEMORY */
+
diff --git a/test/testshmem.c b/test/testshmem.c
deleted file mode 100644
index 1da1e28f8a7..00000000000
--- a/test/testshmem.c
+++ /dev/null
@@ -1,146 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "apr_shmem.h"
-#include "apr_lock.h"
-#include "apr_errno.h"
-#include "apr_general.h"
-#include "apr_lib.h"
-#include "errno.h"
-#include <stdio.h>
-#include <stdlib.h>
-/*#include <process.h>*/
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-typedef struct mbox {
-    char msg[1024]; 
-    int msgavail; 
-} mbox;
-ap_pool_t *context;
-mbox *boxes;
-
-void msgwait(int boxnum)
-{
-    volatile int test = 0;
-    while (test == 0) {
-        sleep(0);
-        test = boxes[boxnum].msgavail;
-    }    
-    fprintf(stdout, "\nreceived a message in box %d, message was: %s\n", 
-            boxnum, boxes[boxnum].msg); 
-}
-
-void msgput(int boxnum, char *msg)
-{
-    fprintf(stdout, "Sending message to box %d\n", boxnum);
-    ap_cpystrn(boxes[boxnum].msg, msg, strlen(msg));
-    boxes[boxnum].msgavail = 1;
-}
-
-int main()
-{
-    ap_shmem_t *shm;
-    pid_t pid;
-    int size;
-
-    ap_initialize();
-
-    fprintf(stdout, "Initializing the context......."); 
-    if (ap_create_pool(&context, NULL) != APR_SUCCESS) {
-        fprintf(stderr, "could not initialize\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK\n");
-
-    fprintf(stdout, "Creating shared memory block......."); 
-    if (ap_shm_init(&shm, 1048576, NULL, context) != APR_SUCCESS) { 
-        fprintf(stderr, "Error allocating shared memory block\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK\n");
-
-    fprintf(stdout, "Allocating shared memory......."); 
-    size = sizeof(mbox) * 2;
-    boxes = ap_shm_calloc(shm, size);
-    if (boxes == NULL) { 
-        fprintf(stderr, "Error creating message boxes.\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK\n");
-
-    fprintf(stdout, "Creating a child process\n");
-    pid = fork();
-    if (pid == 0) {
-sleep(1);
-        if (ap_open_shmem(shm) == APR_SUCCESS) {
-            msgwait(1);
-            msgput(0, "Msg received\n");
-        } else {
-            puts( "Child: unable to get access to shared memory" );
-        }
-        exit(1);
-    }
-    else if (pid > 0) {
-        msgput(1, "Sending a message\n");
-sleep(1);
-        msgwait(0);
-        exit(1);
-    }
-    else {
-        fprintf(stderr, "Error creating a child process\n");
-        exit(1);
-    }
-}
diff --git a/test/testshmproducer.c b/test/testshmproducer.c
new file mode 100644
index 00000000000..58eb94fcd3f
--- /dev/null
+++ b/test/testshmproducer.c
@@ -0,0 +1,89 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_shm.h"
+#include "apr_errno.h"
+#include "apr_general.h"
+#include "apr_lib.h"
+#include "apr_strings.h"
+#include "apr_time.h"
+#include "testshm.h"
+#include "apr.h"
+
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+
+#if APR_HAS_SHARED_MEMORY
+static void msgput(int boxnum, char *msg)
+{
+    apr_cpystrn(boxes[boxnum].msg, msg, strlen(msg) + 1);
+    boxes[boxnum].msgavail = 1;
+}
+
+int main(void)
+{
+    apr_status_t rv;
+    apr_pool_t *pool;
+    apr_shm_t *shm;
+    int i;
+    int sent = 0;
+
+    apr_initialize();
+    
+    if (apr_pool_create(&pool, NULL) != APR_SUCCESS) {
+        exit(-1);
+    }
+
+    rv = apr_shm_attach(&shm, SHARED_FILENAME, pool);
+    if (rv != APR_SUCCESS) {
+        exit(-2);
+    }
+
+    boxes = apr_shm_baseaddr_get(shm);
+
+    /* produce messages on all of the boxes, in descending order,
+     * Yes, we could just return N_BOXES, but I want to have a double-check
+     * in this code.  The original code actually sent N_BOXES - 1 messages,
+     * so rather than rely on possibly buggy code, this way we know that we
+     * are returning the right number.
+     */
+    for (i = N_BOXES - 1, sent = 0; i >= 0; i--, sent++) {
+        msgput(i, MSG);
+        apr_sleep(apr_time_from_sec(1));
+    }
+
+    rv = apr_shm_detach(shm);
+    if (rv != APR_SUCCESS) {
+        exit(-3);
+    }
+
+    return sent;
+}
+
+#else /* APR_HAS_SHARED_MEMORY */
+
+int main(void)
+{
+    /* Just return, this program will never be launched, so there is no
+     * reason to print a message.
+     */
+    return 0;
+}
+
+#endif /* APR_HAS_SHARED_MEMORY */
+
diff --git a/test/testsig.dsp b/test/testsig.dsp
deleted file mode 100644
index c88c6be9669..00000000000
--- a/test/testsig.dsp
+++ /dev/null
@@ -1,90 +0,0 @@
-# Microsoft Developer Studio Project File - Name="testsig" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 5.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=testsig - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "testsig.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 "testsig.mak" CFG="testsig - Win32 Debug"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "testsig - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "testsig - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE 
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF  "$(CFG)" == "testsig - 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 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /W3 /GX /O2 /I "..\include" /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ..\lib\Debug\lib.lib ..\misc\win32\Debug\misc.lib ..\threadproc\win32\Debug\threadproc.lib ..\file_io\win32\Debug\file_io.lib ..\time\win32\Debug\time.lib ..\locks\win32\Debug\locks.lib ..\network_io\win32\Debug\network_io.lib ..\signal\win32\Debug\signal.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-
-!ELSEIF  "$(CFG)" == "testsig - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "testsig_"
-# PROP BASE Intermediate_Dir "testsig_"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "testsig"
-# PROP Intermediate_Dir "testsig"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\include" /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
-# SUBTRACT CPP /YX /Yc /Yu
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 ..\lib\Debug\lib.lib ..\misc\win32\Debug\misc.lib ..\threadproc\win32\Debug\threadproc.lib ..\file_io\win32\Debug\file_io.lib ..\time\win32\Debug\time.lib ..\locks\win32\Debug\locks.lib ..\network_io\win32\Debug\network_io.lib ..\signal\win32\Debug\signal.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"ab.exe" /pdbtype:sept
-
-!ENDIF 
-
-# Begin Target
-
-# Name "testsig - Win32 Release"
-# Name "testsig - Win32 Debug"
-# Begin Source File
-
-SOURCE=.\testsig.c
-# End Source File
-# End Target
-# End Project
diff --git a/test/testsiphash.c b/test/testsiphash.c
new file mode 100644
index 00000000000..58321adebd8
--- /dev/null
+++ b/test/testsiphash.c
@@ -0,0 +1,148 @@
+/* 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 <stdio.h>
+#include <stdlib.h>
+
+#include "apr_siphash.h"
+
+#include "abts.h"
+#include "testutil.h"
+
+/*
+ * Wrapped test vectors from the authors, see
+ *  https://131002.net/siphash/siphash24.c
+ */
+typedef unsigned char u8;
+#define crypto_auth apr_siphash24_auth
+
+#define MAXLEN 64
+
+/*
+   SipHash-2-4 output with
+   k = 00 01 02 ...
+   and
+   in = (empty string)
+   in = 00 (1 byte)
+   in = 00 01 (2 bytes)
+   in = 00 01 02 (3 bytes)
+   ...
+   in = 00 01 02 ... 3e (63 bytes)
+*/
+static const u8 vectors[MAXLEN][8] =
+{
+  { 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72, },
+  { 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74, },
+  { 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d, },
+  { 0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85, },
+  { 0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf, },
+  { 0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18, },
+  { 0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb, },
+  { 0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab, },
+  { 0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93, },
+  { 0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e, },
+  { 0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a, },
+  { 0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4, },
+  { 0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75, },
+  { 0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14, },
+  { 0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7, },
+  { 0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1, },
+  { 0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f, },
+  { 0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69, },
+  { 0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b, },
+  { 0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb, },
+  { 0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe, },
+  { 0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0, },
+  { 0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93, },
+  { 0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8, },
+  { 0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8, },
+  { 0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc, },
+  { 0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17, },
+  { 0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f, },
+  { 0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde, },
+  { 0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6, },
+  { 0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad, },
+  { 0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32, },
+  { 0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71, },
+  { 0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7, },
+  { 0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12, },
+  { 0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15, },
+  { 0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31, },
+  { 0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02, },
+  { 0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca, },
+  { 0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a, },
+  { 0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e, },
+  { 0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad, },
+  { 0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18, },
+  { 0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4, },
+  { 0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9, },
+  { 0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9, },
+  { 0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb, },
+  { 0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0, },
+  { 0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6, },
+  { 0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7, },
+  { 0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee, },
+  { 0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1, },
+  { 0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a, },
+  { 0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81, },
+  { 0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f, },
+  { 0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24, },
+  { 0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7, },
+  { 0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea, },
+  { 0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60, },
+  { 0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66, },
+  { 0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c, },
+  { 0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f, },
+  { 0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5, },
+  { 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95, }
+};
+
+static int test_vectors(void)
+{
+  u8 in[MAXLEN], out[8], k[16];
+  int i;
+  int ok = 1;
+
+  for( i = 0; i < 16; ++i ) k[i] = i;
+
+  for( i = 0; i < MAXLEN; ++i )
+  {
+    in[i] = i;
+    crypto_auth( out, in, i, k );
+
+    if ( memcmp( out, vectors[i], 8 ) )
+    {
+      printf( "test vector failed for %d bytes\n", i );
+      ok = 0;
+    }
+  }
+
+  return ok;
+}
+
+static void test_siphash_vectors(abts_case *tc, void *data)
+{
+    ABTS_ASSERT(tc, "SipHash-2-4 test vectors", test_vectors());
+}
+
+abts_suite *testsiphash(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite);
+
+    abts_run_test(suite, test_siphash_vectors, NULL);
+
+    return suite;
+}
diff --git a/test/testskiplist.c b/test/testskiplist.c
new file mode 100644
index 00000000000..e1f64bad658
--- /dev/null
+++ b/test/testskiplist.c
@@ -0,0 +1,546 @@
+/* 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 "testutil.h"
+#include "apr.h"
+#include "apr_strings.h"
+#include "apr_general.h"
+#include "apr_pools.h"
+#include "apr_skiplist.h"
+#if APR_HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if APR_HAVE_STRING_H
+#include <string.h>
+#endif
+
+static apr_pool_t *ptmp = NULL;
+static apr_skiplist *skiplist = NULL;
+
+static int skiplist_get_size(abts_case *tc, apr_skiplist *sl)
+{
+    size_t size = 0;
+    apr_skiplistnode *n;
+    for (n = apr_skiplist_getlist(sl); n; apr_skiplist_next(sl, &n)) {
+        ++size;
+    }
+    ABTS_TRUE(tc, size == apr_skiplist_size(sl));
+    return size;
+}
+
+static void skiplist_init(abts_case *tc, void *data)
+{
+    apr_time_t now = apr_time_now();
+    srand((unsigned int)(((now >> 32) ^ now) & 0xffffffff));
+
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, apr_skiplist_init(&skiplist, p));
+    ABTS_PTR_NOTNULL(tc, skiplist);
+    apr_skiplist_set_compare(skiplist, (apr_skiplist_compare)strcmp,
+                                       (apr_skiplist_compare)strcmp);
+}
+
+static void skiplist_find(abts_case *tc, void *data)
+{
+    const char *val;
+
+    ABTS_PTR_NOTNULL(tc, apr_skiplist_insert(skiplist, "baton"));
+    val = apr_skiplist_find(skiplist, "baton", NULL);
+    ABTS_PTR_NOTNULL(tc, val);
+    ABTS_STR_EQUAL(tc, "baton", val);
+}
+
+static void skiplist_dontfind(abts_case *tc, void *data)
+{
+    const char *val;
+
+    val = apr_skiplist_find(skiplist, "keynotthere", NULL);
+    ABTS_PTR_EQUAL(tc, NULL, (void *)val);
+}
+
+static void skiplist_insert(abts_case *tc, void *data)
+{
+    const char *val;
+    int i, height = 0;
+
+    for (i = 0; i < 10; ++i) {
+        ABTS_PTR_EQUAL(tc, NULL, apr_skiplist_insert(skiplist, "baton"));
+        ABTS_TRUE(tc, 1 == skiplist_get_size(tc, skiplist));
+        val = apr_skiplist_find(skiplist, "baton", NULL);
+        ABTS_PTR_NOTNULL(tc, val);
+        ABTS_STR_EQUAL(tc, "baton", val);
+
+        if (height == 0) {
+            height = apr_skiplist_height(skiplist);
+        }
+        else {
+            ABTS_INT_EQUAL(tc, height, apr_skiplist_height(skiplist));
+        }
+    }
+
+    ABTS_PTR_NOTNULL(tc, apr_skiplist_insert(skiplist, "foo"));
+    ABTS_TRUE(tc, 2 == skiplist_get_size(tc, skiplist));
+    val = apr_skiplist_find(skiplist, "foo", NULL);
+    ABTS_PTR_NOTNULL(tc, val);
+    ABTS_STR_EQUAL(tc, "foo", val);
+
+    ABTS_PTR_NOTNULL(tc, apr_skiplist_insert(skiplist, "atfirst"));
+    ABTS_TRUE(tc, 3 == skiplist_get_size(tc, skiplist));
+    val = apr_skiplist_find(skiplist, "atfirst", NULL);
+    ABTS_PTR_NOTNULL(tc, val);
+    ABTS_STR_EQUAL(tc, "atfirst", val);
+}
+
+#define NUM_ADDS 100
+static void skiplist_add(abts_case *tc, void *data)
+{
+    const char *val;
+    size_t i, n = 0;
+
+    apr_skiplist_remove_all(skiplist, NULL);
+    ABTS_TRUE(tc, 0 == skiplist_get_size(tc, skiplist));
+
+    for (i = 0; i < NUM_ADDS; ++i) {
+        n++;
+        ABTS_PTR_NOTNULL(tc, apr_skiplist_add(skiplist, "daton"));
+        ABTS_TRUE(tc, n == skiplist_get_size(tc, skiplist));
+        val = apr_skiplist_find(skiplist, "daton", NULL);
+        ABTS_PTR_NOTNULL(tc, val);
+        ABTS_STR_EQUAL(tc, "daton", val);
+
+        n++;
+        ABTS_PTR_NOTNULL(tc, apr_skiplist_add(skiplist, "baton"));
+        ABTS_TRUE(tc, n == skiplist_get_size(tc, skiplist));
+        val = apr_skiplist_find(skiplist, "baton", NULL);
+        ABTS_PTR_NOTNULL(tc, val);
+        ABTS_STR_EQUAL(tc, "baton", val);
+
+        n++;
+        ABTS_PTR_NOTNULL(tc, apr_skiplist_add(skiplist, "caton"));
+        ABTS_TRUE(tc, n == skiplist_get_size(tc, skiplist));
+        val = apr_skiplist_find(skiplist, "caton", NULL);
+        ABTS_PTR_NOTNULL(tc, val);
+        ABTS_STR_EQUAL(tc, "caton", val);
+
+        n++;
+        ABTS_PTR_NOTNULL(tc, apr_skiplist_add(skiplist, "aaton"));
+        ABTS_TRUE(tc, n == skiplist_get_size(tc, skiplist));
+        val = apr_skiplist_find(skiplist, "aaton", NULL);
+        ABTS_PTR_NOTNULL(tc, val);
+        ABTS_STR_EQUAL(tc, "aaton", val);
+    }
+}
+
+static void skiplist_replace(abts_case *tc, void *data)
+{
+    const char *val;
+    size_t n = skiplist_get_size(tc, skiplist);
+
+    n -= NUM_ADDS - 1;
+    apr_skiplist_replace(skiplist, "daton", NULL);
+    ABTS_TRUE(tc, n == skiplist_get_size(tc, skiplist));
+    val = apr_skiplist_find(skiplist, "daton", NULL);
+    ABTS_PTR_NOTNULL(tc, val);
+    ABTS_STR_EQUAL(tc, "daton", val);
+
+    n -= NUM_ADDS - 1;
+    apr_skiplist_replace(skiplist, "baton", NULL);
+    ABTS_TRUE(tc, n == skiplist_get_size(tc, skiplist));
+    val = apr_skiplist_find(skiplist, "baton", NULL);
+    ABTS_PTR_NOTNULL(tc, val);
+    ABTS_STR_EQUAL(tc, "baton", val);
+
+    n -= NUM_ADDS - 1;
+    apr_skiplist_replace(skiplist, "caton", NULL);
+    ABTS_TRUE(tc, n == skiplist_get_size(tc, skiplist));
+    val = apr_skiplist_find(skiplist, "caton", NULL);
+    ABTS_PTR_NOTNULL(tc, val);
+    ABTS_STR_EQUAL(tc, "caton", val);
+
+    n -= NUM_ADDS - 1;
+    apr_skiplist_replace(skiplist, "aaton", NULL);
+    ABTS_TRUE(tc, n == skiplist_get_size(tc, skiplist));
+    val = apr_skiplist_find(skiplist, "aaton", NULL);
+    ABTS_PTR_NOTNULL(tc, val);
+    ABTS_STR_EQUAL(tc, "aaton", val);
+
+    ABTS_TRUE(tc, n == 4);
+}
+
+static void skiplist_destroy(abts_case *tc, void *data)
+{
+    apr_skiplist_destroy(skiplist, NULL);
+    ABTS_TRUE(tc, 0 == apr_skiplist_size(skiplist));
+    ABTS_TRUE(tc, 1 == apr_skiplist_height(skiplist));
+    ABTS_TRUE(tc, NULL == apr_skiplist_getlist(skiplist));
+}
+
+static void skiplist_size(abts_case *tc, void *data)
+{
+    const char *val;
+
+    ABTS_TRUE(tc, 0 == skiplist_get_size(tc, skiplist));
+
+    ABTS_PTR_NOTNULL(tc, apr_skiplist_insert(skiplist, "abc"));
+    ABTS_PTR_NOTNULL(tc, apr_skiplist_insert(skiplist, "ghi"));
+    ABTS_PTR_NOTNULL(tc, apr_skiplist_insert(skiplist, "def"));
+    val = apr_skiplist_find(skiplist, "abc", NULL);
+    ABTS_PTR_NOTNULL(tc, val);
+    ABTS_STR_EQUAL(tc, "abc", val);
+    val = apr_skiplist_find(skiplist, "ghi", NULL);
+    ABTS_PTR_NOTNULL(tc, val);
+    ABTS_STR_EQUAL(tc, "ghi", val);
+    val = apr_skiplist_find(skiplist, "def", NULL);
+    ABTS_PTR_NOTNULL(tc, val);
+    ABTS_STR_EQUAL(tc, "def", val);
+
+    ABTS_TRUE(tc, 3 == skiplist_get_size(tc, skiplist));
+    apr_skiplist_destroy(skiplist, NULL);
+}
+
+static void skiplist_remove(abts_case *tc, void *data)
+{
+    const char *val;
+
+    ABTS_TRUE(tc, 0 == skiplist_get_size(tc, skiplist));
+
+    ABTS_PTR_NOTNULL(tc, apr_skiplist_add(skiplist, "baton"));
+    ABTS_TRUE(tc, 1 == skiplist_get_size(tc, skiplist));
+    val = apr_skiplist_find(skiplist, "baton", NULL);
+    ABTS_PTR_NOTNULL(tc, val);
+    ABTS_STR_EQUAL(tc, "baton", val);
+
+    ABTS_PTR_NOTNULL(tc, apr_skiplist_add(skiplist, "baton"));
+    ABTS_TRUE(tc, 2 == skiplist_get_size(tc, skiplist));
+    val = apr_skiplist_find(skiplist, "baton", NULL);
+    ABTS_PTR_NOTNULL(tc, val);
+    ABTS_STR_EQUAL(tc, "baton", val);
+
+    ABTS_TRUE(tc, apr_skiplist_remove(skiplist, "baton", NULL) != 0);
+    ABTS_TRUE(tc, 1 == skiplist_get_size(tc, skiplist));
+    val = apr_skiplist_find(skiplist, "baton", NULL);
+    ABTS_PTR_NOTNULL(tc, val);
+    ABTS_STR_EQUAL(tc, "baton", val);
+
+    ABTS_PTR_NOTNULL(tc, apr_skiplist_add(skiplist, "baton"));
+    ABTS_TRUE(tc, 2 == skiplist_get_size(tc, skiplist));
+    val = apr_skiplist_find(skiplist, "baton", NULL);
+    ABTS_PTR_NOTNULL(tc, val);
+    ABTS_STR_EQUAL(tc, "baton", val);
+
+    /* remove all "baton"s */
+    while (apr_skiplist_remove(skiplist, "baton", NULL))
+        ;
+    ABTS_TRUE(tc, 0 == skiplist_get_size(tc, skiplist));
+    val = apr_skiplist_find(skiplist, "baton", NULL);
+    ABTS_PTR_EQUAL(tc, NULL, val);
+}
+
+#define NUM_RAND (100)
+#define NUM_FIND (3 * NUM_RAND)
+static void skiplist_random_loop(abts_case *tc, void *data)
+{
+    char **batons;
+    apr_skiplist *sl;
+    const char *val;
+    int i;
+
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, apr_skiplist_init(&sl, ptmp));
+    apr_skiplist_set_compare(sl, (apr_skiplist_compare)strcmp,
+                                 (apr_skiplist_compare)strcmp);
+    apr_skiplist_set_preheight(sl, 7);
+    ABTS_INT_EQUAL(tc, 7, apr_skiplist_preheight(sl));
+
+    batons = apr_palloc(ptmp, NUM_FIND * sizeof(char*));
+
+    for (i = 0; i < NUM_FIND; ++i) {
+        if (i < NUM_RAND) {
+            batons[i] = apr_psprintf(ptmp, "%.6u", rand() % 1000000);
+        }
+        else {
+            batons[i] = apr_pstrdup(ptmp, batons[i % NUM_RAND]);
+        }
+        ABTS_PTR_NOTNULL(tc, apr_skiplist_add(sl, batons[i]));
+        val = apr_skiplist_find(sl, batons[i], NULL);
+        ABTS_PTR_NOTNULL(tc, val);
+        ABTS_STR_EQUAL(tc, batons[i], val);
+    }
+
+    apr_pool_clear(ptmp);
+}
+
+typedef struct elem {
+    int b;
+    int a;
+} elem;
+
+
+static void add_int_to_skiplist(abts_case *tc, apr_skiplist *list, int n){
+    int* a = apr_skiplist_alloc(list, sizeof(int));
+    *a = n;
+    ABTS_PTR_NOTNULL(tc, apr_skiplist_add(list, a));
+}
+
+static void add_elem_to_skiplist(abts_case *tc, apr_skiplist *list, elem n){
+    elem* a = apr_skiplist_alloc(list, sizeof(elem));
+    *a = n;
+    ABTS_PTR_NOTNULL(tc, apr_skiplist_add(list, a));
+}
+
+static int comp(void *a, void *b){
+    return *((int*) a) - *((int*) b);
+}
+
+static int scomp(void *a, void *b){
+    return ((elem*) a)->a - ((elem*) b)->a;
+}
+
+static int ecomp(void *a, void *b)
+{
+    elem const * const e1 = a;
+    elem const * const e2 = b;
+    if (e1->a < e2->a) {
+        return -1;
+    }
+    else if (e1->a > e2->a) {
+        return +1;
+    }
+    else if (e1->b < e2->b) {
+        return -1;
+    }
+    else if (e1->b > e2->b) {
+        return +1;
+    }
+    else {
+        return 0;
+    }
+}
+
+/* Some tests below add multiple duplicates and then try to remove each one
+ * individually, in arbitrary order.
+ *
+ * Using apr_skiplist_remove_compare(..., scomp, NULL) would not work because
+ * it will likely remove any duplicate (the first one) encountered on the path,
+ * hence possibly not the expected one.
+ * 
+ * Using apr_skiplist_remove_compare(..., ecomp, NULL) works provided all the
+ * duplicates (same a) don't also have the same b (which is the case in the
+ * test below), hence uniqueness is cooked in the elem itself.
+ *
+ * Another possibility is to rely on unique pointers, and then cook a remove
+ * function, like the following skiplist_remove_scomp(), which will go straight
+ * to the last duplicate (using scomp) and then iterate on the previous elems
+ * until pointers match.
+ *
+ * Providing uniqueness in the elem itself is the more clean/efficient option,
+ * but if all you have is a unique pointer the pattern in the function may be
+ * worth it ( or it's just a way to test several skiplist functionalities :)
+ */
+static void skiplist_remove_scomp(abts_case *tc, apr_skiplist *list, elem *n)
+{
+    elem *e;
+    apr_skiplistnode *iter = NULL;
+    e = apr_skiplist_last(list, n, &iter);
+    while (e && e != n) {
+        ABTS_INT_EQUAL(tc, 0, scomp(n, e));
+        e = apr_skiplist_previous(list, &iter);
+    }
+    ABTS_PTR_EQUAL(tc, n, apr_skiplist_element(iter));
+    apr_skiplist_remove_node(list, iter, NULL);
+}
+
+static void skiplist_test(abts_case *tc, void *data) {
+    int test_elems = 10;
+    int i = 0, j = 0;
+    int *val = NULL;
+    elem *val2 = NULL;
+    apr_skiplist * list = NULL;
+    apr_skiplist * list2 = NULL;
+    apr_skiplist * list3 = NULL;
+    apr_skiplist * list4 = NULL;
+    int first_forty_two = 42,
+        second_forty_two = 42;
+    apr_array_header_t *array;
+    elem t1, t2, t3, t4, t5;
+    t1.a = 1; t1.b = 1;
+    t2.a = 42; t2.b = 1;
+    t3.a = 42; t3.b = 2;
+    t4.a = 42; t4.b = 3;
+    t5.a = 142; t5.b = 1;
+
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, apr_skiplist_init(&list, ptmp));
+    apr_skiplist_set_compare(list, comp, comp);
+    
+    /* insert 10 objects */
+    for (i = 0; i < test_elems; ++i){
+        add_int_to_skiplist(tc, list, i);
+    }
+
+    /* remove all objects */
+    while ((val = apr_skiplist_pop(list, NULL))){
+        ABTS_INT_EQUAL(tc, *val, j++);
+    }
+
+    /* insert 10 objects again */
+    for (i = test_elems; i < test_elems+test_elems; ++i){
+        add_int_to_skiplist(tc, list, i);
+    }
+
+    j = test_elems;
+    while ((val = apr_skiplist_pop(list, NULL))){
+        ABTS_INT_EQUAL(tc, *val, j++);
+    }
+
+    /* empty */
+    val = apr_skiplist_pop(list, NULL);
+    ABTS_PTR_EQUAL(tc, val, NULL);
+
+    add_int_to_skiplist(tc, list, 42);
+    val = apr_skiplist_pop(list, NULL);
+    ABTS_INT_EQUAL(tc, *val, 42); 
+
+    /* empty */
+    val = apr_skiplist_pop(list, NULL);
+    ABTS_PTR_EQUAL(tc, val, NULL);
+
+    ABTS_PTR_NOTNULL(tc, apr_skiplist_add(list, &first_forty_two));
+    add_int_to_skiplist(tc, list, 1);
+    add_int_to_skiplist(tc, list, 142);
+    ABTS_PTR_NOTNULL(tc, apr_skiplist_add(list, &second_forty_two));
+    val = apr_skiplist_peek(list);
+    ABTS_INT_EQUAL(tc, *val, 1);
+    val = apr_skiplist_pop(list, NULL);
+    ABTS_INT_EQUAL(tc, *val, 1);
+    val = apr_skiplist_peek(list);
+    ABTS_PTR_EQUAL(tc, val, &first_forty_two);
+    ABTS_INT_EQUAL(tc, *val, 42);
+    val = apr_skiplist_pop(list, NULL);
+    ABTS_PTR_EQUAL(tc, val, &first_forty_two);
+    ABTS_INT_EQUAL(tc, *val, 42);
+    val = apr_skiplist_pop(list, NULL);
+    ABTS_PTR_EQUAL(tc, val, &second_forty_two);
+    ABTS_INT_EQUAL(tc, *val, 42);
+    val = apr_skiplist_peek(list);
+    ABTS_INT_EQUAL(tc, *val, 142);
+
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, apr_skiplist_init(&list2, ptmp));
+    apr_skiplist_set_compare(list2, scomp, scomp);
+    add_elem_to_skiplist(tc, list2, t2);
+    add_elem_to_skiplist(tc, list2, t1);
+    add_elem_to_skiplist(tc, list2, t3);
+    add_elem_to_skiplist(tc, list2, t5);
+    add_elem_to_skiplist(tc, list2, t4);
+    val2 = apr_skiplist_pop(list2, NULL);
+    ABTS_INT_EQUAL(tc, val2->a, 1);
+    val2 = apr_skiplist_pop(list2, NULL);
+    ABTS_INT_EQUAL(tc, val2->a, 42);
+    ABTS_INT_EQUAL(tc, val2->b, 1);
+    val2 = apr_skiplist_pop(list2, NULL);
+    ABTS_INT_EQUAL(tc, val2->a, 42);
+    ABTS_INT_EQUAL(tc, val2->b, 2);
+    val2 = apr_skiplist_pop(list2, NULL);
+    ABTS_INT_EQUAL(tc, val2->a, 42);
+    ABTS_INT_EQUAL(tc, val2->b, 3);
+    val2 = apr_skiplist_pop(list2, NULL);
+    ABTS_INT_EQUAL(tc, val2->a, 142);
+    ABTS_INT_EQUAL(tc, val2->b, 1);
+
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, apr_skiplist_init(&list3, ptmp));
+    apr_skiplist_set_compare(list3, ecomp, ecomp);
+    array = apr_array_make(ptmp, 10, sizeof(elem *));
+    for (i = 0; i < 10; ++i) {
+        elem *e = apr_palloc(ptmp, sizeof *e);
+        e->a = 4224;
+        e->b = i;
+        APR_ARRAY_PUSH(array, elem *) = e;
+        ABTS_PTR_NOTNULL(tc, apr_skiplist_insert(list3, e));
+    }
+    for (i = 0; i < 5; ++i) {
+        elem *e = APR_ARRAY_IDX(array, i, elem *);
+        val2 = apr_skiplist_find(list3, e, NULL);
+        ABTS_PTR_EQUAL(tc, e, val2);
+        ABTS_TRUE(tc, apr_skiplist_remove(list3, e, NULL) != 0);
+    }
+    for (i = 0; i < 5; ++i) {
+        elem *e = APR_ARRAY_IDX(array, 9 - i, elem *);
+        val2 = apr_skiplist_find(list3, e, NULL);
+        ABTS_PTR_EQUAL(tc, e, val2);
+        ABTS_TRUE(tc, apr_skiplist_remove(list3, e, NULL) != 0);
+    }
+
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, apr_skiplist_init(&list4, ptmp));
+    apr_skiplist_set_compare(list4, scomp, scomp);
+    for (i = 0; i < 5; ++i){
+        add_elem_to_skiplist(tc, list4, t1);
+    }
+    for (i = 0; i < 5; ++i){
+        add_elem_to_skiplist(tc, list4, t2);
+    }
+    ABTS_PTR_NOTNULL(tc, apr_skiplist_add(list4, &t2));
+    for (i = 0; i < 5; ++i){
+        add_elem_to_skiplist(tc, list4, t2);
+    }
+    for (i = 0; i < 5; ++i){
+        add_elem_to_skiplist(tc, list4, t3);
+    }
+    ABTS_PTR_NOTNULL(tc, apr_skiplist_add(list4, &t3));
+    for (i = 0; i < 5; ++i){
+        add_elem_to_skiplist(tc, list4, t3);
+    }
+    for (i = 0; i < 5; ++i){
+        add_elem_to_skiplist(tc, list4, t4);
+    }
+    ABTS_PTR_NOTNULL(tc, apr_skiplist_add(list4, &t4));
+    for (i = 0; i < 5; ++i){
+        add_elem_to_skiplist(tc, list4, t4);
+    }
+    for (i = 0; i < 5; ++i){
+        add_elem_to_skiplist(tc, list4, t5);
+    }
+    skiplist_remove_scomp(tc, list4, &t2);
+    skiplist_remove_scomp(tc, list4, &t3);
+    skiplist_remove_scomp(tc, list4, &t4);
+
+    apr_pool_clear(ptmp);
+}
+
+
+abts_suite *testskiplist(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite)
+
+    apr_pool_create(&ptmp, p);
+
+    abts_run_test(suite, skiplist_init, NULL);
+    abts_run_test(suite, skiplist_find, NULL);
+    abts_run_test(suite, skiplist_dontfind, NULL);
+    abts_run_test(suite, skiplist_insert, NULL);
+    abts_run_test(suite, skiplist_add, NULL);
+    abts_run_test(suite, skiplist_replace, NULL);
+    abts_run_test(suite, skiplist_destroy, NULL);
+    abts_run_test(suite, skiplist_size, NULL);
+    abts_run_test(suite, skiplist_remove, NULL);
+    abts_run_test(suite, skiplist_random_loop, NULL);
+
+    abts_run_test(suite, skiplist_test, NULL);
+
+    apr_pool_destroy(ptmp);
+
+    return suite;
+}
+
diff --git a/test/testsleep.c b/test/testsleep.c
new file mode 100644
index 00000000000..eff24ddf6ea
--- /dev/null
+++ b/test/testsleep.c
@@ -0,0 +1,53 @@
+/* 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 "time.h"
+#include "apr_thread_proc.h"
+#include "apr_errno.h"
+#include "apr_general.h"
+#include "apr_lib.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include "testutil.h"
+
+#define SLEEP_INTERVAL 5
+
+static void sleep_one(abts_case *tc, void *data)
+{
+    time_t pretime = time(NULL);
+    time_t posttime;
+    time_t timediff;
+
+    apr_sleep(apr_time_from_sec(SLEEP_INTERVAL));
+    posttime = time(NULL);
+
+    /* normalize the timediff.  We should have slept for SLEEP_INTERVAL, so
+     * we should just subtract that out.
+     */
+    timediff = posttime - pretime - SLEEP_INTERVAL;
+    ABTS_TRUE(tc, timediff >= 0);
+    ABTS_TRUE(tc, timediff <= 1);
+}
+
+abts_suite *testsleep(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite)
+
+    abts_run_test(suite, sleep_one, NULL);
+
+    return suite;
+}
+
diff --git a/test/testsock.c b/test/testsock.c
index 98f164480be..23a0073fe42 100644
--- a/test/testsock.c
+++ b/test/testsock.c
@@ -1,134 +1,768 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 <stdio.h>
-#include <stdlib.h>
-#include <signal.h>
+#include "testutil.h"
+#include "testsock.h"
 #include "apr_thread_proc.h"
+#include "apr_network_io.h"
 #include "apr_errno.h"
 #include "apr_general.h"
 #include "apr_lib.h"
+#include "apr_strings.h"
+#include "apr_poll.h"
+#define APR_WANT_BYTEFUNC
+#include "apr_want.h"
 
-#define STRLEN 15
+#define UNIX_SOCKET_NAME    "/tmp/apr-socket"
+#define IPV4_SOCKET_NAME    "127.0.0.1"
+static char *socket_name = NULL;
+static int   socket_type = APR_INET;
 
-int main(int argc, char *argv[])
+static void launch_child(abts_case *tc, apr_proc_t *proc, const char *arg1, apr_pool_t *p)
 {
-    ap_pool_t *context;
+    apr_procattr_t *procattr;
+    const char *args[4];
+    apr_status_t rv;
 
-    ap_procattr_t *attr1 = NULL;
-    ap_procattr_t *attr2 = NULL;
-    ap_proc_t *proc1 = NULL;
-    ap_proc_t *proc2 = NULL;
-    ap_status_t s1;
-    ap_status_t s2;
-    char *args[2];
+    rv = apr_procattr_create(&procattr, p);
+    APR_ASSERT_SUCCESS(tc, "Couldn't create procattr", rv);
 
-    fprintf(stdout, "Initializing.........");
-    if (ap_initialize() != APR_SUCCESS) {
-        fprintf(stderr, "Something went wrong\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK\n");
-    atexit(ap_terminate);
+    rv = apr_procattr_io_set(procattr, APR_NO_PIPE, APR_NO_PIPE,
+            APR_NO_PIPE);
+    APR_ASSERT_SUCCESS(tc, "Couldn't set io in procattr", rv);
+
+    rv = apr_procattr_error_check_set(procattr, 1);
+    APR_ASSERT_SUCCESS(tc, "Couldn't set error check in procattr", rv);
+
+    rv = apr_procattr_cmdtype_set(procattr, APR_PROGRAM_ENV);
+    APR_ASSERT_SUCCESS(tc, "Couldn't set copy environment", rv);
+
+    args[0] = "sockchild" EXTENSION;
+    args[1] = arg1;
+    args[2] = socket_name;
+    args[3] = NULL;
+    rv = apr_proc_create(proc, TESTBINPATH "sockchild" EXTENSION, args, NULL,
+                         procattr, p);
+    APR_ASSERT_SUCCESS(tc, "Couldn't launch program", rv);
+}
+
+static int wait_child(abts_case *tc, apr_proc_t *proc) 
+{
+    int exitcode;
+    apr_exit_why_e why;
+
+    ABTS_ASSERT(tc, "Error waiting for child process",
+            apr_proc_wait(proc, &exitcode, &why, APR_WAIT) == APR_CHILD_DONE);
+
+    ABTS_ASSERT(tc, "child terminated normally", why == APR_PROC_EXIT);
+    return exitcode;
+}
+
+static void test_addr_info(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_sockaddr_t *sa;
+    int rc;
+
+    rv = apr_sockaddr_info_get(&sa, NULL, APR_UNSPEC, 80, 0, p);
+    APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
+
+    rc = apr_sockaddr_is_wildcard(sa);
+    ABTS_INT_NEQUAL(tc, 0, rc);
+
+    rv = apr_sockaddr_info_get(&sa, "127.0.0.1", APR_UNSPEC, 80, 0, p);
+    APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
+    ABTS_STR_EQUAL(tc, "127.0.0.1", sa->hostname);
+
+    rc = apr_sockaddr_is_wildcard(sa);
+    ABTS_INT_EQUAL(tc, 0, rc);
+
+    rv = apr_sockaddr_info_get(&sa, "127.0.0.1", APR_UNSPEC, 0, 0, p);
+    APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
+    ABTS_STR_EQUAL(tc, "127.0.0.1", sa->hostname);
+    ABTS_INT_EQUAL(tc, 0, sa->port);
+    ABTS_INT_EQUAL(tc, 0, ntohs(sa->sa.sin.sin_port));
+}
+
+static void test_addr_copy(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_sockaddr_t *sa1, *sa2;
+    int rc;
+    const char *hosts[] = {
+        "127.0.0.1",
+#if APR_HAVE_IPV6
+        "::1",
+#endif
+        NULL
+    }, **host = hosts;
+
+    /* Loop up to and including NULL */
+    do {
+        rv = apr_sockaddr_info_get(&sa1, *host, APR_UNSPEC, 80, 0, p);
+        APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
+
+        rv = apr_sockaddr_info_copy(&sa2, sa1, p);
+        APR_ASSERT_SUCCESS(tc, "Problem copying sockaddr", rv);
+
+        ABTS_PTR_NOTNULL(tc, sa1);
+        do {
+            ABTS_PTR_NOTNULL(tc, sa2);
+
+            rc = apr_sockaddr_equal(sa2, sa1);
+            ABTS_INT_NEQUAL(tc, 0, rc);
+            ABTS_INT_EQUAL(tc, 80, sa1->port);
+            ABTS_INT_EQUAL(tc, sa2->port, sa1->port);
+            ABTS_INT_EQUAL(tc, 80, ntohs(sa1->sa.sin.sin_port));
+            ABTS_INT_EQUAL(tc, ntohs(sa2->sa.sin.sin_port), ntohs(sa1->sa.sin.sin_port));
+
+            if (*host) {
+                ABTS_PTR_NOTNULL(tc, sa1->hostname);
+                ABTS_PTR_NOTNULL(tc, sa2->hostname);
+                ABTS_STR_EQUAL(tc, *host, sa1->hostname);
+                ABTS_STR_EQUAL(tc, sa1->hostname, sa2->hostname);
+                ABTS_TRUE(tc, sa1->hostname != sa2->hostname);
+            }
+            else {
+                ABTS_PTR_EQUAL(tc, NULL, sa1->hostname);
+                ABTS_PTR_EQUAL(tc, NULL, sa2->hostname);
+            }
+
+        } while ((sa2 = sa2->next, sa1 = sa1->next));
+        ABTS_PTR_EQUAL(tc, NULL, sa2);
+
+    } while (*host++);
+}
+
+static void test_serv_by_name(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_sockaddr_t *sa;
+
+    rv = apr_sockaddr_info_get(&sa, NULL, APR_UNSPEC, 0, 0, p);
+    APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
+
+    rv = apr_getservbyname(sa, "ftp");
+    APR_ASSERT_SUCCESS(tc, "Problem getting ftp service", rv);
+    ABTS_INT_EQUAL(tc, 21, sa->port);
+
+    rv = apr_getservbyname(sa, "complete_and_utter_rubbish");
+    APR_ASSERT_SUCCESS(tc, "Problem getting non-existent service", !rv);
+
+    rv = apr_getservbyname(sa, "telnet");
+    APR_ASSERT_SUCCESS(tc, "Problem getting telnet service", rv);
+    ABTS_INT_EQUAL(tc, 23, sa->port);
+}
 
-    fprintf(stdout, "Creating context.......");
-    if (ap_create_pool(&context, NULL) != APR_SUCCESS) {
-        fprintf(stderr, "Could not create context\n");
-        exit(-1);
+static apr_socket_t *setup_socket(abts_case *tc)
+{
+    apr_status_t rv;
+    apr_sockaddr_t *sa;
+    apr_socket_t *sock;
+
+    rv = apr_sockaddr_info_get(&sa, socket_name, socket_type, 8021, 0, p);
+    APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
+
+    rv = apr_socket_create(&sock, sa->family, SOCK_STREAM, APR_PROTO_TCP, p);
+    APR_ASSERT_SUCCESS(tc, "Problem creating socket", rv);
+
+    rv = apr_socket_opt_set(sock, APR_SO_REUSEADDR, 1);
+    APR_ASSERT_SUCCESS(tc, "Could not set REUSEADDR on socket", rv);
+    
+    rv = apr_socket_bind(sock, sa);
+    APR_ASSERT_SUCCESS(tc, "Problem binding to port", rv);
+    if (rv) return NULL;
+                
+    rv = apr_socket_listen(sock, 5);
+    APR_ASSERT_SUCCESS(tc, "Problem listening on socket", rv);
+
+    return sock;
+}
+
+static void test_create_bind_listen(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_socket_t *sock = setup_socket(tc);
+    
+    if (!sock) return;
+    
+    rv = apr_socket_close(sock);
+    APR_ASSERT_SUCCESS(tc, "Problem closing socket", rv);
+}
+
+static void test_send(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_socket_t *sock;
+    apr_socket_t *sock2;
+    apr_proc_t proc;
+    int protocol;
+    apr_size_t length;
+
+    sock = setup_socket(tc);
+    if (!sock) return;
+
+    launch_child(tc, &proc, "read", p);
+    
+    rv = apr_socket_accept(&sock2, sock, p);
+    APR_ASSERT_SUCCESS(tc, "Problem with receiving connection", rv);
+
+    apr_socket_protocol_get(sock2, &protocol);
+    ABTS_INT_EQUAL(tc, APR_PROTO_TCP, protocol);
+    
+    length = strlen(DATASTR);
+    apr_socket_send(sock2, DATASTR, &length);
+
+    /* Make sure that the client received the data we sent */
+    ABTS_SIZE_EQUAL(tc, strlen(DATASTR), wait_child(tc, &proc));
+
+    rv = apr_socket_close(sock2);
+    APR_ASSERT_SUCCESS(tc, "Problem closing connected socket", rv);
+    rv = apr_socket_close(sock);
+    APR_ASSERT_SUCCESS(tc, "Problem closing socket", rv);
+}
+
+static void test_recv(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_socket_t *sock;
+    apr_socket_t *sock2;
+    apr_proc_t proc;
+    int protocol;
+    apr_size_t length = STRLEN;
+    char datastr[STRLEN];
+    
+    sock = setup_socket(tc);
+    if (!sock) return;
+
+    launch_child(tc, &proc, "write", p);
+    
+    rv = apr_socket_accept(&sock2, sock, p);
+    APR_ASSERT_SUCCESS(tc, "Problem with receiving connection", rv);
+
+    apr_socket_protocol_get(sock2, &protocol);
+    ABTS_INT_EQUAL(tc, APR_PROTO_TCP, protocol);
+    
+    memset(datastr, 0, STRLEN);
+    apr_socket_recv(sock2, datastr, &length);
+
+    /* Make sure that the server received the data we sent */
+    ABTS_STR_EQUAL(tc, DATASTR, datastr);
+    ABTS_SIZE_EQUAL(tc, strlen(datastr), wait_child(tc, &proc));
+
+    rv = apr_socket_close(sock2);
+    APR_ASSERT_SUCCESS(tc, "Problem closing connected socket", rv);
+    rv = apr_socket_close(sock);
+    APR_ASSERT_SUCCESS(tc, "Problem closing socket", rv);
+}
+
+static void test_atreadeof(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_socket_t *sock;
+    apr_socket_t *sock2;
+    apr_proc_t proc;
+    apr_size_t length = STRLEN;
+    char datastr[STRLEN];
+    int atreadeof = -1;
+
+    sock = setup_socket(tc);
+    if (!sock) return;
+
+    launch_child(tc, &proc, "write", p);
+
+    rv = apr_socket_accept(&sock2, sock, p);
+    APR_ASSERT_SUCCESS(tc, "Problem with receiving connection", rv);
+
+    /* Check that the remote socket is still open */
+    rv = apr_socket_atreadeof(sock2, &atreadeof);
+    APR_ASSERT_SUCCESS(tc, "Determine whether at EOF, #1", rv);
+    ABTS_INT_EQUAL(tc, 0, atreadeof);
+
+    memset(datastr, 0, STRLEN);
+    apr_socket_recv(sock2, datastr, &length);
+
+    /* Make sure that the server received the data we sent */
+    ABTS_STR_EQUAL(tc, DATASTR, datastr);
+    ABTS_SIZE_EQUAL(tc, strlen(datastr), wait_child(tc, &proc));
+
+    /* The child is dead, so should be the remote socket */
+    rv = apr_socket_atreadeof(sock2, &atreadeof);
+    APR_ASSERT_SUCCESS(tc, "Determine whether at EOF, #2", rv);
+    ABTS_INT_EQUAL(tc, 1, atreadeof);
+
+    rv = apr_socket_close(sock2);
+    APR_ASSERT_SUCCESS(tc, "Problem closing connected socket", rv);
+
+    launch_child(tc, &proc, "close", p);
+
+    rv = apr_socket_accept(&sock2, sock, p);
+    APR_ASSERT_SUCCESS(tc, "Problem with receiving connection", rv);
+
+    /* The child closed the socket as soon as it could... */
+    rv = apr_socket_atreadeof(sock2, &atreadeof);
+    APR_ASSERT_SUCCESS(tc, "Determine whether at EOF, #3", rv);
+    if (!atreadeof) { /* ... but perhaps not yet; wait a moment */
+        apr_sleep(apr_time_from_msec(5));
+        rv = apr_socket_atreadeof(sock2, &atreadeof);
+        APR_ASSERT_SUCCESS(tc, "Determine whether at EOF, #4", rv);
     }
-    fprintf(stdout, "OK\n");
+    ABTS_INT_EQUAL(tc, 1, atreadeof);
+    wait_child(tc, &proc);
+
+    rv = apr_socket_close(sock2);
+    APR_ASSERT_SUCCESS(tc, "Problem closing connected socket", rv);
+
+    rv = apr_socket_close(sock);
+    APR_ASSERT_SUCCESS(tc, "Problem closing socket", rv);
+}
+
+static void test_timeout(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_socket_t *sock;
+    apr_socket_t *sock2;
+    apr_proc_t proc;
+    int protocol;
+    int exit;
+    
+    sock = setup_socket(tc);
+    if (!sock) return;
+
+    launch_child(tc, &proc, "read", p);
+    
+    rv = apr_socket_accept(&sock2, sock, p);
+    APR_ASSERT_SUCCESS(tc, "Problem with receiving connection", rv);
+
+    apr_socket_protocol_get(sock2, &protocol);
+    ABTS_INT_EQUAL(tc, APR_PROTO_TCP, protocol);
+    
+    exit = wait_child(tc, &proc);    
+    ABTS_INT_EQUAL(tc, SOCKET_TIMEOUT, exit);
 
-    fprintf(stdout, "This test relies on the process test working.  Please\n");
-    fprintf(stdout, "run that test first, and only run this test when it\n");
-    fprintf(stdout, "completes successfully.  Alternatively, you could run\n");
-    fprintf(stdout, "server and client by yourself.\n");
+    /* We didn't write any data, so make sure the child program returns
+     * an error.
+     */
+    rv = apr_socket_close(sock2);
+    APR_ASSERT_SUCCESS(tc, "Problem closing connected socket", rv);
+    rv = apr_socket_close(sock);
+    APR_ASSERT_SUCCESS(tc, "Problem closing socket", rv);
+}
+
+static void test_print_addr(abts_case *tc, void *data)
+{
+    apr_sockaddr_t *sa;
+    apr_status_t rv;
+    char *s;
 
-    fprintf(stdout, "Creating children to run network tests.......\n");
-    s1 = ap_createprocattr_init(&attr1, context);
-    s2 = ap_createprocattr_init(&attr2, context);
+    rv = apr_sockaddr_info_get(&sa, "0.0.0.0", APR_INET, 80, 0, p);
+    APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
 
-    if (s1 != APR_SUCCESS || s2 != APR_SUCCESS) {
-        fprintf(stderr, "Problem creating proc attrs\n");
-        exit(-1);
+    s = apr_psprintf(p, "foo %pI bar", sa);
+
+    ABTS_STR_EQUAL(tc, "foo 0.0.0.0:80 bar", s);
+
+#if APR_HAVE_IPV6
+    rv = apr_sockaddr_info_get(&sa, "::ffff:0.0.0.0", APR_INET6, 80, 0, p);
+    APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
+    if (rv == APR_SUCCESS)
+        ABTS_TRUE(tc, sa != NULL);
+    if (rv == APR_SUCCESS && sa) {
+        /* sa should now be a v4-mapped IPv6 address. */
+        char buf[128];
+        int rc;
+
+        rc = apr_sockaddr_is_wildcard(sa);
+        ABTS_INT_NEQUAL(tc, 0, rc);
+
+        memset(buf, 'z', sizeof buf);
+        
+        APR_ASSERT_SUCCESS(tc, "could not get IP address",
+                           apr_sockaddr_ip_getbuf(buf, 22, sa));
+        
+        ABTS_STR_EQUAL(tc, "0.0.0.0", buf);
     }
+#endif
+}
 
-    args[0] = ap_pstrdup(context, "server");
-    args[1] = NULL; 
-    s1 = ap_create_process(&proc1, "./server", args, NULL, attr1, context);
+static void test_get_addr(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_socket_t *ld, *sd, *cd;
+    apr_sockaddr_t *sa, *ca;
+    apr_pool_t *subp;
+    char *a, *b;
+
+    APR_ASSERT_SUCCESS(tc, "create subpool", apr_pool_create(&subp, p));
+
+    ld = setup_socket(tc);
+    if (!ld) return;
+
+    APR_ASSERT_SUCCESS(tc,
+                       "get local address of bound socket",
+                       apr_socket_addr_get(&sa, APR_LOCAL, ld));
+
+    rv = apr_socket_create(&cd, sa->family, SOCK_STREAM,
+                           APR_PROTO_TCP, subp);
+    APR_ASSERT_SUCCESS(tc, "create client socket", rv);
 
-    args[0] = ap_pstrdup(context, "client");
-    s2 = ap_create_process(&proc2, "./client", args, NULL, attr2, context);
+    APR_ASSERT_SUCCESS(tc, "enable non-block mode",
+                       apr_socket_opt_set(cd, APR_SO_NONBLOCK, 1));
 
-    if (s1 != APR_SUCCESS || s2 != APR_SUCCESS) {
-        fprintf(stderr, "Problem spawning new process\n");
-        exit(-1);
+    /* It is valid for a connect() on a socket with NONBLOCK set to
+     * succeed (if the connection can be established synchronously),
+     * but if it does, this test cannot proceed.  */
+    rv = apr_socket_connect(cd, sa);
+    if (rv == APR_SUCCESS) {
+        apr_socket_close(ld);
+        apr_socket_close(cd);
+        ABTS_NOT_IMPL(tc, "Cannot test if connect completes "
+                      "synchronously");
+        return;
     }
 
-    while ((s1 = ap_wait_proc(proc1, APR_NOWAIT)) != APR_CHILD_DONE || 
-           (s2 = ap_wait_proc(proc2, APR_NOWAIT)) != APR_CHILD_DONE) {
-        continue;
+    if (!APR_STATUS_IS_EINPROGRESS(rv)) {
+        apr_socket_close(ld);
+        apr_socket_close(cd);
+        APR_ASSERT_SUCCESS(tc, "connect to listener", rv);
+        return;
+    }
+
+    APR_ASSERT_SUCCESS(tc, "accept connection",
+                       apr_socket_accept(&sd, ld, subp));
+    
+    {
+        /* wait for writability */
+        apr_pollfd_t pfd;
+        int n;
+
+        pfd.p = p;
+        pfd.desc_type = APR_POLL_SOCKET;
+        pfd.reqevents = APR_POLLOUT|APR_POLLHUP;
+        pfd.desc.s = cd;
+        pfd.client_data = NULL;
+
+        APR_ASSERT_SUCCESS(tc, "poll for connect completion",
+                           apr_poll(&pfd, 1, &n, 5 * APR_USEC_PER_SEC));
+
     }
 
-    if (s1 == APR_SUCCESS) {
-        ap_kill(proc2, SIGTERM);
-        ap_wait_proc(proc2, APR_WAIT);
+    APR_ASSERT_SUCCESS(tc, "get local address of server socket",
+                       apr_socket_addr_get(&sa, APR_LOCAL, sd));
+    APR_ASSERT_SUCCESS(tc, "get remote address of client socket",
+                       apr_socket_addr_get(&ca, APR_REMOTE, cd));
+
+    /* Test that the pool of the returned sockaddr objects exactly
+     * match the socket. */
+    ABTS_PTR_EQUAL(tc, subp, sa->pool);
+    ABTS_PTR_EQUAL(tc, subp, ca->pool);
+
+    /* Check equivalence. */
+    a = apr_psprintf(p, "%pI fam=%d", sa, sa->family);
+    b = apr_psprintf(p, "%pI fam=%d", ca, ca->family);
+    ABTS_STR_EQUAL(tc, a, b);
+
+    /* Check pool of returned sockaddr, as above. */
+    APR_ASSERT_SUCCESS(tc, "get local address of client socket",
+                       apr_socket_addr_get(&sa, APR_LOCAL, cd));
+    APR_ASSERT_SUCCESS(tc, "get remote address of server socket",
+                       apr_socket_addr_get(&ca, APR_REMOTE, sd));
+
+    /* Check equivalence. */
+    a = apr_psprintf(p, "%pI fam=%d", sa, sa->family);
+    b = apr_psprintf(p, "%pI fam=%d", ca, ca->family);
+    ABTS_STR_EQUAL(tc, a, b);
+
+    ABTS_PTR_EQUAL(tc, subp, sa->pool);
+    ABTS_PTR_EQUAL(tc, subp, ca->pool);
+                       
+    apr_socket_close(cd);
+    apr_socket_close(sd);
+    apr_socket_close(ld);
+
+    apr_pool_destroy(subp);
+}
+
+static void test_wait(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_socket_t *server;
+    apr_socket_t *server_connection;
+    apr_sockaddr_t *server_addr;
+    apr_socket_t *client;
+    apr_interval_time_t delay = 200000;
+    apr_time_t start_time;
+    apr_time_t end_time;
+    apr_size_t nbytes;
+    int connected = FALSE;
+
+    server = setup_socket(tc);
+    if (!server) return;
+
+    rv = apr_sockaddr_info_get(&server_addr, socket_name, socket_type, 8021, 0, p);
+    APR_ASSERT_SUCCESS(tc, "setting up sockaddr", rv);
+
+    rv = apr_socket_create(&client, server_addr->family, SOCK_STREAM, 0, p);
+    APR_ASSERT_SUCCESS(tc, "creating client socket", rv);
+
+    rv = apr_socket_timeout_set(client, 0);
+    APR_ASSERT_SUCCESS(tc, "setting client socket timeout", rv);
+
+    rv = apr_socket_connect(client, server_addr);
+
+    if (rv == APR_SUCCESS) {
+        connected = TRUE;
     }
     else {
-        ap_kill(proc1, SIGTERM);
-        ap_wait_proc(proc1, APR_WAIT);
+        ABTS_ASSERT(tc, "connecting client to server", APR_STATUS_IS_EINPROGRESS(rv));
+    }
+
+    rv = apr_socket_accept(&server_connection, server, p);
+    APR_ASSERT_SUCCESS(tc, "accepting client connection", rv);
+
+    if (!connected) {
+        rv = apr_socket_connect(client, server_addr);
+        APR_ASSERT_SUCCESS(tc, "connecting client to server", rv);
     }
-    fprintf(stdout, "Network test completed.\n");   
 
-    return 1;
+    rv = apr_socket_timeout_set(client, delay);
+    APR_ASSERT_SUCCESS(tc, "setting client socket timeout", rv);
+
+    start_time = apr_time_now();
+    rv = apr_socket_wait(client, APR_WAIT_READ);
+    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv));
+
+    end_time = apr_time_now();
+    ABTS_ASSERT(tc, "apr_socket_wait() waited for the time out", end_time - start_time >= delay);
+
+    nbytes = 4;
+    rv = apr_socket_send(server_connection, "data", &nbytes);
+    APR_ASSERT_SUCCESS(tc, "Couldn't write to client", rv);
+
+    rv = apr_socket_wait(client, APR_WAIT_READ);
+    APR_ASSERT_SUCCESS(tc, "Wait for socket failed", rv);
+
+    rv = apr_socket_close(server);
+    APR_ASSERT_SUCCESS(tc, "couldn't close server socket", rv);
 }
+
+/* Make sure that setting a connected socket non-blocking works
+ * when the listening socket was non-blocking.
+ * If APR thinks that non-blocking is inherited but it really
+ * isn't, this testcase will fail.
+ */
+static void test_nonblock_inheritance(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_socket_t *sock;
+    apr_socket_t *sock2;
+    apr_proc_t proc;
+    char buffer[10];
+    apr_size_t length;
+    int tries;
+
+    sock = setup_socket(tc);
+    if (!sock) return;
+
+    rv = apr_socket_opt_set(sock, APR_SO_NONBLOCK, 1);
+    APR_ASSERT_SUCCESS(tc, "Could not make listening socket nonblocking", rv);
+
+    launch_child(tc, &proc, "write_after_delay", p);
+
+    tries = 10;
+    while (tries--) {
+        rv = apr_socket_accept(&sock2, sock, p);
+        if (!APR_STATUS_IS_EAGAIN(rv)) {
+            break;
+        }
+        apr_sleep(apr_time_from_msec(50));
+    }
+    APR_ASSERT_SUCCESS(tc, "Problem with receiving connection", rv);
+
+    rv = apr_socket_opt_set(sock2, APR_SO_NONBLOCK, 1);
+    APR_ASSERT_SUCCESS(tc, "Could not make connected socket nonblocking", rv);
+
+    length = sizeof buffer;
+    rv = apr_socket_recv(sock2, buffer, &length);
+    ABTS_ASSERT(tc, "should have gotten EAGAIN", APR_STATUS_IS_EAGAIN(rv));
+
+    wait_child(tc, &proc);
+
+    rv = apr_socket_close(sock2);
+    APR_ASSERT_SUCCESS(tc, "Problem closing connected socket", rv);
+    rv = apr_socket_close(sock);
+    APR_ASSERT_SUCCESS(tc, "Problem closing socket", rv);
+}
+
+static void test_freebind(abts_case *tc, void *data)
+{
+#ifdef IP_FREEBIND
+    apr_status_t rv;
+    apr_socket_t *sock;
+    apr_sockaddr_t *sa;
+    apr_int32_t on;
+    
+    /* RFC 5737 address */
+    rv = apr_sockaddr_info_get(&sa, "192.0.2.1", APR_INET, 8080, 0, p);
+    APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
+    
+    rv = apr_socket_create(&sock, sa->family, SOCK_STREAM, APR_PROTO_TCP, p);
+    APR_ASSERT_SUCCESS(tc, "Problem creating socket", rv);
+
+    rv = apr_socket_opt_set(sock, APR_SO_REUSEADDR, 1);
+    APR_ASSERT_SUCCESS(tc, "Could not set REUSEADDR on socket", rv);
+
+    rv = apr_socket_opt_set(sock, APR_SO_FREEBIND, 1);
+    APR_ASSERT_SUCCESS(tc, "Could not enable FREEBIND option", rv);
+    
+    rv = apr_socket_opt_get(sock, APR_SO_FREEBIND, &on);
+    APR_ASSERT_SUCCESS(tc, "Could not retrieve FREEBIND option", rv);
+    ABTS_INT_EQUAL(tc, 1, on);
+    
+    rv = apr_socket_bind(sock, sa);
+    APR_ASSERT_SUCCESS(tc, "Problem binding to port with FREEBIND", rv);
+    
+    rv = apr_socket_close(sock);
+    APR_ASSERT_SUCCESS(tc, "Problem closing socket", rv);
+#endif
+}
+
+#define TEST_ZONE_ADDR "fe80::1"
+
+#ifdef __linux__
+/* Reasonable bet that "lo" will exist. */
+#define TEST_ZONE_NAME "lo"
+/* ... fill in other platforms here */
+#endif
+
+#ifdef TEST_ZONE_NAME 
+#define TEST_ZONE_FULLADDR TEST_ZONE_ADDR "%" TEST_ZONE_NAME
+#endif
+
+static void test_zone(abts_case *tc, void *data)
+{
+#if APR_HAVE_IPV6
+    apr_sockaddr_t *sa;
+    apr_status_t rv;
+    const char *name = NULL;
+    apr_uint32_t id = 0;
+    
+    rv = apr_sockaddr_info_get(&sa, "127.0.0.1", APR_INET, 8080, 0, p);
+    APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
+
+    /* Fail for an IPv4 address! */
+    ABTS_INT_EQUAL(tc, APR_EBADIP,
+                   apr_sockaddr_zone_set(sa, "1"));
+    ABTS_INT_EQUAL(tc, APR_EBADIP,
+                   apr_sockaddr_zone_get(sa, &name, &id, p));
+    
+    rv = apr_sockaddr_info_get(&sa, "::1", APR_INET6, 8080, 0, p);
+    APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
+
+    /* Fail for an address which isn't link-local */
+    ABTS_INT_EQUAL(tc, APR_EBADIP, apr_sockaddr_zone_set(sa, "1"));
+
+    rv = apr_sockaddr_info_get(&sa, TEST_ZONE_ADDR, APR_INET6, 8080, 0, p);
+    APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
+
+    ABTS_INT_EQUAL(tc, APR_EBADIP, apr_sockaddr_zone_get(sa, &name, &id, p));
+
+#ifdef TEST_ZONE_NAME
+    {
+        apr_sockaddr_t *sa2;
+        char buf[50];
+        
+        APR_ASSERT_SUCCESS(tc, "Set zone to " TEST_ZONE_NAME,
+                           apr_sockaddr_zone_set(sa, TEST_ZONE_NAME));
+        
+        APR_ASSERT_SUCCESS(tc, "Get zone",
+                           apr_sockaddr_zone_get(sa, NULL, NULL, p));
+        
+        APR_ASSERT_SUCCESS(tc, "Get zone",
+                           apr_sockaddr_zone_get(sa, &name, &id, p));
+        ABTS_STR_EQUAL(tc, TEST_ZONE_NAME, name);
+        ABTS_INT_NEQUAL(tc, 0, id); /* Only guarantee is that it should be non-zero */
+
+        /* Check string translation. */
+        APR_ASSERT_SUCCESS(tc, "get IP address",
+                           apr_sockaddr_ip_getbuf(buf, 50, sa));
+        ABTS_STR_EQUAL(tc, TEST_ZONE_FULLADDR, buf);
+
+        memset(buf, 'A', sizeof buf);
+        ABTS_INT_EQUAL(tc, APR_ENOSPC, apr_sockaddr_ip_getbuf(buf, strlen(TEST_ZONE_ADDR), sa));
+        ABTS_INT_EQUAL(tc, APR_ENOSPC, apr_sockaddr_ip_getbuf(buf, strlen(TEST_ZONE_FULLADDR), sa));
+        
+        APR_ASSERT_SUCCESS(tc, "get IP address",
+                           apr_sockaddr_ip_getbuf(buf, strlen(TEST_ZONE_FULLADDR) + 1, sa));
+        /* Check for overflow. */
+        ABTS_INT_EQUAL(tc, 'A', buf[strlen(buf) + 1]);
+        
+        rv = apr_sockaddr_info_copy(&sa2, sa, p);
+        APR_ASSERT_SUCCESS(tc, "Problem copying sockaddr", rv);
+
+        /* Copy copied zone matches */
+        APR_ASSERT_SUCCESS(tc, "Get zone",
+                           apr_sockaddr_zone_get(sa2, &name, &id, p));
+        ABTS_STR_EQUAL(tc, TEST_ZONE_NAME, name);
+        ABTS_INT_NEQUAL(tc, 0, id); /* Only guarantee is that it should be non-zero */
+
+        /* Should match self and copy */
+        ABTS_INT_NEQUAL(tc, 0, apr_sockaddr_equal(sa, sa));
+        ABTS_INT_NEQUAL(tc, 0, apr_sockaddr_equal(sa2, sa2));
+        ABTS_INT_NEQUAL(tc, 0, apr_sockaddr_equal(sa2, sa));
+
+        /* Should not match against copy without zone set. */
+        rv = apr_sockaddr_info_get(&sa2, TEST_ZONE_ADDR, APR_INET6, 8080, 0, p);
+        APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
+
+        ABTS_INT_EQUAL(tc, 0, apr_sockaddr_equal(sa2, sa));
+    }
+#endif /* TEST_ZONE_NAME */
+#endif /* APR_HAVE_IPV6 */
+}
+    
+abts_suite *testsock(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite)
+    socket_name = IPV4_SOCKET_NAME;
+    abts_run_test(suite, test_addr_info, NULL);
+    abts_run_test(suite, test_addr_copy, NULL);
+    abts_run_test(suite, test_serv_by_name, NULL);
+    abts_run_test(suite, test_create_bind_listen, NULL);
+    abts_run_test(suite, test_send, NULL);
+    abts_run_test(suite, test_recv, NULL);
+    abts_run_test(suite, test_atreadeof, NULL);
+    abts_run_test(suite, test_timeout, NULL);
+    abts_run_test(suite, test_print_addr, NULL);
+    abts_run_test(suite, test_get_addr, NULL);
+    abts_run_test(suite, test_wait, NULL);
+    abts_run_test(suite, test_nonblock_inheritance, NULL);
+    abts_run_test(suite, test_freebind, NULL);
+    abts_run_test(suite, test_zone, NULL);
+#if APR_HAVE_SOCKADDR_UN
+    socket_name = UNIX_SOCKET_NAME;
+    socket_type = APR_UNIX;
+    /* in case AF_UNIX socket exists from a previous run: */
+    apr_file_remove(socket_name, p);
+    abts_run_test(suite, test_create_bind_listen, NULL);
+    abts_run_test(suite, test_send, NULL);
+    abts_run_test(suite, test_recv, NULL);
+    abts_run_test(suite, test_timeout, NULL);
+    abts_run_test(suite, test_wait, NULL);
+#endif
+    return suite;
+}
+
diff --git a/test/testsock.dsp b/test/testsock.dsp
deleted file mode 100644
index ea18db0c7d9..00000000000
--- a/test/testsock.dsp
+++ /dev/null
@@ -1,91 +0,0 @@
-# Microsoft Developer Studio Project File - Name="testsock" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 5.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=testsock - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "testsock.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 "testsock.mak" CFG="testsock - Win32 Debug"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "testsock - Win32 Release" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE "testsock - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE 
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF  "$(CFG)" == "testsock - 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 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /W3 /GX /O2 /I "..\include" /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ..\Release\aprlib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"..\Release\testsock.exe"
-
-!ELSEIF  "$(CFG)" == "testsock - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "testsock"
-# PROP BASE Intermediate_Dir "testsock"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "testsock"
-# PROP Intermediate_Dir "testsock"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\include" /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
-# SUBTRACT CPP /YX /Yc /Yu
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 ..\Debug\aprlib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\Debug\testsock.exe" /pdbtype:sept
-
-!ENDIF 
-
-# Begin Target
-
-# Name "testsock - Win32 Release"
-# Name "testsock - Win32 Debug"
-# Begin Source File
-
-SOURCE=.\testsock.c
-# End Source File
-# End Target
-# End Project
diff --git a/test/testsock.h b/test/testsock.h
new file mode 100644
index 00000000000..12a44f76537
--- /dev/null
+++ b/test/testsock.h
@@ -0,0 +1,34 @@
+/* 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 TESTSOCK_H
+#define TESTSOCK_H
+
+#define DATASTR "This is a test"
+#define STRLEN 8092
+
+/* This is a hack.  We can't return APR_TIMEOUT from sockchild, because
+ * Unix OSes only return the least significant 8 bits of the return code,
+ * which means that instead of receiving 70007, testsock gets 119.  But,
+ * we also don't want to return -1, because we use that value for general
+ * errors from sockchild.  So, we define 1 to mean that the read/write
+ * operation timed out.  This means that we can't write a test that tries
+ * to send a single character between ends of the socket.
+ */
+#define SOCKET_TIMEOUT 1
+
+#endif
+
diff --git a/test/testsockets.c b/test/testsockets.c
new file mode 100644
index 00000000000..2a7499aa781
--- /dev/null
+++ b/test/testsockets.c
@@ -0,0 +1,238 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_network_io.h"
+#include "apr_errno.h"
+#include "apr_general.h"
+#include "apr_lib.h"
+#include "testutil.h"
+
+#define STRLEN 21
+
+static void tcp_socket(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_socket_t *sock = NULL;
+    int type;
+
+    rv = apr_socket_create(&sock, APR_INET, SOCK_STREAM, 0, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_PTR_NOTNULL(tc, sock);
+
+    rv = apr_socket_type_get(sock, &type);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_INT_EQUAL(tc, SOCK_STREAM, type);
+
+    apr_socket_close(sock);
+}
+
+static void udp_socket(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_socket_t *sock = NULL;
+    int type;
+
+    rv = apr_socket_create(&sock, APR_INET, SOCK_DGRAM, 0, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_PTR_NOTNULL(tc, sock);
+
+    rv = apr_socket_type_get(sock, &type);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_INT_EQUAL(tc, SOCK_DGRAM, type);
+
+    apr_socket_close(sock);
+}
+
+#if APR_HAVE_IPV6
+static void tcp6_socket(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_socket_t *sock = NULL;
+
+    rv = apr_socket_create(&sock, APR_INET6, SOCK_STREAM, 0, p);
+    if (APR_STATUS_IS_EAFNOSUPPORT(rv)) {
+        ABTS_NOT_IMPL(tc, "IPv6 not enabled");
+        return;
+    }
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_PTR_NOTNULL(tc, sock);
+    apr_socket_close(sock);
+}
+
+static void udp6_socket(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_socket_t *sock = NULL;
+
+    rv = apr_socket_create(&sock, APR_INET6, SOCK_DGRAM, 0, p);
+    if (APR_STATUS_IS_EAFNOSUPPORT(rv)) {
+        ABTS_NOT_IMPL(tc, "IPv6 not enabled");
+        return;
+    }
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_PTR_NOTNULL(tc, sock);
+    apr_socket_close(sock);
+}
+#endif
+
+static void sendto_receivefrom_helper(abts_case *tc, const char *addr,
+                                      int family)
+{
+    apr_status_t rv;
+    apr_socket_t *sock = NULL;
+    apr_socket_t *sock2 = NULL;
+    char sendbuf[STRLEN] = "APR_INET, SOCK_DGRAM";
+    char recvbuf[80];
+    char *ip_addr;
+    apr_port_t fromport;
+    apr_sockaddr_t *from;
+    apr_sockaddr_t *to;
+    apr_size_t len = 30;
+
+    rv = apr_socket_create(&sock, family, SOCK_DGRAM, 0, p);
+#if APR_HAVE_IPV6
+    if ((family == APR_INET6) && APR_STATUS_IS_EAFNOSUPPORT(rv)) {
+        ABTS_NOT_IMPL(tc, "IPv6 not enabled");
+        return;
+    }
+#endif
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    if (rv != APR_SUCCESS)
+        return;
+    rv = apr_socket_create(&sock2, family, SOCK_DGRAM, 0, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    if (rv != APR_SUCCESS)
+        return;
+
+    rv = apr_sockaddr_info_get(&to, addr, family, 7772, 0, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    rv = apr_sockaddr_info_get(&from, addr, family, 7771, 0, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_socket_opt_set(sock, APR_SO_REUSEADDR, 1);
+    APR_ASSERT_SUCCESS(tc, "Could not set REUSEADDR on socket", rv);
+    rv = apr_socket_opt_set(sock2, APR_SO_REUSEADDR, 1);
+    APR_ASSERT_SUCCESS(tc, "Could not set REUSEADDR on socket2", rv);
+
+    rv = apr_socket_bind(sock, to);
+    APR_ASSERT_SUCCESS(tc, "Could not bind socket", rv);
+    if (rv != APR_SUCCESS)
+        return;
+    rv = apr_mcast_hops(sock, 10);
+    APR_ASSERT_SUCCESS(tc, "Could not set multicast hops", rv);
+    if (rv != APR_SUCCESS)
+        return;
+
+    rv = apr_socket_bind(sock2, from);
+    APR_ASSERT_SUCCESS(tc, "Could not bind second socket", rv);
+    if (rv != APR_SUCCESS)
+        return;
+
+    len = STRLEN;
+    rv = apr_socket_sendto(sock2, to, 0, sendbuf, &len);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_SIZE_EQUAL(tc, STRLEN, len);
+
+    /* fill the "from" sockaddr with a random address from another
+     * family to ensure that recvfrom sets it up properly. */
+#if APR_HAVE_IPV6
+    if (family == APR_INET)
+        rv = apr_sockaddr_info_get(&from, "3ffE:816e:abcd:1234::1",
+                                   APR_INET6, 4242, 0, p);
+    else
+#endif
+        rv = apr_sockaddr_info_get(&from, "127.1.2.3", APR_INET, 4242, 0, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    len = 80;
+    rv = apr_socket_recvfrom(from, sock, 0, recvbuf, &len);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_SIZE_EQUAL(tc, STRLEN, len);
+    ABTS_STR_EQUAL(tc, "APR_INET, SOCK_DGRAM", recvbuf);
+
+    apr_sockaddr_ip_get(&ip_addr, from);
+    fromport = from->port;
+    ABTS_STR_EQUAL(tc, addr, ip_addr);
+    ABTS_INT_EQUAL(tc, 7771, fromport);
+
+    apr_socket_close(sock);
+    apr_socket_close(sock2);
+}
+
+static void sendto_receivefrom(abts_case *tc, void *data)
+{
+    int failed;
+    sendto_receivefrom_helper(tc, "127.0.0.1", APR_INET);
+    failed = tc->failed; tc->failed = 0;
+    ABTS_TRUE(tc, !failed);
+}
+
+#if APR_HAVE_IPV6
+static void sendto_receivefrom6(abts_case *tc, void *data)
+{
+    int failed;
+    sendto_receivefrom_helper(tc, "::1", APR_INET6);
+    failed = tc->failed; tc->failed = 0;
+    ABTS_TRUE(tc, !failed);
+}
+#endif
+
+static void socket_userdata(abts_case *tc, void *data)
+{
+    apr_socket_t *sock1, *sock2;
+    apr_status_t rv;
+    void *user;
+    const char *key = "GENERICKEY";
+
+    rv = apr_socket_create(&sock1, AF_INET, SOCK_STREAM, 0, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    rv = apr_socket_create(&sock2, AF_INET, SOCK_STREAM, 0, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_socket_data_set(sock1, "SOCK1", key, NULL);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    rv = apr_socket_data_set(sock2, "SOCK2", key, NULL);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_socket_data_get(&user, key, sock1);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_STR_EQUAL(tc, "SOCK1", user);
+    rv = apr_socket_data_get(&user, key, sock2);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_STR_EQUAL(tc, "SOCK2", user);
+}
+
+abts_suite *testsockets(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite)
+
+    abts_run_test(suite, tcp_socket, NULL);
+    abts_run_test(suite, udp_socket, NULL);
+
+    abts_run_test(suite, sendto_receivefrom, NULL);
+
+#if APR_HAVE_IPV6
+    abts_run_test(suite, tcp6_socket, NULL);
+    abts_run_test(suite, udp6_socket, NULL);
+
+    abts_run_test(suite, sendto_receivefrom6, NULL);
+#endif
+
+    abts_run_test(suite, socket_userdata, NULL);
+    
+    return suite;
+}
+
diff --git a/test/testsockopt.c b/test/testsockopt.c
new file mode 100644
index 00000000000..203e2c39ff7
--- /dev/null
+++ b/test/testsockopt.c
@@ -0,0 +1,139 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_network_io.h"
+#include "apr_errno.h"
+#include "apr_general.h"
+#include "apr_lib.h"
+#include "testutil.h"
+
+static apr_socket_t *sock = NULL;
+
+static void create_socket(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+
+    rv = apr_socket_create(&sock, APR_INET, SOCK_STREAM, 0, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_PTR_NOTNULL(tc, sock);
+}
+
+static void set_keepalive(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_int32_t ck;
+
+    rv = apr_socket_opt_set(sock, APR_SO_KEEPALIVE, 1);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_socket_opt_get(sock, APR_SO_KEEPALIVE, &ck);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_INT_EQUAL(tc, 1, ck);
+}
+
+static void set_debug(abts_case *tc, void *data)
+{
+    apr_status_t rv1, rv2;
+    apr_int32_t ck;
+    
+    /* On some platforms APR_SO_DEBUG can only be set as root; just test
+     * for get/set consistency of this option. */
+    rv1 = apr_socket_opt_set(sock, APR_SO_DEBUG, 1);
+    rv2 = apr_socket_opt_get(sock, APR_SO_DEBUG, &ck);
+    APR_ASSERT_SUCCESS(tc, "get SO_DEBUG option", rv2);
+    if (rv1 == APR_SUCCESS) {
+        ABTS_INT_EQUAL(tc, 1, ck);
+    } else {
+        ABTS_INT_EQUAL(tc, 0, ck);
+    }
+}
+
+static void remove_keepalive(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_int32_t ck;
+
+    rv = apr_socket_opt_get(sock, APR_SO_KEEPALIVE, &ck);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_INT_EQUAL(tc, 1, ck);
+
+    rv = apr_socket_opt_set(sock, APR_SO_KEEPALIVE, 0);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_socket_opt_get(sock, APR_SO_KEEPALIVE, &ck);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_INT_EQUAL(tc, 0, ck);
+}
+
+static void corkable(abts_case *tc, void *data)
+{
+#if !APR_HAVE_CORKABLE_TCP
+    ABTS_NOT_IMPL(tc, "TCP isn't corkable");
+#else
+    apr_status_t rv;
+    apr_int32_t ck;
+
+    rv = apr_socket_opt_set(sock, APR_TCP_NODELAY, 1);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_socket_opt_get(sock, APR_TCP_NODELAY, &ck);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_INT_EQUAL(tc, 1, ck);
+
+    rv = apr_socket_opt_set(sock, APR_TCP_NOPUSH, 1);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_socket_opt_get(sock, APR_TCP_NOPUSH, &ck);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_INT_EQUAL(tc, 1, ck);
+
+    rv = apr_socket_opt_get(sock, APR_TCP_NODELAY, &ck);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    /* TCP_NODELAY is now in an unknown state; it may be zero if
+     * TCP_NOPUSH and TCP_NODELAY are mutually exclusive on this
+     * platform, e.g. Linux < 2.6. */
+
+    rv = apr_socket_opt_set(sock, APR_TCP_NOPUSH, 0);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    
+    rv = apr_socket_opt_get(sock, APR_TCP_NODELAY, &ck);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_INT_EQUAL(tc, 1, ck);
+#endif
+}
+
+static void close_socket(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+
+    rv = apr_socket_close(sock);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+}
+
+abts_suite *testsockopt(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite)
+
+    abts_run_test(suite, create_socket, NULL);
+    abts_run_test(suite, set_keepalive, NULL);
+    abts_run_test(suite, set_debug, NULL);
+    abts_run_test(suite, remove_keepalive, NULL);
+    abts_run_test(suite, corkable, NULL);
+    abts_run_test(suite, close_socket, NULL);
+
+    return suite;
+}
+
diff --git a/test/teststr.c b/test/teststr.c
new file mode 100644
index 00000000000..d9a5054758a
--- /dev/null
+++ b/test/teststr.c
@@ -0,0 +1,418 @@
+/* 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 "testutil.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#if APR_HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#include "apr_general.h"
+#include "apr_strings.h"
+#include "apr_cstr.h"
+#include "apr_errno.h"
+
+/* I haven't bothered to check for APR_ENOTIMPL here, AFAIK, all string
+ * functions exist on all platforms.
+ */
+
+static void test_strtok(abts_case *tc, void *data)
+{
+    struct {
+        char *input;
+        char *sep;
+    }
+    cases[] = {
+        {
+            "",
+            "Z"
+        },
+        {
+            "      asdf jkl; 77889909            \r\n\1\2\3Z",
+            " \r\n\3\2\1"
+        },
+        {
+            NULL,  /* but who cares if apr_strtok() segfaults? */
+            " \t"
+        },
+#if 0     /* don't do this... you deserve to segfault */
+        {
+            "a b c              ",
+            NULL
+        },
+#endif
+        {
+            "   a       b        c   ",
+            ""
+        },
+        {
+            "a              b c         ",
+            " "
+        }
+    };
+    int curtc;
+
+    for (curtc = 0; curtc < sizeof cases / sizeof cases[0]; curtc++) {
+        char *retval1, *retval2;
+        char *str1, *str2;
+        char *state;
+
+        str1 = apr_pstrdup(p, cases[curtc].input);
+        str2 = apr_pstrdup(p, cases[curtc].input);
+
+        do {
+            retval1 = apr_strtok(str1, cases[curtc].sep, &state);
+            retval2 = strtok(str2, cases[curtc].sep);
+
+            if (!retval1) {
+                ABTS_TRUE(tc, retval2 == NULL);
+            }
+            else {
+                ABTS_TRUE(tc, retval2 != NULL);
+                ABTS_STR_EQUAL(tc, retval2, retval1);
+            }
+
+            str1 = str2 = NULL; /* make sure we pass NULL on subsequent calls */
+        } while (retval1);
+    }
+}
+
+static void snprintf_noNULL(abts_case *tc, void *data)
+{
+    char buff[100];
+    char *testing = apr_palloc(p, 10);
+
+    testing[0] = 't';
+    testing[1] = 'e';
+    testing[2] = 's';
+    testing[3] = 't';
+    testing[4] = 'i';
+    testing[5] = 'n';
+    testing[6] = 'g';
+    
+    /* If this test fails, we are going to seg fault. */
+    apr_snprintf(buff, sizeof(buff), "%.*s", 7, testing);
+    ABTS_STR_NEQUAL(tc, buff, testing, 7);
+}
+
+static void snprintf_0NULL(abts_case *tc, void *data)
+{
+    int rv;
+
+    rv = apr_snprintf(NULL, 0, "%sBAR", "FOO");
+    ABTS_INT_EQUAL(tc, 6, rv);
+}
+
+static void snprintf_0nonNULL(abts_case *tc, void *data)
+{
+    int rv;
+    char *buff = "testing";
+
+    rv = apr_snprintf(buff, 0, "%sBAR", "FOO");
+    ABTS_INT_EQUAL(tc, 6, rv);
+    ABTS_ASSERT(tc, "buff unmangled", strcmp(buff, "FOOBAR") != 0);
+}
+
+static void snprintf_underflow(abts_case *tc, void *data)
+{
+    char buf[20];
+    int rv;
+
+    rv = apr_snprintf(buf, sizeof buf, "%.2f", (double)0.0001);
+    ABTS_INT_EQUAL(tc, 4, rv);
+    ABTS_STR_EQUAL(tc, "0.00", buf);
+    
+    rv = apr_snprintf(buf, sizeof buf, "%.2f", (double)0.001);
+    ABTS_INT_EQUAL(tc, 4, rv);
+    ABTS_STR_EQUAL(tc, "0.00", buf);
+    
+    rv = apr_snprintf(buf, sizeof buf, "%.2f", (double)0.01);
+    ABTS_INT_EQUAL(tc, 4, rv);
+    ABTS_STR_EQUAL(tc, "0.01", buf);
+}
+
+static void string_error(abts_case *tc, void *data)
+{
+     char buf[128], *rv;
+     apr_status_t n;
+
+     buf[0] = '\0';
+     rv = apr_strerror(APR_ENOENT, buf, sizeof buf);
+     ABTS_PTR_EQUAL(tc, buf, rv);
+     ABTS_TRUE(tc, strlen(buf) > 0);
+
+     rv = apr_strerror(APR_TIMEUP, buf, sizeof buf);
+     ABTS_PTR_EQUAL(tc, buf, rv);
+     ABTS_STR_EQUAL(tc, "The timeout specified has expired", buf);
+     
+     /* throw some randomish numbers at it to check for robustness */
+     for (n = 1; n < 1000000; n *= 2) {
+         apr_strerror(n, buf, sizeof buf);
+     }
+}
+
+#define SIZE 180000
+static void string_long(abts_case *tc, void *data)
+{
+    char s[SIZE + 1];
+
+    memset(s, 'A', SIZE);
+    s[SIZE] = '\0';
+
+    apr_psprintf(p, "%s", s);
+}
+
+/* ### FIXME: apr.h/apr_strings.h should provide these! */
+#define MY_LLONG_MAX (APR_INT64_C(9223372036854775807))
+#define MY_LLONG_MIN (-MY_LLONG_MAX - APR_INT64_C(1))
+
+static void string_strtoi64(abts_case *tc, void *data)
+{
+    static const struct {
+        int errnum, base;
+        const char *in, *end;
+        apr_int64_t result;
+    } ts[] = {
+        
+        /* base 10 tests */
+        { 0, 10, "123545", NULL, APR_INT64_C(123545) },
+        { 0, 10, "   123545", NULL, APR_INT64_C(123545) },
+        { 0, 10, "   +123545", NULL, APR_INT64_C(123545) },
+        { 0, 10, "-123545", NULL, APR_INT64_C(-123545) },
+        { 0, 10, "   00000123545", NULL, APR_INT64_C(123545) },
+        { 0, 10, "123545ZZZ", "ZZZ", APR_INT64_C(123545) },
+        { 0, 10, "   123545   ", "   ", APR_INT64_C(123545) },
+
+        /* base 16 tests */
+        { 0, 16, "1E299", NULL, APR_INT64_C(123545) },
+        { 0, 16, "1e299", NULL, APR_INT64_C(123545) },
+        { 0, 16, "0x1e299", NULL, APR_INT64_C(123545) },
+        { 0, 16, "0X1E299", NULL, APR_INT64_C(123545) },
+        { 0, 16, "+1e299", NULL, APR_INT64_C(123545) },
+        { 0, 16, "-1e299", NULL, APR_INT64_C(-123545) },
+        { 0, 16, "   -1e299", NULL, APR_INT64_C(-123545) },
+
+        /* automatic base detection tests */
+        { 0, 0, "123545", NULL, APR_INT64_C(123545) },
+        { 0, 0, "0x1e299", NULL, APR_INT64_C(123545) },
+        { 0, 0, "  0x1e299", NULL, APR_INT64_C(123545) },
+        { 0, 0, "+0x1e299", NULL, APR_INT64_C(123545) },
+        { 0, 0, "-0x1e299", NULL, APR_INT64_C(-123545) },
+
+        /* large number tests */
+        { 0, 10, "8589934605", NULL, APR_INT64_C(8589934605) },
+        { 0, 10, "-8589934605", NULL, APR_INT64_C(-8589934605) },
+        { 0, 16, "0x20000000D", NULL, APR_INT64_C(8589934605) },
+        { 0, 16, "-0x20000000D", NULL, APR_INT64_C(-8589934605) },
+        { 0, 16, "   0x20000000D", NULL, APR_INT64_C(8589934605) },
+        { 0, 16, "   0x20000000D", NULL, APR_INT64_C(8589934605) },
+
+        /* error cases */
+        { ERANGE, 10, "999999999999999999999999999999999", "", MY_LLONG_MAX },
+        { ERANGE, 10, "-999999999999999999999999999999999", "", MY_LLONG_MIN },
+
+#if 0
+        /* C99 doesn't require EINVAL for an invalid range. */
+        { EINVAL, 99, "", (void *)-1 /* don't care */, 0 },
+#endif
+
+        /* some strtoll implementations give EINVAL when no conversion
+         * is performed. */
+        { -1 /* don't care */, 10, "zzz", "zzz", APR_INT64_C(0) },
+        { -1 /* don't care */, 10, "", NULL, APR_INT64_C(0) }
+
+    };
+    int n;
+
+    for (n = 0; n < sizeof(ts)/sizeof(ts[0]); n++) {
+        char *end = "end ptr not changed";
+        apr_int64_t result;
+        int errnum;
+        
+        errno = 0;
+        result = apr_strtoi64(ts[n].in, &end, ts[n].base);
+        errnum = errno;
+
+        ABTS_ASSERT(tc,
+                 apr_psprintf(p, "for '%s': result was %" APR_INT64_T_FMT 
+                              " not %" APR_INT64_T_FMT, ts[n].in,
+                              result, ts[n].result),
+                 result == ts[n].result);
+        
+        if (ts[n].errnum != -1) {
+            ABTS_ASSERT(tc,
+                     apr_psprintf(p, "for '%s': errno was %d not %d", ts[n].in,
+                                  errnum, ts[n].errnum),
+                     ts[n].errnum == errnum);
+        }
+
+        if (ts[n].end == NULL) {
+            /* end must point to NUL terminator of .in */
+            ABTS_PTR_EQUAL(tc, ts[n].in + strlen(ts[n].in), end);
+        } else if (ts[n].end != (void *)-1) {
+            ABTS_ASSERT(tc,
+                     apr_psprintf(p, "for '%s', end was '%s' not '%s'",
+                                  ts[n].in, end, ts[n].end),
+                     strcmp(ts[n].end, end) == 0);
+        }
+    }
+}
+
+static void string_strtoff(abts_case *tc, void *data)
+{
+    apr_off_t off;
+
+    ABTS_ASSERT(tc, "strtoff fails on out-of-range integer",
+                apr_strtoff(&off, "999999999999999999999999999999",
+                            NULL, 10) != APR_SUCCESS);
+
+    ABTS_ASSERT(tc, "strtoff failed for 1234",
+                apr_strtoff(&off, "1234", NULL, 10) == APR_SUCCESS);
+
+    ABTS_ASSERT(tc, "strtoff failed to parse 1234", off == 1234);
+}
+
+/* random-ish checks for strfsize buffer overflows */
+static void overflow_strfsize(abts_case *tc, void *data)
+{
+    apr_off_t off;
+    char buf[7];
+
+    buf[5] = '$';
+    buf[6] = '@';
+
+    for (off = -9999; off < 20000; off++) {
+        apr_strfsize(off, buf);
+    }
+    for (; off < 9999999; off += 9) {
+        apr_strfsize(off, buf);
+    }
+    for (; off < 999999999; off += 999) {
+        apr_strfsize(off, buf);
+    }
+    for (off = 1; off < LONG_MAX && off > 0; off *= 2) {
+        apr_strfsize(off, buf);
+        apr_strfsize(off + 1, buf);
+        apr_strfsize(off - 1, buf);
+    }
+
+    ABTS_ASSERT(tc, "strfsize overflowed", buf[5] == '$');
+    ABTS_ASSERT(tc, "strfsize overflowed", buf[6] == '@');
+}
+
+static void string_strfsize(abts_case *tc, void *data)
+{
+    static const struct {
+        apr_off_t size;
+        const char *buf;
+    } ts[] = {
+        { -1,   "  - " },
+        { 0,    "  0 " },
+        { 666,  "666 " },
+        { 1024, "1.0K" },
+        { 1536, "1.5K" },
+        { 2048, "2.0K" },
+        { 1293874, "1.2M" },
+        { 9999999, "9.5M" },
+        { 103809024, " 99M" },
+        { 1047527424, "1.0G" } /* "999M" would be more correct */
+    };
+    apr_size_t n;
+
+    for (n = 0; n < sizeof(ts)/sizeof(ts[0]); n++) {
+        char buf[6], *ret;
+        
+        buf[5] = '%';
+
+        ret = apr_strfsize(ts[n].size, buf);
+        ABTS_ASSERT(tc, "strfsize returned wrong buffer", ret == buf);
+        ABTS_ASSERT(tc, "strfsize overflowed", buf[5] == '%');
+
+        ABTS_STR_EQUAL(tc, ts[n].buf, ret);
+    }
+}
+
+static void string_cpystrn(abts_case *tc, void *data)
+{
+    char buf[6], *ret;
+    
+    buf[5] = 'Z';
+
+    ret = apr_cpystrn(buf, "123456", 5);
+
+    ABTS_STR_EQUAL(tc, "1234", buf);
+    ABTS_PTR_EQUAL(tc, buf + 4, ret);
+    ABTS_TRUE(tc, *ret == '\0');
+    ABTS_TRUE(tc, ret[1] == 'Z');
+}
+
+static void snprintf_overflow(abts_case *tc, void *data)
+{
+    char buf[4];
+    int rv;
+    
+    buf[2] = '4';
+    buf[3] = '2';
+
+    rv = apr_snprintf(buf, 2, "%s", "a");
+    ABTS_INT_EQUAL(tc, 1, rv);
+
+    rv = apr_snprintf(buf, 2, "%s", "abcd");
+    ABTS_INT_EQUAL(tc, 1, rv);
+
+    ABTS_STR_EQUAL(tc, "a", buf);
+
+    /* Check the buffer really hasn't been overflowed. */
+    ABTS_TRUE(tc, buf[2] == '4' && buf[3] == '2');
+}
+
+static void skip_prefix(abts_case *tc, void *data)
+{
+    ABTS_STR_EQUAL(tc, apr_cstr_skip_prefix("12345", "12345"), "");
+    ABTS_STR_EQUAL(tc, apr_cstr_skip_prefix("12345", "123"),   "45");
+    ABTS_STR_EQUAL(tc, apr_cstr_skip_prefix("12345", ""),      "12345");
+    ABTS_STR_EQUAL(tc, apr_cstr_skip_prefix("12345", "23"),    NULL);
+    ABTS_STR_EQUAL(tc, apr_cstr_skip_prefix("1",     "12"),    NULL);
+    ABTS_STR_EQUAL(tc, apr_cstr_skip_prefix("",      ""),      "");
+    ABTS_STR_EQUAL(tc, apr_cstr_skip_prefix("",      "12"),    NULL);
+}
+
+abts_suite *teststr(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite)
+
+    abts_run_test(suite, snprintf_0NULL, NULL);
+    abts_run_test(suite, snprintf_0nonNULL, NULL);
+    abts_run_test(suite, snprintf_noNULL, NULL);
+    abts_run_test(suite, snprintf_underflow, NULL);
+    abts_run_test(suite, test_strtok, NULL);
+    abts_run_test(suite, string_error, NULL);
+    abts_run_test(suite, string_long, NULL);
+    abts_run_test(suite, string_strtoi64, NULL);
+    abts_run_test(suite, string_strtoff, NULL);
+    abts_run_test(suite, overflow_strfsize, NULL);
+    abts_run_test(suite, string_strfsize, NULL);
+    abts_run_test(suite, string_cpystrn, NULL);
+    abts_run_test(suite, snprintf_overflow, NULL);
+    abts_run_test(suite, skip_prefix, NULL);
+
+    return suite;
+}
+
diff --git a/test/teststrmatch.c b/test/teststrmatch.c
new file mode 100644
index 00000000000..b6a4a12267f
--- /dev/null
+++ b/test/teststrmatch.c
@@ -0,0 +1,92 @@
+/* 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 "testutil.h"
+
+#include "apr.h"
+#include "apr_general.h"
+#include "apr_strmatch.h"
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#define APR_WANT_STDIO
+#define APR_WANT_STRFUNC
+#include "apr_want.h"
+
+static void test_str(abts_case *tc, void *data)
+{
+    apr_pool_t *pool = p;
+    const apr_strmatch_pattern *pattern;
+    const apr_strmatch_pattern *pattern_nocase;
+    const apr_strmatch_pattern *pattern_onechar;
+    const apr_strmatch_pattern *pattern_zero;
+    const char *match = NULL;
+    const char *input1 = "string that contains a patterN...";
+    const char *input2 = "string that contains a pattern...";
+    const char *input3 = "pattern at the start of a string";
+    const char *input4 = "string that ends with a pattern";
+    const char *input5 = "patter\200n not found, negative chars in input";
+    const char *input6 = "patter\200n, negative chars, contains pattern...";
+
+    pattern = apr_strmatch_precompile(pool, "pattern", 1);
+    ABTS_PTR_NOTNULL(tc, pattern);
+ 
+    pattern_nocase = apr_strmatch_precompile(pool, "pattern", 0);
+    ABTS_PTR_NOTNULL(tc, pattern_nocase);
+
+    pattern_onechar = apr_strmatch_precompile(pool, "g", 0);
+    ABTS_PTR_NOTNULL(tc, pattern_onechar);
+
+    pattern_zero = apr_strmatch_precompile(pool, "", 0);
+    ABTS_PTR_NOTNULL(tc, pattern_zero);
+
+    match = apr_strmatch(pattern, input1, strlen(input1));
+    ABTS_PTR_EQUAL(tc, NULL, match);
+
+    match = apr_strmatch(pattern, input2, strlen(input2));
+    ABTS_PTR_EQUAL(tc, input2 + 23, match);
+
+    match = apr_strmatch(pattern_onechar, input1, strlen(input1));
+    ABTS_PTR_EQUAL(tc, input1 + 5, match);
+
+    match = apr_strmatch(pattern_zero, input1, strlen(input1));
+    ABTS_PTR_EQUAL(tc, input1, match);
+
+    match = apr_strmatch(pattern_nocase, input1, strlen(input1));
+    ABTS_PTR_EQUAL(tc, input1 + 23, match);
+
+    match = apr_strmatch(pattern, input3, strlen(input3));
+    ABTS_PTR_EQUAL(tc, input3, match);
+
+    match = apr_strmatch(pattern, input4, strlen(input4));
+    ABTS_PTR_EQUAL(tc, input4 + 24, match);
+
+    match = apr_strmatch(pattern, input5, strlen(input5));
+    ABTS_PTR_EQUAL(tc, NULL, match);
+
+    match = apr_strmatch(pattern, input6, strlen(input6));
+    ABTS_PTR_EQUAL(tc, input6 + 35, match);
+}
+
+abts_suite *teststrmatch(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite);
+
+    abts_run_test(suite, test_str, NULL);
+
+    return suite;
+}
+
diff --git a/test/teststrnatcmp.c b/test/teststrnatcmp.c
new file mode 100644
index 00000000000..3a5e4c67ba7
--- /dev/null
+++ b/test/teststrnatcmp.c
@@ -0,0 +1,78 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_file_io.h"
+#include "apr_errno.h"
+#include "apr_strings.h"
+#include "testutil.h"
+
+static void less0(abts_case *tc, void *data)
+{
+    int rv = apr_strnatcmp("a", "b");
+    ABTS_ASSERT(tc, "didn't compare simple strings properly", rv < 0);
+}
+
+static void str_equal(abts_case *tc, void *data)
+{
+    int rv = apr_strnatcmp("a", "a");
+    ABTS_ASSERT(tc, "didn't compare simple strings properly", rv == 0);
+}
+
+static void more0(abts_case *tc, void *data)
+{
+    int rv = apr_strnatcmp("b", "a");
+    ABTS_ASSERT(tc, "didn't compare simple strings properly", rv > 0);
+}
+
+static void less_ignore_case(abts_case *tc, void *data)
+{
+    int rv = apr_strnatcasecmp("a", "B");
+    ABTS_ASSERT(tc, "didn't compare simple strings properly", rv < 0);
+}
+
+static void str_equal_ignore_case(abts_case *tc, void *data)
+{
+    int rv = apr_strnatcasecmp("a", "A");
+    ABTS_ASSERT(tc, "didn't compare simple strings properly", rv == 0);
+}
+
+static void more_ignore_case(abts_case *tc, void *data)
+{
+    int rv = apr_strnatcasecmp("b", "A");
+    ABTS_ASSERT(tc, "didn't compare simple strings properly", rv > 0);
+}
+
+static void natcmp(abts_case *tc, void *data)
+{
+    int rv = apr_strnatcasecmp("a2", "a10");
+    ABTS_ASSERT(tc, "didn't compare simple strings properly", rv < 0);
+}
+
+abts_suite *teststrnatcmp(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite)
+
+    abts_run_test(suite, less0, NULL);
+    abts_run_test(suite, str_equal, NULL);
+    abts_run_test(suite, more0, NULL);
+    abts_run_test(suite, less_ignore_case, NULL);
+    abts_run_test(suite, str_equal_ignore_case, NULL);
+    abts_run_test(suite, more_ignore_case, NULL);
+    abts_run_test(suite, natcmp, NULL);
+
+    return suite;
+}
+
diff --git a/test/testtable.c b/test/testtable.c
new file mode 100644
index 00000000000..0a9960f12c8
--- /dev/null
+++ b/test/testtable.c
@@ -0,0 +1,245 @@
+/* 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 "testutil.h"
+#include "apr.h"
+#include "apr_strings.h"
+#include "apr_general.h"
+#include "apr_pools.h"
+#include "apr_tables.h"
+#if APR_HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if APR_HAVE_STRING_H
+#include <string.h>
+#endif
+
+static apr_array_header_t *a1 = NULL;
+static apr_table_t *t1 = NULL;
+
+static void array_clear(abts_case *tc, void *data)
+{
+    a1 = apr_array_make(p, 2, sizeof(const char *));
+    APR_ARRAY_PUSH(a1, const char *) = "foo";
+    APR_ARRAY_PUSH(a1, const char *) = "bar";
+    apr_array_clear(a1);
+    ABTS_INT_EQUAL(tc, 0, a1->nelts);
+}
+
+static void table_make(abts_case *tc, void *data)
+{
+    t1 = apr_table_make(p, 5);
+    ABTS_PTR_NOTNULL(tc, t1);
+}
+
+static void table_get(abts_case *tc, void *data)
+{
+    const char *val;
+
+    apr_table_set(t1, "foo", "bar");
+    val = apr_table_get(t1, "foo");
+    ABTS_STR_EQUAL(tc, "bar", val);
+}
+
+static void table_getm(abts_case *tc, void *data)
+{
+    const char *orig, *val;
+    apr_pool_t *subp;
+
+    apr_pool_create(&subp, p);
+
+    orig = "bar";
+    apr_table_setn(t1, "foo", orig);
+    val = apr_table_getm(subp, t1, "foo");
+    ABTS_PTR_EQUAL(tc, orig, val);
+    ABTS_STR_EQUAL(tc, "bar", val);
+    apr_table_add(t1, "foo", "baz");
+    val = apr_table_getm(subp, t1, "foo");
+    ABTS_STR_EQUAL(tc, "bar,baz", val);
+
+    apr_pool_destroy(subp);
+}
+
+static void table_set(abts_case *tc, void *data)
+{
+    const char *val;
+
+    apr_table_set(t1, "setkey", "bar");
+    apr_table_set(t1, "setkey", "2ndtry");
+    val = apr_table_get(t1, "setkey");
+    ABTS_STR_EQUAL(tc, "2ndtry", val);
+}
+
+static void table_getnotthere(abts_case *tc, void *data)
+{
+    const char *val;
+
+    val = apr_table_get(t1, "keynotthere");
+    ABTS_PTR_EQUAL(tc, NULL, (void *)val);
+}
+
+static void table_add(abts_case *tc, void *data)
+{
+    const char *val;
+
+    apr_table_add(t1, "addkey", "bar");
+    apr_table_add(t1, "addkey", "foo");
+    val = apr_table_get(t1, "addkey");
+    ABTS_STR_EQUAL(tc, "bar", val);
+
+}
+
+static void table_nelts(abts_case *tc, void *data)
+{
+    const char *val;
+    apr_table_t *t = apr_table_make(p, 1);
+
+    apr_table_set(t, "abc", "def");
+    apr_table_set(t, "def", "abc");
+    apr_table_set(t, "foo", "zzz");
+    val = apr_table_get(t, "foo");
+    ABTS_STR_EQUAL(tc, "zzz", val);
+    val = apr_table_get(t, "abc");
+    ABTS_STR_EQUAL(tc, "def", val);
+    val = apr_table_get(t, "def");
+    ABTS_STR_EQUAL(tc, "abc", val);
+    ABTS_INT_EQUAL(tc, 3, apr_table_elts(t)->nelts);
+}
+
+static void table_clear(abts_case *tc, void *data)
+{
+    apr_table_clear(t1);
+    ABTS_INT_EQUAL(tc, 0, apr_table_elts(t1)->nelts);
+}
+
+static void table_unset(abts_case *tc, void *data)
+{
+    const char *val;
+    apr_table_t *t = apr_table_make(p, 1);
+
+    apr_table_set(t, "a", "1");
+    apr_table_set(t, "b", "2");
+    apr_table_unset(t, "b");
+    ABTS_INT_EQUAL(tc, 1, apr_table_elts(t)->nelts);
+    val = apr_table_get(t, "a");
+    ABTS_STR_EQUAL(tc, "1", val);
+    val = apr_table_get(t, "b");
+    ABTS_PTR_EQUAL(tc, (void *)NULL, (void *)val);
+}
+
+static void table_overlap(abts_case *tc, void *data)
+{
+    const char *val;
+    apr_table_t *t1 = apr_table_make(p, 1);
+    apr_table_t *t2 = apr_table_make(p, 1);
+
+    apr_table_addn(t1, "a", "0");
+    apr_table_addn(t1, "g", "7");
+    apr_table_addn(t2, "a", "1");
+    apr_table_addn(t2, "b", "2");
+    apr_table_addn(t2, "c", "3");
+    apr_table_addn(t2, "b", "2.0");
+    apr_table_addn(t2, "d", "4");
+    apr_table_addn(t2, "e", "5");
+    apr_table_addn(t2, "b", "2.");
+    apr_table_addn(t2, "f", "6");
+    apr_table_overlap(t1, t2, APR_OVERLAP_TABLES_SET);
+    
+    ABTS_INT_EQUAL(tc, 7, apr_table_elts(t1)->nelts);
+    val = apr_table_get(t1, "a");
+    ABTS_STR_EQUAL(tc, "1", val);
+    val = apr_table_get(t1, "b");
+    ABTS_STR_EQUAL(tc, "2.", val);
+    val = apr_table_get(t1, "c");
+    ABTS_STR_EQUAL(tc, "3", val);
+    val = apr_table_get(t1, "d");
+    ABTS_STR_EQUAL(tc, "4", val);
+    val = apr_table_get(t1, "e");
+    ABTS_STR_EQUAL(tc, "5", val);
+    val = apr_table_get(t1, "f");
+    ABTS_STR_EQUAL(tc, "6", val);
+    val = apr_table_get(t1, "g");
+    ABTS_STR_EQUAL(tc, "7", val);
+}
+
+static void table_overlap2(abts_case *tc, void *data)
+{
+    apr_pool_t *subp;
+    apr_table_t *t1, *t2;
+
+    apr_pool_create(&subp, p);
+
+    t1 = apr_table_make(subp, 1);
+    t2 = apr_table_make(p, 1);
+    apr_table_addn(t1, "t1", "one");
+    apr_table_addn(t2, "t2", "two");
+    
+    apr_table_overlap(t1, t2, APR_OVERLAP_TABLES_SET);
+    
+    ABTS_INT_EQUAL(tc, 2, apr_table_elts(t1)->nelts);
+    
+    ABTS_STR_EQUAL(tc, "one", apr_table_get(t1, "t1"));
+    ABTS_STR_EQUAL(tc, "two", apr_table_get(t1, "t2"));
+
+}
+
+static void table_overlap3(abts_case *tc, void *data)
+{
+    apr_pool_t *subp;
+    apr_table_t *t1, *t2;
+
+    apr_pool_create(&subp, p);
+
+    t1 = apr_table_make(subp, 1);
+    t2 = apr_table_make(p, 1);
+    apr_table_addn(t1, "t1", "one");
+    apr_table_addn(t1, "t1", "overlay");
+    apr_table_addn(t2, "t2", "two");
+    apr_table_addn(t2, "t2", "overlay");
+
+    apr_table_overlap(t1, t2, APR_OVERLAP_TABLES_ADD);
+
+    ABTS_INT_EQUAL(tc, 4, apr_table_elts(t1)->nelts);
+
+    ABTS_STR_EQUAL(tc, "one", apr_table_get(t1, "t1"));
+    ABTS_STR_EQUAL(tc, "two", apr_table_get(t1, "t2"));
+
+}
+
+abts_suite *testtable(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite)
+
+    abts_run_test(suite, array_clear, NULL);
+    abts_run_test(suite, table_make, NULL);
+    abts_run_test(suite, table_get, NULL);
+    abts_run_test(suite, table_getm, NULL);
+    abts_run_test(suite, table_set, NULL);
+    abts_run_test(suite, table_getnotthere, NULL);
+    abts_run_test(suite, table_add, NULL);
+    abts_run_test(suite, table_nelts, NULL);
+    abts_run_test(suite, table_clear, NULL);
+    abts_run_test(suite, table_unset, NULL);
+    abts_run_test(suite, table_overlap, NULL);
+    abts_run_test(suite, table_overlap2, NULL);
+    abts_run_test(suite, table_overlap3, NULL);
+
+    return suite;
+}
+
diff --git a/test/testtemp.c b/test/testtemp.c
new file mode 100644
index 00000000000..1f1143ee359
--- /dev/null
+++ b/test/testtemp.c
@@ -0,0 +1,55 @@
+/* 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 "testutil.h"
+#include "apr_file_io.h"
+#include "apr_strings.h"
+
+static void test_temp_dir(abts_case *tc, void *data)
+{
+    const char *tempdir = NULL;
+    apr_status_t rv;
+
+    rv = apr_temp_dir_get(&tempdir, p);
+    APR_ASSERT_SUCCESS(tc, "Error finding Temporary Directory", rv);
+    ABTS_PTR_NOTNULL(tc, tempdir);
+}
+
+static void test_mktemp(abts_case *tc, void *data)
+{
+    apr_file_t *f = NULL;
+    const char *tempdir = NULL;
+    char *filetemplate;
+    apr_status_t rv;
+
+    rv = apr_temp_dir_get(&tempdir, p);
+    APR_ASSERT_SUCCESS(tc, "Error finding Temporary Directory", rv);
+    
+    filetemplate = apr_pstrcat(p, tempdir, "/tempfileXXXXXX", NULL);
+    rv = apr_file_mktemp(&f, filetemplate, 0, p);
+    APR_ASSERT_SUCCESS(tc, "Error opening Temporary file", rv);
+}
+
+abts_suite *testtemp(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite)
+
+    abts_run_test(suite, test_temp_dir, NULL);
+    abts_run_test(suite, test_mktemp, NULL);
+
+    return suite;
+}
+
diff --git a/test/testthread.c b/test/testthread.c
index f82f496ce69..f3df3678659 100644
--- a/test/testthread.c
+++ b/test/testthread.c
@@ -1,176 +1,132 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
 #include "apr_thread_proc.h"
-#include "apr_lock.h"
 #include "apr_errno.h"
 #include "apr_general.h"
-#include "errno.h"
-#include <stdio.h>
-#ifdef BEOS
-#include <unistd.h>
-#endif
+#include "apr_time.h"
+#include "testutil.h"
 
+#if APR_HAS_THREADS
 
-void * API_THREAD_FUNC thread_func1(void *data);
-void * API_THREAD_FUNC thread_func2(void *data);
-void * API_THREAD_FUNC thread_func3(void *data);
-void * API_THREAD_FUNC thread_func4(void *data);
+static apr_thread_mutex_t *thread_lock;
+static apr_thread_once_t *control = NULL;
+static int x = 0;
+static int value = 0;
 
+static apr_thread_t *t1;
+static apr_thread_t *t2;
+static apr_thread_t *t3;
+static apr_thread_t *t4;
 
-ap_lock_t *thread_lock;
-ap_pool_t *context;
-int x = 0;
+/* just some made up number to check on later */
+static apr_status_t exit_ret_val = 123;
 
-void * API_THREAD_FUNC thread_func1(void *data)
+static void init_func(void)
 {
-    int i;
-    for (i = 0; i < 10000; i++) {
-        ap_lock(thread_lock);
-        x++;
-        ap_unlock(thread_lock);
-    }
-    return NULL;
-} 
+    value++;
+}
 
-void * API_THREAD_FUNC thread_func2(void *data)
+static void * APR_THREAD_FUNC thread_func1(apr_thread_t *thd, void *data)
 {
     int i;
+
+    apr_thread_once(control, init_func);
+
     for (i = 0; i < 10000; i++) {
-        ap_lock(thread_lock);
+        apr_thread_mutex_lock(thread_lock);
         x++;
-        ap_unlock(thread_lock);
+        apr_thread_mutex_unlock(thread_lock);
     }
+    apr_thread_exit(thd, exit_ret_val);
     return NULL;
 } 
 
-void * API_THREAD_FUNC thread_func3(void *data)
+static void thread_init(abts_case *tc, void *data)
 {
-    int i;
-    for (i = 0; i < 10000; i++) {
-        ap_lock(thread_lock);
-        x++;
-        ap_unlock(thread_lock);
-    }
-    return NULL;
-} 
+    apr_status_t rv;
+
+    rv = apr_thread_once_init(&control, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
 
-void * API_THREAD_FUNC thread_func4(void *data)
+    rv = apr_thread_mutex_create(&thread_lock, APR_THREAD_MUTEX_DEFAULT, p); 
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+}
+
+static void create_threads(abts_case *tc, void *data)
 {
-    int i;
-    for (i = 0; i < 10000; i++) {
-        ap_lock(thread_lock);
-        x++;
-        ap_unlock(thread_lock);
-    }
-    return NULL;
-} 
+    apr_status_t rv;
+
+    rv = apr_thread_create(&t1, NULL, thread_func1, NULL, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    rv = apr_thread_create(&t2, NULL, thread_func1, NULL, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    rv = apr_thread_create(&t3, NULL, thread_func1, NULL, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    rv = apr_thread_create(&t4, NULL, thread_func1, NULL, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+}
 
-int main()
+static void join_threads(abts_case *tc, void *data)
 {
-    ap_thread_t *t1;
-    ap_thread_t *t2;
-    ap_thread_t *t3;
-    ap_thread_t *t4;
-    ap_status_t s1;
-    ap_status_t s2;
-    ap_status_t s3;
-    ap_status_t s4;
-
-    ap_initialize();
-
-    fprintf(stdout, "Initializing the context......."); 
-    if (ap_create_pool(&context, NULL) != APR_SUCCESS) {
-        fprintf(stderr, "could not initialize\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK\n");
+    apr_status_t s;
+
+    apr_thread_join(&s, t1);
+    ABTS_INT_EQUAL(tc, exit_ret_val, s);
+    apr_thread_join(&s, t2);
+    ABTS_INT_EQUAL(tc, exit_ret_val, s);
+    apr_thread_join(&s, t3);
+    ABTS_INT_EQUAL(tc, exit_ret_val, s);
+    apr_thread_join(&s, t4);
+    ABTS_INT_EQUAL(tc, exit_ret_val, s);
+}
 
-    fprintf(stdout, "Initializing the lock......."); 
-    s1 = ap_create_lock(&thread_lock, APR_MUTEX, APR_INTRAPROCESS, "lock.file", context); 
-    if (s1 != APR_SUCCESS) {
-        fprintf(stderr, "Could not create lock\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK\n");
-
-    fprintf(stdout, "Starting all the threads......."); 
-    s1 = ap_create_thread(&t1, NULL, thread_func1, NULL, context);
-    s2 = ap_create_thread(&t2, NULL, thread_func2, NULL, context);
-    s3 = ap_create_thread(&t3, NULL, thread_func3, NULL, context);
-    s4 = ap_create_thread(&t4, NULL, thread_func4, NULL, context);
-    if (s1 != APR_SUCCESS || s2 != APR_SUCCESS || 
-        s3 != APR_SUCCESS || s4 != APR_SUCCESS) {
-        fprintf(stderr, "Error starting thread\n");
-        exit(-1);
-    }
-    fprintf(stdout, "OK\n");
-
-    fprintf(stdout, "Waiting for threads to exit.......");
-    ap_thread_join(&s1, t1);
-    ap_thread_join(&s2, t2);
-    ap_thread_join(&s3, t3);
-    ap_thread_join(&s4, t4);
-    fprintf (stdout, "OK\n");   
-
-    fprintf(stdout, "Checking if locks worked......."); 
-    if (x != 40000) {
-        fprintf(stderr, "The locks didn't work????  %d\n", x);
-    }
-    else {
-        fprintf(stdout, "Everything is working!\n");
-    }
+static void check_locks(abts_case *tc, void *data)
+{
+    ABTS_INT_EQUAL(tc, 40000, x);
+}
 
-    return 1;
+static void check_thread_once(abts_case *tc, void *data)
+{
+    ABTS_INT_EQUAL(tc, 1, value);
 }
+
+#else
+
+static void threads_not_impl(abts_case *tc, void *data)
+{
+    ABTS_NOT_IMPL(tc, "Threads not implemented on this platform");
+}
+
+#endif
+
+abts_suite *testthread(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite)
+
+#if !APR_HAS_THREADS
+    abts_run_test(suite, threads_not_impl, NULL);
+#else
+    abts_run_test(suite, thread_init, NULL);
+    abts_run_test(suite, create_threads, NULL);
+    abts_run_test(suite, join_threads, NULL);
+    abts_run_test(suite, check_locks, NULL);
+    abts_run_test(suite, check_thread_once, NULL);
+#endif
+
+    return suite;
+}
+
diff --git a/test/testthread.dsp b/test/testthread.dsp
deleted file mode 100644
index a4b798f0cff..00000000000
--- a/test/testthread.dsp
+++ /dev/null
@@ -1,92 +0,0 @@
-# Microsoft Developer Studio Project File - Name="testthread" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 5.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=testthread - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "testthread.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 "testthread.mak" CFG="testthread - Win32 Debug"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "testthread - Win32 Release" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE "testthread - Win32 Debug" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE 
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF  "$(CFG)" == "testthread - 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 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /W3 /GX /O2 /I "..\include" /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ..\Release\aprlib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"..\Release\testthread.exe"
-
-!ELSEIF  "$(CFG)" == "testthread - 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 /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\include" /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
-# SUBTRACT CPP /YX /Yc /Yu
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 ..\Debug\aprlib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\Debug\testthread.exe" /pdbtype:sept
-
-!ENDIF 
-
-# Begin Target
-
-# Name "testthread - Win32 Release"
-# Name "testthread - Win32 Debug"
-# Begin Source File
-
-SOURCE=.\testthread.c
-# End Source File
-# End Target
-# End Project
diff --git a/test/testtime.c b/test/testtime.c
index 05c3c4d77dc..fadef97c47d 100644
--- a/test/testtime.c
+++ b/test/testtime.c
@@ -1,103 +1,316 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
 #include "apr_time.h"
 #include "apr_errno.h"
 #include "apr_general.h"
-#include "errno.h"
-#include <stdio.h>
-#ifdef BEOS
-#include <unistd.h>
-#endif
+#include "apr_lib.h"
+#include "testutil.h"
+#include "apr_strings.h"
+#include <time.h>
+
+#define STR_SIZE 45
+
+/* The time value is used throughout the tests, so just make this a global.
+ * Also, we need a single value that we can test for the positive tests, so
+ * I chose the number below, it corresponds to:
+ *           2002-09-14 12:05:36.186711 -25200 [257 Sat].
+ * Which happens to be when I wrote the new tests.
+ */
+static apr_time_t now = APR_INT64_C(1032030336186711);
+/* 2012-08-11 16:00:55.151600 -14400 [224 Sat] DST */
+static apr_time_t leap_year_now = APR_INT64_C(1344715255151600);
+
+static char* print_time (apr_pool_t *pool, const apr_time_exp_t *xt)
+{
+    return apr_psprintf (pool,
+                         "%04d-%02d-%02d %02d:%02d:%02d.%06d %+05d [%d %s]%s",
+                         xt->tm_year + 1900,
+                         xt->tm_mon + 1,
+                         xt->tm_mday,
+                         xt->tm_hour,
+                         xt->tm_min,
+                         xt->tm_sec,
+                         xt->tm_usec,
+                         xt->tm_gmtoff,
+                         xt->tm_yday + 1,
+                         apr_day_snames[xt->tm_wday],
+                         (xt->tm_isdst ? " DST" : ""));
+}
+
+
+static void test_now(abts_case *tc, void *data)
+{
+    apr_time_t timediff;
+    apr_time_t current;
+    time_t os_now;
+
+    current = apr_time_now();
+    time(&os_now);
 
-int main()
+    timediff = os_now - (current / APR_USEC_PER_SEC);
+    /* Even though these are called so close together, there is the chance
+     * that the time will be slightly off, so accept anything between -1 and
+     * 1 second.
+     */
+    ABTS_ASSERT(tc, "apr_time and OS time do not agree",
+             (timediff > -2) && (timediff < 2));
+}
+
+static void test_gmtstr(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_time_exp_t xt;
+
+    rv = apr_time_exp_gmt(&xt, now);
+    if (rv == APR_ENOTIMPL) {
+        ABTS_NOT_IMPL(tc, "apr_time_exp_gmt");
+    }
+    ABTS_TRUE(tc, rv == APR_SUCCESS);
+    ABTS_STR_EQUAL(tc, "2002-09-14 19:05:36.186711 +0000 [257 Sat]",
+                      print_time(p, &xt));
+}
+
+static void test_exp_lt(abts_case *tc, void *data)
 {
-    ap_time_t now;
-    ap_exploded_time_t xt;
-    ap_time_t imp;
+    apr_time_t test_times[] = {0, 0, 0};
+    int i;
+
+    test_times[0] = now;
+    test_times[1] = leap_year_now;
 
-    fprintf(stdout, "Testing Time functions.\n");
+    for (i = 0; test_times[i] != 0; i++) {
+        apr_status_t rv;
+        apr_time_exp_t xt;
+        time_t posix_secs = (time_t)apr_time_sec(test_times[i]);
+        struct tm *posix_exp = localtime(&posix_secs);
 
-    fprintf(stdout, "\tap_now.......");
-    now = ap_now();
-    fprintf(stdout, "OK\n");
+        rv = apr_time_exp_lt(&xt, test_times[i]);
+        if (rv == APR_ENOTIMPL) {
+            ABTS_NOT_IMPL(tc, "apr_time_exp_lt");
+        }
+        ABTS_TRUE(tc, rv == APR_SUCCESS);
 
-    fprintf(stdout, "\tap_explode_localtime.......");
-    if (ap_explode_localtime(&xt, now) != APR_SUCCESS) {
-        fprintf(stderr, "Couldn't explode the time\n");
-        exit(-1);
+#define CHK_FIELD(f) \
+        ABTS_ASSERT(tc, "Mismatch in " #f, posix_exp->f == xt.f)
+
+        CHK_FIELD(tm_sec);
+        CHK_FIELD(tm_min);
+        CHK_FIELD(tm_hour);
+        CHK_FIELD(tm_mday);
+        CHK_FIELD(tm_mon);
+        CHK_FIELD(tm_year);
+        CHK_FIELD(tm_wday);
+        CHK_FIELD(tm_yday);
+        CHK_FIELD(tm_isdst);
+#undef CHK_FIELD
     }
-    fprintf(stdout, "OK\n");
-    
-    fprintf(stdout, "\tap_explode_gmt.......");
-    if (ap_explode_gmt(&xt, now) != APR_SUCCESS) {
-        fprintf(stderr, "Couldn't explode the time\n");
-        exit(-1);
+}
+
+static void test_exp_get_gmt(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_time_exp_t xt;
+    apr_time_t imp;
+    apr_int64_t hr_off_64;
+
+    rv = apr_time_exp_gmt(&xt, now);
+    ABTS_TRUE(tc, rv == APR_SUCCESS);
+    rv = apr_time_exp_get(&imp, &xt);
+    if (rv == APR_ENOTIMPL) {
+        ABTS_NOT_IMPL(tc, "apr_time_exp_get");
     }
-    fprintf(stdout, "OK\n");
+    ABTS_TRUE(tc, rv == APR_SUCCESS);
+    hr_off_64 = (apr_int64_t) xt.tm_gmtoff * APR_USEC_PER_SEC;
+    ABTS_TRUE(tc, now + hr_off_64 == imp);
+}
+
+static void test_exp_get_lt(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_time_exp_t xt;
+    apr_time_t imp;
+    apr_int64_t hr_off_64;
 
-    fprintf(stdout, "\tap_implode_time........");
-    if (ap_implode_time(&imp, &xt) != APR_SUCCESS) {
-        fprintf(stderr, "Couldn't implode the time\n");
-        exit(-1);
+    rv = apr_time_exp_lt(&xt, now);
+    ABTS_TRUE(tc, rv == APR_SUCCESS);
+    rv = apr_time_exp_get(&imp, &xt);
+    if (rv == APR_ENOTIMPL) {
+        ABTS_NOT_IMPL(tc, "apr_time_exp_get");
     }
-    if (imp != now) {
-	fprintf(stderr, "implode/explode mismatch\n");
-	exit(-1);
+    ABTS_TRUE(tc, rv == APR_SUCCESS);
+    hr_off_64 = (apr_int64_t) xt.tm_gmtoff * APR_USEC_PER_SEC;
+    ABTS_TRUE(tc, now + hr_off_64 == imp);
+}
+
+static void test_imp_gmt(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_time_exp_t xt;
+    apr_time_t imp;
+
+    rv = apr_time_exp_gmt(&xt, now);
+    ABTS_TRUE(tc, rv == APR_SUCCESS);
+    rv = apr_time_exp_gmt_get(&imp, &xt);
+    if (rv == APR_ENOTIMPL) {
+        ABTS_NOT_IMPL(tc, "apr_time_exp_gmt_get");
     }
-    fprintf(stdout, "OK\n");
+    ABTS_TRUE(tc, rv == APR_SUCCESS);
+    ABTS_TRUE(tc, now == imp);
+}
+
+static void test_rfcstr(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    char str[STR_SIZE];
+
+    rv = apr_rfc822_date(str, now);
+    if (rv == APR_ENOTIMPL) {
+        ABTS_NOT_IMPL(tc, "apr_rfc822_date");
+    }
+    ABTS_TRUE(tc, rv == APR_SUCCESS);
+    ABTS_STR_EQUAL(tc, "Sat, 14 Sep 2002 19:05:36 GMT", str);
+}
+
+static void test_ctime(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    char apr_str[STR_SIZE];
+    char libc_str[STR_SIZE];
+    apr_time_t now_sec = apr_time_sec(now);
+    time_t posix_sec = (time_t) now_sec;
+
+    rv = apr_ctime(apr_str, now);
+    if (rv == APR_ENOTIMPL) {
+        ABTS_NOT_IMPL(tc, "apr_ctime");
+    }
+    ABTS_TRUE(tc, rv == APR_SUCCESS);
+    strcpy(libc_str, ctime(&posix_sec));
+    *strchr(libc_str, '\n') = '\0';
+
+    ABTS_STR_EQUAL(tc, libc_str, apr_str);
+}
+
+static void test_strftime(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_time_exp_t xt;
+    char *str = NULL;
+    apr_size_t sz;
+
+    rv = apr_time_exp_gmt(&xt, now);
+    str = apr_palloc(p, STR_SIZE + 1);
+    rv = apr_strftime(str, &sz, STR_SIZE, "%R %A %d %B %Y", &xt);
+    if (rv == APR_ENOTIMPL) {
+        ABTS_NOT_IMPL(tc, "apr_strftime");
+    }
+    ABTS_TRUE(tc, rv == APR_SUCCESS);
+    ABTS_STR_EQUAL(tc, "19:05 Saturday 14 September 2002", str);
+}
+
+static void test_strftimesmall(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_time_exp_t xt;
+    char str[STR_SIZE];
+    apr_size_t sz;
+
+    rv = apr_time_exp_gmt(&xt, now);
+    rv = apr_strftime(str, &sz, STR_SIZE, "%T", &xt);
+    if (rv == APR_ENOTIMPL) {
+        ABTS_NOT_IMPL(tc, "apr_strftime");
+    }
+    ABTS_TRUE(tc, rv == APR_SUCCESS);
+    ABTS_STR_EQUAL(tc, "19:05:36", str);
+}
+
+static void test_exp_tz(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_time_exp_t xt;
+    apr_int32_t hr_off = -5 * 3600; /* 5 hours in seconds */
+
+    rv = apr_time_exp_tz(&xt, now, hr_off);
+    if (rv == APR_ENOTIMPL) {
+        ABTS_NOT_IMPL(tc, "apr_time_exp_tz");
+    }
+    ABTS_TRUE(tc, rv == APR_SUCCESS);
+    ABTS_TRUE(tc, (xt.tm_usec == 186711) &&
+                     (xt.tm_sec == 36) &&
+                     (xt.tm_min == 5) &&
+                     (xt.tm_hour == 14) &&
+                     (xt.tm_mday == 14) &&
+                     (xt.tm_mon == 8) &&
+                     (xt.tm_year == 102) &&
+                     (xt.tm_wday == 6) &&
+                     (xt.tm_yday == 256));
+}
+
+static void test_strftimeoffset(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_time_exp_t xt;
+    char str[STR_SIZE];
+    apr_size_t sz;
+    apr_int32_t hr_off = -5 * 3600; /* 5 hours in seconds */
+
+    apr_time_exp_tz(&xt, now, hr_off);
+    rv = apr_strftime(str, &sz, STR_SIZE, "%T", &xt);
+    if (rv == APR_ENOTIMPL) {
+        ABTS_NOT_IMPL(tc, "apr_strftime");
+    }
+    ABTS_TRUE(tc, rv == APR_SUCCESS);
+}
+
+/* 0.9.4 and earlier rejected valid dates in 2038 */
+static void test_2038(abts_case *tc, void *data)
+{
+    apr_time_exp_t xt;
+    apr_time_t t;
+
+    /* 2038-01-19T03:14:07.000000Z */
+    xt.tm_year = 138;
+    xt.tm_mon = 0;
+    xt.tm_mday = 19;
+    xt.tm_hour = 3;
+    xt.tm_min = 14;
+    xt.tm_sec = 7;
+
+    APR_ASSERT_SUCCESS(tc, "explode January 19th, 2038",
+                       apr_time_exp_get(&t, &xt));
+}
+
+abts_suite *testtime(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite)
+
+    abts_run_test(suite, test_now, NULL);
+    abts_run_test(suite, test_gmtstr, NULL);
+    abts_run_test(suite, test_exp_lt, NULL);
+    abts_run_test(suite, test_exp_get_gmt, NULL);
+    abts_run_test(suite, test_exp_get_lt, NULL);
+    abts_run_test(suite, test_imp_gmt, NULL);
+    abts_run_test(suite, test_rfcstr, NULL);
+    abts_run_test(suite, test_ctime, NULL);
+    abts_run_test(suite, test_strftime, NULL);
+    abts_run_test(suite, test_strftimesmall, NULL);
+    abts_run_test(suite, test_exp_tz, NULL);
+    abts_run_test(suite, test_strftimeoffset, NULL);
+    abts_run_test(suite, test_2038, NULL);
 
-    return 1;
-}    
+    return suite;
+}
 
diff --git a/test/testud.c b/test/testud.c
new file mode 100644
index 00000000000..7132d6cf78e
--- /dev/null
+++ b/test/testud.c
@@ -0,0 +1,91 @@
+/* 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 <stdio.h>
+#include <stdlib.h>
+#include "apr_file_io.h"
+#include "apr_errno.h"
+#include "apr_general.h"
+#include "apr_lib.h"
+#include "apr_strings.h"
+#include "testutil.h"
+
+static apr_pool_t *pool;
+static char *testdata;
+static int cleanup_called = 0;
+
+static apr_status_t string_cleanup(void *data)
+{
+    cleanup_called = 1;
+    return APR_SUCCESS;
+}
+
+static void set_userdata(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+
+    rv = apr_pool_userdata_set(testdata, "TEST", string_cleanup, pool);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+}
+
+static void get_userdata(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    void *retdata;
+
+    rv = apr_pool_userdata_get(&retdata, "TEST", pool);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_STR_EQUAL(tc, testdata, retdata);
+}
+
+static void get_nonexistkey(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    void *retdata;
+
+    rv = apr_pool_userdata_get(&retdata, "DOESNTEXIST", pool);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_PTR_EQUAL(tc, NULL, retdata);
+}
+
+static void post_pool_clear(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    void *retdata;
+
+    rv = apr_pool_userdata_get(&retdata, "DOESNTEXIST", pool);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    ABTS_PTR_EQUAL(tc, NULL, retdata);
+}
+
+abts_suite *testud(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite)
+
+    apr_pool_create(&pool, p);
+    testdata = apr_pstrdup(pool, "This is a test\n");
+
+    abts_run_test(suite, set_userdata, NULL);
+    abts_run_test(suite, get_userdata, NULL);
+    abts_run_test(suite, get_nonexistkey, NULL);
+
+    apr_pool_clear(pool);
+
+    abts_run_test(suite, post_pool_clear, NULL);
+
+    return suite;
+}
+
diff --git a/test/testuri.c b/test/testuri.c
new file mode 100644
index 00000000000..d0b51e16cfb
--- /dev/null
+++ b/test/testuri.c
@@ -0,0 +1,331 @@
+/* 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 <stdio.h>
+#include <stdlib.h>
+
+#include "testutil.h"
+#include "apr_general.h"
+#include "apr_strings.h"
+#include "apr_uri.h"
+
+struct aup_test {
+    const char *uri;
+    apr_status_t rv;
+    const char *scheme;
+    const char *hostinfo;
+    const char *user;
+    const char *password;
+    const char *hostname;
+    const char *port_str;
+    const char *path;
+    const char *query;
+    const char *fragment;
+    apr_port_t  port;
+};
+
+struct aup_test aup_tests[] =
+{
+    { "http://[/::1]/index.html", APR_EGENERAL },
+    { "http://[", APR_EGENERAL },
+    { "http://[?::1]/index.html", APR_EGENERAL },
+
+    {
+        "http://127.0.0.1:9999/asdf.html",
+        0, "http", "127.0.0.1:9999", NULL, NULL, "127.0.0.1", "9999", "/asdf.html", NULL, NULL, 9999
+    },
+    {
+        "http://127.0.0.1:9999a/asdf.html",
+        APR_EGENERAL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+    },
+    {
+        "http://[::127.0.0.1]:9999/asdf.html",
+        0, "http", "[::127.0.0.1]:9999", NULL, NULL, "::127.0.0.1", "9999", "/asdf.html", NULL, NULL, 9999
+    },
+    {
+        "http://[::127.0.0.1]:9999a/asdf.html",
+        APR_EGENERAL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+    },
+    {
+        "/error/include/top.html",
+        0, NULL, NULL, NULL, NULL, NULL, NULL, "/error/include/top.html", NULL, NULL, 0
+    },
+    {
+        "/error/include/../contact.html.var",
+        0, NULL, NULL, NULL, NULL, NULL, NULL, "/error/include/../contact.html.var", NULL, NULL, 0
+    },
+    {
+        "/",
+        0, NULL, NULL, NULL, NULL, NULL, NULL, "/", NULL, NULL, 0
+    },
+    {
+        "/manual/",
+        0, NULL, NULL, NULL, NULL, NULL, NULL, "/manual/", NULL, NULL, 0
+    },
+    {
+        "/cocoon/developing/graphics/Using%20Databases-label_over.jpg",
+        0, NULL, NULL, NULL, NULL, NULL, NULL, "/cocoon/developing/graphics/Using%20Databases-label_over.jpg", NULL, NULL, 0
+    },
+    {
+        "http://sonyamt:garbage@127.0.0.1/filespace/",
+        0, "http", "sonyamt:garbage@127.0.0.1", "sonyamt", "garbage", "127.0.0.1", NULL, "/filespace/", NULL, NULL, 0
+    },
+    {
+        "http://sonyamt:garbage@[fe80::1]/filespace/",
+        0, "http", "sonyamt:garbage@[fe80::1]", "sonyamt", "garbage", "fe80::1", NULL, "/filespace/", NULL, NULL, 0
+    },
+    {
+        "http://sonyamt@[fe80::1]/filespace/?arg1=store",
+        0, "http", "sonyamt@[fe80::1]", "sonyamt", NULL, "fe80::1", NULL, "/filespace/", "arg1=store", NULL, 0
+    },
+    {
+        "http://localhost",
+        0, "http", "localhost", NULL, NULL, "localhost", NULL, NULL, NULL, NULL, 0
+    },
+    {
+        "//www.apache.org/",
+        0, NULL, "www.apache.org", NULL, NULL, "www.apache.org", NULL, "/", NULL, NULL, 0
+    },
+    {
+        "file:image.jpg",
+        0, "file", NULL, NULL, NULL, NULL, NULL, "image.jpg", NULL, NULL, 0
+    },
+    {
+        "file:/image.jpg",
+        0, "file", NULL, NULL, NULL, NULL, NULL, "/image.jpg", NULL, NULL, 0
+    },
+    {
+        "file:///image.jpg",
+        0, "file", "", NULL, NULL, "", NULL, "/image.jpg", NULL, NULL, 0
+    },
+    {
+        "file:///tmp/photos/image.jpg",
+        0, "file", "", NULL, NULL, "", NULL, "/tmp/photos/image.jpg", NULL, NULL, 0
+    },
+    {
+        "file:./image.jpg",
+        0, "file", NULL, NULL, NULL, NULL, NULL, "./image.jpg", NULL, NULL, 0
+    },
+    {
+        "file:../photos/image.jpg",
+        0, "file", NULL, NULL, NULL, NULL, NULL, "../photos/image.jpg", NULL, NULL, 0
+    },
+    {
+        "file+ssh-2:../photos/image.jpg",
+        0, "file+ssh-2", NULL, NULL, NULL, NULL, NULL, "../photos/image.jpg", NULL, NULL, 0
+    },
+    {
+        "script/foo.js",
+        0, NULL, NULL, NULL, NULL, NULL, NULL, "script/foo.js", NULL, NULL, 0
+    },
+    {
+        "../foo2.js",
+        0, NULL, NULL, NULL, NULL, NULL, NULL, "../foo2.js", NULL, NULL, 0
+    },
+    {
+        "foo3.js",
+        0, NULL, NULL, NULL, NULL, NULL, NULL, "foo3.js", NULL, NULL, 0
+    },
+    {
+        "_foo/bar",
+        0, NULL, NULL, NULL, NULL, NULL, NULL, "_foo/bar", NULL, NULL, 0
+    },
+    {
+        "_foo:/bar",
+        APR_EGENERAL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+    },
+    {
+        "2foo:/bar",
+        APR_EGENERAL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+    },
+    {
+        ".foo:/bar",
+        APR_EGENERAL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+    },
+    {
+        "-foo:/bar",
+        APR_EGENERAL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+    },
+    {
+        "+foo:/bar",
+        APR_EGENERAL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+    },
+    {
+        "::/bar",
+        APR_EGENERAL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+    },
+    {
+        ":/bar",
+        APR_EGENERAL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+    },
+    {
+        ":foo",
+        APR_EGENERAL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+    },
+    {
+        ":",
+        APR_EGENERAL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+    },
+    {
+        "@localhost::8080",
+        APR_EGENERAL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+    },
+};
+
+struct uph_test {
+    const char *hostinfo;
+    apr_status_t rv;
+    const char *hostname;
+    const char *port_str;
+    apr_port_t port;
+};
+
+struct uph_test uph_tests[] =
+{
+    {
+        "www.ibm.com:443",
+        0, "www.ibm.com", "443", 443
+    },
+    {
+        "[fe80::1]:443",
+        0, "fe80::1", "443", 443
+    },
+    {
+        "127.0.0.1:443",
+        0, "127.0.0.1", "443", 443
+    },
+    {
+        "127.0.0.1",
+        APR_EGENERAL, NULL, NULL, 0
+    },
+    {
+        "[fe80:80",
+        APR_EGENERAL, NULL, NULL, 0
+    },
+    {
+        "fe80::80]:443",
+        APR_EGENERAL, NULL, NULL, 0
+    }
+};
+
+#if 0
+static void show_info(apr_status_t rv, apr_status_t expected, const apr_uri_t *info)
+{
+    if (rv != expected) {
+        fprintf(stderr, "  actual rv: %d    expected rv:  %d\n", rv, expected);
+    }
+    else {
+        fprintf(stderr, 
+                "  scheme:           %s\n"
+                "  hostinfo:         %s\n"
+                "  user:             %s\n"
+                "  password:         %s\n"
+                "  hostname:         %s\n"
+                "  port_str:         %s\n"
+                "  path:             %s\n"
+                "  query:            %s\n"
+                "  fragment:         %s\n"
+                "  hostent:          %p\n"
+                "  port:             %u\n"
+                "  is_initialized:   %u\n"
+                "  dns_looked_up:    %u\n"
+                "  dns_resolved:     %u\n",
+                info->scheme, info->hostinfo, info->user, info->password,
+                info->hostname, info->port_str, info->path, info->query,
+                info->fragment, info->hostent, info->port, info->is_initialized,
+                info->dns_looked_up, info->dns_resolved);
+    }
+}
+#endif
+
+static void test_aup(abts_case *tc, void *data)
+{
+    int i;
+    apr_status_t rv;
+    apr_uri_t info;
+    struct aup_test *t;
+    const char *s = NULL;
+
+    for (i = 0; i < sizeof(aup_tests) / sizeof(aup_tests[0]); i++) {
+        char msg[256];
+
+        memset(&info, 0, sizeof(info));
+        t = &aup_tests[i];
+        rv = apr_uri_parse(p, t->uri, &info);
+        apr_snprintf(msg, sizeof msg, "uri '%s': rv=%d not %d", t->uri,
+                     rv, t->rv);
+        ABTS_ASSERT(tc, msg, rv == t->rv);
+        if (t->rv == APR_SUCCESS) {
+            ABTS_STR_EQUAL(tc, t->scheme, info.scheme);
+            ABTS_STR_EQUAL(tc, t->hostinfo, info.hostinfo);
+            ABTS_STR_EQUAL(tc, t->user, info.user);
+            ABTS_STR_EQUAL(tc, t->password, info.password);
+            ABTS_STR_EQUAL(tc, t->hostname, info.hostname);
+            ABTS_STR_EQUAL(tc, t->port_str, info.port_str);
+            ABTS_STR_EQUAL(tc, t->path, info.path);
+            ABTS_STR_EQUAL(tc, t->query, info.query);
+            ABTS_STR_EQUAL(tc, t->user, info.user);
+            ABTS_INT_EQUAL(tc, t->port, info.port);
+
+            s = apr_uri_unparse(p, &info, APR_URI_UNP_REVEALPASSWORD);
+            ABTS_STR_EQUAL(tc, t->uri, s);
+
+            s = apr_uri_unparse(p, &info, APR_URI_UNP_OMITSITEPART);
+            rv = apr_uri_parse(p, s, &info);
+            ABTS_STR_EQUAL(tc, info.scheme, NULL);
+            ABTS_STR_EQUAL(tc, info.hostinfo, NULL);
+            ABTS_STR_EQUAL(tc, info.user, NULL);
+            ABTS_STR_EQUAL(tc, info.password, NULL);
+            ABTS_STR_EQUAL(tc, info.hostname, NULL);
+            ABTS_STR_EQUAL(tc, info.port_str, NULL);
+            ABTS_STR_EQUAL(tc, info.path, t->path);
+            ABTS_STR_EQUAL(tc, info.query, t->query);
+            ABTS_STR_EQUAL(tc, info.user, NULL);
+            ABTS_INT_EQUAL(tc, info.port, 0);
+        }
+    }
+}
+
+static void test_uph(abts_case *tc, void *data)
+{
+    int i;
+    apr_status_t rv;
+    apr_uri_t info;
+    struct uph_test *t;
+
+    for (i = 0; i < sizeof(uph_tests) / sizeof(uph_tests[0]); i++) {
+        memset(&info, 0, sizeof(info));
+        t = &uph_tests[i];
+        rv = apr_uri_parse_hostinfo(p, t->hostinfo, &info);
+        ABTS_INT_EQUAL(tc, t->rv, rv);
+        if (t->rv == APR_SUCCESS) {
+            ABTS_STR_EQUAL(tc, t->hostname, info.hostname);
+            ABTS_STR_EQUAL(tc, t->port_str, info.port_str);
+            ABTS_INT_EQUAL(tc, t->port, info.port);
+        }
+    }
+}
+
+abts_suite *testuri(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite);
+
+    abts_run_test(suite, test_aup, NULL);
+    abts_run_test(suite, test_uph, NULL);
+
+    return suite;
+}
+
diff --git a/test/testuser.c b/test/testuser.c
new file mode 100644
index 00000000000..e75782e902e
--- /dev/null
+++ b/test/testuser.c
@@ -0,0 +1,174 @@
+/* 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 "testutil.h"
+#include "apr_errno.h"
+#include "apr_general.h"
+#include "apr_user.h"
+
+#if APR_HAS_USER
+static void uid_current(abts_case *tc, void *data)
+{
+    apr_uid_t uid;
+    apr_gid_t gid;
+
+    APR_ASSERT_SUCCESS(tc, "apr_uid_current failed",
+                       apr_uid_current(&uid, &gid, p));
+}
+
+static void username(abts_case *tc, void *data)
+{
+    apr_uid_t uid;
+    apr_gid_t gid;
+    apr_uid_t retreived_uid;
+    apr_gid_t retreived_gid;
+    char *uname = NULL;
+
+    APR_ASSERT_SUCCESS(tc, "apr_uid_current failed",
+                       apr_uid_current(&uid, &gid, p));
+   
+    APR_ASSERT_SUCCESS(tc, "apr_uid_name_get failed",
+                       apr_uid_name_get(&uname, uid, p));
+    ABTS_PTR_NOTNULL(tc, uname);
+
+    if (uname == NULL)
+        return;
+
+    APR_ASSERT_SUCCESS(tc, "apr_uid_get failed",
+                       apr_uid_get(&retreived_uid, &retreived_gid, uname, p));
+
+    APR_ASSERT_SUCCESS(tc, "apr_uid_compare failed",
+                       apr_uid_compare(uid, retreived_uid));
+#ifdef WIN32
+    /* ### this fudge was added for Win32 but makes the test return NotImpl
+     * on Unix if run as root, when !gid is also true. */
+    if (!gid || !retreived_gid) {
+        /* The function had no way to recover the gid (this would have been
+         * an ENOTIMPL if apr_uid_ functions didn't try to double-up and
+         * also return apr_gid_t values, which was bogus.
+         */
+        if (!gid) {
+            ABTS_NOT_IMPL(tc, "Groups from apr_uid_current");
+        }
+        else {
+            ABTS_NOT_IMPL(tc, "Groups from apr_uid_get");
+        }        
+    }
+    else {
+#endif
+        APR_ASSERT_SUCCESS(tc, "apr_gid_compare failed",
+                           apr_gid_compare(gid, retreived_gid));
+#ifdef WIN32
+    }
+#endif
+}
+
+static void groupname(abts_case *tc, void *data)
+{
+    apr_uid_t uid;
+    apr_gid_t gid;
+    apr_gid_t retreived_gid;
+    char *gname = NULL;
+
+    APR_ASSERT_SUCCESS(tc, "apr_uid_current failed",
+                       apr_uid_current(&uid, &gid, p));
+
+    APR_ASSERT_SUCCESS(tc, "apr_gid_name_get failed",
+                       apr_gid_name_get(&gname, gid, p));
+    ABTS_PTR_NOTNULL(tc, gname);
+
+    if (gname == NULL)
+        return;
+
+    APR_ASSERT_SUCCESS(tc, "apr_gid_get failed",
+                       apr_gid_get(&retreived_gid, gname, p));
+
+    APR_ASSERT_SUCCESS(tc, "apr_gid_compare failed",
+                       apr_gid_compare(gid, retreived_gid));
+}
+
+#ifdef APR_UID_GID_NUMERIC
+
+static void fail_userinfo(abts_case *tc, void *data)
+{
+    apr_uid_t uid;
+    apr_gid_t gid;
+    apr_status_t rv;
+    char *tmp;
+
+    errno = 0;
+    gid = uid = 9999999;
+    tmp = NULL;
+    rv = apr_uid_name_get(&tmp, uid, p);
+    ABTS_ASSERT(tc, "apr_uid_name_get should fail or "
+                "return a user name",
+                rv != APR_SUCCESS || tmp != NULL);
+
+    errno = 0;
+    tmp = NULL;
+    rv = apr_gid_name_get(&tmp, gid, p);
+    ABTS_ASSERT(tc, "apr_gid_name_get should fail or "
+                "return a group name",
+                rv != APR_SUCCESS || tmp != NULL);
+
+    gid = 424242;
+    errno = 0;
+    rv = apr_gid_get(&gid, "I_AM_NOT_A_GROUP", p);
+    ABTS_ASSERT(tc, "apr_gid_get should fail or "
+                "set a group number",
+                rv != APR_SUCCESS || gid == 424242);
+
+    gid = uid = 424242;
+    errno = 0;
+    rv = apr_uid_get(&uid, &gid, "I_AM_NOT_A_USER", p);
+    ABTS_ASSERT(tc, "apr_gid_get should fail or "
+                "set a user and group number",
+                rv != APR_SUCCESS || uid == 424242 || gid == 4242442);
+
+    errno = 0;
+    tmp = NULL;
+    rv = apr_uid_homepath_get(&tmp, "I_AM_NOT_A_USER", p);
+    ABTS_ASSERT(tc, "apr_uid_homepath_get should fail or "
+                "set a path name",
+                rv != APR_SUCCESS || tmp != NULL);
+}
+
+#endif
+
+#else
+static void users_not_impl(abts_case *tc, void *data)
+{
+    ABTS_NOT_IMPL(tc, "Users not implemented on this platform");
+}
+#endif
+
+abts_suite *testuser(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite)
+
+#if !APR_HAS_USER
+    abts_run_test(suite, users_not_impl, NULL);
+#else
+    abts_run_test(suite, uid_current, NULL);
+    abts_run_test(suite, username, NULL);
+    abts_run_test(suite, groupname, NULL);
+#ifdef APR_UID_GID_NUMERIC
+    abts_run_test(suite, fail_userinfo, NULL);
+#endif
+#endif
+
+    return suite;
+}
diff --git a/test/testutil.c b/test/testutil.c
new file mode 100644
index 00000000000..d3c1ff8ac95
--- /dev/null
+++ b/test/testutil.c
@@ -0,0 +1,56 @@
+/* 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 <stdio.h>
+#include <stdlib.h>
+
+#include "abts.h"
+#include "testutil.h"
+#include "apr_pools.h"
+
+apr_pool_t *p;
+
+void apr_assert_success(abts_case* tc, const char* context, apr_status_t rv, 
+                        int lineno) 
+{
+    if (rv == APR_ENOTIMPL) {
+        abts_not_impl(tc, context, lineno);
+    } else if (rv != APR_SUCCESS) {
+        char buf[STRING_MAX], ebuf[128];
+        sprintf(buf, "%s (%d): %s\n", context, rv,
+                apr_strerror(rv, ebuf, sizeof ebuf));
+        abts_fail(tc, buf, lineno);
+    }
+}
+
+void apr_assert_failure(abts_case* tc, const char* context, apr_status_t rv,
+                        int lineno)
+{
+    if (rv == APR_ENOTIMPL) {
+        abts_not_impl(tc, context, lineno);
+    } else if (rv == APR_SUCCESS) {
+        char buf[STRING_MAX];
+        sprintf(buf, "%s (%d): expected failure, got success\n", context, rv);
+        abts_fail(tc, buf, lineno);
+    }
+}
+
+void initialize(void) {
+    apr_initialize();
+    atexit(apr_terminate);
+    
+    apr_pool_create(&p, NULL);
+}
diff --git a/test/testutil.h b/test/testutil.h
new file mode 100644
index 00000000000..f2a66b585ec
--- /dev/null
+++ b/test/testutil.h
@@ -0,0 +1,137 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_pools.h"
+#include "apr_general.h"
+#include "abts.h"
+
+#ifndef APR_TEST_UTIL
+#define APR_TEST_UTIL
+
+/* XXX: FIXME - these all should become much more utilitarian 
+ * and part of apr, itself
+ */
+
+#ifdef WIN32
+#ifdef BINPATH
+#define TESTBINPATH APR_STRINGIFY(BINPATH) "/"
+#else
+#define TESTBINPATH ""
+#endif
+#else
+#define TESTBINPATH "./"
+#endif
+
+#ifdef WIN32
+#define EXTENSION ".exe"
+#elif NETWARE
+#define EXTENSION ".nlm"
+#else
+#define EXTENSION
+#endif
+
+#define STRING_MAX 8096
+
+/* Some simple functions to make the test apps easier to write and
+ * a bit more consistent...
+ */
+
+extern apr_pool_t *p;
+
+/* Assert that RV is an APR_SUCCESS value; else fail giving strerror
+ * for RV and CONTEXT message. */
+void apr_assert_success(abts_case* tc, const char *context, 
+                        apr_status_t rv, int lineno);
+#define APR_ASSERT_SUCCESS(tc, ctxt, rv) \
+             apr_assert_success(tc, ctxt, rv, __LINE__)
+
+void apr_assert_failure(abts_case* tc, const char *context,
+                        apr_status_t rv, int lineno);
+#define APR_ASSERT_FAILURE(tc, ctxt, rv) \
+             apr_assert_failure(tc, ctxt, rv, __LINE__)
+
+
+void initialize(void);
+
+abts_suite *testatomic(abts_suite *suite);
+abts_suite *testdir(abts_suite *suite);
+abts_suite *testdso(abts_suite *suite);
+abts_suite *testdup(abts_suite *suite);
+abts_suite *testenv(abts_suite *suite);
+abts_suite *testfile(abts_suite *suite);
+abts_suite *testfilecopy(abts_suite *suite);
+abts_suite *testfileinfo(abts_suite *suite);
+abts_suite *testflock(abts_suite *suite);
+abts_suite *testfmt(abts_suite *suite);
+abts_suite *testfnmatch(abts_suite *suite);
+abts_suite *testgetopt(abts_suite *suite);
+abts_suite *testglobalmutex(abts_suite *suite);
+abts_suite *testhash(abts_suite *suite);
+abts_suite *testhooks(abts_suite *suite);
+abts_suite *testipsub(abts_suite *suite);
+abts_suite *testlock(abts_suite *suite);
+abts_suite *testcond(abts_suite *suite);
+abts_suite *testlfs(abts_suite *suite);
+abts_suite *testmmap(abts_suite *suite);
+abts_suite *testnames(abts_suite *suite);
+abts_suite *testoc(abts_suite *suite);
+abts_suite *testpath(abts_suite *suite);
+abts_suite *testpipe(abts_suite *suite);
+abts_suite *testpoll(abts_suite *suite);
+abts_suite *testpool(abts_suite *suite);
+abts_suite *testproc(abts_suite *suite);
+abts_suite *testprocmutex(abts_suite *suite);
+abts_suite *testrand(abts_suite *suite);
+abts_suite *testsleep(abts_suite *suite);
+abts_suite *testshm(abts_suite *suite);
+abts_suite *testsock(abts_suite *suite);
+abts_suite *testsockets(abts_suite *suite);
+abts_suite *testsockopt(abts_suite *suite);
+abts_suite *teststr(abts_suite *suite);
+abts_suite *teststrnatcmp(abts_suite *suite);
+abts_suite *testtable(abts_suite *suite);
+abts_suite *testtemp(abts_suite *suite);
+abts_suite *testthread(abts_suite *suite);
+abts_suite *testtime(abts_suite *suite);
+abts_suite *testud(abts_suite *suite);
+abts_suite *testuser(abts_suite *suite);
+abts_suite *testvsn(abts_suite *suite);
+
+abts_suite *testescape(abts_suite *suite);
+abts_suite *teststrmatch(abts_suite *suite);
+abts_suite *testuri(abts_suite *suite);
+abts_suite *testuuid(abts_suite *suite);
+abts_suite *testbuckets(abts_suite *suite);
+abts_suite *testpass(abts_suite *suite);
+abts_suite *testbase64(abts_suite *suite);
+abts_suite *testmd4(abts_suite *suite);
+abts_suite *testmd5(abts_suite *suite);
+abts_suite *testcrypto(abts_suite *suite);
+abts_suite *testdbd(abts_suite *suite);
+abts_suite *testdate(abts_suite *suite);
+abts_suite *testmemcache(abts_suite *suite);
+abts_suite *testredis(abts_suite *suite);
+abts_suite *testreslist(abts_suite *suite);
+abts_suite *testqueue(abts_suite *suite);
+abts_suite *testxml(abts_suite *suite);
+abts_suite *testxlate(abts_suite *suite);
+abts_suite *testrmm(abts_suite *suite);
+abts_suite *testdbm(abts_suite *suite);
+abts_suite *testlfsabi(abts_suite *suite);
+abts_suite *testskiplist(abts_suite *suite);
+abts_suite *testsiphash(abts_suite *suite);
+
+#endif /* APR_TEST_INCLUDES */
diff --git a/test/testuuid.c b/test/testuuid.c
new file mode 100644
index 00000000000..f33adde11f5
--- /dev/null
+++ b/test/testuuid.c
@@ -0,0 +1,56 @@
+/* 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 "testutil.h"
+#include "apr_general.h"
+#include "apr_uuid.h"
+
+static void test_uuid_parse(abts_case *tc, void *data)
+{
+    apr_uuid_t uuid;
+    apr_uuid_t uuid2;
+    char buf[APR_UUID_FORMATTED_LENGTH + 1];
+
+    apr_uuid_get(&uuid);
+    apr_uuid_format(buf, &uuid);
+
+    apr_uuid_parse(&uuid2, buf);
+    ABTS_ASSERT(tc, "parse produced a different UUID",
+             memcmp(&uuid, &uuid2, sizeof(uuid)) == 0);
+}
+
+static void test_gen2(abts_case *tc, void *data)
+{
+    apr_uuid_t uuid;
+    apr_uuid_t uuid2;
+
+    /* generate two of them quickly */
+    apr_uuid_get(&uuid);
+    apr_uuid_get(&uuid2);
+
+    ABTS_ASSERT(tc, "generated the same UUID twice",
+             memcmp(&uuid, &uuid2, sizeof(uuid)) != 0);
+}
+
+abts_suite *testuuid(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite);
+
+    abts_run_test(suite, test_uuid_parse, NULL);
+    abts_run_test(suite, test_gen2, NULL);
+
+    return suite;
+}
diff --git a/test/testvsn.c b/test/testvsn.c
new file mode 100644
index 00000000000..dbc218a13fe
--- /dev/null
+++ b/test/testvsn.c
@@ -0,0 +1,56 @@
+/* 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 <stdio.h>
+
+#include "testutil.h"
+#include "apr_version.h"
+#include "apr_general.h"
+
+
+static void test_strings(abts_case *tc, void *data)
+{
+    ABTS_STR_EQUAL(tc, APR_VERSION_STRING, apr_version_string());
+}
+
+#ifdef APR_IS_DEV_VERSION
+# define IS_DEV 1
+#else
+# define IS_DEV 0
+#endif
+
+static void test_ints(abts_case *tc, void *data)
+{
+    apr_version_t vsn;
+
+    apr_version(&vsn);
+
+    ABTS_INT_EQUAL(tc, APR_MAJOR_VERSION, vsn.major);
+    ABTS_INT_EQUAL(tc, APR_MINOR_VERSION, vsn.minor);
+    ABTS_INT_EQUAL(tc, APR_PATCH_VERSION, vsn.patch);
+    ABTS_INT_EQUAL(tc, IS_DEV,            vsn.is_dev);
+}
+
+abts_suite *testvsn(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite)
+
+    abts_run_test(suite, test_strings, NULL);
+    abts_run_test(suite, test_ints, NULL);
+
+    return suite;
+}
+
diff --git a/test/testxlate.c b/test/testxlate.c
new file mode 100644
index 00000000000..e70196df6cc
--- /dev/null
+++ b/test/testxlate.c
@@ -0,0 +1,126 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_errno.h"
+#include "apr_general.h"
+#include "apr_strings.h"
+#include "apr_xlate.h"
+#include "abts.h"
+#include "testutil.h"
+
+#if APR_HAS_XLATE
+
+static const char test_utf8[] = "Edelwei\xc3\x9f";
+static const char test_utf7[] = "Edelwei+AN8-";
+static const char test_latin1[] = "Edelwei\xdf";
+static const char test_latin2[] = "Edelwei\xdf";
+
+static void test_conversion(abts_case *tc, apr_xlate_t *convset,
+                            const char *inbuf, const char *expected)
+{
+    static char buf[1024];
+    apr_size_t inbytes_left = strlen(inbuf);
+    apr_size_t outbytes_left = sizeof(buf) - 1;
+    apr_status_t rv;
+
+    rv = apr_xlate_conv_buffer(convset, inbuf, &inbytes_left, buf, &outbytes_left);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    if (rv != APR_SUCCESS)
+        return;
+
+    rv = apr_xlate_conv_buffer(convset, NULL, NULL, buf + sizeof(buf) -
+                               outbytes_left - 1, &outbytes_left);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    buf[sizeof(buf) - outbytes_left - 1] = '\0';
+
+    ABTS_STR_EQUAL(tc, expected, buf);
+}
+
+static void one_test(abts_case *tc, const char *cs1, const char *cs2,
+                     const char *str1, const char *str2,
+                     apr_pool_t *pool)
+{
+    apr_status_t rv;
+    apr_xlate_t *convset;
+
+    rv = apr_xlate_open(&convset, cs2, cs1, pool);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    if (rv != APR_SUCCESS)
+        return;
+
+    test_conversion(tc, convset, str1, str2);
+
+    rv = apr_xlate_close(convset);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+}
+
+/* some iconv implementations don't support all tested transforms;
+ * example: 8859-1 <-> 8859-2 using native Solaris iconv
+ */
+static int is_transform_supported(abts_case *tc, const char *cs1,
+                                  const char *cs2, apr_pool_t *pool) {
+    apr_status_t rv;
+    apr_xlate_t *convset;
+
+    rv = apr_xlate_open(&convset, cs2, cs1, pool);
+    if (rv != APR_SUCCESS) {
+        return 0;
+    }
+
+    rv = apr_xlate_close(convset);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    return 1;
+}
+
+static void test_transformation(abts_case *tc, void *data)
+{
+    /* 1. Identity transformation: UTF-8 -> UTF-8 */
+    one_test(tc, "UTF-8", "UTF-8", test_utf8, test_utf8, p);
+
+    /* 2. UTF-8 <-> ISO-8859-1 */
+    one_test(tc, "UTF-8", "ISO-8859-1", test_utf8, test_latin1, p);
+    one_test(tc, "ISO-8859-1", "UTF-8", test_latin1, test_utf8, p);
+
+    /* 3. ISO-8859-1 <-> ISO-8859-2, identity */
+    if (is_transform_supported(tc, "ISO-8859-1", "ISO-8859-2", p)) {
+        one_test(tc, "ISO-8859-1", "ISO-8859-2", test_latin1, test_latin2, p);
+    }
+    if (is_transform_supported(tc, "ISO-8859-2", "ISO-8859-1", p)) {
+        one_test(tc, "ISO-8859-2", "ISO-8859-1", test_latin2, test_latin1, p);
+    }
+
+    /* 4. Transformation using charset aliases */
+    one_test(tc, "UTF-8", "UTF-7", test_utf8, test_utf7, p);
+    one_test(tc, "UTF-7", "UTF-8", test_utf7, test_utf8, p);
+}
+
+#endif /* APR_HAS_XLATE */
+
+abts_suite *testxlate(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite);
+
+#if APR_HAS_XLATE
+    abts_run_test(suite, test_transformation, NULL);
+#endif
+
+    return suite;
+}
diff --git a/test/testxml.c b/test/testxml.c
new file mode 100644
index 00000000000..3d2542d4445
--- /dev/null
+++ b/test/testxml.c
@@ -0,0 +1,176 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_general.h"
+#include "apr_xml.h"
+#include "abts.h"
+#include "testutil.h"
+
+static apr_status_t create_dummy_file_error(abts_case *tc, apr_pool_t *p,
+                                            apr_file_t **fd)
+{
+    int i;
+    apr_status_t rv;
+    apr_off_t off = 0L;
+    char template[] = "data/testxmldummyerrorXXXXXX";
+
+    rv = apr_file_mktemp(fd, template, APR_FOPEN_CREATE | APR_FOPEN_TRUNCATE | APR_FOPEN_DELONCLOSE |
+                         APR_FOPEN_READ | APR_FOPEN_WRITE | APR_FOPEN_EXCL, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    if (rv != APR_SUCCESS)
+        return rv;
+
+    rv = apr_file_puts("<?xml version=\"1.0\" ?>\n<maryx>"
+                       "<had a=\"little\"/><lamb/>\n", *fd);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    for (i = 0; i < 5000; i++) {
+        rv = apr_file_puts("<hmm roast=\"lamb\" "
+                           "for=\"dinner\">yummy</hmm>\n", *fd);
+        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    }
+
+    rv = apr_file_puts("</mary>\n", *fd);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_file_seek(*fd, APR_SET, &off);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    return rv;
+}
+
+static apr_status_t create_dummy_file(abts_case *tc, apr_pool_t *p,
+                                      apr_file_t **fd)
+{
+    int i;
+    apr_status_t rv;
+    apr_off_t off = 0L;
+    char template[] = "data/testxmldummyXXXXXX";
+
+    rv = apr_file_mktemp(fd, template, APR_FOPEN_CREATE | APR_FOPEN_TRUNCATE | APR_FOPEN_DELONCLOSE |
+                         APR_FOPEN_READ | APR_FOPEN_WRITE | APR_FOPEN_EXCL, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    if (rv != APR_SUCCESS)
+        return rv;
+
+    rv = apr_file_puts("<?xml version=\"1.0\" ?>\n<mary>\n", *fd);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    for (i = 0; i < 5000; i++) {
+        rv = apr_file_puts("<hmm roast=\"lamb\" "
+                           "for=\"dinner &lt;&gt;&#x3D;\">yummy</hmm>\n", *fd);
+        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    }
+
+    rv = apr_file_puts("</mary>\n", *fd);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_file_seek(*fd, APR_SET, &off);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    return rv;
+}
+
+static void dump_xml(abts_case *tc, apr_xml_elem *e, int level)
+{
+    apr_xml_attr *a;
+    apr_xml_elem *ec;
+
+    if (level == 0) {
+        ABTS_STR_EQUAL(tc, "mary", e->name);
+    } else {
+        ABTS_STR_EQUAL(tc, "hmm", e->name);
+    }
+
+    if (e->attr) {
+        a = e->attr;
+        ABTS_PTR_NOTNULL(tc, a);
+        ABTS_STR_EQUAL(tc, "for", a->name);
+        ABTS_STR_EQUAL(tc, "dinner <>=", a->value);
+        a = a->next;
+        ABTS_PTR_NOTNULL(tc, a);
+        ABTS_STR_EQUAL(tc, "roast", a->name);
+        ABTS_STR_EQUAL(tc, "lamb", a->value);
+    }
+    if (e->first_child) {
+        ec = e->first_child;
+        while (ec) {
+            dump_xml(tc, ec, level + 1);
+            ec = ec->next;
+        }
+    }
+}
+
+static void test_xml_parser(abts_case *tc, void *data)
+{
+    apr_file_t *fd;
+    apr_xml_parser *parser;
+    apr_xml_doc *doc;
+    apr_status_t rv;
+
+    rv = create_dummy_file(tc, p, &fd);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    if (rv != APR_SUCCESS)
+        return;
+
+    rv = apr_xml_parse_file(p, &parser, &doc, fd, 2000);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    dump_xml(tc, doc->root, 0);
+
+    rv = apr_file_close(fd);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = create_dummy_file_error(tc, p, &fd);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    if (rv != APR_SUCCESS)
+        return;
+
+    rv = apr_xml_parse_file(p, &parser, &doc, fd, 2000);
+    ABTS_TRUE(tc, rv != APR_SUCCESS);
+}
+
+static void test_billion_laughs(abts_case *tc, void *data)
+{
+    apr_file_t *fd;
+    apr_xml_parser *parser;
+    apr_xml_doc *doc;
+    apr_status_t rv;
+
+    rv = apr_file_open(&fd, "data/billion-laughs.xml", 
+                       APR_FOPEN_READ, 0, p);
+    APR_ASSERT_SUCCESS(tc, "open billion-laughs.xml", rv);
+
+    rv = apr_xml_parse_file(p, &parser, &doc, fd, 2000);
+    ABTS_TRUE(tc, rv != APR_SUCCESS);
+
+    apr_file_close(fd);
+}
+
+abts_suite *testxml(abts_suite *suite)
+{
+    suite = ADD_SUITE(suite);
+
+    abts_run_test(suite, test_xml_parser, NULL);
+    abts_run_test(suite, test_billion_laughs, NULL);
+
+    return suite;
+}
diff --git a/test/timetest.dsp b/test/timetest.dsp
deleted file mode 100644
index 007376cfd52..00000000000
--- a/test/timetest.dsp
+++ /dev/null
@@ -1,91 +0,0 @@
-# Microsoft Developer Studio Project File - Name="timetest" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 5.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=timetest - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "timetest.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 "timetest.mak" CFG="timetest - Win32 Debug"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "timetest - Win32 Release" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE "timetest - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE 
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF  "$(CFG)" == "timetest - 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 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /W3 /GX /O2 /I "..\include" /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ..\Release\aprlib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"..\Release\timetest.exe"
-
-!ELSEIF  "$(CFG)" == "timetest - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "timetest"
-# PROP BASE Intermediate_Dir "timetest"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "timetest"
-# PROP Intermediate_Dir "timetest"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\include" /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
-# SUBTRACT CPP /YX /Yc /Yu
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 ..\Debug\aprlib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\Debug\timetest.exe" /pdbtype:sept
-
-!ENDIF 
-
-# Begin Target
-
-# Name "timetest - Win32 Release"
-# Name "timetest - Win32 Debug"
-# Begin Source File
-
-SOURCE=.\testtime.c
-# End Source File
-# End Target
-# End Project
diff --git a/test/tryread.c b/test/tryread.c
new file mode 100644
index 00000000000..843abe70aac
--- /dev/null
+++ b/test/tryread.c
@@ -0,0 +1,49 @@
+/* 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 "testflock.h"
+#include "apr_pools.h"
+#include "apr_file_io.h"
+#include "apr_general.h"
+#include "apr.h"
+
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+int main(int argc, const char * const *argv)
+{
+    apr_file_t *file;
+    apr_status_t status;
+    apr_pool_t *p;
+
+    apr_initialize();
+    apr_pool_create(&p, NULL);
+
+    if (apr_file_open(&file, TESTFILE, APR_FOPEN_WRITE, APR_FPROT_OS_DEFAULT, p)
+        != APR_SUCCESS) {
+        
+        exit(UNEXPECTED_ERROR);
+    }
+    status = apr_file_lock(file, APR_FLOCK_EXCLUSIVE | APR_FLOCK_NONBLOCK);
+    if (status == APR_SUCCESS) {
+        exit(SUCCESSFUL_READ);
+    }
+    if (APR_STATUS_IS_EAGAIN(status)) {
+        exit(FAILED_READ);
+    }
+    exit(UNEXPECTED_ERROR);
+}
diff --git a/threadproc/beos/Makefile.in b/threadproc/beos/Makefile.in
deleted file mode 100644
index c2b8c6f1728..00000000000
--- a/threadproc/beos/Makefile.in
+++ /dev/null
@@ -1,96 +0,0 @@
-#CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
-#LIBS=$(EXTRA_LIBS) $(LIBS1)
-#INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
-#LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
-
-CC=@CC@
-RANLIB=@RANLIB@
-CFLAGS=@CFLAGS@ @OPTIM@
-LIBS=@LIBS@
-LDFLAGS=@LDFLAGS@ $(LIBS)
-INCDIR=../../include
-INCDIR1=../../file_io/unix
-INCLUDES=-I$(INCDIR) -I$(INCDIR1) -I.
-
-LIB=libthreadproc.a
-
-OBJS=proc.o \
-	thread.o \
-	threadpriv.o \
-	threadproc_common.o \
-        procsup.o \
-        apr_proc_stub
-
-.c.o:
-	$(CC) $(CFLAGS) -c $(INCLUDES) $<
-
-all: $(LIB)
-
-apr_proc_stub:
-	$(CC) apr_proc_stub.c \
-	&& cp apr_proc_stub /boot/home/config/bin
-
-clean:
-	$(RM) -f *.o *.a *.so /boot/home/config/bin/apr_proc_stub apr_proc_stub
-
-distclean: clean
-	-$(RM) -f Makefile
-
-$(OBJS): Makefile
-
-$(LIB): $(OBJS)
-	$(RM) -f $@
-	$(AR) cr $@ $(OBJS)
-	$(RANLIB) $@
-
-#
-# We really don't expect end users to use this rule.  It works only with
-# gcc, and rebuilds Makefile.tmpl.  You have to re-run Configure after
-# using it.
-#
-depend:
-	cp Makefile.in Makefile.in.bak \
-	    && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.in > Makefile.new \
-	    && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \
-	    && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
-	           -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
-		> Makefile.in \
-	    && rm Makefile.new
-
-# DO NOT REMOVE
-apr_proc_stub.o: apr_proc_stub.c
-proc.o: proc.c threadproc.h $(INCDIR)/apr_thread_proc.h \
- $(INCDIR)/apr_file_io.h $(INCDIR)/apr_general.h \
- $(INCDIR)/apr.h $(INCDIR)/apr_errno.h \
- $(INCDIR)/apr_time.h ../../file_io/unix/fileio.h \
- $(INCDIR)/apr_private.h $(INCDIR)/apr_lib.h \
- $(INCDIR)/apr_portable.h $(INCDIR)/apr_network_io.h \
- $(INCDIR)/apr_lock.h
-procsup.o: procsup.c threadproc.h $(INCDIR)/apr_thread_proc.h \
- $(INCDIR)/apr_file_io.h $(INCDIR)/apr_general.h \
- $(INCDIR)/apr.h $(INCDIR)/apr_errno.h \
- $(INCDIR)/apr_time.h ../../file_io/unix/fileio.h \
- $(INCDIR)/apr_private.h $(INCDIR)/apr_lib.h \
- $(INCDIR)/apr_portable.h $(INCDIR)/apr_network_io.h \
- $(INCDIR)/apr_lock.h
-signals.o: signals.c threadproc.h $(INCDIR)/apr_thread_proc.h \
- $(INCDIR)/apr_file_io.h $(INCDIR)/apr_general.h \
- $(INCDIR)/apr.h $(INCDIR)/apr_errno.h \
- $(INCDIR)/apr_time.h ../../file_io/unix/fileio.h \
- $(INCDIR)/apr_private.h $(INCDIR)/apr_lib.h \
- $(INCDIR)/apr_portable.h $(INCDIR)/apr_network_io.h \
- $(INCDIR)/apr_lock.h
-thread.o: thread.c threadproc.h $(INCDIR)/apr_thread_proc.h \
- $(INCDIR)/apr_file_io.h $(INCDIR)/apr_general.h \
- $(INCDIR)/apr.h $(INCDIR)/apr_errno.h \
- $(INCDIR)/apr_time.h ../../file_io/unix/fileio.h \
- $(INCDIR)/apr_private.h $(INCDIR)/apr_lib.h \
- $(INCDIR)/apr_portable.h $(INCDIR)/apr_network_io.h \
- $(INCDIR)/apr_lock.h
-threadpriv.o: threadpriv.c threadproc.h \
- $(INCDIR)/apr_thread_proc.h $(INCDIR)/apr_file_io.h \
- $(INCDIR)/apr_general.h $(INCDIR)/apr.h \
- $(INCDIR)/apr_errno.h $(INCDIR)/apr_time.h \
- ../../file_io/unix/fileio.h $(INCDIR)/apr_private.h \
- $(INCDIR)/apr_lib.h $(INCDIR)/apr_portable.h \
- $(INCDIR)/apr_network_io.h $(INCDIR)/apr_lock.h
diff --git a/threadproc/beos/apr_proc_stub.c b/threadproc/beos/apr_proc_stub.c
index ff2ea87cd1d..011d793e317 100644
--- a/threadproc/beos/apr_proc_stub.c
+++ b/threadproc/beos/apr_proc_stub.c
@@ -1,55 +1,17 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 <kernel/OS.h>
diff --git a/threadproc/beos/proc.c b/threadproc/beos/proc.c
index adeb0db967e..e3698082f35 100644
--- a/threadproc/beos/proc.c
+++ b/threadproc/beos/proc.c
@@ -1,58 +1,26 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "threadproc.h"
+#include "apr_arch_threadproc.h"
+#include "apr_strings.h"
+
+/* Heavy on no'ops, here's what we want to pass if there is APR_NO_FILE
+ * requested for a specific child handle;
+ */
+static apr_file_t no_file = { NULL, -1, };
 
 struct send_pipe {
 	int in;
@@ -60,15 +28,15 @@ struct send_pipe {
 	int err;
 };
 
-ap_status_t ap_createprocattr_init(ap_procattr_t **new, ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_procattr_create(apr_procattr_t **new, apr_pool_t *pool)
 {
-    (*new) = (ap_procattr_t *)ap_palloc(cont, 
-              sizeof(ap_procattr_t));
+    (*new) = (apr_procattr_t *)apr_palloc(pool, 
+              sizeof(apr_procattr_t));
 
     if ((*new) == NULL) {
         return APR_ENOMEM;
     }
-    (*new)->cntxt = cont;
+    (*new)->pool = pool;
     (*new)->parent_in = NULL;
     (*new)->child_in = NULL;
     (*new)->parent_out = NULL;
@@ -81,71 +49,67 @@ ap_status_t ap_createprocattr_init(ap_procattr_t **new, ap_pool_t *cont)
     return APR_SUCCESS;
 }
 
-ap_status_t ap_setprocattr_io(ap_procattr_t *attr, ap_int32_t in, 
-                                 ap_int32_t out, ap_int32_t err)
+APR_DECLARE(apr_status_t) apr_procattr_io_set(apr_procattr_t *attr,
+                                              apr_int32_t in,
+                                              apr_int32_t out,
+                                              apr_int32_t err)
 {
-    ap_status_t status;
-    if (in != 0) {
-        if ((status = ap_create_pipe(&attr->child_in, &attr->parent_in, 
-                                   attr->cntxt)) != APR_SUCCESS) {
-            return status;
-        }
-        switch (in) {
-        case APR_FULL_BLOCK:
-            ap_block_pipe(attr->child_in);
-            ap_block_pipe(attr->parent_in);
-        case APR_PARENT_BLOCK:
-            ap_block_pipe(attr->parent_in);
-        case APR_CHILD_BLOCK:
-            ap_block_pipe(attr->child_in);
-        }
-    } 
-    if (out) {
-        if ((status = ap_create_pipe(&attr->parent_out, &attr->child_out, 
-                                   attr->cntxt)) != APR_SUCCESS) {
-            return status;
-        }
-        switch (out) {
-        case APR_FULL_BLOCK:
-            ap_block_pipe(attr->child_out);
-            ap_block_pipe(attr->parent_out);
-        case APR_PARENT_BLOCK:
-            ap_block_pipe(attr->parent_out);
-        case APR_CHILD_BLOCK:
-            ap_block_pipe(attr->child_out);
-        }
-    } 
-    if (err) {
-        if ((status = ap_create_pipe(&attr->parent_err, &attr->child_err, 
-                                   attr->cntxt)) != APR_SUCCESS) {
-            return status;
-        }
-        switch (err) {
-        case APR_FULL_BLOCK:
-            ap_block_pipe(attr->child_err);
-            ap_block_pipe(attr->parent_err);
-        case APR_PARENT_BLOCK:
-            ap_block_pipe(attr->parent_err);
-        case APR_CHILD_BLOCK:
-            ap_block_pipe(attr->child_err);
-        }
-    } 
+    apr_status_t rv;
+
+    if ((in != APR_NO_PIPE) && (in != APR_NO_FILE)) {
+        /* APR_CHILD_BLOCK maps to APR_WRITE_BLOCK, while
+         * APR_PARENT_BLOCK maps to APR_READ_BLOCK, so transpose 
+         * the CHILD/PARENT blocking flags for the stdin pipe.
+         * stdout/stderr map to the correct mode by default.
+         */
+        if (in == APR_CHILD_BLOCK)
+            in = APR_READ_BLOCK;
+        else if (in == APR_PARENT_BLOCK)
+            in = APR_WRITE_BLOCK;
+
+        if ((rv = apr_file_pipe_create_ex(&attr->child_in, &attr->parent_in,
+                                          in, attr->pool)) == APR_SUCCESS)
+            rv = apr_file_inherit_unset(attr->parent_in);
+        if (rv != APR_SUCCESS)
+            return rv;
+    }
+    else if (in == APR_NO_FILE)
+        attr->child_in = &no_file;
+
+    if ((out != APR_NO_PIPE) && (out != APR_NO_FILE)) {
+        if ((rv = apr_file_pipe_create_ex(&attr->parent_out, &attr->child_out,
+                                          out, attr->pool)) == APR_SUCCESS)
+            rv = apr_file_inherit_unset(attr->parent_out);
+        if (rv != APR_SUCCESS)
+            return rv;
+    }
+    else if (out == APR_NO_FILE)
+        attr->child_out = &no_file;
+
+    if ((err != APR_NO_PIPE) && (err != APR_NO_FILE)) {
+        if ((rv = apr_file_pipe_create_ex(&attr->parent_err, &attr->child_err,
+                                          err, attr->pool)) == APR_SUCCESS)
+            rv = apr_file_inherit_unset(attr->parent_err);
+        if (rv != APR_SUCCESS)
+            return rv;
+    }
+    else if (err == APR_NO_FILE)
+        attr->child_err = &no_file;
+
     return APR_SUCCESS;
 }
 
-ap_status_t ap_setprocattr_dir(ap_procattr_t *attr, 
-                                 const char *dir) 
+APR_DECLARE(apr_status_t) apr_procattr_dir_set(apr_procattr_t *attr, 
+                                               const char *dir) 
 {
     char * cwd;
-    if (strncmp("/",dir,1) != 0 ) {
+    if (dir[0] != '/') {
         cwd = (char*)malloc(sizeof(char) * PATH_MAX);
         getcwd(cwd, PATH_MAX);
-        strncat(cwd,"/\0",2);
-        strcat(cwd,dir);
-        attr->currdir = (char *)ap_pstrdup(attr->cntxt, cwd);
+        attr->currdir = (char *)apr_pstrcat(attr->pool, cwd, "/", dir, NULL);
         free(cwd);
     } else {
-        attr->currdir = (char *)ap_pstrdup(attr->cntxt, dir);
+        attr->currdir = (char *)apr_pstrdup(attr->pool, dir);
     }
     if (attr->currdir) {
         return APR_SUCCESS;
@@ -153,63 +117,113 @@ ap_status_t ap_setprocattr_dir(ap_procattr_t *attr,
     return APR_ENOMEM;
 }
 
-ap_status_t ap_setprocattr_cmdtype(ap_procattr_t *attr,
-                                     ap_cmdtype_e cmd) 
+APR_DECLARE(apr_status_t) apr_procattr_cmdtype_set(apr_procattr_t *attr,
+                                                   apr_cmdtype_e cmd) 
 {
     attr->cmdtype = cmd;
     return APR_SUCCESS;
 }
 
-ap_status_t ap_setprocattr_detach(ap_procattr_t *attr, ap_int32_t detach) 
+APR_DECLARE(apr_status_t) apr_procattr_detach_set(apr_procattr_t *attr, apr_int32_t detach) 
 {
     attr->detached = detach;
     return APR_SUCCESS;
 }
 
-ap_status_t ap_fork(ap_proc_t **proc, ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_proc_fork(apr_proc_t *proc, apr_pool_t *pool)
 {
     int pid;
     
-    (*proc) = (ap_proc_t *)ap_palloc(cont, sizeof(ap_proc_t));
-
     if ((pid = fork()) < 0) {
         return errno;
     }
     else if (pid == 0) {
-        (*proc)->pid = pid;
-        (*proc)->attr = NULL;
+		/* This is really ugly...
+		 * The semantics of BeOS's fork() are that areas (used for shared
+		 * memory) get COW'd :-( The only way we can make shared memory
+		 * work across fork() is therefore to find any areas that have
+		 * been created and then clone them into our address space.
+         * Thankfully only COW'd areas have the lock variable set at
+         * anything but 0, so we can use that to find the areas we need to
+         * copy. Of course what makes it even worse is that the loop through
+         * the area's will go into an infinite loop, eating memory and then
+         * eventually segfault unless we know when we reach then end of the
+         * "original" areas and stop. Why? Well, we delete the area and then
+         * add another to the end of the list...
+		 */
+		area_info ai;
+		int32 cookie = 0;
+        area_id highest = 0;
+		
+        while (get_next_area_info(0, &cookie, &ai) == B_OK)
+            if (ai.area	> highest)
+                highest = ai.area;
+        cookie = 0;
+        while (get_next_area_info(0, &cookie, &ai) == B_OK) {
+            if (ai.area > highest)
+                break;
+            if (ai.lock > 0) {
+                area_id original = find_area(ai.name);
+                delete_area(ai.area);
+                clone_area(ai.name, &ai.address, B_CLONE_ADDRESS,
+                           ai.protection, original);
+            }
+        }
+		
+        proc->pid = pid;
+        proc->in = NULL; 
+        proc->out = NULL; 
+        proc->err = NULL;
         return APR_INCHILD;
     }
-    (*proc)->pid = pid;
-    (*proc)->attr = NULL;
+    proc->pid = pid;
+    proc->in = NULL; 
+    proc->out = NULL; 
+    proc->err = NULL; 
     return APR_INPARENT;
 }
 
+APR_DECLARE(apr_status_t) apr_procattr_child_errfn_set(apr_procattr_t *attr,
+                                                       apr_child_errfn_t *errfn)
+{
+    /* won't ever be called on this platform, so don't save the function pointer */
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_procattr_error_check_set(apr_procattr_t *attr,
+                                                       apr_int32_t chk)
+{
+    /* won't ever be used on this platform, so don't save the flag */
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_procattr_addrspace_set(apr_procattr_t *attr,
+                                                       apr_int32_t addrspace)
+{
+    /* won't ever be used on this platform, so don't save the flag */
+    return APR_SUCCESS;
+}
 
-ap_status_t ap_create_process(ap_proc_t **new, const char *progname, 
-                              char *const args[], char **env, 
-                              ap_procattr_t *attr, ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_proc_create(apr_proc_t *new, const char *progname, 
+                                          const char * const *args,
+                                          const char * const *env, 
+                                          apr_procattr_t *attr, 
+                                          apr_pool_t *pool)
 {
     int i=0,nargs=0;
     char **newargs = NULL;
     thread_id newproc, sender;
-    char * buffer = NULL;
-    size_t bufsize = 0;
     struct send_pipe *sp;        
-	char * dir = NULL;
+    char * dir = NULL;
 	    
-    (*new) = (ap_proc_t *)ap_palloc(cont, sizeof(ap_proc_t));
-	sp = (struct send_pipe *)ap_palloc(cont, sizeof(struct send_pipe));
-
-    if ((*new) == NULL){
-    	return APR_ENOMEM;
-    }
-    
-    (*new)->cntxt = cont;
+    sp = (struct send_pipe *)apr_palloc(pool, sizeof(struct send_pipe));
 
-	sp->in  = attr->child_in?attr->child_in->filedes:-1;
-	sp->out = attr->child_out?attr->child_out->filedes:-1;
-	sp->err = attr->child_err?attr->child_err->filedes:-1;
+    new->in = attr->parent_in;
+    new->err = attr->parent_err;
+    new->out = attr->parent_out;
+    sp->in  = attr->child_in  ? attr->child_in->filedes  : FILENO_STDIN;
+    sp->out = attr->child_out ? attr->child_out->filedes : FILENO_STDOUT;
+    sp->err = attr->child_err ? attr->child_err->filedes : FILENO_STDERR;
 
     i = 0;
     while (args && args[i]) {
@@ -236,148 +250,205 @@ ap_status_t ap_create_process(ap_proc_t **new, const char *progname,
     }
     newargs[nargs] = NULL;
 
-    newproc = load_image(nargs, newargs, env);
+    /* ### we should be looking at attr->cmdtype in here... */
+
+    newproc = load_image(nargs, (const char**)newargs, (const char**)env);
 
     /* load_image copies the data so now we can free it... */
     while (--nargs >= 0)
         free (newargs[nargs]);
     free(newargs);
         
-    if ( newproc < B_NO_ERROR) {
+    if (newproc < B_NO_ERROR) {
         return errno;
     }
+
     resume_thread(newproc);
 
-    if (attr->child_in) {
-        ap_close(attr->child_in);
+    if (attr->child_in && (attr->child_in->filedes != -1)) {
+        apr_file_close(attr->child_in);
     }
-    if (attr->child_out) {
-        ap_close(attr->child_out);
+    if (attr->child_out && (attr->child_in->filedes != -1)) {
+        apr_file_close(attr->child_out);
     }
-    if (attr->child_err) {
-        ap_close(attr->child_err);
+    if (attr->child_err && (attr->child_in->filedes != -1)) {
+        apr_file_close(attr->child_err);
     }
 
     send_data(newproc, 0, (void*)sp, sizeof(struct send_pipe));
-    (*new)->pid = newproc;
+    new->pid = newproc;
 
     /* before we go charging on we need the new process to get to a 
      * certain point.  When it gets there it'll let us know and we
      * can carry on. */
     receive_data(&sender, (void*)NULL,0);
     
-    (*new)->attr = attr;
     return APR_SUCCESS;
 }
 
-ap_status_t ap_get_childin(ap_file_t **new, ap_proc_t *proc)
+APR_DECLARE(apr_status_t) apr_proc_wait_all_procs(apr_proc_t *proc,
+                                                  int *exitcode,
+                                                  apr_exit_why_e *exitwhy,
+                                                  apr_wait_how_e waithow, 
+                                                  apr_pool_t *p)
 {
-    (*new) = proc->attr->parent_in; 
-    return APR_SUCCESS;
-}
+    proc->pid = -1;
+    return apr_proc_wait(proc, exitcode, exitwhy, waithow);
+} 
 
-ap_status_t ap_get_childout(ap_file_t **new, ap_proc_t *proc)
+APR_DECLARE(apr_status_t) apr_proc_wait(apr_proc_t *proc,
+                                        int *exitcode, 
+                                        apr_exit_why_e *exitwhy,
+                                        apr_wait_how_e waithow)
 {
-    (*new) = proc->attr->parent_out;
-    return APR_SUCCESS;
-}
+    pid_t pstatus;
+    int waitpid_options = WUNTRACED;
+    int exit_int;
+    int ignore;
+    apr_exit_why_e ignorewhy;
+
+    if (exitcode == NULL) {
+        exitcode = &ignore;
+    }
+    if (exitwhy == NULL) {
+        exitwhy = &ignorewhy;
+    }
 
-ap_status_t ap_get_childerr(ap_file_t **new, ap_proc_t *proc)
-{
-    (*new) = proc->attr->parent_err; 
-    return APR_SUCCESS;
-}    
+    if (waithow != APR_WAIT) {
+        waitpid_options |= WNOHANG;
+    }
 
-ap_status_t ap_wait_proc(ap_proc_t *proc, 
-                           ap_wait_how_e wait)
-{
-    status_t exitval;
-    thread_info tinfo;
-    
-    if (!proc)
-        return APR_ENOPROC;
-    /* when we run processes we are actually running threads, so here
-       we'll wait on the thread dying... */
-    if (wait == APR_WAIT) {
-        if (wait_for_thread(proc->pid, &exitval) == B_OK) {
-            return APR_CHILD_DONE;
+    if ((pstatus = waitpid(proc->pid, &exit_int, waitpid_options)) > 0) {
+        proc->pid = pstatus;
+        if (WIFEXITED(exit_int)) {
+            *exitwhy = APR_PROC_EXIT;
+            *exitcode = WEXITSTATUS(exit_int);
+        }
+        else if (WIFSIGNALED(exit_int)) {
+            *exitwhy = APR_PROC_SIGNAL;
+            *exitcode = WTERMSIG(exit_int);
+        }
+        else {
+
+            /* unexpected condition */
+            return APR_EGENERAL;
         }
-        return errno;
-    }
-    /* if the thread is still alive then it's not done...
-       this won't hang or holdup the thread checking... */
-    if (get_thread_info(proc->pid, &tinfo) == B_BAD_VALUE) {
         return APR_CHILD_DONE;
     }
-    /* if we get this far it's still going... */
-    return APR_CHILD_NOTDONE;
+    else if (pstatus == 0) {
+        return APR_CHILD_NOTDONE;
+    }
+
+    return errno;
 } 
 
-ap_status_t ap_setprocattr_childin(ap_procattr_t *attr, ap_file_t *child_in,
-                                   ap_file_t *parent_in)
+APR_DECLARE(apr_status_t) apr_procattr_child_in_set(apr_procattr_t *attr, apr_file_t *child_in,
+                                   apr_file_t *parent_in)
 {
-    if (attr->child_in == NULL && attr->parent_in == NULL)
-        ap_create_pipe(&attr->child_in, &attr->parent_in, attr->cntxt);
-
-    if (child_in != NULL)
-        ap_dupfile(&attr->child_in, child_in, attr->cntxt);
+    apr_status_t rv;
+
+    if (attr->child_in == NULL && attr->parent_in == NULL
+            && child_in == NULL && parent_in == NULL)
+        if ((rv = apr_file_pipe_create(&attr->child_in, &attr->parent_in,
+                                       attr->pool)) == APR_SUCCESS)
+            rv = apr_file_inherit_unset(attr->parent_in);
+
+    if (child_in != NULL && rv == APR_SUCCESS) {
+        if (attr->child_in && (attr->child_in->filedes != -1))
+            rv = apr_file_dup2(attr->child_in, child_in, attr->pool);
+        else {
+            attr->child_in = NULL;
+            if ((rv = apr_file_dup(&attr->child_in, child_in, attr->pool))
+                    == APR_SUCCESS)
+                rv = apr_file_inherit_set(attr->child_in);
+        }
+    }
 
-    if (parent_in != NULL)
-        ap_dupfile(&attr->parent_in, parent_in, attr->cntxt);
+    if (parent_in != NULL && rv == APR_SUCCESS)
+        rv = apr_file_dup(&attr->parent_in, parent_in, attr->pool);
 
-    return APR_SUCCESS;
+    return rv;
 }
 
-ap_status_t ap_setprocattr_childout(ap_procattr_t *attr, ap_file_t *child_out,
-                                    ap_file_t *parent_out)
+APR_DECLARE(apr_status_t) apr_procattr_child_out_set(apr_procattr_t *attr, apr_file_t *child_out,
+                                                     apr_file_t *parent_out)
 {
-    if (attr->child_out == NULL && attr->parent_out == NULL)
-        ap_create_pipe(&attr->child_out, &attr->parent_out, attr->cntxt);
-
-    if (child_out != NULL)
-        ap_dupfile(&attr->child_out, child_out, attr->cntxt);
-
-    if (parent_out != NULL)
-        ap_dupfile(&attr->parent_out, parent_out, attr->cntxt);
+    apr_status_t rv;
+
+    if (attr->child_out == NULL && attr->parent_out == NULL
+           && child_out == NULL && parent_out == NULL)
+        if ((rv = apr_file_pipe_create(&attr->parent_out, &attr->child_out,
+                                       attr->pool)) == APR_SUCCESS)
+            rv = apr_file_inherit_unset(attr->parent_out);
+
+    if (child_out != NULL && rv == APR_SUCCESS) {
+        if (attr->child_out && (attr->child_out->filedes != -1))
+            rv = apr_file_dup2(attr->child_out, child_out, attr->pool);
+        else {
+            attr->child_out = NULL;
+            if ((rv = apr_file_dup(&attr->child_out, child_out, attr->pool))
+                    == APR_SUCCESS)
+                rv = apr_file_inherit_set(attr->child_out);
+        }
+    }
+  
+    if (parent_out != NULL && rv == APR_SUCCESS)
+        rv = apr_file_dup(&attr->parent_out, parent_out, attr->pool);
 
-    return APR_SUCCESS;
+    return rv;
 }
 
-ap_status_t ap_setprocattr_childerr(ap_procattr_t *attr, ap_file_t *child_err,
-                                   ap_file_t *parent_err)
+APR_DECLARE(apr_status_t) apr_procattr_child_err_set(apr_procattr_t *attr, apr_file_t *child_err,
+                                                     apr_file_t *parent_err)
 {
-    if (attr->child_err == NULL && attr->parent_err == NULL)
-        ap_create_pipe(&attr->child_err, &attr->parent_err, attr->cntxt);
-
-    if (child_err != NULL)
-        ap_dupfile(&attr->child_err, child_err, attr->cntxt);
+    apr_status_t rv;
+
+    if (attr->child_err == NULL && attr->parent_err == NULL
+           && child_err == NULL && parent_err == NULL)
+        if ((rv = apr_file_pipe_create(&attr->parent_err, &attr->child_err,
+                                       attr->pool)) == APR_SUCCESS)
+            rv = apr_file_inherit_unset(attr->parent_err);
+
+    if (child_err != NULL && rv == APR_SUCCESS) {
+        if (attr->child_err && (attr->child_err->filedes != -1))
+            rv = apr_file_dup2(attr->child_err, child_err, attr->pool);
+        else {
+            attr->child_err = NULL;
+            if ((rv = apr_file_dup(&attr->child_err, child_err, attr->pool))
+                    == APR_SUCCESS)
+                rv = apr_file_inherit_set(attr->child_err);
+        }
+    }
+  
+    if (parent_err != NULL && rv == APR_SUCCESS)
+        rv = apr_file_dup(&attr->parent_err, parent_err, attr->pool);
 
-    if (parent_err != NULL)
-        ap_dupfile(&attr->parent_err, parent_err, attr->cntxt);
+    return rv;
+}
 
-    return APR_SUCCESS;
+APR_DECLARE(apr_status_t) apr_procattr_limit_set(apr_procattr_t *attr, apr_int32_t what, 
+                                                  void *limit)
+{
+    return APR_ENOTIMPL;
 }
 
-ap_status_t ap_get_os_proc(ap_os_proc_t *theproc, ap_proc_t *proc)
+APR_DECLARE(apr_status_t) apr_procattr_user_set(apr_procattr_t *attr, 
+                                                const char *username,
+                                                const char *password)
 {
-    if (proc == NULL) {
-        return APR_ENOPROC;
-    }
-    *theproc = proc->pid;
-    return APR_SUCCESS;
+    return APR_ENOTIMPL;
 }
 
-ap_status_t ap_put_os_proc(ap_proc_t **proc, ap_os_proc_t *theproc, 
-                           ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_procattr_group_set(apr_procattr_t *attr,
+                                                 const char *groupname)
 {
-    if (cont == NULL) {
-        return APR_ENOPOOL;
-    }
-    if ((*proc) == NULL) {
-        (*proc) = (ap_proc_t *)ap_palloc(cont, sizeof(ap_proc_t));
-        (*proc)->cntxt = cont;
-    }
-    (*proc)->pid = *theproc;
-    return APR_SUCCESS;
-}              
+    return APR_ENOTIMPL;
+}
 
+APR_DECLARE(apr_status_t) apr_procattr_perms_set_register(apr_procattr_t *attr,
+                                                 apr_perms_setfn_t *perms_set_fn,
+                                                 void *data,
+                                                 apr_fileperms_t perms)
+{
+    return APR_ENOTIMPL;
+}
diff --git a/threadproc/beos/procsup.c b/threadproc/beos/procsup.c
deleted file mode 100644
index 0512855cd20..00000000000
--- a/threadproc/beos/procsup.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "threadproc.h"
-
-ap_status_t ap_detach(ap_proc_t **new, ap_pool_t *cont)
-{
-    int x;
-
-    (*new) = (ap_proc_t *)ap_palloc(cont, sizeof(ap_proc_t));
-    (*new)->cntxt = cont;
-    (*new)->attr = NULL;
-
-    chdir("/");
-
-    if (((*new)->pid = setsid()) == -1) {
-        return errno;
-    }
-
-    /* close out the standard file descriptors */
-    if (freopen("/dev/null", "r", stdin) == NULL) {
-        return errno;
-        /* continue anyhow -- note we can't close out descriptor 0 because we
-         * have nothing to replace it with, and if we didn't have a descriptor
-         * 0 the next file would be created with that value ... leading to
-         * havoc.
-         */
-    }
-    if (freopen("/dev/null", "w", stdout) == NULL) {
-        return errno;
-    }
-     /* We are going to reopen this again in a little while to the error
-      * log file, but better to do it twice and suffer a small performance
-      * hit for consistancy than not reopen it here.
-      */
-    if (freopen("/dev/null", "w", stderr) == NULL) {
-        return errno;
-    }
-}
-
-ap_status_t ap_get_procdata(char *key, void *data, ap_proc_t *proc)
-{
-    if (proc != NULL) {
-        return ap_get_userdata(data, key, proc->cntxt);
-    }
-    else {
-        data = NULL;
-        return APR_ENOPROC;
-    }
-}
-
-ap_status_t ap_set_procdata(void *data, char *key, 
-                            ap_status_t (*cleanup) (void *), 
-                            ap_proc_t *proc)
-{
-    if (proc != NULL) {
-        return ap_set_userdata(data, key, cleanup, proc->cntxt);
-    }
-    else {
-        data = NULL;
-        return APR_ENOPROC;
-    }
-}
diff --git a/threadproc/beos/thread.c b/threadproc/beos/thread.c
index 85988eb93ae..01bc7a9732a 100644
--- a/threadproc/beos/thread.c
+++ b/threadproc/beos/thread.c
@@ -1,79 +1,38 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "threadproc.h"
+#include "apr_arch_threadproc.h"
+#include "apr_portable.h"
 
-ap_status_t ap_create_threadattr(ap_threadattr_t **new, ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_threadattr_create(apr_threadattr_t **new, apr_pool_t *pool)
 {
-    ap_status_t stat;
-  
-    (*new) = (ap_threadattr_t *)ap_palloc(cont, 
-              sizeof(ap_threadattr_t));
-    (*new)->attr = (int32)ap_palloc(cont, 
-                    sizeof(int32));
+    (*new) = (apr_threadattr_t *)apr_palloc(pool, 
+              sizeof(apr_threadattr_t));
 
     if ((*new) == NULL) {
         return APR_ENOMEM;
     }
 
-    (*new)->cntxt = cont;
+    (*new)->pool = pool;
 	(*new)->attr = (int32)B_NORMAL_PRIORITY;
 
     return APR_SUCCESS;
 }
 
-ap_status_t ap_setthreadattr_detach(ap_threadattr_t *attr, ap_int32_t on)
+APR_DECLARE(apr_status_t) apr_threadattr_detach_set(apr_threadattr_t *attr, apr_int32_t on)
 {
 	if (on == 1){
 		attr->detached = 1;
@@ -83,7 +42,7 @@ ap_status_t ap_setthreadattr_detach(ap_threadattr_t *attr, ap_int32_t on)
     return APR_SUCCESS;
 }
 
-ap_status_t ap_getthreadattr_detach(ap_threadattr_t *attr)
+APR_DECLARE(apr_status_t) apr_threadattr_detach_get(apr_threadattr_t *attr)
 {
 	if (attr->detached == 1){
 		return APR_DETACH;
@@ -91,24 +50,44 @@ ap_status_t ap_getthreadattr_detach(ap_threadattr_t *attr)
 	return APR_NOTDETACH;
 }
 
-ap_status_t ap_create_thread(ap_thread_t **new, ap_threadattr_t *attr,
-                             ap_thread_start_t func, void *data,
-                             ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_threadattr_stacksize_set(apr_threadattr_t *attr,
+                                                       apr_size_t stacksize)
+{
+    return APR_ENOTIMPL;
+}
+
+APR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr,
+                                                       apr_size_t size)
+{
+    return APR_ENOTIMPL;
+}
+
+static void *dummy_worker(void *opaque)
+{
+    apr_thread_t *thd = (apr_thread_t*)opaque;
+    void *ret;
+
+    apr_pool_owner_set(thd->pool, 0);
+    ret = thd->func(thd, thd->data);
+    apr_pool_destroy(thd->pool);
+    return ret;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new, apr_threadattr_t *attr,
+                                            apr_thread_start_t func, void *data,
+                                            apr_pool_t *pool)
 {
     int32 temp;
-    ap_status_t stat;
+    apr_status_t stat;
     
-    (*new) = (ap_thread_t *)ap_palloc(cont, sizeof(ap_thread_t));
+    (*new) = (apr_thread_t *)apr_palloc(pool, sizeof(apr_thread_t));
     if ((*new) == NULL) {
         return APR_ENOMEM;
     }
 
-	(*new)->td = (thread_id) ap_palloc(cont, sizeof(thread_id));
-    if ((*new)->td == (thread_id)NULL) {
-        return APR_ENOMEM;
-    }
-
-    (*new)->cntxt = cont;
+    (*new)->data = data;
+    (*new)->func = func;
+    (*new)->exitval = -1;
 
     /* First we create the new thread...*/
 	if (attr)
@@ -116,12 +95,16 @@ ap_status_t ap_create_thread(ap_thread_t **new, ap_threadattr_t *attr,
 	else
 	    temp = B_NORMAL_PRIORITY;
 
-    stat = ap_create_pool(&(*new)->cntxt, cont);
+    stat = apr_pool_create(&(*new)->pool, pool);
     if (stat != APR_SUCCESS) {
         return stat;
     }
 
-    (*new)->td = spawn_thread((thread_func)func, "apr thread", temp, data);
+    (*new)->td = spawn_thread((thread_func)dummy_worker, 
+                              "apr thread", 
+                              temp, 
+                              (*new));
+
     /* Now we try to run it...*/
     if (resume_thread((*new)->td) == B_NO_ERROR) {
         return APR_SUCCESS;
@@ -131,23 +114,46 @@ ap_status_t ap_create_thread(ap_thread_t **new, ap_threadattr_t *attr,
     } 
 }
 
-ap_status_t ap_thread_exit(ap_thread_t *thd, ap_status_t *retval)
+APR_DECLARE(apr_os_thread_t) apr_os_thread_current(void)
 {
-    ap_destroy_pool(thd->cntxt);
-	exit_thread ((status_t)retval);
+    return find_thread(NULL);
 }
 
-ap_status_t ap_thread_join(ap_status_t *retval, ap_thread_t *thd)
+int apr_os_thread_equal(apr_os_thread_t tid1, apr_os_thread_t tid2)
 {
-    if (wait_for_thread(thd->td,(void *)&retval) == B_NO_ERROR) {
+    return tid1 == tid2;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_exit(apr_thread_t *thd, apr_status_t retval)
+{
+    apr_pool_destroy(thd->pool);
+    thd->exitval = retval;
+    exit_thread ((status_t)(retval));
+    /* This will never be reached... */
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_join(apr_status_t *retval, apr_thread_t *thd)
+{
+    status_t rv = 0, ret;
+    ret = wait_for_thread(thd->td, &rv);
+    if (ret == B_NO_ERROR) {
+        *retval = rv;
         return APR_SUCCESS;
     }
     else {
-        return errno;
+        /* if we've missed the thread's death, did we set an exit value prior
+         * to it's demise?  If we did return that.
+         */
+        if (thd->exitval != -1) {
+            *retval = thd->exitval;
+            return APR_SUCCESS;
+        } else 
+            return ret;
     }
 }
 
-ap_status_t ap_thread_detach(ap_thread_t *thd)
+APR_DECLARE(apr_status_t) apr_thread_detach(apr_thread_t *thd)
 {
 	if (suspend_thread(thd->td) == B_NO_ERROR){
         return APR_SUCCESS;
@@ -156,3 +162,81 @@ ap_status_t ap_thread_detach(ap_thread_t *thd)
         return errno;
     }
 }
+
+void apr_thread_yield()
+{
+}
+
+APR_DECLARE(apr_status_t) apr_thread_data_get(void **data, const char *key, apr_thread_t *thread)
+{
+    return apr_pool_userdata_get(data, key, thread->pool);
+}
+
+APR_DECLARE(apr_status_t) apr_thread_data_set(void *data, const char *key,
+                                              apr_status_t (*cleanup) (void *),
+                                              apr_thread_t *thread)
+{
+    return apr_pool_userdata_set(data, key, cleanup, thread->pool);
+}
+
+APR_DECLARE(apr_status_t) apr_os_thread_get(apr_os_thread_t **thethd, apr_thread_t *thd)
+{
+    *thethd = &thd->td;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_os_thread_put(apr_thread_t **thd, apr_os_thread_t *thethd, 
+                                            apr_pool_t *pool)
+{
+    if (pool == NULL) {
+        return APR_ENOPOOL;
+    }
+    if ((*thd) == NULL) {
+        (*thd) = (apr_thread_t *)apr_pcalloc(pool, sizeof(apr_thread_t));
+        (*thd)->pool = pool;
+    }
+    (*thd)->td = *thethd;
+    return APR_SUCCESS;
+}
+
+static apr_status_t thread_once_cleanup(void *vcontrol)
+{
+    apr_thread_once_t *control = (apr_thread_once_t *)vcontrol;
+
+    if (control->sem) {
+        release_sem(control->sem);
+        delete_sem(control->sem);
+    }
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_once_init(apr_thread_once_t **control,
+                                               apr_pool_t *p)
+{
+    int rc;
+    *control = (apr_thread_once_t *)apr_pcalloc(p, sizeof(apr_thread_once_t));
+    (*control)->hit = 0; /* we haven't done it yet... */
+    rc = ((*control)->sem = create_sem(1, "thread_once"));
+    if (rc < 0)
+        return rc;
+
+    apr_pool_cleanup_register(p, control, thread_once_cleanup, apr_pool_cleanup_null);
+    return APR_SUCCESS;
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_thread_once(apr_thread_once_t *control, 
+                                          void (*func)(void))
+{
+    if (!control->hit) {
+        if (acquire_sem(control->sem) == B_OK) {
+            control->hit = 1;
+            func();
+        }
+    }
+    return APR_SUCCESS;
+}
+
+APR_POOL_IMPLEMENT_ACCESSOR(thread)
diff --git a/threadproc/beos/threadcancel.c b/threadproc/beos/threadcancel.c
deleted file mode 100644
index 94a7e9407c4..00000000000
--- a/threadproc/beos/threadcancel.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "threadproc.h"
-
-
-ap_status_t ap_cancel_thread(ap_thread_t *thd)
-{
-    if (kill_thread(thd->td) == 0) {
-        return APR_SUCCESS;
-    }
-    else {
-        return errno;
-    }
-}
-
-    
-ap_status_t ap_setcanceltype(ap_int32_t type, ap_pool_t *cont)
-{
-/*    if (pthread_setcanceltype(type, NULL) == 0) {*/
-        return APR_SUCCESS;
-/*    }
-    else {
-        return APR_FAILURE;
-    }*/
-}
-
-ap_status_t ap_setcancelstate(ap_int32_t type, ap_pool_t *cont)
-{
-/*    if (pthread_setcanceltype(type, NULL) == 0) {*/
-        return APR_SUCCESS;
-/*    }
-    else {
-        return APR_FAILURE;
-    }*/
-}
-
diff --git a/threadproc/beos/threadpriv.c b/threadproc/beos/threadpriv.c
index bb81fe23e2c..442235f7dd6 100644
--- a/threadproc/beos/threadpriv.c
+++ b/threadproc/beos/threadpriv.c
@@ -1,72 +1,34 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "threadproc.h"
+#include "apr_arch_threadproc.h"
 
 static struct beos_key key_table[BEOS_MAX_DATAKEYS];
 static struct beos_private_data *beos_data[BEOS_MAX_DATAKEYS];
 static sem_id lock;
 
-ap_status_t ap_create_thread_private(ap_threadkey_t **key,
-                                void (*dest)(void *), ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_threadkey_private_create(apr_threadkey_t **key,
+                                       void (*dest)(void *), apr_pool_t *pool)
 {
-    (*key) = (ap_threadkey_t *)ap_palloc(cont, sizeof(ap_threadkey_t));
+    (*key) = (apr_threadkey_t *)apr_palloc(pool, sizeof(apr_threadkey_t));
     if ((*key) == NULL) {
         return APR_ENOMEM;
     }
 
-    (*key)->cntxt = cont;
+    (*key)->pool = pool;
     	
 	acquire_sem(lock);
 	for ((*key)->key=0; (*key)->key < BEOS_MAX_DATAKEYS; (*key)->key++){
@@ -82,7 +44,7 @@ ap_status_t ap_create_thread_private(ap_threadkey_t **key,
     return APR_ENOMEM;
 }
 
-ap_status_t ap_get_thread_private(void **new, ap_threadkey_t *key)
+APR_DECLARE(apr_status_t) apr_threadkey_private_get(void **new, apr_threadkey_t *key)
 {
 	thread_id tid;
 	int i, index=0;
@@ -114,15 +76,15 @@ ap_status_t ap_get_thread_private(void **new, ap_threadkey_t *key)
 	return APR_SUCCESS;
 }
 
-ap_status_t ap_set_thread_private(void *priv, ap_threadkey_t *key)
+APR_DECLARE(apr_status_t) apr_threadkey_private_set(void *priv, apr_threadkey_t *key)
 {
 	thread_id tid;
-	int i,index = 0, ret;
+	int i,index = 0, ret = 0;
 
 	tid = find_thread(NULL);	
 	for (i=0; i < BEOS_MAX_DATAKEYS; i++){
 		if (beos_data[i]->data){
-			if (beos_data[i]->td = tid){index = i;}
+			if (beos_data[i]->td == tid){index = i;}
 		}
 	}
 	if (index==0){
@@ -169,7 +131,7 @@ ap_status_t ap_set_thread_private(void *priv, ap_threadkey_t *key)
 	return APR_ENOMEM;
 }
 
-ap_status_t ap_delete_thread_private(ap_threadkey_t *key)
+APR_DECLARE(apr_status_t) apr_threadkey_private_delete(apr_threadkey_t *key)
 {
 	if (key->key < BEOS_MAX_DATAKEYS){
 		acquire_sem(key_table[key->key].lock);
@@ -183,3 +145,36 @@ ap_status_t ap_delete_thread_private(ap_threadkey_t *key)
 	}
 	return APR_SUCCESS;
 }
+
+APR_DECLARE(apr_status_t) apr_threadkey_data_get(void **data, const char *key,
+                                                 apr_threadkey_t *threadkey)
+{
+    return apr_pool_userdata_get(data, key, threadkey->pool);
+}
+
+APR_DECLARE(apr_status_t) apr_threadkey_data_set(void *data, const char *key,
+                                                 apr_status_t (*cleanup) (void *),
+                                                 apr_threadkey_t *threadkey)
+{
+    return apr_pool_userdata_set(data, key, cleanup, threadkey->pool);
+}
+
+APR_DECLARE(apr_status_t) apr_os_threadkey_get(apr_os_threadkey_t *thekey, apr_threadkey_t *key)
+{
+    *thekey = key->key;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_os_threadkey_put(apr_threadkey_t **key, 
+                                               apr_os_threadkey_t *thekey, apr_pool_t *pool)
+{
+    if (pool == NULL) {
+        return APR_ENOPOOL;
+    }
+    if ((*key) == NULL) {
+        (*key) = (apr_threadkey_t *)apr_pcalloc(pool, sizeof(apr_threadkey_t));
+        (*key)->pool = pool;
+    }
+    (*key)->key = *thekey;
+    return APR_SUCCESS;
+}
diff --git a/threadproc/beos/threadproc.h b/threadproc/beos/threadproc.h
deleted file mode 100644
index 4588105d15f..00000000000
--- a/threadproc/beos/threadproc.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "apr_thread_proc.h"
-#include "fileio.h"
-#include "apr_file_io.h"
-#include "apr_thread_proc.h"
-#include "apr_file_io.h"
-#include "apr_general.h"
-#include "apr_portable.h"
-#include  <kernel/OS.h>
-#include <signal.h>
-#include <string.h>
-#include <sys/wait.h>
-
-#ifndef THREAD_PROC_H
-#define THREAD_PROC_H
-
-#define SHELL_PATH "/bin/sh"
-
-#define PTHREAD_CANCEL_AYNCHRONOUS  CANCEL_ASYNCH; 
-#define PTHREAD_CANCEL_DEFERRED     CANCEL_DEFER; 
-                                   
-#define PTHREAD_CANCEL_ENABLE       CANCEL_ENABLE; 
-#define PTHREAD_CANCEL_DISABLE      CANCEL_DISABLE; 
-
-#define BEOS_MAX_DATAKEYS	128
-
-struct ap_thread_t {
-    ap_pool_t *cntxt;
-    thread_id td;
-};
-
-struct ap_threadattr_t {
-    ap_pool_t *cntxt;
-    int32 attr;
-    int detached;
-    int joinable;
-};
-
-struct ap_threadkey_t {
-    ap_pool_t *cntxt;
-	int32  key;
-};
-
-struct beos_private_data {
-	const void ** data;
-	int count;
-	volatile thread_id  td;
-};
-
-struct beos_key {
-	int  assigned;
-	int  count;
-	sem_id  lock;
-	int32  ben_lock;
-	void (* destructor) ();
-};
-
-struct ap_procattr_t {
-    ap_pool_t *cntxt;
-    ap_file_t *parent_in;
-    ap_file_t *child_in;
-    ap_file_t *parent_out;
-    ap_file_t *child_out;
-    ap_file_t *parent_err;
-    ap_file_t *child_err;
-    char *currdir;
-    ap_int32_t cmdtype;
-    ap_int32_t detached;
-};
-
-struct ap_proc_t {
-    ap_pool_t *cntxt;
-    thread_id pid;
-    struct ap_procattr_t *attr;
-};
-
-/* we need a structure to pass off to the thread that will run any
- * new process we create */
-
-#endif  /* ! THREAD_PROC_H */
-
diff --git a/threadproc/beos/threadproc_common.c b/threadproc/beos/threadproc_common.c
index 548344fd3bd..95e16254400 100644
--- a/threadproc/beos/threadproc_common.c
+++ b/threadproc/beos/threadproc_common.c
@@ -1,58 +1,21 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+/* 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.
  */
 
 /* As the signal code is identical, use the unix version to reduce
    code duplication */
-   
 #include "../unix/signals.c"
+#include "../unix/procsup.c"
+   
diff --git a/threadproc/netware/proc.c b/threadproc/netware/proc.c
new file mode 100644
index 00000000000..f5d24b21b5b
--- /dev/null
+++ b/threadproc/netware/proc.c
@@ -0,0 +1,515 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_arch_threadproc.h"
+#include "apr_arch_file_io.h"
+#include "apr_strings.h"
+#include "apr_portable.h"
+
+#include <proc.h>
+
+/* Heavy on no'ops, here's what we want to pass if there is APR_NO_FILE
+ * requested for a specific child handle;
+ */
+static apr_file_t no_file = { NULL, -1, };
+
+static apr_status_t apr_netware_proc_cleanup(void *theproc)
+{
+    apr_proc_t *proc = theproc;
+    int exit_int;
+    int waitpid_options = WUNTRACED | WNOHANG;
+
+    if (proc->pid > 0) {
+        waitpid(proc->pid, &exit_int, waitpid_options);
+    }
+
+/* NXVmDestroy(proc->pid); */
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_procattr_create(apr_procattr_t **new,apr_pool_t *pool)
+{
+    (*new) = (apr_procattr_t *)apr_pcalloc(pool, sizeof(apr_procattr_t));
+
+    if ((*new) == NULL) {
+        return APR_ENOMEM;
+    }
+    (*new)->pool = pool;
+    (*new)->cmdtype = APR_PROGRAM;
+    /* Default to a current path since NetWare doesn't handle it very well */
+    apr_filepath_get(&((*new)->currdir), APR_FILEPATH_NATIVE, pool);
+    (*new)->detached = 1;
+    return APR_SUCCESS;
+
+}
+
+APR_DECLARE(apr_status_t) apr_procattr_io_set(apr_procattr_t *attr,
+                                              apr_int32_t in,
+                                              apr_int32_t out,
+                                              apr_int32_t err)
+{
+    apr_status_t rv;
+
+    if ((in != APR_NO_PIPE) && (in != APR_NO_FILE)) {
+        /* APR_CHILD_BLOCK maps to APR_WRITE_BLOCK, while
+         * APR_PARENT_BLOCK maps to APR_READ_BLOCK, so transpose 
+         * the CHILD/PARENT blocking flags for the stdin pipe.
+         * stdout/stderr map to the correct mode by default.
+         */
+        if (in == APR_CHILD_BLOCK)
+            in = APR_READ_BLOCK;
+        else if (in == APR_PARENT_BLOCK)
+            in = APR_WRITE_BLOCK;
+
+        if ((rv = apr_file_pipe_create_ex(&attr->child_in, &attr->parent_in,
+                                          in, attr->pool)) == APR_SUCCESS)
+            rv = apr_file_inherit_unset(attr->parent_in);
+        if (rv != APR_SUCCESS)
+            return rv;
+    }
+    else if (in == APR_NO_FILE)
+        attr->child_in = &no_file;
+
+    if ((out != APR_NO_PIPE) && (out != APR_NO_FILE)) {
+        if ((rv = apr_file_pipe_create_ex(&attr->parent_out, &attr->child_out,
+                                          out, attr->pool)) == APR_SUCCESS)
+            rv = apr_file_inherit_unset(attr->parent_out);
+        if (rv != APR_SUCCESS)
+            return rv;
+    }
+    else if (out == APR_NO_FILE)
+        attr->child_out = &no_file;
+
+    if ((err != APR_NO_PIPE) && (err != APR_NO_FILE)) {
+        if ((rv = apr_file_pipe_create_ex(&attr->parent_err, &attr->child_err,
+                                          err, attr->pool)) == APR_SUCCESS)
+            rv = apr_file_inherit_unset(attr->parent_err);
+        if (rv != APR_SUCCESS)
+            return rv;
+    }
+    else if (err == APR_NO_FILE)
+        attr->child_err = &no_file;
+
+    return APR_SUCCESS;
+}
+
+
+APR_DECLARE(apr_status_t) apr_procattr_child_in_set(apr_procattr_t *attr, apr_file_t *child_in,
+                                   apr_file_t *parent_in)
+{
+    apr_status_t rv = APR_SUCCESS;
+
+    if (attr->child_in == NULL && attr->parent_in == NULL
+            && child_in == NULL && parent_in == NULL)
+        if ((rv = apr_file_pipe_create(&attr->child_in, &attr->parent_in,
+                                       attr->pool)) == APR_SUCCESS)
+            rv = apr_file_inherit_unset(attr->parent_in);
+
+    if (child_in != NULL && rv == APR_SUCCESS) {
+        if (attr->child_in && (attr->child_in->filedes != -1))
+            rv = apr_file_dup2(attr->child_in, child_in, attr->pool);
+        else {
+            attr->child_in = NULL;
+            if ((rv = apr_file_dup(&attr->child_in, child_in, attr->pool))
+                    == APR_SUCCESS)
+                rv = apr_file_inherit_set(attr->child_in);
+        }
+    }
+
+    if (parent_in != NULL && rv == APR_SUCCESS) {
+        rv = apr_file_dup(&attr->parent_in, parent_in, attr->pool);
+    }
+
+    return rv;
+}
+
+
+APR_DECLARE(apr_status_t) apr_procattr_child_out_set(apr_procattr_t *attr, apr_file_t *child_out,
+                                                     apr_file_t *parent_out)
+{
+    apr_status_t rv = APR_SUCCESS;
+
+    if (attr->child_out == NULL && attr->parent_out == NULL
+           && child_out == NULL && parent_out == NULL)
+        if ((rv = apr_file_pipe_create(&attr->parent_out, &attr->child_out,
+                                       attr->pool)) == APR_SUCCESS)
+            rv = apr_file_inherit_unset(attr->parent_out);
+
+    if (child_out != NULL && rv == APR_SUCCESS) {
+        if (attr->child_out && (attr->child_out->filedes != -1))
+            rv = apr_file_dup2(attr->child_out, child_out, attr->pool);
+        else {
+            attr->child_out = NULL;
+            if ((rv = apr_file_dup(&attr->child_out, child_out, attr->pool))
+                    == APR_SUCCESS)
+                rv = apr_file_inherit_set(attr->child_out);
+        }
+    }
+  
+    if (parent_out != NULL && rv == APR_SUCCESS) {
+        rv = apr_file_dup(&attr->parent_out, parent_out, attr->pool);
+    }
+
+    return rv;
+}
+
+
+APR_DECLARE(apr_status_t) apr_procattr_child_err_set(apr_procattr_t *attr, apr_file_t *child_err,
+                                                     apr_file_t *parent_err)
+{
+    apr_status_t rv = APR_SUCCESS;
+
+    if (attr->child_err == NULL && attr->parent_err == NULL
+           && child_err == NULL && parent_err == NULL)
+        if ((rv = apr_file_pipe_create(&attr->parent_err, &attr->child_err,
+                                       attr->pool)) == APR_SUCCESS)
+            rv = apr_file_inherit_unset(attr->parent_err);
+
+    if (child_err != NULL && rv == APR_SUCCESS) {
+        if (attr->child_err && (attr->child_err->filedes != -1))
+            rv = apr_file_dup2(attr->child_err, child_err, attr->pool);
+        else {
+            attr->child_err = NULL;
+            if ((rv = apr_file_dup(&attr->child_err, child_err, attr->pool))
+                    == APR_SUCCESS)
+                rv = apr_file_inherit_set(attr->child_err);
+        }
+    }
+  
+    if (parent_err != NULL && rv == APR_SUCCESS) {
+        rv = apr_file_dup(&attr->parent_err, parent_err, attr->pool);
+    }
+
+    return rv;
+}
+
+
+APR_DECLARE(apr_status_t) apr_procattr_dir_set(apr_procattr_t *attr, 
+                               const char *dir) 
+{
+    return apr_filepath_merge(&attr->currdir, NULL, dir, 
+                              APR_FILEPATH_NATIVE, attr->pool);
+}
+
+APR_DECLARE(apr_status_t) apr_procattr_cmdtype_set(apr_procattr_t *attr,
+                                     apr_cmdtype_e cmd) 
+{
+    /* won't ever be called on this platform, so don't save the function pointer */
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_procattr_detach_set(apr_procattr_t *attr, apr_int32_t detach) 
+{
+    attr->detached = detach;
+    return APR_SUCCESS;
+}
+
+#if APR_HAS_FORK
+APR_DECLARE(apr_status_t) apr_proc_fork(apr_proc_t *proc, apr_pool_t *pool)
+{
+    int pid;
+    
+    if ((pid = fork()) < 0) {
+        return errno;
+    }
+    else if (pid == 0) {
+        proc->pid = pid;
+        proc->in = NULL; 
+        proc->out = NULL; 
+        proc->err = NULL; 
+        return APR_INCHILD;
+    }
+    proc->pid = pid;
+    proc->in = NULL; 
+    proc->out = NULL; 
+    proc->err = NULL; 
+    return APR_INPARENT;
+}
+#endif
+
+static apr_status_t limit_proc(apr_procattr_t *attr)
+{
+#if APR_HAVE_STRUCT_RLIMIT && APR_HAVE_SETRLIMIT
+#ifdef RLIMIT_CPU
+    if (attr->limit_cpu != NULL) {
+        if ((setrlimit(RLIMIT_CPU, attr->limit_cpu)) != 0) {
+            return errno;
+        }
+    }
+#endif
+#ifdef RLIMIT_NPROC
+    if (attr->limit_nproc != NULL) {
+        if ((setrlimit(RLIMIT_NPROC, attr->limit_nproc)) != 0) {
+            return errno;
+        }
+    }
+#endif
+#if defined(RLIMIT_AS)
+    if (attr->limit_mem != NULL) {
+        if ((setrlimit(RLIMIT_AS, attr->limit_mem)) != 0) {
+            return errno;
+        }
+    }
+#elif defined(RLIMIT_DATA)
+    if (attr->limit_mem != NULL) {
+        if ((setrlimit(RLIMIT_DATA, attr->limit_mem)) != 0) {
+            return errno;
+        }
+    }
+#elif defined(RLIMIT_VMEM)
+    if (attr->limit_mem != NULL) {
+        if ((setrlimit(RLIMIT_VMEM, attr->limit_mem)) != 0) {
+            return errno;
+        }
+    }
+#endif
+#else
+    /*
+     * Maybe make a note in error_log that setrlimit isn't supported??
+     */
+
+#endif
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_procattr_child_errfn_set(apr_procattr_t *attr,
+                                                       apr_child_errfn_t *errfn)
+{
+    /* won't ever be called on this platform, so don't save the function pointer */
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_procattr_error_check_set(apr_procattr_t *attr,
+                                                       apr_int32_t chk)
+{
+    /* won't ever be used on this platform, so don't save the flag */
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_procattr_addrspace_set(apr_procattr_t *attr,
+                                                       apr_int32_t addrspace)
+{
+    attr->addrspace = addrspace;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_proc_create(apr_proc_t *newproc,
+                                          const char *progname, 
+                                          const char * const *args, 
+                                          const char * const *env,
+                                          apr_procattr_t *attr, 
+                                          apr_pool_t *pool)
+{
+    wiring_t wire;
+    int      addr_space;
+
+    wire.infd  = attr->child_in  
+               ? (attr->child_in->filedes != -1 ? attr->child_in->filedes 
+                                                : FD_UNUSED)
+               : fileno(stdin);
+    wire.outfd  = attr->child_out
+                ? (attr->child_out->filedes != -1 ? attr->child_out->filedes 
+                                                  : FD_UNUSED)
+                : fileno(stdout);
+    wire.errfd  = attr->child_err
+                ? (attr->child_err->filedes != -1 ? attr->child_err->filedes 
+                                                  : FD_UNUSED)
+                : fileno(stderr);
+
+    newproc->in = attr->parent_in;
+    newproc->out = attr->parent_out;
+    newproc->err = attr->parent_err;
+
+    /* attr->detached and PROC_DETACHED do not mean the same thing.  attr->detached means
+     * start the NLM in a separate address space.  PROC_DETACHED means don't wait for the
+     * NLM to unload by calling wait() or waitpid(), just clean up */
+    addr_space = PROC_LOAD_SILENT | (attr->addrspace ? 0 : PROC_CURRENT_SPACE);
+    addr_space |= (attr->detached ? PROC_DETACHED : 0);
+
+    if (attr->currdir) {
+        char *fullpath = NULL;
+        apr_status_t rv;
+
+        if ((rv = apr_filepath_merge(&fullpath, attr->currdir, progname, 
+                                     APR_FILEPATH_NATIVE, pool)) != APR_SUCCESS) {
+            return rv;
+        }
+        progname = fullpath;
+    } 
+
+    if ((newproc->pid = procve(progname, addr_space, (const char**)env, &wire, 
+        NULL, NULL, 0, NULL, (const char **)args)) == -1) {
+        return errno;
+    }
+
+    if (attr->child_in && (attr->child_in->filedes != -1)) {
+        apr_pool_cleanup_kill(apr_file_pool_get(attr->child_in), 
+                              attr->child_in, apr_unix_file_cleanup);
+        apr_file_close(attr->child_in);
+    }
+    if (attr->child_out && (attr->child_out->filedes != -1)) {
+        apr_pool_cleanup_kill(apr_file_pool_get(attr->child_out), 
+                              attr->child_out, apr_unix_file_cleanup);
+        apr_file_close(attr->child_out);
+    }
+    if (attr->child_err && (attr->child_err->filedes != -1)) {
+        apr_pool_cleanup_kill(apr_file_pool_get(attr->child_err), 
+                              attr->child_err, apr_unix_file_cleanup);
+        apr_file_close(attr->child_err);
+    }
+
+    apr_pool_cleanup_register(pool, (void *)newproc, apr_netware_proc_cleanup,
+        apr_pool_cleanup_null);
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_proc_wait_all_procs(apr_proc_t *proc,
+                                                  int *exitcode,
+                                                  apr_exit_why_e *exitwhy,
+                                                  apr_wait_how_e waithow,
+                                                  apr_pool_t *p)
+{
+    proc->pid = -1;
+    return apr_proc_wait(proc, exitcode, exitwhy, waithow);
+}
+
+APR_DECLARE(apr_status_t) apr_proc_wait(apr_proc_t *proc,
+                                        int *exitcode, apr_exit_why_e *exitwhy,
+                                        apr_wait_how_e waithow)
+{
+    pid_t pstatus;
+    int waitpid_options = WUNTRACED;
+    int exit_int;
+    int ignore;
+    apr_exit_why_e ignorewhy;
+
+    if (exitcode == NULL) {
+        exitcode = &ignore;
+    }
+
+    if (exitwhy == NULL) {
+        exitwhy = &ignorewhy;
+    }
+
+    if (waithow != APR_WAIT) {
+        waitpid_options |= WNOHANG;
+    }
+
+    /* If the pid is 0 then the process was started detached. There 
+       is no need to wait since there is nothing to wait for on a 
+       detached process.  Starting a process as non-detached and
+       then calling wait or waitpid could cause the thread to hang.
+       The reason for this is because NetWare does not have a way 
+       to kill or even signal a process to be killed.  Starting 
+       all processes as detached avoids the possibility of a 
+       thread hanging. */
+    if (proc->pid == 0) {
+        *exitwhy = APR_PROC_EXIT;
+        *exitcode = 0;
+        return APR_CHILD_DONE;
+    }
+
+    if ((pstatus = waitpid(proc->pid, &exit_int, waitpid_options)) > 0) {
+        proc->pid = pstatus;
+
+        if (WIFEXITED(exit_int)) {
+            *exitwhy = APR_PROC_EXIT;
+            *exitcode = WEXITSTATUS(exit_int);
+        }
+        else if (WIFSIGNALED(exit_int)) {
+            *exitwhy = APR_PROC_SIGNAL;
+            *exitcode = WIFTERMSIG(exit_int);
+        }
+        else {
+            /* unexpected condition */
+            return APR_EGENERAL;
+        }
+
+        return APR_CHILD_DONE;
+    }
+    else if (pstatus == 0) {
+        return APR_CHILD_NOTDONE;
+    }
+
+    return errno;
+}
+
+#if APR_HAVE_STRUCT_RLIMIT
+APR_DECLARE(apr_status_t) apr_procattr_limit_set(apr_procattr_t *attr,
+                                                 apr_int32_t what, 
+                                                 struct rlimit *limit)
+{
+    switch(what) {
+        case APR_LIMIT_CPU:
+#ifdef RLIMIT_CPU
+            attr->limit_cpu = limit;
+            break;
+#else
+            return APR_ENOTIMPL;
+#endif
+
+        case APR_LIMIT_MEM:
+#if defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS)
+            attr->limit_mem = limit;
+            break;
+#else
+            return APR_ENOTIMPL;
+#endif
+
+        case APR_LIMIT_NPROC:
+#ifdef RLIMIT_NPROC
+            attr->limit_nproc = limit;
+            break;
+#else
+            return APR_ENOTIMPL;
+#endif
+
+        case APR_LIMIT_NOFILE:
+#ifdef RLIMIT_NOFILE
+            attr->limit_nofile = limit;
+            break;
+#else
+            return APR_ENOTIMPL;
+#endif
+
+    }
+    return APR_SUCCESS;
+}  
+#endif /* APR_HAVE_STRUCT_RLIMIT */
+
+APR_DECLARE(apr_status_t) apr_procattr_user_set(apr_procattr_t *attr, 
+                                                const char *username,
+                                                const char *password)
+{
+    /* Always return SUCCESS because NetWare threads don't run as a user */
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_procattr_group_set(apr_procattr_t *attr,
+                                                 const char *groupname)
+{
+    /* Always return SUCCESS because NetWare threads don't run within a group */
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_procattr_perms_set_register(apr_procattr_t *attr,
+                                                 apr_perms_setfn_t *perms_set_fn,
+                                                 void *data,
+                                                 apr_fileperms_t perms)
+{
+    return APR_ENOTIMPL;
+}
diff --git a/threadproc/netware/procsup.c b/threadproc/netware/procsup.c
new file mode 100644
index 00000000000..72fa1d9764d
--- /dev/null
+++ b/threadproc/netware/procsup.c
@@ -0,0 +1,102 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_arch_threadproc.h"
+
+apr_status_t apr_proc_detach(int daemonize)
+{
+#if 0
+    int x;
+    pid_t pgrp;
+
+    chdir("/");
+#if !defined(MPE) && !defined(OS2) && !defined(TPF) && !defined(BEOS)
+/* Don't detach for MPE because child processes can't survive the death of
+   the parent. */
+    if ((x = fork()) > 0)
+        exit(0);
+    else if (x == -1) {
+        perror("fork");
+        fprintf(stderr, "unable to fork new process\n");
+        exit(1);  /* we can't do anything here, so just exit. */
+    }
+/*    RAISE_SIGSTOP(DETACH);*/
+#endif
+#if APR_HAVE_SETSID
+    if ((pgrp = setsid()) == -1) {
+        return errno;
+    }
+#elif defined(NEXT) || defined(NEWSOS)
+    if (setpgrp(0, getpid()) == -1 || (pgrp = getpgrp(0)) == -1) {
+        return errno;
+    }
+#elif defined(OS2) || defined(TPF)
+    /* OS/2 don't support process group IDs */
+    pgrp = getpid();
+#elif defined(MPE)
+    /* MPE uses negative pid for process group */
+    pgrp = -getpid();
+#else
+    if ((pgrp = setpgid(0, 0)) == -1) {
+        return errno;
+    }
+#endif
+
+    /* close out the standard file descriptors */
+    if (freopen("/dev/null", "r", stdin) == NULL) {
+        return errno;
+        /* continue anyhow -- note we can't close out descriptor 0 because we
+         * have nothing to replace it with, and if we didn't have a descriptor
+         * 0 the next file would be created with that value ... leading to
+         * havoc.
+         */
+    }
+    if (freopen("/dev/null", "w", stdout) == NULL) {
+        return errno;
+    }
+     /* We are going to reopen this again in a little while to the error
+      * log file, but better to do it twice and suffer a small performance
+      * hit for consistancy than not reopen it here.
+      */
+    if (freopen("/dev/null", "w", stderr) == NULL) {
+        return errno;
+    }
+#endif
+    return APR_SUCCESS;
+}
+
+#if 0
+#if (!HAVE_WAITPID)
+/* From ikluft@amdahl.com
+ * this is not ideal but it works for SVR3 variants
+ * Modified by dwd@bell-labs.com to call wait3 instead of wait because
+ *   apache started to use the WNOHANG option.
+ */
+int waitpid(pid_t pid, int *statusp, int options)
+{
+    int tmp_pid;
+    if (kill(pid, 0) == -1) {
+        errno = ECHILD;
+        return -1;
+    }
+    while (((tmp_pid = wait3(statusp, options, 0)) != pid) &&
+                (tmp_pid != -1) && (tmp_pid != 0) && (pid != -1))
+        ;
+    return tmp_pid;
+}
+#endif
+#endif
+
diff --git a/threadproc/netware/signals.c b/threadproc/netware/signals.c
new file mode 100644
index 00000000000..c744da5c512
--- /dev/null
+++ b/threadproc/netware/signals.c
@@ -0,0 +1,81 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_arch_threadproc.h"
+#include "apr_private.h"
+#include "apr_pools.h"
+#include "apr_signal.h"
+#include "apr_strings.h"
+
+#include <assert.h>
+#if APR_HAS_THREADS && APR_HAVE_PTHREAD_H
+#include <pthread.h>
+#endif
+
+APR_DECLARE(apr_status_t) apr_proc_kill(apr_proc_t *proc, int signum)
+{
+    return APR_ENOTIMPL;
+}
+
+
+void apr_signal_init(apr_pool_t *pglobal)
+{
+}
+
+const char *apr_signal_description_get(int signum)
+{
+    switch (signum)
+    {
+    case SIGABRT:
+        return "Abort";
+    case SIGFPE:
+        return "Arithmetic exception";
+    case SIGILL:
+        return "Illegal instruction";
+    case SIGINT:
+        return "Interrupt";
+    case SIGSEGV:
+        return "Segmentation fault";
+    case SIGTERM:
+        return "Terminated";
+    case SIGPOLL:
+        return "Pollable event occurred";
+    default:
+        return "unknown signal (not supported)";
+    }
+}
+
+static void *signal_thread_func(void *signal_handler)
+{
+    return NULL;
+}
+
+#if (APR_HAVE_SIGWAIT || APR_HAVE_SIGSUSPEND)
+APR_DECLARE(apr_status_t) apr_setup_signal_thread(void)
+{
+    return 0;
+}
+#endif /* (APR_HAVE_SIGWAIT || APR_HAVE_SIGSUSPEND) */
+
+APR_DECLARE(apr_status_t) apr_signal_block(int signum)
+{
+    return APR_ENOTIMPL;
+}
+
+APR_DECLARE(apr_status_t) apr_signal_unblock(int signum)
+{
+    return APR_ENOTIMPL;
+}
diff --git a/threadproc/netware/thread.c b/threadproc/netware/thread.c
new file mode 100644
index 00000000000..a37b107a02e
--- /dev/null
+++ b/threadproc/netware/thread.c
@@ -0,0 +1,259 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_portable.h"
+#include "apr_strings.h"
+#include "apr_arch_threadproc.h"
+
+static int thread_count = 0;
+
+apr_status_t apr_threadattr_create(apr_threadattr_t **new,
+                                                apr_pool_t *pool)
+{
+    (*new) = (apr_threadattr_t *)apr_palloc(pool, 
+              sizeof(apr_threadattr_t));
+
+    if ((*new) == NULL) {
+        return APR_ENOMEM;
+    }
+
+    (*new)->pool = pool;
+    (*new)->stack_size = APR_DEFAULT_STACK_SIZE;
+    (*new)->detach = 0;
+    (*new)->thread_name = NULL;
+    return APR_SUCCESS;
+}
+
+apr_status_t apr_threadattr_detach_set(apr_threadattr_t *attr,apr_int32_t on)
+{
+    attr->detach = on;
+    return APR_SUCCESS;   
+}
+
+apr_status_t apr_threadattr_detach_get(apr_threadattr_t *attr)
+{
+    if (attr->detach == 1)
+        return APR_DETACH;
+    return APR_NOTDETACH;
+}
+
+APR_DECLARE(apr_status_t) apr_threadattr_stacksize_set(apr_threadattr_t *attr,
+                                                       apr_size_t stacksize)
+{
+    attr->stack_size = stacksize;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr,
+                                                       apr_size_t size)
+{
+    return APR_ENOTIMPL;
+}
+
+static void *dummy_worker(void *opaque)
+{
+    apr_thread_t *thd = (apr_thread_t *)opaque;
+    void *ret;
+
+    apr_pool_owner_set(thd->pool, 0);
+    ret = thd->func(thd, thd->data);
+    apr_pool_destroy(thd->pool);
+    return ret;
+}
+
+apr_status_t apr_thread_create(apr_thread_t **new,
+                                            apr_threadattr_t *attr, 
+                                            apr_thread_start_t func,
+                                            void *data,
+                                            apr_pool_t *pool)
+{
+    apr_status_t stat;
+    unsigned long flags = NX_THR_BIND_CONTEXT;
+    char threadName[NX_MAX_OBJECT_NAME_LEN+1];
+    size_t stack_size = APR_DEFAULT_STACK_SIZE;
+
+    if (attr && attr->thread_name) {
+        strncpy (threadName, attr->thread_name, NX_MAX_OBJECT_NAME_LEN);
+    }
+    else {
+        sprintf(threadName, "APR_thread %04ld", ++thread_count);
+    }
+
+    /* An original stack size of 0 will allow NXCreateThread() to
+    *   assign a default system stack size.  An original stack
+    *   size of less than 0 will assign the APR default stack size.
+    *   anything else will be taken as is.
+    */
+    if (attr && (attr->stack_size >= 0)) {
+        stack_size = attr->stack_size;
+    }
+    
+    (*new) = (apr_thread_t *)apr_palloc(pool, sizeof(apr_thread_t));
+
+    if ((*new) == NULL) {
+        return APR_ENOMEM;
+    }
+    
+    (*new)->data = data;
+    (*new)->func = func;
+    (*new)->thread_name = (char*)apr_pstrdup(pool, threadName);
+    
+    stat = apr_pool_create(&(*new)->pool, pool);
+    if (stat != APR_SUCCESS) {
+        return stat;
+    }
+    
+    if (attr && attr->detach) {
+        flags |= NX_THR_DETACHED;
+    }
+    
+    (*new)->ctx = NXContextAlloc(
+        /* void(*start_routine)(void *arg) */ (void (*)(void *)) dummy_worker,
+        /* void *arg */                       (*new),
+        /* int priority */                    NX_PRIO_MED,
+        /* size_t stackSize */                stack_size,
+        /* unsigned long flags */             NX_CTX_NORMAL,
+        /* int *error */                      &stat);
+                                                                           
+    stat = NXContextSetName(
+        /* NXContext_t ctx */  (*new)->ctx,
+        /* const char *name */ threadName);
+
+    stat = NXThreadCreate(
+        /* NXContext_t context */     (*new)->ctx,
+        /* unsigned long flags */     flags,
+        /* NXThreadId_t *thread_id */ &(*new)->td);
+
+    if (stat == 0)
+        return APR_SUCCESS;
+        
+    return(stat); /* if error */    
+}
+
+apr_os_thread_t apr_os_thread_current()
+{
+    return NXThreadGetId();
+}
+
+int apr_os_thread_equal(apr_os_thread_t tid1, apr_os_thread_t tid2)
+{
+    return (tid1 == tid2);
+}
+
+void apr_thread_yield()
+{
+    NXThreadYield();
+}
+
+apr_status_t apr_thread_exit(apr_thread_t *thd,
+                             apr_status_t retval)
+{
+    thd->exitval = retval;
+    apr_pool_destroy(thd->pool);
+    NXThreadExit(NULL);
+    return APR_SUCCESS;
+}
+
+apr_status_t apr_thread_join(apr_status_t *retval,
+                                          apr_thread_t *thd)
+{
+    apr_status_t  stat;    
+    NXThreadId_t dthr;
+
+    if ((stat = NXThreadJoin(thd->td, &dthr, NULL)) == 0) {
+        *retval = thd->exitval;
+        return APR_SUCCESS;
+    }
+    else {
+        return stat;
+    }
+}
+
+apr_status_t apr_thread_detach(apr_thread_t *thd)
+{
+    return APR_SUCCESS;
+}
+
+apr_status_t apr_thread_data_get(void **data, const char *key,
+                                             apr_thread_t *thread)
+{
+    if (thread != NULL) {
+            return apr_pool_userdata_get(data, key, thread->pool);
+    }
+    else {
+        data = NULL;
+        return APR_ENOTHREAD;
+    }
+}
+
+apr_status_t apr_thread_data_set(void *data, const char *key,
+                              apr_status_t (*cleanup) (void *),
+                              apr_thread_t *thread)
+{
+    if (thread != NULL) {
+       return apr_pool_userdata_set(data, key, cleanup, thread->pool);
+    }
+    else {
+        data = NULL;
+        return APR_ENOTHREAD;
+    }
+}
+
+APR_DECLARE(apr_status_t) apr_os_thread_get(apr_os_thread_t **thethd,
+                                            apr_thread_t *thd)
+{
+    if (thd == NULL) {
+        return APR_ENOTHREAD;
+    }
+    *thethd = &(thd->td);
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_os_thread_put(apr_thread_t **thd,
+                                            apr_os_thread_t *thethd,
+                                            apr_pool_t *pool)
+{
+    if (pool == NULL) {
+        return APR_ENOPOOL;
+    }
+    if ((*thd) == NULL) {
+        (*thd) = (apr_thread_t *)apr_palloc(pool, sizeof(apr_thread_t));
+        (*thd)->pool = pool;
+    }
+    (*thd)->td = *thethd;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_once_init(apr_thread_once_t **control,
+                                               apr_pool_t *p)
+{
+    (*control) = apr_pcalloc(p, sizeof(**control));
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_once(apr_thread_once_t *control,
+                                          void (*func)(void))
+{
+    if (!atomic_xchg(&control->value, 1)) {
+        func();
+    }
+    return APR_SUCCESS;
+}
+
+APR_POOL_IMPLEMENT_ACCESSOR(thread)
+
+
diff --git a/threadproc/netware/threadpriv.c b/threadproc/netware/threadpriv.c
new file mode 100644
index 00000000000..54680a56342
--- /dev/null
+++ b/threadproc/netware/threadpriv.c
@@ -0,0 +1,102 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_portable.h"
+#include "apr_arch_threadproc.h"
+
+apr_status_t apr_threadkey_private_create(apr_threadkey_t **key, 
+                                        void (*dest)(void *), apr_pool_t *pool) 
+{
+    apr_status_t stat;
+    
+    (*key) = (apr_threadkey_t *)apr_palloc(pool, sizeof(apr_threadkey_t));
+	if ((*key) == NULL) {
+        return APR_ENOMEM;
+    }
+
+    (*key)->pool = pool;
+
+    if ((stat = NXKeyCreate(NULL, dest, &(*key)->key)) == 0) {
+        return stat;
+    }
+    return stat;
+}
+
+apr_status_t apr_threadkey_private_get(void **new, apr_threadkey_t *key)
+{
+    apr_status_t stat;
+    
+    if ((stat = NXKeyGetValue(key->key, new)) == 0) {
+        return APR_SUCCESS;
+    }
+    else {
+        return stat;    
+    }
+}
+
+apr_status_t apr_threadkey_private_set(void *priv, apr_threadkey_t *key)
+{
+    apr_status_t stat;
+    if ((stat = NXKeySetValue(key->key, priv)) == 0) {
+        return APR_SUCCESS;
+    }
+    else {
+        return stat;
+    }
+}
+
+apr_status_t apr_threadkey_private_delete(apr_threadkey_t *key)
+{
+    apr_status_t stat;
+    if ((stat = NXKeyDelete(key->key)) == 0) {
+        return APR_SUCCESS; 
+    }
+    return stat;
+}
+
+apr_status_t apr_threadkey_data_get(void **data, const char *key, apr_threadkey_t *threadkey)
+{
+    return apr_pool_userdata_get(data, key, threadkey->pool);
+}
+
+apr_status_t apr_threadkey_data_set(void *data,
+                                 const char *key, apr_status_t (*cleanup) (void *),
+                                 apr_threadkey_t *threadkey)
+{
+    return apr_pool_userdata_set(data, key, cleanup, threadkey->pool);
+}
+
+apr_status_t apr_os_threadkey_get(apr_os_threadkey_t *thekey,
+                                               apr_threadkey_t *key)
+{
+    thekey = &(key->key);
+    return APR_SUCCESS;
+}
+
+apr_status_t apr_os_threadkey_put(apr_threadkey_t **key, 
+                                apr_os_threadkey_t *thekey, apr_pool_t *pool)
+{
+    if (pool == NULL) {
+        return APR_ENOPOOL;
+    }
+    if ((*key) == NULL) {
+        (*key) = (apr_threadkey_t *)apr_palloc(pool, sizeof(apr_threadkey_t));
+        (*key)->pool = pool;
+    }
+    (*key)->key = *thekey;
+    return APR_SUCCESS;
+}           
+
diff --git a/threadproc/os2/.cvsignore b/threadproc/os2/.cvsignore
deleted file mode 100644
index f3c7a7c5da6..00000000000
--- a/threadproc/os2/.cvsignore
+++ /dev/null
@@ -1 +0,0 @@
-Makefile
diff --git a/threadproc/os2/Makefile.in b/threadproc/os2/Makefile.in
deleted file mode 100644
index 49fcb6b0281..00000000000
--- a/threadproc/os2/Makefile.in
+++ /dev/null
@@ -1,80 +0,0 @@
-#CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
-#LIBS=$(EXTRA_LIBS) $(LIBS1)
-#INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
-#LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
-
-CC=@CC@
-RANLIB=@RANLIB@
-CFLAGS=@CFLAGS@ @OPTIM@
-LIBS=@LIBS@
-LDFLAGS=@LDFLAGS@ $(LIBS)
-INCDIR=../../inc
-INCDIR1=../../include
-INCDIR2=../../file_io/os2
-INCLUDES=-I$(INCDIR) -I$(INCDIR1) -I$(INCDIR2) -I.
-
-LIB=threadproc.a
-
-OBJS=proc.o \
-	thread.o \
-	threadpriv.o \
-	signals.o
-
-.c.o:
-	$(CC) $(CFLAGS) -c $(INCLUDES) $<
-
-all: $(LIB)
-
-clean:
-	$(RM) -f *.o *.a *.so
-
-distclean: clean
-	-$(RM) -f Makefile
-
-$(OBJS): Makefile
-
-$(LIB): $(OBJS)
-	$(RM) -f $@
-	$(AR) cr $@ $(OBJS)
-	$(RANLIB) $@
-
-#
-# We really don't expect end users to use this rule.  It works only with
-# gcc, and rebuilds Makefile.tmpl.  You have to re-run Configure after
-# using it.
-#
-depend:
-	cp Makefile.in Makefile.in.bak \
-	    && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.in > Makefile.new \
-	    && gcc -MM $(INCLUDES) $(CFLAGS) *.c | sed -e "s%\\\\\(.\)%/\\1%g" >> Makefile.new \
-	    && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
-                   -e '1,$$s: $(INCDIR1)/: $$(INCDIR1)/:g' \
-                   -e '1,$$s: $(INCDIR2)/: $$(INCDIR2)/:g' \
-	           -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
-		> Makefile.in \
-	    && rm Makefile.new
-
-# DO NOT REMOVE
-proc.o: proc.c threadproc.h $(INCDIR1)/apr_thread_proc.h \
- $(INCDIR1)/apr_file_io.h $(INCDIR1)/apr_general.h \
- $(INCDIR1)/apr.h $(INCDIR1)/apr_errno.h \
- $(INCDIR1)/apr_time.h $(INCDIR2)/fileio.h \
- $(INCDIR1)/apr_private.h $(INCDIR1)/apr_lib.h \
- $(INCDIR1)/apr_portable.h $(INCDIR1)/apr_network_io.h \
- $(INCDIR1)/apr_lock.h
-signals.o: signals.c threadproc.h $(INCDIR1)/apr_thread_proc.h \
- $(INCDIR1)/apr_file_io.h $(INCDIR1)/apr_general.h \
- $(INCDIR1)/apr.h $(INCDIR1)/apr_errno.h \
- $(INCDIR1)/apr_time.h $(INCDIR2)/fileio.h \
- $(INCDIR1)/apr_private.h
-thread.o: thread.c threadproc.h $(INCDIR1)/apr_thread_proc.h \
- $(INCDIR1)/apr_file_io.h $(INCDIR1)/apr_general.h \
- $(INCDIR1)/apr.h $(INCDIR1)/apr_errno.h \
- $(INCDIR1)/apr_time.h $(INCDIR1)/apr_lib.h \
- $(INCDIR2)/fileio.h $(INCDIR1)/apr_private.h
-threadpriv.o: threadpriv.c threadproc.h \
- $(INCDIR1)/apr_thread_proc.h $(INCDIR1)/apr_file_io.h \
- $(INCDIR1)/apr_general.h $(INCDIR1)/apr.h \
- $(INCDIR1)/apr_errno.h $(INCDIR1)/apr_time.h \
- $(INCDIR1)/apr_lib.h $(INCDIR2)/fileio.h \
- $(INCDIR1)/apr_private.h
diff --git a/threadproc/os2/proc.c b/threadproc/os2/proc.c
index 6fc0f755a9c..cd750012966 100644
--- a/threadproc/os2/proc.c
+++ b/threadproc/os2/proc.c
@@ -1,85 +1,53 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
 #define INCL_DOS
 #define INCL_DOSERRORS
 
-#include "threadproc.h"
-#include "fileio.h"
+#include "apr_arch_threadproc.h"
+#include "apr_arch_file_io.h"
 #include "apr_private.h"
 #include "apr_thread_proc.h"
 #include "apr_file_io.h"
 #include "apr_general.h"
 #include "apr_lib.h"
 #include "apr_portable.h"
+#include "apr_strings.h"
+#include "apr_signal.h"
 #include <signal.h>
 #include <string.h>
 #include <sys/wait.h>
 #include <unistd.h>
 #include <process.h>
 #include <stdlib.h>
-#include <os2.h>
 
-ap_status_t ap_createprocattr_init(ap_procattr_t **new, ap_pool_t *cont)
+/* Heavy on no'ops, here's what we want to pass if there is APR_NO_FILE
+ * requested for a specific child handle;
+ */
+static apr_file_t no_file = { NULL, -1, };
+
+APR_DECLARE(apr_status_t) apr_procattr_create(apr_procattr_t **new, apr_pool_t *pool)
 {
-    (*new) = (ap_procattr_t *)ap_palloc(cont, 
-              sizeof(ap_procattr_t));
+    (*new) = (apr_procattr_t *)apr_palloc(pool, 
+              sizeof(apr_procattr_t));
 
     if ((*new) == NULL) {
         return APR_ENOMEM;
     }
-    (*new)->cntxt = cont;
+    (*new)->pool = pool;
     (*new)->parent_in = NULL;
     (*new)->child_in = NULL;
     (*new)->parent_out = NULL;
@@ -92,98 +60,183 @@ ap_status_t ap_createprocattr_init(ap_procattr_t **new, ap_pool_t *cont)
     return APR_SUCCESS;
 }
 
-ap_status_t ap_setprocattr_io(ap_procattr_t *attr, ap_int32_t in, 
-                                 ap_int32_t out, ap_int32_t err)
+APR_DECLARE(apr_status_t) apr_procattr_io_set(apr_procattr_t *attr,
+                                              apr_int32_t in,
+                                              apr_int32_t out,
+                                              apr_int32_t err)
 {
-    ap_status_t stat;
-    if (in) {
-        if ((stat = ap_create_pipe(&attr->child_in, &attr->parent_in,
-                                   attr->cntxt)) != APR_SUCCESS) {
-            return stat;
-        }
-        switch (in) {
-        case APR_FULL_BLOCK:
-            ap_block_pipe(attr->child_in);
-            ap_block_pipe(attr->parent_in);
-        case APR_PARENT_BLOCK:
-            ap_block_pipe(attr->parent_in);
-        case APR_CHILD_BLOCK:
-            ap_block_pipe(attr->child_in);
-        }
-    } 
-    if (out) {
-        if ((stat = ap_create_pipe(&attr->parent_out, &attr->child_out,
-                                   attr->cntxt)) != APR_SUCCESS) {
-            return stat;
-        }
-        switch (out) {
-        case APR_FULL_BLOCK:
-            ap_block_pipe(attr->child_out);
-            ap_block_pipe(attr->parent_out);
-        case APR_PARENT_BLOCK:
-            ap_block_pipe(attr->parent_out);
-        case APR_CHILD_BLOCK:
-            ap_block_pipe(attr->child_out);
+    apr_status_t rv;
+
+    if ((in != APR_NO_PIPE) && (in != APR_NO_FILE)) {
+        /* APR_CHILD_BLOCK maps to APR_WRITE_BLOCK, while
+         * APR_PARENT_BLOCK maps to APR_READ_BLOCK, so transpose 
+         * the CHILD/PARENT blocking flags for the stdin pipe.
+         * stdout/stderr map to the correct mode by default.
+         */
+        if (in == APR_CHILD_BLOCK)
+            in = APR_READ_BLOCK;
+        else if (in == APR_PARENT_BLOCK)
+            in = APR_WRITE_BLOCK;
+
+        if ((rv = apr_file_pipe_create_ex(&attr->child_in, &attr->parent_in,
+                                          in, attr->pool)) == APR_SUCCESS)
+            rv = apr_file_inherit_unset(attr->parent_in);
+        if (rv != APR_SUCCESS)
+            return rv;
+    }
+    else if (in == APR_NO_FILE)
+        attr->child_in = &no_file;
+
+    if ((out != APR_NO_PIPE) && (out != APR_NO_FILE)) {
+        if ((rv = apr_file_pipe_create_ex(&attr->parent_out, &attr->child_out,
+                                          out, attr->pool)) == APR_SUCCESS)
+            rv = apr_file_inherit_unset(attr->parent_out);
+        if (rv != APR_SUCCESS)
+            return rv;
+    }
+    else if (out == APR_NO_FILE)
+        attr->child_out = &no_file;
+
+    if ((err != APR_NO_PIPE) && (err != APR_NO_FILE)) {
+        if ((rv = apr_file_pipe_create_ex(&attr->parent_err, &attr->child_err,
+                                          err, attr->pool)) == APR_SUCCESS)
+            rv = apr_file_inherit_unset(attr->parent_err);
+        if (rv != APR_SUCCESS)
+            return rv;
+    }
+    else if (err == APR_NO_FILE)
+        attr->child_err = &no_file;
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_procattr_child_in_set(apr_procattr_t *attr, apr_file_t *child_in,
+                                   apr_file_t *parent_in)
+{
+    apr_status_t rv;
+
+    if (attr->child_in == NULL && attr->parent_in == NULL
+            && child_in == NULL && parent_in == NULL)
+        if ((rv = apr_file_pipe_create(&attr->child_in, &attr->parent_in,
+                                       attr->pool)) == APR_SUCCESS)
+            rv = apr_file_inherit_unset(attr->parent_in);
+
+    if (child_in != NULL && rv == APR_SUCCESS) {
+        if (attr->child_in && (attr->child_in->filedes != -1))
+            rv = apr_file_dup2(attr->child_in, child_in, attr->pool);
+        else {
+            attr->child_in = NULL;
+            if ((rv = apr_file_dup(&attr->child_in, child_in, attr->pool))
+                    == APR_SUCCESS)
+                rv = apr_file_inherit_set(attr->child_in);
         }
-    } 
-    if (err) {
-        if ((stat = ap_create_pipe(&attr->parent_err, &attr->child_err,
-                                   attr->cntxt)) != APR_SUCCESS) {
-            return stat;
+    }
+
+    if (parent_in != NULL && rv == APR_SUCCESS) {
+        rv = apr_file_dup(&attr->parent_in, parent_in, attr->pool);
+    }
+
+    return rv;
+}
+
+APR_DECLARE(apr_status_t) apr_procattr_child_out_set(apr_procattr_t *attr, apr_file_t *child_out,
+                                                     apr_file_t *parent_out)
+{
+    apr_status_t rv;
+
+    if (attr->child_out == NULL && attr->parent_out == NULL
+           && child_out == NULL && parent_out == NULL)
+        if ((rv = apr_file_pipe_create(&attr->parent_out, &attr->child_out,
+                                       attr->pool)) == APR_SUCCESS)
+            rv = apr_file_inherit_unset(attr->parent_out);
+
+    if (child_out != NULL && rv == APR_SUCCESS) {
+        if (attr->child_out && (attr->child_out->filedes != -1))
+            rv = apr_file_dup2(attr->child_out, child_out, attr->pool);
+        else {
+            attr->child_out = NULL;
+            if ((rv = apr_file_dup(&attr->child_out, child_out, attr->pool))
+                    == APR_SUCCESS)
+                rv = apr_file_inherit_set(attr->child_out);
         }
-        switch (err) {
-        case APR_FULL_BLOCK:
-            ap_block_pipe(attr->child_err);
-            ap_block_pipe(attr->parent_err);
-        case APR_PARENT_BLOCK:
-            ap_block_pipe(attr->parent_err);
-        case APR_CHILD_BLOCK:
-            ap_block_pipe(attr->child_err);
+    }
+  
+    if (parent_out != NULL && rv == APR_SUCCESS) {
+        rv = apr_file_dup(&attr->parent_out, parent_out, attr->pool);
+    }
+
+    return rv;
+}
+
+APR_DECLARE(apr_status_t) apr_procattr_child_err_set(apr_procattr_t *attr, apr_file_t *child_err,
+                                                     apr_file_t *parent_err)
+{
+    apr_status_t rv;
+
+    if (attr->child_err == NULL && attr->parent_err == NULL
+           && child_err == NULL && parent_err == NULL)
+        if ((rv = apr_file_pipe_create(&attr->parent_err, &attr->child_err,
+                                       attr->pool)) == APR_SUCCESS)
+            rv = apr_file_inherit_unset(attr->parent_err);
+
+    if (child_err != NULL && rv == APR_SUCCESS) {
+        if (attr->child_err && (attr->child_err->filedes != -1))
+            rv = apr_file_dup2(attr->child_err, child_err, attr->pool);
+        else {
+            attr->child_err = NULL;
+            if ((rv = apr_file_dup(&attr->child_err, child_err, attr->pool))
+                    == APR_SUCCESS)
+                rv = apr_file_inherit_set(attr->child_err);
         }
-    } 
-    return APR_SUCCESS;
+    }
+  
+    if (parent_err != NULL && rv == APR_SUCCESS) {
+        rv = apr_file_dup(&attr->parent_err, parent_err, attr->pool);
+    }
+
+    return rv;
 }
 
-ap_status_t ap_setprocattr_dir(ap_procattr_t *attr, const char *dir)
+APR_DECLARE(apr_status_t) apr_procattr_dir_set(apr_procattr_t *attr, const char *dir)
 {
-    attr->currdir = ap_pstrdup(attr->cntxt, dir);
+    attr->currdir = apr_pstrdup(attr->pool, dir);
     if (attr->currdir) {
         return APR_SUCCESS;
     }
     return APR_ENOMEM;
 }
 
-ap_status_t ap_setprocattr_cmdtype(ap_procattr_t *attr,
-                                     ap_cmdtype_e cmd) 
+APR_DECLARE(apr_status_t) apr_procattr_cmdtype_set(apr_procattr_t *attr,
+                                                   apr_cmdtype_e cmd) 
 {
     attr->cmdtype = cmd;
     return APR_SUCCESS;
 }
 
-ap_status_t ap_setprocattr_detach(ap_procattr_t *attr, ap_int32_t detach) 
+APR_DECLARE(apr_status_t) apr_procattr_detach_set(apr_procattr_t *attr, apr_int32_t detach) 
 {
     attr->detached = detach;
     return APR_SUCCESS;
 }
 
-ap_status_t ap_fork(ap_proc_t **proc, ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_proc_fork(apr_proc_t *proc, apr_pool_t *pool)
 {
     int pid;
     
-    (*proc) = ap_palloc(cont, sizeof(ap_proc_t));
-
     if ((pid = fork()) < 0) {
         return errno;
-    } else if (pid == 0) {
-        (*proc)->pid = pid;
-        (*proc)->attr = NULL;
-        (*proc)->running = TRUE;
+    }
+    else if (pid == 0) {
+        proc->pid = pid;
+        proc->in = NULL; 
+        proc->out = NULL; 
+        proc->err = NULL; 
         return APR_INCHILD;
     }
-
-    (*proc)->pid = pid;
-    (*proc)->attr = NULL;
-    (*proc)->running = TRUE;
+    proc->pid = pid;
+    proc->in = NULL; 
+    proc->out = NULL; 
+    proc->err = NULL; 
     return APR_INPARENT;
 }
 
@@ -192,7 +245,7 @@ ap_status_t ap_fork(ap_proc_t **proc, ap_pool_t *cont)
 /* quotes in the string are doubled up.
  * Used to escape quotes in args passed to OS/2's cmd.exe
  */
-static char *double_quotes(ap_pool_t *cntxt, char *str)
+static char *double_quotes(apr_pool_t *pool, const char *str)
 {
     int num_quotes = 0;
     int len = 0;
@@ -202,7 +255,7 @@ static char *double_quotes(ap_pool_t *cntxt, char *str)
         num_quotes += str[len++] == '\"';
     }
     
-    quote_doubled_str = ap_palloc(cntxt, len + num_quotes + 1);
+    quote_doubled_str = apr_palloc(pool, len + num_quotes + 1);
     dest = quote_doubled_str;
     
     while (*str) {
@@ -217,32 +270,53 @@ static char *double_quotes(ap_pool_t *cntxt, char *str)
 
 
 
-ap_status_t ap_create_process(ap_proc_t **new, const char *progname,
-                              char *const args[], char **env,
-                              ap_procattr_t *attr, ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_procattr_child_errfn_set(apr_procattr_t *attr,
+                                                       apr_child_errfn_t *errfn)
+{
+    /* won't ever be called on this platform, so don't save the function pointer */
+    return APR_SUCCESS;
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_procattr_error_check_set(apr_procattr_t *attr,
+                                                       apr_int32_t chk)
+{
+    /* won't ever be used on this platform, so don't save the flag */
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_procattr_addrspace_set(apr_procattr_t *attr,
+                                                       apr_int32_t addrspace)
+{
+    /* won't ever be used on this platform, so don't save the flag */
+    return APR_SUCCESS;
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_proc_create(apr_proc_t *proc, const char *progname,
+                                          const char * const *args,
+                                          const char * const *env,
+                                          apr_procattr_t *attr, apr_pool_t *pool)
 {
     int i, arg, numargs, cmdlen;
-    ap_status_t status;
-    char **newargs;
+    apr_status_t status;
+    const char **newargs;
     char savedir[300];
     HFILE save_in, save_out, save_err, dup;
     int criticalsection = FALSE;
     char *extension, *newprogname, *extra_arg = NULL, *cmdline, *cmdline_pos;
     char interpreter[1024];
     char error_object[260];
-    ap_file_t *progfile;
+    apr_file_t *progfile;
     int env_len, e;
     char *env_block, *env_block_pos;
     RESULTCODES rescodes;
 
-    (*new) = (ap_proc_t *)ap_palloc(cont, sizeof(ap_proc_t));
-
-    if ((*new) == NULL) {
-        return APR_ENOMEM;
-    }
-
-    (*new)->cntxt = cont;
-    (*new)->running = FALSE;
+    proc->in = attr->parent_in;
+    proc->err = attr->parent_err;
+    proc->out = attr->parent_out;
 
     /* Prevent other threads from running while these process-wide resources are modified */
     if (attr->child_in || attr->child_out || attr->child_err || attr->currdir) {
@@ -254,27 +328,33 @@ ap_status_t ap_create_process(ap_proc_t **new, const char *progname,
         save_in = -1;
         DosDupHandle(STDIN_FILENO, &save_in);
         dup = STDIN_FILENO;
-        DosDupHandle(attr->child_in->filedes, &dup);
-        DosSetFHState(attr->parent_in->filedes, OPEN_FLAGS_NOINHERIT);
+        if (attr->child_in->filedes == -1)
+            DosClose(dup);
+        else
+            DosDupHandle(attr->child_in->filedes, &dup);
     }
     
     if (attr->child_out) {
         save_out = -1;
         DosDupHandle(STDOUT_FILENO, &save_out);
         dup = STDOUT_FILENO;
-        DosDupHandle(attr->child_out->filedes, &dup);
-        DosSetFHState(attr->parent_out->filedes, OPEN_FLAGS_NOINHERIT);
+        if (attr->child_out->filedes == -1)
+            DosClose(dup);
+        else
+            DosDupHandle(attr->child_out->filedes, &dup);
     }
     
     if (attr->child_err) {
         save_err = -1;
         DosDupHandle(STDERR_FILENO, &save_err);
         dup = STDERR_FILENO;
-        DosDupHandle(attr->child_err->filedes, &dup);
-        DosSetFHState(attr->parent_err->filedes, OPEN_FLAGS_NOINHERIT);
+        if (attr->child_err->filedes == -1)
+            DosClose(dup);
+        else
+            DosDupHandle(attr->child_err->filedes, &dup);
     }
 
-    ap_signal(SIGCHLD, SIG_DFL); /*not sure if this is needed or not */
+    apr_signal(SIGCHLD, SIG_DFL); /*not sure if this is needed or not */
 
     if (attr->currdir != NULL) {
         _getcwd2(savedir, sizeof(savedir));
@@ -292,21 +372,34 @@ ap_status_t ap_create_process(ap_proc_t **new, const char *progname,
     if (extension == NULL || strchr(extension, '/') || strchr(extension, '\\'))
         extension = "";
 
-    if (attr->cmdtype == APR_SHELLCMD || strcasecmp(extension, ".cmd") == 0) {
+    /* ### how to handle APR_PROGRAM_ENV and APR_PROGRAM_PATH? */
+
+    if (attr->cmdtype == APR_SHELLCMD ||
+        attr->cmdtype == APR_SHELLCMD_ENV ||
+        strcasecmp(extension, ".cmd") == 0) {
         strcpy(interpreter, "#!" SHELL_PATH);
         extra_arg = "/C";
     } else if (stricmp(extension, ".exe") != 0) {
-        status = ap_open(&progfile, progname, APR_READ|APR_BUFFERED, 0, cont);
+        status = apr_file_open(&progfile, progname,
+                               APR_FOPEN_READ|APR_FOPEN_BUFFERED, 0, pool);
 
-        if (status == APR_ENOENT) {
-            progname = ap_pstrcat(cont, progname, ".exe", NULL);
+        if (status != APR_SUCCESS && APR_STATUS_IS_ENOENT(status)) {
+            progname = apr_pstrcat(pool, progname, ".exe", NULL);
         }
 
         if (status == APR_SUCCESS) {
-            status = ap_fgets(interpreter, sizeof(interpreter), progfile);
+            status = apr_file_gets(interpreter, sizeof(interpreter), progfile);
 
             if (status == APR_SUCCESS) {
                 if (interpreter[0] == '#' && interpreter[1] == '!') {
+                    /* delete CR/LF & any other whitespace off the end */
+                    int end = strlen(interpreter) - 1;
+
+                    while (end >= 0 && apr_isspace(interpreter[end])) {
+                        interpreter[end] = '\0';
+                        end--;
+                    }
+
                     if (interpreter[2] != '/' && interpreter[2] != '\\' && interpreter[3] != ':') {
                         char buffer[300];
 
@@ -323,8 +416,9 @@ ap_status_t ap_create_process(ap_proc_t **new, const char *progname,
                     interpreter[0] = 0;
                 }
             }
+
+            apr_file_close(progfile);
         }
-        ap_close(progfile);
     }
 
     i = 0;
@@ -333,7 +427,7 @@ ap_status_t ap_create_process(ap_proc_t **new, const char *progname,
         i++;
     }
 
-    newargs = (char **)ap_palloc(cont, sizeof (char *) * (i + 4));
+    newargs = (const char **)apr_palloc(pool, sizeof (char *) * (i + 4));
     numargs = 0;
 
     if (interpreter[0])
@@ -341,7 +435,7 @@ ap_status_t ap_create_process(ap_proc_t **new, const char *progname,
     if (extra_arg)
         newargs[numargs++] = "/c";
 
-    newargs[numargs++] = newprogname = ap_pstrdup(cont, progname);
+    newargs[numargs++] = newprogname = apr_pstrdup(pool, progname);
     arg = 1;
 
     while (args && args[arg]) {
@@ -359,16 +453,18 @@ ap_status_t ap_create_process(ap_proc_t **new, const char *progname,
     for (i=0; i<numargs; i++)
         cmdlen += strlen(newargs[i]) + 3;
 
-    cmdline = ap_pstrndup(cont, newargs[0], cmdlen + 2);
-    cmdline_pos = cmdline + strlen(cmdline);
+    cmdline = apr_palloc(pool, cmdlen + 2);
+    cmdline_pos = cmdline;
 
-    for (i=1; i<numargs; i++) {
-        char *a = newargs[i];
+    for (i=0; i<numargs; i++) {
+        const char *a = newargs[i];
 
         if (strpbrk(a, "&|<>\" "))
-            a = ap_pstrcat(cont, "\"", double_quotes(cont, a), "\"", NULL);
+            a = apr_pstrcat(pool, "\"", double_quotes(pool, a), "\"", NULL);
+
+        if (i)
+            *(cmdline_pos++) = ' ';
 
-        *(cmdline_pos++) = ' ';
         strcpy(cmdline_pos, a);
         cmdline_pos += strlen(cmdline_pos);
     }
@@ -386,7 +482,7 @@ ap_status_t ap_create_process(ap_proc_t **new, const char *progname,
         for (env_len=1, e=0; env[e]; e++)
             env_len += strlen(env[e]) + 1;
 
-        env_block = ap_palloc(cont, env_len);
+        env_block = apr_palloc(pool, env_len);
         env_block_pos = env_block;
 
         for (e=0; env[e]; e++) {
@@ -402,28 +498,37 @@ ap_status_t ap_create_process(ap_proc_t **new, const char *progname,
                         attr->detached ? EXEC_BACKGROUND : EXEC_ASYNCRESULT,
                         cmdline, env_block, &rescodes, cmdline);
 
-    (*new)->pid = rescodes.codeTerminate;
+    proc->pid = rescodes.codeTerminate;
 
     if (attr->currdir != NULL) {
         chdir(savedir);
     }
 
     if (attr->child_in) {
-        ap_close(attr->child_in);
+        if (attr->child_in->filedes != -1) {
+            apr_file_close(attr->child_in);
+        }
+
         dup = STDIN_FILENO;
         DosDupHandle(save_in, &dup);
         DosClose(save_in);
     }
     
     if (attr->child_out) {
-        ap_close(attr->child_out);
+        if  (attr->child_out->filedes != -1) {
+            apr_file_close(attr->child_out);
+        }
+
         dup = STDOUT_FILENO;
         DosDupHandle(save_out, &dup);
         DosClose(save_out);
     }
     
     if (attr->child_err) {
-        ap_close(attr->child_err);
+        if (attr->child_err->filedes != -1) {
+            apr_file_close(attr->child_err);
+        }
+
         dup = STDERR_FILENO;
         DosDupHandle(save_err, &dup);
         DosClose(save_err);
@@ -432,63 +537,137 @@ ap_status_t ap_create_process(ap_proc_t **new, const char *progname,
     if (criticalsection)
         DosExitCritSec();
 
-    (*new)->attr = attr;
-    (*new)->running = status == APR_SUCCESS;
     return status;
 }
 
 
 
-ap_status_t ap_get_childin(ap_file_t **new, ap_proc_t *proc)
+static void proces_result_codes(RESULTCODES codes, 
+                                int *exitcode, 
+                                apr_exit_why_e *exitwhy)
 {
-    (*new) = proc->attr->parent_in;
-    return APR_SUCCESS; 
-}
+    int result = 0;
+    apr_exit_why_e why = APR_PROC_EXIT;
+
+    switch (codes.codeTerminate) {
+    case TC_EXIT:        /* Normal exit */
+        why = APR_PROC_EXIT;
+        result = codes.codeResult;
+        break;
+
+    case TC_HARDERROR:   /* Hard error halt */
+        why = APR_PROC_SIGNAL;
+        result = SIGSYS;
+        break;
+
+    case TC_KILLPROCESS: /* Was killed by a DosKillProcess() */
+        why = APR_PROC_SIGNAL;
+        result = SIGKILL;
+        break;
+
+    case TC_TRAP:        /* TRAP in 16 bit code */
+    case TC_EXCEPTION:   /* Threw an exception (32 bit code) */
+        why = APR_PROC_SIGNAL;
+
+        switch (codes.codeResult | XCPT_FATAL_EXCEPTION) {
+        case XCPT_ACCESS_VIOLATION:
+            result = SIGSEGV;
+            break;
+
+        case XCPT_ILLEGAL_INSTRUCTION:
+            result = SIGILL;
+            break;
+
+        case XCPT_FLOAT_DIVIDE_BY_ZERO:
+        case XCPT_INTEGER_DIVIDE_BY_ZERO:
+            result = SIGFPE;
+            break;
+
+        default:
+            result = codes.codeResult;
+            break;
+        }
+    }
 
-ap_status_t ap_get_childout(ap_file_t **new, ap_proc_t *proc)
-{
-    (*new) = proc->attr->parent_out; 
-    return APR_SUCCESS;
+    if (exitcode) {
+        *exitcode = result;
+    }
+
+    if (exitwhy) {
+        *exitwhy = why;
+    }
 }
 
-ap_status_t ap_get_childerr(ap_file_t **new, ap_proc_t *proc)
-{
-    (*new) = proc->attr->parent_err; 
-    return APR_SUCCESS;
-}    
 
-ap_status_t ap_wait_proc(ap_proc_t *proc, 
-                           ap_wait_how_e wait)
+
+APR_DECLARE(apr_status_t) apr_proc_wait_all_procs(apr_proc_t *proc,
+                                                  int *exitcode,
+                                                  apr_exit_why_e *exitwhy,
+                                                  apr_wait_how_e waithow,
+                                                  apr_pool_t *p)
 {
     RESULTCODES codes;
     ULONG rc;
     PID pid;
 
-    if (!proc)
-        return APR_ENOPROC;
+    rc = DosWaitChild(DCWA_PROCESSTREE, waithow == APR_WAIT ? DCWW_WAIT : DCWW_NOWAIT, &codes, &pid, 0);
 
-    if (!proc->running)
+    if (rc == 0) {
+        proc->pid = pid;
+        proces_result_codes(codes, exitcode, exitwhy);
         return APR_CHILD_DONE;
+    } else if (rc == ERROR_CHILD_NOT_COMPLETE) {
+        return APR_CHILD_NOTDONE;
+    }
 
-    rc = DosWaitChild(DCWA_PROCESS, wait == APR_WAIT ? DCWW_WAIT : DCWW_NOWAIT, &codes, &pid, proc->pid);
+    return APR_FROM_OS_ERROR(rc);
+} 
+
+
+
+APR_DECLARE(apr_status_t) apr_proc_wait(apr_proc_t *proc,
+                                        int *exitcode, apr_exit_why_e *exitwhy,
+                                        apr_wait_how_e waithow)
+{
+    RESULTCODES codes;
+    ULONG rc;
+    PID pid;
+    rc = DosWaitChild(DCWA_PROCESS, waithow == APR_WAIT ? DCWW_WAIT : DCWW_NOWAIT, &codes, &pid, proc->pid);
 
     if (rc == 0) {
-        proc->running = 0;
+        proces_result_codes(codes, exitcode, exitwhy);
         return APR_CHILD_DONE;
     } else if (rc == ERROR_CHILD_NOT_COMPLETE) {
         return APR_CHILD_NOTDONE;
     }
 
-    return APR_OS2_STATUS(rc);
+    return APR_FROM_OS_ERROR(rc);
 } 
 
 
 
-ap_status_t ap_get_os_proc(ap_os_proc_t *theproc, ap_proc_t *proc)
+APR_DECLARE(apr_status_t) apr_proc_detach(int daemonize)
 {
-    if (proc == NULL) {
-        return APR_ENOPROC;
-    }
-    *theproc = proc->pid;
-    return APR_SUCCESS;
+    return APR_ENOTIMPL;
+}
+
+APR_DECLARE(apr_status_t) apr_procattr_user_set(apr_procattr_t *attr, 
+                                                const char *username,
+                                                const char *password)
+{
+    return APR_ENOTIMPL;
+}
+
+APR_DECLARE(apr_status_t) apr_procattr_group_set(apr_procattr_t *attr,
+                                                 const char *groupname)
+{
+    return APR_ENOTIMPL;
+}
+
+APR_DECLARE(apr_status_t) apr_procattr_perms_set_register(apr_procattr_t *attr,
+                                                 apr_perms_setfn_t *perms_set_fn,
+                                                 void *data,
+                                                 apr_fileperms_t perms)
+{
+    return APR_ENOTIMPL;
 }
diff --git a/threadproc/os2/signals.c b/threadproc/os2/signals.c
index 6ba71bada5b..cde3dedd713 100644
--- a/threadproc/os2/signals.c
+++ b/threadproc/os2/signals.c
@@ -1,81 +1,2 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "threadproc.h"
-#include "fileio.h"
-#include "apr_thread_proc.h"
-#include "apr_file_io.h"
-#include "apr_general.h"
-#include <signal.h>
-#include <string.h>
-#include <sys/wait.h>
-#define INCL_DOS
-#include <os2.h>
-
-ap_status_t ap_kill(ap_proc_t *proc, int signal)
-{
-/* SIGTERM's don't work too well in OS/2 (only affects other EMX programs).
-   CGIs may not be, esp. REXX scripts, so use a native call instead */
-   
-    ap_status_t rc;
-    
-    if ( signal == SIGTERM ) {
-        rc = APR_OS2_STATUS(DosSendSignalException(proc->pid, XCPT_SIGNAL_BREAK));
-    } else {
-        rc = kill(proc->pid, signal) < 0 ? errno : APR_SUCCESS;
-    }
-    
-    return rc;
-}
-
+#define SIGPROCMASK_SETS_THREAD_MASK 1
+#include "../unix/signals.c"
diff --git a/threadproc/os2/thread.c b/threadproc/os2/thread.c
index dbfa3482550..9911034ae7c 100644
--- a/threadproc/os2/thread.c
+++ b/threadproc/os2/thread.c
@@ -1,83 +1,46 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
 #define INCL_DOSERRORS
 #define INCL_DOS
-#include "threadproc.h"
+#include "apr_arch_threadproc.h"
 #include "apr_thread_proc.h"
 #include "apr_general.h"
 #include "apr_lib.h"
-#include "fileio.h"
+#include "apr_portable.h"
+#include "apr_arch_file_io.h"
 #include <stdlib.h>
-#include <os2.h>
 
-ap_status_t ap_create_threadattr(ap_threadattr_t **new, ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_threadattr_create(apr_threadattr_t **new, apr_pool_t *pool)
 {
-    (*new) = (ap_threadattr_t *)ap_palloc(cont, sizeof(ap_threadattr_t));
+    (*new) = (apr_threadattr_t *)apr_palloc(pool, sizeof(apr_threadattr_t));
 
     if ((*new) == NULL) {
         return APR_ENOMEM;
     }
 
-    (*new)->cntxt = cont;
+    (*new)->pool = pool;
     (*new)->attr = 0;
+    (*new)->stacksize = 0;
     return APR_SUCCESS;
 }
 
 
 
-ap_status_t ap_setthreadattr_detach(ap_threadattr_t *attr, ap_int32_t on)
+APR_DECLARE(apr_status_t) apr_threadattr_detach_set(apr_threadattr_t *attr, apr_int32_t on)
 {
     attr->attr |= APR_THREADATTR_DETACHED;
     return APR_SUCCESS;
@@ -85,57 +48,69 @@ ap_status_t ap_setthreadattr_detach(ap_threadattr_t *attr, ap_int32_t on)
 
 
 
-ap_status_t ap_getthreadattr_detach(ap_threadattr_t *attr)
+APR_DECLARE(apr_status_t) apr_threadattr_detach_get(apr_threadattr_t *attr)
 {
     return (attr->attr & APR_THREADATTR_DETACHED) ? APR_DETACH : APR_NOTDETACH;
 }
 
+APR_DECLARE(apr_status_t) apr_threadattr_stacksize_set(apr_threadattr_t *attr,
+                                                       apr_size_t stacksize)
+{
+    attr->stacksize = stacksize;
+    return APR_SUCCESS;
+}
 
+APR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr,
+                                                       apr_size_t size)
+{
+    return APR_ENOTIMPL;
+}
 
-static void ap_thread_begin(void *arg)
+static void apr_thread_begin(void *arg)
 {
-  ap_thread_t *thread = (ap_thread_t *)arg;
-  thread->rv = thread->func(thread->data);
+  apr_thread_t *thread = (apr_thread_t *)arg;
+  apr_pool_owner_set(thread->pool, 0);
+  thread->exitval = thread->func(thread, thread->data);
+  apr_pool_destroy(thread->pool);
 }
 
 
 
-ap_status_t ap_create_thread(ap_thread_t **new, ap_threadattr_t *attr, 
-                             ap_thread_start_t func, void *data, 
-                             ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new, apr_threadattr_t *attr, 
+                                            apr_thread_start_t func, void *data, 
+                                            apr_pool_t *pool)
 {
-    ap_status_t stat;
-    ap_thread_t *thread;
+    apr_status_t stat;
+    apr_thread_t *thread;
  
-    thread = (ap_thread_t *)ap_palloc(cont, sizeof(ap_thread_t));
+    thread = (apr_thread_t *)apr_palloc(pool, sizeof(apr_thread_t));
     *new = thread;
 
     if (thread == NULL) {
         return APR_ENOMEM;
     }
 
-    thread->cntxt = cont;
     thread->attr = attr;
     thread->func = func;
     thread->data = data;
-    stat = ap_create_pool(&thread->cntxt, cont);
+    stat = apr_pool_create(&thread->pool, pool);
     
     if (stat != APR_SUCCESS) {
         return stat;
     }
 
     if (attr == NULL) {
-        stat = ap_create_threadattr(&thread->attr, thread->cntxt);
+        stat = apr_threadattr_create(&thread->attr, thread->pool);
         
         if (stat != APR_SUCCESS) {
             return stat;
         }
     }
-    
-    if (thread->attr->attr & APR_THREADATTR_DETACHED)
-        thread->tid = _beginthread((os2_thread_start_t)func, NULL, APR_THREAD_STACKSIZE, data);
-    else
-        thread->tid = _beginthread(ap_thread_begin, NULL, APR_THREAD_STACKSIZE, thread);
+
+    thread->tid = _beginthread(apr_thread_begin, NULL, 
+                               thread->attr->stacksize > 0 ?
+                               thread->attr->stacksize : APR_THREAD_STACKSIZE,
+                               thread);
         
     if (thread->tid < 0) {
         return errno;
@@ -146,16 +121,27 @@ ap_status_t ap_create_thread(ap_thread_t **new, ap_threadattr_t *attr,
 
 
 
-ap_status_t ap_thread_exit(ap_thread_t *thd, ap_status_t *retval)
+APR_DECLARE(apr_os_thread_t) apr_os_thread_current()
+{
+    PIB *ppib;
+    TIB *ptib;
+    DosGetInfoBlocks(&ptib, &ppib);
+    return ptib->tib_ptib2->tib2_ultid;
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_thread_exit(apr_thread_t *thd, apr_status_t retval)
 {
-    thd->rv = retval;
+    thd->exitval = retval;
+    apr_pool_destroy(thd->pool);
     _endthread();
     return -1; /* If we get here something's wrong */
 }
 
 
 
-ap_status_t ap_thread_join(ap_status_t *retval, ap_thread_t *thd)
+APR_DECLARE(apr_status_t) apr_thread_join(apr_status_t *retval, apr_thread_t *thd)
 {
     ULONG rc;
     TID waittid = thd->tid;
@@ -168,16 +154,110 @@ ap_status_t ap_thread_join(ap_status_t *retval, ap_thread_t *thd)
     if (rc == ERROR_INVALID_THREADID)
         rc = 0; /* Thread had already terminated */
 
-    *retval = (ap_status_t)thd->rv;
-    return APR_OS2_STATUS(rc);
+    *retval = thd->exitval;
+    return APR_FROM_OS_ERROR(rc);
 }
 
 
 
-ap_status_t ap_thread_detach(ap_thread_t *thd)
+APR_DECLARE(apr_status_t) apr_thread_detach(apr_thread_t *thd)
 {
     thd->attr->attr |= APR_THREADATTR_DETACHED;
     return APR_SUCCESS;
 }
 
 
+
+void apr_thread_yield()
+{
+    DosSleep(0);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_os_thread_get(apr_os_thread_t **thethd, apr_thread_t *thd)
+{
+    *thethd = &thd->tid;
+    return APR_SUCCESS;
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_os_thread_put(apr_thread_t **thd, apr_os_thread_t *thethd, 
+                                            apr_pool_t *pool)
+{
+    if ((*thd) == NULL) {
+        (*thd) = (apr_thread_t *)apr_pcalloc(pool, sizeof(apr_thread_t));
+        (*thd)->pool = pool;
+    }
+    (*thd)->tid = *thethd;
+    return APR_SUCCESS;
+}
+
+
+
+int apr_os_thread_equal(apr_os_thread_t tid1, apr_os_thread_t tid2)
+{
+    return tid1 == tid2;
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_thread_data_get(void **data, const char *key, apr_thread_t *thread)
+{
+    return apr_pool_userdata_get(data, key, thread->pool);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_thread_data_set(void *data, const char *key,
+                                              apr_status_t (*cleanup) (void *),
+                                              apr_thread_t *thread)
+{
+    return apr_pool_userdata_set(data, key, cleanup, thread->pool);
+}
+
+APR_POOL_IMPLEMENT_ACCESSOR(thread)
+
+
+
+static apr_status_t thread_once_cleanup(void *vcontrol)
+{
+    apr_thread_once_t *control = (apr_thread_once_t *)vcontrol;
+
+    if (control->sem) {
+        DosCloseEventSem(control->sem);
+    }
+
+    return APR_SUCCESS;
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_thread_once_init(apr_thread_once_t **control,
+                                               apr_pool_t *p)
+{
+    ULONG rc;
+    *control = (apr_thread_once_t *)apr_pcalloc(p, sizeof(apr_thread_once_t));
+    rc = DosCreateEventSem(NULL, &(*control)->sem, 0, TRUE);
+    apr_pool_cleanup_register(p, control, thread_once_cleanup, apr_pool_cleanup_null);
+    return APR_FROM_OS_ERROR(rc);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_thread_once(apr_thread_once_t *control, 
+                                          void (*func)(void))
+{
+    if (!control->hit) {
+        ULONG count, rc;
+        rc = DosResetEventSem(control->sem, &count);
+
+        if (rc == 0 && count) {
+            control->hit = 1;
+            func();
+        }
+    }
+
+    return APR_SUCCESS;
+}
diff --git a/threadproc/os2/threadcancel.c b/threadproc/os2/threadcancel.c
deleted file mode 100644
index ca7a187538e..00000000000
--- a/threadproc/os2/threadcancel.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "threadproc.h"
-#include "apr_thread_proc.h"
-#include "apr_general.h"
-#include "fileio.h"
-
-ap_status_t ap_cancel_thread(ap_thread_t *thd)
-{
-    return APR_OS2_STATUS(DosKillThread(thd->tid));
-}
-
-    
-
-ap_status_t ap_setcanceltype(ap_int32_t type, ap_pool_t *cont)
-{
-    ULONG rc, nesting;
-
-    if (type == APR_CANCEL_DEFER)
-        rc = DosEnterMustComplete(&nesting);
-    else
-        rc = DosExitMustComplete(&nesting);
-
-    return APR_OS2_STATUS(rc);
-}
-
-
-
-ap_status_t ap_setcancelstate(ap_int32_t type, ap_pool_t *cont)
-{
-/* There's no way to ignore thread kills altogether in OS/2 (that I know of) */
-    return APR_ENOTIMPL;
-}
diff --git a/threadproc/os2/threadpriv.c b/threadproc/os2/threadpriv.c
index cf436d23708..c0f709c31c6 100644
--- a/threadproc/os2/threadpriv.c
+++ b/threadproc/os2/threadpriv.c
@@ -1,91 +1,88 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "threadproc.h"
+#include "apr_arch_threadproc.h"
 #include "apr_thread_proc.h"
+#include "apr_portable.h"
 #include "apr_general.h"
 #include "apr_errno.h"
 #include "apr_lib.h"
-#include "fileio.h"
+#include "apr_arch_file_io.h"
 
-ap_status_t ap_create_thread_private(ap_threadkey_t **key,
-                                     void (*dest)(void *), ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_threadkey_private_create(apr_threadkey_t **key,
+                                                       void (*dest)(void *), 
+                                                       apr_pool_t *pool)
 {
-    (*key) = (ap_threadkey_t *)ap_palloc(cont, sizeof(ap_threadkey_t));
+    (*key) = (apr_threadkey_t *)apr_palloc(pool, sizeof(apr_threadkey_t));
 
     if ((*key) == NULL) {
         return APR_ENOMEM;
     }
 
-    (*key)->cntxt = cont;
-    return APR_OS2_STATUS(DosAllocThreadLocalMemory(1, &((*key)->key)));
+    (*key)->pool = pool;
+    return APR_FROM_OS_ERROR(DosAllocThreadLocalMemory(1, &((*key)->key)));
 }
 
-ap_status_t ap_get_thread_private(void **new, ap_threadkey_t *key)
+APR_DECLARE(apr_status_t) apr_threadkey_private_get(void **new, apr_threadkey_t *key)
 {
     (*new) = (void *)*(key->key);
     return APR_SUCCESS;
 }
 
-ap_status_t ap_set_thread_private(void *priv, ap_threadkey_t *key)
+APR_DECLARE(apr_status_t) apr_threadkey_private_set(void *priv, apr_threadkey_t *key)
 {
     *(key->key) = (ULONG)priv;
     return APR_SUCCESS;
 }
 
-ap_status_t ap_delete_thread_private(ap_threadkey_t *key)
+APR_DECLARE(apr_status_t) apr_threadkey_private_delete(apr_threadkey_t *key)
+{
+    return APR_FROM_OS_ERROR(DosFreeThreadLocalMemory(key->key));
+}
+
+APR_DECLARE(apr_status_t) apr_threadkey_data_get(void **data, const char *key,
+                                                 apr_threadkey_t *threadkey)
+{
+    return apr_pool_userdata_get(data, key, threadkey->pool);
+}
+
+APR_DECLARE(apr_status_t) apr_threadkey_data_set(void *data, const char *key,
+                                                 apr_status_t (*cleanup) (void *),
+                                                 apr_threadkey_t *threadkey)
+{
+    return apr_pool_userdata_set(data, key, cleanup, threadkey->pool);
+}
+
+APR_DECLARE(apr_status_t) apr_os_threadkey_get(apr_os_threadkey_t *thekey, apr_threadkey_t *key)
 {
-    return APR_OS2_STATUS(DosFreeThreadLocalMemory(key->key));
+    *thekey = key->key;
+    return APR_SUCCESS;
 }
 
+APR_DECLARE(apr_status_t) apr_os_threadkey_put(apr_threadkey_t **key, 
+                                               apr_os_threadkey_t *thekey, 
+                                               apr_pool_t *pool)
+{
+    if (pool == NULL) {
+        return APR_ENOPOOL;
+    }
+    if ((*key) == NULL) {
+        (*key) = (apr_threadkey_t *)apr_pcalloc(pool, sizeof(apr_threadkey_t));
+        (*key)->pool = pool;
+    }
+    (*key)->key = *thekey;
+    return APR_SUCCESS;
+}           
diff --git a/threadproc/os2/threadproc.h b/threadproc/os2/threadproc.h
deleted file mode 100644
index cfcca8d621c..00000000000
--- a/threadproc/os2/threadproc.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "apr_thread_proc.h"
-#include "apr_file_io.h"
-
-#ifndef THREAD_PROC_H
-#define THREAD_PROC_H
-
-#define APR_THREADATTR_DETACHED 1
-
-#define SHELL_PATH "cmd.exe"
-#define APR_THREAD_STACKSIZE 65536
-
-struct ap_threadattr_t {
-    ap_pool_t *cntxt;
-    unsigned long attr;
-};
-
-struct ap_thread_t {
-    ap_pool_t *cntxt;
-    struct ap_threadattr_t *attr;
-    unsigned long tid;
-    ap_thread_start_t func;
-    void *data;
-    void *rv;
-};
-
-struct ap_threadkey_t {
-    ap_pool_t *cntxt;
-    unsigned long *key;
-};
-
-struct ap_procattr_t {
-    ap_pool_t *cntxt;
-    ap_file_t *parent_in;
-    ap_file_t *child_in;
-    ap_file_t *parent_out;
-    ap_file_t *child_out;
-    ap_file_t *parent_err;
-    ap_file_t *child_err;
-    char *currdir;
-    ap_int32_t cmdtype;
-    ap_int32_t detached;
-};
-
-struct ap_proc_t {
-    ap_pool_t *cntxt;
-    pid_t pid;
-    struct ap_procattr_t *attr;
-    int running;
-};
-
-typedef void (*os2_thread_start_t)(void *);
-
-#endif  /* ! THREAD_PROC_H */
-
diff --git a/threadproc/unix/.cvsignore b/threadproc/unix/.cvsignore
deleted file mode 100644
index f3c7a7c5da6..00000000000
--- a/threadproc/unix/.cvsignore
+++ /dev/null
@@ -1 +0,0 @@
-Makefile
diff --git a/threadproc/unix/Makefile.in b/threadproc/unix/Makefile.in
deleted file mode 100644
index 016f07a49c7..00000000000
--- a/threadproc/unix/Makefile.in
+++ /dev/null
@@ -1,93 +0,0 @@
-#CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
-#LIBS=$(EXTRA_LIBS) $(LIBS1)
-#INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
-#LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
-
-RM=@RM@
-CC=@CC@
-RANLIB=@RANLIB@
-CFLAGS=@CFLAGS@ @OPTIM@
-LIBS=@LIBS@
-LDFLAGS=@LDFLAGS@ $(LIBS)
-INCDIR=../../include
-INCDIR1=../../file_io/unix
-INCLUDES=-I$(INCDIR) -I$(INCDIR1) -I.
-
-LIB=libthreadproc.a
-
-OBJS=proc.o \
-	procsup.o \
-	thread.o \
-	threadpriv.o \
-	signals.o
-
-.c.o:
-	$(CC) $(CFLAGS) -c $(INCLUDES) $<
-
-all: $(OBJS)
-
-clean:
-	$(RM) -f *.o *.a *.so
-
-distclean: clean
-	-$(RM) -f Makefile
-
-$(OBJS): Makefile
-
-#$(LIB): $(OBJS)
-#	$(RM) -f $@
-#	$(AR) cr $@ $(OBJS)
-#	$(RANLIB) $@
-
-#
-# We really don't expect end users to use this rule.  It works only with
-# gcc, and rebuilds Makefile.tmpl.  You have to re-run Configure after
-# using it.
-#
-depend:
-	cp Makefile.in Makefile.in.bak \
-	    && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.in > Makefile.new \
-	    && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \
-	    && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
-	           -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
-		> Makefile.in \
-	    && rm Makefile.new
-
-# DO NOT REMOVE
-proc.o: proc.c threadproc.h $(INCDIR)/apr_private.h \
- $(INCDIR)/apr_thread_proc.h $(INCDIR)/apr_file_io.h \
- $(INCDIR)/apr_general.h $(INCDIR)/apr.h \
- $(INCDIR)/apr_errno.h $(INCDIR)/apr_time.h \
- ../../file_io/unix/fileio.h $(INCDIR)/apr_lib.h \
- $(INCDIR)/apr_portable.h $(INCDIR)/apr_network_io.h \
- $(INCDIR)/apr_lock.h
-procsup.o: procsup.c threadproc.h $(INCDIR)/apr_private.h \
- $(INCDIR)/apr_thread_proc.h $(INCDIR)/apr_file_io.h \
- $(INCDIR)/apr_general.h $(INCDIR)/apr.h \
- $(INCDIR)/apr_errno.h $(INCDIR)/apr_time.h \
- ../../file_io/unix/fileio.h $(INCDIR)/apr_lib.h
-signals.o: signals.c threadproc.h $(INCDIR)/apr_private.h \
- $(INCDIR)/apr_thread_proc.h $(INCDIR)/apr_file_io.h \
- $(INCDIR)/apr_general.h $(INCDIR)/apr.h \
- $(INCDIR)/apr_errno.h $(INCDIR)/apr_time.h \
- ../../file_io/unix/fileio.h $(INCDIR)/apr_lib.h
-thread.o: thread.c threadproc.h $(INCDIR)/apr_private.h \
- $(INCDIR)/apr_thread_proc.h $(INCDIR)/apr_file_io.h \
- $(INCDIR)/apr_general.h $(INCDIR)/apr.h \
- $(INCDIR)/apr_errno.h $(INCDIR)/apr_time.h \
- ../../file_io/unix/fileio.h $(INCDIR)/apr_lib.h \
- $(INCDIR)/apr_portable.h $(INCDIR)/apr_network_io.h \
- $(INCDIR)/apr_lock.h
-threadcancel.o: threadcancel.c threadproc.h \
- $(INCDIR)/apr_private.h $(INCDIR)/apr_thread_proc.h \
- $(INCDIR)/apr_file_io.h $(INCDIR)/apr_general.h \
- $(INCDIR)/apr.h $(INCDIR)/apr_errno.h \
- $(INCDIR)/apr_time.h ../../file_io/unix/fileio.h \
- $(INCDIR)/apr_lib.h
-threadpriv.o: threadpriv.c threadproc.h $(INCDIR)/apr_private.h \
- $(INCDIR)/apr_thread_proc.h $(INCDIR)/apr_file_io.h \
- $(INCDIR)/apr_general.h $(INCDIR)/apr.h \
- $(INCDIR)/apr_errno.h $(INCDIR)/apr_time.h \
- ../../file_io/unix/fileio.h $(INCDIR)/apr_lib.h \
- $(INCDIR)/apr_portable.h $(INCDIR)/apr_network_io.h \
- $(INCDIR)/apr_lock.h
diff --git a/threadproc/unix/proc.c b/threadproc/unix/proc.c
index 0d951f8527d..004772ff88e 100644
--- a/threadproc/unix/proc.c
+++ b/threadproc/unix/proc.c
@@ -1,378 +1,739 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "threadproc.h"
+#include "apr_arch_threadproc.h"
+#include "apr_strings.h"
 #include "apr_portable.h"
+#include "apr_signal.h"
+#include "apr_random.h"
+
+/* Heavy on no'ops, here's what we want to pass if there is APR_NO_FILE
+ * requested for a specific child handle;
+ */
+static apr_file_t no_file = { NULL, -1, };
 
-ap_status_t ap_createprocattr_init(ap_procattr_t **new, ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_procattr_create(apr_procattr_t **new,
+                                              apr_pool_t *pool)
 {
-    (*new) = (ap_procattr_t *)ap_palloc(cont, 
-              sizeof(ap_procattr_t));
+    (*new) = (apr_procattr_t *)apr_pcalloc(pool, sizeof(apr_procattr_t));
 
     if ((*new) == NULL) {
         return APR_ENOMEM;
     }
-    (*new)->cntxt = cont;
-    (*new)->parent_in = NULL;
-    (*new)->child_in = NULL;
-    (*new)->parent_out = NULL;
-    (*new)->child_out = NULL;
-    (*new)->parent_err = NULL;
-    (*new)->child_err = NULL;
-    (*new)->currdir = NULL; 
+    (*new)->pool = pool;
     (*new)->cmdtype = APR_PROGRAM;
-    (*new)->detached = 0; 
+    (*new)->uid = (*new)->gid = -1;
     return APR_SUCCESS;
 }
 
-ap_status_t ap_setprocattr_io(ap_procattr_t *attr, ap_int32_t in, 
-                                 ap_int32_t out, ap_int32_t err)
+APR_DECLARE(apr_status_t) apr_procattr_io_set(apr_procattr_t *attr,
+                                              apr_int32_t in,
+                                              apr_int32_t out,
+                                              apr_int32_t err)
 {
-    ap_status_t status;
-    if (in != 0) {
-        if ((status = ap_create_pipe(&attr->child_in, &attr->parent_in, 
-                                   attr->cntxt)) != APR_SUCCESS) {
-            return status;
-        }
-        switch (in) {
-        case APR_FULL_BLOCK:
-            ap_block_pipe(attr->child_in);
-            ap_block_pipe(attr->parent_in);
-        case APR_PARENT_BLOCK:
-            ap_block_pipe(attr->parent_in);
-        case APR_CHILD_BLOCK:
-            ap_block_pipe(attr->child_in);
-        }
-    } 
-    if (out) {
-        if ((status = ap_create_pipe(&attr->parent_out, &attr->child_out, 
-                                   attr->cntxt)) != APR_SUCCESS) {
-            return status;
-        }
-        switch (out) {
-        case APR_FULL_BLOCK:
-            ap_block_pipe(attr->child_out);
-            ap_block_pipe(attr->parent_out);
-        case APR_PARENT_BLOCK:
-            ap_block_pipe(attr->parent_out);
-        case APR_CHILD_BLOCK:
-            ap_block_pipe(attr->child_out);
-        }
-    } 
-    if (err) {
-        if ((status = ap_create_pipe(&attr->parent_err, &attr->child_err, 
-                                   attr->cntxt)) != APR_SUCCESS) {
-            return status;
-        }
-        switch (err) {
-        case APR_FULL_BLOCK:
-            ap_block_pipe(attr->child_err);
-            ap_block_pipe(attr->parent_err);
-        case APR_PARENT_BLOCK:
-            ap_block_pipe(attr->parent_err);
-        case APR_CHILD_BLOCK:
-            ap_block_pipe(attr->child_err);
-        }
-    } 
+    apr_status_t rv;
+
+    if ((in != APR_NO_PIPE) && (in != APR_NO_FILE)) {
+        /* APR_CHILD_BLOCK maps to APR_WRITE_BLOCK, while
+         * APR_PARENT_BLOCK maps to APR_READ_BLOCK, so transpose 
+         * the CHILD/PARENT blocking flags for the stdin pipe.
+         * stdout/stderr map to the correct mode by default.
+         */
+        if (in == APR_CHILD_BLOCK)
+            in = APR_READ_BLOCK;
+        else if (in == APR_PARENT_BLOCK)
+            in = APR_WRITE_BLOCK;
+
+        if ((rv = apr_file_pipe_create_ex(&attr->child_in, &attr->parent_in,
+                                          in, attr->pool)) == APR_SUCCESS)
+            rv = apr_file_inherit_unset(attr->parent_in);
+        if (rv != APR_SUCCESS)
+            return rv;
+    }
+    else if (in == APR_NO_FILE)
+        attr->child_in = &no_file;
+
+    if ((out != APR_NO_PIPE) && (out != APR_NO_FILE)) {
+        if ((rv = apr_file_pipe_create_ex(&attr->parent_out, &attr->child_out,
+                                          out, attr->pool)) == APR_SUCCESS)
+            rv = apr_file_inherit_unset(attr->parent_out);
+        if (rv != APR_SUCCESS)
+            return rv;
+    }
+    else if (out == APR_NO_FILE)
+        attr->child_out = &no_file;
+
+    if ((err != APR_NO_PIPE) && (err != APR_NO_FILE)) {
+        if ((rv = apr_file_pipe_create_ex(&attr->parent_err, &attr->child_err,
+                                          err, attr->pool)) == APR_SUCCESS)
+            rv = apr_file_inherit_unset(attr->parent_err);
+        if (rv != APR_SUCCESS)
+            return rv;
+    }
+    else if (err == APR_NO_FILE)
+        attr->child_err = &no_file;
+
     return APR_SUCCESS;
 }
 
 
-ap_status_t ap_setprocattr_childin(ap_procattr_t *attr, ap_file_t *child_in,
-                                   ap_file_t *parent_in)
+APR_DECLARE(apr_status_t) apr_procattr_child_in_set(apr_procattr_t *attr,
+                                                    apr_file_t *child_in,
+                                                    apr_file_t *parent_in)
 {
-    if (attr->child_in == NULL && attr->parent_in == NULL)
-        ap_create_pipe(&attr->child_in, &attr->parent_in, attr->cntxt);
+    apr_status_t rv = APR_SUCCESS;
 
-    if (child_in != NULL)
-        ap_dupfile(&attr->child_in, child_in, attr->cntxt);
+    if (attr->child_in == NULL && attr->parent_in == NULL
+           && child_in == NULL && parent_in == NULL)
+        if ((rv = apr_file_pipe_create(&attr->child_in, &attr->parent_in,
+                                       attr->pool)) == APR_SUCCESS)
+            rv = apr_file_inherit_unset(attr->parent_in);
 
-    if (parent_in != NULL)
-        ap_dupfile(&attr->parent_in, parent_in, attr->cntxt);
+    if (child_in != NULL && rv == APR_SUCCESS) {
+        if (attr->child_in && (attr->child_in->filedes != -1))
+            rv = apr_file_dup2(attr->child_in, child_in, attr->pool);
+        else {
+            attr->child_in = NULL;
+            if ((rv = apr_file_dup(&attr->child_in, child_in, attr->pool))
+                    == APR_SUCCESS)
+                rv = apr_file_inherit_set(attr->child_in);
+        }
+    }
 
-    return APR_SUCCESS;
+    if (parent_in != NULL && rv == APR_SUCCESS) {
+        if (attr->parent_in)
+            rv = apr_file_dup2(attr->parent_in, parent_in, attr->pool);
+        else
+            rv = apr_file_dup(&attr->parent_in, parent_in, attr->pool);
+    }
+
+    return rv;
 }
 
 
-ap_status_t ap_setprocattr_childout(ap_procattr_t *attr, ap_file_t *child_out,
-                                    ap_file_t *parent_out)
+APR_DECLARE(apr_status_t) apr_procattr_child_out_set(apr_procattr_t *attr,
+                                                     apr_file_t *child_out,
+                                                     apr_file_t *parent_out)
 {
-    if (attr->child_out == NULL && attr->parent_out == NULL)
-        ap_create_pipe(&attr->child_out, &attr->parent_out, attr->cntxt);
+    apr_status_t rv = APR_SUCCESS;
+
+    if (attr->child_out == NULL && attr->parent_out == NULL
+           && child_out == NULL && parent_out == NULL)
+        if ((rv = apr_file_pipe_create(&attr->parent_out, &attr->child_out,
+                                       attr->pool)) == APR_SUCCESS)
+            rv = apr_file_inherit_unset(attr->parent_out);
 
-    if (child_out != NULL)
-        ap_dupfile(&attr->child_out, child_out, attr->cntxt);
+    if (child_out != NULL && rv == APR_SUCCESS) {
+        if (attr->child_out && (attr->child_out->filedes != -1))
+            rv = apr_file_dup2(attr->child_out, child_out, attr->pool);
+        else {
+            attr->child_out = NULL;
+            if ((rv = apr_file_dup(&attr->child_out, child_out, attr->pool))
+                    == APR_SUCCESS)
+                rv = apr_file_inherit_set(attr->child_out);
+        }
+    }
 
-    if (parent_out != NULL)
-        ap_dupfile(&attr->parent_out, parent_out, attr->cntxt);
+    if (parent_out != NULL && rv == APR_SUCCESS) {
+        if (attr->parent_out)
+            rv = apr_file_dup2(attr->parent_out, parent_out, attr->pool);
+        else
+            rv = apr_file_dup(&attr->parent_out, parent_out, attr->pool);
+    }
 
-    return APR_SUCCESS;
+    return rv;
 }
 
 
-ap_status_t ap_setprocattr_childerr(ap_procattr_t *attr, ap_file_t *child_err,
-                                   ap_file_t *parent_err)
+APR_DECLARE(apr_status_t) apr_procattr_child_err_set(apr_procattr_t *attr,
+                                                     apr_file_t *child_err,
+                                                     apr_file_t *parent_err)
 {
-    if (attr->child_err == NULL && attr->parent_err == NULL)
-        ap_create_pipe(&attr->child_err, &attr->parent_err, attr->cntxt);
+    apr_status_t rv = APR_SUCCESS;
 
-    if (child_err != NULL)
-        ap_dupfile(&attr->child_err, child_err, attr->cntxt);
+    if (attr->child_err == NULL && attr->parent_err == NULL
+           && child_err == NULL && parent_err == NULL)
+        if ((rv = apr_file_pipe_create(&attr->parent_err, &attr->child_err,
+                                      attr->pool)) == APR_SUCCESS)
+            rv = apr_file_inherit_unset(attr->parent_err);
 
-    if (parent_err != NULL)
-        ap_dupfile(&attr->parent_err, parent_err, attr->cntxt);
+    if (child_err != NULL && rv == APR_SUCCESS) {
+        if (attr->child_err && (attr->child_err->filedes != -1))
+            rv = apr_file_dup2(attr->child_err, child_err, attr->pool);
+        else {
+            attr->child_err = NULL;
+            if ((rv = apr_file_dup(&attr->child_err, child_err, attr->pool))
+                    == APR_SUCCESS)
+                rv = apr_file_inherit_set(attr->child_err);
+        }
+    }
+    if (parent_err != NULL && rv == APR_SUCCESS) {
+        if (attr->parent_err)
+            rv = apr_file_dup2(attr->parent_err, parent_err, attr->pool);
+        else
+            rv = apr_file_dup(&attr->parent_err, parent_err, attr->pool);
+    }
 
-    return APR_SUCCESS;
+    return rv;
 }
 
 
-ap_status_t ap_setprocattr_dir(ap_procattr_t *attr, 
-                               const char *dir) 
+APR_DECLARE(apr_status_t) apr_procattr_dir_set(apr_procattr_t *attr,
+                                               const char *dir)
 {
-    attr->currdir = ap_pstrdup(attr->cntxt, dir);
+    attr->currdir = apr_pstrdup(attr->pool, dir);
     if (attr->currdir) {
         return APR_SUCCESS;
     }
+
     return APR_ENOMEM;
 }
 
-ap_status_t ap_setprocattr_cmdtype(ap_procattr_t *attr,
-                                     ap_cmdtype_e cmd) 
+APR_DECLARE(apr_status_t) apr_procattr_cmdtype_set(apr_procattr_t *attr,
+                                                   apr_cmdtype_e cmd)
 {
     attr->cmdtype = cmd;
     return APR_SUCCESS;
 }
 
-ap_status_t ap_setprocattr_detach(ap_procattr_t *attr, ap_int32_t detach) 
+APR_DECLARE(apr_status_t) apr_procattr_detach_set(apr_procattr_t *attr,
+                                                  apr_int32_t detach)
 {
     attr->detached = detach;
     return APR_SUCCESS;
 }
 
-ap_status_t ap_fork(ap_proc_t **proc, ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_proc_fork(apr_proc_t *proc, apr_pool_t *pool)
 {
     int pid;
     
-    (*proc) = ap_palloc(cont, sizeof(ap_proc_t));
+    memset(proc, 0, sizeof(apr_proc_t));
 
     if ((pid = fork()) < 0) {
         return errno;
     }
     else if (pid == 0) {
-        (*proc)->pid = pid;
-        (*proc)->attr = NULL;
+        proc->pid = getpid();
+
+        apr_random_after_fork(proc);
+
         return APR_INCHILD;
     }
-    (*proc)->pid = pid;
-    (*proc)->attr = NULL;
+
+    proc->pid = pid;
+
     return APR_INPARENT;
 }
 
-ap_status_t ap_create_process(ap_proc_t **new, const char *progname, 
-                              char *const args[], char **env,
-                              ap_procattr_t *attr, ap_pool_t *cont)
+static apr_status_t limit_proc(apr_procattr_t *attr)
 {
-    int i;
-    typedef const char *my_stupid_string;
-    my_stupid_string *newargs;
-    ap_proc_t *pgrp; 
+#if APR_HAVE_STRUCT_RLIMIT && APR_HAVE_SETRLIMIT
+#ifdef RLIMIT_CPU
+    if (attr->limit_cpu != NULL) {
+        if ((setrlimit(RLIMIT_CPU, attr->limit_cpu)) != 0) {
+            return errno;
+        }
+    }
+#endif
+#ifdef RLIMIT_NPROC
+    if (attr->limit_nproc != NULL) {
+        if ((setrlimit(RLIMIT_NPROC, attr->limit_nproc)) != 0) {
+            return errno;
+        }
+    }
+#endif
+#ifdef RLIMIT_NOFILE
+    if (attr->limit_nofile != NULL) {
+        if ((setrlimit(RLIMIT_NOFILE, attr->limit_nofile)) != 0) {
+            return errno;
+        }
+    }
+#endif
+#if defined(RLIMIT_AS)
+    if (attr->limit_mem != NULL) {
+        if ((setrlimit(RLIMIT_AS, attr->limit_mem)) != 0) {
+            return errno;
+        }
+    }
+#elif defined(RLIMIT_DATA)
+    if (attr->limit_mem != NULL) {
+        if ((setrlimit(RLIMIT_DATA, attr->limit_mem)) != 0) {
+            return errno;
+        }
+    }
+#elif defined(RLIMIT_VMEM)
+    if (attr->limit_mem != NULL) {
+        if ((setrlimit(RLIMIT_VMEM, attr->limit_mem)) != 0) {
+            return errno;
+        }
+    }
+#endif
+#else
+    /*
+     * Maybe make a note in error_log that setrlimit isn't supported??
+     */
 
-    (*new) = (ap_proc_t *)ap_palloc(cont, sizeof(ap_proc_t));
+#endif
+    return APR_SUCCESS;
+}
 
-    if ((*new) == NULL) {
-        return APR_ENOMEM;
+APR_DECLARE(apr_status_t) apr_procattr_child_errfn_set(apr_procattr_t *attr,
+                                                       apr_child_errfn_t *errfn)
+{
+    attr->errfn = errfn;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_procattr_error_check_set(apr_procattr_t *attr,
+                                                       apr_int32_t chk)
+{
+    attr->errchk = chk;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_procattr_addrspace_set(apr_procattr_t *attr,
+                                                       apr_int32_t addrspace)
+{
+    /* won't ever be used on this platform, so don't save the flag */
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_procattr_user_set(apr_procattr_t *attr,
+                                                const char *username,
+                                                const char *password)
+{
+    apr_status_t rv;
+    apr_gid_t    gid;
+
+    if ((rv = apr_uid_get(&attr->uid, &gid, username,
+                          attr->pool)) != APR_SUCCESS) {
+        attr->uid = -1;
+        return rv;
     }
+    
+    /* Use default user group if not already set */
+    if (attr->gid == -1) {
+        attr->gid = gid;
+    }
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_procattr_group_set(apr_procattr_t *attr,
+                                                 const char *groupname)
+{
+    apr_status_t rv;
+
+    if ((rv = apr_gid_get(&attr->gid, groupname, attr->pool)) != APR_SUCCESS)
+        attr->gid = -1;
+    return rv;
+}
+
+APR_DECLARE(apr_status_t) apr_proc_create(apr_proc_t *new,
+                                          const char *progname,
+                                          const char * const *args,
+                                          const char * const *env,
+                                          apr_procattr_t *attr,
+                                          apr_pool_t *pool)
+{
+    int i;
+    const char * const empty_envp[] = {NULL};
 
-    (*new)->cntxt = cont;
+    if (!env) { /* Specs require an empty array instead of NULL;
+                 * Purify will trigger a failure, even if many
+                 * implementations don't.
+                 */
+        env = empty_envp;
+    }
+
+    new->in = attr->parent_in;
+    new->err = attr->parent_err;
+    new->out = attr->parent_out;
+
+    if (attr->errchk) {
+        if (attr->currdir) {
+            if (access(attr->currdir, X_OK) == -1) {
+                /* chdir() in child wouldn't have worked */
+                return errno;
+            }
+        }
+
+        if (attr->cmdtype == APR_PROGRAM ||
+            attr->cmdtype == APR_PROGRAM_ENV ||
+            *progname == '/') {
+            /* for both of these values of cmdtype, caller must pass
+             * full path, so it is easy to check;
+             * caller can choose to pass full path for other
+             * values of cmdtype
+             */
+            if (access(progname, X_OK) == -1) {
+                /* exec*() in child wouldn't have worked */
+                return errno;
+            }
+        }
+        else {
+            /* todo: search PATH for progname then try to access it */
+        }
+    }
 
-    if (((*new)->pid = fork()) < 0) {
+    if ((new->pid = fork()) < 0) {
         return errno;
     }
-    else if ((*new)->pid == 0) { 
+    else if (new->pid == 0) {
         /* child process */
+
+        /*
+         * If we do exec cleanup before the dup2() calls to set up pipes
+         * on 0-2, we accidentally close the pipes used by programs like
+         * mod_cgid.
+         *
+         * If we do exec cleanup after the dup2() calls, cleanup can accidentally
+         * close our pipes which replaced any files which previously had
+         * descriptors 0-2.
+         *
+         * The solution is to kill the cleanup for the pipes, then do
+         * exec cleanup, then do the dup2() calls.
+         */
+
         if (attr->child_in) {
-            ap_close(attr->parent_in);
-            dup2(attr->child_in->filedes, STDIN_FILENO);
-            ap_close(attr->child_in);
+            apr_pool_cleanup_kill(apr_file_pool_get(attr->child_in),
+                                  attr->child_in, apr_unix_file_cleanup);
         }
+
         if (attr->child_out) {
-            ap_close(attr->parent_out);
-            dup2(attr->child_out->filedes, STDOUT_FILENO);
-            ap_close(attr->child_out);
+            apr_pool_cleanup_kill(apr_file_pool_get(attr->child_out),
+                                  attr->child_out, apr_unix_file_cleanup);
         }
+
         if (attr->child_err) {
-            ap_close(attr->parent_err);
+            apr_pool_cleanup_kill(apr_file_pool_get(attr->child_err),
+                                  attr->child_err, apr_unix_file_cleanup);
+        }
+
+        apr_pool_cleanup_for_exec();
+
+        if ((attr->child_in) && (attr->child_in->filedes == -1)) {
+            close(STDIN_FILENO);
+        }
+        else if (attr->child_in &&
+                 attr->child_in->filedes != STDIN_FILENO) {
+            dup2(attr->child_in->filedes, STDIN_FILENO);
+            apr_file_close(attr->child_in);
+        }
+
+        if ((attr->child_out) && (attr->child_out->filedes == -1)) {
+            close(STDOUT_FILENO);
+        }
+        else if (attr->child_out &&
+                 attr->child_out->filedes != STDOUT_FILENO) {
+            dup2(attr->child_out->filedes, STDOUT_FILENO);
+            apr_file_close(attr->child_out);
+        }
+
+        if ((attr->child_err) && (attr->child_err->filedes == -1)) {
+            close(STDERR_FILENO);
+        }
+        else if (attr->child_err &&
+                 attr->child_err->filedes != STDERR_FILENO) {
             dup2(attr->child_err->filedes, STDERR_FILENO);
-            ap_close(attr->child_err);
+            apr_file_close(attr->child_err);
         }
-        
-        ap_signal(SIGCHLD, SIG_DFL); /*not sure if this is needed or not */
+
+        apr_signal(SIGCHLD, SIG_DFL); /* not sure if this is needed or not */
 
         if (attr->currdir != NULL) {
             if (chdir(attr->currdir) == -1) {
-                exit(-1);   /* We have big problems, the child should exit. */
+                if (attr->errfn) {
+                    attr->errfn(pool, errno, "change of working directory failed");
+                }
+                _exit(-1);   /* We have big problems, the child should exit. */
+            }
+        }
+        if (!geteuid()) {
+            apr_procattr_pscb_t *c = attr->perms_set_callbacks;
+
+            while (c) {
+                apr_status_t r;
+                r = (*c->perms_set_fn)((void *)c->data, c->perms,
+                                       attr->uid, attr->gid);
+                if (r != APR_SUCCESS && r != APR_ENOTIMPL) {
+                    _exit(-1);
+                }
+                c = c->next;
+            }
+        }
+        /* Only try to switch if we are running as root */
+        if (attr->gid != -1 && !geteuid()) {
+            if (setgid(attr->gid)) {
+                if (attr->errfn) {
+                    attr->errfn(pool, errno, "setting of group failed");
+                }
+                _exit(-1);   /* We have big problems, the child should exit. */
             }
         }
 
-        ap_cleanup_for_exec();
+        if (attr->uid != -1 && !geteuid()) {
+            if (setuid(attr->uid)) {
+                if (attr->errfn) {
+                    attr->errfn(pool, errno, "setting of user failed");
+                }
+                _exit(-1);   /* We have big problems, the child should exit. */
+            }
+        }
 
-        if (attr->cmdtype == APR_SHELLCMD) {
-            i = 0;
-            while (args[i]) {
-                i++;
+        if (limit_proc(attr) != APR_SUCCESS) {
+            if (attr->errfn) {
+                attr->errfn(pool, errno, "setting of resource limits failed");
             }
-            newargs =
-               (my_stupid_string *) ap_palloc(cont, sizeof (char *) * (i + 3));
+            _exit(-1);   /* We have big problems, the child should exit. */
+        }
+
+        if (attr->cmdtype == APR_SHELLCMD ||
+            attr->cmdtype == APR_SHELLCMD_ENV) {
+            int onearg_len = 0;
+            const char *newargs[4];
+
             newargs[0] = SHELL_PATH;
             newargs[1] = "-c";
+
             i = 0;
             while (args[i]) {
-                newargs[i + 2] = args[i]; 
+                onearg_len += strlen(args[i]);
+                onearg_len++; /* for space delimiter */
                 i++;
             }
-            newargs[i + 3] = NULL;
+
+            switch(i) {
+            case 0:
+                /* bad parameters; we're doomed */
+                break;
+            case 1:
+                /* no args, or caller already built a single string from
+                 * progname and args
+                 */
+                newargs[2] = args[0];
+                break;
+            default:
+            {
+                char *ch, *onearg;
+                
+                ch = onearg = apr_palloc(pool, onearg_len);
+                i = 0;
+                while (args[i]) {
+                    size_t len = strlen(args[i]);
+
+                    memcpy(ch, args[i], len);
+                    ch += len;
+                    *ch = ' ';
+                    ++ch;
+                    ++i;
+                }
+                --ch; /* back up to trailing blank */
+                *ch = '\0';
+                newargs[2] = onearg;
+            }
+            }
+
+            newargs[3] = NULL;
+
             if (attr->detached) {
-                ap_detach(&pgrp, attr->cntxt);
+                apr_proc_detach(APR_PROC_DETACH_DAEMONIZE);
+            }
+
+            if (attr->cmdtype == APR_SHELLCMD) {
+                execve(SHELL_PATH, (char * const *) newargs, (char * const *)env);
+            }
+            else {
+                execv(SHELL_PATH, (char * const *)newargs);
             }
-            execve(SHELL_PATH, (char **) newargs, env);
+        }
+        else if (attr->cmdtype == APR_PROGRAM) {
+            if (attr->detached) {
+                apr_proc_detach(APR_PROC_DETACH_DAEMONIZE);
+            }
+
+            execve(progname, (char * const *)args, (char * const *)env);
+        }
+        else if (attr->cmdtype == APR_PROGRAM_ENV) {
+            if (attr->detached) {
+                apr_proc_detach(APR_PROC_DETACH_DAEMONIZE);
+            }
+
+            execv(progname, (char * const *)args);
         }
         else {
+            /* APR_PROGRAM_PATH */
             if (attr->detached) {
-                ap_detach(&pgrp, attr->cntxt);
+                apr_proc_detach(APR_PROC_DETACH_DAEMONIZE);
             }
-            execve(progname, args, env);
+
+            execvp(progname, (char * const *)args);
         }
-        exit(-1);  /* if we get here, there is a problem, so exit with an */ 
-                   /* error code. */
+        if (attr->errfn) {
+            char *desc;
+
+            desc = apr_psprintf(pool, "exec of '%s' failed",
+                                progname);
+            attr->errfn(pool, errno, desc);
+        }
+
+        _exit(-1);  /* if we get here, there is a problem, so exit with an
+                     * error code. */
     }
+
     /* Parent process */
-    if (attr->child_in) {
-        ap_close(attr->child_in);
+    if (attr->child_in && (attr->child_in->filedes != -1)) {
+        apr_file_close(attr->child_in);
     }
-    if (attr->child_out) {
-        ap_close(attr->child_out);
+
+    if (attr->child_out && (attr->child_out->filedes != -1)) {
+        apr_file_close(attr->child_out);
     }
-    if (attr->child_err) {
-        ap_close(attr->child_err);
+
+    if (attr->child_err && (attr->child_err->filedes != -1)) {
+        apr_file_close(attr->child_err);
     }
-    
-    (*new)->attr = attr;
+
     return APR_SUCCESS;
 }
 
-ap_status_t ap_get_childin(ap_file_t **new, ap_proc_t *proc)
+APR_DECLARE(apr_status_t) apr_proc_wait_all_procs(apr_proc_t *proc,
+                                                  int *exitcode,
+                                                  apr_exit_why_e *exitwhy,
+                                                  apr_wait_how_e waithow,
+                                                  apr_pool_t *p)
 {
-    (*new) = proc->attr->parent_in;
-    return APR_SUCCESS; 
+    proc->pid = -1;
+    return apr_proc_wait(proc, exitcode, exitwhy, waithow);
 }
 
-ap_status_t ap_get_childout(ap_file_t **new, ap_proc_t *proc)
+APR_DECLARE(apr_status_t) apr_proc_wait(apr_proc_t *proc,
+                                        int *exitcode, apr_exit_why_e *exitwhy,
+                                        apr_wait_how_e waithow)
 {
-    (*new) = proc->attr->parent_out; 
-    return APR_SUCCESS;
-}
+    pid_t pstatus;
+    int waitpid_options = WUNTRACED;
+    int exit_int;
+    int ignore;
+    apr_exit_why_e ignorewhy;
+
+    if (exitcode == NULL) {
+        exitcode = &ignore;
+    }
 
-ap_status_t ap_get_childerr(ap_file_t **new, ap_proc_t *proc)
-{
-    (*new) = proc->attr->parent_err; 
-    return APR_SUCCESS;
-}    
+    if (exitwhy == NULL) {
+        exitwhy = &ignorewhy;
+    }
 
-ap_status_t ap_wait_proc(ap_proc_t *proc, 
-                           ap_wait_how_e waithow)
-{
-    pid_t status;
-    if (!proc)
-        return APR_ENOPROC;
-    if (waithow == APR_WAIT) {
-        if ((status = waitpid(proc->pid, NULL, WUNTRACED)) > 0) {
-            return APR_CHILD_DONE;
+    if (waithow != APR_WAIT) {
+        waitpid_options |= WNOHANG;
+    }
+
+    do {
+        pstatus = waitpid(proc->pid, &exit_int, waitpid_options);
+    } while (pstatus < 0 && errno == EINTR);
+
+    if (pstatus > 0) {
+        proc->pid = pstatus;
+
+        if (WIFEXITED(exit_int)) {
+            *exitwhy = APR_PROC_EXIT;
+            *exitcode = WEXITSTATUS(exit_int);
         }
-        else if (status == 0) {
-            return APR_CHILD_NOTDONE;
+        else if (WIFSIGNALED(exit_int)) {
+            *exitwhy = APR_PROC_SIGNAL;
+
+#ifdef WCOREDUMP
+            if (WCOREDUMP(exit_int)) {
+                *exitwhy |= APR_PROC_SIGNAL_CORE;
+            }
+#endif
+
+            *exitcode = WTERMSIG(exit_int);
         }
-        return errno;
-    }
-    if ((status = waitpid(proc->pid, NULL, WUNTRACED | WNOHANG)) > 0) {
+        else {
+            /* unexpected condition */
+            return APR_EGENERAL;
+        }
+
         return APR_CHILD_DONE;
     }
-    else if (status == 0) {
+    else if (pstatus == 0) {
         return APR_CHILD_NOTDONE;
     }
+
     return errno;
-} 
+}
 
-ap_status_t ap_get_os_proc(ap_os_proc_t *theproc, ap_proc_t *proc)
+#if APR_HAVE_STRUCT_RLIMIT
+APR_DECLARE(apr_status_t) apr_procattr_limit_set(apr_procattr_t *attr,
+                                                 apr_int32_t what,
+                                                 struct rlimit *limit)
 {
-    if (proc == NULL) {
-        return APR_ENOPROC;
+    switch(what) {
+        case APR_LIMIT_CPU:
+#ifdef RLIMIT_CPU
+            attr->limit_cpu = limit;
+            break;
+#else
+            return APR_ENOTIMPL;
+#endif
+
+        case APR_LIMIT_MEM:
+#if defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS)
+            attr->limit_mem = limit;
+            break;
+#else
+            return APR_ENOTIMPL;
+#endif
+
+        case APR_LIMIT_NPROC:
+#ifdef RLIMIT_NPROC
+            attr->limit_nproc = limit;
+            break;
+#else
+            return APR_ENOTIMPL;
+#endif
+
+        case APR_LIMIT_NOFILE:
+#ifdef RLIMIT_NOFILE
+            attr->limit_nofile = limit;
+            break;
+#else
+            return APR_ENOTIMPL;
+#endif
+
     }
-    *theproc = proc->pid;
+
     return APR_SUCCESS;
 }
+#endif /* APR_HAVE_STRUCT_RLIMIT */
 
-ap_status_t ap_put_os_proc(ap_proc_t **proc, ap_os_proc_t *theproc, 
-                           ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_procattr_perms_set_register(apr_procattr_t *attr,
+                                                 apr_perms_setfn_t *perms_set_fn,
+                                                 void *data,
+                                                 apr_fileperms_t perms)
 {
-    if (cont == NULL) {
-        return APR_ENOPOOL;
-    }
-    if ((*proc) == NULL) {
-        (*proc) = (ap_proc_t *)ap_palloc(cont, sizeof(ap_proc_t));
-        (*proc)->cntxt = cont;
-    }
-    (*proc)->pid = *theproc;
-    return APR_SUCCESS;
-}              
+    apr_procattr_pscb_t *c;
+
+    c = apr_palloc(attr->pool, sizeof(apr_procattr_pscb_t));
+    c->data = data;
+    c->perms = perms;
+    c->perms_set_fn = perms_set_fn;
+    c->next = attr->perms_set_callbacks;
+    attr->perms_set_callbacks = c;
 
+    return APR_SUCCESS;
+}
diff --git a/threadproc/unix/procsup.c b/threadproc/unix/procsup.c
index a2bdf38f1e5..94177f92a65 100644
--- a/threadproc/unix/procsup.c
+++ b/threadproc/unix/procsup.c
@@ -1,96 +1,61 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "threadproc.h"
+#include "apr_arch_threadproc.h"
 
-ap_status_t ap_detach(ap_proc_t **new, ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_proc_detach(int daemonize)
 {
-    int x;
+    if (chdir("/") == -1) {
+        return errno;
+    }
 
-    (*new) = (ap_proc_t *)ap_palloc(cont, sizeof(ap_proc_t));
-    (*new)->cntxt = cont;
-    (*new)->attr = NULL;
+#if !defined(MPE) && !defined(OS2) && !defined(TPF) && !defined(BEOS)
+    /* Don't detach for MPE because child processes can't survive the death of
+     * the parent. */
+    if (daemonize) {
+        int x;
 
-    chdir("/");
-#if !defined(MPE) && !defined(OS2) && !defined(TPF)
-/* Don't detach for MPE because child processes can't survive the death of
-   the parent. */
-    if ((x = fork()) > 0)
-        exit(0);
-    else if (x == -1) {
-        perror("fork");
-        fprintf(stderr, "unable to fork new process\n");
-        exit(1);  /* we can't do anything here, so just exit. */
+        if ((x = fork()) > 0) {
+            exit(0);
+        }
+        else if (x == -1) {
+            perror("fork");
+            fprintf(stderr, "unable to fork new process\n");
+            exit(1);  /* we can't do anything here, so just exit. */
+        }
+        /* RAISE_SIGSTOP(DETACH); */
     }
-/*    RAISE_SIGSTOP(DETACH);*/
 #endif
-#if HAVE_SETSID
-    if (((*new)->pid = setsid()) == -1) {
+
+#ifdef HAVE_SETSID
+    /* A setsid() failure is not fatal if we didn't just fork().
+     * The calling process may be the process group leader, in
+     * which case setsid() will fail with EPERM.
+     */
+    if (setsid() == -1 && daemonize) {
         return errno;
     }
 #elif defined(NEXT) || defined(NEWSOS)
-    if (setpgrp(0, getpid()) == -1 || ((*new)->pid = getpgrp(0)) == -1) {
+    if (setpgrp(0, getpid()) == -1) {
         return errno;
     }
-#elif defined(OS2) || defined(TPF)
-    /* OS/2 don't support process group IDs */
-    (*new)->pid = getpid();
-#elif defined(MPE)
-    /* MPE uses negative pid for process group */
-     (*new)->pid = -getpid();
+#elif defined(OS2) || defined(TPF) || defined(MPE)
+    /* do nothing */
 #else
-    if (((*new)->pid = setpgrp(getpid(), 0)) == -1) {
+    if (setpgid(0, 0) == -1) {
         return errno;
     }
 #endif
@@ -114,31 +79,26 @@ ap_status_t ap_detach(ap_proc_t **new, ap_pool_t *cont)
     if (freopen("/dev/null", "w", stderr) == NULL) {
         return errno;
     }
-
     return APR_SUCCESS;
 }
 
-ap_status_t ap_get_procdata(char *key, void *data, ap_proc_t *proc)
-{
-    if (proc != NULL) {
-        return ap_get_userdata(data, key, proc->cntxt);
-    }
-    else {
-        data = NULL;
-        return APR_ENOPROC;
-    }
-}
-
-ap_status_t ap_set_procdata(void *data, char *key, 
-                            ap_status_t (*cleanup) (void *),
-                            ap_proc_t *proc)
+#if (!HAVE_WAITPID)
+/* From ikluft@amdahl.com
+ * this is not ideal but it works for SVR3 variants
+ * Modified by dwd@bell-labs.com to call wait3 instead of wait because
+ *   apache started to use the WNOHANG option.
+ */
+int waitpid(pid_t pid, int *statusp, int options)
 {
-    if (proc != NULL) {
-        return ap_set_userdata(data, key, cleanup, proc->cntxt);
-    }
-    else {
-        data = NULL;
-        return APR_ENOPROC;
+    int tmp_pid;
+    if (kill(pid, 0) == -1) {
+        errno = ECHILD;
+        return -1;
     }
+    while (((tmp_pid = wait3(statusp, options, 0)) != pid) &&
+                (tmp_pid != -1) && (tmp_pid != 0) && (pid != -1))
+        ;
+    return tmp_pid;
 }
+#endif
 
diff --git a/threadproc/unix/signals.c b/threadproc/unix/signals.c
index d31edd324b7..361d68acbd9 100644
--- a/threadproc/unix/signals.c
+++ b/threadproc/unix/signals.c
@@ -1,68 +1,487 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 BEOS
-#include "threadproc.h"
+#define INCL_DOSEXCEPTIONS      /* for OS2 */
+#include "apr_arch_threadproc.h"
+#include "apr_private.h"
+#include "apr_pools.h"
+#include "apr_signal.h"
+#include "apr_strings.h"
+
+#include <assert.h>
+#if APR_HAS_THREADS && APR_HAVE_PTHREAD_H
+#include <pthread.h>
+#endif
+
+#ifdef SIGWAIT_TAKES_ONE_ARG
+#define apr_sigwait(a,b) ((*(b)=sigwait((a)))<0?-1:0)
 #else
-#include "../beos/threadproc.h"
+#define apr_sigwait(a,b) sigwait((a),(b))
 #endif
 
-ap_status_t ap_kill(ap_proc_t *proc, int sig)
+APR_DECLARE(apr_status_t) apr_proc_kill(apr_proc_t *proc, int signum)
 {
-    if (kill(proc->pid, sig) == -1) {
+#ifdef OS2
+    /* SIGTERM's don't work too well in OS/2 (only affects other EMX
+     * programs). CGIs may not be, esp. REXX scripts, so use a native
+     * call instead
+     */
+    if (signum == SIGTERM) {
+        return APR_FROM_OS_ERROR(DosSendSignalException(proc->pid,
+                                                     XCPT_SIGNAL_BREAK));
+    }
+#endif /* OS2 */
+
+    if (kill(proc->pid, signum) == -1) {
         return errno;
     }
+
     return APR_SUCCESS;
 }
 
+
+#if APR_HAVE_SIGACTION
+
+#if defined(__NetBSD__) || defined(DARWIN)
+static void avoid_zombies(int signo)
+{
+    int exit_status;
+
+    while (waitpid(-1, &exit_status, WNOHANG) > 0) {
+        /* do nothing */
+    }
+}
+#endif /* DARWIN */
+
+/*
+ * Replace standard signal() with the more reliable sigaction equivalent
+ * from W. Richard Stevens' "Advanced Programming in the UNIX Environment"
+ * (the version that does not automatically restart system calls).
+ */
+APR_DECLARE(apr_sigfunc_t *) apr_signal(int signo, apr_sigfunc_t * func)
+{
+    struct sigaction act, oact;
+
+    act.sa_handler = func;
+    sigemptyset(&act.sa_mask);
+    act.sa_flags = 0;
+#ifdef SA_INTERRUPT             /* SunOS */
+    act.sa_flags |= SA_INTERRUPT;
+#endif
+#if defined(__osf__) && defined(__alpha)
+    /* XXX jeff thinks this should be enabled whenever SA_NOCLDWAIT is defined */
+
+    /* this is required on Tru64 to cause child processes to
+     * disappear gracefully - XPG4 compatible 
+     */
+    if ((signo == SIGCHLD) && (func == SIG_IGN)) {
+        act.sa_flags |= SA_NOCLDWAIT;
+    }
+#endif
+#if defined(__NetBSD__) || defined(DARWIN)
+    /* ignoring SIGCHLD or leaving the default disposition doesn't avoid zombies,
+     * and there is no SA_NOCLDWAIT flag, so catch the signal and reap status in 
+     * the handler to avoid zombies
+     */
+    if ((signo == SIGCHLD) && (func == SIG_IGN)) {
+        act.sa_handler = avoid_zombies;
+    }
+#endif
+    if (sigaction(signo, &act, &oact) < 0)
+        return SIG_ERR;
+    return oact.sa_handler;
+}
+
+#endif /* HAVE_SIGACTION */
+
+/* AC_DECL_SYS_SIGLIST defines either of these symbols depending
+ * on the version of autoconf used. */
+#if defined(SYS_SIGLIST_DECLARED) || HAVE_DECL_SYS_SIGLIST
+
+void apr_signal_init(apr_pool_t *pglobal)
+{
+}
+const char *apr_signal_description_get(int signum)
+{
+    return (signum >= 0) ? sys_siglist[signum] : "unknown signal (number)";
+}
+
+#else /* !(SYS_SIGLIST_DECLARED || HAVE_DECL_SYS_SIGLIST) */
+
+/* we need to roll our own signal description stuff */
+
+#if defined(NSIG)
+#define APR_NUMSIG NSIG
+#elif defined(_NSIG)
+#define APR_NUMSIG _NSIG
+#elif defined(__NSIG)
+#define APR_NUMSIG __NSIG
+#else
+#define APR_NUMSIG 33   /* breaks on OS/390 with < 33; 32 is o.k. for most */
+#endif
+
+static const char *signal_description[APR_NUMSIG];
+
+#define store_desc(index, string) \
+        do { \
+            if (index >= APR_NUMSIG) { \
+                assert(index < APR_NUMSIG); \
+            } \
+            else { \
+                signal_description[index] = string; \
+            } \
+        } while (0)
+
+void apr_signal_init(apr_pool_t *pglobal)
+{
+    int sig;
+
+    store_desc(0, "Signal 0");
+
+#ifdef SIGHUP
+    store_desc(SIGHUP, "Hangup");
+#endif
+#ifdef SIGINT
+    store_desc(SIGINT, "Interrupt");
+#endif
+#ifdef SIGQUIT
+    store_desc(SIGQUIT, "Quit");
+#endif
+#ifdef SIGILL
+    store_desc(SIGILL, "Illegal instruction");
+#endif
+#ifdef SIGTRAP
+    store_desc(SIGTRAP, "Trace/BPT trap");
+#endif
+#ifdef SIGIOT
+    store_desc(SIGIOT, "IOT instruction");
+#endif
+#ifdef SIGABRT
+    store_desc(SIGABRT, "Abort");
+#endif
+#ifdef SIGEMT
+    store_desc(SIGEMT, "Emulator trap");
+#endif
+#ifdef SIGFPE
+    store_desc(SIGFPE, "Arithmetic exception");
+#endif
+#ifdef SIGKILL
+    store_desc(SIGKILL, "Killed");
+#endif
+#ifdef SIGBUS
+    store_desc(SIGBUS, "Bus error");
+#endif
+#ifdef SIGSEGV
+    store_desc(SIGSEGV, "Segmentation fault");
+#endif
+#ifdef SIGSYS
+    store_desc(SIGSYS, "Bad system call");
+#endif
+#ifdef SIGPIPE
+    store_desc(SIGPIPE, "Broken pipe");
+#endif
+#ifdef SIGALRM
+    store_desc(SIGALRM, "Alarm clock");
+#endif
+#ifdef SIGTERM
+    store_desc(SIGTERM, "Terminated");
+#endif
+#ifdef SIGUSR1
+    store_desc(SIGUSR1, "User defined signal 1");
+#endif
+#ifdef SIGUSR2
+    store_desc(SIGUSR2, "User defined signal 2");
+#endif
+#ifdef SIGCLD
+    store_desc(SIGCLD, "Child status change");
+#endif
+#ifdef SIGCHLD
+    store_desc(SIGCHLD, "Child status change");
+#endif
+#ifdef SIGPWR
+    store_desc(SIGPWR, "Power-fail restart");
+#endif
+#ifdef SIGWINCH
+    store_desc(SIGWINCH, "Window changed");
+#endif
+#ifdef SIGURG
+    store_desc(SIGURG, "urgent socket condition");
+#endif
+#ifdef SIGPOLL
+    store_desc(SIGPOLL, "Pollable event occurred");
+#endif
+#ifdef SIGIO
+    store_desc(SIGIO, "socket I/O possible");
+#endif
+#ifdef SIGSTOP
+    store_desc(SIGSTOP, "Stopped (signal)");
+#endif
+#ifdef SIGTSTP
+    store_desc(SIGTSTP, "Stopped");
+#endif
+#ifdef SIGCONT
+    store_desc(SIGCONT, "Continued");
+#endif
+#ifdef SIGTTIN
+    store_desc(SIGTTIN, "Stopped (tty input)");
+#endif
+#ifdef SIGTTOU
+    store_desc(SIGTTOU, "Stopped (tty output)");
+#endif
+#ifdef SIGVTALRM
+    store_desc(SIGVTALRM, "virtual timer expired");
+#endif
+#ifdef SIGPROF
+    store_desc(SIGPROF, "profiling timer expired");
+#endif
+#ifdef SIGXCPU
+    store_desc(SIGXCPU, "exceeded cpu limit");
+#endif
+#ifdef SIGXFSZ
+    store_desc(SIGXFSZ, "exceeded file size limit");
+#endif
+
+    for (sig = 0; sig < APR_NUMSIG; ++sig)
+        if (signal_description[sig] == NULL)
+            signal_description[sig] = apr_psprintf(pglobal, "signal #%d", sig);
+}
+
+const char *apr_signal_description_get(int signum)
+{
+    return
+        (signum >= 0 && signum < APR_NUMSIG)
+        ? signal_description[signum]
+        : "unknown signal (number)";
+}
+
+#endif /* SYS_SIGLIST_DECLARED || HAVE_DECL_SYS_SIGLIST */
+
+#if APR_HAS_THREADS && (HAVE_SIGSUSPEND || APR_HAVE_SIGWAIT) && !defined(OS2)
+
+static void remove_sync_sigs(sigset_t *sig_mask)
+{
+#ifdef SIGABRT
+    sigdelset(sig_mask, SIGABRT);
+#endif
+#ifdef SIGBUS
+    sigdelset(sig_mask, SIGBUS);
+#endif
+#ifdef SIGEMT
+    sigdelset(sig_mask, SIGEMT);
+#endif
+#ifdef SIGFPE
+    sigdelset(sig_mask, SIGFPE);
+#endif
+#ifdef SIGILL
+    sigdelset(sig_mask, SIGILL);
+#endif
+#ifdef SIGIOT
+    sigdelset(sig_mask, SIGIOT);
+#endif
+#ifdef SIGPIPE
+    sigdelset(sig_mask, SIGPIPE);
+#endif
+#ifdef SIGSEGV
+    sigdelset(sig_mask, SIGSEGV);
+#endif
+#ifdef SIGSYS
+    sigdelset(sig_mask, SIGSYS);
+#endif
+#ifdef SIGTRAP
+    sigdelset(sig_mask, SIGTRAP);
+#endif
+
+/* the rest of the signals removed from the mask in this function
+ * absolutely must be removed; you cannot block synchronous signals
+ * (requirement of pthreads API)
+ *
+ * SIGUSR2 is being removed from the mask for the convenience of
+ * Purify users (Solaris, HP-UX, SGI) since Purify uses SIGUSR2
+ */
+#ifdef SIGUSR2
+    sigdelset(sig_mask, SIGUSR2);
+#endif
+}
+
+APR_DECLARE(apr_status_t) apr_signal_thread(int(*signal_handler)(int signum))
+{
+    sigset_t sig_mask;
+#if APR_HAVE_SIGWAIT
+    int (*sig_func)(int signum) = (int (*)(int))signal_handler;
+#endif
+
+    /* This thread will be the one responsible for handling signals */
+    sigfillset(&sig_mask);
+
+    /* On certain platforms, sigwait() returns EINVAL if any of various
+     * unblockable signals are included in the mask.  This was first 
+     * observed on AIX and Tru64.
+     */
+#ifdef SIGKILL
+    sigdelset(&sig_mask, SIGKILL);
+#endif
+#ifdef SIGSTOP
+    sigdelset(&sig_mask, SIGSTOP);
+#endif
+#ifdef SIGCONT
+    sigdelset(&sig_mask, SIGCONT);
+#endif
+#ifdef SIGWAITING
+    sigdelset(&sig_mask, SIGWAITING);
+#endif
+
+    /* no synchronous signals should be in the mask passed to sigwait() */
+    remove_sync_sigs(&sig_mask);
+
+    /* On AIX (4.3.3, at least), sigwait() won't wake up if the high-
+     * order bit of the second word of flags is turned on.  sigdelset()
+     * returns an error when trying to turn this off, so we'll turn it
+     * off manually.
+     *
+     * Note that the private fields differ between 32-bit and 64-bit
+     * and even between _ALL_SOURCE and !_ALL_SOURCE.  Except that on
+     * AIX 4.3 32-bit builds and 64-bit builds use the same definition.
+     *
+     * Applicable AIX fixes such that this is no longer needed:
+     *
+     * APAR IY23096 for AIX 51B, fix included in AIX 51C, and
+     * APAR IY24162 for 43X.
+     */
+#if defined(_AIX)
+#if defined(__64BIT__) && defined(_AIXVERSION_510)
+#ifdef _ALL_SOURCE
+        sig_mask.ss_set[3] &= 0x7FFFFFFF;
+#else /* not _ALL_SOURCE */
+        sig_mask.__ss_set[3] &= 0x7FFFFFFF;
+#endif
+#else /* not 64-bit build, or 64-bit build on 4.3 */
+#ifdef _ALL_SOURCE
+        sig_mask.hisigs &= 0x7FFFFFFF;
+#else /* not _ALL_SOURCE */
+        sig_mask.__hisigs &= 0x7FFFFFFF;
+#endif
+#endif
+#endif /* _AIX */
+
+    while (1) {
+#if APR_HAVE_SIGWAIT
+        int signal_received;
+
+        if (apr_sigwait(&sig_mask, &signal_received) != 0)
+        {
+            /* handle sigwait() error here */
+        }
+        
+        if (sig_func(signal_received) == 1) {
+            return APR_SUCCESS;
+        }
+#elif HAVE_SIGSUSPEND
+	sigsuspend(&sig_mask);
+#else
+#error No apr_sigwait() and no sigsuspend()
+#endif
+    }
+}
+
+APR_DECLARE(apr_status_t) apr_setup_signal_thread(void)
+{
+    sigset_t sig_mask;
+    int rv;
+
+    /* All threads should mask out signals to be handled by
+     * the thread doing sigwait().
+     *
+     * No thread should ever block synchronous signals.
+     * See the Solaris man page for pthread_sigmask() for
+     * some information.  Solaris chooses to knock out such
+     * processes when a blocked synchronous signal is 
+     * delivered, skipping any registered signal handler.
+     * AIX doesn't call a signal handler either.  At least
+     * one level of linux+glibc does call the handler even
+     * when the synchronous signal is blocked.
+     */
+    sigfillset(&sig_mask);
+    remove_sync_sigs(&sig_mask);
+
+#if defined(SIGPROCMASK_SETS_THREAD_MASK) || ! APR_HAS_THREADS
+    if ((rv = sigprocmask(SIG_SETMASK, &sig_mask, NULL)) != 0) {
+        rv = errno;
+    }
+#else
+    if ((rv = pthread_sigmask(SIG_SETMASK, &sig_mask, NULL)) != 0) {
+#ifdef HAVE_ZOS_PTHREADS
+        rv = errno;
+#endif
+    }
+#endif
+    return rv;
+}
+
+#endif /* APR_HAS_THREADS && ... */
+
+APR_DECLARE(apr_status_t) apr_signal_block(int signum)
+{
+#if APR_HAVE_SIGACTION
+    sigset_t sig_mask;
+    int rv;
+
+    sigemptyset(&sig_mask);
+
+    sigaddset(&sig_mask, signum);
+
+#if defined(SIGPROCMASK_SETS_THREAD_MASK) || ! APR_HAS_THREADS
+    if ((rv = sigprocmask(SIG_BLOCK, &sig_mask, NULL)) != 0) {
+        rv = errno;
+    }
+#else
+    if ((rv = pthread_sigmask(SIG_BLOCK, &sig_mask, NULL)) != 0) {
+#ifdef HAVE_ZOS_PTHREADS
+        rv = errno;
+#endif
+    }
+#endif
+    return rv;
+#else
+    return APR_ENOTIMPL;
+#endif
+}
+
+APR_DECLARE(apr_status_t) apr_signal_unblock(int signum)
+{
+#if APR_HAVE_SIGACTION
+    sigset_t sig_mask;
+    int rv;
+
+    sigemptyset(&sig_mask);
+
+    sigaddset(&sig_mask, signum);
+
+#if defined(SIGPROCMASK_SETS_THREAD_MASK) || ! APR_HAS_THREADS
+    if ((rv = sigprocmask(SIG_UNBLOCK, &sig_mask, NULL)) != 0) {
+        rv = errno;
+    }
+#else
+    if ((rv = pthread_sigmask(SIG_UNBLOCK, &sig_mask, NULL)) != 0) {
+#ifdef HAVE_ZOS_PTHREADS
+        rv = errno;
+#endif
+    }
+#endif
+    return rv;
+#else
+    return APR_ENOTIMPL;
+#endif
+}
diff --git a/threadproc/unix/thread.c b/threadproc/unix/thread.c
index 300818e0fa6..dcef500e9f7 100644
--- a/threadproc/unix/thread.c
+++ b/threadproc/unix/thread.c
@@ -1,222 +1,339 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "threadproc.h"
+#include "apr.h"
 #include "apr_portable.h"
+#include "apr_arch_threadproc.h"
 
 #if APR_HAS_THREADS
 
-#ifdef HAVE_PTHREAD_H
-ap_status_t ap_create_threadattr(ap_threadattr_t **new, ap_pool_t *cont)
+#if APR_HAVE_PTHREAD_H
+
+/* Destroy the threadattr object */
+static apr_status_t threadattr_cleanup(void *data)
 {
-    ap_status_t stat;
-  
-    (*new) = (ap_threadattr_t *)ap_palloc(cont, 
-              sizeof(ap_threadattr_t));
-    (*new)->attr = (pthread_attr_t *)ap_palloc(cont, 
-                    sizeof(pthread_attr_t));
+    apr_threadattr_t *attr = data;
+    apr_status_t rv;
 
-    if ((*new) == NULL || (*new)->attr == NULL) {
-        return APR_ENOMEM;
+    rv = pthread_attr_destroy(&attr->attr);
+#ifdef HAVE_ZOS_PTHREADS
+    if (rv) {
+        rv = errno;
     }
+#endif
+    return rv;
+}
 
-    (*new)->cntxt = cont;
-    stat = pthread_attr_init((*new)->attr);
+APR_DECLARE(apr_status_t) apr_threadattr_create(apr_threadattr_t **new,
+                                                apr_pool_t *pool)
+{
+    apr_status_t stat;
+
+    (*new) = apr_palloc(pool, sizeof(apr_threadattr_t));
+    (*new)->pool = pool;
+    stat = pthread_attr_init(&(*new)->attr);
 
     if (stat == 0) {
+        apr_pool_cleanup_register(pool, *new, threadattr_cleanup,
+                                  apr_pool_cleanup_null);
         return APR_SUCCESS;
     }
+#ifdef HAVE_ZOS_PTHREADS
+    stat = errno;
+#endif
+
     return stat;
 }
 
-ap_status_t ap_setthreadattr_detach(ap_threadattr_t *attr, ap_int32_t on)
+#if defined(PTHREAD_CREATE_DETACHED)
+#define DETACH_ARG(v) ((v) ? PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE)
+#else
+#define DETACH_ARG(v) ((v) ? 1 : 0)
+#endif
+
+APR_DECLARE(apr_status_t) apr_threadattr_detach_set(apr_threadattr_t *attr,
+                                                    apr_int32_t on)
 {
-    ap_status_t stat;
-    if ((stat = pthread_attr_setdetachstate(attr->attr, on)) == 0) {
+    apr_status_t stat;
+#ifdef HAVE_ZOS_PTHREADS
+    int arg = DETACH_ARG(on);
+
+    if ((stat = pthread_attr_setdetachstate(&attr->attr, &arg)) == 0) {
+#else
+    if ((stat = pthread_attr_setdetachstate(&attr->attr, 
+                                            DETACH_ARG(on))) == 0) {
+#endif
         return APR_SUCCESS;
     }
     else {
+#ifdef HAVE_ZOS_PTHREADS
+        stat = errno;
+#endif
+
         return stat;
     }
 }
 
-ap_status_t ap_getthreadattr_detach(ap_threadattr_t *attr)
+APR_DECLARE(apr_status_t) apr_threadattr_detach_get(apr_threadattr_t *attr)
 {
     int state;
 
-    pthread_attr_getdetachstate(attr->attr, &state);
-    if (state == 1)
+#ifdef PTHREAD_ATTR_GETDETACHSTATE_TAKES_ONE_ARG
+    state = pthread_attr_getdetachstate(&attr->attr);
+#else
+    pthread_attr_getdetachstate(&attr->attr, &state);
+#endif
+    if (state == DETACH_ARG(1))
         return APR_DETACH;
     return APR_NOTDETACH;
 }
 
-ap_status_t ap_create_thread(ap_thread_t **new, ap_threadattr_t *attr, 
-                             ap_thread_start_t func, void *data, 
-                             ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_threadattr_stacksize_set(apr_threadattr_t *attr,
+                                                       apr_size_t stacksize)
+{
+    int stat;
+
+    stat = pthread_attr_setstacksize(&attr->attr, stacksize);
+    if (stat == 0) {
+        return APR_SUCCESS;
+    }
+#ifdef HAVE_ZOS_PTHREADS
+    stat = errno;
+#endif
+
+    return stat;
+}
+
+APR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr,
+                                                       apr_size_t size)
 {
-    ap_status_t stat;
+#ifdef HAVE_PTHREAD_ATTR_SETGUARDSIZE
+    apr_status_t rv;
+
+    rv = pthread_attr_setguardsize(&attr->attr, size);
+    if (rv == 0) {
+        return APR_SUCCESS;
+    }
+#ifdef HAVE_ZOS_PTHREADS
+    rv = errno;
+#endif
+    return rv;
+#else
+    return APR_ENOTIMPL;
+#endif
+}
+
+static void *dummy_worker(void *opaque)
+{
+    apr_thread_t *thread = (apr_thread_t*)opaque;
+    void *ret;
+
+    apr_pool_owner_set(thread->pool, 0);
+    ret = thread->func(thread, thread->data);
+    apr_pool_destroy(thread->pool);
+    return ret;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new,
+                                            apr_threadattr_t *attr,
+                                            apr_thread_start_t func,
+                                            void *data,
+                                            apr_pool_t *pool)
+{
+    apr_status_t stat;
     pthread_attr_t *temp;
- 
-    (*new) = (ap_thread_t *)ap_palloc(cont, sizeof(ap_thread_t));
+
+    (*new) = (apr_thread_t *)apr_pcalloc(pool, sizeof(apr_thread_t));
 
     if ((*new) == NULL) {
         return APR_ENOMEM;
     }
 
-    (*new)->td = (pthread_t *)ap_palloc(cont, sizeof(pthread_t));
+    (*new)->td = (pthread_t *)apr_pcalloc(pool, sizeof(pthread_t));
 
     if ((*new)->td == NULL) {
         return APR_ENOMEM;
     }
 
-    (*new)->cntxt = cont;
+    (*new)->data = data;
+    (*new)->func = func;
 
     if (attr)
-        temp = attr->attr;
+        temp = &attr->attr;
     else
         temp = NULL;
-    
-    stat = ap_create_pool(&(*new)->cntxt, cont);
+
+    stat = apr_pool_create(&(*new)->pool, pool);
     if (stat != APR_SUCCESS) {
         return stat;
     }
 
-    if ((stat = pthread_create((*new)->td, temp, func, data)) == 0) {
+    if ((stat = pthread_create((*new)->td, temp, dummy_worker, (*new))) == 0) {
         return APR_SUCCESS;
     }
     else {
+#ifdef HAVE_ZOS_PTHREADS
+        stat = errno;
+#endif
+
         return stat;
-    } 
+    }
+}
+
+APR_DECLARE(apr_os_thread_t) apr_os_thread_current(void)
+{
+    return pthread_self();
+}
+
+APR_DECLARE(int) apr_os_thread_equal(apr_os_thread_t tid1,
+                                     apr_os_thread_t tid2)
+{
+    return pthread_equal(tid1, tid2);
 }
 
-ap_status_t ap_thread_exit(ap_thread_t *thd, ap_status_t *retval)
+APR_DECLARE(apr_status_t) apr_thread_exit(apr_thread_t *thd,
+                                          apr_status_t retval)
 {
-    ap_destroy_pool(thd->cntxt);
-    pthread_exit(retval);
+    thd->exitval = retval;
+    apr_pool_destroy(thd->pool);
+    pthread_exit(NULL);
     return APR_SUCCESS;
 }
 
-ap_status_t ap_thread_join(ap_status_t *retval, ap_thread_t *thd)
+APR_DECLARE(apr_status_t) apr_thread_join(apr_status_t *retval,
+                                          apr_thread_t *thd)
 {
-    ap_status_t stat;
+    apr_status_t stat;
+    apr_status_t *thread_stat;
 
-    if ((stat = pthread_join(*thd->td,(void *)&retval)) == 0) {
+    if ((stat = pthread_join(*thd->td,(void *)&thread_stat)) == 0) {
+        *retval = thd->exitval;
         return APR_SUCCESS;
     }
     else {
+#ifdef HAVE_ZOS_PTHREADS
+        stat = errno;
+#endif
+
         return stat;
     }
 }
 
-ap_status_t ap_thread_detach(ap_thread_t *thd)
+APR_DECLARE(apr_status_t) apr_thread_detach(apr_thread_t *thd)
 {
-    ap_status_t stat;
+    apr_status_t stat;
 
+#ifdef HAVE_ZOS_PTHREADS
+    if ((stat = pthread_detach(thd->td)) == 0) {
+#else
     if ((stat = pthread_detach(*thd->td)) == 0) {
+#endif
+
         return APR_SUCCESS;
     }
     else {
+#ifdef HAVE_ZOS_PTHREADS
+        stat = errno;
+#endif
+
         return stat;
     }
 }
 
-ap_status_t ap_get_threaddata(void **data, char *key, ap_thread_t *thread)
+APR_DECLARE(void) apr_thread_yield(void)
 {
-    if (thread != NULL) {
-        return ap_get_userdata(data, key, thread->cntxt);
-    }
-    else {
-        data = NULL;
-        return APR_ENOTHREAD;
-    }
+#ifdef HAVE_PTHREAD_YIELD
+#ifdef HAVE_ZOS_PTHREADS
+    pthread_yield(NULL);
+#else
+    pthread_yield();
+#endif /* HAVE_ZOS_PTHREADS */
+#else
+#ifdef HAVE_SCHED_YIELD
+    sched_yield();
+#endif
+#endif
 }
 
-ap_status_t ap_set_threaddata(void *data, char *key,
-                              ap_status_t (*cleanup) (void *),
-                              ap_thread_t *thread)
+APR_DECLARE(apr_status_t) apr_thread_data_get(void **data, const char *key,
+                                              apr_thread_t *thread)
 {
-    if (thread != NULL) {
-        return ap_set_userdata(data, key, cleanup, thread->cntxt);
-    }
-    else {
-        data = NULL;
-        return APR_ENOTHREAD;
-    }
+    return apr_pool_userdata_get(data, key, thread->pool);
 }
 
-ap_status_t ap_get_os_thread(ap_os_thread_t *thethd, ap_thread_t *thd)
+APR_DECLARE(apr_status_t) apr_thread_data_set(void *data, const char *key,
+                              apr_status_t (*cleanup)(void *),
+                              apr_thread_t *thread)
 {
-    if (thd == NULL) {
-        return APR_ENOTHREAD;
-    }
-    thethd = thd->td;
+    return apr_pool_userdata_set(data, key, cleanup, thread->pool);
+}
+
+APR_DECLARE(apr_status_t) apr_os_thread_get(apr_os_thread_t **thethd,
+                                            apr_thread_t *thd)
+{
+    *thethd = thd->td;
     return APR_SUCCESS;
 }
 
-ap_status_t ap_put_os_thread(ap_thread_t **thd, ap_os_thread_t *thethd, 
-                             ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_os_thread_put(apr_thread_t **thd,
+                                            apr_os_thread_t *thethd,
+                                            apr_pool_t *pool)
 {
-    if (cont == NULL) {
+    if (pool == NULL) {
         return APR_ENOPOOL;
     }
+
     if ((*thd) == NULL) {
-        (*thd) = (ap_thread_t *)ap_palloc(cont, sizeof(ap_thread_t));
-        (*thd)->cntxt = cont;
+        (*thd) = (apr_thread_t *)apr_pcalloc(pool, sizeof(apr_thread_t));
+        (*thd)->pool = pool;
     }
+
     (*thd)->td = thethd;
     return APR_SUCCESS;
 }
+
+APR_DECLARE(apr_status_t) apr_thread_once_init(apr_thread_once_t **control,
+                                               apr_pool_t *p)
+{
+    static const pthread_once_t once_init = PTHREAD_ONCE_INIT;
+
+    *control = apr_palloc(p, sizeof(**control));
+    (*control)->once = once_init;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_once(apr_thread_once_t *control,
+                                          void (*func)(void))
+{
+    return pthread_once(&control->once, func);
+}
+
+APR_POOL_IMPLEMENT_ACCESSOR(thread)
+
 #endif  /* HAVE_PTHREAD_H */
 #endif  /* APR_HAS_THREADS */
 
+#if !APR_HAS_THREADS
+
+/* avoid warning for no prototype */
+APR_DECLARE(apr_status_t) apr_os_thread_get(void);
+
+APR_DECLARE(apr_status_t) apr_os_thread_get(void)
+{
+    return APR_ENOTIMPL;
+}
+
+#endif
diff --git a/threadproc/unix/threadcancel.c b/threadproc/unix/threadcancel.c
deleted file mode 100644
index 81e3d3e7cd5..00000000000
--- a/threadproc/unix/threadcancel.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "threadproc.h"
-#if APR_HAS_THREADS
-
-#ifdef HAVE_PTHREAD_H
-
-#if 0 /* some platforms, e.g. FreeBSD 2.2.8, do not have pthread_cancel (they do have an undocumented pthread_kill, though) */
-/* ***APRDOC********************************************************
- * ap_status_t ap_cancel_thread(ap_thread_t *thd)
- *    Asynchronously kill a thread
- * arg 1) The thread to kill.
- */
-ap_status_t ap_cancel_thread(ap_thread_t *thd)
-{
-    ap_status_t stat;
-    if ((stat = pthread_cancel(*thd->td)) == 0) {
-        return APR_SUCCESS;
-    }
-    else {
-        return stat;
-    }
-}
-#endif
-    
-/* ***APRDOC********************************************************
- * ap_status_t ap_setcanceltype(ap_int32_t type, ap_pool_t *cont)
- *    Determine how threads are cancelable.
- * arg 1) how are threads cancelable.  One of:
- *            APR_CANCEL_ASYNCH  -- cancel it no matter where it is
- *            APR_CANCEL_DEFER   -- only cancel the thread if it is safe. 
- * arg 2) The context to operate on 
- */
-ap_status_t ap_setcanceltype(ap_int32_t type, ap_pool_t *cont)
-{
-    ap_status_t stat;
-    if ((stat = pthread_setcanceltype(type, NULL)) == 0) {
-        return APR_SUCCESS;
-    }
-    else {
-        return stat;
-    }
-}
-
-/* ***APRDOC********************************************************
- * ap_status_t ap_setcancelstate(ap_int32_t type, ap_pool_t *cont)
- *    Determine if threads will be cancelable.
- * arg 1) Are threads cancelable. 
- * arg 2) The context to operate on 
- */
-ap_status_t ap_setcancelstate(ap_int32_t type, ap_pool_t *cont)
-{
-    ap_status_t stat;
-    if ((stat = pthread_setcanceltype(type, NULL)) == 0) {
-        return APR_SUCCESS;
-    }
-    else {
-        return stat;
-    }
-}
-#endif
-#endif
diff --git a/threadproc/unix/threadpriv.c b/threadproc/unix/threadpriv.c
index 9d82395a6e9..c2785203801 100644
--- a/threadproc/unix/threadpriv.c
+++ b/threadproc/unix/threadpriv.c
@@ -1,90 +1,59 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "threadproc.h"
+#include "apr.h"
 #include "apr_portable.h"
+#include "apr_arch_threadproc.h"
 
 #if APR_HAS_THREADS
 
-#ifdef HAVE_PTHREAD_H
-ap_status_t ap_create_thread_private(ap_threadkey_t **key, 
-                                     void (*dest)(void *), ap_pool_t *cont)
+#if APR_HAVE_PTHREAD_H
+APR_DECLARE(apr_status_t) apr_threadkey_private_create(apr_threadkey_t **key,
+                                                       void (*dest)(void *),
+                                                       apr_pool_t *pool)
 {
-    ap_status_t stat;
-    (*key) = (ap_threadkey_t *)ap_palloc(cont, sizeof(ap_threadkey_t));
+    (*key) = (apr_threadkey_t *)apr_pcalloc(pool, sizeof(apr_threadkey_t));
 
     if ((*key) == NULL) {
         return APR_ENOMEM;
     }
 
-    (*key)->cntxt = cont;
+    (*key)->pool = pool;
+
+    return pthread_key_create(&(*key)->key, dest);
 
-    if ((stat = pthread_key_create(&(*key)->key, dest)) == 0) {
-        return stat;
-    }
-    return stat;
 }
 
-ap_status_t ap_get_thread_private(void **new, ap_threadkey_t *key)
+APR_DECLARE(apr_status_t) apr_threadkey_private_get(void **new,
+                                                    apr_threadkey_t *key)
 {
+#ifdef PTHREAD_GETSPECIFIC_TAKES_TWO_ARGS
+    if (pthread_getspecific(key->key,new))
+       *new = NULL;
+#else
     (*new) = pthread_getspecific(key->key);
+#endif
     return APR_SUCCESS;
 }
 
-ap_status_t ap_set_thread_private(void *priv, ap_threadkey_t *key)
+APR_DECLARE(apr_status_t) apr_threadkey_private_set(void *priv,
+                                                    apr_threadkey_t *key)
 {
-    ap_status_t stat;
+    apr_status_t stat;
+
     if ((stat = pthread_setspecific(key->key, priv)) == 0) {
         return APR_SUCCESS;
     }
@@ -93,60 +62,68 @@ ap_status_t ap_set_thread_private(void *priv, ap_threadkey_t *key)
     }
 }
 
-ap_status_t ap_delete_thread_private(ap_threadkey_t *key)
+APR_DECLARE(apr_status_t) apr_threadkey_private_delete(apr_threadkey_t *key)
 {
-    ap_status_t stat;
+#ifdef HAVE_PTHREAD_KEY_DELETE
+    apr_status_t stat;
+
     if ((stat = pthread_key_delete(key->key)) == 0) {
-        return APR_SUCCESS; 
+        return APR_SUCCESS;
     }
+
     return stat;
+#else
+    return APR_ENOTIMPL;
+#endif
 }
 
-ap_status_t ap_get_threadkeydata(void **data, char *key, ap_threadkey_t *threadkey)
+APR_DECLARE(apr_status_t) apr_threadkey_data_get(void **data, const char *key,
+                                                 apr_threadkey_t *threadkey)
 {
-    if (threadkey != NULL) {
-        return ap_get_userdata(data, key, threadkey->cntxt);
-    }
-    else {
-        data = NULL;
-        return APR_ENOTHDKEY;
-    }
+    return apr_pool_userdata_get(data, key, threadkey->pool);
 }
 
-ap_status_t ap_set_threadkeydata(void *data,
-                                 char *key, ap_status_t (*cleanup) (void *),
-                                 ap_threadkey_t *threadkey)
+APR_DECLARE(apr_status_t) apr_threadkey_data_set(void *data, const char *key,
+                              apr_status_t (*cleanup)(void *),
+                              apr_threadkey_t *threadkey)
 {
-    if (threadkey != NULL) {
-        return ap_set_userdata(data, key, cleanup, threadkey->cntxt);
-    }
-    else {
-        data = NULL;
-        return APR_ENOTHDKEY;
-    }
+    return apr_pool_userdata_set(data, key, cleanup, threadkey->pool);
 }
 
-ap_status_t ap_get_os_threadkey(ap_os_threadkey_t *thekey, ap_threadkey_t *key)
+APR_DECLARE(apr_status_t) apr_os_threadkey_get(apr_os_threadkey_t *thekey,
+                                               apr_threadkey_t *key)
 {
-    if (key == NULL) {
-        return APR_ENOFILE;
-    }
-    thekey = &(key->key);
+    *thekey = key->key;
     return APR_SUCCESS;
 }
 
-ap_status_t ap_put_os_threadkey(ap_threadkey_t **key, 
-                                ap_os_threadkey_t *thekey, ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_os_threadkey_put(apr_threadkey_t **key,
+                                               apr_os_threadkey_t *thekey,
+                                               apr_pool_t *pool)
 {
-    if (cont == NULL) {
+    if (pool == NULL) {
         return APR_ENOPOOL;
     }
+
     if ((*key) == NULL) {
-        (*key) = (ap_threadkey_t *)ap_palloc(cont, sizeof(ap_threadkey_t));
-        (*key)->cntxt = cont;
+        (*key) = (apr_threadkey_t *)apr_pcalloc(pool, sizeof(apr_threadkey_t));
+        (*key)->pool = pool;
     }
+
     (*key)->key = *thekey;
     return APR_SUCCESS;
-}           
-#endif
+}
+#endif /* APR_HAVE_PTHREAD_H */
+#endif /* APR_HAS_THREADS */
+
+#if !APR_HAS_THREADS
+
+/* avoid warning for no prototype */
+APR_DECLARE(apr_status_t) apr_os_threadkey_get(void);
+
+APR_DECLARE(apr_status_t) apr_os_threadkey_get(void)
+{
+    return APR_ENOTIMPL;
+}
+
 #endif
diff --git a/threadproc/unix/threadproc.h b/threadproc/unix/threadproc.h
deleted file mode 100644
index ea4c8289db7..00000000000
--- a/threadproc/unix/threadproc.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "apr_private.h"
-#include "apr_thread_proc.h"
-#include "apr_file_io.h"
-#include "fileio.h"
-
-/* System headers required for thread/process library */
-#if HAVE_PTHREAD_H
-#include <pthread.h>
-#endif
-#if HAVE_SIGNAL_H
-#include <signal.h>
-#endif
-#if HAVE_STRING_H
-#include <string.h>
-#endif
-#if HAVE_SYS_WAIT_H
-#include <sys/wait.h>
-#endif
-#if HAVE_STRING_H
-#include <string.h>
-#endif
-/* End System Headers */
-
-
-#ifndef THREAD_PROC_H
-#define THREAD_PROC_H
-
-#define SHELL_PATH "/bin/sh"
-
-#if APR_HAS_THREADS
-struct ap_thread_t {
-    ap_pool_t *cntxt;
-    pthread_t *td;
-};
-
-struct ap_threadattr_t {
-    ap_pool_t *cntxt;
-    pthread_attr_t *attr;
-};
-
-struct ap_threadkey_t {
-    ap_pool_t *cntxt;
-    pthread_key_t key;
-};
-#endif
-
-struct ap_procattr_t {
-    ap_pool_t *cntxt;
-    ap_file_t *parent_in;
-    ap_file_t *child_in;
-    ap_file_t *parent_out;
-    ap_file_t *child_out;
-    ap_file_t *parent_err;
-    ap_file_t *child_err;
-    char *currdir;
-    ap_int32_t cmdtype;
-    ap_int32_t detached;
-};
-
-struct ap_proc_t {
-    ap_pool_t *cntxt;
-    pid_t pid;
-    struct ap_procattr_t *attr;
-};
-
-/*This will move to ap_threadproc.h in time, but I need to figure it out
- * on windows first.  :)
- */
-ap_status_t ap_detach(struct ap_proc_t **, ap_pool_t *);
-
-#endif  /* ! THREAD_PROC_H */
-
diff --git a/threadproc/win32/proc.c b/threadproc/win32/proc.c
index b516a2cdcb5..0357b0bd87d 100644
--- a/threadproc/win32/proc.c
+++ b/threadproc/win32/proc.c
@@ -1,322 +1,654 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "threadproc.h"
-#include "fileio.h"
+#include "apr_arch_threadproc.h"
+#include "apr_arch_file_io.h"
 
 #include "apr_thread_proc.h"
 #include "apr_file_io.h"
 #include "apr_general.h"
-#include "apr_lib.h"
+#include "apr_strings.h"
 #include "apr_portable.h"
+#include "apr_lib.h"
 #include <stdlib.h>
+#if APR_HAVE_SIGNAL_H
 #include <signal.h>
+#endif
 #include <string.h>
+#ifdef HAVE_PROCESS_H
 #include <process.h>
+#endif
 
-ap_status_t ap_createprocattr_init(ap_procattr_t **new, ap_pool_t *cont)
-{
-    (*new) = (ap_procattr_t *)ap_palloc(cont, 
-              sizeof(ap_procattr_t));
+/* Heavy on no'ops, here's what we want to pass if there is APR_NO_FILE
+ * requested for a specific child handle;
+ */
+static apr_file_t no_file = { NULL, INVALID_HANDLE_VALUE, };
 
-    if ((*new) == NULL) {
-        return APR_ENOMEM;
-    }
-    (*new)->cntxt = cont;
-    (*new)->parent_in = NULL;
-    (*new)->child_in = NULL;
-    (*new)->parent_out = NULL;
-    (*new)->child_out = NULL;
-    (*new)->parent_err = NULL;
-    (*new)->child_err = NULL;
-    (*new)->currdir = NULL; 
-    (*new)->cmdtype = APR_PROGRAM;
-    (*new)->detached = TRUE;
+/* We have very carefully excluded volumes of definitions from the
+ * Microsoft Platform SDK, which kill the build time performance.
+ * These the sole constants we borrow from WinBase.h and WinUser.h
+ */
+#ifndef LOGON32_LOGON_NETWORK
+#define LOGON32_LOGON_NETWORK 3
+#endif
 
-    memset(&(*new)->si, 0, sizeof((*new)->si));
+#ifdef _WIN32_WCE
+#ifndef DETACHED_PROCESS
+#define DETACHED_PROCESS 0
+#endif
+#ifndef CREATE_UNICODE_ENVIRONMENT
+#define CREATE_UNICODE_ENVIRONMENT 0
+#endif
+#ifndef STARTF_USESHOWWINDOW
+#define STARTF_USESHOWWINDOW 0
+#endif
+#ifndef SW_HIDE
+#define SW_HIDE 0
+#endif
+#endif
 
+/* 
+ * some of the ideas expressed herein are based off of Microsoft
+ * Knowledge Base article: Q190351
+ *
+ */
+APR_DECLARE(apr_status_t) apr_procattr_create(apr_procattr_t **new,
+                                                  apr_pool_t *pool)
+{
+    (*new) = (apr_procattr_t *)apr_pcalloc(pool, sizeof(apr_procattr_t));
+    (*new)->pool = pool;
+    (*new)->cmdtype = APR_PROGRAM;
     return APR_SUCCESS;
 }
 
-ap_status_t ap_setprocattr_io(ap_procattr_t *attr, ap_int32_t in, 
-                              ap_int32_t out, ap_int32_t err)
+APR_DECLARE(apr_status_t) apr_procattr_io_set(apr_procattr_t *attr,
+                                              apr_int32_t in, 
+                                              apr_int32_t out,
+                                              apr_int32_t err)
 {
-    ap_status_t stat;
+    apr_status_t stat = APR_SUCCESS;
+
     if (in) {
-        if ((stat = ap_create_pipe(&attr->child_in, &attr->parent_in, 
-                                   attr->cntxt)) != APR_SUCCESS) {
-            return stat;
+        /* APR_CHILD_BLOCK maps to APR_WRITE_BLOCK, while
+         * APR_PARENT_BLOCK maps to APR_READ_BLOCK, so transpose 
+         * the CHILD/PARENT blocking flags for the stdin pipe.
+         * stdout/stderr map to the correct mode by default.
+         */
+        if (in == APR_CHILD_BLOCK)
+            in = APR_READ_BLOCK;
+        else if (in == APR_PARENT_BLOCK)
+            in = APR_WRITE_BLOCK;
+
+        if (in == APR_NO_FILE)
+            attr->child_in = &no_file;
+        else { 
+            stat = apr_file_pipe_create_ex(&attr->child_in, &attr->parent_in,
+                                           in, attr->pool);
         }
+        if (stat == APR_SUCCESS)
+            stat = apr_file_inherit_unset(attr->parent_in);
     }
-    if (out) {
-        if ((stat = ap_create_pipe(&attr->parent_out, &attr->child_out, 
-                                   attr->cntxt)) != APR_SUCCESS) {
-            return stat;
+    if (out && stat == APR_SUCCESS) {
+        if (out == APR_NO_FILE)
+            attr->child_out = &no_file;
+        else { 
+            stat = apr_file_pipe_create_ex(&attr->parent_out, &attr->child_out,
+                                           out, attr->pool);
         }
+        if (stat == APR_SUCCESS)
+            stat = apr_file_inherit_unset(attr->parent_out);
     }
-    if (err) {
-        if ((stat = ap_create_pipe(&attr->parent_err, &attr->child_err, 
-                                   attr->cntxt)) != APR_SUCCESS) {
-            return stat;
+    if (err && stat == APR_SUCCESS) {
+        if (err == APR_NO_FILE)
+            attr->child_err = &no_file;
+        else { 
+            stat = apr_file_pipe_create_ex(&attr->parent_err, &attr->child_err,
+                                           err, attr->pool);
         }
-    } 
-    return APR_SUCCESS;
+        if (stat == APR_SUCCESS)
+            stat = apr_file_inherit_unset(attr->parent_err);
+    }
+    return stat;
+}
+
+APR_DECLARE(apr_status_t) apr_procattr_child_in_set(apr_procattr_t *attr, 
+                                                  apr_file_t *child_in, 
+                                                  apr_file_t *parent_in)
+{
+    apr_status_t rv = APR_SUCCESS;
+
+    if (child_in) {
+        if ((attr->child_in == NULL) || (attr->child_in == &no_file))
+            rv = apr_file_dup(&attr->child_in, child_in, attr->pool);
+        else
+            rv = apr_file_dup2(attr->child_in, child_in, attr->pool);
+
+        if (rv == APR_SUCCESS)
+            rv = apr_file_inherit_set(attr->child_in);
+    }
+
+    if (parent_in && rv == APR_SUCCESS) {
+        if (attr->parent_in == NULL)
+            rv = apr_file_dup(&attr->parent_in, parent_in, attr->pool);
+        else
+            rv = apr_file_dup2(attr->parent_in, parent_in, attr->pool);
+    }
+
+    return rv;
 }
-#if 0
-ap_status_t ap_setprocattr_childin(ap_procattr_t *attr, ap_file_t *child_in,
-                                   ap_file_t *parent_in)
+
+APR_DECLARE(apr_status_t) apr_procattr_child_out_set(apr_procattr_t *attr,
+                                                   apr_file_t *child_out,
+                                                   apr_file_t *parent_out)
 {
+    apr_status_t rv = APR_SUCCESS;
+
+    if (child_out) {
+        if ((attr->child_out == NULL) || (attr->child_out == &no_file))
+            rv = apr_file_dup(&attr->child_out, child_out, attr->pool);
+        else
+            rv = apr_file_dup2(attr->child_out, child_out, attr->pool);
+
+        if (rv == APR_SUCCESS)
+            rv = apr_file_inherit_set(attr->child_out);
+    }
+
+    if (parent_out && rv == APR_SUCCESS) {
+        if (attr->parent_out == NULL)
+            rv = apr_file_dup(&attr->parent_out, parent_out, attr->pool);
+        else
+            rv = apr_file_dup2(attr->parent_out, parent_out, attr->pool);
+    }
+
+    return rv;
 }
-ap_status_t ap_setprocattr_childout(ap_procattr_t *attr, ap_file_t *child_out,
-                                    ap_file_t *parent_out)
+
+APR_DECLARE(apr_status_t) apr_procattr_child_err_set(apr_procattr_t *attr,
+                                                   apr_file_t *child_err,
+                                                   apr_file_t *parent_err)
 {
-    if (attr->child_out == NULL && attr->parent_out == NULL)
-        ap_create_pipe(&attr->child_out, &attr->parent_out, attr->cntxt);
+    apr_status_t rv = APR_SUCCESS;
 
-    if (child_out != NULL)
-        ap_dupfile(&attr->child_out, child_out, attr->cntxt);
+    if (child_err) {
+        if ((attr->child_err == NULL) || (attr->child_err == &no_file))
+            rv = apr_file_dup(&attr->child_err, child_err, attr->pool);
+        else
+            rv = apr_file_dup2(attr->child_err, child_err, attr->pool);
 
-    if (parent_out != NULL)
-        ap_dupfile(&attr->parent_out, parent_out, attr->cntxt);
+        if (rv == APR_SUCCESS)
+            rv = apr_file_inherit_set(attr->child_err);
+    }
 
-    return APR_SUCCESS;
+    if (parent_err && rv == APR_SUCCESS) {
+        if (attr->parent_err == NULL)
+            rv = apr_file_dup(&attr->parent_err, parent_err, attr->pool);
+        else
+            rv = apr_file_dup2(attr->parent_err, parent_err, attr->pool);
+    }
+
+    return rv;
+}
+
+APR_DECLARE(apr_status_t) apr_procattr_dir_set(apr_procattr_t *attr,
+                                              const char *dir) 
+{
+    /* curr dir must be in native format, there are all sorts of bugs in
+     * the NT library loading code that flunk the '/' parsing test.
+     */
+    return apr_filepath_merge(&attr->currdir, NULL, dir, 
+                              APR_FILEPATH_NATIVE, attr->pool);
 }
-ap_status_t ap_setprocattr_childerr(ap_procattr_t *attr, ap_file_t *child_err,
-                                   ap_file_t *parent_err)
+
+APR_DECLARE(apr_status_t) apr_procattr_cmdtype_set(apr_procattr_t *attr,
+                                                  apr_cmdtype_e cmd) 
 {
-    if (attr->child_err == NULL && attr->parent_err == NULL)
-        ap_create_pipe(&attr->child_err, &attr->parent_err, attr->cntxt);
+    attr->cmdtype = cmd;
+    return APR_SUCCESS;
+}
 
-    if (child_err != NULL)
-        ap_dupfile(&attr->child_err, child_err, attr->cntxt);
+APR_DECLARE(apr_status_t) apr_procattr_detach_set(apr_procattr_t *attr,
+                                                 apr_int32_t det) 
+{
+    attr->detached = det;
+    return APR_SUCCESS;
+}
 
-    if (parent_err != NULL)
-        ap_dupfile(&attr->parent_err, parent_err, attr->cntxt);
+#ifndef _WIN32_WCE
+static apr_status_t attr_cleanup(void *theattr)
+{
+    apr_procattr_t *attr = (apr_procattr_t *)theattr;    
+    if (attr->user_token)
+        CloseHandle(attr->user_token);
+    attr->user_token = NULL;
     return APR_SUCCESS;
 }
 #endif
-ap_status_t ap_setprocattr_dir(ap_procattr_t *attr, 
-                               const char *dir) 
+
+APR_DECLARE(apr_status_t) apr_procattr_user_set(apr_procattr_t *attr, 
+                                                const char *username,
+                                                const char *password)
 {
-    char path[MAX_PATH];
-    int length;
+#ifdef _WIN32_WCE
+    return APR_ENOTIMPL;
+#else
+    HANDLE user;
+    apr_wchar_t *wusername = NULL;
+    apr_wchar_t *wpassword = NULL;
+    apr_status_t rv;
+    apr_size_t len, wlen;
 
-    if (dir[0] != '\\' && dir[0] != '/' && dir[1] != ':') { 
-        length = GetCurrentDirectory(MAX_PATH, path);
+    if (apr_os_level >= APR_WIN_NT_4) 
+    {
+        if (attr->user_token) {
+            /* Cannot set that twice */
+            if (attr->errfn) {
+                attr->errfn(attr->pool, 0, 
+                            apr_pstrcat(attr->pool, 
+                                        "function called twice" 
+                                         " on username: ", username, NULL));
+            }
+            return APR_EINVAL;
+        }
+        len = strlen(username) + 1;
+        wlen = len;
+        wusername = apr_palloc(attr->pool, wlen * sizeof(apr_wchar_t));
+        if ((rv = apr_conv_utf8_to_ucs2(username, &len, wusername, &wlen))
+                   != APR_SUCCESS) {
+            if (attr->errfn) {
+                attr->errfn(attr->pool, rv, 
+                            apr_pstrcat(attr->pool, 
+                                        "utf8 to ucs2 conversion failed" 
+                                         " on username: ", username, NULL));
+            }
+            return rv;
+        }
+        if (password) {
+            len = strlen(password) + 1;
+            wlen = len;
+            wpassword = apr_palloc(attr->pool, wlen * sizeof(apr_wchar_t));
+            if ((rv = apr_conv_utf8_to_ucs2(password, &len, wpassword, &wlen))
+                       != APR_SUCCESS) {
+                if (attr->errfn) {
+                    attr->errfn(attr->pool, rv, 
+                                apr_pstrcat(attr->pool, 
+                                        "utf8 to ucs2 conversion failed" 
+                                         " on password: ", password, NULL));
+                }
+                return rv;
+            }
+        }
+        if (!LogonUserW(wusername, 
+                        NULL, 
+                        wpassword ? wpassword : L"",
+                        LOGON32_LOGON_NETWORK,
+                        LOGON32_PROVIDER_DEFAULT,
+                        &user)) {
+            /* Logon Failed */            
+            return apr_get_os_error();
+        }
+        if (wpassword)
+            memset(wpassword, 0, wlen * sizeof(apr_wchar_t));
+        /* Get the primary token for user */
+        if (!DuplicateTokenEx(user, 
+                              TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY, 
+                              NULL,
+                              SecurityImpersonation,
+                              TokenPrimary,
+                              &(attr->user_token))) {
+            /* Failed to duplicate the user token */
+            rv = apr_get_os_error();
+            CloseHandle(user);
+            return rv;
+        }
+        CloseHandle(user);
 
-        if (length == 0 || length + strlen(dir) + 1 >= MAX_PATH)
-            return APR_ENOMEM;
+        attr->sd = apr_pcalloc(attr->pool, SECURITY_DESCRIPTOR_MIN_LENGTH);
+        InitializeSecurityDescriptor(attr->sd, SECURITY_DESCRIPTOR_REVISION);
+        SetSecurityDescriptorDacl(attr->sd, -1, 0, 0);
+        attr->sa = apr_palloc(attr->pool, sizeof(SECURITY_ATTRIBUTES));
+        attr->sa->nLength = sizeof (SECURITY_ATTRIBUTES);
+        attr->sa->lpSecurityDescriptor = attr->sd;
+        attr->sa->bInheritHandle = FALSE;
 
-        attr->currdir = ap_pstrcat(attr->cntxt, path, "\\", dir, NULL);
+        /* register the cleanup */
+        apr_pool_cleanup_register(attr->pool, (void *)attr,
+                                  attr_cleanup,
+                                  apr_pool_cleanup_null);
+        return APR_SUCCESS;
     }
-    else {
-        attr->currdir = ap_pstrdup(attr->cntxt, dir);
+    else
+        return APR_ENOTIMPL;
+#endif
+}
+
+APR_DECLARE(apr_status_t) apr_procattr_group_set(apr_procattr_t *attr,
+                                                 const char *groupname)
+{
+    /* Always return SUCCESS cause groups are irrelevant */
+    return APR_SUCCESS;
+}
+
+static const char* has_space(const char *str)
+{
+    const char *ch;
+    for (ch = str; *ch; ++ch) {
+        if (apr_isspace(*ch)) {
+            return ch;
+        }
     }
+    return NULL;
+}
 
-    if (attr->currdir) {
-        return APR_SUCCESS;
+static char *apr_caret_escape_args(apr_pool_t *p, const char *str)
+{
+    char *cmd;
+    unsigned char *d;
+    const unsigned char *s;
+
+    cmd = apr_palloc(p, 2 * strlen(str) + 1);	/* Be safe */
+    d = (unsigned char *)cmd;
+    s = (const unsigned char *)str;
+    for (; *s; ++s) {
+
+        /* 
+         * Newlines to Win32/OS2 CreateProcess() are ill advised.
+         * Convert them to spaces since they are effectively white
+         * space to most applications
+         */
+	if (*s == '\r' || *s == '\n') {
+	    *d++ = ' ';
+            continue;
+	}
+
+	if (IS_SHCHAR(*s)) {
+	    *d++ = '^';
+	}
+	*d++ = *s;
     }
-    return APR_ENOMEM;
+    *d = '\0';
+
+    return cmd;
 }
 
-ap_status_t ap_setprocattr_cmdtype(ap_procattr_t *attr,
-                                     ap_cmdtype_e cmd) 
+APR_DECLARE(apr_status_t) apr_procattr_child_errfn_set(apr_procattr_t *attr,
+                                                       apr_child_errfn_t *errfn)
 {
-    attr->cmdtype = cmd;
+    attr->errfn = errfn;
     return APR_SUCCESS;
 }
 
-ap_status_t ap_setprocattr_detach(ap_procattr_t *attr, ap_int32_t det) 
+APR_DECLARE(apr_status_t) apr_procattr_error_check_set(apr_procattr_t *attr,
+                                                       apr_int32_t chk)
 {
-    attr->detached = det;
+    attr->errchk = chk;
     return APR_SUCCESS;
 }
 
-ap_status_t ap_create_process(ap_proc_t **new, const char *progname, 
-                              char *const args[], char **env, 
-                              ap_procattr_t *attr, ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_procattr_addrspace_set(apr_procattr_t *attr,
+                                                       apr_int32_t addrspace)
 {
-    int i, iEnvBlockLen;
-    char *cmdline;
-    HANDLE hCurrentProcess;
-    HANDLE hParentindup, hParentoutdup,hParenterrdup;
-    char ppid[20];
-    char *envstr;
-    char *pEnvBlock, *pNext;
+    /* won't ever be used on this platform, so don't save the flag */
+    return APR_SUCCESS;
+}
 
-    (*new) = (ap_proc_t *)ap_palloc(cont, sizeof(ap_proc_t));
+#if APR_HAS_UNICODE_FS && !defined(_WIN32_WCE)
 
-    if ((*new) == NULL) {
-        return APR_ENOMEM;
+/* Used only for the NT code path, a critical section is the fastest
+ * implementation available.
+ */
+static CRITICAL_SECTION proc_lock;
+
+static apr_status_t threadproc_global_cleanup(void *ignored)
+{
+    DeleteCriticalSection(&proc_lock);
+    return APR_SUCCESS;
+}
+
+/* Called from apr_initialize, we need a critical section to handle
+ * the pipe inheritance on win32.  This will mutex any process create
+ * so as we change our inherited pipes, we prevent another process from
+ * also inheriting those alternate handles, and prevent the other process
+ * from failing to inherit our standard handles.
+ */
+apr_status_t apr_threadproc_init(apr_pool_t *pool)
+{
+    IF_WIN_OS_IS_UNICODE
+    {
+        InitializeCriticalSection(&proc_lock);
+        /* register the cleanup */
+        apr_pool_cleanup_register(pool, &proc_lock,
+                                  threadproc_global_cleanup,
+                                  apr_pool_cleanup_null);
     }
+    return APR_SUCCESS;
+}
+
+#else /* !APR_HAS_UNICODE_FS || defined(_WIN32_WCE) */
+
+apr_status_t apr_threadproc_init(apr_pool_t *pool)
+{
+    return APR_SUCCESS;
+}
 
-    (*new)->cntxt = cont;
-    (*new)->attr = attr;
+#endif
+
+APR_DECLARE(apr_status_t) apr_proc_create(apr_proc_t *new,
+                                          const char *progname,
+                                          const char * const *args,
+                                          const char * const *env,
+                                          apr_procattr_t *attr,
+                                          apr_pool_t *pool)
+{
+    apr_status_t rv;
+    apr_size_t i;
+    const char *argv0;
+    char *cmdline;
+    char *pEnvBlock;
+    PROCESS_INFORMATION pi;
+    DWORD dwCreationFlags = 0;
+
+    new->in = attr->parent_in;
+    new->out = attr->parent_out;
+    new->err = attr->parent_err;
 
-    attr->si.cb = sizeof(attr->si);
     if (attr->detached) {
-        /* If we are creating ourselves detached, Then we should hide the
-         * window we are starting in.  And we had better redfine our
-         * handles for STDIN, STDOUT, and STDERR.
+        /* If we are creating ourselves detached, then we should hide the
+         * window we are starting in.  And we had better redefine our
+         * handles for STDIN, STDOUT, and STDERR. Do not set the
+         * detached attribute for Win9x. We have found that Win9x does
+         * not manage the stdio handles properly when running old 16
+         * bit executables if the detached attribute is set.
          */
-        attr->si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
-        attr->si.wShowWindow = SW_HIDE;
-
-        if (attr->child_in) {
-            attr->si.hStdInput = attr->child_in->filehand;
+        if (apr_os_level >= APR_WIN_NT) {
+            /* 
+             * XXX DETACHED_PROCESS won't on Win9x at all; on NT/W2K 
+             * 16 bit executables fail (MS KB: Q150956)
+             */
+            dwCreationFlags |= DETACHED_PROCESS;
         }
+    }
 
-        if (attr->child_out) {
-            attr->si.hStdOutput = attr->child_out->filehand;
-        }
+    /* progname must be unquoted, in native format, as there are all sorts 
+     * of bugs in the NT library loader code that fault when parsing '/'.
+     * XXX progname must be NULL if this is a 16 bit app running in WOW
+     */
+    if (progname[0] == '\"') {
+        progname = apr_pstrmemdup(pool, progname + 1, strlen(progname) - 2);
+    }
 
-        if (attr->child_err) {
-            attr->si.hStdError = attr->child_err->filehand;
+    if (attr->cmdtype == APR_PROGRAM || attr->cmdtype == APR_PROGRAM_ENV) {
+        char *fullpath = NULL;
+        if ((rv = apr_filepath_merge(&fullpath, attr->currdir, progname, 
+                                     APR_FILEPATH_NATIVE, pool)) != APR_SUCCESS) {
+            if (attr->errfn) {
+                attr->errfn(pool, rv, 
+                            apr_pstrcat(pool, "filepath_merge failed.", 
+                                        " currdir: ", attr->currdir, 
+                                        " progname: ", progname, NULL));
+            }
+            return rv;
         }
+        progname = fullpath;
+    } 
+    else {
+        /* Do not fail if the path isn't parseable for APR_PROGRAM_PATH
+         * or APR_SHELLCMD.  We only invoke apr_filepath_merge (with no
+         * left hand side expression) in order to correct the path slash
+         * delimiters.  But the filename doesn't need to be in the CWD,
+         * nor does it need to be a filename at all (it could be a
+         * built-in shell command.)
+         */
+        char *fullpath = NULL;
+        if ((rv = apr_filepath_merge(&fullpath, "", progname, 
+                                     APR_FILEPATH_NATIVE, pool)) == APR_SUCCESS) {
+            progname = fullpath;
+        }        
     }
 
-    if (attr->cmdtype == APR_PROGRAM) {
-        const char *ptr = progname;
+    if (has_space(progname)) {
+        argv0 = apr_pstrcat(pool, "\"", progname, "\"", NULL);
+    }
+    else {
+        argv0 = progname;
+    }
 
-        if (*ptr =='"') {
-            ptr++;
+    /* Handle the args, seperate from argv0 */
+    cmdline = "";
+    for (i = 1; args && args[i]; ++i) {
+        if (has_space(args[i]) || !args[i][0]) {
+            cmdline = apr_pstrcat(pool, cmdline, " \"", args[i], "\"", NULL);
         }
+        else {
+            cmdline = apr_pstrcat(pool, cmdline, " ", args[i], NULL);
+        }
+    }
 
-        if (*ptr == '\\' || *++ptr == ':') {
-            cmdline = ap_pstrdup(cont, progname);
+#ifndef _WIN32_WCE
+    if (attr->cmdtype == APR_SHELLCMD || attr->cmdtype == APR_SHELLCMD_ENV) {
+        char *shellcmd = getenv("COMSPEC");
+        if (!shellcmd) {
+            if (attr->errfn) {
+                attr->errfn(pool, APR_EINVAL, "COMSPEC envar is not set");
+            }
+            return APR_EINVAL;
         }
-        else if (attr->currdir == NULL) {
-            cmdline = ap_pstrdup(cont, progname);
+        if (shellcmd[0] == '"') {
+            progname = apr_pstrmemdup(pool, shellcmd + 1, strlen(shellcmd) - 2);
         }
         else {
-            char lastchar = attr->currdir[strlen(attr->currdir)-1];
-            if ( lastchar == '\\' || lastchar == '/') {
-                cmdline = ap_pstrcat(cont, attr->currdir, progname, NULL);
+            progname = shellcmd;
+            if (has_space(shellcmd)) {
+                shellcmd = apr_pstrcat(pool, "\"", shellcmd, "\"", NULL);
+            }
+        }
+        /* Command.com does not support a quoted command, while cmd.exe demands one.
+         */
+        i = strlen(progname);
+        if (i >= 11 && strcasecmp(progname + i - 11, "command.com") == 0) {
+            cmdline = apr_pstrcat(pool, shellcmd, " /C ", argv0, cmdline, NULL);
+        }
+        else {
+            cmdline = apr_pstrcat(pool, shellcmd, " /C \"", argv0, cmdline, "\"", NULL);
+        }
+    } 
+    else 
+#endif
+    {
+#if defined(_WIN32_WCE)
+        {
+#else
+        /* Win32 is _different_ than unix.  While unix will find the given
+         * program since it's already chdir'ed, Win32 cannot since the parent
+         * attempts to open the program with it's own path.
+         * ###: This solution isn't much better - it may defeat path searching
+         * when the path search was desired.  Open to further discussion.
+         */
+        i = strlen(progname);
+        if (i >= 4 && (strcasecmp(progname + i - 4, ".bat") == 0
+                    || strcasecmp(progname + i - 4, ".cmd") == 0))
+        {
+            char *shellcmd = getenv("COMSPEC");
+            if (!shellcmd) {
+                if (attr->errfn) {
+                    attr->errfn(pool, APR_EINVAL, "COMSPEC envar is not set");
+                }
+                return APR_EINVAL;
+            }
+            if (shellcmd[0] == '"') {
+                progname = apr_pstrmemdup(pool, shellcmd + 1, strlen(shellcmd) - 2);
             }
             else {
-            cmdline = ap_pstrcat(cont, attr->currdir, "\\", progname, NULL);
+                progname = shellcmd;
+                if (has_space(shellcmd)) {
+                    shellcmd = apr_pstrcat(pool, "\"", shellcmd, "\"", NULL);
+                }
+            }
+            i = strlen(progname);
+            if (i >= 11 && strcasecmp(progname + i - 11, "command.com") == 0) {
+                /* XXX: Still insecure - need doubled-quotes on each individual
+                 * arg of cmdline.  Suspect we need to postpone cmdline parsing
+                 * until this moment in all four code paths, with some flags
+                 * to toggle 'which flavor' is needed.
+                 */
+                cmdline = apr_pstrcat(pool, shellcmd, " /C ", argv0, cmdline, NULL);
+            }
+            else {
+                /* We must protect the cmdline args from any interpolation - this
+                 * is not a shellcmd, and the source of argv[] is untrusted.
+                 * Notice we escape ALL the cmdline args, including the quotes
+                 * around the individual args themselves.  No sense in allowing
+                 * the shift-state to be toggled, and the application will 
+                 * not see the caret escapes.
+                 */
+                cmdline = apr_caret_escape_args(pool, cmdline);
+                /*
+                 * Our app name must always be quoted so the quotes surrounding
+                 * the entire /c "command args" are unambigious.
+                 */
+                if (*argv0 != '"') {
+                    cmdline = apr_pstrcat(pool, shellcmd, " /C \"\"", argv0, "\"", cmdline, "\"", NULL);
+                }
+                else {
+                    cmdline = apr_pstrcat(pool, shellcmd, " /C \"", argv0, cmdline, "\"", NULL);
+                }
             }
         }
-    }
-    else {
-        char * shell_cmd = getenv("COMSPEC");
-        if (!shell_cmd)
-            shell_cmd = SHELL_PATH;
-        shell_cmd = ap_pstrdup(cont, shell_cmd);
-        cmdline = ap_pstrcat(cont, shell_cmd, " /C ", progname, NULL);
-    }
+        else {
+#endif
+            /* A simple command we are directly invoking.  Do not pass
+             * the first arg to CreateProc() for APR_PROGRAM_PATH
+             * invocation, since it would need to be a literal and
+             * complete file path.  That is; "c:\bin\aprtest.exe"
+             * would succeed, but "c:\bin\aprtest" or "aprtest.exe"
+             * can fail.
+             */
+            cmdline = apr_pstrcat(pool, argv0, cmdline, NULL);
 
-    i = 1;
-    while (args && args[i]) {
-        cmdline = ap_pstrcat(cont, cmdline, " ", args[i], NULL);
-        i++;
-    }
-    /*
-     * When the pipe handles are created, the security descriptor
-     * indicates that the handle can be inherited.  However, we do not
-     * want the server side handles to the pipe to be inherited by the
-     * child CGI process. If the child CGI does inherit the server
-     * side handles, then the child may be left around if the server
-     * closes its handles (e.g. if the http connection is aborted),
-     * because the child will have a valid copy of handles to both
-     * sides of the pipes, and no I/O error will occur.  Microsoft
-     * recommends using DuplicateHandle to turn off the inherit bit
-     * under NT and Win95.
-     */
-    hCurrentProcess = GetCurrentProcess();
-    if ((attr->child_in && !DuplicateHandle(hCurrentProcess, attr->parent_in->filehand, 
-                                            hCurrentProcess,
-                                            &hParentindup, 0, FALSE,
-                                            DUPLICATE_SAME_ACCESS))
-	|| (attr->child_out && !DuplicateHandle(hCurrentProcess, attr->parent_out->filehand,
-                                                hCurrentProcess, &hParentoutdup,
-                                                0, FALSE, DUPLICATE_SAME_ACCESS))
-	|| (attr->child_err && !DuplicateHandle(hCurrentProcess, attr->parent_err->filehand,
-                                                hCurrentProcess, &hParenterrdup,
-                                                0, FALSE, DUPLICATE_SAME_ACCESS))) {
-        if (attr->child_in) {
-            ap_close(attr->child_in);
-            ap_close(attr->parent_in);
-        }
-        if (attr->child_out) {
-            ap_close(attr->child_out);
-            ap_close(attr->parent_out);
-        }
-        if (attr->child_err) {
-            ap_close(attr->child_err);
-            ap_close(attr->parent_err);
-        }
-        return APR_EEXIST;
-    }
-    else {
-        if (attr->child_in) {
-            ap_close(attr->parent_in);
-            attr->parent_in->filehand = hParentindup;
-        }
-        if (attr->child_out) {
-            ap_close(attr->parent_out);
-            attr->parent_out->filehand = hParentoutdup;
-        }
-        if (attr->child_err) {
-            ap_close(attr->parent_err);
-            attr->parent_err->filehand = hParenterrdup;
+            if (attr->cmdtype == APR_PROGRAM_PATH) {
+                progname = NULL;
+            }
         }
     }
 
-    _itoa(_getpid(), ppid, 10);
-    if (env) {
-        envstr = ap_pstrcat(cont, "parentpid=", ppid, NULL);
+    if (!env || attr->cmdtype == APR_PROGRAM_ENV ||
+        attr->cmdtype == APR_SHELLCMD_ENV) {
+        pEnvBlock = NULL;
+    }
+    else {
+        apr_size_t iEnvBlockLen;
         /*
          * Win32's CreateProcess call requires that the environment
          * be passed in an environment block, a null terminated block of
@@ -328,127 +660,499 @@ ap_status_t ap_create_process(ap_proc_t **new, const char *progname,
             iEnvBlockLen += strlen(env[i]) + 1;
             i++;
         }
-  
-        pEnvBlock = (char *)ap_pcalloc(cont, iEnvBlockLen + strlen(envstr));
+        if (!i) 
+            ++iEnvBlockLen;
+
+#if APR_HAS_UNICODE_FS
+        IF_WIN_OS_IS_UNICODE
+        {
+            apr_wchar_t *pNext;
+            pEnvBlock = (char *)apr_palloc(pool, iEnvBlockLen * 2);
+            dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT;
+
+            i = 0;
+            pNext = (apr_wchar_t*)pEnvBlock;
+            while (env[i]) {
+                apr_size_t in = strlen(env[i]) + 1;
+                if ((rv = apr_conv_utf8_to_ucs2(env[i], &in, 
+                                                pNext, &iEnvBlockLen)) 
+                        != APR_SUCCESS) {
+                    if (attr->errfn) {
+                        attr->errfn(pool, rv, 
+                                    apr_pstrcat(pool, 
+                                                "utf8 to ucs2 conversion failed" 
+                                                " on this string: ", env[i], NULL));
+                    }
+                    return rv;
+                }
+                pNext = wcschr(pNext, L'\0') + 1;
+                i++;
+            }
+	    if (!i)
+                *(pNext++) = L'\0';
+	    *pNext = L'\0';
+        }
+#endif /* APR_HAS_UNICODE_FS */
+#if APR_HAS_ANSI_FS
+        ELSE_WIN_OS_IS_ANSI
+        {
+            char *pNext;
+            pEnvBlock = (char *)apr_palloc(pool, iEnvBlockLen);
     
-        i = 0;
-        pNext = pEnvBlock;
-        while (env[i]) {
-            strcpy(pNext, env[i]);
-            pNext = pNext + strlen(pNext) + 1;
-            i++;
+            i = 0;
+            pNext = pEnvBlock;
+            while (env[i]) {
+                strcpy(pNext, env[i]);
+                pNext = strchr(pNext, '\0') + 1;
+                i++;
+            }
+	    if (!i)
+                *(pNext++) = '\0';
+	    *pNext = '\0';
         }
-        strcpy(pNext, envstr);        
-    }
-    else {
-        SetEnvironmentVariable("parentpid", ppid);
-        pEnvBlock = NULL;
+#endif /* APR_HAS_ANSI_FS */
     } 
-    
 
-    if (CreateProcess(NULL, cmdline, NULL, NULL, TRUE, 0, pEnvBlock, attr->currdir, 
-                      &attr->si, &(*new)->pi)) {
-        if (attr->child_in) {
-            ap_close(attr->child_in);
+    new->invoked = cmdline;
+
+#if APR_HAS_UNICODE_FS
+    IF_WIN_OS_IS_UNICODE
+    {
+        STARTUPINFOW si;
+        DWORD stdin_reset = 0;
+        DWORD stdout_reset = 0;
+        DWORD stderr_reset = 0;
+        apr_wchar_t *wprg = NULL;
+        apr_wchar_t *wcmd = NULL;
+        apr_wchar_t *wcwd = NULL;
+
+        if (progname) {
+            apr_size_t nprg = strlen(progname) + 1;
+            apr_size_t nwprg = nprg + 6;
+            wprg = apr_palloc(pool, nwprg * sizeof(wprg[0]));
+            if ((rv = apr_conv_utf8_to_ucs2(progname, &nprg, wprg, &nwprg))
+                   != APR_SUCCESS) {
+                if (attr->errfn) {
+                    attr->errfn(pool, rv, 
+                                apr_pstrcat(pool, 
+                                            "utf8 to ucs2 conversion failed" 
+                                            " on progname: ", progname, NULL));
+                }
+                return rv;
+            }
         }
-        if (attr->child_out) {
-            ap_close(attr->child_out);
+
+        if (cmdline) {
+            apr_size_t ncmd = strlen(cmdline) + 1;
+            apr_size_t nwcmd = ncmd;
+            wcmd = apr_palloc(pool, nwcmd * sizeof(wcmd[0]));
+            if ((rv = apr_conv_utf8_to_ucs2(cmdline, &ncmd, wcmd, &nwcmd))
+                    != APR_SUCCESS) {
+                if (attr->errfn) {
+                    attr->errfn(pool, rv, 
+                                apr_pstrcat(pool, 
+                                            "utf8 to ucs2 conversion failed" 
+                                            " on cmdline: ", cmdline, NULL));
+                }
+                return rv;
+            }
         }
-        if (attr->child_err) {
-            ap_close(attr->child_err);
+
+        if (attr->currdir)
+        {
+            apr_size_t ncwd = strlen(attr->currdir) + 1;
+            apr_size_t nwcwd = ncwd;
+            wcwd = apr_palloc(pool, ncwd * sizeof(wcwd[0]));
+            if ((rv = apr_conv_utf8_to_ucs2(attr->currdir, &ncwd, 
+                                            wcwd, &nwcwd))
+                    != APR_SUCCESS) {
+                if (attr->errfn) {
+                    attr->errfn(pool, rv, 
+                                apr_pstrcat(pool, 
+                                            "utf8 to ucs2 conversion failed" 
+                                            " on currdir: ", attr->currdir, NULL));
+                }
+                return rv;
+            }
         }
-        CloseHandle((*new)->pi.hThread);
-        return APR_SUCCESS;
-    }
 
-    return GetLastError();
-}
+        memset(&si, 0, sizeof(si));
+        si.cb = sizeof(si);
 
-ap_status_t ap_get_childin(ap_file_t **new, ap_proc_t *proc)
-{
-    (*new) = proc->attr->parent_in;
-    return APR_SUCCESS; 
-}
+        if (attr->detached) {
+            si.dwFlags |= STARTF_USESHOWWINDOW;
+            si.wShowWindow = SW_HIDE;
+        }
 
-ap_status_t ap_get_childout(ap_file_t **new, ap_proc_t *proc)
-{
-    (*new) = proc->attr->parent_out; 
-    return APR_SUCCESS;
-}
+#ifndef _WIN32_WCE
+        /* LOCK CRITICAL SECTION 
+         * before we begin to manipulate the inherited handles
+         */
+        EnterCriticalSection(&proc_lock);
 
-ap_status_t ap_get_childerr(ap_file_t **new, ap_proc_t *proc)
-{
-    (*new) = proc->attr->parent_err; 
-    return APR_SUCCESS;
-}    
+        if ((attr->child_in && attr->child_in->filehand)
+            || (attr->child_out && attr->child_out->filehand)
+            || (attr->child_err && attr->child_err->filehand))
+        {
+            si.dwFlags |= STARTF_USESTDHANDLES;
 
-ap_status_t ap_wait_proc(ap_proc_t *proc, 
-                         ap_wait_how_e wait)
-{
-    DWORD stat;
-    if (!proc)
-        return APR_ENOPROC;
-    if (wait == APR_WAIT) {
-        if ((stat = WaitForSingleObject(proc->pi.hProcess, INFINITE)) == WAIT_OBJECT_0) {
-            return APR_CHILD_DONE;
+            si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
+            if (attr->child_in && attr->child_in->filehand)
+            {
+                if (GetHandleInformation(si.hStdInput,
+                                         &stdin_reset)
+                        && (stdin_reset &= HANDLE_FLAG_INHERIT))
+                    SetHandleInformation(si.hStdInput,
+                                         HANDLE_FLAG_INHERIT, 0);
+
+                if ( (si.hStdInput = attr->child_in->filehand) 
+                                   != INVALID_HANDLE_VALUE )
+                    SetHandleInformation(si.hStdInput, HANDLE_FLAG_INHERIT,
+                                                       HANDLE_FLAG_INHERIT);
+            }
+            
+            si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
+            if (attr->child_out && attr->child_out->filehand)
+            {
+                if (GetHandleInformation(si.hStdOutput,
+                                         &stdout_reset)
+                        && (stdout_reset &= HANDLE_FLAG_INHERIT))
+                    SetHandleInformation(si.hStdOutput,
+                                         HANDLE_FLAG_INHERIT, 0);
+
+                if ( (si.hStdOutput = attr->child_out->filehand) 
+                                   != INVALID_HANDLE_VALUE )
+                    SetHandleInformation(si.hStdOutput, HANDLE_FLAG_INHERIT,
+                                                        HANDLE_FLAG_INHERIT);
+            }
+
+            si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
+            if (attr->child_err && attr->child_err->filehand)
+            {
+                if (GetHandleInformation(si.hStdError,
+                                         &stderr_reset)
+                        && (stderr_reset &= HANDLE_FLAG_INHERIT))
+                    SetHandleInformation(si.hStdError,
+                                         HANDLE_FLAG_INHERIT, 0);
+
+                if ( (si.hStdError = attr->child_err->filehand) 
+                                   != INVALID_HANDLE_VALUE )
+                    SetHandleInformation(si.hStdError, HANDLE_FLAG_INHERIT,
+                                                       HANDLE_FLAG_INHERIT);
+            }
         }
-        else if (stat == WAIT_TIMEOUT) {
-            return APR_CHILD_NOTDONE;
+        if (attr->user_token) {
+            /* XXX: for terminal services, handles can't be cannot be
+             * inherited across sessions.  This process must be created 
+             * in our existing session.  lpDesktop assignment appears
+             * to be wrong according to these rules.
+             */
+            si.lpDesktop = L"Winsta0\\Default";
+            if (!ImpersonateLoggedOnUser(attr->user_token)) {
+            /* failed to impersonate the logged user */
+                rv = apr_get_os_error();
+                CloseHandle(attr->user_token);
+                attr->user_token = NULL;
+                LeaveCriticalSection(&proc_lock);
+                return rv;
+            }
+            rv = CreateProcessAsUserW(attr->user_token,
+                                      wprg, wcmd,
+                                      attr->sa,
+                                      NULL,
+                                      TRUE,
+                                      dwCreationFlags,
+                                      pEnvBlock,
+                                      wcwd,
+                                      &si, &pi);
+
+            RevertToSelf();
         }
-        return GetLastError();
+        else {
+            rv = CreateProcessW(wprg, wcmd,        /* Executable & Command line */
+                                NULL, NULL,        /* Proc & thread security attributes */
+                                TRUE,              /* Inherit handles */
+                                dwCreationFlags,   /* Creation flags */
+                                pEnvBlock,         /* Environment block */
+                                wcwd,              /* Current directory name */
+                                &si, &pi);
+        }
+
+        if ((attr->child_in && attr->child_in->filehand)
+            || (attr->child_out && attr->child_out->filehand)
+            || (attr->child_err && attr->child_err->filehand))
+        {
+            if (stdin_reset)
+                SetHandleInformation(GetStdHandle(STD_INPUT_HANDLE),
+                                     stdin_reset, stdin_reset);
+
+            if (stdout_reset)
+                SetHandleInformation(GetStdHandle(STD_OUTPUT_HANDLE),
+                                     stdout_reset, stdout_reset);
+
+            if (stderr_reset)
+                SetHandleInformation(GetStdHandle(STD_ERROR_HANDLE),
+                                     stderr_reset, stderr_reset);
+        }
+        /* RELEASE CRITICAL SECTION 
+         * The state of the inherited handles has been restored.
+         */
+        LeaveCriticalSection(&proc_lock);
+
+#else /* defined(_WIN32_WCE) */
+        rv = CreateProcessW(wprg, wcmd,        /* Executable & Command line */
+                            NULL, NULL,        /* Proc & thread security attributes */
+                            FALSE,             /* must be 0 */
+                            dwCreationFlags,   /* Creation flags */
+                            NULL,              /* Environment block must be NULL */
+                            NULL,              /* Current directory name must be NULL*/
+                            NULL,              /* STARTUPINFO not supported */
+                            &pi);
+#endif
     }
-    if ((stat = WaitForSingleObject(proc->pi.hProcess, 0)) == WAIT_OBJECT_0) {
-        return APR_CHILD_DONE;
+#endif /* APR_HAS_UNICODE_FS */
+#if APR_HAS_ANSI_FS
+    ELSE_WIN_OS_IS_ANSI
+    {
+        STARTUPINFOA si;
+        memset(&si, 0, sizeof(si));
+        si.cb = sizeof(si);
+
+        if (attr->detached) {
+            si.dwFlags |= STARTF_USESHOWWINDOW;
+            si.wShowWindow = SW_HIDE;
+        }
+
+        if ((attr->child_in && attr->child_in->filehand)
+            || (attr->child_out && attr->child_out->filehand)
+            || (attr->child_err && attr->child_err->filehand))
+        {
+            si.dwFlags |= STARTF_USESTDHANDLES;
+
+            si.hStdInput = (attr->child_in) 
+                              ? attr->child_in->filehand
+                              : GetStdHandle(STD_INPUT_HANDLE);
+
+            si.hStdOutput = (attr->child_out)
+                              ? attr->child_out->filehand
+                              : GetStdHandle(STD_OUTPUT_HANDLE);
+
+            si.hStdError = (attr->child_err)
+                              ? attr->child_err->filehand
+                              : GetStdHandle(STD_ERROR_HANDLE);
+        }
+
+        rv = CreateProcessA(progname, cmdline, /* Command line */
+                            NULL, NULL,        /* Proc & thread security attributes */
+                            TRUE,              /* Inherit handles */
+                            dwCreationFlags,   /* Creation flags */
+                            pEnvBlock,         /* Environment block */
+                            attr->currdir,     /* Current directory name */
+                            &si, &pi);
     }
-    else if (stat == WAIT_TIMEOUT) {
-        return APR_CHILD_NOTDONE;
+#endif /* APR_HAS_ANSI_FS */
+
+    /* Check CreateProcess result 
+     */
+    if (!rv)
+        return apr_get_os_error();
+
+    /* XXX Orphaned handle warning - no fix due to broken apr_proc_t api.
+     */
+    new->hproc = pi.hProcess;
+    new->pid = pi.dwProcessId;
+
+    if ((attr->child_in) && (attr->child_in != &no_file)) {
+        apr_file_close(attr->child_in);
+    }
+    if ((attr->child_out) && (attr->child_out != &no_file)) {
+        apr_file_close(attr->child_out);
     }
-    return GetLastError();
+    if ((attr->child_err) && (attr->child_err != &no_file)) {
+        apr_file_close(attr->child_err);
+    }
+    CloseHandle(pi.hThread);
+
+    return APR_SUCCESS;
+}
+
+static apr_exit_why_e why_from_exit_code(DWORD exit) {
+    /* See WinNT.h STATUS_ACCESS_VIOLATION and family for how
+     * this class of failures was determined
+     */
+    if (((exit & 0xC0000000) == 0xC0000000) 
+                    && !(exit & 0x3FFF0000))
+        return APR_PROC_SIGNAL;
+    else
+        return APR_PROC_EXIT;
+
+    /* ### No way to tell if Dr Watson grabbed a core, AFAICT. */
 }
 
-ap_status_t ap_get_procdata(char *key, void *data, ap_proc_t *proc)
+APR_DECLARE(apr_status_t) apr_proc_wait_all_procs(apr_proc_t *proc,
+                                                  int *exitcode,
+                                                  apr_exit_why_e *exitwhy,
+                                                  apr_wait_how_e waithow,
+                                                  apr_pool_t *p)
 {
-    if (proc != NULL) {
-        return ap_get_userdata(data, key, proc->cntxt);
-    }
-    else {
-        data = NULL;
-        return APR_ENOPROC;
+#if APR_HAS_UNICODE_FS
+#ifndef _WIN32_WCE
+    IF_WIN_OS_IS_UNICODE
+    {
+        DWORD  dwId    = GetCurrentProcessId();
+        DWORD  i;
+        DWORD  nChilds = 0;
+        DWORD  nActive = 0;
+        HANDLE ps32;
+        PROCESSENTRY32W pe32;
+        BOOL   bHasMore = FALSE;
+        DWORD  dwFlags  = PROCESS_QUERY_INFORMATION;
+        apr_status_t rv = APR_EGENERAL;
+
+        if (waithow == APR_WAIT)
+            dwFlags |= SYNCHRONIZE;
+        if (!(ps32 = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0))) {
+            return apr_get_os_error();
+        }
+        pe32.dwSize = sizeof(PROCESSENTRY32W);
+        if (!Process32FirstW(ps32, &pe32)) {
+            if (GetLastError() == ERROR_NO_MORE_FILES)
+                return APR_EOF;
+            else
+                return apr_get_os_error();
+        }
+        do {
+            DWORD  dwRetval = 0;
+            DWORD  nHandles = 0;
+            HANDLE hProcess = NULL;
+            HANDLE pHandles[MAXIMUM_WAIT_OBJECTS];
+            do {
+                if (pe32.th32ParentProcessID == dwId) {
+                    nChilds++;
+                    if ((hProcess = OpenProcess(dwFlags, FALSE,
+                                                pe32.th32ProcessID)) != NULL) {
+                        if (GetExitCodeProcess(hProcess, &dwRetval)) {
+                            if (dwRetval == STILL_ACTIVE) {
+                                nActive++;
+                                if (waithow == APR_WAIT)
+                                    pHandles[nHandles++] = hProcess;
+                                else
+                                    CloseHandle(hProcess);
+                            }
+                            else {                                
+                                /* Process has exited.
+                                 * No need to wait for its termination.
+                                 */
+                                CloseHandle(hProcess);
+                                if (exitcode)
+                                    *exitcode = dwRetval;
+                                if (exitwhy)
+                                    *exitwhy  = why_from_exit_code(dwRetval);
+                                proc->pid = pe32.th32ProcessID;
+                            }
+                        }
+                        else {
+                            /* Unexpected error code.
+                             * Cleanup and return;
+                             */
+                            rv = apr_get_os_error();
+                            CloseHandle(hProcess);
+                            for (i = 0; i < nHandles; i++)
+                                CloseHandle(pHandles[i]);
+                            return rv;
+                        }
+                    }
+                    else {
+                        /* This is our child, so it shouldn't happen
+                         * that we cannot open our child's process handle.
+                         * However if the child process increased the
+                         * security token it might fail.
+                         */
+                    }
+                }
+            } while ((bHasMore = Process32NextW(ps32, &pe32)) &&
+                     nHandles < MAXIMUM_WAIT_OBJECTS);
+            if (nHandles) {
+                /* Wait for all collected processes to finish */
+                DWORD waitStatus = WaitForMultipleObjects(nHandles, pHandles,
+                                                          TRUE, INFINITE);
+                for (i = 0; i < nHandles; i++)
+                    CloseHandle(pHandles[i]);
+                if (waitStatus == WAIT_OBJECT_0) {
+                    /* Decrease active count by the number of awaited
+                     * processes.
+                     */
+                    nActive -= nHandles;
+                }
+                else {
+                    /* Broken from the infinite loop */
+                    break;
+                }
+            }
+        } while (bHasMore);
+        CloseHandle(ps32);
+        if (waithow != APR_WAIT) {
+            if (nChilds && nChilds == nActive) {
+                /* All child processes are running */
+                rv = APR_CHILD_NOTDONE;
+                proc->pid = -1;
+            }
+            else {
+                /* proc->pid contains the pid of the
+                 * exited processes
+                 */
+                rv = APR_CHILD_DONE;
+            }
+        }
+        if (nActive == 0) {
+            rv = APR_CHILD_DONE;
+            proc->pid = -1;
+        }
+        return rv;
     }
+#endif /* _WIN32_WCE */
+#endif /* APR_HAS_UNICODE_FS */
+    return APR_ENOTIMPL;
 }
 
-ap_status_t ap_set_procdata(void *data, char *key,
-                            ap_status_t (*cleanup) (void *),
-                            ap_proc_t *proc)
+APR_DECLARE(apr_status_t) apr_proc_wait(apr_proc_t *proc,
+                                        int *exitcode, apr_exit_why_e *exitwhy,
+                                        apr_wait_how_e waithow)
 {
-    if (proc != NULL) {
-        return ap_set_userdata(data, key, cleanup, proc->cntxt);
+    DWORD stat;
+    DWORD time;
+
+    if (waithow == APR_WAIT)
+        time = INFINITE;
+    else
+        time = 0;
+
+    if ((stat = WaitForSingleObject(proc->hproc, time)) == WAIT_OBJECT_0) {
+        if (GetExitCodeProcess(proc->hproc, &stat)) {
+            if (exitcode)
+                *exitcode = stat;
+            if (exitwhy)
+                *exitwhy = why_from_exit_code(stat);
+            CloseHandle(proc->hproc);
+            proc->hproc = NULL;
+            return APR_CHILD_DONE;
+        }
     }
-    else {
-        data = NULL;
-        return APR_ENOPROC;
+    else if (stat == WAIT_TIMEOUT) {
+        return APR_CHILD_NOTDONE;
     }
+    return apr_get_os_error();
 }
 
-ap_status_t ap_get_os_proc(ap_os_proc_t *theproc, ap_proc_t *proc)
+APR_DECLARE(apr_status_t) apr_proc_detach(int daemonize)
 {
-    if (proc == NULL) {
-        return APR_ENOPROC;
-    }
-    *theproc = proc->pi;
-    return APR_SUCCESS;
+    return APR_ENOTIMPL;
 }
 
-ap_status_t ap_put_os_proc(ap_proc_t **proc, ap_os_proc_t *theproc, 
-                           ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_procattr_perms_set_register(apr_procattr_t *attr,
+                                                 apr_perms_setfn_t *perms_set_fn,
+                                                 void *data,
+                                                 apr_fileperms_t perms)
 {
-    if (cont == NULL) {
-        return APR_ENOPOOL;
-    }
-    if ((*proc) == NULL) {
-        (*proc) = (ap_proc_t *)ap_palloc(cont, sizeof(ap_proc_t));
-        (*proc)->cntxt = cont;
-    }
-    (*proc)->pi = *theproc;
-    return APR_SUCCESS;
-}              
+    return APR_ENOTIMPL;
+}
diff --git a/threadproc/win32/signals.c b/threadproc/win32/signals.c
index 08119b78d05..48676d856ca 100644
--- a/threadproc/win32/signals.c
+++ b/threadproc/win32/signals.c
@@ -1,74 +1,67 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "threadproc.h"
-#include "fileio.h"
+#include "apr_arch_threadproc.h"
+#include "apr_arch_file_io.h"
 #include "apr_thread_proc.h"
+#include "apr_signal.h"
 #include "apr_file_io.h"
 #include "apr_general.h"
+#if APR_HAVE_SIGNAL_H
 #include <signal.h>
+#endif
 #include <string.h>
-#ifdef HAVE_SYS_WAIT
+#if APR_HAVE_SYS_WAIT
 #include <sys/wait.h>
 #endif
 
-/* Windows only really support killing process, but that will do for now. */
-ap_status_t ap_kill(ap_proc_t *proc, int signal)
+/* Windows only really support killing process, but that will do for now. 
+ *
+ * ### Actually, closing the input handle to the proc should also do fine 
+ * for most console apps.  This definitely needs improvement...
+ */
+APR_DECLARE(apr_status_t) apr_proc_kill(apr_proc_t *proc, int signal)
 {
-    if (TerminateProcess(proc->pi.hProcess, signal) == 0) {
-        return errno;
+    if (proc->hproc != NULL) {
+        if (TerminateProcess(proc->hproc, signal) == 0) {
+            return apr_get_os_error();
+        }
+        /* On unix, SIGKILL leaves a apr_proc_wait()able pid lying around, 
+         * so we will leave hproc alone until the app calls apr_proc_wait().
+         */
+        return APR_SUCCESS;
     }
-    return APR_SUCCESS;
+    return APR_EPROC_UNKNOWN;
 }
 
+void apr_signal_init(apr_pool_t *pglobal)
+{
+}
+
+APR_DECLARE(const char *) apr_signal_description_get(int signum)
+{
+    return "unknown signal (not supported)";
+}
+
+APR_DECLARE(apr_status_t) apr_signal_block(int signum)
+{
+    return APR_ENOTIMPL;
+}
+
+APR_DECLARE(apr_status_t) apr_signal_unblock(int signum)
+{
+    return APR_ENOTIMPL;
+}
diff --git a/threadproc/win32/thread.c b/threadproc/win32/thread.c
index 5e38f066c07..c713e1444f3 100644
--- a/threadproc/win32/thread.c
+++ b/threadproc/win32/thread.c
@@ -1,205 +1,286 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
 #include "apr_private.h"
-#include "threadproc.h"
+#include "apr_arch_threadproc.h"
 #include "apr_thread_proc.h"
 #include "apr_general.h"
 #include "apr_lib.h"
 #include "apr_portable.h"
+#ifdef HAVE_PROCESS_H
 #include <process.h>
+#endif
+#include "apr_arch_misc.h"   
 
+/* Chosen for us by apr_initialize */
+DWORD tls_apr_thread = 0;
 
-ap_status_t ap_create_threadattr(ap_threadattr_t **new, ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_threadattr_create(apr_threadattr_t **new,
+                                                apr_pool_t *pool)
 {
-    (*new) = (ap_threadattr_t *)ap_palloc(cont, 
-              sizeof(ap_threadattr_t));
+    (*new) = (apr_threadattr_t *)apr_palloc(pool, 
+              sizeof(apr_threadattr_t));
 
     if ((*new) == NULL) {
         return APR_ENOMEM;
     }
 
-    (*new)->cntxt = cont;
+    (*new)->pool = pool;
+    (*new)->detach = 0;
+    (*new)->stacksize = 0;
+
     return APR_SUCCESS;
 }
 
-ap_status_t ap_setthreadattr_detach(ap_threadattr_t *attr, ap_int32_t on)
+APR_DECLARE(apr_status_t) apr_threadattr_detach_set(apr_threadattr_t *attr,
+                                                   apr_int32_t on)
 {
     attr->detach = on;
-	return APR_SUCCESS;
+    return APR_SUCCESS;
 }
 
-ap_status_t ap_getthreadattr_detach(ap_threadattr_t *attr)
+APR_DECLARE(apr_status_t) apr_threadattr_detach_get(apr_threadattr_t *attr)
 {
     if (attr->detach == 1)
         return APR_DETACH;
     return APR_NOTDETACH;
 }
 
-ap_status_t ap_create_thread(ap_thread_t **new, ap_threadattr_t *attr, 
-                             ap_thread_start_t func, void *data, 
-                             ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_threadattr_stacksize_set(apr_threadattr_t *attr,
+                                                       apr_size_t stacksize)
+{
+    attr->stacksize = stacksize;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr,
+                                                       apr_size_t size)
+{
+    return APR_ENOTIMPL;
+}
+
+static void *dummy_worker(void *opaque)
+{
+    apr_thread_t *thd = (apr_thread_t *)opaque;
+    void *ret;
+
+    TlsSetValue(tls_apr_thread, thd->td);
+    apr_pool_owner_set(thd->pool, 0);
+    ret = thd->func(thd, thd->data);
+    apr_pool_destroy(thd->pool);
+    return ret;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new,
+                                            apr_threadattr_t *attr,
+                                            apr_thread_start_t func,
+                                            void *data, apr_pool_t *pool)
 {
-    ap_status_t stat;
+    apr_status_t stat;
 	unsigned temp;
-    int lasterror;
- 
-    (*new) = (ap_thread_t *)ap_palloc(cont, sizeof(ap_thread_t));
+    HANDLE handle;
+
+    (*new) = (apr_thread_t *)apr_palloc(pool, sizeof(apr_thread_t));
 
     if ((*new) == NULL) {
         return APR_ENOMEM;
     }
 
-    (*new)->cntxt = cont;
-    
-    stat = ap_create_pool(&(*new)->cntxt, cont);
+    (*new)->data = data;
+    (*new)->func = func;
+    (*new)->td   = NULL;
+    stat = apr_pool_create(&(*new)->pool, pool);
     if (stat != APR_SUCCESS) {
         return stat;
     }
 
-	/* Use 0 for Thread Stack Size, because that will default the stack to the
-	 * same size as the calling thread. 
-	*/
-    if (((*new)->td = (HANDLE *)_beginthreadex(NULL, 0, (unsigned int (API_THREAD_FUNC *)(void *))func,
-                                               data, 0, &temp)) == 0) {
-        lasterror = GetLastError();
-        return APR_EEXIST;
+    /* Use 0 for default Thread Stack Size, because that will
+     * default the stack to the same size as the calling thread.
+     */
+#ifndef _WIN32_WCE
+    if ((handle = (HANDLE)_beginthreadex(NULL,
+                        (DWORD) (attr ? attr->stacksize : 0),
+                        (unsigned int (APR_THREAD_FUNC *)(void *))dummy_worker,
+                        (*new), 0, &temp)) == 0) {
+        return APR_FROM_OS_ERROR(_doserrno);
     }
+#else
+   if ((handle = CreateThread(NULL,
+                        attr && attr->stacksize > 0 ? attr->stacksize : 0,
+                        (unsigned int (APR_THREAD_FUNC *)(void *))dummy_worker,
+                        (*new), 0, &temp)) == 0) {
+        return apr_get_os_error();
+    }
+#endif
+    if (attr && attr->detach) {
+        CloseHandle(handle);
+    }
+    else
+        (*new)->td = handle;
 
-	if (attr && attr->detach) {
-		CloseHandle((*new)->td);
-	}
-
-	return APR_SUCCESS;
+    return APR_SUCCESS;
 }
 
-ap_status_t ap_thread_exit(ap_thread_t *thd, ap_status_t *retval)
+APR_DECLARE(apr_status_t) apr_thread_exit(apr_thread_t *thd,
+                                          apr_status_t retval)
 {
-    ap_destroy_pool(thd->cntxt);
-    _endthreadex(*retval);
-	return APR_SUCCESS;
+    thd->exitval = retval;
+    apr_pool_destroy(thd->pool);
+    thd->pool = NULL;
+#ifndef _WIN32_WCE
+    _endthreadex(0);
+#else
+    ExitThread(0);
+#endif
+    return APR_SUCCESS;
 }
 
-ap_status_t ap_thread_join(ap_status_t *retval, ap_thread_t *thd)
+APR_DECLARE(apr_status_t) apr_thread_join(apr_status_t *retval,
+                                          apr_thread_t *thd)
 {
-    ap_status_t stat;
-
-    if ((stat = WaitForSingleObject(thd->td, INFINITE)) == WAIT_OBJECT_0) {
-		if (GetExitCodeThread(thd->td, retval) == 0) {
-			return APR_SUCCESS;
-		}
-		return APR_EEXIST;
+    apr_status_t rv = APR_SUCCESS;
+    
+    if (!thd->td) {
+        /* Can not join on detached threads */
+        return APR_DETACH;
     }
-    else {
-        return stat;
+    rv = WaitForSingleObject(thd->td, INFINITE);
+    if ( rv == WAIT_OBJECT_0 || rv == WAIT_ABANDONED) {
+        /* If the thread_exit has been called */
+        if (!thd->pool)
+            *retval = thd->exitval;
+        else
+            rv = APR_INCOMPLETE;
     }
+    else
+        rv = apr_get_os_error();
+    CloseHandle(thd->td);
+    thd->td = NULL;
+
+    return rv;
 }
 
-ap_status_t ap_thread_detach(ap_thread_t *thd)
+APR_DECLARE(apr_status_t) apr_thread_detach(apr_thread_t *thd)
 {
-    if (CloseHandle(thd->td)) {
+    if (thd->td && CloseHandle(thd->td)) {
+        thd->td = NULL;
         return APR_SUCCESS;
     }
     else {
-        return APR_EEXIST;
+        return apr_get_os_error();
     }
 }
 
-ap_status_t ap_get_threaddata(void **data, char *key, ap_thread_t *thread)
+APR_DECLARE(void) apr_thread_yield()
 {
-    if (thread != NULL) {
-        return ap_get_userdata(data, key, thread->cntxt);
-    }
-    else {
-        data = NULL;
-        return APR_ENOTHREAD;
+    /* SwitchToThread is not supported on Win9x, but since it's
+     * primarily a noop (entering time consuming code, therefore
+     * providing more critical threads a bit larger timeslice)
+     * we won't worry too much if it's not available.
+     */
+#ifndef _WIN32_WCE
+    if (apr_os_level >= APR_WIN_NT) {
+        SwitchToThread();
     }
+#endif
 }
 
-ap_status_t ap_set_threaddata(void *data, char *key,
-                              ap_status_t (*cleanup) (void *),
-                              ap_thread_t *thread)
+APR_DECLARE(apr_status_t) apr_thread_data_get(void **data, const char *key,
+                                             apr_thread_t *thread)
 {
-    if (thread != NULL) {
-        return ap_set_userdata(data, key, cleanup, thread->cntxt);
+    return apr_pool_userdata_get(data, key, thread->pool);
+}
+
+APR_DECLARE(apr_status_t) apr_thread_data_set(void *data, const char *key,
+                                             apr_status_t (*cleanup) (void *),
+                                             apr_thread_t *thread)
+{
+    return apr_pool_userdata_set(data, key, cleanup, thread->pool);
+}
+
+
+APR_DECLARE(apr_os_thread_t) apr_os_thread_current(void)
+{
+    HANDLE hthread = (HANDLE)TlsGetValue(tls_apr_thread);
+    HANDLE hproc;
+
+    if (hthread) {
+        return hthread;
     }
-    else {
-        data = NULL;
-        return APR_ENOTHREAD;
+    
+    hproc = GetCurrentProcess();
+    hthread = GetCurrentThread();
+    if (!DuplicateHandle(hproc, hthread, 
+                         hproc, &hthread, 0, FALSE, 
+                         DUPLICATE_SAME_ACCESS)) {
+        return NULL;
     }
+    TlsSetValue(tls_apr_thread, hthread);
+    return hthread;
 }
 
-ap_status_t ap_get_os_thread(ap_os_thread_t *thethd, ap_thread_t *thd)
+APR_DECLARE(apr_status_t) apr_os_thread_get(apr_os_thread_t **thethd,
+                                            apr_thread_t *thd)
 {
     if (thd == NULL) {
         return APR_ENOTHREAD;
     }
-    thethd = thd->td;
+    *thethd = thd->td;
     return APR_SUCCESS;
 }
 
-ap_status_t ap_put_os_thread(ap_thread_t **thd, ap_os_thread_t *thethd, 
-                             ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_os_thread_put(apr_thread_t **thd,
+                                            apr_os_thread_t *thethd,
+                                            apr_pool_t *pool)
 {
-    if (cont == NULL) {
+    if (pool == NULL) {
         return APR_ENOPOOL;
     }
     if ((*thd) == NULL) {
-        (*thd) = (ap_thread_t *)ap_palloc(cont, sizeof(ap_thread_t));
-        (*thd)->cntxt = cont;
+        (*thd) = (apr_thread_t *)apr_palloc(pool, sizeof(apr_thread_t));
+        (*thd)->pool = pool;
     }
     (*thd)->td = thethd;
     return APR_SUCCESS;
 }
 
+APR_DECLARE(apr_status_t) apr_thread_once_init(apr_thread_once_t **control,
+                                               apr_pool_t *p)
+{
+    (*control) = apr_pcalloc(p, sizeof(**control));
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_once(apr_thread_once_t *control,
+                                          void (*func)(void))
+{
+    if (!InterlockedExchange(&control->value, 1)) {
+        func();
+    }
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(int) apr_os_thread_equal(apr_os_thread_t tid1,
+                                     apr_os_thread_t tid2)
+{
+    /* Since the only tid's we support our are own, and
+     * apr_os_thread_current returns the identical handle
+     * to the one we created initially, the test is simple.
+     */
+    return (tid1 == tid2);
+}
+
+APR_POOL_IMPLEMENT_ACCESSOR(thread)
diff --git a/threadproc/win32/threadcancel.c b/threadproc/win32/threadcancel.c
deleted file mode 100644
index 3a509202b6e..00000000000
--- a/threadproc/win32/threadcancel.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "threadproc.h"
-#include "apr_thread_proc.h"
-#include "apr_general.h"
-
-
-ap_status_t ap_cancel_thread(ap_thread_t *thd)
-{
-    if (TerminateThread(thd->td, APR_SUCCESS) == 0) {
-        return APR_EEXIST;
-    }
-    else {
-        return APR_SUCCESS;
-    }
-}
-
-/*  Not sure of the best way to do this just yet.
-ap_status_t ap_setcanceltype(ap_int32_t type, ap_pool_t *cont)
-{
-	
-}
-
-ap_status_t ap_setcancelstate(ap_int32_t type, ap_pool_t *cont)
-{
-    ap_status_t stat;
-    if ((stat = pthread_setcanceltype(type, NULL)) == 0) {
-        return APR_SUCCESS;
-    }
-    else {
-        return stat;
-    }
-}
-*/
diff --git a/threadproc/win32/threadpriv.c b/threadproc/win32/threadpriv.c
index c556be1926f..787c142c49d 100644
--- a/threadproc/win32/threadpriv.c
+++ b/threadproc/win32/threadpriv.c
@@ -1,136 +1,99 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "threadproc.h"
+#include "apr_arch_threadproc.h"
 #include "apr_thread_proc.h"
 #include "apr_general.h"
 #include "apr_lib.h"
 #include "apr_errno.h"
 #include "apr_portable.h"
 
-ap_status_t ap_create_thread_private(ap_threadkey_t **key,
-                                     void (*dest)(void *), ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_threadkey_private_create(apr_threadkey_t **key,
+                                                    void (*dest)(void *),
+                                                    apr_pool_t *pool)
 {
-	(*key)->key = TlsAlloc();
-	return APR_SUCCESS;
+    (*key) = (apr_threadkey_t *)apr_palloc(pool, sizeof(apr_threadkey_t));
+    if ((*key) == NULL) {
+        return APR_ENOMEM;
+    }
+
+    (*key)->pool = pool;
+
+    if (((*key)->key = TlsAlloc()) != 0xFFFFFFFF) {
+        return APR_SUCCESS;
+    }
+    return apr_get_os_error();
 }
 
-ap_status_t ap_get_thread_private(void **new, ap_threadkey_t *key)
+APR_DECLARE(apr_status_t) apr_threadkey_private_get(void **new,
+                                                 apr_threadkey_t *key)
 {
-    if ((*new) = TlsGetValue(key->key)) {
+    if (((*new) = TlsGetValue(key->key))) {
         return APR_SUCCESS;
     }
-    return APR_EEXIST;
+    return apr_get_os_error();
 }
 
-ap_status_t ap_set_thread_private(void *priv, ap_threadkey_t *key)
+APR_DECLARE(apr_status_t) apr_threadkey_private_set(void *priv,
+                                                 apr_threadkey_t *key)
 {
     if (TlsSetValue(key->key, priv)) {
         return APR_SUCCESS;
     }
-    return APR_EEXIST;
+    return apr_get_os_error();
 }
 
-ap_status_t ap_delete_thread_private(ap_threadkey_t *key)
+APR_DECLARE(apr_status_t) apr_threadkey_private_delete(apr_threadkey_t *key)
 {
     if (TlsFree(key->key)) {
         return APR_SUCCESS; 
     }
-    return APR_EEXIST;
+    return apr_get_os_error();
 }
 
-ap_status_t ap_get_threadkeydata(void **data, char *key, ap_threadkey_t *threadkey)
+APR_DECLARE(apr_status_t) apr_threadkey_data_get(void **data, const char *key,
+                                                apr_threadkey_t *threadkey)
 {
-    if (threadkey != NULL) {
-        return ap_get_userdata(data, key, threadkey->cntxt);
-    }
-    else {
-        data = NULL;
-        return APR_ENOTHDKEY;
-    }
+    return apr_pool_userdata_get(data, key, threadkey->pool);
 }
 
-ap_status_t ap_set_threadkeydata(void *data, char *key, ap_status_t (*cleanup) (void *), 
-                                 ap_threadkey_t *threadkey)
+APR_DECLARE(apr_status_t) apr_threadkey_data_set(void *data, const char *key,
+                                                apr_status_t (*cleanup)(void *),
+                                                apr_threadkey_t *threadkey)
 {
-    if (threadkey != NULL) {
-        return ap_set_userdata(data, key, cleanup, threadkey->cntxt);
-    }
-    else {
-        data = NULL;
-        return APR_ENOTHDKEY;
-    }
+    return apr_pool_userdata_set(data, key, cleanup, threadkey->pool);
 }
 
-ap_status_t ap_get_os_threadkey(ap_os_threadkey_t *thekey, ap_threadkey_t *key)
+APR_DECLARE(apr_status_t) apr_os_threadkey_get(apr_os_threadkey_t *thekey,
+                                               apr_threadkey_t *key)
 {
-    if (key == NULL) {
-        return APR_ENOFILE;
-    }
-    thekey = &(key->key);
+    *thekey = key->key;
     return APR_SUCCESS;
 }
 
-ap_status_t ap_put_os_threadkey(ap_threadkey_t **key, 
-                                ap_os_threadkey_t *thekey, ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_os_threadkey_put(apr_threadkey_t **key,
+                                               apr_os_threadkey_t *thekey,
+                                               apr_pool_t *pool)
 {
-    if (cont == NULL) {
+    if (pool == NULL) {
         return APR_ENOPOOL;
     }
     if ((*key) == NULL) {
-        (*key) = (ap_threadkey_t *)ap_palloc(cont, sizeof(ap_threadkey_t));
-        (*key)->cntxt = cont;
+        (*key) = (apr_threadkey_t *)apr_palloc(pool, sizeof(apr_threadkey_t));
+        (*key)->pool = pool;
     }
     (*key)->key = *thekey;
     return APR_SUCCESS;
diff --git a/threadproc/win32/threadproc.h b/threadproc/win32/threadproc.h
deleted file mode 100644
index 16667de67e7..00000000000
--- a/threadproc/win32/threadproc.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "apr_private.h"
-#include "apr_thread_proc.h"
-#include "apr_file_io.h"
-#include <windows.h>
-
-#ifndef THREAD_PROC_H
-#define THREAD_PROC_H
-
-#define SHELL_PATH "cmd.exe"
-
-struct ap_thread_t {
-    ap_pool_t *cntxt;
-    HANDLE td;
-    ap_int32_t cancel;
-    ap_int32_t cancel_how;
-};
-
-struct ap_threadattr_t {
-    ap_pool_t *cntxt;
-    ap_int32_t detach;
-};
-
-struct ap_threadkey_t {
-    ap_pool_t *cntxt;
-    DWORD key;
-};
-
-struct ap_procattr_t {
-    ap_pool_t *cntxt;
-    STARTUPINFO si;
-    ap_file_t *parent_in;
-    ap_file_t *child_in;
-    ap_file_t *parent_out;
-    ap_file_t *child_out;
-    ap_file_t *parent_err;
-    ap_file_t *child_err;
-    char *currdir;
-    ap_int32_t cmdtype;
-    ap_int32_t detached;
-};
-
-struct ap_proc_t {
-    ap_pool_t *cntxt;
-    PROCESS_INFORMATION pi;
-    struct ap_procattr_t *attr;
-};
-
-#endif  /* ! THREAD_PROC_H */
-
diff --git a/threads.m4 b/threads.m4
deleted file mode 100644
index 04207aa79bc..00000000000
--- a/threads.m4
+++ /dev/null
@@ -1,93 +0,0 @@
-dnl
-dnl REENTRANCY_FLAGS
-dnl
-dnl Set some magic defines
-dnl
-AC_DEFUN(REENTRANCY_FLAGS,[
-  case "`uname -sr`" in
-  "SunOS 5"*)
-    CFLAGS="$CFLAGS -D_POSIX_PTHREAD_SEMANTICS";;
-  esac
-  
-dnl This works for now..
-  CFLAGS="$CFLAGS -D_REENTRANT"
-])dnl
-dnl
-dnl PTHREADS_CHECK_COMPILE
-dnl
-dnl Check whether the current setup can use POSIX threads calls
-dnl
-AC_DEFUN(PTHREADS_CHECK_COMPILE, [
-AC_TRY_RUN( [
-#include <pthread.h>
-#include <stddef.h>
-
-void *thread_routine(void *data) {
-    return data;
-}
-
-int main() {
-    pthread_t thd;
-    pthread_mutexattr_t mattr;
-    int data = 1;
-    pthread_mutexattr_init(&mattr);
-    return pthread_create(&thd, NULL, thread_routine, &data);
-} ], [ 
-  pthreads_working="yes"
-  ], [
-  pthreads_working="no"
-  ], pthreads_working="no" ) ] )dnl
-dnl
-dnl PTHREADS_CHECK()
-dnl
-dnl Try to find a way to enable POSIX threads
-dnl
-AC_DEFUN(PTHREADS_CHECK,[
-if test -n "$ac_cv_pthreads_lib"; then
-  LIBS="$LIBS -l$ac_cv_pthreads_lib"
-fi
-
-if test -n "$ac_cv_pthreads_cflags"; then
-  CFLAGS="$CFLAGS $ac_cv_pthreads_cflags"
-fi
-
-PTHREADS_CHECK_COMPILE
-
-AC_CACHE_CHECK(for pthreads_cflags,ac_cv_pthreads_cflags,[
-ac_cv_pthreads_cflags=""
-if test "$pthreads_working" != "yes"; then
-  for flag in -pthreads -pthread -mthreads; do 
-    ac_save="$CFLAGS"
-    CFLAGS="$CFLAGS $flag"
-	PTHREADS_CHECK_COMPILE
-    if test "$pthreads_working" = "yes"; then
-      ac_cv_pthreads_cflags="$flag"
-      break
-    fi
-    CFLAGS="$ac_save"
-  done
-fi
-])
-
-AC_CACHE_CHECK(for pthreads_lib, ac_cv_pthreads_lib,[
-ac_cv_pthreads_lib=""
-if test "$pthreads_working" != "yes"; then
-  for lib in pthread pthreads c_r; do
-    ac_save="$LIBS"
-    LIBS="$LIBS -l$lib"
-    PTHREADS_CHECK_COMPILE
-    if test "$pthreads_working" = "yes"; then
-      ac_cv_pthreads_lib="$lib"
-      break
-    fi
-    LIBS="$ac_save"
-  done
-fi
-])
-
-if test "$pthreads_working" = "yes"; then
-  threads_result="POSIX Threads found"
-else
-  threads_result="POSIX Threads not found"
-fi
-])dnl
diff --git a/time/unix/.cvsignore b/time/unix/.cvsignore
deleted file mode 100644
index f3c7a7c5da6..00000000000
--- a/time/unix/.cvsignore
+++ /dev/null
@@ -1 +0,0 @@
-Makefile
diff --git a/time/unix/Makefile.in b/time/unix/Makefile.in
deleted file mode 100644
index 352364d25da..00000000000
--- a/time/unix/Makefile.in
+++ /dev/null
@@ -1,64 +0,0 @@
-#CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
-#LIBS=$(EXTRA_LIBS) $(LIBS1)
-#INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
-#LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
-
-RM=@RM@
-CC=@CC@
-RANLIB=@RANLIB@
-CFLAGS=@CFLAGS@ @OPTIM@
-LIBS=@LIBS@
-LDFLAGS=@LDFLAGS@ $(LIBS)
-INCDIR=../../include
-INCLUDES=-I$(INCDIR) -I.
-
-#LIB=libtime.a
-
-OBJS=time.o \
-	timestr.o
-
-.c.o:
-	$(CC) $(CFLAGS) -c $(INCLUDES) $<
-
-all: $(OBJS)
-
-clean:
-	$(RM) -f *.o *.a *.so
-
-distclean: clean
-	-$(RM) -f Makefile
-
-$(OBJS): Makefile
-
-#$(LIB): $(OBJS)
-#	$(RM) -f $@
-#	$(AR) cr $@ $(OBJS)
-#	$(RANLIB) $@
-
-#
-# We really don't expect end users to use this rule.  It works only with
-# gcc, and rebuilds Makefile.tmpl.  You have to re-run Configure after
-# using it.
-#
-depend:
-	cp Makefile.in Makefile.in.bak \
-	    && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.in > Makefile.new \
-	    && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \
-	    && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
-	           -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
-		> Makefile.in \
-	    && rm Makefile.new
-
-# DO NOT REMOVE
-time.o: time.c atime.h $(INCDIR)/apr_private.h \
- $(INCDIR)/apr_time.h $(INCDIR)/apr_general.h \
- $(INCDIR)/apr.h $(INCDIR)/apr_errno.h $(INCDIR)/apr_lib.h \
- $(INCDIR)/apr_file_io.h $(INCDIR)/apr_thread_proc.h \
- $(INCDIR)/apr_portable.h $(INCDIR)/apr_network_io.h \
- $(INCDIR)/apr_lock.h
-timestr.o: timestr.c atime.h $(INCDIR)/apr_private.h \
- $(INCDIR)/apr_time.h $(INCDIR)/apr_general.h \
- $(INCDIR)/apr.h $(INCDIR)/apr_errno.h $(INCDIR)/apr_lib.h \
- $(INCDIR)/apr_file_io.h $(INCDIR)/apr_thread_proc.h \
- $(INCDIR)/apr_portable.h $(INCDIR)/apr_network_io.h \
- $(INCDIR)/apr_lock.h
diff --git a/time/unix/atime.h b/time/unix/atime.h
deleted file mode 100644
index f22167486e5..00000000000
--- a/time/unix/atime.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef ATIME_H
-#define ATIME_H
-
-#include "apr_private.h"
-#include "apr_time.h"
-#include "apr_lib.h"
-
-/* System Headers required for time library */
-#if HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#if HAVE_TIME_H
-#include <time.h>
-#endif
-/* End System Headers */
-
-struct atime_t {
-    ap_pool_t *cntxt;
-    struct timeval *currtime;
-    struct tm *explodedtime;
-    int time_ex;    /* have we already exploded the time? */
-};
-    
-
-#endif  /* ! ATIME_H */
-
diff --git a/time/unix/time.c b/time/unix/time.c
index bbd0dd31261..7f095819276 100644
--- a/time/unix/time.c
+++ b/time/unix/time.c
@@ -1,177 +1,149 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "atime.h"
 #include "apr_portable.h"
+#include "apr_time.h"
+#include "apr_lib.h"
+#include "apr_private.h"
+#include "apr_strings.h"
 
-ap_status_t ap_ansi_time_to_ap_time(ap_time_t *result, time_t input)
-{
-    *result = (ap_time_t)input * AP_USEC_PER_SEC;
-    return APR_SUCCESS;
-}
+/* private APR headers */
+#include "apr_arch_internal_time.h"
 
+/* System Headers required for time library */
+#if APR_HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#if APR_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+/* End System Headers */
+
+#if !defined(HAVE_STRUCT_TM_TM_GMTOFF) && !defined(HAVE_STRUCT_TM___TM_GMTOFF)
+static apr_int32_t server_gmt_offset;
+#define NO_GMTOFF_IN_STRUCT_TM
+#endif          
 
-ap_time_t ap_now(void)
+static apr_int32_t get_offset(struct tm *tm)
 {
-    struct timeval tv;
-    gettimeofday(&tv, NULL);
-    return tv.tv_sec * AP_USEC_PER_SEC + tv.tv_usec;
+#if defined(HAVE_STRUCT_TM_TM_GMTOFF)
+    return tm->tm_gmtoff;
+#elif defined(HAVE_STRUCT_TM___TM_GMTOFF)
+    return tm->__tm_gmtoff;
+#else
+#ifdef NETWARE
+    /* Need to adjust the global variable each time otherwise
+        the web server would have to be restarted when daylight
+        savings changes.
+    */
+    if (daylightOnOff) {
+        return server_gmt_offset + daylightOffset;
+    }
+#else
+    if (tm->tm_isdst)
+        return server_gmt_offset + 3600;
+#endif
+    return server_gmt_offset;
+#endif
 }
 
-
-static void tm_to_exp(ap_exploded_time_t *xt, struct tm *tm)
+APR_DECLARE(apr_status_t) apr_time_ansi_put(apr_time_t *result,
+                                            time_t input)
 {
-    xt->tm_sec  = tm->tm_sec;
-    xt->tm_min  = tm->tm_min;
-    xt->tm_hour = tm->tm_hour;
-    xt->tm_mday = tm->tm_mday;
-    xt->tm_mon  = tm->tm_mon;
-    xt->tm_year = tm->tm_year;
-    xt->tm_wday = tm->tm_wday;
-    xt->tm_yday = tm->tm_yday;
-    xt->tm_isdst = tm->tm_isdst;
+    *result = (apr_time_t)input * APR_USEC_PER_SEC;
+    return APR_SUCCESS;
 }
 
+/* NB NB NB NB This returns GMT!!!!!!!!!! */
+APR_DECLARE(apr_time_t) apr_time_now(void)
+{
+    struct timeval tv;
+    gettimeofday(&tv, NULL);
+    return tv.tv_sec * APR_USEC_PER_SEC + tv.tv_usec;
+}
 
-ap_status_t ap_explode_gmt(ap_exploded_time_t *result, ap_time_t input)
+static void explode_time(apr_time_exp_t *xt, apr_time_t t,
+                         apr_int32_t offset, int use_localtime)
 {
-    time_t t = input / AP_USEC_PER_SEC;
-#if APR_HAS_THREADS && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
-    struct tm banana;
+    struct tm tm;
+    time_t tt = (t / APR_USEC_PER_SEC) + offset;
+    xt->tm_usec = t % APR_USEC_PER_SEC;
+
+#if APR_HAS_THREADS && defined (_POSIX_THREAD_SAFE_FUNCTIONS)
+    if (use_localtime)
+        localtime_r(&tt, &tm);
+    else
+        gmtime_r(&tt, &tm);
+#else
+    if (use_localtime)
+        tm = *localtime(&tt);
+    else
+        tm = *gmtime(&tt);
 #endif
 
-    result->tm_usec = input % AP_USEC_PER_SEC;
+    xt->tm_sec  = tm.tm_sec;
+    xt->tm_min  = tm.tm_min;
+    xt->tm_hour = tm.tm_hour;
+    xt->tm_mday = tm.tm_mday;
+    xt->tm_mon  = tm.tm_mon;
+    xt->tm_year = tm.tm_year;
+    xt->tm_wday = tm.tm_wday;
+    xt->tm_yday = tm.tm_yday;
+    xt->tm_isdst = tm.tm_isdst;
+    xt->tm_gmtoff = get_offset(&tm);
+}
 
-#if APR_HAS_THREADS && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
-    gmtime_r(&t, &banana);
-    tm_to_exp(result, &banana);
-#else
-    tm_to_exp(result, gmtime(&t));
-#endif
-    result->tm_gmtoff = 0;
+APR_DECLARE(apr_status_t) apr_time_exp_tz(apr_time_exp_t *result,
+                                          apr_time_t input, apr_int32_t offs)
+{
+    explode_time(result, input, offs, 0);
+    result->tm_gmtoff = offs;
     return APR_SUCCESS;
 }
 
-ap_status_t ap_explode_localtime(ap_exploded_time_t *result, ap_time_t input)
+APR_DECLARE(apr_status_t) apr_time_exp_gmt(apr_time_exp_t *result,
+                                           apr_time_t input)
 {
-#if APR_HAS_THREADS && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
-    time_t t = input / AP_USEC_PER_SEC;
-    struct tm apricot;
-
-    result->tm_usec = input % AP_USEC_PER_SEC;
-
-    localtime_r(&t, &apricot);
-    tm_to_exp(result, &apricot);
-#if defined(HAVE_GMTOFF)
-    result->tm_gmtoff = apricot.tm_gmtoff;
-#elif defined(HAVE___GMTOFF)
-    result->tm_gmtoff = apricot.__tm_gmtoff;
-#else
-    /* solaris is backwards enough to have pthreads but no tm_gmtoff, feh */
-    {
-	int days, hours, minutes;
-
-	gmtime_r(&t, &apricot);
-	days = result->tm_yday - apricot.tm_yday;
-	hours = ((days < -1 ? 24 : 1 < days ? -24 : days * 24)
-		+ result->tm_hour - apricot.tm_hour);
-	minutes = hours * 60 + result->tm_min - apricot.tm_min;
-	result->tm_gmtoff = minutes * 60;
-    }
-#endif
-#else
-    time_t t = input / AP_USEC_PER_SEC;
-    struct tm *tmx;
-
-    result->tm_usec = input % AP_USEC_PER_SEC;
+    return apr_time_exp_tz(result, input, 0);
+}
 
-    tmx = localtime(&t);
-    tm_to_exp(result, tmx);
-#if defined(HAVE_GMTOFF)
-    result->tm_gmtoff = tmx->tm_gmtoff;
-#elif defined(HAVE___GMTOFF)
-    result->tm_gmtoff = tmx->__tm_gmtoff;
+APR_DECLARE(apr_status_t) apr_time_exp_lt(apr_time_exp_t *result,
+                                                apr_time_t input)
+{
+#if defined(__EMX__)
+    /* EMX gcc (OS/2) has a timezone global we can use */
+    return apr_time_exp_tz(result, input, -timezone);
 #else
-    /* need to create tm_gmtoff... assume we are never more than 24 hours away */
-    {
-	int days, hours, minutes;
-
-	tmx = gmtime(&t);
-	days = result->tm_yday - tmx->tm_yday;
-	hours = ((days < -1 ? 24 : 1 < days ? -24 : days * 24)
-		+ result->tm_hour - tmx->tm_hour);
-	minutes = hours * 60 + result->tm_min - tmx->tm_min;
-	result->tm_gmtoff = minutes * 60;
-    }
-#endif
-#endif
+    explode_time(result, input, 0, 1);
     return APR_SUCCESS;
+#endif /* __EMX__ */
 }
 
-
-ap_status_t ap_implode_time(ap_time_t *t, ap_exploded_time_t *xt)
+APR_DECLARE(apr_status_t) apr_time_exp_get(apr_time_t *t, apr_time_exp_t *xt)
 {
-    int year;
-    time_t days;
+    apr_time_t year = xt->tm_year;
+    apr_time_t days;
     static const int dayoffset[12] =
     {306, 337, 0, 31, 61, 92, 122, 153, 184, 214, 245, 275};
 
-    year = xt->tm_year;
-
-    if (year < 70 || ((sizeof(time_t) <= 4) && (year >= 138))) {
+    if (xt->tm_mon < 0 || xt->tm_mon >= 12)
         return APR_EBADDATE;
-    }
 
     /* shift new year to 1st March in order to make leap year calc easy */
 
@@ -183,25 +155,34 @@ ap_status_t ap_implode_time(ap_time_t *t, ap_exploded_time_t *xt)
     days = year * 365 + year / 4 - year / 100 + (year / 100 + 3) / 4;
     days += dayoffset[xt->tm_mon] + xt->tm_mday - 1;
     days -= 25508;              /* 1 jan 1970 is 25508 days since 1 mar 1900 */
-
     days = ((days * 24 + xt->tm_hour) * 60 + xt->tm_min) * 60 + xt->tm_sec;
 
     if (days < 0) {
         return APR_EBADDATE;
     }
-    days -= xt->tm_gmtoff;
-    *t = days * AP_USEC_PER_SEC + xt->tm_usec;
+    *t = days * APR_USEC_PER_SEC + xt->tm_usec;
     return APR_SUCCESS;
 }
 
-ap_status_t ap_get_os_imp_time(ap_os_imp_time_t **ostime, ap_time_t *aprtime)
+APR_DECLARE(apr_status_t) apr_time_exp_gmt_get(apr_time_t *t, 
+                                               apr_time_exp_t *xt)
 {
-    (*ostime)->tv_usec = *aprtime % AP_USEC_PER_SEC;
-    (*ostime)->tv_sec = *aprtime / AP_USEC_PER_SEC;
+    apr_status_t status = apr_time_exp_get(t, xt);
+    if (status == APR_SUCCESS)
+        *t -= (apr_time_t) xt->tm_gmtoff * APR_USEC_PER_SEC;
+    return status;
+}
+
+APR_DECLARE(apr_status_t) apr_os_imp_time_get(apr_os_imp_time_t **ostime,
+                                              apr_time_t *aprtime)
+{
+    (*ostime)->tv_usec = *aprtime % APR_USEC_PER_SEC;
+    (*ostime)->tv_sec = *aprtime / APR_USEC_PER_SEC;
     return APR_SUCCESS;
 }
 
-ap_status_t ap_get_os_exp_time(ap_os_exp_time_t **ostime, ap_exploded_time_t *aprtime)
+APR_DECLARE(apr_status_t) apr_os_exp_time_get(apr_os_exp_time_t **ostime,
+                                              apr_time_exp_t *aprtime)
 {
     (*ostime)->tm_sec  = aprtime->tm_sec;
     (*ostime)->tm_min  = aprtime->tm_min;
@@ -212,18 +193,27 @@ ap_status_t ap_get_os_exp_time(ap_os_exp_time_t **ostime, ap_exploded_time_t *ap
     (*ostime)->tm_wday = aprtime->tm_wday;
     (*ostime)->tm_yday = aprtime->tm_yday;
     (*ostime)->tm_isdst = aprtime->tm_isdst;
+
+#if defined(HAVE_STRUCT_TM_TM_GMTOFF)
+    (*ostime)->tm_gmtoff = aprtime->tm_gmtoff;
+#elif defined(HAVE_STRUCT_TM___TM_GMTOFF)
+    (*ostime)->__tm_gmtoff = aprtime->tm_gmtoff;
+#endif
+
     return APR_SUCCESS;
 }
 
-ap_status_t ap_put_os_imp_time(ap_time_t *aprtime, ap_os_imp_time_t **ostime,
-                               ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_os_imp_time_put(apr_time_t *aprtime,
+                                              apr_os_imp_time_t **ostime,
+                                              apr_pool_t *cont)
 {
-    *aprtime = (*ostime)->tv_sec * AP_USEC_PER_SEC + (*ostime)->tv_usec;
+    *aprtime = (*ostime)->tv_sec * APR_USEC_PER_SEC + (*ostime)->tv_usec;
     return APR_SUCCESS;
 }
 
-ap_status_t ap_put_os_exp_time(ap_exploded_time_t *aprtime,
-                               ap_os_exp_time_t **ostime, ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_os_exp_time_put(apr_time_exp_t *aprtime,
+                                              apr_os_exp_time_t **ostime,
+                                              apr_pool_t *cont)
 {
     aprtime->tm_sec = (*ostime)->tm_sec;
     aprtime->tm_min = (*ostime)->tm_min;
@@ -234,16 +224,36 @@ ap_status_t ap_put_os_exp_time(ap_exploded_time_t *aprtime,
     aprtime->tm_wday = (*ostime)->tm_wday;
     aprtime->tm_yday = (*ostime)->tm_yday;
     aprtime->tm_isdst = (*ostime)->tm_isdst;
-    return APR_SUCCESS;
-}
 
+#if defined(HAVE_STRUCT_TM_TM_GMTOFF)
+    aprtime->tm_gmtoff = (*ostime)->tm_gmtoff;
+#elif defined(HAVE_STRUCT_TM___TM_GMTOFF)
+    aprtime->tm_gmtoff = (*ostime)->__tm_gmtoff;
+#endif
 
+    return APR_SUCCESS;
+}
 
+APR_DECLARE(void) apr_sleep(apr_interval_time_t t)
+{
 #ifdef OS2
-#define INCL_DOS
-#include <os2.h>
+    DosSleep(t/1000);
+#elif defined(BEOS)
+    snooze(t);
+#elif defined(NETWARE)
+    delay(t/1000);
+#else
+    struct timeval tv;
+    tv.tv_usec = t % APR_USEC_PER_SEC;
+    tv.tv_sec = t / APR_USEC_PER_SEC;
+    select(0, NULL, NULL, NULL, &tv);
+#endif
+}
 
-ap_status_t ap_os2_time_to_ap_time(ap_time_t *result, FDATE os2date, FTIME os2time)
+#ifdef OS2
+APR_DECLARE(apr_status_t) apr_os2_time_to_apr_time(apr_time_t *result,
+                                                   FDATE os2date,
+                                                   FTIME os2time)
 {
   struct tm tmpdate;
 
@@ -257,7 +267,86 @@ ap_status_t ap_os2_time_to_ap_time(ap_time_t *result, FDATE os2date, FTIME os2ti
   tmpdate.tm_year  = os2date.year + 80;
   tmpdate.tm_isdst = -1;
 
-  *result = mktime(&tmpdate) * AP_USEC_PER_SEC;
+  *result = mktime(&tmpdate) * APR_USEC_PER_SEC;
   return APR_SUCCESS;
 }
+
+APR_DECLARE(apr_status_t) apr_apr_time_to_os2_time(FDATE *os2date,
+                                                   FTIME *os2time,
+                                                   apr_time_t aprtime)
+{
+    time_t ansitime = aprtime / APR_USEC_PER_SEC;
+    struct tm *lt;
+    lt = localtime(&ansitime);
+    os2time->hours    = lt->tm_hour;
+    os2time->minutes  = lt->tm_min;
+    os2time->twosecs  = lt->tm_sec / 2;
+
+    os2date->day      = lt->tm_mday;
+    os2date->month    = lt->tm_mon + 1;
+    os2date->year     = lt->tm_year - 80;
+    return APR_SUCCESS;
+}
+#endif
+
+#ifdef NETWARE
+APR_DECLARE(void) apr_netware_setup_time(void)
+{
+    tzset();
+    server_gmt_offset = -TZONE;
+}
+#else
+APR_DECLARE(void) apr_unix_setup_time(void)
+{
+#ifdef NO_GMTOFF_IN_STRUCT_TM
+    /* Precompute the offset from GMT on systems where it's not
+       in struct tm.
+
+       Note: This offset is normalized to be independent of daylight
+       savings time; if the calculation happens to be done in a
+       time/place where a daylight savings adjustment is in effect,
+       the returned offset has the same value that it would have
+       in the same location if daylight savings were not in effect.
+       The reason for this is that the returned offset can be
+       applied to a past or future timestamp in explode_time(),
+       so the DST adjustment obtained from the current time won't
+       necessarily be applicable.
+
+       mktime() is the inverse of localtime(); so, presumably,
+       passing in a struct tm made by gmtime() let's us calculate
+       the true GMT offset. However, there's a catch: if daylight
+       savings is in effect, gmtime()will set the tm_isdst field
+       and confuse mktime() into returning a time that's offset
+       by one hour. In that case, we must adjust the calculated GMT
+       offset.
+
+     */
+
+    struct timeval now;
+    time_t t1, t2;
+    struct tm t;
+
+    gettimeofday(&now, NULL);
+    t1 = now.tv_sec;
+    t2 = 0;
+
+#if APR_HAS_THREADS && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
+    gmtime_r(&t1, &t);
+#else
+    t = *gmtime(&t1);
+#endif
+    t.tm_isdst = 0; /* we know this GMT time isn't daylight-savings */
+    t2 = mktime(&t);
+    server_gmt_offset = (apr_int32_t) difftime(t1, t2);
+#endif /* NO_GMTOFF_IN_STRUCT_TM */
+}
+
 #endif
+
+/* A noop on all known Unix implementations */
+APR_DECLARE(void) apr_time_clock_hires(apr_pool_t *p)
+{
+    return;
+}
+
+
diff --git a/time/unix/timestr.c b/time/unix/timestr.c
index 889f4799734..f74febac192 100644
--- a/time/unix/timestr.c
+++ b/time/unix/timestr.c
@@ -1,83 +1,56 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "atime.h"
 #include "apr_portable.h"
-
+#include "apr_time.h"
+#include "apr_lib.h"
+#include "apr_private.h"
+/* System Headers required for time library */
+#if APR_HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+#if APR_HAVE_STRING_H
 #include <string.h>
+#endif
+/* End System Headers */
 
-API_VAR_EXPORT const char ap_month_snames[12][4] =
+APR_DECLARE_DATA const char apr_month_snames[12][4] =
 {
     "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
 };
-API_VAR_EXPORT const char ap_day_snames[7][4] =
+APR_DECLARE_DATA const char apr_day_snames[7][4] =
 {
     "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
 };
 
-ap_status_t ap_rfc822_date(char *date_str, ap_time_t t)
+apr_status_t apr_rfc822_date(char *date_str, apr_time_t t)
 {
-    ap_exploded_time_t xt;
+    apr_time_exp_t xt;
     const char *s;
     int real_year;
 
-    ap_explode_gmt(&xt, t);
+    apr_time_exp_gmt(&xt, t);
 
     /* example: "Sat, 08 Jan 2000 18:31:41 GMT" */
     /*           12345678901234567890123456789  */
 
-    s = &ap_day_snames[xt.tm_wday][0];
+    s = &apr_day_snames[xt.tm_wday][0];
     *date_str++ = *s++;
     *date_str++ = *s++;
     *date_str++ = *s++;
@@ -86,7 +59,7 @@ ap_status_t ap_rfc822_date(char *date_str, ap_time_t t)
     *date_str++ = xt.tm_mday / 10 + '0';
     *date_str++ = xt.tm_mday % 10 + '0';
     *date_str++ = ' ';
-    s = &ap_month_snames[xt.tm_mon][0];
+    s = &apr_month_snames[xt.tm_mon][0];
     *date_str++ = *s++;
     *date_str++ = *s++;
     *date_str++ = *s++;
@@ -114,22 +87,22 @@ ap_status_t ap_rfc822_date(char *date_str, ap_time_t t)
     return APR_SUCCESS;
 }
 
-ap_status_t ap_ctime(char *date_str, ap_time_t t)
+apr_status_t apr_ctime(char *date_str, apr_time_t t)
 {
-    ap_exploded_time_t xt;
+    apr_time_exp_t xt;
     const char *s;
     int real_year;
 
     /* example: "Wed Jun 30 21:49:08 1993" */
     /*           123456789012345678901234  */
 
-    ap_explode_localtime(&xt, t);
-    s = &ap_day_snames[xt.tm_wday][0];
+    apr_time_exp_lt(&xt, t);
+    s = &apr_day_snames[xt.tm_wday][0];
     *date_str++ = *s++;
     *date_str++ = *s++;
     *date_str++ = *s++;
     *date_str++ = ' ';
-    s = &ap_month_snames[xt.tm_mon][0];
+    s = &apr_month_snames[xt.tm_mon][0];
     *date_str++ = *s++;
     *date_str++ = *s++;
     *date_str++ = *s++;
@@ -156,11 +129,10 @@ ap_status_t ap_ctime(char *date_str, ap_time_t t)
     return APR_SUCCESS;
 }
 
-ap_status_t ap_strftime(char *s, ap_size_t *retsize, ap_size_t max, 
-                        const char *format, ap_exploded_time_t *xt)
+apr_status_t apr_strftime(char *s, apr_size_t *retsize, apr_size_t max, 
+                        const char *format, apr_time_exp_t *xt)
 {
     struct tm tm;
-
     memset(&tm, 0, sizeof tm);
     tm.tm_sec  = xt->tm_sec;
     tm.tm_min  = xt->tm_min;
@@ -171,6 +143,11 @@ ap_status_t ap_strftime(char *s, ap_size_t *retsize, ap_size_t max,
     tm.tm_wday = xt->tm_wday;
     tm.tm_yday = xt->tm_yday;
     tm.tm_isdst = xt->tm_isdst;
+#if defined(HAVE_STRUCT_TM_TM_GMTOFF)
+    tm.tm_gmtoff = xt->tm_gmtoff;
+#elif defined(HAVE_STRUCT_TM___TM_GMTOFF)
+    tm.__tm_gmtoff = xt->tm_gmtoff;
+#endif
     (*retsize) = strftime(s, max, format, &tm);
     return APR_SUCCESS;
 }
diff --git a/time/win32/access.c b/time/win32/access.c
deleted file mode 100644
index 7ec0e4ec7d2..00000000000
--- a/time/win32/access.c
+++ /dev/null
@@ -1,267 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "atime.h"
-#include "apr_time.h"
-#include "apr_general.h"
-#include "apr_lib.h"
-
-ap_status_t ap_get_curtime(struct atime_t *time, ap_time_t *rv)
-{
-    if (time) {
-        (*rv) = time->currtime;
-        return APR_SUCCESS;
-    }
-    return APR_ENOTIME;    
-}
-
-ap_status_t ap_get_sec(struct atime_t *time, ap_int32_t *rv)
-{
-    if (time) {
-        (*rv) = time->explodedtime->wSecond;
-        return APR_SUCCESS;
-    }
-    return APR_ENOTIME;
-}
-
-ap_status_t ap_get_min(struct atime_t *time, ap_int32_t *rv)
-{
-    if (time) {
-        (*rv) = time->explodedtime->wMinute;
-        return APR_SUCCESS;
-    }
-    return APR_ENOTIME;
-}
-
-ap_status_t ap_get_hour(struct atime_t *time, ap_int32_t *rv)
-{
-    if (time) {
-        (*rv) = time->explodedtime->wHour;
-        return APR_SUCCESS;
-    }
-    return APR_ENOTIME;
-}
-
-ap_status_t ap_get_mday(struct atime_t *time, ap_int32_t *rv)
-{
-    if (time) {
-        (*rv) = time->explodedtime->wDay;
-        return APR_SUCCESS;
-    }
-    return APR_ENOTIME;
-}
-
-ap_status_t ap_get_mon(struct atime_t *time, ap_int32_t *rv)
-{
-    if (time) {
-        (*rv) = time->explodedtime->wMonth;
-        return APR_SUCCESS;
-    }
-    return APR_ENOTIME;
-}
-
-ap_status_t ap_get_year(struct atime_t *time, ap_int32_t *rv)
-{
-    if (time) {
-        (*rv) = time->explodedtime->wYear;
-        return APR_SUCCESS;
-    }
-    return APR_ENOTIME;
-}
-
-ap_status_t ap_get_wday(struct atime_t *time, ap_int32_t *rv)
-{
-    if (time) {
-        (*rv) = time->explodedtime->wDayOfWeek;
-        return APR_SUCCESS;
-    }
-    return APR_ENOTIME;
-}
-
-ap_status_t ap_set_sec(struct atime_t *time, ap_int32_t value)
-{
-    if (!time) {
-        return APR_ENOTIME;
-    }
-    if (time->explodedtime == NULL) {
-        time->explodedtime = (SYSTEMTIME *)ap_pcalloc(time->cntxt, 
-                              sizeof(SYSTEMTIME));
-    }
-    if (time->explodedtime == NULL) {
-        return APR_ENOMEM;
-    }
-    time->explodedtime->wSecond = value;
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_set_min(struct atime_t *time, ap_int32_t value)
-{
-    if (!time) {
-        return APR_ENOTIME;
-    }
-    if (time->explodedtime == NULL) {
-        time->explodedtime = (SYSTEMTIME *)ap_pcalloc(time->cntxt, 
-                              sizeof(SYSTEMTIME));
-    }
-    if (time->explodedtime == NULL) {
-        return APR_ENOMEM;
-    }
-    time->explodedtime->wMinute = value;
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_set_hour(struct atime_t *time, ap_int32_t value)
-{
-    if (!time) {
-        return APR_ENOTIME;
-    }
-    if (time->explodedtime == NULL) {
-        time->explodedtime = (SYSTEMTIME *)ap_pcalloc(time->cntxt, 
-                              sizeof(SYSTEMTIME));
-    }
-    if (time->explodedtime == NULL) {
-        return APR_ENOMEM;
-    }
-    time->explodedtime->wHour = value;
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_set_mday(struct atime_t *time, ap_int32_t value)
-{
-    if (!time) {
-        return APR_ENOTIME;
-    }
-    if (time->explodedtime == NULL) {
-        time->explodedtime = (SYSTEMTIME *)ap_pcalloc(time->cntxt, 
-                              sizeof(SYSTEMTIME));
-    }
-    if (time->explodedtime == NULL) {
-        return APR_ENOMEM;
-    }
-    time->explodedtime->wDay = value;
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_set_mon(struct atime_t *time, ap_int32_t value)
-{
-    if (!time) {
-        return APR_ENOTIME;
-    }
-    if (time->explodedtime == NULL) {
-        time->explodedtime = (SYSTEMTIME *)ap_pcalloc(time->cntxt, 
-                              sizeof(SYSTEMTIME));
-    }
-    if (time->explodedtime == NULL) {
-        return APR_ENOMEM;
-    }
-    time->explodedtime->wMonth = value;
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_set_year(struct atime_t *time, ap_int32_t value)
-{
-    if (!time) {
-        return APR_ENOTIME;
-    }
-    if (time->explodedtime == NULL) {
-        time->explodedtime = (SYSTEMTIME *)ap_pcalloc(time->cntxt, 
-                              sizeof(SYSTEMTIME));
-    }
-    if (time->explodedtime == NULL) {
-        return APR_ENOMEM;
-    }
-    time->explodedtime->wYear = value;
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_set_wday(struct atime_t *time, ap_int32_t value)
-{
-    if (!time) {
-        return APR_ENOTIME;
-    }
-    if (time->explodedtime == NULL) {
-        time->explodedtime = (SYSTEMTIME *)ap_pcalloc(time->cntxt, 
-                              sizeof(SYSTEMTIME));
-    }
-    if (time->explodedtime == NULL) {
-        return APR_ENOMEM;
-    }
-    time->explodedtime->wDayOfWeek = value;
-    return APR_SUCCESS;
-}
-
-ap_status_t ap_get_timedata(struct atime_t *atime, char *key, void *data)
-{
-    if (atime != NULL) {
-        return ap_get_userdata(data, key, atime->cntxt);
-    }
-    else {
-        data = NULL;
-        return APR_ENOTIME;
-    }
-}
-
-ap_status_t ap_set_timedata(struct atime_t *atime, void *data, char *key,
-                            ap_status_t (*cleanup) (void *))
-{
-    if (atime != NULL) {
-        return ap_set_userdata(data, key, cleanup, atime->cntxt);
-    }
-    else {
-        data = NULL;
-        return APR_ENOTIME;
-    }
-}
-
-
diff --git a/time/win32/atime.h b/time/win32/atime.h
deleted file mode 100644
index cf5ab487386..00000000000
--- a/time/win32/atime.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef ATIME_H
-#define ATIME_H
-
-#include "apr_private.h"
-#include "apr_time.h"
-#include <time.h>
-
-struct atime_t {
-    ap_pool_t *cntxt;
-    ap_time_t currtime;
-    SYSTEMTIME *explodedtime;
-};
-    
-void FileTimeToAprTime(ap_time_t *atime, FILETIME *ft);
-void AprTimeToFileTime(LPFILETIME pft, ap_time_t t);
-
-#endif  /* ! ATIME_H */
-
diff --git a/time/win32/time.c b/time/win32/time.c
index 76d62de33e1..1a705443b2b 100644
--- a/time/win32/time.c
+++ b/time/win32/time.c
@@ -1,94 +1,65 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "atime.h"
+#include "apr_arch_atime.h"
 #include "apr_time.h"
 #include "apr_general.h"
 #include "apr_lib.h"
 #include "apr_portable.h"
+#if APR_HAVE_TIME_H
 #include <time.h>
+#endif
+#if APR_HAVE_ERRNO_H
 #include <errno.h>
+#endif
 #include <string.h>
 #include <winbase.h>
+#include "apr_arch_misc.h"
 
-/* Number of micro-seconds between the beginning of the Windows epoch
- * (Jan. 1, 1601) and the Unix epoch (Jan. 1, 1970) 
+/* Leap year is any year divisible by four, but not by 100 unless also
+ * divisible by 400
  */
-#define AP_DELTA_EPOCH_IN_USEC   11644473600000000;
+#define IsLeapYear(y) ((!(y % 4)) ? (((y % 400) && !(y % 100)) ? 0 : 1) : 0)
 
-void FileTimeToAprTime(ap_time_t *result, FILETIME *input)
+static DWORD get_local_timezone(TIME_ZONE_INFORMATION **tzresult)
 {
-    /* Convert FILETIME one 64 bit number so we can work with it. */
-    *result = input->dwHighDateTime;
-    *result = (*result) << 32;
-    *result |= input->dwLowDateTime;
-    *result /= 10;    /* Convert from 100 nano-sec periods to micro-seconds. */
-    *result -= AP_DELTA_EPOCH_IN_USEC;  /* Convert from Windows epoch to Unix epoch */
-    return;
-}
-void AprTimeToFileTime(LPFILETIME pft, ap_time_t t)
-{
-    LONGLONG ll;
-    t += AP_DELTA_EPOCH_IN_USEC;
-    ll = t * 10;
-    pft->dwLowDateTime = (DWORD)ll;
-    pft->dwHighDateTime = (DWORD) (ll >> 32);
-    return;
+    static TIME_ZONE_INFORMATION tz;
+    static DWORD result;
+    static int init = 0;
+
+    if (!init) {
+        result = GetTimeZoneInformation(&tz);
+        init = 1;
+    }
+
+    *tzresult = &tz;
+    return result;
 }
 
-void SystemTimeToAprExpTime(ap_exploded_time_t *xt, SYSTEMTIME *tm)
+static void SystemTimeToAprExpTime(apr_time_exp_t *xt, SYSTEMTIME *tm)
 {
+    static const int dayoffset[12] =
+    {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
+
+    if (tm->wMonth < 1 || tm->wMonth > 12)
+        return APR_EBADDATE;
+
+    /* Note; the caller is responsible for filling in detailed tm_usec,
+     * tm_gmtoff and tm_isdst data when applicable.
+     */
     xt->tm_usec = tm->wMilliseconds * 1000;
     xt->tm_sec  = tm->wSecond;
     xt->tm_min  = tm->wMinute;
@@ -97,63 +68,167 @@ void SystemTimeToAprExpTime(ap_exploded_time_t *xt, SYSTEMTIME *tm)
     xt->tm_mon  = tm->wMonth - 1;
     xt->tm_year = tm->wYear - 1900;
     xt->tm_wday = tm->wDayOfWeek;
-    xt->tm_yday = 0; /* ToDo: need to compute this */
-    xt->tm_isdst = 0; /* ToDo: need to compute this */
-    xt->tm_gmtoff = 0; /* ToDo: maybe the caller should set this explicitly */
-    return;
+    xt->tm_yday = dayoffset[xt->tm_mon] + (tm->wDay - 1);
+    xt->tm_isdst = 0;
+    xt->tm_gmtoff = 0;
+
+    /* If this is a leap year, and we're past the 28th of Feb. (the
+     * 58th day after Jan. 1), we'll increment our tm_yday by one.
+     */
+    if (IsLeapYear(tm->wYear) && (xt->tm_yday > 58))
+        xt->tm_yday++;
 }
 
-ap_status_t ap_ansi_time_to_ap_time(ap_time_t *result, time_t input)
+APR_DECLARE(apr_status_t) apr_time_ansi_put(apr_time_t *result, 
+                                                    time_t input)
 {
-    *result = (ap_time_t) input * AP_USEC_PER_SEC;
+    *result = (apr_time_t) input * APR_USEC_PER_SEC;
     return APR_SUCCESS;
 }
 
-/* Return micro-seconds since the Unix epoch (jan. 1, 1970) */
-ap_time_t ap_now(void)
+/* Return micro-seconds since the Unix epoch (jan. 1, 1970) UTC */
+APR_DECLARE(apr_time_t) apr_time_now(void)
 {
     LONGLONG aprtime = 0;
     FILETIME time;
+#ifndef _WIN32_WCE
     GetSystemTimeAsFileTime(&time);
+#else
+    SYSTEMTIME st;
+    GetSystemTime(&st);
+    SystemTimeToFileTime(&st, &time);
+#endif
     FileTimeToAprTime(&aprtime, &time);
     return aprtime; 
 }
 
-ap_status_t ap_explode_gmt(ap_exploded_time_t *result, ap_time_t input)
+APR_DECLARE(apr_status_t) apr_time_exp_gmt(apr_time_exp_t *result,
+                                           apr_time_t input)
 {
     FILETIME ft;
     SYSTEMTIME st;
     AprTimeToFileTime(&ft, input);
     FileTimeToSystemTime(&ft, &st);
+    /* The Platform SDK documents that SYSTEMTIME/FILETIME are
+     * generally UTC, so no timezone info needed
+     */
     SystemTimeToAprExpTime(result, &st);
-    result->tm_gmtoff = 0;
+    result->tm_usec = (apr_int32_t) (input % APR_USEC_PER_SEC);
     return APR_SUCCESS;
 }
 
-ap_status_t ap_explode_localtime(ap_exploded_time_t *result, ap_time_t input)
+APR_DECLARE(apr_status_t) apr_time_exp_tz(apr_time_exp_t *result, 
+                                          apr_time_t input, 
+                                          apr_int32_t offs)
+{
+    FILETIME ft;
+    SYSTEMTIME st;
+    AprTimeToFileTime(&ft, input + (offs *  APR_USEC_PER_SEC));
+    FileTimeToSystemTime(&ft, &st);
+    /* The Platform SDK documents that SYSTEMTIME/FILETIME are
+     * generally UTC, so we will simply note the offs used.
+     */
+    SystemTimeToAprExpTime(result, &st);
+    result->tm_usec = (apr_int32_t) (input % APR_USEC_PER_SEC);
+    result->tm_gmtoff = offs;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_time_exp_lt(apr_time_exp_t *result,
+                                          apr_time_t input)
 {
     SYSTEMTIME st;
     FILETIME ft, localft;
 
     AprTimeToFileTime(&ft, input);
-    FileTimeToLocalFileTime(&ft, &localft);
-    FileTimeToSystemTime(&localft, &st);
-    SystemTimeToAprExpTime(result, &st);
+
+#if APR_HAS_UNICODE_FS && !defined(_WIN32_WCE)
+    IF_WIN_OS_IS_UNICODE
+    {
+        TIME_ZONE_INFORMATION *tz;
+        SYSTEMTIME localst;
+        apr_time_t localtime;
+
+        get_local_timezone(&tz);
+
+        FileTimeToSystemTime(&ft, &st);
+
+        /* The Platform SDK documents that SYSTEMTIME/FILETIME are
+         * generally UTC.  We use SystemTimeToTzSpecificLocalTime
+         * because FileTimeToLocalFileFime is documented that the
+         * resulting time local file time would have DST relative
+         * to the *present* date, not the date converted.
+         */
+        SystemTimeToTzSpecificLocalTime(tz, &st, &localst);
+        SystemTimeToAprExpTime(result, &localst);
+        result->tm_usec = (apr_int32_t) (input % APR_USEC_PER_SEC);
+
+
+        /* Recover the resulting time as an apr time and use the
+         * delta for gmtoff in seconds (and ignore msec rounding) 
+         */
+        SystemTimeToFileTime(&localst, &localft);
+        FileTimeToAprTime(&localtime, &localft);
+        result->tm_gmtoff = (int)apr_time_sec(localtime) 
+                          - (int)apr_time_sec(input);
+
+        /* To compute the dst flag, we compare the expected 
+         * local (standard) timezone bias to the delta.
+         * [Note, in war time or double daylight time the
+         * resulting tm_isdst is, desireably, 2 hours]
+         */
+        result->tm_isdst = (result->tm_gmtoff / 3600)
+                         - (-(tz->Bias + tz->StandardBias) / 60);
+    }
+#endif
+#if APR_HAS_ANSI_FS || defined(_WIN32_WCE)
+    ELSE_WIN_OS_IS_ANSI
+    {
+        TIME_ZONE_INFORMATION tz;
+	/* XXX: This code is simply *wrong*.  The time converted will always
+         * map to the *now current* status of daylight savings time.
+         */
+
+        FileTimeToLocalFileTime(&ft, &localft);
+        FileTimeToSystemTime(&localft, &st);
+        SystemTimeToAprExpTime(result, &st);
+        result->tm_usec = (apr_int32_t) (input % APR_USEC_PER_SEC);
+
+        switch (GetTimeZoneInformation(&tz)) {
+            case TIME_ZONE_ID_UNKNOWN:
+                result->tm_isdst = 0;
+                /* Bias = UTC - local time in minutes
+                 * tm_gmtoff is seconds east of UTC
+                 */
+                result->tm_gmtoff = tz.Bias * -60;
+                break;
+            case TIME_ZONE_ID_STANDARD:
+                result->tm_isdst = 0;
+                result->tm_gmtoff = (tz.Bias + tz.StandardBias) * -60;
+                break;
+            case TIME_ZONE_ID_DAYLIGHT:
+                result->tm_isdst = 1;
+                result->tm_gmtoff = (tz.Bias + tz.DaylightBias) * -60;
+                break;
+            default:
+                /* noop */;
+        }
+    }
+#endif
+
     return APR_SUCCESS;
 }
 
-ap_status_t ap_implode_time(ap_time_t *t, ap_exploded_time_t *xt)
+APR_DECLARE(apr_status_t) apr_time_exp_get(apr_time_t *t,
+                                           apr_time_exp_t *xt)
 {
-    int year;
-    time_t days;
+    apr_time_t year = xt->tm_year;
+    apr_time_t days;
     static const int dayoffset[12] =
     {306, 337, 0, 31, 61, 92, 122, 153, 184, 214, 245, 275};
 
-    year = xt->tm_year;
-
-    if (year < 70 || ((sizeof(time_t) <= 4) && (year >= 138))) {
+    if (xt->tm_mon < 0 || xt->tm_mon >= 12)
         return APR_EBADDATE;
-    }
 
     /* shift new year to 1st March in order to make leap year calc easy */
 
@@ -171,19 +246,29 @@ ap_status_t ap_implode_time(ap_time_t *t, ap_exploded_time_t *xt)
     if (days < 0) {
         return APR_EBADDATE;
     }
-    days -= xt->tm_gmtoff;
-    *t = days * AP_USEC_PER_SEC + xt->tm_usec;
+    *t = days * APR_USEC_PER_SEC + xt->tm_usec;
     return APR_SUCCESS;
 }
 
-ap_status_t ap_get_os_imp_time(ap_os_imp_time_t **ostime, ap_time_t *aprtime)
+APR_DECLARE(apr_status_t) apr_time_exp_gmt_get(apr_time_t *t,
+                                               apr_time_exp_t *xt)
+{
+    apr_status_t status = apr_time_exp_get(t, xt);
+    if (status == APR_SUCCESS)
+        *t -= (apr_time_t) xt->tm_gmtoff * APR_USEC_PER_SEC;
+    return status;
+}
+
+APR_DECLARE(apr_status_t) apr_os_imp_time_get(apr_os_imp_time_t **ostime,
+                                              apr_time_t *aprtime)
 {
-    /* TODO: Consider not passing in pointer to ap_time_t (e.g., call by value) */
+    /* TODO: Consider not passing in pointer to apr_time_t (e.g., call by value) */
     AprTimeToFileTime(*ostime, *aprtime);
     return APR_SUCCESS;
 }
 
-ap_status_t ap_get_os_exp_time(ap_os_exp_time_t **ostime, ap_exploded_time_t *aprexptime)
+APR_DECLARE(apr_status_t) apr_os_exp_time_get(apr_os_exp_time_t **ostime, 
+                                              apr_time_exp_t *aprexptime)
 {
     (*ostime)->wYear = aprexptime->tm_year + 1900;
     (*ostime)->wMonth = aprexptime->tm_mon + 1;
@@ -196,17 +281,59 @@ ap_status_t ap_get_os_exp_time(ap_os_exp_time_t **ostime, ap_exploded_time_t *ap
     return APR_SUCCESS;
 }
 
-ap_status_t ap_put_os_imp_time(ap_time_t *aprtime, ap_os_imp_time_t **ostime,
-                               ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_os_imp_time_put(apr_time_t *aprtime,
+                                              apr_os_imp_time_t **ostime,
+                                              apr_pool_t *cont)
 {
+    /* XXX: sanity failure, what is file time, gmt or local ?
+     */
     FileTimeToAprTime(aprtime, *ostime);
     return APR_SUCCESS;
 }
 
-ap_status_t ap_put_os_exp_time(ap_exploded_time_t *aprtime,
-                               ap_os_exp_time_t **ostime, ap_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_os_exp_time_put(apr_time_exp_t *aprtime,
+                                              apr_os_exp_time_t **ostime,
+                                              apr_pool_t *cont)
 {
+    /* The Platform SDK documents that SYSTEMTIME/FILETIME are
+     * generally UTC, so no timezone info needed
+     */
     SystemTimeToAprExpTime(aprtime, *ostime);
     return APR_SUCCESS;
 }
 
+APR_DECLARE(void) apr_sleep(apr_interval_time_t t)
+{
+    /* One of the few sane situations for a cast, Sleep
+     * is in ms, not us, and passed as a DWORD value
+     */
+    Sleep((DWORD)(t / 1000));
+}
+
+#if defined(_WIN32_WCE)
+/* A noop on WinCE, like Unix implementation */
+APR_DECLARE(void) apr_time_clock_hires(apr_pool_t *p)
+{
+    return;
+}
+#else
+static apr_status_t clock_restore(void *unsetres)
+{
+    ULONG newRes;
+    SetTimerResolution((ULONG)(apr_ssize_t)unsetres, FALSE, &newRes);
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(void) apr_time_clock_hires(apr_pool_t *p)
+{
+    ULONG newRes;
+    /* Timer resolution is stated in 100ns units.  Note that TRUE requests the
+     * new clock resolution, FALSE above releases the request.
+     */
+    if (SetTimerResolution(10000, TRUE, &newRes) == 0 /* STATUS_SUCCESS */) {
+        /* register the cleanup... */
+        apr_pool_cleanup_register(p, (void*)10000, clock_restore,
+                                  apr_pool_cleanup_null);
+    }
+}
+#endif
diff --git a/time/win32/timestr.c b/time/win32/timestr.c
index 099fc1448a4..13841235218 100644
--- a/time/win32/timestr.c
+++ b/time/win32/timestr.c
@@ -1,81 +1,48 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* 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
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
- * reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * 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 "atime.h"
+#include "apr_arch_atime.h"
 #include "apr_portable.h"
+#include "apr_strings.h"
+
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
 
-API_VAR_EXPORT const char ap_month_snames[12][4] =
+APR_DECLARE_DATA const char apr_month_snames[12][4] =
 {
     "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
 };
-API_VAR_EXPORT const char ap_day_snames[7][4] =
+APR_DECLARE_DATA const char apr_day_snames[7][4] =
 {
     "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
 };
 
-ap_status_t ap_rfc822_date(char *date_str, ap_time_t t)
+APR_DECLARE(apr_status_t) apr_rfc822_date(char *date_str, apr_time_t t)
 {
-    ap_exploded_time_t xt;
+    apr_time_exp_t xt;
     const char *s;
     int real_year;
 
-    ap_explode_gmt(&xt, t);
+    apr_time_exp_gmt(&xt, t);
 
     /* example: "Sat, 08 Jan 2000 18:31:41 GMT" */
     /*           12345678901234567890123456789  */
 
-    s = &ap_day_snames[xt.tm_wday][0];
+    s = &apr_day_snames[xt.tm_wday][0];
     *date_str++ = *s++;
     *date_str++ = *s++;
     *date_str++ = *s++;
@@ -84,7 +51,7 @@ ap_status_t ap_rfc822_date(char *date_str, ap_time_t t)
     *date_str++ = xt.tm_mday / 10 + '0';
     *date_str++ = xt.tm_mday % 10 + '0';
     *date_str++ = ' ';
-    s = &ap_month_snames[xt.tm_mon][0];
+    s = &apr_month_snames[xt.tm_mon][0];
     *date_str++ = *s++;
     *date_str++ = *s++;
     *date_str++ = *s++;
@@ -112,22 +79,22 @@ ap_status_t ap_rfc822_date(char *date_str, ap_time_t t)
     return APR_SUCCESS;
 }
 
-ap_status_t ap_ctime(char *date_str, ap_time_t t)
+APR_DECLARE(apr_status_t) apr_ctime(char *date_str, apr_time_t t)
 {
-    ap_exploded_time_t xt;
+    apr_time_exp_t xt;
     const char *s;
     int real_year;
 
     /* example: "Wed Jun 30 21:49:08 1993" */
     /*           123456789012345678901234  */
 
-    ap_explode_localtime(&xt, t);
-    s = &ap_day_snames[xt.tm_wday][0];
+    apr_time_exp_lt(&xt, t);
+    s = &apr_day_snames[xt.tm_wday][0];
     *date_str++ = *s++;
     *date_str++ = *s++;
     *date_str++ = *s++;
     *date_str++ = ' ';
-    s = &ap_month_snames[xt.tm_mon][0];
+    s = &apr_month_snames[xt.tm_mon][0];
     *date_str++ = *s++;
     *date_str++ = *s++;
     *date_str++ = *s++;
@@ -154,9 +121,88 @@ ap_status_t ap_ctime(char *date_str, ap_time_t t)
     return APR_SUCCESS;
 }
 
-ap_status_t ap_strftime(char *s, ap_size_t *retsize, ap_size_t max, 
-                        const char *format, ap_exploded_time_t *xt)
+
+#ifndef _WIN32_WCE
+
+static apr_size_t win32_strftime_extra(char *s, size_t max, const char *format,
+                                       const struct tm *tm) 
+{
+   /* If the new format string is bigger than max, the result string won't fit
+    * anyway. If format strings are added, made sure the padding below is
+    * enough */
+    char *new_format = (char *) malloc(max + 11);
+    size_t i, j, format_length = strlen(format);
+    apr_size_t return_value;
+    int length_written;
+
+    for (i = 0, j = 0; (i < format_length && j < max);) {
+        if (format[i] != '%') {
+            new_format[j++] = format[i++];
+            continue;
+        }
+        switch (format[i+1]) {
+            case 'C':
+                length_written = apr_snprintf(new_format + j, max - j, "%2d",
+                    (tm->tm_year + 1970)/100);
+                j = (length_written == -1) ? max : (j + length_written);
+                i += 2;
+                break;
+            case 'D':
+                /* Is this locale dependent? Shouldn't be...
+                   Also note the year 2000 exposure here */
+                memcpy(new_format + j, "%m/%d/%y", 8);
+                i += 2;
+                j += 8;
+                break;
+            case 'r':
+                memcpy(new_format + j, "%I:%M:%S %p", 11);
+                i += 2;
+                j += 11;
+                break;
+            case 'R':
+                memcpy(new_format + j, "%H:%M", 5);
+                i += 2;
+                j += 5;
+                break;
+            case 'T':
+                memcpy(new_format + j, "%H:%M:%S", 8);
+                i += 2;
+                j += 8;
+                break;
+            case 'e':
+                length_written = apr_snprintf(new_format + j, max - j, "%2d",
+                    tm->tm_mday);
+                j = (length_written == -1) ? max : (j + length_written);
+                i += 2;
+                break;
+            default:
+                /* We know we can advance two characters forward here. Also
+                 * makes sure that %% is preserved. */
+                new_format[j++] = format[i++];
+                new_format[j++] = format[i++];
+        }
+    }
+    if (j >= max) {
+        *s = '\0';  /* Defensive programming, okay since output is undefined*/
+        return_value = 0;
+    } else {
+        new_format[j] = '\0';
+        return_value = strftime(s, max, new_format, tm);
+    }
+    free(new_format);
+    return return_value;
+}
+
+#endif
+
+
+APR_DECLARE(apr_status_t) apr_strftime(char *s, apr_size_t *retsize,
+                                       apr_size_t max, const char *format,
+                                       apr_time_exp_t *xt)
 {
+#ifdef _WIN32_WCE
+    return APR_ENOTIMPL;
+#else
     struct tm tm;
     memset(&tm, 0, sizeof tm);
     tm.tm_sec  = xt->tm_sec;
@@ -168,6 +214,7 @@ ap_status_t ap_strftime(char *s, ap_size_t *retsize, ap_size_t max,
     tm.tm_wday = xt->tm_wday;
     tm.tm_yday = xt->tm_yday;
     tm.tm_isdst = xt->tm_isdst;
-    (*retsize) = strftime(s, max, format, &tm);
+    (*retsize) = win32_strftime_extra(s, max, format, &tm);
     return APR_SUCCESS;
+#endif
 }
diff --git a/tools/gen_test_char.c b/tools/gen_test_char.c
new file mode 100644
index 00000000000..c48d2cbe743
--- /dev/null
+++ b/tools/gen_test_char.c
@@ -0,0 +1,131 @@
+/* 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.
+ */
+
+#if defined(WIN32) || defined(OS2)
+#define NEED_ENHANCED_ESCAPES
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+
+/* A bunch of functions in util.c scan strings looking for certain characters.
+ * To make that more efficient we encode a lookup table.
+ */
+#define T_ESCAPE_SHELL_CMD    (0x01)
+#define T_ESCAPE_PATH_SEGMENT (0x02)
+#define T_OS_ESCAPE_PATH      (0x04)
+#define T_ESCAPE_ECHO         (0x08)
+#define T_ESCAPE_URLENCODED   (0x10)
+#define T_ESCAPE_XML          (0x20)
+#define T_ESCAPE_LDAP_DN      (0x40)
+#define T_ESCAPE_LDAP_FILTER  (0x80)
+
+int main(int argc, char *argv[])
+{
+    unsigned c;
+    unsigned char flags;
+
+    printf("/* this file is automatically generated by gen_test_char, "
+           "do not edit. \"make include/private/apr_escape_test_char.h\" to regenerate. */\n"
+           "#define T_ESCAPE_SHELL_CMD     (%u)\n"
+           "#define T_ESCAPE_PATH_SEGMENT  (%u)\n"
+           "#define T_OS_ESCAPE_PATH       (%u)\n"
+           "#define T_ESCAPE_ECHO          (%u)\n"
+           "#define T_ESCAPE_URLENCODED    (%u)\n"
+           "#define T_ESCAPE_XML           (%u)\n"
+           "#define T_ESCAPE_LDAP_DN       (%u)\n"
+           "#define T_ESCAPE_LDAP_FILTER   (%u)\n"
+           "\n"
+           "static const unsigned char test_char_table[256] = {",
+           T_ESCAPE_SHELL_CMD,
+           T_ESCAPE_PATH_SEGMENT,
+           T_OS_ESCAPE_PATH,
+           T_ESCAPE_ECHO,
+           T_ESCAPE_URLENCODED,
+           T_ESCAPE_XML,
+           T_ESCAPE_LDAP_DN,
+           T_ESCAPE_LDAP_FILTER);
+
+    for (c = 0; c < 256; ++c) {
+        flags = 0;
+        if (c % 20 == 0)
+            printf("\n    ");
+
+        /* escape_shell_cmd */
+#ifdef NEED_ENHANCED_ESCAPES
+        /* Win32/OS2 have many of the same vulnerable characters
+         * as Unix sh, plus the carriage return and percent char.
+         * The proper escaping of these characters varies from unix
+         * since Win32/OS2 use carets or doubled-double quotes,
+         * and neither lf nor cr can be escaped.  We escape unix
+         * specific as well, to assure that cross-compiled unix
+         * applications behave similiarly when invoked on win32/os2.
+         *
+         * Rem please keep in-sync with apr's list in win32/filesys.c
+         */
+        if (c && strchr("&;`'\"|*?~<>^()[]{}$\\\n\r%", c)) {
+            flags |= T_ESCAPE_SHELL_CMD;
+        }
+#else
+        if (c && strchr("&;`'\"|*?~<>^()[]{}$\\\n", c)) {
+            flags |= T_ESCAPE_SHELL_CMD;
+        }
+#endif
+
+        if (!isalnum(c) && !strchr("$-_.+!*'(),:@&=~", c)) {
+            flags |= T_ESCAPE_PATH_SEGMENT;
+        }
+
+        if (!isalnum(c) && !strchr("$-_.+!*'(),:@&=/~", c)) {
+            flags |= T_OS_ESCAPE_PATH;
+        }
+
+        if (!isalnum(c) && !strchr(".-*_ ", c)) {
+            flags |= T_ESCAPE_URLENCODED;
+        }
+
+        /* For logging, escape all control characters,
+         * double quotes (because they delimit the request in the log file)
+         * backslashes (because we use backslash for escaping)
+         * and 8-bit chars with the high bit set
+         */
+        if (c && (!isprint(c) || c == '"' || c == '\\' || iscntrl(c))) {
+            flags |= T_ESCAPE_ECHO;
+        }
+
+        if (strchr("<>&\"", c)) {
+            flags |= T_ESCAPE_XML;
+        }
+
+        /* LDAP DN escaping (RFC4514) */
+        if (!isprint(c) || strchr("\"+,;<>\\", c)) {
+            flags |= T_ESCAPE_LDAP_DN;
+        }
+
+        /* LDAP filter escaping (RFC4515) */
+        if (!isprint(c) || strchr("*()\\", c)) {
+            flags |= T_ESCAPE_LDAP_FILTER;
+        }
+
+        printf("%u%c", flags, (c < 255) ? ',' : ' ');
+    }
+
+    printf("\n};\n");
+
+    return 0;
+}
diff --git a/uri/apr_uri.c b/uri/apr_uri.c
new file mode 100644
index 00000000000..8b22d462f9f
--- /dev/null
+++ b/uri/apr_uri.c
@@ -0,0 +1,962 @@
+/* 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.
+ */
+
+/*
+ * apr_uri.c: URI related utility things
+ * 
+ */
+
+#include <stdlib.h>
+
+#include "apu.h"
+#include "apr.h"
+#include "apr_general.h"
+#include "apr_strings.h"
+
+#define APR_WANT_STRFUNC
+#include "apr_want.h"
+
+#include "apr_uri.h"
+
+typedef struct schemes_t schemes_t;
+
+/** Structure to store various schemes and their default ports */
+struct schemes_t {
+    /** The name of the scheme */
+    const char *name;
+    /** The default port for the scheme */
+    apr_port_t default_port;
+};
+
+/* Some WWW schemes and their default ports; this is basically /etc/services */
+/* This will become global when the protocol abstraction comes */
+/* As the schemes are searched by a linear search, */
+/* they are sorted by their expected frequency */
+static schemes_t schemes[] =
+{
+    {"http",     APR_URI_HTTP_DEFAULT_PORT},
+    {"ftp",      APR_URI_FTP_DEFAULT_PORT},
+    {"https",    APR_URI_HTTPS_DEFAULT_PORT},
+    {"gopher",   APR_URI_GOPHER_DEFAULT_PORT},
+    {"ldap",     APR_URI_LDAP_DEFAULT_PORT},
+    {"nntp",     APR_URI_NNTP_DEFAULT_PORT},
+    {"snews",    APR_URI_SNEWS_DEFAULT_PORT},
+    {"imap",     APR_URI_IMAP_DEFAULT_PORT},
+    {"pop",      APR_URI_POP_DEFAULT_PORT},
+    {"sip",      APR_URI_SIP_DEFAULT_PORT},
+    {"rtsp",     APR_URI_RTSP_DEFAULT_PORT},
+    {"wais",     APR_URI_WAIS_DEFAULT_PORT},
+    {"z39.50r",  APR_URI_WAIS_DEFAULT_PORT},
+    {"z39.50s",  APR_URI_WAIS_DEFAULT_PORT},
+    {"prospero", APR_URI_PROSPERO_DEFAULT_PORT},
+    {"nfs",      APR_URI_NFS_DEFAULT_PORT},
+    {"tip",      APR_URI_TIP_DEFAULT_PORT},
+    {"acap",     APR_URI_ACAP_DEFAULT_PORT},
+    {"telnet",   APR_URI_TELNET_DEFAULT_PORT},
+    {"ssh",      APR_URI_SSH_DEFAULT_PORT},
+    { NULL, 0xFFFF }     /* unknown port */
+};
+
+APR_DECLARE(apr_port_t) apr_uri_port_of_scheme(const char *scheme_str)
+{
+    schemes_t *scheme;
+
+    if (scheme_str) {
+        for (scheme = schemes; scheme->name != NULL; ++scheme) {
+            if (strcasecmp(scheme_str, scheme->name) == 0) {
+                return scheme->default_port;
+            }
+        }
+    }
+    return 0;
+}
+
+/* Unparse a apr_uri_t structure to an URI string.
+ * Optionally suppress the password for security reasons.
+ */
+APR_DECLARE(char *) apr_uri_unparse(apr_pool_t *p, 
+                                    const apr_uri_t *uptr, 
+                                    unsigned flags)
+{
+    char *ret = "";
+
+    /* If suppressing the site part, omit both user name & scheme://hostname */
+    if (!(flags & APR_URI_UNP_OMITSITEPART)) {
+
+        /* Construct a "user:password@" string, honoring the passed
+         * APR_URI_UNP_ flags: */
+        if (uptr->user || uptr->password) {
+            ret = apr_pstrcat(p,
+                      (uptr->user     && !(flags & APR_URI_UNP_OMITUSER))
+                          ? uptr->user : "",
+                      (uptr->password && !(flags & APR_URI_UNP_OMITPASSWORD))
+                          ? ":" : "",
+                      (uptr->password && !(flags & APR_URI_UNP_OMITPASSWORD))
+                          ? ((flags & APR_URI_UNP_REVEALPASSWORD)
+                              ? uptr->password : "XXXXXXXX")
+                          : "",
+                      ((uptr->user     && !(flags & APR_URI_UNP_OMITUSER)) ||
+                       (uptr->password && !(flags & APR_URI_UNP_OMITPASSWORD)))
+                          ? "@" : "", 
+                      NULL);
+        }
+
+        /* Construct scheme://site string */
+        if (uptr->hostname) {
+            int is_default_port;
+            const char *lbrk = "", *rbrk = "";
+
+            if (strchr(uptr->hostname, ':')) { /* v6 literal */
+                lbrk = "[";
+                rbrk = "]";
+            }
+
+            is_default_port =
+                (uptr->port_str == NULL ||
+                 uptr->port == 0 ||
+                 uptr->port == apr_uri_port_of_scheme(uptr->scheme));
+
+            ret = apr_pstrcat(p, "//", ret, lbrk, uptr->hostname, rbrk,
+                        is_default_port ? "" : ":",
+                        is_default_port ? "" : uptr->port_str,
+                        NULL);
+        }
+	if (uptr->scheme) {
+	    ret = apr_pstrcat(p, uptr->scheme, ":", ret, NULL);
+	}
+    }
+    
+    /* Should we suppress all path info? */
+    if (!(flags & APR_URI_UNP_OMITPATHINFO)) {
+        /* Append path, query and fragment strings: */
+        ret = apr_pstrcat(p,
+                          ret,
+                          (uptr->path)
+                              ? uptr->path : "",
+                          (uptr->query    && !(flags & APR_URI_UNP_OMITQUERY))
+                              ? "?" : "",
+                          (uptr->query    && !(flags & APR_URI_UNP_OMITQUERY))
+                              ? uptr->query : "",
+                          (uptr->fragment && !(flags & APR_URI_UNP_OMITQUERY))
+                              ? "#" : NULL,
+                          (uptr->fragment && !(flags & APR_URI_UNP_OMITQUERY))
+                              ? uptr->fragment : NULL,
+                          NULL);
+    }
+    return ret;
+}
+
+/* Here is the hand-optimized parse_uri_components().  There are some wild
+ * tricks we could pull in assembly language that we don't pull here... like we
+ * can do word-at-time scans for delimiter characters using the same technique
+ * that fast memchr()s use.  But that would be way non-portable. -djg
+ */
+
+/* We have a apr_table_t that we can index by character and it tells us if the
+ * character is one of the interesting delimiters.  Note that we even get
+ * compares for NUL for free -- it's just another delimiter.
+ */
+
+#define T_SLASH           0x01        /* '/' */
+#define T_QUESTION        0x02        /* '?' */
+#define T_HASH            0x04        /* '#' */
+#define T_ALPHA           0x08        /* 'A' ... 'Z', 'a' ... 'z' */
+#define T_SCHEME          0x10        /* '0' ... '9', '-', '+', '.'
+                                       * (allowed in scheme except first char)
+                                       */
+#define T_NUL             0x80        /* '\0' */
+
+#if APR_CHARSET_EBCDIC
+/* Delimiter table for the EBCDIC character set */
+static const unsigned char uri_delims[256] = {
+    T_NUL,                      /* 0x00     */
+    0,                          /* 0x01     */
+    0,                          /* 0x02     */
+    0,                          /* 0x03     */
+    0,                          /* 0x04     */
+    0,                          /* 0x05     */
+    0,                          /* 0x06     */
+    0,                          /* 0x07     */
+    0,                          /* 0x08     */
+    0,                          /* 0x09     */
+    0,                          /* 0x0a     */
+    0,                          /* 0x0b     */
+    0,                          /* 0x0c     */
+    0,                          /* 0x0d     */
+    0,                          /* 0x0e     */
+    0,                          /* 0x0f     */
+    0,                          /* 0x10     */
+    0,                          /* 0x11     */
+    0,                          /* 0x12     */
+    0,                          /* 0x13     */
+    0,                          /* 0x14     */
+    0,                          /* 0x15     */
+    0,                          /* 0x16     */
+    0,                          /* 0x17     */
+    0,                          /* 0x18     */
+    0,                          /* 0x19     */
+    0,                          /* 0x1a     */
+    0,                          /* 0x1b     */
+    0,                          /* 0x1c     */
+    0,                          /* 0x1d     */
+    0,                          /* 0x1e     */
+    0,                          /* 0x1f     */
+    0,                          /* 0x20     */
+    0,                          /* 0x21     */
+    0,                          /* 0x22     */
+    0,                          /* 0x23     */
+    0,                          /* 0x24     */
+    0,                          /* 0x25     */
+    0,                          /* 0x26     */
+    0,                          /* 0x27     */
+    0,                          /* 0x28     */
+    0,                          /* 0x29     */
+    0,                          /* 0x2a     */
+    0,                          /* 0x2b     */
+    0,                          /* 0x2c     */
+    0,                          /* 0x2d     */
+    0,                          /* 0x2e     */
+    0,                          /* 0x2f     */
+    0,                          /* 0x30     */
+    0,                          /* 0x31     */
+    0,                          /* 0x32     */
+    0,                          /* 0x33     */
+    0,                          /* 0x34     */
+    0,                          /* 0x35     */
+    0,                          /* 0x36     */
+    0,                          /* 0x37     */
+    0,                          /* 0x38     */
+    0,                          /* 0x39     */
+    0,                          /* 0x3a     */
+    0,                          /* 0x3b     */
+    0,                          /* 0x3c     */
+    0,                          /* 0x3d     */
+    0,                          /* 0x3e     */
+    0,                          /* 0x3f     */
+    0,                          /* 0x40 ' ' */
+    0,                          /* 0x41     */
+    0,                          /* 0x42     */
+    0,                          /* 0x43     */
+    0,                          /* 0x44     */
+    0,                          /* 0x45     */
+    0,                          /* 0x46     */
+    0,                          /* 0x47     */
+    0,                          /* 0x48     */
+    0,                          /* 0x49     */
+    0,                          /* 0x4a '[' */
+    T_SCHEME,                   /* 0x4b '.' */
+    0,                          /* 0x4c '<' */
+    0,                          /* 0x4d '(' */
+    T_SCHEME,                   /* 0x4e '+' */
+    0,                          /* 0x4f '!' */
+    0,                          /* 0x50 '&' */
+    0,                          /* 0x51     */
+    0,                          /* 0x52     */
+    0,                          /* 0x53     */
+    0,                          /* 0x54     */
+    0,                          /* 0x55     */
+    0,                          /* 0x56     */
+    0,                          /* 0x57     */
+    0,                          /* 0x58     */
+    0,                          /* 0x59     */
+    0,                          /* 0x5a ']' */
+    0,                          /* 0x5b '$' */
+    0,                          /* 0x5c '*' */
+    0,                          /* 0x5d ')' */
+    0,                          /* 0x5e ';' */
+    0,                          /* 0x5f '^' */
+    T_SCHEME,                   /* 0x60 '-' */
+    T_SLASH,                    /* 0x61 '/' */
+    0,                          /* 0x62     */
+    0,                          /* 0x63     */
+    0,                          /* 0x64     */
+    0,                          /* 0x65     */
+    0,                          /* 0x66     */
+    0,                          /* 0x67     */
+    0,                          /* 0x68     */
+    0,                          /* 0x69     */
+    0,                          /* 0x6a '|' */
+    0,                          /* 0x6b ',' */
+    0,                          /* 0x6c '%' */
+    0,                          /* 0x6d '_' */
+    0,                          /* 0x6e '>' */
+    T_QUESTION,                 /* 0x6f '?' */
+    0,                          /* 0x70     */
+    0,                          /* 0x71     */
+    0,                          /* 0x72     */
+    0,                          /* 0x73     */
+    0,                          /* 0x74     */
+    0,                          /* 0x75     */
+    0,                          /* 0x76     */
+    0,                          /* 0x77     */
+    0,                          /* 0x78     */
+    0,                          /* 0x79 '`' */
+    0,                          /* 0x7a ':' */
+    T_HASH,                     /* 0x7b '#' */
+    0,                          /* 0x7c '@' */
+    0,                          /* 0x7d ''' */
+    0,                          /* 0x7e '=' */
+    0,                          /* 0x7f '"' */
+    0,                          /* 0x80     */
+    T_ALPHA,                    /* 0x81 'a' */
+    T_ALPHA,                    /* 0x82 'b' */
+    T_ALPHA,                    /* 0x83 'c' */
+    T_ALPHA,                    /* 0x84 'd' */
+    T_ALPHA,                    /* 0x85 'e' */
+    T_ALPHA,                    /* 0x86 'f' */
+    T_ALPHA,                    /* 0x87 'g' */
+    T_ALPHA,                    /* 0x88 'h' */
+    T_ALPHA,                    /* 0x89 'i' */
+    0,                          /* 0x8a     */
+    0,                          /* 0x8b     */
+    0,                          /* 0x8c     */
+    0,                          /* 0x8d     */
+    0,                          /* 0x8e     */
+    0,                          /* 0x8f     */
+    0,                          /* 0x90     */
+    T_ALPHA,                    /* 0x91 'j' */
+    T_ALPHA,                    /* 0x92 'k' */
+    T_ALPHA,                    /* 0x93 'l' */
+    T_ALPHA,                    /* 0x94 'm' */
+    T_ALPHA,                    /* 0x95 'n' */
+    T_ALPHA,                    /* 0x96 'o' */
+    T_ALPHA,                    /* 0x97 'p' */
+    T_ALPHA,                    /* 0x98 'q' */
+    T_ALPHA,                    /* 0x99 'r' */
+    0,                          /* 0x9a     */
+    0,                          /* 0x9b     */
+    0,                          /* 0x9c     */
+    0,                          /* 0x9d     */
+    0,                          /* 0x9e     */
+    0,                          /* 0x9f     */
+    0,                          /* 0xa0     */
+    0,                          /* 0xa1 '~' */
+    T_ALPHA,                    /* 0xa2 's' */
+    T_ALPHA,                    /* 0xa3 't' */
+    T_ALPHA,                    /* 0xa4 'u' */
+    T_ALPHA,                    /* 0xa5 'v' */
+    T_ALPHA,                    /* 0xa6 'w' */
+    T_ALPHA,                    /* 0xa7 'x' */
+    T_ALPHA,                    /* 0xa8 'y' */
+    T_ALPHA,                    /* 0xa9 'z' */
+    0,                          /* 0xaa     */
+    0,                          /* 0xab     */
+    0,                          /* 0xac     */
+    0,                          /* 0xad     */
+    0,                          /* 0xae     */
+    0,                          /* 0xaf     */
+    0,                          /* 0xb0     */
+    0,                          /* 0xb1     */
+    0,                          /* 0xb2     */
+    0,                          /* 0xb3     */
+    0,                          /* 0xb4     */
+    0,                          /* 0xb5     */
+    0,                          /* 0xb6     */
+    0,                          /* 0xb7     */
+    0,                          /* 0xb8     */
+    0,                          /* 0xb9     */
+    0,                          /* 0xba     */
+    0,                          /* 0xbb     */
+    0,                          /* 0xbc     */
+    0,                          /* 0xbd     */
+    0,                          /* 0xbe     */
+    0,                          /* 0xbf     */
+    0,                          /* 0xc0 '{' */
+    T_ALPHA,                    /* 0xc1 'A' */
+    T_ALPHA,                    /* 0xc2 'B' */
+    T_ALPHA,                    /* 0xc3 'C' */
+    T_ALPHA,                    /* 0xc4 'D' */
+    T_ALPHA,                    /* 0xc5 'E' */
+    T_ALPHA,                    /* 0xc6 'F' */
+    T_ALPHA,                    /* 0xc7 'G' */
+    T_ALPHA,                    /* 0xc8 'H' */
+    T_ALPHA,                    /* 0xc9 'I' */
+    0,                          /* 0xca     */
+    0,                          /* 0xcb     */
+    0,                          /* 0xcc     */
+    0,                          /* 0xcd     */
+    0,                          /* 0xce     */
+    0,                          /* 0xcf     */
+    0,                          /* 0xd0 '}' */
+    T_ALPHA,                    /* 0xd1 'J' */
+    T_ALPHA,                    /* 0xd2 'K' */
+    T_ALPHA,                    /* 0xd3 'L' */
+    T_ALPHA,                    /* 0xd4 'M' */
+    T_ALPHA,                    /* 0xd5 'N' */
+    T_ALPHA,                    /* 0xd6 'O' */
+    T_ALPHA,                    /* 0xd7 'P' */
+    T_ALPHA,                    /* 0xd8 'Q' */
+    T_ALPHA,                    /* 0xd9 'R' */
+    0,                          /* 0xda     */
+    0,                          /* 0xdb     */
+    0,                          /* 0xdc     */
+    0,                          /* 0xdd     */
+    0,                          /* 0xde     */
+    0,                          /* 0xdf     */
+    0,                          /* 0xe0 '\' */
+    0,                          /* 0xe1     */
+    T_ALPHA,                    /* 0xe2 'S' */
+    T_ALPHA,                    /* 0xe3 'T' */
+    T_ALPHA,                    /* 0xe4 'U' */
+    T_ALPHA,                    /* 0xe5 'V' */
+    T_ALPHA,                    /* 0xe6 'W' */
+    T_ALPHA,                    /* 0xe7 'X' */
+    T_ALPHA,                    /* 0xe8 'Y' */
+    T_ALPHA,                    /* 0xe9 'Z' */
+    0,                          /* 0xea     */
+    0,                          /* 0xeb     */
+    0,                          /* 0xec     */
+    0,                          /* 0xed     */
+    0,                          /* 0xee     */
+    0,                          /* 0xef     */
+    T_SCHEME,                   /* 0xf0 '0' */
+    T_SCHEME,                   /* 0xf1 '1' */
+    T_SCHEME,                   /* 0xf2 '2' */
+    T_SCHEME,                   /* 0xf3 '3' */
+    T_SCHEME,                   /* 0xf4 '4' */
+    T_SCHEME,                   /* 0xf5 '5' */
+    T_SCHEME,                   /* 0xf6 '6' */
+    T_SCHEME,                   /* 0xf7 '7' */
+    T_SCHEME,                   /* 0xf8 '8' */
+    T_SCHEME,                   /* 0xf9 '9' */
+    0,                          /* 0xfa     */
+    0,                          /* 0xfb     */
+    0,                          /* 0xfc     */
+    0,                          /* 0xfd     */
+    0,                          /* 0xfe     */
+    0                           /* 0xff     */
+};
+#else
+/* Delimiter table for the ASCII character set */
+static const unsigned char uri_delims[256] = {
+    T_NUL,                      /* 0x00     */
+    0,                          /* 0x01     */
+    0,                          /* 0x02     */
+    0,                          /* 0x03     */
+    0,                          /* 0x04     */
+    0,                          /* 0x05     */
+    0,                          /* 0x06     */
+    0,                          /* 0x07     */
+    0,                          /* 0x08     */
+    0,                          /* 0x09     */
+    0,                          /* 0x0a     */
+    0,                          /* 0x0b     */
+    0,                          /* 0x0c     */
+    0,                          /* 0x0d     */
+    0,                          /* 0x0e     */
+    0,                          /* 0x0f     */
+    0,                          /* 0x10     */
+    0,                          /* 0x11     */
+    0,                          /* 0x12     */
+    0,                          /* 0x13     */
+    0,                          /* 0x14     */
+    0,                          /* 0x15     */
+    0,                          /* 0x16     */
+    0,                          /* 0x17     */
+    0,                          /* 0x18     */
+    0,                          /* 0x19     */
+    0,                          /* 0x1a     */
+    0,                          /* 0x1b     */
+    0,                          /* 0x1c     */
+    0,                          /* 0x1d     */
+    0,                          /* 0x1e     */
+    0,                          /* 0x1f     */
+    0,                          /* 0x20 ' ' */
+    0,                          /* 0x21 '!' */
+    0,                          /* 0x22 '"' */
+    T_HASH,                     /* 0x23 '#' */
+    0,                          /* 0x24 '$' */
+    0,                          /* 0x25 '%' */
+    0,                          /* 0x26 '&' */
+    0,                          /* 0x27 ''' */
+    0,                          /* 0x28 '(' */
+    0,                          /* 0x29 ')' */
+    0,                          /* 0x2a '*' */
+    T_SCHEME,                   /* 0x2b '+' */
+    0,                          /* 0x2c ',' */
+    T_SCHEME,                   /* 0x2d '-' */
+    T_SCHEME,                   /* 0x2e '.' */
+    T_SLASH,                    /* 0x2f '/' */
+    T_SCHEME,                   /* 0x30 '0' */
+    T_SCHEME,                   /* 0x31 '1' */
+    T_SCHEME,                   /* 0x32 '2' */
+    T_SCHEME,                   /* 0x33 '3' */
+    T_SCHEME,                   /* 0x34 '4' */
+    T_SCHEME,                   /* 0x35 '5' */
+    T_SCHEME,                   /* 0x36 '6' */
+    T_SCHEME,                   /* 0x37 '7' */
+    T_SCHEME,                   /* 0x38 '8' */
+    T_SCHEME,                   /* 0x39 '9' */
+    0,                          /* 0x3a ':' */
+    0,                          /* 0x3b ';' */
+    0,                          /* 0x3c '<' */
+    0,                          /* 0x3d '=' */
+    0,                          /* 0x3e '>' */
+    T_QUESTION,                 /* 0x3f '?' */
+    0,                          /* 0x40 '@' */
+    T_ALPHA,                    /* 0x41 'A' */
+    T_ALPHA,                    /* 0x42 'B' */
+    T_ALPHA,                    /* 0x43 'C' */
+    T_ALPHA,                    /* 0x44 'D' */
+    T_ALPHA,                    /* 0x45 'E' */
+    T_ALPHA,                    /* 0x46 'F' */
+    T_ALPHA,                    /* 0x47 'G' */
+    T_ALPHA,                    /* 0x48 'H' */
+    T_ALPHA,                    /* 0x49 'I' */
+    T_ALPHA,                    /* 0x4a 'J' */
+    T_ALPHA,                    /* 0x4b 'K' */
+    T_ALPHA,                    /* 0x4c 'L' */
+    T_ALPHA,                    /* 0x4d 'M' */
+    T_ALPHA,                    /* 0x4e 'N' */
+    T_ALPHA,                    /* 0x4f 'O' */
+    T_ALPHA,                    /* 0x50 'P' */
+    T_ALPHA,                    /* 0x51 'Q' */
+    T_ALPHA,                    /* 0x52 'R' */
+    T_ALPHA,                    /* 0x53 'S' */
+    T_ALPHA,                    /* 0x54 'T' */
+    T_ALPHA,                    /* 0x55 'U' */
+    T_ALPHA,                    /* 0x56 'V' */
+    T_ALPHA,                    /* 0x57 'W' */
+    T_ALPHA,                    /* 0x58 'X' */
+    T_ALPHA,                    /* 0x59 'Y' */
+    T_ALPHA,                    /* 0x5a 'Z' */
+    0,                          /* 0x5b '[' */
+    0,                          /* 0x5c '\' */
+    0,                          /* 0x5d ']' */
+    0,                          /* 0x5e '^' */
+    0,                          /* 0x5f '_' */
+    0,                          /* 0x60 '`' */
+    T_ALPHA,                    /* 0x61 'a' */
+    T_ALPHA,                    /* 0x62 'b' */
+    T_ALPHA,                    /* 0x63 'c' */
+    T_ALPHA,                    /* 0x64 'd' */
+    T_ALPHA,                    /* 0x65 'e' */
+    T_ALPHA,                    /* 0x66 'f' */
+    T_ALPHA,                    /* 0x67 'g' */
+    T_ALPHA,                    /* 0x68 'h' */
+    T_ALPHA,                    /* 0x69 'i' */
+    T_ALPHA,                    /* 0x6a 'j' */
+    T_ALPHA,                    /* 0x6b 'k' */
+    T_ALPHA,                    /* 0x6c 'l' */
+    T_ALPHA,                    /* 0x6d 'm' */
+    T_ALPHA,                    /* 0x6e 'n' */
+    T_ALPHA,                    /* 0x6f 'o' */
+    T_ALPHA,                    /* 0x70 'p' */
+    T_ALPHA,                    /* 0x71 'q' */
+    T_ALPHA,                    /* 0x72 'r' */
+    T_ALPHA,                    /* 0x73 's' */
+    T_ALPHA,                    /* 0x74 't' */
+    T_ALPHA,                    /* 0x75 'u' */
+    T_ALPHA,                    /* 0x76 'v' */
+    T_ALPHA,                    /* 0x77 'w' */
+    T_ALPHA,                    /* 0x78 'x' */
+    T_ALPHA,                    /* 0x79 'y' */
+    T_ALPHA,                    /* 0x7a 'z' */
+    0,                          /* 0x7b '{' */
+    0,                          /* 0x7c '|' */
+    0,                          /* 0x7d '}' */
+    0,                          /* 0x7e '~' */
+    0,                          /* 0x7f     */
+    0,                          /* 0x80     */
+    0,                          /* 0x81     */
+    0,                          /* 0x82     */
+    0,                          /* 0x83     */
+    0,                          /* 0x84     */
+    0,                          /* 0x85     */
+    0,                          /* 0x86     */
+    0,                          /* 0x87     */
+    0,                          /* 0x88     */
+    0,                          /* 0x89     */
+    0,                          /* 0x8a     */
+    0,                          /* 0x8b     */
+    0,                          /* 0x8c     */
+    0,                          /* 0x8d     */
+    0,                          /* 0x8e     */
+    0,                          /* 0x8f     */
+    0,                          /* 0x90     */
+    0,                          /* 0x91     */
+    0,                          /* 0x92     */
+    0,                          /* 0x93     */
+    0,                          /* 0x94     */
+    0,                          /* 0x95     */
+    0,                          /* 0x96     */
+    0,                          /* 0x97     */
+    0,                          /* 0x98     */
+    0,                          /* 0x99     */
+    0,                          /* 0x9a     */
+    0,                          /* 0x9b     */
+    0,                          /* 0x9c     */
+    0,                          /* 0x9d     */
+    0,                          /* 0x9e     */
+    0,                          /* 0x9f     */
+    0,                          /* 0xa0     */
+    0,                          /* 0xa1     */
+    0,                          /* 0xa2     */
+    0,                          /* 0xa3     */
+    0,                          /* 0xa4     */
+    0,                          /* 0xa5     */
+    0,                          /* 0xa6     */
+    0,                          /* 0xa7     */
+    0,                          /* 0xa8     */
+    0,                          /* 0xa9     */
+    0,                          /* 0xaa     */
+    0,                          /* 0xab     */
+    0,                          /* 0xac     */
+    0,                          /* 0xad     */
+    0,                          /* 0xae     */
+    0,                          /* 0xaf     */
+    0,                          /* 0xb0     */
+    0,                          /* 0xb1     */
+    0,                          /* 0xb2     */
+    0,                          /* 0xb3     */
+    0,                          /* 0xb4     */
+    0,                          /* 0xb5     */
+    0,                          /* 0xb6     */
+    0,                          /* 0xb7     */
+    0,                          /* 0xb8     */
+    0,                          /* 0xb9     */
+    0,                          /* 0xba     */
+    0,                          /* 0xbb     */
+    0,                          /* 0xbc     */
+    0,                          /* 0xbd     */
+    0,                          /* 0xbe     */
+    0,                          /* 0xbf     */
+    0,                          /* 0xc0     */
+    0,                          /* 0xc1     */
+    0,                          /* 0xc2     */
+    0,                          /* 0xc3     */
+    0,                          /* 0xc4     */
+    0,                          /* 0xc5     */
+    0,                          /* 0xc6     */
+    0,                          /* 0xc7     */
+    0,                          /* 0xc8     */
+    0,                          /* 0xc9     */
+    0,                          /* 0xca     */
+    0,                          /* 0xcb     */
+    0,                          /* 0xcc     */
+    0,                          /* 0xcd     */
+    0,                          /* 0xce     */
+    0,                          /* 0xcf     */
+    0,                          /* 0xd0     */
+    0,                          /* 0xd1     */
+    0,                          /* 0xd2     */
+    0,                          /* 0xd3     */
+    0,                          /* 0xd4     */
+    0,                          /* 0xd5     */
+    0,                          /* 0xd6     */
+    0,                          /* 0xd7     */
+    0,                          /* 0xd8     */
+    0,                          /* 0xd9     */
+    0,                          /* 0xda     */
+    0,                          /* 0xdb     */
+    0,                          /* 0xdc     */
+    0,                          /* 0xdd     */
+    0,                          /* 0xde     */
+    0,                          /* 0xdf     */
+    0,                          /* 0xe0     */
+    0,                          /* 0xe1     */
+    0,                          /* 0xe2     */
+    0,                          /* 0xe3     */
+    0,                          /* 0xe4     */
+    0,                          /* 0xe5     */
+    0,                          /* 0xe6     */
+    0,                          /* 0xe7     */
+    0,                          /* 0xe8     */
+    0,                          /* 0xe9     */
+    0,                          /* 0xea     */
+    0,                          /* 0xeb     */
+    0,                          /* 0xec     */
+    0,                          /* 0xed     */
+    0,                          /* 0xee     */
+    0,                          /* 0xef     */
+    0,                          /* 0xf0     */
+    0,                          /* 0xf1     */
+    0,                          /* 0xf2     */
+    0,                          /* 0xf3     */
+    0,                          /* 0xf4     */
+    0,                          /* 0xf5     */
+    0,                          /* 0xf6     */
+    0,                          /* 0xf7     */
+    0,                          /* 0xf8     */
+    0,                          /* 0xf9     */
+    0,                          /* 0xfa     */
+    0,                          /* 0xfb     */
+    0,                          /* 0xfc     */
+    0,                          /* 0xfd     */
+    0,                          /* 0xfe     */
+    0                           /* 0xff     */
+};
+#endif
+
+
+/* it works like this:
+    if (uri_delims[ch] & NOTEND_foobar) {
+        then we're not at a delimiter for foobar
+    }
+*/
+
+#define NOTEND_HOSTINFO   (T_SLASH | T_QUESTION | T_HASH | T_NUL)
+#define NOTEND_PATH       (T_QUESTION | T_HASH | T_NUL)
+
+/* parse_uri_components():
+ * Parse a given URI, fill in all supplied fields of a uri_components
+ * structure. This eliminates the necessity of extracting host, port,
+ * path, query info repeatedly in the modules.
+ * Side effects:
+ *  - fills in fields of uri_components *uptr
+ *  - none on any of the r->* fields
+ */
+APR_DECLARE(apr_status_t) apr_uri_parse(apr_pool_t *p, const char *uri, 
+                                        apr_uri_t *uptr)
+{
+    const char *s;
+    const char *s1;
+    const char *hostinfo;
+    char *endstr;
+    int port;
+    int v6_offset1 = 0, v6_offset2 = 0;
+
+    /* Initialize the structure. parse_uri() and parse_uri_components()
+     * can be called more than once per request.
+     */
+    memset (uptr, '\0', sizeof(*uptr));
+    uptr->is_initialized = 1;
+
+    /* We assume the processor has a branch predictor like most --
+     * it assumes forward branches are untaken and backwards are taken.  That's
+     * the reason for the gotos.  -djg
+     */
+    if (uri[0] == '/') {
+        /* RFC2396 #4.3 says that two leading slashes mean we have an
+         * authority component, not a path!  Fixing this looks scary
+         * with the gotos here.  But if the existing logic is valid,
+         * then presumably a goto pointing to deal_with_authority works.
+         *
+         * RFC2396 describes this as resolving an ambiguity.  In the
+         * case of three or more slashes there would seem to be no
+         * ambiguity, so it is a path after all.
+         */
+        if (uri[1] == '/' && uri[2] != '/') {
+            s = uri + 2 ;
+            goto deal_with_authority ;
+        }
+
+deal_with_path:
+        /* we expect uri to point to first character of path ... remember
+         * that the path could be empty -- http://foobar?query for example
+         */
+        s = uri;
+        while ((uri_delims[*(unsigned char *)s] & NOTEND_PATH) == 0) {
+            ++s;
+        }
+        if (s != uri) {
+            uptr->path = apr_pstrmemdup(p, uri, s - uri);
+        }
+        if (*s == 0) {
+            return APR_SUCCESS;
+        }
+        if (*s == '?') {
+            ++s;
+            s1 = strchr(s, '#');
+            if (s1) {
+                uptr->fragment = apr_pstrdup(p, s1 + 1);
+                uptr->query = apr_pstrmemdup(p, s, s1 - s);
+            }
+            else {
+                uptr->query = apr_pstrdup(p, s);
+            }
+            return APR_SUCCESS;
+        }
+        /* otherwise it's a fragment */
+        uptr->fragment = apr_pstrdup(p, s + 1);
+        return APR_SUCCESS;
+    }
+
+    /* find the scheme: */
+    s = uri;
+    /* first char must be letter */
+    if (uri_delims[*(unsigned char *)s] & T_ALPHA) {
+        ++s;
+        while ((uri_delims[*(unsigned char *)s] & (T_ALPHA|T_SCHEME)))
+            ++s;
+    }
+    /* scheme must be non-empty and followed by : */
+    if (s != uri && s[0] == ':') {
+        uptr->scheme = apr_pstrmemdup(p, uri, s - uri);
+        s++;
+    }
+    else {
+        /* No valid scheme, restart from the beginning */
+        s = uri;
+    }
+
+    if (s[0] != '/' || s[1] != '/') {
+        if (uri == s) {
+            /*
+             * RFC 3986 3.3: If we have no scheme and no authority,
+             * the leading segment of a relative path must not contain a ':'.
+             */
+            char *first_slash = strchr(uri, '/');
+            if (first_slash) {
+                while (s < first_slash) {
+                    if (s[0] == ':')
+                        return APR_EGENERAL;
+                    ++s;
+                }
+                /* no scheme but relative path, e.g. '../image.jpg' */
+            }
+            else {
+                if (strchr(uri, ':') != NULL)
+                    return APR_EGENERAL;
+                /* no scheme, no slash, but relative path, e.g. 'image.jpg' */
+            }
+            goto deal_with_path;
+        }
+        /* scheme and relative path */
+        uri = s;
+        goto deal_with_path;
+    }
+
+    s += 2;
+
+deal_with_authority:
+    hostinfo = s;
+    while ((uri_delims[*(unsigned char *)s] & NOTEND_HOSTINFO) == 0) {
+        ++s;
+    }
+    uri = s;        /* whatever follows hostinfo is start of uri */
+    uptr->hostinfo = apr_pstrmemdup(p, hostinfo, uri - hostinfo);
+
+    /* If there's a username:password@host:port, the @ we want is the last @...
+     * too bad there's no memrchr()... For the C purists, note that hostinfo
+     * is definitely not the first character of the original uri so therefore
+     * &hostinfo[-1] < &hostinfo[0] ... and this loop is valid C.
+     */
+    do {
+        --s;
+    } while (s >= hostinfo && *s != '@');
+    if (s < hostinfo) {
+        /* again we want the common case to be fall through */
+deal_with_host:
+        /* We expect hostinfo to point to the first character of
+         * the hostname.  If there's a port it is the first colon,
+         * except with IPv6.
+         */
+        if (*hostinfo == '[') {
+            v6_offset1 = 1;
+            v6_offset2 = 2;
+            s = memchr(hostinfo, ']', uri - hostinfo);
+            if (s == NULL) {
+                return APR_EGENERAL;
+            }
+            if (*++s != ':') {
+                s = NULL; /* no port */
+            }
+        }
+        else {
+            s = memchr(hostinfo, ':', uri - hostinfo);
+        }
+        if (s == NULL) {
+            /* we expect the common case to have no port */
+            uptr->hostname = apr_pstrmemdup(p,
+                                            hostinfo + v6_offset1,
+                                            uri - hostinfo - v6_offset2);
+            goto deal_with_path;
+        }
+        uptr->hostname = apr_pstrmemdup(p,
+                                        hostinfo + v6_offset1,
+                                        s - hostinfo - v6_offset2);
+        ++s;
+        uptr->port_str = apr_pstrmemdup(p, s, uri - s);
+        if (uri != s) {
+            port = strtol(uptr->port_str, &endstr, 10);
+            uptr->port = port;
+            if (*endstr == '\0') {
+                goto deal_with_path;
+            }
+            /* Invalid characters after ':' found */
+            return APR_EGENERAL;
+        }
+        uptr->port = apr_uri_port_of_scheme(uptr->scheme);
+        goto deal_with_path;
+    }
+
+    /* first colon delimits username:password */
+    s1 = memchr(hostinfo, ':', s - hostinfo);
+    if (s1) {
+        uptr->user = apr_pstrmemdup(p, hostinfo, s1 - hostinfo);
+        ++s1;
+        uptr->password = apr_pstrmemdup(p, s1, s - s1);
+    }
+    else {
+        uptr->user = apr_pstrmemdup(p, hostinfo, s - hostinfo);
+    }
+    hostinfo = s + 1;
+    goto deal_with_host;
+}
+
+/* Special case for CONNECT parsing: it comes with the hostinfo part only */
+/* See the INTERNET-DRAFT document "Tunneling SSL Through a WWW Proxy"
+ * currently at http://www.mcom.com/newsref/std/tunneling_ssl.html
+ * for the format of the "CONNECT host:port HTTP/1.0" request
+ */
+APR_DECLARE(apr_status_t) apr_uri_parse_hostinfo(apr_pool_t *p, 
+                                                 const char *hostinfo, 
+                                                 apr_uri_t *uptr)
+{
+    const char *s;
+    char *endstr;
+    const char *rsb;
+    int v6_offset1 = 0;
+
+    /* Initialize the structure. parse_uri() and parse_uri_components()
+     * can be called more than once per request.
+     */
+    memset(uptr, '\0', sizeof(*uptr));
+    uptr->is_initialized = 1;
+    uptr->hostinfo = apr_pstrdup(p, hostinfo);
+
+    /* We expect hostinfo to point to the first character of
+     * the hostname.  There must be a port, separated by a colon
+     */
+    if (*hostinfo == '[') {
+        if ((rsb = strchr(hostinfo, ']')) == NULL ||
+            *(rsb + 1) != ':') {
+            return APR_EGENERAL;
+        }
+        /* literal IPv6 address */
+        s = rsb + 1;
+        ++hostinfo;
+        v6_offset1 = 1;
+    }
+    else {
+        s = strchr(hostinfo, ':');
+    }
+    if (s == NULL) {
+        return APR_EGENERAL;
+    }
+    uptr->hostname = apr_pstrndup(p, hostinfo, s - hostinfo - v6_offset1);
+    ++s;
+    uptr->port_str = apr_pstrdup(p, s);
+    if (*s != '\0') {
+        uptr->port = (unsigned short) strtol(uptr->port_str, &endstr, 10);
+        if (*endstr == '\0') {
+            return APR_SUCCESS;
+        }
+        /* Invalid characters after ':' found */
+    }
+    return APR_EGENERAL;
+}
diff --git a/user/netware/groupinfo.c b/user/netware/groupinfo.c
new file mode 100644
index 00000000000..e7cfd9b2677
--- /dev/null
+++ b/user/netware/groupinfo.c
@@ -0,0 +1,41 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_strings.h"
+#include "apr_portable.h"
+#include "apr_user.h"
+#include "apr_private.h"
+#ifdef HAVE_GRP_H
+#include <grp.h>
+#endif
+#if APR_HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#if APR_HAVE_UNISTD_H
+#include <unistd.h> /* for _POSIX_THREAD_SAFE_FUNCTIONS */
+#endif
+
+APR_DECLARE(apr_status_t) apr_gid_name_get(char **groupname, apr_gid_t groupid,
+                                           apr_pool_t *p)
+{
+    return APR_ENOTIMPL;
+}
+  
+APR_DECLARE(apr_status_t) apr_gid_get(apr_gid_t *groupid, 
+                                      const char *groupname, apr_pool_t *p)
+{
+    return APR_ENOTIMPL;
+}
diff --git a/user/netware/userinfo.c b/user/netware/userinfo.c
new file mode 100644
index 00000000000..b58991b8ea5
--- /dev/null
+++ b/user/netware/userinfo.c
@@ -0,0 +1,70 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_strings.h"
+#include "apr_portable.h"
+#include "apr_user.h"
+#include "apr_private.h"
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+#if APR_HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#if APR_HAVE_UNISTD_H
+#include <unistd.h> /* for _POSIX_THREAD_SAFE_FUNCTIONS */
+#endif
+
+#define PWBUF_SIZE 512
+
+static apr_status_t getpwnam_safe(const char *username,
+                                  struct passwd *pw,
+                                  char pwbuf[PWBUF_SIZE])
+{
+    return APR_ENOTIMPL;
+}
+
+APR_DECLARE(apr_status_t) apr_uid_homepath_get(char **dirname,
+                                               const char *username,
+                                               apr_pool_t *p)
+{
+    return APR_ENOTIMPL;
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_uid_current(apr_uid_t *uid,
+                                          apr_gid_t *gid,
+                                          apr_pool_t *p)
+{
+    return APR_ENOTIMPL;
+}
+
+
+
+
+APR_DECLARE(apr_status_t) apr_uid_get(apr_uid_t *uid, apr_gid_t *gid,
+                                      const char *username, apr_pool_t *p)
+{
+    return APR_ENOTIMPL;
+}
+
+APR_DECLARE(apr_status_t) apr_uid_name_get(char **username, apr_uid_t userid,
+                                           apr_pool_t *p)
+{
+    return APR_ENOTIMPL;
+}
+
diff --git a/user/unix/groupinfo.c b/user/unix/groupinfo.c
new file mode 100644
index 00000000000..7967219f8fb
--- /dev/null
+++ b/user/unix/groupinfo.c
@@ -0,0 +1,87 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_strings.h"
+#include "apr_portable.h"
+#include "apr_user.h"
+#include "apr_private.h"
+#ifdef HAVE_GRP_H
+#include <grp.h>
+#endif
+#if APR_HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#if APR_HAVE_UNISTD_H
+#include <unistd.h> /* for _POSIX_THREAD_SAFE_FUNCTIONS */
+#endif
+
+#define GRBUF_SIZE 8192
+
+APR_DECLARE(apr_status_t) apr_gid_name_get(char **groupname, apr_gid_t groupid,
+                                           apr_pool_t *p)
+{
+    struct group *gr;
+
+#if APR_HAS_THREADS && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
+    struct group grp;
+    char grbuf[GRBUF_SIZE];
+    apr_status_t rv;
+
+    /* See comment in getpwnam_safe on error handling. */
+    rv = getgrgid_r(groupid, &grp, grbuf, sizeof(grbuf), &gr);
+    if (rv) {
+        return rv;
+    }
+    if (gr == NULL) {
+        return APR_ENOENT;
+    }
+#else
+    errno = 0;
+    if ((gr = getgrgid(groupid)) == NULL) {
+        return errno ? errno : APR_ENOENT;
+    }
+#endif
+    *groupname = apr_pstrdup(p, gr->gr_name);
+    return APR_SUCCESS;
+}
+  
+APR_DECLARE(apr_status_t) apr_gid_get(apr_gid_t *groupid, 
+                                      const char *groupname, apr_pool_t *p)
+{
+    struct group *gr;
+
+#if APR_HAS_THREADS && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRNAM_R)
+    struct group grp;
+    char grbuf[GRBUF_SIZE];
+    apr_status_t rv;
+
+    /* See comment in getpwnam_safe on error handling. */
+    rv = getgrnam_r(groupname, &grp, grbuf, sizeof(grbuf), &gr);
+    if (rv) {
+        return rv;
+    }
+    if (gr == NULL) {
+        return APR_ENOENT;
+    }
+#else
+    errno = 0;
+    if ((gr = getgrnam(groupname)) == NULL) {
+        return errno ? errno : APR_ENOENT;
+    }
+#endif
+    *groupid = gr->gr_gid;
+    return APR_SUCCESS;
+}
diff --git a/user/unix/userinfo.c b/user/unix/userinfo.c
new file mode 100644
index 00000000000..516445b56d5
--- /dev/null
+++ b/user/unix/userinfo.c
@@ -0,0 +1,146 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_strings.h"
+#include "apr_portable.h"
+#include "apr_user.h"
+#include "apr_private.h"
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+#if APR_HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#if APR_HAVE_UNISTD_H
+#include <unistd.h> /* for _POSIX_THREAD_SAFE_FUNCTIONS */
+#endif
+#define APR_WANT_MEMFUNC
+#include "apr_want.h"
+
+#define PWBUF_SIZE 2048
+
+static apr_status_t getpwnam_safe(const char *username,
+                                  struct passwd *pw,
+                                  char pwbuf[PWBUF_SIZE])
+{
+    struct passwd *pwptr;
+#if APR_HAS_THREADS && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
+    apr_status_t rv;
+
+    /* POSIX defines getpwnam_r() et al to return the error number
+     * rather than set errno, and requires pwptr to be set to NULL if
+     * the entry is not found, imply that "not found" is not an error
+     * condition; some implementations do return 0 with pwptr set to
+     * NULL. */
+    rv = getpwnam_r(username, pw, pwbuf, PWBUF_SIZE, &pwptr);
+    if (rv) {
+        return rv;
+    }
+    if (pwptr == NULL) {
+        return APR_ENOENT;
+    }
+#else
+    /* Some platforms (e.g. FreeBSD 4.x) do not set errno on NULL "not
+     * found" return values for the non-threadsafe function either. */
+    errno = 0;
+    if ((pwptr = getpwnam(username)) != NULL) {
+        memcpy(pw, pwptr, sizeof *pw);
+    }
+    else {
+        return errno ? errno : APR_ENOENT;
+    }
+#endif
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_uid_homepath_get(char **dirname,
+                                               const char *username,
+                                               apr_pool_t *p)
+{
+    struct passwd pw;
+    char pwbuf[PWBUF_SIZE];
+    apr_status_t rv;
+
+    if ((rv = getpwnam_safe(username, &pw, pwbuf)) != APR_SUCCESS)
+        return rv;
+
+#ifdef OS2
+    /* Need to manually add user name for OS/2 */
+    *dirname = apr_pstrcat(p, pw.pw_dir, pw.pw_name, NULL);
+#else
+    *dirname = apr_pstrdup(p, pw.pw_dir);
+#endif
+    return APR_SUCCESS;
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_uid_current(apr_uid_t *uid,
+                                          apr_gid_t *gid,
+                                          apr_pool_t *p)
+{
+    *uid = getuid();
+    *gid = getgid();
+  
+    return APR_SUCCESS;
+}
+
+
+
+
+APR_DECLARE(apr_status_t) apr_uid_get(apr_uid_t *uid, apr_gid_t *gid,
+                                      const char *username, apr_pool_t *p)
+{
+    struct passwd pw;
+    char pwbuf[PWBUF_SIZE];
+    apr_status_t rv;
+        
+    if ((rv = getpwnam_safe(username, &pw, pwbuf)) != APR_SUCCESS)
+        return rv;
+
+    *uid = pw.pw_uid;
+    *gid = pw.pw_gid;
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_uid_name_get(char **username, apr_uid_t userid,
+                                           apr_pool_t *p)
+{
+    struct passwd *pw;
+#if APR_HAS_THREADS && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWUID_R)
+    struct passwd pwd;
+    char pwbuf[PWBUF_SIZE];
+    apr_status_t rv;
+
+    rv = getpwuid_r(userid, &pwd, pwbuf, sizeof(pwbuf), &pw);
+    if (rv) {
+        return rv;
+    }
+
+    if (pw == NULL) {
+        return APR_ENOENT;
+    }
+
+#else
+    errno = 0;
+    if ((pw = getpwuid(userid)) == NULL) {
+        return errno ? errno : APR_ENOENT;
+    }
+#endif
+    *username = apr_pstrdup(p, pw->pw_name);
+    return APR_SUCCESS;
+}
diff --git a/user/win32/groupinfo.c b/user/win32/groupinfo.c
new file mode 100644
index 00000000000..b53656962a2
--- /dev/null
+++ b/user/win32/groupinfo.c
@@ -0,0 +1,100 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_strings.h"
+#include "apr_portable.h"
+#include "apr_user.h"
+#include "apr_private.h"
+#if APR_HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+APR_DECLARE(apr_status_t) apr_gid_get(apr_gid_t *gid, 
+                                      const char *groupname, apr_pool_t *p)
+{
+#ifdef _WIN32_WCE
+    return APR_ENOTIMPL;
+#else
+    SID_NAME_USE sidtype;
+    char anydomain[256];
+    char *domain;
+    DWORD sidlen = 0;
+    DWORD domlen = sizeof(anydomain);
+    DWORD rv;
+    char *pos;
+
+    if ((pos = strchr(groupname, '/'))) {
+        domain = apr_pstrmemdup(p, groupname, pos - groupname);
+        groupname = pos + 1;
+    }
+    else if ((pos = strchr(groupname, '\\'))) {
+        domain = apr_pstrmemdup(p, groupname, pos - groupname);
+        groupname = pos + 1;
+    }
+    else {
+        domain = NULL;
+    }
+    /* Get nothing on the first pass ... need to size the sid buffer 
+     */
+    rv = LookupAccountName(domain, groupname, domain, &sidlen, 
+                           anydomain, &domlen, &sidtype);
+    if (sidlen) {
+        /* Give it back on the second pass
+         */
+        *gid = apr_palloc(p, sidlen);
+        domlen = sizeof(anydomain);
+        rv = LookupAccountName(domain, groupname, *gid, &sidlen, 
+                               anydomain, &domlen, &sidtype);
+    }
+    if (!sidlen || !rv) {
+        return apr_get_os_error();
+    }
+    return APR_SUCCESS;
+#endif
+}
+
+APR_DECLARE(apr_status_t) apr_gid_name_get(char **groupname, apr_gid_t groupid, apr_pool_t *p)
+{
+#ifdef _WIN32_WCE
+    *groupname = apr_pstrdup(p, "Administrators");
+#else
+    SID_NAME_USE type;
+    char name[MAX_PATH], domain[MAX_PATH];
+    DWORD cbname = sizeof(name), cbdomain = sizeof(domain);
+    if (!groupid)
+        return APR_EINVAL;
+    if (!LookupAccountSid(NULL, groupid, name, &cbname, domain, &cbdomain, &type))
+        return apr_get_os_error();
+    if (type != SidTypeGroup && type != SidTypeWellKnownGroup 
+                             && type != SidTypeAlias)
+        return APR_EINVAL;
+    *groupname = apr_pstrdup(p, name);
+#endif
+    return APR_SUCCESS;
+}
+  
+APR_DECLARE(apr_status_t) apr_gid_compare(apr_gid_t left, apr_gid_t right)
+{
+    if (!left || !right)
+        return APR_EINVAL;
+#ifndef _WIN32_WCE
+    if (!IsValidSid(left) || !IsValidSid(right))
+        return APR_EINVAL;
+    if (!EqualSid(left, right))
+        return APR_EMISMATCH;
+#endif
+    return APR_SUCCESS;
+}
diff --git a/user/win32/userinfo.c b/user/win32/userinfo.c
new file mode 100644
index 00000000000..c6b5084a536
--- /dev/null
+++ b/user/win32/userinfo.c
@@ -0,0 +1,280 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_private.h"
+#include "apr_strings.h"
+#include "apr_portable.h"
+#include "apr_user.h"
+#include "apr_arch_file_io.h"
+#if APR_HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifndef _WIN32_WCE
+/* Internal sid binary to string translation, see MSKB Q131320.
+ * Several user related operations require our SID to access
+ * the registry, but in a string format.  All error handling
+ * depends on IsValidSid(), which internally we better test long
+ * before we get here!
+ */
+static void get_sid_string(char *buf, apr_size_t blen, apr_uid_t id)
+{
+    PSID_IDENTIFIER_AUTHORITY psia;
+    DWORD nsa;
+    DWORD sa;
+    int slen;
+
+    /* Determine authority values (these is a big-endian value, 
+     * and NT records the value as hex if the value is > 2^32.)
+     */
+    psia = GetSidIdentifierAuthority(id);
+    nsa =  (DWORD)(psia->Value[5])        + ((DWORD)(psia->Value[4]) <<  8)
+        + ((DWORD)(psia->Value[3]) << 16) + ((DWORD)(psia->Value[2]) << 24);
+    sa  =  (DWORD)(psia->Value[1])        + ((DWORD)(psia->Value[0]) <<  8);
+    if (sa) {
+        slen = apr_snprintf(buf, blen, "S-%d-0x%04x%08x",
+                            SID_REVISION, (unsigned int)sa, (unsigned int)nsa);
+    } else {
+        slen = apr_snprintf(buf, blen, "S-%d-%lu",
+                            SID_REVISION, nsa);
+    }
+
+    /* Now append all the subauthority strings.
+     */
+    nsa = *GetSidSubAuthorityCount(id);
+    for (sa = 0; sa < nsa; ++sa) {
+        slen += apr_snprintf(buf + slen, blen - slen, "-%lu",
+                             *GetSidSubAuthority(id, sa));
+    }
+} 
+#endif
+/* Query the ProfileImagePath from the version-specific branch, where the
+ * regkey uses the user's name on 9x, and user's sid string on NT.
+ */
+APR_DECLARE(apr_status_t) apr_uid_homepath_get(char **dirname, 
+                                               const char *username, 
+                                               apr_pool_t *p)
+{
+#ifdef _WIN32_WCE
+    *dirname = apr_pstrdup(p, "/My Documents");
+    return APR_SUCCESS;
+#else
+    apr_status_t rv;
+    char regkey[MAX_PATH * 2];
+    char *fixch;
+    DWORD keylen;
+    DWORD type;
+    HKEY key;
+
+    if (apr_os_level >= APR_WIN_NT) {
+        apr_uid_t uid;
+        apr_gid_t gid;
+    
+        if ((rv = apr_uid_get(&uid, &gid, username, p)) != APR_SUCCESS)
+            return rv;
+
+        strcpy(regkey, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\"
+                       "ProfileList\\");
+        keylen = (DWORD)strlen(regkey);
+        get_sid_string(regkey + keylen, sizeof(regkey) - keylen, uid);
+    }
+    else {
+        strcpy(regkey, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
+                       "ProfileList\\");
+        keylen = (DWORD)strlen(regkey);
+        apr_cpystrn(regkey + keylen, username, sizeof(regkey) - keylen);
+    }
+
+    if ((rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, regkey, 0, 
+                           KEY_QUERY_VALUE, &key)) != ERROR_SUCCESS)
+        return APR_FROM_OS_ERROR(rv);
+
+#if APR_HAS_UNICODE_FS
+    IF_WIN_OS_IS_UNICODE
+    {
+        keylen = sizeof(regkey);
+        rv = RegQueryValueExW(key, L"ProfileImagePath", NULL, &type,
+                                   (void*)regkey, &keylen);
+        RegCloseKey(key);
+        if (rv != ERROR_SUCCESS)
+            return APR_FROM_OS_ERROR(rv);
+        if (type == REG_SZ) {
+            char retdir[MAX_PATH];
+            if ((rv = unicode_to_utf8_path(retdir, sizeof(retdir), 
+                                           (apr_wchar_t*)regkey)) != APR_SUCCESS)
+                return rv;
+            *dirname = apr_pstrdup(p, retdir);
+        }
+        else if (type == REG_EXPAND_SZ) {
+            apr_wchar_t path[MAX_PATH];
+            char retdir[MAX_PATH];
+            ExpandEnvironmentStringsW((apr_wchar_t*)regkey, path, 
+                                      sizeof(path) / 2);
+            if ((rv = unicode_to_utf8_path(retdir, sizeof(retdir), path))
+                    != APR_SUCCESS)
+                return rv;
+            *dirname = apr_pstrdup(p, retdir);
+        }
+        else
+            return APR_ENOENT;
+    }
+#endif
+#if APR_HAS_ANSI_FS
+    ELSE_WIN_OS_IS_ANSI
+    {
+        keylen = sizeof(regkey);
+        rv = RegQueryValueEx(key, "ProfileImagePath", NULL, &type,
+                                  (void*)regkey, &keylen);
+        RegCloseKey(key);
+        if (rv != ERROR_SUCCESS)
+            return APR_FROM_OS_ERROR(rv);
+        if (type == REG_SZ) {
+            *dirname = apr_pstrdup(p, regkey);
+        }
+        else if (type == REG_EXPAND_SZ) {
+            char path[MAX_PATH];
+            ExpandEnvironmentStrings(regkey, path, sizeof(path));
+            *dirname = apr_pstrdup(p, path);
+        }
+        else
+            return APR_ENOENT;
+    }
+#endif /* APR_HAS_ANSI_FS */
+    for (fixch = *dirname; *fixch; ++fixch)
+        if (*fixch == '\\')
+            *fixch = '/';
+    return APR_SUCCESS;
+#endif /* _WIN32_WCE */
+}
+
+APR_DECLARE(apr_status_t) apr_uid_current(apr_uid_t *uid,
+                                          apr_gid_t *gid,
+                                          apr_pool_t *p)
+{
+#ifdef _WIN32_WCE
+    return APR_ENOTIMPL;
+#else
+    HANDLE threadtok;
+    DWORD needed;
+    TOKEN_USER *usr;
+    TOKEN_PRIMARY_GROUP *grp;
+    
+    if(!OpenProcessToken(GetCurrentProcess(), STANDARD_RIGHTS_READ | READ_CONTROL | TOKEN_QUERY, &threadtok)) {
+        return apr_get_os_error();
+    }
+
+    *uid = NULL;
+    if (!GetTokenInformation(threadtok, TokenUser, NULL, 0, &needed)
+        && (GetLastError() == ERROR_INSUFFICIENT_BUFFER) 
+        && (usr = apr_palloc(p, needed))
+        && GetTokenInformation(threadtok, TokenUser, usr, needed, &needed))
+        *uid = usr->User.Sid;
+    else
+        return apr_get_os_error();
+
+    if (!GetTokenInformation(threadtok, TokenPrimaryGroup, NULL, 0, &needed)
+        && (GetLastError() == ERROR_INSUFFICIENT_BUFFER) 
+        && (grp = apr_palloc(p, needed))
+        && GetTokenInformation(threadtok, TokenPrimaryGroup, grp, needed, &needed))
+        *gid = grp->PrimaryGroup;
+    else
+        return apr_get_os_error();
+
+    return APR_SUCCESS;
+#endif 
+}
+
+APR_DECLARE(apr_status_t) apr_uid_get(apr_uid_t *uid, apr_gid_t *gid,
+                                      const char *username, apr_pool_t *p)
+{
+#ifdef _WIN32_WCE
+    return APR_ENOTIMPL;
+#else
+    SID_NAME_USE sidtype;
+    char anydomain[256];
+    char *domain;
+    DWORD sidlen = 0;
+    DWORD domlen = sizeof(anydomain);
+    DWORD rv;
+    char *pos;
+
+    if ((pos = strchr(username, '/'))) {
+        domain = apr_pstrmemdup(p, username, pos - username);
+        username = pos + 1;
+    }
+    else if ((pos = strchr(username, '\\'))) {
+        domain = apr_pstrmemdup(p, username, pos - username);
+        username = pos + 1;
+    }
+    else {
+        domain = NULL;
+    }
+    /* Get nothing on the first pass ... need to size the sid buffer 
+     */
+    rv = LookupAccountName(domain, username, domain, &sidlen, 
+                           anydomain, &domlen, &sidtype);
+    if (sidlen) {
+        /* Give it back on the second pass
+         */
+        *uid = apr_palloc(p, sidlen);
+        domlen = sizeof(anydomain);
+        rv = LookupAccountName(domain, username, *uid, &sidlen, 
+                               anydomain, &domlen, &sidtype);
+    }
+    if (!sidlen || !rv) {
+        return apr_get_os_error();
+    }
+    /* There doesn't seem to be a simple way to retrieve the primary group sid
+     */
+    *gid = NULL;
+    return APR_SUCCESS;
+#endif
+}
+
+APR_DECLARE(apr_status_t) apr_uid_name_get(char **username, apr_uid_t userid,
+                                           apr_pool_t *p)
+{
+#ifdef _WIN32_WCE
+    *username = apr_pstrdup(p, "Administrator");
+    return APR_SUCCESS;
+#else
+    SID_NAME_USE type;
+    char name[MAX_PATH], domain[MAX_PATH];
+    DWORD cbname = sizeof(name), cbdomain = sizeof(domain);
+    if (!userid)
+        return APR_EINVAL;
+    if (!LookupAccountSid(NULL, userid, name, &cbname, domain, &cbdomain, &type))
+        return apr_get_os_error();
+    if (type != SidTypeUser && type != SidTypeAlias && type != SidTypeWellKnownGroup)
+        return APR_EINVAL;
+    *username = apr_pstrdup(p, name);
+    return APR_SUCCESS;
+#endif
+}
+  
+APR_DECLARE(apr_status_t) apr_uid_compare(apr_uid_t left, apr_uid_t right)
+{
+    if (!left || !right)
+        return APR_EINVAL;
+#ifndef _WIN32_WCE
+    if (!IsValidSid(left) || !IsValidSid(right))
+        return APR_EINVAL;
+    if (!EqualSid(left, right))
+        return APR_EMISMATCH;
+#endif
+    return APR_SUCCESS;
+}
+
diff --git a/util-misc/apr_date.c b/util-misc/apr_date.c
new file mode 100644
index 00000000000..e28e967fb15
--- /dev/null
+++ b/util-misc/apr_date.c
@@ -0,0 +1,637 @@
+/* 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.
+ */
+
+/*
+ * apr_date.c: date parsing utility routines
+ *     These routines are (hopefully) platform independent.
+ * 
+ * 27 Oct 1996  Roy Fielding
+ *     Extracted (with many modifications) from mod_proxy.c and
+ *     tested with over 50,000 randomly chosen valid date strings
+ *     and several hundred variations of invalid date strings.
+ * 
+ */
+
+#include "apr.h"
+#include "apr_lib.h"
+
+#define APR_WANT_STRFUNC
+#include "apr_want.h"
+
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#if APR_HAVE_CTYPE_H
+#include <ctype.h>
+#endif
+
+#include "apr_date.h"
+
+/*
+ * Compare a string to a mask
+ * Mask characters (arbitrary maximum is 256 characters, just in case):
+ *   @ - uppercase letter
+ *   $ - lowercase letter
+ *   & - hex digit
+ *   # - digit
+ *   ~ - digit or space
+ *   * - swallow remaining characters 
+ *  <x> - exact match for any other character
+ */
+APR_DECLARE(int) apr_date_checkmask(const char *data, const char *mask)
+{
+    int i;
+    char d;
+
+    for (i = 0; i < 256; i++) {
+        d = data[i];
+        switch (mask[i]) {
+        case '\0':
+            return (d == '\0');
+
+        case '*':
+            return 1;
+
+        case '@':
+            if (!apr_isupper(d))
+                return 0;
+            break;
+        case '$':
+            if (!apr_islower(d))
+                return 0;
+            break;
+        case '#':
+            if (!apr_isdigit(d))
+                return 0;
+            break;
+        case '&':
+            if (!apr_isxdigit(d))
+                return 0;
+            break;
+        case '~':
+            if ((d != ' ') && !apr_isdigit(d))
+                return 0;
+            break;
+        default:
+            if (mask[i] != d)
+                return 0;
+            break;
+        }
+    }
+    return 0;          /* We only get here if mask is corrupted (exceeds 256) */
+}
+
+/*
+ * Parses an HTTP date in one of three standard forms:
+ *
+ *     Sun, 06 Nov 1994 08:49:37 GMT  ; RFC 822, updated by RFC 1123
+ *     Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
+ *     Sun Nov  6 08:49:37 1994       ; ANSI C's asctime() format
+ *
+ * and returns the apr_time_t number of microseconds since 1 Jan 1970 GMT, 
+ * or APR_DATE_BAD if this would be out of range or if the date is invalid.
+ *
+ * The restricted HTTP syntax is
+ * 
+ *     HTTP-date    = rfc1123-date | rfc850-date | asctime-date
+ *
+ *     rfc1123-date = wkday "," SP date1 SP time SP "GMT"
+ *     rfc850-date  = weekday "," SP date2 SP time SP "GMT"
+ *     asctime-date = wkday SP date3 SP time SP 4DIGIT
+ *
+ *     date1        = 2DIGIT SP month SP 4DIGIT
+ *                    ; day month year (e.g., 02 Jun 1982)
+ *     date2        = 2DIGIT "-" month "-" 2DIGIT
+ *                    ; day-month-year (e.g., 02-Jun-82)
+ *     date3        = month SP ( 2DIGIT | ( SP 1DIGIT ))
+ *                    ; month day (e.g., Jun  2)
+ *
+ *     time         = 2DIGIT ":" 2DIGIT ":" 2DIGIT
+ *                    ; 00:00:00 - 23:59:59
+ *
+ *     wkday        = "Mon" | "Tue" | "Wed"
+ *                  | "Thu" | "Fri" | "Sat" | "Sun"
+ *
+ *     weekday      = "Monday" | "Tuesday" | "Wednesday"
+ *                  | "Thursday" | "Friday" | "Saturday" | "Sunday"
+ *
+ *     month        = "Jan" | "Feb" | "Mar" | "Apr"
+ *                  | "May" | "Jun" | "Jul" | "Aug"
+ *                  | "Sep" | "Oct" | "Nov" | "Dec"
+ *
+ * However, for the sake of robustness (and Netscapeness), we ignore the
+ * weekday and anything after the time field (including the timezone).
+ *
+ * This routine is intended to be very fast; 10x faster than using sscanf.
+ *
+ * Originally from Andrew Daviel <andrew@vancouver-webpages.com>, 29 Jul 96
+ * but many changes since then.
+ *
+ */
+APR_DECLARE(apr_time_t) apr_date_parse_http(const char *date)
+{
+    apr_time_exp_t ds;
+    apr_time_t result;
+    int mint, mon;
+    const char *monstr, *timstr;
+    static const int months[12] =
+    {
+    ('J' << 16) | ('a' << 8) | 'n', ('F' << 16) | ('e' << 8) | 'b',
+    ('M' << 16) | ('a' << 8) | 'r', ('A' << 16) | ('p' << 8) | 'r',
+    ('M' << 16) | ('a' << 8) | 'y', ('J' << 16) | ('u' << 8) | 'n',
+    ('J' << 16) | ('u' << 8) | 'l', ('A' << 16) | ('u' << 8) | 'g',
+    ('S' << 16) | ('e' << 8) | 'p', ('O' << 16) | ('c' << 8) | 't',
+    ('N' << 16) | ('o' << 8) | 'v', ('D' << 16) | ('e' << 8) | 'c'};
+
+    if (!date)
+        return APR_DATE_BAD;
+
+    while (*date && apr_isspace(*date))    /* Find first non-whitespace char */
+        ++date;
+
+    if (*date == '\0') 
+        return APR_DATE_BAD;
+
+    if ((date = strchr(date, ' ')) == NULL)       /* Find space after weekday */
+        return APR_DATE_BAD;
+
+    ++date;        /* Now pointing to first char after space, which should be */
+
+    /* start of the actual date information for all 4 formats. */
+
+    if (apr_date_checkmask(date, "## @$$ #### ##:##:## *")) {
+        /* RFC 1123 format with two days */
+        ds.tm_year = ((date[7] - '0') * 10 + (date[8] - '0') - 19) * 100;
+        if (ds.tm_year < 0)
+            return APR_DATE_BAD;
+
+        ds.tm_year += ((date[9] - '0') * 10) + (date[10] - '0');
+
+        ds.tm_mday = ((date[0] - '0') * 10) + (date[1] - '0');
+
+        monstr = date + 3;
+        timstr = date + 12;
+    }
+    else if (apr_date_checkmask(date, "##-@$$-## ##:##:## *")) { 
+        /* RFC 850 format */
+        ds.tm_year = ((date[7] - '0') * 10) + (date[8] - '0');
+        if (ds.tm_year < 70)
+            ds.tm_year += 100;
+
+        ds.tm_mday = ((date[0] - '0') * 10) + (date[1] - '0');
+
+        monstr = date + 3;
+        timstr = date + 10;
+    }
+    else if (apr_date_checkmask(date, "@$$ ~# ##:##:## ####*")) {
+        /* asctime format */
+        ds.tm_year = ((date[16] - '0') * 10 + (date[17] - '0') - 19) * 100;
+        if (ds.tm_year < 0) 
+            return APR_DATE_BAD;
+
+        ds.tm_year += ((date[18] - '0') * 10) + (date[19] - '0');
+
+        if (date[4] == ' ')
+            ds.tm_mday = 0;
+        else
+            ds.tm_mday = (date[4] - '0') * 10;
+
+        ds.tm_mday += (date[5] - '0');
+
+        monstr = date;
+        timstr = date + 7;
+    }
+    else if (apr_date_checkmask(date, "# @$$ #### ##:##:## *")) {
+        /* RFC 1123 format with one day */
+        ds.tm_year = ((date[6] - '0') * 10 + (date[7] - '0') - 19) * 100;
+        if (ds.tm_year < 0)
+            return APR_DATE_BAD;
+
+        ds.tm_year += ((date[8] - '0') * 10) + (date[9] - '0');
+
+        ds.tm_mday = (date[0] - '0');
+
+        monstr = date + 2;
+        timstr = date + 11;
+    }
+    else
+        return APR_DATE_BAD;
+
+    if (ds.tm_mday <= 0 || ds.tm_mday > 31)
+        return APR_DATE_BAD;
+
+    ds.tm_hour = ((timstr[0] - '0') * 10) + (timstr[1] - '0');
+    ds.tm_min = ((timstr[3] - '0') * 10) + (timstr[4] - '0');
+    ds.tm_sec = ((timstr[6] - '0') * 10) + (timstr[7] - '0');
+
+    if ((ds.tm_hour > 23) || (ds.tm_min > 59) || (ds.tm_sec > 61)) 
+        return APR_DATE_BAD;
+
+    mint = (monstr[0] << 16) | (monstr[1] << 8) | monstr[2];
+    for (mon = 0; mon < 12; mon++)
+        if (mint == months[mon])
+            break;
+
+    if (mon == 12)
+        return APR_DATE_BAD;
+
+    if ((ds.tm_mday == 31) && (mon == 3 || mon == 5 || mon == 8 || mon == 10))
+        return APR_DATE_BAD;
+
+    /* February gets special check for leapyear */
+    if ((mon == 1) &&
+        ((ds.tm_mday > 29) || 
+        ((ds.tm_mday == 29)
+        && ((ds.tm_year & 3)
+        || (((ds.tm_year % 100) == 0)
+        && (((ds.tm_year % 400) != 100)))))))
+        return APR_DATE_BAD;
+
+    ds.tm_mon = mon;
+
+    /* ap_mplode_time uses tm_usec and tm_gmtoff fields, but they haven't 
+     * been set yet. 
+     * It should be safe to just zero out these values.
+     * tm_usec is the number of microseconds into the second.  HTTP only
+     * cares about second granularity.
+     * tm_gmtoff is the number of seconds off of GMT the time is.  By
+     * definition all times going through this function are in GMT, so this
+     * is zero. 
+     */
+    ds.tm_usec = 0;
+    ds.tm_gmtoff = 0;
+    if (apr_time_exp_get(&result, &ds) != APR_SUCCESS) 
+        return APR_DATE_BAD;
+    
+    return result;
+}
+
+/*
+ * Parses a string resembling an RFC 822 date.  This is meant to be
+ * leinent in its parsing of dates.  Hence, this will parse a wider 
+ * range of dates than apr_date_parse_http.
+ *
+ * The prominent mailer (or poster, if mailer is unknown) that has
+ * been seen in the wild is included for the unknown formats.
+ *
+ *     Sun, 06 Nov 1994 08:49:37 GMT  ; RFC 822, updated by RFC 1123
+ *     Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
+ *     Sun Nov  6 08:49:37 1994       ; ANSI C's asctime() format
+ *     Sun, 6 Nov 1994 08:49:37 GMT   ; RFC 822, updated by RFC 1123
+ *     Sun, 06 Nov 94 08:49:37 GMT    ; RFC 822
+ *     Sun, 6 Nov 94 08:49:37 GMT     ; RFC 822
+ *     Sun, 06 Nov 94 08:49 GMT       ; Unknown [drtr@ast.cam.ac.uk] 
+ *     Sun, 6 Nov 94 08:49 GMT        ; Unknown [drtr@ast.cam.ac.uk]
+ *     Sun, 06 Nov 94 8:49:37 GMT     ; Unknown [Elm 70.85]
+ *     Sun, 6 Nov 94 8:49:37 GMT      ; Unknown [Elm 70.85] 
+ *     Mon,  7 Jan 2002 07:21:22 GMT  ; Unknown [Postfix]
+ *     Sun, 06-Nov-1994 08:49:37 GMT  ; RFC 850 with four digit years
+ *
+ */
+
+#define TIMEPARSE(ds,hr10,hr1,min10,min1,sec10,sec1)        \
+    {                                                       \
+        ds.tm_hour = ((hr10 - '0') * 10) + (hr1 - '0');     \
+        ds.tm_min = ((min10 - '0') * 10) + (min1 - '0');    \
+        ds.tm_sec = ((sec10 - '0') * 10) + (sec1 - '0');    \
+    }
+#define TIMEPARSE_STD(ds,timstr)                            \
+    {                                                       \
+        TIMEPARSE(ds, timstr[0],timstr[1],                  \
+                      timstr[3],timstr[4],                  \
+                      timstr[6],timstr[7]);                 \
+    }
+
+APR_DECLARE(apr_time_t) apr_date_parse_rfc(const char *date)
+{
+    apr_time_exp_t ds;
+    apr_time_t result;
+    int mint, mon;
+    const char *monstr, *timstr, *gmtstr;
+    static const int months[12] =
+    {
+    ('J' << 16) | ('a' << 8) | 'n', ('F' << 16) | ('e' << 8) | 'b',
+    ('M' << 16) | ('a' << 8) | 'r', ('A' << 16) | ('p' << 8) | 'r',
+    ('M' << 16) | ('a' << 8) | 'y', ('J' << 16) | ('u' << 8) | 'n',
+    ('J' << 16) | ('u' << 8) | 'l', ('A' << 16) | ('u' << 8) | 'g',
+    ('S' << 16) | ('e' << 8) | 'p', ('O' << 16) | ('c' << 8) | 't',
+    ('N' << 16) | ('o' << 8) | 'v', ('D' << 16) | ('e' << 8) | 'c' };
+
+    if (!date)
+        return APR_DATE_BAD;
+
+    /* Not all dates have text days at the beginning. */
+    if (!apr_isdigit(date[0]))
+    {
+        while (*date && apr_isspace(*date)) /* Find first non-whitespace char */
+            ++date;
+
+        if (*date == '\0') 
+            return APR_DATE_BAD;
+
+        if ((date = strchr(date, ' ')) == NULL)   /* Find space after weekday */
+            return APR_DATE_BAD;
+
+        ++date;    /* Now pointing to first char after space, which should be */    }
+
+    /* start of the actual date information for all 11 formats. */
+    if (apr_date_checkmask(date, "## @$$ #### ##:##:## *")) {   /* RFC 1123 format */
+        ds.tm_year = ((date[7] - '0') * 10 + (date[8] - '0') - 19) * 100;
+
+        if (ds.tm_year < 0)
+            return APR_DATE_BAD;
+
+        ds.tm_year += ((date[9] - '0') * 10) + (date[10] - '0');
+
+        ds.tm_mday = ((date[0] - '0') * 10) + (date[1] - '0');
+
+        monstr = date + 3;
+        timstr = date + 12;
+        gmtstr = date + 21;
+
+        TIMEPARSE_STD(ds, timstr);
+    }
+    else if (apr_date_checkmask(date, "##-@$$-## ##:##:## *")) {/* RFC 850 format  */
+        ds.tm_year = ((date[7] - '0') * 10) + (date[8] - '0');
+
+        if (ds.tm_year < 70)
+            ds.tm_year += 100;
+
+        ds.tm_mday = ((date[0] - '0') * 10) + (date[1] - '0');
+
+        monstr = date + 3;
+        timstr = date + 10;
+        gmtstr = date + 19;
+
+        TIMEPARSE_STD(ds, timstr);
+    }
+    else if (apr_date_checkmask(date, "@$$ ~# ##:##:## ####*")) {
+        /* asctime format */
+        ds.tm_year = ((date[16] - '0') * 10 + (date[17] - '0') - 19) * 100;
+        if (ds.tm_year < 0) 
+            return APR_DATE_BAD;
+
+        ds.tm_year += ((date[18] - '0') * 10) + (date[19] - '0');
+
+        if (date[4] == ' ')
+            ds.tm_mday = 0;
+        else
+            ds.tm_mday = (date[4] - '0') * 10;
+
+        ds.tm_mday += (date[5] - '0');
+
+        monstr = date;
+        timstr = date + 7;
+        gmtstr = NULL;
+
+        TIMEPARSE_STD(ds, timstr);
+    }
+    else if (apr_date_checkmask(date, "# @$$ #### ##:##:## *")) {
+        /* RFC 1123 format*/
+        ds.tm_year = ((date[6] - '0') * 10 + (date[7] - '0') - 19) * 100;
+
+        if (ds.tm_year < 0)
+            return APR_DATE_BAD;
+
+        ds.tm_year += ((date[8] - '0') * 10) + (date[9] - '0');
+        ds.tm_mday = (date[0] - '0');
+
+        monstr = date + 2;
+        timstr = date + 11;
+        gmtstr = date + 20;
+
+        TIMEPARSE_STD(ds, timstr);
+    }
+    else if (apr_date_checkmask(date, "## @$$ ## ##:##:## *")) {
+        /* This is the old RFC 1123 date format - many many years ago, people
+         * used two-digit years.  Oh, how foolish.
+         *
+         * Two-digit day, two-digit year version. */
+        ds.tm_year = ((date[7] - '0') * 10) + (date[8] - '0');
+
+        if (ds.tm_year < 70)
+            ds.tm_year += 100;
+
+        ds.tm_mday = ((date[0] - '0') * 10) + (date[1] - '0');
+
+        monstr = date + 3;
+        timstr = date + 10;
+        gmtstr = date + 19;
+
+        TIMEPARSE_STD(ds, timstr);
+    } 
+    else if (apr_date_checkmask(date, " # @$$ ## ##:##:## *")) {
+        /* This is the old RFC 1123 date format - many many years ago, people
+         * used two-digit years.  Oh, how foolish.
+         *
+         * Space + one-digit day, two-digit year version.*/
+        ds.tm_year = ((date[7] - '0') * 10) + (date[8] - '0');
+
+        if (ds.tm_year < 70)
+            ds.tm_year += 100;
+
+        ds.tm_mday = (date[1] - '0');
+
+        monstr = date + 3;
+        timstr = date + 10;
+        gmtstr = date + 19;
+
+        TIMEPARSE_STD(ds, timstr);
+    } 
+    else if (apr_date_checkmask(date, "# @$$ ## ##:##:## *")) {
+        /* This is the old RFC 1123 date format - many many years ago, people
+         * used two-digit years.  Oh, how foolish.
+         *
+         * One-digit day, two-digit year version. */
+        ds.tm_year = ((date[6] - '0') * 10) + (date[7] - '0');
+
+        if (ds.tm_year < 70)
+            ds.tm_year += 100;
+
+        ds.tm_mday = (date[0] - '0');
+
+        monstr = date + 2;
+        timstr = date + 9;
+        gmtstr = date + 18;
+
+        TIMEPARSE_STD(ds, timstr);
+    } 
+    else if (apr_date_checkmask(date, "## @$$ ## ##:## *")) {
+        /* Loser format.  This is quite bogus.  */
+        ds.tm_year = ((date[7] - '0') * 10) + (date[8] - '0');
+
+        if (ds.tm_year < 70)
+            ds.tm_year += 100;
+
+        ds.tm_mday = ((date[0] - '0') * 10) + (date[1] - '0');
+
+        monstr = date + 3;
+        timstr = date + 10;
+        gmtstr = NULL;
+
+        TIMEPARSE(ds, timstr[0],timstr[1], timstr[3],timstr[4], '0','0');
+    } 
+    else if (apr_date_checkmask(date, "# @$$ ## ##:## *")) {
+        /* Loser format.  This is quite bogus.  */
+        ds.tm_year = ((date[6] - '0') * 10) + (date[7] - '0');
+
+        if (ds.tm_year < 70)
+            ds.tm_year += 100;
+
+        ds.tm_mday = (date[0] - '0');
+
+        monstr = date + 2;
+        timstr = date + 9;
+        gmtstr = NULL;
+
+        TIMEPARSE(ds, timstr[0],timstr[1], timstr[3],timstr[4], '0','0');
+    }
+    else if (apr_date_checkmask(date, "## @$$ ## #:##:## *")) {
+        /* Loser format.  This is quite bogus.  */
+        ds.tm_year = ((date[7] - '0') * 10) + (date[8] - '0');
+
+        if (ds.tm_year < 70)
+            ds.tm_year += 100;
+
+        ds.tm_mday = ((date[0] - '0') * 10) + (date[1] - '0');
+
+        monstr = date + 3;
+        timstr = date + 9;
+        gmtstr = date + 18;
+
+        TIMEPARSE(ds, '0',timstr[1], timstr[3],timstr[4], timstr[6],timstr[7]);
+    }
+    else if (apr_date_checkmask(date, "# @$$ ## #:##:## *")) {
+         /* Loser format.  This is quite bogus.  */
+        ds.tm_year = ((date[6] - '0') * 10) + (date[7] - '0');
+
+        if (ds.tm_year < 70)
+            ds.tm_year += 100;
+
+        ds.tm_mday = (date[0] - '0');
+
+        monstr = date + 2;
+        timstr = date + 8;
+        gmtstr = date + 17;
+
+        TIMEPARSE(ds, '0',timstr[1], timstr[3],timstr[4], timstr[6],timstr[7]);
+    }
+    else if (apr_date_checkmask(date, " # @$$ #### ##:##:## *")) {   
+        /* RFC 1123 format with a space instead of a leading zero. */
+        ds.tm_year = ((date[7] - '0') * 10 + (date[8] - '0') - 19) * 100;
+
+        if (ds.tm_year < 0)
+            return APR_DATE_BAD;
+
+        ds.tm_year += ((date[9] - '0') * 10) + (date[10] - '0');
+
+        ds.tm_mday = (date[1] - '0');
+
+        monstr = date + 3;
+        timstr = date + 12;
+        gmtstr = date + 21;
+
+        TIMEPARSE_STD(ds, timstr);
+    }
+    else if (apr_date_checkmask(date, "##-@$$-#### ##:##:## *")) {
+       /* RFC 1123 with dashes instead of spaces between date/month/year
+        * This also looks like RFC 850 with four digit years.
+        */
+        ds.tm_year = ((date[7] - '0') * 10 + (date[8] - '0') - 19) * 100;
+        if (ds.tm_year < 0)
+            return APR_DATE_BAD;
+
+        ds.tm_year += ((date[9] - '0') * 10) + (date[10] - '0');
+
+        ds.tm_mday = ((date[0] - '0') * 10) + (date[1] - '0');
+
+        monstr = date + 3;
+        timstr = date + 12;
+        gmtstr = date + 21;
+
+        TIMEPARSE_STD(ds, timstr);
+    }
+    else
+        return APR_DATE_BAD;
+
+    if (ds.tm_mday <= 0 || ds.tm_mday > 31)
+        return APR_DATE_BAD;
+
+    if ((ds.tm_hour > 23) || (ds.tm_min > 59) || (ds.tm_sec > 61)) 
+        return APR_DATE_BAD;
+
+    mint = (monstr[0] << 16) | (monstr[1] << 8) | monstr[2];
+    for (mon = 0; mon < 12; mon++)
+        if (mint == months[mon])
+            break;
+
+    if (mon == 12)
+        return APR_DATE_BAD;
+
+    if ((ds.tm_mday == 31) && (mon == 3 || mon == 5 || mon == 8 || mon == 10))
+        return APR_DATE_BAD;
+
+    /* February gets special check for leapyear */
+
+    if ((mon == 1) &&
+        ((ds.tm_mday > 29)
+        || ((ds.tm_mday == 29)
+        && ((ds.tm_year & 3)
+        || (((ds.tm_year % 100) == 0)
+        && (((ds.tm_year % 400) != 100)))))))
+        return APR_DATE_BAD;
+
+    ds.tm_mon = mon;
+
+    /* tm_gmtoff is the number of seconds off of GMT the time is.
+     *
+     * We only currently support: [+-]ZZZZ where Z is the offset in
+     * hours from GMT.
+     *
+     * If there is any confusion, tm_gmtoff will remain 0.
+     */
+    ds.tm_gmtoff = 0;
+
+    /* Do we have a timezone ? */
+    if (gmtstr) {
+        int offset;
+        switch (*gmtstr) {
+        case '-':
+            offset = atoi(gmtstr+1);
+            ds.tm_gmtoff -= (offset / 100) * 60 * 60;
+            ds.tm_gmtoff -= (offset % 100) * 60;
+            break;
+        case '+':
+            offset = atoi(gmtstr+1);
+            ds.tm_gmtoff += (offset / 100) * 60 * 60;
+            ds.tm_gmtoff += (offset % 100) * 60;
+            break;
+        }
+    }
+
+    /* apr_time_exp_get uses tm_usec field, but it hasn't been set yet. 
+     * It should be safe to just zero out this value.
+     * tm_usec is the number of microseconds into the second.  HTTP only
+     * cares about second granularity.
+     */
+    ds.tm_usec = 0;
+
+    if (apr_time_exp_gmt_get(&result, &ds) != APR_SUCCESS) 
+        return APR_DATE_BAD;
+    
+    return result;
+}
diff --git a/util-misc/apr_queue.c b/util-misc/apr_queue.c
new file mode 100644
index 00000000000..dbc879b3544
--- /dev/null
+++ b/util-misc/apr_queue.c
@@ -0,0 +1,378 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+
+#if APR_HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if APR_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "apu.h"
+#include "apr_portable.h"
+#include "apr_thread_mutex.h"
+#include "apr_thread_cond.h"
+#include "apr_errno.h"
+#include "apr_queue.h"
+
+#if APR_HAS_THREADS
+/* 
+ * define this to get debug messages
+ *
+#define QUEUE_DEBUG
+ */
+
+struct apr_queue_t {
+    void              **data;
+    unsigned int        nelts; /**< # elements */
+    unsigned int        in;    /**< next empty location */
+    unsigned int        out;   /**< next filled location */
+    unsigned int        bounds;/**< max size of queue */
+    unsigned int        full_waiters;
+    unsigned int        empty_waiters;
+    apr_thread_mutex_t *one_big_mutex;
+    apr_thread_cond_t  *not_empty;
+    apr_thread_cond_t  *not_full;
+    int                 terminated;
+};
+
+#ifdef QUEUE_DEBUG
+static void Q_DBG(char*msg, apr_queue_t *q) {
+    fprintf(stderr, "%ld\t#%d in %d out %d\t%s\n", 
+                    apr_os_thread_current(),
+                    q->nelts, q->in, q->out,
+                    msg
+                    );
+}
+#else
+#define Q_DBG(x,y) 
+#endif
+
+/**
+ * Detects when the apr_queue_t is full. This utility function is expected
+ * to be called from within critical sections, and is not threadsafe.
+ */
+#define apr_queue_full(queue) ((queue)->nelts == (queue)->bounds)
+
+/**
+ * Detects when the apr_queue_t is empty. This utility function is expected
+ * to be called from within critical sections, and is not threadsafe.
+ */
+#define apr_queue_empty(queue) ((queue)->nelts == 0)
+
+/**
+ * Callback routine that is called to destroy this
+ * apr_queue_t when its pool is destroyed.
+ */
+static apr_status_t queue_destroy(void *data) 
+{
+    apr_queue_t *queue = data;
+
+    /* Ignore errors here, we can't do anything about them anyway. */
+
+    apr_thread_cond_destroy(queue->not_empty);
+    apr_thread_cond_destroy(queue->not_full);
+    apr_thread_mutex_destroy(queue->one_big_mutex);
+
+    return APR_SUCCESS;
+}
+
+/**
+ * Initialize the apr_queue_t.
+ */
+APR_DECLARE(apr_status_t) apr_queue_create(apr_queue_t **q, 
+                                           unsigned int queue_capacity, 
+                                           apr_pool_t *a)
+{
+    apr_status_t rv;
+    apr_queue_t *queue;
+    queue = apr_palloc(a, sizeof(apr_queue_t));
+    *q = queue;
+
+    /* nested doesn't work ;( */
+    rv = apr_thread_mutex_create(&queue->one_big_mutex,
+                                 APR_THREAD_MUTEX_UNNESTED,
+                                 a);
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
+    rv = apr_thread_cond_create(&queue->not_empty, a);
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
+    rv = apr_thread_cond_create(&queue->not_full, a);
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
+    /* Set all the data in the queue to NULL */
+    queue->data = apr_pcalloc(a, queue_capacity * sizeof(void*));
+    queue->bounds = queue_capacity;
+    queue->nelts = 0;
+    queue->in = 0;
+    queue->out = 0;
+    queue->terminated = 0;
+    queue->full_waiters = 0;
+    queue->empty_waiters = 0;
+
+    apr_pool_cleanup_register(a, queue, queue_destroy, apr_pool_cleanup_null);
+
+    return APR_SUCCESS;
+}
+
+/**
+ * Push new data onto the queue. Blocks if the queue is full. Once
+ * the push operation has completed, it signals other threads waiting
+ * in apr_queue_pop() that they may continue consuming sockets.
+ */
+static apr_status_t queue_push(apr_queue_t *queue, void *data,
+                               apr_interval_time_t timeout)
+{
+    apr_status_t rv;
+
+    if (queue->terminated) {
+        return APR_EOF; /* no more elements ever again */
+    }
+
+    rv = apr_thread_mutex_lock(queue->one_big_mutex);
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
+    if (apr_queue_full(queue)) {
+        if (!timeout) {
+            apr_thread_mutex_unlock(queue->one_big_mutex);
+            return APR_EAGAIN;
+        }
+        if (!queue->terminated) {
+            queue->full_waiters++;
+            if (timeout > 0) {
+                rv = apr_thread_cond_timedwait(queue->not_full,
+                                               queue->one_big_mutex,
+                                               timeout);
+            }
+            else {
+                rv = apr_thread_cond_wait(queue->not_full,
+                                          queue->one_big_mutex);
+            }
+            queue->full_waiters--;
+            if (rv != APR_SUCCESS) {
+                apr_thread_mutex_unlock(queue->one_big_mutex);
+                return rv;
+            }
+        }
+        /* If we wake up and it's still empty, then we were interrupted */
+        if (apr_queue_full(queue)) {
+            Q_DBG("queue full (intr)", queue);
+            rv = apr_thread_mutex_unlock(queue->one_big_mutex);
+            if (rv != APR_SUCCESS) {
+                return rv;
+            }
+            if (queue->terminated) {
+                return APR_EOF; /* no more elements ever again */
+            }
+            else {
+                return APR_EINTR;
+            }
+        }
+    }
+
+    queue->data[queue->in] = data;
+    queue->in++;
+    if (queue->in >= queue->bounds)
+        queue->in -= queue->bounds;
+    queue->nelts++;
+
+    if (queue->empty_waiters) {
+        Q_DBG("sig !empty", queue);
+        rv = apr_thread_cond_signal(queue->not_empty);
+        if (rv != APR_SUCCESS) {
+            apr_thread_mutex_unlock(queue->one_big_mutex);
+            return rv;
+        }
+    }
+
+    rv = apr_thread_mutex_unlock(queue->one_big_mutex);
+    return rv;
+}
+
+APR_DECLARE(apr_status_t) apr_queue_push(apr_queue_t *queue, void *data)
+{
+    return queue_push(queue, data, -1);
+}
+
+/**
+ * Push new data onto the queue. If the queue is full, return APR_EAGAIN. If
+ * the push operation completes successfully, it signals other threads
+ * waiting in apr_queue_pop() that they may continue consuming sockets.
+ */
+APR_DECLARE(apr_status_t) apr_queue_trypush(apr_queue_t *queue, void *data)
+{
+    return queue_push(queue, data, 0);
+}
+
+APR_DECLARE(apr_status_t) apr_queue_timedpush(apr_queue_t *queue, void *data,
+                                              apr_interval_time_t timeout)
+{
+    return queue_push(queue, data, timeout);
+}
+
+/**
+ * not thread safe
+ */
+APR_DECLARE(unsigned int) apr_queue_size(apr_queue_t *queue) {
+    return queue->nelts;
+}
+
+/**
+ * Retrieves the next item from the queue. If there are no
+ * items available, it will either return APR_EAGAIN (timeout = 0),
+ * or block until one becomes available (infinitely with timeout < 0,
+ * otherwise until the given timeout expires). Once retrieved, the
+ * item is placed into the address specified by 'data'.
+ */
+static apr_status_t queue_pop(apr_queue_t *queue, void **data,
+                              apr_interval_time_t timeout)
+{
+    apr_status_t rv;
+
+    if (queue->terminated) {
+        return APR_EOF; /* no more elements ever again */
+    }
+
+    rv = apr_thread_mutex_lock(queue->one_big_mutex);
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
+    /* Keep waiting until we wake up and find that the queue is not empty. */
+    if (apr_queue_empty(queue)) {
+        if (!timeout) {
+            apr_thread_mutex_unlock(queue->one_big_mutex);
+            return APR_EAGAIN;
+        }
+        if (!queue->terminated) {
+            queue->empty_waiters++;
+            if (timeout > 0) {
+                rv = apr_thread_cond_timedwait(queue->not_empty,
+                                               queue->one_big_mutex,
+                                               timeout);
+            }
+            else {
+                rv = apr_thread_cond_wait(queue->not_empty,
+                                          queue->one_big_mutex);
+            }
+            queue->empty_waiters--;
+            if (rv != APR_SUCCESS) {
+                apr_thread_mutex_unlock(queue->one_big_mutex);
+                return rv;
+            }
+        }
+        /* If we wake up and it's still empty, then we were interrupted */
+        if (apr_queue_empty(queue)) {
+            Q_DBG("queue empty (intr)", queue);
+            rv = apr_thread_mutex_unlock(queue->one_big_mutex);
+            if (rv != APR_SUCCESS) {
+                return rv;
+            }
+            if (queue->terminated) {
+                return APR_EOF; /* no more elements ever again */
+            }
+            else {
+                return APR_EINTR;
+            }
+        }
+    } 
+
+    *data = queue->data[queue->out];
+    queue->nelts--;
+
+    queue->out++;
+    if (queue->out >= queue->bounds)
+        queue->out -= queue->bounds;
+    if (queue->full_waiters) {
+        Q_DBG("signal !full", queue);
+        rv = apr_thread_cond_signal(queue->not_full);
+        if (rv != APR_SUCCESS) {
+            apr_thread_mutex_unlock(queue->one_big_mutex);
+            return rv;
+        }
+    }
+
+    rv = apr_thread_mutex_unlock(queue->one_big_mutex);
+    return rv;
+}
+
+APR_DECLARE(apr_status_t) apr_queue_pop(apr_queue_t *queue, void **data)
+{
+    return queue_pop(queue, data, -1);
+}
+
+APR_DECLARE(apr_status_t) apr_queue_trypop(apr_queue_t *queue, void **data)
+{
+    return queue_pop(queue, data, 0);
+}
+
+APR_DECLARE(apr_status_t) apr_queue_timedpop(apr_queue_t *queue, void **data,
+                                             apr_interval_time_t timeout)
+{
+    return queue_pop(queue, data, timeout);
+}
+
+APR_DECLARE(apr_status_t) apr_queue_interrupt_all(apr_queue_t *queue)
+{
+    apr_status_t rv;
+    Q_DBG("intr all", queue);    
+    if ((rv = apr_thread_mutex_lock(queue->one_big_mutex)) != APR_SUCCESS) {
+        return rv;
+    }
+    apr_thread_cond_broadcast(queue->not_empty);
+    apr_thread_cond_broadcast(queue->not_full);
+
+    if ((rv = apr_thread_mutex_unlock(queue->one_big_mutex)) != APR_SUCCESS) {
+        return rv;
+    }
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_queue_term(apr_queue_t *queue)
+{
+    apr_status_t rv;
+
+    if ((rv = apr_thread_mutex_lock(queue->one_big_mutex)) != APR_SUCCESS) {
+        return rv;
+    }
+
+    /* we must hold one_big_mutex when setting this... otherwise,
+     * we could end up setting it and waking everybody up just after a 
+     * would-be popper checks it but right before they block
+     */
+    queue->terminated = 1;
+    if ((rv = apr_thread_mutex_unlock(queue->one_big_mutex)) != APR_SUCCESS) {
+        return rv;
+    }
+    return apr_queue_interrupt_all(queue);
+}
+
+#endif /* APR_HAS_THREADS */
diff --git a/util-misc/apr_reslist.c b/util-misc/apr_reslist.c
new file mode 100644
index 00000000000..ecc17a7d4d6
--- /dev/null
+++ b/util-misc/apr_reslist.c
@@ -0,0 +1,479 @@
+/* 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 <assert.h>
+
+#include "apu.h"
+#include "apr_reslist.h"
+#include "apr_errno.h"
+#include "apr_strings.h"
+#include "apr_thread_mutex.h"
+#include "apr_thread_cond.h"
+#include "apr_ring.h"
+
+/**
+ * A single resource element.
+ */
+struct apr_res_t {
+    apr_time_t freed;
+    void *opaque;
+    APR_RING_ENTRY(apr_res_t) link;
+};
+typedef struct apr_res_t apr_res_t;
+
+/**
+ * A ring of resources representing the list of available resources.
+ */
+APR_RING_HEAD(apr_resring_t, apr_res_t);
+typedef struct apr_resring_t apr_resring_t;
+
+struct apr_reslist_t {
+    apr_pool_t *pool; /* the pool used in constructor and destructor calls */
+    int ntotal;     /* total number of resources managed by this list */
+    int nidle;      /* number of available resources */
+    int min;  /* desired minimum number of available resources */
+    int smax; /* soft maximum on the total number of resources */
+    int hmax; /* hard maximum on the total number of resources */
+    apr_interval_time_t ttl; /* TTL when we have too many resources */
+    apr_interval_time_t timeout; /* Timeout for waiting on resource */
+    apr_reslist_constructor constructor;
+    apr_reslist_destructor destructor;
+    void *params; /* opaque data passed to constructor and destructor calls */
+    apr_resring_t avail_list;
+    apr_resring_t free_list;
+#if APR_HAS_THREADS
+    apr_thread_mutex_t *listlock;
+    apr_thread_cond_t *avail;
+#endif
+};
+
+/**
+ * Grab a resource from the front of the resource list.
+ * Assumes: that the reslist is locked.
+ */
+static apr_res_t *pop_resource(apr_reslist_t *reslist)
+{
+    apr_res_t *res;
+    res = APR_RING_FIRST(&reslist->avail_list);
+    APR_RING_REMOVE(res, link);
+    reslist->nidle--;
+    return res;
+}
+
+/**
+ * Add a resource to the beginning of the list, set the time at which
+ * it was added to the list.
+ * Assumes: that the reslist is locked.
+ */
+static void push_resource(apr_reslist_t *reslist, apr_res_t *resource)
+{
+    APR_RING_INSERT_HEAD(&reslist->avail_list, resource, apr_res_t, link);
+    resource->freed = apr_time_now();
+    reslist->nidle++;
+}
+
+/**
+ * Get an resource container from the free list or create a new one.
+ */
+static apr_res_t *get_container(apr_reslist_t *reslist)
+{
+    apr_res_t *res;
+
+    if (!APR_RING_EMPTY(&reslist->free_list, apr_res_t, link)) {
+        res = APR_RING_FIRST(&reslist->free_list);
+        APR_RING_REMOVE(res, link);
+    }
+    else
+        res = apr_pcalloc(reslist->pool, sizeof(*res));
+    return res;
+}
+
+/**
+ * Free up a resource container by placing it on the free list.
+ */
+static void free_container(apr_reslist_t *reslist, apr_res_t *container)
+{
+    APR_RING_INSERT_TAIL(&reslist->free_list, container, apr_res_t, link);
+}
+
+/**
+ * Create a new resource and return it.
+ * Assumes: that the reslist is locked.
+ */
+static apr_status_t create_resource(apr_reslist_t *reslist, apr_res_t **ret_res)
+{
+    apr_status_t rv;
+    apr_res_t *res;
+
+    res = get_container(reslist);
+
+    rv = reslist->constructor(&res->opaque, reslist->params, reslist->pool);
+
+    *ret_res = res;
+    return rv;
+}
+
+/**
+ * Destroy a single idle resource.
+ * Assumes: that the reslist is locked.
+ */
+static apr_status_t destroy_resource(apr_reslist_t *reslist, apr_res_t *res)
+{
+    return reslist->destructor(res->opaque, reslist->params, reslist->pool);
+}
+
+static apr_status_t reslist_cleanup(void *data_)
+{
+    apr_status_t rv = APR_SUCCESS;
+    apr_reslist_t *rl = data_;
+    apr_res_t *res;
+
+#if APR_HAS_THREADS
+    apr_thread_mutex_lock(rl->listlock);
+    apr_pool_owner_set(rl->pool, 0);
+#endif
+
+    while (rl->nidle > 0) {
+        apr_status_t rv1;
+        res = pop_resource(rl);
+        rl->ntotal--;
+        rv1 = destroy_resource(rl, res);
+        if (rv1 != APR_SUCCESS) {
+            rv = rv1;  /* loses info in the unlikely event of
+                        * multiple *different* failures */
+        }
+        free_container(rl, res);
+    }
+
+    assert(rl->nidle == 0);
+    assert(rl->ntotal == 0);
+
+#if APR_HAS_THREADS
+    apr_thread_mutex_unlock(rl->listlock);
+    apr_thread_mutex_destroy(rl->listlock);
+    apr_thread_cond_destroy(rl->avail);
+#endif
+
+    return rv;
+}
+
+/**
+ * Perform routine maintenance on the resource list. This call
+ * may instantiate new resources or expire old resources.
+ */
+APR_DECLARE(apr_status_t) apr_reslist_maintain(apr_reslist_t *reslist)
+{
+    apr_time_t now;
+    apr_status_t rv;
+    apr_res_t *res;
+    int created_one = 0;
+
+#if APR_HAS_THREADS
+    apr_thread_mutex_lock(reslist->listlock);
+    apr_pool_owner_set(reslist->pool, 0);
+#endif
+
+    /* Check if we need to create more resources, and if we are allowed to. */
+    while (reslist->nidle < reslist->min && reslist->ntotal < reslist->hmax) {
+        /* Create the resource */
+        rv = create_resource(reslist, &res);
+        if (rv != APR_SUCCESS) {
+            free_container(reslist, res);
+#if APR_HAS_THREADS
+            apr_thread_mutex_unlock(reslist->listlock);
+#endif
+            return rv;
+        }
+        /* Add it to the list */
+        push_resource(reslist, res);
+        /* Update our counters */
+        reslist->ntotal++;
+        /* If someone is waiting on that guy, wake them up. */
+#if APR_HAS_THREADS
+        rv = apr_thread_cond_signal(reslist->avail);
+        if (rv != APR_SUCCESS) {
+            apr_thread_mutex_unlock(reslist->listlock);
+            return rv;
+        }
+#endif
+        created_one++;
+    }
+
+    /* We don't need to see if we're over the max if we were under it before */
+    if (created_one) {
+#if APR_HAS_THREADS
+        apr_thread_mutex_unlock(reslist->listlock);
+#endif
+        return APR_SUCCESS;
+    }
+
+    /* Check if we need to expire old resources */
+    now = apr_time_now();
+    while (reslist->nidle > reslist->smax && reslist->nidle > 0) {
+        /* Peak at the last resource in the list */
+        res = APR_RING_LAST(&reslist->avail_list);
+        /* See if the oldest entry should be expired */
+        if (now - res->freed < reslist->ttl) {
+            /* If this entry is too young, none of the others
+             * will be ready to be expired either, so we are done. */
+            break;
+        }
+        APR_RING_REMOVE(res, link);
+        reslist->nidle--;
+        reslist->ntotal--;
+        rv = destroy_resource(reslist, res);
+        free_container(reslist, res);
+        if (rv != APR_SUCCESS) {
+#if APR_HAS_THREADS
+            apr_thread_mutex_unlock(reslist->listlock);
+#endif
+            return rv;
+        }
+    }
+
+#if APR_HAS_THREADS
+    apr_thread_mutex_unlock(reslist->listlock);
+#endif
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_reslist_create(apr_reslist_t **reslist,
+                                             int min, int smax, int hmax,
+                                             apr_interval_time_t ttl,
+                                             apr_reslist_constructor con,
+                                             apr_reslist_destructor de,
+                                             void *params,
+                                             apr_pool_t *pool)
+{
+    apr_status_t rv;
+    apr_reslist_t *rl;
+
+    /* Do some sanity checks so we don't thrash around in the
+     * maintenance routine later. */
+    if (min < 0 || min > smax || min > hmax || smax > hmax || hmax == 0 ||
+        ttl < 0) {
+        return APR_EINVAL;
+    }
+
+#if !APR_HAS_THREADS
+    /* There can be only one resource when we have no threads. */
+    if (min > 0) {
+        min = 1;
+    }
+    if (smax > 0) {
+        smax = 1;
+    }
+    hmax = 1;
+#endif
+
+    rl = apr_pcalloc(pool, sizeof(*rl));
+    rl->pool = pool;
+    rl->min = min;
+    rl->smax = smax;
+    rl->hmax = hmax;
+    rl->ttl = ttl;
+    rl->constructor = con;
+    rl->destructor = de;
+    rl->params = params;
+
+    APR_RING_INIT(&rl->avail_list, apr_res_t, link);
+    APR_RING_INIT(&rl->free_list, apr_res_t, link);
+
+#if APR_HAS_THREADS
+    rv = apr_thread_mutex_create(&rl->listlock, APR_THREAD_MUTEX_DEFAULT,
+                                 pool);
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+    rv = apr_thread_cond_create(&rl->avail, pool);
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+#endif
+
+    rv = apr_reslist_maintain(rl);
+    if (rv != APR_SUCCESS) {
+        /* Destroy what we've created so far.
+         */
+        reslist_cleanup(rl);
+        return rv;
+    }
+
+    apr_pool_cleanup_register(rl->pool, rl, reslist_cleanup,
+                              apr_pool_cleanup_null);
+
+    *reslist = rl;
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_reslist_destroy(apr_reslist_t *reslist)
+{
+    return apr_pool_cleanup_run(reslist->pool, reslist, reslist_cleanup);
+}
+
+APR_DECLARE(apr_status_t) apr_reslist_acquire(apr_reslist_t *reslist,
+                                              void **resource)
+{
+    apr_status_t rv;
+    apr_res_t *res;
+    apr_time_t now;
+
+#if APR_HAS_THREADS
+    apr_thread_mutex_lock(reslist->listlock);
+    apr_pool_owner_set(reslist->pool, 0);
+#endif
+    /* If there are idle resources on the available list, use
+     * them right away. */
+    now = apr_time_now();
+    while (reslist->nidle > 0) {
+        /* Pop off the first resource */
+        res = pop_resource(reslist);
+        if (reslist->ttl && (now - res->freed >= reslist->ttl)) {
+            /* this res is expired - kill it */
+            reslist->ntotal--;
+            rv = destroy_resource(reslist, res);
+            free_container(reslist, res);
+            if (rv != APR_SUCCESS) {
+#if APR_HAS_THREADS
+                apr_thread_mutex_unlock(reslist->listlock);
+#endif
+                return rv;  /* FIXME: this might cause unnecessary fails */
+            }
+            continue;
+        }
+        *resource = res->opaque;
+        free_container(reslist, res);
+#if APR_HAS_THREADS
+        apr_thread_mutex_unlock(reslist->listlock);
+#endif
+        return APR_SUCCESS;
+    }
+    /* If we've hit our max, block until we're allowed to create
+     * a new one, or something becomes free. */
+    while (reslist->ntotal >= reslist->hmax && reslist->nidle <= 0) {
+#if APR_HAS_THREADS
+        if (reslist->timeout) {
+            if ((rv = apr_thread_cond_timedwait(reslist->avail, 
+                reslist->listlock, reslist->timeout)) != APR_SUCCESS) {
+                apr_thread_mutex_unlock(reslist->listlock);
+                return rv;
+            }
+        }
+        else {
+            apr_thread_cond_wait(reslist->avail, reslist->listlock);
+        }
+#else
+        return APR_EAGAIN;
+#endif
+    }
+    /* If we popped out of the loop, first try to see if there
+     * are new resources available for immediate use. */
+    if (reslist->nidle > 0) {
+        res = pop_resource(reslist);
+        *resource = res->opaque;
+        free_container(reslist, res);
+#if APR_HAS_THREADS
+        apr_thread_mutex_unlock(reslist->listlock);
+#endif
+        return APR_SUCCESS;
+    }
+    /* Otherwise the reason we dropped out of the loop
+     * was because there is a new slot available, so create
+     * a resource to fill the slot and use it. */
+    else {
+        rv = create_resource(reslist, &res);
+        if (rv == APR_SUCCESS) {
+            reslist->ntotal++;
+            *resource = res->opaque;
+        }
+        free_container(reslist, res);
+#if APR_HAS_THREADS
+        apr_thread_mutex_unlock(reslist->listlock);
+#endif
+        return rv;
+    }
+}
+
+APR_DECLARE(apr_status_t) apr_reslist_release(apr_reslist_t *reslist,
+                                              void *resource)
+{
+    apr_res_t *res;
+
+#if APR_HAS_THREADS
+    apr_thread_mutex_lock(reslist->listlock);
+    apr_pool_owner_set(reslist->pool, 0);
+#endif
+    res = get_container(reslist);
+    res->opaque = resource;
+    push_resource(reslist, res);
+#if APR_HAS_THREADS
+    apr_thread_cond_signal(reslist->avail);
+    apr_thread_mutex_unlock(reslist->listlock);
+#endif
+
+    return apr_reslist_maintain(reslist);
+}
+
+APR_DECLARE(void) apr_reslist_timeout_set(apr_reslist_t *reslist,
+                                          apr_interval_time_t timeout)
+{
+    reslist->timeout = timeout;
+}
+
+APR_DECLARE(apr_uint32_t) apr_reslist_acquired_count(apr_reslist_t *reslist)
+{
+    apr_uint32_t count;
+
+#if APR_HAS_THREADS
+    apr_thread_mutex_lock(reslist->listlock);
+    apr_pool_owner_set(reslist->pool, 0);
+#endif
+    count = reslist->ntotal - reslist->nidle;
+#if APR_HAS_THREADS
+    apr_thread_mutex_unlock(reslist->listlock);
+#endif
+
+    return count;
+}
+
+APR_DECLARE(apr_status_t) apr_reslist_invalidate(apr_reslist_t *reslist,
+                                                 void *resource)
+{
+    apr_status_t ret;
+#if APR_HAS_THREADS
+    apr_thread_mutex_lock(reslist->listlock);
+    apr_pool_owner_set(reslist->pool, 0);
+#endif
+    ret = reslist->destructor(resource, reslist->params, reslist->pool);
+    reslist->ntotal--;
+#if APR_HAS_THREADS
+    apr_thread_cond_signal(reslist->avail);
+    apr_thread_mutex_unlock(reslist->listlock);
+#endif
+    return ret;
+}
+
+APR_DECLARE(void) apr_reslist_cleanup_order_set(apr_reslist_t *rl,
+                                                apr_uint32_t mode)
+{
+    apr_pool_cleanup_kill(rl->pool, rl, reslist_cleanup);
+    if (mode == APR_RESLIST_CLEANUP_FIRST)
+        apr_pool_pre_cleanup_register(rl->pool, rl, reslist_cleanup);
+    else
+        apr_pool_cleanup_register(rl->pool, rl, reslist_cleanup,
+                                  apr_pool_cleanup_null);
+}
diff --git a/util-misc/apr_rmm.c b/util-misc/apr_rmm.c
new file mode 100644
index 00000000000..91e30885fc2
--- /dev/null
+++ b/util-misc/apr_rmm.c
@@ -0,0 +1,457 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_general.h"
+#include "apr_rmm.h"
+#include "apr_errno.h"
+#include "apr_lib.h"
+#include "apr_strings.h"
+
+/* The RMM region is made up of two doubly-linked-list of blocks; the
+ * list of used blocks, and the list of free blocks (either list may
+ * be empty).  The base pointer, rmm->base, points at the beginning of
+ * the shmem region in use.  Each block is addressable by an
+ * apr_rmm_off_t value, which represents the offset from the base
+ * pointer.  The term "address" is used here to mean such a value; an
+ * "offset from rmm->base".
+ *
+ * The RMM region contains exactly one "rmm_hdr_block_t" structure,
+ * the "header block", which is always stored at the base pointer.
+ * The firstused field in this structure is the address of the first
+ * block in the "used blocks" list; the firstfree field is the address
+ * of the first block in the "free blocks" list.
+ *
+ * Each block is prefixed by an "rmm_block_t" structure, followed by
+ * the caller-usable region represented by the block.  The next and
+ * prev fields of the structure are zero if the block is at the end or
+ * beginning of the linked-list respectively, or otherwise hold the
+ * address of the next and previous blocks in the list.  ("address 0",
+ * i.e. rmm->base is *not* a valid address for a block, since the
+ * header block is always stored at that address).
+ *
+ * At creation, the RMM region is initialized to hold a single block
+ * on the free list representing the entire available shm segment
+ * (minus header block); subsequent allocation and deallocation of
+ * blocks involves splitting blocks and coalescing adjacent blocks,
+ * and switching them between the free and used lists as
+ * appropriate. */
+
+typedef struct rmm_block_t {
+    apr_size_t size;
+    apr_rmm_off_t prev;
+    apr_rmm_off_t next;
+} rmm_block_t;
+
+/* Always at our apr_rmm_off(0):
+ */
+typedef struct rmm_hdr_block_t {
+    apr_size_t abssize;
+    apr_rmm_off_t /* rmm_block_t */ firstused;
+    apr_rmm_off_t /* rmm_block_t */ firstfree;
+} rmm_hdr_block_t;
+
+#define RMM_HDR_BLOCK_SIZE (APR_ALIGN_DEFAULT(sizeof(rmm_hdr_block_t)))
+#define RMM_BLOCK_SIZE (APR_ALIGN_DEFAULT(sizeof(rmm_block_t)))
+
+struct apr_rmm_t {
+    apr_pool_t *p;
+    rmm_hdr_block_t *base;
+    apr_size_t size;
+    apr_anylock_t lock;
+};
+
+static apr_rmm_off_t find_block_by_offset(apr_rmm_t *rmm, apr_rmm_off_t next, 
+                                          apr_rmm_off_t find, int includes)
+{
+    apr_rmm_off_t prev = 0;
+
+    while (next) {
+        struct rmm_block_t *blk = (rmm_block_t*)((char*)rmm->base + next);
+
+        if (find == next)
+            return next;
+
+        /* Overshot? */
+        if (find < next)
+            return includes ? prev : 0;
+
+        prev = next;
+        next = blk->next;
+    }
+    return includes ? prev : 0;
+}
+
+static apr_rmm_off_t find_block_of_size(apr_rmm_t *rmm, apr_size_t size)
+{
+    apr_rmm_off_t next = rmm->base->firstfree;
+    apr_rmm_off_t best = 0;
+    apr_rmm_off_t bestsize = 0;
+
+    while (next) {
+        struct rmm_block_t *blk = (rmm_block_t*)((char*)rmm->base + next);
+
+        if (blk->size == size)
+            return next;
+
+        if (blk->size >= size) {
+            /* XXX: sub optimal algorithm 
+             * We need the most thorough best-fit logic, since we can
+             * never grow our rmm, we are SOL when we hit the wall.
+             */
+            if (!bestsize || (blk->size < bestsize)) {
+                bestsize = blk->size;
+                best = next;
+            }
+        }
+
+        next = blk->next;
+    }
+
+    if (bestsize > RMM_BLOCK_SIZE + size) {
+        struct rmm_block_t *blk = (rmm_block_t*)((char*)rmm->base + best);
+        struct rmm_block_t *new = (rmm_block_t*)((char*)rmm->base + best + size);
+
+        new->size = blk->size - size;
+        new->next = blk->next;
+        new->prev = best;
+
+        blk->size = size;
+        blk->next = best + size;
+
+        if (new->next) {
+            blk = (rmm_block_t*)((char*)rmm->base + new->next);
+            blk->prev = best + size;
+        }
+    }
+
+    return best;
+}
+
+static void move_block(apr_rmm_t *rmm, apr_rmm_off_t this, int free)
+{   
+    struct rmm_block_t *blk = (rmm_block_t*)((char*)rmm->base + this);
+
+    /* close the gap */
+    if (blk->prev) {
+        struct rmm_block_t *prev = (rmm_block_t*)((char*)rmm->base + blk->prev);
+        prev->next = blk->next;
+    }
+    else {
+        if (free) {
+            rmm->base->firstused = blk->next;
+        }
+        else {
+            rmm->base->firstfree = blk->next;
+        }
+    }
+    if (blk->next) {
+        struct rmm_block_t *next = (rmm_block_t*)((char*)rmm->base + blk->next);
+        next->prev = blk->prev;
+    }
+
+    /* now find it in the other list, pushing it to the head if required */
+    if (free) {
+        blk->prev = find_block_by_offset(rmm, rmm->base->firstfree, this, 1);
+        if (!blk->prev) {
+            blk->next = rmm->base->firstfree;
+            rmm->base->firstfree = this;
+        }
+    }
+    else {
+        blk->prev = find_block_by_offset(rmm, rmm->base->firstused, this, 1);
+        if (!blk->prev) {
+            blk->next = rmm->base->firstused;
+            rmm->base->firstused = this;
+        }
+    }
+
+    /* and open it up */
+    if (blk->prev) {
+        struct rmm_block_t *prev = (rmm_block_t*)((char*)rmm->base + blk->prev);
+        if (free && (blk->prev + prev->size == this)) {
+            /* Collapse us into our predecessor */
+            prev->size += blk->size;
+            this = blk->prev;
+            blk = prev;
+        }
+        else {
+            blk->next = prev->next;
+            prev->next = this;
+        }
+    }
+
+    if (blk->next) {
+        struct rmm_block_t *next = (rmm_block_t*)((char*)rmm->base + blk->next);
+        if (free && (this + blk->size == blk->next)) {
+            /* Collapse us into our successor */
+            blk->size += next->size;
+            blk->next = next->next;
+            if (blk->next) {
+                next = (rmm_block_t*)((char*)rmm->base + blk->next);
+                next->prev = this;
+            }
+        }
+        else {
+            next->prev = this;
+        }
+    }
+}
+
+APR_DECLARE(apr_status_t) apr_rmm_init(apr_rmm_t **rmm, apr_anylock_t *lock, 
+                                       void *base, apr_size_t size,
+                                       apr_pool_t *p)
+{
+    apr_status_t rv;
+    rmm_block_t *blk;
+    apr_anylock_t nulllock;
+    
+    if (!lock) {
+        nulllock.type = apr_anylock_none;
+        nulllock.lock.pm = NULL;
+        lock = &nulllock;
+    }
+    if ((rv = APR_ANYLOCK_LOCK(lock)) != APR_SUCCESS)
+        return rv;
+
+    (*rmm) = (apr_rmm_t *)apr_pcalloc(p, sizeof(apr_rmm_t));
+    (*rmm)->p = p;
+    (*rmm)->base = base;
+    (*rmm)->size = size;
+    (*rmm)->lock = *lock;
+
+    (*rmm)->base->abssize = size;
+    (*rmm)->base->firstused = 0;
+    (*rmm)->base->firstfree = RMM_HDR_BLOCK_SIZE;
+
+    blk = (rmm_block_t *)((char*)base + (*rmm)->base->firstfree);
+
+    blk->size = size - (*rmm)->base->firstfree;
+    blk->prev = 0;
+    blk->next = 0;
+
+    return APR_ANYLOCK_UNLOCK(lock);
+}
+
+APR_DECLARE(apr_status_t) apr_rmm_destroy(apr_rmm_t *rmm)
+{
+    apr_status_t rv;
+    rmm_block_t *blk;
+
+    if ((rv = APR_ANYLOCK_LOCK(&rmm->lock)) != APR_SUCCESS) {
+        return rv;
+    }
+    /* Blast it all --- no going back :) */
+    if (rmm->base->firstused) {
+        apr_rmm_off_t this = rmm->base->firstused;
+        do {
+            blk = (rmm_block_t *)((char*)rmm->base + this);
+            this = blk->next;
+            blk->next = blk->prev = 0;
+        } while (this);
+        rmm->base->firstused = 0;
+    }
+    if (rmm->base->firstfree) {
+        apr_rmm_off_t this = rmm->base->firstfree;
+        do {
+            blk = (rmm_block_t *)((char*)rmm->base + this);
+            this = blk->next;
+            blk->next = blk->prev = 0;
+        } while (this);
+        rmm->base->firstfree = 0;
+    }
+    rmm->base->abssize = 0;
+    rmm->size = 0;
+
+    return APR_ANYLOCK_UNLOCK(&rmm->lock);
+}
+
+APR_DECLARE(apr_status_t) apr_rmm_attach(apr_rmm_t **rmm, apr_anylock_t *lock,
+                                         void *base, apr_pool_t *p)
+{
+    apr_anylock_t nulllock;
+
+    if (!lock) {
+        nulllock.type = apr_anylock_none;
+        nulllock.lock.pm = NULL;
+        lock = &nulllock;
+    }
+
+    /* sanity would be good here */
+    (*rmm) = (apr_rmm_t *)apr_pcalloc(p, sizeof(apr_rmm_t));
+    (*rmm)->p = p;
+    (*rmm)->base = base;
+    (*rmm)->size = (*rmm)->base->abssize;
+    (*rmm)->lock = *lock;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_rmm_detach(apr_rmm_t *rmm) 
+{
+    /* A noop until we introduce locked/refcounts */
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_rmm_off_t) apr_rmm_malloc(apr_rmm_t *rmm, apr_size_t reqsize)
+{
+    apr_size_t size;
+    apr_rmm_off_t this;
+    
+    size = APR_ALIGN_DEFAULT(reqsize) + RMM_BLOCK_SIZE;
+    if (size < reqsize) {
+        return 0;
+    }
+
+    APR_ANYLOCK_LOCK(&rmm->lock);
+
+    this = find_block_of_size(rmm, size);
+
+    if (this) {
+        move_block(rmm, this, 0);
+        this += RMM_BLOCK_SIZE;
+    }
+
+    APR_ANYLOCK_UNLOCK(&rmm->lock);
+    return this;
+}
+
+APR_DECLARE(apr_rmm_off_t) apr_rmm_calloc(apr_rmm_t *rmm, apr_size_t reqsize)
+{
+    apr_size_t size;
+    apr_rmm_off_t this;
+        
+    size = APR_ALIGN_DEFAULT(reqsize) + RMM_BLOCK_SIZE;
+    if (size < reqsize) {
+        return 0;
+    }
+
+    APR_ANYLOCK_LOCK(&rmm->lock);
+
+    this = find_block_of_size(rmm, size);
+
+    if (this) {
+        move_block(rmm, this, 0);
+        this += RMM_BLOCK_SIZE;
+        memset((char*)rmm->base + this, 0, size - RMM_BLOCK_SIZE);
+    }
+
+    APR_ANYLOCK_UNLOCK(&rmm->lock);
+    return this;
+}
+
+APR_DECLARE(apr_rmm_off_t) apr_rmm_realloc(apr_rmm_t *rmm, void *entity,
+                                           apr_size_t reqsize)
+{
+    apr_rmm_off_t this;
+    apr_rmm_off_t old;
+    struct rmm_block_t *blk;
+    apr_size_t size, oldsize;
+
+    if (!entity) {
+        return apr_rmm_malloc(rmm, reqsize);
+    }
+
+    size = APR_ALIGN_DEFAULT(reqsize);
+    if (size < reqsize) {
+        return 0;
+    }
+    old = apr_rmm_offset_get(rmm, entity);
+
+    if ((this = apr_rmm_malloc(rmm, size)) == 0) {
+        return 0;
+    }
+
+    blk = (rmm_block_t*)((char*)rmm->base + old - RMM_BLOCK_SIZE);
+    oldsize = blk->size;
+
+    memcpy(apr_rmm_addr_get(rmm, this),
+           apr_rmm_addr_get(rmm, old), oldsize < size ? oldsize : size);
+    apr_rmm_free(rmm, old);
+
+    return this;
+}
+
+APR_DECLARE(apr_status_t) apr_rmm_free(apr_rmm_t *rmm, apr_rmm_off_t this)
+{
+    apr_status_t rv;
+    struct rmm_block_t *blk;
+
+    /* A little sanity check is always healthy, especially here.
+     * If we really cared, we could make this compile-time
+     */
+    if (this < RMM_HDR_BLOCK_SIZE + RMM_BLOCK_SIZE) {
+        return APR_EINVAL;
+    }
+
+    this -= RMM_BLOCK_SIZE;
+
+    blk = (rmm_block_t*)((char*)rmm->base + this);
+
+    if ((rv = APR_ANYLOCK_LOCK(&rmm->lock)) != APR_SUCCESS) {
+        return rv;
+    }
+    if (blk->prev) {
+        struct rmm_block_t *prev = (rmm_block_t*)((char*)rmm->base + blk->prev);
+        if (prev->next != this) {
+            APR_ANYLOCK_UNLOCK(&rmm->lock);
+            return APR_EINVAL;
+        }
+    }
+    else {
+        if (rmm->base->firstused != this) {
+            APR_ANYLOCK_UNLOCK(&rmm->lock);
+            return APR_EINVAL;
+        }
+    }
+
+    if (blk->next) {
+        struct rmm_block_t *next = (rmm_block_t*)((char*)rmm->base + blk->next);
+        if (next->prev != this) {
+            APR_ANYLOCK_UNLOCK(&rmm->lock);
+            return APR_EINVAL;
+        }
+    }
+
+    /* Ok, it remained [apparently] sane, so unlink it
+     */
+    move_block(rmm, this, 1);
+    
+    return APR_ANYLOCK_UNLOCK(&rmm->lock);
+}
+
+APR_DECLARE(void *) apr_rmm_addr_get(apr_rmm_t *rmm, apr_rmm_off_t entity) 
+{
+    /* debug-sanity checking here would be good
+     */
+    return (void*)((char*)rmm->base + entity);
+}
+
+APR_DECLARE(apr_rmm_off_t) apr_rmm_offset_get(apr_rmm_t *rmm, void* entity)
+{
+    /* debug, or always, sanity checking here would be good
+     * since the primitive is apr_rmm_off_t, I don't mind penalizing
+     * inverse conversions for safety, unless someone can prove that
+     * there is no choice in some cases.
+     */
+    return ((char*)entity - (char*)rmm->base);
+}
+
+APR_DECLARE(apr_size_t) apr_rmm_overhead_get(int n) 
+{
+    /* overhead per block is at most APR_ALIGN_DEFAULT(1) wasted bytes
+     * for alignment overhead, plus the size of the rmm_block_t
+     * structure. */
+    return RMM_HDR_BLOCK_SIZE + n * (RMM_BLOCK_SIZE + APR_ALIGN_DEFAULT(1));
+}
diff --git a/util-misc/apr_thread_pool.c b/util-misc/apr_thread_pool.c
new file mode 100644
index 00000000000..f5a7a4316f1
--- /dev/null
+++ b/util-misc/apr_thread_pool.c
@@ -0,0 +1,964 @@
+/*
+ * 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 <assert.h>
+#include "apr_thread_pool.h"
+#include "apr_ring.h"
+#include "apr_thread_cond.h"
+#include "apr_portable.h"
+
+#if APR_HAS_THREADS
+
+#define TASK_PRIORITY_SEGS 4
+#define TASK_PRIORITY_SEG(x) (((x)->dispatch.priority & 0xFF) / 64)
+
+typedef struct apr_thread_pool_task
+{
+    APR_RING_ENTRY(apr_thread_pool_task) link;
+    apr_thread_start_t func;
+    void *param;
+    void *owner;
+    union
+    {
+        apr_byte_t priority;
+        apr_time_t time;
+    } dispatch;
+} apr_thread_pool_task_t;
+
+APR_RING_HEAD(apr_thread_pool_tasks, apr_thread_pool_task);
+
+struct apr_thread_list_elt
+{
+    APR_RING_ENTRY(apr_thread_list_elt) link;
+    apr_thread_t *thd;
+    volatile void *current_owner;
+    volatile enum { TH_RUN, TH_STOP, TH_PROBATION } state;
+};
+
+APR_RING_HEAD(apr_thread_list, apr_thread_list_elt);
+
+struct apr_thread_pool
+{
+    apr_pool_t *pool;
+    volatile apr_size_t thd_max;
+    volatile apr_size_t idle_max;
+    volatile apr_interval_time_t idle_wait;
+    volatile apr_size_t thd_cnt;
+    volatile apr_size_t idle_cnt;
+    volatile apr_size_t task_cnt;
+    volatile apr_size_t scheduled_task_cnt;
+    volatile apr_size_t threshold;
+    volatile apr_size_t tasks_run;
+    volatile apr_size_t tasks_high;
+    volatile apr_size_t thd_high;
+    volatile apr_size_t thd_timed_out;
+    struct apr_thread_pool_tasks *tasks;
+    struct apr_thread_pool_tasks *scheduled_tasks;
+    struct apr_thread_list *busy_thds;
+    struct apr_thread_list *idle_thds;
+    apr_thread_mutex_t *lock;
+    apr_thread_cond_t *cond;
+    volatile int terminated;
+    struct apr_thread_pool_tasks *recycled_tasks;
+    struct apr_thread_list *recycled_thds;
+    apr_thread_pool_task_t *task_idx[TASK_PRIORITY_SEGS];
+};
+
+static apr_status_t thread_pool_construct(apr_thread_pool_t * me,
+                                          apr_size_t init_threads,
+                                          apr_size_t max_threads)
+{
+    apr_status_t rv;
+    int i;
+
+    me->thd_max = max_threads;
+    me->idle_max = init_threads;
+    me->threshold = init_threads / 2;
+    rv = apr_thread_mutex_create(&me->lock, APR_THREAD_MUTEX_NESTED,
+                                 me->pool);
+    if (APR_SUCCESS != rv) {
+        return rv;
+    }
+    rv = apr_thread_cond_create(&me->cond, me->pool);
+    if (APR_SUCCESS != rv) {
+        apr_thread_mutex_destroy(me->lock);
+        return rv;
+    }
+    me->tasks = apr_palloc(me->pool, sizeof(*me->tasks));
+    if (!me->tasks) {
+        goto CATCH_ENOMEM;
+    }
+    APR_RING_INIT(me->tasks, apr_thread_pool_task, link);
+    me->scheduled_tasks = apr_palloc(me->pool, sizeof(*me->scheduled_tasks));
+    if (!me->scheduled_tasks) {
+        goto CATCH_ENOMEM;
+    }
+    APR_RING_INIT(me->scheduled_tasks, apr_thread_pool_task, link);
+    me->recycled_tasks = apr_palloc(me->pool, sizeof(*me->recycled_tasks));
+    if (!me->recycled_tasks) {
+        goto CATCH_ENOMEM;
+    }
+    APR_RING_INIT(me->recycled_tasks, apr_thread_pool_task, link);
+    me->busy_thds = apr_palloc(me->pool, sizeof(*me->busy_thds));
+    if (!me->busy_thds) {
+        goto CATCH_ENOMEM;
+    }
+    APR_RING_INIT(me->busy_thds, apr_thread_list_elt, link);
+    me->idle_thds = apr_palloc(me->pool, sizeof(*me->idle_thds));
+    if (!me->idle_thds) {
+        goto CATCH_ENOMEM;
+    }
+    APR_RING_INIT(me->idle_thds, apr_thread_list_elt, link);
+    me->recycled_thds = apr_palloc(me->pool, sizeof(*me->recycled_thds));
+    if (!me->recycled_thds) {
+        goto CATCH_ENOMEM;
+    }
+    APR_RING_INIT(me->recycled_thds, apr_thread_list_elt, link);
+    me->thd_cnt = me->idle_cnt = me->task_cnt = me->scheduled_task_cnt = 0;
+    me->tasks_run = me->tasks_high = me->thd_high = me->thd_timed_out = 0;
+    me->idle_wait = 0;
+    me->terminated = 0;
+    for (i = 0; i < TASK_PRIORITY_SEGS; i++) {
+        me->task_idx[i] = NULL;
+    }
+    goto FINAL_EXIT;
+  CATCH_ENOMEM:
+    rv = APR_ENOMEM;
+    apr_thread_mutex_destroy(me->lock);
+    apr_thread_cond_destroy(me->cond);
+  FINAL_EXIT:
+    return rv;
+}
+
+/*
+ * NOTE: This function is not thread safe by itself. Caller should hold the lock
+ */
+static apr_thread_pool_task_t *pop_task(apr_thread_pool_t * me)
+{
+    apr_thread_pool_task_t *task = NULL;
+    int seg;
+
+    /* check for scheduled tasks */
+    if (me->scheduled_task_cnt > 0) {
+        task = APR_RING_FIRST(me->scheduled_tasks);
+        assert(task != NULL);
+        assert(task !=
+               APR_RING_SENTINEL(me->scheduled_tasks, apr_thread_pool_task,
+                                 link));
+        /* if it's time */
+        if (task->dispatch.time <= apr_time_now()) {
+            --me->scheduled_task_cnt;
+            APR_RING_REMOVE(task, link);
+            return task;
+        }
+    }
+    /* check for normal tasks if we're not returning a scheduled task */
+    if (me->task_cnt == 0) {
+        return NULL;
+    }
+
+    task = APR_RING_FIRST(me->tasks);
+    assert(task != NULL);
+    assert(task != APR_RING_SENTINEL(me->tasks, apr_thread_pool_task, link));
+    --me->task_cnt;
+    seg = TASK_PRIORITY_SEG(task);
+    if (task == me->task_idx[seg]) {
+        me->task_idx[seg] = APR_RING_NEXT(task, link);
+        if (me->task_idx[seg] == APR_RING_SENTINEL(me->tasks,
+                                                   apr_thread_pool_task, link)
+            || TASK_PRIORITY_SEG(me->task_idx[seg]) != seg) {
+            me->task_idx[seg] = NULL;
+        }
+    }
+    APR_RING_REMOVE(task, link);
+    return task;
+}
+
+static apr_interval_time_t waiting_time(apr_thread_pool_t * me)
+{
+    apr_thread_pool_task_t *task = NULL;
+
+    task = APR_RING_FIRST(me->scheduled_tasks);
+    assert(task != NULL);
+    assert(task !=
+           APR_RING_SENTINEL(me->scheduled_tasks, apr_thread_pool_task,
+                             link));
+    return task->dispatch.time - apr_time_now();
+}
+
+/*
+ * NOTE: This function is not thread safe by itself. Caller should hold the lock
+ */
+static struct apr_thread_list_elt *elt_new(apr_thread_pool_t * me,
+                                           apr_thread_t * t)
+{
+    struct apr_thread_list_elt *elt;
+
+    if (APR_RING_EMPTY(me->recycled_thds, apr_thread_list_elt, link)) {
+        elt = apr_pcalloc(me->pool, sizeof(*elt));
+        if (NULL == elt) {
+            return NULL;
+        }
+    }
+    else {
+        elt = APR_RING_FIRST(me->recycled_thds);
+        APR_RING_REMOVE(elt, link);
+    }
+
+    APR_RING_ELEM_INIT(elt, link);
+    elt->thd = t;
+    elt->current_owner = NULL;
+    elt->state = TH_RUN;
+    return elt;
+}
+
+/*
+ * The worker thread function. Take a task from the queue and perform it if
+ * there is any. Otherwise, put itself into the idle thread list and waiting
+ * for signal to wake up.
+ * The thread terminate directly by detach and exit when it is asked to stop
+ * after finishing a task. Otherwise, the thread should be in idle thread list
+ * and should be joined.
+ */
+static void *APR_THREAD_FUNC thread_pool_func(apr_thread_t * t, void *param)
+{
+    apr_thread_pool_t *me = param;
+    apr_thread_pool_task_t *task = NULL;
+    apr_interval_time_t wait;
+    struct apr_thread_list_elt *elt;
+
+    apr_thread_mutex_lock(me->lock);
+    apr_pool_owner_set(me->pool, 0);
+    elt = elt_new(me, t);
+    if (!elt) {
+        apr_thread_mutex_unlock(me->lock);
+        apr_thread_exit(t, APR_ENOMEM);
+    }
+
+    while (!me->terminated && elt->state != TH_STOP) {
+        /* Test if not new element, it is awakened from idle */
+        if (APR_RING_NEXT(elt, link) != elt) {
+            --me->idle_cnt;
+            APR_RING_REMOVE(elt, link);
+        }
+
+        APR_RING_INSERT_TAIL(me->busy_thds, elt, apr_thread_list_elt, link);
+        task = pop_task(me);
+        while (NULL != task && !me->terminated) {
+            ++me->tasks_run;
+            elt->current_owner = task->owner;
+            apr_thread_mutex_unlock(me->lock);
+            apr_thread_data_set(task, "apr_thread_pool_task", NULL, t);
+            task->func(t, task->param);
+            apr_thread_mutex_lock(me->lock);
+            apr_pool_owner_set(me->pool, 0);
+            APR_RING_INSERT_TAIL(me->recycled_tasks, task,
+                                 apr_thread_pool_task, link);
+            elt->current_owner = NULL;
+            if (TH_STOP == elt->state) {
+                break;
+            }
+            task = pop_task(me);
+        }
+        assert(NULL == elt->current_owner);
+        if (TH_STOP != elt->state)
+            APR_RING_REMOVE(elt, link);
+
+        /* Test if a busy thread been asked to stop, which is not joinable */
+        if ((me->idle_cnt >= me->idle_max
+             && !(me->scheduled_task_cnt && 0 >= me->idle_max)
+             && !me->idle_wait)
+            || me->terminated || elt->state != TH_RUN) {
+            --me->thd_cnt;
+            if ((TH_PROBATION == elt->state) && me->idle_wait)
+                ++me->thd_timed_out;
+            APR_RING_INSERT_TAIL(me->recycled_thds, elt,
+                                 apr_thread_list_elt, link);
+            apr_thread_mutex_unlock(me->lock);
+            apr_thread_detach(t);
+            apr_thread_exit(t, APR_SUCCESS);
+            return NULL;        /* should not be here, safe net */
+        }
+
+        /* busy thread become idle */
+        ++me->idle_cnt;
+        APR_RING_INSERT_TAIL(me->idle_thds, elt, apr_thread_list_elt, link);
+
+        /* 
+         * If there is a scheduled task, always scheduled to perform that task.
+         * Since there is no guarantee that current idle threads are scheduled
+         * for next scheduled task.
+         */
+        if (me->scheduled_task_cnt)
+            wait = waiting_time(me);
+        else if (me->idle_cnt > me->idle_max) {
+            wait = me->idle_wait;
+            elt->state = TH_PROBATION;
+        }
+        else
+            wait = -1;
+
+        if (wait >= 0) {
+            apr_thread_cond_timedwait(me->cond, me->lock, wait);
+        }
+        else {
+            apr_thread_cond_wait(me->cond, me->lock);
+        }
+    }
+
+    /* idle thread been asked to stop, will be joined */
+    --me->thd_cnt;
+    apr_thread_mutex_unlock(me->lock);
+    apr_thread_exit(t, APR_SUCCESS);
+    return NULL;                /* should not be here, safe net */
+}
+
+static apr_status_t thread_pool_cleanup(void *me)
+{
+    apr_thread_pool_t *_myself = me;
+
+    _myself->terminated = 1;
+    apr_thread_pool_idle_max_set(_myself, 0);
+    while (_myself->thd_cnt) {
+        apr_sleep(20 * 1000);   /* spin lock with 20 ms */
+    }
+    apr_pool_owner_set(_myself->pool, 0);
+    apr_thread_mutex_destroy(_myself->lock);
+    apr_thread_cond_destroy(_myself->cond);
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_pool_create(apr_thread_pool_t ** me,
+                                                 apr_size_t init_threads,
+                                                 apr_size_t max_threads,
+                                                 apr_pool_t * pool)
+{
+    apr_thread_t *t;
+    apr_status_t rv = APR_SUCCESS;
+    apr_thread_pool_t *tp;
+
+    *me = NULL;
+    tp = apr_pcalloc(pool, sizeof(apr_thread_pool_t));
+
+    /*
+     * This pool will be used by different threads. As we cannot ensure that
+     * our caller won't use the pool without acquiring the mutex, we must
+     * create a new sub pool.
+     */
+    rv = apr_pool_create(&tp->pool, pool);
+    if (APR_SUCCESS != rv)
+        return rv;
+    rv = thread_pool_construct(tp, init_threads, max_threads);
+    if (APR_SUCCESS != rv)
+        return rv;
+    apr_pool_pre_cleanup_register(tp->pool, tp, thread_pool_cleanup);
+
+    while (init_threads) {
+        /* Grab the mutex as apr_thread_create() and thread_pool_func() will 
+         * allocate from (*me)->pool. This is dangerous if there are multiple 
+         * initial threads to create.
+         */
+        apr_thread_mutex_lock(tp->lock);
+        apr_pool_owner_set(tp->pool, 0);
+        rv = apr_thread_create(&t, NULL, thread_pool_func, tp, tp->pool);
+        apr_thread_mutex_unlock(tp->lock);
+        if (APR_SUCCESS != rv) {
+            break;
+        }
+        tp->thd_cnt++;
+        if (tp->thd_cnt > tp->thd_high) {
+            tp->thd_high = tp->thd_cnt;
+        }
+        --init_threads;
+    }
+
+    if (rv == APR_SUCCESS) {
+        *me = tp;
+    }
+
+    return rv;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_pool_destroy(apr_thread_pool_t * me)
+{
+    apr_pool_destroy(me->pool);
+    return APR_SUCCESS;
+}
+
+/*
+ * NOTE: This function is not thread safe by itself. Caller should hold the lock
+ */
+static apr_thread_pool_task_t *task_new(apr_thread_pool_t * me,
+                                        apr_thread_start_t func,
+                                        void *param, apr_byte_t priority,
+                                        void *owner, apr_time_t time)
+{
+    apr_thread_pool_task_t *t;
+
+    if (APR_RING_EMPTY(me->recycled_tasks, apr_thread_pool_task, link)) {
+        t = apr_pcalloc(me->pool, sizeof(*t));
+        if (NULL == t) {
+            return NULL;
+        }
+    }
+    else {
+        t = APR_RING_FIRST(me->recycled_tasks);
+        APR_RING_REMOVE(t, link);
+    }
+
+    APR_RING_ELEM_INIT(t, link);
+    t->func = func;
+    t->param = param;
+    t->owner = owner;
+    if (time > 0) {
+        t->dispatch.time = apr_time_now() + time;
+    }
+    else {
+        t->dispatch.priority = priority;
+    }
+    return t;
+}
+
+/*
+ * Test it the task is the only one within the priority segment. 
+ * If it is not, return the first element with same or lower priority. 
+ * Otherwise, add the task into the queue and return NULL.
+ *
+ * NOTE: This function is not thread safe by itself. Caller should hold the lock
+ */
+static apr_thread_pool_task_t *add_if_empty(apr_thread_pool_t * me,
+                                            apr_thread_pool_task_t * const t)
+{
+    int seg;
+    int next;
+    apr_thread_pool_task_t *t_next;
+
+    seg = TASK_PRIORITY_SEG(t);
+    if (me->task_idx[seg]) {
+        assert(APR_RING_SENTINEL(me->tasks, apr_thread_pool_task, link) !=
+               me->task_idx[seg]);
+        t_next = me->task_idx[seg];
+        while (t_next->dispatch.priority > t->dispatch.priority) {
+            t_next = APR_RING_NEXT(t_next, link);
+            if (APR_RING_SENTINEL(me->tasks, apr_thread_pool_task, link) ==
+                t_next) {
+                return t_next;
+            }
+        }
+        return t_next;
+    }
+
+    for (next = seg - 1; next >= 0; next--) {
+        if (me->task_idx[next]) {
+            APR_RING_INSERT_BEFORE(me->task_idx[next], t, link);
+            break;
+        }
+    }
+    if (0 > next) {
+        APR_RING_INSERT_TAIL(me->tasks, t, apr_thread_pool_task, link);
+    }
+    me->task_idx[seg] = t;
+    return NULL;
+}
+
+/*
+*   schedule a task to run in "time" microseconds. Find the spot in the ring where
+*   the time fits. Adjust the short_time so the thread wakes up when the time is reached.
+*/
+static apr_status_t schedule_task(apr_thread_pool_t *me,
+                                  apr_thread_start_t func, void *param,
+                                  void *owner, apr_interval_time_t time)
+{
+    apr_thread_pool_task_t *t;
+    apr_thread_pool_task_t *t_loc;
+    apr_thread_t *thd;
+    apr_status_t rv = APR_SUCCESS;
+    apr_thread_mutex_lock(me->lock);
+    apr_pool_owner_set(me->pool, 0);
+
+    t = task_new(me, func, param, 0, owner, time);
+    if (NULL == t) {
+        apr_thread_mutex_unlock(me->lock);
+        return APR_ENOMEM;
+    }
+    t_loc = APR_RING_FIRST(me->scheduled_tasks);
+    while (NULL != t_loc) {
+        /* if the time is less than the entry insert ahead of it */
+        if (t->dispatch.time < t_loc->dispatch.time) {
+            ++me->scheduled_task_cnt;
+            APR_RING_INSERT_BEFORE(t_loc, t, link);
+            break;
+        }
+        else {
+            t_loc = APR_RING_NEXT(t_loc, link);
+            if (t_loc ==
+                APR_RING_SENTINEL(me->scheduled_tasks, apr_thread_pool_task,
+                                  link)) {
+                ++me->scheduled_task_cnt;
+                APR_RING_INSERT_TAIL(me->scheduled_tasks, t,
+                                     apr_thread_pool_task, link);
+                break;
+            }
+        }
+    }
+    /* there should be at least one thread for scheduled tasks */
+    if (0 == me->thd_cnt) {
+        rv = apr_thread_create(&thd, NULL, thread_pool_func, me, me->pool);
+        if (APR_SUCCESS == rv) {
+            ++me->thd_cnt;
+            if (me->thd_cnt > me->thd_high)
+                me->thd_high = me->thd_cnt;
+        }
+    }
+    apr_thread_cond_signal(me->cond);
+    apr_thread_mutex_unlock(me->lock);
+    return rv;
+}
+
+static apr_status_t add_task(apr_thread_pool_t *me, apr_thread_start_t func,
+                             void *param, apr_byte_t priority, int push,
+                             void *owner)
+{
+    apr_thread_pool_task_t *t;
+    apr_thread_pool_task_t *t_loc;
+    apr_thread_t *thd;
+    apr_status_t rv = APR_SUCCESS;
+
+    apr_thread_mutex_lock(me->lock);
+    apr_pool_owner_set(me->pool, 0);
+
+    t = task_new(me, func, param, priority, owner, 0);
+    if (NULL == t) {
+        apr_thread_mutex_unlock(me->lock);
+        return APR_ENOMEM;
+    }
+
+    t_loc = add_if_empty(me, t);
+    if (NULL == t_loc) {
+        goto FINAL_EXIT;
+    }
+
+    if (push) {
+        while (APR_RING_SENTINEL(me->tasks, apr_thread_pool_task, link) !=
+               t_loc && t_loc->dispatch.priority >= t->dispatch.priority) {
+            t_loc = APR_RING_NEXT(t_loc, link);
+        }
+    }
+    APR_RING_INSERT_BEFORE(t_loc, t, link);
+    if (!push) {
+        if (t_loc == me->task_idx[TASK_PRIORITY_SEG(t)]) {
+            me->task_idx[TASK_PRIORITY_SEG(t)] = t;
+        }
+    }
+
+  FINAL_EXIT:
+    me->task_cnt++;
+    if (me->task_cnt > me->tasks_high)
+        me->tasks_high = me->task_cnt;
+    if (0 == me->thd_cnt || (0 == me->idle_cnt && me->thd_cnt < me->thd_max &&
+                             me->task_cnt > me->threshold)) {
+        rv = apr_thread_create(&thd, NULL, thread_pool_func, me, me->pool);
+        if (APR_SUCCESS == rv) {
+            ++me->thd_cnt;
+            if (me->thd_cnt > me->thd_high)
+                me->thd_high = me->thd_cnt;
+        }
+    }
+
+    apr_thread_cond_signal(me->cond);
+    apr_thread_mutex_unlock(me->lock);
+
+    return rv;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_pool_push(apr_thread_pool_t *me,
+                                               apr_thread_start_t func,
+                                               void *param,
+                                               apr_byte_t priority,
+                                               void *owner)
+{
+    return add_task(me, func, param, priority, 1, owner);
+}
+
+APR_DECLARE(apr_status_t) apr_thread_pool_schedule(apr_thread_pool_t *me,
+                                                   apr_thread_start_t func,
+                                                   void *param,
+                                                   apr_interval_time_t time,
+                                                   void *owner)
+{
+    return schedule_task(me, func, param, owner, time);
+}
+
+APR_DECLARE(apr_status_t) apr_thread_pool_top(apr_thread_pool_t *me,
+                                              apr_thread_start_t func,
+                                              void *param,
+                                              apr_byte_t priority,
+                                              void *owner)
+{
+    return add_task(me, func, param, priority, 0, owner);
+}
+
+static apr_status_t remove_scheduled_tasks(apr_thread_pool_t *me,
+                                           void *owner)
+{
+    apr_thread_pool_task_t *t_loc;
+    apr_thread_pool_task_t *next;
+
+    t_loc = APR_RING_FIRST(me->scheduled_tasks);
+    while (t_loc !=
+           APR_RING_SENTINEL(me->scheduled_tasks, apr_thread_pool_task,
+                             link)) {
+        next = APR_RING_NEXT(t_loc, link);
+        /* if this is the owner remove it */
+        if (t_loc->owner == owner) {
+            --me->scheduled_task_cnt;
+            APR_RING_REMOVE(t_loc, link);
+        }
+        t_loc = next;
+    }
+    return APR_SUCCESS;
+}
+
+static apr_status_t remove_tasks(apr_thread_pool_t *me, void *owner)
+{
+    apr_thread_pool_task_t *t_loc;
+    apr_thread_pool_task_t *next;
+    int seg;
+
+    t_loc = APR_RING_FIRST(me->tasks);
+    while (t_loc != APR_RING_SENTINEL(me->tasks, apr_thread_pool_task, link)) {
+        next = APR_RING_NEXT(t_loc, link);
+        if (t_loc->owner == owner) {
+            --me->task_cnt;
+            seg = TASK_PRIORITY_SEG(t_loc);
+            if (t_loc == me->task_idx[seg]) {
+                me->task_idx[seg] = APR_RING_NEXT(t_loc, link);
+                if (me->task_idx[seg] == APR_RING_SENTINEL(me->tasks,
+                                                           apr_thread_pool_task,
+                                                           link)
+                    || TASK_PRIORITY_SEG(me->task_idx[seg]) != seg) {
+                    me->task_idx[seg] = NULL;
+                }
+            }
+            APR_RING_REMOVE(t_loc, link);
+        }
+        t_loc = next;
+    }
+    return APR_SUCCESS;
+}
+
+static void wait_on_busy_threads(apr_thread_pool_t *me, void *owner)
+{
+#ifndef NDEBUG
+    apr_os_thread_t *os_thread;
+#endif
+    struct apr_thread_list_elt *elt;
+    apr_thread_mutex_lock(me->lock);
+    elt = APR_RING_FIRST(me->busy_thds);
+    while (elt != APR_RING_SENTINEL(me->busy_thds, apr_thread_list_elt, link)) {
+        if (elt->current_owner != owner) {
+            elt = APR_RING_NEXT(elt, link);
+            continue;
+        }
+#ifndef NDEBUG
+        /* make sure the thread is not the one calling tasks_cancel */
+        apr_os_thread_get(&os_thread, elt->thd);
+#ifdef WIN32
+        /* hack for apr win32 bug */
+        assert(!apr_os_thread_equal(apr_os_thread_current(), os_thread));
+#else
+        assert(!apr_os_thread_equal(apr_os_thread_current(), *os_thread));
+#endif
+#endif
+        while (elt->current_owner == owner) {
+            apr_thread_mutex_unlock(me->lock);
+            apr_sleep(200 * 1000);
+            apr_thread_mutex_lock(me->lock);
+        }
+        elt = APR_RING_FIRST(me->busy_thds);
+    }
+    apr_thread_mutex_unlock(me->lock);
+    return;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_pool_tasks_cancel(apr_thread_pool_t *me,
+                                                       void *owner)
+{
+    apr_status_t rv = APR_SUCCESS;
+
+    apr_thread_mutex_lock(me->lock);
+    apr_pool_owner_set(me->pool, 0);
+    if (me->task_cnt > 0) {
+        rv = remove_tasks(me, owner);
+    }
+    if (me->scheduled_task_cnt > 0) {
+        rv = remove_scheduled_tasks(me, owner);
+    }
+    apr_thread_mutex_unlock(me->lock);
+    wait_on_busy_threads(me, owner);
+
+    return rv;
+}
+
+APR_DECLARE(apr_size_t) apr_thread_pool_tasks_count(apr_thread_pool_t *me)
+{
+    return me->task_cnt;
+}
+
+APR_DECLARE(apr_size_t)
+    apr_thread_pool_scheduled_tasks_count(apr_thread_pool_t *me)
+{
+    return me->scheduled_task_cnt;
+}
+
+APR_DECLARE(apr_size_t) apr_thread_pool_threads_count(apr_thread_pool_t *me)
+{
+    return me->thd_cnt;
+}
+
+APR_DECLARE(apr_size_t) apr_thread_pool_busy_count(apr_thread_pool_t *me)
+{
+    return me->thd_cnt - me->idle_cnt;
+}
+
+APR_DECLARE(apr_size_t) apr_thread_pool_idle_count(apr_thread_pool_t *me)
+{
+    return me->idle_cnt;
+}
+
+APR_DECLARE(apr_size_t)
+    apr_thread_pool_tasks_run_count(apr_thread_pool_t * me)
+{
+    return me->tasks_run;
+}
+
+APR_DECLARE(apr_size_t)
+    apr_thread_pool_tasks_high_count(apr_thread_pool_t * me)
+{
+    return me->tasks_high;
+}
+
+APR_DECLARE(apr_size_t)
+    apr_thread_pool_threads_high_count(apr_thread_pool_t * me)
+{
+    return me->thd_high;
+}
+
+APR_DECLARE(apr_size_t)
+    apr_thread_pool_threads_idle_timeout_count(apr_thread_pool_t * me)
+{
+    return me->thd_timed_out;
+}
+
+
+APR_DECLARE(apr_size_t) apr_thread_pool_idle_max_get(apr_thread_pool_t *me)
+{
+    return me->idle_max;
+}
+
+APR_DECLARE(apr_interval_time_t)
+    apr_thread_pool_idle_wait_get(apr_thread_pool_t * me)
+{
+    return me->idle_wait;
+}
+
+/*
+ * This function stop extra idle threads to the cnt.
+ * @return the number of threads stopped
+ * NOTE: There could be busy threads become idle during this function
+ */
+static struct apr_thread_list_elt *trim_threads(apr_thread_pool_t *me,
+                                                apr_size_t *cnt, int idle)
+{
+    struct apr_thread_list *thds;
+    apr_size_t n, n_dbg, i;
+    struct apr_thread_list_elt *head, *tail, *elt;
+
+    apr_thread_mutex_lock(me->lock);
+    apr_pool_owner_set(me->pool, 0);
+    if (idle) {
+        thds = me->idle_thds;
+        n = me->idle_cnt;
+    }
+    else {
+        thds = me->busy_thds;
+        n = me->thd_cnt - me->idle_cnt;
+    }
+    if (n <= *cnt) {
+        apr_thread_mutex_unlock(me->lock);
+        *cnt = 0;
+        return NULL;
+    }
+    n -= *cnt;
+
+    head = APR_RING_FIRST(thds);
+    for (i = 0; i < *cnt; i++) {
+        head = APR_RING_NEXT(head, link);
+    }
+    tail = APR_RING_LAST(thds);
+    if (idle) {
+        APR_RING_UNSPLICE(head, tail, link);
+        me->idle_cnt = *cnt;
+    }
+
+    n_dbg = 0;
+    for (elt = head; elt != tail; elt = APR_RING_NEXT(elt, link)) {
+        elt->state = TH_STOP;
+        n_dbg++;
+    }
+    elt->state = TH_STOP;
+    n_dbg++;
+    assert(n == n_dbg);
+    *cnt = n;
+
+    apr_thread_mutex_unlock(me->lock);
+
+    APR_RING_PREV(head, link) = NULL;
+    APR_RING_NEXT(tail, link) = NULL;
+    return head;
+}
+
+static apr_size_t trim_idle_threads(apr_thread_pool_t *me, apr_size_t cnt)
+{
+    apr_size_t n_dbg;
+    struct apr_thread_list_elt *elt, *head, *tail;
+    apr_status_t rv;
+
+    elt = trim_threads(me, &cnt, 1);
+
+    apr_thread_mutex_lock(me->lock);
+    apr_thread_cond_broadcast(me->cond);
+    apr_thread_mutex_unlock(me->lock);
+
+    n_dbg = 0;
+    if (NULL != (head = elt)) {
+        while (elt) {
+            tail = elt;
+            apr_thread_join(&rv, elt->thd);
+            elt = APR_RING_NEXT(elt, link);
+            ++n_dbg;
+        }
+        apr_thread_mutex_lock(me->lock);
+        APR_RING_SPLICE_TAIL(me->recycled_thds, head, tail,
+                             apr_thread_list_elt, link);
+        apr_thread_mutex_unlock(me->lock);
+    }
+    assert(cnt == n_dbg);
+
+    return cnt;
+}
+
+/* don't join on busy threads for performance reasons, who knows how long will
+ * the task takes to perform
+ */
+static apr_size_t trim_busy_threads(apr_thread_pool_t *me, apr_size_t cnt)
+{
+    trim_threads(me, &cnt, 0);
+    return cnt;
+}
+
+APR_DECLARE(apr_size_t) apr_thread_pool_idle_max_set(apr_thread_pool_t *me,
+                                                     apr_size_t cnt)
+{
+    me->idle_max = cnt;
+    cnt = trim_idle_threads(me, cnt);
+    return cnt;
+}
+
+APR_DECLARE(apr_interval_time_t)
+    apr_thread_pool_idle_wait_set(apr_thread_pool_t * me,
+                                  apr_interval_time_t timeout)
+{
+    apr_interval_time_t oldtime;
+
+    oldtime = me->idle_wait;
+    me->idle_wait = timeout;
+
+    return oldtime;
+}
+
+APR_DECLARE(apr_size_t) apr_thread_pool_thread_max_get(apr_thread_pool_t *me)
+{
+    return me->thd_max;
+}
+
+/*
+ * This function stop extra working threads to the new limit.
+ * NOTE: There could be busy threads become idle during this function
+ */
+APR_DECLARE(apr_size_t) apr_thread_pool_thread_max_set(apr_thread_pool_t *me,
+                                                       apr_size_t cnt)
+{
+    unsigned int n;
+
+    me->thd_max = cnt;
+    if (0 == cnt || me->thd_cnt <= cnt) {
+        return 0;
+    }
+
+    n = me->thd_cnt - cnt;
+    if (n >= me->idle_cnt) {
+        trim_busy_threads(me, n - me->idle_cnt);
+        trim_idle_threads(me, 0);
+    }
+    else {
+        trim_idle_threads(me, me->idle_cnt - n);
+    }
+    return n;
+}
+
+APR_DECLARE(apr_size_t) apr_thread_pool_threshold_get(apr_thread_pool_t *me)
+{
+    return me->threshold;
+}
+
+APR_DECLARE(apr_size_t) apr_thread_pool_threshold_set(apr_thread_pool_t *me,
+                                                      apr_size_t val)
+{
+    apr_size_t ov;
+
+    ov = me->threshold;
+    me->threshold = val;
+    return ov;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_pool_task_owner_get(apr_thread_t *thd,
+                                                         void **owner)
+{
+    apr_status_t rv;
+    apr_thread_pool_task_t *task;
+    void *data;
+
+    rv = apr_thread_data_get(&data, "apr_thread_pool_task", thd);
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
+    task = data;
+    if (!task) {
+        *owner = NULL;
+        return APR_BADARG;
+    }
+
+    *owner = task->owner;
+    return APR_SUCCESS;
+}
+
+#endif /* APR_HAS_THREADS */
+
+/* vim: set ts=4 sw=4 et cin tw=80: */
diff --git a/util-misc/apu_dso.c b/util-misc/apu_dso.c
new file mode 100644
index 00000000000..dd29076eb73
--- /dev/null
+++ b/util-misc/apu_dso.c
@@ -0,0 +1,208 @@
+/* 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 <ctype.h>
+#include <stdio.h>
+
+#include "apu.h"
+#include "apr_private.h"
+#include "apr_pools.h"
+#include "apr_tables.h"
+#include "apr_dso.h"
+#include "apr_strings.h"
+#include "apr_hash.h"
+#include "apr_file_io.h"
+#include "apr_env.h"
+#include "apr_atomic.h"
+#include "apr_version.h"
+
+#include "apu_internal.h"
+
+#if APR_HAVE_MODULAR_DSO
+
+#if APR_HAS_THREADS
+static apr_thread_mutex_t* mutex = NULL;
+#endif
+static apr_hash_t *dsos = NULL;
+static apr_uint32_t initialised = 0, in_init = 1;
+
+#if APR_HAS_THREADS
+apr_status_t apu_dso_mutex_lock()
+{
+    return apr_thread_mutex_lock(mutex);
+}
+apr_status_t apu_dso_mutex_unlock()
+{
+    return apr_thread_mutex_unlock(mutex);
+}
+#else
+apr_status_t apu_dso_mutex_lock() {
+    return APR_SUCCESS;
+}
+apr_status_t apu_dso_mutex_unlock() {
+    return APR_SUCCESS;
+}
+#endif
+
+static apr_status_t apu_dso_term(void *ptr)
+{
+    /* set statics to NULL so init can work again */
+    dsos = NULL;
+#if APR_HAS_THREADS
+    mutex = NULL;
+#endif
+
+    /* Everything else we need is handled by cleanups registered
+     * when we created mutexes and loaded DSOs
+     */
+    return APR_SUCCESS;
+}
+
+apr_status_t apu_dso_init(apr_pool_t *pool)
+{
+    apr_status_t ret = APR_SUCCESS;
+    apr_pool_t *parent;
+
+    if (apr_atomic_inc32(&initialised)) {
+        apr_atomic_set32(&initialised, 1); /* prevent wrap-around */
+
+        while (apr_atomic_read32(&in_init)) /* wait until we get fully inited */
+            ;
+
+        return APR_SUCCESS;
+    }
+
+    /* Top level pool scope, need process-scope lifetime */
+    for (parent = apr_pool_parent_get(pool);
+         parent && parent != pool;
+         parent = apr_pool_parent_get(pool))
+        pool = parent;
+
+    dsos = apr_hash_make(pool);
+
+#if APR_HAS_THREADS
+    ret = apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_DEFAULT, pool);
+    /* This already registers a pool cleanup */
+#endif
+
+    apr_pool_cleanup_register(pool, NULL, apu_dso_term,
+                              apr_pool_cleanup_null);
+
+    apr_atomic_dec32(&in_init);
+
+    return ret;
+}
+
+apr_status_t apu_dso_load(apr_dso_handle_t **dlhandleptr,
+                          apr_dso_handle_sym_t *dsoptr,
+                          const char *module,
+                          const char *modsym,
+                          apr_pool_t *pool)
+{
+    apr_dso_handle_t *dlhandle = NULL;
+    char *pathlist;
+    char path[APR_PATH_MAX + 1];
+    apr_array_header_t *paths;
+    apr_pool_t *global;
+    apr_status_t rv = APR_EDSOOPEN;
+    char *eos = NULL;
+    int i;
+
+    *dsoptr = apr_hash_get(dsos, module, APR_HASH_KEY_STRING);
+    if (*dsoptr) {
+        return APR_EINIT;
+    }
+
+    /* The driver DSO must have exactly the same lifetime as the
+     * drivers hash table; ignore the passed-in pool */
+    global = apr_hash_pool_get(dsos);
+
+    /* Retrieve our path search list or prepare for a single search */
+    if ((apr_env_get(&pathlist, APR_DSOPATH, pool) != APR_SUCCESS)
+          || (apr_filepath_list_split(&paths, pathlist, pool) != APR_SUCCESS))
+        paths = apr_array_make(pool, 1, sizeof(char*));
+
+#if defined(APR_DSO_LIBDIR)
+    /* Always search our prefix path, but on some platforms such as
+     * win32 this may be left undefined
+     */
+    (*((char **)apr_array_push(paths))) = APR_DSO_LIBDIR;
+#endif
+
+    for (i = 0; i < paths->nelts; ++i)
+    {
+#if defined(WIN32)
+        /* Use win32 dso search semantics and attempt to
+         * load the relative lib on the first pass.
+         */
+        if (!eos) {
+            eos = path;
+            --i;
+        }
+        else
+#endif
+        {
+            eos = apr_cpystrn(path, ((char**)paths->elts)[i], sizeof(path));
+            if ((eos > path) && (eos - path < sizeof(path) - 1))
+                *(eos++) = '/';
+        }
+        apr_cpystrn(eos, module, sizeof(path) - (eos - path));
+
+        rv = apr_dso_load(&dlhandle, path, global);
+        if (dlhandleptr) {
+            *dlhandleptr = dlhandle;
+        }
+        if (rv == APR_SUCCESS) { /* APR_EDSOOPEN */
+            break;
+        }
+#if defined(APR_DSO_LIBDIR)
+        else if (i < paths->nelts - 1) {
+#else
+        else {   /* No APR_DSO_LIBDIR to skip */
+#endif
+             /* try with apr-APR_MAJOR_VERSION appended */
+            eos = apr_cpystrn(eos,
+                              "apr-" APR_STRINGIFY(APR_MAJOR_VERSION) "/",
+                              sizeof(path) - (eos - path));
+
+            apr_cpystrn(eos, module, sizeof(path) - (eos - path));
+
+            rv = apr_dso_load(&dlhandle, path, global);
+            if (dlhandleptr) {
+                *dlhandleptr = dlhandle;
+            }
+            if (rv == APR_SUCCESS) { /* APR_EDSOOPEN */
+                break;
+            }
+        }
+    }
+
+    if (rv != APR_SUCCESS) /* APR_ESYMNOTFOUND */
+        return rv;
+
+    rv = apr_dso_sym(dsoptr, dlhandle, modsym);
+    if (rv != APR_SUCCESS) { /* APR_ESYMNOTFOUND */
+        apr_dso_unload(dlhandle);
+    }
+    else {
+        module = apr_pstrdup(global, module);
+        apr_hash_set(dsos, module, APR_HASH_KEY_STRING, *dsoptr);
+    }
+    return rv;
+}
+
+#endif /* APR_DSO_BUILD */
+
diff --git a/xlate/xlate.c b/xlate/xlate.c
new file mode 100644
index 00000000000..6a84c31443e
--- /dev/null
+++ b/xlate/xlate.c
@@ -0,0 +1,406 @@
+/* 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 "apu.h"
+#include "apr_private.h"
+#include "apr_lib.h"
+#include "apr_strings.h"
+#include "apr_portable.h"
+#include "apr_xlate.h"
+
+/* If no implementation is available, don't generate code here since
+ * apr_xlate.h emitted macros which return APR_ENOTIMPL.
+ */
+
+#if APR_HAS_XLATE
+
+#ifdef HAVE_STDDEF_H
+#include <stddef.h> /* for NULL */
+#endif
+#if APR_HAVE_STRING_H
+#include <string.h>
+#endif
+#if APR_HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#ifdef HAVE_ICONV_H
+#include <iconv.h>
+#endif
+
+#if defined(APU_ICONV_INBUF_CONST)
+#define ICONV_INBUF_TYPE const char **
+#else
+#define ICONV_INBUF_TYPE char **
+#endif
+
+#ifndef min
+#define min(x,y) ((x) <= (y) ? (x) : (y))
+#endif
+
+struct apr_xlate_t {
+    apr_pool_t *pool;
+    char *frompage;
+    char *topage;
+    char *sbcs_table;
+#if APU_HAVE_ICONV
+    iconv_t ich;
+#endif
+};
+
+
+static const char *handle_special_names(const char *page, apr_pool_t *pool)
+{
+    if (page == APR_DEFAULT_CHARSET) {
+        return apr_os_default_encoding(pool);
+    }
+    else if (page == APR_LOCALE_CHARSET) {
+        return apr_os_locale_encoding(pool);
+    }
+#ifdef __MVS__
+    else if (!strcasecmp(page, "ISO-8859-1")) {
+       	return "ISO8859-1"; /* z/OS ASCII name has no dash after ISO */
+    }
+#endif
+    else {
+        return page;
+    }
+}
+
+static apr_status_t apr_xlate_cleanup(void *convset)
+{
+    apr_xlate_t *old = convset;
+
+#if APU_HAVE_ICONV
+    if (old->ich != (iconv_t)-1) {
+        if (iconv_close(old->ich)) {
+            int rv = errno;
+
+            /* Sometimes, iconv is not good about setting errno. */
+            return rv ? rv : APR_EINVAL;
+        }
+    }
+#endif
+
+    return APR_SUCCESS;
+}
+
+#if APU_HAVE_ICONV
+static void check_sbcs(apr_xlate_t *convset)
+{
+    char inbuf[256], outbuf[256];
+    char *inbufptr = inbuf;
+    char *outbufptr = outbuf;
+    apr_size_t inbytes_left, outbytes_left;
+    int i;
+    apr_size_t translated;
+
+    for (i = 0; i < sizeof(inbuf); i++) {
+        inbuf[i] = i;
+    }
+
+    inbytes_left = outbytes_left = sizeof(inbuf);
+    translated = iconv(convset->ich, (ICONV_INBUF_TYPE)&inbufptr,
+                       &inbytes_left, &outbufptr, &outbytes_left);
+
+    if (translated != (apr_size_t)-1
+        && inbytes_left == 0
+        && outbytes_left == 0) {
+        /* hurray... this is simple translation; save the table,
+         * close the iconv descriptor
+         */
+
+        convset->sbcs_table = apr_pmemdup(convset->pool, outbuf, sizeof(outbuf));
+
+        iconv_close(convset->ich);
+        convset->ich = (iconv_t)-1;
+
+        /* TODO: add the table to the cache */
+    }
+    else {
+        /* reset the iconv descriptor, since it's now in an undefined
+         * state. */
+        iconv_close(convset->ich);
+        convset->ich = iconv_open(convset->topage, convset->frompage);
+    }
+}
+#elif APU_HAVE_APR_ICONV
+static void check_sbcs(apr_xlate_t *convset)
+{
+    char inbuf[256], outbuf[256];
+    char *inbufptr = inbuf;
+    char *outbufptr = outbuf;
+    apr_size_t inbytes_left, outbytes_left;
+    int i;
+    apr_size_t translated;
+    apr_status_t rv;
+
+    for (i = 0; i < sizeof(inbuf); i++) {
+        inbuf[i] = i;
+    }
+
+    inbytes_left = outbytes_left = sizeof(inbuf);
+    rv = apr_iconv(convset->ich, (ICONV_INBUF_TYPE)&inbufptr,
+                   &inbytes_left, &outbufptr, &outbytes_left,
+                   &translated);
+
+    if ((rv == APR_SUCCESS)
+        && (translated != (apr_size_t)-1)
+        && inbytes_left == 0
+        && outbytes_left == 0) {
+        /* hurray... this is simple translation; save the table,
+         * close the iconv descriptor
+         */
+
+        convset->sbcs_table = apr_palloc(convset->pool, sizeof(outbuf));
+        memcpy(convset->sbcs_table, outbuf, sizeof(outbuf));
+        apr_iconv_close(convset->ich, convset->pool);
+        convset->ich = (apr_iconv_t)-1;
+
+        /* TODO: add the table to the cache */
+    }
+    else {
+        /* reset the iconv descriptor, since it's now in an undefined
+         * state. */
+        apr_iconv_close(convset->ich, convset->pool);
+        rv = apr_iconv_open(convset->topage, convset->frompage, 
+                            convset->pool, &convset->ich);
+    }
+}
+#endif /* APU_HAVE_APR_ICONV */
+
+static void make_identity_table(apr_xlate_t *convset)
+{
+  int i;
+
+  convset->sbcs_table = apr_palloc(convset->pool, 256);
+  for (i = 0; i < 256; i++)
+      convset->sbcs_table[i] = i;
+}
+
+APR_DECLARE(apr_status_t) apr_xlate_open(apr_xlate_t **convset,
+                                         const char *topage,
+                                         const char *frompage,
+                                         apr_pool_t *pool)
+{
+    apr_status_t rv;
+    apr_xlate_t *new;
+    int found = 0;
+
+    *convset = NULL;
+
+    topage = handle_special_names(topage, pool);
+    frompage = handle_special_names(frompage, pool);
+
+    new = (apr_xlate_t *)apr_pcalloc(pool, sizeof(apr_xlate_t));
+    if (!new) {
+        return APR_ENOMEM;
+    }
+
+    new->pool = pool;
+    new->topage = apr_pstrdup(pool, topage);
+    new->frompage = apr_pstrdup(pool, frompage);
+    if (!new->topage || !new->frompage) {
+        return APR_ENOMEM;
+    }
+
+#ifdef TODO
+    /* search cache of codepage pairs; we may be able to avoid the
+     * expensive iconv_open()
+     */
+
+    set found to non-zero if found in the cache
+#endif
+
+    if ((! found) && (strcmp(topage, frompage) == 0)) {
+        /* to and from are the same */
+        found = 1;
+        make_identity_table(new);
+    }
+
+#if APU_HAVE_APR_ICONV
+    if (!found) {
+        rv = apr_iconv_open(topage, frompage, pool, &new->ich);
+        if (rv != APR_SUCCESS) {
+            return rv;
+        }
+        found = 1;
+        check_sbcs(new);
+    } else
+        new->ich = (apr_iconv_t)-1;
+
+#elif APU_HAVE_ICONV
+    if (!found) {
+        new->ich = iconv_open(topage, frompage);
+        if (new->ich == (iconv_t)-1) {
+            int rv = errno;
+            /* Sometimes, iconv is not good about setting errno. */
+            return rv ? rv : APR_EINVAL;
+        }
+        found = 1;
+        check_sbcs(new);
+    } else
+        new->ich = (iconv_t)-1;
+#endif /* APU_HAVE_ICONV */
+
+    if (found) {
+        *convset = new;
+        apr_pool_cleanup_register(pool, (void *)new, apr_xlate_cleanup,
+                            apr_pool_cleanup_null);
+        rv = APR_SUCCESS;
+    }
+    else {
+        rv = APR_EINVAL; /* iconv() would return EINVAL if it
+                                couldn't handle the pair */
+    }
+
+    return rv;
+}
+
+APR_DECLARE(apr_status_t) apr_xlate_sb_get(apr_xlate_t *convset, int *onoff)
+{
+    *onoff = convset->sbcs_table != NULL;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_xlate_conv_buffer(apr_xlate_t *convset,
+                                                const char *inbuf,
+                                                apr_size_t *inbytes_left,
+                                                char *outbuf,
+                                                apr_size_t *outbytes_left)
+{
+    apr_status_t status = APR_SUCCESS;
+
+#if APU_HAVE_ICONV
+    if (convset->ich != (iconv_t)-1) {
+        const char *inbufptr = inbuf;
+        char *outbufptr = outbuf;
+        apr_size_t translated;
+        translated = iconv(convset->ich, (ICONV_INBUF_TYPE)&inbufptr,
+                           inbytes_left, &outbufptr, outbytes_left);
+
+        /* If everything went fine but we ran out of buffer, don't
+         * report it as an error.  Caller needs to look at the two
+         * bytes-left values anyway.
+         *
+         * There are three expected cases where rc is -1.  In each of
+         * these cases, *inbytes_left != 0.
+         * a) the non-error condition where we ran out of output
+         *    buffer
+         * b) the non-error condition where we ran out of input (i.e.,
+         *    the last input character is incomplete)
+         * c) the error condition where the input is invalid
+         */
+        if (translated == (apr_size_t)-1) {
+            int rv = errno;
+            switch (rv) {
+
+            case E2BIG:  /* out of space on output */
+                status = 0; /* change table lookup code below if you
+                               make this an error */
+                break;
+
+            case EINVAL: /* input character not complete (yet) */
+                status = APR_INCOMPLETE;
+                break;
+
+            case EILSEQ: /* bad input byte */
+                status = APR_EINVAL;
+                break;
+
+             /* Sometimes, iconv is not good about setting errno. */
+            case 0:
+                status = APR_INCOMPLETE;
+                break;
+
+            default:
+                status = rv;
+                break;
+            }
+        }
+    }
+    else
+#endif
+
+    if (inbuf) {
+        apr_size_t to_convert = min(*inbytes_left, *outbytes_left);
+        apr_size_t converted = to_convert;
+        char *table = convset->sbcs_table;
+
+        while (to_convert) {
+            *outbuf = table[(unsigned char)*inbuf];
+            ++outbuf;
+            ++inbuf;
+            --to_convert;
+        }
+        *inbytes_left -= converted;
+        *outbytes_left -= converted;
+    }
+
+    return status;
+}
+
+APR_DECLARE(apr_int32_t) apr_xlate_conv_byte(apr_xlate_t *convset,
+                                             unsigned char inchar)
+{
+    if (convset->sbcs_table) {
+        return convset->sbcs_table[inchar];
+    }
+    else {
+        return -1;
+    }
+}
+
+APR_DECLARE(apr_status_t) apr_xlate_close(apr_xlate_t *convset)
+{
+    return apr_pool_cleanup_run(convset->pool, convset, apr_xlate_cleanup);
+}
+
+#else /* !APR_HAS_XLATE */
+
+APR_DECLARE(apr_status_t) apr_xlate_open(apr_xlate_t **convset,
+                                         const char *topage,
+                                         const char *frompage,
+                                         apr_pool_t *pool)
+{
+    return APR_ENOTIMPL;
+}
+
+APR_DECLARE(apr_status_t) apr_xlate_sb_get(apr_xlate_t *convset, int *onoff)
+{
+    return APR_ENOTIMPL;
+}
+
+APR_DECLARE(apr_int32_t) apr_xlate_conv_byte(apr_xlate_t *convset,
+                                             unsigned char inchar)
+{
+    return (-1);
+}
+
+APR_DECLARE(apr_status_t) apr_xlate_conv_buffer(apr_xlate_t *convset,
+                                                const char *inbuf,
+                                                apr_size_t *inbytes_left,
+                                                char *outbuf,
+                                                apr_size_t *outbytes_left)
+{
+    return APR_ENOTIMPL;
+}
+
+APR_DECLARE(apr_status_t) apr_xlate_close(apr_xlate_t *convset)
+{
+    return APR_ENOTIMPL;
+}
+
+#endif /* APR_HAS_XLATE */
diff --git a/xml/NWGNUmakefile b/xml/NWGNUmakefile
new file mode 100644
index 00000000000..9225c6bce4d
--- /dev/null
+++ b/xml/NWGNUmakefile
@@ -0,0 +1,303 @@
+#
+# 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 $(APR_WORK)/build/NWGNUhead.inc
+
+#
+# build this level's files
+
+#
+# Make sure all needed macro's are defined
+#
+
+ifdef EXPATSRC
+
+ifeq "$(wildcard $(EXPATSRC)/lib/expat.h.in)" "$(EXPATSRC)/lib/expat.h.in"
+EXPAT_prebuild_headers += $(EXPATSRC)/lib/expat.h
+endif
+ifeq "$(wildcard $(EXPATSRC)/lib/config.hnw)" "$(EXPATSRC)/lib/config.hnw"
+EXPAT_prebuild_headers += $(EXPATSRC)/lib/config.h
+endif
+ifeq "$(wildcard $(EXPATSRC)/expat_config.h.in)" "$(EXPATSRC)/expat_config.h.in"
+EXPAT_prebuild_headers += $(EXPATSRC)/lib/expat_config.h
+endif
+
+$(EXPATSRC)/lib/%.h: $(EXPATSRC)/lib/%.hnw
+	@echo Creating $@
+	$(call COPY,$<,$@)
+
+$(EXPATSRC)/lib/%.h: $(EXPATSRC)/lib/%.h.in
+	@echo Creating $@
+	$(call COPY,$<,$@)
+
+$(EXPATSRC)/lib/expat_config.h:
+	@echo Creating $@
+	@echo $(DL)/* $(notdir $@) for NetWare platform */$(DL)>>$@
+	@echo $(DL)#ifndef NETWARE$(DL)>>$@
+	@echo $(DL)#error This $(notdir $@) is for NetWare platform!$(DL)>>$@
+	@echo $(DL)#endif$(DL)>>$@
+	@echo $(DL)#ifndef EXPAT_CONFIG_H$(DL)>>$@
+	@echo $(DL)#define EXPAT_CONFIG_H$(DL)>>$@
+	@echo $(DL)#define HAVE_MEMMOVE 1$(DL)>>$@
+	@echo $(DL)#define XML_NS 1$(DL)>>$@
+	@echo $(DL)#define XML_DTD 1$(DL)>>$@
+	@echo $(DL)#define XML_BYTE_ORDER 1234$(DL)>>$@
+	@echo $(DL)#define XML_CONTEXT_BYTES 1024$(DL)>>$@
+	@echo $(DL)#endif /* EXPAT_CONFIG_H */$(DL)>>$@
+
+vpath %.c $(EXPATSRC)/lib
+
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS	+= \
+			$(EXPAT_INC) \
+			$(APR)/include \
+			$(APR)/include/private \
+			$(APR)/include/arch/netware \
+			$(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS		+= \
+			$(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES	+= \
+			-DAPU_USE_EXPAT=1 \
+			-DHAVE_EXPAT_CONFIG_H \
+			$(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS		+= \
+			$(EOLIST)
+
+#
+# These values will be appended to the correct variables based on the value of
+# RELEASE
+#
+ifeq "$(RELEASE)" "debug"
+XINCDIRS	+= \
+			$(EOLIST)
+
+XCFLAGS		+= \
+			$(EOLIST)
+
+XDEFINES	+= \
+			$(EOLIST)
+
+XLFLAGS		+= \
+			$(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "noopt"
+XINCDIRS	+= \
+			$(EOLIST)
+
+XCFLAGS		+= \
+			$(EOLIST)
+
+XDEFINES	+= \
+			$(EOLIST)
+
+XLFLAGS		+= \
+			$(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "release"
+XINCDIRS	+= \
+			$(EOLIST)
+
+XCFLAGS		+= \
+			$(EOLIST)
+
+XDEFINES	+= \
+			$(EOLIST)
+
+XLFLAGS		+= \
+			$(EOLIST)
+endif
+
+#
+# These are used by the link target if an NLM is being generated
+# This is used by the link 'name' directive to name the nlm.  If left blank
+# TARGET_nlm (see below) will be used.
+#
+NLM_NAME	= 
+
+#
+# This is used by the link '-desc ' directive. 
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION	= 
+
+#
+# This is used by the '-threadname' directive.  If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME	= 
+#
+# If this is specified, it will override VERSION value in 
+# $(APR_WORK)/build/NWGNUenvironment.inc
+#
+NLM_VERSION	=
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE	= 
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM	= 
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM	= 
+
+#
+# If this is specified it will be used by the link '-check' directive
+#
+NLM_CHECK_SYM	=
+
+#
+# If this is 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 $(APR)/misc/netware/apache.xdc.  XDCData can 
+# be disabled by setting APACHE_UNIPROC in the environment
+#
+XDCDATA		= 
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+	$(EOLIST)
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+	$(OBJDIR)/xml.lib \
+	$(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+	$(EOLIST)
+
+#
+# These are the LIB files needed to create the NLM target above.
+# These will be added as a library command in the link.opt file.
+#
+FILES_nlm_libs = \
+	$(EOLIST)
+
+#
+# These are the modules that the above NLM target depends on to load.
+# These will be added as a module command in the link.opt file.
+#
+FILES_nlm_modules = \
+	$(EOLIST)
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+ 
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override the default copyright.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+	$(EOLIST)
+ 
+#   
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+	$(EOLIST)
+
+#   
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+	$(OBJDIR)/apr_xml.o \
+	$(OBJDIR)/apr_xml_expat.o \
+	$(EOLIST)
+
+ifdef EXPATSRC
+FILES_lib_objs += \
+	$(OBJDIR)/xmlparse.o \
+	$(OBJDIR)/xmlrole.o \
+	$(OBJDIR)/xmltok.o \
+	$(EOLIST)
+endif
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(EXPAT_prebuild_headers) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the 
+# correct place.  (See $(APR_WORK)/build/NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+clean ::
+	$(foreach file,$(EXPAT_prebuild_headers),$(call DEL,$(file)))
+
+#
+# Any specialized rules here
+#
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(APRBUILD)/NWGNUtail.inc
+
diff --git a/xml/apr_xml.c b/xml/apr_xml.c
new file mode 100644
index 00000000000..82791f49da9
--- /dev/null
+++ b/xml/apr_xml.c
@@ -0,0 +1,977 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_private.h"
+#include "apr_strings.h"
+
+#define APR_WANT_STDIO          /* for sprintf() */
+#define APR_WANT_STRFUNC
+#include "apr_want.h"
+
+#include "apr_xml.h"
+typedef void* XML_Parser;
+typedef int XML_Error;
+typedef unsigned char XML_Char;
+#include "apr_xml_internal.h"
+
+#define DEBUG_CR "\r\n"
+
+static const char APR_KW_xmlns[] = { 0x78, 0x6D, 0x6C, 0x6E, 0x73, '\0' };
+static const char APR_KW_xmlns_lang[] = { 0x78, 0x6D, 0x6C, 0x3A, 0x6C, 0x61, 0x6E, 0x67, '\0' };
+
+/* errors related to namespace processing */
+#define APR_XML_NS_ERROR_UNKNOWN_PREFIX (-1000)
+#define APR_XML_NS_ERROR_INVALID_DECL (-1001)
+
+/* test for a namespace prefix that begins with [Xx][Mm][Ll] */
+#define APR_XML_NS_IS_RESERVED(name) \
+        ( (name[0] == 0x58 || name[0] == 0x78) && \
+          (name[1] == 0x4D || name[1] == 0x6D) && \
+          (name[2] == 0x4C || name[2] == 0x6C) )
+
+
+/* struct for scoping namespace declarations */
+typedef struct apr_xml_ns_scope {
+    const char *prefix;         /* prefix used for this ns */
+    int ns;                     /* index into namespace table */
+    int emptyURI;               /* the namespace URI is the empty string */
+    struct apr_xml_ns_scope *next;      /* next scoped namespace */
+} apr_xml_ns_scope;
+
+
+/* return namespace table index for a given prefix */
+static int find_prefix(apr_xml_parser *parser, const char *prefix)
+{
+    apr_xml_elem *elem = parser->cur_elem;
+
+    /*
+    ** Walk up the tree, looking for a namespace scope that defines this
+    ** prefix.
+    */
+    for (; elem; elem = elem->parent) {
+        apr_xml_ns_scope *ns_scope;
+
+        for (ns_scope = elem->ns_scope; ns_scope; ns_scope = ns_scope->next) {
+            if (strcmp(prefix, ns_scope->prefix) == 0) {
+                if (ns_scope->emptyURI) {
+                    /*
+                    ** It is possible to set the default namespace to an
+                    ** empty URI string; this resets the default namespace
+                    ** to mean "no namespace." We just found the prefix
+                    ** refers to an empty URI, so return "no namespace."
+                    */
+                    return APR_XML_NS_NONE;
+                }
+
+                return ns_scope->ns;
+            }
+        }
+    }
+
+    /*
+     * If the prefix is empty (""), this means that a prefix was not
+     * specified in the element/attribute. The search that was performed
+     * just above did not locate a default namespace URI (which is stored
+     * into ns_scope with an empty prefix). This means the element/attribute
+     * has "no namespace". We have a reserved value for this.
+     */
+    if (*prefix == '\0') {
+        return APR_XML_NS_NONE;
+    }
+
+    /* not found */
+    return APR_XML_NS_ERROR_UNKNOWN_PREFIX;
+}
+
+/* return original prefix given ns index */
+static const char * find_prefix_name(const apr_xml_elem *elem, int ns, int parent)
+{
+    /*
+    ** Walk up the tree, looking for a namespace scope that defines this
+    ** prefix.
+    */
+    for (; elem; elem = parent ? elem->parent : NULL) {
+       apr_xml_ns_scope *ns_scope = elem->ns_scope;
+
+       for (; ns_scope; ns_scope = ns_scope->next) {
+           if (ns_scope->ns == ns)
+               return ns_scope->prefix;
+       }
+    }
+    /* not found */
+    return "";
+}
+
+static void start_handler(void *userdata, const char *name, const char **attrs)
+{
+    apr_xml_parser *parser = userdata;
+    apr_xml_elem *elem;
+    apr_xml_attr *attr;
+    apr_xml_attr *prev;
+    char *colon;
+    const char *quoted;
+    char *elem_name;
+
+    /* punt once we find an error */
+    if (parser->error)
+        return;
+
+    elem = apr_pcalloc(parser->p, sizeof(*elem));
+
+    /* prep the element */
+    elem->name = elem_name = apr_pstrdup(parser->p, name);
+
+    /* fill in the attributes (note: ends up in reverse order) */
+    while (attrs && *attrs) {
+        attr = apr_palloc(parser->p, sizeof(*attr));
+        attr->name = apr_pstrdup(parser->p, *attrs++);
+        attr->value = apr_pstrdup(parser->p, *attrs++);
+        attr->next = elem->attr;
+        elem->attr = attr;
+    }
+
+    /* hook the element into the tree */
+    if (parser->cur_elem == NULL) {
+        /* no current element; this also becomes the root */
+        parser->cur_elem = parser->doc->root = elem;
+    }
+    else {
+        /* this element appeared within the current elem */
+        elem->parent = parser->cur_elem;
+
+        /* set up the child/sibling links */
+        if (elem->parent->last_child == NULL) {
+            /* no first child either */
+            elem->parent->first_child = elem->parent->last_child = elem;
+        }
+        else {
+            /* hook onto the end of the parent's children */
+            elem->parent->last_child->next = elem;
+            elem->parent->last_child = elem;
+        }
+
+        /* this element is now the current element */
+        parser->cur_elem = elem;
+    }
+
+    /* scan the attributes for namespace declarations */
+    for (prev = NULL, attr = elem->attr;
+         attr;
+         attr = attr->next) {
+        if (strncmp(attr->name, APR_KW_xmlns, 5) == 0) {
+            const char *prefix = &attr->name[5];
+            apr_xml_ns_scope *ns_scope;
+
+            /* test for xmlns:foo= form and xmlns= form */
+            if (*prefix == 0x3A) {
+                /* a namespace prefix declaration must have a
+                   non-empty value. */
+                if (attr->value[0] == '\0') {
+                    parser->error = APR_XML_NS_ERROR_INVALID_DECL;
+                    return;
+                }
+                ++prefix;
+            }
+            else if (*prefix != '\0') {
+                /* advance "prev" since "attr" is still present */
+                prev = attr;
+                continue;
+            }
+
+            /* quote the URI before we ever start working with it */
+            quoted = apr_xml_quote_string(parser->p, attr->value, 1);
+
+            /* build and insert the new scope */
+            ns_scope = apr_pcalloc(parser->p, sizeof(*ns_scope));
+            ns_scope->prefix = prefix;
+            ns_scope->ns = apr_xml_insert_uri(parser->doc->namespaces, quoted);
+            ns_scope->emptyURI = *quoted == '\0';
+            ns_scope->next = elem->ns_scope;
+            elem->ns_scope = ns_scope;
+
+            /* remove this attribute from the element */
+            if (prev == NULL)
+                elem->attr = attr->next;
+            else
+                prev->next = attr->next;
+
+            /* Note: prev will not be advanced since we just removed "attr" */
+        }
+        else if (strcmp(attr->name, APR_KW_xmlns_lang) == 0) {
+            /* save away the language (in quoted form) */
+            elem->lang = apr_xml_quote_string(parser->p, attr->value, 1);
+
+            /* remove this attribute from the element */
+            if (prev == NULL)
+                elem->attr = attr->next;
+            else
+                prev->next = attr->next;
+
+            /* Note: prev will not be advanced since we just removed "attr" */
+        }
+        else {
+            /* advance "prev" since "attr" is still present */
+            prev = attr;
+        }
+    }
+
+    /*
+    ** If an xml:lang attribute didn't exist (lang==NULL), then copy the
+    ** language from the parent element (if present).
+    **
+    ** NOTE: elem_size() *depends* upon this pointer equality.
+    */
+    if (elem->lang == NULL && elem->parent != NULL)
+        elem->lang = elem->parent->lang;
+
+    /* adjust the element's namespace */
+    colon = strchr(elem_name, 0x3A);
+    if (colon == NULL) {
+        /*
+         * The element is using the default namespace, which will always
+         * be found. Either it will be "no namespace", or a default
+         * namespace URI has been specified at some point.
+         */
+        elem->ns = find_prefix(parser, "");
+    }
+    else if (APR_XML_NS_IS_RESERVED(elem->name)) {
+        elem->ns = APR_XML_NS_NONE;
+    }
+    else {
+        *colon = '\0';
+        elem->ns = find_prefix(parser, elem->name);
+        elem->name = colon + 1;
+
+        if (APR_XML_NS_IS_ERROR(elem->ns)) {
+            parser->error = elem->ns;
+            return;
+        }
+    }
+
+    /* adjust all remaining attributes' namespaces */
+    for (attr = elem->attr; attr; attr = attr->next) {
+        /*
+         * apr_xml_attr defines this as "const" but we dup'd it, so we
+         * know that we can change it. a bit hacky, but the existing
+         * structure def is best.
+         */
+        char *attr_name = (char *)attr->name;
+
+        colon = strchr(attr_name, 0x3A);
+        if (colon == NULL) {
+            /*
+             * Attributes do NOT use the default namespace. Therefore,
+             * we place them into the "no namespace" category.
+             */
+            attr->ns = APR_XML_NS_NONE;
+        }
+        else if (APR_XML_NS_IS_RESERVED(attr->name)) {
+            attr->ns = APR_XML_NS_NONE;
+        }
+        else {
+            *colon = '\0';
+            attr->ns = find_prefix(parser, attr->name);
+            attr->name = colon + 1;
+
+            if (APR_XML_NS_IS_ERROR(attr->ns)) {
+                parser->error = attr->ns;
+                return;
+            }
+        }
+    }
+}
+
+static void end_handler(void *userdata, const char *name)
+{
+    apr_xml_parser *parser = userdata;
+
+    /* punt once we find an error */
+    if (parser->error)
+        return;
+
+    /* pop up one level */
+    parser->cur_elem = parser->cur_elem->parent;
+}
+
+static void cdata_handler(void *userdata, const char *data, int len)
+{
+    apr_xml_parser *parser = userdata;
+    apr_xml_elem *elem;
+    apr_text_header *hdr;
+    const char *s;
+
+    /* punt once we find an error */
+    if (parser->error)
+        return;
+
+    elem = parser->cur_elem;
+    s = apr_pstrndup(parser->p, data, len);
+
+    if (elem->last_child == NULL) {
+        /* no children yet. this cdata follows the start tag */
+        hdr = &elem->first_cdata;
+    }
+    else {
+        /* child elements exist. this cdata follows the last child. */
+        hdr = &elem->last_child->following_cdata;
+    }
+
+    apr_text_append(parser->p, hdr, s);
+}
+
+APR_DECLARE(apr_xml_parser *) apr_xml_parser_create(apr_pool_t *pool)
+{
+    return apr_xml_parser_create_internal(pool, &start_handler, &end_handler, &cdata_handler);
+}
+
+APR_DECLARE(apr_status_t) apr_xml_parser_feed(apr_xml_parser *parser,
+                                              const char *data,
+                                              apr_size_t len)
+{
+    return parser->impl->Parse(parser, data, len, 0 /* is_final */);
+}
+
+APR_DECLARE(apr_status_t) apr_xml_parser_done(apr_xml_parser *parser,
+                                              apr_xml_doc **pdoc)
+{
+    char end;
+    apr_status_t status = parser->impl->Parse(parser, &end, 0, 1 /* is_final */);
+
+    /* get rid of the parser */
+    (void) apr_pool_cleanup_run(parser->p, parser, parser->impl->cleanup);
+
+    if (status)
+        return status;
+
+    if (pdoc != NULL)
+        *pdoc = parser->doc;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(char *) apr_xml_parser_geterror(apr_xml_parser *parser,
+                                            char *errbuf,
+                                            apr_size_t errbufsize)
+{
+    int error = parser->error;
+    const char *msg;
+
+    /* clear our record of an error */
+    parser->error = 0;
+
+    switch (error) {
+    case 0:
+        msg = "No error.";
+        break;
+
+    case APR_XML_NS_ERROR_UNKNOWN_PREFIX:
+        msg = "An undefined namespace prefix was used.";
+        break;
+
+    case APR_XML_NS_ERROR_INVALID_DECL:
+        msg = "A namespace prefix was defined with an empty URI.";
+        break;
+
+    case APR_XML_ERROR_EXPAT:
+        (void) apr_snprintf(errbuf, errbufsize,
+                            "XML parser error code: %s (%d)",
+                            parser->xp_msg, parser->xp_err);
+        return errbuf;
+
+    case APR_XML_ERROR_PARSE_DONE:
+        msg = "The parser is not active.";
+        break;
+
+    default:
+        msg = "There was an unknown error within the XML body.";
+        break;
+    }
+
+    (void) apr_cpystrn(errbuf, msg, errbufsize);
+    return errbuf;
+}
+
+APR_DECLARE(apr_status_t) apr_xml_parse_file(apr_pool_t *p,
+                                             apr_xml_parser **parser,
+                                             apr_xml_doc **ppdoc,
+                                             apr_file_t *xmlfd,
+                                             apr_size_t buffer_length)
+{
+    apr_status_t rv;
+    char *buffer;
+    apr_size_t length;
+
+    *parser = apr_xml_parser_create(p);
+    if (*parser == NULL) {
+        /* FIXME: returning an error code would be nice,
+         * but we dont get one ;( */
+        return APR_EGENERAL;
+    }
+    buffer = apr_palloc(p, buffer_length);
+    length = buffer_length;
+
+    rv = apr_file_read(xmlfd, buffer, &length);
+
+    while (rv == APR_SUCCESS) {
+        rv = apr_xml_parser_feed(*parser, buffer, length);
+        if (rv != APR_SUCCESS) {
+            return rv;
+        }
+
+        length = buffer_length;
+        rv = apr_file_read(xmlfd, buffer, &length);
+    }
+    if (rv != APR_EOF) {
+        return rv;
+    }
+    rv = apr_xml_parser_done(*parser, ppdoc);
+    *parser = NULL;
+    return rv;
+}
+
+APR_DECLARE(void) apr_text_append(apr_pool_t * p, apr_text_header *hdr,
+                                  const char *text)
+{
+    apr_text *t = apr_palloc(p, sizeof(*t));
+
+    t->text = text;
+    t->next = NULL;
+
+    if (hdr->first == NULL) {
+        /* no text elements yet */
+        hdr->first = hdr->last = t;
+    }
+    else {
+        /* append to the last text element */
+        hdr->last->next = t;
+        hdr->last = t;
+    }
+}
+
+
+/* ---------------------------------------------------------------
+**
+** XML UTILITY FUNCTIONS
+*/
+
+/*
+** apr_xml_quote_string: quote an XML string
+**
+** Replace '<', '>', and '&' with '&lt;', '&gt;', and '&amp;'.
+** If quotes is true, then replace '"' with '&quot;'.
+**
+** quotes is typically set to true for XML strings that will occur within
+** double quotes -- attribute values.
+*/
+APR_DECLARE(const char *) apr_xml_quote_string(apr_pool_t *p, const char *s,
+                                               int quotes)
+{
+    const char *scan;
+    apr_size_t len = 0;
+    apr_size_t extra = 0;
+    char *qstr;
+    char *qscan;
+    char c;
+
+    for (scan = s; (c = *scan) != '\0'; ++scan, ++len) {
+        if (c == '<' || c == '>')
+            extra += 3;         /* &lt; or &gt; */
+        else if (c == '&')
+            extra += 4;         /* &amp; */
+        else if (quotes && c == '"')
+            extra += 5;         /* &quot; */
+    }
+
+    /* nothing to do? */
+    if (extra == 0)
+        return s;
+
+    qstr = apr_palloc(p, len + extra + 1);
+    for (scan = s, qscan = qstr; (c = *scan) != '\0'; ++scan) {
+        if (c == '<') {
+            *qscan++ = '&';
+            *qscan++ = 'l';
+            *qscan++ = 't';
+            *qscan++ = ';';
+        }
+        else if (c == '>') {
+            *qscan++ = '&';
+            *qscan++ = 'g';
+            *qscan++ = 't';
+            *qscan++ = ';';
+        }
+        else if (c == '&') {
+            *qscan++ = '&';
+            *qscan++ = 'a';
+            *qscan++ = 'm';
+            *qscan++ = 'p';
+            *qscan++ = ';';
+        }
+        else if (quotes && c == '"') {
+            *qscan++ = '&';
+            *qscan++ = 'q';
+            *qscan++ = 'u';
+            *qscan++ = 'o';
+            *qscan++ = 't';
+            *qscan++ = ';';
+        }
+        else {
+            *qscan++ = c;
+        }
+    }
+
+    *qscan = '\0';
+    return qstr;
+}
+
+/* how many characters for the given integer? */
+#define APR_XML_NS_LEN(ns) ((ns) < 10 ? 1 : (ns) < 100 ? 2 : (ns) < 1000 ? 3 : \
+                            (ns) < 10000 ? 4 : (ns) < 100000 ? 5 : \
+                            (ns) < 1000000 ? 6 : (ns) < 10000000 ? 7 : \
+                            (ns) < 100000000 ? 8 : (ns) < 1000000000 ? 9 : 10)
+
+static apr_size_t text_size(const apr_text *t)
+{
+    apr_size_t size = 0;
+
+    for (; t; t = t->next)
+        size += strlen(t->text);
+    return size;
+}
+
+static apr_size_t elem_size(const apr_xml_elem *elem, int style,
+                            apr_array_header_t *namespaces, int *ns_map)
+{
+    apr_size_t size;
+
+    if (style == APR_XML_X2T_FULL || style == APR_XML_X2T_FULL_NS_LANG ||
+        style == APR_XML_X2T_PARSED) {
+        const apr_xml_attr *attr;
+
+        size = 0;
+
+        if (style == APR_XML_X2T_FULL_NS_LANG) {
+            int i;
+
+            /*
+            ** The outer element will contain xmlns:ns%d="%s" attributes
+            ** and an xml:lang attribute, if applicable.
+            */
+
+            for (i = namespaces->nelts; i--;) {
+                /* compute size of: ' xmlns:ns%d="%s"' */
+                size += (9 + APR_XML_NS_LEN(i) + 2 +
+                         strlen(APR_XML_GET_URI_ITEM(namespaces, i)) + 1);
+            }
+
+            if (elem->lang != NULL) {
+                /* compute size of: ' xml:lang="%s"' */
+                size += 11 + strlen(elem->lang) + 1;
+            }
+        }
+        else if (style == APR_XML_X2T_PARSED) {
+            apr_xml_ns_scope *ns_scope = elem->ns_scope;
+
+            /* compute size of: ' xmlns:%s="%s"' */
+            for (; ns_scope; ns_scope = ns_scope->next) {
+                size += 10 + strlen(find_prefix_name(elem, ns_scope->ns, 0)) +
+                             strlen(APR_XML_GET_URI_ITEM(namespaces, ns_scope->ns));
+            }
+
+            if (elem->lang != NULL) {
+                /* compute size of: ' xml:lang="%s"' */
+                size += 11 + strlen(elem->lang) + 1;
+            }
+        }
+
+        if (elem->ns == APR_XML_NS_NONE) {
+            /* compute size of: <%s> */
+            size += 1 + strlen(elem->name) + 1;
+        }
+        else if (style == APR_XML_X2T_PARSED) {
+            /* compute size of: <%s:%s> */
+            size += 3 + strlen(find_prefix_name(elem, elem->ns, 1)) + strlen(elem->name);
+        }
+        else {
+            int ns = ns_map ? ns_map[elem->ns] : elem->ns;
+
+            /* compute size of: <ns%d:%s> */
+            size += 3 + APR_XML_NS_LEN(ns) + 1 + strlen(elem->name) + 1;
+        }
+
+        if (APR_XML_ELEM_IS_EMPTY(elem)) {
+            /* insert a closing "/" */
+            size += 1;
+        }
+        else {
+            /*
+             * two of above plus "/":
+             *     <ns%d:%s> ... </ns%d:%s>
+             * OR  <%s> ... </%s>
+             */
+            size = 2 * size + 1;
+        }
+
+        for (attr = elem->attr; attr; attr = attr->next) {
+            if (attr->ns == APR_XML_NS_NONE) {
+                /* compute size of: ' %s="%s"' */
+                size += 1 + strlen(attr->name) + 2 + strlen(attr->value) + 1;
+            }
+            else if (style == APR_XML_X2T_PARSED) {
+                /* compute size of: ' %s:%s="%s"' */
+                size += 5 + strlen(find_prefix_name(elem, attr->ns, 1)) + strlen(attr->name) + strlen(attr->value);
+            }
+            else {
+                /* compute size of: ' ns%d:%s="%s"' */
+                int ns = ns_map ? ns_map[attr->ns] : attr->ns;
+                size += 3 + APR_XML_NS_LEN(ns) + 1 + strlen(attr->name) + 2 + strlen(attr->value) + 1;
+            }
+        }
+
+        /*
+        ** If the element has an xml:lang value that is *different* from
+        ** its parent, then add the thing in: ' xml:lang="%s"'.
+        **
+        ** NOTE: we take advantage of the pointer equality established by
+        ** the parsing for "inheriting" the xml:lang values from parents.
+        */
+        if (elem->lang != NULL &&
+            (elem->parent == NULL || elem->lang != elem->parent->lang)) {
+            size += 11 + strlen(elem->lang) + 1;
+        }
+    }
+    else if (style == APR_XML_X2T_LANG_INNER) {
+        /*
+         * This style prepends the xml:lang value plus a null terminator.
+         * If a lang value is not present, then we insert a null term.
+         */
+        size = elem->lang ? strlen(elem->lang) + 1 : 1;
+    }
+    else
+        size = 0;
+
+    size += text_size(elem->first_cdata.first);
+
+    for (elem = elem->first_child; elem; elem = elem->next) {
+        /* the size of the child element plus the CDATA that follows it */
+        size += (elem_size(elem, style == APR_XML_X2T_PARSED ? APR_XML_X2T_PARSED : APR_XML_X2T_FULL, NULL, ns_map) +
+                 text_size(elem->following_cdata.first));
+    }
+
+    return size;
+}
+
+static char *write_text(char *s, const apr_text *t)
+{
+    for (; t; t = t->next) {
+        apr_size_t len = strlen(t->text);
+        memcpy(s, t->text, len);
+        s += len;
+    }
+    return s;
+}
+
+static char *write_elem(char *s, const apr_xml_elem *elem, int style,
+                        apr_array_header_t *namespaces, int *ns_map)
+{
+    const apr_xml_elem *child;
+    apr_size_t len;
+    int ns;
+
+    if (style == APR_XML_X2T_FULL || style == APR_XML_X2T_FULL_NS_LANG ||
+        style == APR_XML_X2T_PARSED) {
+        int empty = APR_XML_ELEM_IS_EMPTY(elem);
+        const apr_xml_attr *attr;
+
+        if (elem->ns == APR_XML_NS_NONE) {
+            len = sprintf(s, "<%s", elem->name);
+        }
+        else if (style == APR_XML_X2T_PARSED) {
+            len = sprintf(s, "<%s:%s", find_prefix_name(elem, elem->ns, 1), elem->name);
+        }
+        else {
+            ns = ns_map ? ns_map[elem->ns] : elem->ns;
+            len = sprintf(s, "<ns%d:%s", ns, elem->name);
+        }
+        s += len;
+
+        for (attr = elem->attr; attr; attr = attr->next) {
+            if (attr->ns == APR_XML_NS_NONE) {
+                len = sprintf(s, " %s=\"%s\"", attr->name, attr->value);
+            }
+            else if (style == APR_XML_X2T_PARSED) {
+                len = sprintf(s, " %s:%s=\"%s\"",
+                              find_prefix_name(elem, attr->ns, 1), attr->name, attr->value);
+            }
+            else {
+                ns = ns_map ? ns_map[attr->ns] : attr->ns;
+                len = sprintf(s, " ns%d:%s=\"%s\"", ns, attr->name, attr->value);
+            }
+            s += len;
+        }
+
+        /* add the xml:lang value if necessary */
+        if (elem->lang != NULL &&
+            (style == APR_XML_X2T_FULL_NS_LANG ||
+             elem->parent == NULL ||
+             elem->lang != elem->parent->lang)) {
+            len = sprintf(s, " xml:lang=\"%s\"", elem->lang);
+            s += len;
+        }
+
+        /* add namespace definitions, if required */
+        if (style == APR_XML_X2T_FULL_NS_LANG) {
+            int i;
+
+            for (i = namespaces->nelts; i--;) {
+                len = sprintf(s, " xmlns:ns%d=\"%s\"", i,
+                              APR_XML_GET_URI_ITEM(namespaces, i));
+                s += len;
+            }
+        }
+
+        else if (style == APR_XML_X2T_PARSED) {
+            apr_xml_ns_scope *ns_scope = elem->ns_scope;
+
+            for (; ns_scope; ns_scope = ns_scope->next) {
+                const char *prefix = find_prefix_name(elem, ns_scope->ns, 0);
+
+                len = sprintf(s, " xmlns%s%s=\"%s\"",
+                              *prefix ? ":" : "", *prefix ? prefix : "",
+                              APR_XML_GET_URI_ITEM(namespaces, ns_scope->ns));
+                s += len;
+            }
+        }
+
+        /* no more to do. close it up and go. */
+        if (empty) {
+            *s++ = '/';
+            *s++ = '>';
+            return s;
+        }
+
+        /* just close it */
+        *s++ = '>';
+    }
+    else if (style == APR_XML_X2T_LANG_INNER) {
+        /* prepend the xml:lang value */
+        if (elem->lang != NULL) {
+            len = strlen(elem->lang);
+            memcpy(s, elem->lang, len);
+            s += len;
+        }
+        *s++ = '\0';
+    }
+
+    s = write_text(s, elem->first_cdata.first);
+
+    for (child = elem->first_child; child; child = child->next) {
+        s = write_elem(s, child,
+                       style == APR_XML_X2T_PARSED ? APR_XML_X2T_PARSED : APR_XML_X2T_FULL,
+                       NULL, ns_map);
+        s = write_text(s, child->following_cdata.first);
+    }
+
+    if (style == APR_XML_X2T_FULL || style == APR_XML_X2T_FULL_NS_LANG ||
+        style == APR_XML_X2T_PARSED) {
+        if (elem->ns == APR_XML_NS_NONE) {
+            len = sprintf(s, "</%s>", elem->name);
+        }
+        else if (style == APR_XML_X2T_PARSED) {
+            len = sprintf(s, "</%s:%s>", find_prefix_name(elem, elem->ns, 1), elem->name);
+        }
+        else {
+            ns = ns_map ? ns_map[elem->ns] : elem->ns;
+            len = sprintf(s, "</ns%d:%s>", ns, elem->name);
+        }
+        s += len;
+    }
+
+    return s;
+}
+
+APR_DECLARE(void) apr_xml_quote_elem(apr_pool_t *p, apr_xml_elem *elem)
+{
+    apr_text *scan_txt;
+    apr_xml_attr *scan_attr;
+    apr_xml_elem *scan_elem;
+
+    /* convert the element's text */
+    for (scan_txt = elem->first_cdata.first;
+         scan_txt != NULL;
+         scan_txt = scan_txt->next) {
+        scan_txt->text = apr_xml_quote_string(p, scan_txt->text, 0);
+    }
+    for (scan_txt = elem->following_cdata.first;
+         scan_txt != NULL;
+         scan_txt = scan_txt->next) {
+        scan_txt->text = apr_xml_quote_string(p, scan_txt->text, 0);
+    }
+
+    /* convert the attribute values */
+    for (scan_attr = elem->attr;
+         scan_attr != NULL;
+         scan_attr = scan_attr->next) {
+        scan_attr->value = apr_xml_quote_string(p, scan_attr->value, 1);
+    }
+
+    /* convert the child elements */
+    for (scan_elem = elem->first_child;
+         scan_elem != NULL;
+         scan_elem = scan_elem->next) {
+        apr_xml_quote_elem(p, scan_elem);
+    }
+}
+
+/* convert an element to a text string */
+APR_DECLARE(void) apr_xml_to_text(apr_pool_t * p, const apr_xml_elem *elem,
+                                  int style, apr_array_header_t *namespaces,
+                                  int *ns_map, const char **pbuf,
+                                  apr_size_t *psize)
+{
+    /* get the exact size, plus a null terminator */
+    apr_size_t size = elem_size(elem, style, namespaces, ns_map) + 1;
+    char *s = apr_palloc(p, size);
+
+    (void) write_elem(s, elem, style, namespaces, ns_map);
+    s[size - 1] = '\0';
+
+    *pbuf = s;
+    if (psize)
+        *psize = size;
+}
+
+APR_DECLARE(const char *) apr_xml_empty_elem(apr_pool_t * p,
+                                             const apr_xml_elem *elem)
+{
+    if (elem->ns == APR_XML_NS_NONE) {
+        /*
+         * The prefix (xml...) is already within the prop name, or
+         * the element simply has no prefix.
+         */
+        return apr_psprintf(p, "<%s/>" DEBUG_CR, elem->name);
+    }
+
+    return apr_psprintf(p, "<ns%d:%s/>" DEBUG_CR, elem->ns, elem->name);
+}
+
+/* return the URI's (existing) index, or insert it and return a new index */
+APR_DECLARE(int) apr_xml_insert_uri(apr_array_header_t *uri_array,
+                                    const char *uri)
+{
+    int i;
+    const char **pelt;
+
+    /* never insert an empty URI; this index is always APR_XML_NS_NONE */
+    if (*uri == '\0')
+        return APR_XML_NS_NONE;
+
+    for (i = uri_array->nelts; i--;) {
+        if (strcmp(uri, APR_XML_GET_URI_ITEM(uri_array, i)) == 0)
+            return i;
+    }
+
+    pelt = apr_array_push(uri_array);
+    *pelt = uri;                /* assume uri is const or in a pool */
+    return uri_array->nelts - 1;
+}
+
+/* convert the element to EBCDIC */
+#if APR_CHARSET_EBCDIC
+static apr_status_t apr_xml_parser_convert_elem(apr_xml_elem *e,
+                                                apr_xlate_t *convset)
+{
+    apr_xml_attr *a;
+    apr_xml_elem *ec;
+    apr_text *t;
+    apr_size_t inbytes_left, outbytes_left;
+    apr_status_t status;
+
+    inbytes_left = outbytes_left = strlen(e->name);
+    status = apr_xlate_conv_buffer(convset, e->name,  &inbytes_left, (char *) e->name, &outbytes_left);
+    if (status) {
+        return status;
+    }
+
+    for (t = e->first_cdata.first; t != NULL; t = t->next) {
+        inbytes_left = outbytes_left = strlen(t->text);
+        status = apr_xlate_conv_buffer(convset, t->text, &inbytes_left, (char *) t->text, &outbytes_left);
+        if (status) {
+            return status;
+        }
+    }
+
+    for (t = e->following_cdata.first;  t != NULL; t = t->next) {
+        inbytes_left = outbytes_left = strlen(t->text);
+        status = apr_xlate_conv_buffer(convset, t->text, &inbytes_left, (char *) t->text, &outbytes_left);
+        if (status) {
+            return status;
+        }
+    }
+
+    for (a = e->attr; a != NULL; a = a->next) {
+        inbytes_left = outbytes_left = strlen(a->name);
+        status = apr_xlate_conv_buffer(convset, a->name, &inbytes_left, (char *) a->name, &outbytes_left);
+        if (status) {
+            return status;
+        }
+        inbytes_left = outbytes_left = strlen(a->value);
+        status = apr_xlate_conv_buffer(convset, a->value, &inbytes_left, (char *) a->value, &outbytes_left);
+        if (status) {
+            return status;
+        }
+    }
+
+    for (ec = e->first_child; ec != NULL; ec = ec->next) {
+        status = apr_xml_parser_convert_elem(ec, convset);
+        if (status) {
+            return status;
+        }
+    }
+    return APR_SUCCESS;
+}
+
+/* convert the whole document to EBCDIC */
+APR_DECLARE(apr_status_t) apr_xml_parser_convert_doc(apr_pool_t *pool,
+                                                     apr_xml_doc *pdoc,
+                                                     apr_xlate_t *convset)
+{
+    apr_status_t status;
+    /* Don't convert the namespaces: they are constant! */
+    if (pdoc->namespaces != NULL) {
+        int i;
+        apr_array_header_t *namespaces;
+        namespaces = apr_array_make(pool, pdoc->namespaces->nelts, sizeof(const char *));
+        if (namespaces == NULL)
+            return APR_ENOMEM;
+        for (i = 0; i < pdoc->namespaces->nelts; i++) {
+            apr_size_t inbytes_left, outbytes_left;
+            char *ptr = (char *) APR_XML_GET_URI_ITEM(pdoc->namespaces, i);
+            ptr = apr_pstrdup(pool, ptr);
+            if ( ptr == NULL)
+                return APR_ENOMEM;
+            inbytes_left = outbytes_left = strlen(ptr);
+            status = apr_xlate_conv_buffer(convset, ptr, &inbytes_left, ptr, &outbytes_left);
+            if (status) {
+                return status;
+            }
+            apr_xml_insert_uri(namespaces, ptr);
+        }
+        pdoc->namespaces = namespaces;
+    }
+    return apr_xml_parser_convert_elem(pdoc->root, convset);
+}
+#endif
diff --git a/xml/apr_xml_expat.c b/xml/apr_xml_expat.c
new file mode 100644
index 00000000000..1df279988cf
--- /dev/null
+++ b/xml/apr_xml_expat.c
@@ -0,0 +1,137 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+
+#if APU_USE_EXPAT
+#include "apr_xml.h"
+
+#if defined(HAVE_XMLPARSE_XMLPARSE_H)
+#include <xmlparse/xmlparse.h>
+#elif defined(HAVE_XMLTOK_XMLPARSE_H)
+#include <xmltok/xmlparse.h>
+#elif defined(HAVE_XML_XMLPARSE_H)
+#include <xml/xmlparse.h>
+#else
+#include <expat.h>
+#endif
+
+typedef enum XML_Error XML_Error;
+
+#include "apr_xml_internal.h"
+
+static apr_status_t cleanup_parser(void *ctx)
+{
+    apr_xml_parser *parser = ctx;
+
+    XML_ParserFree(parser->xp);
+    parser->xp = NULL;
+
+    return APR_SUCCESS;
+}
+static apr_status_t do_parse(apr_xml_parser *parser,
+                             const char *data, apr_size_t len,
+                             int is_final)
+{
+    if (parser->xp == NULL) {
+        parser->error = APR_XML_ERROR_PARSE_DONE;
+    }
+    else {
+        int rv = XML_Parse(parser->xp, data, (int)len, is_final);
+
+        if (rv == 0) {
+            parser->error = APR_XML_ERROR_EXPAT;
+            parser->xp_err = XML_GetErrorCode(parser->xp);
+            parser->xp_msg = XML_ErrorString(parser->xp_err);
+        }
+    }
+
+    /* ### better error code? */
+    return parser->error ? APR_EGENERAL : APR_SUCCESS;
+}
+
+
+static XMLParserImpl xml_parser_expat = {
+    do_parse,
+    cleanup_parser
+};
+
+XMLParserImpl* apr_xml_get_parser_impl(void) { return &xml_parser_expat; }
+static const char APR_KW_DAV[] = { 0x44, 0x41, 0x56, 0x3A, '\0' };
+
+#if XML_MAJOR_VERSION > 1
+/* Stop the parser if an entity declaration is hit. */
+static void entity_declaration(void *userData, const XML_Char *entityName,
+                               int is_parameter_entity, const XML_Char *value,
+                               int value_length, const XML_Char *base,
+                               const XML_Char *systemId, const XML_Char *publicId,
+                               const XML_Char *notationName)
+{
+    apr_xml_parser *parser = userData;
+
+    XML_StopParser(parser->xp, XML_FALSE);
+}
+#else
+/* A noop default_handler. */
+static void default_handler(void *userData, const XML_Char *s, int len)
+{
+}
+#endif
+
+apr_xml_parser* apr_xml_parser_create_internal(apr_pool_t *pool,
+    void *start_func, void *end_func, void *cdata_func)
+{
+    apr_xml_parser *parser = apr_pcalloc(pool, sizeof(*parser));
+
+    parser->impl = apr_xml_get_parser_impl();
+
+    parser->p = pool;
+    parser->doc = apr_pcalloc(pool, sizeof(*parser->doc));
+
+    parser->doc->namespaces = apr_array_make(pool, 5, sizeof(const char *));
+
+    /* ### is there a way to avoid hard-coding this? */
+    apr_xml_insert_uri(parser->doc->namespaces, APR_KW_DAV);
+
+    parser->xp = XML_ParserCreate(NULL);
+    if (parser->xp == NULL) {
+        (*apr_pool_abort_get(pool))(APR_ENOMEM);
+        return NULL;
+    }
+
+    apr_pool_cleanup_register(pool, parser, cleanup_parser,
+                              apr_pool_cleanup_null);
+
+    XML_SetUserData(parser->xp, parser);
+    XML_SetElementHandler(parser->xp, start_func, end_func);
+    XML_SetCharacterDataHandler(parser->xp, cdata_func);
+
+    /* Prevent the "billion laughs" attack against expat by disabling
+     * internal entity expansion.  With 2.x, forcibly stop the parser
+     * if an entity is declared - this is safer and a more obvious
+     * failure mode.  With older versions, installing a noop
+     * DefaultHandler means that internal entities will be expanded as
+     * the empty string, which is also sufficient to prevent the
+     * attack. */
+#if XML_MAJOR_VERSION > 1
+    XML_SetEntityDeclHandler(parser->xp, entity_declaration);
+#else
+    XML_SetDefaultHandler(parser->xp, default_handler);
+#endif
+
+    return parser;
+}
+#endif
diff --git a/xml/apr_xml_internal.h b/xml/apr_xml_internal.h
new file mode 100644
index 00000000000..dfd191e3276
--- /dev/null
+++ b/xml/apr_xml_internal.h
@@ -0,0 +1,48 @@
+/* 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 APR_XML_INTERNAL_H
+#define APR_XML_INTERNAL_H
+
+
+struct XMLParserImpl {
+    apr_status_t (*Parse)(apr_xml_parser*, const char*, apr_size_t, int);
+    apr_status_t (*cleanup)(void*);
+};
+typedef struct XMLParserImpl XMLParserImpl;
+XMLParserImpl* apr_xml_get_parser_impl(void);
+
+
+/* the real (internal) definition of the parser context */
+struct apr_xml_parser {
+    apr_xml_doc *doc;           /* the doc we're parsing */
+    apr_pool_t *p;              /* the pool we allocate from */
+    apr_xml_elem *cur_elem;     /* current element */
+
+    int error;                  /* an error has occurred */
+#define APR_XML_ERROR_EXPAT             1
+#define APR_XML_ERROR_PARSE_DONE        2
+/* also: public APR_XML_NS_ERROR_* values (if any) */
+
+    XML_Parser xp;              /* the actual (Expat) XML parser */
+    XML_Error xp_err;      /* stored Expat error code */
+    const char *xp_msg;
+    XMLParserImpl *impl;
+};
+
+apr_xml_parser* apr_xml_parser_create_internal(apr_pool_t*, void*, void*, void*);
+
+#endif
diff --git a/xml/apr_xml_libxml2.c b/xml/apr_xml_libxml2.c
new file mode 100644
index 00000000000..ad72441f9a8
--- /dev/null
+++ b/xml/apr_xml_libxml2.c
@@ -0,0 +1,99 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+
+#if APU_USE_LIBXML2
+#include "apr_xml.h"
+
+#include <libxml/parser.h>
+#include <libxml/xmlerror.h>
+
+typedef xmlParserCtxtPtr XML_Parser;
+typedef xmlParserErrors XML_Error;
+
+#include "apr_xml_internal.h"
+
+static apr_status_t cleanup_parser(void *ctx)
+{
+    apr_xml_parser *parser = ctx;
+
+    xmlFreeParserCtxt(parser->xp);
+    parser->xp = NULL;
+
+    return APR_SUCCESS;
+}
+static int libxml2_parse(apr_xml_parser* parser, const char* data,
+                         apr_size_t sz, int final)
+{
+    parser->xp_err = xmlParseChunk(parser->xp, data, sz, final);
+    if (parser->xp_err != 0) {
+        xmlErrorPtr errptr = xmlCtxtGetLastError(parser->xp);
+        parser->xp_msg = errptr->message;
+        /* this misnomer is used as a test for (any) parser error. */
+        parser->error = APR_XML_ERROR_EXPAT;
+    }
+    return parser->xp_err;
+}
+static XMLParserImpl xml_parser_libxml2 = {
+    libxml2_parse,
+    cleanup_parser
+};
+
+static const char APR_KW_DAV[] = { 0x44, 0x41, 0x56, 0x3A, '\0' };
+
+XMLParserImpl* apr_xml_get_parser_impl(void)
+{
+    return &xml_parser_libxml2;
+}
+
+
+apr_xml_parser* apr_xml_parser_create_internal(apr_pool_t *pool,
+    void *start_func, void *end_func, void *cdata_func)
+{
+    apr_xml_parser *parser = apr_pcalloc(pool, sizeof(*parser));
+    /* FIXME: This is a mismatch.  We should create a single global
+     * sax instance and re-use it for every parser.  That means we
+     * need an up-front initialisation function.
+     */
+    xmlSAXHandlerPtr sax = apr_pcalloc(pool, sizeof(xmlSAXHandler));
+    sax->startElement = start_func;
+    sax->endElement = end_func;
+    sax->characters = cdata_func;
+    sax->initialized = 1;
+
+    parser->impl = apr_xml_get_parser_impl();
+
+    parser->p = pool;
+    parser->doc = apr_pcalloc(pool, sizeof(*parser->doc));
+
+    parser->doc->namespaces = apr_array_make(pool, 5, sizeof(const char *));
+
+    /* ### is there a way to avoid hard-coding this? */
+    apr_xml_insert_uri(parser->doc->namespaces, APR_KW_DAV);
+
+    parser->xp = xmlCreatePushParserCtxt(sax, parser, NULL, 0, NULL);
+    if (parser->xp == NULL) {
+        (*apr_pool_abort_get(pool))(APR_ENOMEM);
+        return NULL;
+    }
+
+    apr_pool_cleanup_register(pool, parser, cleanup_parser,
+                              apr_pool_cleanup_null);
+
+    return parser;
+}
+#endif