diff options
| author | Sam Varshavchik | 2021-02-18 08:28:11 -0500 | 
|---|---|---|
| committer | Sam Varshavchik | 2021-02-18 08:45:12 -0500 | 
| commit | 5cba7ab897d2148b68826379218ce15f115d06c5 (patch) | |
| tree | cfb22c40481b0446a8f8707a7083cf13d98a6ba9 /maildir/maildirwatchprog.c | |
| parent | f25a0880d0762e4d8a47cce13ab3cea1a1db01f8 (diff) | |
| download | courier-libs-5cba7ab897d2148b68826379218ce15f115d06c5.tar.bz2 | |
Replace FAM/Gamin with inotify
Diffstat (limited to 'maildir/maildirwatchprog.c')
| -rw-r--r-- | maildir/maildirwatchprog.c | 201 | 
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); +} | 
