summaryrefslogtreecommitdiffstats
path: root/maildir/maildirwatchprog.c
diff options
context:
space:
mode:
Diffstat (limited to 'maildir/maildirwatchprog.c')
-rw-r--r--maildir/maildirwatchprog.c201
1 files changed, 201 insertions, 0 deletions
diff --git a/maildir/maildirwatchprog.c b/maildir/maildirwatchprog.c
new file mode 100644
index 0000000..f169da8
--- /dev/null
+++ b/maildir/maildirwatchprog.c
@@ -0,0 +1,201 @@
+/*
+** Copyright 2021 Double Precision, Inc.
+** See COPYING for distribution information.
+*/
+
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#if HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <poll.h>
+#include "maildirwatch.h"
+
+static void usage()
+{
+ printf("Usage: maildirwatch maildir program arguments...\n");
+ exit(1);
+}
+
+static int forkexec(int argc, char **argv)
+{
+ pid_t p=fork();
+ int s;
+
+ if (p < 0)
+ {
+ perror("fork");
+ return 0;
+ }
+
+ if (p == 0)
+ {
+ char **argvptr=malloc(sizeof(char *)*(argc+1));
+ int n;
+
+ if (!argvptr)
+ {
+ perror("malloc");
+ exit(1);
+ }
+
+ for (n=0; n<argc; ++n)
+ argvptr[n]=argv[n];
+ argvptr[n]=0;
+ execvp(argvptr[0], argvptr);
+ perror(argv[0]);
+ exit(1);
+ }
+
+ if (waitpid(p, &s, 0) != p)
+ return 0;
+
+ if (!WIFEXITED(s))
+ {
+ if (WIFSIGNALED(s))
+ printf("-%d\n", (int)WTERMSIG(s));
+ else
+ printf("-0\n");
+ return 0;
+ }
+
+ if (WEXITSTATUS(s))
+ {
+ printf("%d\n", (int)WEXITSTATUS(s));
+ return 0;
+ }
+ return 1;
+}
+
+int main(int argc, char *argv[])
+{
+ struct maildirwatch *watch;
+ struct maildirwatch_contents mc;
+ int fdret;
+ int rc;
+
+ if (argc < 3)
+ usage();
+
+ /*
+ ** Call maildirwatch_alloc, then maildirwatch_start.
+ */
+
+ watch=maildirwatch_alloc(argv[1]);
+
+ if (maildirwatch_start(watch, &mc) < 0)
+ {
+ perror(argv[1]);
+ exit(1);
+ }
+
+ /*
+ ** poll() the returned file descriptor as long as
+ ** maildirwatch_started returns 0.
+ */
+
+ while ((rc=maildirwatch_started(&mc, &fdret)) == 0)
+ {
+ struct pollfd pfd;
+
+ pfd.fd=fdret;
+ pfd.events=POLLIN;
+
+ if (poll(&pfd, 1, -1) < 0)
+ {
+ perror(argv[1]);
+ exit(1);
+ }
+ }
+
+ if (rc < 0)
+ {
+ perror(argv[1]);
+ exit(1);
+ }
+
+ /*
+ ** The maildir is now being monitored.
+ */
+
+ while (forkexec(argc-2, argv+2))
+ {
+ int was_changed=0;
+
+ while (1)
+ {
+ int changed;
+ int timeout;
+
+ /*
+ ** maildirwatch_check() checks if the maildir has
+ ** been changed.
+ */
+ int rc=maildirwatch_check(&mc, &changed, &fdret,
+ &timeout);
+
+
+ if (rc < 0)
+ {
+ perror(argv[1]);
+ exit(1);
+ }
+
+ /*
+ ** If it's changed, you can call it again.
+ ** maildirwatch_check() does not block.
+ */
+ if (changed)
+ {
+ was_changed=1;
+ continue;
+ }
+
+ if (was_changed)
+ break;
+
+ /*
+ ** If it's not changed, poll() for the number of
+ ** seconds specified by the timeout.
+ **
+ ** In polling mode fdret is 0, so sleep, then
+ ** check the maildir manually.
+ */
+
+ if (fdret < 0)
+ {
+ sleep(timeout);
+ continue;
+ }
+
+ struct pollfd pfd;
+
+ pfd.fd=fdret;
+ pfd.events=POLLIN;
+
+ if (poll(&pfd, 1, timeout * 1000) < 0)
+ {
+ perror("poll");
+ exit(1);
+ }
+ }
+ }
+
+ /*
+ ** Cleanup.
+ */
+
+ maildirwatch_end(&mc);
+ maildirwatch_free(watch);
+ return (0);
+}