Add catsit-watch utility
This commit is contained in:
parent
8bd0b51140
commit
fd25c666d5
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,5 +1,6 @@
|
|||||||
*.o
|
*.o
|
||||||
catsit
|
catsit
|
||||||
|
catsit-watch
|
||||||
catsit.conf
|
catsit.conf
|
||||||
catsitd
|
catsitd
|
||||||
config.mk
|
config.mk
|
||||||
|
46
Makefile
46
Makefile
@ -16,16 +16,18 @@ RC_SCRIPT = ${UNAME}/catsitd
|
|||||||
|
|
||||||
-include config.mk
|
-include config.mk
|
||||||
|
|
||||||
BINS = catsit catsitd
|
BINS = catsit-watch
|
||||||
MAN8 = ${BINS:=.8}
|
SBINS = catsit catsitd
|
||||||
|
MAN1 = ${BINS:=.1}
|
||||||
MAN5 = catsit.conf.5
|
MAN5 = catsit.conf.5
|
||||||
|
MAN8 = ${SBINS:=.8}
|
||||||
|
|
||||||
OBJS += daemon.o
|
OBJS += daemon.o
|
||||||
OBJS += service.o
|
OBJS += service.o
|
||||||
|
|
||||||
dev: tags all
|
dev: tags all
|
||||||
|
|
||||||
all: ${BINS}
|
all: ${BINS} ${SBINS}
|
||||||
|
|
||||||
catsitd: ${OBJS}
|
catsitd: ${OBJS}
|
||||||
${CC} ${LDFLAGS} ${OBJS} ${LDLIBS} -o $@
|
${CC} ${LDFLAGS} ${OBJS} ${LDLIBS} -o $@
|
||||||
@ -38,22 +40,40 @@ ${OBJS}: daemon.h
|
|||||||
sed -e 's|%%PREFIX%%|${PREFIX}|g' -e 's|%%RUNDIR%%|${RUNDIR}|g' $< > $@
|
sed -e 's|%%PREFIX%%|${PREFIX}|g' -e 's|%%RUNDIR%%|${RUNDIR}|g' $< > $@
|
||||||
chmod a+x $@
|
chmod a+x $@
|
||||||
|
|
||||||
tags: *.c *.h
|
tags: *.[ch]
|
||||||
ctags -w *.c *.h
|
ctags -w *.[ch]
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f ${BINS} ${OBJS} ${RC_SCRIPT} tags
|
rm -f ${BINS} ${SBINS} ${OBJS} ${RC_SCRIPT} tags
|
||||||
|
|
||||||
install: ${BINS} ${RC_SCRIPT} ${MAN5} ${MAN8}
|
install: ${BINS} ${SBINS} ${RC_SCRIPT} ${MAN1} ${MAN5} ${MAN8}
|
||||||
install -d ${DESTDIR}${PREFIX}/sbin ${DESTDIR}${ETCDIR}/rc.d
|
install -d ${DESTDIR}${PREFIX}/bin
|
||||||
install -d ${DESTDIR}${MANDIR}/man5 ${DESTDIR}${MANDIR}/man8
|
install -d ${DESTDIR}${PREFIX}/sbin
|
||||||
install ${BINS} ${DESTDIR}${PREFIX}/sbin
|
install -d ${DESTDIR}${MANDIR}/man1
|
||||||
|
install -d ${DESTDIR}${MANDIR}/man5
|
||||||
|
install -d ${DESTDIR}${MANDIR}/man8
|
||||||
|
install -d ${DESTDIR}${ETCDIR}/rc.d
|
||||||
|
install ${BINS} ${DESTDIR}${PREFIX}/bin
|
||||||
|
install ${SBINS} ${DESTDIR}${PREFIX}/sbin
|
||||||
install ${RC_SCRIPT} ${DESTDIR}${ETCDIR}/rc.d
|
install ${RC_SCRIPT} ${DESTDIR}${ETCDIR}/rc.d
|
||||||
|
install -m 644 ${MAN1} ${DESTDIR}${MANDIR}/man1
|
||||||
install -m 644 ${MAN5} ${DESTDIR}${MANDIR}/man5
|
install -m 644 ${MAN5} ${DESTDIR}${MANDIR}/man5
|
||||||
install -m 644 ${MAN8} ${DESTDIR}${MANDIR}/man8
|
install -m 644 ${MAN8} ${DESTDIR}${MANDIR}/man8
|
||||||
|
|
||||||
uninstall:
|
uninstall:
|
||||||
rm -f ${BINS:%=${DESTDIR}${PREFIX}/sbin/%}
|
.for BIN in ${BINS}
|
||||||
rm -f ${MAN5:%=${DESTDIR}${MANDIR}/man5/%}
|
rm -f ${DESTDIR}${PREFIX}/bin/${BIN}
|
||||||
rm -f ${MAN8:%=${DESTDIR}${MANDIR}/man8/%}
|
.endfor
|
||||||
|
.for SBIN in ${SBINS}
|
||||||
|
rm -f ${DESTDIR}${PREFIX}/sbin/${SBIN}
|
||||||
|
.endfor
|
||||||
rm -f ${DESTDIR}${ETCDIR}/rc.d/${RC_SCRIPT:T}
|
rm -f ${DESTDIR}${ETCDIR}/rc.d/${RC_SCRIPT:T}
|
||||||
|
.for MAN in ${MAN1}
|
||||||
|
rm -f ${DESTDIR}${MANDIR}/man1/${MAN}
|
||||||
|
.endfor
|
||||||
|
.for MAN in ${MAN5}
|
||||||
|
rm -f ${DESTDIR}${MANDIR}/man5/${MAN}
|
||||||
|
.endfor
|
||||||
|
.for MAN in ${MAN8}
|
||||||
|
rm -f ${DESTDIR}${MANDIR}/man8/${MAN}
|
||||||
|
.endfor
|
||||||
|
52
catsit-watch.1
Normal file
52
catsit-watch.1
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
.Dd February 25, 2021
|
||||||
|
.Dt CATSIT-WATCH 1
|
||||||
|
.Os
|
||||||
|
.
|
||||||
|
.Sh NAME
|
||||||
|
.Nm catsit-watch
|
||||||
|
.Nd run command when files are modified
|
||||||
|
.
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.Nm
|
||||||
|
.Op Fl i
|
||||||
|
.Op Fl f Ar file
|
||||||
|
.Ar command ...
|
||||||
|
.
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
The
|
||||||
|
.Nm
|
||||||
|
utility runs a command
|
||||||
|
each time any of a set of files
|
||||||
|
are modified.
|
||||||
|
If any watched files are removed
|
||||||
|
or if the command exits non-zero,
|
||||||
|
.Nm
|
||||||
|
exits.
|
||||||
|
.
|
||||||
|
.Pp
|
||||||
|
The arguments are as follows:
|
||||||
|
.Bl -tag -width Ds
|
||||||
|
.It Fl f Ar file
|
||||||
|
Add
|
||||||
|
.Ar file
|
||||||
|
to the set of watched files.
|
||||||
|
.It Fl i
|
||||||
|
Run the command once initially,
|
||||||
|
before watching files.
|
||||||
|
.El
|
||||||
|
.
|
||||||
|
.Sh EXIT STATUS
|
||||||
|
If any watched files are removed,
|
||||||
|
.Nm
|
||||||
|
exits with
|
||||||
|
.Dv EX_TEMPFAIL
|
||||||
|
(75).
|
||||||
|
If the command exits non-zero,
|
||||||
|
.Nm
|
||||||
|
exits with the same status.
|
||||||
|
.
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr catsitd 8
|
||||||
|
.
|
||||||
|
.Sh AUTHORS
|
||||||
|
.An June Bug Aq Mt june@causal.agency
|
94
catsit-watch.c
Normal file
94
catsit-watch.c
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
/* Copyright (C) 2021 C. McEnroe <june@causal.agency>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <err.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/event.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <sysexits.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
static void watch(int kq, char *path) {
|
||||||
|
int fd = open(path, O_RDONLY | O_CLOEXEC);
|
||||||
|
if (fd < 0) err(EX_NOINPUT, "%s", path);
|
||||||
|
|
||||||
|
struct kevent event;
|
||||||
|
EV_SET(
|
||||||
|
&event, fd, EVFILT_VNODE, EV_ADD | EV_CLEAR,
|
||||||
|
NOTE_WRITE | NOTE_DELETE, 0, path
|
||||||
|
);
|
||||||
|
int nevents = kevent(kq, &event, 1, NULL, 0, NULL);
|
||||||
|
if (nevents < 0) err(EX_OSERR, "kevent");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void run(char *argv[]) {
|
||||||
|
pid_t pid = fork();
|
||||||
|
if (pid < 0) err(EX_OSERR, "fork");
|
||||||
|
if (!pid) {
|
||||||
|
execvp(argv[0], argv);
|
||||||
|
err(126, "%s", argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
int status;
|
||||||
|
pid = wait(&status);
|
||||||
|
if (pid < 0) err(EX_OSERR, "wait");
|
||||||
|
if (WIFEXITED(status)) {
|
||||||
|
status = WEXITSTATUS(status);
|
||||||
|
if (status) exit(status);
|
||||||
|
} else {
|
||||||
|
exit(status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
int kq = kqueue();
|
||||||
|
if (kq < 0) err(EX_OSERR, "kqueue");
|
||||||
|
fcntl(kq, F_SETFD, FD_CLOEXEC);
|
||||||
|
|
||||||
|
int init = 0;
|
||||||
|
for (int opt; 0 < (opt = getopt(argc, argv, "f:i"));) {
|
||||||
|
switch (opt) {
|
||||||
|
break; case 'f': watch(kq, optarg);
|
||||||
|
break; case 'i': init = 1;
|
||||||
|
break; default: return EX_USAGE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
argc -= optind;
|
||||||
|
argv += optind;
|
||||||
|
if (!argc) errx(EX_USAGE, "command required");
|
||||||
|
|
||||||
|
#ifdef __OpenBSD__
|
||||||
|
int error = pledge("stdio proc exec", NULL);
|
||||||
|
if (error) err(EX_OSERR, "pledge");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (init) run(argv);
|
||||||
|
for (;;) {
|
||||||
|
struct kevent event;
|
||||||
|
int nevents = kevent(kq, NULL, 0, &event, 1, NULL);
|
||||||
|
if (nevents < 0) err(EX_OSERR, "kevent");
|
||||||
|
|
||||||
|
if (event.fflags & NOTE_DELETE) {
|
||||||
|
errx(EX_TEMPFAIL, "%s: file removed", (char *)event.udata);
|
||||||
|
}
|
||||||
|
run(argv);
|
||||||
|
}
|
||||||
|
}
|
@ -80,6 +80,7 @@ pounce/tilde pounce ${0#*/}.conf
|
|||||||
.Ed
|
.Ed
|
||||||
.
|
.
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
|
.Xr catsit-watch 1 ,
|
||||||
.Xr catsitd 8
|
.Xr catsitd 8
|
||||||
.
|
.
|
||||||
.Sh AUTHORS
|
.Sh AUTHORS
|
||||||
|
Loading…
Reference in New Issue
Block a user