summaryrefslogtreecommitdiffstats
path: root/src/util/load_file.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/load_file.c')
-rw-r--r--src/util/load_file.c80
1 files changed, 80 insertions, 0 deletions
diff --git a/src/util/load_file.c b/src/util/load_file.c
new file mode 100644
index 0000000..4e575d1
--- /dev/null
+++ b/src/util/load_file.c
@@ -0,0 +1,80 @@
+/*++
+/* NAME
+/* load_file 3
+/* SUMMARY
+/* load file with some prejudice
+/* SYNOPSIS
+/* #include <load_file.h>
+/*
+/* void load_file(path, action, context)
+/* const char *path;
+/* void (*action)(VSTREAM, void *);
+/* void *context;
+/* DESCRIPTION
+/* This routine reads a file and reads it again when the
+/* file changed recently.
+/*
+/* Arguments:
+/* .IP path
+/* The file to be opened, read-only.
+/* .IP action
+/* The function that presumably reads the file.
+/* .IP context
+/* Application-specific context for the action routine.
+/* DIAGNOSTICS
+/* Fatal errors: out of memory, cannot open file.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <sys/stat.h>
+#include <time.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <vstream.h>
+#include <iostuff.h>
+#include <load_file.h>
+#include <warn_stat.h>
+
+/* load_file - load file with some prejudice */
+
+void load_file(const char *path, LOAD_FILE_FN action, void *context)
+{
+ VSTREAM *fp;
+ struct stat st;
+ time_t before;
+ time_t after;
+
+ /*
+ * Read the file again if it is hot. This may result in reading a partial
+ * parameter name or missing end marker when a file changes in the middle
+ * of a read.
+ */
+ for (before = time((time_t *) 0); /* see below */ ; before = after) {
+ if ((fp = vstream_fopen(path, O_RDONLY, 0)) == 0)
+ msg_fatal("open %s: %m", path);
+ action(fp, context);
+ if (fstat(vstream_fileno(fp), &st) < 0)
+ msg_fatal("fstat %s: %m", path);
+ if (vstream_ferror(fp) || vstream_fclose(fp))
+ msg_fatal("read %s: %m", path);
+ after = time((time_t *) 0);
+ if (st.st_mtime < before - 1 || st.st_mtime > after)
+ break;
+ if (msg_verbose)
+ msg_info("pausing to let %s cool down", path);
+ doze(300000);
+ }
+}