aboutsummaryrefslogtreecommitdiffstats
path: root/ipc.c
diff options
context:
space:
mode:
authorSven Moritz Hallberg <pesco@khjk.org>2008-07-17 01:22:52 +0200
committerSven Moritz Hallberg <pesco@khjk.org>2008-07-17 01:22:52 +0200
commit6738a676c7a3895988de4bd9eacfe8fa0ef73cc3 (patch)
treed95d913484cf79ff4a3c6d920a4d9b92ecd66de9 /ipc.c
parent9730d7250bb9e938ca00b72efdd8e8b3c03b2753 (diff)
parent6a78c0eed44820a2fefe1e96516e335eddc9c70b (diff)
merge in latest trunk
Diffstat (limited to 'ipc.c')
-rw-r--r--ipc.c121
1 files changed, 80 insertions, 41 deletions
diff --git a/ipc.c b/ipc.c
index 384a9c33..d6b850f1 100644
--- a/ipc.c
+++ b/ipc.c
@@ -32,7 +32,6 @@
#endif
GSList *child_list = NULL;
-static char *statefile = NULL;
static void ipc_master_cmd_client( irc_t *data, char **cmd )
{
@@ -62,6 +61,25 @@ static void ipc_master_cmd_die( irc_t *data, char **cmd )
bitlbee_shutdown( NULL, -1, 0 );
}
+static void ipc_master_cmd_deaf( irc_t *data, char **cmd )
+{
+ if( global.conf->runmode == RUNMODE_DAEMON )
+ {
+ b_event_remove( global.listen_watch_source_id );
+ close( global.listen_socket );
+
+ global.listen_socket = global.listen_watch_source_id = -1;
+
+ ipc_to_children_str( "OPERMSG :Closed listening socket, waiting "
+ "for all users to disconnect." );
+ }
+ else
+ {
+ ipc_to_children_str( "OPERMSG :The DEAF command only works in "
+ "normal daemon mode. Try DIE instead." );
+ }
+}
+
void ipc_master_cmd_rehash( irc_t *data, char **cmd )
{
runmode_t oldmode;
@@ -97,6 +115,7 @@ static const command_t ipc_master_commands[] = {
{ "client", 3, ipc_master_cmd_client, 0 },
{ "hello", 0, ipc_master_cmd_client, 0 },
{ "die", 0, ipc_master_cmd_die, 0 },
+ { "deaf", 0, ipc_master_cmd_deaf, 0 },
{ "wallops", 1, NULL, IPC_CMD_TO_CHILDREN },
{ "wall", 1, NULL, IPC_CMD_TO_CHILDREN },
{ "opermsg", 1, NULL, IPC_CMD_TO_CHILDREN },
@@ -208,19 +227,19 @@ static void ipc_command_exec( void *data, char **cmd, const command_t *commands
}
}
+/* Return just one line. Returns NULL if something broke, an empty string
+ on temporary "errors" (EAGAIN and friends). */
static char *ipc_readline( int fd )
{
- char *buf, *eol;
+ char buf[513], *eol;
int size;
- buf = g_new0( char, 513 );
-
/* Because this is internal communication, it should be pretty safe
to just peek at the message, find its length (by searching for the
end-of-line) and then just read that message. With internal
sockets and limites message length, messages should always be
complete. Saves us quite a lot of code and buffering. */
- size = recv( fd, buf, 512, MSG_PEEK );
+ size = recv( fd, buf, sizeof( buf ) - 1, MSG_PEEK );
if( size == 0 || ( size < 0 && !sockerr_again() ) )
return NULL;
else if( size < 0 ) /* && sockerr_again() */
@@ -228,21 +247,15 @@ static char *ipc_readline( int fd )
else
buf[size] = 0;
- eol = strstr( buf, "\r\n" );
- if( eol == NULL )
+ if( ( eol = strstr( buf, "\r\n" ) ) == NULL )
return NULL;
else
size = eol - buf + 2;
- g_free( buf );
- buf = g_new0( char, size + 1 );
-
if( recv( fd, buf, size, 0 ) != size )
return NULL;
else
- buf[size-2] = 0;
-
- return buf;
+ return g_strndup( buf, size - 2 );
}
gboolean ipc_master_read( gpointer data, gint source, b_input_condition cond )
@@ -253,23 +266,15 @@ gboolean ipc_master_read( gpointer data, gint source, b_input_condition cond )
{
cmd = irc_parse_line( buf );
if( cmd )
+ {
ipc_command_exec( data, cmd, ipc_master_commands );
+ g_free( cmd );
+ }
+ g_free( buf );
}
else
{
- GSList *l;
- struct bitlbee_child *c;
-
- for( l = child_list; l; l = l->next )
- {
- c = l->data;
- if( c->ipc_fd == source )
- {
- ipc_master_free_one( c );
- child_list = g_slist_remove( child_list, c );
- break;
- }
- }
+ ipc_master_free_fd( source );
}
return TRUE;
@@ -283,14 +288,15 @@ gboolean ipc_child_read( gpointer data, gint source, b_input_condition cond )
{
cmd = irc_parse_line( buf );
if( cmd )
+ {
ipc_command_exec( data, cmd, ipc_child_commands );
+ g_free( cmd );
+ }
+ g_free( buf );
}
else
{
- b_event_remove( global.listen_watch_source_id );
- close( global.listen_socket );
-
- global.listen_socket = -1;
+ ipc_child_disable();
}
return TRUE;
@@ -325,7 +331,9 @@ void ipc_to_master_str( char *format, ... )
}
else if( global.conf->runmode == RUNMODE_FORKDAEMON )
{
- write( global.listen_socket, msg_buf, strlen( msg_buf ) );
+ if( global.listen_socket >= 0 )
+ if( write( global.listen_socket, msg_buf, strlen( msg_buf ) ) <= 0 )
+ ipc_child_disable();
}
else if( global.conf->runmode == RUNMODE_DAEMON )
{
@@ -375,12 +383,18 @@ void ipc_to_children_str( char *format, ... )
else if( global.conf->runmode == RUNMODE_FORKDAEMON )
{
int msg_len = strlen( msg_buf );
- GSList *l;
+ GSList *l, *next;
- for( l = child_list; l; l = l->next )
+ for( l = child_list; l; l = next )
{
struct bitlbee_child *c = l->data;
- write( c->ipc_fd, msg_buf, msg_len );
+
+ next = l->next;
+ if( write( c->ipc_fd, msg_buf, msg_len ) <= 0 )
+ {
+ ipc_master_free_one( c );
+ child_list = g_slist_remove( child_list, c );
+ }
}
}
else if( global.conf->runmode == RUNMODE_DAEMON )
@@ -409,6 +423,23 @@ void ipc_master_free_one( struct bitlbee_child *c )
g_free( c );
}
+void ipc_master_free_fd( int fd )
+{
+ GSList *l;
+ struct bitlbee_child *c;
+
+ for( l = child_list; l; l = l->next )
+ {
+ c = l->data;
+ if( c->ipc_fd == fd )
+ {
+ ipc_master_free_one( c );
+ child_list = g_slist_remove( child_list, c );
+ break;
+ }
+ }
+}
+
void ipc_master_free_all()
{
GSList *l;
@@ -420,6 +451,15 @@ void ipc_master_free_all()
child_list = NULL;
}
+void ipc_child_disable()
+{
+ b_event_remove( global.listen_watch_source_id );
+ close( global.listen_socket );
+
+ global.listen_socket = -1;
+}
+
+#ifndef _WIN32
char *ipc_master_save_state()
{
char *fn = g_strdup( "/tmp/bee-restart.XXXXXX" );
@@ -460,11 +500,6 @@ char *ipc_master_save_state()
}
}
-void ipc_master_set_statefile( char *fn )
-{
- statefile = g_strdup( fn );
-}
-
static gboolean new_ipc_client( gpointer data, gint serversock, b_input_condition cond )
{
@@ -485,7 +520,6 @@ static gboolean new_ipc_client( gpointer data, gint serversock, b_input_conditio
return TRUE;
}
-#ifndef _WIN32
int ipc_master_listen_socket()
{
struct sockaddr_un un_addr;
@@ -522,10 +556,14 @@ int ipc_master_listen_socket()
return 1;
}
#else
+int ipc_master_listen_socket()
+{
/* FIXME: Open named pipe \\.\BITLBEE */
+ return 0;
+}
#endif
-int ipc_master_load_state()
+int ipc_master_load_state( char *statefile )
{
struct bitlbee_child *child;
FILE *fp;
@@ -533,6 +571,7 @@ int ipc_master_load_state()
if( statefile == NULL )
return 0;
+
fp = fopen( statefile, "r" );
unlink( statefile ); /* Why do it later? :-) */
if( fp == NULL )