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;
51 G_DEFINE_TYPE (User, user, G_TYPE_OBJECT);
53 /* Connection to AccountsService */
54 static GDBusProxy *accounts_service_proxy = NULL;
55 static gboolean have_accounts_service_proxy = FALSE;
58 call_method (GDBusProxy *proxy, const gchar *method, GVariant *args,
59 const gchar *expected, GVariant **result)
67 answer = g_dbus_proxy_call_sync (proxy,
70 G_DBUS_CALL_FLAGS_NONE,
75 g_warning ("Could not call %s: %s", method, error->message);
76 g_clear_error (&error);
81 if (!g_variant_is_of_type (answer, G_VARIANT_TYPE (expected)))
83 g_warning ("Unexpected response from %s: %s",
84 method, g_variant_get_type_string (answer));
85 g_variant_unref (answer);
92 g_variant_unref (answer);
98 get_property (GDBusProxy *proxy, const gchar *property,
99 const gchar *expected, GVariant **result)
103 answer = g_dbus_proxy_get_cached_property (proxy, property);
107 g_warning ("Could not get accounts property %s", property);
111 if (!g_variant_is_of_type (answer, G_VARIANT_TYPE (expected)))
113 g_warning ("Unexpected accounts property type for %s: %s",
114 property, g_variant_get_type_string (answer));
115 g_variant_unref (answer);
122 g_variant_unref (answer);
127 save_string_to_dmrc (const gchar *username, const gchar *group,
128 const gchar *key, const gchar *value)
132 dmrc = dmrc_load (username);
133 g_key_file_set_string (dmrc, group, key, value);
134 dmrc_save (dmrc, username);
136 g_key_file_free (dmrc);
140 get_string_from_dmrc (const gchar *username, const gchar *group,
146 dmrc = dmrc_load (username);
147 value = g_key_file_get_string (dmrc, group, key, NULL);
149 g_key_file_free (dmrc);
154 get_accounts_service_proxy (void)
156 GError *error = NULL;
158 if (have_accounts_service_proxy)
159 return accounts_service_proxy;
161 have_accounts_service_proxy = TRUE;
162 accounts_service_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
163 G_DBUS_PROXY_FLAGS_NONE,
165 "org.freedesktop.Accounts",
166 "/org/freedesktop/Accounts",
167 "org.freedesktop.Accounts",
170 g_warning ("Could not get accounts proxy: %s", error->message);
171 g_clear_error (&error);
173 if (accounts_service_proxy)
176 name = g_dbus_proxy_get_name_owner (accounts_service_proxy);
179 g_debug ("org.freedesktop.Accounts does not exist, falling back to passwd file");
180 g_object_unref (accounts_service_proxy);
181 accounts_service_proxy = NULL;
186 return accounts_service_proxy;
190 get_accounts_proxy_for_user (const gchar *user)
193 GError *error = NULL;
196 gchar *user_path = NULL;
198 g_return_val_if_fail (user != NULL, NULL);
200 proxy = get_accounts_service_proxy ();
204 success = call_method (proxy, "FindUserByName", g_variant_new ("(s)", user), "(o)", &result);
209 g_variant_get (result, "(o)", &user_path);
210 g_variant_unref (result);
215 proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
216 G_DBUS_PROXY_FLAGS_NONE,
218 "org.freedesktop.Accounts",
220 "org.freedesktop.Accounts.User",
223 g_warning ("Could not get accounts user proxy: %s", error->message);
224 g_clear_error (&error);
231 user_from_passwd (struct passwd *user_info)
235 user = g_object_new (USER_TYPE, NULL);
236 user->priv->name = g_strdup (user_info->pw_name);
237 user->priv->uid = user_info->pw_uid;
238 user->priv->gid = user_info->pw_gid;
239 user->priv->gecos = g_strdup (user_info->pw_gecos);
240 user->priv->home_directory = g_strdup (user_info->pw_dir);
241 user->priv->shell = g_strdup (user_info->pw_shell);
242 user->priv->proxy = get_accounts_proxy_for_user (user->priv->name);
248 accounts_get_user_by_name (const gchar *username)
250 struct passwd *user_info;
253 g_return_val_if_fail (username != NULL, NULL);
256 user_info = getpwnam (username);
258 user = user_from_passwd (user_info);
260 if (!user && errno != 0)
261 g_warning ("Unable to get information on user %s: %s", username, strerror (errno));
267 accounts_get_user_by_uid (uid_t uid)
272 struct passwd *user_info;
274 user_info = getpwuid (uid);
276 user = user_from_passwd (user_info);
278 if (!user && errno != 0)
279 g_warning ("Unable to get information on user %d: %s", uid, strerror (errno));
285 accounts_get_current_user ()
287 return user_from_passwd (getpwuid (getuid ()));
291 user_get_name (User *user)
293 g_return_val_if_fail (user != NULL, NULL);
294 return user->priv->name;
298 user_get_uid (User *user)
300 g_return_val_if_fail (user != NULL, 0);
301 return user->priv->uid;
305 user_get_gid (User *user)
307 g_return_val_if_fail (user != NULL, 0);
308 return user->priv->gid;
312 user_get_gecos (User *user)
314 g_return_val_if_fail (user != NULL, NULL);
315 return user->priv->gecos;
319 user_get_home_directory (User *user)
321 g_return_val_if_fail (user != NULL, NULL);
322 return user->priv->home_directory;
326 user_get_shell (User *user)
328 g_return_val_if_fail (user != NULL, NULL);
329 return user->priv->shell;
333 user_set_language (User *user, const gchar *language)
335 g_return_if_fail (user != NULL);
337 call_method (user->priv->proxy, "SetLanguage", g_variant_new ("(s)", language), "()", NULL);
338 save_string_to_dmrc (user->priv->name, "Desktop", "Language", language);
342 user_get_language (User *user)
344 GVariant *variant, *inner;
347 g_return_val_if_fail (user != NULL, NULL);
349 g_free (user->priv->language);
350 if (user->priv->proxy)
352 /* the "Language" property cannot be retrieved with get_property () here since it
353 * uses g_dbus_proxy_get_cached_property () which would return the previous (cached) value
354 * of the "Language" property
356 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);
359 g_variant_get (variant, "(v)", &inner);
360 user->priv->language = g_variant_dup_string (inner, NULL);
361 g_variant_unref (inner);
362 g_variant_unref (variant);
365 user->priv->language = NULL;
368 user->priv->language = get_string_from_dmrc (user->priv->name, "Desktop", "Language");
370 /* Treat a blank language as unset */
371 if (g_strcmp0 (user->priv->language, "") == 0)
373 g_free (user->priv->language);
374 user->priv->language = NULL;
377 return user->priv->language;
381 user_set_xsession (User *user, const gchar *xsession)
383 g_return_if_fail (user != NULL);
385 call_method (user->priv->proxy, "SetXSession", g_variant_new ("(s)", xsession), "()", NULL);
386 save_string_to_dmrc (user->priv->name, "Desktop", "Session", xsession);
390 user_get_xsession (User *user)
394 g_return_val_if_fail (user != NULL, NULL);
396 g_free (user->priv->xsession);
397 if (user->priv->proxy)
399 if (get_property (user->priv->proxy, "XSession", "s", &result))
401 g_variant_get (result, "s", &user->priv->xsession);
402 g_variant_unref (result);
405 user->priv->xsession = NULL;
408 user->priv->xsession = get_string_from_dmrc (user->priv->name, "Desktop", "Session");
410 if (g_strcmp0 (user->priv->xsession, "") == 0)
412 g_free (user->priv->xsession);
413 user->priv->xsession = NULL;
416 return user->priv->xsession;
420 user_init (User *user)
422 user->priv = G_TYPE_INSTANCE_GET_PRIVATE (user, USER_TYPE, UserPrivate);
426 user_dispose (GObject *object)
430 self = USER (object);
432 if (self->priv->proxy)
434 g_object_unref (self->priv->proxy);
435 self->priv->proxy = NULL;
438 G_OBJECT_CLASS (user_parent_class)->dispose (object);
442 user_finalize (GObject *object)
446 self = USER (object);
448 g_free (self->priv->name);
449 g_free (self->priv->gecos);
450 g_free (self->priv->home_directory);
451 g_free (self->priv->shell);
452 g_free (self->priv->language);
454 G_OBJECT_CLASS (user_parent_class)->finalize (object);
458 user_class_init (UserClass *klass)
460 GObjectClass *object_class = G_OBJECT_CLASS (klass);
462 object_class->dispose = user_dispose;
463 object_class->finalize = user_finalize;
465 g_type_class_add_private (klass, sizeof (UserPrivate));