diff -Nur -x patches gdm-2.30.0/daemon/gdm-simple-slave.c gdm-2.30.2.is.2.30.0/daemon/gdm-simple-slave.c --- gdm-2.30.0/daemon/gdm-simple-slave.c 2010-06-09 15:16:34.000000000 +0200 +++ gdm-2.30.2.is.2.30.0/daemon/gdm-simple-slave.c 2010-06-09 15:16:47.000000000 +0200 @@ -1186,6 +1186,8 @@ start_greeter (slave); create_new_session (slave); } else { + /* Run the init script. gdmslave suspends until script has terminated */ + gdm_slave_run_script (GDM_SLAVE (slave), GDMCONFDIR "/Init", GDM_USERNAME); reset_session (slave); } } else { diff -Nur -x patches gdm-2.30.0/daemon/gdm-user.c gdm-2.30.2.is.2.30.0/daemon/gdm-user.c --- gdm-2.30.0/daemon/gdm-user.c 2010-06-09 15:16:34.000000000 +0200 +++ gdm-2.30.2.is.2.30.0/daemon/gdm-user.c 2010-06-09 15:16:46.000000000 +0200 @@ -36,9 +36,16 @@ #define GDM_IS_USER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDM_TYPE_USER)) #define GDM_USER_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS ((object), GDM_TYPE_USER, GdmUserClass)) +#define GLOBAL_FACEDIR DATADIR "/faces" +#define MAX_ICON_SIZE 128 +#define MAX_FILE_SIZE 65536 +#define MINIMAL_UID 100 + enum { PROP_0, + PROP_MANAGER, PROP_REAL_NAME, + PROP_DISPLAY_NAME, PROP_USER_NAME, PROP_UID, PROP_HOME_DIR, @@ -56,9 +63,12 @@ struct _GdmUser { GObject parent; + GdmUserManager *manager; + uid_t uid; char *user_name; char *real_name; + char *display_name; char *home_dir; char *shell; char *icon_url; @@ -147,6 +157,14 @@ } static void +_gdm_user_set_login_frequency (GdmUser *user, + gulong login_frequency) +{ + user->login_frequency = login_frequency; + g_object_notify (G_OBJECT (user), "login-frequency"); +} + +static void gdm_user_set_property (GObject *object, guint param_id, const GValue *value, @@ -157,9 +175,12 @@ user = GDM_USER (object); switch (param_id) { + case PROP_MANAGER: + user->manager = g_value_get_object (value); + g_assert (user->manager); + break; case PROP_LOGIN_FREQUENCY: - user->login_frequency = g_value_get_ulong (value); - g_object_notify (G_OBJECT (user), "login-frequency"); + _gdm_user_set_login_frequency (user, g_value_get_ulong (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); @@ -178,12 +199,18 @@ user = GDM_USER (object); switch (param_id) { + case PROP_MANAGER: + g_value_set_object (value, user->manager); + break; case PROP_USER_NAME: g_value_set_string (value, user->user_name); break; case PROP_REAL_NAME: g_value_set_string (value, user->real_name); break; + case PROP_DISPLAY_NAME: + g_value_set_string (value, user->display_name); + break; case PROP_HOME_DIR: g_value_set_string (value, user->home_dir); break; @@ -217,6 +244,15 @@ gobject_class->finalize = gdm_user_finalize; g_object_class_install_property (gobject_class, + PROP_MANAGER, + g_param_spec_object ("manager", + _("Manager"), + _("The user manager object this user is controlled by."), + GDM_TYPE_USER_MANAGER, + (G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY))); + + g_object_class_install_property (gobject_class, PROP_REAL_NAME, g_param_spec_string ("real-name", "Real Name", @@ -225,6 +261,14 @@ G_PARAM_READABLE)); g_object_class_install_property (gobject_class, + PROP_DISPLAY_NAME, + g_param_spec_string ("display-name", + "Display Name", + "The unique name to display for this user.", + NULL, + G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, PROP_UID, g_param_spec_ulong ("uid", "User ID", @@ -302,38 +346,29 @@ return; } - g_signal_emit (user, signals[ICON_CHANGED], 0); + _gdm_user_icon_changed (user); } static void update_icon_monitor (GdmUser *user) { GFile *file; - GError *error = NULL; + GError *error; + char *path; - if (user->icon_url != NULL) { - g_free (user->icon_url); - user->icon_url = NULL; - } - if (user->home_dir != NULL) { - gchar *filename; - filename = g_build_filename (user->home_dir, ".face", NULL); - user->icon_url = g_strjoin(NULL, "file://", filename, NULL); - g_free (filename); + if (user->home_dir == NULL) { + return; } - g_object_notify (G_OBJECT (user), "icon-url"); if (user->icon_monitor != NULL) { g_file_monitor_cancel (user->icon_monitor); user->icon_monitor = NULL; } - if (user->icon_url == NULL) { - return; - } - - g_debug ("adding monitor for '%s'", user->icon_url); - file = g_file_new_for_uri (user->icon_url); + path = g_build_filename (user->home_dir, ".face", NULL); + g_debug ("adding monitor for '%s'", path); + file = g_file_new_for_path (path); + error = NULL; user->icon_monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, @@ -344,18 +379,27 @@ G_CALLBACK (on_icon_monitor_changed), user); } else { - g_warning ("Unable to monitor %s: %s", user->icon_url, error->message); + g_warning ("Unable to monitor %s: %s", path, error->message); g_error_free (error); } g_object_unref (file); + + g_free (user->icon_url); + user->icon_url = g_strjoin(NULL, "file://", path, NULL); + g_object_notify (G_OBJECT (user), "icon-url"); + + g_free (path); } static void gdm_user_init (GdmUser *user) { + user->manager = NULL; user->user_name = NULL; user->real_name = NULL; + user->display_name = NULL; user->sessions = NULL; + user->icon_url = NULL; } static void @@ -369,6 +413,8 @@ g_free (user->user_name); g_free (user->real_name); + g_free (user->display_name); + g_free (user->icon_url); if (G_OBJECT_CLASS (gdm_user_parent_class)->finalize) (*G_OBJECT_CLASS (gdm_user_parent_class)->finalize) (object); @@ -387,7 +433,7 @@ _gdm_user_update (GdmUser *user, const struct passwd *pwent) { - gchar *real_name; + gchar *real_name = NULL; g_return_if_fail (GDM_IS_USER (user)); g_return_if_fail (pwent != NULL); @@ -396,20 +442,28 @@ /* Display Name */ if (pwent->pw_gecos && pwent->pw_gecos[0] != '\0') { - gchar *first_comma; - gchar *real_name_utf8; + gchar *first_comma = NULL; + gchar *valid_utf8_name = NULL; - real_name_utf8 = g_locale_to_utf8 (pwent->pw_gecos, -1, NULL, NULL, NULL); + if (g_utf8_validate (pwent->pw_gecos, -1, NULL)) { + valid_utf8_name = pwent->pw_gecos; + first_comma = g_utf8_strchr (valid_utf8_name, -1, ','); + } else { + g_warning ("User %s has invalid UTF-8 in GECOS field. " + "It would be a good thing to check /etc/passwd.", + pwent->pw_name ? pwent->pw_name : ""); + } - first_comma = strchr (real_name_utf8, ','); if (first_comma) { - real_name = g_strndup (real_name_utf8, first_comma - real_name_utf8); - g_free (real_name_utf8); + real_name = g_strndup (valid_utf8_name, + (first_comma - valid_utf8_name)); + } else if (valid_utf8_name) { + real_name = g_strdup (valid_utf8_name); } else { - real_name = real_name_utf8; + real_name = NULL; } - if (real_name[0] == '\0') { + if (real_name && real_name[0] == '\0') { g_free (real_name); real_name = NULL; } @@ -429,6 +483,16 @@ g_free (real_name); } + /* Unique Display Name */ + if ((!user->real_name && user->display_name) || + (user->real_name && + user->display_name && + strncmp (user->real_name, user->display_name, strlen (user->real_name)) != 0)) { + g_free (user->display_name); + user->display_name = NULL; + g_object_notify (G_OBJECT (user), "display-name"); + } + /* UID */ if (pwent->pw_uid != user->uid) { user->uid = pwent->pw_uid; @@ -473,6 +537,22 @@ } /** + * _gdm_user_icon_changed: + * @user: the user to emit the signal for. + * + * Emits the "icon-changed" signal for @user. + * + * Since: 1.0 + **/ +void +_gdm_user_icon_changed (GdmUser *user) +{ + g_return_if_fail (GDM_IS_USER (user)); + + g_signal_emit (user, signals[ICON_CHANGED], 0); +} + +/** * gdm_user_get_uid: * @user: the user object to examine. * @@ -512,6 +592,26 @@ } /** + * gdm_user_get_display_name: + * @user: the user object to examine. + * + * Retrieves the unique display name of @user. + * + * Returns: a pointer to an array of characters which must not be modified or + * freed, or %NULL. + * + * Since: 1.0 + **/ +G_CONST_RETURN gchar * +gdm_user_get_display_name (GdmUser *user) +{ + g_return_val_if_fail (GDM_IS_USER (user), NULL); + + return (user->display_name ? user->display_name + : gdm_user_get_real_name (user)); +} + +/** * gdm_user_get_user_name: * @user: the user object to examine. * @@ -579,7 +679,58 @@ return user->login_frequency; } -G_CONST_RETURN gchar * +int +gdm_user_collate (GdmUser *user1, + GdmUser *user2) +{ + const char *str1; + const char *str2; + gulong num1; + gulong num2; + + g_return_val_if_fail (GDM_IS_USER (user1), 0); + g_return_val_if_fail (GDM_IS_USER (user2), 0); + + if (user1->real_name != NULL) { + str1 = user1->real_name; + } else { + str1 = user1->user_name; + } + + if (user2->real_name != NULL) { + str2 = user2->real_name; + } else { + str2 = user2->user_name; + } + + num1 = user1->login_frequency; + num2 = user2->login_frequency; + g_debug ("Login freq 1=%u 2=%u", (guint)num1, (guint)num2); + if (num1 > num2) { + return -1; + } + + if (num1 < num2) { + return 1; + } + + /* if login frequency is equal try names */ + if (str1 == NULL && str2 != NULL) { + return -1; + } + + if (str1 != NULL && str2 == NULL) { + return 1; + } + + if (str1 == NULL && str2 == NULL) { + return 0; + } + + return g_utf8_collate (str1, str2); +} + +G_CONST_RETURN char * gdm_user_get_icon_url (GdmUser *user) { g_return_val_if_fail (GDM_IS_USER (user), NULL); diff -Nur -x patches gdm-2.30.0/daemon/gdm-user.h gdm-2.30.2.is.2.30.0/daemon/gdm-user.h --- gdm-2.30.0/daemon/gdm-user.h 2010-06-09 15:16:34.000000000 +0200 +++ gdm-2.30.2.is.2.30.0/daemon/gdm-user.h 2010-06-09 15:16:46.000000000 +0200 @@ -36,17 +36,21 @@ typedef struct _GdmUser GdmUser; -GType gdm_user_get_type (void) G_GNUC_CONST; +GType gdm_user_get_type (void) G_GNUC_CONST; -uid_t gdm_user_get_uid (GdmUser *user); -G_CONST_RETURN gchar *gdm_user_get_user_name (GdmUser *user); -G_CONST_RETURN gchar *gdm_user_get_real_name (GdmUser *user); -G_CONST_RETURN gchar *gdm_user_get_home_directory (GdmUser *user); -G_CONST_RETURN gchar *gdm_user_get_shell (GdmUser *user); -guint gdm_user_get_num_sessions (GdmUser *user); -GList *gdm_user_get_sessions (GdmUser *user); -gulong gdm_user_get_login_frequency (GdmUser *user); -G_CONST_RETURN gchar *gdm_user_get_icon_url (GdmUser *user); +uid_t gdm_user_get_uid (GdmUser *user); +G_CONST_RETURN char *gdm_user_get_user_name (GdmUser *user); +G_CONST_RETURN char *gdm_user_get_real_name (GdmUser *user); +G_CONST_RETURN char *gdm_user_get_display_name (GdmUser *user); +G_CONST_RETURN char *gdm_user_get_home_directory (GdmUser *user); +G_CONST_RETURN char *gdm_user_get_shell (GdmUser *user); +guint gdm_user_get_num_sessions (GdmUser *user); +GList *gdm_user_get_sessions (GdmUser *user); +gulong gdm_user_get_login_frequency (GdmUser *user); +G_CONST_RETURN char *gdm_user_get_icon_url (GdmUser *user); + +gint gdm_user_collate (GdmUser *user1, + GdmUser *user2); G_END_DECLS diff -Nur -x patches gdm-2.30.0/daemon/gdm-user-manager.c gdm-2.30.2.is.2.30.0/daemon/gdm-user-manager.c --- gdm-2.30.0/daemon/gdm-user-manager.c 2010-06-09 15:16:34.000000000 +0200 +++ gdm-2.30.2.is.2.30.0/daemon/gdm-user-manager.c 2010-06-09 15:16:46.000000000 +0200 @@ -48,6 +48,7 @@ #include "gdm-user-manager.h" #include "gdm-user-manager-glue.h" #include "gdm-user-private.h" +#include "gdm-settings-keys.h" #define GDM_USER_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_USER_MANAGER, GdmUserManagerPrivate)) @@ -64,6 +65,11 @@ #define CK_SEAT_INTERFACE "org.freedesktop.ConsoleKit.Seat" #define CK_SESSION_INTERFACE "org.freedesktop.ConsoleKit.Session" +/* Prefs Defaults */ +#define DEFAULT_ALLOW_ROOT TRUE +#define DEFAULT_MAX_ICON_SIZE 128 +#define DEFAULT_USER_MAX_FILE 65536 + #ifdef __sun #define DEFAULT_MINIMAL_UID 100 #else @@ -75,36 +81,15 @@ #endif #define PATH_PASSWD "/etc/passwd" -#define LOGIN_CACHE_FILE CACHEDIR "/login_frequency.cache" +#define DEFAULT_GLOBAL_FACE_DIR DATADIR "/faces" +#define DEFAULT_USER_ICON "stock_person" -#define DEFAULT_EXCLUDE { "bin", \ - "root", \ - "daemon", \ - "adm", \ - "lp", \ - "sync", \ - "shutdown", \ - "halt", \ - "mail", \ - "news", \ - "uucp", \ - "operator", \ - "nobody", \ - "nobody4", \ - "noaccess", \ - GDM_USERNAME, \ - "postgres", \ - "pvm", \ - "rpm", \ - "nfsnobody", \ - "pcap", \ - NULL } +#define LOGIN_CACHE_FILE CACHEDIR "/login_frequency.cache" struct GdmUserManagerPrivate { GHashTable *users; GHashTable *sessions; - GHashTable *exclusions; GHashTable *shells; DBusGConnection *connection; DBusGProxy *seat_proxy; @@ -113,15 +98,22 @@ GFileMonitor *passwd_monitor; GFileMonitor *shells_monitor; + GSList *exclude; + GSList *include; + gboolean include_all; + guint reload_id; guint ck_history_id; guint minimal_uid; - guint8 loaded_passwd : 1; + guint8 loaded_passwd : 1; + guint8 users_dirty : 1; guint8 loaded_cache : 1; + guint8 loading_users : 1; }; enum { + LOADING_USERS, USERS_LOADED, USER_ADDED, USER_REMOVED, @@ -135,6 +127,8 @@ static void gdm_user_manager_init (GdmUserManager *user_manager); static void gdm_user_manager_finalize (GObject *object); +static gpointer user_manager_object = NULL; + G_DEFINE_TYPE (GdmUserManager, gdm_user_manager, G_TYPE_OBJECT) GQuark @@ -263,6 +257,43 @@ return x11_display; } +static gint +match_name_cmpfunc (gconstpointer a, + gconstpointer b) +{ + if (a == NULL || b == NULL) { + return -1; + } + + return g_strcmp0 ((char *) a, + (char *) b); +} + +static gboolean +user_in_exclude_list (GdmUserManager *manager, + const char *user) +{ + GSList *found; + gboolean ret = FALSE; + + g_debug ("checking exclude list"); + + /* always exclude the "gdm" user. */ + if (user == NULL || (strcmp (user, GDM_USERNAME) == 0)) { + return TRUE; + } + + if (manager->priv->exclude != NULL) { + found = g_slist_find_custom (manager->priv->exclude, + user, + match_name_cmpfunc); + if (found != NULL) { + ret = TRUE; + } + } + return ret; +} + static gboolean maybe_add_session_for_user (GdmUserManager *manager, GdmUser *user, @@ -292,7 +323,7 @@ goto out; } - if (g_hash_table_lookup (manager->priv->exclusions, gdm_user_get_user_name (user))) { + if (user_in_exclude_list (manager, gdm_user_get_user_name (user))) { g_debug ("GdmUserManager: excluding user '%s'", gdm_user_get_user_name (user)); goto out; } @@ -379,7 +410,7 @@ { GdmUser *user; - user = g_object_new (GDM_TYPE_USER, NULL); + user = g_object_new (GDM_TYPE_USER, "manager", manager, NULL); g_signal_connect (user, "sessions-changed", G_CALLBACK (on_user_sessions_changed), @@ -391,11 +422,39 @@ return user; } +static gint +match_real_name_cmpfunc (gconstpointer a, + gconstpointer b) +{ + if (a == b) + return -1; + + return g_strcmp0 (gdm_user_get_real_name ((GdmUser *) a), + gdm_user_get_real_name ((GdmUser *) b)); +} + +static gboolean +match_real_name_hrfunc (gpointer key, + gpointer value, + gpointer user_data) +{ + return (g_strcmp0 (user_data, gdm_user_get_real_name (value)) == 0); +} + static void add_user (GdmUserManager *manager, GdmUser *user) { + GdmUser *dup; + add_sessions_for_user (manager, user); + dup = g_hash_table_find (manager->priv->users, + match_real_name_hrfunc, + (char *) gdm_user_get_real_name (user)); + if (dup != NULL) { + //_gdm_user_show_full_display_name (user); + //_gdm_user_show_full_display_name (dup); + } g_hash_table_insert (manager->priv->users, g_strdup (gdm_user_get_user_name (user)), g_object_ref (user)); @@ -537,7 +596,7 @@ errno = 0; pwent = getpwuid (uid); if (pwent == NULL) { - g_warning ("Unable to lookup user id %d: %s", (int)uid, g_strerror (errno)); + g_warning ("Unable to lookup user ID %d: %s", (int)uid, g_strerror (errno)); return; } @@ -546,7 +605,7 @@ } /* check exclusions up front */ - if (g_hash_table_lookup (manager->priv->exclusions, pwent->pw_name)) { + if (user_in_exclude_list (manager, pwent->pw_name)) { g_debug ("GdmUserManager: excluding user '%s'", pwent->pw_name); return; } @@ -690,7 +749,7 @@ * * Returns: a pointer to a #GdmUser object. **/ -static GdmUser * +GdmUser * gdm_user_manager_get_user (GdmUserManager *manager, const char *username) { @@ -714,7 +773,7 @@ return user; } -static GdmUser * +GdmUser * gdm_user_manager_get_user_by_uid (GdmUserManager *manager, uid_t uid) { @@ -748,6 +807,19 @@ *list = g_slist_prepend (*list, value); } +GSList * +gdm_user_manager_list_users (GdmUserManager *manager) +{ + GSList *retval; + + g_return_val_if_fail (GDM_IS_USER_MANAGER (manager), NULL); + + retval = NULL; + g_hash_table_foreach (manager->priv->users, listify_hash_values_hfunc, &retval); + + return g_slist_sort (retval, (GCompareFunc) gdm_user_collate); +} + static gboolean parse_value_as_ulong (const char *value, gulong *ulongval) @@ -850,7 +922,7 @@ return; } - if (g_hash_table_lookup (manager->priv->exclusions, username)) { + if (user_in_exclude_list (manager, username)) { g_debug ("GdmUserManager: excluding user '%s'", username); g_free (username); return; @@ -934,6 +1006,11 @@ else g_warning ("Unable to write to login cache file: %s", LOGIN_CACHE_FILE); + if (manager->priv->loading_users) { + g_signal_emit (G_OBJECT (manager), signals[USERS_LOADED], 0); + manager->priv->loading_users = FALSE; + } + manager->priv->ck_history_id = 0; return FALSE; } @@ -1016,6 +1093,35 @@ g_free (command); } +static void +add_included_user (char *username, GdmUserManager *manager) +{ + GdmUser *user; + + g_debug ("Adding included user %s", username); + /* + * The call to gdm_user_manager_get_user will add the user if it is + * valid and not already in the hash. + */ + user = gdm_user_manager_get_user (manager, username); + if (user == NULL) { + g_debug ("GdmUserManager: unable to lookup user '%s'", username); + g_free (username); + return; + } +} + +static void +add_included_users (GdmUserManager *manager) +{ + /* Add users who are specifically included */ + if (manager->priv->include != NULL) { + g_slist_foreach (manager->priv->include, + (GFunc)add_included_user, + (gpointer)manager); + } +} + static void reload_passwd (GdmUserManager *manager) @@ -1024,6 +1130,7 @@ GSList *old_users; GSList *new_users; GSList *list; + GSList *dup; FILE *fp; old_users = NULL; @@ -1043,52 +1150,63 @@ for (list = old_users; list; list = list->next) { if (gdm_user_get_num_sessions (list->data) > 0) { g_object_freeze_notify (G_OBJECT (list->data)); + //_gdm_user_show_short_display_name (list->data); new_users = g_slist_prepend (new_users, g_object_ref (list->data)); } } - for (pwent = fgetpwent (fp); pwent != NULL; pwent = fgetpwent (fp)) { - GdmUser *user; + if (manager->priv->include_all != TRUE) { + g_debug ("GdmUserManager: include_all is FALSE"); + } else { + g_debug ("GdmUserManager: include_all is TRUE"); - user = NULL; + for (pwent = fgetpwent (fp); + pwent != NULL; + pwent = fgetpwent (fp)) { + GdmUser *user; + + user = NULL; + + /* Skip users below MinimalUID... */ + if (pwent->pw_uid < manager->priv->minimal_uid) { + continue; + } - /* Skip users below MinimalUID... */ - if (pwent->pw_uid < manager->priv->minimal_uid) { - continue; - } + /* ...And users w/ invalid shells... */ + if (pwent->pw_shell == NULL || + !g_hash_table_lookup (manager->priv->shells, + pwent->pw_shell)) { + g_debug ("GdmUserManager: skipping user with bad shell: %s", pwent->pw_name); + continue; + } - /* ...And users w/ invalid shells... */ - if (pwent->pw_shell == NULL || - !g_hash_table_lookup (manager->priv->shells, pwent->pw_shell)) { - g_debug ("GdmUserManager: skipping user with bad shell: %s", pwent->pw_name); - continue; - } + /* ...And explicitly excluded users */ + if (user_in_exclude_list (manager, pwent->pw_name)) { + g_debug ("GdmUserManager: explicitly skipping user: %s", pwent->pw_name); + continue; + } - /* ...And explicitly excluded users */ - if (g_hash_table_lookup (manager->priv->exclusions, pwent->pw_name)) { - g_debug ("GdmUserManager: explicitly skipping user: %s", pwent->pw_name); - continue; - } + user = g_hash_table_lookup (manager->priv->users, + pwent->pw_name); - user = g_hash_table_lookup (manager->priv->users, pwent->pw_name); + /* Update users already in the *new* list */ + if (g_slist_find (new_users, user)) { + _gdm_user_update (user, pwent); + continue; + } - /* Update users already in the *new* list */ - if (g_slist_find (new_users, user)) { + if (user == NULL) { + user = create_user (manager); + } else { + g_object_ref (user); + } + + /* Freeze & update users not already in the new list */ + g_object_freeze_notify (G_OBJECT (user)); _gdm_user_update (user, pwent); - continue; - } - if (user == NULL) { - user = create_user (manager); - } else { - g_object_ref (user); + new_users = g_slist_prepend (new_users, user); } - - /* Freeze & update users not already in the new list */ - g_object_freeze_notify (G_OBJECT (user)); - _gdm_user_update (user, pwent); - - new_users = g_slist_prepend (new_users, user); } /* Go through and handle removed users */ @@ -1100,13 +1218,23 @@ } } - /* Go through and handle added users */ + /* Go through and handle added users or update display names */ for (list = new_users; list; list = list->next) { - if (!g_slist_find (old_users, list->data)) { + if (g_slist_find (old_users, list->data)) { + dup = g_slist_find_custom (new_users, + list->data, + match_real_name_cmpfunc); + if (dup != NULL) { + //_gdm_user_show_full_display_name (list->data); + //_gdm_user_show_full_display_name (dup->data); + } + } else { add_user (manager, list->data); } } + add_included_users (manager); + if (!manager->priv->loaded_passwd) { g_signal_emit (manager, signals[USERS_LOADED], 0); manager->priv->loaded_passwd = TRUE; @@ -1141,17 +1269,22 @@ } g_io_channel_close (channel); + + if (manager->priv->loading_users) { + g_signal_emit (G_OBJECT (manager), signals[USERS_LOADED], 0); + manager->priv->loading_users = FALSE; + } } static void reload_users (GdmUserManager *manager) { - reload_passwd (manager); if (!manager->priv->loaded_cache) { load_login_frequency_cache (manager); manager->priv->loaded_cache = TRUE; } reload_ck_history (manager); + reload_passwd (manager); } static gboolean @@ -1170,6 +1303,8 @@ return; } + g_signal_emit (G_OBJECT (manager), signals[LOADING_USERS], 0); + manager->priv->loading_users = TRUE; manager->priv->reload_id = g_idle_add ((GSourceFunc)reload_users_timeout, manager); } @@ -1235,13 +1370,21 @@ object_class->finalize = gdm_user_manager_finalize; + signals [LOADING_USERS] = + g_signal_new ("loading-users", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GdmUserManagerClass, loading_users), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); signals [USERS_LOADED] = g_signal_new ("users-loaded", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GdmUserManagerClass, users_loaded), NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, + g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals [USER_ADDED] = g_signal_new ("user-added", @@ -1273,6 +1416,30 @@ dbus_g_object_type_install_info (GDM_TYPE_USER_MANAGER, &dbus_glib_gdm_user_manager_object_info); } +static void +gdm_set_string_list (char *value, GSList **retval) +{ + char **temp_array; + int i; + + *retval = NULL; + + if (value == NULL || *value == '\0') { + g_debug ("Not adding NULL user"); + *retval = NULL; + return; + } + + temp_array = g_strsplit (value, ",", 0); + for (i = 0; temp_array[i] != NULL; i++) { + g_debug ("Adding value %s", temp_array[i]); + g_strstrip (temp_array[i]); + *retval = g_slist_prepend (*retval, g_strdup (temp_array[i])); + } + + g_strfreev (temp_array); +} + static guint system_minimal_uid (void) @@ -1312,10 +1479,25 @@ int i; GFile *file; GError *error; - const char *exclude_default[] = DEFAULT_EXCLUDE; + char *temp; + gboolean res; manager->priv = GDM_USER_MANAGER_GET_PRIVATE (manager); + /* exclude/include */ + g_debug ("Setting users to include:"); + res = gdm_settings_direct_get_string (GDM_KEY_INCLUDE, + &temp); + gdm_set_string_list (temp, &manager->priv->include); + + g_debug ("Setting users to exclude:"); + res = gdm_settings_direct_get_string (GDM_KEY_EXCLUDE, + &temp); + gdm_set_string_list (temp, &manager->priv->exclude); + + res = gdm_settings_direct_get_boolean (GDM_KEY_INCLUDE_ALL, + &manager->priv->include_all); + manager->priv->minimal_uid = system_minimal_uid (); /* sessions */ @@ -1324,66 +1506,60 @@ g_free, g_free); - /* exclusions */ - manager->priv->exclusions = g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - NULL); - for (i = 0; exclude_default[i] != NULL; i++) { - g_hash_table_insert (manager->priv->exclusions, - g_strdup (exclude_default [i]), - GUINT_TO_POINTER (TRUE)); - } - - /* /etc/shells */ - manager->priv->shells = g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - NULL); - reload_shells (manager); - file = g_file_new_for_path (_PATH_SHELLS); - error = NULL; - manager->priv->shells_monitor = g_file_monitor_file (file, - G_FILE_MONITOR_NONE, - NULL, - &error); - if (manager->priv->shells_monitor != NULL) { - g_signal_connect (manager->priv->shells_monitor, - "changed", - G_CALLBACK (on_shells_monitor_changed), - manager); - } else { - g_warning ("Unable to monitor %s: %s", _PATH_SHELLS, error->message); - g_error_free (error); - } - g_object_unref (file); - - /* /etc/passwd */ + /* users */ manager->priv->users = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_object_run_dispose); - file = g_file_new_for_path (PATH_PASSWD); - manager->priv->passwd_monitor = g_file_monitor_file (file, - G_FILE_MONITOR_NONE, - NULL, - &error); - if (manager->priv->passwd_monitor != NULL) { - g_signal_connect (manager->priv->passwd_monitor, - "changed", - G_CALLBACK (on_passwd_monitor_changed), - manager); - } else { - g_warning ("Unable to monitor %s: %s", PATH_PASSWD, error->message); - g_error_free (error); - } - g_object_unref (file); + if (manager->priv->include_all == TRUE) { + /* /etc/shells */ + manager->priv->shells = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + NULL); + reload_shells (manager); + file = g_file_new_for_path (_PATH_SHELLS); + error = NULL; + manager->priv->shells_monitor = g_file_monitor_file (file, + G_FILE_MONITOR_NONE, + NULL, + &error); + if (manager->priv->shells_monitor != NULL) { + g_signal_connect (manager->priv->shells_monitor, + "changed", + G_CALLBACK (on_shells_monitor_changed), + manager); + } else { + g_warning ("Unable to monitor %s: %s", _PATH_SHELLS, error->message); + g_error_free (error); + } + g_object_unref (file); + + /* /etc/passwd */ + file = g_file_new_for_path (PATH_PASSWD); + manager->priv->passwd_monitor = g_file_monitor_file (file, + G_FILE_MONITOR_NONE, + NULL, + &error); + if (manager->priv->passwd_monitor != NULL) { + g_signal_connect (manager->priv->passwd_monitor, + "changed", + G_CALLBACK (on_passwd_monitor_changed), + manager); + } else { + g_warning ("Unable to monitor %s: %s", PATH_PASSWD, error->message); + g_error_free (error); + } + g_object_unref (file); + } get_seat_proxy (manager); queue_reload_users (manager); + manager->priv->users_dirty = FALSE; + dbus_g_connection_register_g_object (manager->priv->connection, GDM_USER_MANAGER_DBUS_PATH, G_OBJECT (manager)); } @@ -1399,6 +1575,14 @@ g_return_if_fail (manager->priv != NULL); + if (manager->priv->exclude != NULL) { + g_slist_free (manager->priv->exclude); + } + + if (manager->priv->include != NULL) { + g_slist_free (manager->priv->include); + } + if (manager->priv->seat_proxy != NULL) { g_object_unref (manager->priv->seat_proxy); } @@ -1427,9 +1611,17 @@ } GdmUserManager * -gdm_user_manager_new (void) +gdm_user_manager_ref_default (void) { - return GDM_USER_MANAGER (g_object_new (GDM_TYPE_USER_MANAGER, NULL)); + if (user_manager_object != NULL) { + g_object_ref (user_manager_object); + } else { + user_manager_object = g_object_new (GDM_TYPE_USER_MANAGER, NULL); + g_object_add_weak_pointer (user_manager_object, + (gpointer *) &user_manager_object); + } + + return GDM_USER_MANAGER (user_manager_object); } /* diff -Nur -x patches gdm-2.30.0/daemon/gdm-user-manager.h gdm-2.30.2.is.2.30.0/daemon/gdm-user-manager.h --- gdm-2.30.0/daemon/gdm-user-manager.h 2010-06-09 15:16:34.000000000 +0200 +++ gdm-2.30.2.is.2.30.0/daemon/gdm-user-manager.h 2010-06-09 15:16:46.000000000 +0200 @@ -46,6 +46,7 @@ { GObjectClass parent_class; + void (* loading_users) (GdmUserManager *user_manager); void (* users_loaded) (GdmUserManager *user_manager); void (* user_added) (GdmUserManager *user_manager, gint64 uid); @@ -55,12 +56,24 @@ gint64 uid); } GdmUserManagerClass; +typedef enum +{ + GDM_USER_MANAGER_ERROR_GENERAL, + GDM_USER_MANAGER_ERROR_KEY_NOT_FOUND +} GdmUserManagerError; + #define GDM_USER_MANAGER_ERROR gdm_user_manager_error_quark () GQuark gdm_user_manager_error_quark (void); GType gdm_user_manager_get_type (void); -GdmUserManager * gdm_user_manager_new (void); +GdmUserManager * gdm_user_manager_ref_default (void); + +GSList * gdm_user_manager_list_users (GdmUserManager *manager); +GdmUser * gdm_user_manager_get_user (GdmUserManager *manager, + const char *user_name); +GdmUser * gdm_user_manager_get_user_by_uid (GdmUserManager *manager, + uid_t uid); gboolean gdm_user_manager_count_users (GdmUserManager *user_manager, gint *user_count, diff -Nur -x patches gdm-2.30.0/daemon/gdm-user-private.h gdm-2.30.2.is.2.30.0/daemon/gdm-user-private.h --- gdm-2.30.0/daemon/gdm-user-private.h 2010-06-09 15:16:34.000000000 +0200 +++ gdm-2.30.2.is.2.30.0/daemon/gdm-user-private.h 2010-06-09 15:16:46.000000000 +0200 @@ -37,6 +37,9 @@ void _gdm_user_remove_session (GdmUser *user, const char *session_id); +void _gdm_user_icon_changed (GdmUser *user); + + G_END_DECLS #endif /* !__GDM_USER_PRIVATE__ */ diff -Nur -x patches gdm-2.30.0/daemon/main.c gdm-2.30.2.is.2.30.0/daemon/main.c --- gdm-2.30.0/daemon/main.c 2010-06-09 15:16:34.000000000 +0200 +++ gdm-2.30.2.is.2.30.0/daemon/main.c 2010-06-09 15:16:46.000000000 +0200 @@ -60,7 +60,6 @@ extern char **environ; -static GdmUserManager *user_manager = NULL; static GdmManager *manager = NULL; static GdmSettings *settings = NULL; static uid_t gdm_uid = -1; @@ -594,17 +593,13 @@ goto out; } - user_manager = gdm_user_manager_new (); - if (user_manager == NULL) { - g_warning ("Could not construct user manager object"); - exit (1); - } - if (! gdm_settings_direct_init (settings, GDMCONFDIR "/gdm.schemas", "/")) { g_warning ("Unable to initialize settings"); goto out; } + gdm_user_manager_ref_default (); + gdm_log_set_debug (is_debug_set ()); gdm_daemon_change_user (&gdm_uid, &gdm_gid); diff -Nur -x patches gdm-2.30.0/data/Xsession.in gdm-2.30.2.is.2.30.0/data/Xsession.in --- gdm-2.30.0/data/Xsession.in 2010-06-09 15:16:34.000000000 +0200 +++ gdm-2.30.2.is.2.30.0/data/Xsession.in 2010-06-09 15:16:46.000000000 +0200 @@ -164,6 +164,9 @@ # run /etc/X11/Xsession.d/ OPTIONFILE=/etc/X11/Xsession.options +USERXSESSION=$HOME/.xsession +USERXSESSIONRC=$HOME/.xsessionrc +ALTUSERXSESSION=$HOME/.Xsession if [ -d /etc/X11/Xsession.d ]; then for i in `ls /etc/X11/Xsession.d/` ; do if [ -r "/etc/X11/Xsession.d/$i" ] && expr "$i" : '^[[:alnum:]_-]\+$' > /dev/null; then diff -Nur -x patches gdm-2.30.0/debian/changelog gdm-2.30.2.is.2.30.0/debian/changelog --- gdm-2.30.0/debian/changelog 2010-06-09 15:15:51.000000000 +0200 +++ gdm-2.30.2.is.2.30.0/debian/changelog 2010-06-09 15:04:11.000000000 +0200 @@ -1,3 +1,33 @@ +gdm (2.30.2.is.2.30.0-0ubuntu1) lucid-proposed; urgency=low + + * The 2.30.2 upstream version introduces new issues so basing a new stable + updated on the current lucid version with selected changes for now, + the new version can be uploaded again later once the issues are resolved + * debian/patches/90_git_run_init_script_before_autologin.patch: + - git change to run the init scripts when autologin is enabled + (lp: #586503) + * debian/patches/91_git_no_icons_watching.patch: + - git change to not monitor the user icons, it creates issues with + some configurations like autofs (lp: #562509) or nfs (lp: #518810) + * debian/patches/92_git_timed_login_user_selection.patch: + - git change to correct selected the default timed login user (lp: #585574) + * debian/patches/93_git_a11y_label.patch: + - git change to correctly set a11y labels + + [ Martin Pitt ] + * 06_run_xsession.d.patch: Export $USERXSESSION, $USERXSESSIONRC, and + $ALTUSERXSESSION, so that running the "custom"/"default" sessions actually + works. Without those, /etc/X11/Xsession.d/50x11-common_determine-startup + decides to run the system default session even if we have the + "allow-user-xsession" option. This is a prerequisite for fixing LP#398300. + + [ Robert Ancell ] + * debian/patches/16_gdmserver_user_manager.patch: + * debian/patches/24_system_uid.patch: + - Update to match IncludeAll behaviour in greeter (LP: #471542) + + -- Sebastien Bacher Wed, 09 Jun 2010 14:10:46 +0200 + gdm (2.30.0-0ubuntu5) lucid; urgency=low * debian/patches/14_guest_session.patch: diff -Nur -x patches gdm-2.30.0/gui/simple-greeter/gdm-greeter-login-window.c gdm-2.30.2.is.2.30.0/gui/simple-greeter/gdm-greeter-login-window.c --- gdm-2.30.0/gui/simple-greeter/gdm-greeter-login-window.c 2010-06-09 15:16:34.000000000 +0200 +++ gdm-2.30.2.is.2.30.0/gui/simple-greeter/gdm-greeter-login-window.c 2010-06-09 15:16:47.000000000 +0200 @@ -109,6 +109,7 @@ guint dialog_mode; + gboolean timed_login_already_enabled; gboolean timed_login_enabled; guint timed_login_delay; char *timed_login_username; @@ -644,34 +645,55 @@ } +static void +handle_request_timed_login (GdmGreeterLoginWindow *login_window) +{ + if (login_window->priv->dialog_mode != MODE_SELECTION) { + reset_dialog (login_window); + } + gdm_user_chooser_widget_set_show_user_auto (GDM_USER_CHOOSER_WIDGET (login_window->priv->user_chooser), TRUE); + + if (!login_window->priv->timed_login_already_enabled) { + gdm_user_chooser_widget_set_chosen_user_name (GDM_USER_CHOOSER_WIDGET (login_window->priv->user_chooser), + GDM_USER_CHOOSER_USER_AUTO); + } +} + +static void +on_request_timed_login_after_users_loaded (GdmUserChooserWidget *user_chooser, + GdmGreeterLoginWindow *login_window) +{ + g_debug ("Users now loaded, handling timed login request"); + handle_request_timed_login (login_window); +} + void gdm_greeter_login_window_request_timed_login (GdmGreeterLoginWindow *login_window, const char *username, int delay) { - static gboolean timed_login_already_enabled; - g_return_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window)); g_debug ("GdmGreeterLoginWindow: requested automatic login for user '%s' in %d seconds", username, delay); if (login_window->priv->timed_login_username != NULL) { - timed_login_already_enabled = TRUE; + login_window->priv->timed_login_already_enabled = TRUE; g_free (login_window->priv->timed_login_username); } else { - timed_login_already_enabled = FALSE; + login_window->priv->timed_login_already_enabled = FALSE; } login_window->priv->timed_login_username = g_strdup (username); login_window->priv->timed_login_delay = delay; - if (login_window->priv->dialog_mode != MODE_SELECTION) { - reset_dialog (login_window); - } - gdm_user_chooser_widget_set_show_user_auto (GDM_USER_CHOOSER_WIDGET (login_window->priv->user_chooser), TRUE); - - if (!timed_login_already_enabled) { - gdm_user_chooser_widget_set_chosen_user_name (GDM_USER_CHOOSER_WIDGET (login_window->priv->user_chooser), - GDM_USER_CHOOSER_USER_AUTO); + if (login_window->priv->user_chooser_loaded) { + g_debug ("Handling timed login request since users are already loaded."); + handle_request_timed_login (login_window); + } else { + g_debug ("Waiting to handle timed login request until users are loaded."); + g_signal_connect (login_window->priv->user_chooser, + "loaded", + G_CALLBACK (on_request_timed_login_after_users_loaded), + login_window); } } diff -Nur -x patches gdm-2.30.0/gui/simple-greeter/gdm-greeter-login-window.ui gdm-2.30.2.is.2.30.0/gui/simple-greeter/gdm-greeter-login-window.ui --- gdm-2.30.0/gui/simple-greeter/gdm-greeter-login-window.ui 2010-03-29 23:42:03.000000000 +0200 +++ gdm-2.30.2.is.2.30.0/gui/simple-greeter/gdm-greeter-login-window.ui 2010-06-09 15:16:47.000000000 +0200 @@ -169,6 +169,10 @@ True + + + + False @@ -182,6 +186,9 @@ True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True + + + 1 diff -Nur -x patches gdm-2.30.0/gui/simple-greeter/gdm-user.c gdm-2.30.2.is.2.30.0/gui/simple-greeter/gdm-user.c --- gdm-2.30.0/gui/simple-greeter/gdm-user.c 2010-03-29 23:42:03.000000000 +0200 +++ gdm-2.30.2.is.2.30.0/gui/simple-greeter/gdm-user.c 2010-06-09 15:16:47.000000000 +0200 @@ -55,7 +55,6 @@ }; enum { - ICON_CHANGED, SESSIONS_CHANGED, LAST_SIGNAL }; @@ -73,15 +72,12 @@ char *shell; GList *sessions; gulong login_frequency; - - GFileMonitor *icon_monitor; }; typedef struct _GdmUserClass { GObjectClass parent_class; - void (* icon_changed) (GdmUser *user); void (* sessions_changed) (GdmUser *user); } GdmUserClass; @@ -302,14 +298,6 @@ 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - signals [ICON_CHANGED] = - g_signal_new ("icon-changed", - G_TYPE_FROM_CLASS (class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GdmUserClass, icon_changed), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); signals [SESSIONS_CHANGED] = g_signal_new ("sessions-changed", G_TYPE_FROM_CLASS (class), @@ -320,61 +308,6 @@ G_TYPE_NONE, 0); } - -static void -on_icon_monitor_changed (GFileMonitor *monitor, - GFile *file, - GFile *other_file, - GFileMonitorEvent event_type, - GdmUser *user) -{ - g_debug ("Icon changed: %d", event_type); - - if (event_type != G_FILE_MONITOR_EVENT_CHANGED && - event_type != G_FILE_MONITOR_EVENT_CREATED) { - return; - } - - _gdm_user_icon_changed (user); -} - -static void -update_icon_monitor (GdmUser *user) -{ - GFile *file; - GError *error; - char *path; - - if (user->home_dir == NULL) { - return; - } - - if (user->icon_monitor != NULL) { - g_file_monitor_cancel (user->icon_monitor); - user->icon_monitor = NULL; - } - - path = g_build_filename (user->home_dir, ".face", NULL); - g_debug ("adding monitor for '%s'", path); - file = g_file_new_for_path (path); - error = NULL; - user->icon_monitor = g_file_monitor_file (file, - G_FILE_MONITOR_NONE, - NULL, - &error); - if (user->icon_monitor != NULL) { - g_signal_connect (user->icon_monitor, - "changed", - G_CALLBACK (on_icon_monitor_changed), - user); - } else { - g_warning ("Unable to monitor %s: %s", path, error->message); - g_error_free (error); - } - g_object_unref (file); - g_free (path); -} - static void gdm_user_init (GdmUser *user) { @@ -392,8 +325,6 @@ user = GDM_USER (object); - g_file_monitor_cancel (user->icon_monitor); - g_free (user->user_name); g_free (user->real_name); g_free (user->display_name); @@ -499,7 +430,6 @@ g_free (user->home_dir); user->home_dir = g_strdup (pwent->pw_dir); g_object_notify (G_OBJECT (user), "home-directory"); - g_signal_emit (user, signals[ICON_CHANGED], 0); } /* Shell */ @@ -513,28 +443,10 @@ g_object_notify (G_OBJECT (user), "shell"); } - update_icon_monitor (user); - g_object_thaw_notify (G_OBJECT (user)); } /** - * _gdm_user_icon_changed: - * @user: the user to emit the signal for. - * - * Emits the "icon-changed" signal for @user. - * - * Since: 1.0 - **/ -void -_gdm_user_icon_changed (GdmUser *user) -{ - g_return_if_fail (GDM_IS_USER (user)); - - g_signal_emit (user, signals[ICON_CHANGED], 0); -} - -/** * gdm_user_get_uid: * @user: the user object to examine. * diff -Nur -x patches gdm-2.30.0/gui/simple-greeter/gdm-user-manager.c gdm-2.30.2.is.2.30.0/gui/simple-greeter/gdm-user-manager.c --- gdm-2.30.0/gui/simple-greeter/gdm-user-manager.c 2010-06-09 15:16:34.000000000 +0200 +++ gdm-2.30.2.is.2.30.0/gui/simple-greeter/gdm-user-manager.c 2010-06-09 15:16:47.000000000 +0200 @@ -489,13 +489,6 @@ g_signal_emit (manager, signals [USER_IS_LOGGED_IN_CHANGED], 0, user); } -static void -on_user_icon_changed (GdmUser *user, - GdmUserManager *manager) -{ - g_debug ("GdmUserManager: user icon changed"); -} - static char * get_seat_id_for_session (DBusGConnection *connection, const char *session_id) @@ -742,10 +735,6 @@ "sessions-changed", G_CALLBACK (on_user_sessions_changed), manager); - g_signal_connect (user, - "icon-changed", - G_CALLBACK (on_user_icon_changed), - manager); return user; } diff -Nur -x patches gdm-2.30.0/gui/simple-greeter/gdm-user-private.h gdm-2.30.2.is.2.30.0/gui/simple-greeter/gdm-user-private.h --- gdm-2.30.0/gui/simple-greeter/gdm-user-private.h 2010-03-29 23:42:03.000000000 +0200 +++ gdm-2.30.2.is.2.30.0/gui/simple-greeter/gdm-user-private.h 2010-06-09 15:16:47.000000000 +0200 @@ -37,8 +37,6 @@ void _gdm_user_remove_session (GdmUser *user, const char *session_id); -void _gdm_user_icon_changed (GdmUser *user); - void _gdm_user_show_full_display_name (GdmUser *user); void _gdm_user_show_short_display_name (GdmUser *user);