From 7e1a68eaf8e5c52254b82469244e64842a41dda7 Mon Sep 17 00:00:00 2001
From: Ed Kellett <e@kellett.im>
Date: Sun, 7 Jun 2020 00:19:35 +0100
Subject: [PATCH] m_privs: break long responses into multiple lines

---
 modules/m_privs.c | 49 +++++++++++++++++++++++++++--------------------
 1 file changed, 28 insertions(+), 21 deletions(-)

diff --git a/modules/m_privs.c b/modules/m_privs.c
index a650203c..7ff25a6b 100644
--- a/modules/m_privs.c
+++ b/modules/m_privs.c
@@ -81,45 +81,52 @@ static struct mode_table auth_client_table[] = {
 
 DECLARE_MODULE_AV2(privs, NULL, NULL, privs_clist, NULL, NULL, NULL, NULL, privs_desc);
 
+static void append_priv(struct Client *source_p, struct Client *target_p, char *buf, const char *s1, const char *s2)
+{
+	/* 510 - ":" - " 270 " - " " - " :* " */
+	size_t sourcelen = strlen(source_p->name);
+	if (sourcelen < 9) sourcelen = 9;
+	size_t limit = 499 - strlen(me.name) - sourcelen - strlen(target_p->name);
+	if (strlen(s1) + strlen(s2) + strlen(buf) + 1 > limit)
+	{
+		sendto_one_numeric(source_p, RPL_PRIVS, "%s :* %s", target_p->name, buf);
+		buf[0] = '\0';
+	}
+	if (buf[0] != '\0')
+		rb_strlcat(buf, " ", BUFSIZE);
+	rb_strlcat(buf, s1, BUFSIZE);
+	rb_strlcat(buf, s2, BUFSIZE);
+}
+
 static void show_privs(struct Client *source_p, struct Client *target_p)
 {
-	char buf[512];
+	char buf[BUFSIZE];
 	struct mode_table *p;
 
 	buf[0] = '\0';
+
 	if (target_p->user->privset)
-		rb_strlcat(buf, target_p->user->privset->privs, sizeof buf);
+		for (const char *s = strtok(target_p->user->privset->privs, " "); s != NULL; s = strtok(NULL, " "))
+			append_priv(source_p, target_p, buf, s, "");
+
 	if (IsOper(target_p))
 	{
 		if (target_p->user->opername)
-		{
-			if (buf[0] != '\0')
-				rb_strlcat(buf, " ", sizeof buf);
-			rb_strlcat(buf, "operator:", sizeof buf);
-			rb_strlcat(buf, target_p->user->opername, sizeof buf);
-		}
+			append_priv(source_p, target_p, buf, "operator:", target_p->user->opername);
 
 		if (target_p->user->privset)
-		{
-			if (buf[0] != '\0')
-				rb_strlcat(buf, " ", sizeof buf);
-			rb_strlcat(buf, "privset:", sizeof buf);
-			rb_strlcat(buf, target_p->user->privset->name, sizeof buf);
-		}
+			append_priv(source_p, target_p, buf, "privset:", target_p->user->privset->name);
 	}
 	p = &auth_client_table[0];
 	while (p->name != NULL)
 	{
 		if (target_p->flags & p->mode)
-		{
-			if (buf[0] != '\0')
-				rb_strlcat(buf, " ", sizeof buf);
-			rb_strlcat(buf, p->name, sizeof buf);
-		}
+			append_priv(source_p, target_p, buf, p->name, "");
 		p++;
 	}
-	sendto_one_numeric(source_p, RPL_PRIVS, form_str(RPL_PRIVS),
-			target_p->name, buf);
+
+	if (buf[0] != '\0')
+		sendto_one_numeric(source_p, RPL_PRIVS, "%s :%s", target_p->name, buf);
 }
 
 static void