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