1 /*	$NetBSD: load_file.c,v 1.1.1.1 2009/06/23 10:09:00 tron Exp $	*/
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 
52 /* load_file - load file with some prejudice */
53 
54 void    load_file(const char *path, LOAD_FILE_FN action, void *context)
55 {
56     VSTREAM *fp;
57     struct stat st;
58     time_t  before;
59     time_t  after;
60 
61     /*
62      * Read the file again if it is hot. This may result in reading a partial
63      * parameter name or missing end marker when a file changes in the middle
64      * of a read.
65      */
66     for (before = time((time_t *) 0); /* see below */ ; before = after) {
67 	if ((fp = vstream_fopen(path, O_RDONLY, 0)) == 0)
68 	    msg_fatal("open %s: %m", path);
69 	action(fp, context);
70 	if (fstat(vstream_fileno(fp), &st) < 0)
71 	    msg_fatal("fstat %s: %m", path);
72 	if (vstream_ferror(fp) || vstream_fclose(fp))
73 	    msg_fatal("read %s: %m", path);
74 	after = time((time_t *) 0);
75 	if (st.st_mtime < before - 1 || st.st_mtime > after)
76 	    break;
77 	if (msg_verbose)
78 	    msg_info("pausing to let %s cool down", path);
79 	doze(300000);
80     }
81 }
82