aboutsummaryrefslogtreecommitdiff
path: root/watch.c
blob: 12cfbee8db9acf0007c5ece55e0a6c6f4120553b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include <err.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/event.h>
#include <unistd.h>

#define FD 27
#define MAXFILES 100
#define MAXFD 127 /* FD + MAXFILES */

int
main(int argc, char *argv[argc])
{
	char *filenames[MAXFD];
	int fd, i, kq, n;
	struct kevent evs[MAXFILES];
	struct kevent ev[MAXFILES];

	/* parse arguments */
	if (argc-1 == 0) goto usage;
	if (argv[1][0] == '-') {
		if (argv[1][1] == 'i')
			for (i = 2; i < argc; i++)
				printf("%s\n", argv[i]);
		else if (argv[1][1] == '-') ;
		else goto usage;
		argv++; argc--;
	}
	if (argc-1 == 0) goto usage;
	if (argc-1 > MAXFILES)
		errx(1, "more than %d files", MAXFILES);

	/* disable buffering even non-interactively */
	setbuf(stdout, NULL);

	/* initialize kqueue */
	if ((kq = kqueue()) == -1)
		err(1, "kqueue");

	/* process each file */
	for (i = 1; i < argc; i++) {
		if ((fd = open(argv[i], O_RDONLY)) == -1)
			err(1, "%s", argv[i]);

		filenames[fd] = argv[i];
		EV_SET(ev+i-1, fd, EVFILT_VNODE, EV_ADD|EV_CLEAR,
			NOTE_WRITE|NOTE_DELETE, 0, 0);
	}

	/* register events to watch for */
	if (kevent(kq, ev, argc-1, NULL, 0, NULL) == -1)
		err(1, "kevent");

	for (;;) {
		if ((n = kevent(kq, NULL, 0, evs, argc-1, NULL)) == -1)
			err(1, "kevent");
		for (i = 0; i < n; i++) {
			if (evs[i].fflags & NOTE_WRITE)
				printf("%s\n", filenames[evs[i].ident]);
			if (evs[i].flags & EV_ERROR)
				fprintf(stderr, "event error: %s\n",
					strerror(evs[i].data));
			if (evs[i].fflags & NOTE_DELETE) {
				fprintf(stderr, "%s deleted\n",
					filenames[evs[i].ident]);
				close(evs[i].ident);
			}
		}
	}

usage:
	fprintf(stderr, "usage: %s [-i] file\n", argv[0]);
	return 1;
}