示例#1
0
static gboolean
spawn_x_server (State        *state,
                gboolean      allow_remote_connections,
                GCancellable *cancellable)
{
        GPtrArray           *arguments = NULL;
        GSubprocessLauncher *launcher = NULL;
        GSubprocess         *subprocess = NULL;
        GInputStream        *input_stream = NULL;
        GDataInputStream    *data_stream = NULL;
        GError              *error = NULL;

        char     *auth_file;
        gboolean  is_running = FALSE;
        int       ret;
        int       pipe_fds[2];
        char     *display_fd_string = NULL;
        char     *vt_string = NULL;
        char     *display_number;
        gsize     display_number_size;

        auth_file = prepare_auth_file ();

        g_debug ("Running X server");

        ret = g_unix_open_pipe (pipe_fds, FD_CLOEXEC, &error);

        if (!ret) {
                g_debug ("could not open pipe: %s", error->message);
                goto out;
        }

        arguments = g_ptr_array_new ();
        launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDIN_INHERIT);
        g_subprocess_launcher_setenv (launcher, "XORG_RUN_AS_USER_OK", "1", TRUE);
        g_subprocess_launcher_take_fd (launcher, pipe_fds[1], DISPLAY_FILENO);

        if (g_getenv ("XDG_VTNR") != NULL) {
                int vt;

                vt = atoi (g_getenv ("XDG_VTNR"));

                if (vt > 0 && vt < 64) {
                        vt_string = g_strdup_printf ("vt%d", vt);
                }
        }

        display_fd_string = g_strdup_printf ("%d", DISPLAY_FILENO);

        g_ptr_array_add (arguments, X_SERVER);

        if (vt_string != NULL) {
                g_ptr_array_add (arguments, vt_string);
        }

        g_ptr_array_add (arguments, "-displayfd");
        g_ptr_array_add (arguments, display_fd_string);

        g_ptr_array_add (arguments, "-auth");
        g_ptr_array_add (arguments, auth_file);

        /* If we were compiled with Xserver >= 1.17 we need to specify
         * '-listen tcp' as the X server dosen't listen on tcp sockets
         * by default anymore. In older versions we need to pass
         * -nolisten tcp to disable listening on tcp sockets.
         */
#ifdef HAVE_XSERVER_THAT_DEFAULTS_TO_LOCAL_ONLY
        if (allow_remote_connections) {
                g_ptr_array_add (arguments, "-listen");
                g_ptr_array_add (arguments, "tcp");
        }
#else
        if (!allow_remote_connections) {
                g_ptr_array_add (arguments, "-nolisten");
                g_ptr_array_add (arguments, "tcp");
        }
#endif

        g_ptr_array_add (arguments, "-background");
        g_ptr_array_add (arguments, "none");

        g_ptr_array_add (arguments, "-noreset");
        g_ptr_array_add (arguments, "-keeptty");

        g_ptr_array_add (arguments, "-verbose");
        if (state->debug_enabled) {
                g_ptr_array_add (arguments, "7");
        } else {
                g_ptr_array_add (arguments, "3");
        }

        if (state->debug_enabled) {
                g_ptr_array_add (arguments, "-core");
        }
        g_ptr_array_add (arguments, NULL);

        subprocess = g_subprocess_launcher_spawnv (launcher,
                                                   (const char * const *) arguments->pdata,
                                                   &error);
        g_free (display_fd_string);
        g_clear_object (&launcher);
        g_ptr_array_free (arguments, TRUE);

        if (subprocess == NULL) {
                g_debug ("could not start X server: %s", error->message);
                goto out;
        }

        input_stream = g_unix_input_stream_new (pipe_fds[0], TRUE);
        data_stream = g_data_input_stream_new (input_stream);
        g_clear_object (&input_stream);

        display_number = g_data_input_stream_read_line (data_stream,
                                                        &display_number_size,
                                                        cancellable,
                                                        &error);

        if (error != NULL) {
                g_debug ("could not read display string from X server: %s", error->message);
                goto out;
        }

        if (display_number == NULL) {
                g_debug ("X server did not write display string");
                goto out;
        }

        state->display_name = g_strdup_printf (":%s", display_number);
        g_clear_pointer (&display_number, g_free);

        state->auth_file = g_strdup (auth_file);
        state->x_subprocess = g_object_ref (subprocess);

        g_subprocess_wait_async (state->x_subprocess,
                                 cancellable,
                                 (GAsyncReadyCallback)
                                 on_x_server_finished,
                                 state);

        is_running = TRUE;
out:
        g_clear_pointer (&auth_file, g_free);
        g_clear_object (&data_stream);
        g_clear_object (&subprocess);
        g_clear_object (&launcher);
        g_clear_error (&error);

        return is_running;
}
示例#2
0
static gboolean
spawn_bus (State        *state,
           GCancellable *cancellable)
{
        GPtrArray           *arguments = NULL;
        GSubprocessLauncher *launcher = NULL;
        GSubprocess         *subprocess = NULL;
        GInputStream        *input_stream = NULL;
        GDataInputStream    *data_stream = NULL;
        GError              *error = NULL;
        const char          *bus_env = NULL;
        char                *bus_address_fd_string;
        char                *bus_address = NULL;
        gsize                bus_address_size;

        gboolean  is_running = FALSE;
        int       ret;
        int       pipe_fds[2];

        g_debug ("Running session message bus");

        bus_env = g_getenv ("DBUS_SESSION_BUS_ADDRESS");
        if (bus_env != NULL) {
                g_debug ("session message bus already running, not starting another one");
                state->bus_address = g_strdup (bus_env);
                return TRUE;
        }

        ret = g_unix_open_pipe (pipe_fds, FD_CLOEXEC, &error);

        if (!ret) {
                g_debug ("could not open pipe: %s", error->message);
                goto out;
        }

        arguments = g_ptr_array_new ();
        launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE);

        g_subprocess_launcher_setenv (launcher, "DISPLAY", state->display_name, TRUE);
        g_subprocess_launcher_setenv (launcher, "XAUTHORITY", state->auth_file, TRUE);

        g_subprocess_launcher_take_fd (launcher, pipe_fds[1], BUS_ADDRESS_FILENO);

        bus_address_fd_string = g_strdup_printf ("%d", BUS_ADDRESS_FILENO);

        g_ptr_array_add (arguments, "dbus-daemon");

        g_ptr_array_add (arguments, "--print-address");
        g_ptr_array_add (arguments, bus_address_fd_string);
        g_ptr_array_add (arguments, "--session");
        g_ptr_array_add (arguments, NULL);

        subprocess = g_subprocess_launcher_spawnv (launcher,
                                                   (const char * const *) arguments->pdata,
                                                   &error);
        g_free (bus_address_fd_string);
        g_clear_object (&launcher);
        g_ptr_array_free (arguments, TRUE);

        if (subprocess == NULL) {
                g_debug ("could not start dbus-daemon: %s", error->message);
                goto out;
        }

        input_stream = g_unix_input_stream_new (pipe_fds[0], TRUE);
        data_stream = g_data_input_stream_new (input_stream);
        g_clear_object (&input_stream);

        bus_address = g_data_input_stream_read_line (data_stream,
                                                     &bus_address_size,
                                                     cancellable,
                                                     &error);

        if (error != NULL) {
                g_debug ("could not read address from session message bus: %s", error->message);
                goto out;
        }

        if (bus_address == NULL) {
                g_debug ("session message bus did not write address");
                goto out;
        }

        state->bus_address = bus_address;

        state->bus_subprocess = g_object_ref (subprocess);

        g_subprocess_wait_async (state->bus_subprocess,
                                 cancellable,
                                 (GAsyncReadyCallback)
                                 on_bus_finished,
                                 state);

        is_running = TRUE;
out:
        g_clear_object (&data_stream);
        g_clear_object (&subprocess);
        g_clear_object (&launcher);
        g_clear_error (&error);

        return is_running;
}
示例#3
0
gboolean
meta_xwayland_start (MetaXWaylandManager *manager,
                     struct wl_display   *wl_display)
{
  int xwayland_client_fd[2];
  int displayfd[2];
  gboolean started = FALSE;
  g_autoptr(GSubprocessLauncher) launcher = NULL;
  GSubprocessFlags flags;
  GSubprocess *proc;
  GError *error = NULL;

  if (!choose_xdisplay (manager))
    goto out;

  /* We want xwayland to be a wayland client so we make a socketpair to setup a
   * wayland protocol connection. */
  if (socketpair (AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, xwayland_client_fd) < 0)
    {
      g_warning ("xwayland_client_fd socketpair failed\n");
      goto out;
    }

  if (socketpair (AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, displayfd) < 0)
    {
      g_warning ("displayfd socketpair failed\n");
      goto out;
    }

  /* xwayland, please. */
  flags = G_SUBPROCESS_FLAGS_NONE;

  if (getenv ("XWAYLAND_STFU"))
    {
      flags |= G_SUBPROCESS_FLAGS_STDOUT_SILENCE;
      flags |= G_SUBPROCESS_FLAGS_STDERR_SILENCE;
    }

  launcher = g_subprocess_launcher_new (flags);

  g_subprocess_launcher_take_fd (launcher, xwayland_client_fd[1], 3);
  g_subprocess_launcher_take_fd (launcher, manager->abstract_fd, 4);
  g_subprocess_launcher_take_fd (launcher, manager->unix_fd, 5);
  g_subprocess_launcher_take_fd (launcher, displayfd[1], 6);

  g_subprocess_launcher_setenv (launcher, "WAYLAND_SOCKET", "3", TRUE);
  proc = g_subprocess_launcher_spawn (launcher, &error,
                                      XWAYLAND_PATH, manager->display_name,
                                      "-rootless", "-noreset",
                                      "-listen", "4",
                                      "-listen", "5",
                                      "-displayfd", "6",
                                      NULL);
  if (!proc)
    {
      g_error ("Failed to spawn Xwayland: %s", error->message);
      goto out;
    }

  g_subprocess_wait_async  (proc, NULL, xserver_died, NULL);
  g_unix_fd_add (displayfd[0], G_IO_IN, on_displayfd_ready, manager);
  manager->client = wl_client_create (wl_display, xwayland_client_fd[0]);

  /* We need to run a mainloop until we know xwayland has a binding
   * for our xserver interface at which point we can assume it's
   * ready to start accepting connections. */
  manager->init_loop = g_main_loop_new (NULL, FALSE);
  g_main_loop_run (manager->init_loop);

  started = TRUE;

out:
  if (!started)
    {
      unlink (manager->lock_file);
      g_clear_pointer (&manager->lock_file, g_free);
    }
  return started;
}