From 24cb017c045545ac6b239ea28fe005b993e180e5 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 17 May 2011 12:44:22 -0400 Subject: Allow alternative welcome sessions --- common/gdm-settings-keys.h | 1 + daemon/Makefile.am | 3 + daemon/gdm-display.c | 32 ++++ daemon/gdm-display.h | 4 + daemon/gdm-display.xml | 3 + daemon/gdm-session-direct.c | 6 +- daemon/gdm-session-worker.c | 4 +- daemon/gdm-session.c | 3 +- daemon/gdm-session.h | 2 + daemon/gdm-setup-session.c | 162 ++++++++++++++++++++ daemon/gdm-setup-session.h | 61 ++++++++ daemon/gdm-simple-slave.c | 353 +++++++++++++++++++++++++++++++++++++++++-- daemon/gdm-slave.c | 51 ++++++- daemon/gdm-slave.h | 3 + daemon/gdm-welcome-session.c | 34 ++++- data/gdm.schemas.in.in | 5 + 16 files changed, 703 insertions(+), 24 deletions(-) create mode 100644 daemon/gdm-setup-session.c create mode 100644 daemon/gdm-setup-session.h diff --git a/common/gdm-settings-keys.h b/common/gdm-settings-keys.h index 65a16280..e908c642 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 ffbaf9b0..328db904 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"\" \ @@ -120,6 +121,8 @@ gdm_simple_slave_SOURCES = \ gdm-welcome-session.h \ gdm-greeter-session.c \ gdm-greeter-session.h \ + gdm-setup-session.c \ + gdm-setup-session.h \ gdm-server.c \ gdm-server.h \ gdm-session.c \ diff --git a/daemon/gdm-display.c b/daemon/gdm-display.c index e885bdfb..d4b80cd1 100644 --- a/daemon/gdm-display.c +++ b/daemon/gdm-display.c @@ -395,6 +395,37 @@ gdm_display_get_timed_login_details (GdmDisplay *display, return TRUE; } +static void +gdm_display_real_get_initial_setup_details (GdmDisplay *display, + gboolean *enabledp) +{ + gboolean enabled; + gboolean res; + + enabled = FALSE; + + res = gdm_settings_direct_get_boolean (GDM_KEY_INITIAL_SETUP_ENABLE, &enabled); + + if (enabledp != NULL) { + *enabledp = enabled; + } +} + +gboolean +gdm_display_get_initial_setup_details (GdmDisplay *display, + gboolean *enabled) +{ + g_return_val_if_fail (GDM_IS_DISPLAY (display), FALSE); + + GDM_DISPLAY_GET_CLASS (display)->get_initial_setup_details (display, enabled); + + g_debug ("GdmSlave: Got initial setup details for display %s: %d", + display->priv->x11_display_name, + *enabled); + + return TRUE; +} + static gboolean gdm_display_real_remove_user_authorization (GdmDisplay *display, const char *username, @@ -1030,6 +1061,7 @@ gdm_display_class_init (GdmDisplayClass *klass) klass->remove_user_authorization = gdm_display_real_remove_user_authorization; klass->set_slave_bus_name = gdm_display_real_set_slave_bus_name; klass->get_timed_login_details = gdm_display_real_get_timed_login_details; + klass->get_initial_setup_details = gdm_display_real_get_initial_setup_details; klass->prepare = gdm_display_real_prepare; klass->manage = gdm_display_real_manage; klass->finish = gdm_display_real_finish; diff --git a/daemon/gdm-display.h b/daemon/gdm-display.h index 607ea1d4..474a771d 100644 --- a/daemon/gdm-display.h +++ b/daemon/gdm-display.h @@ -74,6 +74,8 @@ typedef struct gboolean *enabled, char **username, int *delay); + void (*get_initial_setup_details) (GdmDisplay *display, + gboolean *enabled); } GdmDisplayClass; typedef enum @@ -122,6 +124,8 @@ gboolean gdm_display_get_timed_login_details (GdmDisplay *disp char **username, int *delay, GError **error); +gboolean gdm_display_get_initial_setup_details (GdmDisplay *display, + gboolean *enabled); /* exported but protected */ gboolean gdm_display_get_x11_cookie (GdmDisplay *display, diff --git a/daemon/gdm-display.xml b/daemon/gdm-display.xml index a92e37fc..87ea7c25 100644 --- a/daemon/gdm-display.xml +++ b/daemon/gdm-display.xml @@ -40,5 +40,8 @@ + + + diff --git a/daemon/gdm-session-direct.c b/daemon/gdm-session-direct.c index 9f750f25..c5be7991 100644 --- a/daemon/gdm-session-direct.c +++ b/daemon/gdm-session-direct.c @@ -1406,6 +1406,7 @@ do_introspect (DBusConnection *connection, " \n" " \n" " \n" + " \n" " \n" " \n" " \n" @@ -2108,6 +2109,7 @@ send_setup_for_user (GdmSessionDirect *session, static void send_setup_for_program (GdmSessionDirect *session, const char *service_name, + const char *username, const char *log_file) { DBusMessage *message; @@ -2155,6 +2157,7 @@ send_setup_for_program (GdmSessionDirect *session, dbus_message_iter_init_append (message, &iter); dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &service_name); + dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &username); dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_name); dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_device); dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_seat_id); @@ -2201,13 +2204,14 @@ gdm_session_direct_setup_for_user (GdmSession *session, static void gdm_session_direct_setup_for_program (GdmSession *session, const char *service_name, + const char *username, const char *log_file) { GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); g_return_if_fail (session != NULL); - send_setup_for_program (impl, service_name, log_file); + send_setup_for_program (impl, service_name, username, log_file); } static void diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c index 57f10718..a314c92d 100644 --- a/daemon/gdm-session-worker.c +++ b/daemon/gdm-session-worker.c @@ -2643,6 +2643,7 @@ on_setup_for_program (GdmSessionWorker *worker, { DBusError error; char *service; + char *username; char *x11_display_name; char *console; char *seat_id; @@ -2660,6 +2661,7 @@ on_setup_for_program (GdmSessionWorker *worker, res = dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &service, + DBUS_TYPE_STRING, &username, DBUS_TYPE_STRING, &x11_display_name, DBUS_TYPE_STRING, &console, DBUS_TYPE_STRING, &seat_id, @@ -2672,7 +2674,7 @@ on_setup_for_program (GdmSessionWorker *worker, queue_state_change (worker); worker->priv->service = g_strdup (service); - worker->priv->username = g_strdup (GDM_USERNAME); + worker->priv->username = g_strdup (username); worker->priv->x11_display_name = g_strdup (x11_display_name); worker->priv->hostname = g_strdup (hostname); worker->priv->display_device = g_strdup (console); diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c index 5ba9fd1a..8f085752 100644 --- a/daemon/gdm-session.c +++ b/daemon/gdm-session.c @@ -128,11 +128,12 @@ gdm_session_setup_for_user (GdmSession *session, void gdm_session_setup_for_program (GdmSession *session, const char *service_name, + const char *username, const char *log_file) { g_return_if_fail (GDM_IS_SESSION (session)); - GDM_SESSION_GET_IFACE (session)->setup_for_program (session, service_name, log_file); + GDM_SESSION_GET_IFACE (session)->setup_for_program (session, service_name, username, log_file); } void diff --git a/daemon/gdm-session.h b/daemon/gdm-session.h index 17accb28..5716f89e 100644 --- a/daemon/gdm-session.h +++ b/daemon/gdm-session.h @@ -58,6 +58,7 @@ struct _GdmSessionIface const char *username); void (* setup_for_program) (GdmSession *session, const char *service_name, + const char *username, const char *log_file); void (* set_environment_variable) (GdmSession *session, const char *key, @@ -169,6 +170,7 @@ void gdm_session_setup_for_user (GdmSession *session, const char *username); void gdm_session_setup_for_program (GdmSession *session, const char *service_name, + const char *username, const char *log_file); void gdm_session_set_environment_variable (GdmSession *session, const char *key, diff --git a/daemon/gdm-setup-session.c b/daemon/gdm-setup-session.c new file mode 100644 index 00000000..d8bbefc2 --- /dev/null +++ b/daemon/gdm-setup-session.c @@ -0,0 +1,162 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2011 Red Hat, Inc. + * Author: Matthias Clasen + * + * 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 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "gdm-welcome-session.h" +#include "gdm-setup-session.h" + +#define GDM_GREETER_SERVER_DBUS_PATH "/org/gnome/DisplayManager/GreeterServer" +#define GDM_GREETER_SERVER_DBUS_INTERFACE "org.gnome.DisplayManager.GreeterServer" + +#define GDM_SETUP_SESSION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_SETUP_SESSION, GdmSetupSessionPrivate)) + +struct GdmSetupSessionPrivate +{ + gpointer dummy; +}; + +enum { + PROP_0, +}; + +static void gdm_setup_session_class_init (GdmSetupSessionClass *klass); +static void gdm_setup_session_init (GdmSetupSession *setup_session); +static void gdm_setup_session_finalize (GObject *object); + +G_DEFINE_TYPE (GdmSetupSession, gdm_setup_session, GDM_TYPE_WELCOME_SESSION) + +static void +gdm_setup_session_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gdm_setup_session_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GObject * +gdm_setup_session_constructor (GType type, + guint n_construct_properties, + GObjectConstructParam *construct_properties) +{ + GdmSetupSession *setup_session; + + setup_session = GDM_SETUP_SESSION (G_OBJECT_CLASS (gdm_setup_session_parent_class)->constructor (type, + n_construct_properties, + construct_properties)); + + return G_OBJECT (setup_session); +} + +static void +gdm_setup_session_class_init (GdmSetupSessionClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->get_property = gdm_setup_session_get_property; + object_class->set_property = gdm_setup_session_set_property; + object_class->constructor = gdm_setup_session_constructor; + object_class->finalize = gdm_setup_session_finalize; + + g_type_class_add_private (klass, sizeof (GdmSetupSessionPrivate)); +} + +static void +gdm_setup_session_init (GdmSetupSession *setup_session) +{ + setup_session->priv = GDM_SETUP_SESSION_GET_PRIVATE (setup_session); +} + +static void +gdm_setup_session_finalize (GObject *object) +{ + GdmSetupSession *setup_session; + + g_return_if_fail (object != NULL); + g_return_if_fail (GDM_IS_SETUP_SESSION (object)); + + setup_session = GDM_SETUP_SESSION (object); + + g_return_if_fail (setup_session->priv != NULL); + + G_OBJECT_CLASS (gdm_setup_session_parent_class)->finalize (object); +} + +GdmSetupSession * +gdm_setup_session_new (const char *display_name, + const char *seat_id, + const char *display_device, + const char *display_hostname, + gboolean display_is_local) +{ + GObject *object; + + object = g_object_new (GDM_TYPE_SETUP_SESSION, + "command", BINDIR "/gnome-session --debug --session gdm-setup", + "log-file", ".xsession-errors", + "server-dbus-path", GDM_GREETER_SERVER_DBUS_PATH, + "server-dbus-interface", GDM_GREETER_SERVER_DBUS_INTERFACE, + "server-env-var-name", "GDM_GREETER_DBUS_ADDRESS", + "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); + + return GDM_SETUP_SESSION (object); +} diff --git a/daemon/gdm-setup-session.h b/daemon/gdm-setup-session.h new file mode 100644 index 00000000..c674c6c1 --- /dev/null +++ b/daemon/gdm-setup-session.h @@ -0,0 +1,61 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2011 Red Hat, Inc. + * Author: Matthias Clasen + * + * 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 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + + +#ifndef __GDM_SETUP_SESSION_H +#define __GDM_SETUP_SESSION_H + +#include + +#include "gdm-welcome-session.h" + +G_BEGIN_DECLS + +#define GDM_TYPE_SETUP_SESSION (gdm_setup_session_get_type ()) +#define GDM_SETUP_SESSION(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_SETUP_SESSION, GdmSetupSession)) +#define GDM_SETUP_SESSION_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_SETUP_SESSION, GdmSetupSessionClass)) +#define GDM_IS_SETUP_SESSION(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_SETUP_SESSION)) +#define GDM_IS_SETUP_SESSION_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDM_TYPE_SETUP_SESSION)) +#define GDM_SETUP_SESSION_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDM_TYPE_SETUP_SESSION, GdmSetupSessionClass)) + +typedef struct GdmSetupSessionPrivate GdmSetupSessionPrivate; + +typedef struct +{ + GdmWelcomeSession parent; + GdmSetupSessionPrivate *priv; +} GdmSetupSession; + +typedef struct +{ + GdmWelcomeSessionClass parent_class; +} GdmSetupSessionClass; + +GType gdm_setup_session_get_type (void); +GdmSetupSession * gdm_setup_session_new (const char *display_name, + const char *seat_id, + const char *display_device, + const char *display_hostname, + gboolean display_is_local); + +G_END_DECLS + +#endif /* __GDM_SETUP_SESSION_H */ diff --git a/daemon/gdm-simple-slave.c b/daemon/gdm-simple-slave.c index 9d1347ad..8f296dc1 100644 --- a/daemon/gdm-simple-slave.c +++ b/daemon/gdm-simple-slave.c @@ -36,8 +36,11 @@ #include #include #include +#include #include +#include + #define DBUS_API_SUBJECT_TO_CHANGE #include #include @@ -57,6 +60,7 @@ #include "gdm-session-direct.h" #include "gdm-greeter-server.h" #include "gdm-greeter-session.h" +#include "gdm-setup-session.h" #include "gdm-settings-direct.h" #include "gdm-settings-keys.h" @@ -86,7 +90,7 @@ struct GdmSimpleSlavePrivate GdmSessionDirect *session; GdmGreeterServer *greeter_server; - GdmGreeterSession *greeter; + GdmWelcomeSession *greeter; guint start_session_when_ready : 1; guint waiting_to_start_session : 1; @@ -108,9 +112,12 @@ G_DEFINE_TYPE (GdmSimpleSlave, gdm_simple_slave, GDM_TYPE_SLAVE) static void create_new_session (GdmSimpleSlave *slave); static void destroy_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); +static void run_initial_setup (GdmSimpleSlave *slave); + +static gboolean check_initial_setup_request (GdmSimpleSlave *slave); +static void clear_initial_setup_request (GdmSimpleSlave *slave); static void on_session_started (GdmSession *session, @@ -1228,7 +1235,7 @@ start_greeter (GdmSimpleSlave *slave) char *display_hostname; char *auth_file; char *address; - gboolean res; + gboolean res G_GNUC_UNUSED; g_debug ("GdmSimpleSlave: Running greeter"); @@ -1327,11 +1334,11 @@ start_greeter (GdmSimpleSlave *slave) gdm_greeter_server_start (slave->priv->greeter_server); g_debug ("GdmSimpleSlave: Creating greeter on %s %s %s", display_name, display_device, display_hostname); - slave->priv->greeter = gdm_greeter_session_new (display_name, - seat_id, - display_device, - display_hostname, - display_is_local); + slave->priv->greeter = (GdmWelcomeSession*)gdm_greeter_session_new (display_name, + seat_id, + display_device, + display_hostname, + display_is_local); g_signal_connect (slave->priv->greeter, "started", G_CALLBACK (on_greeter_session_start), @@ -1365,6 +1372,313 @@ start_greeter (GdmSimpleSlave *slave) g_free (auth_file); } +static const gboolean +create_initial_setup_user (GdmSimpleSlave *slave) +{ + ActUserManager *act; + ActUser *user; + GError *error; + const gchar *username; + gboolean preexisting_user; + const gchar *src_filename; + const gchar *dest_filename; + + username = "gnome-initial-setup"; + src_filename = DATADIR "/gdm/" "20-gnome-initial-setup.pkla"; + dest_filename = LOCALSTATEDIR "/lib/polkit-1/localauthority/10-vendor.d/" "20-gnome-initial-setup.pkla"; + + preexisting_user = FALSE; + + /* First, create the user */ + act = act_user_manager_get_default (); + + error = NULL; + user = act_user_manager_create_user (act, username, "", 0, &error); + if (user == NULL) { + const gchar *e; + if (g_dbus_error_is_remote_error (error)) { + e = g_dbus_error_get_remote_error (error); + } else { + e = NULL; + } + + g_warning ("Creating user '%s' failed: %s / %s", username, e, error->message); + + if (g_strcmp0 (e, "org.freedesktop.Accounts.Error.UserExists") == 0) { + preexisting_user = TRUE; + } + else { + return FALSE; + } + } + else { + g_object_unref (user); + } + + /* Now, make sure the PolicyKit policy is in place */ + if (preexisting_user) { + if (!g_file_test (dest_filename, G_FILE_TEST_EXISTS)) { + g_warning ("User '%s' exists, but file '%s' doesn't", username, dest_filename); + return FALSE; + } + } + else { + gchar *contents; + gsize length; + GError *error; + + contents = NULL; + error = NULL; + if (!g_file_get_contents (src_filename, &contents, &length, &error)) { + g_warning ("Failed to read '%s': %s", src_filename, error->message); + g_error_free (error); + return FALSE; + } + if (!g_file_set_contents (dest_filename, contents, length, &error)) { + g_warning ("Failed to write '%s': %s", dest_filename, error->message); + g_error_free (error); + g_free (contents); + return FALSE; + } + g_free (contents); + } + + return TRUE; +} + +static void +remove_initial_setup_user (GdmSimpleSlave *slave) +{ + ActUserManager *act; + ActUser *user; + const gchar *username; + const gchar *filename; + GError *error; + + username = "gnome-initial-setup"; + filename = LOCALSTATEDIR "/lib/polkit-1/localauthority/10-vendor.d/" "20-gnome-initial-setup.pkla"; + + 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 +on_setup_session_stop (GdmGreeterSession *greeter, + GdmSimpleSlave *slave) +{ + g_debug ("GdmSimpleSlave: Setup stopped"); + clear_initial_setup_request (slave); + remove_initial_setup_user (slave); + + if (slave->priv->start_session_service_name == NULL) { + gdm_slave_stopped (GDM_SLAVE (slave)); + } else { + gdm_greeter_server_stop (slave->priv->greeter_server); + start_session (slave); + } + + g_object_unref (slave->priv->greeter); + slave->priv->greeter = NULL; +} + +static void +run_initial_setup (GdmSimpleSlave *slave) +{ + gboolean display_is_local; + char *display_id; + char *display_name; + char *seat_id; + char *display_device; + char *display_hostname; + char *auth_file; + char *address; + gboolean res G_GNUC_UNUSED; + + g_debug ("GdmSimpleSlave: Running initial setup"); + + display_is_local = FALSE; + display_id = NULL; + display_name = NULL; + seat_id = NULL; + auth_file = NULL; + display_device = NULL; + display_hostname = NULL; + + g_object_get (slave, + "display-id", &display_id, + "display-is-local", &display_is_local, + "display-name", &display_name, + "display-seat-id", &seat_id, + "display-hostname", &display_hostname, + NULL); + + g_debug ("GdmSimpleSlave: Creating initial setup for %s %s", display_name, display_hostname); + + if (slave->priv->server != NULL) { + display_device = gdm_server_get_display_device (slave->priv->server); + } + + /* FIXME: send a signal back to the master */ + + /* If XDMCP setup pinging */ + slave->priv->ping_interval = DEFAULT_PING_INTERVAL; + res = gdm_settings_direct_get_int (GDM_KEY_PING_INTERVAL, + &(slave->priv->ping_interval)); + + if ( ! display_is_local && slave->priv->ping_interval > 0) { + alarm (slave->priv->ping_interval); + } + + /* Run the init script. gdmslave suspends until script has terminated */ + gdm_slave_run_script (GDM_SLAVE (slave), GDMCONFDIR "/Init", GDM_USERNAME); + + slave->priv->greeter_server = gdm_greeter_server_new (display_id); + + /* tell the greeter_server which user to expect a call from */ + g_object_set (slave->priv->greeter_server, + "user-name", "gnome-initial-setup", + "group-name", "gnome-initial-setup", + NULL); + + gdm_slave_add_user_authorization (GDM_SLAVE (slave), + "gnome-initial-setup", + &auth_file); + + g_signal_connect (slave->priv->greeter_server, + "start-conversation", + G_CALLBACK (on_greeter_start_conversation), + slave); + g_signal_connect (slave->priv->greeter_server, + "begin-auto-login", + G_CALLBACK (on_greeter_begin_auto_login), + slave); + g_signal_connect (slave->priv->greeter_server, + "begin-verification", + G_CALLBACK (on_greeter_begin_verification), + slave); + g_signal_connect (slave->priv->greeter_server, + "begin-verification-for-user", + G_CALLBACK (on_greeter_begin_verification_for_user), + slave); + g_signal_connect (slave->priv->greeter_server, + "query-answer", + G_CALLBACK (on_greeter_answer), + slave); + g_signal_connect (slave->priv->greeter_server, + "session-selected", + G_CALLBACK (on_greeter_session_selected), + slave); + g_signal_connect (slave->priv->greeter_server, + "language-selected", + G_CALLBACK (on_greeter_language_selected), + slave); + g_signal_connect (slave->priv->greeter_server, + "user-selected", + G_CALLBACK (on_greeter_user_selected), + slave); + g_signal_connect (slave->priv->greeter_server, + "connected", + G_CALLBACK (on_greeter_connected), + slave); + g_signal_connect (slave->priv->greeter_server, + "disconnected", + G_CALLBACK (on_greeter_disconnected), + slave); + g_signal_connect (slave->priv->greeter_server, + "cancelled", + G_CALLBACK (on_greeter_cancel), + slave); + g_signal_connect (slave->priv->greeter_server, + "start-session-when-ready", + G_CALLBACK (on_start_session_when_ready), + slave); + + g_signal_connect (slave->priv->greeter_server, + "start-session-later", + G_CALLBACK (on_start_session_later), + slave); + + gdm_greeter_server_start (slave->priv->greeter_server); + + g_debug ("GdmSimpleSlave: Creating initial setup on %s %s %s", display_name, display_device, display_hostname); + slave->priv->greeter = (GdmWelcomeSession *)gdm_setup_session_new (display_name, + seat_id, + display_device, + display_hostname, + display_is_local); + + g_signal_connect (slave->priv->greeter, + "started", + G_CALLBACK (on_greeter_session_start), + slave); + g_signal_connect (slave->priv->greeter, + "stopped", + G_CALLBACK (on_setup_session_stop), + slave); + g_signal_connect (slave->priv->greeter, + "exited", + G_CALLBACK (on_greeter_session_exited), + slave); + g_signal_connect (slave->priv->greeter, + "died", + G_CALLBACK (on_greeter_session_died), + slave); + + /* tell the greeter which user to run as */ + g_object_set (slave->priv->greeter, + "user-name", "gnome-initial-setup", + "x11-authority-file", auth_file, + NULL); + + address = gdm_greeter_server_get_address (slave->priv->greeter_server); + gdm_welcome_session_set_server_address (GDM_WELCOME_SESSION (slave->priv->greeter), address); + g_free (address); + gdm_welcome_session_start (GDM_WELCOME_SESSION (slave->priv->greeter)); + + g_free (display_id); + g_free (display_name); + g_free (seat_id); + g_free (display_device); + g_free (display_hostname); + g_free (auth_file); +} + +static gboolean +check_initial_setup_request (GdmSimpleSlave *slave) +{ + const gchar *filename; + + filename = GDMCONFDIR "/run-initial-setup"; + if (g_file_test (filename, G_FILE_TEST_EXISTS)) { + return TRUE; + } + + return FALSE; +} + +static void +clear_initial_setup_request (GdmSimpleSlave *slave) +{ + const gchar *filename; + + filename = GDMCONFDIR "/run-initial-setup"; + if (g_remove (filename) < 0) { + g_warning ("Failed to remove %s: %s", filename, strerror (errno)); + } +} + static gboolean idle_connect_to_display (GdmSimpleSlave *slave) { @@ -1374,17 +1688,28 @@ idle_connect_to_display (GdmSimpleSlave *slave) res = gdm_slave_connect_to_x11_display (GDM_SLAVE (slave)); if (res) { - gboolean enabled; - int delay; + gboolean timed_login_enabled; + int timed_login_delay; + gboolean initial_setup_enabled; + gboolean initial_setup_requested; /* 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) { + initial_setup_enabled = FALSE; + initial_setup_requested = FALSE; + gdm_slave_get_initial_setup_details (GDM_SLAVE (slave), &initial_setup_enabled); + initial_setup_requested = check_initial_setup_request (slave); + + timed_login_delay = 0; + timed_login_enabled = FALSE; + gdm_slave_get_timed_login_details (GDM_SLAVE (slave), &timed_login_enabled, NULL, &timed_login_delay); + if (initial_setup_enabled && initial_setup_requested) { + create_initial_setup_user (slave); + run_initial_setup (slave); + create_new_session (slave); + } else if (! timed_login_enabled || timed_login_delay > 0) { start_greeter (slave); create_new_session (slave); } else { diff --git a/daemon/gdm-slave.c b/daemon/gdm-slave.c index a5ce62f4..f302eda3 100644 --- a/daemon/gdm-slave.c +++ b/daemon/gdm-slave.c @@ -510,11 +510,15 @@ gdm_slave_setup_xhost_auth (XHostAddress *host_entries, XServerInterpretedAddres si_entries[0].typelength = strlen ("localuser"); si_entries[1].type = "localuser"; si_entries[1].typelength = strlen ("localuser"); + si_entries[2].type = "localuser"; + si_entries[2].typelength = strlen ("localuser"); si_entries[0].value = "root"; si_entries[0].valuelength = strlen ("root"); si_entries[1].value = GDM_USERNAME; si_entries[1].valuelength = strlen (GDM_USERNAME); + si_entries[2].value = "gnome-initial-setup"; + si_entries[2].valuelength = strlen ("gnome-initial-setup"); host_entries[0].family = FamilyServerInterpreted; host_entries[0].address = (char *) &si_entries[0]; @@ -522,6 +526,9 @@ gdm_slave_setup_xhost_auth (XHostAddress *host_entries, XServerInterpretedAddres host_entries[1].family = FamilyServerInterpreted; host_entries[1].address = (char *) &si_entries[1]; host_entries[1].length = sizeof (XServerInterpretedAddress); + host_entries[2].family = FamilyServerInterpreted; + host_entries[2].address = (char *) &si_entries[2]; + host_entries[2].length = sizeof (XServerInterpretedAddress); } static void @@ -637,8 +644,8 @@ gdm_slave_connect_to_x11_display (GdmSlave *slave) g_warning ("Unable to connect to display %s", slave->priv->display_name); ret = FALSE; } else if (slave->priv->display_is_local) { - XServerInterpretedAddress si_entries[2]; - XHostAddress host_entries[2]; + XServerInterpretedAddress si_entries[3]; + XHostAddress host_entries[3]; g_debug ("GdmSlave: Connected to display %s", slave->priv->display_name); ret = TRUE; @@ -952,8 +959,8 @@ gdm_slave_add_user_authorization (GdmSlave *slave, const char *username, char **filenamep) { - XServerInterpretedAddress si_entries[2]; - XHostAddress host_entries[2]; + XServerInterpretedAddress si_entries[3]; + XHostAddress host_entries[3]; gboolean res; GError *error; char *filename; @@ -1176,6 +1183,42 @@ gdm_slave_get_timed_login_details (GdmSlave *slave, return res; } +gboolean +gdm_slave_get_initial_setup_details (GdmSlave *slave, + gboolean *enabledp) +{ + GError *error; + gboolean res; + gboolean enabled; + + g_debug ("GdmSlave: Requesting initial setup details"); + + error = NULL; + res = dbus_g_proxy_call (slave->priv->display_proxy, + "GetInitialSetupDetails", + &error, + G_TYPE_INVALID, + G_TYPE_BOOLEAN, &enabled, + G_TYPE_INVALID); + + if (! res) { + if (error != NULL) { + g_warning ("Failed to get initial setup details: %s", error->message); + g_error_free (error); + } else { + g_warning ("Failed to get initial setup details"); + } + } else { + g_debug ("GdmSlave: Got initial setup details: %d", enabled); + } + + if (enabledp != NULL) { + *enabledp = enabled; + } + + return res; +} + static gboolean _get_uid_and_gid_for_user (const char *username, uid_t *uid, diff --git a/daemon/gdm-slave.h b/daemon/gdm-slave.h index 7af20edf..9020b8c7 100644 --- a/daemon/gdm-slave.h +++ b/daemon/gdm-slave.h @@ -65,6 +65,9 @@ gboolean gdm_slave_get_timed_login_details (GdmSlave *slave, char **username, int *delay); +gboolean gdm_slave_get_initial_setup_details (GdmSlave *slave, + gboolean *enabled); + gboolean gdm_slave_add_user_authorization (GdmSlave *slave, const char *username, char **filename); diff --git a/daemon/gdm-welcome-session.c b/daemon/gdm-welcome-session.c index 778d5dce..055cc03b 100644 --- a/daemon/gdm-welcome-session.c +++ b/daemon/gdm-welcome-session.c @@ -59,6 +59,7 @@ struct GdmWelcomeSessionPrivate { GdmSession *session; char *command; + char *log_file; GPid pid; char *user_name; @@ -94,6 +95,7 @@ enum { PROP_RUNTIME_DIR, PROP_SERVER_ADDRESS, PROP_COMMAND, + PROP_LOG_FILE, PROP_SERVER_DBUS_PATH, PROP_SERVER_DBUS_INTERFACE, PROP_SERVER_ENV_VAR_NAME @@ -771,12 +773,17 @@ on_conversation_started (GdmSession *session, char *log_path; char *log_file; - log_file = g_strdup_printf ("%s-greeter.log", welcome_session->priv->x11_display_name); - log_path = g_build_filename (LOGDIR, log_file, NULL); - g_free (log_file); + if (welcome_session->priv->log_file == NULL) { + log_file = g_strdup_printf ("%s-greeter.log", welcome_session->priv->x11_display_name); + log_path = g_build_filename (LOGDIR, log_file, NULL); + g_free (log_file); + } else { + log_path = g_strdup (welcome_session->priv->log_file); + } gdm_session_setup_for_program (GDM_SESSION (welcome_session->priv->session), "gdm-welcome", + welcome_session->priv->user_name, log_path); g_free (log_path); } @@ -1006,6 +1013,14 @@ _gdm_welcome_session_set_command (GdmWelcomeSession *welcome_session, welcome_session->priv->command = g_strdup (name); } +static void +_gdm_welcome_session_set_log_file (GdmWelcomeSession *welcome_session, + const char *log_file) +{ + g_free (welcome_session->priv->log_file); + welcome_session->priv->log_file = g_strdup (log_file); +} + static void _gdm_welcome_session_set_server_env_var_name (GdmWelcomeSession *welcome_session, const char *name) @@ -1067,6 +1082,9 @@ gdm_welcome_session_set_property (GObject *object, case PROP_COMMAND: _gdm_welcome_session_set_command (self, g_value_get_string (value)); break; + case PROP_LOG_FILE: + _gdm_welcome_session_set_log_file (self, g_value_get_string (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1126,6 +1144,9 @@ gdm_welcome_session_get_property (GObject *object, case PROP_COMMAND: g_value_set_string (value, self->priv->command); break; + case PROP_LOG_FILE: + g_value_set_string (value, self->priv->log_file); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1241,6 +1262,13 @@ gdm_welcome_session_class_init (GdmWelcomeSessionClass *klass) "command", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property (object_class, + PROP_LOG_FILE, + g_param_spec_string ("log-file", + "log file", + "log file", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); signals [STARTED] = g_signal_new ("started", G_OBJECT_CLASS_TYPE (object_class), diff --git a/data/gdm.schemas.in.in b/data/gdm.schemas.in.in index 514117d7..f049c2fd 100644 --- a/data/gdm.schemas.in.in +++ b/data/gdm.schemas.in.in @@ -47,6 +47,11 @@ i 30 + + daemon/InitialSetupEnable + b + false + debug/Enable -- cgit v1.2.1