2005-07-16 Colin Walters <walters@verbum.org>
[platform/upstream/dbus.git] / bus / driver.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* driver.c  Bus client (driver)
3  *
4  * Copyright (C) 2003 CodeFactory AB
5  * Copyright (C) 2003, 2004, 2005 Red Hat, Inc.
6  *
7  * Licensed under the Academic Free License version 2.1
8  * 
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  * 
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  *
23  */
24
25 #include "activation.h"
26 #include "connection.h"
27 #include "driver.h"
28 #include "dispatch.h"
29 #include "services.h"
30 #include "selinux.h"
31 #include "signals.h"
32 #include "utils.h"
33 #include <dbus/dbus-string.h>
34 #include <dbus/dbus-internals.h>
35 #include <dbus/dbus-marshal-recursive.h>
36 #include <string.h>
37
38 static dbus_bool_t bus_driver_send_welcome_message (DBusConnection *connection,
39                                                     DBusMessage    *hello_message,
40                                                     BusTransaction *transaction,
41                                                     DBusError      *error);
42
43 dbus_bool_t
44 bus_driver_send_service_owner_changed (const char     *service_name,
45                                        const char     *old_owner,
46                                        const char     *new_owner,
47                                        BusTransaction *transaction,
48                                        DBusError      *error)
49 {
50   DBusMessage *message;
51   dbus_bool_t retval;
52   const char *null_service;
53
54   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
55
56   null_service = "";
57   _dbus_verbose ("sending name owner changed: %s [%s -> %s]\n",
58                  service_name, 
59                  old_owner ? old_owner : null_service, 
60                  new_owner ? new_owner : null_service);
61
62   message = dbus_message_new_signal (DBUS_PATH_DBUS,
63                                      DBUS_INTERFACE_DBUS,
64                                      "NameOwnerChanged");
65   
66   if (message == NULL)
67     {
68       BUS_SET_OOM (error);
69       return FALSE;
70     }
71   
72   if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS))
73     goto oom;
74
75   if (!dbus_message_append_args (message,
76                                  DBUS_TYPE_STRING, &service_name,
77                                  DBUS_TYPE_STRING, old_owner ? &old_owner : &null_service,
78                                  DBUS_TYPE_STRING, new_owner ? &new_owner : &null_service,
79                                  DBUS_TYPE_INVALID))
80     goto oom;
81
82   _dbus_assert (dbus_message_has_signature (message, "sss"));
83   
84   retval = bus_dispatch_matches (transaction, NULL, NULL, message, error);
85   dbus_message_unref (message);
86
87   return retval;
88
89  oom:
90   dbus_message_unref (message);
91   BUS_SET_OOM (error);
92   return FALSE;
93 }
94
95 dbus_bool_t
96 bus_driver_send_service_lost (DBusConnection *connection,
97                               const char     *service_name,
98                               BusTransaction *transaction,
99                               DBusError      *error)
100 {
101   DBusMessage *message;
102
103   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
104   
105   message = dbus_message_new_signal (DBUS_PATH_DBUS,
106                                      DBUS_INTERFACE_DBUS,
107                                      "NameLost");
108   
109   if (message == NULL)
110     {
111       BUS_SET_OOM (error);
112       return FALSE;
113     }
114   
115   if (!dbus_message_set_destination (message, bus_connection_get_name (connection)) ||
116       !dbus_message_append_args (message,
117                                  DBUS_TYPE_STRING, &service_name,
118                                  DBUS_TYPE_INVALID))
119     {
120       dbus_message_unref (message);
121       BUS_SET_OOM (error);
122       return FALSE;
123     }
124
125   if (!bus_transaction_send_from_driver (transaction, connection, message))
126     {
127       dbus_message_unref (message);
128       BUS_SET_OOM (error);
129       return FALSE;
130     }
131   else
132     {
133       dbus_message_unref (message);
134       return TRUE;
135     }
136 }
137
138 dbus_bool_t
139 bus_driver_send_service_acquired (DBusConnection *connection,
140                                   const char     *service_name,
141                                   BusTransaction *transaction,
142                                   DBusError      *error)
143 {
144   DBusMessage *message;
145
146   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
147   
148   message = dbus_message_new_signal (DBUS_PATH_DBUS,
149                                      DBUS_INTERFACE_DBUS,
150                                      "NameAcquired");
151
152   if (message == NULL)
153     {
154       BUS_SET_OOM (error);
155       return FALSE;
156     }
157   
158   if (!dbus_message_set_destination (message, bus_connection_get_name (connection)) ||
159       !dbus_message_append_args (message,
160                                  DBUS_TYPE_STRING, &service_name,
161                                  DBUS_TYPE_INVALID))
162     {
163       dbus_message_unref (message);
164       BUS_SET_OOM (error);
165       return FALSE;
166     }
167
168   if (!bus_transaction_send_from_driver (transaction, connection, message))
169     {
170       dbus_message_unref (message);
171       BUS_SET_OOM (error);
172       return FALSE;
173     }
174   else
175     {
176       dbus_message_unref (message);
177       return TRUE;
178     }
179 }
180
181 static dbus_bool_t
182 create_unique_client_name (BusRegistry *registry,
183                            DBusString  *str)
184 {
185   /* We never want to use the same unique client name twice, because
186    * we want to guarantee that if you send a message to a given unique
187    * name, you always get the same application. So we use two numbers
188    * for INT_MAX * INT_MAX combinations, should be pretty safe against
189    * wraparound.
190    */
191   /* FIXME these should be in BusRegistry rather than static vars */
192   static int next_major_number = 0;
193   static int next_minor_number = 0;
194   int len;
195   
196   len = _dbus_string_get_length (str);
197   
198   while (TRUE)
199     {
200       /* start out with 1-0, go to 1-1, 1-2, 1-3,
201        * up to 1-MAXINT, then 2-0, 2-1, etc.
202        */
203       if (next_minor_number <= 0)
204         {
205           next_major_number += 1;
206           next_minor_number = 0;
207           if (next_major_number <= 0)
208             _dbus_assert_not_reached ("INT_MAX * INT_MAX clients were added");
209         }
210
211       _dbus_assert (next_major_number > 0);
212       _dbus_assert (next_minor_number >= 0);
213
214       /* appname:MAJOR-MINOR */
215       
216       if (!_dbus_string_append (str, ":"))
217         return FALSE;
218       
219       if (!_dbus_string_append_int (str, next_major_number))
220         return FALSE;
221
222       if (!_dbus_string_append (str, "."))
223         return FALSE;
224       
225       if (!_dbus_string_append_int (str, next_minor_number))
226         return FALSE;
227
228       next_minor_number += 1;
229       
230       /* Check if a client with the name exists */
231       if (bus_registry_lookup (registry, str) == NULL)
232         break;
233
234       /* drop the number again, try the next one. */
235       _dbus_string_set_length (str, len);
236     }
237
238   return TRUE;
239 }
240
241 static dbus_bool_t
242 bus_driver_handle_hello (DBusConnection *connection,
243                          BusTransaction *transaction,
244                          DBusMessage    *message,
245                          DBusError      *error)
246 {
247   DBusString unique_name;
248   BusService *service;
249   dbus_bool_t retval;
250   BusRegistry *registry;
251   BusConnections *connections;
252
253   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
254
255   if (bus_connection_is_active (connection))
256     {
257       /* We already handled an Hello message for this connection. */
258       dbus_set_error (error, DBUS_ERROR_FAILED,
259                       "Already handled an Hello message");
260       return FALSE;
261     }
262
263   /* Note that when these limits are exceeded we don't disconnect the
264    * connection; we just sort of leave it hanging there until it times
265    * out or disconnects itself or is dropped due to the max number of
266    * incomplete connections. It's even OK if the connection wants to
267    * retry the hello message, we support that.
268    */
269   connections = bus_connection_get_connections (connection);
270   if (!bus_connections_check_limits (connections, connection,
271                                      error))
272     {
273       _DBUS_ASSERT_ERROR_IS_SET (error);
274       return FALSE;
275     }
276   
277   if (!_dbus_string_init (&unique_name))
278     {
279       BUS_SET_OOM (error);
280       return FALSE;
281     }
282
283   retval = FALSE;
284
285   registry = bus_connection_get_registry (connection);
286   
287   if (!create_unique_client_name (registry, &unique_name))
288     {
289       BUS_SET_OOM (error);
290       goto out_0;
291     }
292
293   if (!bus_connection_complete (connection, &unique_name, error))
294     {
295       _DBUS_ASSERT_ERROR_IS_SET (error);
296       goto out_0;
297     }
298   
299   if (!dbus_message_set_sender (message,
300                                 bus_connection_get_name (connection)))
301     {
302       BUS_SET_OOM (error);
303       goto out_0;
304     }
305   
306   if (!bus_driver_send_welcome_message (connection, message, transaction, error))
307     goto out_0;
308
309   /* Create the service */
310   service = bus_registry_ensure (registry,
311                                  &unique_name, connection, transaction, error);
312   if (service == NULL)
313     goto out_0;
314   
315   bus_service_set_prohibit_replacement (service, TRUE);
316
317   _dbus_assert (bus_connection_is_active (connection));
318   retval = TRUE;
319   
320  out_0:
321   _dbus_string_free (&unique_name);
322   return retval;
323 }
324
325 static dbus_bool_t
326 bus_driver_send_welcome_message (DBusConnection *connection,
327                                  DBusMessage    *hello_message,
328                                  BusTransaction *transaction,
329                                  DBusError      *error)
330 {
331   DBusMessage *welcome;
332   const char *name;
333
334   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
335   
336   name = bus_connection_get_name (connection);
337   _dbus_assert (name != NULL);
338   
339   welcome = dbus_message_new_method_return (hello_message);
340   if (welcome == NULL)
341     {
342       BUS_SET_OOM (error);
343       return FALSE;
344     }
345   
346   if (!dbus_message_append_args (welcome,
347                                  DBUS_TYPE_STRING, &name,
348                                  DBUS_TYPE_INVALID))
349     {
350       dbus_message_unref (welcome);
351       BUS_SET_OOM (error);
352       return FALSE;
353     }
354
355   _dbus_assert (dbus_message_has_signature (welcome, DBUS_TYPE_STRING_AS_STRING));
356   
357   if (!bus_transaction_send_from_driver (transaction, connection, welcome))
358     {
359       dbus_message_unref (welcome);
360       BUS_SET_OOM (error);
361       return FALSE;
362     }
363   else
364     {
365       dbus_message_unref (welcome);
366       return TRUE;
367     }
368 }
369
370 static dbus_bool_t
371 bus_driver_handle_list_services (DBusConnection *connection,
372                                  BusTransaction *transaction,
373                                  DBusMessage    *message,
374                                  DBusError      *error)
375 {
376   DBusMessage *reply;
377   int len;
378   char **services;
379   BusRegistry *registry;
380   int i;
381   DBusMessageIter iter;
382   DBusMessageIter sub;
383
384   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
385   
386   registry = bus_connection_get_registry (connection);
387   
388   reply = dbus_message_new_method_return (message);
389   if (reply == NULL)
390     {
391       BUS_SET_OOM (error);
392       return FALSE;
393     }
394
395   if (!bus_registry_list_services (registry, &services, &len))
396     {
397       dbus_message_unref (reply);
398       BUS_SET_OOM (error);
399       return FALSE;
400     }
401
402   dbus_message_iter_init_append (reply, &iter);
403   
404   if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY,
405                                          DBUS_TYPE_STRING_AS_STRING,
406                                          &sub))
407     {
408       dbus_free_string_array (services);
409       dbus_message_unref (reply);
410       BUS_SET_OOM (error);
411       return FALSE;
412     }
413
414   {
415     /* Include the bus driver in the list */
416     const char *v_STRING = DBUS_SERVICE_DBUS;
417     if (!dbus_message_iter_append_basic (&sub, DBUS_TYPE_STRING,
418                                          &v_STRING))
419       {
420         dbus_free_string_array (services);
421         dbus_message_unref (reply);
422         BUS_SET_OOM (error);
423         return FALSE;
424       }
425   }
426   
427   i = 0;
428   while (i < len)
429     {
430       if (!dbus_message_iter_append_basic (&sub, DBUS_TYPE_STRING,
431                                            &services[i]))
432         {
433           dbus_free_string_array (services);
434           dbus_message_unref (reply);
435           BUS_SET_OOM (error);
436           return FALSE;
437         }
438       ++i;
439     }
440
441   if (!dbus_message_iter_close_container (&iter, &sub))
442     {
443       dbus_free_string_array (services);
444       dbus_message_unref (reply);
445       BUS_SET_OOM (error);
446       return FALSE;
447     }
448   
449   dbus_free_string_array (services);
450   
451   if (!bus_transaction_send_from_driver (transaction, connection, reply))
452     {
453       dbus_message_unref (reply);
454       BUS_SET_OOM (error);
455       return FALSE;
456     }
457   else
458     {
459       dbus_message_unref (reply);
460       return TRUE;
461     }
462 }
463
464 static dbus_bool_t
465 bus_driver_handle_acquire_service (DBusConnection *connection,
466                                    BusTransaction *transaction,
467                                    DBusMessage    *message,
468                                    DBusError      *error)
469 {
470   DBusMessage *reply;
471   DBusString service_name;
472   const char *name;
473   int service_reply;
474   dbus_uint32_t flags;
475   dbus_bool_t retval;
476   BusRegistry *registry;
477
478   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
479   
480   registry = bus_connection_get_registry (connection);
481   
482   if (!dbus_message_get_args (message, error,
483                               DBUS_TYPE_STRING, &name,
484                               DBUS_TYPE_UINT32, &flags,
485                               DBUS_TYPE_INVALID))
486     return FALSE;
487   
488   _dbus_verbose ("Trying to own name %s with flags 0x%x\n", name, flags);
489   
490   retval = FALSE;
491   reply = NULL;
492
493   _dbus_string_init_const (&service_name, name);
494
495   if (!bus_registry_acquire_service (registry, connection,
496                                      &service_name, flags,
497                                      &service_reply, transaction,
498                                      error))
499     goto out;
500   
501   reply = dbus_message_new_method_return (message);
502   if (reply == NULL)
503     {
504       BUS_SET_OOM (error);
505       goto out;
506     }
507
508   if (!dbus_message_append_args (reply, DBUS_TYPE_UINT32, &service_reply, DBUS_TYPE_INVALID))
509     {
510       BUS_SET_OOM (error);
511       goto out;
512     }
513
514   if (!bus_transaction_send_from_driver (transaction, connection, reply))
515     {
516       BUS_SET_OOM (error);
517       goto out;
518     }
519
520   retval = TRUE;
521   
522  out:
523   if (reply)
524     dbus_message_unref (reply);
525   return retval;
526
527
528 static dbus_bool_t
529 bus_driver_handle_service_exists (DBusConnection *connection,
530                                   BusTransaction *transaction,
531                                   DBusMessage    *message,
532                                   DBusError      *error)
533 {
534   DBusMessage *reply;
535   DBusString service_name;
536   BusService *service;
537   dbus_bool_t service_exists;
538   const char *name;
539   dbus_bool_t retval;
540   BusRegistry *registry;
541
542   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
543   
544   registry = bus_connection_get_registry (connection);
545   
546   if (!dbus_message_get_args (message, error,
547                               DBUS_TYPE_STRING, &name,
548                               DBUS_TYPE_INVALID))
549     return FALSE;
550
551   retval = FALSE;
552
553   if (strcmp (name, DBUS_SERVICE_DBUS) == 0)
554     {
555       service_exists = TRUE;
556     }
557   else
558     {
559       _dbus_string_init_const (&service_name, name);
560       service = bus_registry_lookup (registry, &service_name);
561       service_exists = service != NULL;
562     }
563   
564   reply = dbus_message_new_method_return (message);
565   if (reply == NULL)
566     {
567       BUS_SET_OOM (error);
568       goto out;
569     }
570
571   if (!dbus_message_append_args (reply,
572                                  DBUS_TYPE_BOOLEAN, &service_exists,
573                                  0))
574     {
575       BUS_SET_OOM (error);
576       goto out;
577     }
578
579   if (!bus_transaction_send_from_driver (transaction, connection, reply))
580     {
581       BUS_SET_OOM (error);
582       goto out;
583     }
584
585   retval = TRUE;
586   
587  out:
588   if (reply)
589     dbus_message_unref (reply);
590
591   return retval;
592 }
593
594 static dbus_bool_t
595 bus_driver_handle_activate_service (DBusConnection *connection,
596                                     BusTransaction *transaction,
597                                     DBusMessage    *message,
598                                     DBusError      *error)
599 {
600   dbus_uint32_t flags;
601   const char *name;
602   dbus_bool_t retval;
603   BusActivation *activation;
604
605   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
606   
607   activation = bus_connection_get_activation (connection);
608   
609   if (!dbus_message_get_args (message, error,
610                               DBUS_TYPE_STRING, &name,
611                               DBUS_TYPE_UINT32, &flags,
612                               DBUS_TYPE_INVALID))
613     {
614       _DBUS_ASSERT_ERROR_IS_SET (error);
615       _dbus_verbose ("No memory to get arguments to StartServiceByName\n");
616       return FALSE;
617     }
618
619   retval = FALSE;
620
621   if (!bus_activation_activate_service (activation, connection, transaction, FALSE,
622                                         message, name, error))
623     {
624       _DBUS_ASSERT_ERROR_IS_SET (error);
625       _dbus_verbose ("bus_activation_activate_service() failed\n");
626       goto out;
627     }
628
629   retval = TRUE;
630   
631  out:
632   return retval;
633 }
634
635 static dbus_bool_t
636 send_ack_reply (DBusConnection *connection,
637                 BusTransaction *transaction,
638                 DBusMessage    *message,
639                 DBusError      *error)
640 {
641   DBusMessage *reply;
642
643   reply = dbus_message_new_method_return (message);
644   if (reply == NULL)
645     {
646       BUS_SET_OOM (error);
647       return FALSE;
648     }
649
650   if (!bus_transaction_send_from_driver (transaction, connection, reply))
651     {
652       BUS_SET_OOM (error);
653       dbus_message_unref (reply);
654       return FALSE;
655     }
656
657   dbus_message_unref (reply);
658   
659   return TRUE;
660 }
661
662 static dbus_bool_t
663 bus_driver_handle_add_match (DBusConnection *connection,
664                              BusTransaction *transaction,
665                              DBusMessage    *message,
666                              DBusError      *error)
667 {
668   BusMatchRule *rule;
669   const char *text;
670   DBusString str;
671   BusMatchmaker *matchmaker;
672   
673   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
674
675   text = NULL;
676   rule = NULL;
677
678   if (bus_connection_get_n_match_rules (connection) >=
679       bus_context_get_max_match_rules_per_connection (bus_transaction_get_context (transaction)))
680     {
681       dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
682                       "Connection \"%s\" is not allowed to add more match rules "
683                       "(increase limits in configuration file if required)",
684                       bus_connection_is_active (connection) ?
685                       bus_connection_get_name (connection) :
686                       "(inactive)");
687       goto failed;
688     }
689   
690   if (!dbus_message_get_args (message, error,
691                               DBUS_TYPE_STRING, &text,
692                               DBUS_TYPE_INVALID))
693     {
694       _dbus_verbose ("No memory to get arguments to AddMatch\n");
695       goto failed;
696     }
697
698   _dbus_string_init_const (&str, text);
699
700   rule = bus_match_rule_parse (connection, &str, error);
701   if (rule == NULL)
702     goto failed;
703
704   matchmaker = bus_connection_get_matchmaker (connection);
705
706   if (!bus_matchmaker_add_rule (matchmaker, rule))
707     {
708       BUS_SET_OOM (error);
709       goto failed;
710     }
711
712   if (!send_ack_reply (connection, transaction,
713                        message, error))
714     {
715       bus_matchmaker_remove_rule (matchmaker, rule);
716       goto failed;
717     }
718   
719   bus_match_rule_unref (rule);
720   
721   return TRUE;
722
723  failed:
724   _DBUS_ASSERT_ERROR_IS_SET (error);
725   if (rule)
726     bus_match_rule_unref (rule);
727   return FALSE;
728 }
729
730 static dbus_bool_t
731 bus_driver_handle_remove_match (DBusConnection *connection,
732                                 BusTransaction *transaction,
733                                 DBusMessage    *message,
734                                 DBusError      *error)
735 {
736   BusMatchRule *rule;
737   const char *text;
738   DBusString str;
739   BusMatchmaker *matchmaker;
740   
741   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
742
743   text = NULL;
744   rule = NULL;
745   
746   if (!dbus_message_get_args (message, error,
747                               DBUS_TYPE_STRING, &text,
748                               DBUS_TYPE_INVALID))
749     {
750       _dbus_verbose ("No memory to get arguments to RemoveMatch\n");
751       goto failed;
752     }
753
754   _dbus_string_init_const (&str, text);
755
756   rule = bus_match_rule_parse (connection, &str, error);
757   if (rule == NULL)
758     goto failed;
759
760   /* Send the ack before we remove the rule, since the ack is undone
761    * on transaction cancel, but rule removal isn't.
762    */
763   if (!send_ack_reply (connection, transaction,
764                        message, error))
765     goto failed;
766   
767   matchmaker = bus_connection_get_matchmaker (connection);
768
769   if (!bus_matchmaker_remove_rule_by_value (matchmaker, rule, error))
770     goto failed;
771
772   bus_match_rule_unref (rule);
773   
774   return TRUE;
775
776  failed:
777   _DBUS_ASSERT_ERROR_IS_SET (error);
778   if (rule)
779     bus_match_rule_unref (rule);
780   return FALSE;
781 }
782
783 static dbus_bool_t
784 bus_driver_handle_get_service_owner (DBusConnection *connection,
785                                      BusTransaction *transaction,
786                                      DBusMessage    *message,
787                                      DBusError      *error)
788 {
789   const char *text;
790   const char *base_name;
791   DBusString str;
792   BusRegistry *registry;
793   BusService *service;
794   DBusMessage *reply;
795   
796   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
797
798   registry = bus_connection_get_registry (connection);
799
800   text = NULL;
801   reply = NULL;
802
803   if (! dbus_message_get_args (message, error,
804                                DBUS_TYPE_STRING, &text,
805                                DBUS_TYPE_INVALID))
806       goto failed;
807
808   _dbus_string_init_const (&str, text);
809   service = bus_registry_lookup (registry, &str);
810   if (service == NULL &&
811       _dbus_string_equal_c_str (&str, DBUS_SERVICE_DBUS))
812     {
813       /* ORG_FREEDESKTOP_DBUS owns itself */
814       base_name = DBUS_SERVICE_DBUS;
815     }
816   else if (service == NULL)
817     {
818       dbus_set_error (error, 
819                       DBUS_ERROR_NAME_HAS_NO_OWNER,
820                       "Could not get owner of name '%s': no such name", text);
821       goto failed;
822     }
823   else
824     {
825       base_name = bus_connection_get_name (bus_service_get_primary_owner (service));
826       if (base_name == NULL)
827         {
828           /* FIXME - how is this error possible? */
829           dbus_set_error (error,
830                           DBUS_ERROR_FAILED,
831                           "Could not determine unique name for '%s'", text);
832           goto failed;
833         }
834       _dbus_assert (*base_name == ':');      
835     }
836
837   _dbus_assert (base_name != NULL);
838
839   reply = dbus_message_new_method_return (message);
840   if (reply == NULL)
841     goto oom;
842
843   if (! dbus_message_append_args (reply, 
844                                   DBUS_TYPE_STRING, &base_name,
845                                   DBUS_TYPE_INVALID))
846     goto oom;
847   
848   if (! bus_transaction_send_from_driver (transaction, connection, reply))
849     goto oom;
850
851   dbus_message_unref (reply);
852
853   return TRUE;
854
855  oom:
856   BUS_SET_OOM (error);
857
858  failed:
859   _DBUS_ASSERT_ERROR_IS_SET (error);
860   if (reply)
861     dbus_message_unref (reply);
862   return FALSE;
863 }
864
865 static dbus_bool_t
866 bus_driver_handle_get_connection_unix_user (DBusConnection *connection,
867                                             BusTransaction *transaction,
868                                             DBusMessage    *message,
869                                             DBusError      *error)
870 {
871   const char *service;
872   DBusString str;
873   BusRegistry *registry;
874   BusService *serv;
875   DBusConnection *conn;
876   DBusMessage *reply;
877   unsigned long uid;
878   dbus_uint32_t uid32;
879
880   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
881
882   registry = bus_connection_get_registry (connection);
883
884   service = NULL;
885   reply = NULL;
886
887   if (! dbus_message_get_args (message, error,
888                                DBUS_TYPE_STRING, &service,
889                                DBUS_TYPE_INVALID))
890       goto failed;
891
892   _dbus_verbose ("asked for UID of connection %s\n", service);
893
894   _dbus_string_init_const (&str, service);
895   serv = bus_registry_lookup (registry, &str);
896   if (serv == NULL)
897     {
898       dbus_set_error (error, 
899                       DBUS_ERROR_NAME_HAS_NO_OWNER,
900                       "Could not get UID of name '%s': no such name", service);
901       goto failed;
902     }
903
904   conn = bus_service_get_primary_owner (serv);
905
906   reply = dbus_message_new_method_return (message);
907   if (reply == NULL)
908     goto oom;
909
910   if (!dbus_connection_get_unix_user (conn, &uid))
911     {
912       dbus_set_error (error,
913                       DBUS_ERROR_FAILED,
914                       "Could not determine UID for '%s'", service);
915       goto failed;
916     }
917
918   uid32 = uid;
919   if (! dbus_message_append_args (reply,
920                                   DBUS_TYPE_UINT32, &uid32,
921                                   DBUS_TYPE_INVALID))
922     goto oom;
923
924   if (! bus_transaction_send_from_driver (transaction, connection, reply))
925     goto oom;
926
927   dbus_message_unref (reply);
928
929   return TRUE;
930
931  oom:
932   BUS_SET_OOM (error);
933
934  failed:
935   _DBUS_ASSERT_ERROR_IS_SET (error);
936   if (reply)
937     dbus_message_unref (reply);
938   return FALSE;
939 }
940
941 static dbus_bool_t
942 bus_driver_handle_get_connection_unix_process_id (DBusConnection *connection,
943                                                   BusTransaction *transaction,
944                                                   DBusMessage    *message,
945                                                   DBusError      *error)
946 {
947   const char *service;
948   DBusString str;
949   BusRegistry *registry;
950   BusService *serv;
951   DBusConnection *conn;
952   DBusMessage *reply;
953   unsigned long pid;
954   dbus_uint32_t pid32;
955
956   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
957
958   registry = bus_connection_get_registry (connection);
959
960   service = NULL;
961   reply = NULL;
962
963   if (! dbus_message_get_args (message, error,
964                                DBUS_TYPE_STRING, &service,
965                                DBUS_TYPE_INVALID))
966       goto failed;
967
968   _dbus_verbose ("asked for PID of connection %s\n", service);
969
970   _dbus_string_init_const (&str, service);
971   serv = bus_registry_lookup (registry, &str);
972   if (serv == NULL)
973     {
974       dbus_set_error (error, 
975                       DBUS_ERROR_NAME_HAS_NO_OWNER,
976                       "Could not get PID of name '%s': no such name", service);
977       goto failed;
978     }
979
980   conn = bus_service_get_primary_owner (serv);
981
982   reply = dbus_message_new_method_return (message);
983   if (reply == NULL)
984     goto oom;
985
986   if (!dbus_connection_get_unix_process_id (conn, &pid))
987     {
988       dbus_set_error (error,
989                       DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN,
990                       "Could not determine PID for '%s'", service);
991       goto failed;
992     }
993
994   pid32 = pid;
995   if (! dbus_message_append_args (reply,
996                                   DBUS_TYPE_UINT32, &pid32,
997                                   DBUS_TYPE_INVALID))
998     goto oom;
999
1000   if (! bus_transaction_send_from_driver (transaction, connection, reply))
1001     goto oom;
1002
1003   dbus_message_unref (reply);
1004
1005   return TRUE;
1006
1007  oom:
1008   BUS_SET_OOM (error);
1009
1010  failed:
1011   _DBUS_ASSERT_ERROR_IS_SET (error);
1012   if (reply)
1013     dbus_message_unref (reply);
1014   return FALSE;
1015 }
1016
1017 static dbus_bool_t
1018 bus_driver_handle_get_connection_selinux_security_context (DBusConnection *connection,
1019                                                            BusTransaction *transaction,
1020                                                            DBusMessage    *message,
1021                                                            DBusError      *error)
1022 {
1023   const char *service;
1024   DBusString str;
1025   BusRegistry *registry;
1026   BusService *serv;
1027   DBusConnection *conn;
1028   DBusMessage *reply;
1029   BusSELinuxID *context;
1030
1031   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1032
1033   registry = bus_connection_get_registry (connection);
1034
1035   service = NULL;
1036   reply = NULL;
1037
1038   if (! dbus_message_get_args (message, error,
1039                                DBUS_TYPE_STRING, &service,
1040                                DBUS_TYPE_INVALID))
1041       goto failed;
1042
1043   _dbus_verbose ("asked for security context of connection %s\n", service);
1044
1045   _dbus_string_init_const (&str, service);
1046   serv = bus_registry_lookup (registry, &str);
1047   if (serv == NULL)
1048     {
1049       dbus_set_error (error, 
1050                       DBUS_ERROR_NAME_HAS_NO_OWNER,
1051                       "Could not get security context of name '%s': no such name", service);
1052       goto failed;
1053     }
1054
1055   conn = bus_service_get_primary_owner (serv);
1056
1057   reply = dbus_message_new_method_return (message);
1058   if (reply == NULL)
1059     goto oom;
1060
1061   context = bus_connection_get_selinux_id (conn);
1062   if (!context)
1063     {
1064       dbus_set_error (error,
1065                       DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN,
1066                       "Could not determine security context for '%s'", service);
1067       goto failed;
1068     }
1069
1070   if (! bus_selinux_append_context (reply, context, error))
1071     goto failed;
1072
1073   if (! bus_transaction_send_from_driver (transaction, connection, reply))
1074     goto oom;
1075
1076   dbus_message_unref (reply);
1077
1078   return TRUE;
1079
1080  oom:
1081   BUS_SET_OOM (error);
1082
1083  failed:
1084   _DBUS_ASSERT_ERROR_IS_SET (error);
1085   if (reply)
1086     dbus_message_unref (reply);
1087   return FALSE;
1088 }
1089
1090 static dbus_bool_t
1091 bus_driver_handle_reload_config (DBusConnection *connection,
1092                                  BusTransaction *transaction,
1093                                  DBusMessage    *message,
1094                                  DBusError      *error)
1095 {
1096   BusContext *context;
1097   dbus_bool_t retval;
1098
1099   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1100
1101   retval = FALSE;
1102
1103   context = bus_connection_get_context (connection);
1104   if (!bus_context_reload_config (context, error))
1105     {
1106       _DBUS_ASSERT_ERROR_IS_SET (error);
1107       goto out;
1108     }
1109
1110   retval = TRUE;
1111   
1112  out:
1113   return retval;
1114 }
1115
1116 /* For speed it might be useful to sort this in order of
1117  * frequency of use (but doesn't matter with only a few items
1118  * anyhow)
1119  */
1120 struct
1121 {
1122   const char *name;
1123   const char *in_args;
1124   const char *out_args;
1125   dbus_bool_t (* handler) (DBusConnection *connection,
1126                            BusTransaction *transaction,
1127                            DBusMessage    *message,
1128                            DBusError      *error);
1129 } message_handlers[] = {
1130   { "RequestName",
1131     DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_UINT32_AS_STRING,
1132     DBUS_TYPE_UINT32_AS_STRING,
1133     bus_driver_handle_acquire_service },
1134   { "StartServiceByName",
1135     DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_UINT32_AS_STRING,
1136     DBUS_TYPE_UINT32_AS_STRING,
1137     bus_driver_handle_activate_service },
1138   { "Hello",
1139     "",
1140     DBUS_TYPE_STRING_AS_STRING,
1141     bus_driver_handle_hello },
1142   { "NameHasOwner",
1143     DBUS_TYPE_STRING_AS_STRING,
1144     DBUS_TYPE_BOOLEAN_AS_STRING,
1145     bus_driver_handle_service_exists },
1146   { "ListNames",
1147     "",
1148     DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
1149     bus_driver_handle_list_services },
1150   { "AddMatch",
1151     DBUS_TYPE_STRING_AS_STRING,
1152     "",
1153     bus_driver_handle_add_match },
1154   { "RemoveMatch",
1155     DBUS_TYPE_STRING_AS_STRING,
1156     "",
1157     bus_driver_handle_remove_match },
1158   { "GetNameOwner",
1159     DBUS_TYPE_STRING_AS_STRING,
1160     DBUS_TYPE_STRING_AS_STRING,
1161     bus_driver_handle_get_service_owner },
1162   { "GetConnectionUnixUser",
1163     DBUS_TYPE_STRING_AS_STRING,
1164     DBUS_TYPE_UINT32_AS_STRING,
1165     bus_driver_handle_get_connection_unix_user },
1166   { "GetConnectionUnixProcessID",
1167     DBUS_TYPE_STRING_AS_STRING,
1168     DBUS_TYPE_UINT32_AS_STRING,
1169     bus_driver_handle_get_connection_unix_process_id },
1170   { "GetConnectionSELinuxSecurityContext",
1171     DBUS_TYPE_STRING_AS_STRING,
1172     DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING,
1173     bus_driver_handle_get_connection_selinux_security_context },
1174   { "ReloadConfig",
1175     "",
1176     "",
1177     bus_driver_handle_reload_config }
1178 };
1179
1180 static dbus_bool_t
1181 write_args_for_direction (DBusString *xml,
1182                           const char *signature,
1183                           dbus_bool_t in)
1184 {
1185   DBusTypeReader typereader;
1186   DBusString sigstr;
1187   int current_type;
1188   
1189   _dbus_string_init_const (&sigstr, signature);
1190   _dbus_type_reader_init_types_only (&typereader, &sigstr, 0);
1191       
1192   while ((current_type = _dbus_type_reader_get_current_type (&typereader)) != DBUS_TYPE_INVALID)
1193     {
1194       const DBusString *subsig;
1195       int start, len;
1196
1197       _dbus_type_reader_get_signature (&typereader, &subsig, &start, &len);
1198       if (!_dbus_string_append_printf (xml, "      <arg direction=\"%s\" type=\"",
1199                                        in ? "in" : "out"))
1200         goto oom;
1201       if (!_dbus_string_append_len (xml,
1202                                     _dbus_string_get_const_data (subsig) + start,
1203                                     len))
1204         goto oom;
1205       if (!_dbus_string_append (xml, "\"/>\n"))
1206         goto oom;
1207
1208       _dbus_type_reader_next (&typereader);
1209     }
1210   return TRUE;
1211  oom:
1212   return FALSE;
1213 }
1214
1215 static dbus_bool_t
1216 bus_driver_handle_introspect (DBusConnection *connection,
1217                               BusTransaction *transaction,
1218                               DBusMessage    *message,
1219                               DBusError      *error)
1220 {
1221   DBusString xml;
1222   DBusMessage *reply;
1223   const char *v_STRING;
1224   int i;
1225
1226   _dbus_verbose ("Introspect() on bus driver\n");
1227   
1228   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1229
1230   reply = NULL;
1231
1232   if (! dbus_message_get_args (message, error,
1233                                DBUS_TYPE_INVALID))
1234     {
1235       _DBUS_ASSERT_ERROR_IS_SET (error);
1236       return FALSE;
1237     }
1238
1239   if (!_dbus_string_init (&xml))
1240     {
1241       BUS_SET_OOM (error);
1242       return FALSE;
1243     }
1244
1245   if (!_dbus_string_append (&xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE))
1246     goto oom;
1247   if (!_dbus_string_append (&xml, "<node>\n"))
1248     goto oom;
1249   if (!_dbus_string_append_printf (&xml, "  <interface name=\"%s\">\n", DBUS_INTERFACE_INTROSPECTABLE))
1250     goto oom;
1251   if (!_dbus_string_append (&xml, "    <method name=\"Introspect\">\n"))
1252     goto oom;
1253   if (!_dbus_string_append_printf (&xml, "      <arg name=\"data\" direction=\"out\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING))
1254     goto oom;
1255   if (!_dbus_string_append (&xml, "    </method>\n"))
1256     goto oom;
1257   if (!_dbus_string_append (&xml, "  </interface>\n"))
1258     goto oom;
1259
1260   if (!_dbus_string_append_printf (&xml, "  <interface name=\"%s\">\n",
1261                                    DBUS_INTERFACE_DBUS))
1262     goto oom;
1263
1264   i = 0;
1265   while (i < _DBUS_N_ELEMENTS (message_handlers))
1266     {
1267           
1268       if (!_dbus_string_append_printf (&xml, "    <method name=\"%s\">\n",
1269                                        message_handlers[i].name))
1270         goto oom;
1271
1272       if (!write_args_for_direction (&xml, message_handlers[i].in_args, TRUE))
1273         goto oom;
1274
1275       if (!write_args_for_direction (&xml, message_handlers[i].out_args, FALSE))
1276         goto oom;
1277
1278       if (!_dbus_string_append (&xml, "    </method>\n"))
1279         goto oom;
1280       
1281       ++i;
1282     }
1283   
1284   if (!_dbus_string_append (&xml, "  </interface>\n"))
1285     goto oom;
1286   
1287   if (!_dbus_string_append (&xml, "</node>\n"))
1288     goto oom;
1289
1290   reply = dbus_message_new_method_return (message);
1291   if (reply == NULL)
1292     goto oom;
1293
1294   v_STRING = _dbus_string_get_const_data (&xml);
1295   if (! dbus_message_append_args (reply,
1296                                   DBUS_TYPE_STRING, &v_STRING,
1297                                   DBUS_TYPE_INVALID))
1298     goto oom;
1299
1300   if (! bus_transaction_send_from_driver (transaction, connection, reply))
1301     goto oom;
1302
1303   dbus_message_unref (reply);
1304   _dbus_string_free (&xml);
1305
1306   return TRUE;
1307
1308  oom:
1309   BUS_SET_OOM (error);
1310
1311   if (reply)
1312     dbus_message_unref (reply);
1313
1314   _dbus_string_free (&xml);
1315   
1316   return FALSE;
1317 }
1318
1319 dbus_bool_t
1320 bus_driver_handle_message (DBusConnection *connection,
1321                            BusTransaction *transaction,
1322                            DBusMessage    *message,
1323                            DBusError      *error)
1324 {
1325   const char *name, *sender, *interface;
1326   int i;
1327
1328   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1329
1330   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL)
1331     {
1332       _dbus_verbose ("Driver got a non-method-call message, ignoring\n");
1333       return TRUE; /* we just ignore this */
1334     }
1335
1336   if (dbus_message_is_method_call (message,
1337                                    DBUS_INTERFACE_INTROSPECTABLE,
1338                                    "Introspect"))
1339     return bus_driver_handle_introspect (connection, transaction, message, error);
1340   
1341   interface = dbus_message_get_interface (message);
1342   if (interface == NULL)
1343     interface = DBUS_INTERFACE_DBUS;
1344   
1345   _dbus_assert (dbus_message_get_member (message) != NULL);
1346   
1347   name = dbus_message_get_member (message);
1348   sender = dbus_message_get_sender (message);
1349   
1350   if (strcmp (interface,
1351               DBUS_INTERFACE_DBUS) != 0)
1352     {
1353       _dbus_verbose ("Driver got message to unknown interface \"%s\"\n",
1354                      interface);
1355       goto unknown;
1356     }
1357   
1358   _dbus_verbose ("Driver got a method call: %s\n",
1359                  dbus_message_get_member (message));
1360   
1361   /* security checks should have kept this from getting here */
1362   _dbus_assert (sender != NULL || strcmp (name, "Hello") == 0);
1363   
1364   i = 0;
1365   while (i < _DBUS_N_ELEMENTS (message_handlers))
1366     {
1367       if (strcmp (message_handlers[i].name, name) == 0)
1368         {
1369           _dbus_verbose ("Found driver handler for %s\n", name);
1370
1371           if (!dbus_message_has_signature (message, message_handlers[i].in_args))
1372             {
1373               _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1374               _dbus_verbose ("Call to %s has wrong args (%s, expected %s)\n",
1375                              name, dbus_message_get_signature (message),
1376                              message_handlers[i].in_args);
1377               
1378               dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
1379                               "Call to %s has wrong args (%s, expected %s)\n",
1380                               name, dbus_message_get_signature (message),
1381                               message_handlers[i].in_args);
1382               _DBUS_ASSERT_ERROR_IS_SET (error);
1383               return FALSE;
1384             }
1385           
1386           if ((* message_handlers[i].handler) (connection, transaction, message, error))
1387             {
1388               _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1389               _dbus_verbose ("Driver handler succeeded\n");
1390               return TRUE;
1391             }
1392           else
1393             {
1394               _DBUS_ASSERT_ERROR_IS_SET (error);
1395               _dbus_verbose ("Driver handler returned failure\n");
1396               return FALSE;
1397             }
1398         }
1399       
1400       ++i;
1401     }
1402
1403  unknown:
1404   _dbus_verbose ("No driver handler for message \"%s\"\n",
1405                  name);
1406
1407   dbus_set_error (error, DBUS_ERROR_UNKNOWN_METHOD,
1408                   "%s does not understand message %s",
1409                   DBUS_SERVICE_DBUS, name);
1410   
1411   return FALSE;
1412 }
1413
1414 void
1415 bus_driver_remove_connection (DBusConnection *connection)
1416 {
1417   /* FIXME Does nothing for now, should unregister the connection
1418    * with the bus driver.
1419    */
1420 }