source: ipc.c @ e0ca412

Last change on this file since e0ca412 was e0ca412, checked in by Wilmer van der Gaast <wilmer@…>, at 2006-01-15T11:33:54Z

s/WALLOP/WALLOPS/, added LILO command.

  • Property mode set to 100644
File size: 5.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
33static int ipc_master_cmd_die( irc_t *data, char **cmd )
34{
35        /* This shouldn't really be the final implementation... */
36        exit( 0 );
37}
38
39static int ipc_master_cmd_wallops( irc_t *data, char **cmd )
40{
41        GSList *l;
42        char msg_buf[513];
43        int msg_len;
44       
45        if( ( msg_len = g_snprintf( msg_buf, sizeof( msg_buf ) - 1, "%s :%s\r\n", cmd[0], cmd[1] ) ) > ( sizeof( msg_buf ) - 1 ) )
46                return 0;
47       
48        for( l = child_list; l; l = l->next )
49        {
50                struct bitlbee_child *c = l->data;
51                write( c->ipc_fd, msg_buf, msg_len );
52        }
53       
54        return 1;
55}
56
57static const command_t ipc_master_commands[] = {
58        { "die",        0, ipc_master_cmd_die,        0 },
59        { "wallops",    1, ipc_master_cmd_wallops,    1 },
60        { "lilo",       1, ipc_master_cmd_wallops,    1 },
61        { NULL }
62};
63
64static int ipc_child_cmd_wallops( irc_t *data, char **cmd )
65{
66        irc_t *irc = data;
67       
68        if( strchr( irc->umode, 'w' ) )
69                irc_write( irc, ":%s WALLOPS :%s", irc->myhost, cmd[1] );
70       
71        return 1;
72}
73
74static int ipc_child_cmd_lilo( irc_t *data, char **cmd )
75{
76        irc_t *irc = data;
77       
78        irc_write( irc, ":%s NOTICE %s :%s", irc->myhost, irc->nick, cmd[1] );
79       
80        return 1;
81}
82
83static const command_t ipc_child_commands[] = {
84        { "wallops",    1, ipc_child_cmd_wallops,     1 },
85        { "lilo",       1, ipc_child_cmd_lilo,        1 },
86        { NULL }
87};
88
89static void ipc_command_exec( void *data, char **cmd, const command_t *commands )
90{
91        int i;
92       
93        if( !cmd[0] )
94                return;
95       
96        for( i = 0; commands[i].command; i ++ )
97                if( g_strcasecmp( commands[i].command, cmd[0] ) == 0 )
98                {
99                        commands[i].execute( data, cmd );
100                        return;
101                }
102}
103
104static char *ipc_readline( int fd )
105{
106        char *buf, *eol;
107        int size;
108       
109        buf = g_new0( char, 513 );
110       
111        /* Because this is internal communication, it should be pretty safe
112           to just peek at the message, find its length (by searching for the
113           end-of-line) and then just read that message. With internal
114           sockets and limites message length, messages should always be
115           complete. Saves us quite a lot of code and buffering. */
116        size = recv( fd, buf, 512, MSG_PEEK );
117        if( size == 0 || ( size < 0 && !sockerr_again() ) )
118                return NULL;
119        else
120                buf[size] = 0;
121       
122        eol = strstr( buf, "\r\n" );
123        if( eol == NULL )
124                return NULL;
125        else
126                size = eol - buf + 2;
127       
128        g_free( buf );
129        buf = g_new0( char, size + 1 );
130       
131        if( recv( fd, buf, size, 0 ) != size )
132                return NULL;
133        else
134                buf[size-2] = 0;
135       
136        return buf;
137}
138
139void ipc_master_read( gpointer data, gint source, GaimInputCondition cond )
140{
141        char *buf, **cmd;
142       
143        if( ( buf = ipc_readline( source ) ) )
144        {
145                cmd = irc_parse_line( buf );
146                if( cmd )
147                        ipc_command_exec( data, cmd, ipc_master_commands );
148        }
149        else
150        {
151                GSList *l;
152                struct bitlbee_child *c;
153               
154                for( l = child_list; l; l = l->next )
155                {
156                        c = l->data;
157                        if( c->ipc_fd == source )
158                        {
159                                close( c->ipc_fd );
160                                gaim_input_remove( c->ipc_inpa );
161                                g_free( c );
162                               
163                                child_list = g_slist_remove( child_list, l );
164                               
165                                break;
166                        }
167                }
168        }
169}
170
171void ipc_child_read( gpointer data, gint source, GaimInputCondition cond )
172{
173        char *buf, **cmd;
174       
175        if( ( buf = ipc_readline( source ) ) )
176        {
177                cmd = irc_parse_line( buf );
178                if( cmd )
179                        ipc_command_exec( data, cmd, ipc_child_commands );
180        }
181        else
182        {
183                gaim_input_remove( global.listen_watch_source_id );
184                close( global.listen_socket );
185               
186                global.listen_socket = -1;
187        }
188}
189
190void ipc_to_master( char **cmd )
191{
192        if( global.conf->runmode == RUNMODE_FORKDAEMON )
193        {
194                int i, len;
195                char *s;
196               
197                len = 1;
198                for( i = 0; cmd[i]; i ++ )
199                        len += strlen( cmd[i] ) + 1;
200               
201                if( strchr( cmd[i-1], ' ' ) != NULL )
202                        len ++;
203               
204                s = g_new0( char, len + 1 );
205                for( i = 0; cmd[i]; i ++ )
206                {
207                        if( cmd[i+1] == NULL && strchr( cmd[i], ' ' ) != NULL )
208                                strcat( s, ":" );
209                       
210                        strcat( s, cmd[i] );
211                       
212                        if( cmd[i+1] )
213                                strcat( s, " " );
214                }
215                strcat( s, "\r\n" );
216               
217                write( global.listen_socket, s, len );
218        }
219}
Note: See TracBrowser for help on using the repository browser.