xref: /minix3/libexec/httpd/daemon-bozo.c (revision 340f5e56603e4275faeb89a9aacace41ba22d661)
1*340f5e56SDavid van Moolenbroek /*	$NetBSD: daemon-bozo.c,v 1.16 2014/01/02 08:21:38 mrg Exp $	*/
2*340f5e56SDavid van Moolenbroek 
3*340f5e56SDavid van Moolenbroek /*	$eterna: daemon-bozo.c,v 1.24 2011/11/18 09:21:15 mrg Exp $	*/
4*340f5e56SDavid van Moolenbroek 
5*340f5e56SDavid van Moolenbroek /*
6*340f5e56SDavid van Moolenbroek  * Copyright (c) 1997-2014 Matthew R. Green
7*340f5e56SDavid van Moolenbroek  * All rights reserved.
8*340f5e56SDavid van Moolenbroek  *
9*340f5e56SDavid van Moolenbroek  * Redistribution and use in source and binary forms, with or without
10*340f5e56SDavid van Moolenbroek  * modification, are permitted provided that the following conditions
11*340f5e56SDavid van Moolenbroek  * are met:
12*340f5e56SDavid van Moolenbroek  * 1. Redistributions of source code must retain the above copyright
13*340f5e56SDavid van Moolenbroek  *    notice, this list of conditions and the following disclaimer.
14*340f5e56SDavid van Moolenbroek  * 2. Redistributions in binary form must reproduce the above copyright
15*340f5e56SDavid van Moolenbroek  *    notice, this list of conditions and the following disclaimer and
16*340f5e56SDavid van Moolenbroek  *    dedication in the documentation and/or other materials provided
17*340f5e56SDavid van Moolenbroek  *    with the distribution.
18*340f5e56SDavid van Moolenbroek  *
19*340f5e56SDavid van Moolenbroek  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20*340f5e56SDavid van Moolenbroek  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21*340f5e56SDavid van Moolenbroek  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22*340f5e56SDavid van Moolenbroek  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23*340f5e56SDavid van Moolenbroek  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24*340f5e56SDavid van Moolenbroek  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25*340f5e56SDavid van Moolenbroek  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26*340f5e56SDavid van Moolenbroek  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27*340f5e56SDavid van Moolenbroek  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28*340f5e56SDavid van Moolenbroek  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29*340f5e56SDavid van Moolenbroek  * SUCH DAMAGE.
30*340f5e56SDavid van Moolenbroek  *
31*340f5e56SDavid van Moolenbroek  */
32*340f5e56SDavid van Moolenbroek 
33*340f5e56SDavid van Moolenbroek /* this code implements daemon mode for bozohttpd */
34*340f5e56SDavid van Moolenbroek 
35*340f5e56SDavid van Moolenbroek #ifndef NO_DAEMON_MODE
36*340f5e56SDavid van Moolenbroek 
37*340f5e56SDavid van Moolenbroek #include <sys/param.h>
38*340f5e56SDavid van Moolenbroek #include <sys/socket.h>
39*340f5e56SDavid van Moolenbroek #include <sys/wait.h>
40*340f5e56SDavid van Moolenbroek 
41*340f5e56SDavid van Moolenbroek #include <netinet/in.h>
42*340f5e56SDavid van Moolenbroek 
43*340f5e56SDavid van Moolenbroek #include <assert.h>
44*340f5e56SDavid van Moolenbroek #include <errno.h>
45*340f5e56SDavid van Moolenbroek #include <netdb.h>
46*340f5e56SDavid van Moolenbroek #include <poll.h>
47*340f5e56SDavid van Moolenbroek #include <stdio.h>
48*340f5e56SDavid van Moolenbroek #include <stdlib.h>
49*340f5e56SDavid van Moolenbroek #include <string.h>
50*340f5e56SDavid van Moolenbroek #include <unistd.h>
51*340f5e56SDavid van Moolenbroek 
52*340f5e56SDavid van Moolenbroek #include "bozohttpd.h"
53*340f5e56SDavid van Moolenbroek 
54*340f5e56SDavid van Moolenbroek static	void	sigchild(int);	/* SIGCHLD handler */
55*340f5e56SDavid van Moolenbroek 
56*340f5e56SDavid van Moolenbroek #ifndef POLLRDNORM
57*340f5e56SDavid van Moolenbroek #define POLLRDNORM 0
58*340f5e56SDavid van Moolenbroek #endif
59*340f5e56SDavid van Moolenbroek #ifndef POLLRDBAND
60*340f5e56SDavid van Moolenbroek #define POLLRDBAND 0
61*340f5e56SDavid van Moolenbroek #endif
62*340f5e56SDavid van Moolenbroek #ifndef INFTIM
63*340f5e56SDavid van Moolenbroek #define INFTIM -1
64*340f5e56SDavid van Moolenbroek #endif
65*340f5e56SDavid van Moolenbroek 
66*340f5e56SDavid van Moolenbroek static const char* pidfile_path = NULL;
67*340f5e56SDavid van Moolenbroek static pid_t pidfile_pid = 0;
68*340f5e56SDavid van Moolenbroek 
69*340f5e56SDavid van Moolenbroek /* ARGSUSED */
70*340f5e56SDavid van Moolenbroek static void
sigchild(int signo)71*340f5e56SDavid van Moolenbroek sigchild(int signo)
72*340f5e56SDavid van Moolenbroek {
73*340f5e56SDavid van Moolenbroek 	while (waitpid(-1, NULL, WNOHANG) > 0) {
74*340f5e56SDavid van Moolenbroek 	}
75*340f5e56SDavid van Moolenbroek }
76*340f5e56SDavid van Moolenbroek 
77*340f5e56SDavid van Moolenbroek /* Signal handler to exit in a controlled manner.  This ensures that
78*340f5e56SDavid van Moolenbroek  * any atexit(3) handlers are properly executed. */
79*340f5e56SDavid van Moolenbroek /* ARGSUSED */
80*340f5e56SDavid van Moolenbroek BOZO_DEAD static void
controlled_exit(int signo)81*340f5e56SDavid van Moolenbroek controlled_exit(int signo)
82*340f5e56SDavid van Moolenbroek {
83*340f5e56SDavid van Moolenbroek 
84*340f5e56SDavid van Moolenbroek 	exit(EXIT_SUCCESS);
85*340f5e56SDavid van Moolenbroek }
86*340f5e56SDavid van Moolenbroek 
87*340f5e56SDavid van Moolenbroek static void
remove_pidfile(void)88*340f5e56SDavid van Moolenbroek remove_pidfile(void)
89*340f5e56SDavid van Moolenbroek {
90*340f5e56SDavid van Moolenbroek 
91*340f5e56SDavid van Moolenbroek 	if (pidfile_path != NULL && pidfile_pid == getpid()) {
92*340f5e56SDavid van Moolenbroek 		(void)unlink(pidfile_path);
93*340f5e56SDavid van Moolenbroek 		pidfile_path = NULL;
94*340f5e56SDavid van Moolenbroek 	}
95*340f5e56SDavid van Moolenbroek }
96*340f5e56SDavid van Moolenbroek 
97*340f5e56SDavid van Moolenbroek static void
create_pidfile(bozohttpd_t * httpd)98*340f5e56SDavid van Moolenbroek create_pidfile(bozohttpd_t *httpd)
99*340f5e56SDavid van Moolenbroek {
100*340f5e56SDavid van Moolenbroek 	FILE *file;
101*340f5e56SDavid van Moolenbroek 
102*340f5e56SDavid van Moolenbroek 	assert(pidfile_path == NULL);
103*340f5e56SDavid van Moolenbroek 
104*340f5e56SDavid van Moolenbroek 	if (httpd->pidfile == NULL)
105*340f5e56SDavid van Moolenbroek 		return;
106*340f5e56SDavid van Moolenbroek 
107*340f5e56SDavid van Moolenbroek 	if (atexit(remove_pidfile) == -1)
108*340f5e56SDavid van Moolenbroek 		bozo_err(httpd, 1, "Failed to install pidfile handler");
109*340f5e56SDavid van Moolenbroek 
110*340f5e56SDavid van Moolenbroek 	if ((file = fopen(httpd->pidfile, "w")) == NULL)
111*340f5e56SDavid van Moolenbroek 		bozo_err(httpd, 1, "Failed to create pidfile '%s'",
112*340f5e56SDavid van Moolenbroek 		    httpd->pidfile);
113*340f5e56SDavid van Moolenbroek 	(void)fprintf(file, "%d\n", getpid());
114*340f5e56SDavid van Moolenbroek 	(void)fclose(file);
115*340f5e56SDavid van Moolenbroek 
116*340f5e56SDavid van Moolenbroek 	pidfile_path = httpd->pidfile;
117*340f5e56SDavid van Moolenbroek 	pidfile_pid = getpid();
118*340f5e56SDavid van Moolenbroek 
119*340f5e56SDavid van Moolenbroek 	debug((httpd, DEBUG_FAT, "Created pid file '%s' for pid %d",
120*340f5e56SDavid van Moolenbroek 	    pidfile_path, pidfile_pid));
121*340f5e56SDavid van Moolenbroek }
122*340f5e56SDavid van Moolenbroek 
123*340f5e56SDavid van Moolenbroek void
bozo_daemon_init(bozohttpd_t * httpd)124*340f5e56SDavid van Moolenbroek bozo_daemon_init(bozohttpd_t *httpd)
125*340f5e56SDavid van Moolenbroek {
126*340f5e56SDavid van Moolenbroek 	struct addrinfo h, *r, *r0;
127*340f5e56SDavid van Moolenbroek 	const char	*portnum;
128*340f5e56SDavid van Moolenbroek 	int e, i, on = 1;
129*340f5e56SDavid van Moolenbroek 
130*340f5e56SDavid van Moolenbroek 	if (!httpd->background)
131*340f5e56SDavid van Moolenbroek 		return;
132*340f5e56SDavid van Moolenbroek 
133*340f5e56SDavid van Moolenbroek 	portnum = (httpd->bindport) ? httpd->bindport : "http";
134*340f5e56SDavid van Moolenbroek 
135*340f5e56SDavid van Moolenbroek 	memset(&h, 0, sizeof(h));
136*340f5e56SDavid van Moolenbroek 	h.ai_family = PF_UNSPEC;
137*340f5e56SDavid van Moolenbroek 	h.ai_socktype = SOCK_STREAM;
138*340f5e56SDavid van Moolenbroek 	h.ai_flags = AI_PASSIVE;
139*340f5e56SDavid van Moolenbroek 	e = getaddrinfo(httpd->bindaddress, portnum, &h, &r0);
140*340f5e56SDavid van Moolenbroek 	if (e)
141*340f5e56SDavid van Moolenbroek 		bozo_err(httpd, 1, "getaddrinfo([%s]:%s): %s",
142*340f5e56SDavid van Moolenbroek 		    httpd->bindaddress ? httpd->bindaddress : "*",
143*340f5e56SDavid van Moolenbroek 		    portnum, gai_strerror(e));
144*340f5e56SDavid van Moolenbroek 	for (r = r0; r != NULL; r = r->ai_next)
145*340f5e56SDavid van Moolenbroek 		httpd->nsock++;
146*340f5e56SDavid van Moolenbroek 	httpd->sock = bozomalloc(httpd, httpd->nsock * sizeof(*httpd->sock));
147*340f5e56SDavid van Moolenbroek 	httpd->fds = bozomalloc(httpd, httpd->nsock * sizeof(*httpd->fds));
148*340f5e56SDavid van Moolenbroek 	for (i = 0, r = r0; r != NULL; r = r->ai_next) {
149*340f5e56SDavid van Moolenbroek 		httpd->sock[i] = socket(r->ai_family, SOCK_STREAM, 0);
150*340f5e56SDavid van Moolenbroek 		if (httpd->sock[i] == -1)
151*340f5e56SDavid van Moolenbroek 			continue;
152*340f5e56SDavid van Moolenbroek 		if (setsockopt(httpd->sock[i], SOL_SOCKET, SO_REUSEADDR, &on,
153*340f5e56SDavid van Moolenbroek 		    sizeof(on)) == -1)
154*340f5e56SDavid van Moolenbroek 			bozo_warn(httpd, "setsockopt SO_REUSEADDR: %s",
155*340f5e56SDavid van Moolenbroek 			    strerror(errno));
156*340f5e56SDavid van Moolenbroek 		if (bind(httpd->sock[i], r->ai_addr, r->ai_addrlen) == -1)
157*340f5e56SDavid van Moolenbroek 			continue;
158*340f5e56SDavid van Moolenbroek 		if (listen(httpd->sock[i], SOMAXCONN) == -1)
159*340f5e56SDavid van Moolenbroek 			continue;
160*340f5e56SDavid van Moolenbroek 		httpd->fds[i].events = POLLIN | POLLPRI | POLLRDNORM |
161*340f5e56SDavid van Moolenbroek 				POLLRDBAND | POLLERR;
162*340f5e56SDavid van Moolenbroek 		httpd->fds[i].fd = httpd->sock[i];
163*340f5e56SDavid van Moolenbroek 		i++;
164*340f5e56SDavid van Moolenbroek 	}
165*340f5e56SDavid van Moolenbroek 	if (i == 0)
166*340f5e56SDavid van Moolenbroek 		bozo_err(httpd, 1, "could not find any addresses to bind");
167*340f5e56SDavid van Moolenbroek 	httpd->nsock = i;
168*340f5e56SDavid van Moolenbroek 	freeaddrinfo(r0);
169*340f5e56SDavid van Moolenbroek 
170*340f5e56SDavid van Moolenbroek 	if (httpd->foreground == 0)
171*340f5e56SDavid van Moolenbroek 		daemon(1, 0);
172*340f5e56SDavid van Moolenbroek 
173*340f5e56SDavid van Moolenbroek 	create_pidfile(httpd);
174*340f5e56SDavid van Moolenbroek 
175*340f5e56SDavid van Moolenbroek 	bozo_warn(httpd, "started in daemon mode as `%s' port `%s' root `%s'",
176*340f5e56SDavid van Moolenbroek 	    httpd->virthostname, portnum, httpd->slashdir);
177*340f5e56SDavid van Moolenbroek 
178*340f5e56SDavid van Moolenbroek 	signal(SIGHUP, controlled_exit);
179*340f5e56SDavid van Moolenbroek 	signal(SIGINT, controlled_exit);
180*340f5e56SDavid van Moolenbroek 	signal(SIGTERM, controlled_exit);
181*340f5e56SDavid van Moolenbroek 
182*340f5e56SDavid van Moolenbroek 	signal(SIGCHLD, sigchild);
183*340f5e56SDavid van Moolenbroek }
184*340f5e56SDavid van Moolenbroek 
185*340f5e56SDavid van Moolenbroek void
bozo_daemon_closefds(bozohttpd_t * httpd)186*340f5e56SDavid van Moolenbroek bozo_daemon_closefds(bozohttpd_t *httpd)
187*340f5e56SDavid van Moolenbroek {
188*340f5e56SDavid van Moolenbroek 	int i;
189*340f5e56SDavid van Moolenbroek 
190*340f5e56SDavid van Moolenbroek 	for (i = 0; i < httpd->nsock; i++)
191*340f5e56SDavid van Moolenbroek 		close(httpd->sock[i]);
192*340f5e56SDavid van Moolenbroek }
193*340f5e56SDavid van Moolenbroek 
194*340f5e56SDavid van Moolenbroek static void
daemon_runchild(bozohttpd_t * httpd,int fd)195*340f5e56SDavid van Moolenbroek daemon_runchild(bozohttpd_t *httpd, int fd)
196*340f5e56SDavid van Moolenbroek {
197*340f5e56SDavid van Moolenbroek 	httpd->request_times++;
198*340f5e56SDavid van Moolenbroek 
199*340f5e56SDavid van Moolenbroek 	/* setup stdin/stdout/stderr */
200*340f5e56SDavid van Moolenbroek 	dup2(fd, 0);
201*340f5e56SDavid van Moolenbroek 	dup2(fd, 1);
202*340f5e56SDavid van Moolenbroek 	/*dup2(fd, 2);*/
203*340f5e56SDavid van Moolenbroek 	close(fd);
204*340f5e56SDavid van Moolenbroek }
205*340f5e56SDavid van Moolenbroek 
206*340f5e56SDavid van Moolenbroek static int
daemon_poll_err(bozohttpd_t * httpd,int fd,int idx)207*340f5e56SDavid van Moolenbroek daemon_poll_err(bozohttpd_t *httpd, int fd, int idx)
208*340f5e56SDavid van Moolenbroek {
209*340f5e56SDavid van Moolenbroek 	if ((httpd->fds[idx].revents & (POLLNVAL|POLLERR|POLLHUP)) == 0)
210*340f5e56SDavid van Moolenbroek 		return 0;
211*340f5e56SDavid van Moolenbroek 
212*340f5e56SDavid van Moolenbroek 	bozo_warn(httpd, "poll on fd %d pid %d revents %d: %s",
213*340f5e56SDavid van Moolenbroek 	    httpd->fds[idx].fd, getpid(), httpd->fds[idx].revents,
214*340f5e56SDavid van Moolenbroek 	    strerror(errno));
215*340f5e56SDavid van Moolenbroek 	bozo_warn(httpd, "nsock = %d", httpd->nsock);
216*340f5e56SDavid van Moolenbroek 	close(httpd->sock[idx]);
217*340f5e56SDavid van Moolenbroek 	httpd->nsock--;
218*340f5e56SDavid van Moolenbroek 	bozo_warn(httpd, "nsock now = %d", httpd->nsock);
219*340f5e56SDavid van Moolenbroek 	/* no sockets left */
220*340f5e56SDavid van Moolenbroek 	if (httpd->nsock == 0)
221*340f5e56SDavid van Moolenbroek 		exit(0);
222*340f5e56SDavid van Moolenbroek 	/* last socket closed is the easy case */
223*340f5e56SDavid van Moolenbroek 	if (httpd->nsock != idx) {
224*340f5e56SDavid van Moolenbroek 		memmove(&httpd->fds[idx], &httpd->fds[idx+1],
225*340f5e56SDavid van Moolenbroek 			(httpd->nsock - idx) * sizeof(*httpd->fds));
226*340f5e56SDavid van Moolenbroek 		memmove(&httpd->sock[idx], &httpd->sock[idx+1],
227*340f5e56SDavid van Moolenbroek 			(httpd->nsock - idx) * sizeof(*httpd->sock));
228*340f5e56SDavid van Moolenbroek 	}
229*340f5e56SDavid van Moolenbroek 
230*340f5e56SDavid van Moolenbroek 	return 1;
231*340f5e56SDavid van Moolenbroek }
232*340f5e56SDavid van Moolenbroek 
233*340f5e56SDavid van Moolenbroek /*
234*340f5e56SDavid van Moolenbroek  * the parent never returns from this function, only children that
235*340f5e56SDavid van Moolenbroek  * are ready to run... XXXMRG - still true in fork-lesser bozo?
236*340f5e56SDavid van Moolenbroek  */
237*340f5e56SDavid van Moolenbroek int
bozo_daemon_fork(bozohttpd_t * httpd)238*340f5e56SDavid van Moolenbroek bozo_daemon_fork(bozohttpd_t *httpd)
239*340f5e56SDavid van Moolenbroek {
240*340f5e56SDavid van Moolenbroek 	int i;
241*340f5e56SDavid van Moolenbroek 
242*340f5e56SDavid van Moolenbroek 	debug((httpd, DEBUG_FAT, "%s: pid %u request_times %d",
243*340f5e56SDavid van Moolenbroek 		__func__, getpid(),
244*340f5e56SDavid van Moolenbroek 		httpd->request_times));
245*340f5e56SDavid van Moolenbroek 	/* if we've handled 5 files, exit and let someone else work */
246*340f5e56SDavid van Moolenbroek 	if (httpd->request_times > 5 ||
247*340f5e56SDavid van Moolenbroek 	    (httpd->background == 2 && httpd->request_times > 0))
248*340f5e56SDavid van Moolenbroek 		_exit(0);
249*340f5e56SDavid van Moolenbroek 
250*340f5e56SDavid van Moolenbroek #if 1
251*340f5e56SDavid van Moolenbroek 	if (httpd->request_times > 0)
252*340f5e56SDavid van Moolenbroek 		_exit(0);
253*340f5e56SDavid van Moolenbroek #endif
254*340f5e56SDavid van Moolenbroek 
255*340f5e56SDavid van Moolenbroek 	while (httpd->background) {
256*340f5e56SDavid van Moolenbroek 		struct	sockaddr_storage ss;
257*340f5e56SDavid van Moolenbroek 		socklen_t slen;
258*340f5e56SDavid van Moolenbroek 		int fd;
259*340f5e56SDavid van Moolenbroek 
260*340f5e56SDavid van Moolenbroek 		if (httpd->nsock == 0)
261*340f5e56SDavid van Moolenbroek 			exit(0);
262*340f5e56SDavid van Moolenbroek 
263*340f5e56SDavid van Moolenbroek 		/*
264*340f5e56SDavid van Moolenbroek 		 * wait for a connection, then fork() and return NULL in
265*340f5e56SDavid van Moolenbroek 		 * the parent, who will come back here waiting for another
266*340f5e56SDavid van Moolenbroek 		 * connection.  read the request in in the child, and return
267*340f5e56SDavid van Moolenbroek 		 * it, for processing.
268*340f5e56SDavid van Moolenbroek 		 */
269*340f5e56SDavid van Moolenbroek again:
270*340f5e56SDavid van Moolenbroek 		if (poll(httpd->fds, (unsigned)httpd->nsock, INFTIM) == -1) {
271*340f5e56SDavid van Moolenbroek 			/* fail on programmer errors */
272*340f5e56SDavid van Moolenbroek 			if (errno == EFAULT ||
273*340f5e56SDavid van Moolenbroek 			    errno == EINVAL)
274*340f5e56SDavid van Moolenbroek 				bozo_err(httpd, 1, "poll: %s",
275*340f5e56SDavid van Moolenbroek 					strerror(errno));
276*340f5e56SDavid van Moolenbroek 
277*340f5e56SDavid van Moolenbroek 			/* sleep on some temporary kernel failures */
278*340f5e56SDavid van Moolenbroek 			if (errno == ENOMEM ||
279*340f5e56SDavid van Moolenbroek 			    errno == EAGAIN)
280*340f5e56SDavid van Moolenbroek 				sleep(1);
281*340f5e56SDavid van Moolenbroek 
282*340f5e56SDavid van Moolenbroek 			goto again;
283*340f5e56SDavid van Moolenbroek 		}
284*340f5e56SDavid van Moolenbroek 
285*340f5e56SDavid van Moolenbroek 		for (i = 0; i < httpd->nsock; i++) {
286*340f5e56SDavid van Moolenbroek 			if (daemon_poll_err(httpd, fd, i))
287*340f5e56SDavid van Moolenbroek 				break;
288*340f5e56SDavid van Moolenbroek 			if (httpd->fds[i].revents == 0)
289*340f5e56SDavid van Moolenbroek 				continue;
290*340f5e56SDavid van Moolenbroek 
291*340f5e56SDavid van Moolenbroek 			slen = sizeof(ss);
292*340f5e56SDavid van Moolenbroek 			fd = accept(httpd->fds[i].fd,
293*340f5e56SDavid van Moolenbroek 					(struct sockaddr *)(void *)&ss, &slen);
294*340f5e56SDavid van Moolenbroek 			if (fd == -1) {
295*340f5e56SDavid van Moolenbroek 				if (errno == EFAULT ||
296*340f5e56SDavid van Moolenbroek 				    errno == EINVAL)
297*340f5e56SDavid van Moolenbroek 					bozo_err(httpd, 1, "accept: %s",
298*340f5e56SDavid van Moolenbroek 						strerror(errno));
299*340f5e56SDavid van Moolenbroek 
300*340f5e56SDavid van Moolenbroek 				if (errno == ENOMEM ||
301*340f5e56SDavid van Moolenbroek 				    errno == EAGAIN)
302*340f5e56SDavid van Moolenbroek 					sleep(1);
303*340f5e56SDavid van Moolenbroek 
304*340f5e56SDavid van Moolenbroek 				continue;
305*340f5e56SDavid van Moolenbroek 			}
306*340f5e56SDavid van Moolenbroek 
307*340f5e56SDavid van Moolenbroek #if 0
308*340f5e56SDavid van Moolenbroek 			/*
309*340f5e56SDavid van Moolenbroek 			 * This code doesn't work.  It interacts very poorly
310*340f5e56SDavid van Moolenbroek 			 * with ~user translation and needs to be fixed.
311*340f5e56SDavid van Moolenbroek 			 */
312*340f5e56SDavid van Moolenbroek 			if (httpd->request_times > 0) {
313*340f5e56SDavid van Moolenbroek 				daemon_runchild(httpd, fd);
314*340f5e56SDavid van Moolenbroek 				return 0;
315*340f5e56SDavid van Moolenbroek 			}
316*340f5e56SDavid van Moolenbroek #endif
317*340f5e56SDavid van Moolenbroek 
318*340f5e56SDavid van Moolenbroek 			switch (fork()) {
319*340f5e56SDavid van Moolenbroek 			case -1: /* eep, failure */
320*340f5e56SDavid van Moolenbroek 				bozo_warn(httpd, "fork() failed, sleeping for "
321*340f5e56SDavid van Moolenbroek 					"10 seconds: %s", strerror(errno));
322*340f5e56SDavid van Moolenbroek 				close(fd);
323*340f5e56SDavid van Moolenbroek 				sleep(10);
324*340f5e56SDavid van Moolenbroek 				break;
325*340f5e56SDavid van Moolenbroek 
326*340f5e56SDavid van Moolenbroek 			case 0: /* child */
327*340f5e56SDavid van Moolenbroek 				daemon_runchild(httpd, fd);
328*340f5e56SDavid van Moolenbroek 				return 0;
329*340f5e56SDavid van Moolenbroek 
330*340f5e56SDavid van Moolenbroek 			default: /* parent */
331*340f5e56SDavid van Moolenbroek 				close(fd);
332*340f5e56SDavid van Moolenbroek 				break;
333*340f5e56SDavid van Moolenbroek 			}
334*340f5e56SDavid van Moolenbroek 		}
335*340f5e56SDavid van Moolenbroek 	}
336*340f5e56SDavid van Moolenbroek 	return 0;
337*340f5e56SDavid van Moolenbroek }
338*340f5e56SDavid van Moolenbroek 
339*340f5e56SDavid van Moolenbroek #endif /* NO_DAEMON_MODE */
340