Index: ipc.c
===================================================================
--- ipc.c	(revision debe871bbd96a1d4215983265d97b8f0df7a4fbf)
+++ ipc.c	(revision c5bff810e6919dc3daf7f82f761197a27f04538b)
@@ -35,4 +35,7 @@
 static int ipc_child_recv_fd = -1;
 
+static void ipc_master_takeover_fail( struct bitlbee_child *child, gboolean both );
+static gboolean ipc_send_fd( int fd, int send_fd );
+
 static void ipc_master_cmd_client( irc_t *data, char **cmd )
 {
@@ -154,5 +157,5 @@
 	{
 		/* Won't need the fd since we can't send it anywhere. */
-		close( child->to_fd );
+		closesocket( child->to_fd );
 		child->to_fd = -1;
 		resp = "TAKEOVER NO\r\n";
@@ -160,11 +163,7 @@
 	
 	if( write( child->ipc_fd, resp, strlen( resp ) ) != strlen( resp ) )
-	{
 		ipc_master_free_one( child );
-		child_list = g_slist_remove( child_list, child );
-	}
-}
-
-static gboolean ipc_send_fd( int fd, int send_fd );
+}
+
 
 void ipc_master_cmd_takeover( irc_t *data, char **cmd )
@@ -173,7 +172,11 @@
 	char *fwd = NULL;
 	
-	/* TODO: Check if child->to_child is still valid, etc. */
+	if( child->to_child == NULL ||
+	    g_slist_find( child_list, child->to_child ) == NULL )
+		return ipc_master_takeover_fail( child, FALSE );
+	
 	if( strcmp( cmd[1], "AUTH" ) == 0 )
 	{
+		/* New connection -> Master */
 		if( child->to_child &&
 		    child->nick && child->to_child->nick && cmd[2] &&
@@ -188,17 +191,17 @@
 			fwd = irc_build_line( cmd );
 			if( write( child->to_child->ipc_fd, fwd, strlen( fwd ) ) != strlen( fwd ) )
-			{
 				ipc_master_free_one( child );
-				child_list = g_slist_remove( child_list, child );
-			}
 			g_free( fwd );
 		}
+		else
+			return ipc_master_takeover_fail( child, TRUE );
 	}
 	else if( strcmp( cmd[1], "DONE" ) == 0 || strcmp( cmd[1], "FAIL" ) == 0 )
 	{
+		/* Old connection -> Master */
 		int fd;
 		
 		/* The copy was successful (or not), we don't need it anymore. */
-		close( child->to_fd );
+		closesocket( child->to_fd );
 		child->to_fd = -1;
 		
@@ -209,8 +212,5 @@
 		child->to_child = NULL;
 		if( write( fd, fwd, strlen( fwd ) ) != strlen( fwd ) )
-		{
 			ipc_master_free_one( child );
-			child_list = g_slist_remove( child_list, child );
-		}
 		g_free( fwd );
 	}
@@ -343,5 +343,5 @@
 			ipc_child_recv_fd = -1;
 			
-			irc_write( irc, ":%s!%s@%s MODE %s :%s", irc->user->nick,
+			irc_write( irc, ":%s!%s@%s MODE %s :+%s", irc->user->nick,
 			           irc->user->user, irc->user->host, irc->user->nick,
 			           irc->umode );
@@ -434,4 +434,27 @@
 }
 
+static void ipc_master_takeover_fail( struct bitlbee_child *child, gboolean both )
+{
+	if( child == NULL || g_slist_find( child_list, child ) == NULL )
+		return;
+	
+	if( both && child->to_child != NULL )
+		ipc_master_takeover_fail( child->to_child, FALSE );
+	
+	if( child->to_fd > -1 )
+	{
+		/* Send this error only to the new connection, which can be
+		   recognised by to_fd being set. */
+		if( write( child->ipc_fd, "TAKEOVER FAIL\r\n", 15 ) != 15 )
+		{
+			ipc_master_free_one( child );
+			return;
+		}
+		close( child->to_fd );
+		child->to_fd = -1;
+	}
+	child->to_child = NULL;
+}
+
 static void ipc_command_exec( void *data, char **cmd, const command_t *commands )
 {
@@ -651,8 +674,5 @@
 			next = l->next;
 			if( write( c->ipc_fd, msg_buf, msg_len ) <= 0 )
-			{
 				ipc_master_free_one( c );
-				child_list = g_slist_remove( child_list, c );
-			}
 		}
 	}
@@ -680,5 +700,5 @@
 	
 	memset( &msg, 0, sizeof( msg ) );
-	iov.iov_base = "0x90\r\n";
+	iov.iov_base = "0x90\r\n";         /* Ja, noppes */
 	iov.iov_len = 6;
 	msg.msg_iov = &iov;
@@ -699,4 +719,6 @@
 void ipc_master_free_one( struct bitlbee_child *c )
 {
+	GSList *l;
+	
 	b_event_remove( c->ipc_inpa );
 	closesocket( c->ipc_fd );
@@ -710,4 +732,15 @@
 	g_free( c->password );
 	g_free( c );
+	
+	child_list = g_slist_remove( child_list, c );
+	
+	/* Also, if any child has a reference to this one, remove it. */
+	for( l = child_list; l; l = l->next )
+	{
+		struct bitlbee_child *oc = l->data;
+		
+		if( oc->to_child == c )
+			ipc_master_takeover_fail( oc, FALSE );
+	}
 }
 
@@ -723,5 +756,4 @@
 		{
 			ipc_master_free_one( c );
-			child_list = g_slist_remove( child_list, c );
 			break;
 		}
@@ -731,11 +763,6 @@
 void ipc_master_free_all()
 {
-	GSList *l;
-	
-	for( l = child_list; l; l = l->next )
-		ipc_master_free_one( l->data );
-	
-	g_slist_free( child_list );
-	child_list = NULL;
+	while( child_list )
+		ipc_master_free_one( child_list->data );
 }
 
