summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRobert Ancell <robert.ancell@canonical.com>2015-08-05 15:32:06 +1200
committerRobert Ancell <robert.ancell@canonical.com>2015-08-05 15:32:06 +1200
commit8e5f15c3917230d95c1d58a69a526ce2de1228b2 (patch)
tree1d8071dfcf5cf089b3670f20ae9d36f62618a3b1 /src
parent51d955565e4731f85be23fb5203cb2ceac8099bc (diff)
parent645e6a0d231f2b3616ee8330b342d3efbf2c5264 (diff)
downloadlightdm-8e5f15c3917230d95c1d58a69a526ce2de1228b2.tar.gz
Merge with trunk
Diffstat (limited to 'src')
-rw-r--r--src/greeter.c27
-rw-r--r--src/lightdm.c173
-rw-r--r--src/login1.c17
-rw-r--r--src/login1.h2
-rw-r--r--src/seat-unity.c8
-rw-r--r--src/seat-xremote.c2
-rw-r--r--src/seat.c56
-rw-r--r--src/seat.h6
-rw-r--r--src/session-child.c10
-rw-r--r--src/session.c11
-rw-r--r--src/session.h2
-rw-r--r--src/unity-system-compositor.c3
-rw-r--r--src/xdmcp-protocol.c28
-rw-r--r--src/xdmcp-server.c139
14 files changed, 348 insertions, 136 deletions
diff --git a/src/greeter.c b/src/greeter.c
index e1d47f86..b9f4f55a 100644
--- a/src/greeter.c
+++ b/src/greeter.c
@@ -76,6 +76,8 @@ struct GreeterPrivate
gboolean guest_account_authenticated;
/* Communication channels to communicate with */
+ int to_greeter_input;
+ int from_greeter_output;
GIOChannel *to_greeter_channel;
GIOChannel *from_greeter_channel;
guint from_greeter_watch;
@@ -954,6 +956,7 @@ greeter_start (Session *session)
{
Greeter *greeter = GREETER (session);
int to_greeter_pipe[2], from_greeter_pipe[2];
+ int to_greeter_output, from_greeter_input;
gboolean result = FALSE;
gchar *value;
GError *error = NULL;
@@ -964,12 +967,16 @@ greeter_start (Session *session)
g_warning ("Failed to create pipes: %s", strerror (errno));
return FALSE;
}
- greeter->priv->to_greeter_channel = g_io_channel_unix_new (to_greeter_pipe[1]);
+ to_greeter_output = to_greeter_pipe[0];
+ greeter->priv->to_greeter_input = to_greeter_pipe[1];
+ greeter->priv->to_greeter_channel = g_io_channel_unix_new (greeter->priv->to_greeter_input);
g_io_channel_set_encoding (greeter->priv->to_greeter_channel, NULL, &error);
if (error)
g_warning ("Failed to set encoding on to greeter channel to binary: %s\n", error->message);
g_clear_error (&error);
- greeter->priv->from_greeter_channel = g_io_channel_unix_new (from_greeter_pipe[0]);
+ greeter->priv->from_greeter_output = from_greeter_pipe[0];
+ from_greeter_input = from_greeter_pipe[1];
+ greeter->priv->from_greeter_channel = g_io_channel_unix_new (greeter->priv->from_greeter_output);
g_io_channel_set_encoding (greeter->priv->from_greeter_channel, NULL, &error);
if (error)
g_warning ("Failed to set encoding on from greeter channel to binary: %s\n", error->message);
@@ -978,22 +985,22 @@ greeter_start (Session *session)
greeter->priv->from_greeter_watch = g_io_add_watch (greeter->priv->from_greeter_channel, G_IO_IN | G_IO_HUP, read_cb, greeter);
/* Let the greeter session know how to communicate with the daemon */
- value = g_strdup_printf ("%d", from_greeter_pipe[1]);
+ value = g_strdup_printf ("%d", from_greeter_input);
session_set_env (SESSION (greeter), "LIGHTDM_TO_SERVER_FD", value);
g_free (value);
- value = g_strdup_printf ("%d", to_greeter_pipe[0]);
+ value = g_strdup_printf ("%d", to_greeter_output);
session_set_env (SESSION (greeter), "LIGHTDM_FROM_SERVER_FD", value);
g_free (value);
/* Don't allow the daemon end of the pipes to be accessed in child processes */
- fcntl (to_greeter_pipe[1], F_SETFD, FD_CLOEXEC);
- fcntl (from_greeter_pipe[0], F_SETFD, FD_CLOEXEC);
+ fcntl (greeter->priv->to_greeter_input, F_SETFD, FD_CLOEXEC);
+ fcntl (greeter->priv->from_greeter_output, F_SETFD, FD_CLOEXEC);
result = SESSION_CLASS (greeter_parent_class)->start (session);
/* Close the session ends of the pipe */
- close (to_greeter_pipe[0]);
- close (from_greeter_pipe[1]);
+ close (to_greeter_output);
+ close (from_greeter_input);
return result;
}
@@ -1029,6 +1036,8 @@ greeter_init (Greeter *greeter)
greeter->priv->read_buffer = secure_malloc (greeter, HEADER_SIZE);
greeter->priv->hints = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
greeter->priv->use_secure_memory = config_get_boolean (config_get_instance (), "LightDM", "lock-memory");
+ greeter->priv->to_greeter_input = -1;
+ greeter->priv->from_greeter_output = -1;
}
static void
@@ -1049,6 +1058,8 @@ greeter_finalize (GObject *object)
g_signal_handlers_disconnect_matched (self->priv->authentication_session, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);
g_object_unref (self->priv->authentication_session);
}
+ close (self->priv->to_greeter_input);
+ close (self->priv->from_greeter_output);
if (self->priv->to_greeter_channel)
g_io_channel_unref (self->priv->to_greeter_channel);
if (self->priv->from_greeter_channel)
diff --git a/src/lightdm.c b/src/lightdm.c
index f87df156..72f7eb0c 100644
--- a/src/lightdm.c
+++ b/src/lightdm.c
@@ -153,18 +153,16 @@ get_config_sections (const gchar *seat_name)
gchar **groups, **i;
GList *config_sections = NULL;
- config_sections = g_list_append (config_sections, g_strdup ("SeatDefaults"));
-
- if (!seat_name)
- return config_sections;
+ /* Load seat defaults first */
+ config_sections = g_list_append (config_sections, g_strdup ("Seat:*"));
groups = config_get_groups (config_get_instance ());
for (i = groups; *i; i++)
{
- if (g_str_has_prefix (*i, "Seat:"))
+ if (g_str_has_prefix (*i, "Seat:") && strcmp (*i, "Seat:*") != 0)
{
const gchar *seat_name_glob = *i + strlen ("Seat:");
- if (g_pattern_match_simple (seat_name_glob, seat_name))
+ if (g_pattern_match_simple (seat_name_glob, seat_name ? seat_name : ""))
config_sections = g_list_append (config_sections, g_strdup (*i));
}
}
@@ -184,8 +182,9 @@ set_seat_properties (Seat *seat, const gchar *seat_name)
for (link = sections; link; link = link->next)
{
const gchar *section = link->data;
- g_debug ("Loading properties from config section %s", section);
keys = config_get_keys (config_get_instance (), section);
+
+ l_debug (seat, "Loading properties from config section %s", section);
for (i = 0; keys && keys[i]; i++)
{
gchar *value = config_get_string (config_get_instance (), section, keys[i]);
@@ -611,11 +610,6 @@ seat_bus_entry_free (gpointer data)
{
SeatBusEntry *entry = data;
- g_dbus_connection_unregister_object (bus, entry->bus_id);
-
- emit_object_value_changed (bus, "/org/freedesktop/DisplayManager", "org.freedesktop.DisplayManager", "Seats", get_seat_list ());
- emit_object_signal (bus, "/org/freedesktop/DisplayManager", "SeatRemoved", entry->path);
-
g_free (entry->path);
g_free (entry);
}
@@ -625,14 +619,6 @@ session_bus_entry_free (gpointer data)
{
SessionBusEntry *entry = data;
- g_dbus_connection_unregister_object (bus, entry->bus_id);
-
- emit_object_value_changed (bus, "/org/freedesktop/DisplayManager", "org.freedesktop.DisplayManager", "Sessions", get_session_list (NULL));
- emit_object_signal (bus, "/org/freedesktop/DisplayManager", "SessionRemoved", entry->path);
-
- emit_object_value_changed (bus, entry->seat_path, "org.freedesktop.DisplayManager.Seat", "Sessions", get_session_list (entry->seat_path));
- emit_object_signal (bus, entry->seat_path, "SessionRemoved", entry->path);
-
g_free (entry->path);
g_free (entry->seat_path);
g_free (entry);
@@ -659,7 +645,6 @@ running_user_session_cb (Seat *seat, Session *session)
session_set_env (session, "XDG_SESSION_PATH", path);
g_object_set_data_full (G_OBJECT (session), "XDG_SESSION_PATH", path, g_free);
- seat_entry = g_hash_table_lookup (seat_bus_entries, seat);
session_entry = session_bus_entry_new (g_object_get_data (G_OBJECT (session), "XDG_SESSION_PATH"), seat_entry ? seat_entry->path : NULL);
g_hash_table_insert (session_bus_entries, g_object_ref (session), session_entry);
@@ -685,8 +670,28 @@ running_user_session_cb (Seat *seat, Session *session)
static void
session_removed_cb (Seat *seat, Session *session)
{
+ SessionBusEntry *entry;
+ gchar *seat_path = NULL;
+
g_signal_handlers_disconnect_matched (session, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, seat);
+
+ entry = g_hash_table_lookup (session_bus_entries, session);
+ if (entry)
+ {
+ g_dbus_connection_unregister_object (bus, entry->bus_id);
+ emit_object_signal (bus, "/org/freedesktop/DisplayManager", "SessionRemoved", entry->path);
+ emit_object_signal (bus, entry->seat_path, "SessionRemoved", entry->path);
+ seat_path = g_strdup (entry->seat_path);
+ }
+
g_hash_table_remove (session_bus_entries, session);
+
+ if (seat_path)
+ {
+ emit_object_value_changed (bus, "/org/freedesktop/DisplayManager", "org.freedesktop.DisplayManager", "Sessions", get_session_list (NULL));
+ emit_object_value_changed (bus, seat_path, "org.freedesktop.DisplayManager.Seat", "Sessions", get_session_list (seat_path));
+ g_free (seat_path);
+ }
}
static void
@@ -730,7 +735,18 @@ seat_added_cb (DisplayManager *display_manager, Seat *seat)
static void
seat_removed_cb (DisplayManager *display_manager, Seat *seat)
{
+ SeatBusEntry *entry;
+
+ entry = g_hash_table_lookup (seat_bus_entries, seat);
+ if (entry)
+ {
+ g_dbus_connection_unregister_object (bus, entry->bus_id);
+ emit_object_signal (bus, "/org/freedesktop/DisplayManager", "SeatRemoved", entry->path);
+ }
+
g_hash_table_remove (seat_bus_entries, seat);
+
+ emit_object_value_changed (bus, "/org/freedesktop/DisplayManager", "org.freedesktop.DisplayManager", "Seats", get_seat_list ());
}
static gboolean
@@ -1068,6 +1084,48 @@ login1_can_graphical_changed_cb (Login1Seat *login1_seat)
}
static void
+login1_active_session_changed_cb (Login1Seat *login1_seat, const gchar *login1_session_id)
+{
+ g_debug ("Seat %s changes active session to %s", login1_seat_get_id (login1_seat), login1_session_id);
+
+ Seat *seat;
+ seat = display_manager_get_seat (display_manager, login1_seat_get_id (login1_seat));
+
+ if (seat)
+ {
+ Session *active_session;
+ active_session = seat_get_expected_active_session (seat);
+
+ if (g_strcmp0 (login1_session_id, session_get_login1_session_id (active_session)) == 0)
+ {
+ // Session is already active
+ g_debug ("Session %s is already active", login1_session_id);
+ return;
+ }
+
+ active_session = seat_find_session_by_login1_id (seat, login1_session_id);
+ if (active_session != NULL)
+ {
+ g_debug ("Activating session %s", login1_session_id);
+ seat_set_externally_activated_session (seat, active_session);
+ return;
+
+ }
+ }
+}
+
+static gboolean
+login1_add_seat (Login1Seat *login1_seat)
+{
+ if (config_get_boolean (config_get_instance (), "LightDM", "logind-check-graphical"))
+ g_signal_connect (login1_seat, "can-graphical-changed", G_CALLBACK (login1_can_graphical_changed_cb), NULL);
+
+ g_signal_connect (login1_seat, LOGIN1_SIGNAL_ACTIVE_SESION_CHANGED, G_CALLBACK (login1_active_session_changed_cb), NULL);
+
+ return update_login1_seat (login1_seat);
+}
+
+static void
login1_service_seat_added_cb (Login1Service *service, Login1Seat *login1_seat)
{
if (login1_seat_get_can_graphical (login1_seat))
@@ -1075,9 +1133,7 @@ login1_service_seat_added_cb (Login1Service *service, Login1Seat *login1_seat)
else
g_debug ("Seat %s added from logind without graphical output", login1_seat_get_id (login1_seat));
- if (config_get_boolean (config_get_instance (), "LightDM", "logind-check-graphical"))
- g_signal_connect (login1_seat, LOGIN1_SEAT_SIGNAL_CAN_GRAPHICAL_CHANGED, G_CALLBACK (login1_can_graphical_changed_cb), NULL);
- update_login1_seat (login1_seat);
+ login1_add_seat (login1_seat);
}
static void
@@ -1085,6 +1141,7 @@ login1_service_seat_removed_cb (Login1Service *service, Login1Seat *login1_seat)
{
g_debug ("Seat %s removed from logind", login1_seat_get_id (login1_seat));
g_signal_handlers_disconnect_matched (login1_seat, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, login1_can_graphical_changed_cb, NULL);
+ g_signal_handlers_disconnect_matched (login1_seat, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, login1_active_session_changed_cb, NULL);
remove_login1_seat (login1_seat);
}
@@ -1319,36 +1376,38 @@ main (int argc, char **argv)
config_set_string (config_get_instance (), "LightDM", "greeter-user", GREETER_USER);
if (!config_has_key (config_get_instance (), "LightDM", "lock-memory"))
config_set_boolean (config_get_instance (), "LightDM", "lock-memory", TRUE);
- if (!config_has_key (config_get_instance (), "SeatDefaults", "type"))
- config_set_string (config_get_instance (), "SeatDefaults", "type", "xlocal");
- if (!config_has_key (config_get_instance (), "SeatDefaults", "pam-service"))
- config_set_string (config_get_instance (), "SeatDefaults", "pam-service", "lightdm");
- if (!config_has_key (config_get_instance (), "SeatDefaults", "pam-autologin-service"))
- config_set_string (config_get_instance (), "SeatDefaults", "pam-autologin-service", "lightdm-autologin");
- if (!config_has_key (config_get_instance (), "SeatDefaults", "pam-greeter-service"))
- config_set_string (config_get_instance (), "SeatDefaults", "pam-greeter-service", "lightdm-greeter");
- 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"))
- config_set_boolean (config_get_instance (), "SeatDefaults", "start-session", TRUE);
- if (!config_has_key (config_get_instance (), "SeatDefaults", "allow-user-switching"))
- config_set_boolean (config_get_instance (), "SeatDefaults", "allow-user-switching", TRUE);
- if (!config_has_key (config_get_instance (), "SeatDefaults", "allow-guest"))
- config_set_boolean (config_get_instance (), "SeatDefaults", "allow-guest", TRUE);
- if (!config_has_key (config_get_instance (), "SeatDefaults", "greeter-allow-guest"))
- config_set_boolean (config_get_instance (), "SeatDefaults", "greeter-allow-guest", TRUE);
- if (!config_has_key (config_get_instance (), "SeatDefaults", "greeter-show-remote-login"))
- config_set_boolean (config_get_instance (), "SeatDefaults", "greeter-show-remote-login", TRUE);
- if (!config_has_key (config_get_instance (), "SeatDefaults", "greeter-session"))
- config_set_string (config_get_instance (), "SeatDefaults", "greeter-session", GREETER_SESSION);
- if (!config_has_key (config_get_instance (), "SeatDefaults", "user-session"))
- config_set_string (config_get_instance (), "SeatDefaults", "user-session", USER_SESSION);
- if (!config_has_key (config_get_instance (), "SeatDefaults", "session-wrapper"))
- config_set_string (config_get_instance (), "SeatDefaults", "session-wrapper", "lightdm-session");
+ if (!config_has_key (config_get_instance (), "Seat:*", "type"))
+ config_set_string (config_get_instance (), "Seat:*", "type", "xlocal");
+ if (!config_has_key (config_get_instance (), "Seat:*", "pam-service"))
+ config_set_string (config_get_instance (), "Seat:*", "pam-service", "lightdm");
+ if (!config_has_key (config_get_instance (), "Seat:*", "pam-autologin-service"))
+ config_set_string (config_get_instance (), "Seat:*", "pam-autologin-service", "lightdm-autologin");
+ if (!config_has_key (config_get_instance (), "Seat:*", "pam-greeter-service"))
+ config_set_string (config_get_instance (), "Seat:*", "pam-greeter-service", "lightdm-greeter");
+ if (!config_has_key (config_get_instance (), "Seat:*", "xserver-command"))
+ config_set_string (config_get_instance (), "Seat:*", "xserver-command", "X");
+ if (!config_has_key (config_get_instance (), "Seat:*", "xmir-command"))
+ config_set_string (config_get_instance (), "Seat:*", "xmir-command", "Xmir");
+ if (!config_has_key (config_get_instance (), "Seat:*", "xserver-share"))
+ config_set_boolean (config_get_instance (), "Seat:*", "xserver-share", TRUE);
+ if (!config_has_key (config_get_instance (), "Seat:*", "unity-compositor-command"))
+ config_set_string (config_get_instance (), "Seat:*", "unity-compositor-command", "unity-system-compositor");
+ if (!config_has_key (config_get_instance (), "Seat:*", "start-session"))
+ config_set_boolean (config_get_instance (), "Seat:*", "start-session", TRUE);
+ if (!config_has_key (config_get_instance (), "Seat:*", "allow-user-switching"))
+ config_set_boolean (config_get_instance (), "Seat:*", "allow-user-switching", TRUE);
+ if (!config_has_key (config_get_instance (), "Seat:*", "allow-guest"))
+ config_set_boolean (config_get_instance (), "Seat:*", "allow-guest", TRUE);
+ if (!config_has_key (config_get_instance (), "Seat:*", "greeter-allow-guest"))
+ config_set_boolean (config_get_instance (), "Seat:*", "greeter-allow-guest", TRUE);
+ if (!config_has_key (config_get_instance (), "Seat:*", "greeter-show-remote-login"))
+ config_set_boolean (config_get_instance (), "Seat:*", "greeter-show-remote-login", TRUE);
+ if (!config_has_key (config_get_instance (), "Seat:*", "greeter-session"))
+ config_set_string (config_get_instance (), "Seat:*", "greeter-session", GREETER_SESSION);
+ if (!config_has_key (config_get_instance (), "Seat:*", "user-session"))
+ config_set_string (config_get_instance (), "Seat:*", "user-session", USER_SESSION);
+ if (!config_has_key (config_get_instance (), "Seat:*", "session-wrapper"))
+ config_set_string (config_get_instance (), "Seat:*", "session-wrapper", "lightdm-session");
if (!config_has_key (config_get_instance (), "LightDM", "log-directory"))
config_set_string (config_get_instance (), "LightDM", "log-directory", default_log_dir);
g_free (default_log_dir);
@@ -1432,9 +1491,7 @@ main (int argc, char **argv)
for (link = login1_service_get_seats (login1_service_get_instance ()); link; link = link->next)
{
Login1Seat *login1_seat = link->data;
- if (config_get_boolean (config_get_instance (), "LightDM", "logind-check-graphical"))
- g_signal_connect (login1_seat, LOGIN1_SEAT_SIGNAL_CAN_GRAPHICAL_CHANGED, G_CALLBACK (login1_can_graphical_changed_cb), NULL);
- if (!update_login1_seat (login1_seat))
+ if (!login1_add_seat (login1_seat))
return EXIT_FAILURE;
}
}
@@ -1449,7 +1506,7 @@ main (int argc, char **argv)
g_debug ("Adding default seat");
- types = config_get_string_list (config_get_instance (), "SeatDefaults", "type");
+ types = config_get_string_list (config_get_instance (), "Seat:*", "type");
for (type = types; type && *type; type++)
{
seat = seat_new (*type, "seat0");
diff --git a/src/login1.c b/src/login1.c
index 83d64b6e..af8e8a8e 100644
--- a/src/login1.c
+++ b/src/login1.c
@@ -43,6 +43,7 @@ struct Login1ServicePrivate
enum {
CAN_GRAPHICAL_CHANGED,
+ ACTIVE_SESSION_CHANGED,
LAST_SEAT_SIGNAL
};
static guint seat_signals[LAST_SEAT_SIGNAL] = { 0 };
@@ -89,6 +90,12 @@ update_property (Login1Seat *seat, const gchar *name, GVariant *value)
seat->priv->can_graphical = g_variant_get_boolean (value);
g_signal_emit (seat, seat_signals[CAN_GRAPHICAL_CHANGED], 0);
}
+ else if (strcmp (name, "ActiveSession") == 0 && g_variant_is_of_type (value, G_VARIANT_TYPE ("(so)")))
+ {
+ const gchar *login1_session_id;
+ g_variant_get (value, "(&so)", &login1_session_id, NULL);
+ g_signal_emit (seat, seat_signals[ACTIVE_SESSION_CHANGED], 0, login1_session_id);
+ }
}
static void
@@ -133,6 +140,7 @@ seat_properties_changed_cb (GDBusConnection *connection,
{
g_variant_get (result, "(v)", &value);
update_property (seat, name, value);
+ g_variant_unref (value);
g_variant_unref (result);
}
}
@@ -531,4 +539,13 @@ login1_seat_class_init (Login1SeatClass *klass)
NULL, NULL,
NULL,
G_TYPE_NONE, 0);
+
+ seat_signals[ACTIVE_SESSION_CHANGED] =
+ g_signal_new (LOGIN1_SIGNAL_ACTIVE_SESION_CHANGED,
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (Login1SeatClass, active_session_changed),
+ NULL, NULL,
+ NULL,
+ G_TYPE_NONE, 1, G_TYPE_STRING);
}
diff --git a/src/login1.h b/src/login1.h
index c266e23d..e34e806b 100644
--- a/src/login1.h
+++ b/src/login1.h
@@ -26,6 +26,7 @@ G_BEGIN_DECLS
#define LOGIN1_SERVICE_SIGNAL_SEAT_REMOVED "seat-removed"
#define LOGIN1_SEAT_SIGNAL_CAN_GRAPHICAL_CHANGED "can-graphical-changed"
+#define LOGIN1_SIGNAL_ACTIVE_SESION_CHANGED "active-session-changed"
typedef struct Login1SeatPrivate Login1SeatPrivate;
@@ -39,6 +40,7 @@ typedef struct
{
GObjectClass parent_class;
void (*can_graphical_changed)(Login1Seat *seat);
+ void (*active_session_changed)(Login1Seat *seat, const gchar *login1_session_id);
} Login1SeatClass;
typedef struct Login1ServicePrivate Login1ServicePrivate;
diff --git a/src/seat-unity.c b/src/seat-unity.c
index 32d30b23..642be0aa 100644
--- a/src/seat-unity.c
+++ b/src/seat-unity.c
@@ -203,9 +203,11 @@ create_x_server (Seat *seat)
x_server = x_server_local_new ();
- command = seat_get_string_property (seat, "xserver-command");
- if (command)
- x_server_local_set_command (x_server, command);
+ command = seat_get_string_property (seat, "xmir-command");
+ /* Fall back to using X if Xmir is not available as this was the previous way XMir worked */
+ if (strcmp (command, "Xmir") == 0 && !g_find_program_in_path ("Xmir"))
+ command = seat_get_string_property (seat, "xserver-command");
+ x_server_local_set_command (x_server, command);
id = g_strdup_printf ("x-%d", SEAT_UNITY (seat)->priv->next_x_server_id);
SEAT_UNITY (seat)->priv->next_x_server_id++;
diff --git a/src/seat-xremote.c b/src/seat-xremote.c
index 1a46f401..e860e9f3 100644
--- a/src/seat-xremote.c
+++ b/src/seat-xremote.c
@@ -41,7 +41,7 @@ seat_xremote_create_display_server (Seat *seat, Session *session)
hostname = seat_get_string_property (seat, "xserver-hostname");
if (!hostname)
- hostname = "localhost";
+ hostname = "127.0.0.1";
number = seat_get_integer_property (seat, "xserver-display-number");
l_debug (seat, "Starting remote X display %s:%d", hostname, number);
diff --git a/src/seat.c b/src/seat.c
index 9a56baf2..f9b149dd 100644
--- a/src/seat.c
+++ b/src/seat.c
@@ -269,6 +269,54 @@ seat_get_next_session (Seat *seat)
return seat->priv->next_session;
}
+/**
+ * Obtains the active session which lightdm expects to be active.
+ *
+ * This function is different from seat_get_active_session() in that the
+ * later (in the case of xlocal seats) dynamically finds the session that is
+ * really active (based on the active VT), whereas this function returns the
+ * session that lightdm activated last by itself, which may not be the actual
+ * active session (i.e. VT changes).
+ */
+Session *
+seat_get_expected_active_session (Seat *seat)
+{
+ g_return_val_if_fail (seat != NULL, NULL);
+ return seat->priv->active_session;
+}
+
+/**
+ * Sets the active session which lightdm expects to be active.
+ *
+ * This function is different from seat_set_active_session() in that the
+ * later performs an actual session activation, whereas this function just
+ * updates the active session after the session has been activated by some
+ * means external to lightdm (i.e. VT changes).
+ */
+void
+seat_set_externally_activated_session (Seat *seat, Session *session)
+{
+ g_return_if_fail (seat != NULL);
+ if (seat->priv->active_session)
+ g_object_unref (seat->priv->active_session);
+ seat->priv->active_session = g_object_ref (session);
+}
+
+Session *
+seat_find_session_by_login1_id (Seat *seat, const gchar *login1_session_id)
+{
+ GList *session_link;
+
+ for (session_link = seat->priv->sessions; session_link; session_link = session_link->next)
+ {
+ Session *session = session_link->data;
+ if (g_strcmp0 (login1_session_id, session_get_login1_session_id (session)) == 0)
+ return session;
+ }
+
+ return NULL;
+}
+
gboolean
seat_get_can_switch (Seat *seat)
{
@@ -346,13 +394,15 @@ emit_upstart_signal (const gchar *signal)
{
g_return_if_fail (signal != NULL);
g_return_if_fail (signal[0] != 0);
+ const gchar* argv[] = {"initctl", "-q", "emit", signal, "DISPLAY_MANAGER=lightdm", NULL};
if (getuid () != 0)
return;
- gchar *cmd = g_strdup_printf ("initctl -q emit %s DISPLAY_MANAGER=lightdm", signal);
- g_spawn_command_line_async (cmd, NULL); /* OK if it fails, probably not installed */
- g_free (cmd);
+ /* OK if it fails, probably not installed or not running upstart */
+ g_spawn_async (NULL, argv, NULL,
+ G_SPAWN_SEARCH_PATH | G_SPAWN_STDERR_TO_DEV_NULL,
+ NULL, NULL, NULL, NULL);
}
static void
diff --git a/src/seat.h b/src/seat.h
index f8781ef5..e8d2bc6f 100644
--- a/src/seat.h
+++ b/src/seat.h
@@ -93,6 +93,12 @@ Session *seat_get_active_session (Seat *seat);
Session *seat_get_next_session (Seat *seat);
+void seat_set_externally_activated_session (Seat *seat, Session *session);
+
+Session *seat_get_expected_active_session (Seat *seat);
+
+Session *seat_find_session_by_login1_id (Seat *seat, const gchar *login1_session_id);
+
gboolean seat_get_can_switch (Seat *seat);
gboolean seat_get_allow_guest (Seat *seat);
diff --git a/src/session-child.c b/src/session-child.c
index c6f8a7ce..e85f57da 100644
--- a/src/session-child.c
+++ b/src/session-child.c
@@ -243,7 +243,7 @@ session_child_run (int argc, char **argv)
XAuthority *x_authority = NULL;
gchar *x_authority_filename;
GDBusConnection *bus;
- const gchar *login1_session = NULL;
+ const gchar *login1_session_id = NULL;
gchar *console_kit_cookie = NULL;
const gchar *locale_value;
gchar *locale_var;
@@ -545,10 +545,10 @@ session_child_run (int argc, char **argv)
}
/* Check what logind session we are, or fallback to ConsoleKit */
- login1_session = pam_getenv (pam_handle, "XDG_SESSION_ID");
- if (login1_session)
+ login1_session_id = pam_getenv (pam_handle, "XDG_SESSION_ID");
+ if (login1_session_id)
{
- write_string (login1_session);
+ write_string (login1_session_id);
if (version >= 2)
write_string (NULL);
}
@@ -768,7 +768,7 @@ session_child_run (int argc, char **argv)
pam_close_session (pam_handle, 0);
/* Remove credentials */
- result = pam_setcred (pam_handle, PAM_DELETE_CRED);
+ pam_setcred (pam_handle, PAM_DELETE_CRED);
pam_end (pam_handle, 0);
pam_handle = NULL;
diff --git a/src/session.c b/src/session.c
index 1ac16109..e25a69a5 100644
--- a/src/session.c
+++ b/src/session.c
@@ -653,6 +653,13 @@ session_get_username (Session *session)
}
const gchar *
+session_get_login1_session_id (Session *session)
+{
+ g_return_val_if_fail (session != NULL, NULL);
+ return session->priv->login1_session_id;
+}
+
+const gchar *
session_get_console_kit_cookie (Session *session)
{
g_return_val_if_fail (session != NULL, NULL);
@@ -903,6 +910,8 @@ session_init (Session *session)
{
session->priv = G_TYPE_INSTANCE_GET_PRIVATE (session, SESSION_TYPE, SessionPrivate);
session->priv->log_filename = g_strdup (".xsession-errors");
+ session->priv->to_child_input = -1;
+ session->priv->from_child_output = -1;
}
static void
@@ -917,6 +926,8 @@ session_finalize (GObject *object)
g_object_unref (self->priv->display_server);
if (self->priv->pid)
kill (self->priv->pid, SIGKILL);
+ close (self->priv->to_child_input);
+ close (self->priv->from_child_output);
if (self->priv->from_child_channel)
g_io_channel_unref (self->priv->from_child_channel);
if (self->priv->from_child_watch)
diff --git a/src/session.h b/src/session.h
index 513fd12d..c62303e6 100644
--- a/src/session.h
+++ b/src/session.h
@@ -115,6 +115,8 @@ gboolean session_get_is_started (Session *session);
const gchar *session_get_username (Session *session);
+const gchar *session_get_login1_session_id (Session *session);
+
const gchar *session_get_console_kit_cookie (Session *session);
void session_respond (Session *session, struct pam_response *response);
diff --git a/src/unity-system-compositor.c b/src/unity-system-compositor.c
index 03824284..f4b74eb1 100644
--- a/src/unity-system-compositor.c
+++ b/src/unity-system-compositor.c
@@ -147,7 +147,8 @@ write_message (UnitySystemCompositor *compositor, guint16 id, const guint8 *payl
data[1] = id & 0xFF;
data[2] = payload_length >> 8;
data[3] = payload_length & 0xFF;
- memcpy (data + 4, payload, payload_length);
+ if (payload)
+ memcpy (data + 4, payload, payload_length);
errno = 0;
if (write (compositor->priv->to_compositor_pipe[1], data, data_length) != data_length)
diff --git a/src/xdmcp-protocol.c b/src/xdmcp-protocol.c
index eb5517fb..f45e7aeb 100644
--- a/src/xdmcp-protocol.c
+++ b/src/xdmcp-protocol.c
@@ -10,8 +10,10 @@
*/
#include <string.h>
+#include <gio/gio.h>
#include "xdmcp-protocol.h"
+#include "x-authority.h"
typedef struct
{
@@ -481,13 +483,31 @@ xdmcp_packet_tostring (XDMCPPacket *packet)
t3 = g_string_new ("");
for (i = 0; i < packet->Request.n_connections; i++)
{
- gchar *t4;
+ XDMCPConnection *connection = &packet->Request.connections[i];
+ GSocketFamily family = G_SOCKET_FAMILY_INVALID;
if (i != 0)
g_string_append (t3, " ");
- t4 = data_tostring (&packet->Request.connections[i].address);
- g_string_append_printf (t3, "(%d, %s)", packet->Request.connections[i].type, t4);
- g_free (t4);
+
+ if (connection->type == XAUTH_FAMILY_INTERNET && connection->address.length == 4)
+ family = G_SOCKET_FAMILY_IPV4;
+ else if (connection->type == XAUTH_FAMILY_INTERNET6 && connection->address.length == 16)
+ family = G_SOCKET_FAMILY_IPV6;
+
+ if (family != G_SOCKET_FAMILY_INVALID)
+ {
+ GInetAddress *address = g_inet_address_new_from_bytes (connection->address.data, family);
+ gchar *t4 = g_inet_address_to_string (address);
+ g_string_append (t3, t4);
+ g_free (t4);
+ g_object_unref (address);
+ }
+ else
+ {
+ gchar *t4 = data_tostring (&connection->address);
+ g_string_append_printf (t3, "(%d, %s)", connection->type, t4);
+ g_free (t4);
+ }
}
string = g_strdup_printf ("Request(display_number=%d connections=[%s] authentication_name='%s' authentication_data=%s authorization_names=[%s] manufacturer_display_id='%s')",
packet->Request.display_number, t3->str, packet->Request.authentication_name, t2,
diff --git a/src/xdmcp-server.c b/src/xdmcp-server.c
index d92b57d9..197dbc11 100644
--- a/src/xdmcp-server.c
+++ b/src/xdmcp-server.c
@@ -277,10 +277,76 @@ decode_key (const gchar *key, guint8 *data)
}
}
+static GInetAddress *
+connection_to_address (XDMCPConnection *connection)
+{
+ switch (connection->type)
+ {
+ case XAUTH_FAMILY_INTERNET:
+ if (connection->address.length == 4)
+ return g_inet_address_new_from_bytes (connection->address.data, G_SOCKET_FAMILY_IPV4);
+ else
+ return NULL;
+ case XAUTH_FAMILY_INTERNET6:
+ if (connection->address.length == 16)
+ return g_inet_address_new_from_bytes (connection->address.data, G_SOCKET_FAMILY_IPV6);
+ else
+ return NULL;
+ default:
+ return NULL;
+ }
+}
+
+static gssize
+find_address (GInetAddress **addresses, gsize length, GSocketFamily family)
+{
+ int i;
+
+ for (i = 0; i < length; i++)
+ {
+ GInetAddress *address = addresses[i];
+ if (address && g_inet_address_get_family (address) == family)
+ return i;
+ }
+
+ return -1;
+}
+
+static XDMCPConnection *
+choose_connection (XDMCPPacket *packet, GInetAddress *source_address)
+{
+ GInetAddress **addresses;
+ gsize addresses_length, i;
+ gssize index = -1;
+
+ addresses_length = packet->Request.n_connections;
+ addresses = malloc (sizeof (GInetAddress *) * addresses_length);
+ for (i = 0; i < addresses_length; i++)
+ addresses[i] = connection_to_address (&packet->Request.connections[i]);
+
+ /* Use the address the request came in on as this is the least likely to have firewall / routing issues */
+ for (i = 0; i < addresses_length && index < 0; i++)
+ if (g_inet_address_equal (source_address, addresses[i]))
+ index = i;
+
+ /* Otherwise try and find an address that matches the incoming type */
+ if (index < 0)
+ index = find_address (addresses, addresses_length, g_inet_address_get_family (source_address));
+
+ /* Otherwise use the first available */
+ if (index < 0 && addresses_length > 0)
+ index = 0;
+
+ for (i = 0; i < addresses_length; i++)
+ g_object_unref (addresses[i]);
+ g_free (addresses);
+
+ return &packet->Request.connections[index];
+}
+
static void
handle_request (XDMCPServer *server, GSocket *socket, GSocketAddress *address, XDMCPPacket *packet)
{
- int i;
XDMCPPacket *response;
XDMCPSession *session;
guint8 *authentication_data = NULL;
@@ -292,48 +358,15 @@ handle_request (XDMCPServer *server, GSocket *socket, GSocketAddress *address, X
guint8 *session_authorization_data = NULL;
gsize session_authorization_data_length = 0;
gchar **j;
- guint16 family;
- GInetAddress *x_server_address = NULL;
+ XDMCPConnection *connection;
gchar *display_number;
XdmAuthKeyRec rho;
- /* Try and find an IPv6 address */
- for (i = 0; i < packet->Request.n_connections; i++)
- {
- XDMCPConnection *connection = &packet->Request.connections[i];
- if (connection->type == XAUTH_FAMILY_INTERNET6 && connection->address.length == 16)
- {
- family = connection->type;
- x_server_address = g_inet_address_new_from_bytes (connection->address.data, G_SOCKET_FAMILY_IPV6);
-
- /* We can't use link-local addresses, as we need to know what interface it is on */
- if (g_inet_address_get_is_link_local (x_server_address))
- {
- g_object_unref (x_server_address);
- x_server_address = NULL;
- }
- else
- break;
- }
- }
-
- /* If no IPv6 address, then try and find an IPv4 one */
- if (!x_server_address)
- {
- for (i = 0; i < packet->Request.n_connections; i++)
- {
- XDMCPConnection *connection = &packet->Request.connections[i];
- if (connection->type == XAUTH_FAMILY_INTERNET && connection->address.length == 4)
- {
- family = connection->type;
- x_server_address = g_inet_address_new_from_bytes (connection->address.data, G_SOCKET_FAMILY_IPV4);
- break;
- }
- }
- }
+ /* Choose an address to connect back on */
+ connection = choose_connection (packet, g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (address)));
/* Decline if haven't got an address we can connect on */
- if (!x_server_address)
+ if (!connection)
{
response = xdmcp_packet_alloc (XDMCP_Decline);
response->Decline.status = g_strdup ("No valid address found");
@@ -449,34 +482,34 @@ handle_request (XDMCPServer *server, GSocket *socket, GSocketAddress *address, X
}
session = add_session (server);
- session->priv->address = x_server_address;
+ session->priv->address = connection_to_address (connection);
session->priv->display_number = packet->Request.display_number;
display_number = g_strdup_printf ("%d", packet->Request.display_number);
/* We need to check if this is the loopback address and set the authority
* for a local connection if this is so as XCB treats "127.0.0.1" as local
* always */
- if (g_inet_address_get_is_loopback (x_server_address))
+ if (g_inet_address_get_is_loopback (session->priv->address))
{
gchar hostname[1024];
gethostname (hostname, 1024);
session->priv->authority = x_authority_new (XAUTH_FAMILY_LOCAL,
- (guint8 *) hostname,
- strlen (hostname),
- display_number,
- authorization_name,
- session_authorization_data,
- session_authorization_data_length);
+ (guint8 *) hostname,
+ strlen (hostname),
+ display_number,
+ authorization_name,
+ session_authorization_data,
+ session_authorization_data_length);
}
else
- session->priv->authority = x_authority_new (family,
- g_inet_address_to_bytes (G_INET_ADDRESS (x_server_address)),
- g_inet_address_get_native_size (G_INET_ADDRESS (x_server_address)),
- display_number,
- authorization_name,
- session_authorization_data,
- session_authorization_data_length);
+ session->priv->authority = x_authority_new (connection->type,
+ connection->address.data,
+ connection->address.length,
+ display_number,
+ authorization_name,
+ session_authorization_data,
+ session_authorization_data_length);
g_free (display_number);
response = xdmcp_packet_alloc (XDMCP_Accept);