about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ircd.h1
-rw-r--r--loop.c24
-rw-r--r--user.c31
3 files changed, 43 insertions, 13 deletions
diff --git a/ircd.h b/ircd.h
index 8097c26..07bdd0f 100644
--- a/ircd.h
+++ b/ircd.h
@@ -75,6 +75,7 @@ extern int port;
 
 const char *getnick(const struct Peer *peer);
 void user_reg(struct Peer *peer, const char *nick, const char *user, const char *real);
+void user_remove(size_t pid);
 
 int channel_join(struct Channel *channel, struct Peer *peer);
 int channel_exit(struct Channel *channel, struct Peer *peer);
diff --git a/loop.c b/loop.c
index 81ff25d..9e91438 100644
--- a/loop.c
+++ b/loop.c
@@ -123,19 +123,18 @@ loop:
 		if (!(peers[i].flags & DELETE))
 			continue;
 
-		if (!peers[i].type)
-			goto skip;
-		writef(
-			peers[i].fd,
-			":%s!%s@%s QUIT",
-			getnick(&peers[i]),
-			peers[i].user,
-			peers[i].host
-		);
+		if (peers[i].type)
+			writef(
+				peers[i].fd,
+				":%s!%s@%s QUIT",
+				getnick(&peers[i]),
+				peers[i].user,
+				peers[i].host
+			);
 		for (j = 0; j < peers[i].channels_c; ++j)
 		{
 			channel_exit(peers[i].channels[j], &peers[i]);
-			for (k = 0; k < peers[i].channels[j]->users_c; ++k)
+			if (peers[i].type) for (k = 0; k < peers[i].channels[j]->users_c; ++k)
 				peers[i].channels[j]->users[k]->flags |= ANNOUNCE;
 		}
 		for (j = 0; j < peers_c; ++j)
@@ -143,17 +142,16 @@ loop:
 			{
 				writef(
 					peers[j].fd,
-					"%s!%s@%s QUIT",
+					":%s!%s@%s QUIT",
 					getnick(&peers[i]),
 					peers[i].user,
 					peers[i].host
 				);
 				peers[j].flags &= ~ANNOUNCE;
 			}
-skip:
 		writef(peers[i].fd, "ERROR :Closing Link: %s", peers[i].host);
 		close(peers[i].fd);
-		peers[i] = peers[--peers_c];
+		user_remove(i);
 		i = 0;
 	}
 	goto loop;
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];
+}