diff options
| -rw-r--r-- | ipc.c | 73 | ||||
| -rw-r--r-- | root_commands.c | 23 | 
2 files changed, 90 insertions, 6 deletions
| @@ -171,6 +171,11 @@ void ipc_master_cmd_takeover( irc_t *data, char **cmd )  	struct bitlbee_child *child = (void*) data;  	char *fwd = NULL; +	/* Normal daemon mode doesn't keep these and has simplified code for +	   takeovers. */ +	if( child == NULL ) +		return; +	  	if( child->to_child == NULL ||  	    g_slist_find( child_list, child->to_child ) == NULL )  		return ipc_master_takeover_fail( child, FALSE ); @@ -358,22 +363,58 @@ static void ipc_child_cmd_takeover( irc_t *irc, char **cmd )  static void ipc_child_cmd_takeover_yes( void *data )  { -	irc_t *irc = data; +	irc_t *irc = data, *old = NULL; +	char *to_auth[] = { "TAKEOVER", "AUTH", irc->user->nick, irc->password, NULL };  	/* Master->New connection */  	ipc_to_master_str( "TAKEOVER AUTH %s :%s\r\n",  	                   irc->user->nick, irc->password ); +	if( global.conf->runmode == RUNMODE_DAEMON ) +	{ +		GSList *l; +		 +		for( l = irc_connection_list; l; l = l->next ) +		{ +			old = l->data; +			 +			if( irc != old && +			    irc->user->nick && old->user->nick && +			    irc->password && old->password && +			    strcmp( irc->user->nick, old->user->nick ) == 0 && +			    strcmp( irc->password, old->password ) == 0 ) +				break; +		} +		if( l == NULL ) +		{ +			to_auth[1] = "FAIL"; +			ipc_child_cmd_takeover( irc, to_auth ); +			return; +		} +	} +	  	/* Drop credentials, we'll shut down soon and shouldn't overwrite  	   any settings. */  	irc_usermsg( irc, "Trying to take over existing session" ); +	irc_desync( irc ); +	 +	if( old ) +	{ +		ipc_child_recv_fd = dup( irc->fd ); +		ipc_child_cmd_takeover( old, to_auth ); +	} +	  	/* TODO: irc_setpass() should do all of this. */  	irc_setpass( irc, NULL );  	irc->status &= ~USTATUS_IDENTIFIED;  	irc_umode_set( irc, "-R", 1 ); -	irc_desync( irc ); +	if( old ) +	{ +		irc->status |= USTATUS_SHUTDOWN; +		irc_abort( irc, FALSE, NULL ); +	}  }  static void ipc_child_cmd_takeover_no( void *data ) @@ -405,6 +446,30 @@ gboolean ipc_child_identify( irc_t *irc )  		return TRUE;  	} +	else if( global.conf->runmode == RUNMODE_DAEMON ) +	{ +		GSList *l; +		irc_t *old; +		char *to_init[] = { "TAKEOVER", "INIT", NULL }; +		 +		for( l = irc_connection_list; l; l = l->next ) +		{ +			old = l->data; +			 +			if( irc != old && +			    irc->user->nick && old->user->nick && +			    irc->password && old->password && +			    strcmp( irc->user->nick, old->user->nick ) == 0 && +			    strcmp( irc->password, old->password ) == 0 ) +				break; +		} +		if( l == NULL ) +			return FALSE; +		 +		ipc_child_cmd_takeover( irc, to_init ); +		 +		return TRUE; +	}  	else  		return FALSE;  } @@ -508,10 +573,14 @@ static char *ipc_readline( int fd, int *recv_fd )  					close( *recv_fd );  				*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 );  } diff --git a/root_commands.c b/root_commands.c index 6fa4fd54..4aeb1470 100644 --- a/root_commands.c +++ b/root_commands.c @@ -154,16 +154,31 @@ static void cmd_identify( irc_t *irc, char **cmd )  		irc_setpass( irc, password );  		irc->status |= USTATUS_IDENTIFIED;  		irc_umode_set( irc, "+R", 1 ); -		irc_channel_auto_joins( irc, NULL ); -		if( ipc_child_identify( irc ) ) +		/* The following code is a bit hairy now. With takeover +		   support, we shouldn't immediately auto_connect in case +		   we're going to offer taking over an existing session. +		   Do it in 200ms since that should give the parent process +		   enough time to come back to us. */ +		if( load )  		{ -			if( load && set_getbool( &irc->b->set, "auto_connect" ) ) +			irc_channel_auto_joins( irc, NULL ); +			if( set_getbool( &irc->b->set, "auto_connect" ) )  				irc->login_source_id = b_timeout_add( 200,  					cmd_identify_finish, irc );  		} -		else if( load && set_getbool( &irc->b->set, "auto_connect" ) ) +		 +		/* If ipc_child_identify() returns FALSE, it means we're +		   already sure that there's no takeover target (only +		   possible in 1-process daemon mode). Start auto_connect +		   immediately. */ +		if( !ipc_child_identify( irc ) && load && +		    set_getbool( &irc->b->set, "auto_connect" ) ) +		{ +			b_event_remove( irc->login_source_id ); +			irc->login_source_id = -1;  			cmd_identify_finish( irc, 0, 0 ); +		}  		break;  	case STORAGE_OTHER_ERROR: | 
