diff options
author | rbb <rbb@13f79535-47bb-0310-9956-ffa450edef68> | 1999-08-17 15:59:33 +0000 |
---|---|---|
committer | rbb <rbb@13f79535-47bb-0310-9956-ffa450edef68> | 1999-08-17 15:59:33 +0000 |
commit | 6577c978ebc28f950f43591579674e045f3d2a67 (patch) | |
tree | a54b0555bf7862582241f3bc69c81ebf035948f8 /test | |
parent | 3171d4b484045e81ea8289845830823008b48ece (diff) | |
download | libapr-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/.cvsignore | 1 | ||||
-rw-r--r-- | test/Makefile.in | 127 | ||||
-rw-r--r-- | test/ab_apr.c | 975 | ||||
-rw-r--r-- | test/ab_apr.dsp | 90 | ||||
-rw-r--r-- | test/abc.c | 28 | ||||
-rw-r--r-- | test/client.c | 153 | ||||
-rw-r--r-- | test/client.dsp | 90 | ||||
-rw-r--r-- | test/htdigest.c | 280 | ||||
-rw-r--r-- | test/htdigest.dsp | 90 | ||||
-rw-r--r-- | test/htpasswd.c | 538 | ||||
-rw-r--r-- | test/logresolve.c | 345 | ||||
-rw-r--r-- | test/rotatelogs.c | 82 | ||||
-rw-r--r-- | test/server.c | 198 | ||||
-rw-r--r-- | test/server.dsp | 90 | ||||
-rw-r--r-- | test/suexec.c | 565 | ||||
-rw-r--r-- | test/test.dsw | 155 | ||||
-rw-r--r-- | test/testarg.dsp | 90 | ||||
-rw-r--r-- | test/testargs.c | 95 | ||||
-rw-r--r-- | test/testfile.c | 324 | ||||
-rw-r--r-- | test/testfile.dsp | 91 | ||||
-rw-r--r-- | test/testproc.c | 163 | ||||
-rw-r--r-- | test/testproc.dsp | 91 | ||||
-rw-r--r-- | test/testproc.rbb | 148 | ||||
-rw-r--r-- | test/testsig.c | 127 | ||||
-rw-r--r-- | test/testsig.dsp | 90 | ||||
-rw-r--r-- | test/testsock.c | 126 | ||||
-rw-r--r-- | test/testsock.dsp | 91 | ||||
-rw-r--r-- | test/testthread.c | 174 | ||||
-rw-r--r-- | test/testthread.dsp | 92 | ||||
-rw-r--r-- | test/testtime.c | 178 | ||||
-rw-r--r-- | test/timetest.dsp | 91 |
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> </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> </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> </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 |