Beispiel #1
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;
    }

  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;
    }

  _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;
}
Beispiel #2
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 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;
    }
}
/**
 * Writes the given pid_to_write to a pidfile (if non-NULL) and/or to a
 * pipe (if non-NULL). Does nothing if pidfile and print_pid_pipe are both
 * NULL.
 *
 * @param pidfile the file to write to or #NULL
 * @param print_pid_pipe the pipe to write to or #NULL
 * @param pid_to_write the pid to write out
 * @param error error on failure
 * @returns FALSE if error is set
 */
dbus_bool_t
_dbus_write_pid_to_file_and_pipe (const DBusString *pidfile,
                                  DBusPipe         *print_pid_pipe,
                                  dbus_pid_t        pid_to_write,
                                  DBusError        *error)
{
  if (pidfile)
    {
      _dbus_verbose ("writing pid file %s\n", _dbus_string_get_const_data (pidfile));
      if (!_dbus_write_pid_file (pidfile,
                                 pid_to_write,
                                 error))
        {
          _dbus_verbose ("pid file write failed\n");
          _DBUS_ASSERT_ERROR_IS_SET(error);
          return FALSE;
        }
    }
  else
    {
      _dbus_verbose ("No pid file requested\n");
    }

  if (print_pid_pipe != NULL && _dbus_pipe_is_valid (print_pid_pipe))
    {
      DBusString pid;
      int bytes;

      _dbus_verbose ("writing our pid to pipe %d\n",
                     print_pid_pipe->fd);
      
      if (!_dbus_string_init (&pid))
        {
          _DBUS_SET_OOM (error);
          return FALSE;
        }
	  
      if (!_dbus_string_append_int (&pid, pid_to_write) ||
          !_dbus_string_append (&pid, "\n"))
        {
          _dbus_string_free (&pid);
          _DBUS_SET_OOM (error);
          return FALSE;
        }
	  
      bytes = _dbus_string_get_length (&pid);
      if (_dbus_pipe_write (print_pid_pipe, &pid, 0, bytes, error) != bytes)
        {
          /* _dbus_pipe_write sets error only on failure, not short write */
          if (error != NULL && !dbus_error_is_set(error))
            {
              dbus_set_error (error, DBUS_ERROR_FAILED,
                              "Printing message bus PID: did not write enough bytes\n");
            }
          _dbus_string_free (&pid);
          return FALSE;
        }
	  
      _dbus_string_free (&pid);
    }
  else
    {
      _dbus_verbose ("No pid pipe to write to\n");
    }

  return TRUE;
}
Beispiel #4
0
int
main (int argc, char **argv)
{
  DBusError error;
  DBusString config_file;
  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;
  dbus_bool_t is_session_bus;
  int force_fork;

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

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

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

  print_address = FALSE;
  print_pid = FALSE;
  is_session_bus = FALSE;
  force_fork = FORK_FOLLOW_CONFIG_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)
        force_fork = FORK_NEVER;
      else if (strcmp (arg, "--fork") == 0)
        force_fork = FORK_ALWAYS;
      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)
        {
          is_session_bus = TRUE;
          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, "--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, force_fork,
                             &print_addr_pipe, &print_pid_pipe,
                             &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);
    }

  if (is_session_bus)
    _dbus_daemon_publish_session_bus_address (bus_context_get_address (context));

  /* bus_context_new() closes the print_addr_pipe and
   * print_pid_pipe
   */
  
  setup_reload_pipe (bus_context_get_loop (context));

#ifdef SIGHUP
  _dbus_set_signal_handler (SIGHUP, signal_handler);
#endif
  _dbus_set_signal_handler (SIGTERM, signal_handler);
#ifdef DBUS_BUS_ENABLE_DNOTIFY_ON_LINUX 
  _dbus_set_signal_handler (SIGIO, signal_handler);
#endif /* DBUS_BUS_ENABLE_DNOTIFY_ON_LINUX */
  
  _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 ();

  if (is_session_bus)
    _dbus_daemon_unpublish_session_bus_address ();

  return 0;
}
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;

  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");

  dbus_error_init (&error);
  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;
}
/**
 * Get a printable string describing the command used to execute
 * the process with pid.  This string should only be used for
 * informative purposes such as logging; it may not be trusted.
 * 
 * The command is guaranteed to be printable ASCII and no longer
 * than max_len.
 * 
 * @param pid Process id
 * @param str Append command to this string
 * @param max_len Maximum length of returned command
 * @param error return location for errors
 * @returns #FALSE on error
 */
dbus_bool_t 
_dbus_command_for_pid (unsigned long  pid,
                       DBusString    *str,
                       int            max_len,
                       DBusError     *error)
{
  /* This is all Linux-specific for now */
  DBusString path;
  DBusString cmdline;
  int fd;
  
  if (!_dbus_string_init (&path)) 
    {
      _DBUS_SET_OOM (error);
      return FALSE;
    }
  
  if (!_dbus_string_init (&cmdline))
    {
      _DBUS_SET_OOM (error);
      _dbus_string_free (&path);
      return FALSE;
    }
  
  if (!_dbus_string_append_printf (&path, "/proc/%ld/cmdline", pid))
    goto oom;
  
  fd = open (_dbus_string_get_const_data (&path), O_RDONLY);
  if (fd < 0) 
    {
      dbus_set_error (error,
                      _dbus_error_from_errno (errno),
                      "Failed to open \"%s\": %s",
                      _dbus_string_get_const_data (&path),
                      _dbus_strerror (errno));
      goto fail;
    }
  
  if (!_dbus_read (fd, &cmdline, max_len))
    {
      dbus_set_error (error,
                      _dbus_error_from_errno (errno),
                      "Failed to read from \"%s\": %s",
                      _dbus_string_get_const_data (&path),
                      _dbus_strerror (errno));      
      goto fail;
    }
  
  if (!_dbus_close (fd, error))
    goto fail;
  
  string_squash_nonprintable (&cmdline);  

  if (!_dbus_string_copy (&cmdline, 0, str, _dbus_string_get_length (str)))
    goto oom;

  _dbus_string_free (&cmdline);  
  _dbus_string_free (&path);
  return TRUE;
oom:
  _DBUS_SET_OOM (error);
fail:
  _dbus_string_free (&cmdline);
  _dbus_string_free (&path);
  return FALSE;
}
/**
 * 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;
    }

  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;
}
Beispiel #8
0
static dbus_bool_t
handle_reload_watch (DBusWatch    *watch,
                     unsigned int  flags,
                     void         *data)
{
    DBusError error;
    DBusString str;
    char *action_str;
    char action = '\0';

    while (!_dbus_string_init (&str))
        _dbus_wait_for_memory ();

    if ((reload_pipe[RELOAD_READ_END] > 0) &&
            _dbus_read_socket (reload_pipe[RELOAD_READ_END], &str, 1) != 1)
    {
        _dbus_warn ("Couldn't read from reload pipe.\n");
        close_reload_pipe ();
        return TRUE;
    }

    action_str = _dbus_string_get_data (&str);
    if (action_str != NULL)
    {
        action = action_str[0];
    }
    _dbus_string_free (&str);

    /* this can only fail if we don't understand the config file
     * or OOM.  Either way we should just stick with the currently
     * loaded config.
     */
    dbus_error_init (&error);

    switch (action)
    {
    case ACTION_RELOAD:
        if (! bus_context_reload_config (context, &error))
        {
            _DBUS_ASSERT_ERROR_IS_SET (&error);
            _dbus_assert (dbus_error_has_name (&error, DBUS_ERROR_FAILED) ||
                          dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY));
            _dbus_warn ("Unable to reload configuration: %s\n",
                        error.message);
            dbus_error_free (&error);
        }
        break;

    case ACTION_QUIT:
    {
        DBusLoop *loop;
        /*
         * On OSs without abstract sockets, we want to quit
         * gracefully rather than being killed by SIGTERM,
         * so that DBusServer gets a chance to clean up the
         * sockets from the filesystem. fd.o #38656
         */
        loop = bus_context_get_loop (context);
        if (loop != NULL)
        {
            _dbus_loop_quit (loop);
        }
    }
    break;

    default:
        break;
    }

    return TRUE;
}
/**
 * Creates a new debug server using an in-process pipe
 *
 * @param server_name the name of the server.
 * @param error address where an error can be returned.
 * @returns a new server, or #NULL on failure.
 */
DBusServer*
_dbus_server_debug_pipe_new (const char     *server_name,
                             DBusError      *error)
{
  DBusServerDebugPipe *debug_server;
  DBusString address;
  DBusString name_str;
  
  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
  
  if (!pipe_hash_ref ())
    return NULL;
  
  if (_dbus_hash_table_lookup_string (server_pipe_hash, server_name) != NULL)
    {
      dbus_set_error (error, DBUS_ERROR_ADDRESS_IN_USE, NULL);
      pipe_hash_unref ();
      return NULL;
    }
  
  debug_server = dbus_new0 (DBusServerDebugPipe, 1);
  if (debug_server == NULL)
    goto nomem_0;

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

  _dbus_string_init_const (&name_str, server_name);
  if (!_dbus_string_append (&address, "debug-pipe:name=") ||
      !_dbus_address_append_escaped (&address, &name_str))
    goto nomem_2;
  
  debug_server->name = _dbus_strdup (server_name);
  if (debug_server->name == NULL)
    goto nomem_2;
  
  if (!_dbus_server_init_base (&debug_server->base,
			       &debug_vtable, &address))
    goto nomem_3;

  if (!_dbus_hash_table_insert_string (server_pipe_hash,
				       debug_server->name,
				       debug_server))
    goto nomem_4;

  _dbus_string_free (&address);

  /* server keeps the pipe hash ref */

  _dbus_server_trace_ref (&debug_server->base, 0, 1, "debug_pipe_new");
  return (DBusServer *)debug_server;

 nomem_4:
  _dbus_server_finalize_base (&debug_server->base);
 nomem_3:
  dbus_free (debug_server->name);
 nomem_2:
  _dbus_string_free (&address);
 nomem_1:
  dbus_free (debug_server);
 nomem_0:
  pipe_hash_unref ();
  dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
  return NULL;
}
static dbus_bool_t
init_system_db (void)
{
  _dbus_assert (database_locked);
    
  if (system_db == NULL)
    {
      DBusError error;
      const DBusUserInfo *info;
      
      system_db = _dbus_user_database_new ();
      if (system_db == NULL)
        return FALSE;

      dbus_error_init (&error);

      if (!_dbus_user_database_get_uid (system_db,
                                        _dbus_getuid (),
                                        &info,
                                        &error))
        {
          _dbus_user_database_unref (system_db);
          system_db = NULL;
          
          if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
            {
              dbus_error_free (&error);
              return FALSE;
            }
          else
            {
              /* This really should not happen. */
              _dbus_warn ("Could not get password database information for UID of current process: %s\n",
                          error.message);
              dbus_error_free (&error);
              return FALSE;
            }
        }

      if (!_dbus_string_init (&process_username))
        {
          _dbus_user_database_unref (system_db);
          system_db = NULL;
          return FALSE;
        }

      if (!_dbus_string_init (&process_homedir))
        {
          _dbus_string_free (&process_username);
          _dbus_user_database_unref (system_db);
          system_db = NULL;
          return FALSE;
        }

      if (!_dbus_string_append (&process_username,
                                info->username) ||
          !_dbus_string_append (&process_homedir,
                                info->homedir) ||
          !_dbus_register_shutdown_func (shutdown_system_db, NULL))
        {
          _dbus_string_free (&process_username);
          _dbus_string_free (&process_homedir);
          _dbus_user_database_unref (system_db);
          system_db = NULL;
          return FALSE;
        }
    }

  return TRUE;
}
Beispiel #11
0
BusDesktopFile*
bus_desktop_file_load (DBusString *filename,
		       DBusError  *error)
{
  DBusString str;
  BusDesktopFileParser parser;
  DBusStat sb;

  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
  
  /* Clearly there's a race here, but it's just to make it unlikely
   * that we do something silly, we still handle doing it below.
   */
  if (!_dbus_stat (filename, &sb, error))
    return NULL;

  if (sb.size > _DBUS_ONE_KILOBYTE * 128)
    {
      dbus_set_error (error, DBUS_ERROR_FAILED,
                      "Desktop file size (%ld bytes) is too large", (long) sb.size);
      return NULL;
    }
  
  if (!_dbus_string_init (&str))
    {
      BUS_SET_OOM (error);
      return NULL;
    }
  
  if (!_dbus_file_get_contents (&str, filename, error))
    {
      _dbus_string_free (&str);
      return NULL;
    }

  if (!_dbus_string_validate_utf8 (&str, 0, _dbus_string_get_length (&str)))
    {
      _dbus_string_free (&str);
      dbus_set_error (error, DBUS_ERROR_FAILED,
                      "invalid UTF-8");   
      return NULL;
    }
  
  parser.desktop_file = dbus_new0 (BusDesktopFile, 1);
  if (parser.desktop_file == NULL)
    {
      _dbus_string_free (&str);
      BUS_SET_OOM (error);
      return NULL;
    }
  
  parser.data = str;
  parser.line_num = 1;
  parser.pos = 0;
  parser.len = _dbus_string_get_length (&parser.data);
  parser.current_section = -1;

  while (parser.pos < parser.len)
    {
      if (_dbus_string_get_byte (&parser.data, parser.pos) == '[')
	{
	  if (!parse_section_start (&parser, error))
            {
              return NULL;
            }
	}
      else if (is_blank_line (&parser) ||
	       _dbus_string_get_byte (&parser.data, parser.pos) == '#')
	parse_comment_or_blank (&parser);
      else if (parser.current_section < 0)
	{
           dbus_set_error(error, DBUS_ERROR_FAILED,
                          "invalid service file: key=value before [Section]");
           return NULL;
	}
      else
	{
	  if (!parse_key_value (&parser, error))
            {
              return NULL;
            }
	}
    }

  _dbus_string_free (&parser.data);

  return parser.desktop_file;
}
Beispiel #12
0
static dbus_bool_t
parse_key_value (BusDesktopFileParser *parser, DBusError *error)
{
  int line_end, eol_len;
  int key_start, key_end;
  int value_start;
  int p;
  char *value, *tmp;
  DBusString key;
  BusDesktopFileLine *line;

  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
  
  if (!_dbus_string_find_eol (&parser->data, parser->pos, &line_end, &eol_len))
    line_end = parser->len;
  
  p = parser->pos;
  key_start = p;
  while (p < line_end &&
	 (valid[_dbus_string_get_byte (&parser->data, p)] & VALID_KEY_CHAR))
    p++;
  key_end = p;
  
  if (key_start == key_end)
    {
      report_error (parser, "Empty key name", BUS_DESKTOP_PARSE_ERROR_INVALID_SYNTAX, error);
      parser_free (parser);
      return FALSE;
    }

  /* We ignore locales for now */
  if (p < line_end && _dbus_string_get_byte (&parser->data, p) == '[')
    {
      if (line_end == parser->len)
	parser->pos = parser->len;
      else
	parser->pos = line_end + eol_len;
	  
      parser->line_num += 1;

      return TRUE;
    }
  
  /* Skip space before '=' */
  while (p < line_end && _dbus_string_get_byte (&parser->data, p) == ' ')
    p++;

  if (p < line_end && _dbus_string_get_byte (&parser->data, p) != '=')
    {
      report_error (parser, "Invalid characters in key name", BUS_DESKTOP_PARSE_ERROR_INVALID_CHARS, error);
      parser_free (parser);
      return FALSE;
    }

  if (p == line_end)
    {
      report_error (parser, "No '=' in key/value pair", BUS_DESKTOP_PARSE_ERROR_INVALID_SYNTAX, error);
      parser_free (parser);
      return FALSE;
    }

  /* Skip the '=' */
  p++;

  /* Skip space after '=' */
  while (p < line_end && _dbus_string_get_byte (&parser->data, p) == ' ')
    p++;

  value_start = p;
  
  value = unescape_string (parser, &parser->data, value_start, line_end, error);
  if (value == NULL)
    {
      parser_free (parser);
      return FALSE;
    }

  line = new_line (parser);
  if (line == NULL)
    {
      dbus_free (value);
      parser_free (parser);
      BUS_SET_OOM (error);
      return FALSE;
    }
  
  if (!_dbus_string_init (&key))
    {
      dbus_free (value);
      parser_free (parser);
      BUS_SET_OOM (error);
      return FALSE;
    }
  
  if (!_dbus_string_copy_len (&parser->data, key_start, key_end - key_start,
                              &key, 0))
    {
      _dbus_string_free (&key);
      dbus_free (value);
      parser_free (parser);
      BUS_SET_OOM (error);
      return FALSE;
    }
  
  if (!_dbus_string_steal_data (&key, &tmp))
    {
      _dbus_string_free (&key);
      dbus_free (value);
      parser_free (parser);
      BUS_SET_OOM (error);
      return FALSE;
    }
  
  _dbus_string_free (&key);
  
  line->key = tmp;
  line->value = value;

  if (line_end == parser->len)
    parser->pos = parser->len;
  else
    parser->pos = line_end + eol_len;
  
  parser->line_num += 1;

  return TRUE;
}
Beispiel #13
0
static dbus_bool_t
_dbus_read_uuid_file_without_creating (const DBusString *filename,
                                       DBusGUID         *uuid,
                                       DBusError        *error)
{
  DBusString contents;
  DBusString decoded;
  int end;
  
  if (!_dbus_string_init (&contents))
    {
      _DBUS_SET_OOM (error);
      return FALSE;
    }

  if (!_dbus_string_init (&decoded))
    {
      _dbus_string_free (&contents);
      _DBUS_SET_OOM (error);
      return FALSE;
    }
  
  if (!_dbus_file_get_contents (&contents, filename, error))
    goto error;

  _dbus_string_chop_white (&contents);

  if (_dbus_string_get_length (&contents) != DBUS_UUID_LENGTH_HEX)
    {
      dbus_set_error (error, DBUS_ERROR_INVALID_FILE_CONTENT,
                      "UUID file '%s' should contain a hex string of length %d, not length %d, with no other text",
                      _dbus_string_get_const_data (filename),
                      DBUS_UUID_LENGTH_HEX,
                      _dbus_string_get_length (&contents));
      goto error;
    }

  if (!_dbus_string_hex_decode (&contents, 0, &end, &decoded, 0))
    {
      _DBUS_SET_OOM (error);
      goto error;
    }

  if (end == 0)
    {
      dbus_set_error (error, DBUS_ERROR_INVALID_FILE_CONTENT,
                      "UUID file '%s' contains invalid hex data",
                      _dbus_string_get_const_data (filename));
      goto error;
    }

  if (_dbus_string_get_length (&decoded) != DBUS_UUID_LENGTH_BYTES)
    {
      dbus_set_error (error, DBUS_ERROR_INVALID_FILE_CONTENT,
                      "UUID file '%s' contains %d bytes of hex-encoded data instead of %d",
                      _dbus_string_get_const_data (filename),
                      _dbus_string_get_length (&decoded),
                      DBUS_UUID_LENGTH_BYTES);
      goto error;
    }

  _dbus_string_copy_to_buffer (&decoded, uuid->as_bytes, DBUS_UUID_LENGTH_BYTES);

  _dbus_string_free (&decoded);
  _dbus_string_free (&contents);

  _DBUS_ASSERT_ERROR_IS_CLEAR (error);

  return TRUE;
  
 error:
  _DBUS_ASSERT_ERROR_IS_SET (error);
  _dbus_string_free (&contents);
  _dbus_string_free (&decoded);
  return FALSE;
}