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