1/*++ 2/* NAME 3/* load_file 3 4/* SUMMARY 5/* load file with some prejudice 6/* SYNOPSIS 7/* #include <load_file.h> 8/* 9/* void load_file(path, action, context) 10/* const char *path; 11/* void (*action)(VSTREAM, void *); 12/* void *context; 13/* DESCRIPTION 14/* This routine reads a file and reads it again when the 15/* file changed recently. 16/* 17/* Arguments: 18/* .IP path 19/* The file to be opened, read-only. 20/* .IP action 21/* The function that presumably reads the file. 22/* .IP context 23/* Application-specific context for the action routine. 24/* DIAGNOSTICS 25/* Fatal errors: out of memory, cannot open file. 26/* LICENSE 27/* .ad 28/* .fi 29/* The Secure Mailer license must be distributed with this software. 30/* AUTHOR(S) 31/* Wietse Venema 32/* IBM T.J. Watson Research 33/* P.O. Box 704 34/* Yorktown Heights, NY 10598, USA 35/*--*/ 36 37/* System library. */ 38 39#include <sys_defs.h> 40#include <sys/stat.h> 41#include <time.h> 42 43/* Utility library. */ 44 45#include <msg.h> 46#include <vstream.h> 47#include <iostuff.h> 48#include <load_file.h> 49#include <warn_stat.h> 50 51/* load_file - load file with some prejudice */ 52 53void load_file(const char *path, LOAD_FILE_FN action, void *context) 54{ 55 VSTREAM *fp; 56 struct stat st; 57 time_t before; 58 time_t after; 59 60 /* 61 * Read the file again if it is hot. This may result in reading a partial 62 * parameter name or missing end marker when a file changes in the middle 63 * of a read. 64 */ 65 for (before = time((time_t *) 0); /* see below */ ; before = after) { 66 if ((fp = vstream_fopen(path, O_RDONLY, 0)) == 0) 67 msg_fatal("open %s: %m", path); 68 action(fp, context); 69 if (fstat(vstream_fileno(fp), &st) < 0) 70 msg_fatal("fstat %s: %m", path); 71 if (vstream_ferror(fp) || vstream_fclose(fp)) 72 msg_fatal("read %s: %m", path); 73 after = time((time_t *) 0); 74 if (st.st_mtime < before - 1 || st.st_mtime > after) 75 break; 76 if (msg_verbose) 77 msg_info("pausing to let %s cool down", path); 78 doze(300000); 79 } 80} 81