summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--handle.c218
1 files changed, 124 insertions, 94 deletions
diff --git a/handle.c b/handle.c
index 4389ff8..ed1ba35 100644
--- a/handle.c
+++ b/handle.c
@@ -15,6 +15,7 @@
*/
#include <err.h>
+#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -32,15 +33,8 @@ static int color(const char *s) {
return (x == 1) ? 0 : x;
}
-typedef void (*Handler)(char *prefix, char *params);
-
-static char *prift(char **prefix) {
- return strsep(prefix, "!@");
-}
-
-static char *shift(char **params) {
+static char *paramField(char **params) {
char *rest = *params;
- if (!rest) errx(EX_PROTOCOL, "unexpected eol");
if (rest[0] == ':') {
*params = NULL;
return &rest[1];
@@ -48,24 +42,59 @@ static char *shift(char **params) {
return strsep(params, " ");
}
+static void shift(
+ char *prefix, char **nick, char **user, char **host,
+ char *params, size_t req, size_t opt, /* (char **) */ ...
+) {
+ char *field;
+ if (prefix) {
+ field = strsep(&prefix, "!");
+ if (nick) *nick = field;
+ field = strsep(&prefix, "@");
+ if (user) *user = field;
+ if (host) *host = prefix;
+ }
+
+ va_list ap;
+ va_start(ap, opt);
+ for (size_t i = 0; i < req; ++i) {
+ if (!params) {
+ va_end(ap);
+ errx(EX_PROTOCOL, "%zu params required, found %zu", req, i);
+ }
+ field = paramField(&params);
+ char **param = va_arg(ap, char **);
+ if (param) *param = field;
+ }
+ for (size_t i = 0; i < opt; ++i) {
+ char **param = va_arg(ap, char **);
+ if (params) {
+ *param = paramField(&params);
+ } else {
+ *param = NULL;
+ }
+ }
+ va_end(ap);
+}
+
+typedef void (*Handler)(char *prefix, char *params);
+
static void handlePing(char *prefix, char *params) {
(void)prefix;
ircFmt("PONG %s\r\n", params);
}
static void handle432(char *prefix, char *params) {
- (void)prefix;
- shift(&params);
- shift(&params);
- char *mesg = shift(&params);
+ char *mesg;
+ shift(prefix, NULL, NULL, NULL, params, 1, 0, &mesg);
uiLog(L"You can't use that name here");
uiFmt("Sheriff says, \"%s\"", mesg);
uiLog(L"Type /nick <name> to choose a new one");
}
static void handle001(char *prefix, char *params) {
- (void)prefix;
- char *nick = shift(&params);
+ char *nick;
+ shift(prefix, NULL, NULL, NULL, params, 1, 0, &nick);
if (strcmp(nick, chat.nick)) {
free(chat.nick);
chat.nick = strdup(nick);
@@ -74,27 +103,23 @@ static void handle001(char *prefix, char *params) {
}
static void handleJoin(char *prefix, char *params) {
- char *nick = prift(&prefix);
- char *user = prift(&prefix);
- char *chan = shift(&params);
+ char *nick, *user, *chan;
+ shift(prefix, &nick, &user, NULL, params, 1, 0, &chan);
+ uiFmt(
+ "\3%d%s\3 arrives in \3%d%s\3",
+ color(user), nick, color(chan), chan
+ );
if (!strcmp(nick, chat.nick) && strcmp(user, chat.user)) {
free(chat.user);
chat.user = strdup(user);
}
tabTouch(nick);
- uiFmt(
- "\3%d%s\3 arrives in \3%d%s\3",
- color(user), nick, color(chan), chan
- );
}
static void handlePart(char *prefix, char *params) {
- char *nick = prift(&prefix);
- char *user = prift(&prefix);
- char *chan = shift(&params);
- tabRemove(nick);
- if (params) {
- char *mesg = shift(&params);
+ char *nick, *user, *chan, *mesg;
+ shift(prefix, &nick, &user, NULL, params, 1, 1, &chan, &mesg);
+ if (mesg) {
uiFmt(
"\3%d%s\3 leaves \3%d%s\3, \"%s\"",
color(user), nick, color(chan), chan, mesg
@@ -105,14 +130,13 @@ static void handlePart(char *prefix, char *params) {
color(user), nick, color(chan), chan
);
}
+ tabRemove(nick);
}
static void handleQuit(char *prefix, char *params) {
- char *nick = prift(&prefix);
- char *user = prift(&prefix);
- tabRemove(nick);
- if (params) {
- char *mesg = shift(&params);
+ char *nick, *user, *mesg;
+ shift(prefix, &nick, &user, NULL, params, 0, 1, &mesg);
+ if (mesg) {
char *quot = (mesg[0] == '"') ? "" : "\"";
uiFmt(
"\3%d%s\3 leaves, %s%s%s",
@@ -121,51 +145,51 @@ static void handleQuit(char *prefix, char *params) {
} else {
uiFmt("\3%d%s\3 leaves", color(user), nick);
}
+ tabRemove(nick);
}
static void handleKick(char *prefix, char *params) {
- char *nick = prift(&prefix);
- char *user = prift(&prefix);
- char *chan = shift(&params);
- char *kick = shift(&params);
- char *mesg = shift(&params);
+ char *nick, *user, *chan, *kick, *mesg;
+ shift(prefix, &nick, &user, NULL, params, 2, 1, &chan, &kick, &mesg);
+ if (mesg) {
+ uiFmt(
+ "\3%d%s\3 kicks \3%d%s\3 out of \3%d%s\3, \"%s\"",
+ color(user), nick, color(kick), kick, color(chan), chan, mesg
+ );
+ } else {
+ uiFmt(
+ "\3%d%s\3 kicks \3%d%s\3 out of \3%d%s\3",
+ color(user), nick, color(kick), kick, color(chan), chan
+ );
+ }
tabRemove(nick);
- uiFmt(
- "\3%d%s\3 kicks \3%d%s\3 out of \3%d%s\3, \"%s\"",
- color(user), nick, color(kick), kick, color(chan), chan, mesg
- );
}
static void handle332(char *prefix, char *params) {
- (void)prefix;
- shift(&params);
- char *chan = shift(&params);
- char *topic = shift(&params);
- urlScan(topic);
- uiTopicStr(topic);
+ char *chan, *topic;
+ shift(prefix, NULL, NULL, NULL, params, 3, 0, NULL, &chan, &topic);
uiFmt(
"The sign in \3%d%s\3 reads, \"%s\"",
color(chan), chan, topic
);
+ urlScan(topic);
+ uiTopicStr(topic);
}
static void handleTopic(char *prefix, char *params) {
- char *nick = prift(&prefix);
- char *user = prift(&prefix);
- char *chan = shift(&params);
- char *topic = shift(&params);
- urlScan(topic);
- uiTopicStr(topic);
+ char *nick, *user, *chan, *topic;
+ shift(prefix, &nick, &user, NULL, params, 2, 0, &chan, &topic);
uiFmt(
"\3%d%s\3 places a new sign in \3%d%s\3, \"%s\"",
color(user), nick, color(chan), chan, topic
);
+ urlScan(topic);
+ uiTopicStr(topic);
}
static void handle366(char *prefix, char *params) {
- (void)prefix;
- shift(&params);
- char *chan = shift(&params);
+ char *chan;
+ shift(prefix, NULL, NULL, NULL, params, 2, 0, NULL, &chan);
ircFmt("WHO %s\r\n", chan);
}
@@ -175,14 +199,11 @@ static struct {
} who;
static void handle352(char *prefix, char *params) {
- (void)prefix;
- shift(&params);
- shift(&params);
- char *user = shift(&params);
- shift(&params);
- shift(&params);
- char *nick = shift(&params);
- tabTouch(nick);
+ char *user, *nick;
+ shift(
+ prefix, NULL, NULL, NULL,
+ params, 6, 0, NULL, NULL, &user, NULL, NULL, &nick
+ );
size_t cap = sizeof(who.buf) - who.len;
int len = snprintf(
&who.buf[who.len], cap,
@@ -190,65 +211,74 @@ static void handle352(char *prefix, char *params) {
(who.len ? ", " : ""), color(user), nick
);
if ((size_t)len < cap) who.len += len;
+ tabTouch(nick);
}
static void handle315(char *prefix, char *params) {
- (void)prefix;
- shift(&params);
- char *chan = shift(&params);
- who.len = 0;
+ char *chan;
+ shift(prefix, NULL, NULL, NULL, params, 2, 0, NULL, &chan);
uiFmt(
"In \3%d%s\3 are %s",
color(chan), chan, who.buf
);
+ who.len = 0;
}
static void handleNick(char *prefix, char *params) {
- char *prev = prift(&prefix);
- char *user = prift(&prefix);
- char *next = shift(&params);
+ char *prev, *user, *next;
+ shift(prefix, &prev, &user, NULL, params, 1, 0, &next);
+ uiFmt(
+ "\3%d%s\3 is now known as \3%d%s\3",
+ color(user), prev, color(user), next
+ );
if (!strcmp(user, chat.user)) {
free(chat.nick);
chat.nick = strdup(next);
}
tabReplace(prev, next);
+}
+
+static void handleCTCP(char *nick, char *user, char *mesg) {
+ mesg = &mesg[1];
+ char *ctcp = strsep(&mesg, " ");
+ char *params = strsep(&mesg, "\1");
+ if (strcmp(ctcp, "ACTION")) return;
uiFmt(
- "\3%d%s\3 is now known as \3%d%s\3",
- color(user), prev, color(user), next
+ "* \3%d%s\3 %s",
+ color(user), nick, params
);
+ if (strcmp(user, chat.user)) tabTouch(nick);
+ urlScan(params);
}
static void handlePrivmsg(char *prefix, char *params) {
- char *nick = prift(&prefix);
- char *user = prift(&prefix);
- shift(&params);
- char *mesg = shift(&params);
+ char *nick, *user, *mesg;
+ shift(prefix, &nick, &user, NULL, params, 2, 0, NULL, &mesg);
+ if (mesg[0] == '\1') {
+ handleCTCP(nick, user, mesg);
+ return;
+ }
bool self = !strcmp(user, chat.user);
bool ping = !strncasecmp(mesg, chat.nick, strlen(chat.nick));
+ uiFmt(
+ "%c%c\3%d%s\17%c %s",
+ self["<["], ping["\17\26"], color(user), nick, self[">]"], mesg
+ );
if (!self) tabTouch(nick);
- urlScan(mesg);
if (ping) uiBeep();
- if (mesg[0] == '\1') {
- strsep(&mesg, " ");
- char *action = strsep(&mesg, "\1");
- uiFmt("* \3%d%s\3 %s", color(user), nick, action);
- } else {
- uiFmt(
- "%c%c\3%d%s\17%c %s",
- self["<["], ping["\17\26"], color(user), nick, self[">]"], mesg
- );
- }
+ urlScan(mesg);
}
static void handleNotice(char *prefix, char *params) {
- char *nick = prift(&prefix);
- char *user = prift(&prefix);
- char *chan = shift(&params);
- char *mesg = shift(&params);
- if (strcmp(chat.chan, chan)) return;
+ char *nick, *user, *chan, *mesg;
+ shift(prefix, &nick, &user, NULL, params, 2, 0, &chan, &mesg);
+ if (strcmp(chan, chat.chan)) return;
+ uiFmt(
+ "-\3%d%s\3- %s",
+ color(user), nick, mesg
+ );
tabTouch(nick);
urlScan(mesg);
- uiFmt("-\3%d%s\3- %s", color(user), nick, mesg);
}
static const struct {