示例#1
0
void
_dbus_loop_remove_watch (DBusLoop          *loop,
                         DBusWatch        *watch,
                         DBusWatchFunction  function,
                         void             *data)
{
    DBusList *link;

    link = _dbus_list_get_first_link (&loop->callbacks);
    while (link != NULL)
    {
        DBusList *next = _dbus_list_get_next_link (&loop->callbacks, link);
        Callback *this = link->data;

        if (this->type == CALLBACK_WATCH &&
                WATCH_CALLBACK (this)->watch == watch &&
                this->data == data &&
                WATCH_CALLBACK (this)->function == function)
        {
            remove_callback (loop, link);

            return;
        }

        link = next;
    }

    _dbus_warn ("could not find watch %p function %p data %p to remove\n",
                watch, (void *)function, data);
}
示例#2
0
dbus_bool_t 
bus_service_list_queued_owners (BusService *service,
                                DBusList  **return_list,
                                DBusError  *error)
{
  DBusList *link;

  _dbus_assert (*return_list == NULL);

  link = _dbus_list_get_first_link (&service->owners);
  _dbus_assert (link != NULL);
  
  while (link != NULL)
    {
      BusOwner *owner;
      const char *uname;

      owner = (BusOwner *) link->data;
      uname = bus_connection_get_name (owner->conn);

      if (!_dbus_list_append (return_list, (char *)uname))
        goto oom;

      link = _dbus_list_get_next_link (&service->owners, link);
    }
  
  return TRUE;
  
 oom:
  _dbus_list_clear (return_list);
  BUS_SET_OOM (error);
  return FALSE;
}
static int
do_expiration_with_monotonic_time (BusExpireList *list,
                                   long           tv_sec,
                                   long           tv_usec)
{
  DBusList *link;
  int next_interval, min_wait_time, items_to_expire;

  next_interval = -1;
  min_wait_time = 3600 * 1000; /* this is reset anyway if used */
  items_to_expire = 0;
  
  link = _dbus_list_get_first_link (&list->items);
  while (link != NULL)
    {
      DBusList *next = _dbus_list_get_next_link (&list->items, link);
      double elapsed;
      BusExpireItem *item;

      item = link->data;

      elapsed = ELAPSED_MILLISECONDS_SINCE (item->added_tv_sec,
                                            item->added_tv_usec,
                                            tv_sec, tv_usec);

      if (((item->added_tv_sec == 0) && (item->added_tv_usec == 0)) ||
          ((list->expire_after > 0) && (elapsed >= (double) list->expire_after)))
        {
          _dbus_verbose ("Expiring an item %p\n", item);

          /* If the expire function fails, we just end up expiring
           * this item next time we walk through the list. This would
           * be an indeterminate time normally, so we set up the
           * next_interval to be "shortly" (just enough to avoid
           * a busy loop)
           */
          if (!(* list->expire_func) (list, link, list->data))
            {
              next_interval = _dbus_get_oom_wait ();
              break;
            }
        }
      else if (list->expire_after > 0)
        {
          double to_wait;

          items_to_expire = 1;
          to_wait = (double) list->expire_after - elapsed;
          if (min_wait_time > to_wait)
            min_wait_time = to_wait;
        }

      link = next;
    }

  if (next_interval < 0 && items_to_expire)
    next_interval = min_wait_time;

  return next_interval;
}
示例#4
0
void
_dbus_loop_remove_timeout (DBusLoop            *loop,
                           DBusTimeout        *timeout,
                           DBusTimeoutFunction  function,
                           void               *data)
{
    DBusList *link;

    link = _dbus_list_get_first_link (&loop->callbacks);
    while (link != NULL)
    {
        DBusList *next = _dbus_list_get_next_link (&loop->callbacks, link);
        Callback *this = link->data;

        if (this->type == CALLBACK_TIMEOUT &&
                TIMEOUT_CALLBACK (this)->timeout == timeout &&
                this->data == data &&
                TIMEOUT_CALLBACK (this)->function == function)
        {
            remove_callback (loop, link);

            return;
        }

        link = next;
    }

    _dbus_warn ("could not find timeout %p function %p data %p to remove\n",
                timeout, (void *)function, data);
}
示例#5
0
static dbus_bool_t
add_list_to_client (DBusList        **list,
                    BusClientPolicy  *client)
{
    DBusList *link;

    link = _dbus_list_get_first_link (list);
    while (link != NULL)
    {
        BusPolicyRule *rule = link->data;
        link = _dbus_list_get_next_link (list, link);

        switch (rule->type)
        {
        case BUS_POLICY_RULE_USER:
        case BUS_POLICY_RULE_GROUP:
            /* These aren't per-connection policies */
            break;

        case BUS_POLICY_RULE_OWN:
        case BUS_POLICY_RULE_SEND:
        case BUS_POLICY_RULE_RECEIVE:
            /* These are per-connection */
            if (!bus_client_policy_append_rule (client, rule))
                return FALSE;
            break;
        }
    }

    return TRUE;
}
示例#6
0
static dbus_bool_t
list_allows_user (dbus_bool_t           def,
                  DBusList            **list,
                  unsigned long         uid,
                  const unsigned long  *group_ids,
                  int                   n_group_ids)
{
    DBusList *link;
    dbus_bool_t allowed;

    allowed = def;

    link = _dbus_list_get_first_link (list);
    while (link != NULL)
    {
        BusPolicyRule *rule = link->data;
        link = _dbus_list_get_next_link (list, link);

        if (rule->type == BUS_POLICY_RULE_USER)
        {
            _dbus_verbose ("List %p user rule uid="DBUS_UID_FORMAT"\n",
                           list, rule->d.user.uid);

            if (rule->d.user.uid == DBUS_UID_UNSET)
                ; /* '*' wildcard */
            else if (rule->d.user.uid != uid)
                continue;
        }
        else if (rule->type == BUS_POLICY_RULE_GROUP)
        {
            _dbus_verbose ("List %p group rule uid="DBUS_UID_FORMAT"\n",
                           list, rule->d.user.uid);

            if (rule->d.group.gid == DBUS_GID_UNSET)
                ;  /* '*' wildcard */
            else
            {
                int i;

                i = 0;
                while (i < n_group_ids)
                {
                    if (rule->d.group.gid == group_ids[i])
                        break;
                    ++i;
                }

                if (i == n_group_ids)
                    continue;
            }
        }
        else
            continue;

        allowed = rule->allow;
    }

    return allowed;
}
示例#7
0
static int
do_expiration_with_current_time (BusExpireList *list,
                                 long           tv_sec,
                                 long           tv_usec)
{
  DBusList *link;
  int next_interval;

  next_interval = -1;
  
  link = _dbus_list_get_first_link (&list->items);
  while (link != NULL)
    {
      DBusList *next = _dbus_list_get_next_link (&list->items, link);
      double elapsed;
      BusExpireItem *item;

      item = link->data;

      elapsed = ELAPSED_MILLISECONDS_SINCE (item->added_tv_sec,
                                            item->added_tv_usec,
                                            tv_sec, tv_usec);

      if (elapsed >= (double) list->expire_after)
        {
          _dbus_verbose ("Expiring an item %p\n", item);

          /* If the expire function fails, we just end up expiring
           * this item next time we walk through the list. This would
           * be an indeterminate time normally, so we set up the
           * next_interval to be "shortly" (just enough to avoid
           * a busy loop)
           */
          if (!(* list->expire_func) (list, link, list->data))
            {
              next_interval = _dbus_get_oom_wait ();
              break;
            }
        }
      else
        {
          /* We can end the loop, since the connections are in oldest-first order */
          next_interval = ((double)list->expire_after) - elapsed;
          _dbus_verbose ("Item %p expires in %d milliseconds\n",
                         item, next_interval);

          break;
        }

      link = next;
    }

  return next_interval;
}
示例#8
0
文件: dbus-watch.c 项目: d-bus/dbus
/**
 * Sets all watches to the given enabled state, invoking the
 * application's DBusWatchToggledFunction if appropriate.
 *
 * @param watch_list the watch list.
 * @param enabled #TRUE to enable
 */
void
_dbus_watch_list_toggle_all_watches (DBusWatchList           *watch_list,
                                     dbus_bool_t              enabled)
{
  DBusList *link;

  for (link = _dbus_list_get_first_link (&watch_list->watches);
       link != NULL;
       link = _dbus_list_get_next_link (&watch_list->watches, link))
    {
      _dbus_watch_list_toggle_watch (watch_list, link->data, enabled);
    }
}
示例#9
0
/**
 * Removes the first link in the list and returns it.  This is a
 * constant-time operation.
 *
 * @param list address of the list head.
 * @returns the first link in the list, or #NULL for an empty list.
 */
DBusList*
_dbus_list_pop_first_link (DBusList **list)
{
  DBusList *link;
  
  link = _dbus_list_get_first_link (list);
  if (link == NULL)
    return NULL;

  _dbus_list_unlink (list, link);

  return link;
}
示例#10
0
dbus_bool_t
bus_service_get_allow_replacement (BusService *service)
{
  BusOwner *owner;
  DBusList *link;
 
  _dbus_assert (service->owners != NULL);

  link = _dbus_list_get_first_link (&service->owners);
  owner = (BusOwner *) link->data;

  return owner->allow_replacement;
}
示例#11
0
static dbus_bool_t
add_restore_ownership_to_transaction (BusTransaction *transaction,
                                      BusService     *service,
                                      BusOwner       *owner)
{
  OwnershipRestoreData *d;
  DBusList *link;

  d = dbus_new (OwnershipRestoreData, 1);
  if (d == NULL)
    return FALSE;
  
  d->service = service;
  d->owner = owner;
  d->service_link = _dbus_list_alloc_link (service);
  d->owner_link = _dbus_list_alloc_link (owner);
  d->hash_entry = _dbus_hash_table_preallocate_entry (service->registry->service_hash);
  
  bus_service_ref (d->service);
  bus_owner_ref (d->owner);
  dbus_connection_ref (d->owner->conn);

  d->before_owner = NULL;
  link = _dbus_list_get_first_link (&service->owners);
  while (link != NULL)
    {
      if (link->data == owner)
        {
          link = _dbus_list_get_next_link (&service->owners, link);

          if (link)
            d->before_owner = link->data;

          break;
        }
      
      link = _dbus_list_get_next_link (&service->owners, link);
    }
  
  if (d->service_link == NULL ||
      d->owner_link == NULL ||
      d->hash_entry == NULL ||
      !bus_transaction_add_cancel_hook (transaction, restore_ownership, d,
                                        free_ownership_restore_data))
    {
      free_ownership_restore_data (d);
      return FALSE;
    }
  
  return TRUE;
}
示例#12
0
static dbus_bool_t
lists_equal (DBusList **list1,
             DBusList **list2)
{
  DBusList *link1;
  DBusList *link2;
  
  link1 = _dbus_list_get_first_link (list1);
  link2 = _dbus_list_get_first_link (list2);
  while (link1 && link2)
    {
      if (link1->data != link2->data)
        return FALSE;
      
      link1 = _dbus_list_get_next_link (list1, link1);
      link2 = _dbus_list_get_next_link (list2, link2);
    }

  if (link1 || link2)
    return FALSE;

  return TRUE;
}
示例#13
0
/**
 * Removes the first value in the list and returns it.  This is a
 * constant-time operation.
 *
 * @param list address of the list head.
 * @returns the first data in the list, or #NULL for an empty list.
 */
void*
_dbus_list_pop_first (DBusList **list)
{
  DBusList *link;
  void *data;
  
  link = _dbus_list_get_first_link (list);
  if (link == NULL)
    return NULL;
  
  data = link->data;
  _dbus_list_remove_link (list, link);

  return data;
}
示例#14
0
static void
restore_ownership (void *data)
{
  OwnershipRestoreData *d = data;
  DBusList *link;

  _dbus_assert (d->service_link != NULL);
  _dbus_assert (d->owner_link != NULL);
  
  if (d->service->owners == NULL)
    {
      _dbus_assert (d->hash_entry != NULL);
      bus_service_relink (d->service, d->hash_entry);
    }
  else
    {
      _dbus_assert (d->hash_entry == NULL);
    }
  
  /* We don't need to send messages notifying of these
   * changes, since we're reverting something that was
   * cancelled (effectively never really happened)
   */
  link = _dbus_list_get_first_link (&d->service->owners);
  while (link != NULL)
    {
      if (link->data == d->before_owner)
        break;

      link = _dbus_list_get_next_link (&d->service->owners, link);
    }
  
  _dbus_list_insert_before_link (&d->service->owners, link, d->owner_link);

  /* Note that removing then restoring this changes the order in which
   * ServiceDeleted messages are sent on destruction of the
   * connection.  This should be OK as the only guarantee there is
   * that the base service is destroyed last, and we never even
   * tentatively remove the base service.
   */
  bus_connection_add_owned_service_link (d->owner->conn, d->service_link);
  
  d->hash_entry = NULL;
  d->service_link = NULL;
  d->owner_link = NULL;
}
示例#15
0
static dbus_bool_t
all_odd_values (DBusList **list)
{
  DBusList *link;
  
  link = _dbus_list_get_first_link (list);
  while (link != NULL)
    {
      int v = _DBUS_POINTER_TO_INT (link->data);

      if ((v % 2) == 0)
        return FALSE;
      
      link = _dbus_list_get_next_link (list, link);
    }

  return TRUE;
}
示例#16
0
void
bus_test_clients_foreach (BusConnectionForeachFunction  function,
                          void                         *data)
{
  DBusList *link;

  link = _dbus_list_get_first_link (&clients);
  while (link != NULL)
    {
      DBusConnection *connection = link->data;
      DBusList *next = _dbus_list_get_next_link (&clients, link);

      if (!(* function) (connection, data))
        break;

      link = next;
    }
}
示例#17
0
dbus_bool_t
bus_test_client_listed (DBusConnection *connection)
{
  DBusList *link;

  link = _dbus_list_get_first_link (&clients);
  while (link != NULL)
    {
      DBusConnection *c = link->data;
      DBusList *next = _dbus_list_get_next_link (&clients, link);

      if (c == connection)
        return TRUE;

      link = next;
    }

  return FALSE;
}
示例#18
0
static DBusList *
_bus_service_find_owner_link (BusService *service,
                              DBusConnection *connection)
{
  DBusList *link;
  
  link = _dbus_list_get_first_link (&service->owners);

  while (link != NULL)
    {
      BusOwner *bus_owner;

      bus_owner = (BusOwner *) link->data;
      if (bus_owner->conn == connection) 
        break;

      link = _dbus_list_get_next_link (&service->owners, link);
    }

  return link;
}
示例#19
0
static dbus_bool_t
is_descending_sequence (DBusList **list)
{
  DBusList *link;
  int prev;

  prev = _DBUS_INT_MAX;
  
  link = _dbus_list_get_first_link (list);
  while (link != NULL)
    {
      int v = _DBUS_POINTER_TO_INT (link->data);

      if (v >= prev)
        return FALSE;

      prev = v;
      
      link = _dbus_list_get_next_link (list, link);
    }

  return TRUE;
}
示例#20
0
dbus_bool_t
bus_service_swap_owner (BusService     *service,
                        DBusConnection *connection,
                        BusTransaction *transaction,
                        DBusError      *error)
{
  DBusList *swap_link;
  BusOwner *primary_owner;

  _DBUS_ASSERT_ERROR_IS_CLEAR (error);

  /* We send out notifications before we do any work we
   * might have to undo if the notification-sending failed
   */
  
  /* Send service lost message */
  primary_owner = bus_service_get_primary_owner (service);
  if (primary_owner == NULL || primary_owner->conn != connection)
    _dbus_assert_not_reached ("Tried to swap a non primary owner");

    
  if (!bus_driver_send_service_lost (connection, service->name,
                                     transaction, error))
    return FALSE;

  if (service->owners == NULL)
    {
      _dbus_assert_not_reached ("Tried to swap owner of a service that has no owners");
    }
  else if (_dbus_list_length_is_one (&service->owners))
    {
      _dbus_assert_not_reached ("Tried to swap owner of a service that has no other owners in the queue");
    }
  else
    {
      DBusList *link;
      BusOwner *new_owner;
      DBusConnection *new_owner_conn;
      link = _dbus_list_get_first_link (&service->owners);
      _dbus_assert (link != NULL);
      link = _dbus_list_get_next_link (&service->owners, link);
      _dbus_assert (link != NULL);

      new_owner = (BusOwner *)link->data;
      new_owner_conn = new_owner->conn;

      if (!bus_driver_send_service_owner_changed (service->name,
 						  bus_connection_get_name (connection),
 						  bus_connection_get_name (new_owner_conn),
 						  transaction, error))
        return FALSE;

      /* This will be our new owner */
      if (!bus_driver_send_service_acquired (new_owner_conn,
                                             service->name,
                                             transaction,
                                             error))
        return FALSE;
    }

  if (!add_restore_ownership_to_transaction (transaction, service, primary_owner))
    {
      BUS_SET_OOM (error);
      return FALSE;
    }

  /* unlink the primary and make it the second link */
  swap_link = _dbus_list_get_first_link (&service->owners);
  _dbus_list_unlink (&service->owners, swap_link);

  _dbus_list_insert_after_link (&service->owners,
                                _dbus_list_get_first_link (&service->owners),
				swap_link);

  return TRUE;
}
示例#21
0
void
bus_set_watched_dirs (BusContext *context, DBusList **directories)
{
  int new_fds[MAX_DIRS_TO_WATCH];
  char *new_dirs[MAX_DIRS_TO_WATCH];
  DBusList *link;
  int i, j, fd;
  struct kevent ev;
#ifdef O_CLOEXEC
  dbus_bool_t cloexec_done = 0;
#endif

  if (!_init_kqueue (context))
    goto out;

  for (i = 0; i < MAX_DIRS_TO_WATCH; i++)
    {
      new_fds[i] = -1;
      new_dirs[i] = NULL;
    }

  i = 0;
  link = _dbus_list_get_first_link (directories);
  while (link != NULL)
    {
      new_dirs[i++] = (char *)link->data;
      link = _dbus_list_get_next_link (directories, link);
    }

  /* Look for directories in both the old and new sets, if
   * we find one, move its data into the new set.
   */
  for (i = 0; new_dirs[i]; i++)
    {
      for (j = 0; j < num_fds; j++)
        {
          if (dirs[j] && strcmp (new_dirs[i], dirs[j]) == 0)
            {
              new_fds[i] = fds[j];
              new_dirs[i] = dirs[j];
              fds[j] = -1;
              dirs[j] = NULL;
              break;
            }
        }
    }

  /* Any directory we find in "fds" with a nonzero fd must
   * not be in the new set, so perform cleanup now.
   */
  for (j = 0; j < num_fds; j++)
    {
      if (fds[j] != -1)
        {
          close (fds[j]);
          dbus_free (dirs[j]);
          fds[j] = -1;
          dirs[j] = NULL;
        }
    }

  for (i = 0; new_dirs[i]; i++)
    {
      if (new_fds[i] == -1)
        {
          /* FIXME - less lame error handling for failing to add a watch;
           * we may need to sleep.
           */
#ifdef O_CLOEXEC
          fd = open (new_dirs[i], O_RDONLY | O_CLOEXEC);
          cloexec_done = (fd >= 0);

          if (fd < 0 && errno == EINVAL)
#endif
            {
              fd = open (new_dirs[i], O_RDONLY);
            }
          if (fd < 0)
            {
              if (errno != ENOENT)
                {
                  _dbus_warn ("Cannot open directory '%s'; error '%s'\n", new_dirs[i], _dbus_strerror (errno));
                  goto out;
                }
              else
                {
                  new_fds[i] = -1;
                  new_dirs[i] = NULL;
                  continue;
                }
            }
#ifdef O_CLOEXEC
          if (!cloexec_done)
#endif
            {
              _dbus_fd_set_close_on_exec (fd);
            }

          EV_SET (&ev, fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR,
                  NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_RENAME, 0, 0);
          if (kevent (kq, &ev, 1, NULL, 0, NULL) == -1)
            {
              _dbus_warn ("Cannot setup a kevent for '%s'; error '%s'\n", new_dirs[i], _dbus_strerror (errno));
              close (fd);
              goto out;
            }

          new_fds[i] = fd;
          new_dirs[i] = _dbus_strdup (new_dirs[i]);
          if (!new_dirs[i])
            {
              /* FIXME have less lame handling for OOM, we just silently fail to
               * watch.  (In reality though, the whole OOM handling in dbus is
               * stupid but we won't go into that in this comment =) )
               */
              close (fd);
              new_fds[i] = -1;
            }
        }
    }

  num_fds = i;

  for (i = 0; i < MAX_DIRS_TO_WATCH; i++)
    {
      fds[i] = new_fds[i];
      dirs[i] = new_dirs[i];
    }

 out:
  ;
}
示例#22
0
/**
 * Sets the watch functions. This function is the "backend"
 * for dbus_connection_set_watch_functions() and
 * dbus_server_set_watch_functions().
 *
 * @param watch_list the watch list.
 * @param add_function the add watch function.
 * @param remove_function the remove watch function.
 * @param toggled_function function on toggling enabled flag, or #NULL
 * @param data the data for those functions.
 * @param free_data_function the function to free the data.
 * @returns #FALSE if not enough memory
 *
 */
dbus_bool_t
_dbus_watch_list_set_functions (DBusWatchList           *watch_list,
                                DBusAddWatchFunction     add_function,
                                DBusRemoveWatchFunction  remove_function,
                                DBusWatchToggledFunction toggled_function,
                                void                    *data,
                                DBusFreeFunction         free_data_function)
{
  /* Add watches with the new watch function, failing on OOM */
  if (add_function != NULL)
    {
      DBusList *link;
      
      link = _dbus_list_get_first_link (&watch_list->watches);
      while (link != NULL)
        {
          DBusList *next = _dbus_list_get_next_link (&watch_list->watches,
                                                     link);

#ifdef DBUS_ENABLE_VERBOSE_MODE
          {
            const char *watch_type;
            int flags;

            flags = dbus_watch_get_flags (link->data);
            if ((flags & DBUS_WATCH_READABLE) &&
                (flags & DBUS_WATCH_WRITABLE))
              watch_type = "readwrite";
            else if (flags & DBUS_WATCH_READABLE)
              watch_type = "read";
            else if (flags & DBUS_WATCH_WRITABLE)
              watch_type = "write";
            else
              watch_type = "not read or write";
            
            _dbus_verbose ("Adding a %s watch on fd %d using newly-set add watch function\n",
                           watch_type,
                           dbus_watch_get_socket (link->data));
          }
#endif /* DBUS_ENABLE_VERBOSE_MODE */
          
          if (!(* add_function) (link->data, data))
            {
              /* remove it all again and return FALSE */
              DBusList *link2;
              
              link2 = _dbus_list_get_first_link (&watch_list->watches);
              while (link2 != link)
                {
                  DBusList *next = _dbus_list_get_next_link (&watch_list->watches,
                                                             link2);
                  
                  _dbus_verbose ("Removing watch on fd %d using newly-set remove function because initial add failed\n",
                                 dbus_watch_get_socket (link2->data));
                  
                  (* remove_function) (link2->data, data);
                  
                  link2 = next;
                }

              return FALSE;
            }
      
          link = next;
        }
    }
  
  /* Remove all current watches from previous watch handlers */

  if (watch_list->remove_watch_function != NULL)
    {
      _dbus_verbose ("Removing all pre-existing watches\n");
      
      _dbus_list_foreach (&watch_list->watches,
                          (DBusForeachFunction) watch_list->remove_watch_function,
                          watch_list->watch_data);
    }

  if (watch_list->watch_free_data_function != NULL)
    (* watch_list->watch_free_data_function) (watch_list->watch_data);
  
  watch_list->add_watch_function = add_function;
  watch_list->remove_watch_function = remove_function;
  watch_list->watch_toggled_function = toggled_function;
  watch_list->watch_data = data;
  watch_list->watch_free_data_function = free_data_function;

  return TRUE;
}
示例#23
0
/* this function is self-cancelling if you cancel the transaction */
dbus_bool_t
bus_service_add_owner (BusService     *service,
                       DBusConnection *connection,
                       dbus_uint32_t  flags,
                       BusTransaction *transaction,
                       DBusError      *error)
{
  BusOwner *bus_owner;
  DBusList *bus_owner_link;
  
  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
  
 /* Send service acquired message first, OOM will result
  * in cancelling the transaction
  */
  if (service->owners == NULL)
    {
      if (!bus_driver_send_service_acquired (connection, service->name, transaction, error))
        return FALSE;
    }
  
  bus_owner_link = _bus_service_find_owner_link (service, connection);
  
  if (bus_owner_link == NULL)
    {
      bus_owner = bus_owner_new (service, connection, flags);
      if (bus_owner == NULL)
        {
          BUS_SET_OOM (error);
          return FALSE;
        }

      bus_owner_set_flags (bus_owner, flags);
      if (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) || service->owners == NULL)
        {
          if (!_dbus_list_append (&service->owners,
                                  bus_owner))
            {
              bus_owner_unref (bus_owner);
              BUS_SET_OOM (error);
              return FALSE;
            }
        }
      else
        {
          if (!_dbus_list_insert_after (&service->owners,
                                         _dbus_list_get_first_link (&service->owners),
                                         bus_owner))
            {
              bus_owner_unref (bus_owner);
              BUS_SET_OOM (error);
              return FALSE;
            }
        }      
    } 
  else 
    {
      /* Update the link since we are already in the queue
       * No need for operations that can produce OOM
       */

      bus_owner = (BusOwner *) bus_owner_link->data;
      if (flags & DBUS_NAME_FLAG_REPLACE_EXISTING)
        {
	  DBusList *link;
          _dbus_list_unlink (&service->owners, bus_owner_link);
	  link = _dbus_list_get_first_link (&service->owners);
	  _dbus_assert (link != NULL);
	  
          _dbus_list_insert_after_link (&service->owners, link, bus_owner_link);
        }
      
      bus_owner_set_flags (bus_owner, flags);
      return TRUE;
    }

  if (!add_cancel_ownership_to_transaction (transaction,
                                            service,
                                            bus_owner))
    {
      bus_service_unlink_owner (service, bus_owner);
      BUS_SET_OOM (error);
      return FALSE;
    }

  return TRUE;
}
示例#24
0
static dbus_bool_t
test_command_line (const char *arg1, ...)
{
  int i, original_argc, shell_argc;
  char **shell_argv;
  char **original_argv;
  char *command_line, *tmp;
  DBusString str;
  DBusList *list = NULL, *node;
  va_list var_args;
  DBusError error;

  va_start (var_args, arg1);
  _dbus_list_append (&list, (char *)arg1);
  do
    {
      tmp = va_arg (var_args, char *);
      if (!tmp)
        break;
      _dbus_list_append (&list, tmp);
    } while (tmp);
  va_end (var_args);

  original_argc = _dbus_list_get_length (&list);
  original_argv = dbus_new (char *, original_argc);
  _dbus_string_init (&str);
  for (i = 0, node = _dbus_list_get_first_link (&list); i < original_argc && node;
       i++, node = _dbus_list_get_next_link (&list, node))
    {
      original_argv[i] = node->data;
      if (i > 0)
        _dbus_string_append_byte (&str, ' ');
      _dbus_string_append (&str, original_argv[i]);
    }
  
  _dbus_list_clear (&list);
  command_line = _dbus_string_get_data (&str);
  printf ("\n\nTesting command line '%s'\n", command_line);

  dbus_error_init (&error);
  if (!_dbus_shell_parse_argv (command_line, &shell_argc, &shell_argv, &error))
    {
      fprintf (stderr, "Error parsing command line: %s\n", error.message ? error.message : "");
      return FALSE;
    }
  else
    {
      if (shell_argc != original_argc)
        {
          printf ("Number of arguments returned (%d) don't match original (%d)\n",
                  shell_argc, original_argc);
          return FALSE;
        } 
      printf ("Number of arguments: %d\n", shell_argc);
      for (i = 0; i < shell_argc; i++)
        {
          char *unquoted;
          
          unquoted = _dbus_shell_unquote (original_argv[i]);
          if (strcmp (unquoted ? unquoted : "",
                      shell_argv[i] ? shell_argv[i] : ""))
            {
              printf ("Position %d, returned argument (%s) does not match original (%s)\n",
                      i, shell_argv[i], unquoted);
              dbus_free (unquoted);
              return FALSE;
            }
          dbus_free (unquoted);
          if (shell_argv[i])
            printf ("Argument %d = %s\n", i, shell_argv[i]);
        }
      
      dbus_free_string_array (shell_argv);
    }
  
  _dbus_string_free (&str);
  
  return TRUE;
}
示例#25
0
static BusDesktopFile *
desktop_file_for_name (BusConfigParser *parser,
                       const char *name,
                       DBusError  *error)
{
  BusDesktopFile *desktop_file;
  DBusList **service_dirs;
  DBusList *link;
  DBusError tmp_error;
  DBusString full_path;
  DBusString filename;
  const char *dir;

  _DBUS_ASSERT_ERROR_IS_CLEAR (error);

  desktop_file = NULL;

  if (!_dbus_string_init (&filename))
    {
      BUS_SET_OOM (error);
      goto out_all;
    }

  if (!_dbus_string_init (&full_path))
    {
      BUS_SET_OOM (error);
      goto out_filename;
    }

  if (!_dbus_string_append (&filename, name) ||
      !_dbus_string_append (&filename, ".service"))
    {
      BUS_SET_OOM (error);
      goto out;
    }

  service_dirs = bus_config_parser_get_service_dirs (parser);
  for (link = _dbus_list_get_first_link (service_dirs);
       link != NULL;
       link = _dbus_list_get_next_link (service_dirs, link))
    {
      dir = link->data;
      _dbus_verbose ("Looking at '%s'\n", dir);

      dbus_error_init (&tmp_error);

      /* clear the path from last time */
      _dbus_string_set_length (&full_path, 0);

      /* build the full path */
      if (!_dbus_string_append (&full_path, dir) ||
          !_dbus_concat_dir_and_file (&full_path, &filename))
        {
          BUS_SET_OOM (error);
          goto out;
        }

      _dbus_verbose ("Trying to load file '%s'\n", _dbus_string_get_data (&full_path));
      desktop_file = bus_desktop_file_load (&full_path, &tmp_error);
      if (desktop_file == NULL)
        {
          _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
          _dbus_verbose ("Could not load %s: %s: %s\n",
                         _dbus_string_get_const_data (&full_path),
                         tmp_error.name, tmp_error.message);

          /* we may have failed if the file is not found; this is not fatal */
          if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
            {
              dbus_move_error (&tmp_error, error);
              /* we only bail out on OOM */
              goto out;
            }
          dbus_error_free (&tmp_error);
        }

      /* did we find the desktop file we want? */
      if (desktop_file != NULL)
        break;
    }

  /* Didn't find desktop file; set error */
  if (desktop_file == NULL)
    {
      dbus_set_error (error, DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND,
                      "The name %s was not provided by any .service files",
                      name);
    }

out:
  _dbus_string_free (&full_path);
out_filename:
  _dbus_string_free (&filename);
out_all:
  return desktop_file;
}
示例#26
0
/**
 * @ingroup DBusListInternals
 * Unit test for DBusList
 * @returns #TRUE on success.
 */
dbus_bool_t
_dbus_list_test (void)
{
  DBusList *list1;
  DBusList *list2;
  DBusList *link1;
  DBusList *link2;
  DBusList *copy1;
  DBusList *copy2;
  int i;
  
  list1 = NULL;
  list2 = NULL;

  /* Test append and prepend */
  
  i = 0;
  while (i < 10)
    {
      if (!_dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i)))
        _dbus_assert_not_reached ("could not allocate for append");
      
      if (!_dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i)))
        _dbus_assert_not_reached ("count not allocate for prepend");
      ++i;

      verify_list (&list1);
      verify_list (&list2);
      
      _dbus_assert (_dbus_list_get_length (&list1) == i);
      _dbus_assert (_dbus_list_get_length (&list2) == i);
    }

  _dbus_assert (is_ascending_sequence (&list1));
  _dbus_assert (is_descending_sequence (&list2));

  /* Test list clear */
  _dbus_list_clear (&list1);
  _dbus_list_clear (&list2);

  verify_list (&list1);
  verify_list (&list2);

  /* Test get_first, get_last, pop_first, pop_last */
  
  i = 0;
  while (i < 10)
    {
      _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i));
      _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i));
      ++i;
    }

  --i;
  while (i >= 0)
    {
      void *got_data1;
      void *got_data2;
      
      void *data1;
      void *data2;

      got_data1 = _dbus_list_get_last (&list1);
      got_data2 = _dbus_list_get_first (&list2);
      
      data1 = _dbus_list_pop_last (&list1);
      data2 = _dbus_list_pop_first (&list2);

      _dbus_assert (got_data1 == data1);
      _dbus_assert (got_data2 == data2);
      
      _dbus_assert (_DBUS_POINTER_TO_INT (data1) == i);
      _dbus_assert (_DBUS_POINTER_TO_INT (data2) == i);

      verify_list (&list1);
      verify_list (&list2);

      _dbus_assert (is_ascending_sequence (&list1));
      _dbus_assert (is_descending_sequence (&list2));
      
      --i;
    }

  _dbus_assert (list1 == NULL);
  _dbus_assert (list2 == NULL);

  /* Test get_first_link, get_last_link, pop_first_link, pop_last_link */
  
  i = 0;
  while (i < 10)
    {
      _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i));
      _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i));
      ++i;
    }

  --i;
  while (i >= 0)
    {
      DBusList *got_link1;
      DBusList *got_link2;

      DBusList *link1;
      DBusList *link2;
      
      void *data1;
      void *data2;
      
      got_link1 = _dbus_list_get_last_link (&list1);
      got_link2 = _dbus_list_get_first_link (&list2);
      
      link1 = _dbus_list_pop_last_link (&list1);
      link2 = _dbus_list_pop_first_link (&list2);

      _dbus_assert (got_link1 == link1);
      _dbus_assert (got_link2 == link2);

      data1 = link1->data;
      data2 = link2->data;

      _dbus_list_free_link (link1);
      _dbus_list_free_link (link2);
      
      _dbus_assert (_DBUS_POINTER_TO_INT (data1) == i);
      _dbus_assert (_DBUS_POINTER_TO_INT (data2) == i);

      verify_list (&list1);
      verify_list (&list2);

      _dbus_assert (is_ascending_sequence (&list1));
      _dbus_assert (is_descending_sequence (&list2));
      
      --i;
    }

  _dbus_assert (list1 == NULL);
  _dbus_assert (list2 == NULL);
  
  /* Test iteration */
  
  i = 0;
  while (i < 10)
    {
      _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i));
      _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i));
      ++i;

      verify_list (&list1);
      verify_list (&list2);
      
      _dbus_assert (_dbus_list_get_length (&list1) == i);
      _dbus_assert (_dbus_list_get_length (&list2) == i);
    }

  _dbus_assert (is_ascending_sequence (&list1));
  _dbus_assert (is_descending_sequence (&list2));

  --i;
  link2 = _dbus_list_get_first_link (&list2);
  while (link2 != NULL)
    {
      verify_list (&link2); /* pretend this link is the head */
      
      _dbus_assert (_DBUS_POINTER_TO_INT (link2->data) == i);
      
      link2 = _dbus_list_get_next_link (&list2, link2);
      --i;
    }

  i = 0;
  link1 = _dbus_list_get_first_link (&list1);
  while (link1 != NULL)
    {
      verify_list (&link1); /* pretend this link is the head */
      
      _dbus_assert (_DBUS_POINTER_TO_INT (link1->data) == i);
      
      link1 = _dbus_list_get_next_link (&list1, link1);
      ++i;
    }

  --i;
  link1 = _dbus_list_get_last_link (&list1);
  while (link1 != NULL)
    {
      verify_list (&link1); /* pretend this link is the head */

      _dbus_assert (_DBUS_POINTER_TO_INT (link1->data) == i);
      
      link1 = _dbus_list_get_prev_link (&list1, link1);
      --i;
    }

  _dbus_list_clear (&list1);
  _dbus_list_clear (&list2);

  /* Test remove */
  
  i = 0;
  while (i < 10)
    {
      _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i));
      _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i));
      ++i;
    }

  --i;
  while (i >= 0)
    {
      if ((i % 2) == 0)
        {
          if (!_dbus_list_remove (&list1, _DBUS_INT_TO_POINTER (i)))
            _dbus_assert_not_reached ("element should have been in list");
          if (!_dbus_list_remove (&list2, _DBUS_INT_TO_POINTER (i)))
            _dbus_assert_not_reached ("element should have been in list");

          verify_list (&list1);
          verify_list (&list2);
        }
      --i;
    }

  _dbus_assert (all_odd_values (&list1));
  _dbus_assert (all_odd_values (&list2));

  _dbus_list_clear (&list1);
  _dbus_list_clear (&list2);

  /* test removing the other half of the elements */
  
  i = 0;
  while (i < 10)
    {
      _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i));
      _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i));
      ++i;
    }

  --i;
  while (i >= 0)
    {
      if ((i % 2) != 0)
        {
          if (!_dbus_list_remove (&list1, _DBUS_INT_TO_POINTER (i)))
            _dbus_assert_not_reached ("element should have been in list");
          if (!_dbus_list_remove (&list2, _DBUS_INT_TO_POINTER (i)))
            _dbus_assert_not_reached ("element should have been in list");

          verify_list (&list1);
          verify_list (&list2);
        }
      --i;
    }

  _dbus_assert (all_even_values (&list1));
  _dbus_assert (all_even_values (&list2));

  /* clear list using remove_link */
  while (list1 != NULL)
    {
      _dbus_list_remove_link (&list1, list1);
      verify_list (&list1);
    }
  while (list2 != NULL)
    {
      _dbus_list_remove_link (&list2, list2);
      verify_list (&list2);
    }

  /* Test remove link more generally */
  i = 0;
  while (i < 10)
    {
      _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i));
      _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i));
      ++i;
    }

  --i;
  link2 = _dbus_list_get_first_link (&list2);
  while (link2 != NULL)
    {
      DBusList *next = _dbus_list_get_next_link (&list2, link2);
      
      _dbus_assert (_DBUS_POINTER_TO_INT (link2->data) == i);

      if ((i % 2) == 0)
        _dbus_list_remove_link (&list2, link2);

      verify_list (&list2);
      
      link2 = next;
      --i;
    }

  _dbus_assert (all_odd_values (&list2));  
  _dbus_list_clear (&list2);
  
  i = 0;
  link1 = _dbus_list_get_first_link (&list1);
  while (link1 != NULL)
    {
      DBusList *next = _dbus_list_get_next_link (&list1, link1);

      _dbus_assert (_DBUS_POINTER_TO_INT (link1->data) == i);

      if ((i % 2) != 0)
        _dbus_list_remove_link (&list1, link1);

      verify_list (&list1);
      
      link1 = next;
      ++i;
    }

  _dbus_assert (all_even_values (&list1));
  _dbus_list_clear (&list1);

  /* Test copying a list */
  i = 0;
  while (i < 10)
    {
      _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i));
      _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i));
      ++i;
    }

  /* bad pointers, because they are allowed in the copy dest */
  copy1 = _DBUS_INT_TO_POINTER (0x342234);
  copy2 = _DBUS_INT_TO_POINTER (23);
  
  _dbus_list_copy (&list1, &copy1);
  verify_list (&list1);
  verify_list (&copy1);
  _dbus_assert (lists_equal (&list1, &copy1));
  
  _dbus_list_copy (&list2, &copy2);
  verify_list (&list2);
  verify_list (&copy2);
  _dbus_assert (lists_equal (&list2, &copy2));

  /* Now test copying empty lists */
  _dbus_list_clear (&list1);
  _dbus_list_clear (&list2);
  _dbus_list_clear (&copy1);
  _dbus_list_clear (&copy2);
  
  /* bad pointers, because they are allowed in the copy dest */
  copy1 = _DBUS_INT_TO_POINTER (0x342234);
  copy2 = _DBUS_INT_TO_POINTER (23);
  
  _dbus_list_copy (&list1, &copy1);
  verify_list (&list1);
  verify_list (&copy1);
  _dbus_assert (lists_equal (&list1, &copy1));
  
  _dbus_list_copy (&list2, &copy2);
  verify_list (&list2);
  verify_list (&copy2);
  _dbus_assert (lists_equal (&list2, &copy2));

  _dbus_list_clear (&list1);
  _dbus_list_clear (&list2);
  
  /* insert_before on empty list */
  _dbus_list_insert_before (&list1, NULL,
                            _DBUS_INT_TO_POINTER (0));
  verify_list (&list1);

  /* inserting before first element */
  _dbus_list_insert_before (&list1, list1,
                            _DBUS_INT_TO_POINTER (2));
  verify_list (&list1);
  _dbus_assert (is_descending_sequence (&list1));

  /* inserting in the middle */
  _dbus_list_insert_before (&list1, list1->next,
                            _DBUS_INT_TO_POINTER (1));
  verify_list (&list1);
  _dbus_assert (is_descending_sequence (&list1));  

  /* using insert_before to append */
  _dbus_list_insert_before (&list1, NULL,
                            _DBUS_INT_TO_POINTER (-1));
  verify_list (&list1);
  _dbus_assert (is_descending_sequence (&list1));
  
  _dbus_list_clear (&list1);

  /* insert_after on empty list */
  _dbus_list_insert_after (&list1, NULL,
                           _DBUS_INT_TO_POINTER (0));
  verify_list (&list1);

  /* inserting after first element */
  _dbus_list_insert_after (&list1, list1,
                           _DBUS_INT_TO_POINTER (1));
  verify_list (&list1);
  _dbus_assert (is_ascending_sequence (&list1));

  /* inserting at the end */
  _dbus_list_insert_after (&list1, list1->next,
                           _DBUS_INT_TO_POINTER (2));
  verify_list (&list1);
  _dbus_assert (is_ascending_sequence (&list1));

  /* using insert_after to prepend */
  _dbus_list_insert_after (&list1, NULL,
                           _DBUS_INT_TO_POINTER (-1));
  verify_list (&list1);
  _dbus_assert (is_ascending_sequence (&list1));
  
  _dbus_list_clear (&list1);

  /* using remove_last */
  _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (2));
  _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (1));
  _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (3));

  _dbus_list_remove_last (&list1, _DBUS_INT_TO_POINTER (2));
  
  verify_list (&list1);
  _dbus_assert (is_ascending_sequence (&list1));
  
  _dbus_list_clear (&list1);
  
  return TRUE;
}
示例#27
0
文件: bus.c 项目: kobolabs/dbus
/* This code only gets executed the first time the
 * config files are parsed.  It is not executed
 * when config files are reloaded.
 */
static dbus_bool_t
process_config_first_time_only (BusContext       *context,
				BusConfigParser  *parser,
                                const DBusString *address,
                                BusContextFlags   flags,
				DBusError        *error)
{
  DBusString log_prefix;
  DBusList *link;
  DBusList **addresses;
  const char *user, *pidfile;
  char **auth_mechanisms;
  DBusList **auth_mechanisms_list;
  int len;
  dbus_bool_t retval;

  _DBUS_ASSERT_ERROR_IS_CLEAR (error);

  retval = FALSE;
  auth_mechanisms = NULL;
  pidfile = NULL;

  _dbus_init_system_log (TRUE);

  if (flags & BUS_CONTEXT_FLAG_SYSTEMD_ACTIVATION)
    context->systemd_activation = TRUE;
  else
    context->systemd_activation = FALSE;

  /* Check for an existing pid file. Of course this is a race;
   * we'd have to use fcntl() locks on the pid file to
   * avoid that. But we want to check for the pid file
   * before overwriting any existing sockets, etc.
   */

  if (flags & BUS_CONTEXT_FLAG_WRITE_PID_FILE)
    pidfile = bus_config_parser_get_pidfile (parser);

  if (pidfile != NULL)
    {
      DBusString u;
      DBusStat stbuf;

      _dbus_string_init_const (&u, pidfile);

      if (_dbus_stat (&u, &stbuf, NULL))
        {
#ifdef DBUS_CYGWIN
          DBusString p;
          long /* int */ pid;

          _dbus_string_init (&p);
          _dbus_file_get_contents(&p, &u, NULL);
          _dbus_string_parse_int(&p, 0, &pid, NULL);
          _dbus_string_free(&p);

          if ((kill((int)pid, 0))) {
            dbus_set_error(NULL, DBUS_ERROR_FILE_EXISTS,
                           "pid %ld not running, removing stale pid file\n",
                           pid);
            _dbus_delete_file(&u, NULL);
          } else {
#endif
          dbus_set_error (error, DBUS_ERROR_FAILED,
		                  "The pid file \"%s\" exists, if the message bus is not running, remove this file",
                          pidfile);
	      goto failed;
#ifdef DBUS_CYGWIN
          }
#endif
        }
    }

  /* keep around the pid filename so we can delete it later */
  context->pidfile = _dbus_strdup (pidfile);

  /* note that type may be NULL */
  context->type = _dbus_strdup (bus_config_parser_get_type (parser));
  if (bus_config_parser_get_type (parser) != NULL && context->type == NULL)
    goto oom;

  user = bus_config_parser_get_user (parser);
  if (user != NULL)
    {
      context->user = _dbus_strdup (user);
      if (context->user == NULL)
        goto oom;
    }

  /* Set up the prefix for syslog messages */
  if (!_dbus_string_init (&log_prefix))
    goto oom;
  if (context->type && !strcmp (context->type, "system"))
    {
      if (!_dbus_string_append (&log_prefix, "[system] "))
        goto oom;
    }
  else if (context->type && !strcmp (context->type, "session"))
    {
      DBusCredentials *credentials;

      credentials = _dbus_credentials_new_from_current_process ();
      if (!credentials)
        goto oom;
      if (!_dbus_string_append (&log_prefix, "[session "))
        {
          _dbus_credentials_unref (credentials);
          goto oom;
        }
      if (!_dbus_credentials_to_string_append (credentials, &log_prefix))
        {
          _dbus_credentials_unref (credentials);
          goto oom;
        }
      if (!_dbus_string_append (&log_prefix, "] "))
        {
          _dbus_credentials_unref (credentials);
          goto oom;
        }
      _dbus_credentials_unref (credentials);
    }
  if (!_dbus_string_steal_data (&log_prefix, &context->log_prefix))
    goto oom;
  _dbus_string_free (&log_prefix);

  /* Build an array of auth mechanisms */

  auth_mechanisms_list = bus_config_parser_get_mechanisms (parser);
  len = _dbus_list_get_length (auth_mechanisms_list);

  if (len > 0)
    {
      int i;

      auth_mechanisms = dbus_new0 (char*, len + 1);
      if (auth_mechanisms == NULL)
        goto oom;

      i = 0;
      link = _dbus_list_get_first_link (auth_mechanisms_list);
      while (link != NULL)
        {
          auth_mechanisms[i] = _dbus_strdup (link->data);
          if (auth_mechanisms[i] == NULL)
            goto oom;
          link = _dbus_list_get_next_link (auth_mechanisms_list, link);
          i += 1;
        }
    }
static dbus_bool_t
bus_driver_handle_list_queued_owners (DBusConnection *connection,
				      BusTransaction *transaction,
				      DBusMessage    *message,
				      DBusError      *error)
{
  const char *text;
  DBusList *base_names;
  DBusList *link;
  DBusString str;
  BusRegistry *registry;
  BusService *service;
  DBusMessage *reply;
  DBusMessageIter iter, array_iter;
  char *dbus_service_name = DBUS_SERVICE_DBUS;
  
  _DBUS_ASSERT_ERROR_IS_CLEAR (error);

  registry = bus_connection_get_registry (connection);

  base_names = NULL;
  text = NULL;
  reply = NULL;

  if (! dbus_message_get_args (message, error,
			       DBUS_TYPE_STRING, &text,
			       DBUS_TYPE_INVALID))
      goto failed;

  _dbus_string_init_const (&str, text);
  service = bus_registry_lookup (registry, &str);
  if (service == NULL &&
      _dbus_string_equal_c_str (&str, DBUS_SERVICE_DBUS))
    {
      /* ORG_FREEDESKTOP_DBUS owns itself */
      if (! _dbus_list_append (&base_names, dbus_service_name))
        goto oom;
    }
  else if (service == NULL)
    {
      dbus_set_error (error, 
                      DBUS_ERROR_NAME_HAS_NO_OWNER,
                      "Could not get owners of name '%s': no such name", text);
      goto failed;
    }
  else
    {
      if (!bus_service_list_queued_owners (service, 
                                           &base_names,
                                           error))
        goto failed;
    }

  _dbus_assert (base_names != NULL);

  reply = dbus_message_new_method_return (message);
  if (reply == NULL)
    goto oom;

  dbus_message_iter_init_append (reply, &iter);
  if (!dbus_message_iter_open_container (&iter,
                                         DBUS_TYPE_ARRAY,
                                         DBUS_TYPE_STRING_AS_STRING,
                                         &array_iter))
    goto oom;
  
  link = _dbus_list_get_first_link (&base_names);
  while (link != NULL)
    {
      char *uname;

      _dbus_assert (link->data != NULL);
      uname = (char *)link->data;
    
      if (!dbus_message_iter_append_basic (&array_iter, 
                                           DBUS_TYPE_STRING,
                                           &uname))
        goto oom;

      link = _dbus_list_get_next_link (&base_names, link);
    }

  if (! dbus_message_iter_close_container (&iter, &array_iter))
    goto oom;
                                    
 
  if (! bus_transaction_send_from_driver (transaction, connection, reply))
    goto oom;

  dbus_message_unref (reply);

  return TRUE;

 oom:
  BUS_SET_OOM (error);

 failed:
  _DBUS_ASSERT_ERROR_IS_SET (error);
  if (reply)
    dbus_message_unref (reply);

  if (base_names)
    _dbus_list_clear (&base_names);

  return FALSE;
}
示例#29
0
/**
 * Sets the timeout functions. This function is the "backend"
 * for dbus_connection_set_timeout_functions().
 *
 * @param timeout_list the timeout list
 * @param add_function the add timeout function.
 * @param remove_function the remove timeout function.
 * @param toggled_function toggle notify function, or #NULL
 * @param data the data for those functions.
 * @param free_data_function the function to free the data.
 * @returns #FALSE if no memory
 *
 */
dbus_bool_t
_dbus_timeout_list_set_functions (DBusTimeoutList           *timeout_list,
				  DBusAddTimeoutFunction     add_function,
				  DBusRemoveTimeoutFunction  remove_function,
                                  DBusTimeoutToggledFunction toggled_function,
				  void                      *data,
				  DBusFreeFunction           free_data_function)
{
  /* Add timeouts with the new function, failing on OOM */
  if (add_function != NULL)
    {
      DBusList *link;
      
      link = _dbus_list_get_first_link (&timeout_list->timeouts);
      while (link != NULL)
        {
          DBusList *next = _dbus_list_get_next_link (&timeout_list->timeouts,
                                                     link);
      
          if (!(* add_function) (link->data, data))
            {
              /* remove it all again and return FALSE */
              DBusList *link2;
              
              link2 = _dbus_list_get_first_link (&timeout_list->timeouts);
              while (link2 != link)
                {
                  DBusList *next = _dbus_list_get_next_link (&timeout_list->timeouts,
                                                             link2);

                  (* remove_function) (link2->data, data);
                  
                  link2 = next;
                }

              return FALSE;
            }
      
          link = next;
        }
    }
  
  /* Remove all current timeouts from previous timeout handlers */

  if (timeout_list->remove_timeout_function != NULL)
    {
      _dbus_list_foreach (&timeout_list->timeouts,
			  (DBusForeachFunction) timeout_list->remove_timeout_function,
			  timeout_list->timeout_data);
    }

  if (timeout_list->timeout_free_data_function != NULL)
    (* timeout_list->timeout_free_data_function) (timeout_list->timeout_data);

  timeout_list->add_timeout_function = add_function;
  timeout_list->remove_timeout_function = remove_function;
  timeout_list->timeout_toggled_function = toggled_function;
  timeout_list->timeout_data = data;
  timeout_list->timeout_free_data_function = free_data_function;

  return TRUE;
}
示例#30
0
/* this function is self-cancelling if you cancel the transaction */
dbus_bool_t
bus_service_remove_owner (BusService     *service,
                          DBusConnection *connection,
                          BusTransaction *transaction,
                          DBusError      *error)
{
  BusOwner *primary_owner;
  
  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
  
  /* We send out notifications before we do any work we
   * might have to undo if the notification-sending failed
   */
  
  /* Send service lost message */
  primary_owner = bus_service_get_primary_owner (service);
  if (primary_owner != NULL && primary_owner->conn == connection)
    {
      if (!bus_driver_send_service_lost (connection, service->name,
                                         transaction, error))
        return FALSE;
    }
  else
    {
      /* if we are not the primary owner then just remove us from the queue */
      DBusList *link;
      BusOwner *temp_owner;

      link = _bus_service_find_owner_link (service, connection);
      _dbus_list_unlink (&service->owners, link);
      temp_owner = (BusOwner *)link->data;
      bus_owner_unref (temp_owner); 
      _dbus_list_free_link (link);

      return TRUE; 
    }

  if (service->owners == NULL)
    {
      _dbus_assert_not_reached ("Tried to remove owner of a service that has no owners");
    }
  else if (_dbus_list_length_is_one (&service->owners))
    {
      if (!bus_driver_send_service_owner_changed (service->name,
 						  bus_connection_get_name (connection),
 						  NULL,
 						  transaction, error))
        return FALSE;
    }
  else
    {
      DBusList *link;
      BusOwner *new_owner;
      DBusConnection *new_owner_conn;
      link = _dbus_list_get_first_link (&service->owners);
      _dbus_assert (link != NULL);
      link = _dbus_list_get_next_link (&service->owners, link);
      _dbus_assert (link != NULL);

      new_owner = (BusOwner *)link->data;
      new_owner_conn = new_owner->conn;

      if (!bus_driver_send_service_owner_changed (service->name,
 						  bus_connection_get_name (connection),
 						  bus_connection_get_name (new_owner_conn),
 						  transaction, error))
        return FALSE;

      /* This will be our new owner */
      if (!bus_driver_send_service_acquired (new_owner_conn,
                                             service->name,
                                             transaction,
                                             error))
        return FALSE;
    }

  if (!add_restore_ownership_to_transaction (transaction, service, primary_owner))
    {
      BUS_SET_OOM (error);
      return FALSE;
    }
 
  bus_service_unlink_owner (service, primary_owner);

  if (service->owners == NULL)
    bus_service_unlink (service);

  return TRUE;
}