~ubuntu-branches/debian/stretch/lightdm/stretch

« back to all changes in this revision

Viewing changes to src/accounts.c

  • Committer: Package Import Robot
  • Author(s): Yves-Alexis Perez
  • Date: 2014-04-22 23:33:26 UTC
  • mfrom: (1.1.23) (16.1.11 experimental)
  • Revision ID: package-import@ubuntu.com-20140422233326-gpd7rgap1v53zkuy
Tags: 1.10.0-2
Upload to unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
10
10
 * license.
11
11
 */
12
12
 
13
 
#include <errno.h>
14
13
#include <pwd.h>
15
14
#include <stdlib.h>
16
 
#include <string.h>
17
15
 
18
16
#include "accounts.h"
19
 
#include "dmrc.h"
 
17
#include "user-list.h"
20
18
 
21
19
struct UserPrivate
22
20
{
23
 
    /* Name of user */
24
 
    gchar *name;
25
 
 
26
 
    /* Accounts interface proxy */
27
 
    GDBusProxy *proxy;
28
 
 
29
 
    /* User ID */
30
 
    uid_t uid;
31
 
 
32
 
    /* Group ID */
33
 
    gid_t gid;
34
 
 
35
 
    /* GECOS information */
36
 
    gchar *gecos;
37
 
 
38
 
    /* Home directory */
39
 
    gchar *home_directory;
40
 
 
41
 
    /* Shell */
42
 
    gchar *shell;
43
 
 
44
 
    /* Language */
45
 
    gchar *language;
46
 
 
47
 
    /* X session */
48
 
    gchar *xsession;
 
21
    /* Internal user object */
 
22
    CommonUser *common_user;
49
23
};
50
24
 
51
25
G_DEFINE_TYPE (User, user, G_TYPE_OBJECT);
52
26
 
53
 
/* Connection to AccountsService */
54
 
static GDBusProxy *accounts_service_proxy = NULL;
55
 
static gboolean have_accounts_service_proxy = FALSE;
56
 
 
57
 
static gboolean
58
 
call_method (GDBusProxy *proxy, const gchar *method, GVariant *args,
59
 
             const gchar *expected, GVariant **result)
60
 
{
61
 
    GVariant *answer;
62
 
    GError *error = NULL;
63
 
 
64
 
    if (!proxy)
65
 
        return FALSE;
66
 
 
67
 
    answer = g_dbus_proxy_call_sync (proxy,
68
 
                                     method,
69
 
                                     args,
70
 
                                     G_DBUS_CALL_FLAGS_NONE,
71
 
                                     -1,
72
 
                                     NULL,
73
 
                                     &error);
74
 
    if (error)
75
 
        g_warning ("Could not call %s: %s", method, error->message);
76
 
    g_clear_error (&error);
77
 
 
78
 
    if (!answer)
79
 
        return FALSE;
80
 
 
81
 
    if (!g_variant_is_of_type (answer, G_VARIANT_TYPE (expected)))
82
 
    {
83
 
        g_warning ("Unexpected response from %s: %s",
84
 
                   method, g_variant_get_type_string (answer));
85
 
        g_variant_unref (answer);
86
 
        return FALSE;
87
 
    }
88
 
 
89
 
    if (result)
90
 
        *result = answer;
91
 
    else
92
 
        g_variant_unref (answer);
93
 
 
94
 
    return TRUE;
95
 
}
96
 
 
97
 
static gboolean
98
 
get_property (GDBusProxy *proxy, const gchar *property,
99
 
              const gchar *expected, GVariant **result)
100
 
{
101
 
    GVariant *answer;
102
 
 
103
 
    answer = g_dbus_proxy_get_cached_property (proxy, property);
104
 
 
105
 
    if (!answer)
106
 
    {
107
 
        g_warning ("Could not get accounts property %s", property);
108
 
        return FALSE;
109
 
    }
110
 
 
111
 
    if (!g_variant_is_of_type (answer, G_VARIANT_TYPE (expected)))
112
 
    {
113
 
        g_warning ("Unexpected accounts property type for %s: %s",
114
 
                   property, g_variant_get_type_string (answer));
115
 
        g_variant_unref (answer);
116
 
        return FALSE;
117
 
    }
118
 
 
119
 
    if (result)
120
 
        *result = answer;
121
 
    else
122
 
        g_variant_unref (answer);
123
 
    return TRUE;
124
 
}
125
 
 
126
 
static void
127
 
save_string_to_dmrc (const gchar *username, const gchar *group,
128
 
                     const gchar *key, const gchar *value)
129
 
{
130
 
    GKeyFile *dmrc;
131
 
 
132
 
    dmrc = dmrc_load (username);
133
 
    g_key_file_set_string (dmrc, group, key, value);
134
 
    dmrc_save (dmrc, username);
135
 
 
136
 
    g_key_file_free (dmrc);
137
 
}
138
 
 
139
 
static gchar *
140
 
get_string_from_dmrc (const gchar *username, const gchar *group,
141
 
                      const gchar *key)
142
 
{
143
 
    GKeyFile *dmrc;
144
 
    gchar *value;
145
 
 
146
 
    dmrc = dmrc_load (username);
147
 
    value = g_key_file_get_string (dmrc, group, key, NULL);
148
 
 
149
 
    g_key_file_free (dmrc);
150
 
    return value;
151
 
}
152
 
 
153
 
static GDBusProxy *
154
 
get_accounts_service_proxy (void)
155
 
{
156
 
    GError *error = NULL;
157
 
 
158
 
    if (have_accounts_service_proxy)
159
 
        return accounts_service_proxy;
160
 
 
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,
164
 
                                                            NULL,
165
 
                                                            "org.freedesktop.Accounts",
166
 
                                                            "/org/freedesktop/Accounts",
167
 
                                                            "org.freedesktop.Accounts",
168
 
                                                            NULL, &error);
169
 
    if (error)
170
 
        g_warning ("Could not get accounts proxy: %s", error->message);
171
 
    g_clear_error (&error);
172
 
 
173
 
    if (accounts_service_proxy)
174
 
    {
175
 
        gchar *name;
176
 
        name = g_dbus_proxy_get_name_owner (accounts_service_proxy);
177
 
        if (!name)
178
 
        {
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;
182
 
        }
183
 
        g_free (name);
184
 
    }  
185
 
 
186
 
    return accounts_service_proxy;
187
 
}
188
 
 
189
 
static GDBusProxy *
190
 
get_accounts_proxy_for_user (const gchar *user)
191
 
{
192
 
    GDBusProxy *proxy;
193
 
    GError *error = NULL;
194
 
    GVariant *result;
195
 
    gboolean success;
196
 
    gchar *user_path = NULL;
197
 
 
198
 
    g_return_val_if_fail (user != NULL, NULL);  
199
 
 
200
 
    proxy = get_accounts_service_proxy ();
201
 
    if (!proxy)
202
 
        return NULL;
203
 
 
204
 
    success = call_method (proxy, "FindUserByName", g_variant_new ("(s)", user), "(o)", &result);
205
 
 
206
 
    if (!success)
207
 
        return NULL;
208
 
 
209
 
    g_variant_get (result, "(o)", &user_path);
210
 
    g_variant_unref (result);
211
 
 
212
 
    if (!user_path)
213
 
        return NULL;
214
 
  
215
 
    proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
216
 
                                           G_DBUS_PROXY_FLAGS_NONE,
217
 
                                           NULL,
218
 
                                           "org.freedesktop.Accounts",
219
 
                                           user_path,
220
 
                                           "org.freedesktop.Accounts.User",
221
 
                                           NULL, &error);
222
 
    if (error)
223
 
        g_warning ("Could not get accounts user proxy: %s", error->message);
224
 
    g_clear_error (&error);
225
 
    g_free (user_path);
226
 
 
227
 
    return proxy;
228
 
}
229
 
 
230
 
static User *
231
 
user_from_passwd (struct passwd *user_info)
232
 
{
233
 
    User *user;
234
 
 
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);
243
 
 
244
 
    return user;
245
 
}
246
 
 
247
27
User *
248
28
accounts_get_user_by_name (const gchar *username)
249
29
{
250
 
    struct passwd *user_info;
251
30
    User *user = NULL;
 
31
    CommonUser *common_user;
252
32
 
253
33
    g_return_val_if_fail (username != NULL, NULL);
254
34
 
255
 
    errno = 0;
256
 
    user_info = getpwnam (username);
257
 
    if (user_info)
258
 
        user = user_from_passwd (user_info);
259
 
 
260
 
    if (!user && errno != 0)
261
 
        g_warning ("Unable to get information on user %s: %s", username, strerror (errno));
262
 
 
263
 
    return user;
264
 
}
265
 
 
266
 
User *
267
 
accounts_get_user_by_uid (uid_t uid)
268
 
{
269
 
    User *user = NULL;
270
 
 
271
 
    errno = 0;
272
 
    struct passwd *user_info;
273
 
 
274
 
    user_info = getpwuid (uid);
275
 
    if (user_info)
276
 
        user = user_from_passwd (user_info);
277
 
 
278
 
    if (!user && errno != 0)
279
 
        g_warning ("Unable to get information on user %d: %s", uid, strerror (errno));
 
35
    common_user = common_user_list_get_user_by_name (common_user_list_get_instance (), username);
 
36
    if (common_user != NULL)
 
37
    {
 
38
        user = g_object_new (USER_TYPE, NULL);
 
39
        user->priv->common_user = common_user;
 
40
    }
280
41
 
281
42
    return user;
282
43
}
284
45
User *
285
46
accounts_get_current_user ()
286
47
{
287
 
    return user_from_passwd (getpwuid (getuid ()));
 
48
    struct passwd *entry = getpwuid (getuid ());
 
49
    if (entry != NULL)
 
50
        return accounts_get_user_by_name (entry->pw_name);
 
51
    else
 
52
        return NULL;
288
53
}
289
54
 
290
55
const gchar *
291
56
user_get_name (User *user)
292
57
{
293
58
    g_return_val_if_fail (user != NULL, NULL);
294
 
    return user->priv->name;
 
59
    return common_user_get_name (user->priv->common_user);
295
60
}
296
61
 
297
62
uid_t
298
63
user_get_uid (User *user)
299
64
{
300
65
    g_return_val_if_fail (user != NULL, 0);
301
 
    return user->priv->uid;
 
66
    return common_user_get_uid (user->priv->common_user);
302
67
}
303
68
 
304
69
gid_t
305
70
user_get_gid (User *user)
306
71
{
307
72
    g_return_val_if_fail (user != NULL, 0);
308
 
    return user->priv->gid;
309
 
}
310
 
 
311
 
const gchar *
312
 
user_get_gecos (User *user)
313
 
{
314
 
    g_return_val_if_fail (user != NULL, NULL);
315
 
    return user->priv->gecos;
 
73
    return common_user_get_gid (user->priv->common_user);
316
74
}
317
75
 
318
76
const gchar *
319
77
user_get_home_directory (User *user)
320
78
{
321
79
    g_return_val_if_fail (user != NULL, NULL);
322
 
    return user->priv->home_directory;
 
80
    return common_user_get_home_directory (user->priv->common_user);
323
81
}
324
82
 
325
83
const gchar *
326
84
user_get_shell (User *user)
327
85
{
328
86
    g_return_val_if_fail (user != NULL, NULL);
329
 
    return user->priv->shell;
 
87
    return common_user_get_shell (user->priv->common_user);
330
88
}
331
89
 
332
90
void
333
91
user_set_language (User *user, const gchar *language)
334
92
{
335
93
    g_return_if_fail (user != NULL);
336
 
 
337
 
    call_method (user->priv->proxy, "SetLanguage", g_variant_new ("(s)", language), "()", NULL);
338
 
    save_string_to_dmrc (user->priv->name, "Desktop", "Language", language);
 
94
    common_user_set_language (user->priv->common_user, language);
339
95
}
340
96
 
341
97
const gchar *
342
98
user_get_language (User *user)
343
99
{
344
 
    GVariant *variant, *inner;
345
 
    gboolean success;
346
 
 
347
100
    g_return_val_if_fail (user != NULL, NULL);
348
 
 
349
 
    g_free (user->priv->language);
350
 
    if (user->priv->proxy)
351
 
    {
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
355
 
         */
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);
357
 
        if (success)
358
 
        {
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);
363
 
        }
364
 
        else
365
 
            user->priv->language = NULL;
366
 
    }
367
 
    else
368
 
        user->priv->language = get_string_from_dmrc (user->priv->name, "Desktop", "Language");
369
 
 
370
 
    /* Treat a blank language as unset */
371
 
    if (g_strcmp0 (user->priv->language, "") == 0)
372
 
    {
373
 
        g_free (user->priv->language);
374
 
        user->priv->language = NULL;
375
 
    }
376
 
 
377
 
    return user->priv->language;
 
101
    return common_user_get_language (user->priv->common_user);
378
102
}
379
103
 
380
104
void
381
105
user_set_xsession (User *user, const gchar *xsession)
382
106
{
383
107
    g_return_if_fail (user != NULL);
384
 
 
385
 
    call_method (user->priv->proxy, "SetXSession", g_variant_new ("(s)", xsession), "()", NULL);
386
 
    save_string_to_dmrc (user->priv->name, "Desktop", "Session", xsession);
 
108
    common_user_set_session (user->priv->common_user, xsession);
387
109
}
388
110
 
389
111
const gchar *
390
112
user_get_xsession (User *user)
391
113
{
392
 
    GVariant *result;
393
 
 
394
114
    g_return_val_if_fail (user != NULL, NULL);
395
 
 
396
 
    g_free (user->priv->xsession);
397
 
    if (user->priv->proxy)
398
 
    {
399
 
        if (get_property (user->priv->proxy, "XSession", "s", &result))
400
 
        {
401
 
            g_variant_get (result, "s", &user->priv->xsession);
402
 
            g_variant_unref (result);
403
 
        }
404
 
        else
405
 
            user->priv->xsession = NULL;
406
 
    }
407
 
    else
408
 
        user->priv->xsession = get_string_from_dmrc (user->priv->name, "Desktop", "Session");
409
 
 
410
 
    if (g_strcmp0 (user->priv->xsession, "") == 0)
411
 
    {
412
 
        g_free (user->priv->xsession);
413
 
        user->priv->xsession = NULL;
414
 
    }
415
 
 
416
 
    return user->priv->xsession;
 
115
    return common_user_get_session (user->priv->common_user);
417
116
}
418
117
 
419
118
static void
429
128
 
430
129
    self = USER (object);
431
130
 
432
 
    if (self->priv->proxy)
433
 
    {
434
 
        g_object_unref (self->priv->proxy);
435
 
        self->priv->proxy = NULL;
436
 
    }
 
131
    if (self->priv->common_user)
 
132
        g_object_unref (self->priv->common_user);
 
133
    self->priv->common_user = NULL;
437
134
 
438
135
    G_OBJECT_CLASS (user_parent_class)->dispose (object);
439
136
}
440
137
 
441
138
static void
442
 
user_finalize (GObject *object)
443
 
{
444
 
    User *self;
445
 
 
446
 
    self = USER (object);
447
 
 
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);
453
 
 
454
 
    G_OBJECT_CLASS (user_parent_class)->finalize (object);  
455
 
}
456
 
 
457
 
static void
458
139
user_class_init (UserClass *klass)
459
140
{
460
141
    GObjectClass *object_class = G_OBJECT_CLASS (klass);
461
142
 
462
143
    object_class->dispose = user_dispose;
463
 
    object_class->finalize = user_finalize;  
464
144
 
465
145
    g_type_class_add_private (klass, sizeof (UserPrivate));
466
146
}