summaryrefslogtreecommitdiff
path: root/src/child.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/child.c')
-rw-r--r--src/child.c594
1 files changed, 280 insertions, 314 deletions
diff --git a/src/child.c b/src/child.c
index bb4110c..9e8d515 100644
--- a/src/child.c
+++ b/src/child.c
@@ -37,13 +37,11 @@ static socklen_t addrlen;
/*
* Stores the internal data needed for each child (connection)
*/
-enum child_status_t
-{ T_EMPTY, T_WAITING, T_CONNECTED };
-struct child_s
-{
- pid_t tid;
- unsigned int connects;
- enum child_status_t status;
+enum child_status_t { T_EMPTY, T_WAITING, T_CONNECTED };
+struct child_s {
+ pid_t tid;
+ unsigned int connects;
+ enum child_status_t status;
};
/*
@@ -52,10 +50,9 @@ struct child_s
*/
static struct child_s *child_ptr;
-static struct child_config_s
-{
- unsigned int maxclients, maxrequestsperchild;
- unsigned int maxspareservers, minspareservers, startservers;
+static struct child_config_s {
+ unsigned int maxclients, maxrequestsperchild;
+ unsigned int maxspareservers, minspareservers, startservers;
} child_config;
static unsigned int *servers_waiting; /* servers waiting for a connection */
@@ -76,49 +73,45 @@ static unsigned int *servers_waiting; /* servers waiting for a connection */
static struct flock lock_it, unlock_it;
static int lock_fd = -1;
-static void
-_child_lock_init (void)
+static void _child_lock_init (void)
{
- char lock_file[] = "/tmp/tinyproxy.servers.lock.XXXXXX";
+ char lock_file[] = "/tmp/tinyproxy.servers.lock.XXXXXX";
- /* Only allow u+rw bits. This may be required for some versions
- * of glibc so that mkstemp() doesn't make us vulnerable.
- */
- umask (0177);
+ /* Only allow u+rw bits. This may be required for some versions
+ * of glibc so that mkstemp() doesn't make us vulnerable.
+ */
+ umask (0177);
- lock_fd = mkstemp (lock_file);
- unlink (lock_file);
+ lock_fd = mkstemp (lock_file);
+ unlink (lock_file);
- lock_it.l_type = F_WRLCK;
- lock_it.l_whence = SEEK_SET;
- lock_it.l_start = 0;
- lock_it.l_len = 0;
+ lock_it.l_type = F_WRLCK;
+ lock_it.l_whence = SEEK_SET;
+ lock_it.l_start = 0;
+ lock_it.l_len = 0;
- unlock_it.l_type = F_UNLCK;
- unlock_it.l_whence = SEEK_SET;
- unlock_it.l_start = 0;
- unlock_it.l_len = 0;
+ unlock_it.l_type = F_UNLCK;
+ unlock_it.l_whence = SEEK_SET;
+ unlock_it.l_start = 0;
+ unlock_it.l_len = 0;
}
-static void
-_child_lock_wait (void)
+static void _child_lock_wait (void)
{
- int rc;
-
- while ((rc = fcntl (lock_fd, F_SETLKW, &lock_it)) < 0)
- {
- if (errno == EINTR)
- continue;
- else
- return;
- }
+ int rc;
+
+ while ((rc = fcntl (lock_fd, F_SETLKW, &lock_it)) < 0) {
+ if (errno == EINTR)
+ continue;
+ else
+ return;
+ }
}
-static void
-_child_lock_release (void)
+static void _child_lock_release (void)
{
- if (fcntl (lock_fd, F_SETLKW, &unlock_it) < 0)
- return;
+ if (fcntl (lock_fd, F_SETLKW, &unlock_it) < 0)
+ return;
}
/* END OF LOCKING SECTION */
@@ -141,348 +134,321 @@ _child_lock_release (void)
/*
* Set the configuration values for the various child related settings.
*/
-short int
-child_configure (child_config_t type, unsigned int val)
+short int child_configure (child_config_t type, unsigned int val)
{
- switch (type)
- {
- case CHILD_MAXCLIENTS:
- child_config.maxclients = val;
- break;
- case CHILD_MAXSPARESERVERS:
- child_config.maxspareservers = val;
- break;
- case CHILD_MINSPARESERVERS:
- child_config.minspareservers = val;
- break;
- case CHILD_STARTSERVERS:
- child_config.startservers = val;
- break;
- case CHILD_MAXREQUESTSPERCHILD:
- child_config.maxrequestsperchild = val;
- break;
- default:
- DEBUG2 ("Invalid type (%d)", type);
- return -1;
- }
-
- return 0;
+ switch (type) {
+ case CHILD_MAXCLIENTS:
+ child_config.maxclients = val;
+ break;
+ case CHILD_MAXSPARESERVERS:
+ child_config.maxspareservers = val;
+ break;
+ case CHILD_MINSPARESERVERS:
+ child_config.minspareservers = val;
+ break;
+ case CHILD_STARTSERVERS:
+ child_config.startservers = val;
+ break;
+ case CHILD_MAXREQUESTSPERCHILD:
+ child_config.maxrequestsperchild = val;
+ break;
+ default:
+ DEBUG2 ("Invalid type (%d)", type);
+ return -1;
+ }
+
+ return 0;
}
/*
* This is the main (per child) loop.
*/
-static void
-child_main (struct child_s *ptr)
+static void child_main (struct child_s *ptr)
{
- int connfd;
- struct sockaddr *cliaddr;
- socklen_t clilen;
-
- cliaddr = (struct sockaddr *)safemalloc (addrlen);
- if (!cliaddr)
- {
- log_message (LOG_CRIT, "Could not allocate memory for child address.");
- exit (0);
- }
+ int connfd;
+ struct sockaddr *cliaddr;
+ socklen_t clilen;
+
+ cliaddr = (struct sockaddr *) safemalloc (addrlen);
+ if (!cliaddr) {
+ log_message (LOG_CRIT,
+ "Could not allocate memory for child address.");
+ exit (0);
+ }
- ptr->connects = 0;
+ ptr->connects = 0;
- while (!config.quit)
- {
- ptr->status = T_WAITING;
+ while (!config.quit) {
+ ptr->status = T_WAITING;
- clilen = addrlen;
+ clilen = addrlen;
- connfd = accept (listenfd, cliaddr, &clilen);
+ connfd = accept (listenfd, cliaddr, &clilen);
#ifndef NDEBUG
- /*
- * Enable the TINYPROXY_DEBUG environment variable if you
- * want to use the GDB debugger.
- */
- if (getenv ("TINYPROXY_DEBUG"))
- {
- /* Pause for 10 seconds to allow us to connect debugger */
- fprintf (stderr,
- "Process has accepted connection: %ld\n",
- (long int) ptr->tid);
- sleep (10);
- fprintf (stderr, "Continuing process: %ld\n", (long int) ptr->tid);
- }
+ /*
+ * Enable the TINYPROXY_DEBUG environment variable if you
+ * want to use the GDB debugger.
+ */
+ if (getenv ("TINYPROXY_DEBUG")) {
+ /* Pause for 10 seconds to allow us to connect debugger */
+ fprintf (stderr,
+ "Process has accepted connection: %ld\n",
+ (long int) ptr->tid);
+ sleep (10);
+ fprintf (stderr, "Continuing process: %ld\n",
+ (long int) ptr->tid);
+ }
#endif
- /*
- * Make sure no error occurred...
- */
- if (connfd < 0)
- {
- log_message (LOG_ERR,
- "Accept returned an error (%s) ... retrying.",
- strerror (errno));
- continue;
- }
+ /*
+ * Make sure no error occurred...
+ */
+ if (connfd < 0) {
+ log_message (LOG_ERR,
+ "Accept returned an error (%s) ... retrying.",
+ strerror (errno));
+ continue;
+ }
- ptr->status = T_CONNECTED;
+ ptr->status = T_CONNECTED;
- SERVER_DEC ();
+ SERVER_DEC ();
- handle_connection (connfd);
- ptr->connects++;
+ handle_connection (connfd);
+ ptr->connects++;
- if (child_config.maxrequestsperchild != 0)
- {
- DEBUG2 ("%u connections so far...", ptr->connects);
+ if (child_config.maxrequestsperchild != 0) {
+ DEBUG2 ("%u connections so far...", ptr->connects);
- if (ptr->connects == child_config.maxrequestsperchild)
- {
- log_message (LOG_NOTICE,
- "Child has reached MaxRequestsPerChild (%u). "
- "Killing child.", ptr->connects);
- break;
- }
- }
+ if (ptr->connects == child_config.maxrequestsperchild) {
+ log_message (LOG_NOTICE,
+ "Child has reached MaxRequestsPerChild (%u). "
+ "Killing child.", ptr->connects);
+ break;
+ }
+ }
- SERVER_COUNT_LOCK ();
- if (*servers_waiting > child_config.maxspareservers)
- {
- /*
- * There are too many spare children, kill ourself
- * off.
- */
- log_message (LOG_NOTICE,
- "Waiting servers (%d) exceeds MaxSpareServers (%d). "
- "Killing child.",
- *servers_waiting, child_config.maxspareservers);
- SERVER_COUNT_UNLOCK ();
-
- break;
- }
- else
- {
- SERVER_COUNT_UNLOCK ();
- }
+ SERVER_COUNT_LOCK ();
+ if (*servers_waiting > child_config.maxspareservers) {
+ /*
+ * There are too many spare children, kill ourself
+ * off.
+ */
+ log_message (LOG_NOTICE,
+ "Waiting servers (%d) exceeds MaxSpareServers (%d). "
+ "Killing child.",
+ *servers_waiting,
+ child_config.maxspareservers);
+ SERVER_COUNT_UNLOCK ();
+
+ break;
+ } else {
+ SERVER_COUNT_UNLOCK ();
+ }
- SERVER_INC ();
- }
+ SERVER_INC ();
+ }
- ptr->status = T_EMPTY;
+ ptr->status = T_EMPTY;
- safefree (cliaddr);
- exit (0);
+ safefree (cliaddr);
+ exit (0);
}
/*
* Fork a child "child" (or in our case a process) and then start up the
* child_main() function.
*/
-static pid_t
-child_make (struct child_s *ptr)
+static pid_t child_make (struct child_s *ptr)
{
- pid_t pid;
+ pid_t pid;
- if ((pid = fork ()) > 0)
- return pid; /* parent */
+ if ((pid = fork ()) > 0)
+ return pid; /* parent */
- /*
- * Reset the SIGNALS so that the child can be reaped.
- */
- set_signal_handler (SIGCHLD, SIG_DFL);
- set_signal_handler (SIGTERM, SIG_DFL);
- set_signal_handler (SIGHUP, SIG_DFL);
+ /*
+ * Reset the SIGNALS so that the child can be reaped.
+ */
+ set_signal_handler (SIGCHLD, SIG_DFL);
+ set_signal_handler (SIGTERM, SIG_DFL);
+ set_signal_handler (SIGHUP, SIG_DFL);
- child_main (ptr); /* never returns */
- return -1;
+ child_main (ptr); /* never returns */
+ return -1;
}
/*
* Create a pool of children to handle incoming connections
*/
-short int
-child_pool_create (void)
+short int child_pool_create (void)
{
- unsigned int i;
-
- /*
- * Make sure the number of MaxClients is not zero, since this
- * variable determines the size of the array created for children
- * later on.
- */
- if (child_config.maxclients == 0)
- {
- log_message (LOG_ERR,
- "child_pool_create: \"MaxClients\" must be "
- "greater than zero.");
- return -1;
- }
- if (child_config.startservers == 0)
- {
- log_message (LOG_ERR,
- "child_pool_create: \"StartServers\" must be "
- "greater than zero.");
- return -1;
- }
-
- child_ptr = (struct child_s *)calloc_shared_memory (child_config.maxclients,
- sizeof (struct child_s));
- if (!child_ptr)
- {
- log_message (LOG_ERR, "Could not allocate memory for children.");
- return -1;
- }
-
- servers_waiting = (unsigned int *)malloc_shared_memory (sizeof (unsigned int));
- if (servers_waiting == MAP_FAILED)
- {
- log_message (LOG_ERR, "Could not allocate memory for child counting.");
- return -1;
- }
- *servers_waiting = 0;
-
- /*
- * Create a "locking" file for use around the servers_waiting
- * variable.
- */
- _child_lock_init ();
-
- if (child_config.startservers > child_config.maxclients)
- {
- log_message (LOG_WARNING,
- "Can not start more than \"MaxClients\" servers. "
- "Starting %u servers instead.", child_config.maxclients);
- child_config.startservers = child_config.maxclients;
- }
-
- for (i = 0; i != child_config.maxclients; i++)
- {
- child_ptr[i].status = T_EMPTY;
- child_ptr[i].connects = 0;
- }
-
- for (i = 0; i != child_config.startservers; i++)
- {
- DEBUG2 ("Trying to create child %d of %d", i + 1,
- child_config.startservers);
- child_ptr[i].status = T_WAITING;
- child_ptr[i].tid = child_make (&child_ptr[i]);
-
- if (child_ptr[i].tid < 0)
- {
- log_message (LOG_WARNING,
- "Could not create child number %d of %d",
- i, child_config.startservers);
- return -1;
+ unsigned int i;
+
+ /*
+ * Make sure the number of MaxClients is not zero, since this
+ * variable determines the size of the array created for children
+ * later on.
+ */
+ if (child_config.maxclients == 0) {
+ log_message (LOG_ERR,
+ "child_pool_create: \"MaxClients\" must be "
+ "greater than zero.");
+ return -1;
+ }
+ if (child_config.startservers == 0) {
+ log_message (LOG_ERR,
+ "child_pool_create: \"StartServers\" must be "
+ "greater than zero.");
+ return -1;
+ }
+
+ child_ptr =
+ (struct child_s *) calloc_shared_memory (child_config.maxclients,
+ sizeof (struct child_s));
+ if (!child_ptr) {
+ log_message (LOG_ERR,
+ "Could not allocate memory for children.");
+ return -1;
}
- else
- {
- log_message (LOG_INFO,
- "Creating child number %d of %d ...",
- i + 1, child_config.startservers);
- SERVER_INC ();
+ servers_waiting =
+ (unsigned int *) malloc_shared_memory (sizeof (unsigned int));
+ if (servers_waiting == MAP_FAILED) {
+ log_message (LOG_ERR,
+ "Could not allocate memory for child counting.");
+ return -1;
+ }
+ *servers_waiting = 0;
+
+ /*
+ * Create a "locking" file for use around the servers_waiting
+ * variable.
+ */
+ _child_lock_init ();
+
+ if (child_config.startservers > child_config.maxclients) {
+ log_message (LOG_WARNING,
+ "Can not start more than \"MaxClients\" servers. "
+ "Starting %u servers instead.",
+ child_config.maxclients);
+ child_config.startservers = child_config.maxclients;
}
- }
- log_message (LOG_INFO, "Finished creating all children.");
+ for (i = 0; i != child_config.maxclients; i++) {
+ child_ptr[i].status = T_EMPTY;
+ child_ptr[i].connects = 0;
+ }
- return 0;
+ for (i = 0; i != child_config.startservers; i++) {
+ DEBUG2 ("Trying to create child %d of %d", i + 1,
+ child_config.startservers);
+ child_ptr[i].status = T_WAITING;
+ child_ptr[i].tid = child_make (&child_ptr[i]);
+
+ if (child_ptr[i].tid < 0) {
+ log_message (LOG_WARNING,
+ "Could not create child number %d of %d",
+ i, child_config.startservers);
+ return -1;
+ } else {
+ log_message (LOG_INFO,
+ "Creating child number %d of %d ...",
+ i + 1, child_config.startservers);
+
+ SERVER_INC ();
+ }
+ }
+
+ log_message (LOG_INFO, "Finished creating all children.");
+
+ return 0;
}
/*
* Keep the proper number of servers running. This is the birth of the
* servers. It monitors this at least once a second.
*/
-void
-child_main_loop (void)
+void child_main_loop (void)
{
- unsigned int i;
-
- while (1)
- {
- if (config.quit)
- return;
-
- /* If there are not enough spare servers, create more */
- SERVER_COUNT_LOCK ();
- if (*servers_waiting < child_config.minspareservers)
- {
- log_message (LOG_NOTICE,
- "Waiting servers (%d) is less than MinSpareServers (%d). "
- "Creating new child.",
- *servers_waiting, child_config.minspareservers);
-
- SERVER_COUNT_UNLOCK ();
-
- for (i = 0; i != child_config.maxclients; i++)
- {
- if (child_ptr[i].status == T_EMPTY)
- {
- child_ptr[i].status = T_WAITING;
- child_ptr[i].tid = child_make (&child_ptr[i]);
- if (child_ptr[i].tid < 0)
- {
- log_message (LOG_NOTICE, "Could not create child");
-
- child_ptr[i].status = T_EMPTY;
- break;
- }
-
- SERVER_INC ();
-
- break;
+ unsigned int i;
+
+ while (1) {
+ if (config.quit)
+ return;
+
+ /* If there are not enough spare servers, create more */
+ SERVER_COUNT_LOCK ();
+ if (*servers_waiting < child_config.minspareservers) {
+ log_message (LOG_NOTICE,
+ "Waiting servers (%d) is less than MinSpareServers (%d). "
+ "Creating new child.",
+ *servers_waiting,
+ child_config.minspareservers);
+
+ SERVER_COUNT_UNLOCK ();
+
+ for (i = 0; i != child_config.maxclients; i++) {
+ if (child_ptr[i].status == T_EMPTY) {
+ child_ptr[i].status = T_WAITING;
+ child_ptr[i].tid =
+ child_make (&child_ptr[i]);
+ if (child_ptr[i].tid < 0) {
+ log_message (LOG_NOTICE,
+ "Could not create child");
+
+ child_ptr[i].status = T_EMPTY;
+ break;
+ }
+
+ SERVER_INC ();
+
+ break;
+ }
+ }
+ } else {
+ SERVER_COUNT_UNLOCK ();
}
- }
- }
- else
- {
- SERVER_COUNT_UNLOCK ();
- }
- sleep (5);
+ sleep (5);
- /* Handle log rotation if it was requested */
- if (received_sighup)
- {
- truncate_log_file ();
+ /* Handle log rotation if it was requested */
+ if (received_sighup) {
+ truncate_log_file ();
#ifdef FILTER_ENABLE
- if (config.filter)
- {
- filter_destroy ();
- filter_init ();
- }
- log_message (LOG_NOTICE, "Re-reading filter file.");
+ if (config.filter) {
+ filter_destroy ();
+ filter_init ();
+ }
+ log_message (LOG_NOTICE, "Re-reading filter file.");
#endif /* FILTER_ENABLE */
- received_sighup = FALSE;
+ received_sighup = FALSE;
+ }
}
- }
}
/*
* Go through all the non-empty children and cancel them.
*/
-void
-child_kill_children (void)
+void child_kill_children (void)
{
- unsigned int i;
+ unsigned int i;
- for (i = 0; i != child_config.maxclients; i++)
- {
- if (child_ptr[i].status != T_EMPTY)
- kill (child_ptr[i].tid, SIGTERM);
- }
+ for (i = 0; i != child_config.maxclients; i++) {
+ if (child_ptr[i].status != T_EMPTY)
+ kill (child_ptr[i].tid, SIGTERM);
+ }
}
-int
-child_listening_sock (uint16_t port)
+int child_listening_sock (uint16_t port)
{
- listenfd = listen_sock (port, &addrlen);
- return listenfd;
+ listenfd = listen_sock (port, &addrlen);
+ return listenfd;
}
-void
-child_close_sock (void)
+void child_close_sock (void)
{
- close (listenfd);
+ close (listenfd);
}