c97bff5d5741ca749bc998a2c40a5d8f4f371b6d
[platform/upstream/dbus.git] / bus / driver.c
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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
38 static dbus_bool_t bus_driver_send_welcome_message (DBusConnection *connection,
39                                                     DBusMessage    *hello_message,
40                                                     BusTransaction *transaction,
41                                                     DBusError      *error);
42
43 dbus_bool_t
44 bus_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
95 dbus_bool_t
96 bus_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
138 dbus_bool_t
139 bus_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
181 static dbus_bool_t
182 create_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
241 static dbus_bool_t
242 bus_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
323 static dbus_bool_t
324 bus_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
368 static dbus_bool_t
369 bus_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
461 static dbus_bool_t
462 bus_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
554 static dbus_bool_t
555 bus_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
618 static dbus_bool_t
619 bus_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
679 static dbus_bool_t
680 bus_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
745 static dbus_bool_t
746 bus_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
786 static dbus_bool_t
787 send_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
813 static dbus_bool_t
814 bus_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
940 static dbus_bool_t
941 bus_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
1008 static dbus_bool_t
1009 bus_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
1061 static dbus_bool_t
1062 bus_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
1143 static dbus_bool_t
1144 bus_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
1250 static dbus_bool_t
1251 bus_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
1326 static dbus_bool_t
1327 bus_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
1402 static dbus_bool_t
1403 bus_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
1477 static dbus_bool_t
1478 bus_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
1550 static dbus_bool_t
1551 bus_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
1587 static dbus_bool_t
1588 bus_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  */
1646 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
1730 static dbus_bool_t
1731 write_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
1765 dbus_bool_t
1766 bus_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
1855 static dbus_bool_t
1856 bus_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
1917 dbus_bool_t
1918 bus_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
2012 void
2013 bus_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 }