diff -up src/fusa-manager.c.many-users src/fusa-manager.c --- src/fusa-manager.c.many-users 2007-09-17 01:56:45.000000000 -0400 +++ src/fusa-manager.c 2007-09-17 02:08:59.000000000 -0400 @@ -129,11 +129,13 @@ struct _FusaManager GHashTable *shells; GHashTable *exclusions; + GHashTable *inclusions; gchar *global_face_dir; uid_t minimal_uid; gsize user_max_file; gint max_icon_size; + guint8 include_all : 1; guint8 allow_root : 1; guint8 relax_group : 1; guint8 relax_other : 1; @@ -341,6 +343,8 @@ fusa_manager_init (FusaManager *manager) /* GDM config file */ manager->exclusions = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + manager->inclusions = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, NULL); reload_gdm_config (manager, FALSE); error = NULL; uri = g_filename_to_uri (GDMCONFIGFILE, NULL, &error); @@ -645,6 +649,38 @@ merge_gdm_exclusions (FusaManager *mana return TRUE; } +/* Returns TRUE if changed */ +static gboolean +merge_gdm_inclusions (FusaManager *manager, + gchar **includev, + const gchar *include_default[]) +{ + gint i; + + if (strv_equals_string_table (includev, manager->inclusions)) + return FALSE; + + g_hash_table_foreach_remove (manager->inclusions, + clear_hash_table_hrfunc, NULL); + + if (include_default) + { + for (i = 0; include_default[i] != NULL; i++) + g_hash_table_insert (manager->inclusions, + g_strdup (include_default[i]), + GUINT_TO_POINTER (TRUE)); + } + + if (includev) + { + for (i = 0; includev[i] != NULL; i++) + g_hash_table_insert (manager->inclusions, + g_strdup (includev[i]), GUINT_TO_POINTER (TRUE)); + } + + return TRUE; +} + static void resolve_dirty_flags(GdmResultState dummy1, const gchar *dummy2, gpointer data) { FusaManager *manager = data; @@ -687,6 +723,27 @@ static void handler_Exclude(GdmResultSta manager->users_dirty = TRUE; } +static void handler_Include(GdmResultState is_ok, const gchar *value, gpointer data) +{ + FusaManager *manager = data; + gchar** includev = g_strsplit (value, ",", G_MAXINT); + + if (merge_gdm_inclusions (manager, includev, NULL)) + manager->users_dirty = TRUE; +} + +static void handler_IncludeAll(GdmResultState is_ok, const gchar *value, gpointer data) +{ + FusaManager *manager = data; + gboolean tmp_include_all = strcasecmp(value, "false") != 0; + + if (tmp_include_all != manager->include_all) + { + manager->include_all = tmp_include_all; + manager->users_dirty = TRUE; + } +} + static void handler_GlobalFaceDir(GdmResultState is_ok, const gchar *value, gpointer data) { FusaManager *manager = data; @@ -744,6 +801,8 @@ struct SettingsHandler { } settings_handlers[] = { { "greeter/MinimalUID", handler_MinimalUID }, { "greeter/Exclude", handler_Exclude }, + { "greeter/Include", handler_Include }, + { "greeter/IncludeAll", handler_IncludeAll }, { "greeter/GlobalFaceDir", handler_GlobalFaceDir }, { "security/UserMaxFile", handler_UserMaxFile }, { "security/AllowRoot", handler_AllowRoot }, @@ -798,27 +857,76 @@ reload_shells (FusaManager *manager) endusershell (); } -static void -reload_passwd (FusaManager *manager) +#define OLD_FLAG 1 +#define NEW_FLAG 2 + +static void set_flag (GObject *obj, int flag) { - struct passwd *pwent; - GSList *old_users, *new_users, *list; - - old_users = NULL; - new_users = NULL; + int flags; + + flags = GPOINTER_TO_INT (g_object_get_data (obj, "fusa-user-flags")); + flags |= flag; + g_object_set_data (obj, "fusa-user-flags", GINT_TO_POINTER (flags)); +} + +static int get_flags (GObject *obj) +{ + return GPOINTER_TO_INT (g_object_get_data (obj, "fusa-user-flags")); +} + +static void clear_flags (GObject *obj) +{ + g_object_set_data (obj, "fusa-user-flags", NULL); +} - g_hash_table_foreach (manager->users, listify_hash_values_hfunc, &old_users); - g_slist_foreach (old_users, (GFunc) g_object_ref, NULL); +static void mark_as_old (gpointer key, gpointer value, gpointer data) +{ + GObject *user = value; + set_flag (user, OLD_FLAG); /* Make sure we keep users who are logged in no matter what. */ - for (list = old_users; list; list = list->next) + if (fusa_user_get_n_displays (FUSA_USER (user))) { - if (fusa_user_get_n_displays (list->data)) - { - g_object_freeze_notify (G_OBJECT (list->data)); - new_users = g_slist_prepend (new_users, g_object_ref (list->data)); - } + set_flag (user, NEW_FLAG); + g_object_freeze_notify (user); + } +} + +static gboolean emit_add_or_remove (gpointer key, gpointer value, gpointer data) +{ + FusaManager *manager = data; + int flags; + + flags = get_flags (value); + clear_flags (value); + + if (flags == NEW_FLAG) + { + g_signal_emit (manager, signals[USER_ADDED], 0, value); + return FALSE; + } + else if (flags == OLD_FLAG) + { + g_signal_emit (manager, signals[USER_REMOVED], 0, value); + g_hash_table_remove (manager->users_by_uid, + GINT_TO_POINTER (fusa_user_get_uid (value))); + return TRUE; } + else + return FALSE; +} + +static void thaw (gpointer key, gpointer value, gpointer data) +{ + g_object_thaw_notify (value); +} + +static void +reload_passwd (FusaManager *manager) +{ + struct passwd *pwent; + + g_hash_table_foreach (manager->users, mark_as_old, NULL); setpwent (); @@ -841,65 +949,36 @@ reload_passwd (FusaManager *manager) if (g_hash_table_lookup (manager->exclusions, pwent->pw_name)) continue; + if (g_hash_table_size (manager->inclusions) > 0) + { + if (!g_hash_table_lookup (manager->inclusions, pwent->pw_name)) + continue; + } + else if (!manager->include_all) + continue; + user = g_hash_table_lookup (manager->users, pwent->pw_name); - /* Update users already in the *new* list */ - if (g_slist_find (new_users, user)) - { - _fusa_user_update (user, pwent); - continue; - } - - if (!user) - user = g_object_new (FUSA_TYPE_USER, "manager", manager, NULL); - else - g_object_ref (user); + if (!user) + { + user = g_object_new (FUSA_TYPE_USER, "manager", manager, NULL); + g_hash_table_insert (manager->users, + g_strdup (pwent->pw_name), + user); + g_hash_table_insert (manager->users_by_uid, + GINT_TO_POINTER (pwent->pw_uid), + g_object_ref (user)); + } - /* Freeze & update users not already in the new list */ g_object_freeze_notify (G_OBJECT (user)); _fusa_user_update (user, pwent); - - new_users = g_slist_prepend (new_users, user); + set_flag (G_OBJECT (user), NEW_FLAG); } endpwent (); - /* Go through and handle added users */ - for (list = new_users; list; list = list->next) - { - if (!g_slist_find (old_users, list->data)) - { - g_hash_table_insert (manager->users, - g_strdup (fusa_user_get_user_name (list->data)), - g_object_ref (list->data)); - g_hash_table_insert (manager->users_by_uid, - GINT_TO_POINTER (fusa_user_get_uid (list->data)), - list->data); - g_signal_emit (manager, signals[USER_ADDED], 0, list->data); - } - } - - /* Go through and handle removed users */ - for (list = old_users; list; list = list->next) - { - if (!g_slist_find (new_users, list->data)) - { - g_signal_emit (manager, signals[USER_REMOVED], 0, list->data); - g_hash_table_remove (manager->users_by_uid, - GINT_TO_POINTER (fusa_user_get_uid (list->data))); - g_hash_table_remove (manager->users, - fusa_user_get_user_name (list->data)); - /* FIXME: signals[USER_REMOVED]??? Why not? */ - } - } - - /* Cleanup */ - g_slist_foreach (new_users, (GFunc) g_object_thaw_notify, NULL); - g_slist_foreach (new_users, (GFunc) g_object_unref, NULL); - g_slist_free (new_users); - - g_slist_foreach (old_users, (GFunc) g_object_unref, NULL); - g_slist_free (old_users); + g_hash_table_foreach_remove (manager->users, emit_add_or_remove, manager); + g_hash_table_foreach (manager->users, thaw, NULL); } diff -up src/fusa-user.c.many-users src/fusa-user.c --- src/fusa-user.c.many-users 2007-04-09 12:01:02.000000000 -0400 +++ src/fusa-user.c 2007-09-17 01:56:45.000000000 -0400 @@ -81,6 +81,7 @@ struct _FusaUser gchar *display_name; gchar *home_dir; gchar *shell; + gchar *key; GSList *displays; }; @@ -444,6 +445,9 @@ _fusa_user_update (FusaUser * g_object_notify (G_OBJECT (user), "shell"); } + g_free (user->key); + user->key = NULL; + g_object_thaw_notify (G_OBJECT (user)); } @@ -684,12 +688,28 @@ fusa_user_render_icon (FusaUser *user, return _fusa_manager_render_icon (user->manager, user, widget, icon_size); } +static gchar * +get_collate_key (FusaUser *user) +{ + if (!user->key) + { + gchar *str; + + if (user->display_name) + str = user->display_name; + else + str = user->username; + + user->key = g_utf8_collate_key (str, -1); + } + + return user->key; +} + gint fusa_user_collate (FusaUser *user1, FusaUser *user2) { - const gchar *str1, *str2; - g_return_val_if_fail (user1 == NULL || FUSA_IS_USER (user1), 0); g_return_val_if_fail (user2 == NULL || FUSA_IS_USER (user2), 0); @@ -702,24 +722,5 @@ fusa_user_collate (FusaUser *user1, if (!user1 && !user2) return 0; - if (user1->display_name) - str1 = user1->display_name; - else - str1 = user1->username; - - if (user2->display_name) - str2 = user2->display_name; - else - str2 = user2->username; - - if (!str1 && str2) - return -1; - - if (str1 && !str2) - return 1; - - if (!str1 && !str2) - return 0; - - return g_utf8_collate (str1, str2); + return strcmp (get_collate_key (user1), get_collate_key (user2)); }