about summary refs log tree commit diff
path: root/user.c
diff options
context:
space:
mode:
authorNakidai <nakidai@disroot.org>2026-01-07 00:26:37 +0300
committerNakidai <nakidai@disroot.org>2026-01-07 00:26:37 +0300
commit63c0a8860459c0c9bf3b66d4d4ec631ece4bf56e (patch)
treee148ddc96aa7b50e3eb981eae8c9faf9de6ab2f5 /user.c
parentcfcb3b22245c779eb9d216c2909789e4368cce6a (diff)
downloadlibreircd-63c0a8860459c0c9bf3b66d4d4ec631ece4bf56e.tar.gz
libreircd-63c0a8860459c0c9bf3b66d4d4ec631ece4bf56e.zip
Fix user quit
When user A leaves, last user in the peer list B is copied into the
space left by leaving A. But, besides that it also important to not
forget that there can be channels containing B: they store a link
to every user belonging. So, it's important to adjust all links to
B iterating every channel B belongs to.
Diffstat (limited to 'user.c')
-rw-r--r--user.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/user.c b/user.c
index e37452b..f856f6c 100644
--- a/user.c
+++ b/user.c
@@ -16,8 +16,11 @@
 
 #include "ircd.h"
 
+#include <stddef.h>
 #include <string.h>
 
+#include <err.h>
+
 
 const char *
 getnick(const struct Peer *peer)
@@ -40,3 +43,31 @@ user_reg(struct Peer *peer, const char *nick, const char *user, const char *real
 		reply(peer, 1);
 	}
 }
+
+void
+user_remove(size_t pid)
+{
+	size_t i, j;
+
+	for (i = 0; i < peers[peers_c-1].channels_c; ++i)
+	{
+		for (j = 0; j < peers[peers_c-1].channels[i]->users_c; ++j)
+			if (peers[peers_c-1].channels[i]->users[j]->fd == peers[peers_c-1].fd)
+				break;
+		if (j == peers[peers_c-1].channels[i]->users_c)
+		{
+			warnx(
+				"user_unlink(): %s@%s doesn't belong to %s, "
+				"though they believe in the opposite",
+				getnick(&peers[peers_c-1]),
+				peers[peers_c-1].host,
+				peers[peers_c-1].channels[i]->name
+			);
+			continue;
+		}
+
+		peers[peers_c-1].channels[i]->users[j] = &peers[pid];
+	}
+
+	peers[pid] = peers[--peers_c];
+}