Index: ipc.c
===================================================================
--- ipc.c	(revision 6c2404e051cb6a235f985797c149af0791f44bbd)
+++ ipc.c	(revision 0b09da0dbbdf294799bd5335b327c2601f263b01)
@@ -33,4 +33,5 @@
 
 GSList *child_list = NULL;
+static int ipc_child_recv_fd = -1;
 
 static void ipc_master_cmd_client( irc_t *data, char **cmd )
@@ -115,4 +116,5 @@
 {
 	struct bitlbee_child *child = (void*) data, *old = NULL;
+	char *resp;
 	GSList *l;
 	
@@ -127,12 +129,59 @@
 		old = l->data;
 		if( nick_cmp( old->nick, child->nick ) == 0 && child != old &&
-		    old->password && strcmp( old->password, child->password ) )
+		    old->password && strcmp( old->password, child->password ) == 0 )
 			break;
 	}
 	
-	if( old == NULL )
-		return;
-	
 	child->to_child = old;
+	
+	if( l )
+	{
+		resp = "TAKEOVER INIT\r\n";
+	}
+	else
+	{
+		/* Won't need the fd since we can't send it anywhere. */
+		close( child->to_fd );
+		child->to_fd = -1;
+		resp = "TAKEOVER NO\r\n";
+	}
+	
+	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 )
+{
+	struct bitlbee_child *child = (void*) data;
+	
+	/* TODO: Check if child->to_child is still valid, etc. */
+	if( strcmp( cmd[1], "AUTH" ) == 0 )
+	{
+		if( child->to_child &&
+		    child->nick && child->to_child->nick && cmd[2] &&
+		    child->password && child->to_child->password && cmd[3] &&
+		    strcmp( child->nick, child->to_child->nick ) == 0 &&
+		    strcmp( child->nick, cmd[2] ) == 0 &&
+		    strcmp( child->password, child->to_child->password ) == 0 &&
+		    strcmp( child->password, cmd[3] ) == 0 )
+		{
+			char *s;
+			
+			ipc_send_fd( child->to_child->ipc_fd, child->to_fd );
+			
+			s = irc_build_line( cmd );
+			if( write( child->to_child->ipc_fd, s, strlen( s ) ) != strlen( s ) )
+			{
+				ipc_master_free_one( child );
+				child_list = g_slist_remove( child_list, child );
+			}
+			g_free( s );
+		}
+	}
 }
 
@@ -149,4 +198,5 @@
 	{ "restart",    0, ipc_master_cmd_restart,    0 },
 	{ "identify",   2, ipc_master_cmd_identify,   0 },
+	{ "takeover",   1, ipc_master_cmd_takeover,   0 },
 	{ NULL }
 };
@@ -215,4 +265,44 @@
 	else
 		ipc_to_master_str( "HELLO %s %s :%s\r\n", irc->user->host, irc->user->nick, irc->user->fullname );
+}
+
+static void ipc_child_cmd_takeover( irc_t *irc, char **cmd )
+{
+	if( strcmp( cmd[1], "NO" ) == 0 )
+	{
+		/* No takeover, finish the login. */
+	}
+	else if( strcmp( cmd[1], "INIT" ) == 0 )
+	{
+		ipc_to_master_str( "TAKEOVER AUTH %s :%s\r\n",
+		                   irc->user->nick, irc->password );
+		
+		/* Drop credentials, we'll shut down soon and shouldn't overwrite
+		   any settings. */
+		/* TODO: irc_setpass() should do all of this. */
+		irc_usermsg( irc, "Trying to take over existing session" );
+		/** NOT YET
+		irc_setpass( irc, NULL );
+		irc->status &= ~USTATUS_IDENTIFIED;
+		irc_umode_set( irc, "-R", 1 );
+		*/
+	}
+	else if( strcmp( cmd[1], "AUTH" ) == 0 )
+	{
+		if( irc->password && cmd[2] && cmd[3] &&
+		    ipc_child_recv_fd != -1 &&
+		    strcmp( irc->user->nick, cmd[2] ) == 0 &&
+		    strcmp( irc->password, cmd[3] ) == 0 )
+		{
+			fprintf( stderr, "TO\n" );
+			b_event_remove( irc->r_watch_source_id );
+			closesocket( irc->fd );
+			irc->fd = ipc_child_recv_fd;
+			irc->r_watch_source_id = b_input_add( irc->fd, B_EV_IO_READ, bitlbee_io_current_client_read, irc );
+			ipc_child_recv_fd = -1;
+		}
+		fprintf( stderr, "%s %s %s\n", irc->password, cmd[2], cmd[3] );
+		fprintf( stderr, "%d %s %s\n", ipc_child_recv_fd, irc->user->nick, irc->password );
+	}
 }
 
@@ -225,8 +315,7 @@
 	{ "kill",       2, ipc_child_cmd_kill,        0 },
 	{ "hello",      0, ipc_child_cmd_hello,       0 },
+	{ "takeover",   1, ipc_child_cmd_takeover,    0 },
 	{ NULL }
 };
-
-static gboolean ipc_send_fd( int fd, int send_fd );
 
 gboolean ipc_child_identify( irc_t *irc )
@@ -321,6 +410,8 @@
 				
 				*recv_fd = *(int*) CMSG_DATA( cmsg );
+				fprintf( stderr, "pid %d received fd %d\n", (int) getpid(), *recv_fd );
 			}
 	
+	fprintf( stderr, "pid %d received: %s", (int) getpid(), buf );
 	return g_strndup( buf, size - 2 );
 }
@@ -352,7 +443,6 @@
 {
 	char *buf, **cmd;
-	int recv_fd = -1;
-	
-	if( ( buf = ipc_readline( source, &recv_fd ) ) )
+	
+	if( ( buf = ipc_readline( source, &ipc_child_recv_fd ) ) )
 	{
 		cmd = irc_parse_line( buf );
