# xserver-layout = Layout to pass to X server
# xserver-config = Config file to pass to X server
# xserver-allow-tcp = True if TCP/IP connections are allowed to this X server
+# xserver-share = True if the X server is shared for both greeter and session
# xdmcp-manager = XDMCP manager to connect to (implies xserver-allow-tcp=true)
# xdmcp-port = XDMCP UDP/IP port to communicate on
# xdmcp-key = Authentication key to use for XDM-AUTHENTICATION-1 (stored in keys.conf)
#xserver-layout=
#xserver-config=
#xserver-allow-tcp=false
+#xserver-share=true
#xdmcp-manager=
#xdmcp-port=177
#xdmcp-key=
DISPLAY_SERVER_READY,
START_GREETER,
START_SESSION,
+ CREATE_DISPLAY,
STOPPED,
LAST_SIGNAL
};
/* Display server */
DisplayServer *display_server;
+ /* TRUE if the session can run on the same display server as the greeter */
+ gboolean share_display_server;
+
/* Greeter session */
gchar *greeter_session;
return display->priv->display_server;
}
+void
+display_set_share_display_server (Display *display, gboolean share_display_server)
+{
+ g_return_if_fail (display != NULL);
+ display->priv->share_display_server = share_display_server;
+}
+
const gchar *
display_get_username (Display *display)
{
g_signal_emit (display, signals[CREATE_SESSION], 0, &session);
if (!session)
return NULL;
+ session_set_display_server (session, display->priv->display_server);
/* Connect using the session bus */
if (getuid () != 0)
return create_session (display);
}
+static Display *
+create_display (Display *display, Session *session)
+{
+ Display *d;
+
+ g_signal_emit (display, signals[CREATE_DISPLAY], 0, session, &d);
+
+ return d;
+}
+
static gboolean
greeter_start_session_cb (Greeter *greeter, SessionType type, const gchar *session_name, Display *display)
{
return TRUE;
}
- /* Stop the greeter, the session will start when the greeter has quit */
- g_debug ("Stopping greeter");
- session_stop (display->priv->session);
+ /* If we can re-use this display server, then stop the greeter and start the session when it is done */
+ if (display->priv->share_display_server)
+ {
+ g_debug ("Stopping greeter");
+ session_stop (display->priv->session);
+ }
+ else
+ create_display (display, greeter_get_authentication_session (greeter));
return TRUE;
}
return;
}
+ /* If already have a session, run it */
+ if (display->priv->session != NULL)
+ {
+ if (display_start_session (display))
+ display_stop (display);
+ return;
+ }
+
/* Don't run any sessions on local terminals */
if (!display_server_get_start_local_sessions (display_server))
return;
return TRUE;
}
+gboolean
+display_start_with_session (Display *display, Session *session)
+{
+ g_return_val_if_fail (display != NULL, FALSE);
+ g_return_val_if_fail (session != NULL, FALSE);
+
+ display->priv->session = g_object_ref (session);
+ g_signal_connect_after (display->priv->session, "stopped", G_CALLBACK (user_session_stopped_cb), display);
+ session_set_display_server (session, display->priv->display_server);
+
+ return display_start (display);
+}
+
gboolean
display_get_is_ready (Display *display)
{
return NULL;
}
+static Display *
+display_real_create_display (Display *display, Session *session)
+{
+ return NULL;
+}
+
static void
display_init (Display *display)
{
klass->get_guest_username = display_real_get_guest_username;
klass->start_greeter = display_start_greeter;
klass->start_session = display_start_session;
+ klass->create_display = display_real_create_display;
object_class->finalize = display_finalize;
g_type_class_add_private (klass, sizeof (DisplayPrivate));
g_signal_accumulator_true_handled, NULL,
ldm_marshal_BOOLEAN__VOID,
G_TYPE_BOOLEAN, 0);
+ signals[CREATE_DISPLAY] =
+ g_signal_new ("create-display",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (DisplayClass, create_display),
+ NULL, NULL,
+ ldm_marshal_OBJECT__OBJECT,
+ DISPLAY_TYPE, 1, SESSION_TYPE);
signals[STOPPED] =
g_signal_new ("stopped",
G_TYPE_FROM_CLASS (klass),
void (*ready)(Display *display);
gboolean (*switch_to_user)(Display *display, User *user);
gboolean (*switch_to_guest)(Display *display);
+ Display *(*create_display)(Display *display, Session *session);
gchar *(*get_guest_username)(Display *display);
void (*stopped)(Display *display);
} DisplayClass;
DisplayServer *display_get_display_server (Display *display);
+void display_set_share_display_server (Display *display, gboolean share_display_server);
+
const gchar *display_get_username (Display *display);
Session *display_get_session (Display *display);
gboolean display_start (Display *display);
+gboolean display_start_with_session (Display *display, Session *session);
+
gboolean display_get_is_ready (Display *display);
void display_lock (Display *display);
STRING:VOID
OBJECT:VOID
OBJECT:STRING
+OBJECT:OBJECT
config_set_string (config_get_instance (), "SeatDefaults", "type", "xlocal");
if (!config_has_key (config_get_instance (), "SeatDefaults", "xserver-command"))
config_set_string (config_get_instance (), "SeatDefaults", "xserver-command", "X");
+ if (!config_has_key (config_get_instance (), "SeatDefaults", "xserver-share"))
+ config_set_boolean (config_get_instance (), "SeatDefaults", "xserver-share", TRUE);
if (!config_has_key (config_get_instance (), "SeatDefaults", "unity-compositor-command"))
config_set_string (config_get_instance (), "SeatDefaults", "unity-compositor-command", "unity-system-compositor");
if (!config_has_key (config_get_instance (), "SeatDefaults", "start-session"))
else
vt_number = SEAT_UNITY (seat)->priv->vt;
- session = xsession_new (XSERVER (xserver));
+ session = xsession_new ();
t = g_strdup_printf ("/dev/tty%d", vt_number);
session_set_tty (SESSION (session), t);
g_free (t);
xserver = XSERVER_REMOTE (display_get_display_server (display));
- session = xsession_new (XSERVER (xserver));
+ session = xsession_new ();
session_set_remote_host_name (SESSION (session), xserver_get_hostname (XSERVER (xserver)));
return SESSION (session);
seat_xlocal_setup (Seat *seat)
{
seat_set_can_switch (seat, TRUE);
+ seat_set_share_display_server (seat, seat_get_boolean_property (seat, "xserver-share"));
SEAT_CLASS (seat_xlocal_parent_class)->setup (seat);
}
xserver = XSERVER_LOCAL (display_get_display_server (display));
- session = xsession_new (XSERVER (xserver));
+ session = xsession_new ();
t = g_strdup_printf ("/dev/tty%d", xserver_local_get_vt (xserver));
session_set_tty (SESSION (session), t);
g_free (t);
xserver = XSERVER_REMOTE (display_get_display_server (display));
- session = xsession_new (XSERVER (xserver));
+ session = xsession_new ();
session_set_remote_host_name (SESSION (session), xserver_get_hostname (XSERVER (xserver)));
return SESSION (session);
xserver = XSERVER_XVNC (display_get_display_server (display));
- session = xsession_new (XSERVER (xserver));
+ session = xsession_new ();
address = G_INET_SOCKET_ADDRESS (g_socket_get_remote_address (SEAT_XVNC (seat)->priv->connection, NULL));
hostname = g_inet_address_to_string (g_inet_socket_address_get_address (address));
session_set_remote_host_name (SESSION (session), hostname);
/* TRUE if able to switch users */
gboolean can_switch;
+ /* TRUE if display server can be shared for sessions */
+ gboolean share_display_server;
+
/* Name of guest account */
gchar *guest_username;
} SeatModule;
static GHashTable *seat_modules = NULL;
+static Display *create_display (Seat *seat);
+
void
seat_register_module (const gchar *name, GType type)
{
seat->priv->can_switch = can_switch;
}
+void
+seat_set_share_display_server (Seat *seat, gboolean share_display_server)
+{
+ g_return_if_fail (seat != NULL);
+
+ seat->priv->share_display_server = share_display_server;
+}
+
gboolean
seat_start (Seat *seat)
{
SEAT_GET_CLASS (seat)->set_active_display (seat, display);
}
+static Display *
+display_create_display_cb (Display *display, Session *session, Seat *seat)
+{
+ Display *d;
+
+ d = create_display (seat);
+ g_signal_connect (d, "ready", G_CALLBACK (display_ready_cb), seat);
+ g_signal_emit (seat, signals[DISPLAY_ADDED], 0, d);
+
+ display_start_with_session (d, session);
+
+ return g_object_ref (d);
+}
+
static void
check_stopped (Seat *seat)
{
g_signal_connect (display, "start-greeter", G_CALLBACK (display_start_greeter_cb), seat);
g_signal_connect (display, "start-session", G_CALLBACK (display_start_session_cb), seat);
g_signal_connect_after (display, "start-session", G_CALLBACK (display_session_started_cb), seat);
+ g_signal_connect (display, "create-display", G_CALLBACK (display_create_display_cb), seat);
g_signal_connect (display, "stopped", G_CALLBACK (display_stopped_cb), seat);
display_set_greeter_session (display, seat_get_string_property (seat, "greeter-session"));
display_set_session_wrapper (display, seat_get_string_property (seat, "session-wrapper"));
display_set_allow_guest (display, seat_get_allow_guest (seat));
display_set_greeter_allow_guest (display, seat_get_greeter_allow_guest (seat));
display_set_user_session (display, SESSION_TYPE_LOCAL, seat_get_string_property (seat, "user-session"));
+ display_set_share_display_server (display, seat->priv->share_display_server);
seat->priv->displays = g_list_append (seat->priv->displays, display);
{
seat->priv = G_TYPE_INSTANCE_GET_PRIVATE (seat, SEAT_TYPE, SeatPrivate);
seat->priv->properties = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+ seat->priv->share_display_server = TRUE;
}
static void
void seat_set_can_switch (Seat *seat, gboolean can_switch);
+void seat_set_share_display_server (Seat *seat, gboolean share_display_server);
+
gboolean seat_start (Seat *seat);
GList *seat_get_displays (Seat *seat);
struct SessionPrivate
{
+ /* Display server running on */
+ DisplayServer *display_server;
+
/* PID of child process */
GPid pid;
session->priv->class = g_strdup (class);
}
+static void
+session_real_set_display_server (Session *session, DisplayServer *display_server)
+{
+ if (session->priv->display_server)
+ g_object_unref (session->priv->display_server);
+ session->priv->display_server = g_object_ref (display_server);
+}
+
+void
+session_set_display_server (Session *session, DisplayServer *display_server)
+{
+ g_return_if_fail (session != NULL);
+ g_return_if_fail (display_server != NULL);
+ SESSION_GET_CLASS (session)->set_display_server (session, display_server);
+}
+
void
session_set_tty (Session *session, const gchar *tty)
{
Session *self = SESSION (object);
int i;
+ if (self->priv->display_server)
+ g_object_unref (self->priv->display_server);
if (self->priv->pid)
kill (self->priv->pid, SIGKILL);
if (self->priv->from_child_channel)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ klass->set_display_server = session_real_set_display_server;
object_class->finalize = session_finalize;
g_type_class_add_private (klass, sizeof (SessionPrivate));
#include <security/pam_appl.h>
+#include "display-server.h"
#include "accounts.h"
#include "xauthority.h"
void (*got_messages)(Session *session);
void (*authentication_complete)(Session *session);
void (*stopped)(Session *session);
+ void (*set_display_server)(Session *session, DisplayServer *display_server);
} SessionClass;
typedef enum
void session_set_class (Session *session, const gchar *class);
+void session_set_display_server (Session *session, DisplayServer *display_server);
+
void session_set_tty (Session *session, const gchar *tty);
void session_set_xdisplay (Session *session, const gchar *xdisplay);
G_DEFINE_TYPE (XSession, xsession, SESSION_TYPE);
XSession *
-xsession_new (XServer *xserver)
+xsession_new (void)
{
XSession *session;
- XAuthority *authority;
session = g_object_new (XSESSION_TYPE, NULL);
- session->priv->xserver = g_object_ref (xserver);
-
- session_set_env (SESSION (session), "DISPLAY", xserver_get_address (xserver));
- session_set_tty (SESSION (session), xserver_get_address (xserver));
- session_set_xdisplay (SESSION (session), xserver_get_address (xserver));
- authority = xserver_get_authority (xserver);
- if (authority)
- session_set_xauthority (SESSION (session), authority, config_get_boolean (config_get_instance (), "LightDM", "user-authority-in-system-dir"));
session_set_log_file (SESSION (session), ".xsession-errors");
-
+
return session;
}
static void
-xsession_init (XSession *session)
+xsession_set_display_server (Session *session, DisplayServer *display_server)
{
- session->priv = G_TYPE_INSTANCE_GET_PRIVATE (session, XSESSION_TYPE, XSessionPrivate);
-}
+ XServer *xserver;
+ XAuthority *authority;
-static void
-xsession_finalize (GObject *object)
-{
- XSession *self;
+ xserver = XSERVER (display_server);
- self = XSESSION (object);
+ session_set_env (session, "DISPLAY", xserver_get_address (xserver));
+ session_set_tty (session, xserver_get_address (xserver)); // FIXME: This is applied before authentication, it needs to be resent before the process it run
+ session_set_xdisplay (session, xserver_get_address (xserver)); // FIXME: This is applied before authentication, it needs to be resent before the process it run
+ authority = xserver_get_authority (xserver); // FIXME: This is applied before authentication, it needs to be resent before the process it run
+ if (authority)
+ session_set_xauthority (session, authority, config_get_boolean (config_get_instance (), "LightDM", "user-authority-in-system-dir"));
- if (self->priv->xserver)
- g_object_unref (self->priv->xserver);
+ SESSION_CLASS (xsession_parent_class)->set_display_server (session, display_server);
+}
- G_OBJECT_CLASS (xsession_parent_class)->finalize (object);
+static void
+xsession_init (XSession *session)
+{
+ session->priv = G_TYPE_INSTANCE_GET_PRIVATE (session, XSESSION_TYPE, XSessionPrivate);
}
static void
xsession_class_init (XSessionClass *klass)
{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ SessionClass *session_class = SESSION_CLASS (klass);
- object_class->finalize = xsession_finalize;
+ session_class->set_display_server = xsession_set_display_server;
g_type_class_add_private (klass, sizeof (XSessionPrivate));
}
GType xsession_get_type (void);
-XSession *xsession_new (XServer *xserver);
+XSession *xsession_new (void);
G_END_DECLS
test-login-python-remote-session \
test-login-session-crash \
test-login-xserver-crash \
+ test-xserver-no-share \
test-home-dir-on-authenticate \
test-home-dir-on-session \
test-plymouth-active-vt \
scripts/xauthority.conf \
scripts/xdmcp-login.conf \
scripts/xdmcp-open-file-descriptors.conf \
- scripts/xserver-fail-start.conf
+ scripts/xserver-fail-start.conf \
+ scripts/xserver-no-share.conf
--- /dev/null
+#
+# Check can configure a new X server to start for the session
+#
+
+[SeatDefaults]
+user-session=default
+xserver-share=false
+
+#?RUNNER DAEMON-START
+
+# X server starts
+#?XSERVER-0 START VT=7
+#?XSERVER-0 INDICATE-READY
+#?XSERVER-0 ACCEPT-CONNECT
+
+# Greeter starts
+#?GREETER-X-0 START
+#?XSERVER-0 ACCEPT-CONNECT
+#?GREETER-X-0 CONNECT-XSERVER
+#?GREETER-X-0 CONNECT-TO-DAEMON
+#?GREETER-X-0 CONNECTED-TO-DAEMON
+
+# Log into account with a password
+#?*GREETER-X-0 AUTHENTICATE USERNAME=have-password1
+#?GREETER-X-0 SHOW-PROMPT TEXT="Password:"
+#?*GREETER-X-0 RESPOND TEXT="password"
+#?GREETER-X-0 AUTHENTICATION-COMPLETE USERNAME=have-password1 AUTHENTICATED=TRUE
+#?*GREETER-X-0 START-SESSION
+
+# New X server starts for session
+#?XSERVER-1 START VT=8
+#?XSERVER-1 INDICATE-READY
+#?XSERVER-1 ACCEPT-CONNECT
+
+# Session starts
+#?SESSION-X-1 START USER=have-password1
+#?XSERVER-1 ACCEPT-CONNECT
+#?SESSION-X-1 CONNECT-XSERVER
+
+# Greeter stops
+#?GREETER-X-0 TERMINATE SIGNAL=15
+#?XSERVER-0 TERMINATE SIGNAL=15
+
+# Cleanup
+#?*STOP-DAEMON
+#?SESSION-X-1 TERMINATE SIGNAL=15
+#?XSERVER-1 TERMINATE SIGNAL=15
+#?RUNNER DAEMON-EXIT STATUS=0
--- /dev/null
+#!/bin/sh
+./src/dbus-env ./src/test-runner xserver-no-share test-gobject-greeter