diff options
author | clement <clement@FreeBSD.org> | 2004-12-13 18:48:03 +0000 |
---|---|---|
committer | clement <clement@FreeBSD.org> | 2004-12-13 18:48:03 +0000 |
commit | f26e8c8b43d2a848944fa0196da97f060394b991 (patch) | |
tree | 23050945d9a4ed264fdeabd5af342b984a9120d3 /www/apache22 | |
parent | 56cc4ebbb98f9c23847b71cb8cee7f254775db2d (diff) | |
download | FreeBSD-ports-f26e8c8b43d2a848944fa0196da97f060394b991.zip FreeBSD-ports-f26e8c8b43d2a848944fa0196da97f060394b991.tar.gz |
- Move standard configuration files to ${EXAMPLESDIR} to not get
dist config files installed in ${PREFIX}/etc/apache21
- Add support for Event MPM and add backport from apr to support
APR_POLLSET_THREADSAFE (needed by Event MPM and forgotten @ release
time) [1]
- misc cleanups
- Bump PORTREVISION to reflect all cool changes which occured today ;)
Obtained from: apr svn repository
Diffstat (limited to 'www/apache22')
-rw-r--r-- | www/apache22/Makefile | 23 | ||||
-rw-r--r-- | www/apache22/Makefile.doc | 2 | ||||
-rw-r--r-- | www/apache22/Makefile.modules | 13 | ||||
-rw-r--r-- | www/apache22/files/exp-event-mpm-apr-backport.patch | 3046 | ||||
-rw-r--r-- | www/apache22/files/patch-Makefile.in | 41 | ||||
-rw-r--r-- | www/apache22/pkg-plist | 31 |
6 files changed, 3116 insertions, 40 deletions
diff --git a/www/apache22/Makefile b/www/apache22/Makefile index ce85f7d..66f411b 100644 --- a/www/apache22/Makefile +++ b/www/apache22/Makefile @@ -9,6 +9,7 @@ PORTNAME= apache PORTVERSION= 2.1.2 +PORTREVISION= 1 CATEGORIES= www MASTER_SITES= ${MASTER_SITE_LOCAL:S/%SUBDIR%/clement/} DISTNAME= httpd-${PORTVERSION}-alpha @@ -32,14 +33,6 @@ CONFLICTS= apache+mod_ssl-1.* apache+mod_ssl+ipv6-1.* apache+mod_ssl+modsnmp-1.* ru-apache+mod_ssl-1.* ru-apache-1.* thttpd-2.* \ apache-2.0.* apache-*-2.0.* -# patch files -.if defined (WITH_WINDOWSUPDATEFIX) -EXTRA_PATCHES+= ${FILESDIR}/exp-windowsupdate.patch -.endif -.if defined(WITH_EXPERIMENTAL_PATCHES) -EXTRA_PATCHES+= ${FILESDIR}/exp-apr-kqueue.patch -.endif - SCRIPTS_ENV+= LIBTOOL=${LIBTOOL} LIBTOOLIZE=${LIBTOOLIZE} \ LIBTOOL_VERSION=${LIBTOOL_VERSION} AUTOCONF=${AUTOCONF} \ LIBTOOL_M4=${LOCALBASE}/share/aclocal/libtool${LIBTOOL_VERSION}.m4 \ @@ -51,8 +44,9 @@ USE_PERL5= yes USE_RC_SUBR= yes USE_REINPLACE= yes LIBTOOLFILES= configure +.if !defined(WITH_APR_FROM_PORTS) INSTALLS_SHLIB= yes - +.endif CONFIGURE_ARGS= --prefix=${PREFIX_RELDEST} \ --enable-layout=FreeBSD \ --with-perl=${PERL5} \ @@ -71,10 +65,14 @@ RC_SCRIPTS_SUB= PREFIX=${PREFIX} RC_SUBR=${RC_SUBR} MAKE_ENV+= DESTDIR=${DESTDIR} EXPR_COMPAT=yes -WITH_MPM?= prefork # or worker, perchild, threadpool +WITH_MPM?= prefork # or worker, perchild, threadpool, event WITH_HTTP_PORT?= 80 +.if defined (WITH_WINDOWSUPDATEFIX) +EXTRA_PATCHES+= ${FILESDIR}/exp-windowsupdate.patch +.endif + .if defined(WITHOUT_IPV6) CONFIGURE_ARGS+= --disable-ipv6 .else @@ -94,10 +92,6 @@ USE_OPENSSL= yes CONFIGURE_ARGS+= --enable-static-support .endif -.if defined(WITH_SSL_EXPERIMENTAL_ENGINE) -CFLAGS+= -DSSL_EXPERIMENTAL_ENGINE -.endif - # debug overrides CFLAGS .if defined(WITH_DEBUG) DEBUG_FLAGS?= -O0 -g -ggdb3 @@ -196,6 +190,7 @@ post-patch: @${SED} ${RC_SCRIPTS_SUB:S/$/!g/:S/^/ -e s!%%/:S/=/%%!/} \ ${FILESDIR}/apache.sh > ${WRKDIR}/apache21.sh @${RM} -f ${WRKSRC}/docs/manual/index.html.ko.euc-kr + @${RM} -f ${WRKSRC}/docs/conf/highperformance-std.conf @${REINPLACE_CMD} -e 's," PLATFORM ",FreeBSD,' \ ${WRKSRC}/server/core.c @${REINPLACE_CMD} -e 's,freebsd\[2345\],freebsd\[23456\],' \ diff --git a/www/apache22/Makefile.doc b/www/apache22/Makefile.doc index 0382303..1a57625 100644 --- a/www/apache22/Makefile.doc +++ b/www/apache22/Makefile.doc @@ -90,6 +90,8 @@ ## DOCSDIR= ${PREFIX}/share/doc/apache21 +EXAMPLESDIR= ${PREFIX}/share/examples/apache21 +MAKE_ENV+= EXAMPLESDIR=${EXAMPLESDIR} .if defined(NOPORTDOCS) MAKE_ENV+= NOPORTDOCS=yes diff --git a/www/apache22/Makefile.modules b/www/apache22/Makefile.modules index 7166332..1f2404e 100644 --- a/www/apache22/Makefile.modules +++ b/www/apache22/Makefile.modules @@ -24,19 +24,22 @@ WITH_THREADS= yes WITH_THREADS_MODULES= yes WITHOUT_MODULES+= cgi . if ${WITH_MPM:L} == "worker" -PLIST_SUB+= PREFORK="@comment " WORKER="" THREADPOOL="@comment " +PLIST_SUB+= PREFORK="@comment " WORKER="" THREADPOOL="@comment " EVENT="@comment " . elif ${WITH_MPM:L} == "perchild" -PLIST_SUB+= PREFORK="@comment " WORKER="@comment " THREADPOOL="@comment " +PLIST_SUB+= PREFORK="@comment " WORKER="@comment " THREADPOOL="@comment " EVENT="@comment " . elif ${WITH_MPM:L} == "threadpool" -PLIST_SUB+= PREFORK="@comment " WORKER="@comment " THREADPOOL="" +PLIST_SUB+= PREFORK="@comment " WORKER="@comment " THREADPOOL="" EVENT="@comment " +. elif ${WITH_MPM:L} == "event" +PLIST_SUB+= PREFORK="@comment " WORKER="@comment " THREADPOOL="@comment " EVENT="" +EXTRA_PATCHES+= ${FILESDIR}/exp-event-mpm-apr-backport.patch . else IGNORE= "Unknown MPM: ${WITH_MPM}" . endif . else -PLIST_SUB+= PREFORK="@comment " WORKER="@comment " THREADPOOL="@comment " +PLIST_SUB+= PREFORK="@comment " WORKER="@comment " THREADPOOL="@comment " EVENT="@comment " . endif .else -PLIST_SUB+= PREFORK="@comment " WORKER="@comment " THREADPOOL="@comment " +PLIST_SUB+= PREFORK="@comment " WORKER="@comment " THREADPOOL="@comment " EVENT="@comment " .endif # xDBM section diff --git a/www/apache22/files/exp-event-mpm-apr-backport.patch b/www/apache22/files/exp-event-mpm-apr-backport.patch new file mode 100644 index 0000000..9bd67fe --- /dev/null +++ b/www/apache22/files/exp-event-mpm-apr-backport.patch @@ -0,0 +1,3046 @@ +diff -Nur srclib/apr.orig/include/apr_poll.h srclib/apr/include/apr_poll.h +--- srclib/apr.orig/include/apr_poll.h Mon Dec 13 18:57:05 2004 ++++ srclib/apr/include/apr_poll.h Mon Dec 13 18:57:28 2004 +@@ -50,6 +50,11 @@ + #define APR_POLLHUP 0x020 /**< Hangup occurred */ + #define APR_POLLNVAL 0x040 /**< Descriptior invalid */ + ++/** ++ * Pollset Flags ++ */ ++#define APR_POLLSET_THREADSAFE 0x001 /**< Adding or Removing a Descriptor is thread safe */ ++ + /** Used in apr_pollfd_t to determine what the apr_descriptor is */ + typedef enum { + APR_NO_DESC, /**< nothing here */ +diff -Nur srclib/apr.orig/include/apr_poll.h.orig srclib/apr/include/apr_poll.h.orig +--- srclib/apr.orig/include/apr_poll.h.orig Thu Jan 1 01:00:00 1970 ++++ srclib/apr/include/apr_poll.h.orig Fri Feb 13 10:38:38 2004 +@@ -0,0 +1,164 @@ ++/* Copyright 2000-2004 The Apache Software Foundation ++ * ++ * 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. ++ */ ++ ++#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 ++ * @{ ++ */ ++ ++/** ++ * Poll options ++ */ ++#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 /**< Descriptior invalid */ ++ ++/** 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 /**< 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; ++ ++/** ++ * Setup 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 ++ * (reserved for future expansion) ++ */ ++APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset, ++ apr_uint32_t size, ++ apr_pool_t *p, ++ apr_uint32_t flags); ++ ++/** ++ * 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(). ++ */ ++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 ++ */ ++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 Timeout in microseconds ++ * @param num Number of signalled descriptors (output parameter) ++ * @param descriptors Array of signalled descriptors (output parameter) ++ */ ++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); ++ ++ ++/** ++ * Poll the sockets in the poll structure ++ * @param aprset The poll structure we will be using. ++ * @param numsock The number of sockets we are polling ++ * @param nsds The number of sockets signalled. ++ * @param timeout 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. ++ * @remark The number of sockets signalled is returned in the third argument. ++ * This is a blocking call, and it will not return until either a ++ * socket has been signalled, or the timeout has expired. ++ */ ++APR_DECLARE(apr_status_t) apr_poll(apr_pollfd_t *aprset, apr_int32_t numsock, ++ apr_int32_t *nsds, ++ apr_interval_time_t timeout); ++ ++/** @} */ ++ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* ! APR_POLL_H */ ++ +diff -Nur srclib/apr.orig/include/arch/unix/apr_arch_poll_private.h srclib/apr/include/arch/unix/apr_arch_poll_private.h +--- srclib/apr.orig/include/arch/unix/apr_arch_poll_private.h Thu Jan 1 01:00:00 1970 ++++ srclib/apr/include/arch/unix/apr_arch_poll_private.h Mon Dec 13 18:58:32 2004 +@@ -0,0 +1,92 @@ ++/* Copyright 2000-2004 The Apache Software Foundation ++ * ++ * 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. ++ */ ++ ++#ifndef APR_ARCH_POLL_PRIVATE_H ++#define APR_ARCH_POLL_PRIVATE_H ++ ++#include "apr.h" ++#include "apr_poll.h" ++#include "apr_time.h" ++#include "apr_portable.h" ++#include "apr_arch_networkio.h" ++#include "apr_arch_file_io.h" ++ ++#if HAVE_POLL_H ++#include <poll.h> ++#endif ++ ++#if HAVE_SYS_POLL_H ++#include <sys/poll.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 ++ ++/* Choose the best method platform specific to use in apr_pollset */ ++#ifdef HAVE_KQUEUE ++#define POLLSET_USES_KQUEUE ++#elif defined(HAVE_EPOLL) ++#define POLLSET_USES_EPOLL ++#elif defined(HAVE_POLL) ++#define POLLSET_USES_POLL ++#else ++#define POLLSET_USES_SELECT ++#endif ++ ++#ifdef HAVE_POLL ++#define POLL_USES_POLL ++#else ++#define POLL_USES_SELECT ++#endif ++ ++#if defined(POLLSET_USES_KQUEUE) || defined(POLLSET_USES_EPOLL) ++ ++#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->ring_lock); ++#define pollset_unlock_rings() \ ++ if(pollset->flags & APR_POLLSET_THREADSAFE) \ ++ apr_thread_mutex_unlock(pollset->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; ++}; ++ ++#endif ++ ++#endif /* APR_ARCH_POLL_PRIVATE_H */ +diff -Nur srclib/apr.orig/poll/unix/epoll.c srclib/apr/poll/unix/epoll.c +--- srclib/apr.orig/poll/unix/epoll.c Thu Jan 1 01:00:00 1970 ++++ srclib/apr/poll/unix/epoll.c Mon Dec 13 18:57:28 2004 +@@ -0,0 +1,270 @@ ++/* Copyright 2000-2004 The Apache Software Foundation ++ * ++ * 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. ++ */ ++ ++#include "apr_arch_poll_private.h" ++ ++#ifdef POLLSET_USES_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; ++ if (event & APR_POLLERR) ++ rv |= EPOLLERR; ++ if (event & APR_POLLHUP) ++ rv |= EPOLLHUP; ++ /* APR_POLLNVAL is not handled by epoll. */ ++ ++ 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_t ++{ ++ apr_pool_t *pool; ++ apr_uint32_t nelts; ++ apr_uint32_t nalloc; ++ int epoll_fd; ++ struct epoll_event *pollset; ++ apr_pollfd_t *result_set; ++ apr_uint32_t flags; ++#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 backend_cleanup(void *p_) ++{ ++ apr_pollset_t *pollset = (apr_pollset_t *) p_; ++ close(pollset->epoll_fd); ++ return APR_SUCCESS; ++} ++ ++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 rv; ++ ++ *pollset = apr_palloc(p, sizeof(**pollset)); ++#if APR_HAS_THREADS ++ if (flags & APR_POLLSET_THREADSAFE && ++ ((rv = apr_thread_mutex_create(&(*pollset)->ring_lock, ++ APR_THREAD_MUTEX_DEFAULT, ++ p) != APR_SUCCESS))) { ++ *pollset = NULL; ++ return rv; ++ } ++#else ++ if (flags & APR_POLLSET_THREADSAFE) { ++ *pollset = NULL; ++ return APR_ENOTIMPL; ++ } ++#endif ++ (*pollset)->nelts = 0; ++ (*pollset)->nalloc = size; ++ (*pollset)->flags = flags; ++ (*pollset)->pool = p; ++ (*pollset)->epoll_fd = epoll_create(size); ++ (*pollset)->pollset = apr_palloc(p, size * sizeof(struct epoll_event)); ++ apr_pool_cleanup_register(p, (void *) (*pollset), backend_cleanup, ++ apr_pool_cleanup_null); ++ (*pollset)->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t)); ++ ++ APR_RING_INIT(&(*pollset)->query_ring, pfd_elem_t, link); ++ APR_RING_INIT(&(*pollset)->free_ring, pfd_elem_t, link); ++ APR_RING_INIT(&(*pollset)->dead_ring, pfd_elem_t, link); ++ ++ return APR_SUCCESS; ++} ++ ++APR_DECLARE(apr_status_t) apr_pollset_destroy(apr_pollset_t *pollset) ++{ ++ return apr_pool_cleanup_run(pollset->pool, pollset, backend_cleanup); ++} ++ ++APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset, ++ const apr_pollfd_t *descriptor) ++{ ++ struct epoll_event ev; ++ int ret = -1; ++ pfd_elem_t *elem; ++ apr_status_t rv = APR_SUCCESS; ++ ++ pollset_lock_rings(); ++ ++ if (!APR_RING_EMPTY(&(pollset->free_ring), pfd_elem_t, link)) { ++ elem = APR_RING_FIRST(&(pollset->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.events = get_epoll_event(descriptor->reqevents); ++ ev.data.ptr = elem; ++ if (descriptor->desc_type == APR_POLL_SOCKET) { ++ ret = epoll_ctl(pollset->epoll_fd, EPOLL_CTL_ADD, ++ descriptor->desc.s->socketdes, &ev); ++ } ++ else { ++ ret = epoll_ctl(pollset->epoll_fd, EPOLL_CTL_ADD, ++ descriptor->desc.f->filedes, &ev); ++ } ++ ++ if (0 != ret) { ++ rv = APR_EBADF; ++ APR_RING_INSERT_TAIL(&(pollset->free_ring), elem, pfd_elem_t, link); ++ } ++ else { ++ pollset->nelts++; ++ APR_RING_INSERT_TAIL(&(pollset->query_ring), elem, pfd_elem_t, link); ++ } ++ ++ pollset_unlock_rings(); ++ ++ return rv; ++} ++ ++APR_DECLARE(apr_status_t) apr_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; ++ int ret = -1; ++ ++ pollset_lock_rings(); ++ ++ ev.events = get_epoll_event(descriptor->reqevents); ++ ++ if (descriptor->desc_type == APR_POLL_SOCKET) { ++ ret = epoll_ctl(pollset->epoll_fd, EPOLL_CTL_DEL, ++ descriptor->desc.s->socketdes, &ev); ++ } ++ else { ++ ret = epoll_ctl(pollset->epoll_fd, EPOLL_CTL_DEL, ++ descriptor->desc.f->filedes, &ev); ++ } ++ if (ret < 0) { ++ rv = APR_NOTFOUND; ++ } ++ ++ if (!APR_RING_EMPTY(&(pollset->query_ring), pfd_elem_t, link)) { ++ for (ep = APR_RING_FIRST(&(pollset->query_ring)); ++ ep != APR_RING_SENTINEL(&(pollset->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->dead_ring), ++ ep, pfd_elem_t, link); ++ break; ++ } ++ } ++ } ++ ++ pollset_unlock_rings(); ++ ++ return rv; ++} ++ ++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 ret, i; ++ apr_status_t rv = APR_SUCCESS; ++ pfd_elem_t *ep; ++ ++ if (timeout > 0) { ++ timeout /= 1000; ++ } ++ ++ ret = epoll_wait(pollset->epoll_fd, pollset->pollset, pollset->nalloc, ++ timeout); ++ (*num) = ret; ++ ++ if (ret < 0) { ++ rv = apr_get_netos_error(); ++ } ++ else if (ret == 0) { ++ rv = APR_TIMEUP; ++ } ++ else { ++ for (i = 0; i < ret; i++) { ++ pollset->result_set[i] = ++ (((pfd_elem_t *) (pollset->pollset[i].data.ptr))->pfd); ++ pollset->result_set[i].rtnevents = ++ get_epoll_revent(pollset->pollset[i].events); ++ } ++ ++ if (descriptors) { ++ *descriptors = pollset->result_set; ++ } ++ } ++ ++ pollset_lock_rings(); ++ ++ /* Shift all PFDs in the Dead Ring to be Free Ring */ ++ while (!APR_RING_EMPTY(&(pollset->dead_ring), pfd_elem_t, link)) { ++ ep = APR_RING_FIRST(&(pollset->dead_ring)); ++ APR_RING_REMOVE(ep, link); ++ APR_RING_INSERT_TAIL(&(pollset->free_ring), ep, pfd_elem_t, link); ++ } ++ ++ pollset_unlock_rings(); ++ ++ return rv; ++} ++ ++#endif /* POLLSET_USES_EPOLL */ +diff -Nur srclib/apr.orig/poll/unix/kqueue.c srclib/apr/poll/unix/kqueue.c +--- srclib/apr.orig/poll/unix/kqueue.c Thu Jan 1 01:00:00 1970 ++++ srclib/apr/poll/unix/kqueue.c Mon Dec 13 18:57:28 2004 +@@ -0,0 +1,288 @@ ++/* Copyright 2000-2004 The Apache Software Foundation ++ * ++ * 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. ++ */ ++ ++#include "apr_arch_poll_private.h" ++ ++#ifdef POLLSET_USES_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; ++ if (event & EVFILT_WRITE) ++ rv |= APR_POLLOUT; ++ if (flags & EV_EOF) ++ rv |= APR_POLLHUP; ++ if (flags & EV_ERROR) ++ rv |= APR_POLLERR; ++ ++ return rv; ++} ++ ++struct apr_pollset_t ++{ ++ apr_pool_t *pool; ++ apr_uint32_t nelts; ++ apr_uint32_t nalloc; ++ int kqueue_fd; ++ struct kevent kevent; ++ struct kevent *ke_set; ++ apr_pollfd_t *result_set; ++ apr_uint32_t flags; ++#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 backend_cleanup(void *p_) ++{ ++ apr_pollset_t *pollset = (apr_pollset_t *) p_; ++ close(pollset->kqueue_fd); ++ return APR_SUCCESS; ++} ++ ++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 rv = APR_SUCCESS; ++ *pollset = apr_palloc(p, sizeof(**pollset)); ++#if APR_HAS_THREADS ++ if (flags & APR_POLLSET_THREADSAFE && ++ ((rv = apr_thread_mutex_create(&(*pollset)->ring_lock, ++ APR_THREAD_MUTEX_DEFAULT, ++ p) != APR_SUCCESS))) { ++ *pollset = NULL; ++ return rv; ++ } ++#else ++ if (flags & APR_POLLSET_THREADSAFE) { ++ *pollset = NULL; ++ return APR_ENOTIMPL; ++ } ++#endif ++ (*pollset)->nelts = 0; ++ (*pollset)->nalloc = size; ++ (*pollset)->flags = flags; ++ (*pollset)->pool = p; ++ ++ (*pollset)->ke_set = ++ (struct kevent *) apr_palloc(p, size * sizeof(struct kevent)); ++ ++ memset((*pollset)->ke_set, 0, size * sizeof(struct kevent)); ++ ++ (*pollset)->kqueue_fd = kqueue(); ++ ++ if ((*pollset)->kqueue_fd == -1) { ++ return APR_ENOMEM; ++ } ++ ++ apr_pool_cleanup_register(p, (void *) (*pollset), backend_cleanup, ++ apr_pool_cleanup_null); ++ ++ (*pollset)->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t)); ++ ++ APR_RING_INIT(&(*pollset)->query_ring, pfd_elem_t, link); ++ APR_RING_INIT(&(*pollset)->free_ring, pfd_elem_t, link); ++ APR_RING_INIT(&(*pollset)->dead_ring, pfd_elem_t, link); ++ ++ return rv; ++} ++ ++APR_DECLARE(apr_status_t) apr_pollset_destroy(apr_pollset_t * pollset) ++{ ++ return apr_pool_cleanup_run(pollset->pool, pollset, backend_cleanup); ++} ++ ++APR_DECLARE(apr_status_t) apr_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->free_ring), pfd_elem_t, link)) { ++ elem = APR_RING_FIRST(&(pollset->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->kevent, fd, EVFILT_READ, EV_ADD, 0, 0, elem); ++ ++ if (kevent(pollset->kqueue_fd, &pollset->kevent, 1, NULL, 0, ++ NULL) == -1) { ++ rv = APR_ENOMEM; ++ } ++ } ++ ++ if (descriptor->reqevents & APR_POLLOUT && rv == APR_SUCCESS) { ++ EV_SET(&pollset->kevent, fd, EVFILT_WRITE, EV_ADD, 0, 0, elem); ++ ++ if (kevent(pollset->kqueue_fd, &pollset->kevent, 1, NULL, 0, ++ NULL) == -1) { ++ rv = APR_ENOMEM; ++ } ++ } ++ ++ if (rv == APR_SUCCESS) { ++ pollset->nelts++; ++ APR_RING_INSERT_TAIL(&(pollset->query_ring), elem, pfd_elem_t, link); ++ } ++ else { ++ APR_RING_INSERT_TAIL(&(pollset->free_ring), elem, pfd_elem_t, link); ++ } ++ ++ pollset_unlock_rings(); ++ ++ return rv; ++} ++ ++APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset, ++ const apr_pollfd_t *descriptor) ++{ ++ pfd_elem_t *ep; ++ apr_status_t rv = APR_SUCCESS; ++ 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; ++ } ++ ++ if (descriptor->reqevents & APR_POLLIN) { ++ EV_SET(&pollset->kevent, fd, EVFILT_READ, EV_DELETE, 0, 0, NULL); ++ ++ if (kevent(pollset->kqueue_fd, &pollset->kevent, 1, NULL, 0, ++ NULL) == -1) { ++ rv = APR_NOTFOUND; ++ } ++ } ++ ++ if (descriptor->reqevents & APR_POLLOUT && rv == APR_SUCCESS) { ++ EV_SET(&pollset->kevent, fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL); ++ ++ if (kevent(pollset->kqueue_fd, &pollset->kevent, 1, NULL, 0, ++ NULL) == -1) { ++ rv = APR_NOTFOUND; ++ } ++ } ++ ++ if (!APR_RING_EMPTY(&(pollset->query_ring), pfd_elem_t, link)) { ++ for (ep = APR_RING_FIRST(&(pollset->query_ring)); ++ ep != APR_RING_SENTINEL(&(pollset->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->dead_ring), ++ ep, pfd_elem_t, link); ++ break; ++ } ++ } ++ } ++ ++ pollset_unlock_rings(); ++ ++ return rv; ++} ++ ++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 ret, i; ++ pfd_elem_t *ep; ++ 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_msec(timeout); ++ tvptr = &tv; ++ } ++ ++ ret = kevent(pollset->kqueue_fd, NULL, 0, pollset->ke_set, pollset->nalloc, ++ tvptr); ++ (*num) = ret; ++ if (ret < 0) { ++ rv = apr_get_netos_error(); ++ } ++ else if (ret == 0) { ++ rv = APR_TIMEUP; ++ } ++ else { ++ for (i = 0; i < ret; i++) { ++ pollset->result_set[i] = ++ (((pfd_elem_t*)(pollset->ke_set[i].udata))->pfd); ++ pollset->result_set[i].rtnevents = ++ get_kqueue_revent(pollset->ke_set[i].filter, ++ pollset->ke_set[i].flags); ++ } ++ ++ if (descriptors) { ++ *descriptors = pollset->result_set; ++ } ++ } ++ ++ ++ pollset_lock_rings(); ++ ++ /* Shift all PFDs in the Dead Ring to be Free Ring */ ++ while (!APR_RING_EMPTY(&(pollset->dead_ring), pfd_elem_t, link)) { ++ ep = APR_RING_FIRST(&(pollset->dead_ring)); ++ APR_RING_REMOVE(ep, link); ++ APR_RING_INSERT_TAIL(&(pollset->free_ring), ep, pfd_elem_t, link); ++ } ++ ++ pollset_unlock_rings(); ++ ++ return rv; ++} ++ ++#endif /* POLLSET_USES_KQUEUE */ +diff -Nur srclib/apr.orig/poll/unix/poll.c srclib/apr/poll/unix/poll.c +--- srclib/apr.orig/poll/unix/poll.c Mon Dec 13 18:57:05 2004 ++++ srclib/apr/poll/unix/poll.c Mon Dec 13 18:57:28 2004 +@@ -13,111 +13,26 @@ + * limitations under the License. + */ + +-#include "apr.h" +-#include "apr_poll.h" +-#include "apr_time.h" +-#include "apr_portable.h" +-#include "apr_arch_networkio.h" +-#include "apr_arch_file_io.h" +-#if HAVE_POLL_H +-#include <poll.h> +-#endif +-#if HAVE_SYS_POLL_H +-#include <sys/poll.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 +- +-#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; +- if (event & EVFILT_WRITE) +- rv |= APR_POLLOUT; +- if (flags & EV_EOF) +- rv |= APR_POLLHUP; +- if (flags & EV_ERROR) +- rv |= APR_POLLERR; +- +- return rv; +-} +- +-#endif ++#include "apr_arch_poll_private.h" + +-#ifdef 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; +- if (event & APR_POLLERR) +- rv |= EPOLLERR; +- if (event & APR_POLLHUP) +- rv |= EPOLLHUP; +- /* APR_POLLNVAL is not handled by epoll. */ +- +- 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; +-} +-#endif +- +-#ifdef HAVE_POLL /* We can just use poll to do our socket polling. */ ++#if defined(POLL_USES_POLL) || defined(POLLSET_USES_POLL) + + static apr_int16_t get_event(apr_int16_t event) + { + apr_int16_t rv = 0; + + if (event & APR_POLLIN) +- rv |= POLLIN; ++ rv |= POLLIN; + if (event & APR_POLLPRI) +- rv |= POLLPRI; ++ rv |= POLLPRI; + if (event & APR_POLLOUT) +- rv |= POLLOUT; ++ rv |= POLLOUT; + if (event & APR_POLLERR) +- rv |= POLLERR; ++ rv |= POLLERR; + if (event & APR_POLLHUP) +- rv |= POLLHUP; ++ rv |= POLLHUP; + if (event & APR_POLLNVAL) +- rv |= POLLNVAL; ++ rv |= POLLNVAL; + + return rv; + } +@@ -140,12 +55,18 @@ + rv |= APR_POLLNVAL; + + return rv; +-} ++} ++ ++#endif /* POLL_USES_POLL || POLLSET_USES_POLL */ ++ ++ ++#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) ++ apr_int32_t *nsds, ++ apr_interval_time_t timeout) + { + int i, num_to_poll; + #ifdef HAVE_VLA +@@ -215,298 +136,55 @@ + } + + +-#else /* Use select to mimic poll */ +- +-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 +- +- 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; +- } +- } ++#endif /* POLL_USES_POLL */ + +-#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 POLLSET_USES_POLL + +-#ifdef NETWARE +- } +-#endif +- +- (*nsds) = rv; +- if ((*nsds) == 0) { +- return APR_TIMEUP; +- } +- if ((*nsds) < 0) { +- return apr_get_netos_error(); +- } +- +- 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; +- } +- } +- +- return APR_SUCCESS; +-} +- +-#endif +- +-struct apr_pollset_t { ++struct apr_pollset_t ++{ + apr_pool_t *pool; +- + apr_uint32_t nelts; + apr_uint32_t nalloc; +-#ifdef HAVE_KQUEUE +- int kqueue_fd; +- struct kevent kevent; +- struct kevent *ke_set; +-#elif defined(HAVE_EPOLL) +- int epoll_fd; +- struct epoll_event *pollset; +-#elif defined(HAVE_POLL) + struct pollfd *pollset; +-#else +- fd_set readset, writeset, exceptset; +- int maxfd; +-#endif + apr_pollfd_t *query_set; + apr_pollfd_t *result_set; +- +-#ifdef NETWARE +- int set_type; +-#endif + }; + +-#if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL) +-static apr_status_t backend_cleanup(void *p_) +-{ +- apr_pollset_t *pollset = (apr_pollset_t *)p_; +-#ifdef HAVE_KQUEUE +- close(pollset->kqueue_fd); +-#elif defined(HAVE_EPOLL) +- close(pollset->epoll_fd); +-#endif +- return APR_SUCCESS; +-} +-#endif /* HAVE_KQUEUE || HAVE_EPOLL */ +- + APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset, + apr_uint32_t size, + apr_pool_t *p, + apr_uint32_t flags) + { +-#if !defined(HAVE_KQUEUE) && !defined(HAVE_EPOLL) && !defined(HAVE_POLL) && defined(FD_SETSIZE) +- if (size > FD_SETSIZE) { ++ if (flags & APR_POLLSET_THREADSAFE) { + *pollset = NULL; +- return APR_EINVAL; ++ return APR_ENOTIMPL; + } +-#endif ++ + *pollset = apr_palloc(p, sizeof(**pollset)); + (*pollset)->nelts = 0; + (*pollset)->nalloc = size; + (*pollset)->pool = p; +-#ifdef HAVE_KQUEUE +- (*pollset)->ke_set = (struct kevent*)apr_palloc(p, size * sizeof(struct kevent)); +- memset((*pollset)->ke_set, 0, size * sizeof(struct kevent)); +- (*pollset)->kqueue_fd = kqueue(); +- if ((*pollset)->kqueue_fd == -1) { +- return APR_ENOMEM; +- } +- apr_pool_cleanup_register(p, (void*)(*pollset), backend_cleanup, +- apr_pool_cleanup_null); +-#elif defined(HAVE_EPOLL) +- (*pollset)->epoll_fd = epoll_create(size); +- (*pollset)->pollset = apr_palloc(p, size * sizeof(struct epoll_event)); +- apr_pool_cleanup_register(p, (void*)(*pollset), backend_cleanup, +- apr_pool_cleanup_null); +-#elif defined(HAVE_POLL) + (*pollset)->pollset = apr_palloc(p, size * sizeof(struct pollfd)); +-#else +- FD_ZERO(&((*pollset)->readset)); +- FD_ZERO(&((*pollset)->writeset)); +- FD_ZERO(&((*pollset)->exceptset)); +- (*pollset)->maxfd = 0; +-#ifdef NETWARE +- (*pollset)->set_type = APR_NO_DESC; +-#endif +-#endif + (*pollset)->query_set = apr_palloc(p, size * sizeof(apr_pollfd_t)); + (*pollset)->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t)); +- + return APR_SUCCESS; + } + + APR_DECLARE(apr_status_t) apr_pollset_destroy(apr_pollset_t *pollset) + { +-#if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL) +- return apr_pool_cleanup_run(pollset->pool, pollset, backend_cleanup); +-#else + return APR_SUCCESS; +-#endif + } + + APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset, + const apr_pollfd_t *descriptor) + { +-#ifdef HAVE_KQUEUE +- apr_os_sock_t fd; +-#elif defined(HAVE_EPOLL) +- struct epoll_event ev; +- int ret = -1; +-#else +-#if !defined(HAVE_POLL) +- apr_os_sock_t fd; +-#endif +-#endif +- + if (pollset->nelts == pollset->nalloc) { + return APR_ENOMEM; + } + + pollset->query_set[pollset->nelts] = *descriptor; + +-#ifdef HAVE_KQUEUE +- 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->kevent, fd, EVFILT_READ, EV_ADD, 0, 0, NULL); +- +- if (kevent(pollset->kqueue_fd, &pollset->kevent, 1, NULL, 0, +- NULL) == -1) { +- return APR_ENOMEM; +- } +- } +- +- if (descriptor->reqevents & APR_POLLOUT) { +- EV_SET(&pollset->kevent, fd, EVFILT_WRITE, EV_ADD, 0, 0, NULL); +- +- if (kevent(pollset->kqueue_fd, &pollset->kevent, 1, NULL, 0, +- NULL) == -1) { +- return APR_ENOMEM; +- } +- } +- +-#elif defined(HAVE_EPOLL) +- ev.events = get_epoll_event(descriptor->reqevents); +- if (descriptor->desc_type == APR_POLL_SOCKET) { +- ev.data.fd = descriptor->desc.s->socketdes; +- ret = epoll_ctl(pollset->epoll_fd, EPOLL_CTL_ADD, +- descriptor->desc.s->socketdes, &ev); +- } +- else { +- ev.data.fd = descriptor->desc.f->filedes; +- ret = epoll_ctl(pollset->epoll_fd, EPOLL_CTL_ADD, +- descriptor->desc.f->filedes, &ev); +- } +- if (0 != ret) { +- return APR_EBADF; +- } +-#elif defined(HAVE_POLL) +- + if (descriptor->desc_type == APR_POLL_SOCKET) { + pollset->pollset[pollset->nelts].fd = descriptor->desc.s->socketdes; + } +@@ -514,59 +192,10 @@ + pollset->pollset[pollset->nelts].fd = descriptor->desc.f->filedes; + } + +- pollset->pollset[pollset->nelts].events = get_event(descriptor->reqevents); +-#else +- if (descriptor->desc_type == APR_POLL_SOCKET) { +-#ifdef NETWARE +- /* NetWare can't handle mixed descriptor types in select() */ +- if (HAS_PIPES(pollset->set_type)) { +- return APR_EBADF; +- } +- else { +- pollset->set_type = APR_POLL_SOCKET; +- } +-#endif +- fd = descriptor->desc.s->socketdes; +- } +- else { +-#if !APR_FILES_AS_SOCKETS +- return APR_EBADF; +-#else +-#ifdef NETWARE +- /* NetWare can't handle mixed descriptor types in select() */ +- if (descriptor->desc.f->is_pipe && !HAS_SOCKETS(pollset->set_type)) { +- pollset->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->readset)); +- } +- if (descriptor->reqevents & APR_POLLOUT) { +- FD_SET(fd, &(pollset->writeset)); +- } +- if (descriptor->reqevents & +- (APR_POLLPRI | APR_POLLERR | APR_POLLHUP | APR_POLLNVAL)) { +- FD_SET(fd, &(pollset->exceptset)); +- } +- if ((int)fd > pollset->maxfd) { +- pollset->maxfd = (int)fd; +- } +-#endif ++ pollset->pollset[pollset->nelts].events = ++ get_event(descriptor->reqevents); + pollset->nelts++; ++ + return APR_SUCCESS; + } + +@@ -574,97 +203,8 @@ + const apr_pollfd_t *descriptor) + { + apr_uint32_t i; +-#ifdef HAVE_KQUEUE +- apr_os_sock_t fd; +-#elif defined(HAVE_EPOLL) +- struct epoll_event ev; +- int ret = -1; +-#elif !defined(HAVE_POLL) + apr_os_sock_t fd; +-#endif + +-#ifdef HAVE_KQUEUE +- 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->query_set[dst] = pollset->query_set[i]; +- dst++; +- } +- } +- +- 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->kevent, fd, +- EVFILT_READ, EV_DELETE, 0, 0, NULL); +- +- if (kevent(pollset->kqueue_fd, &pollset->kevent, 1, NULL, 0, +- NULL) == -1) { +- return APR_EBADF; +- } +- } +- +- if (descriptor->reqevents & APR_POLLOUT) { +- EV_SET(&pollset->kevent, fd, +- EVFILT_WRITE, EV_DELETE, 0, 0, NULL); +- +- if (kevent(pollset->kqueue_fd, &pollset->kevent, 1, NULL, 0, +- NULL) == -1) { +- return APR_EBADF; +- } +- } +- +- return APR_SUCCESS; +- } +- } +-#elif defined(HAVE_EPOLL) +- 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->query_set[dst] = pollset->query_set[i]; +- dst++; +- } +- } +- ev.events = get_epoll_event(descriptor->reqevents); +- if (descriptor->desc_type == APR_POLL_SOCKET) { +- ev.data.fd = descriptor->desc.s->socketdes; +- ret = epoll_ctl(pollset->epoll_fd, EPOLL_CTL_DEL, +- descriptor->desc.s->socketdes, &ev); +- } +- else { +- ev.data.fd = descriptor->desc.f->filedes; +- ret = epoll_ctl(pollset->epoll_fd, EPOLL_CTL_DEL, +- descriptor->desc.f->filedes, &ev); +- } +- if (ret < 0) { +- return APR_EBADF; +- } +- +- return APR_SUCCESS; +- } +- } +-#elif defined(HAVE_POLL) + 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 */ +@@ -685,159 +225,9 @@ + } + } + +-#else /* no poll */ +- 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->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->query_set[dst] = pollset->query_set[i]; +- dst++; +- } +- } +- FD_CLR(fd, &(pollset->readset)); +- FD_CLR(fd, &(pollset->writeset)); +- FD_CLR(fd, &(pollset->exceptset)); +- if (((int)fd == pollset->maxfd) && (pollset->maxfd > 0)) { +- pollset->maxfd--; +- } +- return APR_SUCCESS; +- } +- } +-#endif /* no poll */ +- + return APR_NOTFOUND; + } +-#ifdef HAVE_KQUEUE +-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, j, r = 0; +- struct timespec tv, *tvptr; +- +- if (timeout < 0) { +- tvptr = NULL; +- } +- else { +- tv.tv_sec = (long)apr_time_sec(timeout); +- tv.tv_nsec = (long)apr_time_msec(timeout); +- tvptr = &tv; +- } + +- rv = kevent(pollset->kqueue_fd, NULL, 0, pollset->ke_set, pollset->nelts, +- tvptr); +- (*num) = rv; +- if (rv < 0) { +- return apr_get_netos_error(); +- } +- if (rv == 0) { +- return APR_TIMEUP; +- } +- +- /* TODO: Is there a better way to re-associate our data? */ +- for (i = 0; i < pollset->nelts; i++) { +- apr_os_sock_t fd; +- if (pollset->query_set[i].desc_type == APR_POLL_SOCKET) { +- fd = pollset->query_set[i].desc.s->socketdes; +- } +- else { +- fd = pollset->query_set[i].desc.f->filedes; +- } +- for (j = 0; j < rv; j++) { +- if (pollset->ke_set[j].ident == fd ) { +- pollset->result_set[r] = pollset->query_set[i]; +- pollset->result_set[r].rtnevents = +- get_kqueue_revent(pollset->ke_set[j].filter, +- pollset->ke_set[j].flags); +- r++; +- } +- } +- } +- +- (*num) = r; +- +- if (descriptors) { +- *descriptors = pollset->result_set; +- } +- +- return APR_SUCCESS; +-} +- +-#elif defined(HAVE_EPOLL) +- +-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, j, k; +- +- if (timeout > 0) { +- timeout /= 1000; +- } +- +- rv = epoll_wait(pollset->epoll_fd, pollset->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 (pollset->pollset[i].events != 0) { +- /* TODO: Is there a better way to re-associate our data? */ +- for (k = 0; k < pollset->nelts; k++) { +- if (pollset->query_set[k].desc_type == APR_POLL_SOCKET && +- pollset->query_set[k].desc.s->socketdes == +- pollset->pollset[i].data.fd) { +- pollset->result_set[j] = pollset->query_set[k]; +- pollset->result_set[j].rtnevents = +- get_epoll_revent(pollset->pollset[i].events); +- j++; +- break; +- } +- else if (pollset->query_set[k].desc_type == APR_POLL_FILE +- && pollset->query_set[k].desc.f->filedes == +- pollset->pollset[i].data.fd) { +- pollset->result_set[j] = pollset->query_set[k]; +- pollset->result_set[j].rtnevents = +- get_epoll_revent(pollset->pollset[i].events); +- j++; +- break; +- } +- } +- } +- } +- if (descriptors) { +- *descriptors = pollset->result_set; +- } +- return APR_SUCCESS; +-} +-#elif defined(HAVE_POLL) + APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset, + apr_interval_time_t timeout, + apr_int32_t *num, +@@ -871,79 +261,4 @@ + return APR_SUCCESS; + } + +-#else /* no poll */ +- +-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, j; +- struct timeval tv, *tvptr; +- fd_set readset, writeset, exceptset; +- +- 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->readset), sizeof(fd_set)); +- memcpy(&writeset, &(pollset->writeset), sizeof(fd_set)); +- memcpy(&exceptset, &(pollset->exceptset), sizeof(fd_set)); +- +-#ifdef NETWARE +- if (HAS_PIPES(pollset->set_type)) { +- rv = pipe_select(pollset->maxfd + 1, &readset, &writeset, &exceptset, tvptr); +- } +- else +-#endif +- rv = select(pollset->maxfd + 1, &readset, &writeset, &exceptset, tvptr); +- +- (*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++) { +- apr_os_sock_t fd; +- if (pollset->query_set[i].desc_type == APR_POLL_SOCKET) { +- fd = pollset->query_set[i].desc.s->socketdes; +- } +- else { +-#if !APR_FILES_AS_SOCKETS +- return APR_EBADF; +-#else +- fd = pollset->query_set[i].desc.f->filedes; +-#endif +- } +- if (FD_ISSET(fd, &readset) || FD_ISSET(fd, &writeset) || +- FD_ISSET(fd, &exceptset)) { +- pollset->result_set[j] = pollset->query_set[i]; +- pollset->result_set[j].rtnevents = 0; +- if (FD_ISSET(fd, &readset)) { +- pollset->result_set[j].rtnevents |= APR_POLLIN; +- } +- if (FD_ISSET(fd, &writeset)) { +- pollset->result_set[j].rtnevents |= APR_POLLOUT; +- } +- if (FD_ISSET(fd, &exceptset)) { +- pollset->result_set[j].rtnevents |= APR_POLLERR; +- } +- j++; +- } +- } +- +- if (descriptors) +- *descriptors = pollset->result_set; +- return APR_SUCCESS; +-} +- +-#endif /* no poll */ ++#endif /* POLLSET_USES_POLL */ +diff -Nur srclib/apr.orig/poll/unix/poll.c.orig srclib/apr/poll/unix/poll.c.orig +--- srclib/apr.orig/poll/unix/poll.c.orig Thu Jan 1 01:00:00 1970 ++++ srclib/apr/poll/unix/poll.c.orig Wed Nov 17 02:07:02 2004 +@@ -0,0 +1,949 @@ ++/* Copyright 2000-2004 The Apache Software Foundation ++ * ++ * 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. ++ */ ++ ++#include "apr.h" ++#include "apr_poll.h" ++#include "apr_time.h" ++#include "apr_portable.h" ++#include "apr_arch_networkio.h" ++#include "apr_arch_file_io.h" ++#if HAVE_POLL_H ++#include <poll.h> ++#endif ++#if HAVE_SYS_POLL_H ++#include <sys/poll.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 ++ ++#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; ++ if (event & EVFILT_WRITE) ++ rv |= APR_POLLOUT; ++ if (flags & EV_EOF) ++ rv |= APR_POLLHUP; ++ if (flags & EV_ERROR) ++ rv |= APR_POLLERR; ++ ++ return rv; ++} ++ ++#endif ++ ++#ifdef 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; ++ if (event & APR_POLLERR) ++ rv |= EPOLLERR; ++ if (event & APR_POLLHUP) ++ rv |= EPOLLHUP; ++ /* APR_POLLNVAL is not handled by epoll. */ ++ ++ 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; ++} ++#endif ++ ++#ifdef HAVE_POLL /* We can just use poll to do our socket polling. */ ++ ++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; ++ if (event & APR_POLLERR) ++ rv |= POLLERR; ++ if (event & APR_POLLHUP) ++ rv |= POLLHUP; ++ if (event & APR_POLLNVAL) ++ rv |= POLLNVAL; ++ ++ 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; ++} ++ ++#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; ++ ++ 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; ++} ++ ++ ++#else /* Use select to mimic poll */ ++ ++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 ++ ++ 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(); ++ } ++ ++ 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; ++ } ++ } ++ ++ return APR_SUCCESS; ++} ++ ++#endif ++ ++struct apr_pollset_t { ++ apr_pool_t *pool; ++ ++ apr_uint32_t nelts; ++ apr_uint32_t nalloc; ++#ifdef HAVE_KQUEUE ++ int kqueue_fd; ++ struct kevent kevent; ++ struct kevent *ke_set; ++#elif defined(HAVE_EPOLL) ++ int epoll_fd; ++ struct epoll_event *pollset; ++#elif defined(HAVE_POLL) ++ struct pollfd *pollset; ++#else ++ fd_set readset, writeset, exceptset; ++ int maxfd; ++#endif ++ apr_pollfd_t *query_set; ++ apr_pollfd_t *result_set; ++ ++#ifdef NETWARE ++ int set_type; ++#endif ++}; ++ ++#if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL) ++static apr_status_t backend_cleanup(void *p_) ++{ ++ apr_pollset_t *pollset = (apr_pollset_t *)p_; ++#ifdef HAVE_KQUEUE ++ close(pollset->kqueue_fd); ++#elif defined(HAVE_EPOLL) ++ close(pollset->epoll_fd); ++#endif ++ return APR_SUCCESS; ++} ++#endif /* HAVE_KQUEUE || HAVE_EPOLL */ ++ ++APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset, ++ apr_uint32_t size, ++ apr_pool_t *p, ++ apr_uint32_t flags) ++{ ++#if !defined(HAVE_KQUEUE) && !defined(HAVE_EPOLL) && !defined(HAVE_POLL) && defined(FD_SETSIZE) ++ if (size > FD_SETSIZE) { ++ *pollset = NULL; ++ return APR_EINVAL; ++ } ++#endif ++ *pollset = apr_palloc(p, sizeof(**pollset)); ++ (*pollset)->nelts = 0; ++ (*pollset)->nalloc = size; ++ (*pollset)->pool = p; ++#ifdef HAVE_KQUEUE ++ (*pollset)->ke_set = (struct kevent*)apr_palloc(p, size * sizeof(struct kevent)); ++ memset((*pollset)->ke_set, 0, size * sizeof(struct kevent)); ++ (*pollset)->kqueue_fd = kqueue(); ++ if ((*pollset)->kqueue_fd == -1) { ++ return APR_ENOMEM; ++ } ++ apr_pool_cleanup_register(p, (void*)(*pollset), backend_cleanup, ++ apr_pool_cleanup_null); ++#elif defined(HAVE_EPOLL) ++ (*pollset)->epoll_fd = epoll_create(size); ++ (*pollset)->pollset = apr_palloc(p, size * sizeof(struct epoll_event)); ++ apr_pool_cleanup_register(p, (void*)(*pollset), backend_cleanup, ++ apr_pool_cleanup_null); ++#elif defined(HAVE_POLL) ++ (*pollset)->pollset = apr_palloc(p, size * sizeof(struct pollfd)); ++#else ++ FD_ZERO(&((*pollset)->readset)); ++ FD_ZERO(&((*pollset)->writeset)); ++ FD_ZERO(&((*pollset)->exceptset)); ++ (*pollset)->maxfd = 0; ++#ifdef NETWARE ++ (*pollset)->set_type = APR_NO_DESC; ++#endif ++#endif ++ (*pollset)->query_set = apr_palloc(p, size * sizeof(apr_pollfd_t)); ++ (*pollset)->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t)); ++ ++ return APR_SUCCESS; ++} ++ ++APR_DECLARE(apr_status_t) apr_pollset_destroy(apr_pollset_t *pollset) ++{ ++#if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL) ++ return apr_pool_cleanup_run(pollset->pool, pollset, backend_cleanup); ++#else ++ return APR_SUCCESS; ++#endif ++} ++ ++APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset, ++ const apr_pollfd_t *descriptor) ++{ ++#ifdef HAVE_KQUEUE ++ apr_os_sock_t fd; ++#elif defined(HAVE_EPOLL) ++ struct epoll_event ev; ++ int ret = -1; ++#else ++#if !defined(HAVE_POLL) ++ apr_os_sock_t fd; ++#endif ++#endif ++ ++ if (pollset->nelts == pollset->nalloc) { ++ return APR_ENOMEM; ++ } ++ ++ pollset->query_set[pollset->nelts] = *descriptor; ++ ++#ifdef HAVE_KQUEUE ++ 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->kevent, fd, EVFILT_READ, EV_ADD, 0, 0, NULL); ++ ++ if (kevent(pollset->kqueue_fd, &pollset->kevent, 1, NULL, 0, ++ NULL) == -1) { ++ return APR_ENOMEM; ++ } ++ } ++ ++ if (descriptor->reqevents & APR_POLLOUT) { ++ EV_SET(&pollset->kevent, fd, EVFILT_WRITE, EV_ADD, 0, 0, NULL); ++ ++ if (kevent(pollset->kqueue_fd, &pollset->kevent, 1, NULL, 0, ++ NULL) == -1) { ++ return APR_ENOMEM; ++ } ++ } ++ ++#elif defined(HAVE_EPOLL) ++ ev.events = get_epoll_event(descriptor->reqevents); ++ if (descriptor->desc_type == APR_POLL_SOCKET) { ++ ev.data.fd = descriptor->desc.s->socketdes; ++ ret = epoll_ctl(pollset->epoll_fd, EPOLL_CTL_ADD, ++ descriptor->desc.s->socketdes, &ev); ++ } ++ else { ++ ev.data.fd = descriptor->desc.f->filedes; ++ ret = epoll_ctl(pollset->epoll_fd, EPOLL_CTL_ADD, ++ descriptor->desc.f->filedes, &ev); ++ } ++ if (0 != ret) { ++ return APR_EBADF; ++ } ++#elif defined(HAVE_POLL) ++ ++ if (descriptor->desc_type == APR_POLL_SOCKET) { ++ pollset->pollset[pollset->nelts].fd = descriptor->desc.s->socketdes; ++ } ++ else { ++ pollset->pollset[pollset->nelts].fd = descriptor->desc.f->filedes; ++ } ++ ++ pollset->pollset[pollset->nelts].events = get_event(descriptor->reqevents); ++#else ++ if (descriptor->desc_type == APR_POLL_SOCKET) { ++#ifdef NETWARE ++ /* NetWare can't handle mixed descriptor types in select() */ ++ if (HAS_PIPES(pollset->set_type)) { ++ return APR_EBADF; ++ } ++ else { ++ pollset->set_type = APR_POLL_SOCKET; ++ } ++#endif ++ fd = descriptor->desc.s->socketdes; ++ } ++ else { ++#if !APR_FILES_AS_SOCKETS ++ return APR_EBADF; ++#else ++#ifdef NETWARE ++ /* NetWare can't handle mixed descriptor types in select() */ ++ if (descriptor->desc.f->is_pipe && !HAS_SOCKETS(pollset->set_type)) { ++ pollset->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->readset)); ++ } ++ if (descriptor->reqevents & APR_POLLOUT) { ++ FD_SET(fd, &(pollset->writeset)); ++ } ++ if (descriptor->reqevents & ++ (APR_POLLPRI | APR_POLLERR | APR_POLLHUP | APR_POLLNVAL)) { ++ FD_SET(fd, &(pollset->exceptset)); ++ } ++ if ((int)fd > pollset->maxfd) { ++ pollset->maxfd = (int)fd; ++ } ++#endif ++ pollset->nelts++; ++ return APR_SUCCESS; ++} ++ ++APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset, ++ const apr_pollfd_t *descriptor) ++{ ++ apr_uint32_t i; ++#ifdef HAVE_KQUEUE ++ apr_os_sock_t fd; ++#elif defined(HAVE_EPOLL) ++ struct epoll_event ev; ++ int ret = -1; ++#elif !defined(HAVE_POLL) ++ apr_os_sock_t fd; ++#endif ++ ++#ifdef HAVE_KQUEUE ++ 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->query_set[dst] = pollset->query_set[i]; ++ dst++; ++ } ++ } ++ ++ 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->kevent, fd, ++ EVFILT_READ, EV_DELETE, 0, 0, NULL); ++ ++ if (kevent(pollset->kqueue_fd, &pollset->kevent, 1, NULL, 0, ++ NULL) == -1) { ++ return APR_EBADF; ++ } ++ } ++ ++ if (descriptor->reqevents & APR_POLLOUT) { ++ EV_SET(&pollset->kevent, fd, ++ EVFILT_WRITE, EV_DELETE, 0, 0, NULL); ++ ++ if (kevent(pollset->kqueue_fd, &pollset->kevent, 1, NULL, 0, ++ NULL) == -1) { ++ return APR_EBADF; ++ } ++ } ++ ++ return APR_SUCCESS; ++ } ++ } ++#elif defined(HAVE_EPOLL) ++ 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->query_set[dst] = pollset->query_set[i]; ++ dst++; ++ } ++ } ++ ev.events = get_epoll_event(descriptor->reqevents); ++ if (descriptor->desc_type == APR_POLL_SOCKET) { ++ ev.data.fd = descriptor->desc.s->socketdes; ++ ret = epoll_ctl(pollset->epoll_fd, EPOLL_CTL_DEL, ++ descriptor->desc.s->socketdes, &ev); ++ } ++ else { ++ ev.data.fd = descriptor->desc.f->filedes; ++ ret = epoll_ctl(pollset->epoll_fd, EPOLL_CTL_DEL, ++ descriptor->desc.f->filedes, &ev); ++ } ++ if (ret < 0) { ++ return APR_EBADF; ++ } ++ ++ return APR_SUCCESS; ++ } ++ } ++#elif defined(HAVE_POLL) ++ 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++; ++ } ++ } ++ return APR_SUCCESS; ++ } ++ } ++ ++#else /* no poll */ ++ 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->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->query_set[dst] = pollset->query_set[i]; ++ dst++; ++ } ++ } ++ FD_CLR(fd, &(pollset->readset)); ++ FD_CLR(fd, &(pollset->writeset)); ++ FD_CLR(fd, &(pollset->exceptset)); ++ if (((int)fd == pollset->maxfd) && (pollset->maxfd > 0)) { ++ pollset->maxfd--; ++ } ++ return APR_SUCCESS; ++ } ++ } ++#endif /* no poll */ ++ ++ return APR_NOTFOUND; ++} ++#ifdef HAVE_KQUEUE ++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, j, r = 0; ++ struct timespec tv, *tvptr; ++ ++ if (timeout < 0) { ++ tvptr = NULL; ++ } ++ else { ++ tv.tv_sec = (long)apr_time_sec(timeout); ++ tv.tv_nsec = (long)apr_time_msec(timeout); ++ tvptr = &tv; ++ } ++ ++ rv = kevent(pollset->kqueue_fd, NULL, 0, pollset->ke_set, pollset->nelts, ++ tvptr); ++ (*num) = rv; ++ if (rv < 0) { ++ return apr_get_netos_error(); ++ } ++ if (rv == 0) { ++ return APR_TIMEUP; ++ } ++ ++ /* TODO: Is there a better way to re-associate our data? */ ++ for (i = 0; i < pollset->nelts; i++) { ++ apr_os_sock_t fd; ++ if (pollset->query_set[i].desc_type == APR_POLL_SOCKET) { ++ fd = pollset->query_set[i].desc.s->socketdes; ++ } ++ else { ++ fd = pollset->query_set[i].desc.f->filedes; ++ } ++ for (j = 0; j < rv; j++) { ++ if (pollset->ke_set[j].ident == fd ) { ++ pollset->result_set[r] = pollset->query_set[i]; ++ pollset->result_set[r].rtnevents = ++ get_kqueue_revent(pollset->ke_set[j].filter, ++ pollset->ke_set[j].flags); ++ r++; ++ } ++ } ++ } ++ ++ (*num) = r; ++ ++ if (descriptors) { ++ *descriptors = pollset->result_set; ++ } ++ ++ return APR_SUCCESS; ++} ++ ++#elif defined(HAVE_EPOLL) ++ ++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, j, k; ++ ++ if (timeout > 0) { ++ timeout /= 1000; ++ } ++ ++ rv = epoll_wait(pollset->epoll_fd, pollset->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 (pollset->pollset[i].events != 0) { ++ /* TODO: Is there a better way to re-associate our data? */ ++ for (k = 0; k < pollset->nelts; k++) { ++ if (pollset->query_set[k].desc_type == APR_POLL_SOCKET && ++ pollset->query_set[k].desc.s->socketdes == ++ pollset->pollset[i].data.fd) { ++ pollset->result_set[j] = pollset->query_set[k]; ++ pollset->result_set[j].rtnevents = ++ get_epoll_revent(pollset->pollset[i].events); ++ j++; ++ break; ++ } ++ else if (pollset->query_set[k].desc_type == APR_POLL_FILE ++ && pollset->query_set[k].desc.f->filedes == ++ pollset->pollset[i].data.fd) { ++ pollset->result_set[j] = pollset->query_set[k]; ++ pollset->result_set[j].rtnevents = ++ get_epoll_revent(pollset->pollset[i].events); ++ j++; ++ break; ++ } ++ } ++ } ++ } ++ if (descriptors) { ++ *descriptors = pollset->result_set; ++ } ++ return APR_SUCCESS; ++} ++#elif defined(HAVE_POLL) ++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, j; ++ ++ if (timeout > 0) { ++ timeout /= 1000; ++ } ++ rv = poll(pollset->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 (pollset->pollset[i].revents != 0) { ++ pollset->result_set[j] = pollset->query_set[i]; ++ pollset->result_set[j].rtnevents = ++ get_revent(pollset->pollset[i].revents); ++ j++; ++ } ++ } ++ if (descriptors) ++ *descriptors = pollset->result_set; ++ return APR_SUCCESS; ++} ++ ++#else /* no poll */ ++ ++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, j; ++ struct timeval tv, *tvptr; ++ fd_set readset, writeset, exceptset; ++ ++ 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->readset), sizeof(fd_set)); ++ memcpy(&writeset, &(pollset->writeset), sizeof(fd_set)); ++ memcpy(&exceptset, &(pollset->exceptset), sizeof(fd_set)); ++ ++#ifdef NETWARE ++ if (HAS_PIPES(pollset->set_type)) { ++ rv = pipe_select(pollset->maxfd + 1, &readset, &writeset, &exceptset, tvptr); ++ } ++ else ++#endif ++ rv = select(pollset->maxfd + 1, &readset, &writeset, &exceptset, tvptr); ++ ++ (*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++) { ++ apr_os_sock_t fd; ++ if (pollset->query_set[i].desc_type == APR_POLL_SOCKET) { ++ fd = pollset->query_set[i].desc.s->socketdes; ++ } ++ else { ++#if !APR_FILES_AS_SOCKETS ++ return APR_EBADF; ++#else ++ fd = pollset->query_set[i].desc.f->filedes; ++#endif ++ } ++ if (FD_ISSET(fd, &readset) || FD_ISSET(fd, &writeset) || ++ FD_ISSET(fd, &exceptset)) { ++ pollset->result_set[j] = pollset->query_set[i]; ++ pollset->result_set[j].rtnevents = 0; ++ if (FD_ISSET(fd, &readset)) { ++ pollset->result_set[j].rtnevents |= APR_POLLIN; ++ } ++ if (FD_ISSET(fd, &writeset)) { ++ pollset->result_set[j].rtnevents |= APR_POLLOUT; ++ } ++ if (FD_ISSET(fd, &exceptset)) { ++ pollset->result_set[j].rtnevents |= APR_POLLERR; ++ } ++ j++; ++ } ++ } ++ ++ if (descriptors) ++ *descriptors = pollset->result_set; ++ return APR_SUCCESS; ++} ++ ++#endif /* no poll */ +diff -Nur srclib/apr.orig/poll/unix/select.c srclib/apr/poll/unix/select.c +--- srclib/apr.orig/poll/unix/select.c Thu Jan 1 01:00:00 1970 ++++ srclib/apr/poll/unix/select.c Mon Dec 13 18:57:28 2004 +@@ -0,0 +1,392 @@ ++/* Copyright 2000-2004 The Apache Software Foundation ++ * ++ * 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. ++ */ ++ ++#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 ++ ++ 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(); ++ } ++ ++ 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; ++ } ++ } ++ ++ return APR_SUCCESS; ++} ++ ++#endif /* POLL_USES_SELECT */ ++ ++#ifdef POLLSET_USES_SELECT ++ ++struct apr_pollset_t ++{ ++ apr_pool_t *pool; ++ ++ apr_uint32_t nelts; ++ apr_uint32_t nalloc; ++ fd_set readset, writeset, exceptset; ++ int maxfd; ++ apr_pollfd_t *query_set; ++ apr_pollfd_t *result_set; ++#ifdef NETWARE ++ int set_type; ++#endif ++}; ++ ++APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset, ++ apr_uint32_t size, ++ apr_pool_t *p, ++ apr_uint32_t flags) ++{ ++ if (flags & APR_POLLSET_THREADSAFE) { ++ *pollset = NULL; ++ return APR_ENOTIMPL; ++ } ++#ifdef FD_SETSIZE ++ if (size > FD_SETSIZE) { ++ *pollset = NULL; ++ return APR_EINVAL; ++ } ++#endif ++ *pollset = apr_palloc(p, sizeof(**pollset)); ++ (*pollset)->nelts = 0; ++ (*pollset)->nalloc = size; ++ (*pollset)->pool = p; ++ FD_ZERO(&((*pollset)->readset)); ++ FD_ZERO(&((*pollset)->writeset)); ++ FD_ZERO(&((*pollset)->exceptset)); ++ (*pollset)->maxfd = 0; ++#ifdef NETWARE ++ (*pollset)->set_type = APR_NO_DESC; ++#endif ++ (*pollset)->query_set = apr_palloc(p, size * sizeof(apr_pollfd_t)); ++ (*pollset)->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t)); ++ ++ return APR_SUCCESS; ++} ++ ++APR_DECLARE(apr_status_t) apr_pollset_destroy(apr_pollset_t * pollset) ++{ ++ return APR_SUCCESS; ++} ++ ++APR_DECLARE(apr_status_t) apr_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->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->set_type)) { ++ return APR_EBADF; ++ } ++ else { ++ pollset->set_type = APR_POLL_SOCKET; ++ } ++#endif ++ fd = descriptor->desc.s->socketdes; ++ } ++ else { ++#if !APR_FILES_AS_SOCKETS ++ return APR_EBADF; ++#else ++#ifdef NETWARE ++ /* NetWare can't handle mixed descriptor types in select() */ ++ if (descriptor->desc.f->is_pipe && !HAS_SOCKETS(pollset->set_type)) { ++ pollset->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->readset)); ++ } ++ if (descriptor->reqevents & APR_POLLOUT) { ++ FD_SET(fd, &(pollset->writeset)); ++ } ++ if (descriptor->reqevents & ++ (APR_POLLPRI | APR_POLLERR | APR_POLLHUP | APR_POLLNVAL)) { ++ FD_SET(fd, &(pollset->exceptset)); ++ } ++ if ((int) fd > pollset->maxfd) { ++ pollset->maxfd = (int) fd; ++ } ++ pollset->nelts++; ++ return APR_SUCCESS; ++} ++ ++APR_DECLARE(apr_status_t) apr_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->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->query_set[dst] = pollset->query_set[i]; ++ dst++; ++ } ++ } ++ FD_CLR(fd, &(pollset->readset)); ++ FD_CLR(fd, &(pollset->writeset)); ++ FD_CLR(fd, &(pollset->exceptset)); ++ if (((int) fd == pollset->maxfd) && (pollset->maxfd > 0)) { ++ pollset->maxfd--; ++ } ++ return APR_SUCCESS; ++ } ++ } ++ ++ return APR_NOTFOUND; ++} ++ ++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, j; ++ struct timeval tv, *tvptr; ++ fd_set readset, writeset, exceptset; ++ ++ 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->readset), sizeof(fd_set)); ++ memcpy(&writeset, &(pollset->writeset), sizeof(fd_set)); ++ memcpy(&exceptset, &(pollset->exceptset), sizeof(fd_set)); ++ ++#ifdef NETWARE ++ if (HAS_PIPES(pollset->set_type)) { ++ rv = pipe_select(pollset->maxfd + 1, &readset, &writeset, &exceptset, ++ tvptr); ++ } ++ else ++#endif ++ rv = select(pollset->maxfd + 1, &readset, &writeset, &exceptset, ++ tvptr); ++ ++ (*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++) { ++ apr_os_sock_t fd; ++ if (pollset->query_set[i].desc_type == APR_POLL_SOCKET) { ++ fd = pollset->query_set[i].desc.s->socketdes; ++ } ++ else { ++#if !APR_FILES_AS_SOCKETS ++ return APR_EBADF; ++#else ++ fd = pollset->query_set[i].desc.f->filedes; ++#endif ++ } ++ if (FD_ISSET(fd, &readset) || FD_ISSET(fd, &writeset) || ++ FD_ISSET(fd, &exceptset)) { ++ pollset->result_set[j] = pollset->query_set[i]; ++ pollset->result_set[j].rtnevents = 0; ++ if (FD_ISSET(fd, &readset)) { ++ pollset->result_set[j].rtnevents |= APR_POLLIN; ++ } ++ if (FD_ISSET(fd, &writeset)) { ++ pollset->result_set[j].rtnevents |= APR_POLLOUT; ++ } ++ if (FD_ISSET(fd, &exceptset)) { ++ pollset->result_set[j].rtnevents |= APR_POLLERR; ++ } ++ j++; ++ } ++ } ++ ++ if (descriptors) ++ *descriptors = pollset->result_set; ++ return APR_SUCCESS; ++} ++ ++#endif /* POLLSET_USES_SELECT */ diff --git a/www/apache22/files/patch-Makefile.in b/www/apache22/files/patch-Makefile.in index 1cd16ef..b9b6ecb 100644 --- a/www/apache22/files/patch-Makefile.in +++ b/www/apache22/files/patch-Makefile.in @@ -1,20 +1,29 @@ --- Makefile.in.orig Thu Dec 2 08:34:20 2004 -+++ Makefile.in Sat Dec 11 16:39:40 2004 -@@ -36,10 +36,13 @@ ++++ Makefile.in Mon Dec 13 19:35:54 2004 +@@ -31,15 +31,22 @@ + if [ ! -d $(DESTDIR)$(sysconfdir) ]; then \ + $(MKINSTALLDIRS) $(DESTDIR)$(sysconfdir) ; \ + fi ; \ ++ if [ ! -d $(DESTDIR)$(EXAMPLESDIR) ]; then \ ++ $(MKINSTALLDIRS) $(DESTDIR)$(EXAMPLESDIR) ; \ ++ fi ; \ + cd $(top_srcdir)/docs/conf; \ + for i in mime.types magic; do \ if test ! -f $(DESTDIR)$(sysconfdir)/$$i; then \ $(INSTALL_DATA) $$i $(DESTDIR)$(sysconfdir); \ fi; \ + cp -f $$i $$i-dist; \ -+ $(INSTALL_DATA) $$i-dist $(DESTDIR)$(sysconfdir); \ ++ $(INSTALL_DATA) $$i-dist $(DESTDIR)$(EXAMPLESDIR); \ done; \ for j in $(top_srcdir)/docs/conf $(top_builddir)/docs/conf ; do \ cd $$j ; \ ++ [ -f `echo "$$i"|sed 's,\.in$$,_nonex,g'` ] || continue; \ for i in *-std*.conf; do \ + [ -f `echo "$$i"|sed 's,\.in$$,_nonex,g'` ] || continue; \ ( \ n_lm=`awk 'BEGIN {n=0} /@@LoadModule@@/ {n+=1} END {print n}' < $$i`; \ if test $$n_lm -eq 0 -o "x$(DSO_MODULES)" = "x"; then \ -@@ -57,6 +60,9 @@ +@@ -57,6 +64,9 @@ if test "x$$j" = "xssl"; then \ echo "<IfDefine SSL>"; \ fi; \ @@ -24,7 +33,27 @@ if test $$j != "^EOL^"; then \ echo "LoadModule $${j}_module $(rel_libexecdir)/mod_$${j}.so"; \ fi; \ -@@ -108,44 +114,40 @@ +@@ -70,14 +80,15 @@ + -e 's#@@Port@@#$(PORT)#g' \ + < $$i; \ + fi \ +- ) > $(DESTDIR)$(sysconfdir)/$$i; \ +- chmod 0644 $(DESTDIR)$(sysconfdir)/$$i; \ +- file=`echo $$i|sed s/-std//`; \ ++ ) > $(DESTDIR)$(EXAMPLESDIR)/$$i; \ ++ chmod 0644 $(DESTDIR)$(EXAMPLESDIR)/$$i; \ ++ chmod 0644 $(DESTDIR)$(EXAMPLESDIR)/$$i; \ ++ file=`echo $$i|sed s/-std//`; \ + if [ "$$file" = "httpd.conf" ]; then \ + file=`echo $$file|sed s/.*.conf/$(PROGRAM_NAME).conf/`; \ + fi; \ + if test "$$file" != "$$i" && test ! -f $(DESTDIR)$(sysconfdir)/$$file; then \ +- $(INSTALL_DATA) $(DESTDIR)$(sysconfdir)/$$i $(DESTDIR)$(sysconfdir)/$$file; \ ++ $(INSTALL_DATA) $(DESTDIR)$(EXAMPLESDIR)/$$i $(DESTDIR)$(sysconfdir)/$$file; \ + fi; \ + done ; \ + done ; \ +@@ -108,44 +119,40 @@ doxygen $(top_srcdir)/docs/doxygen.conf install-htdocs: @@ -97,7 +126,7 @@ install-other: @test -d $(DESTDIR)$(logfiledir) || $(MKINSTALLDIRS) $(DESTDIR)$(logfiledir) -@@ -189,11 +191,13 @@ +@@ -189,11 +196,13 @@ @test -d $(DESTDIR)$(mandir) || $(MKINSTALLDIRS) $(DESTDIR)$(mandir) @test -d $(DESTDIR)$(mandir)/man1 || $(MKINSTALLDIRS) $(DESTDIR)$(mandir)/man1 @test -d $(DESTDIR)$(mandir)/man8 || $(MKINSTALLDIRS) $(DESTDIR)$(mandir)/man8 diff --git a/www/apache22/pkg-plist b/www/apache22/pkg-plist index d5c0504..116f685 100644 --- a/www/apache22/pkg-plist +++ b/www/apache22/pkg-plist @@ -1,19 +1,17 @@ @comment $FreeBSD$ -@unexec if cmp -s %D/etc/apache21/highperformance.conf %D/etc/apache21/highperformance-std.conf; then rm -f %D/etc/apache21/highperformance.conf; fi -etc/apache21/highperformance-std.conf -@exec [ -f %B/highperformance.conf ] || cp %B/%f %B/highperformance.conf -@unexec if cmp -s %D/etc/apache21/httpd.conf %D/etc/apache21/httpd-std.conf; then rm -f %D/etc/apache21/httpd.conf; fi -etc/apache21/httpd-std.conf -@exec [ -f %B/httpd.conf ] || cp %B/%f %B/httpd.conf -@unexec if cmp -s %D/etc/apache21/magic %D/etc/apache21/magic-dist; then rm -f %D/etc/apache21/magic; fi -etc/apache21/magic-dist -@exec [ -f %B/magic ] || cp %B/%f %B/magic -@unexec if cmp -s %D/etc/apache21/mime.types %D/etc/apache21/mime.types-dist; then rm -f %D/etc/apache21/mime.types; fi -etc/apache21/mime.types-dist -@exec [ -f %B/mime.types ] || cp %B/%f %B/mime.types -@unexec if cmp -s %D/etc/apache21/ssl.conf %D/etc/apache21/ssl-std.conf; then rm -f %D/etc/apache21/ssl.conf; fi -etc/apache21/ssl-std.conf -@exec [ -f %B/ssl.conf ] || cp %B/%f %B/ssl.conf +@exec mkdir -p %D/etc/apache21 2> /dev/null +@unexec if cmp -s %D/etc/apache21/httpd.conf %D/%%EXAMPLESDIR%%/httpd-std.conf; then rm -f %D/etc/apache21/httpd.conf; fi +%%EXAMPLESDIR%%/httpd-std.conf +@exec [ -f %D/etc/apache21/httpd.conf ] || cp %D/%%EXAMPLESDIR%%/httpd-std.conf %D/etc/apache21/httpd.conf +@unexec if cmp -s %D/etc/apache21/magic %D/%%EXAMPLESDIR%%/magic-dist; then rm -f %D/etc/apache21/magic; fi +%%EXAMPLESDIR%%/magic-dist +@exec [ -f %D/etc/apache21/magic ] || cp %D/%%EXAMPLESDIR%%/magic-dist %D/etc/apache21/magic +@unexec if cmp -s %D/etc/apache21/mime.types %D/%%EXAMPLESDIR%%/mime.types-dist; then rm -f %D/etc/apache21/mime.types; fi +%%EXAMPLESDIR%%/mime.types-dist +@exec [ -f %D/etc/apache21/mime.types ] || cp %D/%%EXAMPLESDIR%%/mime.types-dist %D/etc/apache21/mime.types +@unexec if cmp -s %D/etc/apache21/ssl.conf %D/%%EXAMPLESDIR%%/ssl-std.conf; then rm -f %D/etc/apache21/ssl.conf; fi +%%EXAMPLESDIR%%/ssl-std.conf +@exec [ -f %D/etc/apache21/ssl.conf ] || cp %D/%%EXAMPLESDIR%%/ssl-std.conf %D/etc/apache21/ssl.conf etc/rc.d/apache21.sh include/apache21/ap_compat.h include/apache21/ap_config.h @@ -87,6 +85,8 @@ include/apache21/ap_release.h %%APR_PORTS%%include/apr-1/apu.h %%APR_PORTS%%include/apr-1/apu_version.h %%APR_PORTS%%include/apr-1/apu_want.h +%%EVENT%%include/apache21/pod.h +%%EVENT%%include/apache21/fdqueue.h %%WORKER%%include/apache21/fdqueue.h %%THREADPOOL%%include/apache21/pod.h include/apache21/http_config.h @@ -497,6 +497,7 @@ share/apache21/build/special.mk %%ERROR%%@dirrm www/error-dist %%WWWDATA%%@dirrm www/data-dist %%CGI%%@dirrm www/cgi-bin-dist +@dirrm %%EXAMPLESDIR%% @dirrm share/apache21/build @dirrm share/apache21 @unexec rmdir %D/libexec/apache21 2> /dev/null || true |