source: ipc.c @ daa9e02

Last change on this file since daa9e02 was daa9e02, checked in by Wilmer van der Gaast <wilmer@…>, at 2006-01-17T18:05:22Z

LILO/WALLOPS commands now check if the receiving user logged in yet.

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