Fix some memory leaks
[platform/upstream/at-spi2-core.git] / dbind / dbind.c
1
2
3 #include <stdio.h>
4 #include <stdarg.h>
5 #include <glib.h>
6
7 #include "config.h"
8 #include "dbind/dbind.h"
9
10 static int dbind_timeout = -1;
11
12 /*
13  * FIXME: compare types - to ensure they match &
14  *        do dynamic padding of structures etc.
15  */
16
17 /*---------------------------------------------------------------------------*/
18
19 typedef struct _SpiReentrantCallClosure 
20 {
21   DBusMessage *reply;
22 } SpiReentrantCallClosure;
23
24 static void
25 set_reply (DBusPendingCall * pending, void *user_data)
26 {
27   SpiReentrantCallClosure* closure = (SpiReentrantCallClosure *) user_data; 
28
29   closure->reply = dbus_pending_call_steal_reply (pending);
30   dbus_pending_call_unref (pending);
31 }
32
33 DBusMessage *
34 dbind_send_and_allow_reentry (DBusConnection * bus, DBusMessage * message, DBusError *error)
35 {
36   DBusPendingCall *pending;
37   SpiReentrantCallClosure closure;
38   const char *unique_name = dbus_bus_get_unique_name (bus);
39   const char *destination = dbus_message_get_destination (message);
40
41   if (unique_name && destination &&
42       strcmp (destination, unique_name) != 0)
43     return dbus_connection_send_with_reply_and_block (bus, message, dbind_timeout, error);
44
45   closure.reply = NULL;
46   dbus_connection_setup_with_g_main(bus, NULL);
47   if (!dbus_connection_send_with_reply (bus, message, &pending, dbind_timeout))
48       return NULL;
49   if (!pending)
50     return NULL;
51   dbus_pending_call_set_notify (pending, set_reply, (void *) &closure, NULL);
52
53   closure.reply = NULL;
54   while (!closure.reply)
55     {
56       if (!dbus_connection_read_write_dispatch (bus, dbind_timeout))
57         return NULL;
58     }
59   
60   return closure.reply;
61 }
62
63 dbus_bool_t
64 dbind_method_call_reentrant_va (DBusConnection *cnx,
65                                 const char     *bus_name,
66                                 const char     *path,
67                                 const char     *interface,
68                                 const char     *method,
69                                 DBusError      *opt_error,
70                                 const char     *arg_types,
71                                 va_list         args)
72 {
73     dbus_bool_t success = FALSE;
74     DBusMessage *msg = NULL, *reply = NULL;
75     DBusMessageIter iter;
76     DBusError *err, real_err;
77     const char *p;
78   va_list args_demarshal;
79
80   va_copy (args_demarshal, args);
81     if (opt_error)
82         err = opt_error;
83     else {
84         dbus_error_init (&real_err);
85         err = &real_err;
86     }
87
88     msg = dbus_message_new_method_call (bus_name, path, interface, method);
89     if (!msg)
90         goto out;
91
92     p = arg_types;
93     dbus_message_iter_init_append (msg, &iter);
94     dbind_any_marshal_va (&iter, &p, args);
95
96     reply = dbind_send_and_allow_reentry (cnx, msg, err);
97     if (!reply)
98         goto out;
99
100     if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR)
101     {
102       const char *name = dbus_message_get_error_name (reply);
103       goto out;
104     }
105     /* demarshal */
106     if (p[0] == '=' && p[1] == '>')
107     {
108         DBusMessageIter iter;
109         dbus_message_iter_init (reply, &iter);
110         p = arg_types;
111         dbind_any_demarshal_va (&iter, &p, args_demarshal);
112     }
113
114     success = TRUE;
115 out:
116     if (msg)
117         dbus_message_unref (msg);
118
119     if (reply)
120         dbus_message_unref (reply);
121
122     if (err == &real_err)
123         dbus_error_free (err);
124
125     va_end (args_demarshal);
126     return success;
127 }
128
129 /**
130  * dbind_method_call_reentrant:
131  *
132  * @cnx:       A D-Bus Connection used to make the method call.
133  * @bus_name:  The D-Bus bus name of the program where the method call should
134  *             be made.
135  * @path:      The D-Bus object path that should handle the method.
136  * @interface: The D-Bus interface used to scope the method name.
137  * @method:    Method to be invoked.
138  * @opt_error: D-Bus error.
139  * @arg_types: Variable length arguments interleaving D-Bus argument types
140  *             and pointers to argument data.
141  *
142  * Makes a D-Bus method call using the supplied location data, method name and
143  * argument data.This function is re-entrant. It continuously reads from the D-Bus
144  * bus and dispatches messages until a reply has been recieved.
145  **/
146 dbus_bool_t
147 dbind_method_call_reentrant (DBusConnection *cnx,
148                              const char     *bus_name,
149                              const char     *path,
150                              const char     *interface,
151                              const char     *method,
152                              DBusError      *opt_error,
153                              const char     *arg_types,
154                              ...)
155 {
156     dbus_bool_t success = FALSE;
157     va_list args;
158
159     va_start (args, arg_types);
160     success = dbind_method_call_reentrant_va (cnx,
161                                               bus_name,
162                                               path,
163                                               interface,
164                                               method,
165                                               opt_error,
166                                               arg_types,
167                                               args);
168     va_end (args);
169
170     return success;
171 }
172
173 /*---------------------------------------------------------------------------*/
174
175 dbus_bool_t
176 dbind_emit_signal_va (DBusConnection *cnx,
177                       const char     *path,
178                       const char     *interface,
179                       const char     *signal,
180                       DBusError      *opt_error,
181                       const char     *arg_types,
182                       va_list         args)
183 {
184     dbus_bool_t success = FALSE;
185     DBusMessage *msg = NULL;
186     DBusMessageIter iter;
187     DBusError *err, real_err;
188     const char *p;
189
190     if (opt_error)
191         err = opt_error;
192     else {
193         dbus_error_init (&real_err);
194         err = &real_err;
195     }
196
197     msg = dbus_message_new_signal (path, interface, signal);
198     if (!msg)
199         goto out;
200
201     p = arg_types;
202     dbus_message_iter_init_append (msg, &iter);
203     dbind_any_marshal_va (&iter, &p, args);
204
205     if (!dbus_connection_send (cnx, msg, NULL))
206        goto out;
207
208     success = TRUE;
209 out:
210
211     if (msg)
212         dbus_message_unref (msg);
213
214     if (err == &real_err)
215         dbus_error_free (err);
216
217     return success;
218 }
219
220 /**
221  * dbind_emit_signal:
222  *
223  * @cnx:       A D-Bus Connection used to make the method call.
224  * @path:      The D-Bus object path that this signal is emitted from.
225  * @interface: The D-Bus interface used to scope the method name.
226  * @signal:    Name of signal to emit.
227  * @opt_error: D-Bus error.
228  * @arg_types: Variable length arguments interleaving D-Bus argument types
229  *             and pointers to argument data.
230  *
231  * Emits a D-Bus signal  using the supplied signal name and argument data.
232  **/
233 dbus_bool_t
234 dbind_emit_signal (DBusConnection *cnx,
235                    const char     *path,
236                    const char     *interface,
237                    const char     *signal,
238                    DBusError      *opt_error,
239                    const char     *arg_types,
240                    ...)
241 {
242     dbus_bool_t success = FALSE;
243     va_list args;
244
245     va_start (args, arg_types);
246     success = dbind_emit_signal_va (cnx, path, interface, signal, opt_error, arg_types, args);
247     va_end (args);
248
249     return success;
250 }
251 void
252 dbind_set_timeout (int timeout)
253 {
254   dbind_timeout = timeout;
255 }
256
257
258 /*END------------------------------------------------------------------------*/