summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Terry <michael.terry@canonical.com>2014-02-04 17:55:32 -0500
committerMichael Terry <michael.terry@canonical.com>2014-02-04 17:55:32 -0500
commit5ba3bc15922902272de7009e02650d39a40da834 (patch)
treedf40f0c89c23902abefe7a83b3a3188489c12b58
parentd5bf5930e9c60fb08c04904fe5befc7ca1a36aa9 (diff)
downloadlightdm-5ba3bc15922902272de7009e02650d39a40da834.tar.gz
And convert accounts.c to use new sharable CommonUser class too
-rw-r--r--Makefile.am2
-rw-r--r--common/Makefile.am23
-rw-r--r--common/configuration.c (renamed from src/configuration.c)0
-rw-r--r--common/configuration.h (renamed from src/configuration.h)0
-rw-r--r--common/dmrc.c (renamed from src/dmrc.c)59
-rw-r--r--common/dmrc.h (renamed from src/dmrc.h)5
-rw-r--r--common/privileges.c (renamed from src/privileges.c)18
-rw-r--r--common/privileges.h (renamed from src/privileges.h)4
-rw-r--r--common/user-list.c499
-rw-r--r--common/user-list.h11
-rw-r--r--configure.ac1
-rw-r--r--liblightdm-gobject/Makefile.am6
-rw-r--r--liblightdm-gobject/session.c11
-rw-r--r--liblightdm-gobject/user.c2
-rw-r--r--src/Makefile.am8
-rw-r--r--src/accounts.c374
-rw-r--r--src/accounts.h4
-rw-r--r--src/session-child.c4
-rw-r--r--tests/src/test-gobject-greeter.c5
-rw-r--r--tests/src/test-runner.c15
20 files changed, 486 insertions, 565 deletions
diff --git a/Makefile.am b/Makefile.am
index 73c6788e..106e891e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -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
index 00000000..f289e6ac
--- /dev/null
+++ b/common/Makefile.am
@@ -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
diff --git a/src/configuration.c b/common/configuration.c
index 5268c8d9..5268c8d9 100644
--- a/src/configuration.c
+++ b/common/configuration.c
diff --git a/src/configuration.h b/common/configuration.h
index cae56912..cae56912 100644
--- a/src/configuration.h
+++ b/common/configuration.h
diff --git a/src/dmrc.c b/common/dmrc.c
index ccde1bf1..e7121ef7 100644
--- a/src/dmrc.c
+++ b/common/dmrc.c
@@ -15,34 +15,26 @@
#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);
}
diff --git a/src/dmrc.h b/common/dmrc.h
index 5e93d2f7..ed1381cc 100644
--- a/src/dmrc.h
+++ b/common/dmrc.h
@@ -13,12 +13,13 @@
#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
diff --git a/src/privileges.c b/common/privileges.c
index 7165b8de..11f34001 100644
--- a/src/privileges.c
+++ b/common/privileges.c
@@ -13,24 +13,24 @@
#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
}
diff --git a/src/privileges.h b/common/privileges.h
index bc407abd..448b0350 100644
--- a/src/privileges.h
+++ b/common/privileges.h
@@ -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);
diff --git a/common/user-list.c b/common/user-list.c
index 58c96aca..d64e615f 100644
--- a/common/user-list.c
+++ b/common/user-list.c
@@ -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;
@@ -754,6 +781,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)
{
CommonUserListPrivate *priv = GET_LIST_PRIVATE (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 */
@@ -1200,6 +1286,22 @@ common_user_get_home_directory (CommonUser *user)
}
/**
+ * 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
@@ -1471,6 +1665,13 @@ common_user_class_init (CommonUserClass *klass)
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",
"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;
}
diff --git a/common/user-list.h b/common/user-list.h
index 19926cf2..820e0b25 100644
--- a/common/user-list.h
+++ b/common/user-list.h
@@ -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_ */
diff --git a/configure.ac b/configure.ac
index 4c0d0895..225de840 100644
--- a/configure.ac
+++ b/configure.ac
@@ -209,6 +209,7 @@ dnl ###########################################################################
AC_CONFIG_FILES([
Makefile
+common/Makefile
data/Makefile
doc/Makefile
help/Makefile
diff --git a/liblightdm-gobject/Makefile.am b/liblightdm-gobject/Makefile.am
index 770ea13b..ef4cee59 100644
--- a/liblightdm-gobject/Makefile.am
+++ b/liblightdm-gobject/Makefile.am
@@ -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
diff --git a/liblightdm-gobject/session.c b/liblightdm-gobject/session.c
index 949778f0..0b89eab7 100644
--- a/liblightdm-gobject/session.c
+++ b/liblightdm-gobject/session.c
@@ -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);
diff --git a/liblightdm-gobject/user.c b/liblightdm-gobject/user.c
index 664cfa64..4fb5f044 100644
--- a/liblightdm-gobject/user.c
+++ b/liblightdm-gobject/user.c
@@ -13,7 +13,7 @@
#include <config.h>
-#include "common/user-list.h"
+#include "user-list.h"
#include "lightdm/user.h"
enum
diff --git a/src/Makefile.am b/src/Makefile.am
index fa3a20f4..766ef679 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -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
diff --git a/src/accounts.c b/src/accounts.c
index 63d8a40d..797b6d9d 100644
--- a/src/accounts.c
+++ b/src/accounts.c
@@ -10,273 +10,34 @@
* 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));
}
diff --git a/src/accounts.h b/src/accounts.h
index 1f9eb078..a6468570 100644
--- a/src/accounts.h
+++ b/src/accounts.h
@@ -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);
diff --git a/src/session-child.c b/src/session-child.c
index 01eb1c37..1feb7ac2 100644
--- a/src/session-child.c
+++ b/src/session-child.c
@@ -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 ();
diff --git a/tests/src/test-gobject-greeter.c b/tests/src/test-gobject-greeter.c
index 077fd2b9..afb14cc6 100644
--- a/tests/src/test-gobject-greeter.c
+++ b/tests/src/test-gobject-greeter.c
@@ -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)
diff --git a/tests/src/test-runner.c b/tests/src/test-runner.c
index 0cffb524..c00a6290 100644
--- a/tests/src/test-runner.c
+++ b/tests/src/test-runner.c
@@ -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'/>"