Module Name: src
Committed By: mrg
Date: Sat May 23 02:26:03 UTC 2009
Modified Files:
src/libexec/httpd: CHANGES Makefile bozohttpd.8 bozohttpd.c bozohttpd.h
cgi-bozo.c daemon-bozo.c
src/libexec/httpd/testsuite: Makefile
Log Message:
merge bozohttpd 20090522
To generate a diff of this commit:
cvs rdiff -u -r1.4 -r1.5 src/libexec/httpd/CHANGES
cvs rdiff -u -r1.8 -r1.9 src/libexec/httpd/Makefile
cvs rdiff -u -r1.13 -r1.14 src/libexec/httpd/bozohttpd.8 \
src/libexec/httpd/bozohttpd.c src/libexec/httpd/cgi-bozo.c
cvs rdiff -u -r1.10 -r1.11 src/libexec/httpd/bozohttpd.h
cvs rdiff -u -r1.6 -r1.7 src/libexec/httpd/daemon-bozo.c
cvs rdiff -u -r1.3 -r1.4 src/libexec/httpd/testsuite/Makefile
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/libexec/httpd/CHANGES
diff -u src/libexec/httpd/CHANGES:1.4 src/libexec/httpd/CHANGES:1.5
--- src/libexec/httpd/CHANGES:1.4 Sat Apr 18 21:22:03 2009
+++ src/libexec/httpd/CHANGES Sat May 23 02:26:03 2009
@@ -1,10 +1,15 @@
-$eterna: CHANGES,v 1.67 2009/04/18 11:42:39 mrg Exp $
+$eterna: CHANGES,v 1.68 2009/05/22 21:51:38 mrg Exp $
changes since bozohttpd 20090417:
o avoid dying in daemon mode for some uncommon, but recoverable, errors
o close leaking file descriptors for CGI and daemon mode
o handle poll errors properly
o don't try to handle more than one request per process yet
+ o add subdirs for build "debug" and "small" versions
+ o clean up a bad merge / duplicate code
+ o make mmap() usage portable, fixes linux & ranges: support
+ o document the -f option
+ o daemon mode now serves 6 files per child
changes since bozohttpd 20080303:
o make bozohttpd internally more modular, preparing the way
Index: src/libexec/httpd/Makefile
diff -u src/libexec/httpd/Makefile:1.8 src/libexec/httpd/Makefile:1.9
--- src/libexec/httpd/Makefile:1.8 Mon Mar 16 02:24:56 2009
+++ src/libexec/httpd/Makefile Sat May 23 02:26:03 2009
@@ -1,6 +1,6 @@
-# $NetBSD: Makefile,v 1.8 2009/03/16 02:24:56 lukem Exp $
+# $NetBSD: Makefile,v 1.9 2009/05/23 02:26:03 mrg Exp $
#
-# $eterna: Makefile,v 1.26 2005/09/27 20:09:20 mrg Exp $
+# $eterna: Makefile,v 1.27 2009/05/22 21:51:38 mrg Exp $
# compile-time options are:
# DEBUG /* include debugging support */
@@ -21,8 +21,6 @@
LDADD= -lcrypt
DPADD= ${LIBCRYPT}
-.include <bsd.own.mk>
-
.if ${MKCRYPTO} != "no"
LDADD+= -lssl -lcrypto
Index: src/libexec/httpd/bozohttpd.8
diff -u src/libexec/httpd/bozohttpd.8:1.13 src/libexec/httpd/bozohttpd.8:1.14
--- src/libexec/httpd/bozohttpd.8:1.13 Sat Apr 18 21:22:03 2009
+++ src/libexec/httpd/bozohttpd.8 Sat May 23 02:26:03 2009
@@ -1,6 +1,6 @@
-.\" $NetBSD: bozohttpd.8,v 1.13 2009/04/18 21:22:03 mrg Exp $
+.\" $NetBSD: bozohttpd.8,v 1.14 2009/05/23 02:26:03 mrg Exp $
.\"
-.\" $eterna: bozohttpd.8,v 1.87 2009/04/18 20:53:58 mrg Exp $
+.\" $eterna: bozohttpd.8,v 1.91 2009/05/23 00:55:22 mrg Exp $
.\"
.\" Copyright (c) 1997-2009 Matthew R. Green
.\" All rights reserved.
@@ -26,7 +26,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd April 17, 2009
+.Dd May 22, 2009
.Dt HTTPD 8
.Os
.Sh NAME
@@ -34,7 +34,7 @@
.Nd hyper text transfer protocol version 1.1 daemon
.Sh SYNOPSIS
.Nm
-.Op Fl HVXbenrus
+.Op Fl HVXbefnrus
.Op Fl C Ar suffix cgihandler
.Op Fl I Ar port
.Op Fl M Ar suffix type encoding encoding11
@@ -97,7 +97,7 @@
looks for URL's in the form of
.Em /cgi-bin/\*[Lt]scriptname\*[Gt]
where
-.Em Aq scriptname
+.Aq scriptname
is a valid CGI program in the
.Ar cgibin
directory.
@@ -114,6 +114,12 @@
or
.Fl U
options.
+.It Fl f
+This option stops the
+.Fl b
+flag from
+.Nm
+detaching from the tty and going into the background.
.It Fl H
This option causes directory index mode to hide files and directories
that start with a period, except for
@@ -370,8 +376,7 @@
with
.Dq -DDO_HTPASSWD
on the compiler command line to enable this support.
-It may require
-linking with the crypt library, using
+It may require linking with the crypt library, using
.Dq -lcrypt .
.Ss SSL SUPPORT
.Nm
@@ -453,7 +458,7 @@
and regular code audits.
This manual documents
.Nm
-version 20090418.
+version 20090522.
.Sh AUTHORS
.Nm
was written by Matthew R. Green
Index: src/libexec/httpd/bozohttpd.c
diff -u src/libexec/httpd/bozohttpd.c:1.13 src/libexec/httpd/bozohttpd.c:1.14
--- src/libexec/httpd/bozohttpd.c:1.13 Sat Apr 18 21:22:03 2009
+++ src/libexec/httpd/bozohttpd.c Sat May 23 02:26:03 2009
@@ -1,6 +1,6 @@
-/* $NetBSD: bozohttpd.c,v 1.13 2009/04/18 21:22:03 mrg Exp $ */
+/* $NetBSD: bozohttpd.c,v 1.14 2009/05/23 02:26:03 mrg Exp $ */
-/* $eterna: bozohttpd.c,v 1.155 2009/04/18 20:53:58 mrg Exp $ */
+/* $eterna: bozohttpd.c,v 1.159 2009/05/23 02:14:30 mrg Exp $ */
/*
* Copyright (c) 1997-2009 Matthew R. Green
@@ -109,7 +109,7 @@
#define INDEX_HTML "index.html"
#endif
#ifndef SERVER_SOFTWARE
-#define SERVER_SOFTWARE "bozohttpd/20090418"
+#define SERVER_SOFTWARE "bozohttpd/20090522"
#endif
#ifndef DIRECT_ACCESS_FILE
#define DIRECT_ACCESS_FILE ".bzdirect"
@@ -179,6 +179,7 @@
static int sflag; /* log to stderr even if it is not a TTY */
static char *vpath; /* virtual directory base */
+ size_t page_size; /* page size */
char *slashdir; /* www slash directory */
const char *server_software = SERVER_SOFTWARE;
@@ -349,7 +350,15 @@
#ifndef NO_DAEMON_MODE
case 'b':
- bflag = 1;
+ /*
+ * test suite support - undocumented
+ * bflag == 2 (aka, -b -b) means to
+ * only process 1 per kid
+ */
+ if (bflag)
+ bflag = 2;
+ else
+ bflag = 1;
break;
case 'e':
@@ -468,6 +477,12 @@
slashdir = argv[0];
debug((DEBUG_OBESE, "myname is %s, slashdir is %s", myname, slashdir));
+#ifdef _SC_PAGESIZE
+ page_size = (long)sysconf(_SC_PAGESIZE);
+#else
+ page_size = 4096;
+#endif
+
/*
* initialise ssl and daemon mode if necessary.
*/
@@ -515,14 +530,6 @@
error(1, "setuid(%d): %s", uid, strerror(errno));
/*
- * be sane, don't start serving up files from a
- * hierarchy we don't have permission to get to.
- */
- if (tflag != NULL)
- if (chdir("/") == -1)
- error(1, "chdir /: %s", strerror(errno));
-
- /*
* read and process the HTTP request.
*/
do {
@@ -530,9 +537,8 @@
if (request) {
process_request(request);
clean_request(request);
- return (0);
}
- } while (bflag && 0);
+ } while (bflag);
return (0);
}
@@ -871,34 +877,6 @@
}
}
- if (request->hr_range != NULL) {
- debug((DEBUG_FAT, "hr_range: %s", request->hr_range));
- /* support only simple ranges %d- and %d-%d */
- if (strchr(request->hr_range, ',') == NULL) {
- const char *rstart, *dash;
-
- rstart = strchr(request->hr_range, '=');
- if (rstart != NULL) {
- rstart++;
- dash = strchr(rstart, '-');
- if (dash != NULL && dash != rstart) {
- dash++;
- request->hr_have_range = 1;
- request->hr_first_byte_pos =
- strtoll(rstart, NULL, 10);
- if (request->hr_first_byte_pos < 0)
- request->hr_first_byte_pos = 0;
- if (*dash != '\0') {
- request->hr_last_byte_pos =
- strtoll(dash, NULL, 10);
- if (request->hr_last_byte_pos < 0)
- request->hr_last_byte_pos = -1;
- }
- }
- }
- }
- }
-
debug((DEBUG_FAT, "read_request returns url %s in request",
request->hr_file));
return (request);
@@ -957,23 +935,42 @@
static int
mmap_and_write_part(int fd, off_t first_byte_pos, size_t sz)
{
- size_t mappedsz;
+ size_t mappedsz, wroffset;
+ off_t mappedoffset;
char *addr;
- void *oaddr;
+ void *mappedaddr;
+
+ /*
+ * we need to ensure that both the size *and* offset arguments to
+ * mmap() are page-aligned. our formala for this is:
+ *
+ * input offset: first_byte_pos
+ * input size: sz
+ *
+ * mapped offset = page align truncate (input offset)
+ * mapped size =
+ * page align extend (input offset - mapped offset + input size)
+ * write offset = input offset - mapped offset
+ *
+ * we use the write offset in all writes
+ */
+ mappedoffset = first_byte_pos & ~(page_size - 1);
+ mappedsz = (first_byte_pos - mappedoffset + sz + page_size - 1) &
+ ~(page_size - 1);
+ wroffset = first_byte_pos - mappedoffset;
- addr = mmap(0, sz, PROT_READ, MAP_SHARED, fd, first_byte_pos);
+ addr = mmap(0, mappedsz, PROT_READ, MAP_SHARED, fd, mappedoffset);
if (addr == (char *)-1) {
warning("mmap failed: %s", strerror(errno));
return -1;
}
- oaddr = addr;
- mappedsz = sz;
+ mappedaddr = addr;
#ifdef MADV_SEQUENTIAL
(void)madvise(addr, sz, MADV_SEQUENTIAL);
#endif
while (sz > WRSZ) {
- if (bozowrite(STDOUT_FILENO, addr, WRSZ) != WRSZ) {
+ if (bozowrite(STDOUT_FILENO, addr + wroffset, WRSZ) != WRSZ) {
warning("write failed: %s", strerror(errno));
goto out;
}
@@ -981,13 +978,13 @@
sz -= WRSZ;
addr += WRSZ;
}
- if (sz && (size_t)bozowrite(STDOUT_FILENO, addr, sz) != sz) {
+ if (sz && (size_t)bozowrite(STDOUT_FILENO, addr + wroffset, sz) != sz) {
warning("final write failed: %s", strerror(errno));
goto out;
}
debug((DEBUG_OBESE, "wrote %d bytes", (int)sz));
out:
- if (munmap(oaddr, mappedsz) < 0) {
+ if (munmap(mappedaddr, mappedsz) < 0) {
warning("munmap failed");
return -1;
}
@@ -1051,7 +1048,7 @@
(void)http_error(404, request, "no file");
} else
(void)http_error(500, request, "open file");
- return;
+ goto cleanup_nofd;
}
if (fstat(fd, &sb) < 0) {
(void)http_error(500, request, "can't fstat");
@@ -1101,26 +1098,41 @@
if (request->hr_method != HTTP_HEAD) {
off_t szleft, cur_byte_pos;
+ static size_t mmapsz = MMAPSZ;
szleft =
request->hr_last_byte_pos - request->hr_first_byte_pos + 1;
cur_byte_pos = request->hr_first_byte_pos;
+ retry:
while (szleft) {
size_t sz;
- if (MMAPSZ < szleft)
- sz = MMAPSZ;
+ /* This should take care of the first unaligned chunk */
+ if ((cur_byte_pos & (page_size - 1)) != 0)
+ sz = cur_byte_pos & ~page_size;
+ if (mmapsz < szleft)
+ sz = mmapsz;
else
sz = szleft;
- if (mmap_and_write_part(fd, cur_byte_pos, sz))
+ if (mmap_and_write_part(fd, cur_byte_pos, sz)) {
+ if (errno == ENOMEM) {
+ mmapsz /= 2;
+ if (mmapsz >= page_size)
+ goto retry;
+ }
goto cleanup;
+ }
cur_byte_pos += sz;
szleft -= sz;
}
}
-cleanup:
+ cleanup:
close(fd);
+ cleanup_nofd:
+ close(STDIN_FILENO);
+ close(STDOUT_FILENO);
+ /*close(STDERR_FILENO);*/
}
/*
@@ -1821,6 +1833,7 @@
va_start(ap, fmt);
if (sflag || isatty(STDERR_FILENO)) {
+ //fputs("warning: ", stderr);
vfprintf(stderr, fmt, ap);
fputs("\n", stderr);
} else
@@ -1835,6 +1848,7 @@
va_start(ap, fmt);
if (sflag || isatty(STDERR_FILENO)) {
+ //fputs("error: ", stderr);
vfprintf(stderr, fmt, ap);
fputs("\n", stderr);
} else
@@ -2016,13 +2030,7 @@
buflen *= 2;
debug((DEBUG_EXPLODING, "bozodgetln: "
"reallocating buffer to buflen %zu", buflen));
- nbuffer = realloc(buffer, buflen);
- if (nbuffer == NULL) {
- free(buffer);
- buflen = 0;
- buffer = NULL;
- return NULL;
- }
+ nbuffer = bozorealloc(buffer, buflen);
buffer = nbuffer;
}
Index: src/libexec/httpd/cgi-bozo.c
diff -u src/libexec/httpd/cgi-bozo.c:1.13 src/libexec/httpd/cgi-bozo.c:1.14
--- src/libexec/httpd/cgi-bozo.c:1.13 Sat Apr 18 21:22:03 2009
+++ src/libexec/httpd/cgi-bozo.c Sat May 23 02:26:03 2009
@@ -1,6 +1,6 @@
-/* $NetBSD: cgi-bozo.c,v 1.13 2009/04/18 21:22:03 mrg Exp $ */
+/* $NetBSD: cgi-bozo.c,v 1.14 2009/05/23 02:26:03 mrg Exp $ */
-/* $eterna: cgi-bozo.c,v 1.30 2009/04/18 12:39:28 mrg Exp $ */
+/* $eterna: cgi-bozo.c,v 1.32 2009/05/22 21:51:38 mrg Exp $ */
/*
* Copyright (c) 1997-2009 Matthew R. Green
@@ -165,10 +165,6 @@
nph = strncmp(command, "nph-", 4) == 0;
- debug((DEBUG_FAT,
- "process_cgi: path `%s' cmd `%s' info `%s' query `%s' nph `%d'",
- path, command, strornull(info), strornull(query), nph));
-
type = request->hr_content_type;
clen = request->hr_content_length;
@@ -182,6 +178,10 @@
auth_cgi_count(request) +
(request->hr_serverport && *request->hr_serverport ? 1 : 0);
+ debug((DEBUG_FAT,
+ "process_cgi: path `%s' cmd `%s' info `%s' query `%s' nph `%d' envpsize `%d'",
+ path, command, strornull(info), strornull(query), nph, envpsize));
+
envp = bozomalloc(sizeof(*envp) * envpsize);
for (ix = 0; ix < envpsize; ix++)
envp[ix] = NULL;
@@ -208,7 +208,7 @@
spsetenv(env, headp->h_value, curenvp++);
free(env);
}
-
+
#ifndef _PATH_DEFPATH
#define _PATH_DEFPATH "/usr/bin:/bin"
#endif
@@ -265,6 +265,7 @@
close(2);
close(sv[1]);
closelog();
+ daemon_closefds();
if (-1 == execve(path, argv, envp))
error(1, "child exec failed: %s: %s",
Index: src/libexec/httpd/bozohttpd.h
diff -u src/libexec/httpd/bozohttpd.h:1.10 src/libexec/httpd/bozohttpd.h:1.11
--- src/libexec/httpd/bozohttpd.h:1.10 Sat Apr 18 21:22:03 2009
+++ src/libexec/httpd/bozohttpd.h Sat May 23 02:26:03 2009
@@ -1,6 +1,6 @@
-/* $NetBSD: bozohttpd.h,v 1.10 2009/04/18 21:22:03 mrg Exp $ */
+/* $NetBSD: bozohttpd.h,v 1.11 2009/05/23 02:26:03 mrg Exp $ */
-/* $eterna: bozohttpd.h,v 1.26 2009/04/18 07:38:56 mrg Exp $ */
+/* $eterna: bozohttpd.h,v 1.27 2009/05/22 21:51:38 mrg Exp $ */
/*
* Copyright (c) 1997-2009 Matthew R. Green
@@ -201,9 +201,11 @@
extern void daemon_init(void);
extern void daemon_fork(void);
+extern void daemon_closefds(void);
#else
#define daemon_init() /* nothing */
#define daemon_fork() /* nothing */
+#define daemon_closefds() /* nothing */
#endif /* NO_DAEMON_MODE */
@@ -214,6 +216,7 @@
int user_transform(http_req *, int *);
#else
+#define uflag 0
#define user_transform(a, b) 0
#endif /* NO_USER_SUPPORT */
Index: src/libexec/httpd/daemon-bozo.c
diff -u src/libexec/httpd/daemon-bozo.c:1.6 src/libexec/httpd/daemon-bozo.c:1.7
--- src/libexec/httpd/daemon-bozo.c:1.6 Sat Apr 18 21:22:03 2009
+++ src/libexec/httpd/daemon-bozo.c Sat May 23 02:26:03 2009
@@ -1,6 +1,6 @@
-/* $NetBSD: daemon-bozo.c,v 1.6 2009/04/18 21:22:03 mrg Exp $ */
+/* $NetBSD: daemon-bozo.c,v 1.7 2009/05/23 02:26:03 mrg Exp $ */
-/* $eterna: daemon-bozo.c,v 1.16 2009/04/18 13:06:45 mrg Exp $ */
+/* $eterna: daemon-bozo.c,v 1.17 2009/05/22 21:51:38 mrg Exp $ */
/*
* Copyright (c) 1997-2009 Matthew R. Green
@@ -52,9 +52,23 @@
char *iflag; /* bind address; default INADDR_ANY */
static int *sock; /* bound sockets */
static int nsock; /* number of above */
+static struct pollfd *fds; /* current poll fd set */
+static int request_times; /* how many times this proc has processed
+ a request */
+static void daemon_runchild(int);
static void sigchild(int); /* SIGCHLD handler */
+#ifndef POLLRDNORM
+#define POLLRDNORM 0
+#endif
+#ifndef POLLRDBAND
+#define POLLRDBAND 0
+#endif
+#ifndef INFTIM
+#define INFTIM -1
+#endif
+
/* ARGSUSED */
static void
sigchild(signo)
@@ -90,6 +104,7 @@
for (r = r0; r != NULL; r = r->ai_next)
nsock++;
sock = bozomalloc(nsock * sizeof *sock);
+ fds = bozomalloc(nsock * sizeof *fds);
for (i = 0, r = r0; r != NULL; r = r->ai_next) {
sock[i] = socket(r->ai_family, SOCK_STREAM, 0);
if (sock[i] == -1)
@@ -102,6 +117,9 @@
continue;
if (listen(sock[i], SOMAXCONN) == -1)
continue;
+ fds[i].events = POLLIN | POLLPRI | POLLRDNORM |
+ POLLRDBAND | POLLERR;
+ fds[i].fd = sock[i];
i++;
}
if (i == 0)
@@ -112,6 +130,28 @@
signal(SIGCHLD, sigchild);
}
+void
+daemon_closefds(void)
+{
+ int i;
+
+ for (i = 0; i < nsock; i++)
+ close(sock[i]);
+}
+
+static void
+daemon_runchild(int fd)
+{
+
+ request_times++;
+
+ /* setup stdin/stdout/stderr */
+ dup2(fd, 0);
+ dup2(fd, 1);
+ /*dup2(fd, 2);*/
+ close(fd);
+}
+
/*
* the parent never returns from this function, only children that
* are ready to run... XXXMRG - still true in fork-lesser bozo?
@@ -119,27 +159,13 @@
void
daemon_fork()
{
- struct pollfd *fds = NULL;
- int i, j;
+ int i;
-#ifndef POLLRDNORM
-#define POLLRDNORM 0
-#endif
-#ifndef POLLRDBAND
-#define POLLRDBAND 0
-#endif
-#ifndef INFTIM
-#define INFTIM -1
-#endif
-
- fds = bozomalloc(nsock * sizeof *fds);
- for (i = 0; i < nsock; i++) {
- if (sock[i] == -1)
- continue;
- fds[i].events = POLLIN | POLLPRI | POLLRDNORM |
- POLLRDBAND | POLLERR;
- fds[i].fd = sock[i];
- }
+ debug((DEBUG_FAT, "%s: pid %u request_times %d", __func__, getpid(),
+ request_times));
+ /* if we've handled 5 files, exit and let someone else work */
+ if (request_times > 5 || (bflag == 2 && request_times > 0))
+ exit(0);
while (bflag) {
struct sockaddr_storage ss;
@@ -173,7 +199,8 @@
for (i = 0; i < nsock; i++) {
if (fds[i].revents & (POLLNVAL|POLLERR|POLLHUP)) {
warning("poll on fd %d pid %d revents %d: %s",
- fds[i].fd, getpid(), fds[i].revents, strerror(errno));
+ fds[i].fd, getpid(), fds[i].revents,
+ strerror(errno));
warning("nsock = %d", nsock);
close(sock[i]);
nsock--;
@@ -206,33 +233,30 @@
continue;
}
+
+ if (request_times > 0) {
+ daemon_runchild(fd);
+ return;
+ }
+
switch (fork()) {
case -1: /* eep, failure */
- warning("fork() failed, sleeping for 10 seconds: %s",
- strerror(errno));
+ warning("fork() failed, sleeping for "
+ "10 seconds: %s", strerror(errno));
close(fd);
sleep(10);
- continue;
+ break;
case 0: /* child */
- /* setup stdin/stdout/stderr */
- dup2(fd, 0);
- dup2(fd, 1);
- /*dup2(fd, 2);*/
- free(fds);
- free(sock);
- close(fd);
- for (j = 0; j < nsock; j++)
- close(sock[j]);
+ daemon_runchild(fd);
return;
default: /* parent */
close(fd);
- continue;
+ break;
}
}
}
- free(fds);
}
#endif /* NO_DAEMON_MODE */
Index: src/libexec/httpd/testsuite/Makefile
diff -u src/libexec/httpd/testsuite/Makefile:1.3 src/libexec/httpd/testsuite/Makefile:1.4
--- src/libexec/httpd/testsuite/Makefile:1.3 Sat Apr 18 07:48:02 2009
+++ src/libexec/httpd/testsuite/Makefile Sat May 23 02:26:03 2009
@@ -1,7 +1,11 @@
-# $eterna: Makefile,v 1.13 2008/03/04 04:46:38 mrg Exp $
+# $eterna: Makefile,v 1.14 2009/05/22 21:51:39 mrg Exp $
SIMPLETESTS= t1 t2 t3 t4 t5 t6 t7 t8 t9 t10
+BIGFILETESTS= partial4000 partial8000
+
BOZOHTTPD?= ../bozohttpd
+BOZOHTTPD?= ../debug/bozohttpd-debug
+WGET?= wget
all:
@@ -10,11 +14,19 @@
rm -f tmp.$$a.out; \
done
-check:
+check: check-simple check-bigfile
+
+check-simple:
.for a in $(SIMPLETESTS)
echo "Running test $a"
$(BOZOHTTPD) ./data < $(.CURDIR)/$a.in > tmp.$a.out || true
$(.CURDIR)/html_cmp $(.CURDIR)/$a.out tmp.$a.out
.endfor
+check-bigfile:
+.for a in $(BIGFILETESTS)
+ echo "Running test $a"
+ $(.CURDIR)/test-bigfile "$a" "${BOZOHTTPD}" "${WGET}" "./data"
+.endfor
+
.include <bsd.obj.mk>