source: ipc.c @ 4c266f2

Last change on this file since 4c266f2 was 4c266f2, checked in by Wilmer van der Gaast <wilmer@…>, at 2006-01-18T22:17:59Z

Merged (and adapted) changes from main tree.

  • Property mode set to 100644
File size: 7.5 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
[48721c3]34static int ipc_master_cmd_die( irc_t *irc, char **cmd )
[0431ea1]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
[48721c3]44static int ipc_master_cmd_rehash( irc_t *irc, 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 },
[48721c3]70        { "kill",       2, NULL,                      IPC_CMD_TO_CHILDREN },
[0431ea1]71        { NULL }
72};
73
[74c119d]74
[48721c3]75static int ipc_child_cmd_die( irc_t *irc, char **cmd )
[74c119d]76{
77        bitlbee_shutdown( NULL );
78       
79        return 1;
80}
81
[48721c3]82static int ipc_child_cmd_wallops( irc_t *irc, char **cmd )
[0431ea1]83{
[daa9e02]84        if( irc->status < USTATUS_LOGGED_IN )
85                return 1;
86       
[0431ea1]87        if( strchr( irc->umode, 'w' ) )
[e0ca412]88                irc_write( irc, ":%s WALLOPS :%s", irc->myhost, cmd[1] );
89       
90        return 1;
91}
92
[48721c3]93static int ipc_child_cmd_lilo( irc_t *irc, char **cmd )
[e0ca412]94{
[daa9e02]95        if( irc->status < USTATUS_LOGGED_IN )
96                return 1;
97       
[74c119d]98        if( strchr( irc->umode, 's' ) )
99                irc_write( irc, ":%s NOTICE %s :%s", irc->myhost, irc->nick, cmd[1] );
[0431ea1]100       
101        return 1;
102}
103
[48721c3]104static int ipc_child_cmd_rehash( irc_t *irc, char **cmd )
[f4a5940]105{
106        runmode_t oldmode;
107       
108        oldmode = global.conf->runmode;
109       
110        g_free( global.conf );
111        global.conf = conf_load( 0, NULL );
112       
113        global.conf->runmode = oldmode;
114       
115        return 1;
116}
117
[48721c3]118static int ipc_child_cmd_kill( irc_t *irc, char **cmd )
119{
120        if( irc->status < USTATUS_LOGGED_IN )
121                return 1;
122       
123        if( nick_cmp( cmd[1], irc->nick ) != 0 )
124                return 1;       /* It's not for us. */
125       
126        irc_write( irc, ":%s!%s@%s KILL %s :%s", irc->mynick, irc->mynick, irc->myhost, irc->nick, cmd[2] );
[4c266f2]127        irc_abort( irc );
128        /* g_io_channel_close( irc->io_channel ); */
[48721c3]129       
130        return 0;
131}
132
[0431ea1]133static const command_t ipc_child_commands[] = {
[74c119d]134        { "die",        0, ipc_child_cmd_die,         0 },
135        { "wallops",    1, ipc_child_cmd_wallops,     0 },
136        { "lilo",       1, ipc_child_cmd_lilo,        0 },
[48721c3]137        { "rehash",     0, ipc_child_cmd_rehash,      0 },
138        { "kill",       2, ipc_child_cmd_kill,        0 },
[0431ea1]139        { NULL }
140};
141
[74c119d]142
[0431ea1]143static void ipc_command_exec( void *data, char **cmd, const command_t *commands )
144{
145        int i;
146       
147        if( !cmd[0] )
148                return;
149       
150        for( i = 0; commands[i].command; i ++ )
151                if( g_strcasecmp( commands[i].command, cmd[0] ) == 0 )
152                {
[f4a5940]153                        if( commands[i].flags & IPC_CMD_TO_CHILDREN )
154                                ipc_to_children( cmd );
155                        else
156                                commands[i].execute( data, cmd );
157                       
[0431ea1]158                        return;
159                }
160}
161
162static char *ipc_readline( int fd )
163{
164        char *buf, *eol;
165        int size;
166       
167        buf = g_new0( char, 513 );
168       
169        /* Because this is internal communication, it should be pretty safe
170           to just peek at the message, find its length (by searching for the
171           end-of-line) and then just read that message. With internal
172           sockets and limites message length, messages should always be
173           complete. Saves us quite a lot of code and buffering. */
174        size = recv( fd, buf, 512, MSG_PEEK );
175        if( size == 0 || ( size < 0 && !sockerr_again() ) )
176                return NULL;
[1ea13be]177        else if( size < 0 ) /* && sockerr_again() */
178                return( g_strdup( "" ) );
[0431ea1]179        else
180                buf[size] = 0;
181       
182        eol = strstr( buf, "\r\n" );
183        if( eol == NULL )
184                return NULL;
185        else
186                size = eol - buf + 2;
187       
188        g_free( buf );
189        buf = g_new0( char, size + 1 );
190       
191        if( recv( fd, buf, size, 0 ) != size )
192                return NULL;
193        else
194                buf[size-2] = 0;
195       
196        return buf;
197}
198
199void ipc_master_read( gpointer data, gint source, GaimInputCondition cond )
200{
201        char *buf, **cmd;
202       
203        if( ( buf = ipc_readline( source ) ) )
204        {
205                cmd = irc_parse_line( buf );
206                if( cmd )
207                        ipc_command_exec( data, cmd, ipc_master_commands );
208        }
209        else
210        {
211                GSList *l;
212                struct bitlbee_child *c;
213               
214                for( l = child_list; l; l = l->next )
215                {
216                        c = l->data;
217                        if( c->ipc_fd == source )
218                        {
219                                close( c->ipc_fd );
220                                gaim_input_remove( c->ipc_inpa );
221                                g_free( c );
222                               
223                                child_list = g_slist_remove( child_list, l );
224                               
225                                break;
226                        }
227                }
228        }
229}
230
231void ipc_child_read( gpointer data, gint source, GaimInputCondition cond )
232{
233        char *buf, **cmd;
234       
235        if( ( buf = ipc_readline( source ) ) )
236        {
237                cmd = irc_parse_line( buf );
238                if( cmd )
239                        ipc_command_exec( data, cmd, ipc_child_commands );
240        }
241        else
242        {
243                gaim_input_remove( global.listen_watch_source_id );
244                close( global.listen_socket );
245               
246                global.listen_socket = -1;
247        }
248}
249
250void ipc_to_master( char **cmd )
251{
252        if( global.conf->runmode == RUNMODE_FORKDAEMON )
253        {
[74c119d]254                char *s = irc_build_line( cmd );
[f4a5940]255                ipc_to_master_str( s );
256                g_free( s );
257        }
258        else if( global.conf->runmode == RUNMODE_DAEMON )
259        {
260                ipc_command_exec( NULL, cmd, ipc_master_commands );
261        }
262}
263
264void ipc_to_master_str( char *msg_buf )
265{
266        if( global.conf->runmode == RUNMODE_FORKDAEMON )
267        {
268                write( global.listen_socket, msg_buf, strlen( msg_buf ) );
269        }
270        else if( global.conf->runmode == RUNMODE_DAEMON )
271        {
272                char *s, **cmd;
273               
274                /* irc_parse_line() wants a read-write string, so get it one: */
275                s = g_strdup( msg_buf );
276                cmd = irc_parse_line( s );
277               
278                ipc_command_exec( NULL, cmd, ipc_master_commands );
279               
280                g_free( cmd );
[74c119d]281                g_free( s );
282        }
283}
284
285void ipc_to_children( char **cmd )
286{
287        if( global.conf->runmode == RUNMODE_FORKDAEMON )
288        {
289                char *msg_buf = irc_build_line( cmd );
290                ipc_to_children_str( msg_buf );
291                g_free( msg_buf );
292        }
[f4a5940]293        else if( global.conf->runmode == RUNMODE_DAEMON )
294        {
295                GSList *l;
296               
297                for( l = irc_connection_list; l; l = l->next )
298                        ipc_command_exec( l->data, cmd, ipc_child_commands );
299        }
[74c119d]300}
301
302void ipc_to_children_str( char *msg_buf )
303{
304        if( global.conf->runmode == RUNMODE_FORKDAEMON )
305        {
306                int msg_len = strlen( msg_buf );
307                GSList *l;
[0431ea1]308               
[74c119d]309                for( l = child_list; l; l = l->next )
[0431ea1]310                {
[74c119d]311                        struct bitlbee_child *c = l->data;
312                        write( c->ipc_fd, msg_buf, msg_len );
[0431ea1]313                }
314        }
[f4a5940]315        else if( global.conf->runmode == RUNMODE_DAEMON )
316        {
317                char *s, **cmd;
318               
319                /* irc_parse_line() wants a read-write string, so get it one: */
320                s = g_strdup( msg_buf );
321                cmd = irc_parse_line( s );
322               
323                ipc_to_children( cmd );
324               
325                g_free( cmd );
326                g_free( s );
327        }
[0431ea1]328}
Note: See TracBrowser for help on using the repository browser.