summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/tmpl/user.sgml5
-rw-r--r--greeters/gtk/lightdm-example-gtk-greeter.c2
-rwxr-xr-xgreeters/python-gtk/lightdm-example-python-gtk-greeter2
-rw-r--r--liblightdm-gobject/greeter-protocol.h4
-rw-r--r--liblightdm-gobject/greeter.c461
-rw-r--r--liblightdm-gobject/lightdm/user.h2
-rw-r--r--liblightdm-gobject/user-private.h6
-rw-r--r--liblightdm-gobject/user.c61
-rw-r--r--liblightdm-qt/Makefile.am17
-rw-r--r--liblightdm-qt/ldmgreeter.cpp17
-rw-r--r--liblightdm-qt/user-manager.xml21
-rw-r--r--src/Makefile.am2
-rw-r--r--src/greeter-protocol.h4
-rw-r--r--src/greeter.c70
-rw-r--r--src/lightdm.c154
-rw-r--r--src/user-manager.c400
-rw-r--r--src/user-manager.h61
17 files changed, 451 insertions, 838 deletions
diff --git a/doc/tmpl/user.sgml b/doc/tmpl/user.sgml
index 9fc94acf..2ca73579 100644
--- a/doc/tmpl/user.sgml
+++ b/doc/tmpl/user.sgml
@@ -52,6 +52,11 @@ A user has the following properties:
</para>
+<!-- ##### ARG LdmUser:home-directory ##### -->
+<para>
+
+</para>
+
<!-- ##### ARG LdmUser:image ##### -->
<para>
diff --git a/greeters/gtk/lightdm-example-gtk-greeter.c b/greeters/gtk/lightdm-example-gtk-greeter.c
index d697931a..a1eb95a3 100644
--- a/greeters/gtk/lightdm-example-gtk-greeter.c
+++ b/greeters/gtk/lightdm-example-gtk-greeter.c
@@ -516,7 +516,7 @@ connect_cb (LdmGreeter *greeter)
GdkPixbuf *pixbuf = NULL;
image = ldm_user_get_image (user);
- if (strcmp (image, "") == 0)
+ if (image)
{
gchar *path;
diff --git a/greeters/python-gtk/lightdm-example-python-gtk-greeter b/greeters/python-gtk/lightdm-example-python-gtk-greeter
index d7c9aba2..3edbb91e 100755
--- a/greeters/python-gtk/lightdm-example-python-gtk-greeter
+++ b/greeters/python-gtk/lightdm-example-python-gtk-greeter
@@ -196,7 +196,7 @@ class Greeter:
for user in users:
image = user.get_image()
pixbuf = None
- if image != '':
+ if image != None:
path = GLib.filename_from_uri(image)
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(path, 64, 64, True)
model.append((user.get_name(), user.get_display_name(), pixbuf, True))
diff --git a/liblightdm-gobject/greeter-protocol.h b/liblightdm-gobject/greeter-protocol.h
index 3a9c6dd7..c72fc636 100644
--- a/liblightdm-gobject/greeter-protocol.h
+++ b/liblightdm-gobject/greeter-protocol.h
@@ -20,12 +20,14 @@ typedef enum
GREETER_MESSAGE_CONTINUE_AUTHENTICATION = 3,
GREETER_MESSAGE_LOGIN = 4,
GREETER_MESSAGE_CANCEL_AUTHENTICATION = 5,
+ GREETER_MESSAGE_GET_USER_DEFAULTS = 6,
/* Messages from the server to the greeter */
GREETER_MESSAGE_CONNECTED = 101,
GREETER_MESSAGE_QUIT = 102,
GREETER_MESSAGE_PROMPT_AUTHENTICATION = 103,
- GREETER_MESSAGE_END_AUTHENTICATION = 104
+ GREETER_MESSAGE_END_AUTHENTICATION = 104,
+ GREETER_MESSAGE_USER_DEFAULTS = 106
} GreeterMessage;
#endif /* _GREETER_PROTOCOL_H_ */
diff --git a/liblightdm-gobject/greeter.c b/liblightdm-gobject/greeter.c
index 34af0cdd..5a7e73cb 100644
--- a/liblightdm-gobject/greeter.c
+++ b/liblightdm-gobject/greeter.c
@@ -10,10 +10,11 @@
*/
#include <stdlib.h>
+#include <errno.h>
#include <string.h>
#include <locale.h>
#include <sys/utsname.h>
-
+#include <pwd.h>
#include <gio/gdesktopappinfo.h>
#include <security/pam_appl.h>
#include <libxklavier/xklavier.h>
@@ -64,7 +65,7 @@ struct _LdmGreeterPrivate
GDBusConnection *system_bus;
- GDBusProxy *session_proxy, *user_proxy;
+ GDBusProxy *lightdm_proxy;
GIOChannel *to_server_channel, *from_server_channel;
gchar *read_buffer;
@@ -74,10 +75,19 @@ struct _LdmGreeterPrivate
gchar *hostname;
+ /* Configuration file */
+ GKeyFile *config;
+
gchar *theme;
GKeyFile *theme_file;
+ /* File monitor for password file */
+ GFileMonitor *passwd_monitor;
+
+ /* TRUE if have scanned users */
gboolean have_users;
+
+ /* List of users */
GList *users;
gboolean have_languages;
@@ -254,32 +264,36 @@ handle_prompt_authentication (LdmGreeter *greeter, gsize *offset)
}
static gboolean
-from_server_cb (GIOChannel *source, GIOCondition condition, gpointer data)
+read_packet (LdmGreeter *greeter, gboolean block)
{
- LdmGreeter *greeter = data;
- gsize n_to_read, n_read, offset;
- GIOStatus status;
- guint32 id, return_code;
+ gsize n_to_read, n_read;
GError *error = NULL;
+ /* Read the header, or the whole packet if we already have that */
n_to_read = HEADER_SIZE;
if (greeter->priv->n_read >= HEADER_SIZE)
n_to_read += get_packet_length (greeter);
- status = g_io_channel_read_chars (greeter->priv->from_server_channel,
- greeter->priv->read_buffer + greeter->priv->n_read,
- n_to_read - greeter->priv->n_read,
- &n_read,
- &error);
- if (status != G_IO_STATUS_NORMAL)
- g_warning ("Error reading from server: %s", error->message);
- g_clear_error (&error);
- if (status != G_IO_STATUS_NORMAL)
- return TRUE;
+ do
+ {
+ GIOStatus status;
+ status = g_io_channel_read_chars (greeter->priv->from_server_channel,
+ greeter->priv->read_buffer + greeter->priv->n_read,
+ n_to_read - greeter->priv->n_read,
+ &n_read,
+ &error);
+ if (status == G_IO_STATUS_ERROR)
+ g_warning ("Error reading from server: %s", error->message);
+ g_clear_error (&error);
+ if (status != G_IO_STATUS_NORMAL)
+ break;
+
+ greeter->priv->n_read += n_read;
+ } while (greeter->priv->n_read < n_to_read && block);
- greeter->priv->n_read += n_read;
+ /* Stop if haven't got all the data we want */
if (greeter->priv->n_read != n_to_read)
- return TRUE;
+ return FALSE;
/* If have header, rerun for content */
if (greeter->priv->n_read == HEADER_SIZE)
@@ -288,10 +302,23 @@ from_server_cb (GIOChannel *source, GIOCondition condition, gpointer data)
if (n_to_read > 0)
{
greeter->priv->read_buffer = g_realloc (greeter->priv->read_buffer, HEADER_SIZE + n_to_read);
- return from_server_cb (source, condition, data);
+ return read_packet (greeter, block);
}
}
+ return TRUE;
+}
+
+static gboolean
+from_server_cb (GIOChannel *source, GIOCondition condition, gpointer data)
+{
+ LdmGreeter *greeter = data;
+ gsize offset;
+ guint32 id, return_code;
+
+ if (!read_packet (greeter, FALSE))
+ return TRUE;
+
offset = 0;
id = read_int (greeter, &offset);
read_int (greeter, &offset);
@@ -400,20 +427,13 @@ ldm_greeter_connect_to_server (LdmGreeter *greeter)
g_io_channel_set_encoding (greeter->priv->from_server_channel, NULL, NULL);
g_io_add_watch (greeter->priv->from_server_channel, G_IO_IN, from_server_cb, greeter);
- greeter->priv->session_proxy = g_dbus_proxy_new_sync (greeter->priv->lightdm_bus,
+ greeter->priv->lightdm_proxy = g_dbus_proxy_new_sync (greeter->priv->lightdm_bus,
G_DBUS_PROXY_FLAGS_NONE,
NULL,
"org.lightdm.LightDisplayManager",
- "/org/lightdm/LightDisplayManager/Session",
- "org.lightdm.LightDisplayManager.Session",
+ "/org/lightdm/LightDisplayManager",
+ "org.lightdm.LightDisplayManager",
NULL, NULL);
- greeter->priv->user_proxy = g_dbus_proxy_new_sync (greeter->priv->lightdm_bus,
- G_DBUS_PROXY_FLAGS_NONE,
- NULL,
- "org.lightdm.LightDisplayManager",
- "/org/lightdm/LightDisplayManager/Users",
- "org.lightdm.LightDisplayManager.Users",
- NULL, NULL);
g_debug ("Connecting to display manager...");
write_header (greeter, GREETER_MESSAGE_CONNECT, 0);
@@ -563,160 +583,264 @@ get_user_by_name (LdmGreeter *greeter, const gchar *username)
return NULL;
}
+static gint
+compare_user (gconstpointer a, gconstpointer b)
+{
+ LdmUser *user_a = (LdmUser *) a, *user_b = (LdmUser *) b;
+ return strcmp (ldm_user_get_display_name (user_a), ldm_user_get_display_name (user_b));
+}
+
static void
-user_changed_cb (GDBusConnection *connection,
- const gchar *sender_name,
- const gchar *object_path,
- const gchar *interface_name,
- const gchar *signal_name,
- GVariant *parameters,
- gpointer user_data)
-{
- LdmGreeter *greeter = user_data;
- gchar *username, *real_name, *image;
- gboolean logged_in;
- LdmUser *user;
-
- if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(sssb)")))
+load_config (LdmGreeter *greeter)
+{
+ GVariant *result;
+ const gchar *config_path = NULL;
+
+ if (greeter->priv->config)
+ return;
+
+ result = g_dbus_proxy_get_cached_property (greeter->priv->lightdm_proxy,
+ "ConfigFile");
+ if (!result)
{
- g_warning ("Unknown type in %s signal", signal_name);
+ g_warning ("No ConfigFile property");
return;
}
- g_variant_get (parameters, "(sssb)", &username, &real_name, &image, &logged_in);
+ if (g_variant_is_of_type (result, G_VARIANT_TYPE_STRING))
+ config_path = g_variant_get_string (result, NULL);
+ else
+ g_warning ("Invalid type for config file: %s, expected string", g_variant_get_type_string (result));
- user = get_user_by_name (greeter, username);
- if (user)
+ if (config_path)
{
- g_debug ("User %s changed", username);
- ldm_user_set_real_name (user, real_name);
- ldm_user_set_image (user, image);
- ldm_user_set_logged_in (user, logged_in);
- g_signal_emit (greeter, signals[USER_CHANGED], 0, user);
+ GError *error = NULL;
+
+ g_debug ("Loading config from %s", config_path);
+
+ greeter->priv->config = g_key_file_new ();
+ if (!g_key_file_load_from_file (greeter->priv->config, config_path, G_KEY_FILE_NONE, &error))
+ g_warning ("Failed to load configuration from %s: %s", config_path, error->message); // FIXME: Don't make warning on no file, just info
+ g_clear_error (&error);
}
+
+ g_variant_unref (result);
+}
+
+static void
+load_users (LdmGreeter *greeter)
+{
+ gchar **hidden_users, **hidden_shells;
+ gchar *value;
+ gint minimum_uid;
+ GList *users = NULL, *old_users, *new_users = NULL, *changed_users = NULL, *link;
+
+ load_config (greeter);
+
+ if (g_key_file_has_key (greeter->priv->config, "UserManager", "minimum-uid", NULL))
+ minimum_uid = g_key_file_get_integer (greeter->priv->config, "UserManager", "minimum-uid", NULL);
else
+ minimum_uid = 500;
+
+ value = g_key_file_get_string (greeter->priv->config, "UserManager", "hidden-users", NULL);
+ if (!value)
+ value = g_strdup ("nobody nobody4 noaccess");
+ hidden_users = g_strsplit (value, " ", -1);
+ g_free (value);
+
+ value = g_key_file_get_string (greeter->priv->config, "UserManager", "hidden-shells", NULL);
+ if (!value)
+ value = g_strdup ("/bin/false /usr/sbin/nologin");
+ hidden_shells = g_strsplit (value, " ", -1);
+ g_free (value);
+
+ setpwent ();
+
+ while (TRUE)
{
- g_debug ("User %s added", username);
- user = ldm_user_new (greeter, username, real_name, image, logged_in);
- greeter->priv->users = g_list_append (greeter->priv->users, user);
- g_signal_emit (greeter, signals[USER_ADDED], 0, user);
+ struct passwd *entry;
+ LdmUser *user;
+ char **tokens;
+ gchar *real_name, *image_path, *image;
+ int i;
+
+ errno = 0;
+ entry = getpwent ();
+ if (!entry)
+ break;
+
+ /* Ignore system users */
+ if (entry->pw_uid < minimum_uid)
+ continue;
+
+ /* Ignore users disabled by shell */
+ if (entry->pw_shell)
+ {
+ for (i = 0; hidden_shells[i] && strcmp (entry->pw_shell, hidden_shells[i]) != 0; i++);
+ if (hidden_shells[i])
+ continue;
+ }
+
+ /* Ignore certain users */
+ for (i = 0; hidden_users[i] && strcmp (entry->pw_name, hidden_users[i]) != 0; i++);
+ if (hidden_users[i])
+ continue;
+
+ tokens = g_strsplit (entry->pw_gecos, ",", -1);
+ if (tokens[0] != NULL && tokens[0][0] != '\0')
+ real_name = g_strdup (tokens[0]);
+ else
+ real_name = NULL;
+ g_strfreev (tokens);
+
+ image_path = g_build_filename (entry->pw_dir, ".face", NULL);
+ if (!g_file_test (image_path, G_FILE_TEST_EXISTS))
+ {
+ g_free (image_path);
+ image_path = g_build_filename (entry->pw_dir, ".face.icon", NULL);
+ if (!g_file_test (image_path, G_FILE_TEST_EXISTS))
+ {
+ g_free (image_path);
+ image_path = NULL;
+ }
+ }
+ if (image_path)
+ image = g_filename_to_uri (image_path, NULL, NULL);
+ else
+ image = NULL;
+ g_free (image_path);
+
+ user = ldm_user_new (greeter, entry->pw_name, real_name, entry->pw_dir, image, FALSE);
+ g_free (real_name);
+ g_free (image);
+
+ /* Update existing users if have them */
+ for (link = greeter->priv->users; link; link = link->next)
+ {
+ LdmUser *info = link->data;
+ if (strcmp (ldm_user_get_name (info), ldm_user_get_name (user)) == 0)
+ {
+ // FIXME: Use changed signal from user object?
+ if (g_strcmp0 (ldm_user_get_real_name (info), ldm_user_get_real_name (user)) != 0 ||
+ g_strcmp0 (ldm_user_get_image (info), ldm_user_get_image (user)) != 0 ||
+ g_strcmp0 (ldm_user_get_home_directory (info), ldm_user_get_home_directory (user)) != 0 ||
+ ldm_user_get_logged_in (info) != ldm_user_get_logged_in (user))
+ {
+ ldm_user_set_real_name (info, ldm_user_get_real_name (user));
+ ldm_user_set_image (info, ldm_user_get_image (user));
+ ldm_user_set_home_directory (info, ldm_user_get_home_directory (user));
+ ldm_user_set_logged_in (info, ldm_user_get_logged_in (user));
+ g_object_unref (user);
+ user = info;
+ changed_users = g_list_insert_sorted (changed_users, user, compare_user);
+ }
+ else
+ {
+ g_object_unref (user);
+ user = info;
+ }
+ break;
+ }
+ }
+ if (!link)
+ {
+ /* Only notify once we have loaded the user list */
+ if (greeter->priv->have_users)
+ new_users = g_list_insert_sorted (new_users, user, compare_user);
+ }
+ users = g_list_insert_sorted (users, user, compare_user);
}
+ g_strfreev (hidden_users);
+ g_strfreev (hidden_shells);
- g_free (username);
- g_free (real_name);
- g_free (image);
-}
+ if (errno != 0)
+ g_warning ("Failed to read password database: %s", strerror (errno));
-static void
-user_removed_cb (GDBusConnection *connection,
- const gchar *sender_name,
- const gchar *object_path,
- const gchar *interface_name,
- const gchar *signal_name,
- GVariant *parameters,
- gpointer user_data)
-{
- LdmGreeter *greeter = user_data;
- gchar *username;
- LdmUser *user;
-
- if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(s)")))
+ endpwent ();
+
+ /* Use new user list */
+ old_users = greeter->priv->users;
+ greeter->priv->users = users;
+
+ /* Notify of changes */
+ for (link = new_users; link; link = link->next)
{
- g_warning ("Unknown type in %s signal", signal_name);
- return;
+ LdmUser *info = link->data;
+ g_debug ("User %s added", ldm_user_get_name (info));
+ g_signal_emit (greeter, signals[USER_ADDED], 0, info);
+ }
+ g_list_free (new_users);
+ for (link = changed_users; link; link = link->next)
+ {
+ LdmUser *info = link->data;
+ g_debug ("User %s changed", ldm_user_get_name (info));
+ g_signal_emit (greeter, signals[USER_CHANGED], 0, info);
}
+ g_list_free (changed_users);
+ for (link = old_users; link; link = link->next)
+ {
+ GList *new_link;
- g_variant_get (parameters, "(s)", &username);
+ /* See if this user is in the current list */
+ for (new_link = greeter->priv->users; new_link; new_link = new_link->next)
+ {
+ if (new_link->data == link->data)
+ break;
+ }
- user = get_user_by_name (greeter, username);
- if (user)
- {
- g_debug ("User %s removed", username);
- greeter->priv->users = g_list_remove (greeter->priv->users, user);
- g_signal_emit (greeter, signals[USER_REMOVED], 0, user);
- g_object_unref (user);
+ if (!new_link)
+ {
+ LdmUser *info = link->data;
+ g_debug ("User %s removed", ldm_user_get_name (info));
+ g_signal_emit (greeter, signals[USER_REMOVED], 0, info);
+ g_object_unref (info);
+ }
}
+ g_list_free (old_users);
+}
- g_free (username);
+static void
+passwd_changed_cb (GFileMonitor *monitor, GFile *file, GFile *other_file, GFileMonitorEvent event_type, LdmGreeter *greeter)
+{
+ if (event_type == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT)
+ {
+ g_debug ("%s changed, reloading user list", g_file_get_path (file));
+ load_users (greeter);
+ }
}
static void
update_users (LdmGreeter *greeter)
{
- GVariant *result, *user_array;
- GVariantIter iter;
- gchar *name, *real_name, *image;
- gboolean logged_in;
+ GFile *passwd_file;
GError *error = NULL;
if (greeter->priv->have_users)
return;
- g_dbus_connection_signal_subscribe (greeter->priv->lightdm_bus,
- "org.lightdm.LightDisplayManager",
- "org.lightdm.LightDisplayManager.Users",
- "UserAdded",
- "/org/lightdm/LightDisplayManager/Users",
- NULL,
- G_DBUS_SIGNAL_FLAGS_NONE,
- user_changed_cb,
- greeter,
- NULL);
- g_dbus_connection_signal_subscribe (greeter->priv->lightdm_bus,
- "org.lightdm.LightDisplayManager",
- "org.lightdm.LightDisplayManager.Users",
- "UserChanged",
- "/org/lightdm/LightDisplayManager/Users",
- NULL,
- G_DBUS_SIGNAL_FLAGS_NONE,
- user_changed_cb,
- greeter,
- NULL);
- g_dbus_connection_signal_subscribe (greeter->priv->lightdm_bus,
- "org.lightdm.LightDisplayManager",
- "org.lightdm.LightDisplayManager.Users",
- "UserRemoved",
- "/org/lightdm/LightDisplayManager/Users",
- NULL,
- G_DBUS_SIGNAL_FLAGS_NONE,
- user_removed_cb,
- greeter,
- NULL);
-
- g_debug ("Getting user list...");
- result = g_dbus_proxy_call_sync (greeter->priv->user_proxy,
- "GetUsers",
- NULL,
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- NULL,
- &error);
- if (!result)
- g_warning ("Failed to get users: %s", error->message);
- g_clear_error (&error);
- if (!result)
- return;
+ load_config (greeter);
- if (!g_variant_is_of_type (result, G_VARIANT_TYPE ("(a(sssb))")))
+ /* User listing is disabled */
+ if (g_key_file_has_key (greeter->priv->config, "UserManager", "load-users", NULL) &&
+ !g_key_file_get_boolean (greeter->priv->config, "UserManager", "load-users", NULL))
{
- g_warning ("Unknown type returned");
- g_variant_unref (result);
+ greeter->priv->have_users = TRUE;
return;
}
- user_array = g_variant_get_child_value (result, 0);
- g_debug ("Got %zi users", g_variant_n_children (user_array));
- g_variant_iter_init (&iter, user_array);
- while (g_variant_iter_next (&iter, "(&s&s&sb)", &name, &real_name, &image, &logged_in))
- {
- LdmUser *user;
- user = ldm_user_new (greeter, name, real_name, image, logged_in);
- greeter->priv->users = g_list_append (greeter->priv->users, user);
- }
+ load_users (greeter);
- greeter->priv->have_users = TRUE;
+ /* Watch for changes to user list */
+ passwd_file = g_file_new_for_path ("/etc/passwd");
+ greeter->priv->passwd_monitor = g_file_monitor (passwd_file, G_FILE_MONITOR_NONE, NULL, &error);
+ g_object_unref (passwd_file);
+ if (!greeter->priv->passwd_monitor)
+ g_warning ("Error monitoring /etc/passwd: %s", error->message);
+ else
+ g_signal_connect (greeter->priv->passwd_monitor, "changed", G_CALLBACK (passwd_changed_cb), greeter);
+ g_clear_error (&error);
- g_variant_unref (result);
+ greeter->priv->have_users = TRUE;
}
/**
@@ -1466,37 +1590,34 @@ ldm_greeter_shutdown (LdmGreeter *greeter)
gboolean
ldm_greeter_get_user_defaults (LdmGreeter *greeter, const gchar *username, gchar **language, gchar **layout, gchar **session)
{
- GError *error = NULL;
- GVariant *result;
- gboolean got_defaults = FALSE;
+ gsize offset = 0;
+ guint32 id;
g_return_val_if_fail (LDM_IS_GREETER (greeter), FALSE);
g_return_val_if_fail (username != NULL, FALSE);
- result = g_dbus_proxy_call_sync (greeter->priv->user_proxy,
- "GetUserDefaults",
- g_variant_new ("(s)", username),
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- NULL,
- &error);
-
- if (!result)
- g_warning ("Failed to get user defaults: %s", error->message);
- g_clear_error (&error);
-
- if (!result)
- return FALSE;
+ write_header (greeter, GREETER_MESSAGE_GET_USER_DEFAULTS, string_length (username));
+ write_string (greeter, username);
+ flush (greeter);
- if (g_variant_is_of_type (result, G_VARIANT_TYPE ("(sss)")))
+ if (!read_packet (greeter, TRUE))
{
- g_variant_get (result, "(sss)", language, layout, session);
- got_defaults = TRUE;
+ g_warning ("Error reading user defaults from server");
+ return FALSE;
}
- g_variant_unref (result);
+ id = read_int (greeter, &offset);
+ g_assert (id == GREETER_MESSAGE_USER_DEFAULTS);
+ read_int (greeter, &offset);
+ *language = read_string (greeter, &offset);
+ *layout = read_string (greeter, &offset);
+ *session = read_string (greeter, &offset);
- return got_defaults;
+ g_debug ("User defaults for %s: language=%s, layout=%s, session=%s", username, *language, *layout, *session);
+
+ greeter->priv->n_read = 0;
+
+ return TRUE;
}
static void
diff --git a/liblightdm-gobject/lightdm/user.h b/liblightdm-gobject/lightdm/user.h
index 053fb31b..c3a75b4f 100644
--- a/liblightdm-gobject/lightdm/user.h
+++ b/liblightdm-gobject/lightdm/user.h
@@ -47,6 +47,8 @@ const gchar *ldm_user_get_real_name (LdmUser *user);
const gchar *ldm_user_get_display_name (LdmUser *user);
+const gchar *ldm_user_get_home_directory (LdmUser *user);
+
const gchar *ldm_user_get_image (LdmUser *user);
const gchar *ldm_user_get_language (LdmUser *user);
diff --git a/liblightdm-gobject/user-private.h b/liblightdm-gobject/user-private.h
index 2cdaa6ab..4b706048 100644
--- a/liblightdm-gobject/user-private.h
+++ b/liblightdm-gobject/user-private.h
@@ -4,10 +4,14 @@
#include "lightdm/greeter.h"
#include "lightdm/user.h"
-LdmUser *ldm_user_new (LdmGreeter *greeter, const gchar *name, const gchar *real_name, const gchar *image, gboolean logged_in);
+LdmUser *ldm_user_new (LdmGreeter *greeter, const gchar *name, const gchar *real_name, const gchar *home_directory, const gchar *image, gboolean logged_in);
+
+void ldm_user_set_name (LdmUser *user, const gchar *name);
void ldm_user_set_real_name (LdmUser *user, const gchar *real_name);
+void ldm_user_set_home_directory (LdmUser *user, const gchar *home_directory);
+
void ldm_user_set_image (LdmUser *user, const gchar *image);
void ldm_user_set_logged_in (LdmUser *user, gboolean logged_in);
diff --git a/liblightdm-gobject/user.c b/liblightdm-gobject/user.c
index d8e36747..32f36cda 100644
--- a/liblightdm-gobject/user.c
+++ b/liblightdm-gobject/user.c
@@ -17,6 +17,7 @@ enum {
PROP_NAME,
PROP_REAL_NAME,
PROP_DISPLAY_NAME,
+ PROP_HOME_DIRECTORY,
PROP_IMAGE,
PROP_LANGUAGE,
PROP_LAYOUT,
@@ -30,6 +31,7 @@ struct _LdmUserPrivate
gchar *name;
gchar *real_name;
+ gchar *home_directory;
gchar *image;
gboolean logged_in;
@@ -48,15 +50,16 @@ G_DEFINE_TYPE (LdmUser, ldm_user, G_TYPE_OBJECT);
* @greeter: The greeter the user is connected to
* @name: The username
* @real_name: The real name of the user
+ * @home_directory: The home directory of the user
* @image: The image URI
* @logged_in: TRUE if this user is currently logged in
*
* Return value: the new #LdmUser
**/
LdmUser *
-ldm_user_new (LdmGreeter *greeter, const gchar *name, const gchar *real_name, const gchar *image, gboolean logged_in)
+ldm_user_new (LdmGreeter *greeter, const gchar *name, const gchar *real_name, const gchar *home_directory, const gchar *image, gboolean logged_in)
{
- return g_object_new (LDM_TYPE_USER, "greeter", greeter, "name", name, "real-name", real_name, "image", image, "logged-in", logged_in, NULL);
+ return g_object_new (LDM_TYPE_USER, "greeter", greeter, "name", name, "real-name", real_name, "home-directory", home_directory, "image", image, "logged-in", logged_in, NULL);
}
/**
@@ -74,6 +77,14 @@ ldm_user_get_name (LdmUser *user)
return user->priv->name;
}
+void
+ldm_user_set_name (LdmUser *user, const gchar *name)
+{
+ g_return_if_fail (LDM_IS_USER (user));
+ g_free (user->priv->name);
+ user->priv->name = g_strdup (name);
+}
+
/**
* ldm_user_get_real_name:
* @user: A #LdmUser
@@ -110,13 +121,36 @@ ldm_user_get_display_name (LdmUser *user)
{
g_return_val_if_fail (LDM_IS_USER (user), NULL);
- if (user->priv->real_name[0] != '\0')
+ if (user->priv->real_name)
return user->priv->real_name;
else
return user->priv->name;
}
/**
+ * ldm_user_get_home_directory:
+ * @user: A #LdmUser
+ *
+ * Get the home directory for a user.
+ *
+ * Return value: The users home directory
+ */
+const gchar *
+ldm_user_get_home_directory (LdmUser *user)
+{
+ g_return_val_if_fail (LDM_IS_USER (user), NULL);
+ return user->priv->home_directory;
+}
+
+void
+ldm_user_set_home_directory (LdmUser *user, const gchar *home_directory)
+{
+ g_return_if_fail (LDM_IS_USER (user));
+ g_free (user->priv->home_directory);
+ user->priv->home_directory = g_strdup (home_directory);
+}
+
+/**
* ldm_user_get_image:
* @user: A #LdmUser
*
@@ -240,16 +274,19 @@ ldm_user_set_property (GObject *object,
self->priv->greeter = g_object_ref (g_value_get_object (value));
break;
case PROP_NAME:
- self->priv->name = g_strdup (g_value_get_string (value));
+ ldm_user_set_name (self, g_value_get_string (value));
break;
case PROP_REAL_NAME:
- self->priv->real_name = g_strdup (g_value_get_string (value));
+ ldm_user_set_real_name (self, g_value_get_string (value));
+ break;
+ case PROP_HOME_DIRECTORY:
+ ldm_user_set_home_directory (self, g_value_get_string (value));
break;
case PROP_IMAGE:
- self->priv->image = g_strdup (g_value_get_string (value));
+ ldm_user_set_image (self, g_value_get_string (value));
break;
case PROP_LOGGED_IN:
- self->priv->logged_in = g_value_get_boolean (value);
+ ldm_user_set_logged_in (self, g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -277,6 +314,9 @@ ldm_user_get_property (GObject *object,
case PROP_DISPLAY_NAME:
g_value_set_string (value, ldm_user_get_display_name (self));
break;
+ case PROP_HOME_DIRECTORY:
+ g_value_set_string (value, ldm_user_get_home_directory (self));
+ break;
case PROP_IMAGE:
g_value_set_string (value, ldm_user_get_image (self));
break;
@@ -337,6 +377,13 @@ ldm_user_class_init (LdmUserClass *klass)
NULL,
G_PARAM_READABLE));
g_object_class_install_property(object_class,
+ PROP_HOME_DIRECTORY,
+ g_param_spec_string("home-directory",
+ "home-directory",
+ "Home directory",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property(object_class,
PROP_IMAGE,
g_param_spec_string("image",
"image",
diff --git a/liblightdm-qt/Makefile.am b/liblightdm-qt/Makefile.am
index f9c10bbe..6ea1fc7f 100644
--- a/liblightdm-qt/Makefile.am
+++ b/liblightdm-qt/Makefile.am
@@ -1,31 +1,19 @@
lib_LTLIBRARIES = liblightdm-qt-0.la
-# Generate interfaces from D-Bus definitions
-INTERFACE_FILES = \
- usermanagerinterface.cpp \
- usermanagerinterface.h
-usermanagerinterface.cpp usermanagerinterface.h: user-manager.xml
- qdbusxml2cpp $< -i ldmuser.h -c UserManagerInterface -p usermanagerinterface
-
# Generate metadata for QObjects
MOC_FILES = \
consolekitinterface_moc.cpp \
ldmgreeter_moc.cpp \
- powermanagementinterface_moc.cpp \
- usermanagerinterface_moc.cpp
+ powermanagementinterface_moc.cpp
consolekitinterface_moc.cpp: consolekitinterface.h
moc $< -o $@
ldmgreeter_moc.cpp: ldmgreeter.h
moc $< -o $@
powermanagementinterface_moc.cpp: powermanagementinterface.h
moc $< -o $@
-usermanagerinterface_moc.cpp: usermanagerinterface.h
- moc $< -o $@
GENERATED_FILES = $(INTERFACE_FILES) $(MOC_FILES)
-ldmgreeter.cpp: usermanagerinterface.h
-
liblightdm_qt_0include_HEADERS = \
ldmgreeter.h \
ldmlanguage.h \
@@ -58,9 +46,6 @@ pkgconfig_DATA = liblightdm-qt-0.pc
CLEANFILES = \
$(GENERATED_FILES)
-EXTRA_DIST = \
- user-manager.xml
-
DISTCLEANFILES = \
Makefile.in \
$(pkgconfig_DATA)
diff --git a/liblightdm-qt/ldmgreeter.cpp b/liblightdm-qt/ldmgreeter.cpp
index 9a46b94a..2d14c8be 100644
--- a/liblightdm-qt/ldmgreeter.cpp
+++ b/liblightdm-qt/ldmgreeter.cpp
@@ -1,7 +1,6 @@
#include "ldmgreeter.h"
#include "powermanagementinterface.h"
-#include "usermanagerinterface.h"
#include "consolekitinterface.h"
#include "ldmuser.h"
#include "ldmsession.h"
@@ -43,7 +42,6 @@ public:
int loginDelay;
PowerManagementInterface* powerManagement;
- UserManagerInterface* userManager;
ConsoleKitInterface* consoleKit;
int toServerFd;
@@ -160,8 +158,6 @@ void LdmGreeter::connectToServer()
busType = QDBusConnection::sessionBus();
}
- d->userManager = new UserManagerInterface("org.lightdm.LightDisplayManager", "/org/lightdm/LightDisplayManager/Users", busType, this);
-
char* fd = getenv("LDM_TO_SERVER_FD");
if(!fd)
{
@@ -390,18 +386,7 @@ int LdmGreeter::timedLoginDelay() const
QList<LdmUser> LdmGreeter::users() const
{
- QDBusPendingReply<QList<LdmUser> > users = d->userManager->GetUsers();
- users.waitForFinished();
- if (users.isValid())
- {
- return users.value();
- }
- else
- {
- qDebug() << users.error().name();
- qDebug() << users.error().message();
- return QList<LdmUser>();
- }
+ // FIXME
}
QList<LdmSession> LdmGreeter::sessions() const
diff --git a/liblightdm-qt/user-manager.xml b/liblightdm-qt/user-manager.xml
deleted file mode 100644
index 9857237b..00000000
--- a/liblightdm-qt/user-manager.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
-<node>
- <interface name="org.lightdm.LightDisplayManager.Users">
-
- <!-- Method to return the users -->
- <method name="GetUsers">
- <!-- name,real name,image,logged in -->
- <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QList&lt;LdmUser&gt;"/>
- <arg name="users" direction="out" type="a(sssb)"/>
- </method>
-
- <!-- Method to get user default information -->
- <method name="GetUserDefaults">
- <arg name="username" direction="in" type="s"/>
- <arg name="language" direction="out" type="s"/>
- <arg name="layout" direction="out" type="s"/>
- <arg name="session" direction="out" type="s"/>
- </method>
-
- </interface>
-</node>
diff --git a/src/Makefile.am b/src/Makefile.am
index 32ddd6bf..74196706 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -25,8 +25,6 @@ lightdm_SOURCES = \
session.h \
theme.c \
theme.h \
- user-manager.c \
- user-manager.h \
xauth.c \
xauth.h \
xdmcp-protocol.c \
diff --git a/src/greeter-protocol.h b/src/greeter-protocol.h
index 3a9c6dd7..bf471f4e 100644
--- a/src/greeter-protocol.h
+++ b/src/greeter-protocol.h
@@ -20,12 +20,14 @@ typedef enum
GREETER_MESSAGE_CONTINUE_AUTHENTICATION = 3,
GREETER_MESSAGE_LOGIN = 4,
GREETER_MESSAGE_CANCEL_AUTHENTICATION = 5,
+ GREETER_MESSAGE_GET_USER_DEFAULTS = 6,
/* Messages from the server to the greeter */
GREETER_MESSAGE_CONNECTED = 101,
GREETER_MESSAGE_QUIT = 102,
GREETER_MESSAGE_PROMPT_AUTHENTICATION = 103,
- GREETER_MESSAGE_END_AUTHENTICATION = 104
+ GREETER_MESSAGE_END_AUTHENTICATION = 104,
+ GREETER_MESSAGE_USER_DEFAULTS = 106
} GreeterMessage;
#endif /* _GREETER_PROTOCOL_H_ */
diff --git a/src/greeter.c b/src/greeter.c
index a53e5f1e..cd1338f6 100644
--- a/src/greeter.c
+++ b/src/greeter.c
@@ -10,6 +10,8 @@
*/
#include <string.h>
+#include <pwd.h>
+#include <errno.h>
#include "greeter.h"
#include "ldm-marshal.h"
@@ -332,6 +334,69 @@ handle_login (Greeter *greeter, gchar *username, gchar *session, gchar *language
g_signal_emit (greeter, signals[LOGIN], 0, username, session, language);
}
+static void
+handle_get_user_defaults (Greeter *greeter, gchar *username)
+{
+ struct passwd *user_info;
+ GKeyFile *dmrc_file;
+ gboolean have_dmrc = FALSE;
+ gchar *language, *layout, *session;
+
+ user_info = getpwnam (username);
+ if (!user_info)
+ {
+ if (errno == 0)
+ g_warning ("Unable to get information on user %s: User does not exist", username);
+ else
+ g_warning ("Unable to get information on user %s: %s", username, strerror (errno));
+ }
+
+ dmrc_file = g_key_file_new ();
+
+ /* Load the users login settings (~/.dmrc) */
+ if (user_info)
+ {
+ gchar *path;
+ path = g_build_filename (user_info->pw_dir, ".dmrc", NULL);
+ have_dmrc = g_key_file_load_from_file (dmrc_file, path, G_KEY_FILE_NONE, NULL);
+ g_free (path);
+ }
+
+ /* If no .dmrc, then load from the cache */
+ if (!have_dmrc)
+ {
+ gchar *path, *filename;
+
+ filename = g_strdup_printf ("%s.dmrc", username);
+ path = g_build_filename (CACHE_DIR, "dmrc", filename, NULL);
+ g_free (filename);
+ have_dmrc = g_key_file_load_from_file (dmrc_file, path, G_KEY_FILE_NONE, NULL);
+ g_free (path);
+ }
+
+ language = g_key_file_get_string (dmrc_file, "Desktop", "Language", NULL);
+ if (!language)
+ language = g_strdup ("");
+ layout = g_key_file_get_string (dmrc_file, "Desktop", "Layout", NULL);
+ if (!layout)
+ layout = g_strdup ("");
+ session = g_key_file_get_string (dmrc_file, "Desktop", "Session", NULL);
+ if (!session)
+ session = g_strdup ("");
+
+ write_header (greeter, GREETER_MESSAGE_USER_DEFAULTS, string_length (language) + string_length (layout) + string_length (session));
+ write_string (greeter, language);
+ write_string (greeter, layout);
+ write_string (greeter, session);
+ flush (greeter);
+
+ g_free (language);
+ g_free (layout);
+ g_free (session);
+
+ g_key_file_free (dmrc_file);
+}
+
#define HEADER_SIZE (sizeof (guint32) * 2)
static guint32
@@ -451,6 +516,11 @@ got_data_cb (Greeter *greeter)
g_free (session_name);
g_free (language);
break;
+ case GREETER_MESSAGE_GET_USER_DEFAULTS:
+ username = read_string (greeter, &offset);
+ handle_get_user_defaults (greeter, username);
+ g_free (username);
+ break;
default:
g_warning ("Unknown message from greeter: %d", id);
break;
diff --git a/src/lightdm.c b/src/lightdm.c
index 526ec541..de61f6d2 100644
--- a/src/lightdm.c
+++ b/src/lightdm.c
@@ -18,7 +18,6 @@
#include <unistd.h>
#include "display-manager.h"
-#include "user-manager.h"
#include "xserver.h"
static GKeyFile *config_file = NULL;
@@ -30,7 +29,6 @@ static GTimer *log_timer;
static FILE *log_file;
static gboolean debug = FALSE;
-static UserManager *user_manager = NULL;
static DisplayManager *display_manager = NULL;
static GDBusConnection *bus = NULL;
@@ -251,98 +249,20 @@ handle_display_manager_call (GDBusConnection *connection,
}
static GVariant *
-user_info_to_args (UserInfo *info)
+handle_display_manager_get_property (GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *property_name,
+ GError **error,
+ gpointer user_data)
{
- return g_variant_new ("(sssb)",
- info->name,
- info->real_name ? info->real_name : "",
- info->image ? info->image : "",
- info->logged_in);
-}
-
-static void
-handle_user_manager_call (GDBusConnection *connection,
- const gchar *sender,
- const gchar *object_path,
- const gchar *interface_name,
- const gchar *method_name,
- GVariant *parameters,
- GDBusMethodInvocation *invocation,
- gpointer user_data)
-{
- if (g_strcmp0 (method_name, "GetUsers") == 0)
+ if (g_strcmp0 (property_name, "ConfigFile") == 0)
{
- GVariantBuilder *builder;
- GVariant *arg0;
- GList *users, *iter;
-
- if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("()")))
- return;
-
- builder = g_variant_builder_new (G_VARIANT_TYPE ("a(sssb)"));
- users = user_manager_get_users (user_manager);
- for (iter = users; iter; iter = iter->next)
- {
- UserInfo *info = iter->data;
- g_variant_builder_add_value (builder, user_info_to_args (info));
- }
- arg0 = g_variant_builder_end (builder);
- g_dbus_method_invocation_return_value (invocation, g_variant_new_tuple (&arg0, 1));
- g_variant_builder_unref (builder);
+ return g_variant_new_string (config_path);
}
- else if (g_strcmp0 (method_name, "GetUserDefaults") == 0)
- {
- gchar *username, *language, *layout, *session;
- if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(s)")))
- return;
-
- g_variant_get (parameters, "(s)", &username);
- if (user_manager_get_user_defaults (user_manager, username, &language, &layout, &session))
- {
- g_dbus_method_invocation_return_value (invocation, g_variant_new ("(sss)", language, layout, session));
- g_free (language);
- g_free (layout);
- g_free (session);
- }
- g_free (username);
- }
-}
-
-static void
-user_added_cb (UserManager *user_manager, UserInfo *info)
-{
- g_dbus_connection_emit_signal (bus,
- NULL,
- "/org/lightdm/LightDisplayManager/Users",
- "org.lightdm.LightDisplayManager.Users",
- "UserAdded",
- user_info_to_args (info),
- NULL);
-}
-
-static void
-user_changed_cb (UserManager *user_manager, UserInfo *info)
-{
- g_dbus_connection_emit_signal (bus,
- NULL,
- "/org/lightdm/LightDisplayManager/Users",
- "org.lightdm.LightDisplayManager.Users",
- "UserChanged",
- user_info_to_args (info),
- NULL);
-}
-
-static void
-user_removed_cb (UserManager *user_manager, UserInfo *info)
-{
- g_dbus_connection_emit_signal (bus,
- NULL,
- "/org/lightdm/LightDisplayManager/Users",
- "org.lightdm.LightDisplayManager.Users",
- "UserRemoved",
- g_variant_new ("(s)", info->name),
- NULL);
+ return NULL;
}
static void
@@ -353,6 +273,7 @@ bus_acquired_cb (GDBusConnection *connection,
const gchar *display_manager_interface =
"<node>"
" <interface name='org.lightdm.LightDisplayManager'>"
+ " <property name='ConfigFile' type='s' access='read'/>"
" <method name='AddDisplay'/>"
" <method name='SwitchToUser'>"
" <arg name='username' direction='in' type='s'/>"
@@ -361,43 +282,10 @@ bus_acquired_cb (GDBusConnection *connection,
"</node>";
static const GDBusInterfaceVTable display_manager_vtable =
{
- handle_display_manager_call
- };
-
- const gchar *user_manager_interface =
- "<node>"
- " <interface name='org.lightdm.LightDisplayManager.Users'>"
- " <method name='GetUsers'>"
- " <arg name='users' direction='out' type='a(sssb)'/>"
- " </method>"
- " <method name='GetUserDefaults'>"
- " <arg name='username' direction='in' type='s'/>"
- " <arg name='language' direction='out' type='s'/>"
- " <arg name='layout' direction='out' type='s'/>"
- " <arg name='session' direction='out' type='s'/>"
- " </method>"
- " <signal name='UserAdded'>"
- " <arg name='username' type='s'/>"
- " <arg name='real-name' type='s'/>"
- " <arg name='image' type='s'/>"
- " <arg name='username' type='b'/>"
- " </signal>"
- " <signal name='UserChanged'>"
- " <arg name='username' type='s'/>"
- " <arg name='real-name' type='s'/>"
- " <arg name='image' type='s'/>"
- " <arg name='username' type='b'/>"
- " </signal>"
- " <signal name='UserRemoved'>"
- " <arg name='username' type='s'/>"
- " </signal>"
- " </interface>"
- "</node>";
- static const GDBusInterfaceVTable user_manager_vtable =
- {
- handle_user_manager_call
+ handle_display_manager_call,
+ handle_display_manager_get_property
};
- GDBusNodeInfo *display_manager_info, *user_manager_info;
+ GDBusNodeInfo *display_manager_info;
bus = connection;
@@ -409,19 +297,6 @@ bus_acquired_cb (GDBusConnection *connection,
&display_manager_vtable,
NULL, NULL,
NULL);
-
- user_manager_info = g_dbus_node_info_new_for_xml (user_manager_interface, NULL);
- g_assert (user_manager_info != NULL);
- g_dbus_connection_register_object (connection,
- "/org/lightdm/LightDisplayManager/Users",
- user_manager_info->interfaces[0],
- &user_manager_vtable,
- NULL, NULL,
- NULL);
-
- g_signal_connect (user_manager, "user-added", G_CALLBACK (user_added_cb), NULL);
- g_signal_connect (user_manager, "user-changed", G_CALLBACK (user_changed_cb), NULL);
- g_signal_connect (user_manager, "user-removed", G_CALLBACK (user_removed_cb), NULL);
}
static void
@@ -500,7 +375,6 @@ main(int argc, char **argv)
g_debug ("Loaded configuration from %s", config_path);
- user_manager = user_manager_new (config_file);
display_manager = display_manager_new (config_file);
display_manager_start (display_manager);
diff --git a/src/user-manager.c b/src/user-manager.c
deleted file mode 100644
index 71e201a5..00000000
--- a/src/user-manager.c
+++ /dev/null
@@ -1,400 +0,0 @@
-/*
- * Copyright (C) 2010 Robert Ancell.
- * Author: Robert Ancell <robert.ancell@canonical.com>
- *
- * This program is free software: you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free Software
- * Foundation, either version 3 of the License, or (at your option) any later
- * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
- * license.
- */
-
-#include <string.h>
-#include <pwd.h>
-#include <errno.h>
-#include <gio/gio.h>
-
-#include "user-manager.h"
-
-enum {
- USER_ADDED,
- USER_CHANGED,
- USER_REMOVED,
- LAST_SIGNAL
-};
-static guint signals[LAST_SIGNAL] = { 0 };
-
-struct UserManagerPrivate
-{
- /* Configuration file */
- GKeyFile *config;
-
- /* File monitor for password file */
- GFileMonitor *passwd_monitor;
-
- /* TRUE if have scanned users */
- gboolean have_users;
-
- /* List of users */
- GList *users;
-};
-
-G_DEFINE_TYPE (UserManager, user_manager, G_TYPE_OBJECT);
-
-UserManager *
-user_manager_new (GKeyFile *config_file)
-{
- UserManager *manager;
-
- manager = g_object_new (USER_MANAGER_TYPE, NULL);
- manager->priv->config = config_file;
-
- return manager;
-}
-
-static gint
-compare_user (gconstpointer a, gconstpointer b)
-{
- const UserInfo *user_a = a, *user_b = b;
- const gchar *name_a, *name_b;
- name_a = user_a->real_name ? user_a->real_name : user_a->name;
- name_b = user_b->real_name ? user_b->real_name : user_b->name;
- return strcmp (name_a, name_b);
-}
-
-static void
-load_users (UserManager *manager)
-{
- gchar **hidden_users, **hidden_shells;
- gchar *value;
- gint minimum_uid;
- GList *users = NULL, *old_users, *new_users = NULL, *changed_users = NULL, *link;
-
- if (g_key_file_has_key (manager->priv->config, "UserManager", "minimum-uid", NULL))
- minimum_uid = g_key_file_get_integer (manager->priv->config, "UserManager", "minimum-uid", NULL);
- else
- minimum_uid = 500;
-
- value = g_key_file_get_string (manager->priv->config, "UserManager", "hidden-users", NULL);
- if (!value)
- value = g_strdup ("nobody nobody4 noaccess");
- hidden_users = g_strsplit (value, " ", -1);
- g_free (value);
-
- value = g_key_file_get_string (manager->priv->config, "UserManager", "hidden-shells", NULL);
- if (!value)
- value = g_strdup ("/bin/false /usr/sbin/nologin");
- hidden_shells = g_strsplit (value, " ", -1);
- g_free (value);
-
- setpwent ();
-
- while (TRUE)
- {
- struct passwd *entry;
- UserInfo *user;
- char **tokens;
- gchar *image_path;
- int i;
-
- errno = 0;
- entry = getpwent ();
- if (!entry)
- break;
-
- /* Ignore system users */
- if (entry->pw_uid < minimum_uid)
- continue;
-
- /* Ignore users disabled by shell */
- if (entry->pw_shell)
- {
- for (i = 0; hidden_shells[i] && strcmp (entry->pw_shell, hidden_shells[i]) != 0; i++);
- if (hidden_shells[i])
- continue;
- }
-
- /* Ignore certain users */
- for (i = 0; hidden_users[i] && strcmp (entry->pw_name, hidden_users[i]) != 0; i++);
- if (hidden_users[i])
- continue;
-
- user = g_malloc0 (sizeof (UserInfo));
- user->name = g_strdup (entry->pw_name);
-
- tokens = g_strsplit (entry->pw_gecos, ",", -1);
- if (tokens[0] != NULL && tokens[0][0] != '\0')
- user->real_name = g_strdup (tokens[0]);
- else
- user->real_name = NULL;
- g_strfreev (tokens);
-
- user->home_dir = g_strdup (entry->pw_dir);
-
- image_path = g_build_filename (user->home_dir, ".face", NULL);
- if (!g_file_test (image_path, G_FILE_TEST_EXISTS))
- {
- g_free (image_path);
- image_path = g_build_filename (user->home_dir, ".face.icon", NULL);
- if (!g_file_test (image_path, G_FILE_TEST_EXISTS))
- {
- g_free (image_path);
- image_path = NULL;
- }
- }
- if (image_path)
- user->image = g_filename_to_uri (image_path, NULL, NULL);
- else
- user->image = g_strdup ("");
- g_free (image_path);
-
- /* Update existing users if have them */
- for (link = manager->priv->users; link; link = link->next)
- {
- UserInfo *info = link->data;
- if (strcmp (info->name, user->name) == 0)
- {
- if (strcmp (info->real_name, user->real_name) != 0 ||
- strcmp (info->image, user->image) != 0 ||
- strcmp (info->home_dir, user->home_dir) != 0 ||
- info->logged_in != user->logged_in)
- {
- g_free (info->real_name);
- g_free (info->image);
- g_free (info->home_dir);
- info->real_name = user->real_name;
- info->image = user->image;
- info->home_dir = user->home_dir;
- info->logged_in = user->logged_in;
- g_free (user);
- user = info;
- changed_users = g_list_insert_sorted (changed_users, user, compare_user);
- }
- else
- {
- g_free (user->real_name);
- g_free (user->image);
- g_free (user->home_dir);
- g_free (user);
- user = info;
- }
- break;
- }
- }
- if (!link)
- {
- /* Only notify once we have loaded the user list */
- if (manager->priv->have_users)
- new_users = g_list_insert_sorted (new_users, user, compare_user);
- }
- users = g_list_insert_sorted (users, user, compare_user);
- }
- g_strfreev (hidden_users);
- g_strfreev (hidden_shells);
-
- if (errno != 0)
- g_warning ("Failed to read password database: %s", strerror (errno));
-
- endpwent ();
-
- /* Use new user list */
- old_users = manager->priv->users;
- manager->priv->users = users;
-
- /* Notify of changes */
- for (link = new_users; link; link = link->next)
- {
- UserInfo *info = link->data;
- g_debug ("User %s added", info->name);
- g_signal_emit (manager, signals[USER_ADDED], 0, info);
- }
- g_list_free (new_users);
- for (link = changed_users; link; link = link->next)
- {
- UserInfo *info = link->data;
- g_debug ("User %s changed", info->name);
- g_signal_emit (manager, signals[USER_CHANGED], 0, info);
- }
- g_list_free (changed_users);
- for (link = old_users; link; link = link->next)
- {
- GList *new_link;
-
- /* See if this user is in the current list */
- for (new_link = manager->priv->users; new_link; new_link = new_link->next)
- {
- if (new_link->data == link->data)
- break;
- }
-
- if (!new_link)
- {
- UserInfo *info = link->data;
- g_debug ("User %s removed", info->name);
- g_signal_emit (manager, signals[USER_REMOVED], 0, info);
- g_free (info->name);
- g_free (info->real_name);
- g_free (info->image);
- g_free (info->home_dir);
- g_free (info);
- }
- }
- g_list_free (old_users);
-}
-
-static void
-passwd_changed_cb (GFileMonitor *monitor, GFile *file, GFile *other_file, GFileMonitorEvent event_type, UserManager *manager)
-{
- if (event_type == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT)
- {
- g_debug ("%s changed, reloading user list", g_file_get_path (file));
- load_users (manager);
- }
-}
-
-static void
-update_users (UserManager *manager)
-{
- GFile *passwd_file;
- GError *error = NULL;
-
- if (manager->priv->have_users)
- return;
-
- /* User listing is disabled */
- if (g_key_file_has_key (manager->priv->config, "UserManager", "load-users", NULL) &&
- !g_key_file_get_boolean (manager->priv->config, "UserManager", "load-users", NULL))
- {
- manager->priv->have_users = TRUE;
- return;
- }
-
- load_users (manager);
-
- /* Watch for changes to user list */
- passwd_file = g_file_new_for_path ("/etc/passwd");
- manager->priv->passwd_monitor = g_file_monitor (passwd_file, G_FILE_MONITOR_NONE, NULL, &error);
- g_object_unref (passwd_file);
- if (!manager->priv->passwd_monitor)
- g_warning ("Error monitoring /etc/passwd: %s", error->message);
- else
- g_signal_connect (manager->priv->passwd_monitor, "changed", G_CALLBACK (passwd_changed_cb), manager);
- g_clear_error (&error);
-
- manager->priv->have_users = TRUE;
-}
-
-gint
-user_manager_get_num_users (UserManager *manager)
-{
- update_users (manager);
- return g_list_length (manager->priv->users);
-}
-
-const UserInfo *
-user_manager_get_user (UserManager *manager, const gchar *username)
-{
- GList *link;
-
- update_users (manager);
-
- for (link = manager->priv->users; link; link = link->next)
- {
- UserInfo *info = link->data;
- if (strcmp (info->name, username) == 0)
- return info;
- }
-
- return NULL;
-}
-
-GList *
-user_manager_get_users (UserManager *manager)
-{
- update_users (manager);
- return manager->priv->users;
-}
-
-gboolean
-user_manager_get_user_defaults (UserManager *manager, gchar *username, gchar **language, gchar **layout, gchar **session)
-{
- const UserInfo *info;
- GKeyFile *dmrc_file;
- gboolean have_dmrc;
- gchar *path;
-
- info = user_manager_get_user (manager, username);
- if (!info)
- {
- g_debug ("Unable to get user defaults, user %s does not exist", username);
- return FALSE;
- }
-
- dmrc_file = g_key_file_new ();
- g_key_file_set_string (dmrc_file, "Desktop", "Language", "");
- g_key_file_set_string (dmrc_file, "Desktop", "Layout", "");
- g_key_file_set_string (dmrc_file, "Desktop", "Session", "");
-
- /* Load the users login settings (~/.dmrc) */
- path = g_build_filename (info->home_dir, ".dmrc", NULL);
- have_dmrc = g_key_file_load_from_file (dmrc_file, path, G_KEY_FILE_NONE, NULL);
- g_free (path);
-
- /* If no .dmrc, then load from the cache */
- if (!have_dmrc)
- {
- gchar *filename;
-
- filename = g_strdup_printf ("%s.dmrc", username);
- path = g_build_filename (CACHE_DIR, "dmrc", filename, NULL);
- g_free (filename);
- have_dmrc = g_key_file_load_from_file (dmrc_file, path, G_KEY_FILE_NONE, NULL);
- g_free (path);
- }
-
- *language = g_key_file_get_string (dmrc_file, "Desktop", "Language", NULL);
- *layout = g_key_file_get_string (dmrc_file, "Desktop", "Layout", NULL);
- *session = g_key_file_get_string (dmrc_file, "Desktop", "Session", NULL);
-
- g_key_file_free (dmrc_file);
-
- return TRUE;
-}
-
-
-static void
-user_manager_init (UserManager *manager)
-{
- manager->priv = G_TYPE_INSTANCE_GET_PRIVATE (manager, USER_MANAGER_TYPE, UserManagerPrivate);
-}
-
-static void
-user_manager_class_init (UserManagerClass *klass)
-{
- g_type_class_add_private (klass, sizeof (UserManagerPrivate));
-
- signals[USER_ADDED] =
- g_signal_new ("user-added",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (UserManagerClass, user_added),
- NULL, NULL,
- g_cclosure_marshal_VOID__POINTER,
- G_TYPE_NONE, 1, G_TYPE_POINTER);
- signals[USER_CHANGED] =
- g_signal_new ("user-changed",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (UserManagerClass, user_changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__POINTER,
- G_TYPE_NONE, 1, G_TYPE_POINTER);
- signals[USER_REMOVED] =
- g_signal_new ("user-removed",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (UserManagerClass, user_removed),
- NULL, NULL,
- g_cclosure_marshal_VOID__POINTER,
- G_TYPE_NONE, 1, G_TYPE_POINTER);
-}
diff --git a/src/user-manager.h b/src/user-manager.h
deleted file mode 100644
index a7e5a8de..00000000
--- a/src/user-manager.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2010 Robert Ancell.
- * Author: Robert Ancell <robert.ancell@canonical.com>
- *
- * This program is free software: you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free Software
- * Foundation, either version 3 of the License, or (at your option) any later
- * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
- * license.
- */
-
-#ifndef _USER_MANAGER_H_
-#define _USER_MANAGER_H_
-
-#include <glib-object.h>
-
-G_BEGIN_DECLS
-
-#define USER_MANAGER_TYPE (user_manager_get_type())
-#define USER_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), USER_MANAGER_TYPE, UserManager));
-
-typedef struct UserManagerPrivate UserManagerPrivate;
-
-typedef struct
-{
- gchar *name;
- gchar *real_name;
- gchar *image;
- gchar *home_dir;
- gboolean logged_in;
-} UserInfo;
-
-typedef struct
-{
- GObject parent_instance;
- UserManagerPrivate *priv;
-} UserManager;
-
-typedef struct
-{
- GObjectClass parent_class;
- void (*user_added)(UserManager *manager, UserInfo *user);
- void (*user_changed)(UserManager *manager, UserInfo *user);
- void (*user_removed)(UserManager *manager, UserInfo *user);
-} UserManagerClass;
-
-GType user_manager_get_type (void);
-
-UserManager *user_manager_new (GKeyFile *config_file);
-
-gint user_manager_get_num_users (UserManager *manager);
-
-const UserInfo *user_manager_get_user (UserManager *manager, const gchar *username);
-
-GList *user_manager_get_users (UserManager *manager);
-
-gboolean user_manager_get_user_defaults (UserManager *manager, gchar *username, gchar **language, gchar **layout, gchar **session);
-
-G_END_DECLS
-
-#endif /* _USER_MANAGER_H_ */