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