diff options
-rw-r--r-- | ChangeLog | 29 | ||||
-rw-r--r-- | daemon/Makefile.am | 2 | ||||
-rw-r--r-- | daemon/gdm-greeter-server.c | 20 | ||||
-rw-r--r-- | daemon/gdm-greeter-server.h | 4 | ||||
-rw-r--r-- | daemon/gdm-session-direct.c | 56 | ||||
-rw-r--r-- | daemon/gdm-session-private.h | 6 | ||||
-rw-r--r-- | daemon/gdm-session-worker.c | 99 | ||||
-rw-r--r-- | daemon/gdm-session.c | 43 | ||||
-rw-r--r-- | daemon/gdm-session.h | 5 | ||||
-rw-r--r-- | daemon/gdm-simple-slave.c | 29 |
10 files changed, 289 insertions, 4 deletions
@@ -1,3 +1,32 @@ +2008-02-18 Ray Strode <rstrode@redhat.com> + + Read ~/.dmrc when available, and bubble the + results up to the greeter + + * daemon/Makefile.am: add gdm-session-settings.[ch] to + worker sources + * daemon/gdm-session-private.h: + * daemon/gdm-session.[ch]: + (_gdm_session_saved_language_name_read), + (_gdm_session_saved_session_name_read), + (gdm_session_class_init): + Add two new signals: "saved-language-name-read" + and "saved-session-name-read" + * daemon/gdm-session-worker.c (GdmSessionWorkerPrivate): + session settings object to hold ~/.dmrc info. + (attempt_to_load_user_settings_as_root): new function + to switch from root to user, load settings, and switch + back + (do_setup), (gdm_session_worker_update_username): + Create session settings object, and try to load ~/.dmrc + in to object at various points in the pam conversation. + (on_saved_language_name_read), (on_saved_session_name_read): + report session settings changes from worker to slave + * daemon/gdm-greeter-server.[ch]: + (gdm_greeter_server_saved_language_name_read), + (gdm_greeter_server_saved_session_name_read), + (do_introspect): send language and session name to greeter + 2008-02-18 William Jon McCann <jmccann@redhat.com> * gui/simple-greeter/gdm-language-option-widget.c: diff --git a/daemon/Makefile.am b/daemon/Makefile.am index 93b18cf2..03b7e83f 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -244,6 +244,8 @@ gdm_xdmcp_chooser_slave_LDADD = \ gdm_session_worker_SOURCES = \ session-worker-main.c \ + gdm-session-settings.h \ + gdm-session-settings.c \ gdm-session-auditor.h \ gdm-session-auditor.c \ gdm-session-worker.h \ diff --git a/daemon/gdm-greeter-server.c b/daemon/gdm-greeter-server.c index db568d7d..2fa8a8f2 100644 --- a/daemon/gdm-greeter-server.c +++ b/daemon/gdm-greeter-server.c @@ -221,6 +221,20 @@ gdm_greeter_server_selected_user_changed (GdmGreeterServer *greeter_server, send_dbus_string_signal (greeter_server, "SelectedUserChanged", username); } +void +gdm_greeter_server_saved_language_name_read (GdmGreeterServer *greeter_server, + const char *language_name) +{ + send_dbus_string_signal (greeter_server, "SavedLanguageNameRead", language_name); +} + +void +gdm_greeter_server_saved_session_name_read (GdmGreeterServer *greeter_server, + const char *session_name) +{ + send_dbus_string_signal (greeter_server, "SavedSessionNameRead", session_name); +} + /* Note: Use abstract sockets like dbus does by default on Linux. Abstract * sockets are only available on Linux. */ @@ -576,6 +590,12 @@ do_introspect (DBusConnection *connection, " <signal name=\"SelectedUserChanged\">\n" " <arg name=\"username\" type=\"s\"/>\n" " </signal>\n" + " <signal name=\"SavedLanguageNameRead\">\n" + " <arg name=\"language_name\" type=\"s\"/>\n" + " </signal>\n" + " <signal name=\"SavedSessionNameRead\">\n" + " <arg name=\"session_name\" type=\"s\"/>\n" + " </signal>\n" " <signal name=\"Ready\">\n" " </signal>\n" " <signal name=\"Reset\">\n" diff --git a/daemon/gdm-greeter-server.h b/daemon/gdm-greeter-server.h index 1b9ef288..c37a43ab 100644 --- a/daemon/gdm-greeter-server.h +++ b/daemon/gdm-greeter-server.h @@ -83,6 +83,10 @@ gboolean gdm_greeter_server_reset (GdmGreeterServer * gboolean gdm_greeter_server_ready (GdmGreeterServer *greeter_server); void gdm_greeter_server_selected_user_changed (GdmGreeterServer *greeter_server, const char *text); +void gdm_greeter_server_saved_language_name_read (GdmGreeterServer *greeter_server, + const char *text); +void gdm_greeter_server_saved_session_name_read (GdmGreeterServer *greeter_server, + const char *text); G_END_DECLS diff --git a/daemon/gdm-session-direct.c b/daemon/gdm-session-direct.c index 46277f67..e3c258a0 100644 --- a/daemon/gdm-session-direct.c +++ b/daemon/gdm-session-direct.c @@ -775,6 +775,58 @@ gdm_session_direct_handle_session_died (GdmSessionDirect *session, } static DBusHandlerResult +gdm_session_direct_handle_saved_language_name_read (GdmSessionDirect *session, + DBusConnection *connection, + DBusMessage *message) +{ + DBusMessage *reply; + DBusError error; + const char *language_name; + int code; + + dbus_error_init (&error); + if (! dbus_message_get_args (message, &error, + DBUS_TYPE_STRING, &language_name, + DBUS_TYPE_INVALID)) { + g_warning ("ERROR: %s", error.message); + } + + reply = dbus_message_new_method_return (message); + dbus_connection_send (connection, reply, NULL); + dbus_message_unref (reply); + + _gdm_session_saved_language_name_read (GDM_SESSION (session), language_name); + + return DBUS_HANDLER_RESULT_HANDLED; +} + +static DBusHandlerResult +gdm_session_direct_handle_saved_session_name_read (GdmSessionDirect *session, + DBusConnection *connection, + DBusMessage *message) +{ + DBusMessage *reply; + DBusError error; + const char *session_name; + int code; + + dbus_error_init (&error); + if (! dbus_message_get_args (message, &error, + DBUS_TYPE_STRING, &session_name, + DBUS_TYPE_INVALID)) { + g_warning ("ERROR: %s", error.message); + } + + reply = dbus_message_new_method_return (message); + dbus_connection_send (connection, reply, NULL); + dbus_message_unref (reply); + + _gdm_session_saved_session_name_read (GDM_SESSION (session), session_name); + + return DBUS_HANDLER_RESULT_HANDLED; +} + +static DBusHandlerResult session_worker_message (DBusConnection *connection, DBusMessage *message, void *user_data) @@ -821,6 +873,10 @@ session_worker_message (DBusConnection *connection, return gdm_session_direct_handle_session_exited (session, connection, message); } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SessionDied")) { return gdm_session_direct_handle_session_died (session, connection, message); + } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SavedLanguageNameRead")) { + return gdm_session_direct_handle_saved_language_name_read (session, connection, message); + } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SavedSessionNameRead")) { + return gdm_session_direct_handle_saved_session_name_read (session, connection, message); } return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; diff --git a/daemon/gdm-session-private.h b/daemon/gdm-session-private.h index af22f14b..491eab0d 100644 --- a/daemon/gdm-session-private.h +++ b/daemon/gdm-session-private.h @@ -52,7 +52,11 @@ void _gdm_session_session_died (GdmSession *sessio int signal_number); void _gdm_session_closed (GdmSession *session); - +/* user settings read from ~/.dmrc */ +void _gdm_session_saved_language_name_read (GdmSession *session, + const char *language_name); +void _gdm_session_saved_session_name_read (GdmSession *session, + const char *session_name); /* user is selected/changed internally */ void _gdm_session_selected_user_changed (GdmSession *session, const char *text); diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c index 66e045ed..4f2a50ef 100644 --- a/daemon/gdm-session-worker.c +++ b/daemon/gdm-session-worker.c @@ -54,6 +54,8 @@ #include "gdm-session-auditor.h" #endif +#include "gdm-session-settings.h" + #define GDM_SESSION_WORKER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_SESSION_WORKER, GdmSessionWorkerPrivate)) #define GDM_SESSION_DBUS_PATH "/org/gnome/DisplayManager/Session" @@ -119,7 +121,8 @@ struct GdmSessionWorkerPrivate char *server_address; DBusConnection *connection; - GdmSessionAuditor *auditor; + GdmSessionAuditor *auditor; + GdmSessionSettings *user_settings; }; enum { @@ -483,6 +486,39 @@ gdm_session_worker_get_username (GdmSessionWorker *worker, } static void +attempt_to_load_user_settings_as_root (GdmSessionWorker *worker, + const char *username) +{ + struct passwd *passwd_entry; + uid_t old_uid; + gid_t old_gid; + + old_uid = geteuid (); + old_gid = getegid (); + + g_assert (old_uid == 0); + g_assert (old_gid == 0); + + passwd_entry = getpwnam (username); + + /* User input isn't a valid username + */ + if (passwd_entry == NULL) { + return; + } + + setegid (passwd_entry->pw_gid); + seteuid (passwd_entry->pw_uid); + + gdm_session_settings_load (worker->priv->user_settings, + passwd_entry->pw_dir, + NULL); + + seteuid (old_uid); + setegid (old_gid); +} + +static void gdm_session_worker_update_username (GdmSessionWorker *worker) { char *username; @@ -497,6 +533,16 @@ gdm_session_worker_update_username (GdmSessionWorker *worker) gdm_session_auditor_set_username (worker->priv->auditor, worker->priv->username); + /* We have a new username to try. If we haven't been able to + * read user settings up until now, then give it a go now + * (see the comment in do_setup for rationale on why it's useful + * to keep trying to read settings) + */ + if (username != NULL && + !gdm_session_settings_is_loaded (worker->priv->user_settings)) { + attempt_to_load_user_settings_as_root (worker, username); + } + if ((worker->priv->username == username) || ((worker->priv->username != NULL) && (username != NULL) && (strcmp (worker->priv->username, username) == 0))) @@ -1579,11 +1625,62 @@ on_set_environment_variable (GdmSessionWorker *worker, } static void +on_saved_language_name_read (GdmSessionWorker *worker) +{ + char *language_name; + + language_name = gdm_session_settings_get_language_name (worker->priv->user_settings); + send_dbus_string_method (worker->priv->connection, + "SavedLanguageNameRead", + language_name); + g_free (language_name); +} + +static void +on_saved_session_name_read (GdmSessionWorker *worker) +{ + char *session_name; + + session_name = gdm_session_settings_get_session_name (worker->priv->user_settings); + send_dbus_string_method (worker->priv->connection, + "SavedSessionNameRead", + session_name); + g_free (session_name); +} + +static void do_setup (GdmSessionWorker *worker) { GError *error; gboolean res; + worker->priv->user_settings = gdm_session_settings_new (); + + g_signal_connect_swapped (worker->priv->user_settings, + "notify::language-name", + G_CALLBACK (on_saved_language_name_read), + worker); + + g_signal_connect_swapped (worker->priv->user_settings, + "notify::session-name", + G_CALLBACK (on_saved_session_name_read), + worker); + + /* In some setups the user can read ~/.dmrc at this point. + * In some other setups the user can only read ~/.dmrc after completing + * the pam conversation. + * + * The user experience is better if we can read .dmrc now since we can + * prefill in the language and session combo boxes in the greeter with + * the right values. + * + * We'll try now, and if it doesn't work out, try later. + */ + if (worker->priv->username != NULL) { + attempt_to_load_user_settings_as_root (worker, + worker->priv->username); + } + error = NULL; res = gdm_session_worker_initialize_pam (worker, worker->priv->service, diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c index 99548915..34ae9392 100644 --- a/daemon/gdm-session.c +++ b/daemon/gdm-session.c @@ -49,6 +49,8 @@ enum { SESSION_EXITED, SESSION_DIED, SELECTED_USER_CHANGED, + SAVED_LANGUAGE_NAME_READ, + SAVED_SESSION_NAME_READ, LAST_SIGNAL }; @@ -413,7 +415,28 @@ gdm_session_class_init (gpointer g_iface) G_TYPE_NONE, 1, G_TYPE_STRING); - + signals [SAVED_LANGUAGE_NAME_READ] = + g_signal_new ("saved-language-name-read", + iface_type, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GdmSessionIface, saved_language_name_read), + NULL, + NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, + 1, + G_TYPE_STRING); + signals [SAVED_SESSION_NAME_READ] = + g_signal_new ("saved-session-name-read", + iface_type, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GdmSessionIface, saved_session_name_read), + NULL, + NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, + 1, + G_TYPE_STRING); } void @@ -574,6 +597,24 @@ _gdm_session_closed (GdmSession *session) } void +_gdm_session_saved_language_name_read (GdmSession *session, + const char *language_name) +{ + g_return_if_fail (GDM_IS_SESSION (session)); + + g_signal_emit (session, signals [SAVED_LANGUAGE_NAME_READ], 0, language_name); +} + +void +_gdm_session_saved_session_name_read (GdmSession *session, + const char *session_name) +{ + g_return_if_fail (GDM_IS_SESSION (session)); + + g_signal_emit (session, signals [SAVED_SESSION_NAME_READ], 0, session_name); +} + +void _gdm_session_selected_user_changed (GdmSession *session, const char *text) { diff --git a/daemon/gdm-session.h b/daemon/gdm-session.h index 50cf28bb..579f2590 100644 --- a/daemon/gdm-session.h +++ b/daemon/gdm-session.h @@ -102,7 +102,10 @@ struct _GdmSessionIface void (* closed) (GdmSession *session); void (* selected_user_changed) (GdmSession *session, const char *text); - + void (* saved_language_name_read) (GdmSession *session, + const char *text); + void (* saved_session_name_read) (GdmSession *session, + const char *text); }; GType gdm_session_get_type (void) G_GNUC_CONST; diff --git a/daemon/gdm-simple-slave.c b/daemon/gdm-simple-slave.c index 59dab017..35bff1d0 100644 --- a/daemon/gdm-simple-slave.c +++ b/daemon/gdm-simple-slave.c @@ -373,6 +373,25 @@ on_session_selected_user_changed (GdmSession *session, gdm_greeter_server_selected_user_changed (slave->priv->greeter_server, text); } +static void +on_saved_language_name_read (GdmSession *session, + const char *text, + GdmSimpleSlave *slave) +{ + g_debug ("GdmSimpleSlave: Saved language name read: %s", text); + + gdm_greeter_server_saved_language_name_read (slave->priv->greeter_server, text); +} + +static void +on_saved_session_name_read (GdmSession *session, + const char *text, + GdmSimpleSlave *slave) +{ + g_debug ("GdmSimpleSlave: Saved session name read: %s", text); + + gdm_greeter_server_saved_session_name_read (slave->priv->greeter_server, text); +} static void create_new_session (GdmSimpleSlave *slave) @@ -488,6 +507,16 @@ create_new_session (GdmSimpleSlave *slave) "selected-user-changed", G_CALLBACK (on_session_selected_user_changed), slave); + + g_signal_connect (slave->priv->session, + "saved-language-name-read", + G_CALLBACK (on_saved_language_name_read), + slave); + + g_signal_connect (slave->priv->session, + "saved-session-name-read", + G_CALLBACK (on_saved_session_name_read), + slave); } static void |