Exemplo n.º 1
0
static void
close_reload_pipe (void)
{
    _dbus_close_socket (reload_pipe[RELOAD_READ_END], NULL);
    reload_pipe[RELOAD_READ_END] = -1;

    _dbus_close_socket (reload_pipe[RELOAD_WRITE_END], NULL);
    reload_pipe[RELOAD_WRITE_END] = -1;
}
Exemplo n.º 2
0
static void
close_reload_pipe (DBusWatch **watch)
{
    _dbus_loop_remove_watch (bus_context_get_loop (context), *watch);
    _dbus_watch_invalidate (*watch);
    _dbus_watch_unref (*watch);
    *watch = NULL;

    _dbus_close_socket (reload_pipe[RELOAD_READ_END], NULL);
    reload_pipe[RELOAD_READ_END] = -1;

    _dbus_close_socket (reload_pipe[RELOAD_WRITE_END], NULL);
    reload_pipe[RELOAD_WRITE_END] = -1;
}
Exemplo n.º 3
0
static void
close_error_pipe_from_child (DBusBabysitter *sitter)
{
  _dbus_verbose ("Closing child error\n");
  _dbus_close_socket (sitter->error_pipe_from_child, NULL);
  sitter->error_pipe_from_child = -1;
}
Exemplo n.º 4
0
static void
close_socket_to_babysitter (DBusBabysitter *sitter)
{
  _dbus_verbose ("Closing babysitter\n");
  _dbus_close_socket (sitter->socket_to_babysitter, NULL);
  sitter->socket_to_babysitter = -1;
}
Exemplo n.º 5
0
DBusSocket
_dbus_accept_with_noncefile (DBusSocket listen_fd, const DBusNonceFile *noncefile)
{
  DBusSocket fd = _dbus_socket_get_invalid ();
  DBusString nonce;

  _dbus_assert (noncefile != NULL);

  /* Make it valid to "free" this even if _dbus_string_init() runs
   * out of memory: see comment in do_check_nonce() */
  _dbus_string_init_const (&nonce, "");

  if (!_dbus_string_init (&nonce))
    goto out;

  //PENDING(kdab): set better errors
  if (_dbus_read_nonce (_dbus_noncefile_get_path(noncefile), &nonce, NULL) != TRUE)
    goto out;

  fd = _dbus_accept (listen_fd);

  if (!_dbus_socket_is_valid (fd))
    goto out;

  if (do_check_nonce(fd, &nonce, NULL) != TRUE) {
    _dbus_verbose ("nonce check failed. Closing socket.\n");
    _dbus_close_socket(fd, NULL);
    _dbus_socket_invalidate (&fd);
    goto out;
  }

out:
  _dbus_string_free (&nonce);
  return fd;
}
Exemplo n.º 6
0
static void
socket_disconnect (DBusServer *server)
{
  DBusServerSocket *socket_server = (DBusServerSocket*) server;
  int i;

  HAVE_LOCK_CHECK (server);

  for (i = 0 ; i < socket_server->n_fds ; i++)
    {
      if (socket_server->watch[i])
        {
          _dbus_server_remove_watch (server,
                                     socket_server->watch[i]);
          _dbus_watch_unref (socket_server->watch[i]);
          socket_server->watch[i] = NULL;
        }

      _dbus_close_socket (socket_server->fds[i], NULL);
      socket_server->fds[i] = -1;
    }

  if (socket_server->socket_name != NULL)
    {
      DBusString tmp;
      _dbus_string_init_const (&tmp, socket_server->socket_name);
      _dbus_delete_file (&tmp, NULL);
    }

  if (server->published_address)
      _dbus_daemon_unpublish_session_bus_address();

  HAVE_LOCK_CHECK (server);
}
Exemplo n.º 7
0
/**
 * Creates a new transport for the given Unix domain socket
 * path. This creates a client-side of a transport.
 *
 * @todo once we add a way to escape paths in a dbus
 * address, this function needs to do escaping.
 *
 * @param path the path to the domain socket.
 * @param abstract #TRUE to use abstract socket namespace
 * @param error address where an error can be returned.
 * @returns a new transport, or #NULL on failure.
 */
DBusTransport*
_dbus_transport_new_for_domain_socket (const char     *path,
                                       dbus_bool_t     abstract,
                                       DBusError      *error)
{
  int fd;
  DBusTransport *transport;
  DBusString address;
  
  _DBUS_ASSERT_ERROR_IS_CLEAR (error);

  if (!_dbus_string_init (&address))
    {
      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
      return NULL;
    }

  fd = -1;

  if ((abstract &&
       !_dbus_string_append (&address, "unix:abstract=")) ||
      (!abstract &&
       !_dbus_string_append (&address, "unix:path=")) ||
      !_dbus_string_append (&address, path))
    {
      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
      goto failed_0;
    }
  
  fd = _dbus_connect_unix_socket (path, abstract, error);
  if (fd < 0)
    {
      _DBUS_ASSERT_ERROR_IS_SET (error);
      goto failed_0;
    }

  _dbus_verbose ("Successfully connected to unix socket %s\n",
                 path);

  transport = _dbus_transport_new_for_socket (fd, NULL, &address);
  if (transport == NULL)
    {
      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
      goto failed_1;
    }
  
  _dbus_string_free (&address);
  
  return transport;

 failed_1:
  _dbus_close_socket (fd, NULL);
 failed_0:
  _dbus_string_free (&address);
  return NULL;
}
Exemplo n.º 8
0
/**
 * Creates a new transport for the given VMWare Communication Interface
 * CID and port. This creates a client-side of a transport.
 *
 * @param cid the virtual machine context ID to connect to
 * @param port the port to connect to
 * @param error address where an error can be returned.
 * @returns a new transport, or #NULL on failure.
 */
static
DBusTransport*
_dbus_transport_new_for_vmci (const char *cid,
                              const char *port,
                              DBusError  *error)
{
  int fd;
  DBusTransport *transport;
  DBusString address;

  _DBUS_ASSERT_ERROR_IS_CLEAR (error);

  if (!_dbus_string_init (&address))
    {
      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
      return NULL;
    }

  fd = -1;

  if (!_dbus_string_append (&address, "vmci:cid=") ||
      !_dbus_string_append(&address, cid) ||
      !_dbus_string_append(&address, "port=") ||
      !_dbus_string_append(&address, port)) {
      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
      goto failed_0;
  }

  fd = _dbus_connect_vmci (cid, port, error);
  if (fd < 0)
    {
      _DBUS_ASSERT_ERROR_IS_SET (error);
      goto failed_0;
    }

  _dbus_verbose ("Successfully connected to vmci stream socket %s:%s\n",
                 cid, port);

  transport = _dbus_transport_new_for_socket (fd, NULL, &address);
  if (transport == NULL)
    {
      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
      goto failed_1;
    }

  _dbus_string_free (&address);

  return transport;

 failed_1:
  _dbus_close_socket (fd, NULL);
 failed_0:
  _dbus_string_free (&address);
  return NULL;
}
Exemplo n.º 9
0
static void
socket_disconnect (DBusTransport *transport)
{
  DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;

  _dbus_verbose ("\n");
  
  free_watches (transport);
  
  _dbus_close_socket (socket_transport->fd, NULL);
  _dbus_socket_invalidate (&socket_transport->fd);
}
Exemplo n.º 10
0
/* Avoids a danger in threaded situations (calling close()
 * on a file descriptor twice, and another thread has
 * re-opened it since the first close)
 */
static int
close_and_invalidate (int *fd)
{
    int ret;

    if (*fd < 0)
        return -1;
    else
    {
        ret = _dbus_close_socket (*fd, NULL);
        *fd = -1;
    }

    return ret;
}
Exemplo n.º 11
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;
    }
}
Exemplo n.º 12
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_socket (sitter->error_pipe_from_child, NULL);
        sitter->error_pipe_from_child = -1;
    }
}
Exemplo n.º 13
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;
}
Exemplo n.º 14
0
static dbus_bool_t
handle_watch (DBusWatch       *watch,
              unsigned int     condition,
              void            *data)
{
  DBusBabysitter *sitter = data;

  /* On Unix dbus-spawn uses a babysitter *process*, thus it has to
   * actually send the exit statuses, error codes and whatnot through
   * sockets and/or pipes. On Win32, the babysitter is jus a thread,
   * so it can set the status fields directly in the babysitter struct
   * just fine. The socket pipe is used just so we can watch it with
   * select(), as soon as anything is written to it we know that the
   * babysitter thread has recorded the status in the babysitter
   * struct.
   */

  PING();
  _dbus_close_socket (sitter->socket_to_babysitter, NULL);
  PING();
  sitter->socket_to_babysitter = -1;

  return TRUE;
}
Exemplo n.º 15
0
/**
 * Creates a new transport for the given hostname and port.
 * If host is NULL, it will default to localhost
 *
 * @param host the host to connect to
 * @param port the port to connect to
 * @param family the address family to connect to
 * @param noncefile path to nonce file
 * @param error location to store reason for failure.
 * @returns a new transport, or #NULL on failure.
 */
DBusTransport*
_dbus_transport_new_for_tcp_socket (const char     *host,
                                    const char     *port,
                                    const char     *family,
                                    const char     *noncefile,
                                    DBusError      *error)
{
  DBusSocket fd;
  DBusTransport *transport;
  DBusString address;
  
  _DBUS_ASSERT_ERROR_IS_CLEAR (error);

  if (!_dbus_string_init (&address))
    {
      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
      return NULL;
    }

  if (host == NULL)
    host = "localhost";

  if (!_dbus_string_append (&address, noncefile ? "nonce-tcp:" : "tcp:"))
    goto error;

  if (!_dbus_string_append (&address, "host=") ||
      !_dbus_string_append (&address, host))
    goto error;

  if (!_dbus_string_append (&address, ",port=") ||
      !_dbus_string_append (&address, port))
    goto error;

  if (family != NULL &&
      (!_dbus_string_append (&address, ",family=") ||
       !_dbus_string_append (&address, family)))
    goto error;

  if (noncefile != NULL &&
      (!_dbus_string_append (&address, ",noncefile=") ||
       !_dbus_string_append (&address, noncefile)))
    goto error;

  fd = _dbus_connect_tcp_socket_with_nonce (host, port, family, noncefile, error);
  if (!_dbus_socket_is_valid (fd))
    {
      _DBUS_ASSERT_ERROR_IS_SET (error);
      _dbus_string_free (&address);
      return NULL;
    }

  _dbus_verbose ("Successfully connected to tcp socket %s:%s\n",
                 host, port);
  
  transport = _dbus_transport_new_for_socket (fd, NULL, &address);
  _dbus_string_free (&address);
  if (transport == NULL)
    {
      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
      _dbus_close_socket (fd, NULL);
      _dbus_socket_invalidate (&fd);
    }

  return transport;

error:
  _dbus_string_free (&address);
  dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
  return NULL;
}
Exemplo n.º 16
0
/**
 * Tries to interpret the address entry in a platform-specific
 * way, creating a platform-specific server type if appropriate.
 * Sets error if the result is not OK.
 *
 * @param entry an address entry
 * @param server_p location to store a new DBusServer, or #NULL on failure.
 * @param error location to store rationale for failure on bad address
 * @returns the outcome
 *
 */
DBusServerListenResult
_dbus_server_listen_platform_specific (DBusAddressEntry *entry,
                                       DBusServer      **server_p,
                                       DBusError        *error)
{
  const char *method;

  *server_p = NULL;

  method = dbus_address_entry_get_method (entry);

  if (strcmp (method, "unix") == 0)
    {
      const char *path = dbus_address_entry_get_value (entry, "path");
      const char *tmpdir = dbus_address_entry_get_value (entry, "tmpdir");
      const char *abstract = dbus_address_entry_get_value (entry, "abstract");

      if (path == NULL && tmpdir == NULL && abstract == NULL)
        {
          _dbus_set_bad_address(error, "unix",
                                "path or tmpdir or abstract",
                                NULL);
          return DBUS_SERVER_LISTEN_BAD_ADDRESS;
        }

      if ((path && tmpdir) ||
          (path && abstract) ||
          (tmpdir && abstract))
        {
          _dbus_set_bad_address(error, NULL, NULL,
                                "cannot specify two of \"path\" and \"tmpdir\" and \"abstract\" at the same time");
          return DBUS_SERVER_LISTEN_BAD_ADDRESS;
        }

      if (tmpdir != NULL)
        {
          DBusString full_path;
          DBusString filename;

          if (!_dbus_string_init (&full_path))
            {
              dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
              return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
            }

          if (!_dbus_string_init (&filename))
            {
              _dbus_string_free (&full_path);
              dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
              return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
            }

          if (!_dbus_string_append (&filename,
                                    "dbus-") ||
              !_dbus_generate_random_ascii (&filename, 10) ||
              !_dbus_string_append (&full_path, tmpdir) ||
              !_dbus_concat_dir_and_file (&full_path, &filename))
            {
              _dbus_string_free (&full_path);
              _dbus_string_free (&filename);
              dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
              return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
            }

          /* Always use abstract namespace if possible with tmpdir */

          *server_p =
            _dbus_server_new_for_domain_socket (_dbus_string_get_const_data (&full_path),
#ifdef HAVE_ABSTRACT_SOCKETS
                                                TRUE,
#else
                                                FALSE,
#endif
                                                error);

          _dbus_string_free (&full_path);
          _dbus_string_free (&filename);
        }
      else
        {
          if (path)
            *server_p = _dbus_server_new_for_domain_socket (path, FALSE, error);
          else
            *server_p = _dbus_server_new_for_domain_socket (abstract, TRUE, error);
        }

      if (*server_p != NULL)
        {
          _DBUS_ASSERT_ERROR_IS_CLEAR(error);
          return DBUS_SERVER_LISTEN_OK;
        }
      else
        {
          _DBUS_ASSERT_ERROR_IS_SET(error);
          return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
        }
    }
  else if (strcmp (method, "systemd") == 0)
    {
      int i, n, *fds;
      DBusString address;

      n = _dbus_listen_systemd_sockets (&fds, error);
      if (n < 0)
        {
          _DBUS_ASSERT_ERROR_IS_SET (error);
          return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
        }

      if(!_dbus_string_init(&address))
          goto oom;

      for (i = 0; i < n; i++)
        {
          if ( i > 0)
            {
              if(!_dbus_string_append (&address, ";"))
                goto oom;
            }
          if(!_dbus_append_address_from_socket (fds[i], &address))
            goto oom;
        }

      *server_p = _dbus_server_new_for_socket (fds, n, &address, NULL);
      if (*server_p == NULL)
        goto oom;

      dbus_free (fds);

      return DBUS_SERVER_LISTEN_OK;
  oom:
      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
      for (i = 0; i < n; i++)
        {
          _dbus_close_socket (fds[i], NULL);
        }
      dbus_free (fds);
      _dbus_string_free (&address);

      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
      return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
    }
#ifdef DBUS_ENABLE_LAUNCHD
  else if (strcmp (method, "launchd") == 0)
    {
      const char *launchd_env_var = dbus_address_entry_get_value (entry, "env");
      if (launchd_env_var == NULL)
        {
          _dbus_set_bad_address (error, "launchd", "env", NULL);
          return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
        }
      *server_p = _dbus_server_new_for_launchd (launchd_env_var, error);

      if (*server_p != NULL)
        {
          _DBUS_ASSERT_ERROR_IS_CLEAR(error);
          return DBUS_SERVER_LISTEN_OK;
        }
      else
        {
          _DBUS_ASSERT_ERROR_IS_SET(error);
          return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
        }
    }
#endif
  else
    {
      /* If we don't handle the method, we return NULL with the
       * error unset
       */
      _DBUS_ASSERT_ERROR_IS_CLEAR(error);
      return DBUS_SERVER_LISTEN_NOT_HANDLED;
    }
}
Exemplo n.º 17
0
/**
 * Creates a new server listening on the given Unix domain socket.
 *
 * @param path the path for the domain socket.
 * @param abstract #TRUE to use abstract socket namespace
 * @param error location to store reason for failure.
 * @returns the new server, or #NULL on failure.
 */
DBusServer*
_dbus_server_new_for_domain_socket (const char     *path,
                                    dbus_bool_t     abstract,
                                    DBusError      *error)
{
  DBusServer *server;
  int listen_fd;
  DBusString address;
  char *path_copy;
  DBusString path_str;

  _DBUS_ASSERT_ERROR_IS_CLEAR (error);

  if (!_dbus_string_init (&address))
    {
      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
      return NULL;
    }

  _dbus_string_init_const (&path_str, path);
  if ((abstract &&
       !_dbus_string_append (&address, "unix:abstract=")) ||
      (!abstract &&
       !_dbus_string_append (&address, "unix:path=")) ||
      !_dbus_address_append_escaped (&address, &path_str))
    {
      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
      goto failed_0;
    }

  if (abstract)
    {
      path_copy = NULL;
    }
  else
    {
      path_copy = _dbus_strdup (path);
      if (path_copy == NULL)
        {
          dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
          goto failed_0;
        }
    }

  listen_fd = _dbus_listen_unix_socket (path, abstract, error);

  if (listen_fd < 0)
    {
      _DBUS_ASSERT_ERROR_IS_SET (error);
      goto failed_1;
    }

  server = _dbus_server_new_for_socket (&listen_fd, 1, &address, 0);
  if (server == NULL)
    {
      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
      goto failed_2;
    }

  if (path_copy != NULL)
    _dbus_server_socket_own_filename(server, path_copy);

  _dbus_string_free (&address);

  return server;

 failed_2:
  _dbus_close_socket (listen_fd, NULL);
 failed_1:
  dbus_free (path_copy);
 failed_0:
  _dbus_string_free (&address);

  return NULL;
}
Exemplo n.º 18
0
/**
 * Decrement the reference count on the babysitter object.
 *
 * @param sitter the babysitter
 */
void
_dbus_babysitter_unref (DBusBabysitter *sitter)
{
  int i;

  PING();
  _dbus_assert (sitter != NULL);
  _dbus_assert (sitter->refcount > 0);

  sitter->refcount -= 1;

  if (sitter->refcount == 0)
    {
      if (sitter->socket_to_babysitter != -1)
        {
          _dbus_close_socket (sitter->socket_to_babysitter, NULL);
          sitter->socket_to_babysitter = -1;
        }

      if (sitter->socket_to_main != -1)
        {
          _dbus_close_socket (sitter->socket_to_main, NULL);
          sitter->socket_to_main = -1;
        }

      PING();
      if (sitter->argv != NULL)
        {
          for (i = 0; i < sitter->argc; i++)
            if (sitter->argv[i] != NULL)
              {
                dbus_free (sitter->argv[i]);
                sitter->argv[i] = NULL;
              }
          dbus_free (sitter->argv);
          sitter->argv = NULL;
        }

      if (sitter->envp != NULL)
        {
          char **e = sitter->envp;

          while (*e)
            dbus_free (*e++);
          dbus_free (sitter->envp);
          sitter->envp = NULL;
        }

      if (sitter->child_handle != NULL)
        {
          CloseHandle (sitter->child_handle);
          sitter->child_handle = NULL;
        }

      if (sitter->sitter_watch)
        {
          _dbus_watch_invalidate (sitter->sitter_watch);
          _dbus_watch_unref (sitter->sitter_watch);
          sitter->sitter_watch = NULL;
        }

      if (sitter->watches)
        _dbus_watch_list_free (sitter->watches);

      if (sitter->start_sync_event != NULL)
        {
          PING();
          CloseHandle (sitter->start_sync_event);
          sitter->start_sync_event = NULL;
        }

#ifdef DBUS_BUILD_TESTS
      if (sitter->end_sync_event != NULL)
        {
          CloseHandle (sitter->end_sync_event);
          sitter->end_sync_event = NULL;
        }
#endif

      dbus_free (sitter->executable);

      dbus_free (sitter);
    }
}
Exemplo n.º 19
0
/* Return value is just for memory, not other failures. */
static dbus_bool_t
handle_new_client_fd_and_unlock (DBusServer *server,
                                 int         client_fd)
{
  DBusConnection *connection;
  DBusTransport *transport;
  DBusNewConnectionFunction new_connection_function;
  DBusServerSocket* socket_server;
  void *new_connection_data;

  socket_server = (DBusServerSocket*)server;
  _dbus_verbose ("Creating new client connection with fd %d\n", client_fd);

  HAVE_LOCK_CHECK (server);

  if (!_dbus_set_fd_nonblocking (client_fd, NULL))
    {
      SERVER_UNLOCK (server);
      return TRUE;
    }

  transport = _dbus_transport_new_for_socket (client_fd, &server->guid_hex, FALSE);
  if (transport == NULL)
    {
      _dbus_close_socket (client_fd, NULL);
      SERVER_UNLOCK (server);
      return FALSE;
    }

  if (!_dbus_transport_set_auth_mechanisms (transport,
                                            (const char **) server->auth_mechanisms))
    {
      _dbus_transport_unref (transport);
      SERVER_UNLOCK (server);
      return FALSE;
    }

  /* note that client_fd is now owned by the transport, and will be
   * closed on transport disconnection/finalization
   */

  connection = _dbus_connection_new_for_transport (transport);
  _dbus_transport_unref (transport);
  transport = NULL; /* now under the connection lock */

  if (connection == NULL)
    {
      SERVER_UNLOCK (server);
      return FALSE;
    }

  /* See if someone wants to handle this new connection, self-referencing
   * for paranoia.
   */
  new_connection_function = server->new_connection_function;
  new_connection_data = server->new_connection_data;

  _dbus_server_ref_unlocked (server);
  SERVER_UNLOCK (server);

  if (new_connection_function)
    {
      (* new_connection_function) (server, connection,
                                   new_connection_data);
    }
  dbus_server_unref (server);

  /* If no one grabbed a reference, the connection will die. */
  _dbus_connection_close_if_only_one_ref (connection);
  dbus_connection_unref (connection);

  return TRUE;
}
Exemplo n.º 20
0
/**
 * Decrement the reference count on the babysitter object.
 * When the reference count of the babysitter object reaches
 * zero, the babysitter is killed and the child that was being
 * babysat gets emancipated.
 *
 * @param sitter the babysitter
 */
void
_dbus_babysitter_unref (DBusBabysitter *sitter)
{
  _dbus_assert (sitter != NULL);
  _dbus_assert (sitter->refcount > 0);
  
  sitter->refcount -= 1;
  if (sitter->refcount == 0)
    {      
      if (sitter->socket_to_babysitter >= 0)
        {
          /* If we haven't forked other babysitters
           * since this babysitter and socket were
           * created then this close will cause the
           * babysitter to wake up from poll with
           * a hangup and then the babysitter will
           * quit itself.
           */
          _dbus_close_socket (sitter->socket_to_babysitter, NULL);
          sitter->socket_to_babysitter = -1;
        }

      if (sitter->error_pipe_from_child >= 0)
        {
          _dbus_close_socket (sitter->error_pipe_from_child, NULL);
          sitter->error_pipe_from_child = -1;
        }

      if (sitter->sitter_pid > 0)
        {
          int status;
          int ret;

          /* It's possible the babysitter died on its own above 
           * from the close, or was killed randomly
           * by some other process, so first try to reap it
           */
          ret = waitpid (sitter->sitter_pid, &status, WNOHANG);

          /* If we couldn't reap the child then kill it, and
           * try again
           */
          if (ret == 0)
            kill (sitter->sitter_pid, SIGKILL);

        again:
          if (ret == 0)
            ret = waitpid (sitter->sitter_pid, &status, 0);

          if (ret < 0)
            {
              if (errno == EINTR)
                goto again;
              else if (errno == ECHILD)
                _dbus_warn ("Babysitter process not available to be reaped; should not happen\n");
              else
                _dbus_warn ("Unexpected error %d in waitpid() for babysitter: %s\n",
                            errno, _dbus_strerror (errno));
            }
          else
            {
              _dbus_verbose ("Reaped %ld, waiting for babysitter %ld\n",
                             (long) ret, (long) sitter->sitter_pid);
              
              if (WIFEXITED (sitter->status))
                _dbus_verbose ("Babysitter exited with status %d\n",
                               WEXITSTATUS (sitter->status));
              else if (WIFSIGNALED (sitter->status))
                _dbus_verbose ("Babysitter received signal %d\n",
                               WTERMSIG (sitter->status));
              else
                _dbus_verbose ("Babysitter exited abnormally\n");
            }

          sitter->sitter_pid = -1;
        }
      
      if (sitter->error_watch)
        {
          _dbus_watch_invalidate (sitter->error_watch);
          _dbus_watch_unref (sitter->error_watch);
          sitter->error_watch = NULL;
        }

      if (sitter->sitter_watch)
        {
          _dbus_watch_invalidate (sitter->sitter_watch);
          _dbus_watch_unref (sitter->sitter_watch);
          sitter->sitter_watch = NULL;
        }
      
      if (sitter->watches)
        _dbus_watch_list_free (sitter->watches);

      dbus_free (sitter->executable);
      
      dbus_free (sitter);
    }
}
/**
 * Creates the client-side transport for
 * a debug-pipe connection connected to the
 * given debug-pipe server name.
 *
 * @param server_name name of server to connect to
 * @param error address where an error can be returned.
 * @returns #NULL on no memory or transport
 */
DBusTransport*
_dbus_transport_debug_pipe_new (const char     *server_name,
                                DBusError      *error)
{
    DBusTransport *client_transport;
    DBusTransport *server_transport;
    DBusConnection *connection;
    int client_fd, server_fd;
    DBusServer *server;
    DBusString address;

    _DBUS_ASSERT_ERROR_IS_CLEAR (error);

    if (server_pipe_hash == NULL)
    {
        dbus_set_error (error, DBUS_ERROR_NO_SERVER, NULL);
        return NULL;
    }

    server = _dbus_hash_table_lookup_string (server_pipe_hash,
             server_name);
    if (server == NULL ||
            ((DBusServerDebugPipe*)server)->disconnected)
    {
        dbus_set_error (error, DBUS_ERROR_NO_SERVER, NULL);
        return NULL;
    }

    if (!_dbus_string_init (&address))
    {
        dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
        return NULL;
    }

    if (!_dbus_string_append (&address, "debug-pipe:name=") ||
            !_dbus_string_append (&address, server_name))
    {
        dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
        _dbus_string_free (&address);
        return NULL;
    }

    if (!_dbus_full_duplex_pipe (&client_fd, &server_fd, FALSE,
                                 NULL))
    {
        _dbus_verbose ("failed to create full duplex pipe\n");
        dbus_set_error (error, DBUS_ERROR_FAILED, "Could not create full-duplex pipe");
        _dbus_string_free (&address);
        return NULL;
    }

    _dbus_fd_set_close_on_exec (client_fd);
    _dbus_fd_set_close_on_exec (server_fd);

    client_transport = _dbus_transport_new_for_socket (client_fd,
                       NULL, &address);
    if (client_transport == NULL)
    {
        _dbus_close_socket (client_fd, NULL);
        _dbus_close_socket (server_fd, NULL);
        dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
        _dbus_string_free (&address);
        return NULL;
    }

    _dbus_string_free (&address);

    client_fd = -1;

    server_transport = _dbus_transport_new_for_socket (server_fd,
                       &server->guid_hex, NULL);
    if (server_transport == NULL)
    {
        _dbus_transport_unref (client_transport);
        _dbus_close_socket (server_fd, NULL);
        dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
        return NULL;
    }

    server_fd = -1;

    if (!_dbus_transport_set_auth_mechanisms (server_transport,
            (const char**) server->auth_mechanisms))
    {
        dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
        _dbus_transport_unref (server_transport);
        _dbus_transport_unref (client_transport);
        return NULL;
    }

    connection = _dbus_connection_new_for_transport (server_transport);
    _dbus_transport_unref (server_transport);
    server_transport = NULL;

    if (connection == NULL)
    {
        _dbus_transport_unref (client_transport);
        dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
        return NULL;
    }

    /* See if someone wants to handle this new connection,
     * self-referencing for paranoia
     */
    if (server->new_connection_function)
    {
        dbus_server_ref (server);
        (* server->new_connection_function) (server, connection,
                                             server->new_connection_data);
        dbus_server_unref (server);
    }

    /* If no one grabbed a reference, the connection will die,
     * and the client transport will get an immediate disconnect
     */
    _dbus_connection_close_if_only_one_ref (connection);
    dbus_connection_unref (connection);

    return client_transport;
}
Exemplo n.º 22
0
/**
 * Creates a new server listening on TCP.
 * If host is NULL, it will default to localhost.
 * If bind is NULL, it will default to the value for the host
 * parameter, and if that is NULL, then localhost
 * If bind is a hostname, it will be resolved and will listen
 * on all returned addresses.
 * If family is NULL, hostname resolution will try all address
 * families, otherwise it can be ipv4 or ipv6 to restrict the
 * addresses considered.
 *
 * @param host the hostname to report for the listen address
 * @param bind the hostname to listen on
 * @param port the port to listen on or 0 to let the OS choose
 * @param family
 * @param error location to store reason for failure.
 * @param use_nonce whether to use a nonce for low-level authentication (nonce-tcp transport) or not (tcp transport)
 * @returns the new server, or #NULL on failure.
 */
DBusServer*
_dbus_server_new_for_tcp_socket (const char     *host,
                                 const char     *bind,
                                 const char     *port,
                                 const char     *family,
                                 DBusError      *error,
                                 dbus_bool_t    use_nonce)
{
  DBusServer *server;
  int *listen_fds = NULL;
  int nlisten_fds = 0, i;
  DBusString address;
  DBusString host_str;
  DBusString port_str;
  DBusNonceFile *noncefile;
  
  _DBUS_ASSERT_ERROR_IS_CLEAR (error);

  noncefile = NULL;

  if (!_dbus_string_init (&address))
    {
      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
      return NULL;
    }

  if (!_dbus_string_init (&port_str))
    {
      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
      goto failed_0;
    }

  if (host == NULL)
    host = "localhost";

  if (port == NULL)
    port = "0";

  if (bind == NULL)
    bind = host;
  else if (strcmp (bind, "*") == 0)
    bind = NULL;

  nlisten_fds =_dbus_listen_tcp_socket (bind, port, family,
                                        &port_str,
                                        &listen_fds, error);
  if (nlisten_fds <= 0)
    {
      _DBUS_ASSERT_ERROR_IS_SET(error);
      goto failed_1;
    }

  _dbus_string_init_const (&host_str, host);
  if (!_dbus_string_append (&address, use_nonce ? "nonce-tcp:host=" : "tcp:host=") ||
      !_dbus_address_append_escaped (&address, &host_str) ||
      !_dbus_string_append (&address, ",port=") ||
      !_dbus_string_append (&address, _dbus_string_get_const_data(&port_str)))
    {
      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
      goto failed_2;
    }
  if (family &&
      (!_dbus_string_append (&address, ",family=") ||
       !_dbus_string_append (&address, family)))
    {
      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
      goto failed_2;
    }

  if (use_nonce)
    {
      noncefile = dbus_new0 (DBusNonceFile, 1);
      if (noncefile == NULL)
        {
          dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
          goto failed_2;
        }

      if (!_dbus_noncefile_create (noncefile, error))
          goto failed_3;

      if (!_dbus_string_append (&address, ",noncefile=") ||
          !_dbus_address_append_escaped (&address, _dbus_noncefile_get_path (noncefile)))
        {
          dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
          goto failed_4;
        }

    }

  server = _dbus_server_new_for_socket (listen_fds, nlisten_fds, &address, noncefile);
  if (server == NULL)
    {
      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
      goto failed_4;
    }

  _dbus_string_free (&port_str);
  _dbus_string_free (&address);
  dbus_free(listen_fds);

  return server;

 failed_4:
  _dbus_noncefile_delete (noncefile, NULL);

 failed_3:
  dbus_free (noncefile);

 failed_2:
  for (i = 0 ; i < nlisten_fds ; i++)
    _dbus_close_socket (listen_fds[i], NULL);
  dbus_free(listen_fds);

 failed_1:
  _dbus_string_free (&port_str);

 failed_0:
  _dbus_string_free (&address);

  return NULL;
}