summaryrefslogtreecommitdiffhomepage
path: root/src/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.c')
-rw-r--r--src/main.c242
1 files changed, 106 insertions, 136 deletions
diff --git a/src/main.c b/src/main.c
index 43170c5..1309284 100644
--- a/src/main.c
+++ b/src/main.c
@@ -38,6 +38,7 @@
#include "heap.h"
#include "filter.h"
#include "child.h"
+#include "loop.h"
#include "log.h"
#include "reqs.h"
#include "sock.h"
@@ -47,10 +48,18 @@
/*
* Global Structures
*/
-struct config_s config;
-struct config_s config_defaults;
+struct config_s *config;
+static struct config_s configs[2];
+static const char* config_file;
unsigned int received_sighup = FALSE; /* boolean */
+static struct config_s*
+get_next_config(void)
+{
+ if (config == &configs[0]) return &configs[1];
+ return &configs[0];
+}
+
/*
* Handle a signal
*/
@@ -61,12 +70,14 @@ takesig (int sig)
int status;
switch (sig) {
+ case SIGUSR1:
case SIGHUP:
received_sighup = TRUE;
break;
+ case SIGINT:
case SIGTERM:
- config.quit = TRUE;
+ config->quit = TRUE;
break;
case SIGCHLD:
@@ -162,52 +173,6 @@ get_id (char *str)
}
/**
- * process_cmdline:
- * @argc: argc as passed to main()
- * @argv: argv as passed to main()
- *
- * This function parses command line arguments.
- **/
-static void
-process_cmdline (int argc, char **argv, struct config_s *conf)
-{
- int opt;
-
- while ((opt = getopt (argc, argv, "c:vdh")) != EOF) {
- switch (opt) {
- case 'v':
- display_version ();
- exit (EX_OK);
-
- case 'd':
- conf->godaemon = FALSE;
- break;
-
- case 'c':
- if (conf->config_file != NULL) {
- safefree (conf->config_file);
- }
- conf->config_file = safestrdup (optarg);
- if (!conf->config_file) {
- fprintf (stderr,
- "%s: Could not allocate memory.\n",
- argv[0]);
- exit (EX_SOFTWARE);
- }
- break;
-
- case 'h':
- display_usage ();
- exit (EX_OK);
-
- default:
- display_usage ();
- exit (EX_USAGE);
- }
- }
-}
-
-/**
* change_user:
* @program: The name of the program. Pass argv[0] here.
*
@@ -218,16 +183,16 @@ process_cmdline (int argc, char **argv, struct config_s *conf)
static void
change_user (const char *program)
{
- if (config.group && strlen (config.group) > 0) {
- int gid = get_id (config.group);
+ if (config->group && strlen (config->group) > 0) {
+ int gid = get_id (config->group);
if (gid < 0) {
- struct group *thisgroup = getgrnam (config.group);
+ struct group *thisgroup = getgrnam (config->group);
if (!thisgroup) {
fprintf (stderr,
"%s: Unable to find group \"%s\".\n",
- program, config.group);
+ program, config->group);
exit (EX_NOUSER);
}
@@ -237,7 +202,7 @@ change_user (const char *program)
if (setgid (gid) < 0) {
fprintf (stderr,
"%s: Unable to change to group \"%s\".\n",
- program, config.group);
+ program, config->group);
exit (EX_NOPERM);
}
@@ -252,19 +217,19 @@ change_user (const char *program)
#endif
log_message (LOG_INFO, "Now running as group \"%s\".",
- config.group);
+ config->group);
}
- if (config.user && strlen (config.user) > 0) {
- int uid = get_id (config.user);
+ if (config->user && strlen (config->user) > 0) {
+ int uid = get_id (config->user);
if (uid < 0) {
- struct passwd *thisuser = getpwnam (config.user);
+ struct passwd *thisuser = getpwnam (config->user);
if (!thisuser) {
fprintf (stderr,
"%s: Unable to find user \"%s\".\n",
- program, config.user);
+ program, config->user);
exit (EX_NOUSER);
}
@@ -274,78 +239,99 @@ change_user (const char *program)
if (setuid (uid) < 0) {
fprintf (stderr,
"%s: Unable to change to user \"%s\".\n",
- program, config.user);
+ program, config->user);
exit (EX_NOPERM);
}
log_message (LOG_INFO, "Now running as user \"%s\".",
- config.user);
+ config->user);
}
}
-static void initialize_config_defaults (struct config_s *conf)
-{
- memset (conf, 0, sizeof(*conf));
-
- conf->config_file = safestrdup (SYSCONFDIR "/tinyproxy.conf");
- if (!conf->config_file) {
- fprintf (stderr, PACKAGE ": Could not allocate memory.\n");
- exit (EX_SOFTWARE);
- }
- conf->godaemon = TRUE;
- /*
- * Make sure the HTML error pages array is NULL to begin with.
- * (FIXME: Should have a better API for all this)
- */
- conf->errorpages = NULL;
- conf->stathost = safestrdup (TINYPROXY_STATHOST);
- conf->idletimeout = MAX_IDLE_TIME;
- conf->logf_name = NULL;
- conf->pidpath = NULL;
-}
-
/**
* convenience wrapper around reload_config_file
* that also re-initializes logging.
*/
-int reload_config (void)
+int reload_config (int reload_logging)
{
int ret;
+ struct config_s *c_next = get_next_config();
- shutdown_logging ();
+ log_message (LOG_NOTICE, "Reloading config file");
+
+ if (reload_logging) shutdown_logging ();
+
+ ret = reload_config_file (config_file, c_next);
- ret = reload_config_file (config_defaults.config_file, &config,
- &config_defaults);
if (ret != 0) {
goto done;
}
- ret = setup_logging ();
+ if(config) free_config (config);
+ config = c_next;
+
+ if (reload_logging) ret = setup_logging ();
+ log_message (LOG_NOTICE, "Reloading config file finished");
done:
return ret;
}
+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);
+ }
+}
+
int
main (int argc, char **argv)
{
+ int opt, daemonized = TRUE;
+
+ srand(time(NULL)); /* for hashmap seeds */
+
/* Only allow u+rw bits. This may be required for some versions
* of glibc so that mkstemp() doesn't make us vulnerable.
*/
umask (0177);
- log_message (LOG_INFO, "Initializing " PACKAGE " ...");
+ log_message (LOG_NOTICE, "Initializing " PACKAGE " ...");
- if (config_compile_regex()) {
+ if (config_init()) {
+ fprintf(stderr, "ERROR: config_init() failed\n");
exit (EX_SOFTWARE);
}
- initialize_config_defaults (&config_defaults);
- process_cmdline (argc, argv, &config_defaults);
+ config_file = SYSCONFDIR "/tinyproxy.conf";
+
+ while ((opt = getopt (argc, argv, "c:vdh")) != EOF) {
+ switch (opt) {
+ case 'v':
+ display_version ();
+ exit (EX_OK);
+
+ case 'd':
+ daemonized = FALSE;
+ break;
+
+ case 'c':
+ config_file = optarg;
+ break;
+
+ case 'h':
+ display_usage ();
+ exit (EX_OK);
- if (reload_config_file (config_defaults.config_file,
- &config,
- &config_defaults)) {
+ default:
+ display_usage ();
+ exit (EX_USAGE);
+ }
+ }
+
+ if (reload_config(0)) {
exit (EX_SOFTWARE);
}
@@ -355,40 +341,36 @@ main (int argc, char **argv)
* in the list of allowed headers, since it is required in a
* HTTP/1.0 request. Also add the Content-Type header since it
* goes hand in hand with Content-Length. */
- if (is_anonymous_enabled ()) {
- anonymous_insert ("Content-Length");
- anonymous_insert ("Content-Type");
+ if (is_anonymous_enabled (config)) {
+ anonymous_insert (config, safestrdup("Content-Length"));
+ anonymous_insert (config, safestrdup("Content-Type"));
}
- if (config.godaemon == TRUE) {
- if (!config.syslog && config.logf_name == NULL)
+ if (daemonized == TRUE) {
+ if (!config->syslog && config->logf_name == NULL)
fprintf(stderr, "WARNING: logging deactivated "
"(can't log to stdout when daemonized)\n");
makedaemon ();
}
- if (set_signal_handler (SIGPIPE, SIG_IGN) == SIG_ERR) {
- fprintf (stderr, "%s: Could not set the \"SIGPIPE\" signal.\n",
- argv[0]);
- exit (EX_OSERR);
- }
+ setup_sig(SIGPIPE, SIG_IGN, "SIGPIPE", argv[0]);
#ifdef FILTER_ENABLE
- if (config.filter)
+ if (config->filter)
filter_init ();
#endif /* FILTER_ENABLE */
/* Start listening on the selected port. */
- if (child_listening_sockets(config.listen_addrs, config.port) < 0) {
+ if (child_listening_sockets(config->listen_addrs, config->port) < 0) {
fprintf (stderr, "%s: Could not create listening sockets.\n",
argv[0]);
exit (EX_OSERR);
}
/* Create pid file before we drop privileges */
- if (config.pidpath) {
- if (pidfile_create (config.pidpath) < 0) {
+ if (config->pidpath) {
+ if (pidfile_create (config->pidpath) < 0) {
fprintf (stderr, "%s: Could not create PID file.\n",
argv[0]);
exit (EX_OSERR);
@@ -399,7 +381,7 @@ main (int argc, char **argv)
if (geteuid () == 0)
change_user (argv[0]);
else
- log_message (LOG_WARNING,
+ log_message (LOG_INFO,
"Not running as root, so not changing UID/GID.");
/* Create log file after we drop privileges */
@@ -407,56 +389,44 @@ main (int argc, char **argv)
exit (EX_SOFTWARE);
}
- if (child_pool_create () < 0) {
- fprintf (stderr,
- "%s: Could not create the pool of children.\n",
- argv[0]);
- exit (EX_SOFTWARE);
- }
-
/* These signals are only for the parent process. */
log_message (LOG_INFO, "Setting the various signals.");
- if (set_signal_handler (SIGCHLD, takesig) == SIG_ERR) {
- fprintf (stderr, "%s: Could not set the \"SIGCHLD\" signal.\n",
- argv[0]);
- exit (EX_OSERR);
- }
+ setup_sig (SIGCHLD, takesig, "SIGCHLD", argv[0]);
+ setup_sig (SIGTERM, takesig, "SIGTERM", argv[0]);
+ setup_sig (SIGINT, takesig, "SIGINT", argv[0]);
+ if (daemonized) setup_sig (SIGHUP, takesig, "SIGHUP", argv[0]);
+ setup_sig (SIGUSR1, takesig, "SIGUSR1", argv[0]);
- if (set_signal_handler (SIGTERM, takesig) == SIG_ERR) {
- fprintf (stderr, "%s: Could not set the \"SIGTERM\" signal.\n",
- argv[0]);
- exit (EX_OSERR);
- }
-
- if (set_signal_handler (SIGHUP, takesig) == SIG_ERR) {
- fprintf (stderr, "%s: Could not set the \"SIGHUP\" signal.\n",
- argv[0]);
- exit (EX_OSERR);
- }
+ loop_records_init();
/* Start the main loop */
log_message (LOG_INFO, "Starting main loop. Accepting connections.");
child_main_loop ();
- log_message (LOG_INFO, "Shutting down.");
+ log_message (LOG_NOTICE, "Shutting down.");
child_kill_children (SIGTERM);
child_close_sock ();
+ child_free_children();
+
+ loop_records_destroy();
/* Remove the PID file */
- if (config.pidpath != NULL && unlink (config.pidpath) < 0) {
+ if (config->pidpath != NULL && unlink (config->pidpath) < 0) {
log_message (LOG_WARNING,
"Could not remove PID file \"%s\": %s.",
- config.pidpath, strerror (errno));
+ config->pidpath, strerror (errno));
}
#ifdef FILTER_ENABLE
- if (config.filter)
+ if (config->filter)
filter_destroy ();
#endif /* FILTER_ENABLE */
+ free_config (config);
+
shutdown_logging ();
return EXIT_SUCCESS;