2003-09-21 Havoc Pennington <hp@pobox.com>
[platform/upstream/dbus.git] / dbus / dbus-bus.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-bus.c  Convenience functions for communicating with the bus.
3  *
4  * Copyright (C) 2003  CodeFactory AB
5  * Copyright (C) 2003  Red Hat, Inc.
6  *
7  * Licensed under the Academic Free License version 1.2
8  * 
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  * 
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  *
23  */
24
25 #include "dbus-bus.h"
26 #include "dbus-protocol.h"
27 #include "dbus-internals.h"
28 #include "dbus-message.h"
29 #include <string.h>
30
31 /**
32  * @defgroup DBusBus Message bus APIs
33  * @ingroup DBus
34  * @brief Functions for communicating with the message bus
35  *
36  *
37  * @todo get rid of most of these; they should be done
38  * with DBusGProxy and the Qt equivalent, i.e. the same
39  * way any other interface would be used.
40  */
41
42
43 /**
44  * @defgroup DBusBusInternals Message bus APIs internals
45  * @ingroup DBusInternals
46  * @brief Internals of functions for communicating with the message bus
47  *
48  * @{
49  */
50
51 /**
52  * Block of message-bus-related data we attach to each
53  * #DBusConnection used with these convenience functions.
54  *
55  */
56 typedef struct
57 {
58   DBusConnection *connection; /**< Connection we're associated with */
59   char *base_service; /**< Base service name of this connection */
60
61   unsigned int is_well_known : 1; /**< Is one of the well-known connections in our global array */
62 } BusData;
63
64 /** The slot we have reserved to store BusData.
65  */
66 static dbus_int32_t bus_data_slot = -1;
67
68 /** Number of bus types */
69 #define N_BUS_TYPES 3
70
71 static DBusConnection *bus_connections[N_BUS_TYPES];
72 static char *bus_connection_addresses[N_BUS_TYPES] = { NULL, NULL, NULL };
73
74 static DBusBusType activation_bus_type = DBUS_BUS_ACTIVATION;
75
76 static dbus_bool_t initialized = FALSE;
77
78 /**
79  * Lock for globals in this file
80  */
81 _DBUS_DEFINE_GLOBAL_LOCK (bus);
82
83 static void
84 addresses_shutdown_func (void *data)
85 {
86   int i;
87
88   i = 0;
89   while (i < N_BUS_TYPES)
90     {
91       if (bus_connections[i] != NULL)
92         _dbus_warn ("dbus_shutdown() called but connections were still live!");
93       
94       dbus_free (bus_connection_addresses[i]);
95       bus_connection_addresses[i] = NULL;
96       ++i;
97     }
98
99   activation_bus_type = DBUS_BUS_ACTIVATION;
100 }
101
102 static dbus_bool_t
103 get_from_env (char           **connection_p,
104               const char      *env_var)
105 {
106   const char *s;
107   
108   _dbus_assert (*connection_p == NULL);
109   
110   s = _dbus_getenv (env_var);
111   if (s == NULL || *s == '\0')
112     return TRUE; /* successfully didn't use the env var */
113   else
114     {
115       *connection_p = _dbus_strdup (s);
116       return *connection_p != NULL;
117     }
118 }
119
120 static dbus_bool_t
121 init_connections_unlocked (void)
122 {
123   if (!initialized)
124     {
125       const char *s;
126       int i;
127
128       i = 0;
129       while (i < N_BUS_TYPES)
130         {
131           bus_connections[i] = NULL;
132           ++i;
133         }
134
135       /* Don't init these twice, we may run this code twice if
136        * init_connections_unlocked() fails midway through.
137        */
138       
139        if (bus_connection_addresses[DBUS_BUS_SYSTEM] == NULL)
140          {
141            if (!get_from_env (&bus_connection_addresses[DBUS_BUS_SYSTEM],
142                               "DBUS_SYSTEM_BUS_ADDRESS"))
143              return FALSE;
144            
145            if (bus_connection_addresses[DBUS_BUS_SYSTEM] == NULL)
146              {
147                /* Use default system bus address if none set in environment */
148                bus_connection_addresses[DBUS_BUS_SYSTEM] =
149                  _dbus_strdup ("unix:path=" DBUS_SYSTEM_BUS_PATH);
150                if (bus_connection_addresses[DBUS_BUS_SYSTEM] == NULL)
151                  return FALSE;
152              }
153          }
154           
155       if (bus_connection_addresses[DBUS_BUS_SESSION] == NULL)
156         {
157           if (!get_from_env (&bus_connection_addresses[DBUS_BUS_SESSION],
158                              "DBUS_SESSION_BUS_ADDRESS"))
159             return FALSE;
160         }
161
162       if (bus_connection_addresses[DBUS_BUS_ACTIVATION] == NULL)
163         {
164           if (!get_from_env (&bus_connection_addresses[DBUS_BUS_ACTIVATION],
165                              "DBUS_ACTIVATION_ADDRESS"))
166             return FALSE;
167         }
168
169       s = _dbus_getenv ("DBUS_ACTIVATION_BUS_TYPE");
170
171       if (s != NULL)
172         {
173           if (strcmp (s, "system") == 0)
174             activation_bus_type = DBUS_BUS_SYSTEM;
175           else if (strcmp (s, "session") == 0)
176             activation_bus_type = DBUS_BUS_SESSION;
177         }
178
179       /* If we return FALSE we have to be sure that restarting
180        * the above code will work right
181        */
182       
183       if (!_dbus_setenv ("DBUS_ACTIVATION_ADDRESS", NULL))
184         return FALSE;
185
186       if (!_dbus_setenv ("DBUS_ACTIVATION_BUS_TYPE", NULL))
187         return FALSE;
188       
189       if (!_dbus_register_shutdown_func (addresses_shutdown_func,
190                                          NULL))
191         return FALSE;
192       
193       initialized = TRUE;
194     }
195
196   return initialized;
197 }
198
199 static void
200 bus_data_free (void *data)
201 {
202   BusData *bd = data;
203   
204   if (bd->is_well_known)
205     {
206       int i;
207       _DBUS_LOCK (bus);
208       /* We may be stored in more than one slot */
209       i = 0;
210       while (i < N_BUS_TYPES)
211         {
212           if (bus_connections[i] == bd->connection)
213             bus_connections[i] = NULL;
214           
215           ++i;
216         }
217       _DBUS_UNLOCK (bus);
218     }
219   
220   dbus_free (bd->base_service);
221   dbus_free (bd);
222
223   dbus_connection_free_data_slot (&bus_data_slot);
224 }
225
226 static BusData*
227 ensure_bus_data (DBusConnection *connection)
228 {
229   BusData *bd;
230
231   if (!dbus_connection_allocate_data_slot (&bus_data_slot))
232     return NULL;
233
234   bd = dbus_connection_get_data (connection, bus_data_slot);
235   if (bd == NULL)
236     {      
237       bd = dbus_new0 (BusData, 1);
238       if (bd == NULL)
239         {
240           dbus_connection_free_data_slot (&bus_data_slot);
241           return NULL;
242         }
243
244       bd->connection = connection;
245       
246       if (!dbus_connection_set_data (connection, bus_data_slot, bd,
247                                      bus_data_free))
248         {
249           dbus_free (bd);
250           dbus_connection_free_data_slot (&bus_data_slot);
251           return NULL;
252         }
253
254       /* Data slot refcount now held by the BusData */
255     }
256   else
257     {
258       dbus_connection_free_data_slot (&bus_data_slot);
259     }
260
261   return bd;
262 }
263
264 /** @} */ /* end of implementation details docs */
265
266 /**
267  * @addtogroup DBusBus
268  * @{
269  */
270
271 /**
272  * Connects to a bus daemon and registers the client with it.
273  * If a connection to the bus already exists, then that connection is returned.
274  *
275  * @todo alex thinks we should nullify the connection when we get a disconnect-message.
276  *
277  * @param type bus type
278  * @param error address where an error can be returned.
279  * @returns a DBusConnection
280  */
281 DBusConnection *
282 dbus_bus_get (DBusBusType  type,
283               DBusError   *error)
284 {
285   const char *address;
286   DBusConnection *connection;
287   BusData *bd;
288   DBusBusType address_type;
289
290   _dbus_return_val_if_fail (type >= 0 && type < N_BUS_TYPES, NULL);
291   _dbus_return_val_if_error_is_set (error, NULL);
292
293   _DBUS_LOCK (bus);
294
295   if (!init_connections_unlocked ())
296     {
297       _DBUS_UNLOCK (bus);
298       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
299       return NULL;
300     }
301
302   /* We want to use the activation address even if the
303    * activating bus is the session or system bus,
304    * per the spec.
305    */
306   address_type = type;
307   
308   /* Use the real type of the activation bus for getting its
309    * connection. (If the activating bus isn't a well-known
310    * bus then activation_bus_type == DBUS_BUS_ACTIVATION)
311    */
312   if (type == DBUS_BUS_ACTIVATION)
313     type = activation_bus_type;
314   
315   if (bus_connections[type] != NULL)
316     {
317       connection = bus_connections[type];
318       dbus_connection_ref (connection);
319       
320       _DBUS_UNLOCK (bus);
321       return connection;
322     }
323
324   address = bus_connection_addresses[address_type];
325   if (address == NULL)
326     {
327       dbus_set_error (error, DBUS_ERROR_FAILED,
328                       "Unable to determine the address of the message bus");
329       _DBUS_UNLOCK (bus);
330       return NULL;
331     }
332
333   connection = dbus_connection_open (address, error);
334   
335   if (!connection)
336     {
337       _DBUS_ASSERT_ERROR_IS_SET (error);
338       _DBUS_UNLOCK (bus);
339       return NULL;
340     }
341
342   /* By default we're bound to the lifecycle of
343    * the message bus.
344    */
345   dbus_connection_set_exit_on_disconnect (connection,
346                                           TRUE);
347   
348   if (!dbus_bus_register (connection, error))
349     {
350       _DBUS_ASSERT_ERROR_IS_SET (error);
351       dbus_connection_disconnect (connection);
352       dbus_connection_unref (connection);
353
354       _DBUS_UNLOCK (bus);
355       return NULL;
356     }
357
358   bus_connections[type] = connection;
359   bd = ensure_bus_data (connection);
360   _dbus_assert (bd != NULL);
361
362   bd->is_well_known = TRUE;
363
364   _DBUS_UNLOCK (bus);
365   return connection;
366 }
367
368
369 /**
370  * Registers a connection with the bus. This must be the first
371  * thing an application does when connecting to the message bus.
372  * If registration succeeds, the base service name will be set,
373  * and can be obtained using dbus_bus_get_base_service().
374  *
375  * @todo if we get an error reply, it has to be converted into
376  * DBusError and returned
377  * 
378  * @param connection the connection
379  * @param error place to store errors
380  * @returns #TRUE on success
381  */
382 dbus_bool_t
383 dbus_bus_register (DBusConnection *connection,
384                    DBusError      *error)
385 {
386   DBusMessage *message, *reply;
387   char *name;
388   BusData *bd;
389   dbus_bool_t retval;
390
391   _dbus_return_val_if_fail (connection != NULL, FALSE);
392   _dbus_return_val_if_error_is_set (error, FALSE);
393
394   retval = FALSE;
395   
396   bd = ensure_bus_data (connection);
397   if (bd == NULL)
398     {
399       _DBUS_SET_OOM (error);
400       return FALSE;
401     }
402
403   if (bd->base_service != NULL)
404     {
405       _dbus_warn ("Attempt to register the same DBusConnection with the message bus, but it is already registered\n");
406       /* This isn't an error, it's a programming bug. We'll be nice
407        * and not _dbus_assert_not_reached()
408        */
409       return TRUE;
410     }
411   
412   message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
413                                           DBUS_PATH_ORG_FREEDESKTOP_DBUS,
414                                           DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
415                                           "Hello"); 
416
417   if (!message)
418     {
419       _DBUS_SET_OOM (error);
420       return FALSE;
421     }
422   
423   reply = dbus_connection_send_with_reply_and_block (connection, message, -1, error);
424
425   dbus_message_unref (message);
426   
427   if (reply == NULL)
428     goto out;
429   else if (dbus_set_error_from_message (error, reply))
430     goto out;
431   else if (!dbus_message_get_args (reply, error,
432                                    DBUS_TYPE_STRING, &name,
433                                    DBUS_TYPE_INVALID))
434     goto out;
435   
436   bd->base_service = name;
437
438   retval = TRUE;
439   
440  out:
441   if (reply)
442     dbus_message_unref (reply);
443
444   if (!retval)
445     _DBUS_ASSERT_ERROR_IS_SET (error);
446   
447   return retval;
448 }
449
450
451 /**
452  * Sets the base service name of the connection.
453  * Can only be used if you registered with the
454  * bus manually (i.e. if you did not call
455  * dbus_bus_register()). Can only be called
456  * once per connection.
457  *
458  * @param connection the connection
459  * @param base_service the base service name
460  * @returns #FALSE if not enough memory
461  */
462 dbus_bool_t
463 dbus_bus_set_base_service (DBusConnection *connection,
464                            const char     *base_service)
465 {
466   BusData *bd;
467
468   _dbus_return_val_if_fail (connection != NULL, FALSE);
469   _dbus_return_val_if_fail (base_service != NULL, FALSE);
470   
471   bd = ensure_bus_data (connection);
472   if (bd == NULL)
473     return FALSE;
474
475   _dbus_assert (bd->base_service == NULL);
476   
477   bd->base_service = _dbus_strdup (base_service);
478   return bd->base_service != NULL;
479 }
480
481 /**
482  * Gets the base service name of the connection.
483  * Only possible after the connection has been registered
484  * with the message bus.
485  *
486  * @param connection the connection
487  * @returns the base service name
488  */
489 const char*
490 dbus_bus_get_base_service (DBusConnection *connection)
491 {
492   BusData *bd;
493
494   _dbus_return_val_if_fail (connection != NULL, NULL);
495   
496   bd = ensure_bus_data (connection);
497   if (bd == NULL)
498     return NULL;
499   
500   return bd->base_service;
501 }
502
503 /**
504  * Asks the bus to try to acquire a certain service.
505  *
506  * @todo these docs are not complete, need to document the
507  * return value and flags
508  * 
509  * @todo if we get an error reply, it has to be converted into
510  * DBusError and returned
511  *
512  * @param connection the connection
513  * @param service_name the service name
514  * @param flags flags
515  * @param error location to store the error
516  * @returns a result code, -1 if error is set
517  */ 
518 int
519 dbus_bus_acquire_service (DBusConnection *connection,
520                           const char     *service_name,
521                           unsigned int    flags,
522                           DBusError      *error)
523 {
524   DBusMessage *message, *reply;
525   dbus_uint32_t service_result;
526
527   _dbus_return_val_if_fail (connection != NULL, 0);
528   _dbus_return_val_if_fail (service_name != NULL, 0);
529   _dbus_return_val_if_error_is_set (error, 0);
530   
531   message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
532                                           DBUS_PATH_ORG_FREEDESKTOP_DBUS,
533                                           DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
534                                           "AcquireService");
535
536   if (message == NULL)
537     {
538       _DBUS_SET_OOM (error);
539       return -1;
540     }
541  
542   if (!dbus_message_append_args (message,
543                                  DBUS_TYPE_STRING, service_name,
544                                  DBUS_TYPE_UINT32, flags,
545                                  DBUS_TYPE_INVALID))
546     {
547       dbus_message_unref (message);
548       _DBUS_SET_OOM (error);
549       return -1;
550     }
551   
552   reply = dbus_connection_send_with_reply_and_block (connection, message, -1,
553                                                      error);
554   
555   dbus_message_unref (message);
556   
557   if (reply == NULL)
558     {
559       _DBUS_ASSERT_ERROR_IS_SET (error);
560       return -1;
561     }  
562
563   if (dbus_set_error_from_message (error, reply))
564     {
565       _DBUS_ASSERT_ERROR_IS_SET (error);
566       dbus_message_unref (reply);
567       return -1;
568     }
569   
570   if (!dbus_message_get_args (reply, error,
571                               DBUS_TYPE_UINT32, &service_result,
572                               DBUS_TYPE_INVALID))
573     {
574       _DBUS_ASSERT_ERROR_IS_SET (error);
575       dbus_message_unref (reply);
576       return -1;
577     }
578
579   dbus_message_unref (reply);
580   
581   return service_result;
582 }
583
584 /**
585  * Checks whether a certain service exists.
586  *
587  * @todo the SERVICE_EXISTS message should use BOOLEAN not UINT32
588  *
589  * @param connection the connection
590  * @param service_name the service name
591  * @param error location to store any errors
592  * @returns #TRUE if the service exists, #FALSE if not or on error
593  */
594 dbus_bool_t
595 dbus_bus_service_exists (DBusConnection *connection,
596                          const char     *service_name,
597                          DBusError      *error)
598 {
599   DBusMessage *message, *reply;
600   unsigned int exists;
601
602   _dbus_return_val_if_fail (connection != NULL, FALSE);
603   _dbus_return_val_if_fail (service_name != NULL, FALSE);
604   _dbus_return_val_if_error_is_set (error, FALSE);
605   
606   message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
607                                           DBUS_PATH_ORG_FREEDESKTOP_DBUS,
608                                           DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
609                                           "ServiceExists");
610   if (message == NULL)
611     {
612       _DBUS_SET_OOM (error);
613       return FALSE;
614     }
615   
616   if (!dbus_message_append_args (message,
617                                  DBUS_TYPE_STRING, service_name,
618                                  DBUS_TYPE_INVALID))
619     {
620       dbus_message_unref (message);
621       _DBUS_SET_OOM (error);
622       return FALSE;
623     }
624   
625   reply = dbus_connection_send_with_reply_and_block (connection, message, -1, error);
626   dbus_message_unref (message);
627
628   if (reply == NULL)
629     {
630       _DBUS_ASSERT_ERROR_IS_SET (error);
631       return FALSE;
632     }
633
634   if (!dbus_message_get_args (reply, error,
635                               DBUS_TYPE_UINT32, &exists,
636                               DBUS_TYPE_INVALID))
637     {
638       _DBUS_ASSERT_ERROR_IS_SET (error);
639       return FALSE;
640     }
641   
642   return (exists != FALSE);
643 }
644
645 /**
646  * Activates a given service
647  *
648  * @param connection the connection
649  * @param service_name the service name
650  * @param flags the flags
651  * @param result a place to store the result of the activation, which will
652  * be one of DBUS_ACTIVATION_REPLY_ACTIVATED or
653  * DBUS_ACTIVATION_REPLY_ALREADY_ACTIVE if successful.  Pass NULL if you
654  * don't care about the result.
655  * @param error location to store any errors
656  * @returns #TRUE if the activation succeeded, #FALSE if not
657  *
658  * @todo document what the flags do
659  */
660 dbus_bool_t
661 dbus_bus_activate_service (DBusConnection *connection,
662                            const char     *service_name,
663                            dbus_uint32_t   flags,
664                            dbus_uint32_t  *result,
665                            DBusError      *error)
666 {
667   DBusMessage *msg;
668   DBusMessage *reply;
669
670   msg = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
671                                       DBUS_PATH_ORG_FREEDESKTOP_DBUS,
672                                       DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
673                                       "ActivateService");
674
675   if (!dbus_message_append_args (msg, DBUS_TYPE_STRING, service_name,
676                                  DBUS_TYPE_UINT32, flags, DBUS_TYPE_INVALID))
677     {
678       dbus_message_unref (msg);
679       _DBUS_SET_OOM (error);
680       return FALSE;
681     }
682
683   reply = dbus_connection_send_with_reply_and_block (connection, msg,
684                                                      -1, error);
685   dbus_message_unref (msg);
686
687   if (reply == NULL)
688     {
689       _DBUS_ASSERT_ERROR_IS_SET (error);
690       return FALSE;
691     }
692
693   if (dbus_set_error_from_message (error, reply))
694     {
695       _DBUS_ASSERT_ERROR_IS_SET (error);
696       dbus_message_unref (reply);
697       return FALSE;
698     }
699
700   if (result != NULL &&
701       !dbus_message_get_args (reply, error, DBUS_TYPE_UINT32,
702                               result, DBUS_TYPE_INVALID))
703     {
704       _DBUS_ASSERT_ERROR_IS_SET (error);
705       dbus_message_unref (reply);
706       return FALSE;
707     }
708   
709   dbus_message_unref (reply);
710   return TRUE;
711 }
712
713 static void
714 send_no_return_values (DBusConnection *connection,
715                        DBusMessage    *msg,
716                        DBusError      *error)
717 {
718   if (error)
719     {
720       /* Block to check success codepath */
721       DBusMessage *reply;
722       
723       reply = dbus_connection_send_with_reply_and_block (connection, msg,
724                                                          -1, error);
725       
726       if (reply == NULL)
727         {
728           _DBUS_ASSERT_ERROR_IS_SET (error);
729           return;
730         }
731
732       if (dbus_set_error_from_message (error, reply))
733         {
734           _DBUS_ASSERT_ERROR_IS_SET (error);
735           dbus_message_unref (reply);
736           return;
737         }
738
739       dbus_message_unref (reply);
740     }
741   else
742     {
743       /* Silently-fail nonblocking codepath */
744       if (!dbus_connection_send (connection, msg, NULL))
745         return;
746     }
747 }
748
749 /**
750  * Adds a match rule to match messages going through the message bus.
751  * The "rule" argument is the string form of a match rule.
752  *
753  * If you pass #NULL for the error, this function will not
754  * block; the match thus won't be added until you flush the
755  * connection, and if there's an error adding the match
756  * (only possible error is lack of resources in the bus),
757  * you won't find out about it.
758  *
759  * If you pass non-#NULL for the error this function will
760  * block until it gets a reply.
761  *
762  * Normal API conventions would have the function return
763  * a boolean value indicating whether the error was set,
764  * but that would require blocking always to determine
765  * the return value.
766  * 
767  * @param connection connection to the message bus
768  * @param rule textual form of match rule
769  * @param error location to store any errors
770  */
771 void
772 dbus_bus_add_match (DBusConnection *connection,
773                     const char     *rule,
774                     DBusError      *error)
775 {
776   DBusMessage *msg;
777
778   msg = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
779                                       DBUS_PATH_ORG_FREEDESKTOP_DBUS,
780                                       DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
781                                       "AddMatch");
782
783   if (!dbus_message_append_args (msg, DBUS_TYPE_STRING, rule,
784                                  DBUS_TYPE_INVALID))
785     {
786       dbus_message_unref (msg);
787       _DBUS_SET_OOM (error);
788       return;
789     }
790
791   send_no_return_values (connection, msg, error);
792
793   dbus_message_unref (msg);
794 }
795
796 /**
797  * Removes a previously-added match rule "by value" (the most
798  * recently-added identical rule gets removed).  The "rule" argument
799  * is the string form of a match rule.
800  *
801  * If you pass #NULL for the error, this function will not
802  * block; otherwise it will. See detailed explanation in
803  * docs for dbus_bus_add_match().
804  * 
805  * @param connection connection to the message bus
806  * @param rule textual form of match rule
807  * @param error location to store any errors
808  */
809 void
810 dbus_bus_remove_match (DBusConnection *connection,
811                        const char     *rule,
812                        DBusError      *error)
813 {
814   DBusMessage *msg;
815
816   msg = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
817                                       DBUS_PATH_ORG_FREEDESKTOP_DBUS,
818                                       DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
819                                       "RemoveMatch");
820
821   if (!dbus_message_append_args (msg, DBUS_TYPE_STRING, rule,
822                                  DBUS_TYPE_INVALID))
823     {
824       dbus_message_unref (msg);
825       _DBUS_SET_OOM (error);
826       return;
827     }
828
829   send_no_return_values (connection, msg, error);
830
831   dbus_message_unref (msg);
832 }
833
834 /** @} */