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