Changeset 6c2404e


Ignore:
Timestamp:
2010-07-06T21:44:52Z (9 years ago)
Author:
Wilmer van der Gaast <wilmer@…>
Branches:
master
Children:
0b09da0
Parents:
006a84f
Message:

First part of the handshake, including sending a file descriptor to the
IPC master.

Files:
6 edited

Legend:

Unmodified
Added
Removed
  • bitlbee.c

    r006a84f r6c2404e  
    318318                        struct bitlbee_child *child;
    319319                       
     320                        /* TODO: Stuff like this belongs in ipc.c. */
    320321                        child = g_new0( struct bitlbee_child, 1 );
    321322                        child->pid = client_pid;
    322323                        child->ipc_fd = fds[0];
    323324                        child->ipc_inpa = b_input_add( child->ipc_fd, B_EV_IO_READ, ipc_master_read, child );
     325                        child->to_fd = -1;
    324326                        child_list = g_slist_append( child_list, child );
    325327                       
  • bitlbee.h

    r006a84f r6c2404e  
    163163void root_command_string( irc_t *irc, char *command );
    164164void root_command( irc_t *irc, char *command[] );
     165gboolean cmd_identify_finish( gpointer data, gint fd, b_input_condition cond );
    165166gboolean bitlbee_shutdown( gpointer data, gint fd, b_input_condition cond );
    166167
  • ipc.c

    r006a84f r6c2404e  
    110110        global.restart = -1;
    111111        bitlbee_shutdown( NULL, -1, 0 );
     112}
     113
     114void ipc_master_cmd_identify( irc_t *data, char **cmd )
     115{
     116        struct bitlbee_child *child = (void*) data, *old = NULL;
     117        GSList *l;
     118       
     119        if( strcmp( child->nick, cmd[1] ) != 0 )
     120                return;
     121       
     122        g_free( child->password );
     123        child->password = g_strdup( cmd[2] );
     124       
     125        for( l = child_list; l; l = l->next )
     126        {
     127                old = l->data;
     128                if( nick_cmp( old->nick, child->nick ) == 0 && child != old &&
     129                    old->password && strcmp( old->password, child->password ) )
     130                        break;
     131        }
     132       
     133        if( old == NULL )
     134                return;
     135       
     136        child->to_child = old;
    112137}
    113138
     
    123148        { "kill",       2, NULL,                      IPC_CMD_TO_CHILDREN },
    124149        { "restart",    0, ipc_master_cmd_restart,    0 },
     150        { "identify",   2, ipc_master_cmd_identify,   0 },
    125151        { NULL }
    126152};
     
    202228};
    203229
     230static gboolean ipc_send_fd( int fd, int send_fd );
     231
     232gboolean ipc_child_identify( irc_t *irc )
     233{
     234        if( global.conf->runmode == RUNMODE_FORKDAEMON )
     235        {
     236                if( !ipc_send_fd( global.listen_socket, irc->fd ) )
     237                        ipc_child_disable();
     238       
     239                ipc_to_master_str( "IDENTIFY %s :%s\r\n", irc->user->nick, irc->password );
     240               
     241                return TRUE;
     242        }
     243        else
     244                return FALSE;
     245}
    204246
    205247static void ipc_command_exec( void *data, char **cmd, const command_t *commands )
     
    230272/* Return just one line. Returns NULL if something broke, an empty string
    231273   on temporary "errors" (EAGAIN and friends). */
    232 static char *ipc_readline( int fd )
    233 {
     274static char *ipc_readline( int fd, int *recv_fd )
     275{
     276        struct msghdr msg;
     277        struct iovec iov;
     278        char ccmsg[CMSG_SPACE(sizeof(recv_fd))];
     279        struct cmsghdr *cmsg;
    234280        char buf[513], *eol;
    235281        int size;
     
    253299                size = eol - buf + 2;
    254300       
    255         if( recv( fd, buf, size, 0 ) != size )
     301        iov.iov_base = buf;
     302        iov.iov_len = size;
     303       
     304        memset( &msg, 0, sizeof( msg ) );
     305        msg.msg_iov = &iov;
     306        msg.msg_iovlen = 1;
     307        msg.msg_control = ccmsg;
     308        msg.msg_controllen = sizeof( ccmsg );
     309       
     310        if( recvmsg( fd, &msg, 0 ) != size )
    256311                return NULL;
    257         else
    258                 return g_strndup( buf, size - 2 );
     312       
     313        if( recv_fd )
     314                for( cmsg = CMSG_FIRSTHDR( &msg ); cmsg; cmsg = CMSG_NXTHDR( &msg, cmsg ) )
     315                        if( cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS )
     316                        {
     317                                /* Getting more than one shouldn't happen but if it does,
     318                                   make sure we don't leave them around. */
     319                                if( *recv_fd != -1 )
     320                                        close( *recv_fd );
     321                               
     322                                *recv_fd = *(int*) CMSG_DATA( cmsg );
     323                        }
     324       
     325        return g_strndup( buf, size - 2 );
    259326}
    260327
    261328gboolean ipc_master_read( gpointer data, gint source, b_input_condition cond )
    262329{
     330        struct bitlbee_child *child = data;
    263331        char *buf, **cmd;
    264332       
    265         if( ( buf = ipc_readline( source ) ) )
     333        if( ( buf = ipc_readline( source, &child->to_fd ) ) )
    266334        {
    267335                cmd = irc_parse_line( buf );
    268336                if( cmd )
    269337                {
    270                         ipc_command_exec( data, cmd, ipc_master_commands );
     338                        ipc_command_exec( child, cmd, ipc_master_commands );
    271339                        g_free( cmd );
    272340                }
     
    284352{
    285353        char *buf, **cmd;
    286        
    287         if( ( buf = ipc_readline( source ) ) )
     354        int recv_fd = -1;
     355       
     356        if( ( buf = ipc_readline( source, &recv_fd ) ) )
    288357        {
    289358                cmd = irc_parse_line( buf );
     
    413482}
    414483
     484static gboolean ipc_send_fd( int fd, int send_fd )
     485{
     486        struct msghdr msg;
     487        struct iovec iov;
     488        char ccmsg[CMSG_SPACE(sizeof(fd))];
     489        struct cmsghdr *cmsg;
     490       
     491        memset( &msg, 0, sizeof( msg ) );
     492        iov.iov_base = "0x90\r\n";
     493        iov.iov_len = 6;
     494        msg.msg_iov = &iov;
     495        msg.msg_iovlen = 1;
     496       
     497        msg.msg_control = ccmsg;
     498        msg.msg_controllen = sizeof( ccmsg );
     499        cmsg = CMSG_FIRSTHDR( &msg );
     500        cmsg->cmsg_level = SOL_SOCKET;
     501        cmsg->cmsg_type = SCM_RIGHTS;
     502        cmsg->cmsg_len = CMSG_LEN( sizeof( send_fd ) );
     503        *(int*)CMSG_DATA( cmsg ) = send_fd;
     504        msg.msg_controllen = cmsg->cmsg_len;
     505       
     506        return sendmsg( fd, &msg, 0 ) == 6;
     507}
     508
    415509void ipc_master_free_one( struct bitlbee_child *c )
    416510{
    417511        b_event_remove( c->ipc_inpa );
    418512        closesocket( c->ipc_fd );
     513       
     514        if( c->to_fd != -1 )
     515                close( c->to_fd );
    419516       
    420517        g_free( c->host );
    421518        g_free( c->nick );
    422519        g_free( c->realname );
     520        g_free( c->password );
    423521        g_free( c );
    424522}
     
    506604        struct bitlbee_child *child = g_new0( struct bitlbee_child, 1 );
    507605       
     606        child->to_fd = -1;
    508607        child->ipc_fd = accept( serversock, NULL, 0 );
    509        
    510608        if( child->ipc_fd == -1 )
    511609        {
     
    516614        child->ipc_inpa = b_input_add( child->ipc_fd, B_EV_IO_READ, ipc_master_read, child );
    517615       
    518         child_list = g_slist_append( child_list, child );
     616        child_list = g_slist_prepend( child_list, child );
    519617       
    520618        return TRUE;
     
    598696                }
    599697                child->ipc_inpa = b_input_add( child->ipc_fd, B_EV_IO_READ, ipc_master_read, child );
    600                
    601                 child_list = g_slist_append( child_list, child );
     698                child->to_fd = -1;
     699               
     700                child_list = g_slist_prepend( child_list, child );
    602701        }
    603702       
  • ipc.h

    r006a84f r6c2404e  
    3737        char *nick;
    3838        char *realname;
     39       
     40        char *password;
     41       
     42        /* For takeovers: */
     43        struct bitlbee_child *to_child;
     44        int to_fd;
    3945};
    4046
  • irc.h

    r006a84f r6c2404e  
    8787        gint w_watch_source_id;
    8888        gint ping_source_id;
     89        gint login_source_id; /* To slightly delay some events at login time. */
    8990       
    9091        struct bee *b;
  • root_commands.c

    r006a84f r6c2404e  
    105105{
    106106        storage_status_t status;
    107         char *account_on[] = { "account", "on", NULL };
    108107        gboolean load = TRUE;
    109108        char *password = cmd[1];
     
    158157                irc_umode_set( irc, "+R", 1 );
    159158                irc_channel_auto_joins( irc, NULL );
    160                 if( load && set_getbool( &irc->b->set, "auto_connect" ) )
    161                         cmd_account( irc, account_on );
     159               
     160                if( ipc_child_identify( irc ) )
     161                {
     162                        if( load && set_getbool( &irc->b->set, "auto_connect" ) )
     163                                irc->login_source_id = b_timeout_add( 200,
     164                                        cmd_identify_finish, irc );
     165                }
     166                else if( load && set_getbool( &irc->b->set, "auto_connect" ) )
     167                        cmd_identify_finish( irc, 0, 0 );
     168               
    162169                break;
    163170        case STORAGE_OTHER_ERROR:
     
    166173                break;
    167174        }
     175}
     176
     177gboolean cmd_identify_finish( gpointer data, gint fd, b_input_condition cond )
     178{
     179        char *account_on[] = { "account", "on", NULL };
     180        irc_t *irc = data;
     181       
     182        cmd_account( irc, account_on );
     183       
     184        return FALSE;
    168185}
    169186
     
    672689        else if( iu == irc->user )
    673690        {
    674                 irc_usermsg( irc, "Nick `%s' can't be changed", cmd[1] );
     691                irc_usermsg( irc, "Use /nick to change your own nickname" );
    675692        }
    676693        else if( !nick_ok( cmd[2] ) )
Note: See TracChangeset for help on using the changeset viewer.