*
* Copyright (C) 2010-2011 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
* 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;
-
- /* Locale */
- gchar *locale;
-
- /* 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 ()
-{
- 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;
}
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;
-}
-
-const gchar *
-user_get_locale (User *user)
-{
- g_return_val_if_fail (user != NULL, NULL);
-
- g_free (user->priv->locale);
- if (user->priv->proxy)
- user->priv->locale = NULL;
- else
- user->priv->locale = get_string_from_dmrc (user->priv->name, "Desktop", "Language");
-
- /* Treat a blank locale as unset */
- if (g_strcmp0 (user->priv->locale, "") == 0)
- {
- g_free (user->priv->locale);
- user->priv->locale = NULL;
- }
-
- return user->priv->locale;
+ return common_user_get_shell (user->priv->common_user);
}
void
user_set_language (User *user, const gchar *language)
{
g_return_if_fail (user != NULL);
+ common_user_set_language (user->priv->common_user, language);
+}
- if (user->priv->proxy)
- call_method (user->priv->proxy, "SetLanguage", g_variant_new ("(s)", language), "()", NULL);
- else
- save_string_to_dmrc (user->priv->name, "Desktop", "Language", language);
+const gchar *
+user_get_language (User *user)
+{
+ g_return_val_if_fail (user != NULL, NULL);
+ 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
user->priv = G_TYPE_INSTANCE_GET_PRIVATE (user, USER_TYPE, UserPrivate);
}
-static void
-user_dispose (GObject *object)
-{
- User *self;
-
- self = USER (object);
-
- if (self->priv->proxy)
- {
- g_object_unref (self->priv->proxy);
- self->priv->proxy = NULL;
- }
-
- G_OBJECT_CLASS (user_parent_class)->dispose (object);
-}
-
static void
user_finalize (GObject *object)
{
- User *self;
-
- self = USER (object);
+ User *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_clear_object (&self->priv->common_user);
- G_OBJECT_CLASS (user_parent_class)->finalize (object);
+ G_OBJECT_CLASS (user_parent_class)->finalize (object);
}
static void
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
- object_class->dispose = user_dispose;
- object_class->finalize = user_finalize;
+ object_class->finalize = user_finalize;
g_type_class_add_private (klass, sizeof (UserPrivate));
}