summary refs log tree commit diff
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2019-10-26 04:57:33 -0400
committerJune McEnroe <june@causal.agency>2019-10-26 04:57:33 -0400
commit648c5cc21484a4f0d9846f04bc47c1e35fa18234 (patch)
tree02847d4c25ec01c65ce3db9b0ab2cc5e61dbb568
parentSet AWAY when no clients are connected (diff)
downloadpounce-648c5cc21484a4f0d9846f04bc47c1e35fa18234.tar.gz
pounce-648c5cc21484a4f0d9846f04bc47c1e35fa18234.zip
Track channel topics
-rw-r--r--bounce.c3
-rw-r--r--bounce.h1
-rw-r--r--pounce.17
-rw-r--r--state.c75
4 files changed, 58 insertions, 28 deletions
diff --git a/bounce.c b/bounce.c
index 648a17b..8d9a4b5 100644
--- a/bounce.c
+++ b/bounce.c
@@ -94,7 +94,7 @@ int main(int argc, char *argv[]) {
 	const char *away = "pounced :3";
 
 	int opt;
-	while (0 < (opt = getopt(argc, argv, "A:C:H:K:NTP:W:a:h:j:n:p:r:u:vw:"))) {
+	while (0 < (opt = getopt(argc, argv, "A:C:H:K:NP:W:a:h:j:n:p:r:u:vw:"))) {
 		switch (opt) {
 			break; case 'A': away = optarg;
 			break; case 'C': strlcpy(certPath, optarg, sizeof(certPath));
@@ -102,7 +102,6 @@ int main(int argc, char *argv[]) {
 			break; case 'K': strlcpy(privPath, optarg, sizeof(privPath));
 			break; case 'N': stateJoinNames = true;
 			break; case 'P': localPort = optarg;
-			break; case 'T': stateJoinTopic = true;
 			break; case 'W': clientPass = sensitive(optarg);
 			break; case 'a': auth = sensitive(optarg);
 			break; case 'h': host = optarg;
diff --git a/bounce.h b/bounce.h
index 4945931..26e62df 100644
--- a/bounce.h
+++ b/bounce.h
@@ -88,7 +88,6 @@ size_t clientDiff(const struct Client *client);
 void clientConsume(struct Client *client);
 
 bool stateJoinNames;
-bool stateJoinTopic;
 bool stateReady(void);
 void stateParse(char *line);
 void stateSync(struct Client *client);
diff --git a/pounce.1 b/pounce.1
index 95e554b..b76d819 100644
--- a/pounce.1
+++ b/pounce.1
@@ -8,7 +8,7 @@
 .
 .Sh SYNOPSIS
 .Nm
-.Op Fl NTv
+.Op Fl Nv
 .Op Fl A Ar away
 .Op Fl C Ar cert
 .Op Fl H Ar host
@@ -80,11 +80,6 @@ Bind to local
 .Ar port .
 The default port is 6697.
 .
-.It Fl T
-Request
-.Ql TOPIC
-for each channel when a client connects.
-.
 .It Fl W Ar pass
 Require the password
 .Ar pass
diff --git a/state.c b/state.c
index 02eaf72..a5bdaee 100644
--- a/state.c
+++ b/state.c
@@ -43,28 +43,45 @@ static void set(char **field, const char *value) {
 	if (!*field) err(EX_OSERR, "strdup");
 }
 
+struct Channel {
+	char *name;
+	char *topic;
+};
+
 static struct {
-	char **names;
+	struct Channel *ptr;
 	size_t cap, len;
-} chan;
+} chans;
 
 static void chanAdd(const char *name) {
-	if (chan.len == chan.cap) {
-		chan.cap = (chan.cap ? chan.cap * 2 : 8);
-		chan.names = realloc(chan.names, sizeof(char *) * chan.cap);
-		if (!chan.names) err(EX_OSERR, "realloc");
+	if (chans.len == chans.cap) {
+		chans.cap = (chans.cap ? chans.cap * 2 : 8);
+		chans.ptr = realloc(chans.ptr, sizeof(*chans.ptr) * chans.cap);
+		if (!chans.ptr) err(EX_OSERR, "realloc");
+	}
+	struct Channel *chan = &chans.ptr[chans.len++];
+	chan->name = strdup(name);
+	if (!chan->name) err(EX_OSERR, "strdup");
+	chan->topic = NULL;
+}
+
+static void chanTopic(const char *name, const char *topic) {
+	for (size_t i = 0; i < chans.len; ++i) {
+		if (strcmp(chans.ptr[i].name, name)) continue;
+		free(chans.ptr[i].topic);
+		chans.ptr[i].topic = strdup(topic);
+		if (!chans.ptr[i].topic) err(EX_OSERR, "strdup");
+		break;
 	}
-	chan.names[chan.len] = strdup(name);
-	if (!chan.names[chan.len]) err(EX_OSERR, "strdup");
-	chan.len++;
 }
 
 static void chanRemove(const char *name) {
-	for (size_t i = 0; i < chan.len; ++i) {
-		if (strcmp(chan.names[i], name)) continue;
-		free(chan.names[i]);
-		chan.names[i] = chan.names[--chan.len];
-		return;
+	for (size_t i = 0; i < chans.len; ++i) {
+		if (strcmp(chans.ptr[i].name, name)) continue;
+		free(chans.ptr[i].name);
+		free(chans.ptr[i].topic);
+		chans.ptr[i] = chans.ptr[--chans.len];
+		break;
 	}
 }
 
@@ -179,6 +196,18 @@ static void handleKick(struct Message *msg) {
 	}
 }
 
+static void handleTopic(struct Message *msg) {
+	if (!msg->params[0]) errx(EX_PROTOCOL, "TOPIC without channel");
+	if (!msg->params[1]) errx(EX_PROTOCOL, "TOPIC without topic");
+	chanTopic(msg->params[0], msg->params[1]);
+}
+
+static void handleReplyTopic(struct Message *msg) {
+	if (!msg->params[1]) errx(EX_PROTOCOL, "RPL_TOPIC without channel");
+	if (!msg->params[2]) errx(EX_PROTOCOL, "RPL_TOPIC without topic");
+	chanTopic(msg->params[1], msg->params[2]);
+}
+
 static void handleError(struct Message *msg) {
 	errx(EX_UNAVAILABLE, "%s", msg->params[0]);
 }
@@ -192,12 +221,14 @@ static const struct {
 	{ "003", handleReplyCreated },
 	{ "004", handleReplyMyInfo },
 	{ "005", handleReplyISupport },
+	{ "332", handleReplyTopic },
 	{ "CAP", handleCap },
 	{ "ERROR", handleError },
 	{ "JOIN", handleJoin },
 	{ "KICK", handleKick },
 	{ "NICK", handleNick },
 	{ "PART", handlePart },
+	{ "TOPIC", handleTopic },
 };
 
 void stateParse(char *line) {
@@ -260,10 +291,16 @@ void stateSync(struct Client *client) {
 		clientFormat(client, " :are supported by this server\r\n");
 	}
 
-	if (chan.len) assert(self.origin);
-	for (size_t i = 0; i < chan.len; ++i) {
-		clientFormat(client, ":%s JOIN %s\r\n", self.origin, chan.names[i]);
-		if (stateJoinTopic) serverFormat("TOPIC %s\r\n", chan.names[i]);
-		if (stateJoinNames) serverFormat("NAMES %s\r\n", chan.names[i]);
+	if (chans.len) assert(self.origin);
+	for (size_t i = 0; i < chans.len; ++i) {
+		const struct Channel *chan = &chans.ptr[i];
+		clientFormat(client, ":%s JOIN %s\r\n", self.origin, chan->name);
+		if (chan->topic) {
+			clientFormat(
+				client, ":%s 332 %s %s :%s\r\n",
+				Origin, self.nick, chan->name, chan->topic
+			);
+		}
+		if (stateJoinNames) serverFormat("NAMES %s\r\n", chan->name);
 	}
 }
> | | | No code changes required, just bump the submodule and Makefile versions. Signed-off-by: Lukas Fleischer <cgit@cryptocrack.de> * git: update to 1.8.5Christian Hesse2014-01-08 | | | | | | | Everything works just bumping the version in Makefile and commit hash in submodule. No code changes required. Signed-off-by: Lukas Fleischer <cgit@cryptocrack.de> * git: update to 1.8.4John Keeping2013-08-26 | | | | | | No code changes required, just bump the submodule and makefile versions. Signed-off-by: John Keeping <john@keeping.me.uk> * git: update to 1.8.3John Keeping2013-05-25 | | | | | | No changes required, just bump the submodule and Makefile versions. Signed-off-by: John Keeping <john@keeping.me.uk> * git: update to 1.8.2.2John Keeping2013-04-27 | | | | | | No changes required, just bump the submodule and Makefile version. Signed-off-by: John Keeping <john@keeping.me.uk> * Update git to v1.8.2.1John Keeping2013-04-08 | | | | | | | | | | | This requires a small change to how we handle notes, but otherwise just works. Note that we can't use anything from v1.8.0 until v1.8.2.1 because some of the symbols that we need for graph drawing were made private in v1.8.0 and this was not reverted until v1.8.2.1. Signed-off-by: John Keeping <john@keeping.me.uk> * Update git to v1.7.12.4John Keeping2013-03-02 | | | | | | No changes needed. Signed-off-by: John Keeping <john@keeping.me.uk> * Update git to v1.7.9.7John Keeping2013-03-02 | | | | | | resolve_ref() is renamed to resolve_ref_unsafe(). CGit's usage is safe. Signed-off-by: John Keeping <john@keeping.me.uk> * Update git to v1.7.8.6John Keeping2013-03-02 | | | | | | No changes required. Signed-off-by: John Keeping <john@keeping.me.uk> * Update git to v1.7.7.7John Keeping2013-03-02 | | | | | | | This release changes the archive interface so that we now need to pass argv into write_archive(). Signed-off-by: John Keeping <john@keeping.me.uk> * Update git to v1.7.6.5John Keeping2013-03-02 | | | | | | struct pathspec is now used in more places. Signed-off-by: John Keeping <john@keeping.me.uk> * Update git to v1.7.5.4John Keeping2013-03-02 | | | | | | | | | Some changes to diff options: - no_merges has become the more general max_parents - path restriction now uses struct pathspec Signed-off-by: John Keeping <john@keeping.me.uk> * Use GIT-1.7.4Lars Hjemli2011-02-19 | | | | Signed-off-by: Lars Hjemli <hjemli@gmail.com> * Use GIT-1.7.3Lars Hjemli2010-09-19 | | | | Signed-off-by: Lars Hjemli <hjemli@gmail.com> * Use GIT-1.7.2.2Lars Hjemli2010-08-22 | | | | Signed-off-by: Lars Hjemli <hjemli@gmail.com> * Use GIT-1.7.0Lars Hjemli2010-02-27 | | | | Signed-off-by: Lars Hjemli <hjemli@gmail.com> * Use GIT-1.6.4.3Lars Hjemli2009-09-13 | | | | Signed-off-by: Lars Hjemli <larsh@slackbox.hjemli.net> * Use GIT-1.6.3.4Lars Hjemli2009-08-16 | | | | Signed-off-by: Lars Hjemli <hjemli@gmail.com> * Use GIT-1.6.1.1Lars Hjemli2009-02-01 | | | | Signed-off-by: Lars Hjemli <hjemli@gmail.com> * Use GIT-1.6.1Lars Hjemli2008-12-26 | | | | Signed-off-by: Lars Hjemli <hjemli@gmail.com> * Use GIT-1.6.0.3Lars Hjemli2008-11-06 | | | | Signed-off-by: Lars Hjemli <hjemli@gmail.com> * Use GIT-1.6.0.2Lars Hjemli2008-10-05 | | | | Signed-off-by: Lars Hjemli <hjemli@gmail.com> * Use GIT-1.6.0.1Lars Hjemli2008-09-02 | | | | Signed-off-by: Lars Hjemli <hjemli@gmail.com> * Use GIT-1.6.0Lars Hjemli2008-09-01 | * Use GIT-1.6.0.rc1Lars Hjemli2008-08-06 | | | | | | | Now that rc1 is released as a tarball `make get-git` should start working again. Signed-off-by: Lars Hjemli <hjemli@gmail.com> * Use GIT-1.6.0-rc0Lars Hjemli2008-07-21 | * Use GIT-1.5.6Lars Hjemli2008-06-25 | * Use GIT-1.5.5.1Lars Hjemli2008-05-18 | | | | Signed-off-by: Lars Hjemli <hjemli@gmail.com> * Use GIT-1.5.5Lars Hjemli2008-04-09 | * Use GIT-1.5.5-rc2Lars Hjemli2008-04-01 | * Use GIT-1.5.5.rc1Lars Hjemli2008-03-23 | * Use GIT-1.5.4.4Lars Hjemli2008-03-17 |