summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorrbb <rbb@13f79535-47bb-0310-9956-ffa450edef68>1999-08-17 15:59:33 +0000
committerrbb <rbb@13f79535-47bb-0310-9956-ffa450edef68>1999-08-17 15:59:33 +0000
commit6577c978ebc28f950f43591579674e045f3d2a67 (patch)
treea54b0555bf7862582241f3bc69c81ebf035948f8 /test
parent3171d4b484045e81ea8289845830823008b48ece (diff)
downloadlibapr-6577c978ebc28f950f43591579674e045f3d2a67.tar.gz
Initial revision
git-svn-id: http://svn.apache.org/repos/asf/apr/apr/trunk@59151 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'test')
-rw-r--r--test/.cvsignore1
-rw-r--r--test/Makefile.in127
-rw-r--r--test/ab_apr.c975
-rw-r--r--test/ab_apr.dsp90
-rw-r--r--test/abc.c28
-rw-r--r--test/client.c153
-rw-r--r--test/client.dsp90
-rw-r--r--test/htdigest.c280
-rw-r--r--test/htdigest.dsp90
-rw-r--r--test/htpasswd.c538
-rw-r--r--test/logresolve.c345
-rw-r--r--test/rotatelogs.c82
-rw-r--r--test/server.c198
-rw-r--r--test/server.dsp90
-rw-r--r--test/suexec.c565
-rw-r--r--test/test.dsw155
-rw-r--r--test/testarg.dsp90
-rw-r--r--test/testargs.c95
-rw-r--r--test/testfile.c324
-rw-r--r--test/testfile.dsp91
-rw-r--r--test/testproc.c163
-rw-r--r--test/testproc.dsp91
-rw-r--r--test/testproc.rbb148
-rw-r--r--test/testsig.c127
-rw-r--r--test/testsig.dsp90
-rw-r--r--test/testsock.c126
-rw-r--r--test/testsock.dsp91
-rw-r--r--test/testthread.c174
-rw-r--r--test/testthread.dsp92
-rw-r--r--test/testtime.c178
-rw-r--r--test/timetest.dsp91
31 files changed, 5778 insertions, 0 deletions
diff --git a/test/.cvsignore b/test/.cvsignore
new file mode 100644
index 000000000..f3c7a7c5d
--- /dev/null
+++ b/test/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/test/Makefile.in b/test/Makefile.in
new file mode 100644
index 000000000..2c6a35381
--- /dev/null
+++ b/test/Makefile.in
@@ -0,0 +1,127 @@
+# 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../network_io -lnetwork -L../threadproc -lthreadproc -L../file_io -lfile -L../misc -lmisc -L../lib -lapr -L../time -ltime -L../locks -llock -L../signal -lsig -lcrypt @LIBS@
+LDFLAGS=@LDFLAGS@ $(LIBS)
+INCDIR=../include
+INCDIR1=../../inc
+INCLUDES=-I$(INCDIR) -I$(INCDIR1)
+
+TARGETS= testfile@EXEEXT@ \
+ testproc@EXEEXT@ \
+ testsock@EXEEXT@ \
+ testthread@EXEEXT@ \
+ testtime@EXEEXT@ \
+ testsig@EXEEXT@ \
+ testargs@EXEEXT@ \
+ ab@EXEEXT@ \
+ htdigest@EXEEXT@
+
+OBJS= testfile.o \
+ testproc.o \
+ testsock.o \
+ testthread.o \
+ testtime.o \
+ testsig.o \
+ testargs.o \
+ ab_apr.o \
+ htdigest.o
+
+.c.o:
+ $(CC) -c $(CFLAGS) $(INCLUDES) $<
+
+all: $(TARGETS)
+
+testfile@EXEEXT@: testfile.o
+ $(CC) $(CFLAGS) testfile.o -o testfile@EXEEXT@ $(LDFLAGS)
+
+testargs@EXEEXT@: testargs.o
+ $(CC) $(CFLAGS) testargs.o -o testargs@EXEEXT@ $(LDFLAGS)
+
+ab@EXEEXT@: ab_apr.o
+ $(CC) $(CFLAGS) ab_apr.o -o ab@EXEEXT@ $(LDFLAGS)
+
+htdigest@EXEEXT@: htdigest.o
+ $(CC) $(CFLAGS) htdigest.o -o htdigest@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)
+
+testsig@EXEEXT@: testsig.o
+ $(CC) $(CFLAGS) testsig.o -o testsig@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
+
+# DO NOT REMOVE
+ab_apr.o: ab_apr.c ../include/apr_network_io.h \
+ ../include/apr_general.h $(INCDIR)/apr_config.h \
+ ../include/apr_errno.h ../include/apr_file_io.h
+client.o: client.c ../include/apr_network_io.h \
+ ../include/apr_general.h $(INCDIR)/apr_config.h \
+ ../include/apr_errno.h
+server.o: server.c ../include/apr_network_io.h \
+ ../include/apr_general.h $(INCDIR)/apr_config.h \
+ ../include/apr_errno.h
+testargs.o: testargs.c ../include/apr_file_io.h \
+ ../include/apr_general.h $(INCDIR)/apr_config.h \
+ ../include/apr_errno.h $(INCDIR)/apr_lib.h $(INCDIR)/hsregex.h
+testfile.o: testfile.c ../include/apr_file_io.h \
+ ../include/apr_general.h $(INCDIR)/apr_config.h \
+ ../include/apr_errno.h $(INCDIR)/apr_lib.h $(INCDIR)/hsregex.h
+testproc.o: testproc.c ../include/apr_thread_proc.h \
+ ../include/apr_file_io.h ../include/apr_general.h \
+ $(INCDIR)/apr_config.h ../include/apr_errno.h \
+ $(INCDIR)/apr_win.h $(INCDIR)/apr_lib.h $(INCDIR)/hsregex.h
+testsig.o: testsig.c ../include/apr_thread_proc.h \
+ ../include/apr_file_io.h ../include/apr_general.h \
+ $(INCDIR)/apr_config.h ../include/apr_errno.h \
+ $(INCDIR)/apr_win.h $(INCDIR)/apr_lib.h $(INCDIR)/hsregex.h
+testsock.o: testsock.c ../include/apr_thread_proc.h \
+ ../include/apr_file_io.h ../include/apr_general.h \
+ $(INCDIR)/apr_config.h ../include/apr_errno.h \
+ $(INCDIR)/apr_win.h $(INCDIR)/apr_lib.h $(INCDIR)/hsregex.h
+testthread.o: testthread.c ../include/apr_thread_proc.h \
+ ../include/apr_file_io.h ../include/apr_general.h \
+ $(INCDIR)/apr_config.h ../include/apr_errno.h \
+ $(INCDIR)/apr_win.h ../include/apr_lock.h
+testtime.o: testtime.c ../include/apr_time.h \
+ ../include/apr_general.h $(INCDIR)/apr_config.h \
+ ../include/apr_errno.h
diff --git a/test/ab_apr.c b/test/ab_apr.c
new file mode 100644
index 000000000..d3357b7fe
--- /dev/null
+++ b/test/ab_apr.c
@@ -0,0 +1,975 @@
+/* ====================================================================
+ * Copyright (c) 1998-1999 The Apache Group. 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 Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * 4. The names "Apache Server" and "Apache Group" 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 Group.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the Apache Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``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 GROUP 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 Group and was originally based
+ * on public domain software written at the National Center for
+ * Supercomputing Applications, University of Illinois, Urbana-Champaign.
+ * For more information on the Apache Group and the Apache HTTP server
+ * project, please see <http://www.apache.org/>.
+ *
+ */
+
+/*
+ ** This program is based on ZeusBench V1.0 written by Adam Twiss
+ ** which is Copyright (c) 1996 by Zeus Technology Ltd. http://www.zeustech.net/
+ **
+ ** This software is provided "as is" and any express or implied waranties,
+ ** including but not limited to, the implied warranties of merchantability and
+ ** fitness for a particular purpose are disclaimed. In no event shall
+ ** Zeus Technology Ltd. be liable for any direct, indirect, incidental, special,
+ ** exemplary, or consequential damaged (including, but not limited to,
+ ** procurement of substitute good or services; loss of use, data, or profits;
+ ** or business interruption) however caused and on 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.
+ **
+ */
+
+/*
+ ** HISTORY:
+ ** - Originally written by Adam Twiss <adam@zeus.co.uk>, March 1996
+ ** with input from Mike Belshe <mbelshe@netscape.com> and
+ ** Michael Campanella <campanella@stevms.enet.dec.com>
+ ** - Enhanced by Dean Gaudet <dgaudet@apache.org>, November 1997
+ ** - Cleaned up by Ralf S. Engelschall <rse@apache.org>, March 1998
+ ** - POST and verbosity by Kurt Sussman <kls@merlot.com>, August 1998
+ ** - HTML table output added by David N. Welton <davidw@prosa.it>, January 1999
+ **
+ */
+
+/*
+ * BUGS:
+ *
+ * - uses strcpy/etc.
+ * - has various other poor buffer attacks related to the lazy parsing of
+ * response headers from the server
+ * - doesn't implement much of HTTP/1.x, only accepts certain forms of
+ * responses
+ * - (performance problem) heavy use of strstr shows up top in profile
+ * only an issue for loopback usage
+ */
+
+#define VERSION "1.3"
+
+/* -------------------------------------------------------------------- */
+
+/* affects include files on Solaris */
+#define BSD_COMP
+
+#include "apr_network_io.h"
+#include "apr_file_io.h"
+#include "apr_time.h"
+#include <string.h>
+#include <stdio.h>
+
+/* ------------------- DEFINITIONS -------------------------- */
+/* maximum number of requests on a time limited test */
+#define MAX_REQUESTS 50000
+
+/* good old state hostname */
+#define STATE_UNCONNECTED 0
+#define STATE_CONNECTING 1
+#define STATE_READ 2
+
+#define CBUFFSIZE 512
+
+struct connection {
+ ap_socket_t *aprsock;
+ int state;
+ int read; /* amount of bytes read */
+ int bread; /* amount of body read */
+ int length; /* Content-Length value used for keep-alive */
+ char cbuff[CBUFFSIZE]; /* a buffer to store server response header */
+ int cbx; /* offset in cbuffer */
+ int keepalive; /* non-zero if a keep-alive request */
+ int gotheader; /* non-zero if we have the entire header in cbuff */
+ ap_time_t *start, *connect, *done;
+ int socknum;
+};
+
+struct data {
+ int read; /* number of bytes read */
+ int ctime; /* time in ms to connect */
+ int time; /* time in ms for connection */
+};
+
+#define ap_min(a,b) ((a)<(b))?(a):(b)
+#define ap_max(a,b) ((a)>(b))?(a):(b)
+
+/* --------------------- GLOBALS ---------------------------- */
+API_VAR_IMPORT char *optarg; /* argument associated with option */
+API_VAR_IMPORT int optind;
+
+int verbosity = 0; /* no verbosity by default */
+int posting = 0; /* GET by default */
+int requests = 1; /* Number of requests to make */
+int concurrency = 1; /* Number of multiple requests to make */
+int tlimit = 0; /* time limit in cs */
+int keepalive = 0; /* try and do keepalive connections */
+char servername[1024]; /* name that server reports */
+char hostname[1024]; /* host name */
+char path[1024]; /* path name */
+char postfile[1024]; /* name of file containing post data */
+char *postdata; /* *buffer containing data from postfile */
+ap_ssize_t postlen = 0; /* length of data to be POSTed */
+char content_type[1024]; /* content type to put in POST header */
+int port = 80; /* port number */
+time_t aprtimeout = 30000; /* timeout value... */
+
+int use_html = 0; /* use html in the report */
+char *tablestring;
+char *trstring;
+char *tdstring;
+
+int doclen = 0; /* the length the document should be */
+int totalread = 0; /* total number of bytes read */
+int totalbread = 0; /* totoal amount of entity body read */
+int totalposted = 0; /* total number of bytes posted, inc. headers */
+int done = 0; /* number of requests we have done */
+int doneka = 0; /* number of keep alive connections done */
+int good = 0, bad = 0; /* number of good and bad requests */
+
+/* store error cases */
+int err_length = 0, err_conn = 0, err_except = 0;
+int err_response = 0;
+
+ap_time_t *start, *endtime;
+
+/* global request (and its length) */
+char request[512];
+ap_ssize_t reqlen;
+
+/* one global throw-away buffer to read stuff into */
+char buffer[8192];
+
+struct connection *con; /* connection array */
+struct data *stats; /* date for each request */
+ap_context_t *cntxt;
+
+ap_pollfd_t *readbits;
+
+/* --------------------------------------------------------- */
+
+/* simple little function to perror and exit */
+
+static void err(char *s)
+{
+ if (errno) {
+ perror(s);
+ }
+ else {
+ printf("%s", s);
+ }
+ exit(errno);
+}
+
+/* --------------------------------------------------------- */
+
+/* write out request to a connection - assumes we can write
+ (small) request out in one go into our new socket buffer */
+
+static void write_request(struct connection *c)
+{
+ ap_ssize_t len = reqlen;
+ ap_current_time(c->connect);
+ if (ap_send(c->aprsock, request, &reqlen, 30) != APR_SUCCESS &&
+ reqlen != len) {
+ printf("Send request failed!\n");
+ }
+ if (posting) {
+ ap_send(c->aprsock, postdata, &postlen, 30);
+ totalposted += (reqlen + postlen);
+ }
+
+ c->state = STATE_READ;
+ ap_add_poll_socket(readbits, c->aprsock, APR_POLLIN);
+ ap_remove_poll_socket(readbits, c->aprsock, APR_POLLOUT);
+}
+
+ /* --------------------------------------------------------- */
+
+ /* calculate and output results */
+
+static void output_results(void)
+{
+ int timetaken;
+
+ ap_current_time(endtime);
+ ap_timediff(endtime, start, &timetaken);
+
+ printf("\r \r");
+ printf("Server Software: %s\n", servername);
+ printf("Server Hostname: %s\n", hostname);
+ printf("Server Port: %d\n", port);
+ printf("\n");
+ printf("Document Path: %s\n", path);
+ printf("Document Length: %d bytes\n", doclen);
+ printf("\n");
+ printf("Concurrency Level: %d\n", concurrency);
+ printf("Time taken for tests: %d.%03d seconds\n",
+ timetaken / 1000, timetaken % 1000);
+ printf("Complete requests: %d\n", done);
+ printf("Failed requests: %d\n", bad);
+ if (bad)
+ printf(" (Connect: %d, Length: %d, Exceptions: %d)\n",
+ err_conn, err_length, err_except);
+ if (err_response)
+ printf("Non-2xx responses: %d\n", err_response);
+ if (keepalive)
+ printf("Keep-Alive requests: %d\n", doneka);
+ printf("Total transferred: %d bytes\n", totalread);
+ if (posting)
+ printf("Total POSTed: %d\n", totalposted);
+ printf("HTML transferred: %d bytes\n", totalbread);
+
+ /* avoid divide by zero */
+ if (timetaken) {
+ printf("Requests per second: %.2f\n", 1000 * (float) (done) / timetaken);
+ printf("Transfer rate: %.2f kb/s received\n",
+ (float) (totalread) / timetaken);
+ if (posting) {
+ printf(" %.2f kb/s sent\n",
+ (float) (totalposted) / timetaken);
+ printf(" %.2f kb/s total\n",
+ (float) (totalread + totalposted) / timetaken);
+ }
+ }
+
+ {
+ /* work out connection times */
+ int i;
+ int totalcon = 0, total = 0;
+ int mincon = 9999999, mintot = 999999;
+ int maxcon = 0, maxtot = 0;
+
+ for (i = 0; i < requests; i++) {
+ struct data s = stats[i];
+ mincon = ap_min(mincon, s.ctime);
+ mintot = ap_min(mintot, s.time);
+ maxcon = ap_max(maxcon, s.ctime);
+ maxtot = ap_max(maxtot, s.time);
+ totalcon += s.ctime;
+ total += s.time;
+ }
+ printf("\nConnnection Times (ms)\n");
+ printf(" min avg max\n");
+ printf("Connect: %5d %5d %5d\n", mincon, totalcon / requests, maxcon);
+ printf("Processing: %5d %5d %5d\n",
+ mintot - mincon, (total / requests) - (totalcon / requests),
+ maxtot - maxcon);
+ printf("Total: %5d %5d %5d\n", mintot, total / requests, maxtot);
+ }
+}
+
+ /* --------------------------------------------------------- */
+
+ /* calculate and output results in HTML */
+
+static void output_html_results(void)
+{
+ int timetaken;
+
+ ap_current_time(endtime);
+ ap_timediff(endtime, start, &timetaken);
+
+ printf("\n\n<table %s>\n", tablestring);
+ printf("<tr %s><th colspan=2 %s>Server Software:</th>"
+ "<td colspan=2 %s>%s</td></tr>\n",
+ trstring, tdstring, tdstring, servername);
+ printf("<tr %s><th colspan=2 %s>Server Hostname:</th>"
+ "<td colspan=2 %s>%s</td></tr>\n",
+ trstring, tdstring, tdstring, hostname);
+ printf("<tr %s><th colspan=2 %s>Server Port:</th>"
+ "<td colspan=2 %s>%d</td></tr>\n",
+ trstring, tdstring, tdstring, port);
+ printf("<tr %s><th colspan=2 %s>Document Path:</th>"
+ "<td colspan=2 %s>%s</td></tr>\n",
+ trstring, tdstring, tdstring, path);
+ printf("<tr %s><th colspan=2 %s>Document Length:</th>"
+ "<td colspan=2 %s>%d bytes</td></tr>\n",
+ trstring, tdstring, tdstring, doclen);
+ printf("<tr %s><th colspan=2 %s>Concurrency Level:</th>"
+ "<td colspan=2 %s>%d</td></tr>\n",
+ trstring, tdstring, tdstring, concurrency);
+ printf("<tr %s><th colspan=2 %s>Time taken for tests:</th>"
+ "<td colspan=2 %s>%d.%03d seconds</td></tr>\n",
+ trstring, tdstring, tdstring, timetaken / 1000, timetaken % 1000);
+ printf("<tr %s><th colspan=2 %s>Complete requests:</th>"
+ "<td colspan=2 %s>%d</td></tr>\n",
+ trstring, tdstring, tdstring, done);
+ printf("<tr %s><th colspan=2 %s>Failed requests:</th>"
+ "<td colspan=2 %s>%d</td></tr>\n",
+ trstring, tdstring, tdstring, bad);
+ if (bad)
+ printf("<tr %s><td colspan=4 %s > (Connect: %d, Length: %d, Exceptions: %d)</td></tr>\n",
+ trstring, tdstring, err_conn, err_length, err_except);
+ if (err_response)
+ printf("<tr %s><th colspan=2 %s>Non-2xx responses:</th>"
+ "<td colspan=2 %s>%d</td></tr>\n",
+ trstring, tdstring, tdstring, err_response);
+ if (keepalive)
+ printf("<tr %s><th colspan=2 %s>Keep-Alive requests:</th>"
+ "<td colspan=2 %s>%d</td></tr>\n",
+ trstring, tdstring, tdstring, doneka);
+ printf("<tr %s><th colspan=2 %s>Total transferred:</th>"
+ "<td colspan=2 %s>%d bytes</td></tr>\n",
+ trstring, tdstring, tdstring, totalread);
+ if (posting)
+ printf("<tr %s><th colspan=2 %s>Total POSTed:</th>"
+ "<td colspan=2 %s>%d</td></tr>\n",
+ trstring, tdstring, tdstring, totalposted);
+ printf("<tr %s><th colspan=2 %s>HTML transferred:</th>"
+ "<td colspan=2 %s>%d bytes</td></tr>\n",
+ trstring, tdstring, tdstring, totalbread);
+
+ /* avoid divide by zero */
+ if (timetaken) {
+ printf("<tr %s><th colspan=2 %s>Requests per second:</th>"
+ "<td colspan=2 %s>%.2f</td></tr>\n",
+ trstring, tdstring, tdstring, 1000 * (float) (done) / timetaken);
+ printf("<tr %s><th colspan=2 %s>Transfer rate:</th>"
+ "<td colspan=2 %s>%.2f kb/s received</td></tr>\n",
+ trstring, tdstring, tdstring, (float) (totalread) / timetaken);
+ if (posting) {
+ printf("<tr %s><td colspan=2 %s>&nbsp;</td>"
+ "<td colspan=2 %s>%.2f kb/s sent</td></tr>\n",
+ trstring, tdstring, tdstring,
+ (float) (totalposted) / timetaken);
+ printf("<tr %s><td colspan=2 %s>&nbsp;</td>"
+ "<td colspan=2 %s>%.2f kb/s total</td></tr>\n",
+ trstring, tdstring, tdstring,
+ (float) (totalread + totalposted) / timetaken);
+ }
+ }
+
+ {
+ /* work out connection times */
+ int i;
+ int totalcon = 0, total = 0;
+ int mincon = 9999999, mintot = 999999;
+ int maxcon = 0, maxtot = 0;
+
+ for (i = 0; i < requests; i++) {
+ struct data s = stats[i];
+ mincon = ap_min(mincon, s.ctime);
+ mintot = ap_min(mintot, s.time);
+ maxcon = ap_max(maxcon, s.ctime);
+ maxtot = ap_max(maxtot, s.time);
+ totalcon += s.ctime;
+ total += s.time;
+ }
+
+ printf("<tr %s><th %s colspan=4>Connnection Times (ms)</th></tr>\n",
+ trstring, tdstring);
+ printf("<tr %s><th %s>&nbsp;</th> <th %s>min</th> <th %s>avg</th> <th %s>max</th></tr>\n",
+ trstring, tdstring, tdstring, tdstring, tdstring);
+ printf("<tr %s><th %s>Connect:</th>"
+ "<td %s>%5d</td>"
+ "<td %s>%5d</td>"
+ "<td %s>%5d</td></tr>\n",
+ trstring, tdstring, tdstring, mincon, tdstring, totalcon / requests, tdstring, maxcon);
+ printf("<tr %s><th %s>Processing:</th>"
+ "<td %s>%5d</td>"
+ "<td %s>%5d</td>"
+ "<td %s>%5d</td></tr>\n",
+ trstring, tdstring, tdstring, mintot - mincon, tdstring,
+ (total / requests) - (totalcon / requests), tdstring, maxtot - maxcon);
+ printf("<tr %s><th %s>Total:</th>"
+ "<td %s>%5d</td>"
+ "<td %s>%5d</td>"
+ "<td %s>%5d</td></tr>\n",
+ trstring, tdstring, tdstring, mintot, tdstring, total / requests, tdstring, maxtot);
+ printf("</table>\n");
+ }
+}
+
+/* --------------------------------------------------------- */
+
+/* start asnchronous non-blocking connection */
+
+static void start_connect(struct connection *c)
+{
+ c->read = 0;
+ c->bread = 0;
+ c->keepalive = 0;
+ c->cbx = 0;
+ c->gotheader = 0;
+
+ if (ap_create_tcp_socket(cntxt, &c->aprsock) != APR_SUCCESS) {
+ err("Socket:");
+ }
+ if (ap_setport(c->aprsock, port) != APR_SUCCESS) {
+ err("Port:");
+ }
+ ap_current_time(c->start);
+ if (ap_connect(c->aprsock, hostname) != APR_SUCCESS) {
+ if (errno == APR_EINPROGRESS) {
+ c->state = STATE_CONNECTING;
+ ap_add_poll_socket(readbits, c->aprsock, APR_POLLOUT);
+ return;
+ }
+ else {
+ /* we don't have to close the socket. If we have an error this bad,
+ ap_connect will destroy it for us. */
+ err_conn++;
+ if (bad++ > 10) {
+ err("\nTest aborted after 10 failures\n\n");
+ }
+ start_connect(c);
+ }
+ }
+ /* connected first time */
+ write_request(c);
+}
+
+/* --------------------------------------------------------- */
+
+/* close down connection and save stats */
+
+static void close_connection(struct connection *c)
+{
+ if (c->read == 0 && c->keepalive) {
+ /* server has legitimately shut down an idle keep alive request */
+ good--; /* connection never happend */
+ }
+ else {
+ if (good == 1) {
+ /* first time here */
+ doclen = c->bread;
+ }
+ else if (c->bread != doclen) {
+ bad++;
+ err_length++;
+ }
+ /* save out time */
+ if (done < requests) {
+ struct data s;
+ ap_current_time(c->done);
+ s.read = c->read;
+ ap_timediff(c->connect, c->start, &s.ctime);
+ ap_timediff(c->done, c->start, &s.time);
+ stats[done++] = s;
+ }
+ }
+
+ ap_remove_poll_socket(readbits, c->aprsock, APR_POLLIN | APR_POLLOUT);
+ ap_close_socket(c->aprsock);
+
+ /* connect again */
+ start_connect(c);
+ return;
+}
+
+/* --------------------------------------------------------- */
+
+/* read data from connection */
+
+static void read_connection(struct connection *c)
+{
+ ap_ssize_t r;
+ char *part;
+ char respcode[4]; /* 3 digits and null */
+
+ r = sizeof(buffer);
+ ap_recv(c->aprsock, buffer, &r, aprtimeout);
+ if (r == 0 || (r < 0 && errno != EAGAIN)) {
+ good++;
+ close_connection(c);
+ return;
+ }
+
+ if (r < 0 && errno == EAGAIN)
+ return;
+
+ c->read += r;
+ totalread += r;
+
+ if (!c->gotheader) {
+ char *s;
+ int l = 4;
+ int space = CBUFFSIZE - c->cbx - 1; /* -1 to allow for 0 terminator */
+ int tocopy = (space < r) ? space : r;
+#ifndef CHARSET_EBCDIC
+ memcpy(c->cbuff + c->cbx, buffer, space);
+#else /*CHARSET_EBCDIC */
+ ascii2ebcdic(c->cbuff + c->cbx, buffer, space);
+#endif /*CHARSET_EBCDIC */
+ c->cbx += tocopy;
+ space -= tocopy;
+ c->cbuff[c->cbx] = 0; /* terminate for benefit of strstr */
+ if (verbosity >= 4) {
+ printf("LOG: header received:\n%s\n", c->cbuff);
+ }
+ s = strstr(c->cbuff, "\r\n\r\n");
+ /* this next line is so that we talk to NCSA 1.5 which blatantly breaks
+ the http specifaction */
+ if (!s) {
+ s = strstr(c->cbuff, "\n\n");
+ l = 2;
+ }
+
+ if (!s) {
+ /* read rest next time */
+ if (space) {
+ return;
+ }
+ else {
+ /* header is in invalid or too big - close connection */
+ ap_remove_poll_socket(readbits, c->aprsock, APR_POLLOUT);
+ ap_close_socket(c->aprsock);
+ if (bad++ > 10) {
+ err("\nTest aborted after 10 failures\n\n");
+ }
+ start_connect(c);
+ }
+ }
+ else {
+ /* have full header */
+ if (!good) {
+ /* this is first time, extract some interesting info */
+ char *p, *q;
+ p = strstr(c->cbuff, "Server:");
+ q = servername;
+ if (p) {
+ p += 8;
+ while (*p > 32)
+ *q++ = *p++;
+ }
+ *q = 0;
+ }
+
+ /* XXX: this parsing isn't even remotely HTTP compliant...
+ * but in the interest of speed it doesn't totally have to be,
+ * it just needs to be extended to handle whatever servers
+ * folks want to test against. -djg */
+
+ /* check response code */
+ part = strstr(c->cbuff, "HTTP"); /* really HTTP/1.x_ */
+ strncpy(respcode, (part + strlen("HTTP/1.x_")), 3);
+ respcode[3] = '\0';
+ if (respcode[0] != '2') {
+ err_response++;
+ if (verbosity >= 2)
+ printf("WARNING: Response code not 2xx (%s)\n", respcode);
+ }
+ else if (verbosity >= 3) {
+ printf("LOG: Response code = %s\n", respcode);
+ }
+
+ c->gotheader = 1;
+ *s = 0; /* terminate at end of header */
+ if (keepalive &&
+ (strstr(c->cbuff, "Keep-Alive")
+ || strstr(c->cbuff, "keep-alive"))) { /* for benefit of MSIIS */
+ char *cl;
+ cl = strstr(c->cbuff, "Content-Length:");
+ /* handle NCSA, which sends Content-length: */
+ if (!cl)
+ cl = strstr(c->cbuff, "Content-length:");
+ if (cl) {
+ c->keepalive = 1;
+ c->length = atoi(cl + 16);
+ }
+ }
+ c->bread += c->cbx - (s + l - c->cbuff) + r - tocopy;
+ totalbread += c->bread;
+ }
+ }
+ else {
+ /* outside header, everything we have read is entity body */
+ c->bread += r;
+ totalbread += r;
+ }
+
+ if (c->keepalive && (c->bread >= c->length)) {
+ /* finished a keep-alive connection */
+ good++;
+ doneka++;
+ /* save out time */
+ if (good == 1) {
+ /* first time here */
+ doclen = c->bread;
+ }
+ else if (c->bread != doclen) {
+ bad++;
+ err_length++;
+ }
+ if (done < requests) {
+ struct data s;
+ ap_current_time(c->done);
+ s.read = c->read;
+ ap_timediff(c->connect, c->start, &s.ctime);
+ ap_timediff(c->done, c->start, &s.time);
+ stats[done++] = s;
+ }
+ c->keepalive = 0;
+ c->length = 0;
+ c->gotheader = 0;
+ c->cbx = 0;
+ c->read = c->bread = 0;
+ write_request(c);
+ c->start = c->connect; /* zero connect time with keep-alive */
+ }
+}
+
+/* --------------------------------------------------------- */
+
+/* run the tests */
+
+static void test(void)
+{
+ ap_time_t *now;
+ time_t timeout;
+ ap_int16_t rv;
+ int i;
+
+ if (!use_html) {
+ printf("Benchmarking %s (be patient)...", hostname);
+ fflush(stdout);
+ }
+
+ ap_make_time(cntxt, &now);
+
+ con = (struct connection *)malloc(concurrency * sizeof(struct connection));
+ memset(con, 0, concurrency * sizeof(struct connection));
+
+ stats = (struct data *)malloc(requests * sizeof(struct data));
+ ap_setup_poll(cntxt, concurrency, &readbits);
+
+ for (i = 0; i < concurrency; i++) {
+ ap_make_time(cntxt, &con[i].start);
+ ap_make_time(cntxt, &con[i].connect);
+ ap_make_time(cntxt, &con[i].done);
+ }
+
+ /* setup request */
+ if (!posting) {
+ sprintf(request, "GET %s HTTP/1.0\r\n"
+ "User-Agent: ApacheBench/%s\r\n"
+ "%s"
+ "Host: %s\r\n"
+ "Accept: */*\r\n"
+ "\r\n",
+ path,
+ VERSION,
+ keepalive ? "Connection: Keep-Alive\r\n" : "",
+ hostname);
+ }
+ else {
+ sprintf(request, "POST %s HTTP/1.0\r\n"
+ "User-Agent: ApacheBench/%s\r\n"
+ "%s"
+ "Host: %s\r\n"
+ "Accept: */*\r\n"
+ "Content-length: %d\r\n"
+ "Content-type: %s\r\n"
+ "\r\n",
+ path,
+ VERSION,
+ keepalive ? "Connection: Keep-Alive\r\n" : "",
+ hostname, postlen,
+ (content_type[0]) ? content_type : "text/plain");
+ }
+
+ if (verbosity >= 2)
+ printf("INFO: POST header == \n---\n%s\n---\n", request);
+
+ reqlen = strlen(request);
+
+#ifdef CHARSET_EBCDIC
+ ebcdic2ascii(request, request, reqlen);
+#endif /*CHARSET_EBCDIC */
+
+ /* ok - lets start */
+ ap_current_time(start);
+
+ /* initialise lots of requests */
+ for (i = 0; i < concurrency; i++) {
+ con[i].socknum = i;
+ start_connect(&con[i]);
+ }
+
+ while (done < requests) {
+ ap_int32_t n;
+ ap_int32_t timed;
+
+ /* check for time limit expiry */
+ ap_current_time(now);
+ ap_timediff(now, start, &timed);
+ if (tlimit && timed > (tlimit * 1000)) {
+ requests = done; /* so stats are correct */
+ }
+ /* Timeout of 30 seconds. */
+ timeout = 30;
+
+ n = concurrency;
+ ap_poll(readbits, &n, timeout);
+
+ if (!n) {
+ err("\nServer timed out\n\n");
+ }
+ if (n < 1)
+ err("select");
+
+ for (i = 0; i < concurrency; i++) {
+ ap_get_revents(readbits, con[i].aprsock, &rv);
+ if ((rv & APR_POLLERR) || (rv & APR_POLLNVAL) || (rv & APR_POLLHUP)) {
+ bad++;
+ err_except++;
+ start_connect(&con[i]);
+ continue;
+ }
+ if ((rv & APR_POLLIN) || (rv & APR_POLLPRI))
+ read_connection(&con[i]);
+ if (rv & APR_POLLOUT)
+ write_request(&con[i]);
+ }
+ }
+ if (use_html)
+ output_html_results();
+ else
+ output_results();
+}
+
+/* ------------------------------------------------------- */
+
+/* display copyright information */
+static void copyright(void)
+{
+ if (!use_html) {
+ printf("This is ApacheBench, Version %s\n", VERSION);
+ printf("Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/\n");
+ printf("Copyright (c) 1998-1999 The Apache Group, http://www.apache.org/\n");
+ printf("\n");
+ }
+ else {
+ printf("<p>\n");
+ printf(" This is ApacheBench, Version %s<br>\n", VERSION);
+ printf(" Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/<br>\n");
+ printf(" Copyright (c) 1998-1999 The Apache Group, http://www.apache.org/<br>\n");
+ printf("</p>\n<p>\n");
+ }
+}
+
+/* display usage information */
+static void usage(char *progname)
+{
+ fprintf(stderr, "Usage: %s [options] [http://]hostname[:port]/path\n", progname);
+ fprintf(stderr, "Options are:\n");
+ fprintf(stderr, " -n requests Number of requests to perform\n");
+ fprintf(stderr, " -c concurrency Number of multiple requests to make\n");
+ fprintf(stderr, " -t timelimit Seconds to max. wait for responses\n");
+ fprintf(stderr, " -p postfile File containg data to POST\n");
+ fprintf(stderr, " -T content-type Content-type header for POSTing\n");
+ fprintf(stderr, " -v verbosity How much troubleshooting info to print\n");
+ fprintf(stderr, " -w Print out results in HTML tables\n");
+ fprintf(stderr, " -x attributes String to insert as table attributes\n");
+ fprintf(stderr, " -y attributes String to insert as tr attributes\n");
+ fprintf(stderr, " -z attributes String to insert as td or th attributes\n");
+ fprintf(stderr, " -V Print version number and exit\n");
+ fprintf(stderr, " -k Use HTTP KeepAlive feature\n");
+ fprintf(stderr, " -h Display usage information (this message)\n");
+ exit(EINVAL);
+}
+
+/* ------------------------------------------------------- */
+
+/* split URL into parts */
+
+static int parse_url(char *url)
+{
+ char *cp;
+ char *h;
+ char *p = NULL;
+
+ if (strlen(url) > 7 && strncmp(url, "http://", 7) == 0)
+ url += 7;
+ h = url;
+ if ((cp = strchr(url, ':')) != NULL) {
+ *cp++ = '\0';
+ p = cp;
+ url = cp;
+ }
+ if ((cp = strchr(url, '/')) == NULL)
+ return 1;
+ strcpy(path, cp);
+ *cp = '\0';
+ strcpy(hostname, h);
+ if (p != NULL)
+ port = atoi(p);
+ return 0;
+}
+
+/* ------------------------------------------------------- */
+
+/* read data to POST from file, save contents and length */
+
+static int open_postfile(char *pfile)
+{
+ ap_file_t *postfd = NULL;
+ ap_fileperms_t mode;
+ ap_ssize_t length;
+
+ if (ap_open(cntxt, pfile, APR_READ, mode, &postfd) != APR_SUCCESS) {
+ printf("Invalid postfile name (%s)\n", pfile);
+ return errno;
+ }
+
+ /* No need to perform stat here, the apr_open will do it for us. */
+
+ ap_get_filesize(postfd, &postlen);
+ postdata = (char *)malloc(postlen);
+ if (!postdata) {
+ printf("Can\'t alloc postfile buffer\n");
+ return ENOMEM;
+ }
+ length = postlen;
+ if (ap_read(postfd, postdata, &length) != APR_SUCCESS &&
+ length != postlen) {
+ printf("error reading postfilen");
+ return EIO;
+ }
+ return 0;
+}
+
+/* ------------------------------------------------------- */
+
+/* sort out command-line args and call test */
+int main(int argc, char **argv)
+{
+ int c, r;
+
+ /* table defaults */
+ tablestring = "";
+ trstring = "";
+ tdstring = "bgcolor=white";
+
+ ap_create_context(NULL, NULL, &cntxt);
+
+ ap_make_time(cntxt, &start);
+ ap_make_time(cntxt, &endtime);
+
+ optind = 1;
+ while (ap_getopt(cntxt, argc, argv, "n:c:t:T:p:v:kVhwx:y:z:", &c) == APR_SUCCESS) {
+ switch (c) {
+ case 'n':
+ requests = atoi(optarg);
+ if (!requests) {
+ err("Invalid number of requests\n");
+ }
+ break;
+ case 'k':
+ keepalive = 1;
+ break;
+ case 'c':
+ concurrency = atoi(optarg);
+ break;
+ case 'p':
+ if (0 == (r = open_postfile(optarg))) {
+ posting = 1;
+ }
+ else if (postdata) {
+ exit(r);
+ }
+ break;
+ case 'v':
+ verbosity = atoi(optarg);
+ break;
+ case 't':
+ tlimit = atoi(optarg);
+ requests = MAX_REQUESTS; /* need to size data array on something */
+ break;
+ case 'T':
+ strcpy(content_type, optarg);
+ break;
+ case 'V':
+ copyright();
+ exit(0);
+ break;
+ case 'w':
+ use_html = 1;
+ break;
+ /* if any of the following three are used, turn on html output automatically */
+ case 'x':
+ use_html = 1;
+ tablestring = optarg;
+ break;
+ case 'y':
+ use_html = 1;
+ trstring = optarg;
+ break;
+ case 'z':
+ use_html = 1;
+ tdstring = optarg;
+ break;
+ case 'h':
+ usage(argv[0]);
+ break;
+ default:
+ fprintf(stderr, "%s: invalid option `%c'\n", argv[0], c);
+ usage(argv[0]);
+ break;
+ }
+ }
+ if (optind != argc - 1) {
+ fprintf(stderr, "%s: wrong number of arguments\n", argv[0]);
+ usage(argv[0]);
+ }
+
+ if (parse_url(argv[optind++])) {
+ fprintf(stderr, "%s: invalid URL\n", argv[0]);
+ usage(argv[0]);
+ }
+
+ copyright();
+ test();
+
+ return(0);
+}
diff --git a/test/ab_apr.dsp b/test/ab_apr.dsp
new file mode 100644
index 000000000..a3071cbae
--- /dev/null
+++ b/test/ab_apr.dsp
@@ -0,0 +1,90 @@
+# 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 ..\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)" == "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 ..\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_apr\ab.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
new file mode 100644
index 000000000..43583ec52
--- /dev/null
+++ b/test/abc.c
@@ -0,0 +1,28 @@
+#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;
+ char ch;
+ int status = 0;
+ ap_context_t *context;
+
+ ap_create_context(NULL, NULL, &context);
+
+ ap_open(context, argv[1], APR_READ, -1, &fd);
+
+ while (!status) {
+ status = ap_getc(fd, &ch);
+ 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/client.c b/test/client.c
new file mode 100644
index 000000000..a8bf93c7e
--- /dev/null
+++ b/test/client.c
@@ -0,0 +1,153 @@
+/* ====================================================================
+ * Copyright (c) 1999 The Apache Group. 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 Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * 4. The names "Apache Server" and "Apache Group" 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 Group.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the Apache Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``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 GROUP 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 Group.
+ * For more information on the Apache Group and the Apache HTTP server
+ * project, please see <http://www.apache.org/>.
+ *
+ */
+
+#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_context_t *context;
+ ap_socket_t *sock;
+ ap_ssize_t length;
+ ap_status_t stat;
+ char datasend[STRLEN] = "Send data test";
+ char datarecv[STRLEN];
+
+ fprintf(stdout, "Creating context.......");
+ if (ap_create_context(NULL, NULL, &context) != 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(context, &sock) != APR_SUCCESS) {
+ fprintf(stderr, "Couldn't create socket\n");
+ exit(-1);
+ }
+ fprintf(stdout, "OK\n");
+
+ 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_setport(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, "127.0.0.1");
+} 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");
+
+ fprintf(stdout, "\tClient: Trying to send data over socket.......");
+ length = STRLEN;
+ if (ap_send(sock, datasend, &length, 5) != APR_SUCCESS) {
+ ap_close_socket(sock);
+ fprintf(stderr, "Problem sending data\n");
+ exit(-1);
+ }
+ fprintf(stdout, "OK\n");
+
+ length = STRLEN;
+ fprintf(stdout, "\tClient: Trying to receive data over socket.......");
+ if (ap_recv(sock, datarecv, &length, 5) != APR_SUCCESS) {
+ ap_close_socket(sock);
+ fprintf(stderr, "Problem receiving data\n");
+ 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;
+} \ No newline at end of file
diff --git a/test/client.dsp b/test/client.dsp
new file mode 100644
index 000000000..47f807aed
--- /dev/null
+++ b/test/client.dsp
@@ -0,0 +1,90 @@
+# 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 ..\network_io\win32\Debug\network_io.lib ..\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 ..\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)" == "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 ..\locks\win32\debug\locks.lib ..\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 "client - Win32 Release"
+# Name "client - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\client.c
+# End Source File
+# End Target
+# End Project
diff --git a/test/htdigest.c b/test/htdigest.c
new file mode 100644
index 000000000..528aa5c81
--- /dev/null
+++ b/test/htdigest.c
@@ -0,0 +1,280 @@
+/* ====================================================================
+ * Copyright (c) 1995-1999 The Apache Group. 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 Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * 4. The names "Apache Server" and "Apache Group" 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 Group.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the Apache Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``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 GROUP 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 Group and was originally based
+ * on public domain software written at the National Center for
+ * Supercomputing Applications, University of Illinois, Urbana-Champaign.
+ * For more information on the Apache Group and the Apache HTTP server
+ * project, please see <http://www.apache.org/>.
+ *
+ */
+/******************************************************************************
+ ******************************************************************************
+ * NOTE! This program is not safe as a setuid executable! Do not make it
+ * setuid!
+ ******************************************************************************
+ *****************************************************************************/
+/*
+ * htdigest.c: simple program for manipulating digest passwd file for Apache
+ *
+ * by Alexei Kosut, based on htpasswd.c, by Rob McCool
+ */
+
+#include "apr_lib.h"
+#include "apr_md5.h"
+#include <sys/types.h>
+#if defined(MPE) || defined(QNX) || defined(WIN32)
+#include <signal.h>
+#else
+#include <sys/signal.h>
+#endif
+
+#ifdef WIN32
+#include <conio.h>
+#endif
+
+#ifdef CHARSET_EBCDIC
+#define LF '\n'
+#define CR '\r'
+#else
+#define LF 10
+#define CR 13
+#endif /* CHARSET_EBCDIC */
+
+#define MAX_STRING_LEN 256
+
+char *tn;
+ap_context_t *cntxt;
+
+static void getword(char *word, char *line, char stop)
+{
+ int x = 0, y;
+
+ for (x = 0; ((line[x]) && (line[x] != stop)); x++)
+ word[x] = line[x];
+
+ word[x] = '\0';
+ if (line[x])
+ ++x;
+ y = 0;
+
+ while ((line[y++] = line[x++]));
+}
+
+static int getline(char *s, int n, ap_file_t *f)
+{
+ register int i = 0;
+ char ch;
+
+ while (1) {
+ ap_getc(f, &ch);
+ s[i] = ch;
+
+ if (s[i] == CR)
+ ap_getc(f, &ch);
+ s[i] = ch;
+
+ if ((s[i] == 0x4) || (s[i] == LF) || (i == (n - 1))) {
+ s[i] = '\0';
+ if (ap_eof(f) == APR_EOF) {
+ return 1;
+ }
+ return 0;
+ }
+ ++i;
+ }
+}
+
+static void putline(ap_file_t *f, char *l)
+{
+ int x;
+
+ for (x = 0; l[x]; x++)
+ ap_putc(f, l[x]);
+ ap_putc(f, '\n');
+}
+
+
+static void add_password(char *user, char *realm, ap_file_t *f)
+{
+ char *pw;
+ APR_MD5_CTX context;
+ unsigned char digest[16];
+ char string[MAX_STRING_LEN];
+ char pwin[MAX_STRING_LEN];
+ char pwv[MAX_STRING_LEN];
+ unsigned int i;
+ size_t len = sizeof(pwin);
+
+ if (ap_getpass("New password: ", pwin, &len) != APR_SUCCESS) {
+ fprintf(stderr, "password too long");
+ exit(5);
+ }
+ len = sizeof(pwin);
+ ap_getpass("Re-type new password: ", pwv, &len);
+ if (strcmp(pwin, pwv) != 0) {
+ fprintf(stderr, "They don't match, sorry.\n");
+ if (tn) {
+ ap_remove_file(cntxt, tn);
+ }
+ exit(1);
+ }
+ pw = pwin;
+ ap_fprintf(f, "%s:%s:", user, realm);
+
+ /* Do MD5 stuff */
+ sprintf(string, "%s:%s:%s", user, realm, pw);
+
+ apr_MD5Init(&context);
+ apr_MD5Update(&context, (unsigned char *) string, strlen(string));
+ apr_MD5Final(digest, &context);
+
+ for (i = 0; i < 16; i++)
+ ap_fprintf(f, "%02x", digest[i]);
+
+ ap_fprintf(f, "\n");
+}
+
+static void usage(void)
+{
+ fprintf(stderr, "Usage: htdigest [-c] passwordfile realm username\n");
+ fprintf(stderr, "The -c flag creates a new file.\n");
+ exit(1);
+}
+
+static void interrupted(void)
+{
+ fprintf(stderr, "Interrupted.\n");
+ if (tn)
+ ap_remove_file(cntxt, tn);
+ exit(1);
+}
+
+int main(int argc, char *argv[])
+{
+ ap_file_t *tfp, *f;
+ char user[MAX_STRING_LEN];
+ char realm[MAX_STRING_LEN];
+ char line[MAX_STRING_LEN];
+ char l[MAX_STRING_LEN];
+ char w[MAX_STRING_LEN];
+ char x[MAX_STRING_LEN];
+ char command[MAX_STRING_LEN];
+ int found;
+
+ ap_create_context(NULL, NULL, &cntxt);
+
+ tn = NULL;
+ signal(SIGINT, (void (*)(int)) interrupted);
+ if (argc == 5) {
+ if (strcmp(argv[1], "-c"))
+ usage();
+ if (ap_open(cntxt, argv[2], APR_WRITE | APR_CREATE, -1, &tfp) != APR_SUCCESS) {
+ fprintf(stderr, "Could not open passwd file %s for writing.\n",
+ argv[2]);
+ perror("ap_open");
+ exit(1);
+ }
+ printf("Adding password for %s in realm %s.\n", argv[4], argv[3]);
+ add_password(argv[4], argv[3], tfp);
+ ap_close(tfp);
+ exit(0);
+ }
+ else if (argc != 4)
+ usage();
+
+ tn = tmpnam(NULL);
+ if (ap_open(cntxt, tn, APR_WRITE | APR_CREATE, -1, &tfp)!= APR_SUCCESS) {
+ fprintf(stderr, "Could not open temp file.\n");
+ exit(1);
+ }
+
+ if (ap_open(cntxt, argv[1], APR_READ, -1, &f) != APR_SUCCESS) {
+ fprintf(stderr,
+ "Could not open passwd file %s for reading.\n", argv[1]);
+ fprintf(stderr, "Use -c option to create new one.\n");
+ exit(1);
+ }
+ strcpy(user, argv[3]);
+ strcpy(realm, argv[2]);
+
+ found = 0;
+ while (!(getline(line, MAX_STRING_LEN, f))) {
+ if (found || (line[0] == '#') || (!line[0])) {
+ putline(tfp, line);
+ continue;
+ }
+ strcpy(l, line);
+ getword(w, l, ':');
+ getword(x, l, ':');
+ if (strcmp(user, w) || strcmp(realm, x)) {
+ putline(tfp, line);
+ continue;
+ }
+ else {
+ printf("Changing password for user %s in realm %s\n", user, realm);
+ add_password(user, realm, tfp);
+ found = 1;
+ }
+ }
+ if (!found) {
+ printf("Adding user %s in realm %s\n", user, realm);
+ add_password(user, realm, tfp);
+ }
+ ap_close(f);
+ ap_close(tfp);
+#if defined(OS2) || defined(WIN32)
+ sprintf(command, "copy \"%s\" \"%s\"", tn, argv[1]);
+#else
+ sprintf(command, "cp %s %s", tn, argv[1]);
+#endif
+ system(command);
+ ap_remove_file(cntxt, tn);
+ return 0;
+}
diff --git a/test/htdigest.dsp b/test/htdigest.dsp
new file mode 100644
index 000000000..a0f8f0bf3
--- /dev/null
+++ b/test/htdigest.dsp
@@ -0,0 +1,90 @@
+# 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/htpasswd.c b/test/htpasswd.c
new file mode 100644
index 000000000..2c268ea55
--- /dev/null
+++ b/test/htpasswd.c
@@ -0,0 +1,538 @@
+/* ====================================================================
+ * Copyright (c) 1995-1999 The Apache Group. 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 Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * 4. The names "Apache Server" and "Apache Group" 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 Group.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the Apache Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``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 GROUP 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 Group and was originally based
+ * on public domain software written at the National Center for
+ * Supercomputing Applications, University of Illinois, Urbana-Champaign.
+ * For more information on the Apache Group and the Apache HTTP server
+ * project, please see <http://www.apache.org/>.
+ *
+ */
+
+/******************************************************************************
+ ******************************************************************************
+ * NOTE! This program is not safe as a setuid executable! Do not make it
+ * setuid!
+ ******************************************************************************
+ *****************************************************************************/
+/*
+ * htpasswd.c: simple program for manipulating password file for
+ * the Apache HTTP server
+ *
+ * Originally by Rob McCool
+ *
+ * Exit values:
+ * 0: Success
+ * 1: Failure; file access/permission problem
+ * 2: Failure; command line syntax problem (usage message issued)
+ * 3: Failure; password verification failure
+ * 4: Failure; operation interrupted (such as with CTRL/C)
+ * 5: Failure; buffer would overflow (username, filename, or computed
+ * record too long)
+ * 6: Failure; username contains illegal or reserved characters
+ */
+
+#include "apr_signal.h"
+#include "apr_errno.h"
+#include "apr_lib.h"
+#include <sys/types.h>
+#include <errno.h>
+
+#ifdef WIN32
+#include <conio.h>
+#include "../os/win32/getopt.h"
+#define unlink _unlink
+#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 ALG_CRYPT 1
+#define ALG_APMD5 2
+
+#define ERR_FILEPERM 1
+#define ERR_SYNTAX 2
+#define ERR_PWMISMATCH 3
+#define ERR_INTERRUPTED 4
+#define ERR_OVERFLOW 5
+#define ERR_BADUSER 6
+
+/*
+ * This needs to be declared statically so the signal handler can
+ * access it.
+ */
+static char *tempfilename;
+
+/*
+ * Get a line of input from the user, not including any terminating
+ * newline.
+ */
+static int getline(char *s, int n, FILE *f)
+{
+ register int i = 0;
+
+ while (1) {
+ s[i] = (char) fgetc(f);
+
+ if (s[i] == CR) {
+ s[i] = fgetc(f);
+ }
+
+ if ((s[i] == 0x4) || (s[i] == LF) || (i == (n - 1))) {
+ s[i] = '\0';
+ return (feof(f) ? 1 : 0);
+ }
+ ++i;
+ }
+}
+
+static void putline(FILE *f, char *l)
+{
+ int x;
+
+ for (x = 0; l[x]; x++) {
+ fputc(l[x], f);
+ }
+ fputc('\n', f);
+}
+
+
+/* From local_passwd.c (C) Regents of Univ. of California blah blah */
+static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */
+ "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+static void to64(register char *s, register long v, register int n)
+{
+ while (--n >= 0) {
+ *s++ = itoa64[v & 0x3f];
+ v >>= 6;
+ }
+}
+
+/*
+ * Make a password record from the given information. A zero return
+ * indicates success; failure means that the output buffer contains an
+ * error message instead.
+ */
+static int mkrecord(char *user, char *record, size_t rlen, char *passwd,
+ int alg)
+{
+ char *pw;
+ char cpw[120];
+ char salt[9];
+ char pwin[MAX_STRING_LEN];
+ char pwv[MAX_STRING_LEN];
+
+ if (passwd != NULL) {
+ pw = passwd;
+ }
+ else {
+ if (ap_getpass("New password: ", pwin, sizeof(pwin)) != 0) {
+ ap_snprintf(record, (rlen - 1), "password too long (>%d)",
+ sizeof(pwin) - 1);
+ return ERR_OVERFLOW;
+ }
+ ap_getpass("Re-type new password: ", pwv, sizeof(pwv));
+ if (strcmp(pwin, pwv) != 0) {
+ ap_cpystrn(record, "password verification error", (rlen - 1));
+ return ERR_PWMISMATCH;
+ }
+ pw = pwin;
+ }
+ (void) srand((int) time((time_t *) NULL));
+ to64(&salt[0], rand(), 8);
+ salt[8] = '\0';
+
+ switch (alg) {
+ case ALG_APMD5:
+ ap_MD5Encode((const unsigned char *)pw, (const unsigned char *)salt,
+ cpw, sizeof(cpw));
+ break;
+ case ALG_CRYPT:
+ ap_cpystrn(cpw, (char *)crypt(pw, salt), sizeof(cpw) - 1);
+ break;
+ }
+
+ /*
+ * Check to see if the buffer is large enough to hold the username,
+ * hash, and delimiters.
+ */
+ if ((strlen(user) + 1 + strlen(cpw)) > (rlen - 1)) {
+ ap_cpystrn(record, "resultant record too long", (rlen - 1));
+ return ERR_OVERFLOW;
+ }
+ strcpy(record, user);
+ strcat(record, ":");
+ strcat(record, cpw);
+ return 0;
+}
+
+static int usage(void)
+{
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, "\thtpasswd [-cm] passwordfile username\n");
+ fprintf(stderr, "\thtpasswd -b[cm] passwordfile username password\n\n");
+ fprintf(stderr, " -c Create a new file.\n");
+ fprintf(stderr, " -m Force MD5 encryption of the password.\n");
+ fprintf(stderr, " -b Use the password from the command line rather ");
+ fprintf(stderr, "than prompting for it.\n");
+ fprintf(stderr, "On Windows systems the -m flag is used by default.\n");
+ return ERR_SYNTAX;
+}
+
+static void interrupted(void)
+{
+ fprintf(stderr, "Interrupted.\n");
+ if (tempfilename != NULL) {
+ unlink(tempfilename);
+ }
+ exit(ERR_INTERRUPTED);
+}
+
+/*
+ * Check to see if the specified file can be opened for the given
+ * access.
+ */
+static int accessible(char *fname, char *mode)
+{
+ FILE *s;
+
+ s = fopen(fname, mode);
+ if (s == NULL) {
+ return 0;
+ }
+ fclose(s);
+ return 1;
+}
+
+/*
+ * Return true if a file is readable.
+ */
+static int readable(char *fname)
+{
+ return accessible(fname, "r");
+}
+
+/*
+ * Return true if the specified file can be opened for write access.
+ */
+static int writable(char *fname)
+{
+ return accessible(fname, "a");
+}
+
+/*
+ * Return true if the named file exists, regardless of permissions.
+ */
+static int exists(char *fname)
+{
+#ifdef WIN32
+ struct _stat sbuf;
+#else
+ struct stat sbuf;
+#endif
+ int check;
+
+#ifdef WIN32
+ check = _stat(fname, &sbuf);
+#else
+ check = stat(fname, &sbuf);
+#endif
+ return ((check == -1) && (errno == ENOENT)) ? 0 : 1;
+}
+
+/*
+ * Copy from the current position of one file to the current position
+ * of another.
+ */
+static void copy_file(FILE *target, FILE *source)
+{
+ static char line[MAX_STRING_LEN];
+
+ while (fgets(line, sizeof(line), source) != NULL) {
+ fputs(line, target);
+ }
+}
+
+/*
+ * Let's do it. We end up doing a lot of file opening and closing,
+ * but what do we care? This application isn't run constantly.
+ */
+int main(int argc, char *argv[])
+{
+ FILE *ftemp = NULL;
+ FILE *fpw = NULL;
+ char user[MAX_STRING_LEN];
+ char password[MAX_STRING_LEN];
+ char record[MAX_STRING_LEN];
+ char line[MAX_STRING_LEN];
+ char pwfilename[MAX_STRING_LEN];
+ char *arg;
+ int found = 0;
+ int alg = ALG_CRYPT;
+ int newfile = 0;
+ int noninteractive = 0;
+ int i;
+ int args_left = 2;
+
+ tempfilename = NULL;
+ signal(SIGINT, (void (*)(int)) interrupted);
+
+ /*
+ * Preliminary check to make sure they provided at least
+ * three arguments, we'll do better argument checking as
+ * we parse the command line.
+ */
+ if (argc < 3) {
+ return usage();
+ }
+
+ /*
+ * Go through the argument list and pick out any options. They
+ * have to precede any other arguments.
+ */
+ for (i = 1; i < argc; i++) {
+ arg = argv[i];
+ if (*arg != '-') {
+ break;
+ }
+ while (*++arg != '\0') {
+ if (*arg == 'c') {
+ newfile++;
+ }
+ else if (*arg == 'm') {
+ alg = ALG_APMD5;
+ }
+ else if (*arg == 'b') {
+ noninteractive++;
+ args_left++;
+ }
+ else {
+ return usage();
+ }
+ }
+ }
+
+ /*
+ * Make sure we still have exactly the right number of arguments left
+ * (the filename, the username, and possibly the password if -b was
+ * specified).
+ */
+ if ((argc - i) != args_left) {
+ return usage();
+ }
+ if (strlen(argv[i]) > (sizeof(pwfilename) - 1)) {
+ fprintf(stderr, "%s: filename too long\n", argv[0]);
+ return ERR_OVERFLOW;
+ }
+ strcpy(pwfilename, argv[i]);
+ if (strlen(argv[i + 1]) > (sizeof(user) - 1)) {
+ fprintf(stderr, "%s: username too long (>%d)\n", argv[0],
+ sizeof(user) - 1);
+ return ERR_OVERFLOW;
+ }
+ strcpy(user, argv[i + 1]);
+ if ((arg = strchr(user, ':')) != NULL) {
+ fprintf(stderr, "%s: username contains illegal character '%c'\n",
+ argv[0], *arg);
+ return ERR_BADUSER;
+ }
+ if (noninteractive) {
+ if (strlen(argv[i + 2]) > (sizeof(password) - 1)) {
+ fprintf(stderr, "%s: password too long (>%d)\n", argv[0],
+ sizeof(password) - 1);
+ return ERR_OVERFLOW;
+ }
+ strcpy(password, argv[i + 2]);
+ }
+
+#ifdef WIN32
+ if (alg == ALG_CRYPT) {
+ alg = ALG_APMD5;
+ fprintf(stderr, "Automatically using MD5 format on Windows.\n");
+ }
+#endif
+
+ /*
+ * Verify that the file exists if -c was omitted. We give a special
+ * message if it doesn't.
+ */
+ if ((! newfile) && (! exists(pwfilename))) {
+ fprintf(stderr, "%s: cannot modify file %s; use '-c' to create it\n",
+ argv[0], pwfilename);
+ perror("fopen");
+ exit(ERR_FILEPERM);
+ }
+ /*
+ * Verify that we can read the existing file in the case of an update
+ * to it (rather than creation of a new one).
+ */
+ if ((! newfile) && (! readable(pwfilename))) {
+ fprintf(stderr, "%s: cannot open file %s for read access\n",
+ argv[0], pwfilename);
+ perror("fopen");
+ exit(ERR_FILEPERM);
+ }
+ /*
+ * Now check to see if we can preserve an existing file in case
+ * of password verification errors on a -c operation.
+ */
+ if (newfile && exists(pwfilename) && (! readable(pwfilename))) {
+ fprintf(stderr, "%s: cannot open file %s for read access\n"
+ "%s: existing auth data would be lost on password mismatch",
+ argv[0], pwfilename, argv[0]);
+ perror("fopen");
+ exit(ERR_FILEPERM);
+ }
+ /*
+ * Now verify that the file is writable!
+ */
+ if (! writable(pwfilename)) {
+ fprintf(stderr, "%s: cannot open file %s for write access\n",
+ argv[0], pwfilename);
+ perror("fopen");
+ exit(ERR_FILEPERM);
+ }
+
+ /*
+ * All the file access checks have been made. Time to go to work;
+ * try to create the record for the username in question. If that
+ * fails, there's no need to waste any time on file manipulations.
+ * Any error message text is returned in the record buffer, since
+ * the mkrecord() routine doesn't have access to argv[].
+ */
+ i = mkrecord(user, record, sizeof(record) - 1,
+ noninteractive ? password : NULL,
+ alg);
+ if (i != 0) {
+ fprintf(stderr, "%s: %s\n", argv[0], record);
+ exit(i);
+ }
+
+ /*
+ * We can access the files the right way, and we have a record
+ * to add or update. Let's do it..
+ */
+ tempfilename = tmpnam(NULL);
+ ftemp = fopen(tempfilename, "w+");
+ if (ftemp == NULL) {
+ fprintf(stderr, "%s: unable to create temporary file\n", argv[0]);
+ perror("fopen");
+ exit(ERR_FILEPERM);
+ }
+ /*
+ * If we're not creating a new file, copy records from the existing
+ * one to the temporary file until we find the specified user.
+ */
+ if (! newfile) {
+ char scratch[MAX_STRING_LEN];
+
+ fpw = fopen(pwfilename, "r");
+ while (! (getline(line, sizeof(line), fpw))) {
+ char *colon;
+
+ if ((line[0] == '#') || (line[0] == '\0')) {
+ putline(ftemp, line);
+ continue;
+ }
+ strcpy(scratch, line);
+ /*
+ * See if this is our user.
+ */
+ colon = strchr(scratch, ':');
+ if (colon != NULL) {
+ *colon = '\0';
+ }
+ if (strcmp(user, scratch) != 0) {
+ putline(ftemp, line);
+ continue;
+ }
+ found++;
+ break;
+ }
+ }
+ if (found) {
+ fprintf(stderr, "Updating ");
+ }
+ else {
+ fprintf(stderr, "Adding ");
+ }
+ fprintf(stderr, "password for user %s\n", user);
+ /*
+ * Now add the user record we created.
+ */
+ putline(ftemp, record);
+ /*
+ * If we're updating an existing file, there may be additional
+ * records beyond the one we're updating, so copy them.
+ */
+ if (! newfile) {
+ copy_file(ftemp, fpw);
+ fclose(fpw);
+ }
+ /*
+ * The temporary file now contains the information that should be
+ * in the actual password file. Close the open files, re-open them
+ * in the appropriate mode, and copy them file to the real one.
+ */
+ fclose(ftemp);
+ fpw = fopen(pwfilename, "w+");
+ ftemp = fopen(tempfilename, "r");
+ copy_file(fpw, ftemp);
+ fclose(fpw);
+ fclose(ftemp);
+ unlink(tempfilename);
+ return 0;
+}
diff --git a/test/logresolve.c b/test/logresolve.c
new file mode 100644
index 000000000..bcdc6e51b
--- /dev/null
+++ b/test/logresolve.c
@@ -0,0 +1,345 @@
+/*
+ * logresolve 1.1
+ *
+ * Tom Rathborne - tomr@uunet.ca - http://www.uunet.ca/~tomr/
+ * UUNET Canada, April 16, 1995
+ *
+ * Rewritten by David Robinson. (drtr@ast.cam.ac.uk)
+ *
+ * Usage: logresolve [-s filename] [-c] < access_log > new_log
+ *
+ * Arguments:
+ * -s filename name of a file to record statistics
+ * -c check the DNS for a matching A record for the host.
+ *
+ * Notes:
+ *
+ * To generate meaningful statistics from an HTTPD log file, it's good
+ * to have the domain name of each machine that accessed your site, but
+ * doing this on the fly can slow HTTPD down.
+ *
+ * Compiling NCSA HTTPD with the -DMINIMAL_DNS flag turns IP#->hostname
+ * resolution off. Before running your stats program, just run your log
+ * file through this program (logresolve) and all of your IP numbers will
+ * be resolved into hostnames (where possible).
+ *
+ * logresolve takes an HTTPD access log (in the COMMON log file format,
+ * or any other format that has the IP number/domain name as the first
+ * field for that matter), and outputs the same file with all of the
+ * domain names looked up. Where no domain name can be found, the IP
+ * number is left in.
+ *
+ * To minimize impact on your nameserver, logresolve has its very own
+ * internal hash-table cache. This means that each IP number will only
+ * be looked up the first time it is found in the log file.
+ *
+ * The -c option causes logresolve to apply the same check as httpd
+ * compiled with -DMAXIMUM_DNS; after finding the hostname from the IP
+ * address, it looks up the IP addresses for the hostname and checks
+ * that one of these matches the original address.
+ */
+
+#include "ap_config.h"
+#include <sys/types.h>
+
+#include <ctype.h>
+
+#ifndef MPE
+#include <arpa/inet.h>
+#endif
+
+static void cgethost(struct in_addr ipnum, char *string, int check);
+static int getline(char *s, int n);
+static void stats(FILE *output);
+
+
+/* maximum line length */
+#define MAXLINE 1024
+
+/* maximum length of a domain name */
+#ifndef MAXDNAME
+#define MAXDNAME 256
+#endif
+
+/* number of buckets in cache hash table */
+#define BUCKETS 256
+
+#if defined(NEED_STRDUP)
+char *strdup (const char *str)
+{
+ char *dup;
+
+ if (!(dup = (char *) malloc(strlen(str) + 1)))
+ return NULL;
+ dup = strcpy(dup, str);
+
+ return dup;
+}
+#endif
+
+/*
+ * struct nsrec - record of nameservice for cache linked list
+ *
+ * ipnum - IP number hostname - hostname noname - nonzero if IP number has no
+ * hostname, i.e. hostname=IP number
+ */
+
+struct nsrec {
+ struct in_addr ipnum;
+ char *hostname;
+ int noname;
+ struct nsrec *next;
+} *nscache[BUCKETS];
+
+/*
+ * statistics - obvious
+ */
+
+#ifndef h_errno
+extern int h_errno; /* some machines don't have this in their headers */
+#endif
+
+/* largeste value for h_errno */
+#define MAX_ERR (NO_ADDRESS)
+#define UNKNOWN_ERR (MAX_ERR+1)
+#define NO_REVERSE (MAX_ERR+2)
+
+static int cachehits = 0;
+static int cachesize = 0;
+static int entries = 0;
+static int resolves = 0;
+static int withname = 0;
+static int errors[MAX_ERR + 3];
+
+/*
+ * cgethost - gets hostname by IP address, caching, and adding unresolvable
+ * IP numbers with their IP number as hostname, setting noname flag
+ */
+
+static void cgethost (struct in_addr ipnum, char *string, int check)
+{
+ struct nsrec **current, *new;
+ struct hostent *hostdata;
+ char *name;
+
+ current = &nscache[((ipnum.s_addr + (ipnum.s_addr >> 8) +
+ (ipnum.s_addr >> 16) + (ipnum.s_addr >> 24)) % BUCKETS)];
+
+ while (*current != NULL && ipnum.s_addr != (*current)->ipnum.s_addr)
+ current = &(*current)->next;
+
+ if (*current == NULL) {
+ cachesize++;
+ new = (struct nsrec *) malloc(sizeof(struct nsrec));
+ if (new == NULL) {
+ perror("malloc");
+ fprintf(stderr, "Insufficient memory\n");
+ exit(1);
+ }
+ *current = new;
+ new->next = NULL;
+
+ new->ipnum = ipnum;
+
+ hostdata = gethostbyaddr((const char *) &ipnum, sizeof(struct in_addr),
+ AF_INET);
+ if (hostdata == NULL) {
+ if (h_errno > MAX_ERR)
+ errors[UNKNOWN_ERR]++;
+ else
+ errors[h_errno]++;
+ new->noname = h_errno;
+ name = strdup(inet_ntoa(ipnum));
+ }
+ else {
+ new->noname = 0;
+ name = strdup(hostdata->h_name);
+ if (check) {
+ if (name == NULL) {
+ perror("strdup");
+ fprintf(stderr, "Insufficient memory\n");
+ exit(1);
+ }
+ hostdata = gethostbyname(name);
+ if (hostdata != NULL) {
+ char **hptr;
+
+ for (hptr = hostdata->h_addr_list; *hptr != NULL; hptr++)
+ if (((struct in_addr *) (*hptr))->s_addr == ipnum.s_addr)
+ break;
+ if (*hptr == NULL)
+ hostdata = NULL;
+ }
+ if (hostdata == NULL) {
+ fprintf(stderr, "Bad host: %s != %s\n", name,
+ inet_ntoa(ipnum));
+ new->noname = NO_REVERSE;
+ free(name);
+ name = strdup(inet_ntoa(ipnum));
+ errors[NO_REVERSE]++;
+ }
+ }
+ }
+ new->hostname = name;
+ if (new->hostname == NULL) {
+ perror("strdup");
+ fprintf(stderr, "Insufficient memory\n");
+ exit(1);
+ }
+ }
+ else
+ cachehits++;
+
+ /* size of string == MAXDNAME +1 */
+ strncpy(string, (*current)->hostname, MAXDNAME);
+ string[MAXDNAME] = '\0';
+}
+
+/*
+ * prints various statistics to output
+ */
+
+static void stats (FILE *output)
+{
+ int i;
+ char *ipstring;
+ struct nsrec *current;
+ char *errstring[MAX_ERR + 3];
+
+ for (i = 0; i < MAX_ERR + 3; i++)
+ errstring[i] = "Unknown error";
+ errstring[HOST_NOT_FOUND] = "Host not found";
+ errstring[TRY_AGAIN] = "Try again";
+ errstring[NO_RECOVERY] = "Non recoverable error";
+ errstring[NO_DATA] = "No data record";
+ errstring[NO_ADDRESS] = "No address";
+ errstring[NO_REVERSE] = "No reverse entry";
+
+ fprintf(output, "logresolve Statistics:\n");
+
+ fprintf(output, "Entries: %d\n", entries);
+ fprintf(output, " With name : %d\n", withname);
+ fprintf(output, " Resolves : %d\n", resolves);
+ if (errors[HOST_NOT_FOUND])
+ fprintf(output, " - Not found : %d\n", errors[HOST_NOT_FOUND]);
+ if (errors[TRY_AGAIN])
+ fprintf(output, " - Try again : %d\n", errors[TRY_AGAIN]);
+ if (errors[NO_DATA])
+ fprintf(output, " - No data : %d\n", errors[NO_DATA]);
+ if (errors[NO_ADDRESS])
+ fprintf(output, " - No address: %d\n", errors[NO_ADDRESS]);
+ if (errors[NO_REVERSE])
+ fprintf(output, " - No reverse: %d\n", errors[NO_REVERSE]);
+ fprintf(output, "Cache hits : %d\n", cachehits);
+ fprintf(output, "Cache size : %d\n", cachesize);
+ fprintf(output, "Cache buckets : IP number * hostname\n");
+
+ for (i = 0; i < BUCKETS; i++)
+ for (current = nscache[i]; current != NULL; current = current->next) {
+ ipstring = inet_ntoa(current->ipnum);
+ if (current->noname == 0)
+ fprintf(output, " %3d %15s - %s\n", i, ipstring,
+ current->hostname);
+ else {
+ if (current->noname > MAX_ERR + 2)
+ fprintf(output, " %3d %15s : Unknown error\n", i,
+ ipstring);
+ else
+ fprintf(output, " %3d %15s : %s\n", i, ipstring,
+ errstring[current->noname]);
+ }
+ }
+}
+
+
+/*
+ * gets a line from stdin
+ */
+
+static int getline (char *s, int n)
+{
+ char *cp;
+
+ if (!fgets(s, n, stdin))
+ return (0);
+ cp = strchr(s, '\n');
+ if (cp)
+ *cp = '\0';
+ return (1);
+}
+
+int main (int argc, char *argv[])
+{
+ struct in_addr ipnum;
+ char *bar, hoststring[MAXDNAME + 1], line[MAXLINE], *statfile;
+ int i, check;
+
+ check = 0;
+ statfile = NULL;
+ for (i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-c") == 0)
+ check = 1;
+ else if (strcmp(argv[i], "-s") == 0) {
+ if (i == argc - 1) {
+ fprintf(stderr, "logresolve: missing filename to -s\n");
+ exit(1);
+ }
+ i++;
+ statfile = argv[i];
+ }
+ else {
+ fprintf(stderr, "Usage: logresolve [-s statfile] [-c] < input > output\n");
+ exit(0);
+ }
+ }
+
+
+ for (i = 0; i < BUCKETS; i++)
+ nscache[i] = NULL;
+ for (i = 0; i < MAX_ERR + 2; i++)
+ errors[i] = 0;
+
+ while (getline(line, MAXLINE)) {
+ if (line[0] == '\0')
+ continue;
+ entries++;
+ if (!isdigit(line[0])) { /* short cut */
+ puts(line);
+ withname++;
+ continue;
+ }
+ bar = strchr(line, ' ');
+ if (bar != NULL)
+ *bar = '\0';
+ ipnum.s_addr = inet_addr(line);
+ if (ipnum.s_addr == 0xffffffffu) {
+ if (bar != NULL)
+ *bar = ' ';
+ puts(line);
+ withname++;
+ continue;
+ }
+
+ resolves++;
+
+ cgethost(ipnum, hoststring, check);
+ if (bar != NULL)
+ printf("%s %s\n", hoststring, bar + 1);
+ else
+ puts(hoststring);
+ }
+
+ if (statfile != NULL) {
+ FILE *fp;
+ fp = fopen(statfile, "w");
+ if (fp == NULL) {
+ fprintf(stderr, "logresolve: could not open statistics file '%s'\n"
+ ,statfile);
+ exit(1);
+ }
+ stats(fp);
+ fclose(fp);
+ }
+
+ return (0);
+}
diff --git a/test/rotatelogs.c b/test/rotatelogs.c
new file mode 100644
index 000000000..dc6bd9772
--- /dev/null
+++ b/test/rotatelogs.c
@@ -0,0 +1,82 @@
+/*
+ * Simple program to rotate Apache logs without having to kill the server.
+ *
+ * Contributed by Ben Laurie <ben@algroup.co.uk>
+ *
+ * 12 Mar 1996
+ */
+
+
+#define BUFSIZE 65536
+#define MAX_PATH 1024
+
+#include "ap_config.h"
+#include <time.h>
+#include <errno.h>
+#include <fcntl.h>
+
+int main (int argc, char **argv)
+{
+ char buf[BUFSIZE], buf2[MAX_PATH];
+ time_t tLogEnd = 0;
+ time_t tRotation;
+ int nLogFD = -1;
+ int nRead;
+ char *szLogRoot;
+
+ if (argc != 3) {
+ fprintf(stderr,
+ "%s <logfile> <rotation time in seconds>\n\n",
+ argv[0]);
+#ifdef OS2
+ fprintf(stderr,
+ "Add this:\n\nTransferLog \"|%s.exe /some/where 86400\"\n\n",
+ argv[0]);
+#else
+ fprintf(stderr,
+ "Add this:\n\nTransferLog \"|%s /some/where 86400\"\n\n",
+ argv[0]);
+#endif
+ fprintf(stderr,
+ "to httpd.conf. The generated name will be /some/where.nnnn "
+ "where nnnn is the\nsystem time at which the log nominally "
+ "starts (N.B. this time will always be a\nmultiple of the "
+ "rotation time, so you can synchronize cron scripts with it).\n"
+ "At the end of each rotation time a new log is started.\n");
+ exit(1);
+ }
+
+ szLogRoot = argv[1];
+ tRotation = atoi(argv[2]);
+ if (tRotation <= 0) {
+ fprintf(stderr, "Rotation time must be > 0\n");
+ exit(6);
+ }
+
+ for (;;) {
+ nRead = read(0, buf, sizeof buf);
+ if (nRead == 0)
+ exit(3);
+ if (nRead < 0)
+ if (errno != EINTR)
+ exit(4);
+ if (nLogFD >= 0 && (time(NULL) >= tLogEnd || nRead < 0)) {
+ close(nLogFD);
+ nLogFD = -1;
+ }
+ if (nLogFD < 0) {
+ time_t tLogStart = (time(NULL) / tRotation) * tRotation;
+ sprintf(buf2, "%s.%010d", szLogRoot, (int) tLogStart);
+ tLogEnd = tLogStart + tRotation;
+ nLogFD = open(buf2, O_WRONLY | O_CREAT | O_APPEND, 0666);
+ if (nLogFD < 0) {
+ perror(buf2);
+ exit(2);
+ }
+ }
+ if (write(nLogFD, buf, nRead) != nRead) {
+ perror(buf2);
+ exit(5);
+ }
+ }
+}
diff --git a/test/server.c b/test/server.c
new file mode 100644
index 000000000..79eac9125
--- /dev/null
+++ b/test/server.c
@@ -0,0 +1,198 @@
+/* ====================================================================
+ * Copyright (c) 1999 The Apache Group. 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 Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * 4. The names "Apache Server" and "Apache Group" 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 Group.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the Apache Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``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 GROUP 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 Group.
+ * For more information on the Apache Group and the Apache HTTP server
+ * project, please see <http://www.apache.org/>.
+ *
+ */
+
+#include "apr_network_io.h"
+#include "apr_errno.h"
+#include "apr_general.h"
+
+#define STRLEN 15
+
+int main(int argc, char *argv[])
+{
+ ap_context_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";
+
+ fprintf(stdout, "Creating context.......");
+ if (ap_create_context(NULL, NULL, &context) != 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(context, &sock) != 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_setport(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(context, 1, &sdset);
+ 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(sock, &sock2) != APR_SUCCESS) {
+ ap_close_socket(sock);
+ fprintf(stderr, "Could not accept connection.\n");
+ exit(-1);
+ }
+ fprintf(stdout, "OK\n");
+
+ length = STRLEN;
+ fprintf(stdout, "\tServer: Trying to recv data from socket.......");
+ if (ap_recv(sock2, datasend, &length, 5) != 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, 5) != 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
new file mode 100644
index 000000000..dda23de75
--- /dev/null
+++ b/test/server.dsp
@@ -0,0 +1,90 @@
+# 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 ..\network_io\win32\Debug\network_io.lib ..\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 ..\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)" == "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 ..\locks\win32\debug\locks.lib ..\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 "server - Win32 Release"
+# Name "server - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\server.c
+# End Source File
+# End Target
+# End Project
diff --git a/test/suexec.c b/test/suexec.c
new file mode 100644
index 000000000..3114b5e21
--- /dev/null
+++ b/test/suexec.c
@@ -0,0 +1,565 @@
+/* ====================================================================
+ * Copyright (c) 1995-1999 The Apache Group. 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 Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * 4. The names "Apache Server" and "Apache Group" 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 Group.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the Apache Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``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 GROUP 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 Group and was originally based
+ * on public domain software written at the National Center for
+ * Supercomputing Applications, University of Illinois, Urbana-Champaign.
+ * For more information on the Apache Group and the Apache HTTP server
+ * project, please see <http://www.apache.org/>.
+ *
+ */
+
+/*
+ * suexec.c -- "Wrapper" support program for suEXEC behaviour for Apache
+ *
+ ***********************************************************************
+ *
+ * NOTE! : DO NOT edit this code!!! Unless you know what you are doing,
+ * editing this code might open up your system in unexpected
+ * ways to would-be crackers. Every precaution has been taken
+ * to make this code as safe as possible; alter it at your own
+ * risk.
+ *
+ ***********************************************************************
+ *
+ *
+ */
+
+#include "ap_config.h"
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <stdarg.h>
+
+#include "suexec.h"
+
+/*
+ ***********************************************************************
+ * There is no initgroups() in QNX, so I believe this is safe :-)
+ * Use cc -osuexec -3 -O -mf -DQNX suexec.c to compile.
+ *
+ * May 17, 1997.
+ * Igor N. Kovalenko -- infoh@mail.wplus.net
+ ***********************************************************************
+ */
+
+#if defined(NEED_INITGROUPS)
+int initgroups(const char *name, gid_t basegid)
+{
+/* QNX and MPE do not appear to support supplementary groups. */
+ return 0;
+}
+#endif
+
+#if defined(PATH_MAX)
+#define AP_MAXPATH PATH_MAX
+#elif defined(MAXPATHLEN)
+#define AP_MAXPATH MAXPATHLEN
+#else
+#define AP_MAXPATH 8192
+#endif
+
+#define AP_ENVBUF 256
+
+extern char **environ;
+static FILE *log = NULL;
+
+char *safe_env_lst[] =
+{
+ "AUTH_TYPE",
+ "CONTENT_LENGTH",
+ "CONTENT_TYPE",
+ "DATE_GMT",
+ "DATE_LOCAL",
+ "DOCUMENT_NAME",
+ "DOCUMENT_PATH_INFO",
+ "DOCUMENT_ROOT",
+ "DOCUMENT_URI",
+ "FILEPATH_INFO",
+ "GATEWAY_INTERFACE",
+ "LAST_MODIFIED",
+ "PATH_INFO",
+ "PATH_TRANSLATED",
+ "QUERY_STRING",
+ "QUERY_STRING_UNESCAPED",
+ "REMOTE_ADDR",
+ "REMOTE_HOST",
+ "REMOTE_IDENT",
+ "REMOTE_PORT",
+ "REMOTE_USER",
+ "REDIRECT_QUERY_STRING",
+ "REDIRECT_STATUS",
+ "REDIRECT_URL",
+ "REQUEST_METHOD",
+ "REQUEST_URI",
+ "SCRIPT_FILENAME",
+ "SCRIPT_NAME",
+ "SCRIPT_URI",
+ "SCRIPT_URL",
+ "SERVER_ADMIN",
+ "SERVER_NAME",
+ "SERVER_PORT",
+ "SERVER_PROTOCOL",
+ "SERVER_SOFTWARE",
+ "UNIQUE_ID",
+ "USER_NAME",
+ "TZ",
+ NULL
+};
+
+
+static void err_output(const char *fmt, va_list ap)
+{
+#ifdef LOG_EXEC
+ time_t timevar;
+ struct tm *lt;
+
+ if (!log) {
+ if ((log = fopen(LOG_EXEC, "a")) == NULL) {
+ fprintf(stderr, "failed to open log file\n");
+ perror("fopen");
+ exit(1);
+ }
+ }
+
+ time(&timevar);
+ lt = localtime(&timevar);
+
+ fprintf(log, "[%d-%.2d-%.2d %.2d:%.2d:%.2d]: ",
+ lt->tm_year + 1900, lt->tm_mon + 1, lt->tm_mday,
+ lt->tm_hour, lt->tm_min, lt->tm_sec);
+
+ vfprintf(log, fmt, ap);
+
+ fflush(log);
+#endif /* LOG_EXEC */
+ return;
+}
+
+static void log_err(const char *fmt,...)
+{
+#ifdef LOG_EXEC
+ va_list ap;
+
+ va_start(ap, fmt);
+ err_output(fmt, ap);
+ va_end(ap);
+#endif /* LOG_EXEC */
+ return;
+}
+
+static void clean_env(void)
+{
+ char pathbuf[512];
+ char **cleanenv;
+ char **ep;
+ int cidx = 0;
+ int idx;
+
+
+ if ((cleanenv = (char **) calloc(AP_ENVBUF, sizeof(char *))) == NULL) {
+ log_err("failed to malloc memory for environment\n");
+ exit(120);
+ }
+
+ sprintf(pathbuf, "PATH=%s", SAFE_PATH);
+ cleanenv[cidx] = strdup(pathbuf);
+ cidx++;
+
+ for (ep = environ; *ep && cidx < AP_ENVBUF-1; ep++) {
+ if (!strncmp(*ep, "HTTP_", 5)) {
+ cleanenv[cidx] = *ep;
+ cidx++;
+ }
+ else {
+ for (idx = 0; safe_env_lst[idx]; idx++) {
+ if (!strncmp(*ep, safe_env_lst[idx],
+ strlen(safe_env_lst[idx]))) {
+ cleanenv[cidx] = *ep;
+ cidx++;
+ break;
+ }
+ }
+ }
+ }
+
+ cleanenv[cidx] = NULL;
+
+ environ = cleanenv;
+}
+
+int main(int argc, char *argv[])
+{
+ int userdir = 0; /* ~userdir flag */
+ uid_t uid; /* user information */
+ gid_t gid; /* target group placeholder */
+ char *target_uname; /* target user name */
+ char *target_gname; /* target group name */
+ char *target_homedir; /* target home directory */
+ char *actual_uname; /* actual user name */
+ char *actual_gname; /* actual group name */
+ char *prog; /* name of this program */
+ char *cmd; /* command to be executed */
+ char cwd[AP_MAXPATH]; /* current working directory */
+ char dwd[AP_MAXPATH]; /* docroot working directory */
+ struct passwd *pw; /* password entry holder */
+ struct group *gr; /* group entry holder */
+ struct stat dir_info; /* directory info holder */
+ struct stat prg_info; /* program info holder */
+
+ /*
+ * If there are a proper number of arguments, set
+ * all of them to variables. Otherwise, error out.
+ */
+ prog = argv[0];
+ if (argc < 4) {
+ log_err("too few arguments\n");
+ exit(101);
+ }
+ target_uname = argv[1];
+ target_gname = argv[2];
+ cmd = argv[3];
+
+ /*
+ * Check existence/validity of the UID of the user
+ * running this program. Error out if invalid.
+ */
+ uid = getuid();
+ if ((pw = getpwuid(uid)) == NULL) {
+ log_err("invalid uid: (%ld)\n", uid);
+ exit(102);
+ }
+
+ /*
+ * Check to see if the user running this program
+ * is the user allowed to do so as defined in
+ * suexec.h. If not the allowed user, error out.
+ */
+#ifdef _OSD_POSIX
+ /* User name comparisons are case insensitive on BS2000/OSD */
+ if (strcasecmp(HTTPD_USER, pw->pw_name)) {
+ log_err("user mismatch (%s instead of %s)\n", pw->pw_name, HTTPD_USER);
+ exit(103);
+ }
+#else /*_OSD_POSIX*/
+ if (strcmp(HTTPD_USER, pw->pw_name)) {
+ log_err("user mismatch (%s instead of %s)\n", pw->pw_name, HTTPD_USER);
+ exit(103);
+ }
+#endif /*_OSD_POSIX*/
+
+ /*
+ * Check for a leading '/' (absolute path) in the command to be executed,
+ * or attempts to back up out of the current directory,
+ * to protect against attacks. If any are
+ * found, error out. Naughty naughty crackers.
+ */
+ if ((cmd[0] == '/') || (!strncmp(cmd, "../", 3))
+ || (strstr(cmd, "/../") != NULL)) {
+ log_err("invalid command (%s)\n", cmd);
+ exit(104);
+ }
+
+ /*
+ * Check to see if this is a ~userdir request. If
+ * so, set the flag, and remove the '~' from the
+ * target username.
+ */
+ if (!strncmp("~", target_uname, 1)) {
+ target_uname++;
+ userdir = 1;
+ }
+
+ /*
+ * Error out if the target username is invalid.
+ */
+ if ((pw = getpwnam(target_uname)) == NULL) {
+ log_err("invalid target user name: (%s)\n", target_uname);
+ exit(105);
+ }
+
+ /*
+ * Error out if the target group name is invalid.
+ */
+ if (strspn(target_gname, "1234567890") != strlen(target_gname)) {
+ if ((gr = getgrnam(target_gname)) == NULL) {
+ log_err("invalid target group name: (%s)\n", target_gname);
+ exit(106);
+ }
+ gid = gr->gr_gid;
+ actual_gname = strdup(gr->gr_name);
+ }
+ else {
+ gid = atoi(target_gname);
+ actual_gname = strdup(target_gname);
+ }
+
+#ifdef _OSD_POSIX
+ /*
+ * Initialize BS2000 user environment
+ */
+ {
+ pid_t pid;
+ int status;
+
+ switch (pid = ufork(target_uname))
+ {
+ case -1: /* Error */
+ log_err("failed to setup bs2000 environment for user %s: %s\n",
+ target_uname, strerror(errno));
+ exit(150);
+ case 0: /* Child */
+ break;
+ default: /* Father */
+ while (pid != waitpid(pid, &status, 0))
+ ;
+ /* @@@ FIXME: should we deal with STOP signals as well? */
+ if (WIFSIGNALED(status))
+ kill (getpid(), WTERMSIG(status));
+ exit(WEXITSTATUS(status));
+ }
+ }
+#endif /*_OSD_POSIX*/
+
+ /*
+ * Save these for later since initgroups will hose the struct
+ */
+ uid = pw->pw_uid;
+ actual_uname = strdup(pw->pw_name);
+ target_homedir = strdup(pw->pw_dir);
+
+ /*
+ * Log the transaction here to be sure we have an open log
+ * before we setuid().
+ */
+ log_err("uid: (%s/%s) gid: (%s/%s) cmd: %s\n",
+ target_uname, actual_uname,
+ target_gname, actual_gname,
+ cmd);
+
+ /*
+ * Error out if attempt is made to execute as root or as
+ * a UID less than UID_MIN. Tsk tsk.
+ */
+ if ((uid == 0) || (uid < UID_MIN)) {
+ log_err("cannot run as forbidden uid (%d/%s)\n", uid, cmd);
+ exit(107);
+ }
+
+ /*
+ * Error out if attempt is made to execute as root group
+ * or as a GID less than GID_MIN. Tsk tsk.
+ */
+ if ((gid == 0) || (gid < GID_MIN)) {
+ log_err("cannot run as forbidden gid (%d/%s)\n", gid, cmd);
+ exit(108);
+ }
+
+ /*
+ * Change UID/GID here so that the following tests work over NFS.
+ *
+ * Initialize the group access list for the target user,
+ * and setgid() to the target group. If unsuccessful, error out.
+ */
+ if (((setgid(gid)) != 0) || (initgroups(actual_uname, gid) != 0)) {
+ log_err("failed to setgid (%ld: %s)\n", gid, cmd);
+ exit(109);
+ }
+
+ /*
+ * setuid() to the target user. Error out on fail.
+ */
+ if ((setuid(uid)) != 0) {
+ log_err("failed to setuid (%ld: %s)\n", uid, cmd);
+ exit(110);
+ }
+
+ /*
+ * Get the current working directory, as well as the proper
+ * document root (dependant upon whether or not it is a
+ * ~userdir request). Error out if we cannot get either one,
+ * or if the current working directory is not in the docroot.
+ * Use chdir()s and getcwd()s to avoid problems with symlinked
+ * directories. Yuck.
+ */
+ if (getcwd(cwd, AP_MAXPATH) == NULL) {
+ log_err("cannot get current working directory\n");
+ exit(111);
+ }
+
+ if (userdir) {
+ if (((chdir(target_homedir)) != 0) ||
+ ((chdir(USERDIR_SUFFIX)) != 0) ||
+ ((getcwd(dwd, AP_MAXPATH)) == NULL) ||
+ ((chdir(cwd)) != 0)) {
+ log_err("cannot get docroot information (%s)\n", target_homedir);
+ exit(112);
+ }
+ }
+ else {
+ if (((chdir(DOC_ROOT)) != 0) ||
+ ((getcwd(dwd, AP_MAXPATH)) == NULL) ||
+ ((chdir(cwd)) != 0)) {
+ log_err("cannot get docroot information (%s)\n", DOC_ROOT);
+ exit(113);
+ }
+ }
+
+ if ((strncmp(cwd, dwd, strlen(dwd))) != 0) {
+ log_err("command not in docroot (%s/%s)\n", cwd, cmd);
+ exit(114);
+ }
+
+ /*
+ * Stat the cwd and verify it is a directory, or error out.
+ */
+ if (((lstat(cwd, &dir_info)) != 0) || !(S_ISDIR(dir_info.st_mode))) {
+ log_err("cannot stat directory: (%s)\n", cwd);
+ exit(115);
+ }
+
+ /*
+ * Error out if cwd is writable by others.
+ */
+ if ((dir_info.st_mode & S_IWOTH) || (dir_info.st_mode & S_IWGRP)) {
+ log_err("directory is writable by others: (%s)\n", cwd);
+ exit(116);
+ }
+
+ /*
+ * Error out if we cannot stat the program.
+ */
+ if (((lstat(cmd, &prg_info)) != 0) || (S_ISLNK(prg_info.st_mode))) {
+ log_err("cannot stat program: (%s)\n", cmd);
+ exit(117);
+ }
+
+ /*
+ * Error out if the program is writable by others.
+ */
+ if ((prg_info.st_mode & S_IWOTH) || (prg_info.st_mode & S_IWGRP)) {
+ log_err("file is writable by others: (%s/%s)\n", cwd, cmd);
+ exit(118);
+ }
+
+ /*
+ * Error out if the file is setuid or setgid.
+ */
+ if ((prg_info.st_mode & S_ISUID) || (prg_info.st_mode & S_ISGID)) {
+ log_err("file is either setuid or setgid: (%s/%s)\n", cwd, cmd);
+ exit(119);
+ }
+
+ /*
+ * Error out if the target name/group is different from
+ * the name/group of the cwd or the program.
+ */
+ if ((uid != dir_info.st_uid) ||
+ (gid != dir_info.st_gid) ||
+ (uid != prg_info.st_uid) ||
+ (gid != prg_info.st_gid)) {
+ log_err("target uid/gid (%ld/%ld) mismatch "
+ "with directory (%ld/%ld) or program (%ld/%ld)\n",
+ uid, gid,
+ dir_info.st_uid, dir_info.st_gid,
+ prg_info.st_uid, prg_info.st_gid);
+ exit(120);
+ }
+ /*
+ * Error out if the program is not executable for the user.
+ * Otherwise, she won't find any error in the logs except for
+ * "[error] Premature end of script headers: ..."
+ */
+ if (!(prg_info.st_mode & S_IXUSR)) {
+ log_err("file has no execute permission: (%s/%s)\n", cwd, cmd);
+ exit(121);
+ }
+
+ clean_env();
+
+ /*
+ * Be sure to close the log file so the CGI can't
+ * mess with it. If the exec fails, it will be reopened
+ * automatically when log_err is called. Note that the log
+ * might not actually be open if LOG_EXEC isn't defined.
+ * However, the "log" cell isn't ifdef'd so let's be defensive
+ * and assume someone might have done something with it
+ * outside an ifdef'd LOG_EXEC block.
+ */
+ if (log != NULL) {
+ fclose(log);
+ log = NULL;
+ }
+
+ /*
+ * Execute the command, replacing our image with its own.
+ */
+#ifdef NEED_HASHBANG_EMUL
+ /* We need the #! emulation when we want to execute scripts */
+ {
+ extern char **environ;
+
+ ap_execve(cmd, &argv[3], environ);
+ }
+#else /*NEED_HASHBANG_EMUL*/
+ execv(cmd, &argv[3]);
+#endif /*NEED_HASHBANG_EMUL*/
+
+ /*
+ * (I can't help myself...sorry.)
+ *
+ * Uh oh. Still here. Where's the kaboom? There was supposed to be an
+ * EARTH-shattering kaboom!
+ *
+ * Oh well, log the failure and error out.
+ */
+ log_err("(%d)%s: exec failed (%s)\n", errno, strerror(errno), cmd);
+ exit(255);
+}
diff --git a/test/test.dsw b/test/test.dsw
new file mode 100644
index 000000000..7ecd85f8e
--- /dev/null
+++ b/test/test.dsw
@@ -0,0 +1,155 @@
+Microsoft Developer Studio Workspace File, Format Version 5.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "ab_apr"=".\ab_apr.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "client"=".\client.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "htdigest"=".\htdigest.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "server"=".\server.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "testarg"=".\testarg.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "testfile"=".\testfile.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "testproc"=".\testproc.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "testsig"=".\testsig.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "testsock"=".\testsock.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name client
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name server
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "testthread"=".\testthread.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "timetest"=".\timetest.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/test/testarg.dsp b/test/testarg.dsp
new file mode 100644
index 000000000..c804b1f05
--- /dev/null
+++ b/test/testarg.dsp
@@ -0,0 +1,90 @@
+# 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 ..\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)" == "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 ..\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 "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
new file mode 100644
index 000000000..5b03876bd
--- /dev/null
+++ b/test/testargs.c
@@ -0,0 +1,95 @@
+/* ====================================================================
+ * Copyright (c) 1999 The Apache Group. 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 Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * 4. The names "Apache Server" and "Apache Group" 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 Group.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the Apache Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``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 GROUP 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 Group.
+ * For more information on the Apache Group and the Apache HTTP server
+ * project, please see <http://www.apache.org/>.
+ *
+ */
+
+#include "apr_file_io.h"
+#include "apr_errno.h"
+#include "apr_general.h"
+#include "apr_lib.h"
+#include <stdio.h>
+#ifdef BEOS
+#include <unistd.h>
+#endif
+
+API_VAR_IMPORT char *optarg; /* argument associated with option */
+
+int main(int argc, char * const argv[])
+{
+ ap_context_t *context;
+ ap_int32_t data;
+
+ ap_create_context(NULL, NULL, &context);
+
+ while (ap_getopt(context, argc, argv, "abc:d::", &data) == APR_SUCCESS) {
+ switch(data) {
+ case 'a':
+ case 'b':
+ printf("option %c\n", data);
+ break;
+ case 'c':
+ printf("option %c with %s\n", data, optarg);
+ break;
+ case 'd':
+ printf("option %c", data);
+ if (optarg) {
+ printf(" with %s\n", optarg);
+ }
+ else {
+ printf("\n");
+ }
+ break;
+ }
+ }
+ return 1;
+}
diff --git a/test/testfile.c b/test/testfile.c
new file mode 100644
index 000000000..8d3cfb0c4
--- /dev/null
+++ b/test/testfile.c
@@ -0,0 +1,324 @@
+/* ====================================================================
+ * Copyright (c) 1999 The Apache Group. 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 Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * 4. The names "Apache Server" and "Apache Group" 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 Group.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the Apache Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``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 GROUP 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 Group.
+ * For more information on the Apache Group and the Apache HTTP server
+ * project, please see <http://www.apache.org/>.
+ *
+ */
+#include <stdio.h>
+#include "apr_file_io.h"
+#include "apr_errno.h"
+#include "apr_general.h"
+#include "apr_lib.h"
+#ifdef BEOS
+#include <unistd.h>
+#endif
+
+int test_filedel(ap_context_t *);
+int testdirs(ap_context_t *);
+
+int main()
+{
+ ap_context_t *context;
+ ap_file_t *thefile = NULL;
+ ap_status_t status = 0;
+ ap_int32_t flag = APR_READ | APR_WRITE | APR_CREATE;
+ ap_uint64_t rv = 0;
+ ap_ssize_t nbytes = 0;
+ ap_off_t zer = 0;
+ char *buf;
+ char *str;
+ char *filename = "test.fil";
+ if (ap_create_context(NULL, NULL, &context) != APR_SUCCESS) {
+ fprintf(stderr, "Couldn't allocate context.");
+ exit(-1);
+ }
+
+ fprintf(stdout, "Testing file functions.\n");
+
+ fprintf(stdout, "\tOpening file.......");
+ if (ap_open(context, filename, flag, APR_UREAD | APR_UWRITE | APR_GREAD, &thefile) != APR_SUCCESS) {
+ perror("Didn't open file");
+ exit(-1);
+ }
+ else {
+ fprintf(stdout, "OK\n");
+ }
+
+ fprintf(stdout, "\tChecking file.......");
+ if (thefile == NULL) {
+ fprintf(stderr, "Bad file des\n");
+ exit(-1);
+ }
+ ap_get_filename(thefile, &str);
+ if (strcmp(str, filename) != 0) {
+ fprintf(stderr, "wrong filename\n");
+ exit(-1);
+ }
+ else {
+ fprintf(stdout, "OK\n");
+ }
+
+ fprintf(stdout, "\tWriting to file.......");
+
+ 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");
+ }
+
+ 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");
+ }
+
+ 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");
+ }
+
+ 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");
+ }
+
+ fprintf(stdout, "\tDeleting file.......");
+ status = ap_remove_file(context, filename);
+ if (status != APR_SUCCESS) {
+ fprintf(stderr, "Couldn't delete the file\n");
+ exit(-1);
+ }
+ else {
+ fprintf(stdout, "OK\n");
+ }
+
+ fprintf(stdout, "\tMaking sure it's gone.......");
+ status = ap_open(context, filename, APR_READ, APR_UREAD | APR_UWRITE | APR_GREAD, &thefile);
+ if (status == APR_SUCCESS) {
+ fprintf(stderr, "I could open the file for some reason?\n");
+ exit(-1);
+ }
+ else {
+ fprintf(stdout, "OK\n");
+ }
+
+ testdirs(context);
+ test_filedel(context);
+
+ return 1;
+}
+
+int test_filedel(ap_context_t *context)
+{
+ ap_file_t *thefile;
+ ap_int32_t flag = APR_READ | APR_WRITE | APR_CREATE;
+ ap_status_t stat;
+
+ stat = ap_open(context, "testdel", flag, APR_UREAD | APR_UWRITE | APR_GREAD, &thefile);
+ if (stat != APR_SUCCESS) {
+ return stat;
+ }
+
+ if ((stat = ap_close(thefile)) != APR_SUCCESS) {
+ return stat;
+ }
+
+ if ((stat = ap_remove_file(context, "testdel")) != APR_SUCCESS) {
+ return stat;
+ }
+
+ stat = ap_open(context, "testdel", APR_READ, APR_UREAD | APR_UWRITE | APR_GREAD, &thefile);
+ if (stat == APR_SUCCESS) {
+ return stat;
+ }
+
+ return APR_SUCCESS;
+}
+
+int testdirs(ap_context_t *context)
+{
+ ap_dir_t *temp;
+ ap_file_t *file;
+ ap_ssize_t bytes;
+ ap_filetype_e type;
+ char *fname;
+
+ fprintf(stdout, "Testing Directory functions.\n");
+
+ fprintf(stdout, "\tMakeing Directory.......");
+ if (ap_make_dir(context, "testdir", APR_UREAD | APR_UWRITE | APR_UEXECUTE | APR_GREAD | APR_GWRITE | APR_GEXECUTE | APR_WREAD | APR_WWRITE | APR_WEXECUTE) != APR_SUCCESS) {
+ fprintf(stderr, "Could not create directory\n");
+ return -1;
+ }
+ else {
+ fprintf(stdout, "OK\n");
+ }
+
+ if (ap_open(context, "testdir/testfile", APR_READ | APR_WRITE | APR_CREATE, APR_UREAD | APR_UWRITE | APR_UEXECUTE, &file) != APR_SUCCESS) {;
+ return -1;
+ }
+
+ bytes = strlen("Another test!!!");
+ ap_write(file, "Another test!!", &bytes);
+ ap_close(file);
+
+ fprintf(stdout, "\tOpening Directory.......");
+ if (ap_opendir(context, "testdir", &temp) != APR_SUCCESS) {
+ fprintf(stderr, "Could not open directory\n");
+ return -1;
+ }
+ else {
+ fprintf(stdout, "OK\n");
+ }
+
+ 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(temp, &fname);
+ } while (fname[0] == '.');
+ if (strcmp(fname, "testfile")) {
+ fprintf(stderr, "Got wrong file name %s\n", fname);
+ return -1;
+ }
+ fprintf(stdout, "OK\n");
+
+ fprintf(stdout, "\t\tFile type.......");
+ ap_dir_entry_ftype(temp, &type);
+ if (type != APR_REG) {
+ fprintf(stderr, "Got wrong file type\n");
+ return -1;
+ }
+ fprintf(stdout, "OK\n");
+
+ fprintf(stdout, "\t\tFile size.......");
+ ap_dir_entry_size(temp, &bytes);
+ if (bytes != (ap_ssize_t)strlen("Another test!!!")) {
+ fprintf(stderr, "Got wrong file size %d\n", bytes);
+ return -1;
+ }
+ fprintf(stdout, "OK\n");
+
+ fprintf(stdout, "\tRewinding directory.......");
+ ap_rewinddir(temp);
+ fprintf(stdout, "OK\n");
+
+ fprintf(stdout, "\tClosing Directory.......");
+ if (ap_closedir(temp) != APR_SUCCESS) {
+ fprintf(stderr, "Could not close directory\n");
+ return -1;
+ }
+ else {
+ fprintf(stdout, "OK\n");
+ }
+
+ fprintf(stdout, "\tRemoving file from directory.......");
+ if (ap_remove_file(context, "testdir/testfile") != APR_SUCCESS) {
+ fprintf(stderr, "Could not remove file\n");
+ return -1;
+ }
+ else {
+ fprintf(stdout, "OK\n");
+ }
+
+ fprintf(stdout, "\tRemoving Directory.......");
+ if (ap_remove_dir(context, "testdir") != APR_SUCCESS) {
+ fprintf(stderr, "Could not remove directory\n");
+ return -1;
+ }
+ else {
+ fprintf(stdout, "OK\n");
+ }
+
+ return 1;
+}
+
diff --git a/test/testfile.dsp b/test/testfile.dsp
new file mode 100644
index 000000000..149b3fff5
--- /dev/null
+++ b/test/testfile.dsp
@@ -0,0 +1,91 @@
+# 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 ..\network_io\win32\Debug ..\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 ..\network_io\win32\Debug\network_io.lib ..\locks\win32\Debug\locks.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
+
+!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 ..\locks\win32\debug\locks.lib ..\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 "testfile - Win32 Release"
+# Name "testfile - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\testfile.c
+# End Source File
+# End Target
+# End Project
diff --git a/test/testproc.c b/test/testproc.c
new file mode 100644
index 000000000..4a38c95ba
--- /dev/null
+++ b/test/testproc.c
@@ -0,0 +1,163 @@
+/* ====================================================================
+ * Copyright (c) 1999 The Apache Group. 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 Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * 4. The names "Apache Server" and "Apache Group" 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 Group.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the Apache Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``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 GROUP 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 Group.
+ * For more information on the Apache Group 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\0");
+
+ if (argc > 1) {
+ fprintf(stdout, "%s", teststr);
+ exit(1);
+ }
+
+ fprintf(stdout, "Creating directory for later use.......");
+ if (ap_make_dir(context, "proctest", APR_UREAD | APR_UWRITE | APR_UEXECUTE) != APR_SUCCESS) {
+ fprintf(stderr, "Could not create dir\n");
+ exit(-1);
+ }
+ fprintf(stdout, "OK\n");
+
+ 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");
+
+ fprintf(stdout, "Removing directory.......");
+ if (ap_remove_dir(context, "proctest") != APR_SUCCESS) {
+ fprintf(stderr, "Could not remove directory.\n");
+ exit(-1);
+ }
+ fprintf(stdout, "OK\n");
+
+ return(1);
+}
+
diff --git a/test/testproc.dsp b/test/testproc.dsp
new file mode 100644
index 000000000..b1f12ce43
--- /dev/null
+++ b/test/testproc.dsp
@@ -0,0 +1,91 @@
+# 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 ..\network_io\win32\Debug ..\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 ..\network_io\win32\Debug\network_io.lib ..\locks\win32\Debug\locks.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)" == "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 ..\locks\win32\debug\locks.lib ..\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 "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
new file mode 100644
index 000000000..395a4854c
--- /dev/null
+++ b/test/testproc.rbb
@@ -0,0 +1,148 @@
+/* ====================================================================
+ * Copyright (c) 1999 The Apache Group. 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 Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * 4. The names "Apache Server" and "Apache Group" 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 Group.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the Apache Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``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 GROUP 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 Group.
+ * For more information on the Apache Group 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/testsig.c b/test/testsig.c
new file mode 100644
index 000000000..d17aeb9f0
--- /dev/null
+++ b/test/testsig.c
@@ -0,0 +1,127 @@
+/* ====================================================================
+ * Copyright (c) 1999 The Apache Group. 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 Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * 4. The names "Apache Server" and "Apache Group" 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 Group.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the Apache Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``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 GROUP 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 Group.
+ * For more information on the Apache Group 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 time_to_die = 0;
+
+void hup_handler(int sig)
+{
+ fprintf(stdout, "I got the signal\n");
+ time_to_die++;
+}
+
+int main(int argc, char *argv[])
+{
+ ap_context_t *context;
+ ap_proc_t *newproc;
+ ap_procattr_t *attr;
+ char *args[3];
+
+ ap_initialize();
+
+ ap_create_context(NULL, NULL, &context);
+
+ if (argc > 1) {
+
+ ap_setup_signal(context, APR_SIGHUP, hup_handler);
+
+ while(time_to_die == 0) {
+ sleep(1);
+ }
+ return(1);
+ }
+
+ fprintf(stdout, "Creating new signal.......");
+ if (ap_create_signal(context, APR_SIGHUP) != APR_SUCCESS) {
+ fprintf(stderr, "Could not create attr\n");
+ exit(-1);
+ }
+ fprintf(stdout, "OK\n");
+
+ if (ap_createprocattr_init(context, &attr) != APR_SUCCESS) {
+ fprintf(stderr, "Could not create attr\n");
+ exit(-1);;
+ }
+ ap_setprocattr_detach(attr, FALSE);
+
+ args[0] = ap_pstrdup(context, "testsig");
+ args[1] = ap_pstrdup(context, "-X");
+ args[2] = NULL;
+
+ if (ap_create_process(context, "./testsig", args, NULL, attr, &newproc) != APR_SUCCESS) {
+ fprintf(stderr, "Could not create the new process\n");
+ exit(-1);
+ }
+
+ fprintf(stdout, "Sending the signal.......");
+ fflush(stdout);
+ ap_send_signal(context, APR_SIGHUP);
+
+ ap_wait_proc(newproc, APR_WAIT);
+
+ return(1);
+}
+
diff --git a/test/testsig.dsp b/test/testsig.dsp
new file mode 100644
index 000000000..c88c6be96
--- /dev/null
+++ b/test/testsig.dsp
@@ -0,0 +1,90 @@
+# 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/testsock.c b/test/testsock.c
new file mode 100644
index 000000000..b8f5984ba
--- /dev/null
+++ b/test/testsock.c
@@ -0,0 +1,126 @@
+/* ====================================================================
+ * Copyright (c) 1999 The Apache Group. 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 Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * 4. The names "Apache Server" and "Apache Group" 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 Group.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the Apache Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``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 GROUP 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 Group.
+ * For more information on the Apache Group and the Apache HTTP server
+ * project, please see <http://www.apache.org/>.
+ *
+ */
+
+#include <stdio.h>
+#include <signal.h>
+#include "apr_thread_proc.h"
+#include "apr_errno.h"
+#include "apr_general.h"
+#include "apr_lib.h"
+
+#define STRLEN 15
+
+int main(int argc, char *argv[])
+{
+ ap_context_t *context;
+
+ 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];
+
+ fprintf(stdout, "Creating context.......");
+ if (ap_create_context(NULL, NULL, &context) != APR_SUCCESS) {
+ fprintf(stderr, "Could not create context\n");
+ exit(-1);
+ }
+ fprintf(stdout, "OK\n");
+
+ 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. Alternitevly, you could run\n");
+ fprintf(stdout, "server and client by yourself.\n");
+
+ fprintf(stdout, "Creating children to run network tests.......\n");
+ s1 = ap_createprocattr_init(context, &attr1);
+ s2 = ap_createprocattr_init(context, &attr2);
+
+ if (s1 != APR_SUCCESS || s2 != APR_SUCCESS) {
+ fprintf(stderr, "Problem creating proc attrs\n");
+ exit(-1);
+ }
+
+ args[0] = ap_pstrdup(context, "server");
+ args[1] = NULL;
+ s1 = ap_create_process(context, "./server", args, NULL, attr1, &proc1);
+
+ args[0] = ap_pstrdup(context, "client");
+ s2 = ap_create_process(context, "./client", args, NULL, attr2, &proc2);
+
+ if (s1 != APR_SUCCESS || s2 != APR_SUCCESS) {
+ fprintf(stderr, "Problem spawning new process\n");
+ exit(-1);
+ }
+
+ while ((s1 = ap_wait_proc(proc1, APR_NOWAIT)) != APR_CHILD_DONE ||
+ (s2 = ap_wait_proc(proc2, APR_NOWAIT)) != APR_CHILD_DONE) {
+ continue;
+ }
+
+ if (s1 == APR_SUCCESS) {
+ ap_kill(proc2, SIGTERM);
+ ap_wait_proc(proc2, APR_WAIT);
+ }
+ else {
+ ap_kill(proc1, SIGTERM);
+ ap_wait_proc(proc1, APR_WAIT);
+ }
+ fprintf(stdout, "Network test completed.\n");
+
+ return 1;
+}
diff --git a/test/testsock.dsp b/test/testsock.dsp
new file mode 100644
index 000000000..5c7e1a87d
--- /dev/null
+++ b/test/testsock.dsp
@@ -0,0 +1,91 @@
+# 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 ..\network_io\win32\Debug ..\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 ..\network_io\win32\Debug\network_io.lib ..\locks\win32\Debug\locks.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)" == "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 ..\locks\win32\debug\locks.lib ..\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 "testsock - Win32 Release"
+# Name "testsock - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\testsock.c
+# End Source File
+# End Target
+# End Project
diff --git a/test/testthread.c b/test/testthread.c
new file mode 100644
index 000000000..ae7a93904
--- /dev/null
+++ b/test/testthread.c
@@ -0,0 +1,174 @@
+/* ====================================================================
+ * Copyright (c) 1999 The Apache Group. 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 Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * 4. The names "Apache Server" and "Apache Group" 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 Group.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the Apache Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``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 GROUP 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 Group.
+ * For more information on the Apache Group and the Apache HTTP server
+ * project, please see <http://www.apache.org/>.
+ *
+ */
+#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
+
+
+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);
+
+
+ap_lock_t *thread_lock;
+ap_context_t *context;
+int x = 0;
+
+void * API_THREAD_FUNC thread_func1(void *data)
+{
+ int i;
+ for (i = 0; i < 10000; i++) {
+ ap_lock(thread_lock);
+ x++;
+ ap_unlock(thread_lock);
+ }
+ return NULL;
+}
+
+void * API_THREAD_FUNC thread_func2(void *data)
+{
+ int i;
+ for (i = 0; i < 10000; i++) {
+ ap_lock(thread_lock);
+ x++;
+ ap_unlock(thread_lock);
+ }
+ return NULL;
+}
+
+void * API_THREAD_FUNC thread_func3(void *data)
+{
+ int i;
+ for (i = 0; i < 10000; i++) {
+ ap_lock(thread_lock);
+ x++;
+ ap_unlock(thread_lock);
+ }
+ return NULL;
+}
+
+void * API_THREAD_FUNC thread_func4(void *data)
+{
+ int i;
+ for (i = 0; i < 10000; i++) {
+ ap_lock(thread_lock);
+ x++;
+ ap_unlock(thread_lock);
+ }
+ return NULL;
+}
+
+int main()
+{
+ 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;
+
+ fprintf(stdout, "Initializing the context.......");
+ if (ap_create_context(NULL, NULL, &context) != APR_SUCCESS) {
+ fprintf(stderr, "could not initialize\n");
+ exit(-1);
+ }
+ fprintf(stdout, "OK\n");
+
+ fprintf(stdout, "Initializing the lock.......");
+ s1 = ap_create_lock(context, APR_INTRAPROCESS, "lock.file", &thread_lock);
+ 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(context, NULL, thread_func1, NULL, &t1);
+ s2 = ap_create_thread(context, NULL, thread_func2, NULL, &t2);
+ s3 = ap_create_thread(context, NULL, thread_func3, NULL, &t3);
+ s4 = ap_create_thread(context, NULL, thread_func4, NULL, &t4);
+ 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(t1, &s1);
+ ap_thread_join(t2, &s2);
+ ap_thread_join(t3, &s3);
+ ap_thread_join(t4, &s4);
+ 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");
+ }
+
+ return 1;
+}
diff --git a/test/testthread.dsp b/test/testthread.dsp
new file mode 100644
index 000000000..3a094074e
--- /dev/null
+++ b/test/testthread.dsp
@@ -0,0 +1,92 @@
+# 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 ..\network_io\win32\Debug\network_io.lib ..\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 ..\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)" == "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 ..\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 "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
new file mode 100644
index 000000000..dbc3d330d
--- /dev/null
+++ b/test/testtime.c
@@ -0,0 +1,178 @@
+/* ====================================================================
+ * Copyright (c) 1999 The Apache Group. 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 Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * 4. The names "Apache Server" and "Apache Group" 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 Group.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the Apache Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``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 GROUP 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 Group.
+ * For more information on the Apache Group and the Apache HTTP server
+ * project, please see <http://www.apache.org/>.
+ *
+ */
+#include "apr_time.h"
+#include "apr_errno.h"
+#include "apr_general.h"
+#include "errno.h"
+#include <stdio.h>
+#ifdef BEOS
+#include <unistd.h>
+#endif
+
+int main()
+{
+ ap_context_t *context;
+ ap_time_t *time;
+ ap_time_t *time2;
+ ap_int32_t rv = 0;
+ ap_int64_t t1, t2;
+
+ fprintf(stdout, "Creating context.......");
+ if (ap_create_context(NULL, NULL, &context) != APR_SUCCESS) {
+ fprintf(stderr, "could not create context\n");
+ exit(-1);
+ }
+ fprintf(stdout, "OK\n");
+
+ fprintf(stdout, "Testing Time functions.\n");
+
+ fprintf(stdout, "\tMaking new time variable.......");
+ if (ap_make_time(context, &time) != APR_SUCCESS) {
+ fprintf(stderr, "Couldn't allocate memory\n");
+ exit(-1);
+ }
+ fprintf(stdout, "OK\n");
+
+ fprintf(stdout, "\tGetting current time.......");
+ if (ap_current_time(time) != APR_SUCCESS) {
+ fprintf(stderr, "Couldn't get the time\n");
+ exit(-1);
+ }
+ fprintf(stdout, "OK\n");
+
+ fprintf(stdout, "\tExploding Current time.......");
+ if (ap_explode_time(time, APR_UTCTIME) != APR_SUCCESS) {
+ fprintf(stderr, "Couldn't explode the time\n");
+ exit(-1);
+ }
+ fprintf(stdout, "OK\n");
+
+ ap_make_time(context, &time2);
+ fprintf(stdout, "\tGetting the number of seconds.......");
+ if (ap_get_sec(time, &rv) != APR_SUCCESS) {
+ fprintf(stderr, "Couldn't get the seconds\n");
+ exit(-1);
+ }
+ ap_set_sec(time2, rv);
+ fprintf(stdout, "OK\n");
+
+ fprintf(stdout, "\tGetting the number of minutes.......");
+ if (ap_get_min(time, &rv) != APR_SUCCESS) {
+ fprintf(stderr, "Couldn't get the minutes\n");
+ exit(-1);
+ }
+ ap_set_min(time2, rv);
+ fprintf(stdout, "OK\n");
+
+ fprintf(stdout, "\tGetting the number of hours.......");
+ if (ap_get_hour(time, &rv) != APR_SUCCESS) {
+ fprintf(stderr, "Couldn't get the hours\n");
+ exit(-1);
+ }
+ ap_set_hour(time2, rv);
+ fprintf(stdout, "OK\n");
+
+ fprintf(stdout, "\tGetting the number of days.......");
+ if (ap_get_mday(time, &rv) != APR_SUCCESS) {
+ fprintf(stderr, "Couldn't get the days\n");
+ exit(-1);
+ }
+ ap_set_mday(time2, rv);
+ fprintf(stdout, "OK\n");
+
+ fprintf(stdout, "\tGetting the month .......");
+ if (ap_get_mon(time, &rv) != APR_SUCCESS) {
+ fprintf(stderr, "Couldn't get the month\n");
+ exit(-1);
+ }
+ ap_set_mon(time2, rv);
+ fprintf(stdout, "OK\n");
+
+ fprintf(stdout, "\tGetting the year.......");
+ if (ap_get_year(time, &rv) != APR_SUCCESS) {
+ fprintf(stderr, "Couldn't get the year\n");
+ exit(-1);
+ }
+ ap_set_year(time2, rv);
+ fprintf(stdout, "OK\n");
+
+ fprintf(stdout, "\tGetting the weekday.......");
+ if (ap_get_wday(time, &rv) != APR_SUCCESS) {
+ fprintf(stderr, "Couldn't get the week day\n");
+ exit(-1);
+ }
+ ap_set_wday(time2, rv);
+ fprintf(stdout, "OK\n");
+
+ fprintf(stdout, "\tImploding the time.......");
+ if (ap_implode_time(time2) != APR_SUCCESS ||
+ ap_implode_time(time) != APR_SUCCESS) {
+ fprintf(stderr, "Couldn't implode time\n");
+ exit(-1);
+ }
+ fprintf(stdout, "OK\n");
+
+ fprintf(stdout, "\tComparing two time values.......");
+ ap_get_curtime(time, &t1);
+ ap_get_curtime(time2, &t2);
+ if ((t1 == -1) || (t2 == -1) || (t1 != t2)) {
+ fprintf(stderr, "Values don't match\n");
+ exit(-1);
+ }
+ fprintf(stdout, "OK\n");
+
+ return 1;
+}
+
diff --git a/test/timetest.dsp b/test/timetest.dsp
new file mode 100644
index 000000000..08fb1f35d
--- /dev/null
+++ b/test/timetest.dsp
@@ -0,0 +1,91 @@
+# 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 ..\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 ..\network_io\win32\Debug\network_io.lib ..\locks\win32\Debug\locks.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)" == "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 ..\locks\win32\debug\locks.lib ..\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 "timetest - Win32 Release"
+# Name "timetest - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\testtime.c
+# End Source File
+# End Target
+# End Project