Overview of changes in lightdm 0.9.6
- *
+ * Add VNC server support
Overview of changes in lightdm 0.9.5
#enabled=false
#port=177
#key=
+
+#
+# VNC Server configuration
+#
+# enabled = True if VNC connections should be allowed
+# port = TCP/IP port to listen for connections on
+#
+[XDMCPServer]
+#enabled=false
+#port=5900
seat-xlocal.h \
seat-xremote.c \
seat-xremote.h \
+ seat-xvnc.c \
+ seat-xvnc.h \
session.c \
session.h \
user.c \
user.h \
+ vnc-server.c \
+ vnc-server.h \
vt.c \
vt.h \
xauthority.c \
xserver-local.h \
xserver-remote.c \
xserver-remote.h \
+ xserver-xvnc.c \
+ xserver-xvnc.h \
xserver.c \
xserver.h \
xsession.c \
#include "configuration.h"
#include "display-manager.h"
#include "xdmcp-server.h"
+#include "vnc-server.h"
#include "seat-xdmcp-session.h"
+#include "seat-xvnc.h"
#include "xserver.h"
#include "user.h"
#include "pam-session.h"
static DisplayManager *display_manager = NULL;
static XDMCPServer *xdmcp_server = NULL;
+static VNCServer *vnc_server = NULL;
static GDBusConnection *bus = NULL;
static guint bus_id;
static GDBusNodeInfo *seat_info;
return result;
}
+static void
+vnc_connection_cb (VNCServer *server, GSocket *connection)
+{
+ SeatXVNC *seat;
+
+ seat = seat_xvnc_new (connection);
+ set_seat_properties (SEAT (seat), NULL);
+ display_manager_add_seat (display_manager, SEAT (seat));
+ g_object_unref (seat);
+}
+
int
main (int argc, char **argv)
{
xdmcp_server_start (xdmcp_server);
}
+ /* Start the VNC server */
+ if (config_get_boolean (config_get_instance (), "VNCServer", "enabled"))
+ {
+ vnc_server = vnc_server_new ();
+ if (config_has_key (config_get_instance (), "VNCServer", "port"))
+ {
+ gint port;
+ port = config_get_integer (config_get_instance (), "VNCServer", "port");
+ if (port > 0)
+ vnc_server_set_port (vnc_server, port);
+ }
+ g_signal_connect (vnc_server, "new-connection", G_CALLBACK (vnc_connection_cb), NULL);
+
+ g_debug ("Starting VNC server on TCP/IP port %d", vnc_server_get_port (vnc_server));
+ vnc_server_start (vnc_server);
+ }
+
g_main_loop_run (loop);
return EXIT_SUCCESS;
#include "process.h"
enum {
+ RUN,
STARTED,
GOT_DATA,
GOT_SIGNAL,
/* Environment variables */
GHashTable *env;
+ /* Command to run */
+ gchar *command;
+
+ /* Working directory */
+ gchar *working_directory;
+
/* User to run as */
User *user;
/* Path of file to log to */
- gchar *log_file;
-
- /* Timeout waiting for process to quit */
- guint quit_timeout;
-
+ gchar *log_file;
+
/* Process ID */
GPid pid;
+
+ /* Timeout waiting for process to quit */
+ guint quit_timeout;
};
G_DEFINE_TYPE (Process, process, G_TYPE_OBJECT);
return g_object_new (PROCESS_TYPE, NULL);
}
+void
+process_set_command (Process *process, const gchar *command)
+{
+ g_return_if_fail (process != NULL);
+
+ g_free (process->priv->command);
+ process->priv->command = g_strdup (command);
+}
+
+const gchar *
+process_get_command (Process *process)
+{
+ g_return_val_if_fail (process != NULL, NULL);
+ return process->priv->command;
+}
+
void
process_set_log_file (Process *process, const gchar *log_file)
{
g_return_val_if_fail (process != NULL, NULL);
return process->priv->log_file;
}
-
+
+void
+process_set_working_directory (Process *process, const gchar *working_directory)
+{
+ g_return_if_fail (process != NULL);
+
+ g_free (process->priv->working_directory);
+ process->priv->working_directory = g_strdup (working_directory);
+}
+
+const gchar *
+process_get_working_directory (Process *process)
+{
+ g_return_val_if_fail (process != NULL, NULL);
+ return process->priv->working_directory;
+}
+
+void
+process_set_user (Process *process, User *user)
+{
+ g_return_if_fail (process != NULL);
+
+ if (process->priv->user)
+ g_object_unref (process->priv->user);
+ process->priv->user = g_object_ref (user);
+}
+
+User *
+process_get_user (Process *process)
+{
+ g_return_val_if_fail (process != NULL, NULL);
+ return process->priv->user;
+}
+
void
process_set_env (Process *process, const gchar *name, const gchar *value)
{
}
static void
-run_process (Process *process, char *const argv[])
+process_run (Process *process)
+{
+ gint argc;
+ gchar **argv;
+ GError *error = NULL;
+
+ if (!g_shell_parse_argv (process->priv->command, &argc, &argv, &error))
+ {
+ g_warning ("Error parsing command %s: %s", process->priv->command, error->message);
+ _exit (EXIT_FAILURE);
+ }
+
+ execv (argv[0], argv);
+
+ g_warning ("Error executing child process %s: %s", argv[0], g_strerror (errno));
+ _exit (EXIT_FAILURE);
+}
+
+static void
+run (Process *process)
{
GHashTableIter iter;
gpointer key, value;
- int fd;
/* FIXME: Close existing file descriptors */
- /* Make input non-blocking */
- fd = g_open ("/dev/null", O_RDONLY);
- dup2 (fd, STDIN_FILENO);
- close (fd);
-
/* Set environment */
clearenv ();
g_hash_table_iter_init (&iter, process->priv->env);
while (g_hash_table_iter_next (&iter, &key, &value))
g_setenv ((gchar *)key, (gchar *)value, TRUE);
- /* Set SIGUSR1 to ignore so the child process can indicate it when it is ready */
- // FIXME: Should be in the xserver only
- signal (SIGUSR1, SIG_IGN);
-
- /* Make this process its own session so */
+ /* Make this process its own session */
if (setsid () < 0)
g_warning ("Failed to make process a new session: %s", strerror (errno));
}
}
- execv (argv[0], argv);
-
- g_warning ("Error executing child process %s: %s", argv[0], g_strerror (errno));
- _exit (EXIT_FAILURE);
+ g_signal_emit (process, signals[RUN], 0);
}
gboolean
-process_start (Process *process,
- User *user,
- const gchar *working_dir,
- const gchar *command,
- GError **error)
+process_start (Process *process)
{
- gboolean result;
- gint argc;
- gchar **argv;
GString *string;
gpointer key, value;
GHashTableIter iter;
pid_t pid;
g_return_val_if_fail (process != NULL, FALSE);
+ g_return_val_if_fail (process->priv->command != NULL, FALSE);
g_return_val_if_fail (process->priv->pid == 0, FALSE);
- process->priv->user = g_object_ref (user);
-
/* Create the log file owned by the target user */
if (process->priv->log_file)
{
g_warning ("Failed to set process log file ownership: %s", strerror (errno));
}
- result = g_shell_parse_argv (command, &argc, &argv, error);
- if (!result)
- return FALSE;
-
pid = fork ();
if (pid < 0)
{
}
if (pid == 0)
- run_process (process, argv);
- g_strfreev (argv);
+ run (process);
string = g_string_new ("");
g_hash_table_iter_init (&iter, process->priv->env);
while (g_hash_table_iter_next (&iter, &key, &value))
g_string_append_printf (string, "%s=%s ", (gchar *)key, (gchar *)value);
- g_string_append (string, command);
+ g_string_append (string, process->priv->command);
g_debug ("Launching process %d: %s", pid, string->str);
g_string_free (string, TRUE);
self = PROCESS (object);
- if (self->priv->user)
- g_object_unref (self->priv->user);
-
if (self->priv->pid > 0)
g_hash_table_remove (processes, GINT_TO_POINTER (self->priv->pid));
+ g_free (self->priv->command);
+ g_free (self->priv->working_directory);
+ g_free (self->priv->log_file);
+ if (self->priv->user)
+ g_object_unref (self->priv->user);
+
if (self->priv->pid)
kill (self->priv->pid, SIGTERM);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
struct sigaction action;
+ klass->run = process_run;
klass->stopped = process_stopped;
object_class->finalize = process_finalize;
g_type_class_add_private (klass, sizeof (ProcessPrivate));
+ signals[RUN] =
+ g_signal_new ("run",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (ProcessClass, run),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
signals[STARTED] =
g_signal_new ("started",
G_TYPE_FROM_CLASS (klass),
typedef struct
{
GObjectClass parent_class;
+ void (*run)(Process *process);
void (*started)(Process *process);
void (*got_data)(Process *process);
void (*got_signal)(Process *process, int signum);
Process *process_new (void);
+void process_set_command (Process *process, const gchar *command);
+
+const gchar *process_get_command (Process *process);
+
void process_set_log_file (Process *process, const gchar *log_file);
const gchar *process_get_log_file (Process *process);
+void process_set_working_directory (Process *process, const gchar *working_directory);
+
+const gchar *process_get_working_directory (Process *process);
+
+void process_set_user (Process *process, User *user);
+
+User *process_get_user (Process *process);
+
void process_set_env (Process *process, const gchar *name, const gchar *value);
const gchar *process_get_env (Process *process, const gchar *name);
-gboolean process_start (Process *process,
- User *user,
- const gchar *working_dir,
- const gchar *command,
- GError **error);
+gboolean process_start (Process *process);
gboolean process_get_is_running (Process *process);
void process_signal (Process *process, int signum);
+// FIXME: Move out of here
GIOChannel *process_get_to_child_channel (Process *process);
+// FIXME: Move out of here
GIOChannel *process_get_from_child_channel (Process *process);
void process_stop (Process *process);
--- /dev/null
+/*
+ * Copyright (C) 2010-2011 Robert Ancell.
+ * Author: Robert Ancell <robert.ancell@canonical.com>
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
+ * license.
+ */
+
+#include "seat-xvnc.h"
+#include "xdisplay.h"
+#include "xserver-xvnc.h"
+
+G_DEFINE_TYPE (SeatXVNC, seat_xvnc, SEAT_TYPE);
+
+struct SeatXVNCPrivate
+{
+ /* Remote display */
+ XDisplay *display;
+
+ /* VNC connection */
+ GSocket *connection;
+};
+
+SeatXVNC *seat_xvnc_new (GSocket *connection)
+{
+ SeatXVNC *seat;
+
+ seat = g_object_new (SEAT_XVNC_TYPE, NULL);
+ seat->priv->connection = g_object_ref (connection);
+
+ return seat;
+}
+
+static Display *
+seat_xvnc_add_display (Seat *seat)
+{
+ XServerXVNC *xserver;
+
+ xserver = xserver_xvnc_new ();
+ xserver_xvnc_set_stdin (xserver, g_socket_get_fd (SEAT_XVNC (seat)->priv->connection));
+
+ SEAT_XVNC (seat)->priv->display = xdisplay_new (XSERVER (xserver));
+ g_object_unref (xserver);
+
+ return DISPLAY (SEAT_XVNC (seat)->priv->display);
+}
+
+static void
+seat_xvnc_display_removed (Seat *seat, Display *display)
+{
+ seat_stop (seat);
+}
+
+static void
+seat_xvnc_init (SeatXVNC *seat)
+{
+ seat->priv = G_TYPE_INSTANCE_GET_PRIVATE (seat, SEAT_XVNC_TYPE, SeatXVNCPrivate);
+}
+
+static void
+seat_xdmcp_session_finalize (GObject *object)
+{
+ SeatXVNC *self;
+
+ self = SEAT_XVNC (object);
+
+ if (self->priv->display)
+ g_object_unref (self->priv->display);
+ g_object_unref (self->priv->connection);
+
+ G_OBJECT_CLASS (seat_xvnc_parent_class)->finalize (object);
+}
+
+static void
+seat_xvnc_class_init (SeatXVNCClass *klass)
+{
+ SeatClass *seat_class = SEAT_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ seat_class->add_display = seat_xvnc_add_display;
+ seat_class->display_removed = seat_xvnc_display_removed;
+ object_class->finalize = seat_xdmcp_session_finalize;
+
+ g_type_class_add_private (klass, sizeof (SeatXVNCPrivate));
+}
--- /dev/null
+/*
+ * Copyright (C) 2010-2011 Robert Ancell.
+ * Author: Robert Ancell <robert.ancell@canonical.com>
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
+ * license.
+ */
+
+#ifndef _SEAT_xvnc_H_
+#define _SEAT_xvnc_H_
+
+#include <glib-object.h>
+#include "seat.h"
+
+G_BEGIN_DECLS
+
+#define SEAT_XVNC_TYPE (seat_xvnc_get_type())
+#define SEAT_XVNC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAT_XVNC_TYPE, SeatXVNC))
+
+typedef struct SeatXVNCPrivate SeatXVNCPrivate;
+
+typedef struct
+{
+ Seat parent_instance;
+ SeatXVNCPrivate *priv;
+} SeatXVNC;
+
+typedef struct
+{
+ SeatClass parent_class;
+} SeatXVNCClass;
+
+GType seat_xvnc_get_type (void);
+
+SeatXVNC *seat_xvnc_new (GSocket *connection);
+
+G_END_DECLS
+
+#endif /* _SEAT_xvnc_H_ */
User *user;
gboolean result;
gchar *absolute_command;
- GError *error = NULL;
absolute_command = get_absolute_command (session->priv->command);
if (!absolute_command)
g_debug ("Can't launch session %s, not found in path", session->priv->command);
return FALSE;
}
+ process_set_command (PROCESS (session), absolute_command);
+ g_free (absolute_command);
user = pam_session_get_user (session->priv->authentication);
- result = process_start (PROCESS (session),
- user,
- user_get_home_directory (user),
- absolute_command,
- &error);
- if (error)
- g_warning ("Failed to spawn session: %s", error->message);
- g_clear_error (&error);
- g_free (absolute_command);
+ process_set_user (PROCESS (session), user);
+ process_set_working_directory (PROCESS (session), user_get_home_directory (user));
+ result = process_start (PROCESS (session));
return result;
}
SESSION_GET_CLASS (session)->stop (session);
}
+static void
+session_run (Process *process)
+{
+ int fd;
+
+ /* Make input non-blocking */
+ fd = g_open ("/dev/null", O_RDONLY);
+ dup2 (fd, STDIN_FILENO);
+ close (fd);
+}
+
static void
session_stopped (Process *process)
{
klass->start = session_real_start;
klass->stop = session_real_stop;
+ process_class->run = session_run;
process_class->stopped = session_stopped;
object_class->finalize = session_finalize;
--- /dev/null
+/*
+ * Copyright (C) 2010-2011 Robert Ancell.
+ * Author: Robert Ancell <robert.ancell@canonical.com>
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
+ * license.
+ */
+
+#include <gio/gio.h>
+
+#include "vnc-server.h"
+
+enum {
+ NEW_CONNECTION,
+ LAST_SIGNAL
+};
+static guint signals[LAST_SIGNAL] = { 0 };
+
+struct VNCServerPrivate
+{
+ /* Port to listen on */
+ guint port;
+
+ /* Listening sockets */
+ GSocket *socket, *socket6;
+};
+
+G_DEFINE_TYPE (VNCServer, vnc_server, G_TYPE_OBJECT);
+
+VNCServer *
+vnc_server_new (void)
+{
+ return g_object_new (VNC_SERVER_TYPE, NULL);
+}
+
+void
+vnc_server_set_port (VNCServer *server, guint port)
+{
+ g_return_if_fail (server != NULL);
+ server->priv->port = port;
+}
+
+guint
+vnc_server_get_port (VNCServer *server)
+{
+ g_return_val_if_fail (server != NULL, 0);
+ return server->priv->port;
+}
+
+static gboolean
+read_cb (GSocket *socket, GIOCondition condition, VNCServer *server)
+{
+ GError *error = NULL;
+ GSocket *client_socket;
+
+ client_socket = g_socket_accept (socket, NULL, &error);
+ if (error)
+ g_warning ("Failed to get connection from from VNC socket: %s", error->message);
+ g_clear_error (&error);
+
+ if (client_socket)
+ {
+ GInetSocketAddress *address;
+ gchar *hostname;
+
+ address = G_INET_SOCKET_ADDRESS (g_socket_get_remote_address (client_socket, NULL));
+ hostname = g_inet_address_to_string (g_inet_socket_address_get_address (address));
+ g_debug ("Got VNC connection from %s:%d", hostname, g_inet_socket_address_get_port (address));
+ g_free (hostname);
+
+ g_signal_emit (server, signals[NEW_CONNECTION], 0, client_socket);
+ }
+
+ return TRUE;
+}
+
+static GSocket *
+open_tcp_socket (GSocketFamily family, guint port, GError **error)
+{
+ GSocket *socket;
+ GSocketAddress *address;
+
+ socket = g_socket_new (family, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_TCP, error);
+ if (!socket)
+ return NULL;
+
+ address = g_inet_socket_address_new (g_inet_address_new_any (family), port);
+ if (!g_socket_bind (socket, address, TRUE, error) ||
+ !g_socket_listen (socket, error))
+ {
+ g_object_unref (socket);
+ return NULL;
+ }
+
+ return socket;
+}
+
+gboolean
+vnc_server_start (VNCServer *server)
+{
+ GSource *source;
+ GError *error = NULL;
+
+ g_return_val_if_fail (server != NULL, FALSE);
+
+ server->priv->socket = open_tcp_socket (G_SOCKET_FAMILY_IPV4, server->priv->port, &error);
+ if (error)
+ g_warning ("Failed to create IPv4 VNC socket: %s", error->message);
+ g_clear_error (&error);
+
+ if (server->priv->socket)
+ {
+ source = g_socket_create_source (server->priv->socket, G_IO_IN, NULL);
+ g_source_set_callback (source, (GSourceFunc) read_cb, server, NULL);
+ g_source_attach (source, NULL);
+ }
+
+ server->priv->socket6 = open_tcp_socket (G_SOCKET_FAMILY_IPV6, server->priv->port, &error);
+ if (error)
+ g_warning ("Failed to create IPv6 VNC socket: %s", error->message);
+ g_clear_error (&error);
+
+ if (server->priv->socket6)
+ {
+ source = g_socket_create_source (server->priv->socket6, G_IO_IN, NULL);
+ g_source_set_callback (source, (GSourceFunc) read_cb, server, NULL);
+ g_source_attach (source, NULL);
+ }
+
+ if (!server->priv->socket && !server->priv->socket6)
+ return FALSE;
+
+ return TRUE;
+}
+
+static void
+vnc_server_init (VNCServer *server)
+{
+ server->priv = G_TYPE_INSTANCE_GET_PRIVATE (server, VNC_SERVER_TYPE, VNCServerPrivate);
+ server->priv->port = 5900;
+}
+
+static void
+vnc_server_finalize (GObject *object)
+{
+ VNCServer *self;
+
+ self = VNC_SERVER (object);
+
+ if (self->priv->socket)
+ g_object_unref (self->priv->socket);
+ if (self->priv->socket6)
+ g_object_unref (self->priv->socket6);
+
+ G_OBJECT_CLASS (vnc_server_parent_class)->finalize (object);
+}
+
+static void
+vnc_server_class_init (VNCServerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = vnc_server_finalize;
+
+ g_type_class_add_private (klass, sizeof (VNCServerPrivate));
+
+ signals[NEW_CONNECTION] =
+ g_signal_new ("new-connection",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (VNCServerClass, new_connection),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, G_TYPE_SOCKET);
+}
--- /dev/null
+/*
+ * Copyright (C) 2010-2011 Robert Ancell.
+ * Author: Robert Ancell <robert.ancell@canonical.com>
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
+ * license.
+ */
+
+#ifndef _VNC_SERVER_H_
+#define _VNC_SERVER_H_
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define VNC_SERVER_TYPE (vnc_server_get_type())
+#define VNC_SERVER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), VNC_SERVER_TYPE, VNCServer));
+
+typedef struct VNCServerPrivate VNCServerPrivate;
+
+typedef struct
+{
+ GObject parent_instance;
+ VNCServerPrivate *priv;
+} VNCServer;
+
+typedef struct
+{
+ GObjectClass parent_class;
+
+ gboolean (*new_connection)(VNCServer *server, GSocket *socket);
+} VNCServerClass;
+
+GType vnc_server_get_type (void);
+
+VNCServer *vnc_server_new (void);
+
+void vnc_server_set_port (VNCServer *server, guint port);
+
+guint vnc_server_get_port (VNCServer *server);
+
+gboolean vnc_server_start (VNCServer *server);
+
+G_END_DECLS
+
+#endif /* _VNC_SERVER_H_ */
/* X server process */
Process *xserver_process;
- /* Path of file to log to */
- gchar *log_file;
-
/* Command to run the X server */
gchar *command;
G_DEFINE_TYPE (XServerLocal, xserver_local, XSERVER_TYPE);
-static GList *display_numbers = NULL;
-
-static gboolean
-display_number_used (guint number)
-{
- gchar *path;
- gboolean result;
-
- if (g_list_find (display_numbers, GINT_TO_POINTER (number)))
- return TRUE;
-
- path = g_strdup_printf ("/tmp/.X%d-lock", number);
- result = g_file_test (path, G_FILE_TEST_EXISTS);
- g_free (path);
-
- return result;
-}
-
static guint
get_free_display_number (void)
{
guint number;
number = config_get_integer (config_get_instance (), "LightDM", "minimum-display-number");
- while (display_number_used (number))
- number++;
+ while (TRUE)
+ {
+ gchar *path;
+ gboolean result;
+
+ path = g_strdup_printf ("/tmp/.X%d-lock", number);
+ result = g_file_test (path, G_FILE_TEST_EXISTS);
+ g_free (path);
- display_numbers = g_list_append (display_numbers, GINT_TO_POINTER (number));
+ if (!result)
+ break;
+ number++;
+ }
+
return number;
}
-static void
-release_display_number (guint number)
-{
- display_numbers = g_list_remove (display_numbers, GINT_TO_POINTER (number));
-}
-
XServerLocal *
xserver_local_new (void)
{
return absolute_command;
}
+static void
+run_cb (Process *process, XServerLocal *server)
+{
+ int fd;
+
+ /* Make input non-blocking */
+ fd = open ("/dev/null", O_RDONLY);
+ dup2 (fd, STDIN_FILENO);
+ close (fd);
+
+ /* Set SIGUSR1 to ignore so the X server can indicate it when it is ready */
+ signal (SIGUSR1, SIG_IGN);
+}
+
static void
got_signal_cb (Process *process, int signum, XServerLocal *server)
{
}
}
-static void
-exit_cb (Process *process, int status, XServerLocal *server)
-{
- if (status != 0)
- g_debug ("X server exited with value %d", status);
-}
-
-static void
-terminated_cb (Process *process, int signum, XServerLocal *server)
-{
- g_debug ("X server terminated with signal %d", signum);
-}
-
static void
stopped_cb (Process *process, XServerLocal *server)
{
server->priv->authority_file = NULL;
}
- release_display_number (xserver_get_display_number (XSERVER (server)));
-
if (server->priv->vt >= 0)
{
vt_unref (server->priv->vt);
gchar *filename, *dir, *path, *absolute_command;
gchar hostname[1024], *number;
GString *command;
- GError *error = NULL;
g_return_val_if_fail (server->priv->xserver_process == NULL, FALSE);
g_return_val_if_fail (server->priv->command != NULL, FALSE);
server->priv->xserver_process = process_new ();
+ g_signal_connect (server->priv->xserver_process, "run", G_CALLBACK (run_cb), server);
g_signal_connect (server->priv->xserver_process, "got-signal", G_CALLBACK (got_signal_cb), server);
- g_signal_connect (server->priv->xserver_process, "exited", G_CALLBACK (exit_cb), server);
- g_signal_connect (server->priv->xserver_process, "terminated", G_CALLBACK (terminated_cb), server);
g_signal_connect (server->priv->xserver_process, "stopped", G_CALLBACK (stopped_cb), server);
/* Setup logging */
if (server->priv->replacing_plymouth)
g_string_append (command, " -background none");
+ process_set_command (server->priv->xserver_process, command->str);
+ g_string_free (command, TRUE);
g_debug ("Launching X Server");
process_set_env (server->priv->xserver_process, "LD_LIBRARY_PATH", g_getenv ("LD_LIBRARY_PATH"));
}
- result = process_start (server->priv->xserver_process,
- user_get_current (),
- NULL,
- command->str,
- &error);
- if (error)
- g_warning ("Unable to create display: %s", error->message);
- g_clear_error (&error);
- g_string_free (command, TRUE);
+ process_set_user (server->priv->xserver_process, user_get_current ());
+ result = process_start (server->priv->xserver_process);
if (result)
g_debug ("Waiting for ready signal from X server :%d", xserver_get_display_number (XSERVER (server)));