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