summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/remctld.c43
1 files changed, 28 insertions, 15 deletions
diff --git a/server/remctld.c b/server/remctld.c
index a891cc5..e83a8d4 100644
--- a/server/remctld.c
+++ b/server/remctld.c
@@ -226,7 +226,7 @@ acquire_creds(char *service, gss_cred_id_t *creds)
* completed, either successfully or unsuccessfully.
*/
static void
-server_handle_connection(int fd, struct config *config, gss_cred_id_t creds)
+handle_connection(int fd, struct config *config, gss_cred_id_t creds)
{
struct client *client;
@@ -260,7 +260,7 @@ server_handle_connection(int fd, struct config *config, gss_cred_id_t creds)
* a non-zero exit status.
*/
static void
-server_log_child(pid_t pid, int status)
+log_child(pid_t pid, int status)
{
if (WIFEXITED(status)) {
if (WEXITSTATUS(status) != 0)
@@ -409,6 +409,7 @@ server_daemon(struct options *options, struct config *config,
struct sockaddr_storage ss;
socklen_t sslen;
char ip[INET6_ADDRSTRLEN];
+ OM_uint32 minor;
/* Set up a SIGCHLD handler so that we know when to reap children. */
memset(&sa, 0, sizeof(sa));
@@ -461,11 +462,11 @@ server_daemon(struct options *options, struct config *config,
* processes, so you may want to set system resource limits to prevent an
* attacker from consuming all available processes.
*/
- do {
+ while (1) {
if (child_signaled) {
child_signaled = 0;
while ((child = waitpid(0, &status, WNOHANG)) > 0)
- server_log_child(child, status);
+ log_child(child, status);
if (child < 0 && errno != ECHILD)
sysdie("waitpid failed");
}
@@ -479,9 +480,7 @@ server_daemon(struct options *options, struct config *config,
}
if (exit_signaled) {
notice("signal received, exiting");
- if (options->pid_path != NULL)
- unlink(options->pid_path);
- exit(0);
+ break;
}
sslen = sizeof(ss);
s = network_accept_any(fds, nfds, (struct sockaddr *) &ss, &sslen);
@@ -499,18 +498,33 @@ server_daemon(struct options *options, struct config *config,
} else if (child == 0) {
for (i = 0; i < nfds; i++)
close(fds[i]);
+ network_bind_all_free(fds);
if (sigaction(SIGCHLD, &oldsa, NULL) < 0)
syswarn("cannot reset SIGCHLD handler");
- server_handle_connection(s, config, creds);
+ handle_connection(s, config, creds);
+ if (creds != GSS_C_NO_CREDENTIAL)
+ gss_release_cred(&minor, &creds);
if (options->log_stdout)
fflush(stdout);
+ server_config_free(config);
+ vector_free(options->bindaddrs);
exit(0);
} else {
close(s);
network_sockaddr_sprint(ip, sizeof(ip), (struct sockaddr *) &ss);
debug("child %lu for %s", (unsigned long) child, ip);
}
- } while (1);
+ }
+
+ /*
+ * Clean up resources at the end of the loop. This is not strictly
+ * necessary, but it helps valgrind testing.
+ */
+ if (options->pid_path != NULL)
+ unlink(options->pid_path);
+ for (i = 0; i < nfds; i++)
+ close(fds[i]);
+ network_bind_all_free(fds);
}
@@ -546,8 +560,6 @@ main(int argc, char *argv[])
/* Initialize options. */
memset(&options, 0, sizeof(options));
options.port = 4373;
- options.service = NULL;
- options.pid_path = NULL;
options.config_path = CONFIG_FILE;
options.bindaddrs = vector_new();
@@ -639,10 +651,9 @@ main(int argc, char *argv[])
* keep its default value of GSS_C_NO_CREDENTIAL, which means support
* anything that's in the keytab.
*/
- if (options.service != NULL) {
+ if (options.service != NULL)
if (!acquire_creds(options.service, &creds))
die("unable to acquire creds, aborting");
- }
/*
* If we're not running as a daemon, just process the connection.
@@ -650,13 +661,15 @@ main(int argc, char *argv[])
* incoming connection.
*/
if (!options.standalone)
- server_handle_connection(0, config, creds);
+ handle_connection(STDIN_FILENO, config, creds);
else
server_daemon(&options, config, creds);
- /* Clean up and exit. We only reach here in regular mode. */
+ /* Clean up and exit. */
+ server_config_free(config);
if (creds != GSS_C_NO_CREDENTIAL)
gss_release_cred(&minor, &creds);
+ vector_free(options.bindaddrs);
libevent_global_shutdown();
return 0;
}