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