static void
socket_finalize (DBusTransport *transport)
{
  DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;

  _dbus_verbose ("\n");
  
  free_watches (transport);

  _dbus_string_free (&socket_transport->encoded_outgoing);
  _dbus_string_free (&socket_transport->encoded_incoming);
  
  _dbus_transport_finalize_base (transport);

  _dbus_assert (socket_transport->read_watch == NULL);
  _dbus_assert (socket_transport->write_watch == NULL);
  
  dbus_free (transport);
}
Пример #2
0
static void
handle_babysitter_socket (DBusBabysitter *sitter,
                          int             revents)
{
  /* Even if we have POLLHUP, we want to keep reading
   * data until POLLIN goes away; so this function only
   * looks at HUP/ERR if no IN is set.
   */
  if (revents & _DBUS_POLLIN)
    {
      _dbus_verbose ("Reading data from babysitter\n");
      if (read_data (sitter, sitter->socket_to_babysitter.fd) != READ_STATUS_OK)
        close_socket_to_babysitter (sitter);
    }
  else if (revents & (_DBUS_POLLERR | _DBUS_POLLHUP))
    {
      close_socket_to_babysitter (sitter);
    }
}
void
_dbus_data_slot_allocator_free (DBusDataSlotAllocator *allocator,
                                dbus_int32_t          *slot_id_p)
{
    _dbus_mutex_lock (*(allocator->lock_loc));

    _dbus_assert (*slot_id_p < allocator->n_allocated_slots);
    _dbus_assert (allocator->allocated_slots[*slot_id_p].slot_id == *slot_id_p);
    _dbus_assert (allocator->allocated_slots[*slot_id_p].refcount > 0);

    allocator->allocated_slots[*slot_id_p].refcount -= 1;

    if (allocator->allocated_slots[*slot_id_p].refcount > 0)
    {
        _dbus_mutex_unlock (*(allocator->lock_loc));
        return;
    }

    /* refcount is 0, free the slot */
    _dbus_verbose ("Freeing slot %d on allocator %p total %d allocated %d used\n",
                   *slot_id_p, allocator, allocator->n_allocated_slots, allocator->n_used_slots);

    allocator->allocated_slots[*slot_id_p].slot_id = -1;
    *slot_id_p = -1;

    allocator->n_used_slots -= 1;

    if (allocator->n_used_slots == 0)
    {
        DBusMutex **mutex_loc = allocator->lock_loc;

        dbus_free (allocator->allocated_slots);
        allocator->allocated_slots = NULL;
        allocator->n_allocated_slots = 0;
        allocator->lock_loc = NULL;

        _dbus_mutex_unlock (*mutex_loc);
    }
    else
    {
        _dbus_mutex_unlock (*(allocator->lock_loc));
    }
}
Пример #4
0
EXPORT_C
#endif
void
_dbus_babysitter_kill_child (DBusBabysitter *sitter)
{
  /* be sure we have the PID of the child */
  while (LIVE_CHILDREN (sitter) &&
         sitter->grandchild_pid == -1)
    babysitter_iteration (sitter, TRUE);

  _dbus_verbose ("Got child PID %ld for killing\n",
                 (long) sitter->grandchild_pid);
  
  if (sitter->grandchild_pid == -1)
    return; /* child is already dead, or we're so hosed we'll never recover */
#ifndef __SYMBIAN32__
  kill (sitter->grandchild_pid, SIGKILL);
#endif  
}
Пример #5
0
/**
 * Adjusts the value of the unix fd counter by the given
 * delta which may be positive or negative.
 *
 * This function may be called with locks held. After calling it, when
 * any relevant locks are no longer held you must call _dbus_counter_notify().
 *
 * @param counter the counter
 * @param delta value to add to the unix fds counter's current value
 */
void
_dbus_counter_adjust_unix_fd (DBusCounter *counter,
                              long         delta)
{
  long old = counter->unix_fd_value;
  
  counter->unix_fd_value += delta;

#if 0
  _dbus_verbose ("Adjusting counter %ld by %ld = %ld\n",
                 old, delta, counter->unix_fd_value);
#endif
  
  if (counter->notify_function != NULL &&
      ((old < counter->notify_unix_fd_guard_value &&
        counter->unix_fd_value >= counter->notify_unix_fd_guard_value) ||
       (old >= counter->notify_unix_fd_guard_value &&
        counter->unix_fd_value < counter->notify_unix_fd_guard_value)))
    counter->notify_pending = TRUE;
}
Пример #6
0
static void
close_socket_to_babysitter (DBusBabysitter *sitter)
{
  _dbus_verbose ("Closing babysitter\n");

  if (sitter->sitter_watch != NULL)
    {
      _dbus_assert (sitter->watches != NULL);
      _dbus_watch_list_remove_watch (sitter->watches,  sitter->sitter_watch);
      _dbus_watch_invalidate (sitter->sitter_watch);
      _dbus_watch_unref (sitter->sitter_watch);
      sitter->sitter_watch = NULL;
    }

  if (sitter->socket_to_babysitter.fd >= 0)
    {
      _dbus_close_socket (sitter->socket_to_babysitter, NULL);
      sitter->socket_to_babysitter.fd = -1;
    }
}
Пример #7
0
static void
close_error_pipe_from_child (DBusBabysitter *sitter)
{
  _dbus_verbose ("Closing child error\n");

  if (sitter->error_watch != NULL)
    {
      _dbus_assert (sitter->watches != NULL);
      _dbus_watch_list_remove_watch (sitter->watches,  sitter->error_watch);
      _dbus_watch_invalidate (sitter->error_watch);
      _dbus_watch_unref (sitter->error_watch);
      sitter->error_watch = NULL;
    }

  if (sitter->error_pipe_from_child >= 0)
    {
      _dbus_close (sitter->error_pipe_from_child, NULL);
      sitter->error_pipe_from_child = -1;
    }
}
Пример #8
0
int
main (int    argc,
      char **argv)
{
  open_destroy_shared_session_bus_connection ();

  dbus_shutdown ();

  open_destroy_shared_session_bus_connection ();

  dbus_shutdown ();

  open_destroy_shared_session_bus_connection ();

  dbus_shutdown ();

  _dbus_verbose ("*** Test shutdown exiting\n");
  
  return 0;
}
Пример #9
0
static dbus_bool_t
_dbus_open_socket (int              *fd_p,
                   int               domain,
                   int               type,
                   int               protocol,
                   DBusError        *error)
{
#ifdef SOCK_CLOEXEC
  dbus_bool_t cloexec_done;

  *fd_p = socket (domain, type | SOCK_CLOEXEC, protocol);
  cloexec_done = *fd_p >= 0;

  /* Check if kernel seems to be too old to know SOCK_CLOEXEC */
  if (*fd_p < 0 && errno == EINVAL)
#endif
    {
      *fd_p = socket (domain, type, protocol);
    }

  if (*fd_p >= 0)
    {
#ifdef SOCK_CLOEXEC
      if (!cloexec_done)
#endif
        {
          _dbus_fd_set_close_on_exec(*fd_p);
        }

      _dbus_verbose ("socket fd %d opened\n", *fd_p);
      return TRUE;
    }
  else
    {
      dbus_set_error(error,
                     _dbus_error_from_errno (errno),
                     "Failed to open socket: %s",
                     _dbus_strerror (errno));
      return FALSE;
    }
}
/**
 * Allocates the given number of bytes, as with standard
 * malloc(). Guaranteed to return #NULL if bytes is zero
 * on all platforms. Returns #NULL if the allocation fails.
 * The memory must be released with dbus_free().
 *
 * @param bytes number of bytes to allocate
 * @return allocated memory, or #NULL if the allocation fails.
 */
void*
dbus_malloc (size_t bytes)
{
#ifdef DBUS_BUILD_TESTS
  _dbus_initialize_malloc_debug ();
  
  if (_dbus_decrement_fail_alloc_counter ())
    {
      _dbus_verbose (" FAILING malloc of %ld bytes\n", (long) bytes);
      
      return NULL;
    }
#endif
  
  if (bytes == 0) /* some system mallocs handle this, some don't */
    return NULL;
#ifdef DBUS_BUILD_TESTS
  else if (fail_size != 0 && bytes > fail_size)
    return NULL;
  else if (guards)
    {
      void *block;

      block = malloc (bytes + GUARD_EXTRA_SIZE);
      if (block)
        n_blocks_outstanding += 1;
      
      return set_guards (block, bytes, SOURCE_MALLOC);
    }
#endif
  else
    {
      void *mem;
      mem = malloc (bytes);
#ifdef DBUS_BUILD_TESTS
      if (mem)
        n_blocks_outstanding += 1;
#endif
      return mem;
    }
}
Пример #11
0
/**
 * Sets a watch to the given enabled state, invoking the
 * application's DBusWatchToggledFunction if appropriate.
 *
 * @param watch_list the watch list.
 * @param watch the watch to toggle.
 * @param enabled #TRUE to enable
 */
void
_dbus_watch_list_toggle_watch (DBusWatchList           *watch_list,
                               DBusWatch               *watch,
                               dbus_bool_t              enabled)
{
  enabled = !!enabled;
  
  if (enabled == watch->enabled)
    return;

  watch->enabled = enabled;
  
  if (watch_list->watch_toggled_function != NULL)
    {
      _dbus_verbose ("Toggling watch %p on fd %d to %d\n",
                     watch, dbus_watch_get_socket (watch), watch->enabled);
      
      (* watch_list->watch_toggled_function) (watch,
                                              watch_list->watch_data);
    }
}
Пример #12
0
static void
live_messages_size_notify (DBusCounter *counter,
                           void        *user_data)
{
  DBusTransport *transport = user_data;

  _dbus_transport_ref (transport);

#if 0
  _dbus_verbose ("Counter value is now %d\n",
                 (int) _dbus_counter_get_value (counter));
#endif
  
  /* disable or re-enable the read watch for the transport if
   * required.
   */
  if (transport->vtable->live_messages_changed)
    (* transport->vtable->live_messages_changed) (transport);

  _dbus_transport_unref (transport);
}
Пример #13
0
/**
 * reads the nonce from the nonce file and stores it in a string
 *
 * @param fname the file to read the nonce from
 * @param nonce returns the nonce. Must be an initialized string, the nonce will be appended.
 * @param error error object to report possible errors
 * @return FALSE iff reading the nonce fails (error is set then)
 */
dbus_bool_t
_dbus_read_nonce (const DBusString *fname, DBusString *nonce, DBusError* error)
{
  FILE *fp;
  char buffer[17];
  size_t nread;

  buffer[sizeof buffer - 1] = '\0';

  _DBUS_ASSERT_ERROR_IS_CLEAR (error);

  _dbus_verbose ("reading nonce from file: %s\n", _dbus_string_get_const_data (fname));


  fp = fopen (_dbus_string_get_const_data (fname), "rb");
  if (!fp)
    {
      dbus_set_error (error,
		      _dbus_error_from_system_errno (),
		      "Failed to open %s for read: %s",
		      _dbus_string_get_const_data (fname),
		      _dbus_strerror_from_errno ());
      return FALSE;
    }

  nread = fread (buffer, 1, sizeof buffer - 1, fp);
  fclose (fp);
  if (!nread)
    {
      dbus_set_error (error, DBUS_ERROR_FILE_NOT_FOUND, "Could not read nonce from file %s", _dbus_string_get_const_data (fname));
      return FALSE;
    }

  if (!_dbus_string_append_len (nonce, buffer, sizeof buffer - 1 ))
    {
      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
      return FALSE;
    }
  return TRUE;
}
Пример #14
0
/**
 * Allocates the given number of bytes, as with standard malloc(), but
 * all bytes are initialized to zero as with calloc(). Guaranteed to
 * return #NULL if bytes is zero on all platforms. Returns #NULL if the
 * allocation fails.  The memory must be released with dbus_free().
 *
 * dbus_malloc0() memory is NOT safe to free with regular free() from
 * the C library. Free it with dbus_free() only.
 *
 * @param bytes number of bytes to allocate
 * @return allocated memory, or #NULL if the allocation fails.
 */
void*
dbus_malloc0 (size_t bytes)
{
#ifdef DBUS_BUILD_TESTS
  _dbus_initialize_malloc_debug ();
  
  if (_dbus_decrement_fail_alloc_counter ())
    {
      _dbus_verbose (" FAILING malloc0 of %ld bytes\n", (long) bytes);
      
      return NULL;
    }
#endif
  
  if (bytes == 0)
    return NULL;
#ifdef DBUS_BUILD_TESTS
  else if (fail_size != 0 && bytes > fail_size)
    return NULL;
  else if (guards)
    {
      void *block;

      block = calloc (bytes + GUARD_EXTRA_SIZE, 1);
      if (block)
	_dbus_atomic_inc (&n_blocks_outstanding);
      return set_guards (block, bytes, SOURCE_MALLOC_ZERO);
    }
#endif
  else
    {
      void *mem;
      mem = calloc (bytes, 1);
#ifdef DBUS_BUILD_TESTS
      if (mem)
	_dbus_atomic_inc (&n_blocks_outstanding);
#endif
      return mem;
    }
}
Пример #15
0
/** Creates the given file, failing if the file already exists.
 *
 * @param filename the filename
 * @param error error location
 * @returns #TRUE if we created the file and it didn't exist
 */
dbus_bool_t
_dbus_create_file_exclusively (const DBusString *filename,
                               DBusError        *error)
{
  HANDLE hnd;
  const char *filename_c;

  _DBUS_ASSERT_ERROR_IS_CLEAR (error);

  filename_c = _dbus_string_get_const_data (filename);

  hnd = CreateFileA (filename_c, GENERIC_WRITE,
                     FILE_SHARE_READ | FILE_SHARE_WRITE,
                     NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL,
                     INVALID_HANDLE_VALUE);
  if (hnd == INVALID_HANDLE_VALUE)
    {
      char *emsg = _dbus_win_error_string (GetLastError ());
      dbus_set_error (error, _dbus_win_error_from_last_error (),
                       "Could not create file %s: %s",
                       filename_c, emsg);
      _dbus_win_free_error_string (emsg);
      return FALSE;
    }

  _dbus_verbose ("exclusive file %s hnd %p opened\n", filename_c, hnd);

  if (CloseHandle (hnd) == 0)
    {
      char *emsg = _dbus_win_error_string (GetLastError ());
      dbus_set_error (error, _dbus_win_error_from_last_error (),
                       "Could not close file %s: %s",
                       filename_c, emsg);
      _dbus_win_free_error_string (emsg);

      return FALSE;
    }

  return TRUE;
}
Пример #16
0
static void
do_exec (int                       child_err_report_fd,
	 char                    **argv,
	 DBusSpawnChildSetupFunc   child_setup,
	 void                     *user_data)
{
#ifdef DBUS_BUILD_TESTS
  int i, max_open;
#endif

  _dbus_verbose_reset ();
  _dbus_verbose ("Child process has PID %lu\n",
                 _dbus_getpid ());
  
  if (child_setup)
    (* child_setup) (user_data);

#ifdef DBUS_BUILD_TESTS
  max_open = sysconf (_SC_OPEN_MAX);
  
  for (i = 3; i < max_open; i++)
    {
      int retval;

      if (i == child_err_report_fd)
        continue;
      
      retval = fcntl (i, F_GETFD);

      if (retval != -1 && !(retval & FD_CLOEXEC))
	_dbus_warn ("Fd %d did not have the close-on-exec flag set!\n", i);
    }
#endif
  #ifndef __SYMBIAN32__
  execv (argv[0], argv);
  #endif
  /* Exec failed */
  write_err_and_exit (child_err_report_fd,
                      CHILD_EXEC_FAILED);
}
Пример #17
0
int dbusrecv_uninit(dbusrecv_hdl_st *p_dbusrecv_hdl)
{
    if (NULL == p_dbusrecv_hdl)
    {
        printf("dbusrecv_uninit: invalid parameter, p_dbusrecv_hdl!");
        return -1;
    }
    if (p_dbusrecv_hdl->dbusloop)
    {
        _dbus_loop_quit (p_dbusrecv_hdl->dbusloop);
        sleep(2);
    }

    if (p_dbusrecv_hdl->connection)
    {
        test_connection_shutdown (p_dbusrecv_hdl->dbusloop, p_dbusrecv_hdl->connection);
        if (p_dbusrecv_hdl->filter_func)
            dbus_connection_remove_filter (p_dbusrecv_hdl->connection, p_dbusrecv_hdl->filter_func, NULL);
        dbus_connection_unref (p_dbusrecv_hdl->connection);
        p_dbusrecv_hdl->connection = NULL;
    }
    if (p_dbusrecv_hdl->dbusloop)
    {
        _dbus_loop_unref (p_dbusrecv_hdl->dbusloop);
        p_dbusrecv_hdl->dbusloop = NULL;
    }
    dbus_shutdown();

    if (p_dbusrecv_hdl->dbusrecv_cfg.myname)
    {
        free(p_dbusrecv_hdl->dbusrecv_cfg.myname);
        p_dbusrecv_hdl->dbusrecv_cfg.myname = NULL;
    }
    free(p_dbusrecv_hdl);
    p_dbusrecv_hdl = NULL;

    _dbus_verbose("%s: service exiting!\n", __FILE__);

    return 0;
}
Пример #18
0
int
main (int    argc,
      char **argv)
{
  DBusError error;
  DBusConnection *connection;
  char *id;
  char *server_id;
  
  dbus_error_init (&error);
  connection = dbus_bus_get (DBUS_BUS_SESSION, &error);
  if (connection == NULL)
    {
      fprintf (stderr, "*** Failed to open connection to system bus: %s\n",
               error.message);
      dbus_error_free (&error);
      return 1;
    }

  server_id = dbus_connection_get_server_id (connection);
  if (server_id == NULL)
    die ("No bus server ID retrieved\n");
  /* printf("'%s'\n", server_id); */
  if (strlen (server_id) != 32)
    die ("Bus server id should have length 32\n");
  dbus_free (server_id);

  id = dbus_bus_get_id (connection, NULL);
  if (id == NULL)
    die ("No bus ID retrieved\n");
  /* printf("'%s'\n", id); */
  if (strlen (id) != 32)
    die ("Bus ID should have length 32\n");
  dbus_free (id);  
  
  _dbus_verbose ("*** Test IDs exiting\n");
  
  return 0;
}
static void
xml_text_reader_error (void *arg, xmlErrorPtr xml_error)
{
  DBusError *error = arg;

#if 0
  _dbus_verbose ("XML_ERROR level=%d, domain=%d, code=%d, msg=%s\n",
                 xml_error->level, xml_error->domain,
                 xml_error->code, xml_error->message);
#endif

  if (!dbus_error_is_set (error))
    {
      if (xml_error->code == XML_ERR_NO_MEMORY)
        _DBUS_SET_OOM (error);
      else if (xml_error->level == XML_ERR_ERROR ||
               xml_error->level == XML_ERR_FATAL)
        dbus_set_error (error, DBUS_ERROR_FAILED,
                        "Error loading config file: '%s'",
                        xml_error->message);
    }
}
Пример #20
0
static void
_dbus_initialize_malloc_debug (void)
{
  if (!debug_initialized)
    {
      debug_initialized = TRUE;
      
      if (_dbus_getenv ("DBUS_MALLOC_FAIL_NTH") != NULL)
	{
	  fail_nth = atoi (_dbus_getenv ("DBUS_MALLOC_FAIL_NTH"));
          fail_alloc_counter = fail_nth;
          _dbus_verbose ("Will fail dbus_malloc every %d times\n", fail_nth);
	}
      
      if (_dbus_getenv ("DBUS_MALLOC_FAIL_GREATER_THAN") != NULL)
        {
          fail_size = atoi (_dbus_getenv ("DBUS_MALLOC_FAIL_GREATER_THAN"));
          _dbus_verbose ("Will fail mallocs over %ld bytes\n",
                         (long) fail_size);
        }

      if (_dbus_getenv ("DBUS_MALLOC_GUARDS") != NULL)
        {
          guards = TRUE;
          _dbus_verbose ("Will use dbus_malloc guards\n");
        }

      if (_dbus_getenv ("DBUS_DISABLE_MEM_POOLS") != NULL)
        {
          disable_mem_pools = TRUE;
          _dbus_verbose ("Will disable memory pools\n");
        }

      if (_dbus_getenv ("DBUS_MALLOC_BACKTRACES") != NULL)
        {
          backtrace_on_fail_alloc = TRUE;
          _dbus_verbose ("Will backtrace on failing a dbus_malloc\n");
        }

      if (_dbus_getenv ("DBUS_MALLOC_CANNOT_FAIL") != NULL)
        {
          malloc_cannot_fail = TRUE;
          _dbus_verbose ("Will abort if system malloc() and friends fail\n");
        }
    }
}
Пример #21
0
/* Return value is whether we successfully wrote any bytes */
static dbus_bool_t
write_data_from_auth (DBusTransport *transport)
{
  DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
  int bytes_written;
  int saved_errno;
  const DBusString *buffer;

  if (!_dbus_auth_get_bytes_to_send (transport->auth,
                                     &buffer))
    return FALSE;
  
  bytes_written = _dbus_write_socket (socket_transport->fd,
                                      buffer,
                                      0, _dbus_string_get_length (buffer));
  saved_errno = _dbus_save_socket_errno ();

  if (bytes_written > 0)
    {
      _dbus_auth_bytes_sent (transport->auth, bytes_written);
      return TRUE;
    }
  else if (bytes_written < 0)
    {
      /* EINTR already handled for us */
      
      if (_dbus_get_is_errno_eagain_or_ewouldblock (saved_errno))
        ;
      else
        {
          _dbus_verbose ("Error writing to remote app: %s\n",
                         _dbus_strerror (saved_errno));
          do_io_error (transport);
        }
    }

  return FALSE;
}
Пример #22
0
/**
 * Sets a watch to the given enabled state, invoking the
 * application's DBusWatchToggledFunction if appropriate.
 *
 * @param watch_list the watch list.
 * @param watch the watch to toggle.
 * @param enabled #TRUE to enable
 */
void
_dbus_watch_list_toggle_watch (DBusWatchList           *watch_list,
                               DBusWatch               *watch,
                               dbus_bool_t              enabled)
{
  enabled = !!enabled;
  
  if (enabled == watch->enabled)
    return;

  watch->enabled = enabled;
  
  if (watch_list->watch_toggled_function != NULL)
    {
      _dbus_verbose ("Toggling watch %p on fd %" DBUS_POLLABLE_FORMAT " to %d\n",
                     watch,
                     _dbus_pollable_printable (watch->fd),
                     watch->enabled);
      
      (* watch_list->watch_toggled_function) (watch,
                                              watch_list->watch_data);
    }
}
Пример #23
0
int
_dbus_accept_with_noncefile (int listen_fd, const DBusNonceFile *noncefile)
{
  int fd;
  DBusString nonce;

  _dbus_assert (noncefile != NULL);
  if (!_dbus_string_init (&nonce))
    return -1;
  //PENDING(kdab): set better errors
  if (_dbus_read_nonce (_dbus_noncefile_get_path(noncefile), &nonce, NULL) != TRUE)
    return -1;
  fd = _dbus_accept (listen_fd);
  if (_dbus_socket_is_invalid (fd))
    return fd;
  if (do_check_nonce(fd, &nonce, NULL) != TRUE) {
    _dbus_verbose ("nonce check failed. Closing socket.\n");
    _dbus_close_socket(fd, NULL);
    return -1;
  }

  return fd;
}
Пример #24
0
dbus_bool_t
_dbus_loop_dispatch (DBusLoop *loop)
{

#if MAINLOOP_SPEW
    _dbus_verbose ("  %d connections to dispatch\n", _dbus_list_get_length (&loop->need_dispatch));
#endif

    if (loop->need_dispatch == NULL)
        return FALSE;

next:
    while (loop->need_dispatch != NULL)
    {
        DBusConnection *connection = _dbus_list_pop_first (&loop->need_dispatch);

        while (TRUE)
        {
            DBusDispatchStatus status;

            status = dbus_connection_dispatch (connection);

            if (status == DBUS_DISPATCH_COMPLETE)
            {
                dbus_connection_unref (connection);
                goto next;
            }
            else
            {
                if (status == DBUS_DISPATCH_NEED_MEMORY)
                    _dbus_wait_for_memory ();
            }
        }
    }

    return TRUE;
}
Пример #25
0
/**
 * Sets the reply of a pending call with the given message,
 * or if the message is #NULL, by timing out the pending call.
 * 
 * @param pending the pending call
 * @param message the message to complete the call with, or #NULL
 *  to time out the call
 */
void
_dbus_pending_call_set_reply_unlocked (DBusPendingCall *pending,
                                       DBusMessage     *message)
{
  if (message == NULL)
    {
      message = pending->timeout_link->data;
      _dbus_list_clear (&pending->timeout_link);
    }
  else
    dbus_message_ref (message);

  _dbus_verbose ("  handing message %p (%s) to pending call serial %u\n",
                 message,
                 dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN ?
                 "method return" :
                 dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR ?
                 "error" : "other type",
                 pending->reply_serial);
  
  _dbus_assert (pending->reply == NULL);
  _dbus_assert (pending->reply_serial == dbus_message_get_reply_serial (message));
  pending->reply = message;
}
static DBusHandlerResult
handle_echo (DBusConnection     *connection,
             DBusMessage        *message)
{
  DBusError error;
  DBusMessage *reply;
  DBusMessageIter iter;
  int i;
  EchoData *d;

  _dbus_verbose ("sending reply to Echo method\n");

  if (!dbus_connection_get_object_path_data (connection, echo_path, (void **)&d))
      die ("No memory");


  dbus_error_init (&error);

  reply = dbus_message_new_method_return (message);
  if (reply == NULL)
    die ("No memory\n");
  
  dbus_message_iter_init_append (reply, &iter);
  for (i = 0; i < d->argc; ++i)
    if (!dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &(d->argv[i])))
      die ("No memory\n");

  if (!dbus_connection_send (connection, reply, NULL))
    die ("No memory\n");

  fprintf (stderr, "Shell echo service echoed the command line\n");
  
  dbus_message_unref (reply);
    
  return DBUS_HANDLER_RESULT_HANDLED;
}
Пример #27
0
static void
new_connection_callback (DBusServer     *server,
                         DBusConnection *new_connection,
                         void           *data)
{
  BusContext *context = data;

  if (!bus_connections_setup_connection (context->connections, new_connection))
    {
      _dbus_verbose ("No memory to setup new connection\n");

      /* if we don't do this, it will get unref'd without
       * being disconnected... kind of strange really
       * that we have to do this, people won't get it right
       * in general.
       */
      dbus_connection_close (new_connection);
    }

  dbus_connection_set_max_received_size (new_connection,
                                         context->limits.max_incoming_bytes);

  dbus_connection_set_max_message_size (new_connection,
                                        context->limits.max_message_size);

  dbus_connection_set_max_received_unix_fds (new_connection,
                                         context->limits.max_incoming_unix_fds);

  dbus_connection_set_max_message_unix_fds (new_connection,
                                        context->limits.max_message_unix_fds);

  dbus_connection_set_allow_anonymous (new_connection,
                                       context->allow_anonymous);

  /* on OOM, we won't have ref'd the connection so it will die. */
}
Пример #28
0
int
main (int argc, char **argv)
{
  DBusError error;
  DBusString config_file;
  DBusString address;
  DBusString addr_fd;
  DBusString pid_fd;
  const char *prev_arg;
  DBusPipe print_addr_pipe;
  DBusPipe print_pid_pipe;
  int i;
  dbus_bool_t print_address;
  dbus_bool_t print_pid;
  BusContextFlags flags;

  if (!_dbus_string_init (&config_file))
    return 1;

  if (!_dbus_string_init (&address))
    return 1;

  if (!_dbus_string_init (&addr_fd))
    return 1;

  if (!_dbus_string_init (&pid_fd))
    return 1;

  print_address = FALSE;
  print_pid = FALSE;

  flags = BUS_CONTEXT_FLAG_WRITE_PID_FILE;

  prev_arg = NULL;
  i = 1;
  while (i < argc)
    {
      const char *arg = argv[i];

      if (strcmp (arg, "--help") == 0 ||
          strcmp (arg, "-h") == 0 ||
          strcmp (arg, "-?") == 0)
        {
          usage ();
        }
      else if (strcmp (arg, "--version") == 0)
        {
          version ();
        }
      else if (strcmp (arg, "--introspect") == 0)
        {
          introspect ();
        }
      else if (strcmp (arg, "--nofork") == 0)
        {
          flags &= ~BUS_CONTEXT_FLAG_FORK_ALWAYS;
          flags |= BUS_CONTEXT_FLAG_FORK_NEVER;
        }
#ifdef DBUS_UNIX
      else if (strcmp (arg, "--fork") == 0)
        {
          flags &= ~BUS_CONTEXT_FLAG_FORK_NEVER;
          flags |= BUS_CONTEXT_FLAG_FORK_ALWAYS;
        }
      else if (strcmp (arg, "--systemd-activation") == 0)
        {
          flags |= BUS_CONTEXT_FLAG_SYSTEMD_ACTIVATION;
        }
#endif
      else if (strcmp (arg, "--nopidfile") == 0)
        {
          flags &= ~BUS_CONTEXT_FLAG_WRITE_PID_FILE;
        }
      else if (strcmp (arg, "--system") == 0)
        {
          check_two_config_files (&config_file, "system");

          if (!_dbus_append_system_config_file (&config_file))
            exit (1);
        }
      else if (strcmp (arg, "--session") == 0)
        {
          check_two_config_files (&config_file, "session");

          if (!_dbus_append_session_config_file (&config_file))
            exit (1);
        }
      else if (strstr (arg, "--config-file=") == arg)
        {
          const char *file;

          check_two_config_files (&config_file, "config-file");

          file = strchr (arg, '=');
          ++file;

          if (!_dbus_string_append (&config_file, file))
            exit (1);
        }
      else if (prev_arg &&
               strcmp (prev_arg, "--config-file") == 0)
        {
          check_two_config_files (&config_file, "config-file");

          if (!_dbus_string_append (&config_file, arg))
            exit (1);
        }
      else if (strcmp (arg, "--config-file") == 0)
        {
          /* wait for next arg */
        }
      else if (strstr (arg, "--address=") == arg)
        {
          const char *file;

          check_two_addresses (&address, "address");

          file = strchr (arg, '=');
          ++file;

          if (!_dbus_string_append (&address, file))
            exit (1);
        }
      else if (prev_arg &&
               strcmp (prev_arg, "--address") == 0)
        {
          check_two_addresses (&address, "address");

          if (!_dbus_string_append (&address, arg))
            exit (1);
        }
      else if (strcmp (arg, "--address") == 0)
        {
          /* wait for next arg */
        }
      else if (strstr (arg, "--print-address=") == arg)
        {
          const char *desc;

          check_two_addr_descriptors (&addr_fd, "print-address");

          desc = strchr (arg, '=');
          ++desc;

          if (!_dbus_string_append (&addr_fd, desc))
            exit (1);

          print_address = TRUE;
        }
      else if (prev_arg &&
               strcmp (prev_arg, "--print-address") == 0)
        {
          check_two_addr_descriptors (&addr_fd, "print-address");

          if (!_dbus_string_append (&addr_fd, arg))
            exit (1);

          print_address = TRUE;
        }
      else if (strcmp (arg, "--print-address") == 0)
        {
          print_address = TRUE; /* and we'll get the next arg if appropriate */
        }
      else if (strstr (arg, "--print-pid=") == arg)
        {
          const char *desc;

          check_two_pid_descriptors (&pid_fd, "print-pid");

          desc = strchr (arg, '=');
          ++desc;

          if (!_dbus_string_append (&pid_fd, desc))
            exit (1);

          print_pid = TRUE;
        }
      else if (prev_arg &&
               strcmp (prev_arg, "--print-pid") == 0)
        {
          check_two_pid_descriptors (&pid_fd, "print-pid");

          if (!_dbus_string_append (&pid_fd, arg))
            exit (1);

          print_pid = TRUE;
        }
      else if (strcmp (arg, "--print-pid") == 0)
        {
          print_pid = TRUE; /* and we'll get the next arg if appropriate */
        }
      else
        {
          usage ();
        }

      prev_arg = arg;

      ++i;
    }

  if (_dbus_string_get_length (&config_file) == 0)
    {
      fprintf (stderr, "No configuration file specified.\n");
      usage ();
    }

  _dbus_pipe_invalidate (&print_addr_pipe);
  if (print_address)
    {
      _dbus_pipe_init_stdout (&print_addr_pipe);
      if (_dbus_string_get_length (&addr_fd) > 0)
        {
          long val;
          int end;
          if (!_dbus_string_parse_int (&addr_fd, 0, &val, &end) ||
              end != _dbus_string_get_length (&addr_fd) ||
              val < 0 || val > _DBUS_INT_MAX)
            {
              fprintf (stderr, "Invalid file descriptor: \"%s\"\n",
                       _dbus_string_get_const_data (&addr_fd));
              exit (1);
            }

          _dbus_pipe_init (&print_addr_pipe, val);
        }
    }
  _dbus_string_free (&addr_fd);

  _dbus_pipe_invalidate (&print_pid_pipe);
  if (print_pid)
    {
      _dbus_pipe_init_stdout (&print_pid_pipe);
      if (_dbus_string_get_length (&pid_fd) > 0)
        {
          long val;
          int end;
          if (!_dbus_string_parse_int (&pid_fd, 0, &val, &end) ||
              end != _dbus_string_get_length (&pid_fd) ||
              val < 0 || val > _DBUS_INT_MAX)
            {
              fprintf (stderr, "Invalid file descriptor: \"%s\"\n",
                       _dbus_string_get_const_data (&pid_fd));
              exit (1);
            }

          _dbus_pipe_init (&print_pid_pipe, val);
        }
    }
  _dbus_string_free (&pid_fd);

  if (!bus_selinux_pre_init ())
    {
      _dbus_warn ("SELinux pre-initialization failed\n");
      exit (1);
    }

  dbus_error_init (&error);
  context = bus_context_new (&config_file, flags,
                             &print_addr_pipe, &print_pid_pipe,
                             _dbus_string_get_length(&address) > 0 ? &address : NULL,
                             &error);
  _dbus_string_free (&config_file);
  if (context == NULL)
    {
      _dbus_warn ("Failed to start message bus: %s\n",
                  error.message);
      dbus_error_free (&error);
      exit (1);
    }

  /* bus_context_new() closes the print_addr_pipe and
   * print_pid_pipe
   */

#ifdef DBUS_UNIX
  setup_reload_pipe (bus_context_get_loop (context));

  /* POSIX signals are Unix-specific, and _dbus_set_signal_handler is
   * unimplemented (and probably unimplementable) on Windows, so there's
   * no point in trying to make the handler portable to non-Unix. */

  _dbus_set_signal_handler (SIGTERM, signal_handler);
  _dbus_set_signal_handler (SIGHUP, signal_handler);
#endif /* DBUS_UNIX */

  _dbus_verbose ("We are on D-Bus...\n");
  _dbus_loop_run (bus_context_get_loop (context));

  bus_context_shutdown (context);
  bus_context_unref (context);
  bus_selinux_shutdown ();

  return 0;
}
/**
 * @ingroup DBusMessageInternals
 * Unit test for DBusMessage.
 *
 * @returns #TRUE on success.
 */
dbus_bool_t
_dbus_message_test (const char *test_data_dir)
{
  DBusMessage *message, *message_without_unix_fds;
  DBusMessageLoader *loader;
  int i;
  const char *data;
  DBusMessage *copy;
  const char *name1;
  const char *name2;
  const dbus_uint32_t our_uint32_array[] =
    { 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
  const dbus_int32_t our_int32_array[] =
    { 0x12345678, -0x23456781, 0x34567812, -0x45678123 };
  const dbus_uint32_t *v_ARRAY_UINT32 = our_uint32_array;
  const dbus_int32_t *v_ARRAY_INT32 = our_int32_array;
#ifdef DBUS_HAVE_INT64
  const dbus_uint64_t our_uint64_array[] =
    { 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
  const dbus_int64_t our_int64_array[] =
    { 0x12345678, -0x23456781, 0x34567812, -0x45678123 };
  const dbus_uint64_t *v_ARRAY_UINT64 = our_uint64_array;
  const dbus_int64_t *v_ARRAY_INT64 = our_int64_array;
#endif
  const char *our_string_array[] = { "Foo", "bar", "", "woo woo woo woo" };
  const char **v_ARRAY_STRING = our_string_array;
  const double our_double_array[] = { 0.1234, 9876.54321, -300.0 };
  const double *v_ARRAY_DOUBLE = our_double_array;
  const unsigned char our_byte_array[] = { 'a', 'b', 'c', 234 };
  const unsigned char *v_ARRAY_BYTE = our_byte_array;
  const dbus_bool_t our_boolean_array[] = { TRUE, FALSE, TRUE, TRUE, FALSE };
  const dbus_bool_t *v_ARRAY_BOOLEAN = our_boolean_array;
  char sig[64];
  const char *s;
  const char *v_STRING;
  double v_DOUBLE;
  dbus_int16_t v_INT16;
  dbus_uint16_t v_UINT16;
  dbus_int32_t v_INT32;
  dbus_uint32_t v_UINT32;
#ifdef DBUS_HAVE_INT64
  dbus_int64_t v_INT64;
  dbus_uint64_t v_UINT64;
#endif
  unsigned char v_BYTE;
  unsigned char v2_BYTE;
  dbus_bool_t v_BOOLEAN;
  DBusMessageIter iter, array_iter, struct_iter;
#ifdef HAVE_UNIX_FD_PASSING
  int v_UNIX_FD;
#endif
  char **decomposed;

  message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
                                          "/org/freedesktop/TestPath",
                                          "Foo.TestInterface",
                                          "TestMethod");
  _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService"));
  _dbus_assert (dbus_message_is_method_call (message, "Foo.TestInterface",
                                             "TestMethod"));
  _dbus_assert (strcmp (dbus_message_get_path (message),
                        "/org/freedesktop/TestPath") == 0);
  dbus_message_set_serial (message, 1234);

  /* string length including nul byte not a multiple of 4 */
  if (!dbus_message_set_sender (message, "org.foo.bar1"))
    _dbus_assert_not_reached ("out of memory");

  _dbus_assert (dbus_message_has_sender (message, "org.foo.bar1"));
  dbus_message_set_reply_serial (message, 5678);

  _dbus_verbose_bytes_of_string (&message->header.data, 0,
                                 _dbus_string_get_length (&message->header.data));
  _dbus_verbose_bytes_of_string (&message->body, 0,
                                 _dbus_string_get_length (&message->body));

  if (!dbus_message_set_sender (message, NULL))
    _dbus_assert_not_reached ("out of memory");


  _dbus_verbose_bytes_of_string (&message->header.data, 0,
                                 _dbus_string_get_length (&message->header.data));
  _dbus_verbose_bytes_of_string (&message->body, 0,
                                 _dbus_string_get_length (&message->body));


  _dbus_assert (!dbus_message_has_sender (message, "org.foo.bar1"));
  _dbus_assert (dbus_message_get_serial (message) == 1234);
  _dbus_assert (dbus_message_get_reply_serial (message) == 5678);
  _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService"));

  _dbus_assert (dbus_message_get_no_reply (message) == FALSE);
  dbus_message_set_no_reply (message, TRUE);
  _dbus_assert (dbus_message_get_no_reply (message) == TRUE);
  dbus_message_set_no_reply (message, FALSE);
  _dbus_assert (dbus_message_get_no_reply (message) == FALSE);

  /* Set/get some header fields */

  if (!dbus_message_set_path (message, "/foo"))
    _dbus_assert_not_reached ("out of memory");
  _dbus_assert (strcmp (dbus_message_get_path (message),
                        "/foo") == 0);

  if (!dbus_message_set_interface (message, "org.Foo"))
    _dbus_assert_not_reached ("out of memory");
  _dbus_assert (strcmp (dbus_message_get_interface (message),
                        "org.Foo") == 0);

  if (!dbus_message_set_member (message, "Bar"))
    _dbus_assert_not_reached ("out of memory");
  _dbus_assert (strcmp (dbus_message_get_member (message),
                        "Bar") == 0);

  /* Set/get them with longer values */
  if (!dbus_message_set_path (message, "/foo/bar"))
    _dbus_assert_not_reached ("out of memory");
  _dbus_assert (strcmp (dbus_message_get_path (message),
                        "/foo/bar") == 0);

  if (!dbus_message_set_interface (message, "org.Foo.Bar"))
    _dbus_assert_not_reached ("out of memory");
  _dbus_assert (strcmp (dbus_message_get_interface (message),
                        "org.Foo.Bar") == 0);

  if (!dbus_message_set_member (message, "BarFoo"))
    _dbus_assert_not_reached ("out of memory");
  _dbus_assert (strcmp (dbus_message_get_member (message),
                        "BarFoo") == 0);

  /* Realloc shorter again */

  if (!dbus_message_set_path (message, "/foo"))
    _dbus_assert_not_reached ("out of memory");
  _dbus_assert (strcmp (dbus_message_get_path (message),
                        "/foo") == 0);

  if (!dbus_message_set_interface (message, "org.Foo"))
    _dbus_assert_not_reached ("out of memory");
  _dbus_assert (strcmp (dbus_message_get_interface (message),
                        "org.Foo") == 0);

  if (!dbus_message_set_member (message, "Bar"))
    _dbus_assert_not_reached ("out of memory");
  _dbus_assert (strcmp (dbus_message_get_member (message),
                        "Bar") == 0);

  /* Path decomposing */
  dbus_message_set_path (message, NULL);
  dbus_message_get_path_decomposed (message, &decomposed);
  _dbus_assert (decomposed == NULL);
  dbus_free_string_array (decomposed);

  dbus_message_set_path (message, "/");
  dbus_message_get_path_decomposed (message, &decomposed);
  _dbus_assert (decomposed != NULL);
  _dbus_assert (decomposed[0] == NULL);
  dbus_free_string_array (decomposed);

  dbus_message_set_path (message, "/a/b");
  dbus_message_get_path_decomposed (message, &decomposed);
  _dbus_assert (decomposed != NULL);
  _dbus_assert (strcmp (decomposed[0], "a") == 0);
  _dbus_assert (strcmp (decomposed[1], "b") == 0);
  _dbus_assert (decomposed[2] == NULL);
  dbus_free_string_array (decomposed);

  dbus_message_set_path (message, "/spam/eggs");
  dbus_message_get_path_decomposed (message, &decomposed);
  _dbus_assert (decomposed != NULL);
  _dbus_assert (strcmp (decomposed[0], "spam") == 0);
  _dbus_assert (strcmp (decomposed[1], "eggs") == 0);
  _dbus_assert (decomposed[2] == NULL);
  dbus_free_string_array (decomposed);

  dbus_message_unref (message);

  /* Test the vararg functions */
  message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
                                          "/org/freedesktop/TestPath",
                                          "Foo.TestInterface",
                                          "TestMethod");
  dbus_message_set_serial (message, 1);
  dbus_message_set_reply_serial (message, 5678);

  v_INT16 = -0x123;
  v_UINT16 = 0x123;
  v_INT32 = -0x12345678;
  v_UINT32 = 0x12300042;
#ifdef DBUS_HAVE_INT64
  v_INT64 = DBUS_INT64_CONSTANT (-0x123456789abcd);
  v_UINT64 = DBUS_UINT64_CONSTANT (0x123456789abcd);
#endif
  v_STRING = "Test string";
  v_DOUBLE = 3.14159;
  v_BOOLEAN = TRUE;
  v_BYTE = 42;
  v2_BYTE = 24;
#ifdef HAVE_UNIX_FD_PASSING
  v_UNIX_FD = 1;
#endif

  dbus_message_append_args (message,
                            DBUS_TYPE_INT16, &v_INT16,
                            DBUS_TYPE_UINT16, &v_UINT16,
			    DBUS_TYPE_INT32, &v_INT32,
                            DBUS_TYPE_UINT32, &v_UINT32,
#ifdef DBUS_HAVE_INT64
                            DBUS_TYPE_INT64, &v_INT64,
                            DBUS_TYPE_UINT64, &v_UINT64,
#endif
			    DBUS_TYPE_STRING, &v_STRING,
			    DBUS_TYPE_DOUBLE, &v_DOUBLE,
			    DBUS_TYPE_BOOLEAN, &v_BOOLEAN,
			    DBUS_TYPE_BYTE, &v_BYTE,
			    DBUS_TYPE_BYTE, &v2_BYTE,
			    DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &v_ARRAY_UINT32,
                            _DBUS_N_ELEMENTS (our_uint32_array),
                            DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, &v_ARRAY_INT32,
                            _DBUS_N_ELEMENTS (our_int32_array),
#ifdef DBUS_HAVE_INT64
                            DBUS_TYPE_ARRAY, DBUS_TYPE_UINT64, &v_ARRAY_UINT64,
                            _DBUS_N_ELEMENTS (our_uint64_array),
                            DBUS_TYPE_ARRAY, DBUS_TYPE_INT64, &v_ARRAY_INT64,
                            _DBUS_N_ELEMENTS (our_int64_array),
#endif
                            DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE, &v_ARRAY_DOUBLE,
                            _DBUS_N_ELEMENTS (our_double_array),
                            DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &v_ARRAY_BYTE,
                            _DBUS_N_ELEMENTS (our_byte_array),
                            DBUS_TYPE_ARRAY, DBUS_TYPE_BOOLEAN, &v_ARRAY_BOOLEAN,
                            _DBUS_N_ELEMENTS (our_boolean_array),
                            DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &v_ARRAY_STRING,
                            _DBUS_N_ELEMENTS (our_string_array),

			    DBUS_TYPE_INVALID);

  i = 0;
  sig[i++] = DBUS_TYPE_INT16;
  sig[i++] = DBUS_TYPE_UINT16;
  sig[i++] = DBUS_TYPE_INT32;
  sig[i++] = DBUS_TYPE_UINT32;
#ifdef DBUS_HAVE_INT64
  sig[i++] = DBUS_TYPE_INT64;
  sig[i++] = DBUS_TYPE_UINT64;
#endif
  sig[i++] = DBUS_TYPE_STRING;
  sig[i++] = DBUS_TYPE_DOUBLE;
  sig[i++] = DBUS_TYPE_BOOLEAN;
  sig[i++] = DBUS_TYPE_BYTE;
  sig[i++] = DBUS_TYPE_BYTE;
  sig[i++] = DBUS_TYPE_ARRAY;
  sig[i++] = DBUS_TYPE_UINT32;
  sig[i++] = DBUS_TYPE_ARRAY;
  sig[i++] = DBUS_TYPE_INT32;
#ifdef DBUS_HAVE_INT64
  sig[i++] = DBUS_TYPE_ARRAY;
  sig[i++] = DBUS_TYPE_UINT64;
  sig[i++] = DBUS_TYPE_ARRAY;
  sig[i++] = DBUS_TYPE_INT64;
#endif
  sig[i++] = DBUS_TYPE_ARRAY;
  sig[i++] = DBUS_TYPE_DOUBLE;
  sig[i++] = DBUS_TYPE_ARRAY;
  sig[i++] = DBUS_TYPE_BYTE;
  sig[i++] = DBUS_TYPE_ARRAY;
  sig[i++] = DBUS_TYPE_BOOLEAN;
  sig[i++] = DBUS_TYPE_ARRAY;
  sig[i++] = DBUS_TYPE_STRING;

  message_without_unix_fds = dbus_message_copy(message);
  _dbus_assert(message_without_unix_fds);
#ifdef HAVE_UNIX_FD_PASSING
  dbus_message_append_args (message,
                            DBUS_TYPE_UNIX_FD, &v_UNIX_FD,
			    DBUS_TYPE_INVALID);
  sig[i++] = DBUS_TYPE_UNIX_FD;
#endif
  sig[i++] = DBUS_TYPE_INVALID;

  _dbus_assert (i < (int) _DBUS_N_ELEMENTS (sig));

  _dbus_verbose ("HEADER\n");
  _dbus_verbose_bytes_of_string (&message->header.data, 0,
                                 _dbus_string_get_length (&message->header.data));
  _dbus_verbose ("BODY\n");
  _dbus_verbose_bytes_of_string (&message->body, 0,
                                 _dbus_string_get_length (&message->body));

  _dbus_verbose ("Signature expected \"%s\" actual \"%s\"\n",
                 sig, dbus_message_get_signature (message));

  s = dbus_message_get_signature (message);

  _dbus_assert (dbus_message_has_signature (message, sig));
  _dbus_assert (strcmp (s, sig) == 0);

  verify_test_message (message);

  copy = dbus_message_copy (message);

  _dbus_assert (dbus_message_get_reply_serial (message) ==
                dbus_message_get_reply_serial (copy));
  _dbus_assert (message->header.padding == copy->header.padding);

  _dbus_assert (_dbus_string_get_length (&message->header.data) ==
                _dbus_string_get_length (&copy->header.data));

  _dbus_assert (_dbus_string_get_length (&message->body) ==
                _dbus_string_get_length (&copy->body));

  verify_test_message (copy);

  name1 = dbus_message_get_interface (message);
  name2 = dbus_message_get_interface (copy);

  _dbus_assert (strcmp (name1, name2) == 0);

  name1 = dbus_message_get_member (message);
  name2 = dbus_message_get_member (copy);

  _dbus_assert (strcmp (name1, name2) == 0);

  dbus_message_unref (copy);

  /* Message loader test */
  dbus_message_lock (message);
  loader = _dbus_message_loader_new ();
  
  /* check ref/unref */
  _dbus_message_loader_ref (loader);
  _dbus_message_loader_unref (loader);

  /* Write the header data one byte at a time */
  data = _dbus_string_get_const_data (&message->header.data);
  for (i = 0; i < _dbus_string_get_length (&message->header.data); i++)
    {
      DBusString *buffer;

      _dbus_message_loader_get_buffer (loader, &buffer);
      _dbus_string_append_byte (buffer, data[i]);
      _dbus_message_loader_return_buffer (loader, buffer, 1);
    }

  /* Write the body data one byte at a time */
  data = _dbus_string_get_const_data (&message->body);
  for (i = 0; i < _dbus_string_get_length (&message->body); i++)
    {
      DBusString *buffer;

      _dbus_message_loader_get_buffer (loader, &buffer);
      _dbus_string_append_byte (buffer, data[i]);
      _dbus_message_loader_return_buffer (loader, buffer, 1);
    }

#ifdef HAVE_UNIX_FD_PASSING
  {
    int *unix_fds;
    unsigned n_unix_fds;
    /* Write unix fd */
    _dbus_message_loader_get_unix_fds(loader, &unix_fds, &n_unix_fds);
    _dbus_assert(n_unix_fds > 0);
    _dbus_assert(message->n_unix_fds == 1);
    unix_fds[0] = _dbus_dup(message->unix_fds[0], NULL);
    _dbus_assert(unix_fds[0] >= 0);
    _dbus_message_loader_return_unix_fds(loader, unix_fds, 1);
  }
#endif

  dbus_message_unref (message);

  /* Now pop back the message */
  if (!_dbus_message_loader_queue_messages (loader))
    _dbus_assert_not_reached ("no memory to queue messages");

  if (_dbus_message_loader_get_is_corrupted (loader))
    _dbus_assert_not_reached ("message loader corrupted");

  message = _dbus_message_loader_pop_message (loader);
  if (!message)
    _dbus_assert_not_reached ("received a NULL message");

  if (dbus_message_get_reply_serial (message) != 5678)
    _dbus_assert_not_reached ("reply serial fields differ");

  dbus_message_unref (message);

  /* ovveride the serial, since it was reset by dbus_message_copy() */
  dbus_message_set_serial(message_without_unix_fds, 8901);

  dbus_message_lock (message_without_unix_fds);

  verify_test_message (message_without_unix_fds);

    {
      /* Marshal and demarshal the message. */

      DBusMessage *message2;
      DBusError error = DBUS_ERROR_INIT;
      char *marshalled = NULL;
      int len = 0;
      char garbage_header[DBUS_MINIMUM_HEADER_SIZE] = "xxx";

      if (!dbus_message_marshal (message_without_unix_fds, &marshalled, &len))
        _dbus_assert_not_reached ("failed to marshal message");

      _dbus_assert (len != 0);
      _dbus_assert (marshalled != NULL);

      _dbus_assert (dbus_message_demarshal_bytes_needed (marshalled, len) == len);
      message2 = dbus_message_demarshal (marshalled, len, &error);

      _dbus_assert (message2 != NULL);
      _dbus_assert (!dbus_error_is_set (&error));
      verify_test_message (message2);

      dbus_message_unref (message2);
      dbus_free (marshalled);

      /* Demarshal invalid message. */

      message2 = dbus_message_demarshal ("invalid", 7, &error);
      _dbus_assert (message2 == NULL);
      _dbus_assert (dbus_error_is_set (&error));
      dbus_error_free (&error);

      /* Demarshal invalid (empty) message. */

      message2 = dbus_message_demarshal ("", 0, &error);
      _dbus_assert (message2 == NULL);
      _dbus_assert (dbus_error_is_set (&error));
      dbus_error_free (&error);

      /* Bytes needed to demarshal empty message: 0 (more) */

      _dbus_assert (dbus_message_demarshal_bytes_needed ("", 0) == 0);
      
      /* Bytes needed to demarshal invalid message: -1 (error). */

      _dbus_assert (dbus_message_demarshal_bytes_needed (garbage_header, DBUS_MINIMUM_HEADER_SIZE) == -1);
    }

  dbus_message_unref (message_without_unix_fds);
  _dbus_message_loader_unref (loader);

  check_memleaks ();
  _dbus_check_fdleaks();

  /* Check that we can abandon a container */
  message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
		  			  "/org/freedesktop/TestPath",
					  "Foo.TestInterface",
					  "Method");

  dbus_message_iter_init_append (message, &iter);

  _dbus_assert (dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY,
			  			  (DBUS_STRUCT_BEGIN_CHAR_AS_STRING
						   DBUS_TYPE_STRING_AS_STRING
						   DBUS_TYPE_STRING_AS_STRING
						   DBUS_STRUCT_END_CHAR_AS_STRING),
						  &array_iter));
  _dbus_assert (dbus_message_iter_open_container (&array_iter, DBUS_TYPE_STRUCT,
			  			  NULL, &struct_iter));

  s = "peaches";
  _dbus_assert (dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_STRING,
			  			&s));

  /* uh-oh, error, try and unwind */

  dbus_message_iter_abandon_container (&array_iter, &struct_iter);
  dbus_message_iter_abandon_container (&array_iter, &iter);

  dbus_message_unref (message);

  /* Load all the sample messages from the message factory */
  {
    DBusMessageDataIter diter;
    DBusMessageData mdata;
    int count;

    reset_validities_seen ();
    
    count = 0;
    _dbus_message_data_iter_init (&diter);
    
    while (_dbus_message_data_iter_get_and_next (&diter,
                                                 &mdata))
      {
        if (!dbus_internal_do_not_use_try_message_data (&mdata.data,
                                                        mdata.expected_validity))
          {
            _dbus_warn ("expected validity %d and did not get it\n",
                        mdata.expected_validity);
            _dbus_assert_not_reached ("message data failed");
          }

        _dbus_message_data_free (&mdata);

        count += 1;
      }

    printf ("%d sample messages tested\n", count);

    print_validities_seen (FALSE);
    print_validities_seen (TRUE);
  }

  check_memleaks ();
  _dbus_check_fdleaks();

  /* Now load every message in test_data_dir if we have one */
  if (test_data_dir == NULL)
    return TRUE;

  return dbus_internal_do_not_use_foreach_message_file (test_data_dir,
                                                        (DBusForeachMessageFileFunc)
                                                        dbus_internal_do_not_use_try_message_file,
                                                        NULL);  
}
static dbus_bool_t
process_test_subdir (const DBusString          *test_base_dir,
                     const char                *subdir,
                     DBusValidity               expected_validity,
                     DBusForeachMessageFileFunc function,
                     void                      *user_data)
{
  DBusString test_directory;
  DBusString filename;
  DBusDirIter *dir;
  dbus_bool_t retval;
  DBusError error = DBUS_ERROR_INIT;

  retval = FALSE;
  dir = NULL;

  if (!_dbus_string_init (&test_directory))
    _dbus_assert_not_reached ("didn't allocate test_directory\n");

  _dbus_string_init_const (&filename, subdir);

  if (!_dbus_string_copy (test_base_dir, 0,
                          &test_directory, 0))
    _dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");

  if (!_dbus_concat_dir_and_file (&test_directory, &filename))
    _dbus_assert_not_reached ("couldn't allocate full path");

  _dbus_string_free (&filename);
  if (!_dbus_string_init (&filename))
    _dbus_assert_not_reached ("didn't allocate filename string\n");

  dir = _dbus_directory_open (&test_directory, &error);
  if (dir == NULL)
    {
      _dbus_warn ("Could not open %s: %s\n",
                  _dbus_string_get_const_data (&test_directory),
                  error.message);
      dbus_error_free (&error);
      goto failed;
    }

  printf ("Testing %s:\n", subdir);

 next:
  while (_dbus_directory_get_next_file (dir, &filename, &error))
    {
      DBusString full_path;

      if (!_dbus_string_init (&full_path))
        _dbus_assert_not_reached ("couldn't init string");

      if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
        _dbus_assert_not_reached ("couldn't copy dir to full_path");

      if (!_dbus_concat_dir_and_file (&full_path, &filename))
        _dbus_assert_not_reached ("couldn't concat file to dir");

      if (_dbus_string_ends_with_c_str (&filename, ".message-raw"))
        ;
      else
        {
          if (_dbus_string_ends_with_c_str (&filename, ".message"))
            {
              _dbus_warn ("Could not load %s, message builder language no longer supported\n",
                          _dbus_string_get_const_data (&filename));
            }
          
          _dbus_verbose ("Skipping non-.message file %s\n",
                         _dbus_string_get_const_data (&filename));
	  _dbus_string_free (&full_path);
          goto next;
        }

      printf ("    %s\n",
              _dbus_string_get_const_data (&filename));

      if (! (*function) (&full_path,
                         expected_validity, user_data))
        {
          _dbus_string_free (&full_path);
          goto failed;
        }
      else
        _dbus_string_free (&full_path);
    }

  if (dbus_error_is_set (&error))
    {
      _dbus_warn ("Could not get next file in %s: %s\n",
                  _dbus_string_get_const_data (&test_directory),
                  error.message);
      dbus_error_free (&error);
      goto failed;
    }

  retval = TRUE;

 failed:

  if (dir)
    _dbus_directory_close (dir);
  _dbus_string_free (&test_directory);
  _dbus_string_free (&filename);

  return retval;
}