diff options
author | Wilmer van der Gaast <wilmer@gaast.net> | 2010-07-07 00:10:17 +0100 |
---|---|---|
committer | Wilmer van der Gaast <wilmer@gaast.net> | 2010-07-07 00:10:17 +0100 |
commit | 0b09da0dbbdf294799bd5335b327c2601f263b01 (patch) | |
tree | fc69940f89ad6eaabbe776c320e038e7b748d152 | |
parent | 6c2404e051cb6a235f985797c149af0791f44bbd (diff) |
It works! Fragile like hell though, and without any confirmation or whatever.
-rw-r--r-- | ipc.c | 106 |
1 files changed, 98 insertions, 8 deletions
@@ -32,6 +32,7 @@ #endif GSList *child_list = NULL; +static int ipc_child_recv_fd = -1; static void ipc_master_cmd_client( irc_t *data, char **cmd ) { @@ -114,6 +115,7 @@ void ipc_master_cmd_restart( irc_t *data, char **cmd ) void ipc_master_cmd_identify( irc_t *data, char **cmd ) { struct bitlbee_child *child = (void*) data, *old = NULL; + char *resp; GSList *l; if( strcmp( child->nick, cmd[1] ) != 0 ) @@ -126,14 +128,61 @@ void ipc_master_cmd_identify( irc_t *data, char **cmd ) { 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 ); + } + } } static const command_t ipc_master_commands[] = { @@ -148,6 +197,7 @@ static const command_t ipc_master_commands[] = { { "kill", 2, NULL, IPC_CMD_TO_CHILDREN }, { "restart", 0, ipc_master_cmd_restart, 0 }, { "identify", 2, ipc_master_cmd_identify, 0 }, + { "takeover", 1, ipc_master_cmd_takeover, 0 }, { NULL } }; @@ -216,6 +266,46 @@ static void ipc_child_cmd_hello( irc_t *irc, char **cmd ) 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 ); + } +} + static const command_t ipc_child_commands[] = { { "die", 0, ipc_child_cmd_die, 0 }, { "wallops", 1, ipc_child_cmd_wallops, 0 }, @@ -224,11 +314,10 @@ static const command_t ipc_child_commands[] = { { "rehash", 0, ipc_child_cmd_rehash, 0 }, { "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 ) { if( global.conf->runmode == RUNMODE_FORKDAEMON ) @@ -320,8 +409,10 @@ 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 ); } @@ -351,9 +442,8 @@ gboolean ipc_master_read( gpointer data, gint source, b_input_condition cond ) gboolean ipc_child_read( gpointer data, gint source, b_input_condition cond ) { 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 ); if( cmd ) |