]> git.ipfire.org Git - thirdparty/rng-tools.git/commitdiff
Create PID file at startup, in daemon mode
authorJeff Garzik <jeff@garzik.org>
Wed, 18 Jul 2012 00:19:24 +0000 (20:19 -0400)
committerJeff Garzik <jgarzik@redhat.com>
Wed, 18 Jul 2012 00:19:24 +0000 (20:19 -0400)
Code imported from Project Hail

Makefile.am
rngd.8.in
rngd.c
rngd.h
util.c [new file with mode: 0644]

index d0cec2d01a2d3c8041d411a4b748050c5273f3b7..682218194c324a11b757dc4e1a4ac2edb29ea45b 100644 (file)
@@ -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
index bbd9e3cf534d34e6d70aa3f66bb92d4b31786372..2fd357fe2dde2b057f74cbe2c72fef900a5c24c9 100644 (file)
--- 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 90232f88245a0190d33ebd12a4560566ae017369..587567175b4660b9fd2bf19c79acc328068f238c 100644 (file)
--- 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 60a98611dc8cf58105d5aa2767f137cd62d82933..074bcd65a0400f5f2c5d4a73d54fca5d04d1a617 100644 (file)
--- 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 (file)
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;
+}
+