Add /man command

master
Curtis McEnroe 2018-09-10 19:18:26 -04:00
parent c9968aadb9
commit 86e80edfcd
No known key found for this signature in database
GPG Key ID: CEA2F97ADCFCD77C
5 changed files with 61 additions and 31 deletions

3
chat.h
View File

@ -37,7 +37,8 @@ void selfNick(const char *nick);
void selfUser(const char *user); void selfUser(const char *user);
void selfJoin(const char *join); 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); void eventLoop(int ui, int irc);
struct Tag { struct Tag {

View File

@ -100,6 +100,9 @@ are renumbered.
.It Ic /join Ar chan .It Ic /join Ar chan
Join a channel. Join a channel.
. .
.It Ic /man
View this manual.
.
.It Ic /me Ar action .It Ic /me Ar action
Send a CTCP Send a CTCP
.Ql ACTION .Ql ACTION

75
event.c
View File

@ -27,18 +27,26 @@
#include "chat.h" #include "chat.h"
static union { static struct {
struct { bool wait;
struct pollfd ui; bool pipe;
struct pollfd irc; int fd;
struct pollfd pipe; } spawn;
};
struct pollfd fds[3];
} fds;
void eventSpawn(char *const argv[]) { void eventWait(char *const argv[]) {
if (fds.pipe.events) { uiHide();
uiLog(TagStatus, UIHot, L"eventSpawn: existing pipe"); 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 eventPipe(char *const argv[]) {
if (spawn.pipe) {
uiLog(TagStatus, UIHot, L"event: existing pipe");
return; return;
} }
@ -60,21 +68,21 @@ void eventSpawn(char *const argv[]) {
} }
close(rw[1]); close(rw[1]);
fds.pipe.fd = rw[0]; spawn.fd = rw[0];
fds.pipe.events = POLLIN; spawn.pipe = true;
} }
static void pipeRead(void) { static void pipeRead(void) {
char buf[256]; 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 < 0) err(EX_IOERR, "read");
if (len) { if (len) {
buf[len] = '\0'; buf[len] = '\0';
len = strcspn(buf, "\n"); len = strcspn(buf, "\n");
uiFmt(TagStatus, UIHot, "eventSpawn: %.*s", (int)len, buf); uiFmt(TagStatus, UIHot, "event: %.*s", (int)len, buf);
} else { } else {
close(fds.pipe.fd); close(spawn.fd);
memset(&fds.pipe, 0, sizeof(fds.pipe)); spawn.pipe = false;
} }
} }
@ -84,10 +92,11 @@ static void sigchld(int sig) {
pid_t pid = wait(&status); pid_t pid = wait(&status);
if (pid < 0) err(EX_OSERR, "wait"); if (pid < 0) err(EX_OSERR, "wait");
if (WIFEXITED(status) && WEXITSTATUS(status)) { 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)) { } 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) { static void sigint(int sig) {
@ -101,23 +110,31 @@ void eventLoop(int ui, int irc) {
signal(SIGINT, sigint); signal(SIGINT, sigint);
signal(SIGCHLD, sigchld); signal(SIGCHLD, sigchld);
fds.ui.fd = ui; struct pollfd fds[3] = {
fds.irc.fd = irc; { irc, POLLIN, 0 },
fds.ui.events = POLLIN; { ui, POLLIN, 0 },
fds.irc.events = POLLIN; { -1, POLLIN, 0 },
};
for (;;) { 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 (ready < 0) {
if (errno != EINTR) err(EX_IOERR, "poll"); if (errno != EINTR) err(EX_IOERR, "poll");
uiRead(); uiRead();
uiDraw();
continue; continue;
} }
if (fds.ui.revents) uiRead(); if (fds[0].revents) ircRead();
if (fds.irc.revents) ircRead(); if (nfds > 1 && fds[1].revents) uiRead();
if (fds.pipe.revents) pipeRead(); if (nfds > 2 && fds[2].revents) pipeRead();
if (nfds > 1) uiDraw();
} }
} }

View File

@ -135,12 +135,20 @@ static void inputClose(struct Tag tag, char *params) {
tabRemove(TagNone, tag.name); 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 { static const struct {
const char *command; const char *command;
Handler handler; Handler handler;
} Commands[] = { } Commands[] = {
{ "/close", inputClose }, { "/close", inputClose },
{ "/join", inputJoin }, { "/join", inputJoin },
{ "/man", inputMan },
{ "/me", inputMe }, { "/me", inputMe },
{ "/names", inputWho }, { "/names", inputWho },
{ "/nick", inputNick }, { "/nick", inputNick },

3
url.c
View File

@ -82,5 +82,6 @@ void urlOpen(struct Tag tag, size_t at, size_t to) {
if (tagIndex >= at && tagIndex < to) argv[argc++] = entry.url; if (tagIndex >= at && tagIndex < to) argv[argc++] = entry.url;
tagIndex++; tagIndex++;
} }
if (argc > 1) eventSpawn(argv); argv[argc] = NULL;
if (argc > 1) eventPipe(argv);
} }