a6c4faff11b437df8fee4b1bcc2de8dca28630d8
[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   DBusMessage *reply;
1098
1099   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1100
1101   reply = NULL;
1102   
1103   context = bus_connection_get_context (connection);
1104   if (!bus_context_reload_config (context, error))
1105     goto failed;
1106
1107   reply = dbus_message_new_method_return (message);
1108   if (reply == NULL)
1109     goto oom;
1110
1111   if (! bus_transaction_send_from_driver (transaction, connection, reply))
1112     goto oom;
1113
1114   dbus_message_unref (reply);
1115   return TRUE;
1116
1117  oom:
1118   BUS_SET_OOM (error);
1119
1120  failed:
1121   _DBUS_ASSERT_ERROR_IS_SET (error);
1122   if (reply)
1123     dbus_message_unref (reply);
1124   return FALSE;
1125 }
1126
1127 /* For speed it might be useful to sort this in order of
1128  * frequency of use (but doesn't matter with only a few items
1129  * anyhow)
1130  */
1131 struct
1132 {
1133   const char *name;
1134   const char *in_args;
1135   const char *out_args;
1136   dbus_bool_t (* handler) (DBusConnection *connection,
1137                            BusTransaction *transaction,
1138                            DBusMessage    *message,
1139                            DBusError      *error);
1140 } message_handlers[] = {
1141   { "RequestName",
1142     DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_UINT32_AS_STRING,
1143     DBUS_TYPE_UINT32_AS_STRING,
1144     bus_driver_handle_acquire_service },
1145   { "StartServiceByName",
1146     DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_UINT32_AS_STRING,
1147     DBUS_TYPE_UINT32_AS_STRING,
1148     bus_driver_handle_activate_service },
1149   { "Hello",
1150     "",
1151     DBUS_TYPE_STRING_AS_STRING,
1152     bus_driver_handle_hello },
1153   { "NameHasOwner",
1154     DBUS_TYPE_STRING_AS_STRING,
1155     DBUS_TYPE_BOOLEAN_AS_STRING,
1156     bus_driver_handle_service_exists },
1157   { "ListNames",
1158     "",
1159     DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
1160     bus_driver_handle_list_services },
1161   { "AddMatch",
1162     DBUS_TYPE_STRING_AS_STRING,
1163     "",
1164     bus_driver_handle_add_match },
1165   { "RemoveMatch",
1166     DBUS_TYPE_STRING_AS_STRING,
1167     "",
1168     bus_driver_handle_remove_match },
1169   { "GetNameOwner",
1170     DBUS_TYPE_STRING_AS_STRING,
1171     DBUS_TYPE_STRING_AS_STRING,
1172     bus_driver_handle_get_service_owner },
1173   { "GetConnectionUnixUser",
1174     DBUS_TYPE_STRING_AS_STRING,
1175     DBUS_TYPE_UINT32_AS_STRING,
1176     bus_driver_handle_get_connection_unix_user },
1177   { "GetConnectionUnixProcessID",
1178     DBUS_TYPE_STRING_AS_STRING,
1179     DBUS_TYPE_UINT32_AS_STRING,
1180     bus_driver_handle_get_connection_unix_process_id },
1181   { "GetConnectionSELinuxSecurityContext",
1182     DBUS_TYPE_STRING_AS_STRING,
1183     DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING,
1184     bus_driver_handle_get_connection_selinux_security_context },
1185   { "ReloadConfig",
1186     "",
1187     "",
1188     bus_driver_handle_reload_config }
1189 };
1190
1191 static dbus_bool_t
1192 write_args_for_direction (DBusString *xml,
1193                           const char *signature,
1194                           dbus_bool_t in)
1195 {
1196   DBusTypeReader typereader;
1197   DBusString sigstr;
1198   int current_type;
1199   
1200   _dbus_string_init_const (&sigstr, signature);
1201   _dbus_type_reader_init_types_only (&typereader, &sigstr, 0);
1202       
1203   while ((current_type = _dbus_type_reader_get_current_type (&typereader)) != DBUS_TYPE_INVALID)
1204     {
1205       const DBusString *subsig;
1206       int start, len;
1207
1208       _dbus_type_reader_get_signature (&typereader, &subsig, &start, &len);
1209       if (!_dbus_string_append_printf (xml, "      <arg direction=\"%s\" type=\"",
1210                                        in ? "in" : "out"))
1211         goto oom;
1212       if (!_dbus_string_append_len (xml,
1213                                     _dbus_string_get_const_data (subsig) + start,
1214                                     len))
1215         goto oom;
1216       if (!_dbus_string_append (xml, "\"/>\n"))
1217         goto oom;
1218
1219       _dbus_type_reader_next (&typereader);
1220     }
1221   return TRUE;
1222  oom:
1223   return FALSE;
1224 }
1225
1226 static dbus_bool_t
1227 bus_driver_handle_introspect (DBusConnection *connection,
1228                               BusTransaction *transaction,
1229                               DBusMessage    *message,
1230                               DBusError      *error)
1231 {
1232   DBusString xml;
1233   DBusMessage *reply;
1234   const char *v_STRING;
1235   int i;
1236
1237   _dbus_verbose ("Introspect() on bus driver\n");
1238   
1239   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1240
1241   reply = NULL;
1242
1243   if (! dbus_message_get_args (message, error,
1244                                DBUS_TYPE_INVALID))
1245     {
1246       _DBUS_ASSERT_ERROR_IS_SET (error);
1247       return FALSE;
1248     }
1249
1250   if (!_dbus_string_init (&xml))
1251     {
1252       BUS_SET_OOM (error);
1253       return FALSE;
1254     }
1255
1256   if (!_dbus_string_append (&xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE))
1257     goto oom;
1258   if (!_dbus_string_append (&xml, "<node>\n"))
1259     goto oom;
1260   if (!_dbus_string_append_printf (&xml, "  <interface name=\"%s\">\n", DBUS_INTERFACE_INTROSPECTABLE))
1261     goto oom;
1262   if (!_dbus_string_append (&xml, "    <method name=\"Introspect\">\n"))
1263     goto oom;
1264   if (!_dbus_string_append_printf (&xml, "      <arg name=\"data\" direction=\"out\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING))
1265     goto oom;
1266   if (!_dbus_string_append (&xml, "    </method>\n"))
1267     goto oom;
1268   if (!_dbus_string_append (&xml, "  </interface>\n"))
1269     goto oom;
1270
1271   if (!_dbus_string_append_printf (&xml, "  <interface name=\"%s\">\n",
1272                                    DBUS_INTERFACE_DBUS))
1273     goto oom;
1274
1275   i = 0;
1276   while (i < _DBUS_N_ELEMENTS (message_handlers))
1277     {
1278           
1279       if (!_dbus_string_append_printf (&xml, "    <method name=\"%s\">\n",
1280                                        message_handlers[i].name))
1281         goto oom;
1282
1283       if (!write_args_for_direction (&xml, message_handlers[i].in_args, TRUE))
1284         goto oom;
1285
1286       if (!write_args_for_direction (&xml, message_handlers[i].out_args, FALSE))
1287         goto oom;
1288
1289       if (!_dbus_string_append (&xml, "    </method>\n"))
1290         goto oom;
1291       
1292       ++i;
1293     }
1294
1295   if (!_dbus_string_append_printf (&xml, "    <signal name=\"NameOwnerChanged\">\n"))
1296     goto oom;
1297   
1298   if (!_dbus_string_append_printf (&xml, "      <arg type=\"s\"/>\n"))
1299     goto oom;
1300   
1301   if (!_dbus_string_append_printf (&xml, "      <arg type=\"s\"/>\n"))
1302     goto oom;
1303   
1304   if (!_dbus_string_append_printf (&xml, "      <arg type=\"s\"/>\n"))
1305     goto oom;
1306   
1307   if (!_dbus_string_append_printf (&xml, "    </signal>\n"))
1308     goto oom;
1309
1310
1311
1312   if (!_dbus_string_append_printf (&xml, "    <signal name=\"NameLost\">\n"))
1313     goto oom;
1314   
1315   if (!_dbus_string_append_printf (&xml, "      <arg type=\"s\"/>\n"))
1316     goto oom;
1317   
1318   if (!_dbus_string_append_printf (&xml, "    </signal>\n"))
1319     goto oom;
1320
1321
1322
1323   if (!_dbus_string_append_printf (&xml, "    <signal name=\"NameAcquired\">\n"))
1324     goto oom;
1325   
1326   if (!_dbus_string_append_printf (&xml, "      <arg type=\"s\"/>\n"))
1327     goto oom;
1328   
1329   if (!_dbus_string_append_printf (&xml, "    </signal>\n"))
1330     goto oom;
1331
1332
1333   
1334   if (!_dbus_string_append (&xml, "  </interface>\n"))
1335     goto oom;
1336   
1337   if (!_dbus_string_append (&xml, "</node>\n"))
1338     goto oom;
1339
1340   reply = dbus_message_new_method_return (message);
1341   if (reply == NULL)
1342     goto oom;
1343
1344   v_STRING = _dbus_string_get_const_data (&xml);
1345   if (! dbus_message_append_args (reply,
1346                                   DBUS_TYPE_STRING, &v_STRING,
1347                                   DBUS_TYPE_INVALID))
1348     goto oom;
1349
1350   if (! bus_transaction_send_from_driver (transaction, connection, reply))
1351     goto oom;
1352
1353   dbus_message_unref (reply);
1354   _dbus_string_free (&xml);
1355
1356   return TRUE;
1357
1358  oom:
1359   BUS_SET_OOM (error);
1360
1361   if (reply)
1362     dbus_message_unref (reply);
1363
1364   _dbus_string_free (&xml);
1365   
1366   return FALSE;
1367 }
1368
1369 dbus_bool_t
1370 bus_driver_handle_message (DBusConnection *connection,
1371                            BusTransaction *transaction,
1372                            DBusMessage    *message,
1373                            DBusError      *error)
1374 {
1375   const char *name, *sender, *interface;
1376   int i;
1377
1378   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1379
1380   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL)
1381     {
1382       _dbus_verbose ("Driver got a non-method-call message, ignoring\n");
1383       return TRUE; /* we just ignore this */
1384     }
1385
1386   if (dbus_message_is_method_call (message,
1387                                    DBUS_INTERFACE_INTROSPECTABLE,
1388                                    "Introspect"))
1389     return bus_driver_handle_introspect (connection, transaction, message, error);
1390   
1391   interface = dbus_message_get_interface (message);
1392   if (interface == NULL)
1393     interface = DBUS_INTERFACE_DBUS;
1394   
1395   _dbus_assert (dbus_message_get_member (message) != NULL);
1396   
1397   name = dbus_message_get_member (message);
1398   sender = dbus_message_get_sender (message);
1399   
1400   if (strcmp (interface,
1401               DBUS_INTERFACE_DBUS) != 0)
1402     {
1403       _dbus_verbose ("Driver got message to unknown interface \"%s\"\n",
1404                      interface);
1405       goto unknown;
1406     }
1407   
1408   _dbus_verbose ("Driver got a method call: %s\n",
1409                  dbus_message_get_member (message));
1410   
1411   /* security checks should have kept this from getting here */
1412   _dbus_assert (sender != NULL || strcmp (name, "Hello") == 0);
1413   
1414   i = 0;
1415   while (i < _DBUS_N_ELEMENTS (message_handlers))
1416     {
1417       if (strcmp (message_handlers[i].name, name) == 0)
1418         {
1419           _dbus_verbose ("Found driver handler for %s\n", name);
1420
1421           if (!dbus_message_has_signature (message, message_handlers[i].in_args))
1422             {
1423               _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1424               _dbus_verbose ("Call to %s has wrong args (%s, expected %s)\n",
1425                              name, dbus_message_get_signature (message),
1426                              message_handlers[i].in_args);
1427               
1428               dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
1429                               "Call to %s has wrong args (%s, expected %s)\n",
1430                               name, dbus_message_get_signature (message),
1431                               message_handlers[i].in_args);
1432               _DBUS_ASSERT_ERROR_IS_SET (error);
1433               return FALSE;
1434             }
1435           
1436           if ((* message_handlers[i].handler) (connection, transaction, message, error))
1437             {
1438               _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1439               _dbus_verbose ("Driver handler succeeded\n");
1440               return TRUE;
1441             }
1442           else
1443             {
1444               _DBUS_ASSERT_ERROR_IS_SET (error);
1445               _dbus_verbose ("Driver handler returned failure\n");
1446               return FALSE;
1447             }
1448         }
1449       
1450       ++i;
1451     }
1452
1453  unknown:
1454   _dbus_verbose ("No driver handler for message \"%s\"\n",
1455                  name);
1456
1457   dbus_set_error (error, DBUS_ERROR_UNKNOWN_METHOD,
1458                   "%s does not understand message %s",
1459                   DBUS_SERVICE_DBUS, name);
1460   
1461   return FALSE;
1462 }
1463
1464 void
1465 bus_driver_remove_connection (DBusConnection *connection)
1466 {
1467   /* FIXME Does nothing for now, should unregister the connection
1468    * with the bus driver.
1469    */
1470 }