$ git clone https://ion.nu/git/webchat
commit 49847d5e12c0e13d69befabc98335a238796c9ae
Author: Alicia <...>
Date:   Tue Dec 29 02:53:39 2015 +0100

    Free channels when the last user leaves, unless it's a registered channel which might have data that should be kept (banlist, topic)

diff --git a/src/channels.c b/src/channels.c
index e1e7fef..ba91313 100644
--- a/src/channels.c
+++ b/src/channels.c
@@ -171,3 +171,26 @@ char channel_checkban(struct channel* channel, struct sockaddr* useraddr)
   }
   return 0;
 }
+
+void channel_free(struct channel* channel)
+{
+  unsigned int i;
+  for(i=0; i<channel->bancount; ++i)
+  {
+    free((void*)channel->bans[i].addr);
+    free((void*)channel->bans[i].nickname);
+  }
+  free((void*)channel->name);
+  free(channel->users);
+  free(channel->password);
+  free(channel->bans);
+  for(i=0; i<channelcount; ++i)
+  {
+    if(channels[i]==channel)
+    {
+      --channelcount;
+      memmove(&channels[i], &channels[i+1], sizeof(struct channel*)*(channelcount-i));
+      return;
+    }
+  }
+}
diff --git a/src/channels.h b/src/channels.h
index 23baf7e..30ace31 100644
--- a/src/channels.h
+++ b/src/channels.h
@@ -42,3 +42,4 @@ extern char channel_register(struct channel* channel, struct user* owner);
 extern void channel_ban(struct channel* channel, struct user* user);
 extern char channel_unban(struct channel* channel, unsigned int id);
 extern char channel_checkban(struct channel* channel, struct sockaddr* useraddr);
+extern void channel_free(struct channel* channel);
diff --git a/src/users.c b/src/users.c
index 00e057c..499a935 100644
--- a/src/users.c
+++ b/src/users.c
@@ -97,6 +97,10 @@ void freeuser(struct user* user)
       {
         --user->channel->usercount;
         memmove(&user->channel->users[i], &user->channel->users[i+1], sizeof(struct user*)*(user->channel->usercount-i));
+        if(user->channel->usercount==0 && user->channel->id==-1) // Last one to leave frees the channel, unless it's a registered channel which might have a banlist and/or topic to keep
+        {
+          channel_free(user->channel);
+        }
       }
     }
   }