source: ipc.c @ f4a5940

Last change on this file since f4a5940 was f4a5940, checked in by Wilmer van der Gaast <wilmer@…>, at 2006-01-15T20:31:59Z

Added REHASH command, IPC emulation in daemon (non-forked) mode.

  • Property mode set to 100644
File size: 6.9 KB
RevLine 
[0431ea1]1  /********************************************************************\
2  * BitlBee -- An IRC to other IM-networks gateway                     *
3  *                                                                    *
4  * Copyright 2002-2004 Wilmer van der Gaast and others                *
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"
30
31GSList *child_list = NULL;
32
[74c119d]33
[0431ea1]34static int ipc_master_cmd_die( irc_t *data, char **cmd )
35{
[74c119d]36        if( global.conf->runmode == RUNMODE_FORKDAEMON )
37                ipc_to_children_str( "DIE\r\n" );
38       
[13caf0a]39        bitlbee_shutdown( NULL );
[74c119d]40       
41        return 1;
[0431ea1]42}
43
[f4a5940]44static int ipc_master_cmd_rehash( irc_t *data, char **cmd )
[0431ea1]45{
[f4a5940]46        runmode_t oldmode;
47       
48        oldmode = global.conf->runmode;
49       
50        g_free( global.conf );
51        global.conf = conf_load( 0, NULL );
52       
53        if( global.conf->runmode != oldmode )
54        {
55                log_message( LOGLVL_WARNING, "Can't change RunMode setting at runtime, restoring original setting" );
56                global.conf->runmode = oldmode;
57        }
58       
59        if( global.conf->runmode == RUNMODE_FORKDAEMON )
60                ipc_to_children( cmd );
[0431ea1]61       
62        return 1;
63}
64
65static const command_t ipc_master_commands[] = {
66        { "die",        0, ipc_master_cmd_die,        0 },
[f4a5940]67        { "wallops",    1, NULL,                      IPC_CMD_TO_CHILDREN },
68        { "lilo",       1, NULL,                      IPC_CMD_TO_CHILDREN },
69        { "rehash",     0, ipc_master_cmd_rehash,     0 },
[0431ea1]70        { NULL }
71};
72
[74c119d]73
74static int ipc_child_cmd_die( irc_t *data, char **cmd )
75{
76        bitlbee_shutdown( NULL );
77       
78        return 1;
79}
80
[e0ca412]81static int ipc_child_cmd_wallops( irc_t *data, char **cmd )
[0431ea1]82{
83        irc_t *irc = data;
84       
85        if( strchr( irc->umode, 'w' ) )
[e0ca412]86                irc_write( irc, ":%s WALLOPS :%s", irc->myhost, cmd[1] );
87       
88        return 1;
89}
90
91static int ipc_child_cmd_lilo( irc_t *data, char **cmd )
92{
93        irc_t *irc = data;
94       
[74c119d]95        if( strchr( irc->umode, 's' ) )
96                irc_write( irc, ":%s NOTICE %s :%s", irc->myhost, irc->nick, cmd[1] );
[0431ea1]97       
98        return 1;
99}
100
[f4a5940]101static int ipc_child_cmd_rehash( irc_t *data, char **cmd )
102{
103        runmode_t oldmode;
104       
105        oldmode = global.conf->runmode;
106       
107        g_free( global.conf );
108        global.conf = conf_load( 0, NULL );
109       
110        global.conf->runmode = oldmode;
111       
112        return 1;
113}
114
[0431ea1]115static const command_t ipc_child_commands[] = {
[74c119d]116        { "die",        0, ipc_child_cmd_die,         0 },
117        { "wallops",    1, ipc_child_cmd_wallops,     0 },
118        { "lilo",       1, ipc_child_cmd_lilo,        0 },
[f4a5940]119        { "rehash",     0, ipc_child_cmd_rehash,     0 },
[0431ea1]120        { NULL }
121};
122
[74c119d]123
[0431ea1]124static void ipc_command_exec( void *data, char **cmd, const command_t *commands )
125{
126        int i;
127       
128        if( !cmd[0] )
129                return;
130       
131        for( i = 0; commands[i].command; i ++ )
132                if( g_strcasecmp( commands[i].command, cmd[0] ) == 0 )
133                {
[f4a5940]134                        if( commands[i].flags & IPC_CMD_TO_CHILDREN )
135                                ipc_to_children( cmd );
136                        else
137                                commands[i].execute( data, cmd );
138                       
[0431ea1]139                        return;
140                }
141}
142
143static char *ipc_readline( int fd )
144{
145        char *buf, *eol;
146        int size;
147       
148        buf = g_new0( char, 513 );
149       
150        /* Because this is internal communication, it should be pretty safe
151           to just peek at the message, find its length (by searching for the
152           end-of-line) and then just read that message. With internal
153           sockets and limites message length, messages should always be
154           complete. Saves us quite a lot of code and buffering. */
155        size = recv( fd, buf, 512, MSG_PEEK );
156        if( size == 0 || ( size < 0 && !sockerr_again() ) )
157                return NULL;
158        else
159                buf[size] = 0;
160       
161        eol = strstr( buf, "\r\n" );
162        if( eol == NULL )
163                return NULL;
164        else
165                size = eol - buf + 2;
166       
167        g_free( buf );
168        buf = g_new0( char, size + 1 );
169       
170        if( recv( fd, buf, size, 0 ) != size )
171                return NULL;
172        else
173                buf[size-2] = 0;
174       
175        return buf;
176}
177
178void ipc_master_read( gpointer data, gint source, GaimInputCondition cond )
179{
180        char *buf, **cmd;
181       
182        if( ( buf = ipc_readline( source ) ) )
183        {
184                cmd = irc_parse_line( buf );
185                if( cmd )
186                        ipc_command_exec( data, cmd, ipc_master_commands );
187        }
188        else
189        {
190                GSList *l;
191                struct bitlbee_child *c;
192               
193                for( l = child_list; l; l = l->next )
194                {
195                        c = l->data;
196                        if( c->ipc_fd == source )
197                        {
198                                close( c->ipc_fd );
199                                gaim_input_remove( c->ipc_inpa );
200                                g_free( c );
201                               
202                                child_list = g_slist_remove( child_list, l );
203                               
204                                break;
205                        }
206                }
207        }
208}
209
210void ipc_child_read( gpointer data, gint source, GaimInputCondition cond )
211{
212        char *buf, **cmd;
213       
214        if( ( buf = ipc_readline( source ) ) )
215        {
216                cmd = irc_parse_line( buf );
217                if( cmd )
218                        ipc_command_exec( data, cmd, ipc_child_commands );
219        }
220        else
221        {
222                gaim_input_remove( global.listen_watch_source_id );
223                close( global.listen_socket );
224               
225                global.listen_socket = -1;
226        }
227}
228
229void ipc_to_master( char **cmd )
230{
231        if( global.conf->runmode == RUNMODE_FORKDAEMON )
232        {
[74c119d]233                char *s = irc_build_line( cmd );
[f4a5940]234                ipc_to_master_str( s );
235                g_free( s );
236        }
237        else if( global.conf->runmode == RUNMODE_DAEMON )
238        {
239                ipc_command_exec( NULL, cmd, ipc_master_commands );
240        }
241}
242
243void ipc_to_master_str( char *msg_buf )
244{
245        if( global.conf->runmode == RUNMODE_FORKDAEMON )
246        {
247                write( global.listen_socket, msg_buf, strlen( msg_buf ) );
248        }
249        else if( global.conf->runmode == RUNMODE_DAEMON )
250        {
251                char *s, **cmd;
252               
253                /* irc_parse_line() wants a read-write string, so get it one: */
254                s = g_strdup( msg_buf );
255                cmd = irc_parse_line( s );
256               
257                ipc_command_exec( NULL, cmd, ipc_master_commands );
258               
259                g_free( cmd );
[74c119d]260                g_free( s );
261        }
262}
263
264void ipc_to_children( char **cmd )
265{
266        if( global.conf->runmode == RUNMODE_FORKDAEMON )
267        {
268                char *msg_buf = irc_build_line( cmd );
269                ipc_to_children_str( msg_buf );
270                g_free( msg_buf );
271        }
[f4a5940]272        else if( global.conf->runmode == RUNMODE_DAEMON )
273        {
274                GSList *l;
275               
276                for( l = irc_connection_list; l; l = l->next )
277                        ipc_command_exec( l->data, cmd, ipc_child_commands );
278        }
[74c119d]279}
280
281void ipc_to_children_str( char *msg_buf )
282{
283        if( global.conf->runmode == RUNMODE_FORKDAEMON )
284        {
285                int msg_len = strlen( msg_buf );
286                GSList *l;
[0431ea1]287               
[74c119d]288                for( l = child_list; l; l = l->next )
[0431ea1]289                {
[74c119d]290                        struct bitlbee_child *c = l->data;
291                        write( c->ipc_fd, msg_buf, msg_len );
[0431ea1]292                }
293        }
[f4a5940]294        else if( global.conf->runmode == RUNMODE_DAEMON )
295        {
296                char *s, **cmd;
297               
298                /* irc_parse_line() wants a read-write string, so get it one: */
299                s = g_strdup( msg_buf );
300                cmd = irc_parse_line( s );
301               
302                ipc_to_children( cmd );
303               
304                g_free( cmd );
305                g_free( s );
306        }
[0431ea1]307}
Note: See TracBrowser for help on using the repository browser.