Add /man command
parent
c9968aadb9
commit
86e80edfcd
3
chat.h
3
chat.h
|
@ -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 {
|
||||||
|
|
3
chatte.1
3
chatte.1
|
@ -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
75
event.c
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
8
input.c
8
input.c
|
@ -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
3
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;
|
if (tagIndex >= at && tagIndex < to) argv[argc++] = entry.url;
|
||||||
tagIndex++;
|
tagIndex++;
|
||||||
}
|
}
|
||||||
if (argc > 1) eventSpawn(argv);
|
argv[argc] = NULL;
|
||||||
|
if (argc > 1) eventPipe(argv);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue