about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2018-09-10 19:18:26 -0400
committerJune McEnroe <june@causal.agency>2018-09-10 19:18:26 -0400
commit86e80edfcd3ba660dea1ce337467a10e2e878b18 (patch)
treed32d05f2cb51c08d963ffe3d2f4b4caf84ad12cb
parentInstall man page in chroot (diff)
downloadcatgirl-86e80edfcd3ba660dea1ce337467a10e2e878b18.tar.gz
catgirl-86e80edfcd3ba660dea1ce337467a10e2e878b18.zip
Add /man command
-rw-r--r--chat.h3
-rw-r--r--chatte.13
-rw-r--r--event.c75
-rw-r--r--input.c8
-rw-r--r--url.c3
5 files changed, 61 insertions, 31 deletions
diff --git a/chat.h b/chat.h
index 6c95ab6..2ee80db 100644
--- a/chat.h
+++ b/chat.h
@@ -37,7 +37,8 @@ void selfNick(const char *nick);
 void selfUser(const char *user);
 void selfJoin(const char *join);
 
-void eventSpawn(char *const argv[]);
+void eventWait(char *const argv[]);
+void eventPipe(char *const argv[]);
 void eventLoop(int ui, int irc);
 
 struct Tag {
diff --git a/chatte.1 b/chatte.1
index e3dbbb6..4dce17b 100644
--- a/chatte.1
+++ b/chatte.1
@@ -100,6 +100,9 @@ are renumbered.
 .It Ic /join Ar chan
 Join a channel.
 .
+.It Ic /man
+View this manual.
+.
 .It Ic /me Ar action
 Send a CTCP
 .Ql ACTION
diff --git a/event.c b/event.c
index 4771aac..cad170f 100644
--- a/event.c
+++ b/event.c
@@ -27,18 +27,26 @@
 
 #include "chat.h"
 
-static union {
-	struct {
-		struct pollfd ui;
-		struct pollfd irc;
-		struct pollfd pipe;
-	};
-	struct pollfd fds[3];
-} fds;
+static struct {
+	bool wait;
+	bool pipe;
+	int fd;
+} spawn;
+
+void eventWait(char *const argv[]) {
+	uiHide();
+	pid_t pid = fork();
+	if (pid < 0) err(EX_OSERR, "fork");
+	if (!pid) {
+		execvp(argv[0], argv);
+		err(EX_CONFIG, "%s", argv[0]);
+	}
+	spawn.wait = true;
+}
 
-void eventSpawn(char *const argv[]) {
-	if (fds.pipe.events) {
-		uiLog(TagStatus, UIHot, L"eventSpawn: existing pipe");
+void eventPipe(char *const argv[]) {
+	if (spawn.pipe) {
+		uiLog(TagStatus, UIHot, L"event: existing pipe");
 		return;
 	}
 
@@ -60,21 +68,21 @@ void eventSpawn(char *const argv[]) {
 	}
 
 	close(rw[1]);
-	fds.pipe.fd = rw[0];
-	fds.pipe.events = POLLIN;
+	spawn.fd = rw[0];
+	spawn.pipe = true;
 }
 
 static void pipeRead(void) {
 	char buf[256];
-	ssize_t len = read(fds.pipe.fd, buf, sizeof(buf) - 1);
+	ssize_t len = read(spawn.fd, buf, sizeof(buf) - 1);
 	if (len < 0) err(EX_IOERR, "read");
 	if (len) {
 		buf[len] = '\0';
 		len = strcspn(buf, "\n");
-		uiFmt(TagStatus, UIHot, "eventSpawn: %.*s", (int)len, buf);
+		uiFmt(TagStatus, UIHot, "event: %.*s", (int)len, buf);
 	} else {
-		close(fds.pipe.fd);
-		memset(&fds.pipe, 0, sizeof(fds.pipe));
+		close(spawn.fd);
+		spawn.pipe = false;
 	}
 }
 
@@ -84,10 +92,11 @@ static void sigchld(int sig) {
 	pid_t pid = wait(&status);
 	if (pid < 0) err(EX_OSERR, "wait");
 	if (WIFEXITED(status) && WEXITSTATUS(status)) {
-		uiFmt(TagStatus, UIHot, "eventSpawn: exit %d", WEXITSTATUS(status));
+		uiFmt(TagStatus, UIHot, "event: exit %d", WEXITSTATUS(status));
 	} else if (WIFSIGNALED(status)) {
-		uiFmt(TagStatus, UIHot, "eventSpawn: singal %d", WTERMSIG(status));
+		uiFmt(TagStatus, UIHot, "event: signal %d", WTERMSIG(status));
 	}
+	spawn.wait = false;
 }
 
 static void sigint(int sig) {
@@ -101,23 +110,31 @@ void eventLoop(int ui, int irc) {
 	signal(SIGINT, sigint);
 	signal(SIGCHLD, sigchld);
 
-	fds.ui.fd = ui;
-	fds.irc.fd = irc;
-	fds.ui.events = POLLIN;
-	fds.irc.events = POLLIN;
-
+	struct pollfd fds[3] = {
+		{ irc, POLLIN, 0 },
+		{ ui, POLLIN, 0 },
+		{ -1, POLLIN, 0 },
+	};
 	for (;;) {
-		uiDraw();
+		nfds_t nfds = 2;
+		if (spawn.wait) nfds = 1;
+		if (spawn.pipe) {
+			fds[2].fd = spawn.fd;
+			nfds = 3;
+		}
 
-		int ready = poll(fds.fds, (fds.pipe.events ? 3 : 2), -1);
+		int ready = poll(fds, nfds, -1);
 		if (ready < 0) {
 			if (errno != EINTR) err(EX_IOERR, "poll");
 			uiRead();
+			uiDraw();
 			continue;
 		}
 
-		if (fds.ui.revents) uiRead();
-		if (fds.irc.revents) ircRead();
-		if (fds.pipe.revents) pipeRead();
+		if (fds[0].revents) ircRead();
+		if (nfds > 1 && fds[1].revents) uiRead();
+		if (nfds > 2 && fds[2].revents) pipeRead();
+
+		if (nfds > 1) uiDraw();
 	}
 }
diff --git a/input.c b/input.c
index 0d8e491..6e95b11 100644
--- a/input.c
+++ b/input.c
@@ -135,12 +135,20 @@ static void inputClose(struct Tag tag, char *params) {
 	tabRemove(TagNone, tag.name);
 }
 
+static void inputMan(struct Tag tag, char *params) {
+	(void)tag;
+	(void)params;
+	char *argv[] = { "man", "1", "chatte", NULL };
+	eventWait(argv);
+}
+
 static const struct {
 	const char *command;
 	Handler handler;
 } Commands[] = {
 	{ "/close", inputClose },
 	{ "/join", inputJoin },
+	{ "/man", inputMan },
 	{ "/me", inputMe },
 	{ "/names", inputWho },
 	{ "/nick", inputNick },
diff --git a/url.c b/url.c
index 49bea65..902128a 100644
--- a/url.c
+++ b/url.c
@@ -82,5 +82,6 @@ void urlOpen(struct Tag tag, size_t at, size_t to) {
 		if (tagIndex >= at && tagIndex < to) argv[argc++] = entry.url;
 		tagIndex++;
 	}
-	if (argc > 1) eventSpawn(argv);
+	argv[argc] = NULL;
+	if (argc > 1) eventPipe(argv);
 }