summary refs log tree commit diff
path: root/bin/ever.c
diff options
context:
space:
mode:
Diffstat (limited to 'bin/ever.c')
-rw-r--r--bin/ever.c53
1 files changed, 37 insertions, 16 deletions
diff --git a/bin/ever.c b/bin/ever.c
index 9fd48f96..24575617 100644
--- a/bin/ever.c
+++ b/bin/ever.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2017  C. McEnroe <june@causal.agency>
+/* Copyright (C) 2017  June 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
@@ -18,15 +18,15 @@
 
 #include <err.h>
 #include <fcntl.h>
+#include <stdbool.h>
 #include <stdlib.h>
 #include <sys/event.h>
 #include <sys/wait.h>
-#include <sysexits.h>
 #include <unistd.h>
 
-static void watch(int kq, char *path) {
+static int watch(int kq, char *path) {
 	int fd = open(path, O_CLOEXEC);
-	if (fd < 0) err(EX_NOINPUT, "%s", path);
+	if (fd < 0) err(1, "%s", path);
 
 	struct kevent event;
 	EV_SET(
@@ -39,22 +39,27 @@ static void watch(int kq, char *path) {
 		path
 	);
 	int nevents = kevent(kq, &event, 1, NULL, 0, NULL);
-	if (nevents < 0) err(EX_OSERR, "kevent");
+	if (nevents < 0) err(1, "kevent");
+
+	return fd;
 }
 
-static void exec(char *const argv[]) {
+static bool quiet;
+static void exec(int fd, char *const argv[]) {
 	pid_t pid = fork();
-	if (pid < 0) err(EX_OSERR, "fork");
+	if (pid < 0) err(1, "fork");
 
 	if (!pid) {
+		dup2(fd, STDIN_FILENO);
 		execvp(*argv, argv);
-		err(EX_NOINPUT, "%s", *argv);
+		err(127, "%s", *argv);
 	}
 
 	int status;
 	pid = wait(&status);
-	if (pid < 0) err(EX_OSERR, "wait");
+	if (pid < 0) err(1, "wait");
 
+	if (quiet) return;
 	if (WIFEXITED(status)) {
 		warnx("exit %d\n", WEXITSTATUS(status));
 	} else if (WIFSIGNALED(status)) {
@@ -65,13 +70,24 @@ static void exec(char *const argv[]) {
 }
 
 int main(int argc, char *argv[]) {
-	if (argc < 3) return EX_USAGE;
+	bool input = false;
+
+	for (int opt; 0 < (opt = getopt(argc, argv, "iq"));) {
+		switch (opt) {
+			break; case 'i': input = true;
+			break; case 'q': quiet = true;
+			break; default:  return 1;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+	if (argc < 2) return 1;
 
 	int kq = kqueue();
-	if (kq < 0) err(EX_OSERR, "kqueue");
+	if (kq < 0) err(1, "kqueue");
 
 	int i;
-	for (i = 1; i < argc - 1; ++i) {
+	for (i = 0; i < argc - 1; ++i) {
 		if (argv[i][0] == '-') {
 			i++;
 			break;
@@ -79,19 +95,24 @@ int main(int argc, char *argv[]) {
 		watch(kq, argv[i]);
 	}
 
-	exec(&argv[i]);
+	if (!input) {
+		exec(STDIN_FILENO, &argv[i]);
+	}
 
 	for (;;) {
 		struct kevent event;
 		int nevents = kevent(kq, NULL, 0, &event, 1, NULL);
-		if (nevents < 0) err(EX_OSERR, "kevent");
+		if (nevents < 0) err(1, "kevent");
 
 		if (event.fflags & NOTE_DELETE) {
 			close(event.ident);
 			sleep(1);
-			watch(kq, (char *)event.udata);
+			event.ident = watch(kq, (char *)event.udata);
+		} else if (input) {
+			off_t off = lseek(event.ident, 0, SEEK_SET);
+			if (off < 0) err(1, "lseek");
 		}
 
-		exec(&argv[i]);
+		exec((input ? event.ident : STDIN_FILENO), &argv[i]);
 	}
 }