source: ipc.c @ 6c2404e

Last change on this file since 6c2404e was 6c2404e, checked in by Wilmer van der Gaast <wilmer@…>, at 2010-07-06T21:44:52Z

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

  • Property mode set to 100644
File size: 16.8 KB
RevLine 
[0431ea1]1  /********************************************************************\
2  * BitlBee -- An IRC to other IM-networks gateway                     *
3  *                                                                    *
[54879ab]4  * Copyright 2002-2006 Wilmer van der Gaast and others                *
[0431ea1]5  \********************************************************************/
6
7/* IPC - communication between BitlBee processes                        */
8
9/*
10  This program is free software; you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation; either version 2 of the License, or
13  (at your option) any later version.
14
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  GNU General Public License for more details.
19
20  You should have received a copy of the GNU General Public License with
21  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
22  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
23  Suite 330, Boston, MA  02111-1307  USA
24*/
25
26#define BITLBEE_CORE
27#include "bitlbee.h"
28#include "ipc.h"
29#include "commands.h"
[6dff9d4]30#ifndef _WIN32
31#include <sys/un.h>
32#endif
[0431ea1]33
34GSList *child_list = NULL;
[74c119d]35
[f73b969]36static void ipc_master_cmd_client( irc_t *data, char **cmd )
[2face62]37{
[5e713f6]38        /* Normally data points at an irc_t block, but for the IPC master
39           this is different. We think this scary cast is better than
40           creating a new command_t structure, just to make the compiler
41           happy. */
[2face62]42        struct bitlbee_child *child = (void*) data;
43       
[54879ab]44        if( child && cmd[1] )
[bd9b00f]45        {
46                child->host = g_strdup( cmd[1] );
47                child->nick = g_strdup( cmd[2] );
48                child->realname = g_strdup( cmd[3] );
49        }
[2face62]50       
[54879ab]51        if( g_strcasecmp( cmd[0], "CLIENT" ) == 0 )
52                ipc_to_children_str( "OPERMSG :Client connecting (PID=%d): %s@%s (%s)\r\n",
[52744f8]53                                     (int) ( child ? child->pid : -1 ), cmd[2], cmd[1], cmd[3] );
[2face62]54}
55
[f73b969]56static void ipc_master_cmd_die( irc_t *data, char **cmd )
[0431ea1]57{
[74c119d]58        if( global.conf->runmode == RUNMODE_FORKDAEMON )
59                ipc_to_children_str( "DIE\r\n" );
60       
[ba9edaa]61        bitlbee_shutdown( NULL, -1, 0 );
[0431ea1]62}
63
[565a1ea]64static void ipc_master_cmd_deaf( irc_t *data, char **cmd )
65{
66        if( global.conf->runmode == RUNMODE_DAEMON )
67        {
68                b_event_remove( global.listen_watch_source_id );
69                close( global.listen_socket );
70               
71                global.listen_socket = global.listen_watch_source_id = -1;
72       
73                ipc_to_children_str( "OPERMSG :Closed listening socket, waiting "
74                                     "for all users to disconnect." );
75        }
76        else
77        {
78                ipc_to_children_str( "OPERMSG :The DEAF command only works in "
79                                     "normal daemon mode. Try DIE instead." );
80        }
81}
82
[f73b969]83void ipc_master_cmd_rehash( irc_t *data, char **cmd )
[0431ea1]84{
[f4a5940]85        runmode_t oldmode;
86       
87        oldmode = global.conf->runmode;
88       
89        g_free( global.conf );
90        global.conf = conf_load( 0, NULL );
91       
92        if( global.conf->runmode != oldmode )
93        {
94                log_message( LOGLVL_WARNING, "Can't change RunMode setting at runtime, restoring original setting" );
95                global.conf->runmode = oldmode;
96        }
97       
98        if( global.conf->runmode == RUNMODE_FORKDAEMON )
99                ipc_to_children( cmd );
[0431ea1]100}
101
[54879ab]102void ipc_master_cmd_restart( irc_t *data, char **cmd )
103{
104        if( global.conf->runmode != RUNMODE_FORKDAEMON )
105        {
106                /* Tell child that this is unsupported. */
107                return;
108        }
109       
110        global.restart = -1;
[ba9edaa]111        bitlbee_shutdown( NULL, -1, 0 );
[54879ab]112}
113
[6c2404e]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;
137}
138
[0431ea1]139static const command_t ipc_master_commands[] = {
[2face62]140        { "client",     3, ipc_master_cmd_client,     0 },
[54879ab]141        { "hello",      0, ipc_master_cmd_client,     0 },
[0431ea1]142        { "die",        0, ipc_master_cmd_die,        0 },
[565a1ea]143        { "deaf",       0, ipc_master_cmd_deaf,       0 },
[f4a5940]144        { "wallops",    1, NULL,                      IPC_CMD_TO_CHILDREN },
[dfc8a46]145        { "wall",       1, NULL,                      IPC_CMD_TO_CHILDREN },
[2face62]146        { "opermsg",    1, NULL,                      IPC_CMD_TO_CHILDREN },
[f4a5940]147        { "rehash",     0, ipc_master_cmd_rehash,     0 },
[48721c3]148        { "kill",       2, NULL,                      IPC_CMD_TO_CHILDREN },
[54879ab]149        { "restart",    0, ipc_master_cmd_restart,    0 },
[6c2404e]150        { "identify",   2, ipc_master_cmd_identify,   0 },
[0431ea1]151        { NULL }
152};
153
[74c119d]154
[f73b969]155static void ipc_child_cmd_die( irc_t *irc, char **cmd )
[74c119d]156{
[87de505]157        irc_abort( irc, 0, "Shutdown requested by operator" );
[74c119d]158}
159
[f73b969]160static void ipc_child_cmd_wallops( irc_t *irc, char **cmd )
[0431ea1]161{
[3af70b0]162        if( !( irc->status & USTATUS_LOGGED_IN ) )
[f73b969]163                return;
[daa9e02]164       
[0431ea1]165        if( strchr( irc->umode, 'w' ) )
[3ddb7477]166                irc_write( irc, ":%s WALLOPS :%s", irc->root->host, cmd[1] );
[e0ca412]167}
168
[dfc8a46]169static void ipc_child_cmd_wall( irc_t *irc, char **cmd )
[e0ca412]170{
[3af70b0]171        if( !( irc->status & USTATUS_LOGGED_IN ) )
[f73b969]172                return;
[daa9e02]173       
[74c119d]174        if( strchr( irc->umode, 's' ) )
[3ddb7477]175                irc_write( irc, ":%s NOTICE %s :%s", irc->root->host, irc->user->nick, cmd[1] );
[0431ea1]176}
177
[f73b969]178static void ipc_child_cmd_opermsg( irc_t *irc, char **cmd )
[2face62]179{
[3af70b0]180        if( !( irc->status & USTATUS_LOGGED_IN ) )
[f73b969]181                return;
[2face62]182       
183        if( strchr( irc->umode, 'o' ) )
[3ddb7477]184                irc_write( irc, ":%s NOTICE %s :*** OperMsg *** %s", irc->root->host, irc->user->nick, cmd[1] );
[2face62]185}
186
[f73b969]187static void ipc_child_cmd_rehash( irc_t *irc, char **cmd )
[f4a5940]188{
189        runmode_t oldmode;
190       
191        oldmode = global.conf->runmode;
192       
193        g_free( global.conf );
194        global.conf = conf_load( 0, NULL );
195       
196        global.conf->runmode = oldmode;
197}
198
[f73b969]199static void ipc_child_cmd_kill( irc_t *irc, char **cmd )
[48721c3]200{
[3af70b0]201        if( !( irc->status & USTATUS_LOGGED_IN ) )
[f73b969]202                return;
[48721c3]203       
[3ddb7477]204        if( nick_cmp( cmd[1], irc->user->nick ) != 0 )
[f73b969]205                return;         /* It's not for us. */
[48721c3]206       
[3ddb7477]207        irc_write( irc, ":%s!%s@%s KILL %s :%s", irc->root->nick, irc->root->nick, irc->root->host, irc->user->nick, cmd[2] );
[f73b969]208        irc_abort( irc, 0, "Killed by operator: %s", cmd[2] );
[48721c3]209}
210
[54879ab]211static void ipc_child_cmd_hello( irc_t *irc, char **cmd )
212{
[3af70b0]213        if( !( irc->status & USTATUS_LOGGED_IN ) )
[54879ab]214                ipc_to_master_str( "HELLO\r\n" );
215        else
[3ddb7477]216                ipc_to_master_str( "HELLO %s %s :%s\r\n", irc->user->host, irc->user->nick, irc->user->fullname );
[54879ab]217}
218
[0431ea1]219static const command_t ipc_child_commands[] = {
[74c119d]220        { "die",        0, ipc_child_cmd_die,         0 },
221        { "wallops",    1, ipc_child_cmd_wallops,     0 },
[dfc8a46]222        { "wall",       1, ipc_child_cmd_wall,        0 },
[2face62]223        { "opermsg",    1, ipc_child_cmd_opermsg,     0 },
[48721c3]224        { "rehash",     0, ipc_child_cmd_rehash,      0 },
225        { "kill",       2, ipc_child_cmd_kill,        0 },
[54879ab]226        { "hello",      0, ipc_child_cmd_hello,       0 },
[0431ea1]227        { NULL }
228};
229
[6c2404e]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}
[74c119d]246
[0431ea1]247static void ipc_command_exec( void *data, char **cmd, const command_t *commands )
248{
[f1d38f2]249        int i, j;
[0431ea1]250       
251        if( !cmd[0] )
252                return;
253       
254        for( i = 0; commands[i].command; i ++ )
255                if( g_strcasecmp( commands[i].command, cmd[0] ) == 0 )
256                {
[f1d38f2]257                        /* There is no typo in this line: */
258                        for( j = 1; cmd[j]; j ++ ); j --;
259                       
260                        if( j < commands[i].required_parameters )
261                                break;
262                       
[f4a5940]263                        if( commands[i].flags & IPC_CMD_TO_CHILDREN )
264                                ipc_to_children( cmd );
265                        else
266                                commands[i].execute( data, cmd );
267                       
[f1d38f2]268                        break;
[0431ea1]269                }
270}
271
[da7b484]272/* Return just one line. Returns NULL if something broke, an empty string
273   on temporary "errors" (EAGAIN and friends). */
[6c2404e]274static char *ipc_readline( int fd, int *recv_fd )
[0431ea1]275{
[6c2404e]276        struct msghdr msg;
277        struct iovec iov;
278        char ccmsg[CMSG_SPACE(sizeof(recv_fd))];
279        struct cmsghdr *cmsg;
[da7b484]280        char buf[513], *eol;
[0431ea1]281        int size;
282       
283        /* Because this is internal communication, it should be pretty safe
284           to just peek at the message, find its length (by searching for the
285           end-of-line) and then just read that message. With internal
286           sockets and limites message length, messages should always be
287           complete. Saves us quite a lot of code and buffering. */
[da7b484]288        size = recv( fd, buf, sizeof( buf ) - 1, MSG_PEEK );
[0431ea1]289        if( size == 0 || ( size < 0 && !sockerr_again() ) )
290                return NULL;
[1ea13be]291        else if( size < 0 ) /* && sockerr_again() */
292                return( g_strdup( "" ) );
[0431ea1]293        else
294                buf[size] = 0;
295       
[da7b484]296        if( ( eol = strstr( buf, "\r\n" ) ) == NULL )
[0431ea1]297                return NULL;
298        else
299                size = eol - buf + 2;
300       
[6c2404e]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 )
[0431ea1]311                return NULL;
[6c2404e]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 );
[0431ea1]326}
327
[ba9edaa]328gboolean ipc_master_read( gpointer data, gint source, b_input_condition cond )
[0431ea1]329{
[6c2404e]330        struct bitlbee_child *child = data;
[0431ea1]331        char *buf, **cmd;
332       
[6c2404e]333        if( ( buf = ipc_readline( source, &child->to_fd ) ) )
[0431ea1]334        {
335                cmd = irc_parse_line( buf );
336                if( cmd )
[edc767b]337                {
[6c2404e]338                        ipc_command_exec( child, cmd, ipc_master_commands );
[edc767b]339                        g_free( cmd );
340                }
341                g_free( buf );
[0431ea1]342        }
343        else
344        {
[171ef85]345                ipc_master_free_fd( source );
[0431ea1]346        }
[ba9edaa]347       
348        return TRUE;
[0431ea1]349}
350
[ba9edaa]351gboolean ipc_child_read( gpointer data, gint source, b_input_condition cond )
[0431ea1]352{
353        char *buf, **cmd;
[6c2404e]354        int recv_fd = -1;
[0431ea1]355       
[6c2404e]356        if( ( buf = ipc_readline( source, &recv_fd ) ) )
[0431ea1]357        {
358                cmd = irc_parse_line( buf );
359                if( cmd )
[edc767b]360                {
[0431ea1]361                        ipc_command_exec( data, cmd, ipc_child_commands );
[edc767b]362                        g_free( cmd );
363                }
364                g_free( buf );
[0431ea1]365        }
366        else
367        {
[171ef85]368                ipc_child_disable();
[0431ea1]369        }
[ba9edaa]370       
371        return TRUE;
[0431ea1]372}
373
374void ipc_to_master( char **cmd )
375{
376        if( global.conf->runmode == RUNMODE_FORKDAEMON )
377        {
[74c119d]378                char *s = irc_build_line( cmd );
[2face62]379                ipc_to_master_str( "%s", s );
[f4a5940]380                g_free( s );
381        }
382        else if( global.conf->runmode == RUNMODE_DAEMON )
383        {
384                ipc_command_exec( NULL, cmd, ipc_master_commands );
385        }
386}
387
[2face62]388void ipc_to_master_str( char *format, ... )
[f4a5940]389{
[2face62]390        char *msg_buf;
391        va_list params;
392
393        va_start( params, format );
394        msg_buf = g_strdup_vprintf( format, params );
395        va_end( params );
396       
397        if( strlen( msg_buf ) > 512 )
398        {
399                /* Don't send it, it's too long... */
400        }
401        else if( global.conf->runmode == RUNMODE_FORKDAEMON )
[f4a5940]402        {
[171ef85]403                if( global.listen_socket >= 0 )
404                        if( write( global.listen_socket, msg_buf, strlen( msg_buf ) ) <= 0 )
405                                ipc_child_disable();
[f4a5940]406        }
407        else if( global.conf->runmode == RUNMODE_DAEMON )
408        {
[bd9b00f]409                char **cmd, *s;
410               
411                if( ( s = strchr( msg_buf, '\r' ) ) )
412                        *s = 0;
[f4a5940]413               
[2face62]414                cmd = irc_parse_line( msg_buf );
[f4a5940]415                ipc_command_exec( NULL, cmd, ipc_master_commands );
416                g_free( cmd );
[74c119d]417        }
[2face62]418       
419        g_free( msg_buf );
[74c119d]420}
421
422void ipc_to_children( char **cmd )
423{
424        if( global.conf->runmode == RUNMODE_FORKDAEMON )
425        {
426                char *msg_buf = irc_build_line( cmd );
[2face62]427                ipc_to_children_str( "%s", msg_buf );
[74c119d]428                g_free( msg_buf );
429        }
[f4a5940]430        else if( global.conf->runmode == RUNMODE_DAEMON )
431        {
432                GSList *l;
433               
434                for( l = irc_connection_list; l; l = l->next )
435                        ipc_command_exec( l->data, cmd, ipc_child_commands );
436        }
[74c119d]437}
438
[2face62]439void ipc_to_children_str( char *format, ... )
[74c119d]440{
[2face62]441        char *msg_buf;
442        va_list params;
443
444        va_start( params, format );
445        msg_buf = g_strdup_vprintf( format, params );
446        va_end( params );
447       
448        if( strlen( msg_buf ) > 512 )
449        {
450                /* Don't send it, it's too long... */
451        }
452        else if( global.conf->runmode == RUNMODE_FORKDAEMON )
[74c119d]453        {
454                int msg_len = strlen( msg_buf );
[171ef85]455                GSList *l, *next;
[0431ea1]456               
[171ef85]457                for( l = child_list; l; l = next )
[0431ea1]458                {
[74c119d]459                        struct bitlbee_child *c = l->data;
[171ef85]460                       
461                        next = l->next;
462                        if( write( c->ipc_fd, msg_buf, msg_len ) <= 0 )
463                        {
464                                ipc_master_free_one( c );
465                                child_list = g_slist_remove( child_list, c );
466                        }
[0431ea1]467                }
468        }
[f4a5940]469        else if( global.conf->runmode == RUNMODE_DAEMON )
470        {
[bd9b00f]471                char **cmd, *s;
472               
473                if( ( s = strchr( msg_buf, '\r' ) ) )
474                        *s = 0;
[f4a5940]475               
[2face62]476                cmd = irc_parse_line( msg_buf );
[f4a5940]477                ipc_to_children( cmd );
478                g_free( cmd );
479        }
[2face62]480       
481        g_free( msg_buf );
482}
483
[6c2404e]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
[2face62]509void ipc_master_free_one( struct bitlbee_child *c )
510{
[ba9edaa]511        b_event_remove( c->ipc_inpa );
[2face62]512        closesocket( c->ipc_fd );
513       
[6c2404e]514        if( c->to_fd != -1 )
515                close( c->to_fd );
516       
[2face62]517        g_free( c->host );
518        g_free( c->nick );
519        g_free( c->realname );
[6c2404e]520        g_free( c->password );
[2face62]521        g_free( c );
522}
523
[171ef85]524void ipc_master_free_fd( int fd )
525{
526        GSList *l;
527        struct bitlbee_child *c;
528       
529        for( l = child_list; l; l = l->next )
530        {
531                c = l->data;
532                if( c->ipc_fd == fd )
533                {
534                        ipc_master_free_one( c );
535                        child_list = g_slist_remove( child_list, c );
536                        break;
537                }
538        }
539}
540
[2face62]541void ipc_master_free_all()
542{
543        GSList *l;
544       
545        for( l = child_list; l; l = l->next )
546                ipc_master_free_one( l->data );
547       
548        g_slist_free( child_list );
549        child_list = NULL;
[0431ea1]550}
[54879ab]551
[171ef85]552void ipc_child_disable()
553{
554        b_event_remove( global.listen_watch_source_id );
555        close( global.listen_socket );
556       
557        global.listen_socket = -1;
558}
559
[80c1e4d]560#ifndef _WIN32
[54879ab]561char *ipc_master_save_state()
562{
563        char *fn = g_strdup( "/tmp/bee-restart.XXXXXX" );
564        int fd = mkstemp( fn );
565        GSList *l;
566        FILE *fp;
567        int i;
568       
569        if( fd == -1 )
570        {
571                log_message( LOGLVL_ERROR, "Could not create temporary file: %s", strerror( errno ) );
572                g_free( fn );
573                return NULL;
574        }
575       
576        /* This is more convenient now. */
577        fp = fdopen( fd, "w" );
578       
579        for( l = child_list, i = 0; l; l = l->next )
580                i ++;
581       
582        /* Number of client processes. */
583        fprintf( fp, "%d\n", i );
584       
585        for( l = child_list; l; l = l->next )
[52744f8]586                fprintf( fp, "%d %d\n", (int) ((struct bitlbee_child*)l->data)->pid,
[54879ab]587                                        ((struct bitlbee_child*)l->data)->ipc_fd );
588       
589        if( fclose( fp ) == 0 )
590        {
591                return fn;
592        }
593        else
594        {
595                unlink( fn );
596                g_free( fn );
597                return NULL;
598        }
599}
600
[6dff9d4]601
[ba9edaa]602static gboolean new_ipc_client( gpointer data, gint serversock, b_input_condition cond )
[6dff9d4]603{
604        struct bitlbee_child *child = g_new0( struct bitlbee_child, 1 );
[a0d04d6]605       
[6c2404e]606        child->to_fd = -1;
[a0d04d6]607        child->ipc_fd = accept( serversock, NULL, 0 );
608        if( child->ipc_fd == -1 )
609        {
[8a56e52]610                log_message( LOGLVL_WARNING, "Unable to accept connection on UNIX domain socket: %s", strerror(errno) );
611                return TRUE;
612        }
[6dff9d4]613               
[e046390]614        child->ipc_inpa = b_input_add( child->ipc_fd, B_EV_IO_READ, ipc_master_read, child );
[a0d04d6]615       
[6c2404e]616        child_list = g_slist_prepend( child_list, child );
[ba9edaa]617       
[6dff9d4]618        return TRUE;
619}
620
621int ipc_master_listen_socket()
622{
623        struct sockaddr_un un_addr;
624        int serversock;
625
626        /* Clean up old socket files that were hanging around.. */
[8a56e52]627        if (unlink(IPCSOCKET) == -1 && errno != ENOENT) {
628                log_message( LOGLVL_ERROR, "Could not remove old IPC socket at %s: %s", IPCSOCKET, strerror(errno) );
629                return 0;
630        }
[6dff9d4]631
632        un_addr.sun_family = AF_UNIX;
633        strcpy(un_addr.sun_path, IPCSOCKET);
634
635        serversock = socket(AF_UNIX, SOCK_STREAM, PF_UNIX);
636
[8a56e52]637        if (serversock == -1) {
638                log_message( LOGLVL_WARNING, "Unable to create UNIX socket: %s", strerror(errno) );
639                return 0;
640        }
[6dff9d4]641
[5d6c178]642        if (bind(serversock, (struct sockaddr *)&un_addr, sizeof(un_addr)) == -1) {
[8a56e52]643                log_message( LOGLVL_WARNING, "Unable to bind UNIX socket to %s: %s", IPCSOCKET, strerror(errno) );
644                return 0;
645        }
646
647        if (listen(serversock, 5) == -1) {
648                log_message( LOGLVL_WARNING, "Unable to listen on UNIX socket: %s", strerror(errno) );
649                return 0;
650        }
[6dff9d4]651       
[e046390]652        b_input_add( serversock, B_EV_IO_READ, new_ipc_client, NULL );
[8a56e52]653       
[6dff9d4]654        return 1;
655}
656#else
[1cda4f3]657int ipc_master_listen_socket()
658{
[6dff9d4]659        /* FIXME: Open named pipe \\.\BITLBEE */
[1cda4f3]660        return 0;
661}
[6dff9d4]662#endif
663
[cd63d58]664int ipc_master_load_state( char *statefile )
[54879ab]665{
666        struct bitlbee_child *child;
667        FILE *fp;
668        int i, n;
669       
670        if( statefile == NULL )
671                return 0;
[cd63d58]672       
[54879ab]673        fp = fopen( statefile, "r" );
674        unlink( statefile );    /* Why do it later? :-) */
675        if( fp == NULL )
676                return 0;
677       
678        if( fscanf( fp, "%d", &n ) != 1 )
679        {
680                log_message( LOGLVL_WARNING, "Could not import state information for child processes." );
681                fclose( fp );
682                return 0;
683        }
684       
685        log_message( LOGLVL_INFO, "Importing information for %d child processes.", n );
686        for( i = 0; i < n; i ++ )
687        {
688                child = g_new0( struct bitlbee_child, 1 );
689               
[52744f8]690                if( fscanf( fp, "%d %d", (int *) &child->pid, &child->ipc_fd ) != 2 )
[54879ab]691                {
692                        log_message( LOGLVL_WARNING, "Unexpected end of file: Only processed %d clients.", i );
693                        g_free( child );
694                        fclose( fp );
695                        return 0;
696                }
[e046390]697                child->ipc_inpa = b_input_add( child->ipc_fd, B_EV_IO_READ, ipc_master_read, child );
[6c2404e]698                child->to_fd = -1;
[54879ab]699               
[6c2404e]700                child_list = g_slist_prepend( child_list, child );
[54879ab]701        }
702       
703        ipc_to_children_str( "HELLO\r\n" );
704        ipc_to_children_str( "OPERMSG :New BitlBee master process started (version " BITLBEE_VERSION ")\r\n" );
705       
[dd89a55]706        fclose( fp );
[54879ab]707        return 1;
708}
Note: See TracBrowser for help on using the repository browser.