2008-05-24 16:05:49 +08:00
|
|
|
/* tinyproxy - A fast light-weight HTTP proxy
|
2009-10-07 07:08:03 +08:00
|
|
|
*
|
2008-05-24 16:05:49 +08:00
|
|
|
* Copyright (C) 1998 Steven Young <sdyoung@miranda.org>
|
|
|
|
* Copyright (C) 1998-2002 Robert James Kaes <rjkaes@users.sourceforge.net>
|
|
|
|
* Copyright (C) 2000 Chris Lightfoot <chris@ex-parrot.com>
|
2010-01-10 20:51:33 +08:00
|
|
|
* Copyright (C) 2009-2010 Mukund Sivaraman <muks@banu.com>
|
|
|
|
* Copyright (C) 2009-2010 Michael Adam <obnox@samba.org>
|
2000-02-17 01:32:49 +08:00
|
|
|
*
|
2008-05-24 16:05:49 +08:00
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* The initialize routine. Basically sets up all the initial stuff (logfile,
|
2000-02-17 01:32:49 +08:00
|
|
|
* listening socket, config options, etc.) and then sits there and loops
|
|
|
|
* over the new connections until the daemon is closed. Also has additional
|
|
|
|
* functions to handle the "user friendly" aspects of a program (usage,
|
|
|
|
* stats, etc.) Like any good program, most of the work is actually done
|
|
|
|
* elsewhere.
|
|
|
|
*/
|
|
|
|
|
2009-08-07 06:12:53 +08:00
|
|
|
#include "main.h"
|
2000-02-17 01:32:49 +08:00
|
|
|
|
2000-09-12 08:03:53 +08:00
|
|
|
#include "anonymous.h"
|
2000-02-17 01:32:49 +08:00
|
|
|
#include "buffer.h"
|
2009-09-21 12:11:59 +08:00
|
|
|
#include "conf.h"
|
2002-05-24 02:27:01 +08:00
|
|
|
#include "daemon.h"
|
|
|
|
#include "heap.h"
|
2000-02-17 01:32:49 +08:00
|
|
|
#include "filter.h"
|
2002-05-27 02:52:23 +08:00
|
|
|
#include "child.h"
|
2020-09-16 06:20:14 +08:00
|
|
|
#include "loop.h"
|
2000-09-12 08:03:53 +08:00
|
|
|
#include "log.h"
|
|
|
|
#include "reqs.h"
|
|
|
|
#include "sock.h"
|
|
|
|
#include "stats.h"
|
|
|
|
#include "utils.h"
|
2000-02-17 01:32:49 +08:00
|
|
|
|
2008-05-24 16:05:49 +08:00
|
|
|
/*
|
2000-02-17 01:32:49 +08:00
|
|
|
* Global Structures
|
|
|
|
*/
|
2020-01-16 00:09:41 +08:00
|
|
|
struct config_s *config;
|
2020-01-16 01:02:22 +08:00
|
|
|
static struct config_s configs[2];
|
2020-01-15 23:42:20 +08:00
|
|
|
static const char* config_file;
|
2008-12-08 21:39:44 +08:00
|
|
|
unsigned int received_sighup = FALSE; /* boolean */
|
2000-02-17 01:32:49 +08:00
|
|
|
|
2020-01-16 01:02:22 +08:00
|
|
|
static struct config_s*
|
|
|
|
get_next_config(void)
|
|
|
|
{
|
|
|
|
if (config == &configs[0]) return &configs[1];
|
|
|
|
return &configs[0];
|
|
|
|
}
|
|
|
|
|
2000-02-17 01:32:49 +08:00
|
|
|
/*
|
|
|
|
* Handle a signal
|
|
|
|
*/
|
2009-09-20 16:33:56 +08:00
|
|
|
static void
|
2009-09-15 06:23:35 +08:00
|
|
|
takesig (int sig)
|
2000-02-17 01:32:49 +08:00
|
|
|
{
|
2009-09-15 03:41:25 +08:00
|
|
|
pid_t pid;
|
|
|
|
int status;
|
2002-05-24 02:27:01 +08:00
|
|
|
|
2009-09-15 03:41:25 +08:00
|
|
|
switch (sig) {
|
2020-09-07 06:11:19 +08:00
|
|
|
case SIGUSR1:
|
2009-09-15 03:41:25 +08:00
|
|
|
case SIGHUP:
|
|
|
|
received_sighup = TRUE;
|
|
|
|
break;
|
2002-04-19 00:57:06 +08:00
|
|
|
|
simplify codebase by using one thread/conn, instead of preforked procs
the existing codebase used an elaborate and complex approach for
its parallelism:
5 different config file options, namely
- MaxClients
- MinSpareServers
- MaxSpareServers
- StartServers
- MaxRequestsPerChild
were used to steer how (and how many) parallel processes tinyproxy
would spin up at start, how many processes at each point needed to
be idle, etc.
it seems all preforked processes would listen on the server port
and compete with each other about who would get assigned the new
incoming connections.
since some data needs to be shared across those processes, a half-
baked "shared memory" implementation was provided for this purpose.
that implementation used to use files in the filesystem, and since
it had a big FIXME comment, the author was well aware of how hackish
that approach was.
this entire complexity is now removed. the main thread enters
a loop which polls on the listening fds, then spins up a new
thread per connection, until the maximum number of connections
(MaxClients) is hit. this is the only of the 5 config options
left after this cleanup. since threads share the same address space,
the code necessary for shared memory access has been removed.
this means that the other 4 mentioned config option will now
produce a parse error, when encountered.
currently each thread uses a hardcoded default of 256KB per thread
for the thread stack size, which is quite lavish and should be
sufficient for even the worst C libraries, but people may want
to tweak this value to the bare minimum, thus we may provide a new
config option for this purpose in the future.
i suspect that on heavily optimized C libraries such a musl, a
stack size of 8-16 KB per thread could be sufficient.
since the existing list implementation in vector.c did not provide
a way to remove a single item from an existing list, i added my
own list implementation from my libulz library which offers this
functionality, rather than trying to add an ad-hoc, and perhaps
buggy implementation to the vector_t list code. the sblist
code is contained in an 80 line C file and as simple as it can get,
while offering good performance and is proven bugfree due to years
of use in other projects.
2018-12-17 08:23:09 +08:00
|
|
|
case SIGINT:
|
2009-09-15 03:41:25 +08:00
|
|
|
case SIGTERM:
|
2020-01-16 00:09:41 +08:00
|
|
|
config->quit = TRUE;
|
2009-09-15 03:41:25 +08:00
|
|
|
break;
|
2002-05-24 02:27:01 +08:00
|
|
|
|
2009-09-15 03:41:25 +08:00
|
|
|
case SIGCHLD:
|
|
|
|
while ((pid = waitpid (-1, &status, WNOHANG)) > 0) ;
|
|
|
|
break;
|
|
|
|
}
|
2000-12-08 11:35:07 +08:00
|
|
|
|
2009-09-15 03:41:25 +08:00
|
|
|
return;
|
2000-02-17 01:32:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2000-09-12 08:03:53 +08:00
|
|
|
* Display the version information for the user.
|
|
|
|
*/
|
2009-09-15 06:23:35 +08:00
|
|
|
static void
|
|
|
|
display_version (void)
|
2000-09-12 08:03:53 +08:00
|
|
|
{
|
2009-09-20 15:10:52 +08:00
|
|
|
printf ("%s %s\n", PACKAGE, VERSION);
|
2001-08-27 05:17:30 +08:00
|
|
|
}
|
|
|
|
|
2000-09-12 08:03:53 +08:00
|
|
|
/*
|
|
|
|
* Display usage to the user.
|
2000-02-17 01:32:49 +08:00
|
|
|
*/
|
2009-09-15 06:23:35 +08:00
|
|
|
static void
|
|
|
|
display_usage (void)
|
2000-02-17 01:32:49 +08:00
|
|
|
{
|
2009-09-26 15:00:54 +08:00
|
|
|
int features = 0;
|
|
|
|
|
2009-09-15 03:41:25 +08:00
|
|
|
printf ("Usage: %s [options]\n", PACKAGE);
|
2009-09-26 15:00:54 +08:00
|
|
|
printf ("\n"
|
|
|
|
"Options are:\n"
|
|
|
|
" -d Do not daemonize (run in foreground).\n"
|
|
|
|
" -c FILE Use an alternate configuration file.\n"
|
|
|
|
" -h Display this usage information.\n"
|
|
|
|
" -v Display version information.\n");
|
2000-09-12 08:03:53 +08:00
|
|
|
|
2009-09-15 03:41:25 +08:00
|
|
|
/* Display the modes compiled into tinyproxy */
|
|
|
|
printf ("\nFeatures compiled in:\n");
|
2009-09-26 15:00:54 +08:00
|
|
|
|
2000-09-12 08:03:53 +08:00
|
|
|
#ifdef XTINYPROXY_ENABLE
|
2009-09-15 03:41:25 +08:00
|
|
|
printf (" XTinyproxy header\n");
|
2009-09-26 15:00:54 +08:00
|
|
|
features++;
|
2008-12-01 23:01:11 +08:00
|
|
|
#endif /* XTINYPROXY */
|
2009-09-26 15:00:54 +08:00
|
|
|
|
2000-02-17 01:32:49 +08:00
|
|
|
#ifdef FILTER_ENABLE
|
2009-09-15 03:41:25 +08:00
|
|
|
printf (" Filtering\n");
|
2009-09-26 15:00:54 +08:00
|
|
|
features++;
|
2008-12-01 23:01:11 +08:00
|
|
|
#endif /* FILTER_ENABLE */
|
2009-09-26 15:00:54 +08:00
|
|
|
|
2000-02-17 01:32:49 +08:00
|
|
|
#ifndef NDEBUG
|
2009-09-15 03:41:25 +08:00
|
|
|
printf (" Debugging code\n");
|
2009-09-26 15:00:54 +08:00
|
|
|
features++;
|
2008-12-01 23:01:11 +08:00
|
|
|
#endif /* NDEBUG */
|
2009-09-26 15:00:54 +08:00
|
|
|
|
2002-06-07 04:28:02 +08:00
|
|
|
#ifdef TRANSPARENT_PROXY
|
2009-09-15 03:41:25 +08:00
|
|
|
printf (" Transparent proxy support\n");
|
2009-09-26 15:00:54 +08:00
|
|
|
features++;
|
2008-12-01 23:01:11 +08:00
|
|
|
#endif /* TRANSPARENT_PROXY */
|
2009-09-26 15:00:54 +08:00
|
|
|
|
2004-01-27 03:11:52 +08:00
|
|
|
#ifdef REVERSE_SUPPORT
|
2009-09-15 03:41:25 +08:00
|
|
|
printf (" Reverse proxy support\n");
|
2009-09-26 15:00:54 +08:00
|
|
|
features++;
|
2008-12-01 23:01:11 +08:00
|
|
|
#endif /* REVERSE_SUPPORT */
|
2009-09-26 15:00:54 +08:00
|
|
|
|
2010-02-18 01:41:45 +08:00
|
|
|
#ifdef UPSTREAM_SUPPORT
|
|
|
|
printf (" Upstream proxy support\n");
|
|
|
|
features++;
|
|
|
|
#endif /* UPSTREAM_SUPPORT */
|
|
|
|
|
2009-09-26 15:00:54 +08:00
|
|
|
if (0 == features)
|
|
|
|
printf (" None\n");
|
|
|
|
|
|
|
|
printf ("\n"
|
2010-02-17 02:59:29 +08:00
|
|
|
"For support and bug reporting instructions, please visit\n"
|
2016-01-04 05:16:21 +08:00
|
|
|
"<https://tinyproxy.github.io/>.\n");
|
2000-02-17 01:32:49 +08:00
|
|
|
}
|
|
|
|
|
2009-09-15 06:23:35 +08:00
|
|
|
static int
|
|
|
|
get_id (char *str)
|
2008-07-14 20:10:20 +08:00
|
|
|
{
|
2009-09-15 03:41:25 +08:00
|
|
|
char *tstr;
|
2008-07-14 20:10:20 +08:00
|
|
|
|
2009-09-15 03:41:25 +08:00
|
|
|
if (str == NULL)
|
|
|
|
return -1;
|
2008-07-14 20:10:20 +08:00
|
|
|
|
2009-09-15 03:41:25 +08:00
|
|
|
tstr = str;
|
|
|
|
while (*tstr != 0) {
|
|
|
|
if (!isdigit (*tstr))
|
|
|
|
return -1;
|
|
|
|
tstr++;
|
|
|
|
}
|
2008-07-14 20:10:20 +08:00
|
|
|
|
2009-09-15 03:41:25 +08:00
|
|
|
return atoi (str);
|
2008-07-14 20:10:20 +08:00
|
|
|
}
|
|
|
|
|
2009-09-15 04:30:20 +08:00
|
|
|
/**
|
|
|
|
* change_user:
|
|
|
|
* @program: The name of the program. Pass argv[0] here.
|
|
|
|
*
|
|
|
|
* This function tries to change UID and GID to the ones specified in
|
|
|
|
* the config file. This function is typically called during
|
|
|
|
* initialization when the effective user is root.
|
|
|
|
**/
|
2009-09-15 04:23:07 +08:00
|
|
|
static void
|
|
|
|
change_user (const char *program)
|
|
|
|
{
|
2020-01-16 00:09:41 +08:00
|
|
|
if (config->group && strlen (config->group) > 0) {
|
|
|
|
int gid = get_id (config->group);
|
2009-09-15 04:23:07 +08:00
|
|
|
|
|
|
|
if (gid < 0) {
|
2020-01-16 00:09:41 +08:00
|
|
|
struct group *thisgroup = getgrnam (config->group);
|
2009-09-15 04:23:07 +08:00
|
|
|
|
|
|
|
if (!thisgroup) {
|
|
|
|
fprintf (stderr,
|
|
|
|
"%s: Unable to find group \"%s\".\n",
|
2020-01-16 00:09:41 +08:00
|
|
|
program, config->group);
|
2009-09-15 04:23:07 +08:00
|
|
|
exit (EX_NOUSER);
|
|
|
|
}
|
|
|
|
|
|
|
|
gid = thisgroup->gr_gid;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (setgid (gid) < 0) {
|
|
|
|
fprintf (stderr,
|
|
|
|
"%s: Unable to change to group \"%s\".\n",
|
2020-01-16 00:09:41 +08:00
|
|
|
program, config->group);
|
2009-09-15 04:24:26 +08:00
|
|
|
exit (EX_NOPERM);
|
2009-09-15 04:23:07 +08:00
|
|
|
}
|
|
|
|
|
2013-09-09 14:33:48 +08:00
|
|
|
#ifdef HAVE_SETGROUPS
|
|
|
|
/* Drop all supplementary groups, otherwise these are inherited from the calling process */
|
|
|
|
if (setgroups (0, NULL) < 0) {
|
|
|
|
fprintf (stderr,
|
|
|
|
"%s: Unable to drop supplementary groups.\n",
|
|
|
|
program);
|
|
|
|
exit (EX_NOPERM);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-09-15 04:23:07 +08:00
|
|
|
log_message (LOG_INFO, "Now running as group \"%s\".",
|
2020-01-16 00:09:41 +08:00
|
|
|
config->group);
|
2009-09-15 04:23:07 +08:00
|
|
|
}
|
|
|
|
|
2020-01-16 00:09:41 +08:00
|
|
|
if (config->user && strlen (config->user) > 0) {
|
|
|
|
int uid = get_id (config->user);
|
2009-09-15 04:23:07 +08:00
|
|
|
|
|
|
|
if (uid < 0) {
|
2020-01-16 00:09:41 +08:00
|
|
|
struct passwd *thisuser = getpwnam (config->user);
|
2009-09-15 04:23:07 +08:00
|
|
|
|
|
|
|
if (!thisuser) {
|
|
|
|
fprintf (stderr,
|
|
|
|
"%s: Unable to find user \"%s\".\n",
|
2020-01-16 00:09:41 +08:00
|
|
|
program, config->user);
|
2009-09-15 04:23:07 +08:00
|
|
|
exit (EX_NOUSER);
|
|
|
|
}
|
|
|
|
|
|
|
|
uid = thisuser->pw_uid;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (setuid (uid) < 0) {
|
|
|
|
fprintf (stderr,
|
|
|
|
"%s: Unable to change to user \"%s\".\n",
|
2020-01-16 00:09:41 +08:00
|
|
|
program, config->user);
|
2009-09-15 04:24:26 +08:00
|
|
|
exit (EX_NOPERM);
|
2009-09-15 04:23:07 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
log_message (LOG_INFO, "Now running as user \"%s\".",
|
2020-01-16 00:09:41 +08:00
|
|
|
config->user);
|
2009-09-15 04:23:07 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-12-22 06:37:17 +08:00
|
|
|
/**
|
|
|
|
* convenience wrapper around reload_config_file
|
2009-12-23 07:18:31 +08:00
|
|
|
* that also re-initializes logging.
|
2009-12-22 06:37:17 +08:00
|
|
|
*/
|
2020-01-16 00:35:43 +08:00
|
|
|
int reload_config (int reload_logging)
|
2009-12-22 06:37:17 +08:00
|
|
|
{
|
|
|
|
int ret;
|
2020-01-16 01:02:22 +08:00
|
|
|
struct config_s *c_next = get_next_config();
|
2009-12-22 06:37:17 +08:00
|
|
|
|
2020-01-16 00:35:43 +08:00
|
|
|
if (reload_logging) shutdown_logging ();
|
2009-12-23 07:18:31 +08:00
|
|
|
|
2020-01-16 01:02:22 +08:00
|
|
|
ret = reload_config_file (config_file, c_next);
|
2020-01-16 00:35:43 +08:00
|
|
|
|
2009-12-23 07:18:31 +08:00
|
|
|
if (ret != 0) {
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2020-09-16 06:01:44 +08:00
|
|
|
if(config) free_config (config);
|
2020-01-16 01:02:22 +08:00
|
|
|
config = c_next;
|
2020-01-16 00:09:41 +08:00
|
|
|
|
2020-01-16 00:35:43 +08:00
|
|
|
if (reload_logging) ret = setup_logging ();
|
2009-12-22 06:37:17 +08:00
|
|
|
|
2009-12-23 07:18:31 +08:00
|
|
|
done:
|
2009-12-22 06:37:17 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2020-09-07 06:08:10 +08:00
|
|
|
static void setup_sig(int sig, signal_func *sigh,
|
|
|
|
const char* signame, const char* argv0) {
|
|
|
|
if (set_signal_handler (sig, sigh) == SIG_ERR) {
|
|
|
|
fprintf (stderr, "%s: Could not set the \"%s\" signal.\n",
|
|
|
|
argv0, signame);
|
|
|
|
exit (EX_OSERR);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-09-15 04:04:30 +08:00
|
|
|
int
|
|
|
|
main (int argc, char **argv)
|
|
|
|
{
|
2020-01-15 23:26:40 +08:00
|
|
|
int opt, daemonized = TRUE;
|
2020-01-15 22:45:23 +08:00
|
|
|
|
simplify codebase by using one thread/conn, instead of preforked procs
the existing codebase used an elaborate and complex approach for
its parallelism:
5 different config file options, namely
- MaxClients
- MinSpareServers
- MaxSpareServers
- StartServers
- MaxRequestsPerChild
were used to steer how (and how many) parallel processes tinyproxy
would spin up at start, how many processes at each point needed to
be idle, etc.
it seems all preforked processes would listen on the server port
and compete with each other about who would get assigned the new
incoming connections.
since some data needs to be shared across those processes, a half-
baked "shared memory" implementation was provided for this purpose.
that implementation used to use files in the filesystem, and since
it had a big FIXME comment, the author was well aware of how hackish
that approach was.
this entire complexity is now removed. the main thread enters
a loop which polls on the listening fds, then spins up a new
thread per connection, until the maximum number of connections
(MaxClients) is hit. this is the only of the 5 config options
left after this cleanup. since threads share the same address space,
the code necessary for shared memory access has been removed.
this means that the other 4 mentioned config option will now
produce a parse error, when encountered.
currently each thread uses a hardcoded default of 256KB per thread
for the thread stack size, which is quite lavish and should be
sufficient for even the worst C libraries, but people may want
to tweak this value to the bare minimum, thus we may provide a new
config option for this purpose in the future.
i suspect that on heavily optimized C libraries such a musl, a
stack size of 8-16 KB per thread could be sufficient.
since the existing list implementation in vector.c did not provide
a way to remove a single item from an existing list, i added my
own list implementation from my libulz library which offers this
functionality, rather than trying to add an ad-hoc, and perhaps
buggy implementation to the vector_t list code. the sblist
code is contained in an 80 line C file and as simple as it can get,
while offering good performance and is proven bugfree due to years
of use in other projects.
2018-12-17 08:23:09 +08:00
|
|
|
srand(time(NULL)); /* for hashmap seeds */
|
|
|
|
|
2009-09-15 04:04:30 +08:00
|
|
|
/* Only allow u+rw bits. This may be required for some versions
|
|
|
|
* of glibc so that mkstemp() doesn't make us vulnerable.
|
|
|
|
*/
|
|
|
|
umask (0177);
|
|
|
|
|
2020-09-07 23:59:37 +08:00
|
|
|
log_message (LOG_NOTICE, "Initializing " PACKAGE " ...");
|
2010-03-03 05:05:28 +08:00
|
|
|
|
2010-06-02 12:41:10 +08:00
|
|
|
if (config_compile_regex()) {
|
2010-06-01 10:24:25 +08:00
|
|
|
exit (EX_SOFTWARE);
|
|
|
|
}
|
|
|
|
|
2020-01-15 23:42:20 +08:00
|
|
|
config_file = SYSCONFDIR "/tinyproxy.conf";
|
2020-01-15 22:45:23 +08:00
|
|
|
|
|
|
|
while ((opt = getopt (argc, argv, "c:vdh")) != EOF) {
|
|
|
|
switch (opt) {
|
|
|
|
case 'v':
|
|
|
|
display_version ();
|
|
|
|
exit (EX_OK);
|
|
|
|
|
|
|
|
case 'd':
|
2020-01-15 23:26:40 +08:00
|
|
|
daemonized = FALSE;
|
2020-01-15 22:45:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'c':
|
2020-01-15 23:42:20 +08:00
|
|
|
config_file = optarg;
|
2020-01-15 22:45:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'h':
|
|
|
|
display_usage ();
|
|
|
|
exit (EX_OK);
|
|
|
|
|
|
|
|
default:
|
|
|
|
display_usage ();
|
|
|
|
exit (EX_USAGE);
|
|
|
|
}
|
|
|
|
}
|
2009-11-04 07:29:35 +08:00
|
|
|
|
2020-01-16 00:35:43 +08:00
|
|
|
if (reload_config(0)) {
|
2010-03-03 04:57:03 +08:00
|
|
|
exit (EX_SOFTWARE);
|
|
|
|
}
|
|
|
|
|
2009-09-15 03:41:25 +08:00
|
|
|
init_stats ();
|
|
|
|
|
2009-09-15 06:37:06 +08:00
|
|
|
/* If ANONYMOUS is turned on, make sure that Content-Length is
|
2009-09-15 03:41:25 +08:00
|
|
|
* in the list of allowed headers, since it is required in a
|
2009-09-15 06:37:06 +08:00
|
|
|
* HTTP/1.0 request. Also add the Content-Type header since it
|
|
|
|
* goes hand in hand with Content-Length. */
|
2020-03-16 21:19:39 +08:00
|
|
|
if (is_anonymous_enabled (config)) {
|
2020-09-13 04:33:59 +08:00
|
|
|
anonymous_insert (config, safestrdup("Content-Length"));
|
|
|
|
anonymous_insert (config, safestrdup("Content-Type"));
|
2009-09-15 03:41:25 +08:00
|
|
|
}
|
|
|
|
|
2020-01-15 23:26:40 +08:00
|
|
|
if (daemonized == TRUE) {
|
2020-01-16 00:09:41 +08:00
|
|
|
if (!config->syslog && config->logf_name == NULL)
|
2017-11-05 03:40:42 +08:00
|
|
|
fprintf(stderr, "WARNING: logging deactivated "
|
|
|
|
"(can't log to stdout when daemonized)\n");
|
|
|
|
|
2009-09-15 03:41:25 +08:00
|
|
|
makedaemon ();
|
2017-11-05 03:40:42 +08:00
|
|
|
}
|
2009-09-15 03:41:25 +08:00
|
|
|
|
2020-09-07 06:08:10 +08:00
|
|
|
setup_sig(SIGPIPE, SIG_IGN, "SIGPIPE", argv[0]);
|
2009-09-15 06:37:06 +08:00
|
|
|
|
2000-09-12 08:03:53 +08:00
|
|
|
#ifdef FILTER_ENABLE
|
2020-01-16 00:09:41 +08:00
|
|
|
if (config->filter)
|
2009-09-15 03:41:25 +08:00
|
|
|
filter_init ();
|
2008-12-01 23:01:11 +08:00
|
|
|
#endif /* FILTER_ENABLE */
|
|
|
|
|
2009-09-15 06:37:06 +08:00
|
|
|
/* Start listening on the selected port. */
|
2020-01-16 00:09:41 +08:00
|
|
|
if (child_listening_sockets(config->listen_addrs, config->port) < 0) {
|
2013-11-07 18:00:19 +08:00
|
|
|
fprintf (stderr, "%s: Could not create listening sockets.\n",
|
2009-09-15 03:41:25 +08:00
|
|
|
argv[0]);
|
|
|
|
exit (EX_OSERR);
|
2008-12-08 21:39:44 +08:00
|
|
|
}
|
2009-09-15 03:41:25 +08:00
|
|
|
|
2017-11-16 08:52:55 +08:00
|
|
|
/* Create pid file before we drop privileges */
|
2020-01-16 00:09:41 +08:00
|
|
|
if (config->pidpath) {
|
|
|
|
if (pidfile_create (config->pidpath) < 0) {
|
2017-11-16 08:52:55 +08:00
|
|
|
fprintf (stderr, "%s: Could not create PID file.\n",
|
|
|
|
argv[0]);
|
|
|
|
exit (EX_OSERR);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-04-21 22:40:56 +08:00
|
|
|
/* Switch to a different user if we're running as root */
|
|
|
|
if (geteuid () == 0)
|
|
|
|
change_user (argv[0]);
|
|
|
|
else
|
|
|
|
log_message (LOG_WARNING,
|
|
|
|
"Not running as root, so not changing UID/GID.");
|
|
|
|
|
2010-06-02 12:49:49 +08:00
|
|
|
/* Create log file after we drop privileges */
|
|
|
|
if (setup_logging ()) {
|
|
|
|
exit (EX_SOFTWARE);
|
|
|
|
}
|
|
|
|
|
2009-09-15 06:37:06 +08:00
|
|
|
/* These signals are only for the parent process. */
|
2009-09-15 03:41:25 +08:00
|
|
|
log_message (LOG_INFO, "Setting the various signals.");
|
2009-09-15 06:37:06 +08:00
|
|
|
|
2020-09-07 06:08:10 +08:00
|
|
|
setup_sig (SIGCHLD, takesig, "SIGCHLD", argv[0]);
|
|
|
|
setup_sig (SIGTERM, takesig, "SIGTERM", argv[0]);
|
2020-09-15 03:55:52 +08:00
|
|
|
setup_sig (SIGINT, takesig, "SIGINT", argv[0]);
|
2020-09-07 06:08:10 +08:00
|
|
|
if (daemonized) setup_sig (SIGHUP, takesig, "SIGHUP", argv[0]);
|
2020-09-07 06:11:19 +08:00
|
|
|
setup_sig (SIGUSR1, takesig, "SIGUSR1", argv[0]);
|
2009-09-15 03:41:25 +08:00
|
|
|
|
2020-09-16 06:11:09 +08:00
|
|
|
loop_records_init();
|
|
|
|
|
2009-09-15 06:37:06 +08:00
|
|
|
/* Start the main loop */
|
2009-09-15 03:41:25 +08:00
|
|
|
log_message (LOG_INFO, "Starting main loop. Accepting connections.");
|
|
|
|
|
|
|
|
child_main_loop ();
|
|
|
|
|
2020-09-07 23:59:37 +08:00
|
|
|
log_message (LOG_NOTICE, "Shutting down.");
|
2009-09-15 03:41:25 +08:00
|
|
|
|
2009-10-26 03:25:06 +08:00
|
|
|
child_kill_children (SIGTERM);
|
2009-09-15 03:41:25 +08:00
|
|
|
child_close_sock ();
|
2020-09-16 05:32:25 +08:00
|
|
|
child_free_children();
|
2009-09-15 03:41:25 +08:00
|
|
|
|
2020-09-16 06:11:09 +08:00
|
|
|
loop_records_destroy();
|
|
|
|
|
2009-09-15 06:37:06 +08:00
|
|
|
/* Remove the PID file */
|
2020-01-16 00:09:41 +08:00
|
|
|
if (config->pidpath != NULL && unlink (config->pidpath) < 0) {
|
2009-09-15 03:41:25 +08:00
|
|
|
log_message (LOG_WARNING,
|
|
|
|
"Could not remove PID file \"%s\": %s.",
|
2020-01-16 00:09:41 +08:00
|
|
|
config->pidpath, strerror (errno));
|
2008-12-08 21:39:44 +08:00
|
|
|
}
|
2009-09-15 06:37:06 +08:00
|
|
|
|
2000-02-17 01:32:49 +08:00
|
|
|
#ifdef FILTER_ENABLE
|
2020-01-16 00:09:41 +08:00
|
|
|
if (config->filter)
|
2009-09-15 03:41:25 +08:00
|
|
|
filter_destroy ();
|
2008-12-01 23:01:11 +08:00
|
|
|
#endif /* FILTER_ENABLE */
|
2000-02-17 01:32:49 +08:00
|
|
|
|
2020-09-16 06:01:44 +08:00
|
|
|
free_config (config);
|
|
|
|
|
2009-12-23 07:30:11 +08:00
|
|
|
shutdown_logging ();
|
2000-02-17 01:32:49 +08:00
|
|
|
|
2009-09-15 06:36:26 +08:00
|
|
|
return EXIT_SUCCESS;
|
2000-02-17 01:32:49 +08:00
|
|
|
}
|