commit 06dd73f39357458f84854d4f22fac139a3210b32
Author: Willy Goiffon <w.goiffon@gmail.com>
Date: Fri, 2 Aug 2013 15:30:09 +0200
first commit
Diffstat:
A | Makefile | | | 36 | ++++++++++++++++++++++++++++++++++++ |
A | wendy.c | | | 139 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
2 files changed, 175 insertions(+), 0 deletions(-)
diff --git a/Makefile b/Makefile
@@ -0,0 +1,36 @@
+# BEGINNING OF THE FILE
+
+# Compilation settings
+PROG=wendy
+CC=gcc
+CFLAGS=-Wall -I inc --std=c99 -pedantic
+LDFLAGS=
+
+# Command paths
+RM=/bin/rm
+
+.PHONY : all list mrproper clean init
+
+$(PROG) : $(PROG).o
+ @echo -e "LD $(PROG)"
+ @$(CC) $^ -o$@ $(LDFLAGS)
+
+$(PROG).o : $(PROG).c
+ @echo -e "CC $<"
+ @$(CC) -c $(CFLAGS) $< -o $@
+
+all : clean $(PROG)
+
+mrproper : clean
+ $(RM) $(PROG)
+
+clean :
+ $(RM) -f *.o
+ $(RM) -f *~
+
+init :
+ @echo "CC = $(CC)"
+ @echo "CFLAGS = $(CFLAGS)"
+ @echo "LDFLAGS = $(LDFLAGS)"
+ @echo
+## EOF
diff --git a/wendy.c b/wendy.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2013 Willy 'z3bra' Goiffon <willy at mailoo dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/inotify.h>
+
+/* definitions, defaults, bla bla blah */
+#define EVENT_SIZE (sizeof(struct inotify_event))
+/* maximum number of event * queuing at the same time */
+#define BUF_LEN (512 * (EVENT_SIZE+16))
+
+#define DEFAULT_directory "/var/spool/mail/directory/new"
+#define DEFAULT_CHECK 300 /* defaults to 5 minutes */
+
+extern char **environ;
+
+void
+usage()
+{
+ fputs("usage: wendy [-C] [-D] [-M] [-d directory] [-t timeout] "
+ "-e command [arguments]\n"
+ "\t-C : raise creation events\n"
+ "\t-D : raise deletion events\n"
+ "\t-M : raise modification events\n"
+ "\t-d directory : directory to watch\n"
+ "\t-t timeout : time between event check (in seconds)\n"
+ "\t-e command : command to launch (must be the last argument!)\n",
+ stdout);
+ exit(1);
+}
+
+int
+execvpe(const char *program, char **argv, char **envp)
+{
+ char **saved = environ;
+ int rc;
+ environ = envp;
+ rc = execvp(program, argv);
+ environ = saved;
+ return rc;
+}
+
+int
+main (int argc, char **argv)
+{
+ int fd, wd, len, mask = 0, i = 0, timeout = 0, ignore = 0;
+ char buf[BUF_LEN];
+ char *directory = NULL, **cmd = NULL;
+ struct inotify_event *ev;
+
+ 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++) {
+ switch (argv[i][1]) {
+ case 'C': mask |= IN_CREATE; break;
+ case 'D': mask |= IN_DELETE; break;
+ case 'M': mask |= IN_MODIFY; break;
+ case 'd': directory = argv[++i]; break;
+ case 't': timeout = atoi(argv[++i]); break;
+ case 'e': cmd = &argv[++i]; ignore=1; break;
+ }
+ }
+
+ /* test given arguments */
+ if (!directory) { directory = DEFAULT_directory; }
+ if (!timeout) { timeout = DEFAULT_CHECK; }
+ if (!cmd) { usage(); }
+ if (!mask) { mask |= IN_CREATE; }
+
+ /* get file descriptor */
+ fd = inotify_init();
+ if (fd < 0)
+ perror("inotify_init");
+
+ /* add a watcher on the directory */
+ wd = inotify_add_watch(fd, directory, mask);
+
+ if (wd < 0)
+ perror("inotify_add_watch");
+
+ /* start looping */
+ while (1) {
+ /* get every event raised, and queue them */
+ len = read(fd, buf, BUF_LEN);
+
+ if (!len || len < 0) {
+ perror("read");
+ }
+
+ i = 0;
+
+
+ /* treat all events queued */
+ while (i < len) {
+
+ /* get events one by one */
+ ev = (struct inotify_event *) &buf[i];
+
+ if (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);
+ }
+
+ /* jump to the next one */
+ i += EVENT_SIZE + ev->len;
+ }
+ /* wait before queuing events */
+ sleep(timeout);
+ }
+
+ return EXIT_SUCCESS;
+}