-static LightDMUser *
-get_user_by_name (LightDMUserList *user_list, const gchar *username)
-{
- LightDMUserListPrivate *priv = GET_LIST_PRIVATE (user_list);
- GList *link;
-
- for (link = priv->users; link; link = link->next)
- {
- LightDMUser *user = link->data;
- if (strcmp (lightdm_user_get_name (user), username) == 0)
- return user;
- }
-
- return NULL;
-}
-
-static gint
-compare_user (gconstpointer a, gconstpointer b)
-{
- LightDMUser *user_a = (LightDMUser *) a, *user_b = (LightDMUser *) b;
- return strcmp (lightdm_user_get_display_name (user_a), lightdm_user_get_display_name (user_b));
-}
-
-static gboolean
-update_passwd_user (LightDMUser *user, const gchar *real_name, const gchar *home_directory, const gchar *image)
-{
- LightDMUserPrivate *priv = GET_USER_PRIVATE (user);
-
- if (g_strcmp0 (lightdm_user_get_real_name (user), real_name) == 0 &&
- g_strcmp0 (lightdm_user_get_home_directory (user), home_directory) == 0 &&
- g_strcmp0 (lightdm_user_get_image (user), image) == 0)
- return FALSE;
-
- g_free (priv->real_name);
- priv->real_name = g_strdup (real_name);
- g_free (priv->home_directory);
- priv->home_directory = g_strdup (home_directory);
- g_free (priv->image);
- priv->image = g_strdup (image);
-
- return TRUE;
-}
-
-static void
-user_changed_cb (LightDMUser *user, LightDMUserList *user_list)
-{
- g_signal_emit (user_list, list_signals[USER_CHANGED], 0, user);
-}
-
-static void
-load_passwd_file (LightDMUserList *user_list, gboolean emit_add_signal)
-{
- LightDMUserListPrivate *priv = GET_LIST_PRIVATE (user_list);
- GKeyFile *config;
- gchar *value;
- gint minimum_uid;
- gchar **hidden_users, **hidden_shells;
- GList *users = NULL, *old_users, *new_users = NULL, *changed_users = NULL, *link;
- GError *error = NULL;
-
- g_debug ("Loading user config from %s", USER_CONFIG_FILE);
-
- config = g_key_file_new ();
- g_key_file_load_from_file (config, USER_CONFIG_FILE, G_KEY_FILE_NONE, &error);
- if (error && !g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
- g_warning ("Failed to load configuration from %s: %s", USER_CONFIG_FILE, error->message); // FIXME: Don't make warning on no file, just info
- g_clear_error (&error);
-
- if (g_key_file_has_key (config, "UserList", "minimum-uid", NULL))
- minimum_uid = g_key_file_get_integer (config, "UserList", "minimum-uid", NULL);
- else
- minimum_uid = 500;
-
- value = g_key_file_get_string (config, "UserList", "hidden-users", NULL);
- if (!value)
- value = g_strdup ("nobody nobody4 noaccess");
- hidden_users = g_strsplit (value, " ", -1);
- g_free (value);
-
- value = g_key_file_get_string (config, "UserList", "hidden-shells", NULL);
- if (!value)
- value = g_strdup ("/bin/false /usr/sbin/nologin");
- hidden_shells = g_strsplit (value, " ", -1);
- g_free (value);
-
- g_key_file_free (config);
-
- setpwent ();
-
- while (TRUE)
- {
- struct passwd *entry;
- LightDMUser *user;
- LightDMUserPrivate *user_priv;
- char **tokens;
- gchar *real_name, *image;
- int i;
-
- errno = 0;
- entry = getpwent ();
- if (!entry)
- break;
-
- /* Ignore system users */
- if (entry->pw_uid < minimum_uid)
- continue;
-
- /* Ignore users disabled by shell */
- if (entry->pw_shell)
- {
- for (i = 0; hidden_shells[i] && strcmp (entry->pw_shell, hidden_shells[i]) != 0; i++);
- if (hidden_shells[i])
- continue;
- }
-
- /* Ignore certain users */
- for (i = 0; hidden_users[i] && strcmp (entry->pw_name, hidden_users[i]) != 0; i++);
- if (hidden_users[i])
- continue;
-
- tokens = g_strsplit (entry->pw_gecos, ",", -1);
- if (tokens[0] != NULL && tokens[0][0] != '\0')
- real_name = g_strdup (tokens[0]);
- else
- real_name = g_strdup ("");
- g_strfreev (tokens);
-
- image = g_build_filename (entry->pw_dir, ".face", NULL);
- if (!g_file_test (image, G_FILE_TEST_EXISTS))
- {
- g_free (image);
- image = g_build_filename (entry->pw_dir, ".face.icon", NULL);
- if (!g_file_test (image, G_FILE_TEST_EXISTS))
- {
- g_free (image);
- image = NULL;
- }
- }
-
- user = g_object_new (LIGHTDM_TYPE_USER, NULL);
- user_priv = GET_USER_PRIVATE (user);
- user_priv->user_list = user_list;
- g_free (user_priv->name);
- user_priv->name = g_strdup (entry->pw_name);
- g_free (user_priv->real_name);
- user_priv->real_name = real_name;
- g_free (user_priv->home_directory);
- user_priv->home_directory = g_strdup (entry->pw_dir);
- g_free (user_priv->image);
- user_priv->image = image;
-
- /* Update existing users if have them */
- for (link = priv->users; link; link = link->next)
- {
- LightDMUser *info = link->data;
- if (strcmp (lightdm_user_get_name (info), lightdm_user_get_name (user)) == 0)
- {
- if (update_passwd_user (info, lightdm_user_get_real_name (user), lightdm_user_get_home_directory (user), lightdm_user_get_image (user)))
- changed_users = g_list_insert_sorted (changed_users, info, compare_user);
- g_object_unref (user);
- user = info;
- break;
- }
- }
- if (!link)
- {
- /* Only notify once we have loaded the user list */
- if (priv->have_users)
- new_users = g_list_insert_sorted (new_users, user, compare_user);
- }
- users = g_list_insert_sorted (users, user, compare_user);
- }
- g_strfreev (hidden_users);
- g_strfreev (hidden_shells);
-
- if (errno != 0)
- g_warning ("Failed to read password database: %s", strerror (errno));
-
- endpwent ();
-
- /* Use new user list */
- old_users = priv->users;
- priv->users = users;
-
- /* Notify of changes */
- for (link = new_users; link; link = link->next)
- {
- LightDMUser *info = link->data;
- g_debug ("User %s added", lightdm_user_get_name (info));
- g_signal_connect (info, "changed", G_CALLBACK (user_changed_cb), user_list);
- if (emit_add_signal)
- g_signal_emit (user_list, list_signals[USER_ADDED], 0, info);
- }
- g_list_free (new_users);
- for (link = changed_users; link; link = link->next)
- {
- LightDMUser *info = link->data;
- g_debug ("User %s changed", lightdm_user_get_name (info));
- g_signal_emit (info, user_signals[CHANGED], 0);
- }
- g_list_free (changed_users);
- for (link = old_users; link; link = link->next)
- {
- GList *new_link;
-
- /* See if this user is in the current list */
- for (new_link = priv->users; new_link; new_link = new_link->next)
- {
- if (new_link->data == link->data)
- break;
- }
-
- if (!new_link)
- {
- LightDMUser *info = link->data;
- g_debug ("User %s removed", lightdm_user_get_name (info));
- g_signal_emit (user_list, list_signals[USER_REMOVED], 0, info);
- g_object_unref (info);
- }
- }
- g_list_free (old_users);
-}
-