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