Cleanup: simplify assertion check
[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   _dbus_assert (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_ARRAY);
889
890   dbus_message_iter_recurse (&iter, &dict_iter);
891
892   retval = FALSE;
893
894   /* Then loop through the sent dictionary, add the location of
895    * the environment keys and values to lists. The result will
896    * be in reverse order, so we don't have to constantly search
897    * for the end of the list in a loop.
898    */
899   keys = NULL;
900   values = NULL;
901   while ((array_type = dbus_message_iter_get_arg_type (&dict_iter)) == DBUS_TYPE_DICT_ENTRY)
902     {
903       dbus_message_iter_recurse (&dict_iter, &dict_entry_iter);
904
905       while ((key_type = dbus_message_iter_get_arg_type (&dict_entry_iter)) == DBUS_TYPE_STRING)
906         {
907           char *key;
908           char *value;
909           int value_type;
910
911           dbus_message_iter_get_basic (&dict_entry_iter, &key);
912           dbus_message_iter_next (&dict_entry_iter);
913
914           value_type = dbus_message_iter_get_arg_type (&dict_entry_iter);
915
916           if (value_type != DBUS_TYPE_STRING)
917             break;
918
919           dbus_message_iter_get_basic (&dict_entry_iter, &value);
920
921           if (!_dbus_list_append (&keys, key))
922             {
923               BUS_SET_OOM (error);
924               break;
925             }
926
927           if (!_dbus_list_append (&values, value))
928             {
929               BUS_SET_OOM (error);
930               break;
931             }
932
933           dbus_message_iter_next (&dict_entry_iter);
934         }
935
936       if (key_type != DBUS_TYPE_INVALID)
937         break;
938
939       dbus_message_iter_next (&dict_iter);
940     }
941
942   if (array_type != DBUS_TYPE_INVALID)
943     goto out;
944
945   _dbus_assert (_dbus_list_get_length (&keys) == _dbus_list_get_length (&values));
946
947   key_link = keys;
948   value_link = values;
949   while (key_link != NULL)
950   {
951       const char *key;
952       const char *value;
953
954       key = key_link->data;
955       value = value_link->data;
956
957       if (!bus_activation_set_environment_variable (activation,
958                                                     key, value, error))
959       {
960           _DBUS_ASSERT_ERROR_IS_SET (error);
961           _dbus_verbose ("bus_activation_set_environment_variable() failed\n");
962           break;
963       }
964       key_link = _dbus_list_get_next_link (&keys, key_link);
965       value_link = _dbus_list_get_next_link (&values, value_link);
966   }
967
968   /* FIXME: We can fail early having set only some of the environment variables,
969    * (because of OOM failure).  It's sort of hard to fix and it doesn't really
970    * matter, so we're punting for now.
971    */
972   if (key_link != NULL)
973     goto out;
974
975   if (!send_ack_reply (connection, transaction,
976                        message, error))
977     goto out;
978
979   retval = TRUE;
980
981  out:
982   _dbus_list_clear (&keys);
983   _dbus_list_clear (&values);
984   return retval;
985 }
986
987 static dbus_bool_t
988 bus_driver_handle_add_match (DBusConnection *connection,
989                              BusTransaction *transaction,
990                              DBusMessage    *message,
991                              DBusError      *error)
992 {
993   BusMatchRule *rule;
994   const char *text;
995   DBusString str;
996   BusMatchmaker *matchmaker;
997
998   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
999
1000   text = NULL;
1001   rule = NULL;
1002
1003   if (bus_connection_get_n_match_rules (connection) >=
1004       bus_context_get_max_match_rules_per_connection (bus_transaction_get_context (transaction)))
1005     {
1006       dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
1007                       "Connection \"%s\" is not allowed to add more match rules "
1008                       "(increase limits in configuration file if required)",
1009                       bus_connection_is_active (connection) ?
1010                       bus_connection_get_name (connection) :
1011                       "(inactive)");
1012       goto failed;
1013     }
1014
1015   if (!dbus_message_get_args (message, error,
1016                               DBUS_TYPE_STRING, &text,
1017                               DBUS_TYPE_INVALID))
1018     {
1019       _dbus_verbose ("No memory to get arguments to AddMatch\n");
1020       goto failed;
1021     }
1022
1023   _dbus_string_init_const (&str, text);
1024
1025   rule = bus_match_rule_parse (connection, &str, error);
1026   if (rule == NULL)
1027     goto failed;
1028
1029   matchmaker = bus_connection_get_matchmaker (connection);
1030
1031   if (!bus_matchmaker_add_rule (matchmaker, rule))
1032     {
1033       BUS_SET_OOM (error);
1034       goto failed;
1035     }
1036
1037   if (!send_ack_reply (connection, transaction,
1038                        message, error))
1039     {
1040       bus_matchmaker_remove_rule (matchmaker, rule);
1041       goto failed;
1042     }
1043
1044   bus_match_rule_unref (rule);
1045
1046   return TRUE;
1047
1048  failed:
1049   _DBUS_ASSERT_ERROR_IS_SET (error);
1050   if (rule)
1051     bus_match_rule_unref (rule);
1052   return FALSE;
1053 }
1054
1055 static dbus_bool_t
1056 bus_driver_handle_remove_match (DBusConnection *connection,
1057                                 BusTransaction *transaction,
1058                                 DBusMessage    *message,
1059                                 DBusError      *error)
1060 {
1061   BusMatchRule *rule;
1062   const char *text;
1063   DBusString str;
1064   BusMatchmaker *matchmaker;
1065
1066   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1067
1068   text = NULL;
1069   rule = NULL;
1070
1071   if (!dbus_message_get_args (message, error,
1072                               DBUS_TYPE_STRING, &text,
1073                               DBUS_TYPE_INVALID))
1074     {
1075       _dbus_verbose ("No memory to get arguments to RemoveMatch\n");
1076       goto failed;
1077     }
1078
1079   _dbus_string_init_const (&str, text);
1080
1081   rule = bus_match_rule_parse (connection, &str, error);
1082   if (rule == NULL)
1083     goto failed;
1084
1085   /* Send the ack before we remove the rule, since the ack is undone
1086    * on transaction cancel, but rule removal isn't.
1087    */
1088   if (!send_ack_reply (connection, transaction,
1089                        message, error))
1090     goto failed;
1091
1092   matchmaker = bus_connection_get_matchmaker (connection);
1093
1094   if (!bus_matchmaker_remove_rule_by_value (matchmaker, rule, error))
1095     goto failed;
1096
1097   bus_match_rule_unref (rule);
1098
1099   return TRUE;
1100
1101  failed:
1102   _DBUS_ASSERT_ERROR_IS_SET (error);
1103   if (rule)
1104     bus_match_rule_unref (rule);
1105   return FALSE;
1106 }
1107
1108 static dbus_bool_t
1109 bus_driver_handle_get_service_owner (DBusConnection *connection,
1110                                      BusTransaction *transaction,
1111                                      DBusMessage    *message,
1112                                      DBusError      *error)
1113 {
1114   const char *text;
1115   const char *base_name;
1116   DBusString str;
1117   BusRegistry *registry;
1118   BusService *service;
1119   DBusMessage *reply;
1120
1121   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1122
1123   registry = bus_connection_get_registry (connection);
1124
1125   text = NULL;
1126   reply = NULL;
1127
1128   if (! dbus_message_get_args (message, error,
1129                                DBUS_TYPE_STRING, &text,
1130                                DBUS_TYPE_INVALID))
1131       goto failed;
1132
1133   _dbus_string_init_const (&str, text);
1134   service = bus_registry_lookup (registry, &str);
1135   if (service == NULL &&
1136       _dbus_string_equal_c_str (&str, DBUS_SERVICE_DBUS))
1137     {
1138       /* ORG_FREEDESKTOP_DBUS owns itself */
1139       base_name = DBUS_SERVICE_DBUS;
1140     }
1141   else if (service == NULL)
1142     {
1143       dbus_set_error (error,
1144                       DBUS_ERROR_NAME_HAS_NO_OWNER,
1145                       "Could not get owner of name '%s': no such name", text);
1146       goto failed;
1147     }
1148   else
1149     {
1150       base_name = bus_connection_get_name (bus_service_get_primary_owners_connection (service));
1151       if (base_name == NULL)
1152         {
1153           /* FIXME - how is this error possible? */
1154           dbus_set_error (error,
1155                           DBUS_ERROR_FAILED,
1156                           "Could not determine unique name for '%s'", text);
1157           goto failed;
1158         }
1159       _dbus_assert (*base_name == ':');
1160     }
1161
1162   _dbus_assert (base_name != NULL);
1163
1164   reply = dbus_message_new_method_return (message);
1165   if (reply == NULL)
1166     goto oom;
1167
1168   if (! dbus_message_append_args (reply,
1169                                   DBUS_TYPE_STRING, &base_name,
1170                                   DBUS_TYPE_INVALID))
1171     goto oom;
1172
1173   if (! bus_transaction_send_from_driver (transaction, connection, reply))
1174     goto oom;
1175
1176   dbus_message_unref (reply);
1177
1178   return TRUE;
1179
1180  oom:
1181   BUS_SET_OOM (error);
1182
1183  failed:
1184   _DBUS_ASSERT_ERROR_IS_SET (error);
1185   if (reply)
1186     dbus_message_unref (reply);
1187   return FALSE;
1188 }
1189
1190 static dbus_bool_t
1191 bus_driver_handle_list_queued_owners (DBusConnection *connection,
1192                                       BusTransaction *transaction,
1193                                       DBusMessage    *message,
1194                                       DBusError      *error)
1195 {
1196   const char *text;
1197   DBusList *base_names;
1198   DBusList *link;
1199   DBusString str;
1200   BusRegistry *registry;
1201   BusService *service;
1202   DBusMessage *reply;
1203   DBusMessageIter iter, array_iter;
1204   char *dbus_service_name = DBUS_SERVICE_DBUS;
1205
1206   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1207
1208   registry = bus_connection_get_registry (connection);
1209
1210   base_names = NULL;
1211   text = NULL;
1212   reply = NULL;
1213
1214   if (! dbus_message_get_args (message, error,
1215                                DBUS_TYPE_STRING, &text,
1216                                DBUS_TYPE_INVALID))
1217       goto failed;
1218
1219   _dbus_string_init_const (&str, text);
1220   service = bus_registry_lookup (registry, &str);
1221   if (service == NULL &&
1222       _dbus_string_equal_c_str (&str, DBUS_SERVICE_DBUS))
1223     {
1224       /* ORG_FREEDESKTOP_DBUS owns itself */
1225       if (! _dbus_list_append (&base_names, dbus_service_name))
1226         goto oom;
1227     }
1228   else if (service == NULL)
1229     {
1230       dbus_set_error (error,
1231                       DBUS_ERROR_NAME_HAS_NO_OWNER,
1232                       "Could not get owners of name '%s': no such name", text);
1233       goto failed;
1234     }
1235   else
1236     {
1237       if (!bus_service_list_queued_owners (service,
1238                                            &base_names,
1239                                            error))
1240         goto failed;
1241     }
1242
1243   _dbus_assert (base_names != NULL);
1244
1245   reply = dbus_message_new_method_return (message);
1246   if (reply == NULL)
1247     goto oom;
1248
1249   dbus_message_iter_init_append (reply, &iter);
1250   if (!dbus_message_iter_open_container (&iter,
1251                                          DBUS_TYPE_ARRAY,
1252                                          DBUS_TYPE_STRING_AS_STRING,
1253                                          &array_iter))
1254     goto oom;
1255
1256   link = _dbus_list_get_first_link (&base_names);
1257   while (link != NULL)
1258     {
1259       char *uname;
1260
1261       _dbus_assert (link->data != NULL);
1262       uname = (char *)link->data;
1263
1264       if (!dbus_message_iter_append_basic (&array_iter,
1265                                            DBUS_TYPE_STRING,
1266                                            &uname))
1267         goto oom;
1268
1269       link = _dbus_list_get_next_link (&base_names, link);
1270     }
1271
1272   if (! dbus_message_iter_close_container (&iter, &array_iter))
1273     goto oom;
1274
1275
1276   if (! bus_transaction_send_from_driver (transaction, connection, reply))
1277     goto oom;
1278
1279   dbus_message_unref (reply);
1280
1281   return TRUE;
1282
1283  oom:
1284   BUS_SET_OOM (error);
1285
1286  failed:
1287   _DBUS_ASSERT_ERROR_IS_SET (error);
1288   if (reply)
1289     dbus_message_unref (reply);
1290
1291   if (base_names)
1292     _dbus_list_clear (&base_names);
1293
1294   return FALSE;
1295 }
1296
1297 static dbus_bool_t
1298 bus_driver_handle_get_connection_unix_user (DBusConnection *connection,
1299                                             BusTransaction *transaction,
1300                                             DBusMessage    *message,
1301                                             DBusError      *error)
1302 {
1303   DBusConnection *conn;
1304   DBusMessage *reply;
1305   unsigned long uid;
1306   dbus_uint32_t uid32;
1307   const char *service;
1308
1309   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1310
1311   reply = NULL;
1312
1313   conn = bus_driver_get_conn_helper (connection, message, "UID", &service,
1314                                      error);
1315
1316   if (conn == NULL)
1317     goto failed;
1318
1319   reply = dbus_message_new_method_return (message);
1320   if (reply == NULL)
1321     goto oom;
1322
1323   if (!dbus_connection_get_unix_user (conn, &uid))
1324     {
1325       dbus_set_error (error,
1326                       DBUS_ERROR_FAILED,
1327                       "Could not determine UID for '%s'", service);
1328       goto failed;
1329     }
1330
1331   uid32 = uid;
1332   if (! dbus_message_append_args (reply,
1333                                   DBUS_TYPE_UINT32, &uid32,
1334                                   DBUS_TYPE_INVALID))
1335     goto oom;
1336
1337   if (! bus_transaction_send_from_driver (transaction, connection, reply))
1338     goto oom;
1339
1340   dbus_message_unref (reply);
1341
1342   return TRUE;
1343
1344  oom:
1345   BUS_SET_OOM (error);
1346
1347  failed:
1348   _DBUS_ASSERT_ERROR_IS_SET (error);
1349   if (reply)
1350     dbus_message_unref (reply);
1351   return FALSE;
1352 }
1353
1354 static dbus_bool_t
1355 bus_driver_handle_get_connection_unix_process_id (DBusConnection *connection,
1356                                                   BusTransaction *transaction,
1357                                                   DBusMessage    *message,
1358                                                   DBusError      *error)
1359 {
1360   DBusConnection *conn;
1361   DBusMessage *reply;
1362   unsigned long pid;
1363   dbus_uint32_t pid32;
1364   const char *service;
1365
1366   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1367
1368   reply = NULL;
1369
1370   conn = bus_driver_get_conn_helper (connection, message, "PID", &service,
1371                                      error);
1372
1373   if (conn == NULL)
1374     goto failed;
1375
1376   reply = dbus_message_new_method_return (message);
1377   if (reply == NULL)
1378     goto oom;
1379
1380   if (!dbus_connection_get_unix_process_id (conn, &pid))
1381     {
1382       dbus_set_error (error,
1383                       DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN,
1384                       "Could not determine PID for '%s'", service);
1385       goto failed;
1386     }
1387
1388   pid32 = pid;
1389   if (! dbus_message_append_args (reply,
1390                                   DBUS_TYPE_UINT32, &pid32,
1391                                   DBUS_TYPE_INVALID))
1392     goto oom;
1393
1394   if (! bus_transaction_send_from_driver (transaction, connection, reply))
1395     goto oom;
1396
1397   dbus_message_unref (reply);
1398
1399   return TRUE;
1400
1401  oom:
1402   BUS_SET_OOM (error);
1403
1404  failed:
1405   _DBUS_ASSERT_ERROR_IS_SET (error);
1406   if (reply)
1407     dbus_message_unref (reply);
1408   return FALSE;
1409 }
1410
1411 static dbus_bool_t
1412 bus_driver_handle_get_adt_audit_session_data (DBusConnection *connection,
1413                                               BusTransaction *transaction,
1414                                               DBusMessage    *message,
1415                                               DBusError      *error)
1416 {
1417   DBusConnection *conn;
1418   DBusMessage *reply;
1419   void *data = NULL;
1420   dbus_uint32_t data_size;
1421   const char *service;
1422
1423   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1424
1425   reply = NULL;
1426
1427   conn = bus_driver_get_conn_helper (connection, message,
1428                                      "audit session data", &service, error);
1429
1430   if (conn == NULL)
1431     goto failed;
1432
1433   reply = dbus_message_new_method_return (message);
1434   if (reply == NULL)
1435     goto oom;
1436
1437   if (!dbus_connection_get_adt_audit_session_data (conn, &data, &data_size) || data == NULL)
1438     {
1439       dbus_set_error (error,
1440                       DBUS_ERROR_ADT_AUDIT_DATA_UNKNOWN,
1441                       "Could not determine audit session data for '%s'", service);
1442       goto failed;
1443     }
1444
1445   if (! dbus_message_append_args (reply,
1446                                   DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &data, data_size,
1447                                   DBUS_TYPE_INVALID))
1448     goto oom;
1449
1450   if (! bus_transaction_send_from_driver (transaction, connection, reply))
1451     goto oom;
1452
1453   dbus_message_unref (reply);
1454
1455   return TRUE;
1456
1457  oom:
1458   BUS_SET_OOM (error);
1459
1460  failed:
1461   _DBUS_ASSERT_ERROR_IS_SET (error);
1462   if (reply)
1463     dbus_message_unref (reply);
1464   return FALSE;
1465 }
1466
1467 static dbus_bool_t
1468 bus_driver_handle_get_connection_selinux_security_context (DBusConnection *connection,
1469                                                            BusTransaction *transaction,
1470                                                            DBusMessage    *message,
1471                                                            DBusError      *error)
1472 {
1473   DBusConnection *conn;
1474   DBusMessage *reply;
1475   BusSELinuxID *context;
1476   const char *service;
1477
1478   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1479
1480   reply = NULL;
1481
1482   conn = bus_driver_get_conn_helper (connection, message, "security context",
1483                                      &service, error);
1484
1485   if (conn == NULL)
1486     goto failed;
1487
1488   reply = dbus_message_new_method_return (message);
1489   if (reply == NULL)
1490     goto oom;
1491
1492   context = bus_connection_get_selinux_id (conn);
1493   if (!context)
1494     {
1495       dbus_set_error (error,
1496                       DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN,
1497                       "Could not determine security context for '%s'", service);
1498       goto failed;
1499     }
1500
1501   if (! bus_selinux_append_context (reply, context, error))
1502     goto failed;
1503
1504   if (! bus_transaction_send_from_driver (transaction, connection, reply))
1505     goto oom;
1506
1507   dbus_message_unref (reply);
1508
1509   return TRUE;
1510
1511  oom:
1512   BUS_SET_OOM (error);
1513
1514  failed:
1515   _DBUS_ASSERT_ERROR_IS_SET (error);
1516   if (reply)
1517     dbus_message_unref (reply);
1518   return FALSE;
1519 }
1520
1521 static dbus_bool_t
1522 bus_driver_handle_get_connection_credentials (DBusConnection *connection,
1523                                               BusTransaction *transaction,
1524                                               DBusMessage    *message,
1525                                               DBusError      *error)
1526 {
1527   DBusConnection *conn;
1528   DBusMessage *reply;
1529   DBusMessageIter reply_iter;
1530   DBusMessageIter array_iter;
1531   unsigned long ulong_val;
1532   const char *service;
1533
1534   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1535
1536   reply = NULL;
1537
1538   conn = bus_driver_get_conn_helper (connection, message, "credentials",
1539                                      &service, error);
1540
1541   if (conn == NULL)
1542     goto failed;
1543
1544   reply = _dbus_asv_new_method_return (message, &reply_iter, &array_iter);
1545   if (reply == NULL)
1546     goto oom;
1547
1548   /* we can't represent > 32-bit pids; if your system needs them, please
1549    * add ProcessID64 to the spec or something */
1550   if (dbus_connection_get_unix_process_id (conn, &ulong_val) &&
1551       ulong_val <= _DBUS_UINT32_MAX)
1552     {
1553       if (!_dbus_asv_add_uint32 (&array_iter, "ProcessID", ulong_val))
1554         goto oom;
1555     }
1556
1557   /* we can't represent > 32-bit uids; if your system needs them, please
1558    * add UnixUserID64 to the spec or something */
1559   if (dbus_connection_get_unix_user (conn, &ulong_val) &&
1560       ulong_val <= _DBUS_UINT32_MAX)
1561     {
1562       if (!_dbus_asv_add_uint32 (&array_iter, "UnixUserID", ulong_val))
1563         goto oom;
1564     }
1565
1566   if (!_dbus_asv_close (&reply_iter, &array_iter))
1567     goto oom;
1568
1569   if (! bus_transaction_send_from_driver (transaction, connection, reply))
1570     {
1571       /* this time we don't want to close the iterator again, so just
1572        * get rid of the message */
1573       dbus_message_unref (reply);
1574       reply = NULL;
1575       goto oom;
1576     }
1577
1578   return TRUE;
1579
1580  oom:
1581   BUS_SET_OOM (error);
1582
1583  failed:
1584   _DBUS_ASSERT_ERROR_IS_SET (error);
1585
1586   if (reply)
1587     {
1588       _dbus_asv_abandon (&reply_iter, &array_iter);
1589       dbus_message_unref (reply);
1590     }
1591
1592   return FALSE;
1593 }
1594
1595 static dbus_bool_t
1596 bus_driver_handle_reload_config (DBusConnection *connection,
1597                                  BusTransaction *transaction,
1598                                  DBusMessage    *message,
1599                                  DBusError      *error)
1600 {
1601   BusContext *context;
1602   DBusMessage *reply;
1603
1604   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1605
1606   reply = NULL;
1607
1608   context = bus_connection_get_context (connection);
1609   if (!bus_context_reload_config (context, error))
1610     goto failed;
1611
1612   reply = dbus_message_new_method_return (message);
1613   if (reply == NULL)
1614     goto oom;
1615
1616   if (! bus_transaction_send_from_driver (transaction, connection, reply))
1617     goto oom;
1618
1619   dbus_message_unref (reply);
1620   return TRUE;
1621
1622  oom:
1623   BUS_SET_OOM (error);
1624
1625  failed:
1626   _DBUS_ASSERT_ERROR_IS_SET (error);
1627   if (reply)
1628     dbus_message_unref (reply);
1629   return FALSE;
1630 }
1631
1632 static dbus_bool_t
1633 bus_driver_handle_get_id (DBusConnection *connection,
1634                           BusTransaction *transaction,
1635                           DBusMessage    *message,
1636                           DBusError      *error)
1637 {
1638   BusContext *context;
1639   DBusMessage *reply;
1640   DBusString uuid;
1641   const char *v_STRING;
1642
1643   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1644
1645   if (!_dbus_string_init (&uuid))
1646     {
1647       BUS_SET_OOM (error);
1648       return FALSE;
1649     }
1650
1651   reply = NULL;
1652
1653   context = bus_connection_get_context (connection);
1654   if (!bus_context_get_id (context, &uuid))
1655     goto oom;
1656
1657   reply = dbus_message_new_method_return (message);
1658   if (reply == NULL)
1659     goto oom;
1660
1661   v_STRING = _dbus_string_get_const_data (&uuid);
1662   if (!dbus_message_append_args (reply,
1663                                  DBUS_TYPE_STRING, &v_STRING,
1664                                  DBUS_TYPE_INVALID))
1665     goto oom;
1666
1667   _dbus_assert (dbus_message_has_signature (reply, "s"));
1668
1669   if (! bus_transaction_send_from_driver (transaction, connection, reply))
1670     goto oom;
1671
1672   _dbus_string_free (&uuid);
1673   dbus_message_unref (reply);
1674   return TRUE;
1675
1676  oom:
1677   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1678
1679   BUS_SET_OOM (error);
1680
1681   if (reply)
1682     dbus_message_unref (reply);
1683   _dbus_string_free (&uuid);
1684   return FALSE;
1685 }
1686
1687 typedef struct
1688 {
1689   const char *name;
1690   const char *in_args;
1691   const char *out_args;
1692   dbus_bool_t (* handler) (DBusConnection *connection,
1693                            BusTransaction *transaction,
1694                            DBusMessage    *message,
1695                            DBusError      *error);
1696 } MessageHandler;
1697
1698 /* For speed it might be useful to sort this in order of
1699  * frequency of use (but doesn't matter with only a few items
1700  * anyhow)
1701  */
1702 static const MessageHandler dbus_message_handlers[] = {
1703   { "Hello",
1704     "",
1705     DBUS_TYPE_STRING_AS_STRING,
1706     bus_driver_handle_hello },
1707   { "RequestName",
1708     DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_UINT32_AS_STRING,
1709     DBUS_TYPE_UINT32_AS_STRING,
1710     bus_driver_handle_acquire_service },
1711   { "ReleaseName",
1712     DBUS_TYPE_STRING_AS_STRING,
1713     DBUS_TYPE_UINT32_AS_STRING,
1714     bus_driver_handle_release_service },
1715   { "StartServiceByName",
1716     DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_UINT32_AS_STRING,
1717     DBUS_TYPE_UINT32_AS_STRING,
1718     bus_driver_handle_activate_service },
1719   { "UpdateActivationEnvironment",
1720     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,
1721     "",
1722     bus_driver_handle_update_activation_environment },
1723   { "NameHasOwner",
1724     DBUS_TYPE_STRING_AS_STRING,
1725     DBUS_TYPE_BOOLEAN_AS_STRING,
1726     bus_driver_handle_service_exists },
1727   { "ListNames",
1728     "",
1729     DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
1730     bus_driver_handle_list_services },
1731   { "ListActivatableNames",
1732     "",
1733     DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
1734     bus_driver_handle_list_activatable_services },
1735   { "AddMatch",
1736     DBUS_TYPE_STRING_AS_STRING,
1737     "",
1738     bus_driver_handle_add_match },
1739   { "RemoveMatch",
1740     DBUS_TYPE_STRING_AS_STRING,
1741     "",
1742     bus_driver_handle_remove_match },
1743   { "GetNameOwner",
1744     DBUS_TYPE_STRING_AS_STRING,
1745     DBUS_TYPE_STRING_AS_STRING,
1746     bus_driver_handle_get_service_owner },
1747   { "ListQueuedOwners",
1748     DBUS_TYPE_STRING_AS_STRING,
1749     DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
1750     bus_driver_handle_list_queued_owners },
1751   { "GetConnectionUnixUser",
1752     DBUS_TYPE_STRING_AS_STRING,
1753     DBUS_TYPE_UINT32_AS_STRING,
1754     bus_driver_handle_get_connection_unix_user },
1755   { "GetConnectionUnixProcessID",
1756     DBUS_TYPE_STRING_AS_STRING,
1757     DBUS_TYPE_UINT32_AS_STRING,
1758     bus_driver_handle_get_connection_unix_process_id },
1759   { "GetAdtAuditSessionData",
1760     DBUS_TYPE_STRING_AS_STRING,
1761     DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING,
1762     bus_driver_handle_get_adt_audit_session_data },
1763   { "GetConnectionSELinuxSecurityContext",
1764     DBUS_TYPE_STRING_AS_STRING,
1765     DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING,
1766     bus_driver_handle_get_connection_selinux_security_context },
1767   { "ReloadConfig",
1768     "",
1769     "",
1770     bus_driver_handle_reload_config },
1771   { "GetId",
1772     "",
1773     DBUS_TYPE_STRING_AS_STRING,
1774     bus_driver_handle_get_id },
1775   { "GetConnectionCredentials", "s", "a{sv}",
1776     bus_driver_handle_get_connection_credentials },
1777   { NULL, NULL, NULL, NULL }
1778 };
1779
1780 static dbus_bool_t bus_driver_handle_introspect (DBusConnection *,
1781     BusTransaction *, DBusMessage *, DBusError *);
1782
1783 static const MessageHandler introspectable_message_handlers[] = {
1784   { "Introspect", "", DBUS_TYPE_STRING_AS_STRING, bus_driver_handle_introspect },
1785   { NULL, NULL, NULL, NULL }
1786 };
1787
1788 #ifdef DBUS_ENABLE_STATS
1789 static const MessageHandler stats_message_handlers[] = {
1790   { "GetStats", "", "a{sv}", bus_stats_handle_get_stats },
1791   { "GetConnectionStats", "s", "a{sv}", bus_stats_handle_get_connection_stats },
1792   { NULL, NULL, NULL, NULL }
1793 };
1794 #endif
1795
1796 typedef struct {
1797   const char *name;
1798   const MessageHandler *message_handlers;
1799   const char *extra_introspection;
1800 } InterfaceHandler;
1801
1802 /* These should ideally be sorted by frequency of use, although it
1803  * probably doesn't matter with this few items */
1804 static InterfaceHandler interface_handlers[] = {
1805   { DBUS_INTERFACE_DBUS, dbus_message_handlers,
1806     "    <signal name=\"NameOwnerChanged\">\n"
1807     "      <arg type=\"s\"/>\n"
1808     "      <arg type=\"s\"/>\n"
1809     "      <arg type=\"s\"/>\n"
1810     "    </signal>\n"
1811     "    <signal name=\"NameLost\">\n"
1812     "      <arg type=\"s\"/>\n"
1813     "    </signal>\n"
1814     "    <signal name=\"NameAcquired\">\n"
1815     "      <arg type=\"s\"/>\n"
1816     "    </signal>\n" },
1817   { DBUS_INTERFACE_INTROSPECTABLE, introspectable_message_handlers, NULL },
1818 #ifdef DBUS_ENABLE_STATS
1819   { BUS_INTERFACE_STATS, stats_message_handlers, NULL },
1820 #endif
1821   { NULL, NULL, NULL }
1822 };
1823
1824 static dbus_bool_t
1825 write_args_for_direction (DBusString *xml,
1826                           const char *signature,
1827                           dbus_bool_t in)
1828 {
1829   DBusTypeReader typereader;
1830   DBusString sigstr;
1831   int current_type;
1832
1833   _dbus_string_init_const (&sigstr, signature);
1834   _dbus_type_reader_init_types_only (&typereader, &sigstr, 0);
1835
1836   while ((current_type = _dbus_type_reader_get_current_type (&typereader)) != DBUS_TYPE_INVALID)
1837     {
1838       const DBusString *subsig;
1839       int start, len;
1840
1841       _dbus_type_reader_get_signature (&typereader, &subsig, &start, &len);
1842       if (!_dbus_string_append_printf (xml, "      <arg direction=\"%s\" type=\"",
1843                                        in ? "in" : "out"))
1844         goto oom;
1845       if (!_dbus_string_append_len (xml,
1846                                     _dbus_string_get_const_data (subsig) + start,
1847                                     len))
1848         goto oom;
1849       if (!_dbus_string_append (xml, "\"/>\n"))
1850         goto oom;
1851
1852       _dbus_type_reader_next (&typereader);
1853     }
1854   return TRUE;
1855  oom:
1856   return FALSE;
1857 }
1858
1859 dbus_bool_t
1860 bus_driver_generate_introspect_string (DBusString *xml)
1861 {
1862   const InterfaceHandler *ih;
1863   const MessageHandler *mh;
1864
1865   if (!_dbus_string_append (xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE))
1866     return FALSE;
1867   if (!_dbus_string_append (xml, "<node>\n"))
1868     return FALSE;
1869
1870   for (ih = interface_handlers; ih->name != NULL; ih++)
1871     {
1872       if (!_dbus_string_append_printf (xml, "  <interface name=\"%s\">\n",
1873                                        ih->name))
1874         return FALSE;
1875
1876       for (mh = ih->message_handlers; mh->name != NULL; mh++)
1877         {
1878           if (!_dbus_string_append_printf (xml, "    <method name=\"%s\">\n",
1879                                            mh->name))
1880             return FALSE;
1881
1882           if (!write_args_for_direction (xml, mh->in_args, TRUE))
1883             return FALSE;
1884
1885           if (!write_args_for_direction (xml, mh->out_args, FALSE))
1886             return FALSE;
1887
1888           if (!_dbus_string_append (xml, "    </method>\n"))
1889             return FALSE;
1890         }
1891
1892       if (ih->extra_introspection != NULL &&
1893           !_dbus_string_append (xml, ih->extra_introspection))
1894         return FALSE;
1895
1896       if (!_dbus_string_append (xml, "  </interface>\n"))
1897         return FALSE;
1898     }
1899
1900   if (!_dbus_string_append (xml, "</node>\n"))
1901     return FALSE;
1902
1903   return TRUE;
1904 }
1905
1906 static dbus_bool_t
1907 bus_driver_handle_introspect (DBusConnection *connection,
1908                               BusTransaction *transaction,
1909                               DBusMessage    *message,
1910                               DBusError      *error)
1911 {
1912   DBusString xml;
1913   DBusMessage *reply;
1914   const char *v_STRING;
1915
1916   _dbus_verbose ("Introspect() on bus driver\n");
1917
1918   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1919
1920   reply = NULL;
1921
1922   if (! dbus_message_get_args (message, error,
1923                                DBUS_TYPE_INVALID))
1924     {
1925       _DBUS_ASSERT_ERROR_IS_SET (error);
1926       return FALSE;
1927     }
1928
1929   if (!_dbus_string_init (&xml))
1930     {
1931       BUS_SET_OOM (error);
1932       return FALSE;
1933     }
1934
1935   if (!bus_driver_generate_introspect_string (&xml))
1936     goto oom;
1937
1938   v_STRING = _dbus_string_get_const_data (&xml);
1939
1940   reply = dbus_message_new_method_return (message);
1941   if (reply == NULL)
1942     goto oom;
1943
1944   if (! dbus_message_append_args (reply,
1945                                   DBUS_TYPE_STRING, &v_STRING,
1946                                   DBUS_TYPE_INVALID))
1947     goto oom;
1948
1949   if (! bus_transaction_send_from_driver (transaction, connection, reply))
1950     goto oom;
1951
1952   dbus_message_unref (reply);
1953   _dbus_string_free (&xml);
1954
1955   return TRUE;
1956
1957  oom:
1958   BUS_SET_OOM (error);
1959
1960   if (reply)
1961     dbus_message_unref (reply);
1962
1963   _dbus_string_free (&xml);
1964
1965   return FALSE;
1966 }
1967
1968 dbus_bool_t
1969 bus_driver_handle_message (DBusConnection *connection,
1970                            BusTransaction *transaction,
1971                            DBusMessage    *message,
1972                            DBusError      *error)
1973 {
1974   const char *name, *interface;
1975   const InterfaceHandler *ih;
1976   const MessageHandler *mh;
1977   dbus_bool_t found_interface = FALSE;
1978
1979   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1980
1981   if (dbus_message_is_signal (message, "org.freedesktop.systemd1.Activator", "ActivationFailure"))
1982     {
1983       BusContext *context;
1984
1985       context = bus_connection_get_context (connection);
1986       return dbus_activation_systemd_failure(bus_context_get_activation(context), message);
1987     }
1988
1989   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL)
1990     {
1991       _dbus_verbose ("Driver got a non-method-call message, ignoring\n");
1992       return TRUE; /* we just ignore this */
1993     }
1994
1995   /* may be NULL, which means "any interface will do" */
1996   interface = dbus_message_get_interface (message);
1997
1998   _dbus_assert (dbus_message_get_member (message) != NULL);
1999
2000   name = dbus_message_get_member (message);
2001
2002   _dbus_verbose ("Driver got a method call: %s\n", name);
2003
2004   /* security checks should have kept this from getting here */
2005   _dbus_assert (dbus_message_get_sender (message) != NULL ||
2006                 strcmp (name, "Hello") == 0);
2007
2008   for (ih = interface_handlers; ih->name != NULL; ih++)
2009     {
2010       if (interface != NULL && strcmp (interface, ih->name) != 0)
2011         continue;
2012
2013       found_interface = TRUE;
2014
2015       for (mh = ih->message_handlers; mh->name != NULL; mh++)
2016         {
2017           if (strcmp (mh->name, name) != 0)
2018             continue;
2019
2020           _dbus_verbose ("Found driver handler for %s\n", name);
2021
2022           if (!dbus_message_has_signature (message, mh->in_args))
2023             {
2024               _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2025               _dbus_verbose ("Call to %s has wrong args (%s, expected %s)\n",
2026                              name, dbus_message_get_signature (message),
2027                              mh->in_args);
2028
2029               dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
2030                               "Call to %s has wrong args (%s, expected %s)\n",
2031                               name, dbus_message_get_signature (message),
2032                               mh->in_args);
2033               _DBUS_ASSERT_ERROR_IS_SET (error);
2034               return FALSE;
2035             }
2036
2037           if ((* mh->handler) (connection, transaction, message, error))
2038             {
2039               _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2040               _dbus_verbose ("Driver handler succeeded\n");
2041               return TRUE;
2042             }
2043           else
2044             {
2045               _DBUS_ASSERT_ERROR_IS_SET (error);
2046               _dbus_verbose ("Driver handler returned failure\n");
2047               return FALSE;
2048             }
2049         }
2050     }
2051
2052   _dbus_verbose ("No driver handler for message \"%s\"\n",
2053                  name);
2054
2055   dbus_set_error (error, found_interface ? DBUS_ERROR_UNKNOWN_METHOD : DBUS_ERROR_UNKNOWN_INTERFACE,
2056                   "%s does not understand message %s",
2057                   DBUS_SERVICE_DBUS, name);
2058
2059   return FALSE;
2060 }
2061
2062 void
2063 bus_driver_remove_connection (DBusConnection *connection)
2064 {
2065   /* FIXME 1.0 Does nothing for now, should unregister the connection
2066    * with the bus driver.
2067    */
2068 }