Blame SOURCES/0006-daemon-add-new-HasMultipleUsers-and-HasNoUsers-prope.patch

34a24a
From dc41728b9c4ec35fb7bd41cdc646b77dcb41f6dd Mon Sep 17 00:00:00 2001
34a24a
From: Ray Strode <rstrode@redhat.com>
34a24a
Date: Mon, 2 Oct 2017 15:45:01 -0400
34a24a
Subject: [PATCH 06/13] daemon: add new HasMultipleUsers and HasNoUsers
34a24a
 properties
34a24a
34a24a
Every gnome-shell instance wants to know if the system has multiple
34a24a
users or not, in order to know whether or not to show the
34a24a
'Switch User' feature in the menu.
34a24a
34a24a
accountsservice doesn't provide this information directly, though,
34a24a
so libaccountsservice instead requests a list of all users on the
34a24a
system and counts the provided list, filtering out system users.
34a24a
34a24a
This is a lot of work for every gnome-shell instance to do, when
34a24a
it doesn't actually need the list of users at all.
34a24a
34a24a
This adds a new property HasMultipleUsers which libaccountsservice
34a24a
can watch for instead.  For good measure, this commit also adds a
34a24a
HasNoUsers boolean which can be used to know whether or not to start
34a24a
gnome-initial-setup.
34a24a
---
34a24a
 data/org.freedesktop.Accounts.xml | 20 ++++++++++++++++++++
34a24a
 src/daemon.c                      | 24 +++++++++++++++++++++---
34a24a
 2 files changed, 41 insertions(+), 3 deletions(-)
34a24a
34a24a
diff --git a/data/org.freedesktop.Accounts.xml b/data/org.freedesktop.Accounts.xml
34a24a
index 692540a..ed7db50 100644
34a24a
--- a/data/org.freedesktop.Accounts.xml
34a24a
+++ b/data/org.freedesktop.Accounts.xml
34a24a
@@ -197,32 +197,52 @@
34a24a
           <doc:para>
34a24a
             Emitted when a user is added.
34a24a
           </doc:para>
34a24a
         </doc:description>
34a24a
       </doc:doc>
34a24a
     </signal>
34a24a
 
34a24a
     <signal name="UserDeleted">
34a24a
       <arg name="user" type="o">
34a24a
         <doc:doc><doc:summary>Object path of the user that was deleted.</doc:summary></doc:doc>
34a24a
       </arg>
34a24a
       <doc:doc>
34a24a
         <doc:description>
34a24a
           <doc:para>
34a24a
             Emitted when a user is deleted.
34a24a
           </doc:para>
34a24a
         </doc:description>
34a24a
       </doc:doc>
34a24a
     </signal>
34a24a
 
34a24a
    <property name="DaemonVersion" type="s" access="read">
34a24a
      <doc:doc>
34a24a
        <doc:description>
34a24a
          <doc:para>
34a24a
            The version of the running daemon.
34a24a
          </doc:para>
34a24a
        </doc:description>
34a24a
      </doc:doc>
34a24a
    </property>
34a24a
 
34a24a
+   <property name="HasNoUsers" type="b" access="read">
34a24a
+     <doc:doc>
34a24a
+       <doc:description>
34a24a
+         <doc:para>
34a24a
+           Whether or not the system has no users
34a24a
+         </doc:para>
34a24a
+       </doc:description>
34a24a
+     </doc:doc>
34a24a
+   </property>
34a24a
+
34a24a
+   <property name="HasMultipleUsers" type="b" access="read">
34a24a
+     <doc:doc>
34a24a
+       <doc:description>
34a24a
+         <doc:para>
34a24a
+           Whether or not the system has multiple users
34a24a
+         </doc:para>
34a24a
+       </doc:description>
34a24a
+     </doc:doc>
34a24a
+   </property>
34a24a
+
34a24a
   </interface>
34a24a
 </node>
34a24a
diff --git a/src/daemon.c b/src/daemon.c
34a24a
index 6e3e4b3..a4e18df 100644
34a24a
--- a/src/daemon.c
34a24a
+++ b/src/daemon.c
34a24a
@@ -35,60 +35,61 @@
34a24a
 #include <unistd.h>
34a24a
 #include <errno.h>
34a24a
 #include <sys/types.h>
34a24a
 
34a24a
 #include <glib.h>
34a24a
 #include <glib/gi18n.h>
34a24a
 #include <glib-object.h>
34a24a
 #include <glib/gstdio.h>
34a24a
 #include <gio/gio.h>
34a24a
 #include <polkit/polkit.h>
34a24a
 
34a24a
 #include "user-classify.h"
34a24a
 #include "wtmp-helper.h"
34a24a
 #include "daemon.h"
34a24a
 #include "util.h"
34a24a
 
34a24a
 #define PATH_PASSWD "/etc/passwd"
34a24a
 #define PATH_SHADOW "/etc/shadow"
34a24a
 #define PATH_GROUP "/etc/group"
34a24a
 #define PATH_GDM_CUSTOM "/etc/gdm/custom.conf"
34a24a
 
34a24a
 enum {
34a24a
         PROP_0,
34a24a
         PROP_DAEMON_VERSION
34a24a
 };
34a24a
 
34a24a
 struct DaemonPrivate {
34a24a
         GDBusConnection *bus_connection;
34a24a
 
34a24a
         GHashTable *users;
34a24a
+        gsize number_of_normal_users;
34a24a
         GList *explicitly_requested_users;
34a24a
 
34a24a
         User *autologin;
34a24a
 
34a24a
         GFileMonitor *passwd_monitor;
34a24a
         GFileMonitor *shadow_monitor;
34a24a
         GFileMonitor *group_monitor;
34a24a
         GFileMonitor *gdm_monitor;
34a24a
         GFileMonitor *wtmp_monitor;
34a24a
 
34a24a
         guint reload_id;
34a24a
         guint autologin_id;
34a24a
 
34a24a
         PolkitAuthority *authority;
34a24a
         GHashTable *extension_ifaces;
34a24a
 };
34a24a
 
34a24a
 typedef struct passwd * (* EntryGeneratorFunc) (Daemon *, GHashTable *, gpointer *, struct spwd **shadow_entry);
34a24a
 
34a24a
 static void daemon_accounts_accounts_iface_init (AccountsAccountsIface *iface);
34a24a
 
34a24a
 G_DEFINE_TYPE_WITH_CODE (Daemon, daemon, ACCOUNTS_TYPE_ACCOUNTS_SKELETON, G_IMPLEMENT_INTERFACE (ACCOUNTS_TYPE_ACCOUNTS, daemon_accounts_accounts_iface_init));
34a24a
 
34a24a
 #define DAEMON_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_DAEMON, DaemonPrivate))
34a24a
 
34a24a
 static const GDBusErrorEntry accounts_error_entries[] =
34a24a
 { 
34a24a
         { ERROR_FAILED, "org.freedesktop.Accounts.Error.Failed" },
34a24a
         { ERROR_USER_EXISTS, "org.freedesktop.Accounts.Error.UserExists" },
34a24a
         { ERROR_USER_DOES_NOT_EXIST, "org.freedesktop.Accounts.Error.UserDoesNotExist" },
34a24a
@@ -395,98 +396,115 @@ load_entries (Daemon             *daemon,
34a24a
 
34a24a
                         /* freeze & update users not already in the new list */
34a24a
                         g_object_freeze_notify (G_OBJECT (user));
34a24a
                         user_update_from_pwent (user, pwent, spent);
34a24a
 
34a24a
                         g_hash_table_insert (users, g_strdup (user_get_user_name (user)), user);
34a24a
                         g_debug ("loaded user: %s", user_get_user_name (user));
34a24a
                 }
34a24a
 
34a24a
                 if (!explicitly_requested) {
34a24a
                         user_set_cached (user, TRUE);
34a24a
                 }
34a24a
         }
34a24a
 
34a24a
         /* Generator should have cleaned up */
34a24a
         g_assert (generator_state == NULL);
34a24a
 }
34a24a
 
34a24a
 static GHashTable *
34a24a
 create_users_hash_table (void)
34a24a
 {
34a24a
         return g_hash_table_new_full (g_str_hash,
34a24a
                                       g_str_equal,
34a24a
                                       g_free,
34a24a
                                       g_object_unref);
34a24a
 }
34a24a
 
34a24a
 static void
34a24a
 reload_users (Daemon *daemon)
34a24a
 {
34a24a
+        AccountsAccounts *accounts = ACCOUNTS_ACCOUNTS (daemon);
34a24a
+        gboolean had_no_users, has_no_users, had_multiple_users, has_multiple_users;
34a24a
         GHashTable *users;
34a24a
         GHashTable *old_users;
34a24a
         GHashTable *local;
34a24a
         GHashTableIter iter;
34a24a
+        gsize number_of_normal_users = 0;
34a24a
         gpointer name;
34a24a
         User *user;
34a24a
 
34a24a
         /* Track the users that we saw during our (re)load */
34a24a
         users = create_users_hash_table ();
34a24a
 
34a24a
         /*
34a24a
          * NOTE: As we load data from all the sources, notifies are
34a24a
          * frozen in load_entries() and then thawed as we process
34a24a
          * them below.
34a24a
          */
34a24a
 
34a24a
         /* Load the local users into our hash table */
34a24a
         load_entries (daemon, users, FALSE, entry_generator_fgetpwent);
34a24a
         local = g_hash_table_new (g_str_hash, g_str_equal);
34a24a
         g_hash_table_iter_init (&iter, users);
34a24a
         while (g_hash_table_iter_next (&iter, &name, NULL))
34a24a
                 g_hash_table_add (local, name);
34a24a
 
34a24a
         /* and add users to hash table that were explicitly requested  */
34a24a
         load_entries (daemon, users, TRUE, entry_generator_requested_users);
34a24a
 
34a24a
         /* Now add/update users from other sources, possibly non-local */
34a24a
         load_entries (daemon, users, FALSE, entry_generator_cachedir);
34a24a
 
34a24a
         wtmp_helper_update_login_frequencies (users);
34a24a
 
34a24a
-        /* Mark which users are local, which are not */
34a24a
+        /* Count the non-system users. Mark which users are local, which are not. */
34a24a
         g_hash_table_iter_init (&iter, users);
34a24a
-        while (g_hash_table_iter_next (&iter, &name, (gpointer *)&user))
34a24a
+        while (g_hash_table_iter_next (&iter, &name, (gpointer *)&user)) {
34a24a
+                if (!user_get_system_account (user))
34a24a
+                        number_of_normal_users++;
34a24a
                 user_update_local_account_property (user, g_hash_table_lookup (local, name) != NULL);
34a24a
-
34a24a
+        }
34a24a
         g_hash_table_destroy (local);
34a24a
 
34a24a
+        had_no_users = accounts_accounts_get_has_no_users (accounts);
34a24a
+        has_no_users = number_of_normal_users == 0;
34a24a
+
34a24a
+        if (had_no_users != has_no_users)
34a24a
+                accounts_accounts_set_has_no_users (accounts, has_no_users);
34a24a
+
34a24a
+        had_multiple_users = accounts_accounts_get_has_multiple_users (accounts);
34a24a
+        has_multiple_users = number_of_normal_users > 1;
34a24a
+
34a24a
+        if (had_multiple_users != has_multiple_users)
34a24a
+                accounts_accounts_set_has_multiple_users (accounts, has_multiple_users);
34a24a
+
34a24a
         /* Swap out the users */
34a24a
         old_users = daemon->priv->users;
34a24a
         daemon->priv->users = users;
34a24a
 
34a24a
         /* Remove all the old users */
34a24a
         g_hash_table_iter_init (&iter, old_users);
34a24a
         while (g_hash_table_iter_next (&iter, &name, (gpointer *)&user)) {
34a24a
                 User *refreshed_user;
34a24a
 
34a24a
                 refreshed_user = g_hash_table_lookup (users, name);
34a24a
 
34a24a
                 if (!refreshed_user || !user_get_cached (refreshed_user)) {
34a24a
                         user_unregister (user);
34a24a
                         accounts_accounts_emit_user_deleted (ACCOUNTS_ACCOUNTS (daemon),
34a24a
                                                              user_get_object_path (user));
34a24a
                 }
34a24a
         }
34a24a
 
34a24a
         /* Register all the new users */
34a24a
         g_hash_table_iter_init (&iter, users);
34a24a
         while (g_hash_table_iter_next (&iter, &name, (gpointer *)&user)) {
34a24a
                 User *stale_user;
34a24a
 
34a24a
                 stale_user = g_hash_table_lookup (old_users, name);
34a24a
 
34a24a
                 if (!stale_user || !user_get_cached (stale_user) && user_get_cached (user)) {
34a24a
                         user_register (user);
34a24a
                         accounts_accounts_emit_user_added (ACCOUNTS_ACCOUNTS (daemon),
34a24a
                                                            user_get_object_path (user));
34a24a
                 }
34a24a
-- 
34a24a
2.14.1
34a24a