1 /* -*- Mode: C; indent-tabs-mode: nil; tab-width: 4 -*-
3 * Copyright (C) 2010-2011 Robert Ancell.
4 * Author: Robert Ancell <robert.ancell@canonical.com>
6 * This program is free software: you can redistribute it and/or modify it under
7 * the terms of the GNU General Public License as published by the Free Software
8 * Foundation, either version 3 of the License, or (at your option) any later
9 * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
26 /* Accounts interface proxy */
35 /* GECOS information */
39 gchar *home_directory;
54 G_DEFINE_TYPE (User, user, G_TYPE_OBJECT);
56 /* Connection to AccountsService */
57 static GDBusProxy *accounts_service_proxy = NULL;
58 static gboolean have_accounts_service_proxy = FALSE;
61 call_method (GDBusProxy *proxy, const gchar *method, GVariant *args,
62 const gchar *expected, GVariant **result)
70 answer = g_dbus_proxy_call_sync (proxy,
73 G_DBUS_CALL_FLAGS_NONE,
78 g_warning ("Could not call %s: %s", method, error->message);
79 g_clear_error (&error);
84 if (!g_variant_is_of_type (answer, G_VARIANT_TYPE (expected)))
86 g_warning ("Unexpected response from %s: %s",
87 method, g_variant_get_type_string (answer));
88 g_variant_unref (answer);
95 g_variant_unref (answer);
101 get_property (GDBusProxy *proxy, const gchar *property,
102 const gchar *expected, GVariant **result)
106 answer = g_dbus_proxy_get_cached_property (proxy, property);
110 g_warning ("Could not get accounts property %s", property);
114 if (!g_variant_is_of_type (answer, G_VARIANT_TYPE (expected)))
116 g_warning ("Unexpected accounts property type for %s: %s",
117 property, g_variant_get_type_string (answer));
118 g_variant_unref (answer);
125 g_variant_unref (answer);
130 save_string_to_dmrc (const gchar *username, const gchar *group,
131 const gchar *key, const gchar *value)
135 dmrc = dmrc_load (username);
136 g_key_file_set_string (dmrc, group, key, value);
137 dmrc_save (dmrc, username);
139 g_key_file_free (dmrc);
143 get_string_from_dmrc (const gchar *username, const gchar *group,
149 dmrc = dmrc_load (username);
150 value = g_key_file_get_string (dmrc, group, key, NULL);
152 g_key_file_free (dmrc);
157 get_accounts_service_proxy ()
159 GError *error = NULL;
161 if (have_accounts_service_proxy)
162 return accounts_service_proxy;
164 have_accounts_service_proxy = TRUE;
165 accounts_service_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
166 G_DBUS_PROXY_FLAGS_NONE,
168 "org.freedesktop.Accounts",
169 "/org/freedesktop/Accounts",
170 "org.freedesktop.Accounts",
173 g_warning ("Could not get accounts proxy: %s", error->message);
174 g_clear_error (&error);
176 if (accounts_service_proxy)
179 name = g_dbus_proxy_get_name_owner (accounts_service_proxy);
182 g_debug ("org.freedesktop.Accounts does not exist, falling back to passwd file");
183 g_object_unref (accounts_service_proxy);
184 accounts_service_proxy = NULL;
189 return accounts_service_proxy;
193 get_accounts_proxy_for_user (const gchar *user)
196 GError *error = NULL;
199 gchar *user_path = NULL;
201 g_return_val_if_fail (user != NULL, NULL);
203 proxy = get_accounts_service_proxy ();
207 success = call_method (proxy, "FindUserByName", g_variant_new ("(s)", user), "(o)", &result);
212 g_variant_get (result, "(o)", &user_path);
213 g_variant_unref (result);
218 proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
219 G_DBUS_PROXY_FLAGS_NONE,
221 "org.freedesktop.Accounts",
223 "org.freedesktop.Accounts.User",
226 g_warning ("Could not get accounts user proxy: %s", error->message);
227 g_clear_error (&error);
234 user_from_passwd (struct passwd *user_info)
238 user = g_object_new (USER_TYPE, NULL);
239 user->priv->name = g_strdup (user_info->pw_name);
240 user->priv->uid = user_info->pw_uid;
241 user->priv->gid = user_info->pw_gid;
242 user->priv->gecos = g_strdup (user_info->pw_gecos);
243 user->priv->home_directory = g_strdup (user_info->pw_dir);
244 user->priv->shell = g_strdup (user_info->pw_shell);
245 user->priv->proxy = get_accounts_proxy_for_user (user->priv->name);
251 accounts_get_user_by_name (const gchar *username)
253 struct passwd *user_info;
256 g_return_val_if_fail (username != NULL, NULL);
259 user_info = getpwnam (username);
261 user = user_from_passwd (user_info);
263 if (!user && errno != 0)
264 g_warning ("Unable to get information on user %s: %s", username, strerror (errno));
270 accounts_get_user_by_uid (uid_t uid)
275 struct passwd *user_info;
277 user_info = getpwuid (uid);
279 user = user_from_passwd (user_info);
281 if (!user && errno != 0)
282 g_warning ("Unable to get information on user %d: %s", uid, strerror (errno));
288 accounts_get_current_user ()
290 return user_from_passwd (getpwuid (getuid ()));
294 user_get_name (User *user)
296 g_return_val_if_fail (user != NULL, NULL);
297 return user->priv->name;
301 user_get_uid (User *user)
303 g_return_val_if_fail (user != NULL, 0);
304 return user->priv->uid;
308 user_get_gid (User *user)
310 g_return_val_if_fail (user != NULL, 0);
311 return user->priv->gid;
315 user_get_gecos (User *user)
317 g_return_val_if_fail (user != NULL, NULL);
318 return user->priv->gecos;
322 user_get_home_directory (User *user)
324 g_return_val_if_fail (user != NULL, NULL);
325 return user->priv->home_directory;
329 user_get_shell (User *user)
331 g_return_val_if_fail (user != NULL, NULL);
332 return user->priv->shell;
336 user_get_locale (User *user)
338 g_return_val_if_fail (user != NULL, NULL);
340 g_free (user->priv->locale);
341 if (user->priv->proxy)
342 user->priv->locale = NULL;
344 user->priv->locale = get_string_from_dmrc (user->priv->name, "Desktop", "Language");
346 /* Treat a blank locale as unset */
347 if (g_strcmp0 (user->priv->locale, "") == 0)
349 g_free (user->priv->locale);
350 user->priv->locale = NULL;
353 return user->priv->locale;
357 user_set_language (User *user, const gchar *language)
359 g_return_if_fail (user != NULL);
361 if (user->priv->proxy)
362 call_method (user->priv->proxy, "SetLanguage", g_variant_new ("(s)", language), "()", NULL);
364 save_string_to_dmrc (user->priv->name, "Desktop", "Language", language);
368 user_set_xsession (User *user, const gchar *xsession)
370 g_return_if_fail (user != NULL);
372 call_method (user->priv->proxy, "SetXSession", g_variant_new ("(s)", xsession), "()", NULL);
373 save_string_to_dmrc (user->priv->name, "Desktop", "Session", xsession);
377 user_get_xsession (User *user)
381 g_return_val_if_fail (user != NULL, NULL);
383 g_free (user->priv->xsession);
384 if (user->priv->proxy)
386 if (get_property (user->priv->proxy, "XSession", "s", &result))
388 g_variant_get (result, "s", &user->priv->xsession);
389 g_variant_unref (result);
392 user->priv->xsession = NULL;
395 user->priv->xsession = get_string_from_dmrc (user->priv->name, "Desktop", "Session");
397 if (g_strcmp0 (user->priv->xsession, "") == 0)
399 g_free (user->priv->xsession);
400 user->priv->xsession = NULL;
403 return user->priv->xsession;
407 user_init (User *user)
409 user->priv = G_TYPE_INSTANCE_GET_PRIVATE (user, USER_TYPE, UserPrivate);
413 user_dispose (GObject *object)
417 self = USER (object);
419 if (self->priv->proxy)
421 g_object_unref (self->priv->proxy);
422 self->priv->proxy = NULL;
425 G_OBJECT_CLASS (user_parent_class)->dispose (object);
429 user_finalize (GObject *object)
433 self = USER (object);
435 g_free (self->priv->name);
436 g_free (self->priv->gecos);
437 g_free (self->priv->home_directory);
438 g_free (self->priv->shell);
440 G_OBJECT_CLASS (user_parent_class)->finalize (object);
444 user_class_init (UserClass *klass)
446 GObjectClass *object_class = G_OBJECT_CLASS (klass);
448 object_class->dispose = user_dispose;
449 object_class->finalize = user_finalize;
451 g_type_class_add_private (klass, sizeof (UserPrivate));