driver.c revision dc33f4f7749ed303374ebdf00e48ea8a471afd25
1/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2/* driver.c  Bus client (driver)
3 *
4 * Copyright (C) 2003 CodeFactory AB
5 * Copyright (C) 2003, 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22 *
23 */
24
25#include "activation.h"
26#include "connection.h"
27#include "driver.h"
28#include "dispatch.h"
29#include "services.h"
30#include "selinux.h"
31#include "signals.h"
32#include "utils.h"
33#include <dbus/dbus-string.h>
34#include <dbus/dbus-internals.h>
35#include <dbus/dbus-marshal-recursive.h>
36#include <string.h>
37
38static dbus_bool_t bus_driver_send_welcome_message (DBusConnection *connection,
39                                                    DBusMessage    *hello_message,
40                                                    BusTransaction *transaction,
41                                                    DBusError      *error);
42
43dbus_bool_t
44bus_driver_send_service_owner_changed (const char     *service_name,
45				       const char     *old_owner,
46				       const char     *new_owner,
47				       BusTransaction *transaction,
48				       DBusError      *error)
49{
50  DBusMessage *message;
51  dbus_bool_t retval;
52  const char *null_service;
53
54  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
55
56  null_service = "";
57  _dbus_verbose ("sending name owner changed: %s [%s -> %s]\n",
58                 service_name,
59                 old_owner ? old_owner : null_service,
60                 new_owner ? new_owner : null_service);
61
62  message = dbus_message_new_signal (DBUS_PATH_DBUS,
63                                     DBUS_INTERFACE_DBUS,
64                                     "NameOwnerChanged");
65
66  if (message == NULL)
67    {
68      BUS_SET_OOM (error);
69      return FALSE;
70    }
71
72  if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS))
73    goto oom;
74
75  if (!dbus_message_append_args (message,
76                                 DBUS_TYPE_STRING, &service_name,
77                                 DBUS_TYPE_STRING, old_owner ? &old_owner : &null_service,
78                                 DBUS_TYPE_STRING, new_owner ? &new_owner : &null_service,
79                                 DBUS_TYPE_INVALID))
80    goto oom;
81
82  _dbus_assert (dbus_message_has_signature (message, "sss"));
83
84  retval = bus_dispatch_matches (transaction, NULL, NULL, message, error);
85  dbus_message_unref (message);
86
87  return retval;
88
89 oom:
90  dbus_message_unref (message);
91  BUS_SET_OOM (error);
92  return FALSE;
93}
94
95dbus_bool_t
96bus_driver_send_service_lost (DBusConnection *connection,
97			      const char     *service_name,
98                              BusTransaction *transaction,
99                              DBusError      *error)
100{
101  DBusMessage *message;
102
103  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
104
105  message = dbus_message_new_signal (DBUS_PATH_DBUS,
106                                     DBUS_INTERFACE_DBUS,
107                                     "NameLost");
108
109  if (message == NULL)
110    {
111      BUS_SET_OOM (error);
112      return FALSE;
113    }
114
115  if (!dbus_message_set_destination (message, bus_connection_get_name (connection)) ||
116      !dbus_message_append_args (message,
117                                 DBUS_TYPE_STRING, &service_name,
118                                 DBUS_TYPE_INVALID))
119    {
120      dbus_message_unref (message);
121      BUS_SET_OOM (error);
122      return FALSE;
123    }
124
125  if (!bus_transaction_send_from_driver (transaction, connection, message))
126    {
127      dbus_message_unref (message);
128      BUS_SET_OOM (error);
129      return FALSE;
130    }
131  else
132    {
133      dbus_message_unref (message);
134      return TRUE;
135    }
136}
137
138dbus_bool_t
139bus_driver_send_service_acquired (DBusConnection *connection,
140                                  const char     *service_name,
141                                  BusTransaction *transaction,
142                                  DBusError      *error)
143{
144  DBusMessage *message;
145
146  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
147
148  message = dbus_message_new_signal (DBUS_PATH_DBUS,
149                                     DBUS_INTERFACE_DBUS,
150                                     "NameAcquired");
151
152  if (message == NULL)
153    {
154      BUS_SET_OOM (error);
155      return FALSE;
156    }
157
158  if (!dbus_message_set_destination (message, bus_connection_get_name (connection)) ||
159      !dbus_message_append_args (message,
160                                 DBUS_TYPE_STRING, &service_name,
161                                 DBUS_TYPE_INVALID))
162    {
163      dbus_message_unref (message);
164      BUS_SET_OOM (error);
165      return FALSE;
166    }
167
168  if (!bus_transaction_send_from_driver (transaction, connection, message))
169    {
170      dbus_message_unref (message);
171      BUS_SET_OOM (error);
172      return FALSE;
173    }
174  else
175    {
176      dbus_message_unref (message);
177      return TRUE;
178    }
179}
180
181static dbus_bool_t
182create_unique_client_name (BusRegistry *registry,
183                           DBusString  *str)
184{
185  /* We never want to use the same unique client name twice, because
186   * we want to guarantee that if you send a message to a given unique
187   * name, you always get the same application. So we use two numbers
188   * for INT_MAX * INT_MAX combinations, should be pretty safe against
189   * wraparound.
190   */
191  /* FIXME these should be in BusRegistry rather than static vars */
192  static int next_major_number = 0;
193  static int next_minor_number = 0;
194  int len;
195
196  len = _dbus_string_get_length (str);
197
198  while (TRUE)
199    {
200      /* start out with 1-0, go to 1-1, 1-2, 1-3,
201       * up to 1-MAXINT, then 2-0, 2-1, etc.
202       */
203      if (next_minor_number <= 0)
204        {
205          next_major_number += 1;
206          next_minor_number = 0;
207          if (next_major_number <= 0)
208            _dbus_assert_not_reached ("INT_MAX * INT_MAX clients were added");
209        }
210
211      _dbus_assert (next_major_number > 0);
212      _dbus_assert (next_minor_number >= 0);
213
214      /* appname:MAJOR-MINOR */
215
216      if (!_dbus_string_append (str, ":"))
217        return FALSE;
218
219      if (!_dbus_string_append_int (str, next_major_number))
220        return FALSE;
221
222      if (!_dbus_string_append (str, "."))
223        return FALSE;
224
225      if (!_dbus_string_append_int (str, next_minor_number))
226        return FALSE;
227
228      next_minor_number += 1;
229
230      /* Check if a client with the name exists */
231      if (bus_registry_lookup (registry, str) == NULL)
232	break;
233
234      /* drop the number again, try the next one. */
235      _dbus_string_set_length (str, len);
236    }
237
238  return TRUE;
239}
240
241static dbus_bool_t
242bus_driver_handle_hello (DBusConnection *connection,
243                         BusTransaction *transaction,
244                         DBusMessage    *message,
245                         DBusError      *error)
246{
247  DBusString unique_name;
248  BusService *service;
249  dbus_bool_t retval;
250  BusRegistry *registry;
251  BusConnections *connections;
252
253  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
254
255  if (bus_connection_is_active (connection))
256    {
257      /* We already handled an Hello message for this connection. */
258      dbus_set_error (error, DBUS_ERROR_FAILED,
259                      "Already handled an Hello message");
260      return FALSE;
261    }
262
263  /* Note that when these limits are exceeded we don't disconnect the
264   * connection; we just sort of leave it hanging there until it times
265   * out or disconnects itself or is dropped due to the max number of
266   * incomplete connections. It's even OK if the connection wants to
267   * retry the hello message, we support that.
268   */
269  connections = bus_connection_get_connections (connection);
270  if (!bus_connections_check_limits (connections, connection,
271                                     error))
272    {
273      _DBUS_ASSERT_ERROR_IS_SET (error);
274      return FALSE;
275    }
276
277  if (!_dbus_string_init (&unique_name))
278    {
279      BUS_SET_OOM (error);
280      return FALSE;
281    }
282
283  retval = FALSE;
284
285  registry = bus_connection_get_registry (connection);
286
287  if (!create_unique_client_name (registry, &unique_name))
288    {
289      BUS_SET_OOM (error);
290      goto out_0;
291    }
292
293  if (!bus_connection_complete (connection, &unique_name, error))
294    {
295      _DBUS_ASSERT_ERROR_IS_SET (error);
296      goto out_0;
297    }
298
299  if (!dbus_message_set_sender (message,
300                                bus_connection_get_name (connection)))
301    {
302      BUS_SET_OOM (error);
303      goto out_0;
304    }
305
306  if (!bus_driver_send_welcome_message (connection, message, transaction, error))
307    goto out_0;
308
309  /* Create the service */
310  service = bus_registry_ensure (registry,
311                                 &unique_name, connection, 0, transaction, error);
312  if (service == NULL)
313    goto out_0;
314
315  _dbus_assert (bus_connection_is_active (connection));
316  retval = TRUE;
317
318 out_0:
319  _dbus_string_free (&unique_name);
320  return retval;
321}
322
323static dbus_bool_t
324bus_driver_send_welcome_message (DBusConnection *connection,
325                                 DBusMessage    *hello_message,
326                                 BusTransaction *transaction,
327                                 DBusError      *error)
328{
329  DBusMessage *welcome;
330  const char *name;
331
332  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
333
334  name = bus_connection_get_name (connection);
335  _dbus_assert (name != NULL);
336
337  welcome = dbus_message_new_method_return (hello_message);
338  if (welcome == NULL)
339    {
340      BUS_SET_OOM (error);
341      return FALSE;
342    }
343
344  if (!dbus_message_append_args (welcome,
345                                 DBUS_TYPE_STRING, &name,
346                                 DBUS_TYPE_INVALID))
347    {
348      dbus_message_unref (welcome);
349      BUS_SET_OOM (error);
350      return FALSE;
351    }
352
353  _dbus_assert (dbus_message_has_signature (welcome, DBUS_TYPE_STRING_AS_STRING));
354
355  if (!bus_transaction_send_from_driver (transaction, connection, welcome))
356    {
357      dbus_message_unref (welcome);
358      BUS_SET_OOM (error);
359      return FALSE;
360    }
361  else
362    {
363      dbus_message_unref (welcome);
364      return TRUE;
365    }
366}
367
368static dbus_bool_t
369bus_driver_handle_list_services (DBusConnection *connection,
370                                 BusTransaction *transaction,
371                                 DBusMessage    *message,
372                                 DBusError      *error)
373{
374  DBusMessage *reply;
375  int len;
376  char **services;
377  BusRegistry *registry;
378  int i;
379  DBusMessageIter iter;
380  DBusMessageIter sub;
381
382  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
383
384  registry = bus_connection_get_registry (connection);
385
386  reply = dbus_message_new_method_return (message);
387  if (reply == NULL)
388    {
389      BUS_SET_OOM (error);
390      return FALSE;
391    }
392
393  if (!bus_registry_list_services (registry, &services, &len))
394    {
395      dbus_message_unref (reply);
396      BUS_SET_OOM (error);
397      return FALSE;
398    }
399
400  dbus_message_iter_init_append (reply, &iter);
401
402  if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY,
403                                         DBUS_TYPE_STRING_AS_STRING,
404                                         &sub))
405    {
406      dbus_free_string_array (services);
407      dbus_message_unref (reply);
408      BUS_SET_OOM (error);
409      return FALSE;
410    }
411
412  {
413    /* Include the bus driver in the list */
414    const char *v_STRING = DBUS_SERVICE_DBUS;
415    if (!dbus_message_iter_append_basic (&sub, DBUS_TYPE_STRING,
416                                         &v_STRING))
417      {
418        dbus_free_string_array (services);
419        dbus_message_unref (reply);
420        BUS_SET_OOM (error);
421        return FALSE;
422      }
423  }
424
425  i = 0;
426  while (i < len)
427    {
428      if (!dbus_message_iter_append_basic (&sub, DBUS_TYPE_STRING,
429                                           &services[i]))
430        {
431          dbus_free_string_array (services);
432          dbus_message_unref (reply);
433          BUS_SET_OOM (error);
434          return FALSE;
435        }
436      ++i;
437    }
438
439  dbus_free_string_array (services);
440
441  if (!dbus_message_iter_close_container (&iter, &sub))
442    {
443      dbus_message_unref (reply);
444      BUS_SET_OOM (error);
445      return FALSE;
446    }
447
448  if (!bus_transaction_send_from_driver (transaction, connection, reply))
449    {
450      dbus_message_unref (reply);
451      BUS_SET_OOM (error);
452      return FALSE;
453    }
454  else
455    {
456      dbus_message_unref (reply);
457      return TRUE;
458    }
459}
460
461static dbus_bool_t
462bus_driver_handle_list_activatable_services (DBusConnection *connection,
463					     BusTransaction *transaction,
464					     DBusMessage    *message,
465					     DBusError      *error)
466{
467  DBusMessage *reply;
468  int len;
469  char **services;
470  BusActivation *activation;
471  int i;
472  DBusMessageIter iter;
473  DBusMessageIter sub;
474
475  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
476
477  activation = bus_connection_get_activation (connection);
478
479  reply = dbus_message_new_method_return (message);
480  if (reply == NULL)
481    {
482      BUS_SET_OOM (error);
483      return FALSE;
484    }
485
486  if (!bus_activation_list_services (activation, &services, &len))
487    {
488      dbus_message_unref (reply);
489      BUS_SET_OOM (error);
490      return FALSE;
491    }
492
493  dbus_message_iter_init_append (reply, &iter);
494
495  if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY,
496					 DBUS_TYPE_STRING_AS_STRING,
497					 &sub))
498    {
499      dbus_free_string_array (services);
500      dbus_message_unref (reply);
501      BUS_SET_OOM (error);
502      return FALSE;
503    }
504
505  {
506    /* Include the bus driver in the list */
507    const char *v_STRING = DBUS_SERVICE_DBUS;
508    if (!dbus_message_iter_append_basic (&sub, DBUS_TYPE_STRING,
509					 &v_STRING))
510      {
511	dbus_free_string_array (services);
512	dbus_message_unref (reply);
513	BUS_SET_OOM (error);
514	return FALSE;
515      }
516  }
517
518  i = 0;
519  while (i < len)
520    {
521      if (!dbus_message_iter_append_basic (&sub, DBUS_TYPE_STRING,
522					   &services[i]))
523	{
524	  dbus_free_string_array (services);
525	  dbus_message_unref (reply);
526	  BUS_SET_OOM (error);
527	  return FALSE;
528	}
529      ++i;
530    }
531
532  dbus_free_string_array (services);
533
534  if (!dbus_message_iter_close_container (&iter, &sub))
535    {
536      dbus_message_unref (reply);
537      BUS_SET_OOM (error);
538      return FALSE;
539    }
540
541  if (!bus_transaction_send_from_driver (transaction, connection, reply))
542    {
543      dbus_message_unref (reply);
544      BUS_SET_OOM (error);
545      return FALSE;
546    }
547  else
548    {
549      dbus_message_unref (reply);
550      return TRUE;
551    }
552}
553
554static dbus_bool_t
555bus_driver_handle_acquire_service (DBusConnection *connection,
556                                   BusTransaction *transaction,
557                                   DBusMessage    *message,
558                                   DBusError      *error)
559{
560  DBusMessage *reply;
561  DBusString service_name;
562  const char *name;
563  dbus_uint32_t service_reply;
564  dbus_uint32_t flags;
565  dbus_bool_t retval;
566  BusRegistry *registry;
567
568  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
569
570  registry = bus_connection_get_registry (connection);
571
572  if (!dbus_message_get_args (message, error,
573                              DBUS_TYPE_STRING, &name,
574                              DBUS_TYPE_UINT32, &flags,
575                              DBUS_TYPE_INVALID))
576    return FALSE;
577
578  _dbus_verbose ("Trying to own name %s with flags 0x%x\n", name, flags);
579
580  retval = FALSE;
581  reply = NULL;
582
583  _dbus_string_init_const (&service_name, name);
584
585  if (!bus_registry_acquire_service (registry, connection,
586                                     &service_name, flags,
587                                     &service_reply, transaction,
588                                     error))
589    goto out;
590
591  reply = dbus_message_new_method_return (message);
592  if (reply == NULL)
593    {
594      BUS_SET_OOM (error);
595      goto out;
596    }
597
598  if (!dbus_message_append_args (reply, DBUS_TYPE_UINT32, &service_reply, DBUS_TYPE_INVALID))
599    {
600      BUS_SET_OOM (error);
601      goto out;
602    }
603
604  if (!bus_transaction_send_from_driver (transaction, connection, reply))
605    {
606      BUS_SET_OOM (error);
607      goto out;
608    }
609
610  retval = TRUE;
611
612 out:
613  if (reply)
614    dbus_message_unref (reply);
615  return retval;
616}
617
618static dbus_bool_t
619bus_driver_handle_release_service (DBusConnection *connection,
620                                   BusTransaction *transaction,
621                                   DBusMessage    *message,
622                                   DBusError      *error)
623{
624  DBusMessage *reply;
625  DBusString service_name;
626  const char *name;
627  dbus_uint32_t service_reply;
628  dbus_bool_t retval;
629  BusRegistry *registry;
630
631  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
632
633  registry = bus_connection_get_registry (connection);
634
635  if (!dbus_message_get_args (message, error,
636                              DBUS_TYPE_STRING, &name,
637                              DBUS_TYPE_INVALID))
638    return FALSE;
639
640  _dbus_verbose ("Trying to release name %s\n", name);
641
642  retval = FALSE;
643  reply = NULL;
644
645  _dbus_string_init_const (&service_name, name);
646
647  if (!bus_registry_release_service (registry, connection,
648                                     &service_name, &service_reply,
649                                     transaction, error))
650    goto out;
651
652  reply = dbus_message_new_method_return (message);
653  if (reply == NULL)
654    {
655      BUS_SET_OOM (error);
656      goto out;
657    }
658
659  if (!dbus_message_append_args (reply, DBUS_TYPE_UINT32, &service_reply, DBUS_TYPE_INVALID))
660    {
661      BUS_SET_OOM (error);
662      goto out;
663    }
664
665  if (!bus_transaction_send_from_driver (transaction, connection, reply))
666    {
667      BUS_SET_OOM (error);
668      goto out;
669    }
670
671  retval = TRUE;
672
673 out:
674  if (reply)
675    dbus_message_unref (reply);
676  return retval;
677}
678
679static dbus_bool_t
680bus_driver_handle_service_exists (DBusConnection *connection,
681                                  BusTransaction *transaction,
682                                  DBusMessage    *message,
683                                  DBusError      *error)
684{
685  DBusMessage *reply;
686  DBusString service_name;
687  BusService *service;
688  dbus_bool_t service_exists;
689  const char *name;
690  dbus_bool_t retval;
691  BusRegistry *registry;
692
693  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
694
695  registry = bus_connection_get_registry (connection);
696
697  if (!dbus_message_get_args (message, error,
698                              DBUS_TYPE_STRING, &name,
699                              DBUS_TYPE_INVALID))
700    return FALSE;
701
702  retval = FALSE;
703
704  if (strcmp (name, DBUS_SERVICE_DBUS) == 0)
705    {
706      service_exists = TRUE;
707    }
708  else
709    {
710      _dbus_string_init_const (&service_name, name);
711      service = bus_registry_lookup (registry, &service_name);
712      service_exists = service != NULL;
713    }
714
715  reply = dbus_message_new_method_return (message);
716  if (reply == NULL)
717    {
718      BUS_SET_OOM (error);
719      goto out;
720    }
721
722  if (!dbus_message_append_args (reply,
723                                 DBUS_TYPE_BOOLEAN, &service_exists,
724                                 0))
725    {
726      BUS_SET_OOM (error);
727      goto out;
728    }
729
730  if (!bus_transaction_send_from_driver (transaction, connection, reply))
731    {
732      BUS_SET_OOM (error);
733      goto out;
734    }
735
736  retval = TRUE;
737
738 out:
739  if (reply)
740    dbus_message_unref (reply);
741
742  return retval;
743}
744
745static dbus_bool_t
746bus_driver_handle_activate_service (DBusConnection *connection,
747                                    BusTransaction *transaction,
748                                    DBusMessage    *message,
749                                    DBusError      *error)
750{
751  dbus_uint32_t flags;
752  const char *name;
753  dbus_bool_t retval;
754  BusActivation *activation;
755
756  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
757
758  activation = bus_connection_get_activation (connection);
759
760  if (!dbus_message_get_args (message, error,
761                              DBUS_TYPE_STRING, &name,
762                              DBUS_TYPE_UINT32, &flags,
763                              DBUS_TYPE_INVALID))
764    {
765      _DBUS_ASSERT_ERROR_IS_SET (error);
766      _dbus_verbose ("No memory to get arguments to StartServiceByName\n");
767      return FALSE;
768    }
769
770  retval = FALSE;
771
772  if (!bus_activation_activate_service (activation, connection, transaction, FALSE,
773                                        message, name, error))
774    {
775      _DBUS_ASSERT_ERROR_IS_SET (error);
776      _dbus_verbose ("bus_activation_activate_service() failed\n");
777      goto out;
778    }
779
780  retval = TRUE;
781
782 out:
783  return retval;
784}
785
786static dbus_bool_t
787send_ack_reply (DBusConnection *connection,
788                BusTransaction *transaction,
789                DBusMessage    *message,
790                DBusError      *error)
791{
792  DBusMessage *reply;
793
794  reply = dbus_message_new_method_return (message);
795  if (reply == NULL)
796    {
797      BUS_SET_OOM (error);
798      return FALSE;
799    }
800
801  if (!bus_transaction_send_from_driver (transaction, connection, reply))
802    {
803      BUS_SET_OOM (error);
804      dbus_message_unref (reply);
805      return FALSE;
806    }
807
808  dbus_message_unref (reply);
809
810  return TRUE;
811}
812
813static dbus_bool_t
814bus_driver_handle_update_activation_environment (DBusConnection *connection,
815                                                 BusTransaction *transaction,
816                                                 DBusMessage    *message,
817                                                 DBusError      *error)
818{
819  dbus_bool_t retval;
820  BusActivation *activation;
821  DBusMessageIter iter;
822  DBusMessageIter dict_iter;
823  DBusMessageIter dict_entry_iter;
824  int msg_type;
825  int array_type;
826  int key_type;
827  DBusList *keys, *key_link;
828  DBusList *values, *value_link;
829
830  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
831
832  activation = bus_connection_get_activation (connection);
833
834  dbus_message_iter_init (message, &iter);
835
836  /* The message signature has already been checked for us,
837   * so let's just assert it's right.
838   */
839  msg_type = dbus_message_iter_get_arg_type (&iter);
840
841  _dbus_assert (msg_type == DBUS_TYPE_ARRAY);
842
843  dbus_message_iter_recurse (&iter, &dict_iter);
844
845  retval = FALSE;
846
847  /* Then loop through the sent dictionary, add the location of
848   * the environment keys and values to lists. The result will
849   * be in reverse order, so we don't have to constantly search
850   * for the end of the list in a loop.
851   */
852  keys = NULL;
853  values = NULL;
854  while ((array_type = dbus_message_iter_get_arg_type (&dict_iter)) == DBUS_TYPE_DICT_ENTRY)
855    {
856      dbus_message_iter_recurse (&dict_iter, &dict_entry_iter);
857
858      while ((key_type = dbus_message_iter_get_arg_type (&dict_entry_iter)) == DBUS_TYPE_STRING)
859        {
860          char *key;
861          char *value;
862          int value_type;
863
864          dbus_message_iter_get_basic (&dict_entry_iter, &key);
865          dbus_message_iter_next (&dict_entry_iter);
866
867          value_type = dbus_message_iter_get_arg_type (&dict_entry_iter);
868
869          if (value_type != DBUS_TYPE_STRING)
870            break;
871
872          dbus_message_iter_get_basic (&dict_entry_iter, &value);
873
874          if (!_dbus_list_append (&keys, key))
875            {
876              BUS_SET_OOM (error);
877              break;
878            }
879
880          if (!_dbus_list_append (&values, value))
881            {
882              BUS_SET_OOM (error);
883              break;
884            }
885
886          dbus_message_iter_next (&dict_entry_iter);
887        }
888
889      if (key_type != DBUS_TYPE_INVALID)
890        break;
891
892      dbus_message_iter_next (&dict_iter);
893    }
894
895  if (array_type != DBUS_TYPE_INVALID)
896    goto out;
897
898  _dbus_assert (_dbus_list_get_length (&keys) == _dbus_list_get_length (&values));
899
900  key_link = keys;
901  value_link = values;
902  while (key_link != NULL)
903  {
904      const char *key;
905      const char *value;
906
907      key = key_link->data;
908      value = value_link->data;
909
910      if (!bus_activation_set_environment_variable (activation,
911                                                    key, value, error))
912      {
913          _DBUS_ASSERT_ERROR_IS_SET (error);
914          _dbus_verbose ("bus_activation_set_environment_variable() failed\n");
915          break;
916      }
917      key_link = _dbus_list_get_next_link (&keys, key_link);
918      value_link = _dbus_list_get_next_link (&values, value_link);
919  }
920
921  /* FIXME: We can fail early having set only some of the environment variables,
922   * (because of OOM failure).  It's sort of hard to fix and it doesn't really
923   * matter, so we're punting for now.
924   */
925  if (key_link != NULL)
926    goto out;
927
928  if (!send_ack_reply (connection, transaction,
929                       message, error))
930    goto out;
931
932  retval = TRUE;
933
934 out:
935  _dbus_list_clear (&keys);
936  _dbus_list_clear (&values);
937  return retval;
938}
939
940static dbus_bool_t
941bus_driver_handle_add_match (DBusConnection *connection,
942                             BusTransaction *transaction,
943                             DBusMessage    *message,
944                             DBusError      *error)
945{
946  BusMatchRule *rule;
947  const char *text;
948  DBusString str;
949  BusMatchmaker *matchmaker;
950
951  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
952
953  text = NULL;
954  rule = NULL;
955
956  if (bus_connection_get_n_match_rules (connection) >=
957      bus_context_get_max_match_rules_per_connection (bus_transaction_get_context (transaction)))
958    {
959      dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
960                      "Connection \"%s\" is not allowed to add more match rules "
961                      "(increase limits in configuration file if required)",
962                      bus_connection_is_active (connection) ?
963                      bus_connection_get_name (connection) :
964                      "(inactive)");
965      goto failed;
966    }
967
968  if (!dbus_message_get_args (message, error,
969                              DBUS_TYPE_STRING, &text,
970                              DBUS_TYPE_INVALID))
971    {
972      _dbus_verbose ("No memory to get arguments to AddMatch\n");
973      goto failed;
974    }
975
976  _dbus_string_init_const (&str, text);
977
978  rule = bus_match_rule_parse (connection, &str, error);
979  if (rule == NULL)
980    goto failed;
981
982  matchmaker = bus_connection_get_matchmaker (connection);
983
984  if (!bus_matchmaker_add_rule (matchmaker, rule))
985    {
986      BUS_SET_OOM (error);
987      goto failed;
988    }
989
990  if (!send_ack_reply (connection, transaction,
991                       message, error))
992    {
993      bus_matchmaker_remove_rule (matchmaker, rule);
994      goto failed;
995    }
996
997  bus_match_rule_unref (rule);
998
999  return TRUE;
1000
1001 failed:
1002  _DBUS_ASSERT_ERROR_IS_SET (error);
1003  if (rule)
1004    bus_match_rule_unref (rule);
1005  return FALSE;
1006}
1007
1008static dbus_bool_t
1009bus_driver_handle_remove_match (DBusConnection *connection,
1010                                BusTransaction *transaction,
1011                                DBusMessage    *message,
1012                                DBusError      *error)
1013{
1014  BusMatchRule *rule;
1015  const char *text;
1016  DBusString str;
1017  BusMatchmaker *matchmaker;
1018
1019  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1020
1021  text = NULL;
1022  rule = NULL;
1023
1024  if (!dbus_message_get_args (message, error,
1025                              DBUS_TYPE_STRING, &text,
1026                              DBUS_TYPE_INVALID))
1027    {
1028      _dbus_verbose ("No memory to get arguments to RemoveMatch\n");
1029      goto failed;
1030    }
1031
1032  _dbus_string_init_const (&str, text);
1033
1034  rule = bus_match_rule_parse (connection, &str, error);
1035  if (rule == NULL)
1036    goto failed;
1037
1038  /* Send the ack before we remove the rule, since the ack is undone
1039   * on transaction cancel, but rule removal isn't.
1040   */
1041  if (!send_ack_reply (connection, transaction,
1042                       message, error))
1043    goto failed;
1044
1045  matchmaker = bus_connection_get_matchmaker (connection);
1046
1047  if (!bus_matchmaker_remove_rule_by_value (matchmaker, rule, error))
1048    goto failed;
1049
1050  bus_match_rule_unref (rule);
1051
1052  return TRUE;
1053
1054 failed:
1055  _DBUS_ASSERT_ERROR_IS_SET (error);
1056  if (rule)
1057    bus_match_rule_unref (rule);
1058  return FALSE;
1059}
1060
1061static dbus_bool_t
1062bus_driver_handle_get_service_owner (DBusConnection *connection,
1063				     BusTransaction *transaction,
1064				     DBusMessage    *message,
1065				     DBusError      *error)
1066{
1067  const char *text;
1068  const char *base_name;
1069  DBusString str;
1070  BusRegistry *registry;
1071  BusService *service;
1072  DBusMessage *reply;
1073
1074  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1075
1076  registry = bus_connection_get_registry (connection);
1077
1078  text = NULL;
1079  reply = NULL;
1080
1081  if (! dbus_message_get_args (message, error,
1082			       DBUS_TYPE_STRING, &text,
1083			       DBUS_TYPE_INVALID))
1084      goto failed;
1085
1086  _dbus_string_init_const (&str, text);
1087  service = bus_registry_lookup (registry, &str);
1088  if (service == NULL &&
1089      _dbus_string_equal_c_str (&str, DBUS_SERVICE_DBUS))
1090    {
1091      /* ORG_FREEDESKTOP_DBUS owns itself */
1092      base_name = DBUS_SERVICE_DBUS;
1093    }
1094  else if (service == NULL)
1095    {
1096      dbus_set_error (error,
1097                      DBUS_ERROR_NAME_HAS_NO_OWNER,
1098                      "Could not get owner of name '%s': no such name", text);
1099      goto failed;
1100    }
1101  else
1102    {
1103      base_name = bus_connection_get_name (bus_service_get_primary_owners_connection (service));
1104      if (base_name == NULL)
1105        {
1106          /* FIXME - how is this error possible? */
1107          dbus_set_error (error,
1108                          DBUS_ERROR_FAILED,
1109                          "Could not determine unique name for '%s'", text);
1110          goto failed;
1111        }
1112      _dbus_assert (*base_name == ':');
1113    }
1114
1115  _dbus_assert (base_name != NULL);
1116
1117  reply = dbus_message_new_method_return (message);
1118  if (reply == NULL)
1119    goto oom;
1120
1121  if (! dbus_message_append_args (reply,
1122				  DBUS_TYPE_STRING, &base_name,
1123				  DBUS_TYPE_INVALID))
1124    goto oom;
1125
1126  if (! bus_transaction_send_from_driver (transaction, connection, reply))
1127    goto oom;
1128
1129  dbus_message_unref (reply);
1130
1131  return TRUE;
1132
1133 oom:
1134  BUS_SET_OOM (error);
1135
1136 failed:
1137  _DBUS_ASSERT_ERROR_IS_SET (error);
1138  if (reply)
1139    dbus_message_unref (reply);
1140  return FALSE;
1141}
1142
1143static dbus_bool_t
1144bus_driver_handle_list_queued_owners (DBusConnection *connection,
1145				      BusTransaction *transaction,
1146				      DBusMessage    *message,
1147				      DBusError      *error)
1148{
1149  const char *text;
1150  DBusList *base_names;
1151  DBusList *link;
1152  DBusString str;
1153  BusRegistry *registry;
1154  BusService *service;
1155  DBusMessage *reply;
1156  DBusMessageIter iter, array_iter;
1157  char *dbus_service_name = DBUS_SERVICE_DBUS;
1158
1159  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1160
1161  registry = bus_connection_get_registry (connection);
1162
1163  base_names = NULL;
1164  text = NULL;
1165  reply = NULL;
1166
1167  if (! dbus_message_get_args (message, error,
1168			       DBUS_TYPE_STRING, &text,
1169			       DBUS_TYPE_INVALID))
1170      goto failed;
1171
1172  _dbus_string_init_const (&str, text);
1173  service = bus_registry_lookup (registry, &str);
1174  if (service == NULL &&
1175      _dbus_string_equal_c_str (&str, DBUS_SERVICE_DBUS))
1176    {
1177      /* ORG_FREEDESKTOP_DBUS owns itself */
1178      if (! _dbus_list_append (&base_names, dbus_service_name))
1179        goto oom;
1180    }
1181  else if (service == NULL)
1182    {
1183      dbus_set_error (error,
1184                      DBUS_ERROR_NAME_HAS_NO_OWNER,
1185                      "Could not get owners of name '%s': no such name", text);
1186      goto failed;
1187    }
1188  else
1189    {
1190      if (!bus_service_list_queued_owners (service,
1191                                           &base_names,
1192                                           error))
1193        goto failed;
1194    }
1195
1196  _dbus_assert (base_names != NULL);
1197
1198  reply = dbus_message_new_method_return (message);
1199  if (reply == NULL)
1200    goto oom;
1201
1202  dbus_message_iter_init_append (reply, &iter);
1203  if (!dbus_message_iter_open_container (&iter,
1204                                         DBUS_TYPE_ARRAY,
1205                                         DBUS_TYPE_STRING_AS_STRING,
1206                                         &array_iter))
1207    goto oom;
1208
1209  link = _dbus_list_get_first_link (&base_names);
1210  while (link != NULL)
1211    {
1212      char *uname;
1213
1214      _dbus_assert (link->data != NULL);
1215      uname = (char *)link->data;
1216
1217      if (!dbus_message_iter_append_basic (&array_iter,
1218                                           DBUS_TYPE_STRING,
1219                                           &uname))
1220        goto oom;
1221
1222      link = _dbus_list_get_next_link (&base_names, link);
1223    }
1224
1225  if (! dbus_message_iter_close_container (&iter, &array_iter))
1226    goto oom;
1227
1228
1229  if (! bus_transaction_send_from_driver (transaction, connection, reply))
1230    goto oom;
1231
1232  dbus_message_unref (reply);
1233
1234  return TRUE;
1235
1236 oom:
1237  BUS_SET_OOM (error);
1238
1239 failed:
1240  _DBUS_ASSERT_ERROR_IS_SET (error);
1241  if (reply)
1242    dbus_message_unref (reply);
1243
1244  if (base_names)
1245    _dbus_list_clear (&base_names);
1246
1247  return FALSE;
1248}
1249
1250static dbus_bool_t
1251bus_driver_handle_get_connection_unix_user (DBusConnection *connection,
1252                                            BusTransaction *transaction,
1253                                            DBusMessage    *message,
1254                                            DBusError      *error)
1255{
1256  const char *service;
1257  DBusString str;
1258  BusRegistry *registry;
1259  BusService *serv;
1260  DBusConnection *conn;
1261  DBusMessage *reply;
1262  unsigned long uid;
1263  dbus_uint32_t uid32;
1264
1265  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1266
1267  registry = bus_connection_get_registry (connection);
1268
1269  service = NULL;
1270  reply = NULL;
1271
1272  if (! dbus_message_get_args (message, error,
1273			       DBUS_TYPE_STRING, &service,
1274			       DBUS_TYPE_INVALID))
1275      goto failed;
1276
1277  _dbus_verbose ("asked for UID of connection %s\n", service);
1278
1279  _dbus_string_init_const (&str, service);
1280  serv = bus_registry_lookup (registry, &str);
1281  if (serv == NULL)
1282    {
1283      dbus_set_error (error,
1284		      DBUS_ERROR_NAME_HAS_NO_OWNER,
1285		      "Could not get UID of name '%s': no such name", service);
1286      goto failed;
1287    }
1288
1289  conn = bus_service_get_primary_owners_connection (serv);
1290
1291  reply = dbus_message_new_method_return (message);
1292  if (reply == NULL)
1293    goto oom;
1294
1295  if (!dbus_connection_get_unix_user (conn, &uid))
1296    {
1297      dbus_set_error (error,
1298                      DBUS_ERROR_FAILED,
1299                      "Could not determine UID for '%s'", service);
1300      goto failed;
1301    }
1302
1303  uid32 = uid;
1304  if (! dbus_message_append_args (reply,
1305                                  DBUS_TYPE_UINT32, &uid32,
1306                                  DBUS_TYPE_INVALID))
1307    goto oom;
1308
1309  if (! bus_transaction_send_from_driver (transaction, connection, reply))
1310    goto oom;
1311
1312  dbus_message_unref (reply);
1313
1314  return TRUE;
1315
1316 oom:
1317  BUS_SET_OOM (error);
1318
1319 failed:
1320  _DBUS_ASSERT_ERROR_IS_SET (error);
1321  if (reply)
1322    dbus_message_unref (reply);
1323  return FALSE;
1324}
1325
1326static dbus_bool_t
1327bus_driver_handle_get_connection_unix_process_id (DBusConnection *connection,
1328						  BusTransaction *transaction,
1329						  DBusMessage    *message,
1330						  DBusError      *error)
1331{
1332  const char *service;
1333  DBusString str;
1334  BusRegistry *registry;
1335  BusService *serv;
1336  DBusConnection *conn;
1337  DBusMessage *reply;
1338  unsigned long pid;
1339  dbus_uint32_t pid32;
1340
1341  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1342
1343  registry = bus_connection_get_registry (connection);
1344
1345  service = NULL;
1346  reply = NULL;
1347
1348  if (! dbus_message_get_args (message, error,
1349			       DBUS_TYPE_STRING, &service,
1350			       DBUS_TYPE_INVALID))
1351      goto failed;
1352
1353  _dbus_verbose ("asked for PID of connection %s\n", service);
1354
1355  _dbus_string_init_const (&str, service);
1356  serv = bus_registry_lookup (registry, &str);
1357  if (serv == NULL)
1358    {
1359      dbus_set_error (error,
1360		      DBUS_ERROR_NAME_HAS_NO_OWNER,
1361		      "Could not get PID of name '%s': no such name", service);
1362      goto failed;
1363    }
1364
1365  conn = bus_service_get_primary_owners_connection (serv);
1366
1367  reply = dbus_message_new_method_return (message);
1368  if (reply == NULL)
1369    goto oom;
1370
1371  if (!dbus_connection_get_unix_process_id (conn, &pid))
1372    {
1373      dbus_set_error (error,
1374                      DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN,
1375                      "Could not determine PID for '%s'", service);
1376      goto failed;
1377    }
1378
1379  pid32 = pid;
1380  if (! dbus_message_append_args (reply,
1381                                  DBUS_TYPE_UINT32, &pid32,
1382                                  DBUS_TYPE_INVALID))
1383    goto oom;
1384
1385  if (! bus_transaction_send_from_driver (transaction, connection, reply))
1386    goto oom;
1387
1388  dbus_message_unref (reply);
1389
1390  return TRUE;
1391
1392 oom:
1393  BUS_SET_OOM (error);
1394
1395 failed:
1396  _DBUS_ASSERT_ERROR_IS_SET (error);
1397  if (reply)
1398    dbus_message_unref (reply);
1399  return FALSE;
1400}
1401
1402static dbus_bool_t
1403bus_driver_handle_get_adt_audit_session_data (DBusConnection *connection,
1404					      BusTransaction *transaction,
1405					      DBusMessage    *message,
1406					      DBusError      *error)
1407{
1408  const char *service;
1409  DBusString str;
1410  BusRegistry *registry;
1411  BusService *serv;
1412  DBusConnection *conn;
1413  DBusMessage *reply;
1414  void *data = NULL;
1415  dbus_uint32_t data_size;
1416
1417  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1418
1419  registry = bus_connection_get_registry (connection);
1420
1421  service = NULL;
1422  reply = NULL;
1423
1424  if (! dbus_message_get_args (message, error,
1425			       DBUS_TYPE_STRING, &service,
1426			       DBUS_TYPE_INVALID))
1427      goto failed;
1428
1429  _dbus_verbose ("asked for audit session data for connection %s\n", service);
1430
1431  _dbus_string_init_const (&str, service);
1432  serv = bus_registry_lookup (registry, &str);
1433  if (serv == NULL)
1434    {
1435      dbus_set_error (error,
1436		      DBUS_ERROR_NAME_HAS_NO_OWNER,
1437		      "Could not get audit session data for name '%s': no such name", service);
1438      goto failed;
1439    }
1440
1441  conn = bus_service_get_primary_owners_connection (serv);
1442
1443  reply = dbus_message_new_method_return (message);
1444  if (reply == NULL)
1445    goto oom;
1446
1447  if (!dbus_connection_get_adt_audit_session_data (conn, &data, &data_size) || data == NULL)
1448    {
1449      dbus_set_error (error,
1450                      DBUS_ERROR_ADT_AUDIT_DATA_UNKNOWN,
1451                      "Could not determine audit session data for '%s'", service);
1452      goto failed;
1453    }
1454
1455  if (! dbus_message_append_args (reply,
1456                                  DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &data, data_size,
1457                                  DBUS_TYPE_INVALID))
1458    goto oom;
1459
1460  if (! bus_transaction_send_from_driver (transaction, connection, reply))
1461    goto oom;
1462
1463  dbus_message_unref (reply);
1464
1465  return TRUE;
1466
1467 oom:
1468  BUS_SET_OOM (error);
1469
1470 failed:
1471  _DBUS_ASSERT_ERROR_IS_SET (error);
1472  if (reply)
1473    dbus_message_unref (reply);
1474  return FALSE;
1475}
1476
1477static dbus_bool_t
1478bus_driver_handle_get_connection_selinux_security_context (DBusConnection *connection,
1479							   BusTransaction *transaction,
1480							   DBusMessage    *message,
1481							   DBusError      *error)
1482{
1483  const char *service;
1484  DBusString str;
1485  BusRegistry *registry;
1486  BusService *serv;
1487  DBusConnection *conn;
1488  DBusMessage *reply;
1489  BusSELinuxID *context;
1490
1491  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1492
1493  registry = bus_connection_get_registry (connection);
1494
1495  service = NULL;
1496  reply = NULL;
1497
1498  if (! dbus_message_get_args (message, error,
1499			       DBUS_TYPE_STRING, &service,
1500			       DBUS_TYPE_INVALID))
1501      goto failed;
1502
1503  _dbus_verbose ("asked for security context of connection %s\n", service);
1504
1505  _dbus_string_init_const (&str, service);
1506  serv = bus_registry_lookup (registry, &str);
1507  if (serv == NULL)
1508    {
1509      dbus_set_error (error,
1510		      DBUS_ERROR_NAME_HAS_NO_OWNER,
1511		      "Could not get security context of name '%s': no such name", service);
1512      goto failed;
1513    }
1514
1515  conn = bus_service_get_primary_owners_connection (serv);
1516
1517  reply = dbus_message_new_method_return (message);
1518  if (reply == NULL)
1519    goto oom;
1520
1521  context = bus_connection_get_selinux_id (conn);
1522  if (!context)
1523    {
1524      dbus_set_error (error,
1525                      DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN,
1526                      "Could not determine security context for '%s'", service);
1527      goto failed;
1528    }
1529
1530  if (! bus_selinux_append_context (reply, context, error))
1531    goto failed;
1532
1533  if (! bus_transaction_send_from_driver (transaction, connection, reply))
1534    goto oom;
1535
1536  dbus_message_unref (reply);
1537
1538  return TRUE;
1539
1540 oom:
1541  BUS_SET_OOM (error);
1542
1543 failed:
1544  _DBUS_ASSERT_ERROR_IS_SET (error);
1545  if (reply)
1546    dbus_message_unref (reply);
1547  return FALSE;
1548}
1549
1550static dbus_bool_t
1551bus_driver_handle_reload_config (DBusConnection *connection,
1552				 BusTransaction *transaction,
1553				 DBusMessage    *message,
1554				 DBusError      *error)
1555{
1556  BusContext *context;
1557  DBusMessage *reply;
1558
1559  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1560
1561  reply = NULL;
1562
1563  context = bus_connection_get_context (connection);
1564  if (!bus_context_reload_config (context, error))
1565    goto failed;
1566
1567  reply = dbus_message_new_method_return (message);
1568  if (reply == NULL)
1569    goto oom;
1570
1571  if (! bus_transaction_send_from_driver (transaction, connection, reply))
1572    goto oom;
1573
1574  dbus_message_unref (reply);
1575  return TRUE;
1576
1577 oom:
1578  BUS_SET_OOM (error);
1579
1580 failed:
1581  _DBUS_ASSERT_ERROR_IS_SET (error);
1582  if (reply)
1583    dbus_message_unref (reply);
1584  return FALSE;
1585}
1586
1587static dbus_bool_t
1588bus_driver_handle_get_id (DBusConnection *connection,
1589                          BusTransaction *transaction,
1590                          DBusMessage    *message,
1591                          DBusError      *error)
1592{
1593  BusContext *context;
1594  DBusMessage *reply;
1595  DBusString uuid;
1596  const char *v_STRING;
1597
1598  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1599
1600  if (!_dbus_string_init (&uuid))
1601    {
1602      BUS_SET_OOM (error);
1603      return FALSE;
1604    }
1605
1606  reply = NULL;
1607
1608  context = bus_connection_get_context (connection);
1609  if (!bus_context_get_id (context, &uuid))
1610    goto oom;
1611
1612  reply = dbus_message_new_method_return (message);
1613  if (reply == NULL)
1614    goto oom;
1615
1616  v_STRING = _dbus_string_get_const_data (&uuid);
1617  if (!dbus_message_append_args (reply,
1618                                 DBUS_TYPE_STRING, &v_STRING,
1619                                 DBUS_TYPE_INVALID))
1620    goto oom;
1621
1622  _dbus_assert (dbus_message_has_signature (reply, "s"));
1623
1624  if (! bus_transaction_send_from_driver (transaction, connection, reply))
1625    goto oom;
1626
1627  _dbus_string_free (&uuid);
1628  dbus_message_unref (reply);
1629  return TRUE;
1630
1631 oom:
1632  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1633
1634  BUS_SET_OOM (error);
1635
1636  if (reply)
1637    dbus_message_unref (reply);
1638  _dbus_string_free (&uuid);
1639  return FALSE;
1640}
1641
1642/* For speed it might be useful to sort this in order of
1643 * frequency of use (but doesn't matter with only a few items
1644 * anyhow)
1645 */
1646static struct
1647{
1648  const char *name;
1649  const char *in_args;
1650  const char *out_args;
1651  dbus_bool_t (* handler) (DBusConnection *connection,
1652                           BusTransaction *transaction,
1653                           DBusMessage    *message,
1654                           DBusError      *error);
1655} message_handlers[] = {
1656  { "Hello",
1657    "",
1658    DBUS_TYPE_STRING_AS_STRING,
1659    bus_driver_handle_hello },
1660  { "RequestName",
1661    DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_UINT32_AS_STRING,
1662    DBUS_TYPE_UINT32_AS_STRING,
1663    bus_driver_handle_acquire_service },
1664  { "ReleaseName",
1665    DBUS_TYPE_STRING_AS_STRING,
1666    DBUS_TYPE_UINT32_AS_STRING,
1667    bus_driver_handle_release_service },
1668  { "StartServiceByName",
1669    DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_UINT32_AS_STRING,
1670    DBUS_TYPE_UINT32_AS_STRING,
1671    bus_driver_handle_activate_service },
1672  { "UpdateActivationEnvironment",
1673    DBUS_TYPE_ARRAY_AS_STRING DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
1674    "",
1675    bus_driver_handle_update_activation_environment },
1676  { "NameHasOwner",
1677    DBUS_TYPE_STRING_AS_STRING,
1678    DBUS_TYPE_BOOLEAN_AS_STRING,
1679    bus_driver_handle_service_exists },
1680  { "ListNames",
1681    "",
1682    DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
1683    bus_driver_handle_list_services },
1684  { "ListActivatableNames",
1685    "",
1686    DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
1687    bus_driver_handle_list_activatable_services },
1688  { "AddMatch",
1689    DBUS_TYPE_STRING_AS_STRING,
1690    "",
1691    bus_driver_handle_add_match },
1692  { "RemoveMatch",
1693    DBUS_TYPE_STRING_AS_STRING,
1694    "",
1695    bus_driver_handle_remove_match },
1696  { "GetNameOwner",
1697    DBUS_TYPE_STRING_AS_STRING,
1698    DBUS_TYPE_STRING_AS_STRING,
1699    bus_driver_handle_get_service_owner },
1700  { "ListQueuedOwners",
1701    DBUS_TYPE_STRING_AS_STRING,
1702    DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
1703    bus_driver_handle_list_queued_owners },
1704  { "GetConnectionUnixUser",
1705    DBUS_TYPE_STRING_AS_STRING,
1706    DBUS_TYPE_UINT32_AS_STRING,
1707    bus_driver_handle_get_connection_unix_user },
1708  { "GetConnectionUnixProcessID",
1709    DBUS_TYPE_STRING_AS_STRING,
1710    DBUS_TYPE_UINT32_AS_STRING,
1711    bus_driver_handle_get_connection_unix_process_id },
1712  { "GetAdtAuditSessionData",
1713    DBUS_TYPE_STRING_AS_STRING,
1714    DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING,
1715    bus_driver_handle_get_adt_audit_session_data },
1716  { "GetConnectionSELinuxSecurityContext",
1717    DBUS_TYPE_STRING_AS_STRING,
1718    DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING,
1719    bus_driver_handle_get_connection_selinux_security_context },
1720  { "ReloadConfig",
1721    "",
1722    "",
1723    bus_driver_handle_reload_config },
1724  { "GetId",
1725    "",
1726    DBUS_TYPE_STRING_AS_STRING,
1727    bus_driver_handle_get_id }
1728};
1729
1730static dbus_bool_t
1731write_args_for_direction (DBusString *xml,
1732			  const char *signature,
1733			  dbus_bool_t in)
1734{
1735  DBusTypeReader typereader;
1736  DBusString sigstr;
1737  int current_type;
1738
1739  _dbus_string_init_const (&sigstr, signature);
1740  _dbus_type_reader_init_types_only (&typereader, &sigstr, 0);
1741
1742  while ((current_type = _dbus_type_reader_get_current_type (&typereader)) != DBUS_TYPE_INVALID)
1743    {
1744      const DBusString *subsig;
1745      int start, len;
1746
1747      _dbus_type_reader_get_signature (&typereader, &subsig, &start, &len);
1748      if (!_dbus_string_append_printf (xml, "      <arg direction=\"%s\" type=\"",
1749				       in ? "in" : "out"))
1750	goto oom;
1751      if (!_dbus_string_append_len (xml,
1752				    _dbus_string_get_const_data (subsig) + start,
1753				    len))
1754	goto oom;
1755      if (!_dbus_string_append (xml, "\"/>\n"))
1756	goto oom;
1757
1758      _dbus_type_reader_next (&typereader);
1759    }
1760  return TRUE;
1761 oom:
1762  return FALSE;
1763}
1764
1765dbus_bool_t
1766bus_driver_generate_introspect_string (DBusString *xml)
1767{
1768  int i;
1769
1770  if (!_dbus_string_append (xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE))
1771    return FALSE;
1772  if (!_dbus_string_append (xml, "<node>\n"))
1773    return FALSE;
1774  if (!_dbus_string_append_printf (xml, "  <interface name=\"%s\">\n", DBUS_INTERFACE_INTROSPECTABLE))
1775    return FALSE;
1776  if (!_dbus_string_append (xml, "    <method name=\"Introspect\">\n"))
1777    return FALSE;
1778  if (!_dbus_string_append_printf (xml, "      <arg name=\"data\" direction=\"out\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING))
1779    return FALSE;
1780  if (!_dbus_string_append (xml, "    </method>\n"))
1781    return FALSE;
1782  if (!_dbus_string_append (xml, "  </interface>\n"))
1783    return FALSE;
1784
1785  if (!_dbus_string_append_printf (xml, "  <interface name=\"%s\">\n",
1786                                   DBUS_INTERFACE_DBUS))
1787    return FALSE;
1788
1789  i = 0;
1790  while (i < _DBUS_N_ELEMENTS (message_handlers))
1791    {
1792
1793      if (!_dbus_string_append_printf (xml, "    <method name=\"%s\">\n",
1794                                       message_handlers[i].name))
1795        return FALSE;
1796
1797      if (!write_args_for_direction (xml, message_handlers[i].in_args, TRUE))
1798	return FALSE;
1799
1800      if (!write_args_for_direction (xml, message_handlers[i].out_args, FALSE))
1801	return FALSE;
1802
1803      if (!_dbus_string_append (xml, "    </method>\n"))
1804	return FALSE;
1805
1806      ++i;
1807    }
1808
1809  if (!_dbus_string_append_printf (xml, "    <signal name=\"NameOwnerChanged\">\n"))
1810    return FALSE;
1811
1812  if (!_dbus_string_append_printf (xml, "      <arg type=\"s\"/>\n"))
1813    return FALSE;
1814
1815  if (!_dbus_string_append_printf (xml, "      <arg type=\"s\"/>\n"))
1816    return FALSE;
1817
1818  if (!_dbus_string_append_printf (xml, "      <arg type=\"s\"/>\n"))
1819    return FALSE;
1820
1821  if (!_dbus_string_append_printf (xml, "    </signal>\n"))
1822    return FALSE;
1823
1824
1825
1826  if (!_dbus_string_append_printf (xml, "    <signal name=\"NameLost\">\n"))
1827    return FALSE;
1828
1829  if (!_dbus_string_append_printf (xml, "      <arg type=\"s\"/>\n"))
1830    return FALSE;
1831
1832  if (!_dbus_string_append_printf (xml, "    </signal>\n"))
1833    return FALSE;
1834
1835
1836
1837  if (!_dbus_string_append_printf (xml, "    <signal name=\"NameAcquired\">\n"))
1838    return FALSE;
1839
1840  if (!_dbus_string_append_printf (xml, "      <arg type=\"s\"/>\n"))
1841    return FALSE;
1842
1843  if (!_dbus_string_append_printf (xml, "    </signal>\n"))
1844    return FALSE;
1845
1846  if (!_dbus_string_append (xml, "  </interface>\n"))
1847    return FALSE;
1848
1849  if (!_dbus_string_append (xml, "</node>\n"))
1850    return FALSE;
1851
1852  return TRUE;
1853}
1854
1855static dbus_bool_t
1856bus_driver_handle_introspect (DBusConnection *connection,
1857                              BusTransaction *transaction,
1858                              DBusMessage    *message,
1859                              DBusError      *error)
1860{
1861  DBusString xml;
1862  DBusMessage *reply;
1863  const char *v_STRING;
1864
1865  _dbus_verbose ("Introspect() on bus driver\n");
1866
1867  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1868
1869  reply = NULL;
1870
1871  if (! dbus_message_get_args (message, error,
1872			       DBUS_TYPE_INVALID))
1873    {
1874      _DBUS_ASSERT_ERROR_IS_SET (error);
1875      return FALSE;
1876    }
1877
1878  if (!_dbus_string_init (&xml))
1879    {
1880      BUS_SET_OOM (error);
1881      return FALSE;
1882    }
1883
1884  if (!bus_driver_generate_introspect_string (&xml))
1885    goto oom;
1886
1887  v_STRING = _dbus_string_get_const_data (&xml);
1888
1889  reply = dbus_message_new_method_return (message);
1890  if (reply == NULL)
1891    goto oom;
1892
1893  if (! dbus_message_append_args (reply,
1894                                  DBUS_TYPE_STRING, &v_STRING,
1895                                  DBUS_TYPE_INVALID))
1896    goto oom;
1897
1898  if (! bus_transaction_send_from_driver (transaction, connection, reply))
1899    goto oom;
1900
1901  dbus_message_unref (reply);
1902  _dbus_string_free (&xml);
1903
1904  return TRUE;
1905
1906 oom:
1907  BUS_SET_OOM (error);
1908
1909  if (reply)
1910    dbus_message_unref (reply);
1911
1912  _dbus_string_free (&xml);
1913
1914  return FALSE;
1915}
1916
1917dbus_bool_t
1918bus_driver_handle_message (DBusConnection *connection,
1919                           BusTransaction *transaction,
1920			   DBusMessage    *message,
1921                           DBusError      *error)
1922{
1923  const char *name, *sender, *interface;
1924  int i;
1925
1926  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1927
1928  if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL)
1929    {
1930      _dbus_verbose ("Driver got a non-method-call message, ignoring\n");
1931      return TRUE; /* we just ignore this */
1932    }
1933
1934  if (dbus_message_is_method_call (message,
1935                                   DBUS_INTERFACE_INTROSPECTABLE,
1936                                   "Introspect"))
1937    return bus_driver_handle_introspect (connection, transaction, message, error);
1938
1939  interface = dbus_message_get_interface (message);
1940  if (interface == NULL)
1941    interface = DBUS_INTERFACE_DBUS;
1942
1943  _dbus_assert (dbus_message_get_member (message) != NULL);
1944
1945  name = dbus_message_get_member (message);
1946  sender = dbus_message_get_sender (message);
1947
1948  if (strcmp (interface,
1949              DBUS_INTERFACE_DBUS) != 0)
1950    {
1951      _dbus_verbose ("Driver got message to unknown interface \"%s\"\n",
1952                     interface);
1953      goto unknown;
1954    }
1955
1956  _dbus_verbose ("Driver got a method call: %s\n",
1957		 dbus_message_get_member (message));
1958
1959  /* security checks should have kept this from getting here */
1960  _dbus_assert (sender != NULL || strcmp (name, "Hello") == 0);
1961
1962  i = 0;
1963  while (i < _DBUS_N_ELEMENTS (message_handlers))
1964    {
1965      if (strcmp (message_handlers[i].name, name) == 0)
1966        {
1967          _dbus_verbose ("Found driver handler for %s\n", name);
1968
1969          if (!dbus_message_has_signature (message, message_handlers[i].in_args))
1970            {
1971              _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1972              _dbus_verbose ("Call to %s has wrong args (%s, expected %s)\n",
1973                             name, dbus_message_get_signature (message),
1974                             message_handlers[i].in_args);
1975
1976              dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
1977                              "Call to %s has wrong args (%s, expected %s)\n",
1978                              name, dbus_message_get_signature (message),
1979                              message_handlers[i].in_args);
1980              _DBUS_ASSERT_ERROR_IS_SET (error);
1981              return FALSE;
1982            }
1983
1984          if ((* message_handlers[i].handler) (connection, transaction, message, error))
1985            {
1986              _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1987              _dbus_verbose ("Driver handler succeeded\n");
1988              return TRUE;
1989            }
1990          else
1991            {
1992              _DBUS_ASSERT_ERROR_IS_SET (error);
1993              _dbus_verbose ("Driver handler returned failure\n");
1994              return FALSE;
1995            }
1996        }
1997
1998      ++i;
1999    }
2000
2001 unknown:
2002  _dbus_verbose ("No driver handler for message \"%s\"\n",
2003                 name);
2004
2005  dbus_set_error (error, DBUS_ERROR_UNKNOWN_METHOD,
2006                  "%s does not understand message %s",
2007                  DBUS_SERVICE_DBUS, name);
2008
2009  return FALSE;
2010}
2011
2012void
2013bus_driver_remove_connection (DBusConnection *connection)
2014{
2015  /* FIXME 1.0 Does nothing for now, should unregister the connection
2016   * with the bus driver.
2017   */
2018}
2019