aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Garzik <jeff@garzik.org>2012-07-17 20:19:24 -0400
committerJeff Garzik <jgarzik@redhat.com>2012-07-17 20:19:24 -0400
commitc192b4cf8bb8715dd4c5e4058f5638fc5c4a81d1 (patch)
tree49425c96020ee70a0cf2f14e934b979ca5e721c2
parente42da63c90b4221b7d427566aa05b5d330890e0a (diff)
downloadrng-tools-c192b4cf8bb8715dd4c5e4058f5638fc5c4a81d1.tar.gz
rng-tools-c192b4cf8bb8715dd4c5e4058f5638fc5c4a81d1.tar.xz
rng-tools-c192b4cf8bb8715dd4c5e4058f5638fc5c4a81d1.zip
Create PID file at startup, in daemon mode
Code imported from Project Hail
-rw-r--r--Makefile.am2
-rw-r--r--rngd.8.in5
-rw-r--r--rngd.c36
-rw-r--r--rngd.h2
-rw-r--r--util.c104
5 files changed, 146 insertions, 3 deletions
diff --git a/Makefile.am b/Makefile.am
index d0cec2d..6822181 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -10,7 +10,7 @@ man_MANS = rngd.8 rngtest.1
noinst_LIBRARIES = librngd.a
rngd_SOURCES = rngd.h rngd.c rngd_entsource.h rngd_entsource.c \
- rngd_linux.h rngd_linux.c
+ rngd_linux.h rngd_linux.c util.c
rngd_LDADD = librngd.a
rngtest_SOURCES = exits.h stats.h stats.c rngtest.c
diff --git a/rngd.8.in b/rngd.8.in
index bbd9e3c..2fd357f 100644
--- a/rngd.8.in
+++ b/rngd.8.in
@@ -10,6 +10,7 @@ rngd \- Check and feed random data from hardware device to kernel random device
[\fB\-b\fR, \fB\-\-background\fR]
[\fB\-f\fR, \fB\-\-foreground\fR]
[\fB\-o\fR, \fB\-\-random-device=\fIfile\fR]
+[\fB\-p\fR, \fB\-\-pid-file=\fIfile\fR]
[\fB\-r\fR, \fB\-\-rng-device=\fIfile\fR]
[\fB\-s\fR, \fB\-\-random-step=\fInnn\fR]
[\fB\-W\fR, \fB\-\-fill-watermark=\fInnn\fR]
@@ -48,6 +49,10 @@ Become a daemon (default)
\fB\-f\fR, \fB\-\-foreground\fR
Do not fork and become a daemon
.TP
+\fB\-p\fI file\fR, \fB\-\-pid-file=\fIfile\fR
+File used for recording daemon PID, and multiple exclusion
+(default: /var/run/rngd.pid)
+.TP
\fB\-o\fI file\fR, \fB\-\-random-device=\fIfile\fR
Kernel device used for random number output
(default: /dev/random)
diff --git a/rngd.c b/rngd.c
index 90232f8..5875671 100644
--- a/rngd.c
+++ b/rngd.c
@@ -45,6 +45,7 @@
#include <string.h>
#include <argp.h>
#include <syslog.h>
+#include <signal.h>
#include "rngd.h"
#include "fips.h"
@@ -59,6 +60,8 @@
/* Background/daemon mode */
int am_daemon; /* Nonzero if we went daemon */
+bool server_running = true; /* set to false, to stop daemon */
+
/* Command line arguments and processing */
const char *argp_program_version =
"rngd " VERSION "\n"
@@ -83,6 +86,9 @@ static struct argp_option options[] = {
{ "rng-device", 'r', "file", 0,
"Kernel device used for random number input (default: /dev/hw_random)" },
+ { "pid-file", 'p', "file", 0,
+ "File used for recording daemon PID, and multiple exclusion (default: /var/run/rngd.pid)" },
+
{ "random-step", 's', "nnn", 0,
"Number of bytes written to random-device at a time (default: 64)" },
@@ -103,6 +109,7 @@ static struct argp_option options[] = {
static struct arguments default_arguments = {
.random_name = "/dev/random",
+ .pid_file = "/var/run/rngd.pid",
.poll_timeout = 60,
.random_step = 64,
.fill_watermark = 2048,
@@ -136,6 +143,9 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state)
case 'o':
arguments->random_name = arg;
break;
+ case 'p':
+ arguments->pid_file = arg;
+ break;
case 'r':
rng_default.rng_name = arg;
break;
@@ -227,6 +237,9 @@ static void do_loop(int random_step, double poll_timeout)
{
int rc;
+ if (!server_running)
+ return;
+
if (iter->disabled)
continue; /* failed, no work */
@@ -260,10 +273,16 @@ static void do_loop(int random_step, double poll_timeout)
"No entropy sources working, exiting rngd\n");
}
+static void term_signal(int signo)
+{
+ server_running = false;
+}
+
int main(int argc, char **argv)
{
int rc_rng = 0;
int rc_tpm = 0;
+ int pid_fd = -1;
openlog("rngd", 0, LOG_DAEMON);
@@ -284,7 +303,7 @@ int main(int argc, char **argv)
}
return 1;
}
-
+
if (arguments->verbose) {
printf("Available entropy sources:\n");
if (!rc_rng)
@@ -293,7 +312,7 @@ int main(int argc, char **argv)
printf("\tTPM\n");
}
- if (rc_rng
+ if (rc_rng
&& (rc_tpm || !arguments->enable_tpm)) {
if (!arguments->quiet)
message(LOG_DAEMON|LOG_ERR,
@@ -313,10 +332,23 @@ int main(int argc, char **argv)
strerror(errno));
return 1;
}
+
+ /* require valid, locked PID file to proceed */
+ pid_fd = write_pid_file(arguments->pid_file);
+ if (pid_fd < 0)
+ return 1;
+
+ signal(SIGHUP, SIG_IGN);
+ signal(SIGPIPE, SIG_IGN);
+ signal(SIGINT, term_signal);
+ signal(SIGTERM, term_signal);
}
do_loop(arguments->random_step,
arguments->poll_timeout ? : -1.0);
+ if (pid_fd >= 0)
+ unlink(arguments->pid_file);
+
return 0;
}
diff --git a/rngd.h b/rngd.h
index 60a9861..074bcd6 100644
--- a/rngd.h
+++ b/rngd.h
@@ -40,6 +40,7 @@ enum {
/* Command line arguments and processing */
struct arguments {
char *random_name;
+ char *pid_file;
int random_step;
int fill_watermark;
@@ -82,5 +83,6 @@ extern int am_daemon; /* Nonzero if we went daemon */
} while (0)
extern void src_list_add(struct rng *ent_src);
+extern int write_pid_file(const char *pid_fn);
#endif /* RNGD__H */
diff --git a/util.c b/util.c
new file mode 100644
index 0000000..bc1903a
--- /dev/null
+++ b/util.c
@@ -0,0 +1,104 @@
+
+/*
+ * Copyright 2009 Red Hat, Inc.
+ *
+ * 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.
+ *
+ * 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; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#define _GNU_SOURCE
+
+#ifndef HAVE_CONFIG_H
+#error Invalid or missing autoconf build environment
+#endif
+
+#include "rng-tools-config.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+
+#include "rngd.h"
+
+int write_pid_file(const char *pid_fn)
+{
+ char str[32], *s;
+ size_t bytes;
+ int fd;
+ struct flock lock;
+ int err;
+
+ /* build file data */
+ sprintf(str, "%u\n", (unsigned int) getpid());
+
+ /* open non-exclusively (works on NFS v2) */
+ fd = open(pid_fn, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
+ if (fd < 0) {
+ err = errno;
+
+ message(LOG_DAEMON|LOG_ERR, "Cannot open PID file %s: %s",
+ pid_fn, strerror(err));
+ return -err;
+ }
+
+ /* lock */
+ memset(&lock, 0, sizeof(lock));
+ lock.l_type = F_WRLCK;
+ lock.l_whence = SEEK_SET;
+ if (fcntl(fd, F_SETLK, &lock) != 0) {
+ err = errno;
+ if (err == EAGAIN) {
+ message(LOG_DAEMON|LOG_ERR, "PID file %s is already locked",
+ pid_fn);
+ } else {
+ message(LOG_DAEMON|LOG_ERR, "Cannot lock PID file %s: %s",
+ pid_fn, strerror(err));
+ }
+ close(fd);
+ return -err;
+ }
+
+ /* write file data */
+ bytes = strlen(str);
+ s = str;
+ while (bytes > 0) {
+ ssize_t rc = write(fd, s, bytes);
+ if (rc < 0) {
+ err = errno;
+ message(LOG_DAEMON|LOG_ERR, "PID number write failed: %s",
+ strerror(err));
+ goto err_out;
+ }
+
+ bytes -= rc;
+ s += rc;
+ }
+
+ /* make sure file data is written to disk */
+ if (fsync(fd) < 0) {
+ err = errno;
+ message(LOG_DAEMON|LOG_ERR, "PID file fsync failed: %s", strerror(err));
+ goto err_out;
+ }
+
+ return fd;
+
+err_out:
+ unlink(pid_fn);
+ close(fd);
+ return -err;
+}
+