commit d9b41bb26d563a50964b320cbe9f2634e7c0c784
parent 44ee3d650cfbd4e583dfac2f978ceb82d031f6c2
Author: z3bra <willy@mailoo.org>
Date: Wed, 12 Feb 2014 13:37:01 +0100
Merge branch 'master' of z3bra.org:wendy
Diffstat:
M | Makefile | | | 4 | +--- |
M | README | | | 38 | +++++++++++++++++++++++++++++++++++--- |
M | wendy.c | | | 76 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------ |
3 files changed, 100 insertions(+), 18 deletions(-)
diff --git a/Makefile b/Makefile
@@ -14,9 +14,7 @@ wendy : wendy.o
all : wendy
clean :
- ${RM} wendy
- ${RM} -f *.o
- ${RM} -f *~
+ ${RM} -f wendy *.o *~
path:
@echo PREFIX: ${PREFIX}
diff --git a/README b/README
@@ -12,13 +12,45 @@ specific command when an event occurs.
The program is made the moire simple possible, to leave the room to unlimited
uses. Be creative !
+Every event raised by inotify is handled. Just sum them up to watch multiple
+event at the same time. Here is the full table:
+(see inotify(1) for a better explanation of those events)
+
+ IN_ACCESS ........ 1
+ IN_MODIFY ........ 2
+ IN_ATTRIB ........ 4
+ IN_CLOSE_WRITE ... 8
+ IN_CLOSE_NOWRITE . 16
+ IN_OPEN .......... 32
+ IN_MOVED_FROM .... 64
+ IN_MOVED_TO ...... 128
+ IN_CREATE ........ 256
+ IN_DELETE ........ 512
+ IN_DELETE_SELF ... 1024
+ IN_MOVE_SELF ..... 2048
+
+To watch for both creation AND deletion in a directory, do some math:
+
+ 256 + 512 = 768
+
+then, pass that value to wendy so that she can watch after both of them (did I
+just say 'she'?).
+
+For more convenience, the IN_CREATE, IN_DELETE and IN_MODIFY events are bound to
+(respectively) -C, -D and -M.
+
Here are some examples:
# Tell me whenever I have a new mail
- wendy -C ~/mails/INBOX/new -t 60 -e espeak "You got a new mail"
+ wendy -C -d ~/mails/INBOX/new -t 60 -e espeak "You got a new mail"
# On-the-fly recompilation
- wendy -M -f ~/src/dev/program/source.c -t 1 -e make
+ wendy -M -q -d ~/src/dev/program/ -f source.c -t 1 -e make
+ # or eventually
+ wendy -l | grep -i close_write
+ IN_CLOSE_WRITE ... 8
+ wendy -m 8 -q -d ~/src/dev/program/ -f source.c -t 1 -e make
+
# Get up to date with community based projects
- wendy -DMC -f /mnt/nfs/project/ -t 30 -e notify-send 'project updated'
+ wendy -D -M -C -d /mnt/nfs/project/ -t 30 -e notify-send 'project updated'
diff --git a/wendy.c b/wendy.c
@@ -34,18 +34,53 @@ extern char **environ;
void
usage()
{
- fputs("usage: wendy [-C] [-D] [-M] [-f file] [-t timeout] "
- "-e command [arguments]\n"
- "\t-C : raise creation events\n"
+ fputs("usage: wendy [-C] [-D] [-M] [-m mask] [-l] [-f file] [-t timeout] [-q] "
+ "[-e command [args] ..]\n"
+ "\t-C : raise creation events (default)\n"
"\t-D : raise deletion events\n"
"\t-M : raise modification events\n"
+ "\t-m mask : set mask manually (see -l))\n"
+ "\t-l : list events mask values\n"
"\t-f file : file to watch (everything is a file)\n"
"\t-t timeout : time between event check (in seconds)\n"
+ "\t-q : don't talk to me, program\n"
"\t-e command : command to launch (must be the last argument!)\n",
stdout);
exit(1);
}
+void
+list_events()
+{
+ fprintf(stdout,
+ "IN_ACCESS ........ %u\n"
+ "IN_MODIFY ........ %u\n"
+ "IN_ATTRIB ........ %u\n"
+ "IN_CLOSE_WRITE ... %u\n"
+ "IN_CLOSE_NOWRITE . %u\n"
+ "IN_OPEN .......... %u\n"
+ "IN_MOVED_FROM .... %u\n"
+ "IN_MOVED_TO ...... %u\n"
+ "IN_CREATE ........ %u\n"
+ "IN_DELETE ........ %u\n"
+ "IN_DELETE_SELF ... %u\n"
+ "IN_MOVE_SELF ..... %u\n",
+ IN_ACCESS,
+ IN_MODIFY,
+ IN_ATTRIB,
+ IN_CLOSE_WRITE,
+ IN_CLOSE_NOWRITE,
+ IN_OPEN,
+ IN_MOVED_FROM,
+ IN_MOVED_TO,
+ IN_CREATE,
+ IN_DELETE,
+ IN_DELETE_SELF,
+ IN_MOVE_SELF
+ );
+ exit(0);
+}
+
int
execvpe(const char *program, char **argv, char **envp)
{
@@ -60,7 +95,8 @@ execvpe(const char *program, char **argv, char **envp)
int
main (int argc, char **argv)
{
- int fd, wd, len, mask = 0, i = 0, timeout = 0, ignore = 0;
+ int fd, wd, len, i = 0, timeout = 0, ignore = 0, quiet = 0;
+ uint32_t mask = 0;
char buf[BUF_LEN];
char *file = NULL, **cmd = NULL;
struct inotify_event *ev;
@@ -68,22 +104,24 @@ main (int argc, char **argv)
if ((argc == 2 && argv[1][0] == '-' && argv[1][1] == 'h')) usage();
/* parse option given. see usage() above */
- for(i = 1; (i + 1 < argc) && (argv[i][0] == '-') && !ignore; i++) {
+ for(i = 1; (i < argc) && (argv[i][0] == '-') && !ignore; i++) {
switch (argv[i][1]) {
case 'C': mask |= IN_CREATE; break;
case 'D': mask |= IN_DELETE; break;
case 'M': mask |= IN_MODIFY; break;
+ case 'm': mask |= atoi(argv[++i]); break;
+ case 'l': list_events(); break;
+ case 'q': quiet = 1; break;
case 'f': file = argv[++i]; break;
case 't': timeout = atoi(argv[++i]); break;
case 'e': cmd = &argv[++i]; ignore=1; break;
+ default: usage();
}
}
/* test given arguments */
if (!file) { file = DEFAULT_FILE; }
if (!timeout) { timeout = DEFAULT_CHECK; }
- if (!cmd) { usage(); }
- if (!mask) { mask |= IN_CREATE; }
/* get file descriptor */
fd = inotify_init();
@@ -96,8 +134,12 @@ main (int argc, char **argv)
if (wd < 0)
perror("inotify_add_watch");
+ if (!quiet) {
+ printf( "watching file %s with event mask %u\n", file, mask);
+ }
+
/* start looping */
- while (1) {
+ for (;;) {
/* get every event raised, and queue them */
len = read(fd, buf, BUF_LEN);
@@ -114,13 +156,23 @@ main (int argc, char **argv)
/* get events one by one */
ev = (struct inotify_event *) &buf[i];
- if (ev->len > 0) {
+ if (!quiet && ev->len > 0) {
printf("event on file %s: %u\n", ev->name, ev->mask);
}
- /* OMG a new event ! Quick, raise an alert ! */
- if (!fork()) {
- execvpe(cmd[0], cmd, environ);
+ /*
+ * do not do anything if no command given.
+ * Also only execute the command if the file concerned by the event
+ * is the one we're watching, or if we're not looking for a specific
+ * file.
+ *
+ * If you don't undersand this sentence, don't worry. Me neither.
+ * Just trust the if().
+ */
+ if (cmd && !(file && strncmp(file, ev->name, 255))) {
+
+ /* OMG a new event ! Quick, raise an alert ! */
+ if (!fork()) { execvpe(cmd[0], cmd, environ); }
}
/* jump to the next one */