summaryrefslogtreecommitdiffstats
path: root/dcopc/dcopc.c
diff options
context:
space:
mode:
Diffstat (limited to 'dcopc/dcopc.c')
-rw-r--r--dcopc/dcopc.c1579
1 files changed, 1579 insertions, 0 deletions
diff --git a/dcopc/dcopc.c b/dcopc/dcopc.c
new file mode 100644
index 00000000..fcb51e2b
--- /dev/null
+++ b/dcopc/dcopc.c
@@ -0,0 +1,1579 @@
+/*
+Copyright (c) 2000 Simon Hausmann <hausmann@kde.org>
+Copyright (c) 2000 Lars Knoll <knoll@kde.org>
+Copyright (c) 1999 Preston Brown <pbrown@kde.org>
+Copyright (c) 1999, 2000 Matthias Ettrich <ettrich@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include <config.h>
+
+#include "global.h"
+#include "dcopc.h"
+#include "dcopobject.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <ctype.h>
+
+typedef struct _DcopClientMessage DcopClientMessage;
+
+struct _DcopClientMessage
+{
+ int opcode;
+ CARD32 key;
+ dcop_data *data;
+};
+
+typedef struct _DcopClientPrivate DcopClientPrivate;
+
+struct _DcopClientPrivate
+{
+ gchar *app_id;
+ IceConn ice_conn;
+ gint major_opcode;
+ gint major_version, minor_version;
+ gchar *vendor, *release;
+ gboolean registered;
+ gchar *sender_id;
+
+ gchar *default_object;
+
+ CARD32 key;
+ CARD32 current_key;
+
+ GList *transaction_list;
+ gboolean transaction;
+ gint32 transaction_id;
+
+ int opcode;
+
+ guint post_message_timer;
+ GList *messages;
+};
+
+struct _DcopClientTransaction
+{
+ gint32 id;
+ CARD32 key;
+ gchar *sender_id;
+};
+
+int DCOPAuthCount = 1;
+const char *DCOPAuthNames[] = {"MIT-MAGIC-COOKIE-1"};
+
+extern IcePoAuthStatus _IcePoMagicCookie1Proc (IceConn, void **, int, int, int, void *, int *, void **, char **);
+extern IcePaAuthStatus _IcePaMagicCookie1Proc (IceConn, void **, int, int, void *, int *, void **, char **);
+
+IcePoAuthProc DCOPClientAuthProcs[] = {_IcePoMagicCookie1Proc};
+IcePaAuthProc DCOPServerAuthProcs[] = {_IcePaMagicCookie1Proc};
+
+enum reply_status
+{ Pending, Ok, Rejected, Failed };
+
+typedef struct _reply_struct reply_struct;
+
+struct _reply_struct
+{
+ gint status;
+ gchar **reply_type;
+ dcop_data **reply_data;
+ guint reply_id;
+};
+
+static void reply_struct_init( reply_struct *s )
+{
+ s->status = Pending;
+ s->reply_type = 0;
+ s->reply_data = 0;
+ s->reply_id = 0;
+}
+
+#define P ((DcopClientPrivate *)(client->priv))
+#define ERR( emsg ) \
+ { \
+ if ( dcop_client_free_error_msg ) \
+ g_free( dcop_client_error_msg ); \
+ dcop_client_error_msg = (gchar *)emsg; \
+ dcop_client_free_error_msg = FALSE; \
+ }
+
+#define CLIENT_CLASS(obj) DCOP_CLIENT_CLASS(GTK_OBJECT(obj)->klass)
+
+static gchar *dcop_client_server_address = 0;
+static gchar *dcop_client_error_msg = 0;
+static gboolean dcop_client_free_error_msg;
+
+/* don't use the glib types for args here, as this is an ICE callback (Simon)*/
+void dcop_process_message( IceConn ice_conn, IcePointer client_object,
+ int opcode, unsigned long length, Bool swap,
+ IceReplyWaitInfo *replyWait,
+ Bool *replyWaitRet );
+
+gchar *dcop_client_normalize_function_signature( const gchar *fun );
+
+static IcePoVersionRec DCOPVersions[] = {
+ { DCOPVersionMajor, DCOPVersionMinor, dcop_process_message
+ }
+};
+
+static unsigned int dcop_client_count = 0;
+static GtkObjectClass *parent_class = 0;
+
+static void dcop_client_class_init(DcopClientClass *klass);
+static void dcop_client_init(DcopClient *client);
+
+static gboolean dcop_client_real_process ( DcopClient *client, const char *fun, dcop_data *data,
+ char **reply_type, dcop_data **reply_data );
+
+GtkType
+dcop_client_get_type(void)
+{
+ static GtkType dcop_client_type = 0;
+ if (!dcop_client_type)
+ {
+ static const GtkTypeInfo dcop_client_info =
+ {
+ (gchar *)"DcopClient",
+ sizeof(DcopClient),
+ sizeof(DcopClientClass),
+ (GtkClassInitFunc)dcop_client_class_init,
+ (GtkObjectInitFunc)dcop_client_init,
+ 0,
+ 0,
+ 0
+ };
+ dcop_client_type = gtk_type_unique(GTK_TYPE_OBJECT, &dcop_client_info);
+ }
+ return dcop_client_type;
+}
+
+static void dcop_client_destroy( GtkObject *obj );
+static void dcop_init(void);
+static void dcop_shutdown(void);
+
+void
+dcop_client_class_init(DcopClientClass *klass)
+{
+ GtkObjectClass *object_class;
+ object_class = (GtkObjectClass *)klass;
+
+ parent_class = (GtkObjectClass *)gtk_type_class(gtk_object_get_type());
+
+ object_class->destroy = dcop_client_destroy;
+ klass->process = dcop_client_real_process;
+}
+
+void
+dcop_client_init(DcopClient *client)
+{
+ DcopClientPrivate *p;
+/* tststs :-) C++ hackers :-) (Simon)*/
+/* p = new GtkDcopClientPrivate;*/
+ p = g_new( DcopClientPrivate, 1 );
+
+ p->app_id = 0;
+ p->ice_conn = 0;
+ p->major_opcode = p->major_version = p->minor_version = 0;
+ p->vendor = p->release = 0;
+ p->registered = FALSE;
+ p->sender_id = 0;
+ p->key = 0;
+ p->current_key = 0;
+ p->post_message_timer = 0;
+ p->messages = 0;
+ p->default_object = 0;
+ p->transaction_list = 0;
+ p->transaction = FALSE;
+ p->transaction_id = 0;
+ p->opcode = 0;
+
+ client->priv = p;
+
+ if ( dcop_client_count == 0 )
+ dcop_init();
+
+ dcop_client_count++;
+}
+
+void dcop_client_destroy( GtkObject *obj )
+{
+ DcopClient *client = DCOP_CLIENT(obj);
+
+ g_message( "dcop_client_destructor()\n" );
+
+ if ( P->ice_conn && IceConnectionStatus( P->ice_conn ) == IceConnectAccepted )
+ dcop_client_detach( client );
+
+ if ( P->post_message_timer != 0 )
+ g_source_remove( P->post_message_timer );
+
+ {
+ GList *it = g_list_first( P->messages );
+ while ( it )
+ {
+ DcopClientMessage *msg = (DcopClientMessage *)it->data;
+ dcop_data_deref( msg->data );
+ g_free( msg );
+ it = g_list_next( it );
+ }
+ g_list_free( P->messages );
+ }
+
+ {
+ GList *it = g_list_first( P->transaction_list );
+ while ( it )
+ {
+ g_free( ((DcopClientTransaction *)it->data)->sender_id );
+ g_free( (DcopClientTransaction *)it );
+ it = g_list_next( it );
+ }
+
+ g_list_free( P->transaction_list );
+ }
+
+ g_free( P->app_id );
+ g_free( P->vendor );
+ g_free( P->release );
+ g_free( P->sender_id );
+
+ g_free( P );
+
+ if ( !--dcop_client_count )
+ dcop_shutdown();
+
+ parent_class->destroy(GTK_OBJECT(client));
+}
+
+
+void dcop_init()
+{
+ g_message( "dcop_init\n" );
+ dcop_client_free_error_msg = FALSE;
+}
+
+void dcop_shutdown()
+{
+ g_message( "dcop_shutdown\n" );
+ dcop_free( dcop_client_server_address );
+
+ if ( dcop_client_free_error_msg )
+ dcop_free( dcop_client_error_msg );
+}
+
+DcopClient *dcop_client_new()
+{
+ return (DcopClient *) gtk_type_new(dcop_client_get_type());
+}
+
+void dcop_client_set_server_address( const gchar *addr )
+{
+ dcop_string_copy( dcop_client_server_address, addr );
+}
+
+/* SM DUMMY */
+#include <X11/SM/SMlib.h>
+static gboolean HostBasedAuthProc ( char* hostname)
+{
+ /* we don't need any security here, as this is only a hack to
+ * get the protocol number we want for DCOP. We don't use the SM
+ * connection in any way */
+ return True;
+}
+
+static Status NewClientProc ( SmsConn c, SmPointer p, unsigned long*l, SmsCallbacks*cb, char**s )
+{
+ return 0;
+}
+
+static void dcop_client_registerXSM()
+{
+ char errormsg[256];
+ if (!SmsInitialize ((char *)("SAMPLE-SM"), (char *)("1.0"),
+ NewClientProc, NULL,
+ HostBasedAuthProc, 256, errormsg))
+ {
+ g_error( "register xsm failed");
+ exit( 1 );
+ }
+}
+
+/* hack*/
+extern int _IceLastMajorOpcode;
+
+static void dcop_client_xsm_check()
+{
+ if ( _IceLastMajorOpcode < 1 )
+ /* hack to enforce the correct ICE major opcode for DCOP*/
+ dcop_client_registerXSM();
+}
+
+static gboolean dcop_client_attach_internal( DcopClient *client, gboolean anonymous )
+{
+ gboolean bClearServerAddr = FALSE;
+ gchar *fname = 0;
+ const gchar *dcopSrvEnv = 0;
+ gchar *dcopSrv = 0;
+ gchar *dcopServerFileContent = 0;
+ glong dcopServerFileContentSize = 0;
+ ssize_t bytesRead = 0;
+ gchar *newLine = 0;
+ FILE *f = 0;
+ gchar errBuf[1024];
+ gint setupstat;
+
+ g_message( "dcop_client_attach\n" );
+
+ if ( dcop_client_is_attached( client ) )
+ dcop_client_detach( client );
+
+ dcop_client_xsm_check();
+
+ if ( ( P->major_opcode = IceRegisterForProtocolSetup( (char *)("DCOP"),
+ (char *)(DCOPVendorString),
+ (char *)(DCOPReleaseString),
+ 1, DCOPVersions,
+ DCOPAuthCount,
+ (char **)(DCOPAuthNames),
+ DCOPClientAuthProcs, 0 ) ) < 0 )
+ {
+ ERR( "Communications could not be established." );
+ return FALSE;
+ }
+ else
+ {
+ g_message( "dcop: major opcode is %d\n", P->major_opcode );
+ }
+
+ if ( !dcop_client_server_address )
+ {
+ dcopSrvEnv = getenv( "DCOPSERVER" );
+ if ( !dcopSrvEnv || strlen( dcopSrvEnv ) == 0 )
+ {
+ char hostName[255];
+
+ fname = g_strdup( getenv( "HOME" ) );
+ fname = (gchar *)g_realloc( fname, strlen( fname ) + 1 + 13 );
+ strcat( fname, "/.DCOPserver_" );
+
+ if ( gethostname( hostName, 255 ) == 0 )
+ {
+ fname = (gchar *)g_realloc( fname, strlen( fname ) + 1 + strlen( hostName ) );
+ strcat( fname, hostName );
+ }
+ else
+ {
+ fname = (gchar *)g_realloc( fname, strlen( fname ) + 1 + 9 );
+ strcat( fname, "localhost" );
+ }
+
+ f = fopen( fname, "r" );
+
+ if ( f == NULL ) /* try .DCOPServer_hostname_display (for KDE > 2.0) */
+ {
+ char *i;
+ char *display = getenv( "DISPLAY" );
+ gchar *display_real = g_strdup( display );
+ gchar *disppos;
+
+ /* dcopserver per display, not per screen */
+ if ( ( disppos = strchr( display_real, '.' ) ) > strchr( display_real, ':' ) && disppos != NULL )
+ (*disppos) = '\0';
+
+ while((i = strchr(display_real, ':')) != NULL)
+ *i = '_';
+
+ fname = (gchar *)g_realloc( fname, strlen( fname ) + 1 + 1 + strlen( display_real ) );
+ strcat( fname, "_" );
+ strcat( fname, display_real );
+
+ g_free( display_real );
+
+ f = fopen( fname, "r" );
+
+ if ( f == NULL )
+ {
+ g_free( fname );
+ ERR( "Cannot open ~/.DCOPserver" );
+ return FALSE;
+ }
+ }
+
+ fseek( f, 0L, SEEK_END );
+
+ dcopServerFileContentSize = ftell( f );
+
+ if ( dcopServerFileContentSize == 0L )
+ {
+ g_free( fname );
+ ERR( "Invalid ~/.DCOPserver" );
+ return FALSE;
+ }
+
+ fseek( f, 0L, SEEK_SET );
+
+ dcopServerFileContent = (gchar *)g_malloc( dcopServerFileContentSize );
+
+ bytesRead = fread( (void *)dcopServerFileContent, sizeof(gchar), dcopServerFileContentSize, f );
+
+ if ( bytesRead != dcopServerFileContentSize )
+ {
+ g_free( fname );
+ g_free( dcopServerFileContent );
+ fclose( f );
+ ERR( "Cannot read ~/.DCOPserver" );
+ return FALSE;
+ }
+
+ newLine = strchr( dcopServerFileContent, '\n' );
+
+ if ( newLine == NULL )
+ {
+ g_free( fname );
+ g_free( dcopServerFileContent );
+ fclose( f );
+ ERR( "Invalid ~/.DCOPserver" );
+ return FALSE;
+ }
+
+ *newLine = '\0';
+
+ fclose( f );
+ g_free( fname );
+
+ dcopSrv = g_strdup( dcopServerFileContent );
+
+ g_free( dcopServerFileContent );
+ }
+ else
+ dcopSrv = g_strdup( dcopSrvEnv );
+
+ if ( dcopSrv == NULL )
+ {
+ ERR( "Cannot determine dcop server address." );
+ return FALSE;
+ }
+
+ g_message( "dcop server address is : %s\n", dcopSrv );
+
+ dcop_client_server_address = dcopSrv;
+
+ bClearServerAddr = TRUE;
+
+ }
+
+ if ( ( P->ice_conn = IceOpenConnection( (char *)( dcop_client_server_address ),
+ (IcePointer)( client ), False, P->major_opcode,
+ sizeof( errBuf ), errBuf ) ) == NULL )
+ {
+ if ( bClearServerAddr )
+ dcop_free( dcop_client_server_address );
+ ERR( g_strdup( errBuf ) );
+ dcop_client_free_error_msg = TRUE;
+ return FALSE;
+
+ }
+
+ IceSetShutdownNegotiation( P->ice_conn, False );
+
+ setupstat = IceProtocolSetup( P->ice_conn, P->major_opcode, (IcePointer *)client, False,
+ &(P->major_version), &(P->minor_version),
+ &(P->vendor), &(P->release), sizeof( errBuf ), errBuf );
+
+ if ( setupstat == IceProtocolSetupFailure ||
+ setupstat == IceProtocolSetupIOError )
+ {
+ IceCloseConnection( P->ice_conn );
+
+ if ( bClearServerAddr )
+ dcop_free( dcop_client_server_address );
+
+ ERR( g_strdup( errBuf ) );
+ dcop_client_free_error_msg = TRUE;
+ return FALSE;
+ }
+ else if ( setupstat == IceProtocolAlreadyActive )
+ {
+ if ( bClearServerAddr )
+ dcop_free( dcop_client_server_address );
+
+ ERR( "Internal error in IceOpenConnection" );
+ return FALSE;
+ }
+
+ if ( IceConnectionStatus( P->ice_conn ) != IceConnectAccepted )
+ {
+ if ( bClearServerAddr )
+ dcop_free( dcop_client_server_address );
+
+ ERR( "DCOP server did not accept the connection" );
+ return FALSE;
+ }
+
+ if ( anonymous )
+ dcop_client_register_as( client, "anonymous", TRUE );
+
+ return TRUE;
+}
+
+gboolean dcop_client_attach( DcopClient *client )
+{
+ if ( !dcop_client_attach_internal( client, TRUE ) )
+ if ( !dcop_client_attach_internal( client, TRUE ) )
+ return FALSE; /* try two times!*/
+
+ return TRUE;
+}
+
+gboolean dcop_client_detach( DcopClient *client )
+{
+ int status;
+
+ g_message( "dcop_client_detach\n" );
+
+ if ( P->ice_conn )
+ {
+ IceProtocolShutdown( P->ice_conn, P->major_opcode );
+ status = IceCloseConnection( P->ice_conn );
+ if ( status != IceClosedNow )
+ {
+ ERR( "error detaching from DCOP server" );
+ return FALSE;
+ }
+ else
+ P->ice_conn = 0L;
+ }
+
+ P->registered = FALSE;
+
+ return TRUE;
+}
+
+gboolean dcop_client_is_attached( DcopClient *client )
+{
+ if ( !P->ice_conn )
+ return FALSE;
+
+ return (IceConnectionStatus( P->ice_conn ) == IceConnectAccepted );
+}
+
+const gchar *dcop_client_register_as( DcopClient *client, const gchar *app_id, gboolean add_pid /* = TRUE */ )
+{
+ gchar *result = 0;
+
+ gchar *id = g_strdup( app_id );
+ gchar pid[64];
+ gint pid_len = 0;
+
+ dcop_data *data = 0;
+ gchar *reply_type = 0;
+ dcop_data *reply_data = 0;
+
+ g_message( "dcop_client_register_as %s\n", app_id );
+
+ if ( dcop_client_is_registered( client ) )
+ dcop_client_detach( client );
+
+ if ( !dcop_client_is_attached( client ) )
+ if ( !dcop_client_attach_internal( client, FALSE ) )
+ return result; /*try two times*/
+
+ if ( add_pid )
+ {
+ pid_len = g_snprintf( pid, sizeof( pid ), "-%d", getpid() );
+ id = (gchar *)g_realloc( id, strlen( id ) + 1 + pid_len );
+ strcat( id, pid );
+ }
+
+
+ g_message( "trying to register as %s\n", id );
+
+ data = dcop_data_ref( dcop_data_new() );
+
+ dcop_marshal_string( data, id );
+
+ if ( dcop_client_call( client, "DCOPServer", "", "registerAs(QCString)", data,
+ &reply_type,
+ &reply_data ) )
+ {
+ dcop_data_reset( reply_data );
+ dcop_demarshal_string( reply_data, &result );
+
+ dcop_data_deref( reply_data );
+ g_free( reply_type );
+ }
+
+ dcop_string_assign( P->app_id, result );
+
+ P->registered = ( P->app_id != NULL && strlen( P->app_id ) > 0 );
+
+ if ( P->registered )
+ g_message( "we are registered as %s\n", P->app_id );
+ else
+ g_message( "registration failed\n" );
+
+ dcop_data_deref( data );
+
+ g_free( id );
+
+ return result;
+}
+
+gboolean dcop_client_is_registered( DcopClient *client )
+{
+ return P->registered;
+}
+
+const gchar *dcop_client_app_id( DcopClient *client )
+{
+ return P->app_id;
+}
+
+int dcop_client_socket( DcopClient *client )
+{
+ if ( P->ice_conn )
+ return IceConnectionNumber( P->ice_conn );
+ else
+ return 0;
+}
+
+gboolean dcop_client_send( DcopClient *client,
+ const gchar *rem_app, const gchar *rem_obj, const gchar *rem_fun,
+ dcop_data *data )
+{
+ struct DCOPMsg *pMsg = 0;
+ dcop_data *hdata = 0;
+ gchar *func = 0;
+ gboolean res = TRUE;
+
+ g_message( "dcop_client_send( %s, %s, %s )\n", rem_app, rem_obj, rem_fun);
+
+ if ( !dcop_client_is_attached( client ) )
+ return FALSE;
+
+ if ( strcmp( P->app_id, rem_app ) == 0 )
+ {
+ gchar *reply_type = 0;
+ dcop_data *reply_data = 0;
+
+ if ( !dcop_client_receive( client, rem_app, rem_obj, rem_fun, data, &reply_type, &reply_data ) )
+ g_warning( "dcop failure in app %s:\n object '%s' has no function '%s'", rem_app, rem_obj, rem_fun );
+
+ return TRUE;
+ }
+
+ hdata = dcop_data_ref( dcop_data_new() );
+
+ dcop_marshal_string( hdata, P->app_id );
+ dcop_marshal_string( hdata, rem_app );
+ dcop_marshal_string( hdata, rem_obj );
+
+ func = dcop_client_normalize_function_signature( rem_fun );
+ dcop_marshal_string( hdata, func );
+
+ dcop_marshal_uint32( hdata, data->size );
+
+ IceGetHeader( P->ice_conn, P->major_opcode, DCOPSend, sizeof(struct DCOPMsg), struct DCOPMsg, pMsg );
+
+ pMsg->key = 1; /* DCOPSend always uses the magic key 1*/
+ pMsg->length += hdata->size + data->size;
+
+ IceSendData( P->ice_conn, hdata->size, hdata->ptr );
+ IceSendData( P->ice_conn, data->size, data->ptr );
+
+ /* IceFlush( P->ice_conn );
+ */
+ if ( IceConnectionStatus( P->ice_conn ) != IceConnectAccepted )
+ res = FALSE;
+
+ g_free( func );
+
+ return res;
+}
+
+static gboolean dcop_client_call_internal( DcopClient *client,
+ const gchar *rem_app, const gchar *rem_obj, const gchar *rem_fun,
+ dcop_data *data,
+ gchar **reply_type, dcop_data **reply_data,
+ gint minor_opcode )
+{
+ gboolean success = FALSE;
+ struct DCOPMsg *pMsg = 0;
+ dcop_data *hdata = 0;
+ gchar *func = 0;
+ IceReplyWaitInfo waitInfo;
+ reply_struct reply;
+ gboolean readyRet;
+ IceProcessMessagesStatus status;
+ CARD32 old_current_key = 0;
+
+ reply_struct_init( &reply );
+
+ if ( !dcop_client_is_attached( client ) )
+ return FALSE;
+
+ old_current_key = P->current_key;
+ if ( !P->current_key )
+ P->current_key = P->key; /* no key, yet, initiate new call*/
+
+ hdata = dcop_data_ref( dcop_data_new() );
+
+ dcop_marshal_string( hdata, P->app_id );
+ dcop_marshal_string( hdata, rem_app );
+ dcop_marshal_string( hdata, rem_obj );
+
+ func = dcop_client_normalize_function_signature( rem_fun );
+ dcop_marshal_string( hdata, func );
+
+ dcop_marshal_uint32( hdata, data->size );
+
+ IceGetHeader( P->ice_conn, P->major_opcode, minor_opcode,
+ sizeof(struct DCOPMsg), struct DCOPMsg, pMsg );
+
+ pMsg->key = P->current_key;
+ pMsg->length += hdata->size + data->size;
+
+ IceSendData( P->ice_conn, hdata->size, hdata->ptr );
+ IceSendData( P->ice_conn, data->size, data->ptr );
+
+ if ( IceConnectionStatus( P->ice_conn ) != IceConnectAccepted )
+ {
+ dcop_data_deref( hdata );
+ g_free( func );
+ P->current_key = old_current_key;
+ return FALSE;
+ }
+
+ IceFlush( P->ice_conn );
+
+ waitInfo.sequence_of_request = IceLastSentSequenceNumber( P->ice_conn );
+ waitInfo.major_opcode_of_request = P->major_opcode;
+ waitInfo.minor_opcode_of_request = minor_opcode;
+ reply.reply_type = reply_type;
+ reply.reply_data = reply_data;
+ waitInfo.reply = (IcePointer)&reply;
+
+ readyRet = False;
+
+ do
+ {
+ status = IceProcessMessages( P->ice_conn, &waitInfo, &readyRet );
+ if ( status == IceProcessMessagesIOError )
+ {
+ IceCloseConnection( P->ice_conn );
+ dcop_data_deref( hdata );
+ g_free( func );
+ P->current_key = old_current_key;
+ return FALSE;
+ }
+ } while ( !readyRet );
+
+ dcop_data_deref( hdata );
+
+ success = reply.status == Ok;
+
+ g_free( func );
+
+ P->current_key = old_current_key;
+ return success;
+}
+
+gboolean dcop_client_call( DcopClient *client,
+ const gchar *rem_app, const gchar *rem_obj, const gchar *rem_fun,
+ dcop_data *data,
+ gchar **reply_type, dcop_data **reply_data )
+{
+ return dcop_client_call_internal( client, rem_app, rem_obj, rem_fun, data,
+ reply_type, reply_data, DCOPCall );
+}
+
+gboolean dcop_client_is_application_registered( DcopClient *client, const gchar *app )
+{
+ gchar *reply_type = 0;
+ dcop_data *reply_data = 0;
+ dcop_data *data = dcop_data_ref( dcop_data_new() );
+ gboolean res = FALSE;
+
+ dcop_marshal_string( data, app );
+
+ if ( dcop_client_call( client, "DCOPServer", "", "isApplicationRegistered(QCString)", data, &reply_type, &reply_data ) )
+ {
+ dcop_data_reset( reply_data );
+ dcop_demarshal_boolean( reply_data, &res );
+ }
+
+ g_free( reply_type );
+ if ( reply_data )
+ dcop_data_deref( reply_data );
+ dcop_data_deref( data );
+
+ return res;
+}
+
+GList *dcop_client_registered_applications( DcopClient *client )
+{
+ GList *res = 0;
+ dcop_data *data = 0;
+ dcop_data *reply_data = 0;
+ gchar *reply_type = 0;
+
+ data = dcop_data_ref( dcop_data_new() );
+
+ if ( dcop_client_call( client, "DCOPServer", "", "registeredApplications()", data,
+ &reply_type, &reply_data ) )
+ {
+ fprintf( stderr, "reply type is %s\n", reply_type );
+ dcop_data_reset( reply_data );
+ dcop_demarshal_stringlist( reply_data, &res );
+ dcop_data_deref( reply_data );
+ }
+
+ g_free( reply_type );
+ dcop_data_deref( data );
+ return res;
+}
+
+extern GHashTable *object_dict;
+
+GList *g_temp_object_list = 0;
+
+static void dcop_client_receive_list_objects_internal( gpointer key, gpointer val, gpointer user_data )
+{
+ gchar *nam = (gchar *)key;
+ DcopObject *obj = (DcopObject *)val;
+ DcopClient *client = (DcopClient *)user_data;
+ const gchar *id = DCOP_ID( obj );
+
+ if ( id && strlen( id ) > 0 )
+ {
+ if ( P->default_object &&
+ strcmp( id, P->default_object ) == 0 )
+ g_temp_object_list = g_list_append( g_temp_object_list, (gchar *)"default" );
+
+ g_temp_object_list = g_list_append( g_temp_object_list, (gchar *)id );
+ }
+}
+
+gboolean dcop_client_receive( DcopClient *client,
+ const gchar *app, const gchar *obj, const gchar *fun,
+ dcop_data *data,
+ gchar **reply_type, dcop_data **reply_data )
+{
+ DcopObject *o;
+
+ g_message( "dcop_client_receive app=%s obj=%s fun=%s\n", app, obj, fun);
+
+ if ( obj && strcmp( obj, "DCOPClient" ) == 0 )
+ {
+ if ( strcmp( fun, "objects()" ) == 0 )
+ {
+ GList *list = 0;
+
+ *reply_type = strdup( "QCStringList" );
+ *reply_data = dcop_data_ref( dcop_data_new() );
+
+ if ( object_dict )
+ {
+ /*
+ GList *it = g_list_first( object_list );
+
+ while ( it )
+ {
+ if ( it->data )
+ {
+ const gchar *id;
+ o = (DcopObject *)it->data;
+ id = DCOP_ID(o);
+ if ( id && strlen( id ) > 0 )
+ {
+ if ( P->default_object &&
+ strcmp( id, P->default_object ) == 0 )
+ list = g_list_append( list, (gchar *)"default" );
+
+ list = g_list_append( list, (gchar *)id );
+ }
+ }
+ it = g_list_next( it );
+ }
+ */
+ g_temp_object_list = 0;
+
+ g_hash_table_foreach( object_dict, dcop_client_receive_list_objects_internal, client );
+
+ list = g_temp_object_list;
+ }
+
+ dcop_marshal_stringlist( *reply_data, list );
+ /* important: only "free" (return to internal allocator) the list*/
+ /* itself, not it's data, as that data are either static strings*/
+ /* or strings already owned by someone else*/
+ g_list_free( list );
+ return TRUE;
+ }
+
+ if ( CLIENT_CLASS(client)->process( client, fun, data, reply_type, reply_data ) )
+ return TRUE;
+ }
+
+ if ( !obj || strlen( obj ) == 0 || strcmp( obj, "default" ) == 0 )
+ if ( P->default_object && strlen( P->default_object ) != 0 )
+ {
+ o = dcop_object_lookup( P->default_object );
+ if ( o && DCOP_OBJECT_CLASS(GTK_OBJECT(o)->klass)->process( o, fun, data, reply_type, reply_data ) )
+ return TRUE;
+ }
+
+ if ( obj && obj[ strlen( obj ) - 1 ] == '*' )
+ {
+ gchar *partial_id = (gchar *)g_malloc( strlen( obj ) - 1 );
+ GList *match_list = 0;
+
+ strncpy( partial_id, obj, strlen( obj ) - 1 );
+
+ match_list = dcop_object_match( partial_id );
+
+ if ( match_list )
+ {
+ GList *it = g_list_first( match_list );
+
+ while ( it )
+ {
+ o = (DcopObject *)it->data;
+
+ if ( !DCOP_OBJECT_CLASS(GTK_OBJECT(o)->klass)->process( o, fun, data, reply_type, reply_data ) )
+ {
+ g_list_free( match_list );
+ g_free( partial_id );
+ return FALSE;
+ }
+
+ it = g_list_next( it );
+ }
+
+ g_list_free( match_list );
+ }
+
+ g_free( partial_id );
+ return TRUE;
+ }
+
+ /* ### proxy support
+ */
+ o = dcop_object_lookup( obj );
+ if ( !o )
+ return FALSE;
+ return DCOP_OBJECT_CLASS(GTK_OBJECT(o)->klass)->process( o, fun, data, reply_type, reply_data );
+}
+
+static inline gboolean is_ident_char( gchar x )
+{ /* Avoid bug in isalnum */
+ return x == '_' || (x >= '0' && x <= '9') ||
+ (x >= 'a' && x <= 'z') || (x >= 'A' && x <= 'Z');
+}
+
+gchar *dcop_client_normalize_function_signature( const gchar *fun )
+{
+ gchar *result;
+ size_t len = strlen( fun );
+ const gchar *from;
+ gchar *to, *first;
+ gchar last;
+
+ if ( len == 0 )
+ return g_strdup( fun );
+
+ result = (gchar *)g_malloc( len + 1 );
+
+ from = fun;
+ first = to = result;
+ last = 0;
+
+ while ( 42 )
+ {
+ while ( *from && isspace( *from ) )
+ from++;
+ if ( last && is_ident_char( last ) && is_ident_char( *from ) )
+ *to++ = 0x20;
+ while ( *from && !isspace( *from ) )
+ {
+ last = *from++;
+ *to++ = last;
+ }
+ if ( !*from )
+ break;
+ }
+ if ( to > first && *(to-1) == 0x20 )
+ to--;
+ *to = '\0';
+ result = (gchar *)g_realloc( result, (int)((long)to - (long)result) + 1 );
+ return result;
+}
+
+const gchar *dcop_client_sender_id( DcopClient *client )
+{
+ return P->sender_id;
+}
+
+gboolean dcop_client_process( DcopClient *client, const gchar *fun, dcop_data *data,
+ gchar **reply_type, dcop_data **reply_data )
+{
+ return CLIENT_CLASS( client )->process( client, fun, data, reply_type, reply_data );
+}
+
+gboolean dcop_client_real_process( DcopClient *client, const gchar *fun, dcop_data *data,
+ gchar **reply_type, dcop_data **reply_data )
+{
+ /* empty default implementation*/
+ return FALSE;
+}
+
+void dcop_client_process_socket_data( DcopClient *client )
+{
+ IceProcessMessagesStatus status;
+
+ g_message( "dcop_client_process_socket_data\n" );
+
+ status = IceProcessMessages( P->ice_conn, 0, 0 );
+
+ g_message( "dcop_client_process_socket_data : messages processed\n" );
+
+ if ( status == IceProcessMessagesIOError )
+ {
+ IceCloseConnection( P->ice_conn );
+ g_message( "error receiving data from the DCOP server.\n" );
+ return;
+ }
+}
+
+const gchar *dcop_client_error_message()
+{
+ return dcop_client_error_msg;
+}
+
+void dcop_process_internal( DcopClient *client, int opcode, CARD32 key, dcop_data *data_received, gboolean can_post );
+
+/* don't use the glib types for args here, as this is an ICE callback (Simon)*/
+void dcop_process_message( IceConn ice_conn, IcePointer client_object,
+ int opcode, unsigned long length, Bool swap,
+ IceReplyWaitInfo *replyWait,
+ Bool *replyWaitRet )
+{
+ struct DCOPMsg *pMsg = 0;
+ DcopClient *client = (DcopClient *)client_object;
+ void *data_received;
+ dcop_data *tmp_stream = 0;
+ unsigned int id;
+ char *called_app = 0;
+ char *app = 0;
+ char *obj = 0;
+ char *fun = 0;
+ CARD32 key;
+
+ IceReadMessageHeader( ice_conn, sizeof( struct DCOPMsg ), struct DCOPMsg, pMsg );
+
+ key = pMsg->key;
+ if ( P->key == 0 )
+ P->key = key; /* received a key from the server*/
+
+ data_received = g_malloc( length );
+ IceReadData( ice_conn, length, data_received );
+
+ tmp_stream = dcop_data_ref( dcop_data_new() );
+ dcop_data_assign( tmp_stream, (char *)data_received, length );
+
+ P->opcode = opcode;
+
+ switch ( opcode )
+ {
+ case DCOPReplyFailed:
+ if ( replyWait )
+ {
+ ((reply_struct *)replyWait->reply)->status = Failed;
+ *replyWaitRet = True;
+ break;
+ }
+ else
+ {
+ g_warning( "dcop error: received an unexpected DCOPReplyFailed opcode.\n" );
+ break;
+ }
+ case DCOPReply:
+ if ( replyWait )
+ {
+ ((reply_struct *)replyWait->reply)->status = Ok;
+
+ dcop_demarshal_string( tmp_stream, &called_app );
+ dcop_demarshal_string( tmp_stream, &app );
+ dcop_demarshal_string( tmp_stream, ((reply_struct *)replyWait->reply)->reply_type );
+ dcop_demarshal_data( tmp_stream, ((reply_struct *)replyWait->reply)->reply_data );
+
+ *replyWaitRet = True;
+ break;
+ }
+ else
+ {
+ g_warning( "dcop error: received an unexpected DCOPReply.\n" );
+ break;
+ }
+ case DCOPReplyWait:
+ if ( replyWait )
+ {
+ dcop_demarshal_string( tmp_stream, &called_app );
+ dcop_demarshal_string( tmp_stream, &app );
+ dcop_demarshal_uint32( tmp_stream, &id );
+
+ ((reply_struct *)replyWait->reply)->reply_id = id;
+
+ break;
+ }
+ else
+ {
+ g_warning( "dcop error: received an unexpected DCOPReplyWait.\n" );
+ break;
+ }
+ case DCOPReplyDelayed:
+ if ( replyWait )
+ {
+ ((reply_struct *)replyWait->reply)->status = Ok;
+
+ dcop_demarshal_string( tmp_stream, &called_app );
+ dcop_demarshal_string( tmp_stream, &app );
+ dcop_demarshal_uint32( tmp_stream, &id );
+ dcop_demarshal_string( tmp_stream, ((reply_struct *)replyWait->reply)->reply_type );
+ dcop_demarshal_data( tmp_stream, ((reply_struct *)replyWait->reply)->reply_data );
+
+ if ( id != ((reply_struct *)replyWait->reply)->reply_id )
+ {
+ ((reply_struct *)replyWait->reply)->status = Failed;
+ g_warning( "dcop error: received a wrong sequence id for DCOPReplyDelayed.\n" );
+ }
+
+ *replyWaitRet = True;
+
+ break;
+ }
+ else
+ {
+ g_message( "dcop error: received an unexpeced DCOPReplyDelayed.\n" );
+ break;
+ }
+ case DCOPCall:
+ case DCOPFind:
+ case DCOPSend:
+ dcop_process_internal( client, opcode, key, tmp_stream, TRUE );
+ break;
+ }
+
+ dcop_data_deref( tmp_stream );
+
+ g_free( called_app );
+ g_free( app );
+}
+
+static gboolean dcop_client_process_post_messages_internal( gpointer data )
+{
+ DcopClient *client = DCOP_CLIENT( data );
+ GList *it = 0;
+
+ g_message( "dcop_client_process_post_messages_internal" );
+
+ if ( g_list_length( P->messages ) == 0 )
+ return FALSE;
+
+ it = g_list_first( P->messages );
+ while ( it )
+ {
+ DcopClientMessage *msg = (DcopClientMessage *)it->data;
+ it = g_list_next( it );
+
+ g_assert( msg );
+
+ if ( P->current_key && msg->key != P->current_key )
+ continue;
+
+ P->messages = g_list_remove( P->messages, msg );
+ dcop_process_internal( client, msg->opcode, msg->key, msg->data, FALSE );
+ dcop_data_deref( msg->data );
+ g_free( msg );
+ }
+
+ if ( g_list_length( P->messages ) == 0 )
+ return FALSE;
+
+ return TRUE;
+}
+
+void dcop_process_internal( DcopClient *client, int opcode, CARD32 key, dcop_data *data_received, gboolean can_post )
+{
+ gchar *app = 0;
+ gchar *obj = 0;
+ gchar *fun = 0;
+ char *reply_type = 0;
+ dcop_data *reply_data = 0;
+ gboolean b = FALSE;
+ CARD32 old_current_key = 0;
+ dcop_data *data = 0;
+ dcop_data *reply = 0;
+ struct DCOPMsg *pMsg = 0;
+
+ dcop_free( P->sender_id );
+ dcop_demarshal_string( data_received, &P->sender_id );
+ dcop_demarshal_string( data_received, &app );
+ dcop_demarshal_string( data_received, &obj );
+ dcop_demarshal_string( data_received, &fun );
+ dcop_demarshal_data( data_received, &data );
+
+ if ( can_post && P->current_key && key != P->current_key )
+ {
+ DcopClientMessage *msg = g_new( DcopClientMessage, 1 );
+ g_message( "posting message with key %i", key );
+ msg->opcode = opcode;
+ msg->key = key;
+ msg->data = dcop_data_ref( data_received );
+ P->messages = g_list_append( P->messages, msg );
+ if ( P->post_message_timer != 0 )
+ g_source_remove( P->post_message_timer );
+ P->post_message_timer = g_timeout_add( 0, dcop_client_process_post_messages_internal, client );
+ return;
+ }
+
+ old_current_key = P->current_key;
+ if ( opcode != DCOPSend ) /* DCOPSend doesn't change the current key*/
+ P->current_key = key;
+
+ if ( opcode == DCOPFind )
+ {
+ /* #### b = dcop_client_find( app, obj, fun, data, &reply_type, &reply_data ); */
+ }
+ else
+ b = dcop_client_receive( client, app, obj, fun, data, &reply_type, &reply_data );
+
+ if ( opcode == DCOPSend )
+ {
+ g_free( app );
+ g_free( obj );
+ g_free( fun );
+ if ( data )
+ dcop_data_deref( data );
+ g_free( reply_type );
+ if ( reply_data )
+ dcop_data_deref( reply_data );
+ return;
+ }
+
+ P->current_key = old_current_key;
+
+ reply = dcop_data_ref( dcop_data_new() );
+
+ if ( P->transaction_id )
+ {
+ dcop_marshal_string( reply, P->app_id );
+ dcop_marshal_string( reply, P->sender_id );
+ dcop_marshal_uint32( reply, (guint32)P->transaction_id );
+
+ IceGetHeader( P->ice_conn, P->major_opcode, DCOPReplyWait,
+ sizeof( struct DCOPMsg ), struct DCOPMsg, pMsg );
+
+ pMsg->key = key;
+ pMsg->length += reply->size;
+
+ IceSendData( P->ice_conn, reply->size, reply->ptr );
+
+ dcop_data_deref( reply );
+ g_free( app );
+ g_free( obj );
+ g_free( fun );
+ dcop_data_deref( data );
+ return;
+ }
+
+ if ( !b )
+ {
+ g_warning( "dcop failure in app %s:\n object '%s' has no function '%s'", app, obj, fun );
+
+ dcop_marshal_string( reply, P->app_id );
+ dcop_marshal_string( reply, P->sender_id );
+
+ IceGetHeader( P->ice_conn, P->major_opcode, DCOPReplyFailed,
+ sizeof( struct DCOPMsg ), struct DCOPMsg, pMsg );
+ pMsg->key = key;
+ pMsg->length += reply->size;
+ IceSendData( P->ice_conn, reply->size, reply->ptr );
+
+ dcop_data_deref( reply );
+ g_free( app );
+ g_free( obj );
+ g_free( fun );
+ dcop_data_deref( data );
+ return;
+ }
+
+ if ( !reply_data )
+ reply_data = dcop_data_ref( dcop_data_new() );
+
+ dcop_marshal_string( reply, P->app_id );
+ dcop_marshal_string( reply, P->sender_id );
+ dcop_marshal_string( reply, reply_type );
+ dcop_marshal_uint32( reply, reply_data->size );
+
+ IceGetHeader( P->ice_conn, P->major_opcode, DCOPReply,
+ sizeof( struct DCOPMsg ), struct DCOPMsg, pMsg );
+
+ pMsg->key = key;
+ pMsg->length += reply->size + reply_data->size;
+ /* use IceSendData not IceWriteData to avoid a copy. Output buffer
+ shouldn't need to be flushed. */
+ IceSendData( P->ice_conn, reply->size, reply->ptr );
+ IceSendData( P->ice_conn, reply_data->size, reply_data->ptr );
+
+ dcop_data_deref( reply );
+ g_free( app );
+ g_free( obj );
+ g_free( fun );
+ dcop_data_deref( data );
+ dcop_data_deref( reply_data );
+}
+
+void dcop_client_set_default_object( DcopClient *client, const gchar *obj_id )
+{
+ dcop_string_copy( P->default_object, obj_id );
+}
+
+const gchar *dcop_client_default_object( DcopClient *client )
+{
+ return P->default_object;
+}
+
+DcopClientTransaction *dcop_client_begin_transaction( DcopClient *client )
+{
+ DcopClientTransaction *transaction = 0;
+
+ if ( P->opcode == DCOPSend )
+ return 0;
+
+ P->transaction = TRUE;
+ transaction = g_new( DcopClientTransaction, 1 );
+ transaction->sender_id = g_strdup( P->sender_id );
+
+ if ( !P->transaction_id )
+ P->transaction_id++;
+
+ transaction->id = ++(P->transaction_id);
+ transaction->key = P->current_key;
+
+ P->transaction_list = g_list_append( P->transaction_list, transaction );
+
+ return transaction;
+}
+
+gint32 dcop_client_transaction_id( DcopClient *client )
+{
+ if ( P->transaction )
+ return P->transaction_id;
+ else
+ return 0;
+}
+
+void dcop_client_end_transaction( DcopClient *client, DcopClientTransaction *trans, gchar *reply_type, dcop_data *reply_data )
+{
+ struct DCOPMsg *pMsg = 0;
+ dcop_data *data = 0;
+
+ if ( !trans )
+ return;
+
+ if ( !dcop_client_is_attached( client ) )
+ return;
+
+ if ( !P->transaction_list )
+ {
+ g_warning( "dcop_client_end_transaction: no pending transactions!" );
+ return;
+ }
+
+ if ( !g_list_find( P->transaction_list, trans ) )
+ {
+ g_warning( "dcop_client_end_transaction: unknown transaction!" );
+ return;
+ }
+
+ P->transaction_list = g_list_remove( P->transaction_list, trans );
+
+ data = dcop_data_ref( dcop_data_new() );
+
+ dcop_data_ref( reply_data );
+
+ dcop_marshal_string( data, P->app_id );
+ dcop_marshal_string( data, trans->sender_id );
+ dcop_marshal_uint32( data, (guint32)trans->id );
+ dcop_marshal_string( data, reply_type );
+ dcop_marshal_data( data, reply_data );
+
+ IceGetHeader( P->ice_conn, P->major_opcode, DCOPReplyDelayed, sizeof( struct DCOPMsg ), struct DCOPMsg, pMsg );
+
+ pMsg->key = trans->key;
+ pMsg->length += data->size;
+
+ IceSendData( P->ice_conn, data->size, data->ptr );
+
+ dcop_data_deref( data );
+ dcop_data_deref( reply_data );
+
+ g_free( trans->sender_id );
+ g_free( trans );
+}
+
+void dcop_client_emit_dcop_signal( DcopClient *client,
+ const gchar *object, const gchar *signal, dcop_data *data )
+{
+ gchar *normalized_signal_name = dcop_client_normalize_function_signature( signal );
+ gchar *signame = g_strdup( object );
+
+ signame = (gchar *)g_realloc( signame, strlen( object ) + 1 + 1 + strlen( normalized_signal_name ) );
+ strcat( signame, "#" );
+ strcat( signame, normalized_signal_name );
+
+ dcop_client_send( client, "DCOPServer", "emit", signame, data );
+
+ g_free( signame );
+}
+
+gboolean dcop_client_connect_dcop_signal( DcopClient *client,
+ const gchar *sender, const gchar *sender_obj,
+ const gchar *signal,
+ const gchar *receiver_obj, const gchar *slot,
+ gboolean _volatile )
+{
+ gchar *reply_type = 0;
+ dcop_data *reply_data = 0;
+ dcop_data *data = dcop_data_ref( dcop_data_new() );
+ guint8 ivolatile = _volatile ? 1 : 0;
+ gchar *normalized_signame = dcop_client_normalize_function_signature( signal );
+ gchar *normalized_slotname = dcop_client_normalize_function_signature( slot );
+ guint8 result = 0;
+
+ dcop_marshal_string( data, sender );
+ dcop_marshal_string( data, sender_obj );
+ dcop_marshal_string( data, normalized_signame );
+ dcop_marshal_string( data, receiver_obj );
+ dcop_marshal_string( data, normalized_slotname );
+ dcop_marshal_uint8( data, ivolatile );
+
+ if ( dcop_client_call( client, "DCOPServer", "", "connectSignal(QCString,QCString,QCString,QCString,QCString,bool)", data, &reply_type, &reply_data ) == FALSE )
+ {
+ g_free( normalized_signame );
+ g_free( normalized_slotname );
+ dcop_data_deref( data );
+ return FALSE;
+ }
+
+ if ( reply_type == NULL || strcmp( reply_type, "bool" ) != 0 ||
+ reply_data == NULL )
+ {
+ g_free( normalized_signame );
+ g_free( normalized_slotname );
+ dcop_data_deref( data );
+ if ( reply_data != NULL )
+ dcop_data_deref( reply_data );
+ return FALSE;
+ }
+
+ dcop_data_reset( reply_data );
+ dcop_demarshal_uint8( reply_data, &result );
+
+ g_free( normalized_signame );
+ g_free( normalized_slotname );
+ dcop_data_deref( data );
+ dcop_data_deref( reply_data );
+
+ if ( result == 0 )
+ return FALSE;
+
+ return TRUE;
+}
+
+gboolean dcop_client_disconnect_dcop_signal( DcopClient *client,
+ const gchar *sender, const gchar *sender_obj,
+ const gchar *signal,
+ const gchar *receiver_obj, const gchar *slot )
+{
+ gchar *reply_type = 0;
+ dcop_data *reply_data = 0;
+ dcop_data *data = dcop_data_ref( dcop_data_new() );
+ gchar *normalized_signame = dcop_client_normalize_function_signature( signal );
+ gchar *normalized_slotname = dcop_client_normalize_function_signature( slot );
+ guint8 result = 0;
+
+ dcop_marshal_string( data, sender );
+ dcop_marshal_string( data, sender_obj );
+ dcop_marshal_string( data, normalized_signame );
+ dcop_marshal_string( data, receiver_obj );
+ dcop_marshal_string( data, normalized_slotname );
+
+ if ( dcop_client_call( client, "DCOPServer", "", "disconnectSignal(QCString,QCString,QCString,QCString,QCString)", data, &reply_type, &reply_data ) == FALSE )
+ {
+ g_free( normalized_signame );
+ g_free( normalized_slotname );
+ dcop_data_deref( data );
+ return FALSE;
+ }
+
+ if ( reply_type == NULL || strcmp( reply_type, "bool" ) != 0 ||
+ reply_data == NULL )
+ {
+ g_free( normalized_signame );
+ g_free( normalized_slotname );
+ dcop_data_deref( data );
+ if ( reply_data != NULL )
+ dcop_data_deref( reply_data );
+ return FALSE;
+ }
+
+ dcop_data_reset( reply_data );
+ dcop_demarshal_uint8( reply_data, &result );
+
+ g_free( normalized_signame );
+ g_free( normalized_slotname );
+ dcop_data_deref( data );
+ dcop_data_deref( reply_data );
+
+ if ( result == 0 )
+ return FALSE;
+
+ return TRUE;
+}
+
+void dcop_client_set_daemon_mode( DcopClient *client, gboolean daemon )
+{
+ gchar *reply_type = 0;
+ dcop_data *reply_data = 0;
+ dcop_data *data = dcop_data_ref( dcop_data_new() );
+ guint8 idaemon = daemon ? 1 : 0;
+ dcop_marshal_uint8( data, idaemon );
+
+ dcop_client_call( client, "DCOPServer", "", "setDaemonMode(bool)", data, &reply_type, &reply_data );
+
+ if ( reply_data != NULL )
+ dcop_data_deref( reply_data );
+
+ dcop_data_deref( data );
+
+ dcop_free( reply_type );
+}