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