NetBSD/libexec/httpd/daemon-bozo.c

345 lines
8.1 KiB
C
Raw Normal View History

various updates from <henrik@gulbra.net> / freebsd. the list from Henrik: bozohttpd.8: o Added -d flag to the man page o Moved -E flag in man page to keep alphabetic order o Grammar fix for description of -E flag in man page o Moved a word in the man description for the -f flag o Made -f imply -b as a backwards-compatible shortcut o Updated man description of -n to mention Lua scripts o Moved -z below -Z to keep the uppercase options first bozohttpd.c: o Removed obsolete comment about ~user missing cgi-bin support o Removed "/* ARGSUSED */" lines; was that a macro or a reminder? o Added USE_ARG macro call for sig, which was otherwise not used o Added USE_ARG macro call for msg (only used if debug is enabled) bozohttpd.h: o Fixed typo in the include guard (BOZOHTTOPD_H_ -> BOZOHTTPD_H_) o Renamed have_all to have_core; it didn't mean "all" options content-bozo.c: o Added USE_ARG macro call for signo, which was otherwise not used o Made -f imply -b as a backwards-compatible shortcut main.c: o Simplified -b text to be symmetric with that for the -f option o Updated -C text to make "suffix" explicit; it's better than "arg" o Changed to only show the -E description if have_user is true o Always show the -e option, which incorrectly used the -E logic o Renamed have_all to have_core; it didn't mean "all" options o Added three missing tabs for the description of the -G option o Updated -L text to make "prefix" explicit; it's better than "arg" o Updated -M text to make "suffix" explicit; it's slightly better o Added a previously missing description for the -n option o Documented the otherwise obscure valid types for the -T option o Shortened "username" to "user" to match the actual help text o Moved handling of -c below that for -C to standardize the order o Broke the enabling test for -C into two lines for consistency o Inverted the enabling test for -E; this is what was meant, right? o Removed the enabling test for -e, which should always be enabled ssl-bozo.c: o Added USE_ARG for httpd, which is not used if SSL has been excluded
2020-10-15 07:21:53 +03:00
/* $NetBSD: daemon-bozo.c,v 1.22 2020/10/15 04:21:53 mrg Exp $ */
2007-10-17 22:47:59 +04:00
2011-11-18 13:51:31 +04:00
/* $eterna: daemon-bozo.c,v 1.24 2011/11/18 09:21:15 mrg Exp $ */
/*
* Copyright (c) 1997-2019 Matthew R. Green
* 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 and
* dedication in the documentation and/or other materials provided
* with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 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 AUTHOR 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 code implements daemon mode for bozohttpd */
#ifndef NO_DAEMON_MODE
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <assert.h>
#include <errno.h>
#include <netdb.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "bozohttpd.h"
static void sigchild(int); /* SIGCHLD handler */
2009-05-23 06:26:03 +04:00
#ifndef POLLRDNORM
#define POLLRDNORM 0
#endif
#ifndef POLLRDBAND
#define POLLRDBAND 0
#endif
#ifndef INFTIM
#define INFTIM -1
#endif
various updates from <henrik@gulbra.net> / freebsd. the list from Henrik: bozohttpd.8: o Added -d flag to the man page o Moved -E flag in man page to keep alphabetic order o Grammar fix for description of -E flag in man page o Moved a word in the man description for the -f flag o Made -f imply -b as a backwards-compatible shortcut o Updated man description of -n to mention Lua scripts o Moved -z below -Z to keep the uppercase options first bozohttpd.c: o Removed obsolete comment about ~user missing cgi-bin support o Removed "/* ARGSUSED */" lines; was that a macro or a reminder? o Added USE_ARG macro call for sig, which was otherwise not used o Added USE_ARG macro call for msg (only used if debug is enabled) bozohttpd.h: o Fixed typo in the include guard (BOZOHTTOPD_H_ -> BOZOHTTPD_H_) o Renamed have_all to have_core; it didn't mean "all" options content-bozo.c: o Added USE_ARG macro call for signo, which was otherwise not used o Made -f imply -b as a backwards-compatible shortcut main.c: o Simplified -b text to be symmetric with that for the -f option o Updated -C text to make "suffix" explicit; it's better than "arg" o Changed to only show the -E description if have_user is true o Always show the -e option, which incorrectly used the -E logic o Renamed have_all to have_core; it didn't mean "all" options o Added three missing tabs for the description of the -G option o Updated -L text to make "prefix" explicit; it's better than "arg" o Updated -M text to make "suffix" explicit; it's slightly better o Added a previously missing description for the -n option o Documented the otherwise obscure valid types for the -T option o Shortened "username" to "user" to match the actual help text o Moved handling of -c below that for -C to standardize the order o Broke the enabling test for -C into two lines for consistency o Inverted the enabling test for -E; this is what was meant, right? o Removed the enabling test for -e, which should always be enabled ssl-bozo.c: o Added USE_ARG for httpd, which is not used if SSL has been excluded
2020-10-15 07:21:53 +03:00
#ifndef USE_ARG
#define USE_ARG(x) /*LINTED*/(void)&(x)
#endif
2009-05-23 06:26:03 +04:00
static const char* pidfile_path = NULL;
static pid_t pidfile_pid = 0;
static void
2010-05-10 07:37:45 +04:00
sigchild(int signo)
{
various updates from <henrik@gulbra.net> / freebsd. the list from Henrik: bozohttpd.8: o Added -d flag to the man page o Moved -E flag in man page to keep alphabetic order o Grammar fix for description of -E flag in man page o Moved a word in the man description for the -f flag o Made -f imply -b as a backwards-compatible shortcut o Updated man description of -n to mention Lua scripts o Moved -z below -Z to keep the uppercase options first bozohttpd.c: o Removed obsolete comment about ~user missing cgi-bin support o Removed "/* ARGSUSED */" lines; was that a macro or a reminder? o Added USE_ARG macro call for sig, which was otherwise not used o Added USE_ARG macro call for msg (only used if debug is enabled) bozohttpd.h: o Fixed typo in the include guard (BOZOHTTOPD_H_ -> BOZOHTTPD_H_) o Renamed have_all to have_core; it didn't mean "all" options content-bozo.c: o Added USE_ARG macro call for signo, which was otherwise not used o Made -f imply -b as a backwards-compatible shortcut main.c: o Simplified -b text to be symmetric with that for the -f option o Updated -C text to make "suffix" explicit; it's better than "arg" o Changed to only show the -E description if have_user is true o Always show the -e option, which incorrectly used the -E logic o Renamed have_all to have_core; it didn't mean "all" options o Added three missing tabs for the description of the -G option o Updated -L text to make "prefix" explicit; it's better than "arg" o Updated -M text to make "suffix" explicit; it's slightly better o Added a previously missing description for the -n option o Documented the otherwise obscure valid types for the -T option o Shortened "username" to "user" to match the actual help text o Moved handling of -c below that for -C to standardize the order o Broke the enabling test for -C into two lines for consistency o Inverted the enabling test for -E; this is what was meant, right? o Removed the enabling test for -e, which should always be enabled ssl-bozo.c: o Added USE_ARG for httpd, which is not used if SSL has been excluded
2020-10-15 07:21:53 +03:00
USE_ARG(signo);
while (waitpid(-1, NULL, WNOHANG) > 0)
/* nothing */;
}
/* Signal handler to exit in a controlled manner. This ensures that
* any atexit(3) handlers are properly executed. */
BOZO_DEAD static void
controlled_exit(int signo)
{
various updates from <henrik@gulbra.net> / freebsd. the list from Henrik: bozohttpd.8: o Added -d flag to the man page o Moved -E flag in man page to keep alphabetic order o Grammar fix for description of -E flag in man page o Moved a word in the man description for the -f flag o Made -f imply -b as a backwards-compatible shortcut o Updated man description of -n to mention Lua scripts o Moved -z below -Z to keep the uppercase options first bozohttpd.c: o Removed obsolete comment about ~user missing cgi-bin support o Removed "/* ARGSUSED */" lines; was that a macro or a reminder? o Added USE_ARG macro call for sig, which was otherwise not used o Added USE_ARG macro call for msg (only used if debug is enabled) bozohttpd.h: o Fixed typo in the include guard (BOZOHTTOPD_H_ -> BOZOHTTPD_H_) o Renamed have_all to have_core; it didn't mean "all" options content-bozo.c: o Added USE_ARG macro call for signo, which was otherwise not used o Made -f imply -b as a backwards-compatible shortcut main.c: o Simplified -b text to be symmetric with that for the -f option o Updated -C text to make "suffix" explicit; it's better than "arg" o Changed to only show the -E description if have_user is true o Always show the -e option, which incorrectly used the -E logic o Renamed have_all to have_core; it didn't mean "all" options o Added three missing tabs for the description of the -G option o Updated -L text to make "prefix" explicit; it's better than "arg" o Updated -M text to make "suffix" explicit; it's slightly better o Added a previously missing description for the -n option o Documented the otherwise obscure valid types for the -T option o Shortened "username" to "user" to match the actual help text o Moved handling of -c below that for -C to standardize the order o Broke the enabling test for -C into two lines for consistency o Inverted the enabling test for -E; this is what was meant, right? o Removed the enabling test for -e, which should always be enabled ssl-bozo.c: o Added USE_ARG for httpd, which is not used if SSL has been excluded
2020-10-15 07:21:53 +03:00
USE_ARG(signo);
exit(EXIT_SUCCESS);
}
static void
remove_pidfile(void)
{
if (pidfile_path != NULL && pidfile_pid == getpid()) {
(void)unlink(pidfile_path);
pidfile_path = NULL;
}
}
static void
create_pidfile(bozohttpd_t *httpd)
{
FILE *file;
assert(pidfile_path == NULL);
if (httpd->pidfile == NULL)
return;
if (atexit(remove_pidfile) == -1)
bozoerr(httpd, 1, "Failed to install pidfile handler");
if ((file = fopen(httpd->pidfile, "w")) == NULL)
bozoerr(httpd, 1, "Failed to create pidfile '%s'",
httpd->pidfile);
(void)fprintf(file, "%d\n", getpid());
(void)fclose(file);
pidfile_path = httpd->pidfile;
pidfile_pid = getpid();
debug((httpd, DEBUG_FAT, "Created pid file '%s' for pid %d",
pidfile_path, pidfile_pid));
}
void
2010-05-10 07:37:45 +04:00
bozo_daemon_init(bozohttpd_t *httpd)
{
struct addrinfo h, *r, *r0;
2010-05-10 07:37:45 +04:00
const char *portnum;
int e, i, on = 1;
various updates from <henrik@gulbra.net> / freebsd. the list from Henrik: bozohttpd.8: o Added -d flag to the man page o Moved -E flag in man page to keep alphabetic order o Grammar fix for description of -E flag in man page o Moved a word in the man description for the -f flag o Made -f imply -b as a backwards-compatible shortcut o Updated man description of -n to mention Lua scripts o Moved -z below -Z to keep the uppercase options first bozohttpd.c: o Removed obsolete comment about ~user missing cgi-bin support o Removed "/* ARGSUSED */" lines; was that a macro or a reminder? o Added USE_ARG macro call for sig, which was otherwise not used o Added USE_ARG macro call for msg (only used if debug is enabled) bozohttpd.h: o Fixed typo in the include guard (BOZOHTTOPD_H_ -> BOZOHTTPD_H_) o Renamed have_all to have_core; it didn't mean "all" options content-bozo.c: o Added USE_ARG macro call for signo, which was otherwise not used o Made -f imply -b as a backwards-compatible shortcut main.c: o Simplified -b text to be symmetric with that for the -f option o Updated -C text to make "suffix" explicit; it's better than "arg" o Changed to only show the -E description if have_user is true o Always show the -e option, which incorrectly used the -E logic o Renamed have_all to have_core; it didn't mean "all" options o Added three missing tabs for the description of the -G option o Updated -L text to make "prefix" explicit; it's better than "arg" o Updated -M text to make "suffix" explicit; it's slightly better o Added a previously missing description for the -n option o Documented the otherwise obscure valid types for the -T option o Shortened "username" to "user" to match the actual help text o Moved handling of -c below that for -C to standardize the order o Broke the enabling test for -C into two lines for consistency o Inverted the enabling test for -E; this is what was meant, right? o Removed the enabling test for -e, which should always be enabled ssl-bozo.c: o Added USE_ARG for httpd, which is not used if SSL has been excluded
2020-10-15 07:21:53 +03:00
if (!httpd->background && !httpd->foreground)
return;
various updates from <henrik@gulbra.net> / freebsd. the list from Henrik: bozohttpd.8: o Added -d flag to the man page o Moved -E flag in man page to keep alphabetic order o Grammar fix for description of -E flag in man page o Moved a word in the man description for the -f flag o Made -f imply -b as a backwards-compatible shortcut o Updated man description of -n to mention Lua scripts o Moved -z below -Z to keep the uppercase options first bozohttpd.c: o Removed obsolete comment about ~user missing cgi-bin support o Removed "/* ARGSUSED */" lines; was that a macro or a reminder? o Added USE_ARG macro call for sig, which was otherwise not used o Added USE_ARG macro call for msg (only used if debug is enabled) bozohttpd.h: o Fixed typo in the include guard (BOZOHTTOPD_H_ -> BOZOHTTPD_H_) o Renamed have_all to have_core; it didn't mean "all" options content-bozo.c: o Added USE_ARG macro call for signo, which was otherwise not used o Made -f imply -b as a backwards-compatible shortcut main.c: o Simplified -b text to be symmetric with that for the -f option o Updated -C text to make "suffix" explicit; it's better than "arg" o Changed to only show the -E description if have_user is true o Always show the -e option, which incorrectly used the -E logic o Renamed have_all to have_core; it didn't mean "all" options o Added three missing tabs for the description of the -G option o Updated -L text to make "prefix" explicit; it's better than "arg" o Updated -M text to make "suffix" explicit; it's slightly better o Added a previously missing description for the -n option o Documented the otherwise obscure valid types for the -T option o Shortened "username" to "user" to match the actual help text o Moved handling of -c below that for -C to standardize the order o Broke the enabling test for -C into two lines for consistency o Inverted the enabling test for -E; this is what was meant, right? o Removed the enabling test for -e, which should always be enabled ssl-bozo.c: o Added USE_ARG for httpd, which is not used if SSL has been excluded
2020-10-15 07:21:53 +03:00
if (!httpd->background)
httpd->background = 1;
2010-05-10 07:37:45 +04:00
portnum = (httpd->bindport) ? httpd->bindport : "http";
2010-05-10 07:37:45 +04:00
memset(&h, 0, sizeof(h));
h.ai_family = PF_UNSPEC;
h.ai_socktype = SOCK_STREAM;
h.ai_flags = AI_PASSIVE;
2010-05-10 07:37:45 +04:00
e = getaddrinfo(httpd->bindaddress, portnum, &h, &r0);
if (e)
bozoerr(httpd, 1, "getaddrinfo([%s]:%s): %s",
2010-05-10 07:37:45 +04:00
httpd->bindaddress ? httpd->bindaddress : "*",
portnum, gai_strerror(e));
for (r = r0; r != NULL; r = r->ai_next)
2010-05-10 07:37:45 +04:00
httpd->nsock++;
httpd->sock = bozomalloc(httpd, httpd->nsock * sizeof(*httpd->sock));
httpd->fds = bozomalloc(httpd, httpd->nsock * sizeof(*httpd->fds));
for (i = 0, r = r0; r != NULL; r = r->ai_next) {
2010-05-10 07:37:45 +04:00
httpd->sock[i] = socket(r->ai_family, SOCK_STREAM, 0);
if (httpd->sock[i] == -1)
continue;
2010-05-10 07:37:45 +04:00
if (setsockopt(httpd->sock[i], SOL_SOCKET, SO_REUSEADDR, &on,
sizeof(on)) == -1)
bozowarn(httpd, "setsockopt SO_REUSEADDR: %s",
strerror(errno));
2010-05-10 07:37:45 +04:00
if (bind(httpd->sock[i], r->ai_addr, r->ai_addrlen) == -1)
continue;
2010-05-10 07:37:45 +04:00
if (listen(httpd->sock[i], SOMAXCONN) == -1)
continue;
2010-05-10 07:37:45 +04:00
httpd->fds[i].events = POLLIN | POLLPRI | POLLRDNORM |
2009-05-23 06:26:03 +04:00
POLLRDBAND | POLLERR;
2010-05-10 07:37:45 +04:00
httpd->fds[i].fd = httpd->sock[i];
i++;
}
if (i == 0)
bozoerr(httpd, 1, "could not find any addresses to bind");
2010-05-10 07:37:45 +04:00
httpd->nsock = i;
freeaddrinfo(r0);
if (httpd->foreground == 0)
daemon(1, 0);
create_pidfile(httpd);
bozowarn(httpd, "started in daemon mode as `%s' port `%s' root `%s'",
httpd->virthostname, portnum, httpd->slashdir);
signal(SIGHUP, controlled_exit);
signal(SIGINT, controlled_exit);
signal(SIGTERM, controlled_exit);
signal(SIGCHLD, sigchild);
}
2009-05-23 06:26:03 +04:00
void
2010-05-10 07:37:45 +04:00
bozo_daemon_closefds(bozohttpd_t *httpd)
2009-05-23 06:26:03 +04:00
{
int i;
2010-05-10 07:37:45 +04:00
for (i = 0; i < httpd->nsock; i++)
close(httpd->sock[i]);
2009-05-23 06:26:03 +04:00
}
static void
2010-05-10 07:37:45 +04:00
daemon_runchild(bozohttpd_t *httpd, int fd)
2009-05-23 06:26:03 +04:00
{
2010-05-10 07:37:45 +04:00
httpd->request_times++;
2009-05-23 06:26:03 +04:00
/* setup stdin/stdout/stderr */
dup2(fd, 0);
dup2(fd, 1);
/*dup2(fd, 2);*/
close(fd);
}
2010-05-10 18:44:19 +04:00
static int
daemon_poll_err(bozohttpd_t *httpd, int idx)
2010-05-10 18:44:19 +04:00
{
if ((httpd->fds[idx].revents & (POLLNVAL|POLLERR|POLLHUP)) == 0)
return 0;
bozowarn(httpd, "poll on fd %d pid %d revents %d: %s",
2010-05-10 18:44:19 +04:00
httpd->fds[idx].fd, getpid(), httpd->fds[idx].revents,
strerror(errno));
bozowarn(httpd, "nsock = %d", httpd->nsock);
2010-05-10 18:44:19 +04:00
close(httpd->sock[idx]);
httpd->nsock--;
bozowarn(httpd, "nsock now = %d", httpd->nsock);
2010-05-10 18:44:19 +04:00
/* no sockets left */
if (httpd->nsock == 0)
exit(0);
/* last socket closed is the easy case */
if (httpd->nsock != idx) {
memmove(&httpd->fds[idx], &httpd->fds[idx+1],
(httpd->nsock - idx) * sizeof(*httpd->fds));
memmove(&httpd->sock[idx], &httpd->sock[idx+1],
(httpd->nsock - idx) * sizeof(*httpd->sock));
}
return 1;
}
/*
* the parent never returns from this function, only children that
2009-04-18 11:28:24 +04:00
* are ready to run... XXXMRG - still true in fork-lesser bozo?
*/
2010-06-17 23:43:30 +04:00
int
2010-05-10 07:37:45 +04:00
bozo_daemon_fork(bozohttpd_t *httpd)
{
2009-05-23 06:26:03 +04:00
int i;
2010-05-10 07:37:45 +04:00
debug((httpd, DEBUG_FAT, "%s: pid %u request_times %d",
__func__, getpid(),
httpd->request_times));
2009-05-23 06:26:03 +04:00
/* if we've handled 5 files, exit and let someone else work */
2010-05-10 07:37:45 +04:00
if (httpd->request_times > 5 ||
(httpd->background == 2 && httpd->request_times > 0))
2010-06-22 09:24:12 +04:00
_exit(0);
#if 1
if (httpd->request_times > 0)
_exit(0);
#endif
2010-05-10 07:37:45 +04:00
while (httpd->background) {
struct sockaddr_storage ss;
socklen_t slen;
int fd;
2010-05-10 07:37:45 +04:00
if (httpd->nsock == 0)
exit(0);
/*
* wait for a connection, then fork() and return NULL in
* the parent, who will come back here waiting for another
* connection. read the request in in the child, and return
* it, for processing.
*/
again:
2010-05-10 07:37:45 +04:00
if (poll(httpd->fds, (unsigned)httpd->nsock, INFTIM) == -1) {
/* fail on programmer errors */
if (errno == EFAULT ||
errno == EINVAL)
bozoerr(httpd, 1, "poll: %s",
2010-05-10 07:37:45 +04:00
strerror(errno));
/* sleep on some temporary kernel failures */
if (errno == ENOMEM ||
errno == EAGAIN)
sleep(1);
goto again;
}
2010-05-10 07:37:45 +04:00
for (i = 0; i < httpd->nsock; i++) {
if (daemon_poll_err(httpd, i))
break;
2010-05-10 07:37:45 +04:00
if (httpd->fds[i].revents == 0)
continue;
slen = sizeof(ss);
2010-05-10 07:37:45 +04:00
fd = accept(httpd->fds[i].fd,
(struct sockaddr *)(void *)&ss, &slen);
if (fd == -1) {
if (errno == EFAULT ||
errno == EINVAL)
bozoerr(httpd, 1, "accept: %s",
2010-05-10 07:37:45 +04:00
strerror(errno));
if (errno == ENOMEM ||
errno == EAGAIN)
sleep(1);
continue;
}
2009-05-23 06:26:03 +04:00
2010-06-17 23:43:30 +04:00
#if 0
/*
* This code doesn't work. It interacts very poorly
* with ~user translation and needs to be fixed.
*/
2010-05-10 07:37:45 +04:00
if (httpd->request_times > 0) {
daemon_runchild(httpd, fd);
2010-06-17 23:43:30 +04:00
return 0;
2009-05-23 06:26:03 +04:00
}
2010-06-17 23:43:30 +04:00
#endif
2009-05-23 06:26:03 +04:00
switch (fork()) {
case -1: /* eep, failure */
bozowarn(httpd, "fork() failed, sleeping for "
2009-05-23 06:26:03 +04:00
"10 seconds: %s", strerror(errno));
close(fd);
sleep(10);
2009-05-23 06:26:03 +04:00
break;
case 0: /* child */
2010-05-10 07:37:45 +04:00
daemon_runchild(httpd, fd);
2010-06-17 23:43:30 +04:00
return 0;
default: /* parent */
close(fd);
2009-05-23 06:26:03 +04:00
break;
}
}
}
2010-06-17 23:43:30 +04:00
return 0;
}
#endif /* NO_DAEMON_MODE */