summaryrefslogtreecommitdiff
path: root/daemon/gdm-display.c
diff options
context:
space:
mode:
Diffstat (limited to 'daemon/gdm-display.c')
-rw-r--r--daemon/gdm-display.c307
1 files changed, 297 insertions, 10 deletions
diff --git a/daemon/gdm-display.c b/daemon/gdm-display.c
index 97f0e7da..77302f65 100644
--- a/daemon/gdm-display.c
+++ b/daemon/gdm-display.c
@@ -42,9 +42,14 @@
#include "gdm-settings-direct.h"
#include "gdm-settings-keys.h"
+#include "gdm-launch-environment.h"
#include "gdm-simple-slave.h"
+#include "gdm-xdmcp-chooser-slave.h"
#include "gdm-dbus-util.h"
+#define INITIAL_SETUP_USERNAME "gnome-initial-setup"
+#define GNOME_SESSION_SESSIONS_PATH DATADIR "/gnome-session/sessions"
+
#define GDM_DISPLAY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_DISPLAY, GdmDisplayPrivate))
struct GdmDisplayPrivate
@@ -83,6 +88,7 @@ struct GdmDisplayPrivate
guint is_initial : 1;
guint allow_timed_login : 1;
guint have_existing_user_accounts : 1;
+ guint doing_initial_setup : 1;
};
enum {
@@ -101,7 +107,8 @@ enum {
PROP_LAUNCH_ENVIRONMENT,
PROP_IS_INITIAL,
PROP_ALLOW_TIMED_LOGIN,
- PROP_HAVE_EXISTING_USER_ACCOUNTS
+ PROP_HAVE_EXISTING_USER_ACCOUNTS,
+ PROP_DOING_INITIAL_SETUP,
};
static void gdm_display_class_init (GdmDisplayClass *klass);
@@ -110,9 +117,79 @@ static void gdm_display_finalize (GObject *object);
static void queue_finish (GdmDisplay *self);
static void _gdm_display_set_status (GdmDisplay *self,
int status);
-
G_DEFINE_ABSTRACT_TYPE (GdmDisplay, gdm_display, G_TYPE_OBJECT)
+static gboolean
+chown_file (GFile *file,
+ uid_t uid,
+ gid_t gid,
+ GError **error)
+{
+ if (!g_file_set_attribute_uint32 (file, G_FILE_ATTRIBUTE_UNIX_UID, uid,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ NULL, error)) {
+ return FALSE;
+ }
+ if (!g_file_set_attribute_uint32 (file, G_FILE_ATTRIBUTE_UNIX_GID, gid,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ NULL, error)) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static gboolean
+chown_recursively (GFile *dir,
+ uid_t uid,
+ gid_t gid,
+ GError **error)
+{
+ GFile *file = NULL;
+ GFileInfo *info = NULL;
+ GFileEnumerator *enumerator = NULL;
+ gboolean retval = FALSE;
+
+ if (chown_file (dir, uid, gid, error) == FALSE) {
+ goto out;
+ }
+
+ enumerator = g_file_enumerate_children (dir,
+ G_FILE_ATTRIBUTE_STANDARD_TYPE","
+ G_FILE_ATTRIBUTE_STANDARD_NAME,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ NULL, error);
+ if (!enumerator) {
+ goto out;
+ }
+
+ while ((info = g_file_enumerator_next_file (enumerator, NULL, error)) != NULL) {
+ file = g_file_get_child (dir, g_file_info_get_name (info));
+
+ if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
+ if (chown_recursively (file, uid, gid, error) == FALSE) {
+ goto out;
+ }
+ } else if (chown_file (file, uid, gid, error) == FALSE) {
+ goto out;
+ }
+
+ g_clear_object (&file);
+ g_clear_object (&info);
+ }
+
+ if (*error) {
+ goto out;
+ }
+
+ retval = TRUE;
+out:
+ g_clear_object (&file);
+ g_clear_object (&info);
+ g_clear_object (&enumerator);
+
+ return retval;
+}
+
GQuark
gdm_display_error_quark (void)
{
@@ -523,11 +600,6 @@ gdm_display_real_prepare (GdmDisplay *self)
G_CALLBACK (on_slave_stopped),
self,
0);
- g_object_bind_property (G_OBJECT (self->priv->slave),
- "session-id",
- G_OBJECT (self),
- "session-id",
- G_BINDING_DEFAULT);
return TRUE;
}
@@ -796,6 +868,12 @@ _gdm_display_set_launch_environment (GdmDisplay *self,
g_clear_object (&self->priv->launch_environment);
self->priv->launch_environment = g_object_ref (launch_environment);
+
+ g_object_bind_property (launch_environment,
+ "session-id",
+ self,
+ "session-id",
+ G_BINDING_SYNC_CREATE);
}
static void
@@ -922,6 +1000,9 @@ gdm_display_get_property (GObject *object,
case PROP_HAVE_EXISTING_USER_ACCOUNTS:
g_value_set_boolean (value, self->priv->have_existing_user_accounts);
break;
+ case PROP_DOING_INITIAL_SETUP:
+ g_value_set_boolean (value, self->priv->doing_initial_setup);
+ break;
case PROP_ALLOW_TIMED_LOGIN:
g_value_set_boolean (value, self->priv->allow_timed_login);
break;
@@ -1337,6 +1418,13 @@ gdm_display_class_init (GdmDisplayClass *klass)
FALSE,
G_PARAM_READABLE));
g_object_class_install_property (object_class,
+ PROP_DOING_INITIAL_SETUP,
+ g_param_spec_boolean ("doing-initial-setup",
+ NULL,
+ NULL,
+ FALSE,
+ G_PARAM_READABLE));
+ g_object_class_install_property (object_class,
PROP_LAUNCH_ENVIRONMENT,
g_param_spec_object ("launch-environment",
NULL,
@@ -1418,23 +1506,222 @@ gdm_display_get_object_skeleton (GdmDisplay *self)
return self->priv->object_skeleton;
}
+static void
+on_launch_environment_session_opened (GdmLaunchEnvironment *launch_environment,
+ GdmDisplay *self)
+{
+ char *session_id;
+
+ g_debug ("GdmDisplay: Greeter session opened");
+ session_id = gdm_launch_environment_get_session_id (launch_environment);
+
+ g_object_set (GDM_SLAVE (self), "session-id", session_id, NULL);
+ g_free (session_id);
+}
+
+static void
+on_launch_environment_session_started (GdmLaunchEnvironment *launch_environment,
+ GdmDisplay *self)
+{
+ g_debug ("GdmDisplay: Greeter started");
+}
+
+static void
+on_launch_environment_session_stopped (GdmLaunchEnvironment *launch_environment,
+ GdmDisplay *self)
+{
+ g_debug ("GdmDisplay: Greeter stopped");
+ gdm_slave_stop (self->priv->slave);
+
+ g_clear_object (&self->priv->launch_environment);
+}
+
+static void
+on_launch_environment_session_exited (GdmLaunchEnvironment *launch_environment,
+ int code,
+ GdmDisplay *self)
+{
+ g_debug ("GdmDisplay: Greeter exited: %d", code);
+ gdm_slave_stop (self->priv->slave);
+}
+
+static void
+on_launch_environment_session_died (GdmLaunchEnvironment *launch_environment,
+ int signal,
+ GdmDisplay *self)
+{
+ g_debug ("GdmDisplay: Greeter died: %d", signal);
+ gdm_slave_stop (self->priv->slave);
+}
+
+static gboolean
+can_create_environment (const char *session_id)
+{
+ char *path;
+ gboolean session_exists;
+
+ path = g_strdup_printf (GNOME_SESSION_SESSIONS_PATH "/%s.session", session_id);
+ session_exists = g_file_test (path, G_FILE_TEST_EXISTS);
+
+ g_free (path);
+
+ return session_exists;
+}
+
+static gboolean
+wants_initial_setup (GdmDisplay *self)
+{
+ gboolean enabled = FALSE;
+
+ /* don't run initial-setup on remote displays
+ */
+ if (!self->priv->is_local) {
+ return FALSE;
+ }
+
+ /* don't run if the system has existing users */
+ if (self->priv->have_existing_user_accounts) {
+ return FALSE;
+ }
+
+ /* don't run if initial-setup is unavailable */
+ if (!can_create_environment ("gnome-initial-setup")) {
+ return FALSE;
+ }
+
+ if (!gdm_settings_direct_get_boolean (GDM_KEY_INITIAL_SETUP_ENABLE, &enabled)) {
+ return FALSE;
+ }
+
+ return enabled;
+}
+
void
gdm_display_set_up_greeter_session (GdmDisplay *self,
char **username)
{
- gdm_slave_set_up_greeter_session (self->priv->slave, username);
+ self->priv->doing_initial_setup = wants_initial_setup (self);
+
+ if (self->priv->doing_initial_setup) {
+ *username = g_strdup (INITIAL_SETUP_USERNAME);
+ } else {
+ *username = g_strdup (GDM_USERNAME);
+ }
}
void
gdm_display_start_greeter_session (GdmDisplay *self)
{
- gdm_slave_start_greeter_session (self->priv->slave);
+ char *display_name;
+ char *seat_id;
+ char *hostname;
+ char *auth_file;
+
+ g_debug ("GdmDisplay: Running greeter");
+
+ display_name = NULL;
+ seat_id = NULL;
+ hostname = NULL;
+
+ g_object_get (self,
+ "x11-display-name", &display_name,
+ "seat-id", &seat_id,
+ "remote-hostname", &hostname,
+ NULL);
+ auth_file = gdm_display_access_file_get_path (self->priv->access_file);
+
+ g_debug ("GdmDisplay: Creating greeter for %s %s", display_name, hostname);
+
+ g_signal_connect (self->priv->launch_environment,
+ "opened",
+ G_CALLBACK (on_launch_environment_session_opened),
+ self);
+ g_signal_connect (self->priv->launch_environment,
+ "started",
+ G_CALLBACK (on_launch_environment_session_started),
+ self);
+ g_signal_connect (self->priv->launch_environment,
+ "stopped",
+ G_CALLBACK (on_launch_environment_session_stopped),
+ self);
+ g_signal_connect (self->priv->launch_environment,
+ "exited",
+ G_CALLBACK (on_launch_environment_session_exited),
+ self);
+ g_signal_connect (self->priv->launch_environment,
+ "died",
+ G_CALLBACK (on_launch_environment_session_died),
+ self);
+
+ g_object_set (self->priv->launch_environment,
+ "x11-authority-file", auth_file,
+ NULL);
+
+ gdm_launch_environment_start (self->priv->launch_environment);
+
+ g_free (display_name);
+ g_free (seat_id);
+ g_free (hostname);
+ g_free (auth_file);
+}
+
+static void
+chown_initial_setup_home_dir (void)
+{
+ GFile *dir;
+ GError *error;
+ char *gis_dir_path;
+ char *gis_uid_path;
+ char *gis_uid_contents;
+ struct passwd *pwe;
+ uid_t uid;
+
+ if (!gdm_get_pwent_for_name (INITIAL_SETUP_USERNAME, &pwe)) {
+ g_warning ("Unknown user %s", INITIAL_SETUP_USERNAME);
+ return;
+ }
+
+ gis_dir_path = g_strdup (pwe->pw_dir);
+
+ gis_uid_path = g_build_filename (gis_dir_path,
+ "gnome-initial-setup-uid",
+ NULL);
+ if (!g_file_get_contents (gis_uid_path, &gis_uid_contents, NULL, NULL)) {
+ g_warning ("Unable to read %s", gis_uid_path);
+ goto out;
+ }
+
+ uid = (uid_t) atoi (gis_uid_contents);
+ pwe = getpwuid (uid);
+ if (uid == 0 || pwe == NULL) {
+ g_warning ("UID '%s' in %s is not valid", gis_uid_contents, gis_uid_path);
+ goto out;
+ }
+
+ error = NULL;
+ dir = g_file_new_for_path (gis_dir_path);
+ if (!chown_recursively (dir, pwe->pw_uid, pwe->pw_gid, &error)) {
+ g_warning ("Failed to change ownership for %s: %s", gis_dir_path, error->message);
+ g_error_free (error);
+ }
+ g_object_unref (dir);
+out:
+ g_free (gis_uid_contents);
+ g_free (gis_uid_path);
+ g_free (gis_dir_path);
}
void
gdm_display_stop_greeter_session (GdmDisplay *self)
{
- gdm_slave_stop_greeter_session (self->priv->slave);
+ if (self->priv->launch_environment != NULL) {
+ gdm_launch_environment_stop (self->priv->launch_environment);
+ g_clear_object (&self->priv->launch_environment);
+ }
+
+ if (self->priv->doing_initial_setup) {
+ chown_initial_setup_home_dir ();
+ }
}
GdmSlave *