diff options
| -rw-r--r-- | handle.c | 218 | 
1 files changed, 124 insertions, 94 deletions
| @@ -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(¶ms); +		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(¶ms); +		} 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(¶ms); -	shift(¶ms); -	char *mesg = shift(¶ms); +	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(¶ms); +	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(¶ms); +	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(¶ms); -	tabRemove(nick); -	if (params) { -		char *mesg = shift(¶ms); +	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(¶ms); +	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(¶ms); -	char *kick = shift(¶ms); -	char *mesg = shift(¶ms); +	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(¶ms); -	char *chan = shift(¶ms); -	char *topic = shift(¶ms); -	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(¶ms); -	char *topic = shift(¶ms); -	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(¶ms); -	char *chan = shift(¶ms); +	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(¶ms); -	shift(¶ms); -	char *user = shift(¶ms); -	shift(¶ms); -	shift(¶ms); -	char *nick = shift(¶ms); -	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(¶ms); -	char *chan = shift(¶ms); -	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(¶ms); +	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(¶ms); -	char *mesg = shift(¶ms); +	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(¶ms); -	char *mesg = shift(¶ms); -	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 { | 
