source: ipc.c @ 0431ea1

Last change on this file since 0431ea1 was 0431ea1, checked in by Wilmer van der Gaast <wilmer@…>, at 2006-01-15T01:49:49Z

Imported irc_command branch and used this addition for parsing IPC commands. (Implemented WALLOP and a very evil DIE.)

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