2005-04-13 David Zeuthen <davidz@redhat.com>
[platform/upstream/dbus.git] / bus / services.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* services.c  Service management
3  *
4  * Copyright (C) 2003  Red Hat, Inc.
5  * Copyright (C) 2003  CodeFactory AB
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 #include <dbus/dbus-hash.h>
25 #include <dbus/dbus-list.h>
26 #include <dbus/dbus-mempool.h>
27 #include <dbus/dbus-marshal-validate.h>
28
29 #include "driver.h"
30 #include "services.h"
31 #include "connection.h"
32 #include "utils.h"
33 #include "activation.h"
34 #include "policy.h"
35 #include "bus.h"
36 #include "selinux.h"
37
38 struct BusService
39 {
40   int refcount;
41
42   BusRegistry *registry;
43   char *name;
44   DBusList *owners;
45   
46   unsigned int prohibit_replacement : 1;
47 };
48
49 struct BusRegistry
50 {
51   int refcount;
52
53   BusContext *context;
54   
55   DBusHashTable *service_hash;
56   DBusMemPool   *service_pool;
57
58   DBusHashTable *service_sid_table;
59 };
60
61 BusRegistry*
62 bus_registry_new (BusContext *context)
63 {
64   BusRegistry *registry;
65
66   registry = dbus_new0 (BusRegistry, 1);
67   if (registry == NULL)
68     return NULL;
69
70   registry->refcount = 1;
71   registry->context = context;
72   
73   registry->service_hash = _dbus_hash_table_new (DBUS_HASH_STRING,
74                                                  NULL, NULL);
75   if (registry->service_hash == NULL)
76     goto failed;
77   
78   registry->service_pool = _dbus_mem_pool_new (sizeof (BusService),
79                                                TRUE);
80   if (registry->service_pool == NULL)
81     goto failed;
82
83   registry->service_sid_table = NULL;
84   
85   return registry;
86
87  failed:
88   bus_registry_unref (registry);
89   return NULL;
90 }
91
92 BusRegistry *
93 bus_registry_ref (BusRegistry *registry)
94 {
95   _dbus_assert (registry->refcount > 0);
96   registry->refcount += 1;
97
98   return registry;
99 }
100
101 void
102 bus_registry_unref  (BusRegistry *registry)
103 {
104   _dbus_assert (registry->refcount > 0);
105   registry->refcount -= 1;
106
107   if (registry->refcount == 0)
108     {
109       if (registry->service_hash)
110         _dbus_hash_table_unref (registry->service_hash);
111       if (registry->service_pool)
112         _dbus_mem_pool_free (registry->service_pool);
113       if (registry->service_sid_table)
114         _dbus_hash_table_unref (registry->service_sid_table);
115       
116       dbus_free (registry);
117     }
118 }
119
120 BusService*
121 bus_registry_lookup (BusRegistry      *registry,
122                      const DBusString *service_name)
123 {
124   BusService *service;
125
126   service = _dbus_hash_table_lookup_string (registry->service_hash,
127                                             _dbus_string_get_const_data (service_name));
128
129   return service;
130 }
131
132 BusService*
133 bus_registry_ensure (BusRegistry               *registry,
134                      const DBusString          *service_name,
135                      DBusConnection            *owner_if_created,
136                      BusTransaction            *transaction,
137                      DBusError                 *error)
138 {
139   BusService *service;
140
141   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
142   
143   _dbus_assert (owner_if_created != NULL);
144   _dbus_assert (transaction != NULL);
145
146   service = _dbus_hash_table_lookup_string (registry->service_hash,
147                                             _dbus_string_get_const_data (service_name));
148   if (service != NULL)
149     return service;
150   
151   service = _dbus_mem_pool_alloc (registry->service_pool);
152   if (service == NULL)
153     {
154       BUS_SET_OOM (error);
155       return NULL;
156     }
157
158   service->registry = registry;  
159   service->refcount = 1;
160
161   _dbus_verbose ("copying string %p '%s' to service->name\n",
162                  service_name, _dbus_string_get_const_data (service_name));
163   if (!_dbus_string_copy_data (service_name, &service->name))
164     {
165       _dbus_mem_pool_dealloc (registry->service_pool, service);
166       BUS_SET_OOM (error);
167       return NULL;
168     }
169   _dbus_verbose ("copied string %p '%s' to '%s'\n",
170                  service_name, _dbus_string_get_const_data (service_name),
171                  service->name);
172
173   if (!bus_driver_send_service_owner_changed (service->name, 
174                                               NULL,
175                                               bus_connection_get_name (owner_if_created),
176                                               transaction, error))
177     {
178       bus_service_unref (service);
179       return NULL;
180     }
181
182   if (!bus_activation_service_created (bus_context_get_activation (registry->context),
183                                        service->name, transaction, error))
184     {
185       bus_service_unref (service);
186       return NULL;
187     }
188   
189   if (!bus_service_add_owner (service, owner_if_created,
190                               transaction, error))
191     {
192       bus_service_unref (service);
193       return NULL;
194     }
195   
196   if (!_dbus_hash_table_insert_string (registry->service_hash,
197                                        service->name,
198                                        service))
199     {
200       /* The add_owner gets reverted on transaction cancel */
201       BUS_SET_OOM (error);
202       return NULL;
203     }
204   
205   return service;
206 }
207
208 void
209 bus_registry_foreach (BusRegistry               *registry,
210                       BusServiceForeachFunction  function,
211                       void                      *data)
212 {
213   DBusHashIter iter;
214   
215   _dbus_hash_iter_init (registry->service_hash, &iter);
216   while (_dbus_hash_iter_next (&iter))
217     {
218       BusService *service = _dbus_hash_iter_get_value (&iter);
219
220       (* function) (service, data);
221     }
222 }
223
224 dbus_bool_t
225 bus_registry_list_services (BusRegistry *registry,
226                             char      ***listp,
227                             int         *array_len)
228 {
229   int i, j, len;
230   char **retval;
231   DBusHashIter iter;
232    
233   len = _dbus_hash_table_get_n_entries (registry->service_hash);
234   retval = dbus_new (char *, len + 1);
235
236   if (retval == NULL)
237     return FALSE;
238
239   _dbus_hash_iter_init (registry->service_hash, &iter);
240   i = 0;
241   while (_dbus_hash_iter_next (&iter))
242     {
243       BusService *service = _dbus_hash_iter_get_value (&iter);
244
245       retval[i] = _dbus_strdup (service->name);
246       if (retval[i] == NULL)
247         goto error;
248
249       i++;
250     }
251
252   retval[i] = NULL;
253   
254   if (array_len)
255     *array_len = len;
256   
257   *listp = retval;
258   return TRUE;
259   
260  error:
261   for (j = 0; j < i; j++)
262     dbus_free (retval[i]);
263   dbus_free (retval);
264
265   return FALSE;
266 }
267
268 dbus_bool_t
269 bus_registry_acquire_service (BusRegistry      *registry,
270                               DBusConnection   *connection,
271                               const DBusString *service_name,
272                               dbus_uint32_t     flags,
273                               dbus_uint32_t    *result,
274                               BusTransaction   *transaction,
275                               DBusError        *error)
276 {
277   dbus_bool_t retval;
278   DBusConnection *old_owner;
279   DBusConnection *current_owner;
280   BusClientPolicy *policy;
281   BusService *service;
282   BusActivation  *activation;
283   BusSELinuxID *sid;
284   
285   retval = FALSE;
286
287   if (!_dbus_validate_bus_name (service_name, 0,
288                                 _dbus_string_get_length (service_name)))
289     {
290       dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
291                       "Requested bus name \"%s\" is not valid",
292                       _dbus_string_get_const_data (service_name));
293       
294       _dbus_verbose ("Attempt to acquire invalid service name\n");
295       
296       goto out;
297     }
298   
299   if (_dbus_string_get_byte (service_name, 0) == ':')
300     {
301       /* Not allowed; only base services can start with ':' */
302       dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
303                       "Cannot acquire a service starting with ':' such as \"%s\"",
304                       _dbus_string_get_const_data (service_name));
305       
306       _dbus_verbose ("Attempt to acquire invalid base service name \"%s\"",
307                      _dbus_string_get_const_data (service_name));
308       
309       goto out;
310     }
311
312   policy = bus_connection_get_policy (connection);
313   _dbus_assert (policy != NULL);
314
315   /* Note that if sid is #NULL then the bus's own context gets used
316    * in bus_connection_selinux_allows_acquire_service()
317    */
318   sid = bus_selinux_id_table_lookup (registry->service_sid_table,
319                                      service_name);
320
321   if (!bus_selinux_allows_acquire_service (connection, sid,
322                                            _dbus_string_get_const_data (service_name), error))
323     {
324
325       if (dbus_error_is_set (error) &&
326           dbus_error_has_name (error, DBUS_ERROR_NO_MEMORY))
327         {
328           goto out;
329         }
330
331       dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
332                       "Connection \"%s\" is not allowed to own the service \"%s\" due "
333                       "to SELinux policy",
334                       bus_connection_is_active (connection) ?
335                       bus_connection_get_name (connection) :
336                       "(inactive)",
337                       _dbus_string_get_const_data (service_name));
338       goto out;
339     }
340       
341   if (!bus_client_policy_check_can_own (policy, connection,
342                                         service_name))
343     {
344       dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
345                       "Connection \"%s\" is not allowed to own the service \"%s\" due "
346                       "to security policies in the configuration file",
347                       bus_connection_is_active (connection) ?
348                       bus_connection_get_name (connection) :
349                       "(inactive)",
350                       _dbus_string_get_const_data (service_name));
351       goto out;
352     }
353
354   if (bus_connection_get_n_services_owned (connection) >=
355       bus_context_get_max_services_per_connection (registry->context))
356     {
357       dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
358                       "Connection \"%s\" is not allowed to own more services "
359                       "(increase limits in configuration file if required)",
360                       bus_connection_is_active (connection) ?
361                       bus_connection_get_name (connection) :
362                       "(inactive)");
363       goto out;
364     }
365   
366   service = bus_registry_lookup (registry, service_name);
367
368   if (service != NULL)
369     old_owner = bus_service_get_primary_owner (service);
370   else
371     old_owner = NULL;
372       
373   if (service == NULL)
374     {
375       service = bus_registry_ensure (registry,
376                                      service_name, connection, transaction, error);
377       if (service == NULL)
378         goto out;
379     }
380
381   current_owner = bus_service_get_primary_owner (service);
382
383   if (old_owner == NULL)
384     {
385       _dbus_assert (current_owner == connection);
386
387       bus_service_set_prohibit_replacement (service,
388                                             (flags & DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT));      
389                         
390       *result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;      
391     }
392   else if (old_owner == connection)
393     *result = DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER;
394   else if (!((flags & DBUS_NAME_FLAG_REPLACE_EXISTING)))
395     *result = DBUS_REQUEST_NAME_REPLY_EXISTS;
396   else if (bus_service_get_prohibit_replacement (service))
397     {
398       /* Queue the connection */
399       if (!bus_service_add_owner (service, connection,
400                                   transaction, error))
401         goto out;
402       
403       *result = DBUS_REQUEST_NAME_REPLY_IN_QUEUE;
404     }
405   else
406     {
407       /* Replace the current owner */
408
409       /* We enqueue the new owner and remove the first one because
410        * that will cause NameAcquired and NameLost messages to
411        * be sent.
412        */
413       
414       if (!bus_service_add_owner (service, connection,
415                                   transaction, error))
416         goto out;
417
418       if (!bus_service_remove_owner (service, old_owner,
419                                      transaction, error))
420         goto out;
421       
422       _dbus_assert (connection == bus_service_get_primary_owner (service));
423       *result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
424     }
425
426   activation = bus_context_get_activation (registry->context);
427   retval = bus_activation_send_pending_auto_activation_messages (activation,
428                                                                  service,
429                                                                  transaction,
430                                                                  error);
431   
432  out:
433   return retval;
434 }
435
436 dbus_bool_t
437 bus_registry_set_service_context_table (BusRegistry   *registry,
438                                         DBusHashTable *table)
439 {
440   DBusHashTable *new_table;
441   DBusHashIter iter;
442   
443   new_table = bus_selinux_id_table_new ();
444   if (!new_table)
445     return FALSE;
446
447   _dbus_hash_iter_init (table, &iter);
448   while (_dbus_hash_iter_next (&iter))
449     {
450       const char *service = _dbus_hash_iter_get_string_key (&iter);
451       const char *context = _dbus_hash_iter_get_value (&iter);
452
453       if (!bus_selinux_id_table_insert (new_table,
454                                         service,
455                                         context))
456         return FALSE;
457     }
458   
459   if (registry->service_sid_table)
460     _dbus_hash_table_unref (registry->service_sid_table);
461   registry->service_sid_table = new_table;
462   return TRUE;
463 }
464
465 static void
466 bus_service_unlink_owner (BusService      *service,
467                           DBusConnection  *owner)
468 {
469   _dbus_list_remove_last (&service->owners, owner);
470   bus_connection_remove_owned_service (owner, service);
471 }
472
473 static void
474 bus_service_unlink (BusService *service)
475 {
476   _dbus_assert (service->owners == NULL);
477
478   /* the service may not be in the hash, if
479    * the failure causing transaction cancel
480    * was in the right place, but that's OK
481    */
482   _dbus_hash_table_remove_string (service->registry->service_hash,
483                                   service->name);
484   
485   bus_service_unref (service);
486 }
487
488 static void
489 bus_service_relink (BusService           *service,
490                     DBusPreallocatedHash *preallocated)
491 {
492   _dbus_assert (service->owners == NULL);
493   _dbus_assert (preallocated != NULL);
494
495   _dbus_hash_table_insert_string_preallocated (service->registry->service_hash,
496                                                preallocated,
497                                                service->name,
498                                                service);
499   
500   bus_service_ref (service);
501 }
502
503 /**
504  * Data used to represent an ownership cancellation in
505  * a bus transaction.
506  */
507 typedef struct
508 {
509   DBusConnection *connection; /**< the connection */
510   BusService *service;        /**< service to cancel ownership of */
511 } OwnershipCancelData;
512
513 static void
514 cancel_ownership (void *data)
515 {
516   OwnershipCancelData *d = data;
517
518   /* We don't need to send messages notifying of these
519    * changes, since we're reverting something that was
520    * cancelled (effectively never really happened)
521    */
522   bus_service_unlink_owner (d->service, d->connection);
523   
524   if (d->service->owners == NULL)
525     bus_service_unlink (d->service);
526 }
527
528 static void
529 free_ownership_cancel_data (void *data)
530 {
531   OwnershipCancelData *d = data;
532
533   dbus_connection_unref (d->connection);
534   bus_service_unref (d->service);
535   
536   dbus_free (d);
537 }
538
539 static dbus_bool_t
540 add_cancel_ownership_to_transaction (BusTransaction *transaction,
541                                      BusService     *service,
542                                      DBusConnection *connection)
543 {
544   OwnershipCancelData *d;
545
546   d = dbus_new (OwnershipCancelData, 1);
547   if (d == NULL)
548     return FALSE;
549   
550   d->service = service;
551   d->connection = connection;
552
553   if (!bus_transaction_add_cancel_hook (transaction, cancel_ownership, d,
554                                         free_ownership_cancel_data))
555     {
556       dbus_free (d);
557       return FALSE;
558     }
559
560   bus_service_ref (d->service);
561   dbus_connection_ref (d->connection);
562   
563   return TRUE;
564 }
565
566 /* this function is self-cancelling if you cancel the transaction */
567 dbus_bool_t
568 bus_service_add_owner (BusService     *service,
569                        DBusConnection *owner,
570                        BusTransaction *transaction,
571                        DBusError      *error)
572 {
573   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
574   
575  /* Send service acquired message first, OOM will result
576   * in cancelling the transaction
577   */
578   if (service->owners == NULL)
579     {
580       if (!bus_driver_send_service_acquired (owner, service->name, transaction, error))
581         return FALSE;
582     }
583   
584   if (!_dbus_list_append (&service->owners,
585                           owner))
586     {
587       BUS_SET_OOM (error);
588       return FALSE;
589     }
590
591   if (!bus_connection_add_owned_service (owner, service))
592     {
593       _dbus_list_remove_last (&service->owners, owner);
594       BUS_SET_OOM (error);
595       return FALSE;
596     }
597
598   if (!add_cancel_ownership_to_transaction (transaction,
599                                             service,
600                                             owner))
601     {
602       bus_service_unlink_owner (service, owner);
603       BUS_SET_OOM (error);
604       return FALSE;
605     }
606   
607   return TRUE;
608 }
609
610 typedef struct
611 {
612   DBusConnection *connection;
613   BusService     *service;
614   DBusConnection *before_connection; /* restore to position before this connection in owners list */
615   DBusList       *connection_link;
616   DBusList       *service_link;
617   DBusPreallocatedHash *hash_entry;
618 } OwnershipRestoreData;
619
620 static void
621 restore_ownership (void *data)
622 {
623   OwnershipRestoreData *d = data;
624   DBusList *link;
625
626   _dbus_assert (d->service_link != NULL);
627   _dbus_assert (d->connection_link != NULL);
628   
629   if (d->service->owners == NULL)
630     {
631       _dbus_assert (d->hash_entry != NULL);
632       bus_service_relink (d->service, d->hash_entry);
633     }
634   else
635     {
636       _dbus_assert (d->hash_entry == NULL);
637     }
638   
639   /* We don't need to send messages notifying of these
640    * changes, since we're reverting something that was
641    * cancelled (effectively never really happened)
642    */
643   link = _dbus_list_get_first_link (&d->service->owners);
644   while (link != NULL)
645     {
646       if (link->data == d->before_connection)
647         break;
648
649       link = _dbus_list_get_next_link (&d->service->owners, link);
650     }
651   
652   _dbus_list_insert_before_link (&d->service->owners, link, d->connection_link);
653
654   /* Note that removing then restoring this changes the order in which
655    * ServiceDeleted messages are sent on destruction of the
656    * connection.  This should be OK as the only guarantee there is
657    * that the base service is destroyed last, and we never even
658    * tentatively remove the base service.
659    */
660   bus_connection_add_owned_service_link (d->connection, d->service_link);
661   
662   d->hash_entry = NULL;
663   d->service_link = NULL;
664   d->connection_link = NULL;
665 }
666
667 static void
668 free_ownership_restore_data (void *data)
669 {
670   OwnershipRestoreData *d = data;
671
672   if (d->service_link)
673     _dbus_list_free_link (d->service_link);
674   if (d->connection_link)
675     _dbus_list_free_link (d->connection_link);
676   if (d->hash_entry)
677     _dbus_hash_table_free_preallocated_entry (d->service->registry->service_hash,
678                                               d->hash_entry);
679
680   dbus_connection_unref (d->connection);
681   bus_service_unref (d->service);
682   
683   dbus_free (d);
684 }
685
686 static dbus_bool_t
687 add_restore_ownership_to_transaction (BusTransaction *transaction,
688                                       BusService     *service,
689                                       DBusConnection *connection)
690 {
691   OwnershipRestoreData *d;
692   DBusList *link;
693
694   d = dbus_new (OwnershipRestoreData, 1);
695   if (d == NULL)
696     return FALSE;
697   
698   d->service = service;
699   d->connection = connection;
700   d->service_link = _dbus_list_alloc_link (service);
701   d->connection_link = _dbus_list_alloc_link (connection);
702   d->hash_entry = _dbus_hash_table_preallocate_entry (service->registry->service_hash);
703   
704   bus_service_ref (d->service);
705   dbus_connection_ref (d->connection);
706
707   d->before_connection = NULL;
708   link = _dbus_list_get_first_link (&service->owners);
709   while (link != NULL)
710     {
711       if (link->data == connection)
712         {
713           link = _dbus_list_get_next_link (&service->owners, link);
714
715           if (link)
716             d->before_connection = link->data;
717
718           break;
719         }
720       
721       link = _dbus_list_get_next_link (&service->owners, link);
722     }
723   
724   if (d->service_link == NULL ||
725       d->connection_link == NULL ||
726       d->hash_entry == NULL ||
727       !bus_transaction_add_cancel_hook (transaction, restore_ownership, d,
728                                         free_ownership_restore_data))
729     {
730       free_ownership_restore_data (d);
731       return FALSE;
732     }
733   
734   return TRUE;
735 }
736
737 /* this function is self-cancelling if you cancel the transaction */
738 dbus_bool_t
739 bus_service_remove_owner (BusService     *service,
740                           DBusConnection *owner,
741                           BusTransaction *transaction,
742                           DBusError      *error)
743 {
744   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
745   
746   /* We send out notifications before we do any work we
747    * might have to undo if the notification-sending failed
748    */
749   
750   /* Send service lost message */
751   if (bus_service_get_primary_owner (service) == owner)
752     {
753       if (!bus_driver_send_service_lost (owner, service->name,
754                                          transaction, error))
755         return FALSE;
756     }
757
758   if (service->owners == NULL)
759     {
760       _dbus_assert_not_reached ("Tried to remove owner of a service that has no owners");
761     }
762   else if (_dbus_list_length_is_one (&service->owners))
763     {
764       if (!bus_driver_send_service_owner_changed (service->name,
765                                                   bus_connection_get_name (owner),
766                                                   NULL,
767                                                   transaction, error))
768         return FALSE;
769     }
770   else
771     {
772       DBusList *link;
773       DBusConnection *new_owner;
774       link = _dbus_list_get_first_link (&service->owners);
775       _dbus_assert (link != NULL);
776       link = _dbus_list_get_next_link (&service->owners, link);
777       _dbus_assert (link != NULL);
778
779       new_owner = link->data;
780
781       if (!bus_driver_send_service_owner_changed (service->name,
782                                                   bus_connection_get_name (owner),
783                                                   bus_connection_get_name (new_owner),
784                                                   transaction, error))
785         return FALSE;
786
787       /* This will be our new owner */
788       if (!bus_driver_send_service_acquired (new_owner,
789                                              service->name,
790                                              transaction,
791                                              error))
792         return FALSE;
793     }
794
795   if (!add_restore_ownership_to_transaction (transaction, service, owner))
796     {
797       BUS_SET_OOM (error);
798       return FALSE;
799     }
800   
801   bus_service_unlink_owner (service, owner);
802
803   if (service->owners == NULL)
804     bus_service_unlink (service);
805
806   return TRUE;
807 }
808
809 BusService *
810 bus_service_ref (BusService *service)
811 {
812   _dbus_assert (service->refcount > 0);
813   
814   service->refcount += 1;
815
816   return service;
817 }
818
819 void
820 bus_service_unref (BusService *service)
821 {
822   _dbus_assert (service->refcount > 0);
823   
824   service->refcount -= 1;
825
826   if (service->refcount == 0)
827     {
828       _dbus_assert (service->owners == NULL);
829       
830       dbus_free (service->name);
831       _dbus_mem_pool_dealloc (service->registry->service_pool, service);
832     }
833 }
834
835 DBusConnection*
836 bus_service_get_primary_owner (BusService *service)
837 {
838   return _dbus_list_get_first (&service->owners);
839 }
840
841 const char*
842 bus_service_get_name (BusService *service)
843 {
844   return service->name;
845 }
846
847 void
848 bus_service_set_prohibit_replacement (BusService  *service,
849                                       dbus_bool_t  prohibit_replacement)
850 {
851   service->prohibit_replacement = prohibit_replacement != FALSE;
852 }
853
854 dbus_bool_t
855 bus_service_get_prohibit_replacement (BusService *service)
856 {
857   return service->prohibit_replacement;
858 }
859
860 dbus_bool_t
861 bus_service_has_owner (BusService     *service,
862                        DBusConnection *owner)
863 {
864   DBusList *link;
865
866   link = _dbus_list_get_first_link (&service->owners);
867   
868   while (link != NULL)
869     {
870       if (link->data == owner)
871         return TRUE;
872       
873       link = _dbus_list_get_next_link (&service->owners, link);
874     }
875
876   return FALSE;
877 }