Changes in / [277674c:9d6b229]


Ignore:
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • bitlbee.c

    r277674c r9d6b229  
    3333#include <errno.h>
    3434
    35 gboolean bitlbee_io_new_client( GIOChannel *source, GIOCondition condition, gpointer data )
    36 {
    37         size_t size = sizeof( struct sockaddr_in );
    38         struct sockaddr_in conn_info;
    39         int new_socket = accept( global.listen_socket, (struct sockaddr *) &conn_info, &size );
    40         pid_t client_pid = 0;
    41        
    42         if( global.conf->runmode == RUNMODE_FORKDAEMON )
    43                 client_pid = fork();
    44        
    45         if( client_pid == 0 )
    46         {
    47                 log_message( LOGLVL_INFO, "Creating new connection with fd %d.", new_socket );
    48                 irc_new( new_socket );
    49                
    50                 if( global.conf->runmode == RUNMODE_FORKDAEMON )
    51                 {
    52                         /* Close the listening socket, we're a client. */
    53                         close( global.listen_socket );
    54                         g_source_remove( global.listen_watch_source_id );
    55                 }
    56         }
    57         else
    58         {
    59                 /* We don't need this one, only the client does. */
    60                 close( new_socket );
    61                
    62                 /* Or maybe we didn't even get a child process... */
    63                 if( client_pid == -1 )
    64                         log_message( LOGLVL_ERROR, "Failed to fork() subprocess for client: %s", strerror( errno ) );
    65         }
    66        
    67         return TRUE;
    68 }
     35struct bitlbee_child
     36{
     37        pid_t pid;
     38        int ipc_fd;
     39        gint ipc_inpa;
     40};
     41
     42static GSList *child_list = NULL;
     43
     44gboolean bitlbee_io_new_client( GIOChannel *source, GIOCondition condition, gpointer data );
    6945 
    70 
    71 
    7246int bitlbee_daemon_init()
    7347{
     
    258232}
    259233
     234gboolean bitlbee_io_master_ipc_read( gpointer data, gint source, GaimInputCondition cond );
     235gboolean bitlbee_io_child_ipc_read( gpointer data, gint source, GaimInputCondition cond );
     236
     237gboolean bitlbee_io_new_client( GIOChannel *source, GIOCondition condition, gpointer data )
     238{
     239        size_t size = sizeof( struct sockaddr_in );
     240        struct sockaddr_in conn_info;
     241        int new_socket = accept( global.listen_socket, (struct sockaddr *) &conn_info, &size );
     242        pid_t client_pid = 0;
     243       
     244        if( global.conf->runmode == RUNMODE_FORKDAEMON )
     245        {
     246                int fds[2];
     247               
     248                if( socketpair( AF_UNIX, SOCK_STREAM, 0, fds ) == -1 )
     249                {
     250                        log_message( LOGLVL_WARNING, "Could not create IPC socket for client: %s", strerror( errno ) );
     251                        fds[0] = fds[1] = -1;
     252                }
     253               
     254                sock_make_nonblocking( fds[0] );
     255                sock_make_nonblocking( fds[1] );
     256               
     257                client_pid = fork();
     258               
     259                if( client_pid > 0 && fds[0] != -1 )
     260                {
     261                        struct bitlbee_child *child;
     262                       
     263                        child = g_new0( struct bitlbee_child, 1 );
     264                        child->pid = client_pid;
     265                        child->ipc_fd = fds[0];
     266                        child->ipc_inpa = gaim_input_add( child->ipc_fd, GAIM_INPUT_READ, bitlbee_io_master_ipc_read, child );
     267                        child_list = g_slist_append( child_list, child );
     268                       
     269                        close( fds[1] );
     270                }
     271                else if( client_pid == 0 )
     272                {
     273                        /* Close the listening socket, we're a client. */
     274                        close( global.listen_socket );
     275                        g_source_remove( global.listen_watch_source_id );
     276                       
     277                        /* We can store the IPC fd there now. */
     278                        global.listen_socket = fds[1];
     279                        global.listen_watch_source_id = gaim_input_add( fds[1], GAIM_INPUT_READ, bitlbee_io_child_ipc_read, NULL );
     280                       
     281                        close( fds[0] );
     282                }
     283        }
     284       
     285        if( client_pid == 0 )
     286        {
     287                log_message( LOGLVL_INFO, "Creating new connection with fd %d.", new_socket );
     288                irc_new( new_socket );
     289        }
     290        else
     291        {
     292                /* We don't need this one, only the client does. */
     293                close( new_socket );
     294        }
     295       
     296        return TRUE;
     297}
     298
    260299void bitlbee_shutdown( gpointer data )
    261300{
     
    267306        g_main_quit( global.loop );
    268307}
     308
     309gboolean bitlbee_io_master_ipc_read( gpointer data, gint source, GaimInputCondition cond )
     310{
     311        struct bitlbee_child *child = data;
     312        char buf[513], *eol;
     313        int size;
     314       
     315        size = recv( child->ipc_fd, buf, sizeof( buf ) - 1, MSG_PEEK );
     316       
     317        if( size < 0 || ( size < 0 && !sockerr_again() ) )
     318                goto error_abort;
     319        else
     320                buf[size] = 0;
     321       
     322        eol = strstr( buf, "\r\n" );
     323        if( eol == NULL )
     324                goto error_abort;
     325       
     326        size = recv( child->ipc_fd, buf, eol - buf + 2, 0 );
     327        buf[size] = 0;
     328       
     329        if( strcmp( buf, "DIE\r\n" ) == 0 )
     330        {
     331                printf( "Bye...\n" );
     332                exit( 0 );
     333        }
     334       
     335        return TRUE;
     336       
     337error_abort:
     338        {
     339                GSList *l;
     340                struct bitlbee_child *c;
     341               
     342                for( l = child_list; l; l = l->next )
     343                {
     344                        c = l->data;
     345                        if( c->ipc_fd == source )
     346                        {
     347                                close( c->ipc_fd );
     348                                gaim_input_remove( c->ipc_inpa );
     349                                g_free( c );
     350                               
     351                                child_list = g_slist_remove( child_list, l );
     352                               
     353                                break;
     354                        }
     355                }
     356               
     357                return FALSE;
     358        }
     359}
     360
     361gboolean bitlbee_io_child_ipc_read( gpointer data, gint source, GaimInputCondition cond )
     362{
     363        return TRUE;
     364}
  • bitlbee.h

    r277674c r9d6b229  
    112112#include "sock.h"
    113113
    114 typedef struct global_t {
     114typedef struct global {
     115        /* In forked mode, child processes store the fd of the IPC socket here. */
    115116        int listen_socket;
    116117        gint listen_watch_source_id;
  • irc.c

    r277674c r9d6b229  
    874874                irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS ", "END" );
    875875        }
     876        else if( g_strcasecmp( cmd[0], "DIE" ) == 0 )
     877        {
     878                printf( "%d %d\n", global.listen_socket, write( global.listen_socket, "DIE\r\n", 5 ) );
     879        }
    876880        else if( set_getint( irc, "debug" ) )
    877881        {
Note: See TracChangeset for help on using the changeset viewer.