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

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