[gdm] daemon: Add initial setup integration
- From: Jasper St. Pierre <jstpierre src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gdm] daemon: Add initial setup integration
- Date: Wed, 1 Aug 2012 15:21:39 +0000 (UTC)
commit 4e2a75a1fb0932e346cfe5a2fe350b684b867463
Author: Jasper St. Pierre <jstpierre mecheye net>
Date: Tue Jul 17 18:16:56 2012 -0400
daemon: Add initial setup integration
When a system boots for the first time, we want to show a special
tool that will allow the user to set up their system the way they
want to. This will be triggered by a special file:
/var/run/wants-initial-setup
The responsibilities of this tool include creating the user's
account, so we have to create a special user account to run the
tool under.
Administrators are given the ability to turn this off in a GDM
setting if they want to.
https://bugzilla.gnome.org/show_bug.cgi?id=678057
common/gdm-settings-keys.h | 1 +
daemon/Makefile.am | 1 +
daemon/gdm-simple-slave.c | 229 +++++++++++++++++++++++++++++++++++++-------
data/gdm.schemas.in.in | 5 +
4 files changed, 201 insertions(+), 35 deletions(-)
---
diff --git a/common/gdm-settings-keys.h b/common/gdm-settings-keys.h
index 65a1628..e908c64 100644
--- a/common/gdm-settings-keys.h
+++ b/common/gdm-settings-keys.h
@@ -32,6 +32,7 @@ G_BEGIN_DECLS
#define GDM_KEY_TIMED_LOGIN_ENABLE "daemon/TimedLoginEnable"
#define GDM_KEY_TIMED_LOGIN_USER "daemon/TimedLogin"
#define GDM_KEY_TIMED_LOGIN_DELAY "daemon/TimedLoginDelay"
+#define GDM_KEY_INITIAL_SETUP_ENABLE "daemon/InitialSetupEnable"
#define GDM_KEY_DEBUG "debug/Enable"
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 1e497e5..8e74620 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -12,6 +12,7 @@ AM_CPPFLAGS = \
-DGDMCONFDIR=\"$(gdmconfdir)\" \
-DLIBDIR=\"$(libdir)\" \
-DLIBEXECDIR=\"$(libexecdir)\" \
+ -DLOCALSTATEDIR=\"$(localstatedir)\" \
-DLOGDIR=\"$(logdir)\" \
-DSBINDIR=\"$(sbindir)\" \
-DGNOMELOCALEDIR=\""$(datadir)/locale"\" \
diff --git a/daemon/gdm-simple-slave.c b/daemon/gdm-simple-slave.c
index c00fd80..f0f27b4 100644
--- a/daemon/gdm-simple-slave.c
+++ b/daemon/gdm-simple-slave.c
@@ -40,6 +40,8 @@
#include <X11/Xlib.h> /* for Display */
+#include <act/act-user-manager.h>
+
#include "gdm-common.h"
#include "gdm-settings-client.h"
@@ -62,6 +64,8 @@
#define MAX_CONNECT_ATTEMPTS 10
#define DEFAULT_PING_INTERVAL 15
+#define INITIAL_SETUP_USERNAME "gdm-initial-setup"
+
struct GdmSimpleSlavePrivate
{
GPid pid;
@@ -107,7 +111,6 @@ static void gdm_simple_slave_finalize (GObject *object);
G_DEFINE_TYPE (GdmSimpleSlave, gdm_simple_slave, GDM_TYPE_SLAVE)
static void create_new_session (GdmSimpleSlave *slave);
-static void start_greeter (GdmSimpleSlave *slave);
static void start_session (GdmSimpleSlave *slave);
static void queue_start_session (GdmSimpleSlave *slave,
const char *service_name);
@@ -949,34 +952,59 @@ setup_server (GdmSimpleSlave *slave)
}
static GdmLaunchEnvironment *
-create_greeter_environment (const char *display_name,
- const char *seat_id,
- const char *display_device,
- const char *display_hostname,
- gboolean display_is_local)
+create_environment (const char *session_id,
+ const char *user_name,
+ const char *display_name,
+ const char *seat_id,
+ const char *display_device,
+ const char *display_hostname,
+ gboolean display_is_local)
{
gboolean debug = FALSE;
- char *command = BINDIR "/gnome-session -f";
+ char *command;
+ GdmLaunchEnvironment *launch_environment;
+ char **argv;
+ GPtrArray *args;
gdm_settings_direct_get_boolean (GDM_KEY_DEBUG, &debug);
+ args = g_ptr_array_new ();
+ g_ptr_array_add (args, BINDIR "/gnome-session -f");
+
if (debug) {
- command = BINDIR "/gnome-session -f --debug";
+ g_ptr_array_add (args, "--debug");
+ }
+
+ if (session_id != NULL) {
+ g_ptr_array_add (args, " --session=");
+ g_ptr_array_add (args, (char *) session_id);
}
- return g_object_new (GDM_TYPE_LAUNCH_ENVIRONMENT,
- "command", command,
- "x11-display-name", display_name,
- "x11-display-seat-id", seat_id,
- "x11-display-device", display_device,
- "x11-display-hostname", display_hostname,
- "x11-display-is-local", display_is_local,
- "runtime-dir", GDM_SCREENSHOT_DIR,
- NULL);
+ g_ptr_array_add (args, NULL);
+
+ argv = (char **) g_ptr_array_free (args, FALSE);
+ command = g_strjoinv (" ", argv);
+ g_free (argv);
+
+ launch_environment = g_object_new (GDM_TYPE_LAUNCH_ENVIRONMENT,
+ "command", command,
+ "user-name", user_name,
+ "x11-display-name", display_name,
+ "x11-display-seat-id", seat_id,
+ "x11-display-device", display_device,
+ "x11-display-hostname", display_hostname,
+ "x11-display-is-local", display_is_local,
+ "runtime-dir", GDM_SCREENSHOT_DIR,
+ NULL);
+
+ g_free (command);
+ return launch_environment;
}
static void
-start_greeter (GdmSimpleSlave *slave)
+start_launch_environment (GdmSimpleSlave *slave,
+ char *username,
+ char *session_id)
{
gboolean display_is_local;
char *display_id;
@@ -1027,11 +1055,13 @@ start_greeter (GdmSimpleSlave *slave)
gdm_slave_run_script (GDM_SLAVE (slave), GDMCONFDIR "/Init", GDM_USERNAME);
g_debug ("GdmSimpleSlave: Creating greeter on %s %s %s", display_name, display_device, display_hostname);
- slave->priv->greeter_environment = create_greeter_environment (display_name,
- seat_id,
- display_device,
- display_hostname,
- display_is_local);
+ slave->priv->greeter_environment = create_environment (session_id,
+ GDM_USERNAME,
+ display_name,
+ seat_id,
+ display_device,
+ display_hostname,
+ display_is_local);
g_signal_connect (slave->priv->greeter_environment,
"opened",
G_CALLBACK (on_greeter_environment_session_opened),
@@ -1066,6 +1096,142 @@ start_greeter (GdmSimpleSlave *slave)
g_free (auth_file);
}
+static void
+start_greeter (GdmSimpleSlave *slave)
+{
+ start_launch_environment (slave, GDM_USERNAME, NULL);
+}
+
+#define RULES_DIR LOCALSTATEDIR "/lib/polkit-1/localauthority/10-vendor.d/"
+#define RULES_FILE "20-gnome-initial-setup.rules"
+
+static const gboolean
+create_initial_setup_user (GdmSimpleSlave *slave)
+{
+ gboolean ret = TRUE;
+ ActUserManager *act;
+ ActUser *user;
+ const char *username;
+ GFile *src_file, *dest_file;
+ GError *error = NULL;
+ const char *e = NULL;
+
+ username = "gnome-initial-setup";
+
+ /* First, create the user */
+ act = act_user_manager_get_default ();
+
+ user = act_user_manager_create_user (act, username, "", 0, &error);
+ if (user == NULL) {
+ if (g_dbus_error_is_remote_error (error)) {
+ e = g_dbus_error_get_remote_error (error);
+ }
+
+ g_warning ("Creating user '%s' failed: %s / %s", username, e, error->message);
+
+ if (g_strcmp0 (e, "org.freedesktop.Accounts.Error.UserExists") != 0) {
+ ret = FALSE;
+ goto out;
+ }
+ } else {
+ g_object_unref (user);
+ }
+
+ /* Now, make sure the PolicyKit policy is in place */
+ src_file = g_file_new_for_path (DATADIR "/gnome-initial-setup" RULES_FILE);
+ dest_file = g_file_new_for_path (RULES_DIR RULES_FILE);
+
+ if (!g_file_copy (src_file,
+ dest_file,
+ G_FILE_COPY_OVERWRITE,
+ NULL, NULL, NULL, &error)) {
+ g_warning ("Failed to copy '%s' to '%s': %s",
+ g_file_get_path (src_file),
+ g_file_get_path (dest_file),
+ error->message);
+ ret = FALSE;
+ goto out_clear_files;
+ }
+
+ out_clear_files:
+ g_object_unref (src_file);
+ g_object_unref (dest_file);
+
+ out:
+ g_clear_pointer (&e, g_free);
+ g_clear_error (&error);
+ return ret;
+}
+
+static void
+destroy_initial_setup_user (GdmSimpleSlave *slave)
+{
+ ActUserManager *act;
+ ActUser *user;
+ const char *username;
+ const char *filename;
+ GError *error;
+
+ username = "gnome-initial-setup";
+ filename = RULES_DIR RULES_FILE;
+
+ if (g_remove (filename) < 0) {
+ g_warning ("Failed to remove '%s': %s", filename, g_strerror (errno));
+ }
+
+ act = act_user_manager_get_default ();
+
+ error = NULL;
+ user = act_user_manager_get_user (act, username);
+ if (!act_user_manager_delete_user (act, user, TRUE, &error)) {
+ g_warning ("Failed to create user '%s': %s", username, error->message);
+ g_error_free (error);
+ }
+
+ g_object_unref (user);
+}
+
+static void
+start_initial_setup (GdmSimpleSlave *slave)
+{
+ create_initial_setup_user (slave);
+ start_launch_environment (slave, INITIAL_SETUP_USERNAME, "gnome-initial-setup");
+ destroy_initial_setup_user (slave);
+}
+
+static gboolean
+wants_autologin (GdmSimpleSlave *slave)
+{
+ gboolean enabled = FALSE;
+ int delay = 0;
+ /* FIXME: handle wait-for-go */
+
+ gdm_slave_get_timed_login_details (GDM_SLAVE (slave), &enabled, NULL, &delay);
+ return enabled && delay > 0;
+}
+
+#define INITIAL_SETUP_TRIGGER_FILE LOCALSTATEDIR "lib/gdm/run-initial-setup"
+
+static gboolean
+wants_initial_setup (GdmSimpleSlave *slave)
+{
+ gboolean enabled;
+
+ if (!g_file_test (INITIAL_SETUP_TRIGGER_FILE, G_FILE_TEST_EXISTS)) {
+ return FALSE;
+ }
+
+ if (!gdm_settings_direct_get_boolean (GDM_KEY_INITIAL_SETUP_ENABLE, &enabled)) {
+ return FALSE;
+ }
+
+ if (!enabled) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
static gboolean
idle_connect_to_display (GdmSimpleSlave *slave)
{
@@ -1075,23 +1241,16 @@ idle_connect_to_display (GdmSimpleSlave *slave)
res = gdm_slave_connect_to_x11_display (GDM_SLAVE (slave));
if (res) {
- gboolean enabled;
- int delay;
-
- /* FIXME: handle wait-for-go */
-
setup_server (slave);
- delay = 0;
- enabled = FALSE;
- gdm_slave_get_timed_login_details (GDM_SLAVE (slave), &enabled, NULL, &delay);
- if (! enabled || delay > 0) {
- start_greeter (slave);
- } else {
+ if (wants_initial_setup (slave)) {
+ start_initial_setup (slave);
+ } else if (wants_autologin (slave)) {
/* Run the init script. gdmslave suspends until script has terminated */
gdm_slave_run_script (GDM_SLAVE (slave), GDMCONFDIR "/Init", GDM_USERNAME);
+ } else {
+ start_greeter (slave);
}
-
create_new_session (slave);
} else {
if (slave->priv->connection_attempts >= MAX_CONNECT_ATTEMPTS) {
diff --git a/data/gdm.schemas.in.in b/data/gdm.schemas.in.in
index 514117d..f049c2f 100644
--- a/data/gdm.schemas.in.in
+++ b/data/gdm.schemas.in.in
@@ -47,6 +47,11 @@
<signature>i</signature>
<default>30</default>
</schema>
+ <schema>
+ <key>daemon/InitialSetupEnable</key>
+ <signature>b</signature>
+ <default>false</default>
+ </schema>
<schema>
<key>debug/Enable</key>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]