]> rtime.felk.cvut.cz Git - sojka/lightdm.git/commitdiff
And convert accounts.c to use new sharable CommonUser class too
authorMichael Terry <michael.terry@canonical.com>
Tue, 4 Feb 2014 22:55:32 +0000 (17:55 -0500)
committerMichael Terry <michael.terry@canonical.com>
Tue, 4 Feb 2014 22:55:32 +0000 (17:55 -0500)
20 files changed:
Makefile.am
common/Makefile.am [new file with mode: 0644]
common/configuration.c [moved from src/configuration.c with 100% similarity]
common/configuration.h [moved from src/configuration.h with 100% similarity]
common/dmrc.c [moved from src/dmrc.c with 63% similarity]
common/dmrc.h [moved from src/dmrc.h with 81% similarity]
common/privileges.c [moved from src/privileges.c with 68% similarity]
common/privileges.h [moved from src/privileges.h with 88% similarity]
common/user-list.c
common/user-list.h
configure.ac
liblightdm-gobject/Makefile.am
liblightdm-gobject/session.c
liblightdm-gobject/user.c
src/Makefile.am
src/accounts.c
src/accounts.h
src/session-child.c
tests/src/test-gobject-greeter.c
tests/src/test-runner.c

index 73c6788e93bf7cce892f98cd9d5531a157d871b2..106e891e0fe38776fb37a83cba7d2d80ecad80f6 100644 (file)
@@ -1,4 +1,4 @@
-SUBDIRS =
+SUBDIRS = common
 if COMPILE_LIBLIGHTDM_GOBJECT
 SUBDIRS += liblightdm-gobject
 endif
diff --git a/common/Makefile.am b/common/Makefile.am
new file mode 100644 (file)
index 0000000..f289e6a
--- /dev/null
@@ -0,0 +1,23 @@
+# -*- Mode: Automake; indent-tabs-mode: t; tab-width: 4 -*-
+
+noinst_LTLIBRARIES = libcommon.la
+
+libcommon_la_SOURCES = \
+       configuration.c \
+       configuration.h \
+       dmrc.c \
+       dmrc.h \
+       privileges.c \
+       privileges.h \
+       user-list.c \
+       user-list.h
+
+libcommon_la_CFLAGS = \
+       $(WARN_CFLAGS) \
+       $(GLIB_CFLAGS)
+
+libcommon_la_LIBADD = \
+       $(GLIB_LDFLAGS)
+
+DISTCLEANFILES = \
+       Makefile.in
similarity index 100%
rename from src/configuration.c
rename to common/configuration.c
similarity index 100%
rename from src/configuration.h
rename to common/configuration.h
similarity index 63%
rename from src/dmrc.c
rename to common/dmrc.c
index ccde1bf14d9b3daae0d93a1892deb50db3fd5cdf..e7121ef79149aa6a1b428a848a539828bb844d12 100644 (file)
 
 #include "dmrc.h"
 #include "configuration.h"
-#include "accounts.h"
 #include "privileges.h"
+#include "user-list.h"
 
 GKeyFile *
-dmrc_load (const gchar *username)
+dmrc_load (CommonUser *user)
 {
-    User *user;
     GKeyFile *dmrc_file;
     gchar *path;
     gboolean have_dmrc, drop_privileges;
 
     dmrc_file = g_key_file_new ();
 
-    user = accounts_get_user_by_name (username);
-    if (!user)
-    {
-        g_warning ("Cannot load .dmrc file, unable to get information on user %s", username);      
-        return dmrc_file;
-    }
-
     /* Load from the user directory, if this fails (e.g. the user directory
      * is not yet mounted) then load from the cache */
-    path = g_build_filename (user_get_home_directory (user), ".dmrc", NULL);
+    path = g_build_filename (common_user_get_home_directory (user), ".dmrc", NULL);
 
     /* Guard against privilege escalation through symlinks, etc. */
     drop_privileges = geteuid () == 0;
     if (drop_privileges)
-        privileges_drop (user);
+        privileges_drop (common_user_get_uid (user), common_user_get_gid (user));
     have_dmrc = g_key_file_load_from_file (dmrc_file, path, G_KEY_FILE_KEEP_COMMENTS, NULL);
     if (drop_privileges)
         privileges_reclaim ();
@@ -53,7 +45,7 @@ dmrc_load (const gchar *username)
     {
         gchar *filename, *cache_dir;
 
-        filename = g_strdup_printf ("%s.dmrc", user_get_name (user));
+        filename = g_strdup_printf ("%s.dmrc", common_user_get_name (user));
         cache_dir = config_get_string (config_get_instance (), "LightDM", "cache-directory");
         path = g_build_filename (cache_dir, "dmrc", filename, NULL);
         g_free (filename);
@@ -63,46 +55,32 @@ dmrc_load (const gchar *username)
         g_free (path);
     }
 
-    g_object_unref (user);
-
     return dmrc_file;
 }
 
 void
-dmrc_save (GKeyFile *dmrc_file, const gchar *username)
+dmrc_save (GKeyFile *dmrc_file, CommonUser *user)
 {
-    User *user;
     gchar *path, *filename, *cache_dir, *dmrc_cache_dir;
     gchar *data;
     gsize length;
-
-    user = accounts_get_user_by_name (username);
-    if (!user)
-    {
-        g_warning ("Not saving DMRC file - unable to get information on user %s", username);
-        return;
-    }
+    gboolean drop_privileges;
 
     data = g_key_file_to_data (dmrc_file, &length, NULL);
 
     /* Update the users .dmrc */
-    if (user)
-    {
-        gboolean drop_privileges;
-
-        path = g_build_filename (user_get_home_directory (user), ".dmrc", NULL);
+    path = g_build_filename (common_user_get_home_directory (user), ".dmrc", NULL);
 
-        /* Guard against privilege escalation through symlinks, etc. */
-        drop_privileges = geteuid () == 0;
-        if (drop_privileges)
-            privileges_drop (user);
-        g_debug ("Writing %s", path);
-        g_file_set_contents (path, data, length, NULL);
-        if (drop_privileges)
-            privileges_reclaim ();
+    /* Guard against privilege escalation through symlinks, etc. */
+    drop_privileges = geteuid () == 0;
+    if (drop_privileges)
+        privileges_drop (common_user_get_uid (user), common_user_get_gid (user));
+    g_debug ("Writing %s", path);
+    g_file_set_contents (path, data, length, NULL);
+    if (drop_privileges)
+        privileges_reclaim ();
 
-        g_free (path);
-    }
+    g_free (path);
 
     /* Update the .dmrc cache */
     cache_dir = config_get_string (config_get_instance (), "LightDM", "cache-directory");
@@ -110,12 +88,11 @@ dmrc_save (GKeyFile *dmrc_file, const gchar *username)
     if (g_mkdir_with_parents (dmrc_cache_dir, 0700) < 0)
         g_warning ("Failed to make DMRC cache directory %s: %s", dmrc_cache_dir, strerror (errno));
 
-    filename = g_strdup_printf ("%s.dmrc", username);
+    filename = g_strdup_printf ("%s.dmrc", common_user_get_name (user));
     path = g_build_filename (dmrc_cache_dir, filename, NULL);
     g_file_set_contents (path, data, length, NULL);
 
     g_free (dmrc_cache_dir);
     g_free (path);
     g_free (filename);
-    g_object_unref (user);
 }
similarity index 81%
rename from src/dmrc.h
rename to common/dmrc.h
index 5e93d2f76be513f8159632a7be7ae08df2064f8a..ed1381cc6a023e36f6dc6664bb4991bd5d79b7d3 100644 (file)
 #define DMRC_H_
 
 #include <glib.h>
+#include "user-list.h"
 
 G_BEGIN_DECLS
 
-GKeyFile *dmrc_load (const gchar *username);
+GKeyFile *dmrc_load (CommonUser *user);
 
-void dmrc_save (GKeyFile *dmrc_file, const gchar *username);
+void dmrc_save (GKeyFile *dmrc_file, CommonUser *user);
 
 G_END_DECLS
 
similarity index 68%
rename from src/privileges.c
rename to common/privileges.c
index 7165b8de5738b7f3c968b9047d0ea7272d52a2f2..11f3400155ff0191ca269570dd5e00576ebe83bb 100644 (file)
 #define _GNU_SOURCE
 
 #include <config.h>
+#include <glib.h>
+#include <unistd.h>
 #include "privileges.h"
 
 void
-privileges_drop (User *user)
+privileges_drop (uid_t uid, gid_t gid)
 {
-    g_return_if_fail (user != NULL);
-
 #ifdef HAVE_SETRESGID
-    g_assert (setresgid (user_get_gid (user), user_get_gid (user), -1) == 0);
+    g_assert (setresgid (gid, gid, -1) == 0);
 #else
-    g_assert (setgid (user_get_gid (user)) == 0);
-    g_assert (setegid (user_get_gid (user)) == 0);
+    g_assert (setgid (gid) == 0);
+    g_assert (setegid (gid) == 0);
 #endif
 #ifdef HAVE_SETRESUID
-    g_assert (setresuid (user_get_uid (user), user_get_uid (user), -1) == 0);
+    g_assert (setresuid (uid, uid, -1) == 0);
 #else
-    g_assert (setuid (user_get_uid (user)) == 0);
-    g_assert (seteuid (user_get_uid (user)) == 0);
+    g_assert (setuid (uid) == 0);
+    g_assert (seteuid (uid) == 0);
 #endif
 }
 
similarity index 88%
rename from src/privileges.h
rename to common/privileges.h
index bc407abd9291ce4310735e3a58c6a732c58f1972..448b03508b1b4b54db0521567be215d857005b4d 100644 (file)
@@ -12,9 +12,9 @@
 #ifndef PRIVILEGES_H_
 #define PRIVILEGES_H_
 
-#include "accounts.h"
+#include <sys/types.h>
 
-void privileges_drop (User *user);
+void privileges_drop (uid_t uid, gid_t gid);
 
 void privileges_reclaim (void);
 
index 58c96aca69aa0a302b39bd8e5d99da47c4e24ac9..d64e615fb4448a32a4f08c1715f2014459ad9a78 100644 (file)
@@ -19,6 +19,7 @@
 #include <pwd.h>
 #include <gio/gio.h>
 
+#include "dmrc.h"
 #include "user-list.h"
 
 enum
@@ -35,6 +36,7 @@ enum
     USER_PROP_REAL_NAME,
     USER_PROP_DISPLAY_NAME,
     USER_PROP_HOME_DIRECTORY,
+    USER_PROP_SHELL,
     USER_PROP_IMAGE,
     USER_PROP_BACKGROUND,
     USER_PROP_LANGUAGE,
@@ -42,7 +44,9 @@ enum
     USER_PROP_LAYOUTS,
     USER_PROP_SESSION,
     USER_PROP_LOGGED_IN,
-    USER_PROP_HAS_MESSAGES
+    USER_PROP_HAS_MESSAGES,
+    USER_PROP_UID,
+    USER_PROP_GID,
 };
 
 enum
@@ -98,9 +102,6 @@ typedef struct
     /* Accounts service path */
     gchar *path;
 
-    /* DMRC file */
-    GKeyFile *dmrc_file;
-
     /* Update signal from accounts service */
     guint changed_signal;
 
@@ -113,6 +114,9 @@ typedef struct
     /* Home directory of user */
     gchar *home_directory;
 
+    /* Shell for user */
+    gchar *shell;
+
     /* Image for user */
     gchar *image;
 
@@ -122,6 +126,12 @@ typedef struct
     /* TRUE if this user has messages available */
     gboolean has_messages;
 
+    /* UID of user */
+    guint64 uid;
+
+    /* GID of user */
+    guint64 gid;
+
     /* User chosen language */
     gchar *language;
 
@@ -137,18 +147,18 @@ typedef struct
     GObject parent_instance;
     gchar *path;
     gchar *username;
-} Session;
+} CommonSession;
 
 typedef struct
 {
     GObjectClass parent_class;
-} SessionClass;
+} CommonSessionClass;
 
 G_DEFINE_TYPE (CommonUserList, common_user_list, G_TYPE_OBJECT);
 G_DEFINE_TYPE (CommonUser, common_user, G_TYPE_OBJECT);
-#define SESSION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), session_get_type (), Session))
-GType session_get_type (void);
-G_DEFINE_TYPE (Session, session, G_TYPE_OBJECT);
+#define COMMON_SESSION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), common_session_get_type (), CommonSession))
+GType common_session_get_type (void);
+G_DEFINE_TYPE (CommonSession, common_session, G_TYPE_OBJECT);
 
 #define GET_LIST_PRIVATE(obj) G_TYPE_INSTANCE_GET_PRIVATE ((obj), COMMON_TYPE_USER_LIST, CommonUserListPrivate)
 #define GET_USER_PRIVATE(obj) G_TYPE_INSTANCE_GET_PRIVATE ((obj), COMMON_TYPE_USER, CommonUserPrivate)
@@ -213,13 +223,14 @@ compare_user (gconstpointer a, gconstpointer b)
 }
 
 static gboolean
-update_passwd_user (CommonUser *user, const gchar *real_name, const gchar *home_directory, const gchar *image)
+update_passwd_user (CommonUser *user, const gchar *real_name, const gchar *home_directory, const gchar *shell, const gchar *image)
 {
     CommonUserPrivate *priv = GET_USER_PRIVATE (user);
 
     /* Skip if already set to this */
     if (g_strcmp0 (common_user_get_real_name (user), real_name) == 0 &&
         g_strcmp0 (common_user_get_home_directory (user), home_directory) == 0 &&
+        g_strcmp0 (common_user_get_shell (user), shell) == 0 &&
         g_strcmp0 (common_user_get_image (user), image) == 0)
         return FALSE;
 
@@ -227,6 +238,8 @@ update_passwd_user (CommonUser *user, const gchar *real_name, const gchar *home_
     priv->real_name = g_strdup (real_name);
     g_free (priv->home_directory);
     priv->home_directory = g_strdup (home_directory);
+    g_free (priv->shell);
+    priv->shell = g_strdup (shell);
     g_free (priv->image);
     priv->image = g_strdup (image);
 
@@ -239,6 +252,45 @@ user_changed_cb (CommonUser *user)
     g_signal_emit (GET_USER_PRIVATE (user)->user_list, list_signals[USER_CHANGED], 0, user);
 }
 
+static CommonUser *
+make_passwd_user (CommonUserList *user_list, struct passwd *entry)
+{
+    CommonUser *user = g_object_new (COMMON_TYPE_USER, NULL);
+    CommonUserPrivate *priv = GET_USER_PRIVATE (user);
+    char **tokens;
+    gchar *real_name, *image;
+
+    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;
+        }
+    }
+
+    priv->user_list = user_list;
+    priv->name = g_strdup (entry->pw_name);
+    priv->real_name = real_name;
+    priv->home_directory = g_strdup (entry->pw_dir);
+    priv->shell = g_strdup (entry->pw_shell);
+    priv->image = image;
+    priv->uid = entry->pw_uid;
+    priv->gid = entry->pw_gid;
+
+    return user;
+}
+
 static void
 load_passwd_file (CommonUserList *user_list, gboolean emit_add_signal)
 {
@@ -283,9 +335,6 @@ load_passwd_file (CommonUserList *user_list, gboolean emit_add_signal)
     {
         struct passwd *entry;
         CommonUser *user;
-        CommonUserPrivate *user_priv;
-        char **tokens;
-        gchar *real_name, *image;
         int i;
 
         errno = 0;
@@ -310,36 +359,7 @@ load_passwd_file (CommonUserList *user_list, gboolean emit_add_signal)
         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 (COMMON_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;
+        user = make_passwd_user (user_list, entry);
 
         /* Update existing users if have them */
         for (link = priv->users; link; link = link->next)
@@ -347,7 +367,7 @@ load_passwd_file (CommonUserList *user_list, gboolean emit_add_signal)
             CommonUser *info = link->data;
             if (strcmp (common_user_get_name (info), common_user_get_name (user)) == 0)
             {
-                if (update_passwd_user (info, common_user_get_real_name (user), common_user_get_home_directory (user), common_user_get_image (user)))
+                if (update_passwd_user (info, common_user_get_real_name (user), common_user_get_home_directory (user), common_user_get_shell (user), common_user_get_image (user)))
                     changed_users = g_list_insert_sorted (changed_users, info, compare_user);
                 g_object_unref (user);
                 user = info;
@@ -500,6 +520,11 @@ load_accounts_user (CommonUser *user)
             g_free (priv->home_directory);
             priv->home_directory = g_variant_dup_string (value, NULL);
         }
+        else if (strcmp (name, "Shell") == 0 && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
+        {
+            g_free (priv->shell);
+            priv->shell = g_variant_dup_string (value, NULL);
+        }
         else if (strcmp (name, "SystemAccount") == 0 && g_variant_is_of_type (value, G_VARIANT_TYPE_BOOLEAN))
             system_account = g_variant_get_boolean (value);
         else if (strcmp (name, "Language") == 0 && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
@@ -545,6 +570,8 @@ load_accounts_user (CommonUser *user)
         }
         else if (strcmp (name, "XHasMessages") == 0 && g_variant_is_of_type (value, G_VARIANT_TYPE_BOOLEAN))
             priv->has_messages = g_variant_get_boolean (value);
+        else if (strcmp (name, "Uid") == 0 && g_variant_is_of_type (value, G_VARIANT_TYPE_UINT64))
+            priv->uid = g_variant_get_uint64 (value);
     }
     g_variant_iter_free (iter);
 
@@ -641,11 +668,11 @@ accounts_user_deleted_cb (GDBusConnection *connection,
     }
 }
 
-static Session *
+static CommonSession *
 load_session (CommonUserList *user_list, const gchar *path)
 {
     CommonUserListPrivate *priv = GET_LIST_PRIVATE (user_list);
-    Session *session = NULL;
+    CommonSession *session = NULL;
     GVariant *result, *username;
     GError *error = NULL;
 
@@ -674,7 +701,7 @@ load_session (CommonUserList *user_list, const gchar *path)
         g_variant_get (username, "&s", &name);
 
         g_debug ("Loaded session %s (%s)", path, name);
-        session = g_object_new (session_get_type (), NULL);
+        session = g_object_new (common_session_get_type (), NULL);
         session->username = g_strdup (name);
         session->path = g_strdup (path);
         priv->sessions = g_list_append (priv->sessions, session);
@@ -696,7 +723,7 @@ session_added_cb (GDBusConnection *connection,
 {
     CommonUserList *user_list = data;
     gchar *path;
-    Session *session;
+    CommonSession *session;
     CommonUser *user = NULL;
 
     if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(o)")))
@@ -737,7 +764,7 @@ session_removed_cb (GDBusConnection *connection,
 
     for (link = priv->sessions; link; link = link->next)
     {
-        Session *session = link->data;
+        CommonSession *session = link->data;
         if (strcmp (session->path, path) == 0)
         {
             CommonUser *user;
@@ -753,6 +780,72 @@ session_removed_cb (GDBusConnection *connection,
     }
 }
 
+static void
+load_sessions (CommonUserList *user_list)
+{
+    CommonUserListPrivate *priv = GET_LIST_PRIVATE (user_list);
+    GVariant *result;
+    GError *error = NULL;
+
+    priv->session_added_signal = g_dbus_connection_signal_subscribe (priv->bus,
+                                                                     "org.freedesktop.DisplayManager",
+                                                                     "org.freedesktop.DisplayManager",
+                                                                     "SessionAdded",
+                                                                     "/org/freedesktop/DisplayManager",
+                                                                     NULL,
+                                                                     G_DBUS_SIGNAL_FLAGS_NONE,
+                                                                     session_added_cb,
+                                                                     user_list,
+                                                                     NULL);
+    priv->session_removed_signal = g_dbus_connection_signal_subscribe (priv->bus,
+                                                                       "org.freedesktop.DisplayManager",
+                                                                       "org.freedesktop.DisplayManager",
+                                                                       "SessionRemoved",
+                                                                       "/org/freedesktop/DisplayManager",
+                                                                       NULL,
+                                                                       G_DBUS_SIGNAL_FLAGS_NONE,
+                                                                       session_removed_cb,
+                                                                       user_list,
+                                                                       NULL);
+    result = g_dbus_connection_call_sync (priv->bus,
+                                          "org.freedesktop.DisplayManager",
+                                          "/org/freedesktop/DisplayManager",
+                                          "org.freedesktop.DBus.Properties",
+                                          "Get",
+                                          g_variant_new ("(ss)", "org.freedesktop.DisplayManager", "Sessions"),
+                                          G_VARIANT_TYPE ("(v)"),
+                                          G_DBUS_CALL_FLAGS_NONE,
+                                          -1,
+                                          NULL,
+                                          &error);
+    if (error)
+        g_warning ("Error getting session list from org.freedesktop.DisplayManager: %s", error->message);
+    g_clear_error (&error);
+    if (result)
+    {
+        if (g_variant_is_of_type (result, G_VARIANT_TYPE ("(v)")))
+        {
+            GVariant *value;
+            GVariantIter *iter;
+            const gchar *path;
+
+            g_variant_get (result, "(v)", &value);
+
+            g_debug ("Loading sessions from org.freedesktop.DisplayManager");
+            g_variant_get (value, "ao", &iter);
+            while (g_variant_iter_loop (iter, "&o", &path))
+                load_session (user_list, path);
+            g_variant_iter_free (iter);
+
+            g_variant_unref (value);
+        }
+        else
+            g_warning ("Unexpected type from org.freedesktop.DisplayManager.Sessions: %s", g_variant_get_type_string (result));
+
+        g_variant_unref (result);
+    }
+}
+
 static void
 load_users (CommonUserList *user_list)
 {
@@ -833,65 +926,6 @@ load_users (CommonUserList *user_list)
             g_signal_connect (priv->passwd_monitor, "changed", G_CALLBACK (passwd_changed_cb), user_list);
         g_clear_error (&error);
     }
-
-    priv->session_added_signal = g_dbus_connection_signal_subscribe (priv->bus,
-                                                                     "org.freedesktop.DisplayManager",
-                                                                     "org.freedesktop.DisplayManager",
-                                                                     "SessionAdded",
-                                                                     "/org/freedesktop/DisplayManager",
-                                                                     NULL,
-                                                                     G_DBUS_SIGNAL_FLAGS_NONE,
-                                                                     session_added_cb,
-                                                                     user_list,
-                                                                     NULL);
-    priv->session_removed_signal = g_dbus_connection_signal_subscribe (priv->bus,
-                                                                       "org.freedesktop.DisplayManager",
-                                                                       "org.freedesktop.DisplayManager",
-                                                                       "SessionRemoved",
-                                                                       "/org/freedesktop/DisplayManager",
-                                                                       NULL,
-                                                                       G_DBUS_SIGNAL_FLAGS_NONE,
-                                                                       session_removed_cb,
-
-                                                                    user_list,
-                                                                    NULL);
-    result = g_dbus_connection_call_sync (priv->bus,
-                                          "org.freedesktop.DisplayManager",
-                                          "/org/freedesktop/DisplayManager",
-                                          "org.freedesktop.DBus.Properties",
-                                          "Get",
-                                          g_variant_new ("(ss)", "org.freedesktop.DisplayManager", "Sessions"),
-                                          G_VARIANT_TYPE ("(v)"),
-                                          G_DBUS_CALL_FLAGS_NONE,
-                                          -1,
-                                          NULL,
-                                          &error);
-    if (error)
-        g_warning ("Error getting session list from org.freedesktop.DisplayManager: %s", error->message);
-    g_clear_error (&error);
-    if (result)
-    {
-        if (g_variant_is_of_type (result, G_VARIANT_TYPE ("(v)")))
-        {
-            GVariant *value;
-            GVariantIter *iter;
-            const gchar *path;
-
-            g_variant_get (result, "(v)", &value);
-
-            g_debug ("Loading sessions from org.freedesktop.DisplayManager");
-            g_variant_get (value, "ao", &iter);
-            while (g_variant_iter_loop (iter, "&o", &path))
-                load_session (user_list, path);
-            g_variant_iter_free (iter);
-
-            g_variant_unref (value);
-        }
-        else
-            g_warning ("Unexpected type from org.freedesktop.DisplayManager.Sessions: %s", g_variant_get_type_string (result));
-
-        g_variant_unref (result);
-    }
 }
 
 /**
@@ -931,8 +965,10 @@ common_user_list_get_users (CommonUserList *user_list)
  * @username: Name of user to get.
  *
  * Get infomation about a given user or #NULL if this user doesn't exist.
+ * Includes hidden and system users, unlike the list from
+ * common_user_list_get_users.
  *
- * Return value: (transfer none): A #CommonUser entry for the given user.
+ * Return value: (transfer full): A #CommonUser entry for the given user.
  **/
 CommonUser *
 common_user_list_get_user_by_name (CommonUserList *user_list, const gchar *username)
@@ -942,7 +978,19 @@ common_user_list_get_user_by_name (CommonUserList *user_list, const gchar *usern
 
     load_users (user_list);
 
-    return get_user_by_name (user_list, username);
+    CommonUser *user = get_user_by_name (user_list, username);
+    if (user)
+        return g_object_ref (user);
+
+    /* Sometimes we need to look up users that aren't in AccountsService.
+       Notably we need to look up the user that the greeter runs as, which
+       is usually 'lightdm'. For such cases, we manually create a one-off
+       CommonUser object and pre-seed with passwd info. */
+    struct passwd *entry = getpwnam (username);
+    if (entry != NULL)
+        return make_passwd_user (user_list, entry);
+
+    return NULL;
 }
 
 static void
@@ -1075,42 +1123,80 @@ common_user_list_class_init (CommonUserListClass *klass)
                       G_TYPE_NONE, 1, COMMON_TYPE_USER);
 }
 
+static gboolean
+call_method (CommonUser *user, const gchar *method, GVariant *args,
+             const gchar *expected, GVariant **result)
+{
+    GVariant *answer;
+    GError *error = NULL;
+    CommonUserPrivate *user_priv = GET_USER_PRIVATE (user);
+    CommonUserListPrivate *list_priv = GET_LIST_PRIVATE (user_priv->user_list);
+
+    answer = g_dbus_connection_call_sync (list_priv->bus,
+                                          "org.freedesktop.Accounts",
+                                          user_priv->path,
+                                          "org.freedesktop.Accounts.User",
+                                          method,
+                                          args,
+                                          G_VARIANT_TYPE (expected),
+                                          G_DBUS_CALL_FLAGS_NONE,
+                                          -1,
+                                          NULL,
+                                          &error);
+    if (error)
+        g_warning ("Could not call %s: %s", method, error->message);
+    g_clear_error (&error);
+
+    if (!answer)
+        return FALSE;
+
+    if (result)
+        *result = answer;
+    else
+        g_variant_unref (answer);
+
+    return TRUE;
+}
+
 static void
-load_dmrc (CommonUser *user)
+save_string_to_dmrc (CommonUser *user, const gchar *group,
+                     const gchar *key, const gchar *value)
 {
-    CommonUserPrivate *priv = GET_USER_PRIVATE (user);
-    gchar *path;
-    //gboolean have_dmrc;
+    GKeyFile *dmrc;
+
+    dmrc = dmrc_load (user);
+    g_key_file_set_string (dmrc, group, key, value);
+    dmrc_save (dmrc, user);
 
-    if (!priv->dmrc_file)
-        priv->dmrc_file = g_key_file_new ();
+    g_key_file_free (dmrc);
+}
 
-    /* Load from the user directory */  
-    path = g_build_filename (priv->home_directory, ".dmrc", NULL);
-    /*have_dmrc = */g_key_file_load_from_file (priv->dmrc_file, path, G_KEY_FILE_KEEP_COMMENTS, NULL);
-    g_free (path);
+static void
+load_dmrc (CommonUser *user)
+{
+    CommonUserPrivate *priv = GET_USER_PRIVATE (user);
+    GKeyFile *dmrc;
 
-    /* If no ~/.dmrc, then load from the cache */
-    // FIXME
+    dmrc = dmrc_load (user);
 
     // FIXME: Watch for changes
 
     /* The Language field contains the locale */
-    if (priv->language)
-        g_free (priv->language);
-    priv->language = g_key_file_get_string (priv->dmrc_file, "Desktop", "Language", NULL);
+    g_free (priv->language);
+    priv->language = g_key_file_get_string (dmrc, "Desktop", "Language", NULL);
 
-    if (g_key_file_has_key (priv->dmrc_file, "Desktop", "Layout", NULL))
+    if (g_key_file_has_key (dmrc, "Desktop", "Layout", NULL))
     {
         g_strfreev (priv->layouts);
         priv->layouts = g_malloc (sizeof (gchar *) * 2);
-        priv->layouts[0] = g_key_file_get_string (priv->dmrc_file, "Desktop", "Layout", NULL);
+        priv->layouts[0] = g_key_file_get_string (dmrc, "Desktop", "Layout", NULL);
         priv->layouts[1] = NULL;
     }
 
-    if (priv->session)
-        g_free (priv->session);
-    priv->session = g_key_file_get_string (priv->dmrc_file, "Desktop", "Session", NULL);
+    g_free (priv->session);
+    priv->session = g_key_file_get_string (dmrc, "Desktop", "Session", NULL);
+
+    g_key_file_free (dmrc);
 }
 
 /* Loads language/layout/session info for user */
@@ -1199,6 +1285,22 @@ common_user_get_home_directory (CommonUser *user)
     return GET_USER_PRIVATE (user)->home_directory;
 }
 
+/**
+ * common_user_get_shell:
+ * @user: A #CommonUser
+ * 
+ * Get the shell for a user.
+ * 
+ * Return value: The user's shell
+ */
+const gchar *
+common_user_get_shell (CommonUser *user)
+{
+    g_return_val_if_fail (COMMON_IS_USER (user), NULL);
+    load_user_values (user);
+    return GET_USER_PRIVATE (user)->shell;
+}
+
 /**
  * common_user_get_image:
  * @user: A #CommonUser
@@ -1244,7 +1346,26 @@ common_user_get_language (CommonUser *user)
 {
     g_return_val_if_fail (COMMON_IS_USER (user), NULL);
     load_user_values (user);
-    return GET_USER_PRIVATE (user)->language;
+    const gchar *language = GET_USER_PRIVATE (user)->language;
+    return (language && language[0] == 0) ? NULL : language; /* Treat "" as NULL */
+}
+
+/**
+ * common_user_set_language:
+ * @user: A #CommonUser
+ * @language: The user's new language
+ * 
+ * Set the language for a user.
+ **/
+void
+common_user_set_language (CommonUser *user, const gchar *language)
+{
+    g_return_if_fail (COMMON_IS_USER (user));
+    if (g_strcmp0 (common_user_get_language (user), language) != 0)
+    {
+        call_method (user, "SetLanguage", g_variant_new ("(s)", language), "()", NULL);
+        save_string_to_dmrc (user, "Desktop", "Language", language);
+    }
 }
 
 /**
@@ -1292,7 +1413,26 @@ common_user_get_session (CommonUser *user)
 {
     g_return_val_if_fail (COMMON_IS_USER (user), NULL);
     load_user_values (user);
-    return GET_USER_PRIVATE (user)->session; 
+    const gchar *session = GET_USER_PRIVATE (user)->session;
+    return (session && session[0] == 0) ? NULL : session; /* Treat "" as NULL */
+}
+
+/**
+ * common_user_set_session:
+ * @user: A #CommonUser
+ * @language: The user's new session
+ * 
+ * Set the session for a user.
+ **/
+void
+common_user_set_session (CommonUser *user, const gchar *session)
+{
+    g_return_if_fail (COMMON_IS_USER (user));
+    if (g_strcmp0 (common_user_get_session (user), session) != 0)
+    {
+        call_method (user, "SetXSession", g_variant_new ("(s)", session), "()", NULL);
+        save_string_to_dmrc (user, "Desktop", "Session", session);
+    }
 }
 
 /**
@@ -1315,9 +1455,13 @@ common_user_get_logged_in (CommonUser *user)
     priv = GET_USER_PRIVATE (user);
     list_priv = GET_LIST_PRIVATE (priv->user_list);
 
+    // Lazily decide to load/listen to sessions
+    if (list_priv->session_added_signal == 0)
+        load_sessions (priv->user_list);
+
     for (link = list_priv->sessions; link; link = link->next)
     {
-        Session *session = link->data;
+        CommonSession *session = link->data;
         if (strcmp (session->username, priv->name) == 0)
             return TRUE;
     }
@@ -1341,6 +1485,48 @@ common_user_get_has_messages (CommonUser *user)
     return GET_USER_PRIVATE (user)->has_messages;
 }
 
+/**
+ * common_user_get_uid:
+ * @user: A #CommonUser
+ * 
+ * Get the uid of a user
+ * 
+ * Return value: The user's uid
+ **/
+uid_t
+common_user_get_uid (CommonUser *user)
+{
+    g_return_val_if_fail (COMMON_IS_USER (user), 0);
+    load_user_values (user);
+    return GET_USER_PRIVATE (user)->uid;
+}
+
+/**
+ * common_user_get_gid:
+ * @user: A #CommonUser
+ * 
+ * Get the gid of a user
+ * 
+ * Return value: The user's gid
+ **/
+gid_t
+common_user_get_gid (CommonUser *user)
+{
+    g_return_val_if_fail (COMMON_IS_USER (user), 0);
+    load_user_values (user);
+    /* gid is not actually stored in AccountsService, so if our user is from
+       AccountsService, we have to look up manually in passwd.  gid won't
+       change, so just look up the first time we're asked and never again. */
+    CommonUserPrivate *priv = GET_USER_PRIVATE (user);
+    if (priv->uid != 0 && priv->gid == 0)
+    {
+        struct passwd *entry = getpwuid (priv->uid);
+        if (entry != NULL)
+            priv->gid = entry->pw_gid;
+    }
+    return priv->gid;
+}
+
 static void
 common_user_init (CommonUser *user)
 {
@@ -1382,6 +1568,9 @@ common_user_get_property (GObject    *object,
     case USER_PROP_HOME_DIRECTORY:
         g_value_set_string (value, common_user_get_home_directory (self));
         break;
+    case USER_PROP_SHELL:
+        g_value_set_string (value, common_user_get_shell (self));
+        break;
     case USER_PROP_IMAGE:
         g_value_set_string (value, common_user_get_image (self));
         break;
@@ -1406,6 +1595,12 @@ common_user_get_property (GObject    *object,
     case USER_PROP_HAS_MESSAGES:
         g_value_set_boolean (value, common_user_get_has_messages (self));
         break;
+    case USER_PROP_UID:
+        g_value_set_uint64 (value, common_user_get_uid (self));
+        break;
+    case USER_PROP_GID:
+        g_value_set_uint64 (value, common_user_get_gid (self));
+        break;
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
         break;
@@ -1424,11 +1619,10 @@ common_user_finalize (GObject *object)
     g_free (priv->name);
     g_free (priv->real_name);
     g_free (priv->home_directory);
+    g_free (priv->shell);
     g_free (priv->image);
     g_free (priv->background);
     g_strfreev (priv->layouts);
-    if (priv->dmrc_file)
-        g_key_file_free (priv->dmrc_file);
 }
 
 static void
@@ -1470,6 +1664,13 @@ common_user_class_init (CommonUserClass *klass)
                                                           "Home directory",
                                                           NULL,
                                                           G_PARAM_READWRITE));
+    g_object_class_install_property (object_class,
+                                     USER_PROP_SHELL,
+                                     g_param_spec_string ("shell",
+                                                          "shell",
+                                                          "Shell",
+                                                          NULL,
+                                                          G_PARAM_READWRITE));
     g_object_class_install_property (object_class,
                                      USER_PROP_IMAGE,
                                      g_param_spec_string ("image",
@@ -1526,6 +1727,24 @@ common_user_class_init (CommonUserClass *klass)
                                                            "TRUE if the user is has waiting messages",
                                                            FALSE,
                                                            G_PARAM_READWRITE));
+    g_object_class_install_property (object_class,
+                                     USER_PROP_UID,
+                                     g_param_spec_uint64 ("uid",
+                                                          "uid",
+                                                          "Uid",
+                                                          0,
+                                                          G_MAXUINT64,
+                                                          0,
+                                                          G_PARAM_READWRITE));
+    g_object_class_install_property (object_class,
+                                     USER_PROP_GID,
+                                     g_param_spec_uint64 ("gd",
+                                                          "gid",
+                                                          "Gid",
+                                                          0,
+                                                          G_MAXUINT64,
+                                                          0,
+                                                          G_PARAM_READWRITE));
 
     /**
      * CommonUser::changed:
@@ -1544,22 +1763,22 @@ common_user_class_init (CommonUserClass *klass)
 }
 
 static void
-session_init (Session *session)
+common_session_init (CommonSession *common_session)
 {
 }
 
 static void
-session_finalize (GObject *object)
+common_session_finalize (GObject *object)
 {
-    Session *self = SESSION (object);
+    CommonSession *self = COMMON_SESSION (object);
 
     g_free (self->path);
     g_free (self->username);
 }
 
 static void
-session_class_init (SessionClass *klass)
+common_session_class_init (CommonSessionClass *klass)
 {
     GObjectClass *object_class = G_OBJECT_CLASS (klass);
-    object_class->finalize = session_finalize;
+    object_class->finalize = common_session_finalize;
 }
index 19926cf2539d9cea7e3fb6d8ebaaf8b76e45fe6c..820e0b256149079fc998dc29c6c9ea756c02feb1 100644 (file)
@@ -14,6 +14,7 @@
 #define COMMON_USER_LIST_H_
 
 #include <glib-object.h>
+#include <sys/types.h>
 
 G_BEGIN_DECLS
 
@@ -77,22 +78,32 @@ const gchar *common_user_get_display_name (CommonUser *user);
 
 const gchar *common_user_get_home_directory (CommonUser *user);
 
+const gchar *common_user_get_shell (CommonUser *user);
+
 const gchar *common_user_get_image (CommonUser *user);
 
 const gchar *common_user_get_background (CommonUser *user);
 
 const gchar *common_user_get_language (CommonUser *user);
 
+void common_user_set_language (CommonUser *user, const gchar *language);
+
 const gchar *common_user_get_layout (CommonUser *user);
 
 const gchar * const *common_user_get_layouts (CommonUser *user);
 
 const gchar *common_user_get_session (CommonUser *user);
 
+void common_user_set_session (CommonUser *user, const gchar *session);
+
 gboolean common_user_get_logged_in (CommonUser *user);
 
 gboolean common_user_get_has_messages (CommonUser *user);
 
+uid_t common_user_get_uid (CommonUser *user);
+
+gid_t common_user_get_gid (CommonUser *user);
+
 G_END_DECLS
 
 #endif /* COMMON_USER_LIST_H_ */
index 4c0d0895fa3f370e942639afef94941d4c94bd12..225de84090caa111bcc44544007ade483e85536e 100644 (file)
@@ -209,6 +209,7 @@ dnl ###########################################################################
 
 AC_CONFIG_FILES([
 Makefile
+common/Makefile
 data/Makefile
 doc/Makefile
 help/Makefile
index 770ea13bf39c2189a0e5df5df6c7a068c411fa7d..ef4cee5907c78178867310c453461258816dd9a7 100644 (file)
@@ -1,9 +1,12 @@
 lib_LTLIBRARIES = liblightdm-gobject-1.la
 
 liblightdm_gobject_1_la_LDFLAGS = -export-symbols-regex \^lightdm_.*
-liblightdm_gobject_1_la_LIBADD = $(LIBLIGHTDM_GOBJECT_LIBS)
+liblightdm_gobject_1_la_LIBADD = \
+       $(LIBLIGHTDM_GOBJECT_LIBS) \
+       $(top_builddir)/common/libcommon.la
 liblightdm_gobject_1_la_CFLAGS = $(LIBLIGHTDM_GOBJECT_CFLAGS) \
        $(WARN_CFLAGS) \
+       -I"$(top_srcdir)/common" \
        -DCONFIG_DIR=\"$(sysconfdir)/lightdm\" \
        -DSESSIONS_DIR=\"$(pkgdatadir)/sessions:$(datadir)/xsessions\" \
        -DREMOTE_SESSIONS_DIR=\"$(pkgdatadir)/remote-sessions\"
@@ -29,7 +32,6 @@ liblightdm_gobject_1_la_SOURCES= \
        power.c \
        session.c \
        user.c \
-       $(top_srcdir)/common/user-list.c \
        $(liblightdm_gobject_1include_HEADERS)
 
 if HAVE_INTROSPECTION
index 949778f035852bf12f7c60ea2c6d45e642a09964..0b89eab74313fff1896ab020434f411f0a85793c 100644 (file)
@@ -11,6 +11,7 @@
 #include <string.h>
 #include <gio/gdesktopappinfo.h>
 
+#include "configuration.h"
 #include "lightdm/session.h"
 
 enum {
@@ -191,7 +192,6 @@ load_sessions (const gchar *sessions_dir)
 static void
 update_sessions (void)
 {
-    GKeyFile *config_key_file = NULL;
     gchar *config_path = NULL;
     gchar *sessions_dir;
     gchar *remote_sessions_dir;
@@ -207,8 +207,8 @@ update_sessions (void)
     /* Use session directory from configuration */
     /* FIXME: This should be sent in the greeter connection */
     config_path = g_build_filename (CONFIG_DIR, "lightdm.conf", NULL);
-    config_key_file = g_key_file_new ();
-    result = g_key_file_load_from_file (config_key_file, config_path, G_KEY_FILE_NONE, &error);
+    /* FIXME: This should load from lightdm.conf.d as well */
+    result = config_load_from_file (config_get_instance (), config_path, &error);
     if (error && !g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
         g_warning ("Failed to open configuration file: %s", error->message);
     g_clear_error (&error);
@@ -216,21 +216,20 @@ update_sessions (void)
     {
         gchar *value;
       
-        value = g_key_file_get_string (config_key_file, "LightDM", "sessions-directory", NULL);
+        value = config_get_string (config_get_instance (), "LightDM", "sessions-directory");
         if (value)
         {
             g_free (sessions_dir);
             sessions_dir = value;
         }
 
-        value = g_key_file_get_string (config_key_file, "LightDM", "remote-sessions-directory", NULL);
+        value = config_get_string (config_get_instance (), "LightDM", "remote-sessions-directory");
         if (value)
         {
             g_free (remote_sessions_dir);
             remote_sessions_dir = value;
         }
     }
-    g_key_file_free (config_key_file);
     g_free (config_path);
 
     local_sessions = load_sessions (sessions_dir);
index 664cfa642e3de4ee4e5014bf8cf84d6ba4eeffdc..4fb5f0449bb698d6ce47c494aab81f469f328dda 100644 (file)
@@ -13,7 +13,7 @@
 
 #include <config.h>
 
-#include "common/user-list.h"
+#include "user-list.h"
 #include "lightdm/user.h"
 
 enum
index fa3a20f42bbe3f193aa0402d714c5af3bb9a26e0..766ef679dd34ec588b73c491c14c9bc71f088c8e 100644 (file)
@@ -4,16 +4,12 @@ bin_PROGRAMS = dm-tool
 lightdm_SOURCES = \
        accounts.c \
        accounts.h \
-       configuration.c \
-       configuration.h \
        console-kit.c \
        console-kit.h \
        display-manager.c \
        display-manager.h \
        display-server.c \
        display-server.h \
-       dmrc.c \
-       dmrc.h \
        greeter.c \
        greeter.h \
        guest-account.c \
@@ -27,8 +23,6 @@ lightdm_SOURCES = \
        mir-server.h \
        plymouth.c \
        plymouth.h \
-       privileges.c \
-       privileges.h \
        process.c \
        process.h \
        seat.c \
@@ -80,6 +74,7 @@ lightdm_SOURCES = \
 lightdm_CFLAGS = \
        $(LIGHTDM_CFLAGS) \
        $(WARN_CFLAGS) \
+       -I"$(top_srcdir)/common" \
        -DSBIN_DIR=\"$(sbindir)\" \
        -DCONFIG_DIR=\"$(sysconfdir)/lightdm\" \
        -DLOG_DIR=\"$(localstatedir)/log/lightdm\" \
@@ -92,6 +87,7 @@ lightdm_CFLAGS = \
 
 lightdm_LDADD = \
        $(LIGHTDM_LIBS) \
+       $(top_builddir)/common/libcommon.la \
        -lgcrypt \
        -lpam
 
index 63d8a40d043e3cecbc0222a6140ad3ed09fa6f8e..797b6d9df9e714b838221e81c116daa9c83a0477 100644 (file)
  * license.
  */
 
-#include <errno.h>
 #include <pwd.h>
 #include <stdlib.h>
-#include <string.h>
 
 #include "accounts.h"
-#include "dmrc.h"
+#include "user-list.h"
 
 struct UserPrivate
 {
-    /* Name of user */
-    gchar *name;
-
-    /* Accounts interface proxy */
-    GDBusProxy *proxy;
-
-    /* User ID */
-    uid_t uid;
-
-    /* Group ID */
-    gid_t gid;
-
-    /* GECOS information */
-    gchar *gecos;
-
-    /* Home directory */
-    gchar *home_directory;
-
-    /* Shell */
-    gchar *shell;
-
-    /* Language */
-    gchar *language;
-
-    /* X session */
-    gchar *xsession;
+    /* Internal user object */
+    CommonUser *common_user;
 };
 
 G_DEFINE_TYPE (User, user, G_TYPE_OBJECT);
 
-/* Connection to AccountsService */
-static GDBusProxy *accounts_service_proxy = NULL;
-static gboolean have_accounts_service_proxy = FALSE;
-
-static gboolean
-call_method (GDBusProxy *proxy, const gchar *method, GVariant *args,
-             const gchar *expected, GVariant **result)
-{
-    GVariant *answer;
-    GError *error = NULL;
-
-    if (!proxy)
-        return FALSE;
-
-    answer = g_dbus_proxy_call_sync (proxy,
-                                     method,
-                                     args,
-                                     G_DBUS_CALL_FLAGS_NONE,
-                                     -1,
-                                     NULL,
-                                     &error);
-    if (error)
-        g_warning ("Could not call %s: %s", method, error->message);
-    g_clear_error (&error);
-
-    if (!answer)
-        return FALSE;
-
-    if (!g_variant_is_of_type (answer, G_VARIANT_TYPE (expected)))
-    {
-        g_warning ("Unexpected response from %s: %s",
-                   method, g_variant_get_type_string (answer));
-        g_variant_unref (answer);
-        return FALSE;
-    }
-
-    if (result)
-        *result = answer;
-    else
-        g_variant_unref (answer);
-
-    return TRUE;
-}
-
-static gboolean
-get_property (GDBusProxy *proxy, const gchar *property,
-              const gchar *expected, GVariant **result)
-{
-    GVariant *answer;
-
-    answer = g_dbus_proxy_get_cached_property (proxy, property);
-
-    if (!answer)
-    {
-        g_warning ("Could not get accounts property %s", property);
-        return FALSE;
-    }
-
-    if (!g_variant_is_of_type (answer, G_VARIANT_TYPE (expected)))
-    {
-        g_warning ("Unexpected accounts property type for %s: %s",
-                   property, g_variant_get_type_string (answer));
-        g_variant_unref (answer);
-        return FALSE;
-    }
-
-    if (result)
-        *result = answer;
-    else
-        g_variant_unref (answer);
-    return TRUE;
-}
-
-static void
-save_string_to_dmrc (const gchar *username, const gchar *group,
-                     const gchar *key, const gchar *value)
-{
-    GKeyFile *dmrc;
-
-    dmrc = dmrc_load (username);
-    g_key_file_set_string (dmrc, group, key, value);
-    dmrc_save (dmrc, username);
-
-    g_key_file_free (dmrc);
-}
-
-static gchar *
-get_string_from_dmrc (const gchar *username, const gchar *group,
-                      const gchar *key)
-{
-    GKeyFile *dmrc;
-    gchar *value;
-
-    dmrc = dmrc_load (username);
-    value = g_key_file_get_string (dmrc, group, key, NULL);
-
-    g_key_file_free (dmrc);
-    return value;
-}
-
-static GDBusProxy *
-get_accounts_service_proxy (void)
-{
-    GError *error = NULL;
-
-    if (have_accounts_service_proxy)
-        return accounts_service_proxy;
-
-    have_accounts_service_proxy = TRUE;
-    accounts_service_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
-                                                            G_DBUS_PROXY_FLAGS_NONE,
-                                                            NULL,
-                                                            "org.freedesktop.Accounts",
-                                                            "/org/freedesktop/Accounts",
-                                                            "org.freedesktop.Accounts",
-                                                            NULL, &error);
-    if (error)
-        g_warning ("Could not get accounts proxy: %s", error->message);
-    g_clear_error (&error);
-
-    if (accounts_service_proxy)
-    {
-        gchar *name;
-        name = g_dbus_proxy_get_name_owner (accounts_service_proxy);
-        if (!name)
-        {
-            g_debug ("org.freedesktop.Accounts does not exist, falling back to passwd file");
-            g_object_unref (accounts_service_proxy);
-            accounts_service_proxy = NULL;
-        }
-        g_free (name);
-    }  
-
-    return accounts_service_proxy;
-}
-
-static GDBusProxy *
-get_accounts_proxy_for_user (const gchar *user)
-{
-    GDBusProxy *proxy;
-    GError *error = NULL;
-    GVariant *result;
-    gboolean success;
-    gchar *user_path = NULL;
-
-    g_return_val_if_fail (user != NULL, NULL);  
-
-    proxy = get_accounts_service_proxy ();
-    if (!proxy)
-        return NULL;
-
-    success = call_method (proxy, "FindUserByName", g_variant_new ("(s)", user), "(o)", &result);
-
-    if (!success)
-        return NULL;
-
-    g_variant_get (result, "(o)", &user_path);
-    g_variant_unref (result);
-
-    if (!user_path)
-        return NULL;
-  
-    proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
-                                           G_DBUS_PROXY_FLAGS_NONE,
-                                           NULL,
-                                           "org.freedesktop.Accounts",
-                                           user_path,
-                                           "org.freedesktop.Accounts.User",
-                                           NULL, &error);
-    if (error)
-        g_warning ("Could not get accounts user proxy: %s", error->message);
-    g_clear_error (&error);
-    g_free (user_path);
-
-    return proxy;
-}
-
-static User *
-user_from_passwd (struct passwd *user_info)
-{
-    User *user;
-
-    user = g_object_new (USER_TYPE, NULL);
-    user->priv->name = g_strdup (user_info->pw_name);
-    user->priv->uid = user_info->pw_uid;
-    user->priv->gid = user_info->pw_gid;
-    user->priv->gecos = g_strdup (user_info->pw_gecos);
-    user->priv->home_directory = g_strdup (user_info->pw_dir);
-    user->priv->shell = g_strdup (user_info->pw_shell);
-    user->priv->proxy = get_accounts_proxy_for_user (user->priv->name);
-
-    return user;
-}
-
 User *
 accounts_get_user_by_name (const gchar *username)
 {
-    struct passwd *user_info;
     User *user = NULL;
+    CommonUser *common_user;
 
     g_return_val_if_fail (username != NULL, NULL);
 
-    errno = 0;
-    user_info = getpwnam (username);
-    if (user_info)
-        user = user_from_passwd (user_info);
-
-    if (!user && errno != 0)
-        g_warning ("Unable to get information on user %s: %s", username, strerror (errno));
-
-    return user;
-}
-
-User *
-accounts_get_user_by_uid (uid_t uid)
-{
-    User *user = NULL;
-
-    errno = 0;
-    struct passwd *user_info;
-
-    user_info = getpwuid (uid);
-    if (user_info)
-        user = user_from_passwd (user_info);
-
-    if (!user && errno != 0)
-        g_warning ("Unable to get information on user %d: %s", uid, strerror (errno));
+    common_user = common_user_list_get_user_by_name (common_user_list_get_instance (), username);
+    if (common_user != NULL)
+    {
+        user = g_object_new (USER_TYPE, NULL);
+        user->priv->common_user = common_user;
+    }
 
     return user;
 }
@@ -284,136 +45,74 @@ accounts_get_user_by_uid (uid_t uid)
 User *
 accounts_get_current_user ()
 {
-    return user_from_passwd (getpwuid (getuid ()));
+    struct passwd *entry = getpwuid (getuid ());
+    if (entry != NULL)
+        return accounts_get_user_by_name (entry->pw_name);
+    else
+        return NULL;
 }
 
 const gchar *
 user_get_name (User *user)
 {
     g_return_val_if_fail (user != NULL, NULL);
-    return user->priv->name;
+    return common_user_get_name (user->priv->common_user);
 }
 
 uid_t
 user_get_uid (User *user)
 {
     g_return_val_if_fail (user != NULL, 0);
-    return user->priv->uid;
+    return common_user_get_uid (user->priv->common_user);
 }
 
 gid_t
 user_get_gid (User *user)
 {
     g_return_val_if_fail (user != NULL, 0);
-    return user->priv->gid;
-}
-
-const gchar *
-user_get_gecos (User *user)
-{
-    g_return_val_if_fail (user != NULL, NULL);
-    return user->priv->gecos;
+    return common_user_get_gid (user->priv->common_user);
 }
 
 const gchar *
 user_get_home_directory (User *user)
 {
     g_return_val_if_fail (user != NULL, NULL);
-    return user->priv->home_directory;
+    return common_user_get_home_directory (user->priv->common_user);
 }
 
 const gchar *
 user_get_shell (User *user)
 {
     g_return_val_if_fail (user != NULL, NULL);
-    return user->priv->shell;
+    return common_user_get_shell (user->priv->common_user);
 }
 
 void
 user_set_language (User *user, const gchar *language)
 {
     g_return_if_fail (user != NULL);
-
-    call_method (user->priv->proxy, "SetLanguage", g_variant_new ("(s)", language), "()", NULL);
-    save_string_to_dmrc (user->priv->name, "Desktop", "Language", language);
+    common_user_set_language (user->priv->common_user, language);
 }
 
 const gchar *
 user_get_language (User *user)
 {
-    GVariant *variant, *inner;
-    gboolean success;
-
     g_return_val_if_fail (user != NULL, NULL);
-
-    g_free (user->priv->language);
-    if (user->priv->proxy)
-    {
-        /* the "Language" property cannot be retrieved with get_property () here since it
-         * uses g_dbus_proxy_get_cached_property () which would return the previous (cached) value
-         * of the "Language" property
-         */
-        success = call_method (user->priv->proxy, "org.freedesktop.DBus.Properties.Get", g_variant_new ("(ss)", g_dbus_proxy_get_interface_name(user->priv->proxy), "Language"), "(v)", &variant);
-        if (success)
-        {
-            g_variant_get (variant, "(v)", &inner);
-            user->priv->language = g_variant_dup_string (inner, NULL);
-            g_variant_unref (inner);
-            g_variant_unref (variant);
-        }
-        else
-            user->priv->language = NULL;
-    }
-    else
-        user->priv->language = get_string_from_dmrc (user->priv->name, "Desktop", "Language");
-
-    /* Treat a blank language as unset */
-    if (g_strcmp0 (user->priv->language, "") == 0)
-    {
-        g_free (user->priv->language);
-        user->priv->language = NULL;
-    }
-
-    return user->priv->language;
+    return common_user_get_language (user->priv->common_user);
 }
 
 void
 user_set_xsession (User *user, const gchar *xsession)
 {
     g_return_if_fail (user != NULL);
-
-    call_method (user->priv->proxy, "SetXSession", g_variant_new ("(s)", xsession), "()", NULL);
-    save_string_to_dmrc (user->priv->name, "Desktop", "Session", xsession);
+    common_user_set_session (user->priv->common_user, xsession);
 }
 
 const gchar *
 user_get_xsession (User *user)
 {
-    GVariant *result;
-
     g_return_val_if_fail (user != NULL, NULL);
-
-    g_free (user->priv->xsession);
-    if (user->priv->proxy)
-    {
-        if (get_property (user->priv->proxy, "XSession", "s", &result))
-        {
-            g_variant_get (result, "s", &user->priv->xsession);
-            g_variant_unref (result);
-        }
-        else
-            user->priv->xsession = NULL;
-    }
-    else
-        user->priv->xsession = get_string_from_dmrc (user->priv->name, "Desktop", "Session");
-
-    if (g_strcmp0 (user->priv->xsession, "") == 0)
-    {
-        g_free (user->priv->xsession);
-        user->priv->xsession = NULL;
-    }
-
-    return user->priv->xsession;
+    return common_user_get_session (user->priv->common_user);
 }
 
 static void
@@ -429,38 +128,19 @@ user_dispose (GObject *object)
 
     self = USER (object);
 
-    if (self->priv->proxy)
-    {
-        g_object_unref (self->priv->proxy);
-        self->priv->proxy = NULL;
-    }
+    if (self->priv->common_user)
+        g_object_unref (self->priv->common_user);
+    self->priv->common_user = NULL;
 
     G_OBJECT_CLASS (user_parent_class)->dispose (object);
 }
 
-static void
-user_finalize (GObject *object)
-{
-    User *self;
-
-    self = USER (object);
-
-    g_free (self->priv->name);
-    g_free (self->priv->gecos);
-    g_free (self->priv->home_directory);
-    g_free (self->priv->shell);
-    g_free (self->priv->language);
-
-    G_OBJECT_CLASS (user_parent_class)->finalize (object);  
-}
-
 static void
 user_class_init (UserClass *klass)
 {
     GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
     object_class->dispose = user_dispose;
-    object_class->finalize = user_finalize;  
 
     g_type_class_add_private (klass, sizeof (UserPrivate));
 }
index 1f9eb078fb9775f8f0369076d3c081fda231566c..a64685705ac3cc4876d9355287ecc0f27519b0ea 100644 (file)
@@ -36,8 +36,6 @@ typedef struct
 
 User *accounts_get_user_by_name (const gchar *username);
 
-User *accounts_get_user_by_uid (uid_t uid);
-
 User *accounts_get_current_user (void);
 
 GType user_get_type (void);
@@ -48,8 +46,6 @@ uid_t user_get_uid (User *user);
 
 gid_t user_get_gid (User *user);
 
-const gchar *user_get_gecos (User *user);
-
 const gchar *user_get_home_directory (User *user);
 
 const gchar *user_get_shell (User *user);
index 01eb1c37adc97fec1e482a9ff16d8bf3d4789ca3..1feb7ac25239419d33819a1fbde1fafddeda7e18 100644 (file)
@@ -512,7 +512,7 @@ session_child_run (int argc, char **argv)
 
         drop_privileges = geteuid () == 0;
         if (drop_privileges)
-            privileges_drop (user);
+            privileges_drop (user_get_uid (user), user_get_gid (user));
         result = x_authority_write (x_authority, XAUTH_WRITE_MODE_REPLACE, x_authority_filename, &error);
         if (drop_privileges)
             privileges_reclaim ();
@@ -660,7 +660,7 @@ session_child_run (int argc, char **argv)
 
         drop_privileges = geteuid () == 0;
         if (drop_privileges)
-            privileges_drop (user);
+            privileges_drop (user_get_uid (user), user_get_gid (user));
         result = x_authority_write (x_authority, XAUTH_WRITE_MODE_REMOVE, x_authority_filename, &error);
         if (drop_privileges)
             privileges_reclaim ();
index 077fd2b9105025f2721e924352b32d68f63e2e0d..afb14cc6995a4bba1b4b17b778b499373beb24d6 100644 (file)
@@ -218,7 +218,7 @@ request_cb (const gchar *request)
     if (strcmp (name, "LOG-USER") == 0)
     {
         LightDMUser *user;
-        const gchar *username, *image, *background, *layout, *session;
+        const gchar *username, *image, *background, *language, *layout, *session;
         const gchar * const * layouts;
         gchar **fields = NULL;
         gchar *layouts_text;
@@ -237,6 +237,7 @@ request_cb (const gchar *request)
         user = lightdm_user_list_get_user_by_name (lightdm_user_list_get_instance (), username);
         image = lightdm_user_get_image (user);
         background = lightdm_user_get_background (user);
+        language = lightdm_user_get_language (user);
         layout = lightdm_user_get_layout (user);
         layouts = lightdm_user_get_layouts (user);
         layouts_text = g_strjoinv (";", (gchar **) layouts);
@@ -255,7 +256,7 @@ request_cb (const gchar *request)
             else if (strcmp (fields[i], "BACKGROUND") == 0)
                 g_string_append_printf (status_text, " BACKGROUND=%s", background ? background : "");
             else if (strcmp (fields[i], "LANGUAGE") == 0)
-                g_string_append_printf (status_text, " LANGUAGE=%s", lightdm_user_get_language (user));
+                g_string_append_printf (status_text, " LANGUAGE=%s", language ? language : "");
             else if (strcmp (fields[i], "LAYOUT") == 0)
                 g_string_append_printf (status_text, " LAYOUT=%s", layout ? layout : "");
             else if (strcmp (fields[i], "LAYOUTS") == 0)
index 0cffb524c542bff04a4ee87ba6ba8a7000b93555..c00a6290e755736b8c538da892d97dc34424d97f 100644 (file)
@@ -1715,6 +1715,15 @@ handle_user_call (GDBusConnection       *connection,
         user->xsession = g_strdup (xsession);
 
         g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
+
+        /* And notify others that it took */
+        g_dbus_connection_emit_signal (accounts_connection,
+                                       NULL,
+                                       user->path,
+                                       "org.freedesktop.Accounts.User",
+                                       "Changed",
+                                       g_variant_new ("()"),
+                                       NULL);
     }
     else
         g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "No such method: %s", method_name);
@@ -1745,6 +1754,10 @@ handle_user_get_property (GDBusConnection       *connection,
         return g_variant_new_string (user->language ? user->language : "");
     else if (strcmp (property_name, "IconFile") == 0)
         return g_variant_new_string (user->image ? user->image : "");
+    else if (strcmp (property_name, "Shell") == 0)
+        return g_variant_new_string ("/bin/sh");
+    else if (strcmp (property_name, "Uid") == 0)
+        return g_variant_new_uint64 (user->uid);
     else if (strcmp (property_name, "XSession") == 0)
         return g_variant_new_string (user->xsession ? user->xsession : "");
     else if (strcmp (property_name, "XKeyboardLayouts") == 0)
@@ -1800,6 +1813,8 @@ accounts_name_acquired_cb (GDBusConnection *connection,
         "    <property name='BackgroundFile' type='s' access='read'/>"
         "    <property name='Language' type='s' access='read'/>"
         "    <property name='IconFile' type='s' access='read'/>"
+        "    <property name='Shell' type='s' access='read'/>"
+        "    <property name='Uid' type='t' access='read'/>"
         "    <property name='XSession' type='s' access='read'/>"
         "    <property name='XKeyboardLayouts' type='as' access='read'/>"
         "    <property name='XHasMessages' type='b' access='read'/>"